Documentation Index Fetch the complete documentation index at: https://mintlify.com/badlogic/pi-mono/llms.txt
Use this file to discover all available pages before exploring further.
The complete() and completeSimple() functions provide a synchronous interface for getting LLM responses. They internally use stream() and streamSimple() but await the full result.
Import
import { complete , completeSimple } from "@mariozechner/pi-ai" ;
complete
Get a complete response with provider-specific options.
complete < TApi extends Api > (
model : Model < TApi > ,
context : Context ,
options ?: ProviderStreamOptions
): Promise < AssistantMessage >
The model to use for generation
Message content (text, thinking, tool calls)
Message timestamp (ms since epoch)
Why generation stopped (“stop”, “length”, “tool_use”, etc.)
Example
import { complete , getModel } from "@mariozechner/pi-ai" ;
const model = getModel ( "anthropic" , "claude-4.5-sonnet-20250514" );
const message = await complete ( model , {
systemPrompt: "You are a helpful assistant." ,
messages: [
{ role: "user" , content: "Explain TypeScript generics" , timestamp: Date . now () }
],
}, {
temperature: 0.7 ,
maxTokens: 1000 ,
});
console . log ( message . content );
console . log ( `Tokens used: ${ message . usage . input + message . usage . output } ` );
completeSimple
Get a complete response with unified reasoning parameter.
completeSimple < TApi extends Api > (
model : Model < TApi > ,
context : Context ,
options ?: SimpleStreamOptions
): Promise < AssistantMessage >
The model to use for generation
Example
import { completeSimple , getModel } from "@mariozechner/pi-ai" ;
const model = getModel ( "openai" , "gpt-5.3-codex" );
const message = await completeSimple ( model , {
systemPrompt: "You are a coding assistant." ,
messages: [
{ role: "user" , content: "Write a Fibonacci function" , timestamp: Date . now () }
],
}, {
reasoning: "medium" ,
temperature: 0.7 ,
});
// Extract thinking and text
const thinking = message . content . filter ( c => c . type === "thinking" );
const text = message . content . filter ( c => c . type === "text" );
console . log ( "Thinking:" , thinking );
console . log ( "Response:" , text );
Error Handling
Both functions throw errors on failure:
try {
const message = await complete ( model , context , options );
console . log ( message . content );
} catch ( error ) {
if ( error . name === "AbortError" ) {
console . log ( "Request was cancelled" );
} else if ( error . message . includes ( "context_length_exceeded" )) {
console . log ( "Context too long" );
} else {
console . error ( "API error:" , error );
}
}
Cancellation
Use AbortSignal to cancel requests:
const controller = new AbortController ();
// Cancel after 10 seconds
setTimeout (() => controller . abort (), 10000 );
try {
const message = await complete ( model , context , {
signal: controller . signal ,
});
console . log ( message . content );
} catch ( error ) {
if ( error . name === "AbortError" ) {
console . log ( "Request timed out" );
}
}
When the response includes tool calls:
const message = await complete ( model , {
systemPrompt: "You are a helpful assistant." ,
messages: [
{ role: "user" , content: "What's the weather?" , timestamp: Date . now () }
],
tools: [
{
type: "function" ,
function: {
name: "get_weather" ,
description: "Get current weather" ,
parameters: {
type: "object" ,
properties: {
location: { type: "string" },
},
required: [ "location" ],
},
},
},
],
});
// Check for tool calls
const toolCalls = message . content . filter ( c => c . type === "toolCall" );
if ( toolCalls . length > 0 ) {
console . log ( "Tool calls:" , toolCalls );
// Execute tools and send results back
}
Usage Statistics
All responses include token usage:
const message = await complete ( model , context );
console . log ( "Input tokens:" , message . usage . input );
console . log ( "Output tokens:" , message . usage . output );
console . log ( "Cache read:" , message . usage . cacheRead );
console . log ( "Cache write:" , message . usage . cacheWrite );
console . log ( "Cost:" , message . usage . cost . total );
Comparison with Stream
Use Case Function When to Use Real-time output stream() / streamSimple()Interactive applications, showing progress Batch processing complete() / completeSimple()Background tasks, API servers Tool execution stream()Need to show tool execution progress Simple Q&A complete()Just need the final answer
complete() and completeSimple() have the same performance as their streaming counterparts - they just buffer the events internally:
// These are equivalent:
const message1 = await complete ( model , context );
const stream = stream ( model , context );
const message2 = await stream . result ();
// Both take the same time and use the same network requests