import type { Context as RuntimeContext } from "@steve.kite/stdlib"; import type { AgentContext } from "./context/AgentContext.js"; import type { BashSessionActivity } from "./context/BashContext.js"; import { type PresentedToolCall } from "./impl/presentToolCall.js"; import type { AnyDefinedTool, CompactionMessage, Message, SteeringMessage, ToolResultBlock } from "./types.js"; import type { AssistantMessageEvent, Context as ProviderContext, Message as ProviderMessage, Model, Provider, ProviderError, ServiceTier, StopReason } from "@slopus/rig-execution"; import { type AutoPermissionRisk, type AutoPermissionUserAuthorization, type PermissionReviewAgent, type PermissionReviewTranscript } from "../permissions/index.js"; import type { DebugLog } from "../debug/index.js"; import type { DurableSkillDefinition } from "../external-skills/types.js"; export interface RunAgentLoopOptions { /** Allows a dedicated permission reviewer to use the provider's hidden reviewer model. */ allowReviewerModel?: boolean; appendSystemPrompt?: string; systemPrompt?: string; debug?: DebugLog; provider: Provider; /** Provider whose session is isolated from the coding agent and has no tools. */ /** Lazily returns the sister agent that reviews Auto permission decisions. */ permissionReviewAgent?: () => PermissionReviewAgent; modelId: string; effort?: string; serviceTier?: ServiceTier; tools: readonly AnyDefinedTool[]; /** Returns the complete fixed tool array for the next inference iteration. */ resolveTools?: () => Promise; durableSkills?: readonly DurableSkillDefinition[]; instructions?: string; messages: readonly Message[]; /** Model-facing history, when the visible transcript has been compacted. */ contextMessages?: readonly Message[]; compactContext?: (messages: readonly Message[], options: { createProviderContext: (messages: readonly Message[]) => Promise; force: boolean; reportedTokens?: number; }) => Promise<{ compacted: boolean; compactionMessage?: CompactionMessage; contextMessages: readonly Message[]; } | undefined>; signal?: AbortSignal; sessionId?: string; startDate?: string; idFactory?: () => string; now?: () => number; onEvent?: (event: AgentLoopEvent) => void | Promise; onMessage?: (message: Message) => void | Promise; /** Checkpoints canonical model context before its durable messages are published. */ onContextChanged?: (messages: readonly Message[]) => void | Promise; takeSteering?: () => readonly SteeringMessage[]; /** Returns the signal aborted by the next scheduled steering message. */ getSteeringSignal?: () => AbortSignal; context: AgentContext; } export type AgentLoopEvent = AssistantMessageEvent | { type: "context_compaction_started"; compactionId: string; estimatedTokensBefore: number; reason: "context_window" | "manual" | "threshold"; } | { type: "context_compacted"; compactionId: string; compactedMessageCount: number; elapsedMs: number; estimatedTokensAfter: number; estimatedTokensBefore: number; reason: "context_window" | "manual" | "threshold"; } | { type: "context_compaction_finished"; compactionId: string; elapsedMs: number; status: "cancelled" | "completed" | "failed"; errorMessage?: string; } | { type: "inference_iteration_start"; iteration: number; messageId: string; } | { type: "steering_applied"; messageIds: readonly string[]; } | { type: "tool_execution_start"; toolCall: PresentedToolCall; } | { type: "tool_execution_end"; result: Pick; } | { type: "tool_execution_progress"; display: string; toolCallId: string; } | { type: "tool_execution_status"; status: string; toolCallId: string; } | { type: "permission_review_started"; action: string; toolCallId: string; toolName: string; } | { type: "permission_review"; action: string; decision: "allow" | "deny"; reason: string; risk: AutoPermissionRisk; toolCallId: string; /** The reviewer's own reasoning, tool calls, and token usage for this verdict. */ transcript?: PermissionReviewTranscript; userAuthorization: AutoPermissionUserAuthorization; } | { action: string; reason: string; risk: AutoPermissionRisk; type: "temporary_full_access_started"; toolCallId: string; userAuthorization: AutoPermissionUserAuthorization; } | { type: "permission_denial_limit_reached"; reason: string; } | { type: "background_processes_changed"; processes?: readonly BashSessionActivity[]; running: number; } | { type: "background_processes_stopped"; count: number; } | { type: "background_process_exited"; command: string; exitCode: number | null; processId: number; status: "completed" | "killed"; }; interface AgentLoopOutcome { messages: readonly Message[]; contextMessages: readonly Message[]; } /** * A failed run always carries the text that explains the failure, so no exit path can * report an error the session and the transcript are unable to describe. */ export type AgentLoopResult = (AgentLoopOutcome & { errorMessage: string; providerError: ProviderError; providerId: string; requestedModelId: string; stopReason: "error"; }) | (AgentLoopOutcome & { errorMessage?: never; stopReason: Exclude; }); export declare function runAgentLoop(ctx: RuntimeContext, options: RunAgentLoopOptions): Promise; export declare function toProviderMessages(messages: readonly Message[], options: { model: Model; now: () => number; providerId: string; }): ProviderMessage[]; export {};