import type { Context, ImageContent, Message, SimpleStreamOptions, ThinkingBudgets, Transport } from "@earendil-works/pi-ai"; import type { AfterToolCallContext, AfterToolCallResult, AgentContext, AgentEvent, AgentLoopConfig, AgentLoopTurnUpdate, AgentMessage, AgentState, BeforeToolCallContext, BeforeToolCallResult, PrepareNextTurnContext, QueueMode, ShouldStopAfterTurnContext, StreamFn, ToolExecutionMode } from "./types.ts"; export type { QueueMode } from "./types.ts"; /** Options for constructing an {@link Agent}. */ export interface AgentOptions { initialState?: Partial>; convertToLlm?: (messages: AgentMessage[]) => Message[] | Promise; transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise; streamFn: StreamFn; getApiKey?: (provider: string) => Promise | string | undefined; onPayload?: SimpleStreamOptions["onPayload"]; onResponse?: SimpleStreamOptions["onResponse"]; beforeToolCall?: (context: BeforeToolCallContext, signal?: AbortSignal) => Promise; afterToolCall?: (context: AfterToolCallContext, signal?: AbortSignal) => Promise; shouldStopAfterTurn?: (context: ShouldStopAfterTurnContext, signal?: AbortSignal) => boolean | Promise; prepareNextTurn?: (signal?: AbortSignal) => Promise | AgentLoopTurnUpdate | undefined; prepareNextTurnWithContext?: (context: PrepareNextTurnContext, signal?: AbortSignal) => Promise | AgentLoopTurnUpdate | undefined; steeringMode?: QueueMode; followUpMode?: QueueMode; sessionId?: string; thinkingBudgets?: ThinkingBudgets; transport?: Transport; timeoutMs?: number; streamStartTimeoutMs?: number; maxRetryDelayMs?: number; toolExecution?: ToolExecutionMode; removedToolHints?: Record; resolveUnknownToolCall?: AgentLoopConfig["resolveUnknownToolCall"]; abortServerSideFallback?: boolean; /** Cursor exec-channel tool handlers; see {@link AgentLoopConfig.cursorExecHandlers}. */ cursorExecHandlers?: AgentLoopConfig["cursorExecHandlers"]; } export interface AgentContinuationOptions { /** Keep queued steering and follow-up input out of the continuation's first provider request only. */ deferQueuedMessages?: boolean; /** Override the provider stream idle timeout for the continuation's first provider request only. */ timeoutMs?: number; /** Override the provider stream-start timeout for the continuation's first provider request only. */ streamStartTimeoutMs?: number; } /** * Stateful wrapper around the low-level agent loop. * * `Agent` owns the current transcript, emits lifecycle events, executes tools, * and exposes queueing APIs for steering and follow-up messages. */ export declare class Agent { private _state; private readonly listeners; private readonly steeringQueue; private readonly followUpQueue; convertToLlm: (messages: AgentMessage[]) => Message[] | Promise; transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise; streamFunction: StreamFn; getApiKey?: (provider: string) => Promise | string | undefined; onPayload?: SimpleStreamOptions["onPayload"]; onResponse?: SimpleStreamOptions["onResponse"]; beforeToolCall?: (context: BeforeToolCallContext, signal?: AbortSignal) => Promise; afterToolCall?: (context: AfterToolCallContext, signal?: AbortSignal) => Promise; shouldStopAfterTurn?: (context: ShouldStopAfterTurnContext, signal?: AbortSignal) => boolean | Promise; prepareNextTurn?: (signal?: AbortSignal) => Promise | AgentLoopTurnUpdate | undefined; prepareNextTurnWithContext?: (context: PrepareNextTurnContext, signal?: AbortSignal) => Promise | AgentLoopTurnUpdate | undefined; private activeRun?; /** Session identifier forwarded to providers for cache-aware backends. */ sessionId?: string; /** Optional per-level thinking token budgets forwarded to the stream function. */ thinkingBudgets?: ThinkingBudgets; /** Preferred transport forwarded to the stream function. */ transport: Transport; timeoutMs?: number; /** Optional bound on the wait for the first provider stream event. */ streamStartTimeoutMs?: number; /** Optional cap for provider-requested retry delays. */ maxRetryDelayMs?: number; /** Tool execution strategy for assistant messages that contain multiple tool calls. */ toolExecution: ToolExecutionMode; /** Migration guidance returned when a removed tool name is called. */ removedToolHints: Record; /** Optional call-time resolver for tools absent from the request context. */ resolveUnknownToolCall?: AgentLoopConfig["resolveUnknownToolCall"]; /** Forwarded to the stream function; providers without server-side fallback ignore it. */ abortServerSideFallback?: boolean; /** Cursor exec-channel tool handlers; see {@link AgentLoopConfig.cursorExecHandlers}. */ cursorExecHandlers?: AgentLoopConfig["cursorExecHandlers"]; buildProviderContext(context: AgentContext, signal?: AbortSignal): Promise; constructor(options: AgentOptions); /** * Subscribe to agent lifecycle events. * * Listener promises are awaited in subscription order and are included in * the current run's settlement. Listeners also receive the active abort * signal for the current run. * * `agent_end` is the final emitted event for a run, but the agent does not * become idle until all awaited listeners for that event have settled. */ subscribe(listener: (event: AgentEvent, signal: AbortSignal) => Promise | void): () => void; /** * Current agent state. * * Assigning `state.tools` or `state.messages` copies the provided top-level array. */ get state(): AgentState; /** Controls how queued steering messages are drained. */ set steeringMode(mode: QueueMode); get steeringMode(): QueueMode; /** Controls how queued follow-up messages are drained. */ set followUpMode(mode: QueueMode); get followUpMode(): QueueMode; /** Queue a message to be injected after the current assistant turn finishes. */ steer(message: AgentMessage): void; /** Queue a message to run only after the agent would otherwise stop. */ followUp(message: AgentMessage): void; /** Remove all queued steering messages. */ clearSteeringQueue(): void; /** Remove all queued follow-up messages. */ clearFollowUpQueue(): void; /** Remove all queued steering and follow-up messages. */ clearAllQueues(): void; /** Returns true when either queue still contains pending messages. */ hasQueuedMessages(): boolean; /** Active abort signal for the current run, if any. */ get signal(): AbortSignal | undefined; /** Abort the current run, if one is active. */ abort(reason?: unknown): void; /** * Keep queued steering and follow-up messages for an external owner after * this run reaches agent_end, without changing the active abort signal. * This is ownership suppression for one active run; terminal error/abort * parking is a separate stop-reason policy enforced by the run lifecycle. */ suppressQueuedMessageDrain(): void; /** * Resolve when the current run and all awaited event listeners have finished. * * This resolves after `agent_end` listeners settle. */ waitForIdle(): Promise; /** Clear transcript state, runtime state, and queued messages. */ reset(): void; /** Start a new prompt from text, a single message, or a batch of messages. */ prompt(message: AgentMessage | AgentMessage[]): Promise; prompt(input: string, images?: ImageContent[]): Promise; /** * Continue by delivering queued input first when a compaction leaves custom context at the tail. * Queue-first recovery takes precedence over `deferQueuedMessages`: the selected queued message is * the continuation input, while timeout overrides still apply to its first provider request. */ continueWithQueuedMessages(options?: AgentContinuationOptions): Promise; /** * Continue from the current transcript. The last message must be a user or tool-result message. * Queue deferral and timeout overrides apply only to the first provider request; later requests in * the same run and later runs use the configured Agent defaults. */ continue(options?: AgentContinuationOptions): Promise; private normalizePromptInput; private runPromptMessages; private runContinuation; private createContextSnapshot; private createLoopConfig; private runWithLifecycle; private canDrainQueuedMessagesAfterRun; private runQueuedMessagesAfterAgentEnd; private handleRunFailure; private finishRun; /** * Reduce internal state for a loop event, then await listeners. * * `agent_end` only means no further loop events will be emitted. The run is * considered idle later, after all awaited listeners for `agent_end` finish * and `finishRun()` clears runtime-owned state. */ private processEvents; /** * Emit a host-generated event through the normal listener pipeline. * * Used by the Cursor exec bridge: bridge-run tools execute inside the * provider stream, outside the loop's executor, so their * `tool_execution_start`/`tool_execution_end` lifecycle must be injected * here or the live tool card for a synthesized call never resolves. * A bridge execution may settle after an aborted run has already ended; its * late lifecycle event belongs to that finished run and must be discarded. */ emitExternalEvent(event: AgentEvent, runSignal?: AbortSignal): Promise; } //# sourceMappingURL=agent.d.ts.map