import type { AdvisoryContext } from '../../../../advisory/context.js'; import type { AgentBus } from '../../../../bus/index.js'; import type { WorkingStateManager } from '../../../../compaction/manager.js'; import type { ContextReducer } from '../../../../compaction/reducer.js'; import type { CompactionConfig } from '../../../../config/runtime.js'; import type { PlanManager } from '../../../../manager/plan/lifecycle.js'; import type { TurnRecorder } from '../../../../manager/session/turn-recorder.js'; import type { PromptContributionRegistry } from '../../../../prompt/contributions.js'; import type { ResolvedProviderCapabilities } from '../../../../provider/capabilities.js'; import type { ServingMember } from '../../../../provider/fallback.js'; import type { CompletionInbox } from '../../../../scheduler/completion-inbox.js'; import type { ActivityStore } from '../../../../store/activity/memory.js'; import type { TaskScheduler } from '../../../../types/agent/scheduler.js'; import type { WorkingMemoryProvider } from '../../../../types/agent/working-memory.js'; import type { HITLResumeDecision, ResumeHandler } from '../../../../types/hitl/index.js'; import type { CheckpointId } from '../../../../types/ids/index.js'; import type { LLMProvider } from '../../../../types/provider/index.js'; import type { TaskRouterConfig } from '../../../../types/router/index.js'; import type { ReviewAnswer } from '../../../../types/session/answer-review.js'; import type { BeforeStep, PrepareStepChain, PrepareStepContext, SessionEvent, StepResult, StopCondition, TurnConfig } from '../../../../types/session/index.js'; import type { StructuredOutputConfig } from '../../../../types/structured-output/index.js'; import type { TaskStore } from '../../../../types/task/index.js'; import type { ToolRegistryContract } from '../../../../types/tool/index.js'; import type { Logger } from '../../../../utils/logger.js'; import type { AwaitedJobs } from '../../../jobs/awaited-jobs.js'; import type { CheckpointManager } from '../../checkpoint.js'; import type { EmitEvent } from '../../events.js'; import type { ToolExecutor } from '../../executor.js'; import type { GuardCoordinator } from '../../guard.js'; import type { ProjectInstructionContext } from '../../project-instructions.js'; import type { RepeatCallTracker } from '../../repeat-call.js'; import type { SteeringChannel } from '../../steering.js'; import type { ToolGrantSet } from '../../tool-grants.js'; export interface IterationContext { readonly provider: LLMProvider; /** Driver-level request shapes negotiated for this turn. */ readonly providerCapabilities?: ResolvedProviderCapabilities; /** Refuse a capability mismatch instead of emitting a warning and degrading. */ readonly strictCapabilities?: boolean; /** * Which chain member `provider` will route the NEXT request to. * * `provider` cannot answer this itself: `withProviderFallback` keeps its * `id` transparently equal to the head's, deliberately, because that is * what capability negotiation and the turn's `gen_ai.system` attribute are * about. Asking the wrapper who it is gets the declaration; this gets the * observation. * * Optional because a host may build an `IterationContext` without a chain * at all. Absent, the loop attributes each step to `provider.id` and the * model it requested, which is exactly right when nothing can fall over — * and exactly wrong when something can, so the wiring from `query()` is * covered end-to-end rather than by a unit test on this accessor. */ readonly servingMember?: () => ServingMember; /** * The turn's `invoke_agent` span, so each iteration can parent itself to * it. Explicit rather than ambient because this loop is an async * generator — see `parentContext` in `telemetry/attributes.ts`. */ readonly rootSpan?: import('@opentelemetry/api').Span; readonly turnConfig: TurnConfig; /** * Caller-supplied halt predicate, evaluated after each step's tools have * run. See {@link StopCondition}. */ readonly stopWhen?: StopCondition; /** * Host verdict on the answer the turn is about to settle with, and how * many rejections it may spend before stopping. */ readonly reviewAnswer?: ReviewAnswer; readonly maxAnswerReviews?: number; /** Called with each completed step, as it completes. */ readonly onStepFinish?: (step: StepResult) => void; /** Demand a schema-validated final answer. See QueryParams.structuredOutput. */ readonly structuredOutput?: StructuredOutputConfig; readonly tools: ToolRegistryContract; readonly allowedTools?: string[]; readonly recorder: TurnRecorder; readonly toolExecutor: ToolExecutor; readonly guard: GuardCoordinator; readonly activityStore: ActivityStore; readonly emitEvent: EmitEvent; readonly drainPending: () => Generator; readonly abortController: AbortController; readonly log: Logger; readonly resumeHandler: ResumeHandler; /** * The policy change the model has not been told about, if there is one. * * Read-and-CLEAR: calling this marks the change announced, so the caller * must be the one that actually puts it in front of the model. Optional * because a host driving the phases directly may have no policy box, and * a turn with no changes to report behaves identically either way. */ readonly takeApprovalPolicyChange?: () => import('../../../../types/hitl/policy.js').ApprovalPolicyChange | undefined; /** * Contributions that report state changing DURING the turn. * * Rendered once per iteration, never into the system prompt: `turn` * into the ephemeral trailing system message, `context` into the * request-only context channel after the history — see * `PromptPlacement`'s notes on both. */ readonly promptContributions?: PromptContributionRegistry; /** * Guidance a host may hand to the turn while it runs. * * Absent means the loop behaves exactly as it always has — nothing is * drained and no tool result is extended. */ readonly steering?: SteeringChannel; /** Records operator intent only after guidance was accepted by a tool result. */ readonly onSteeringDelivered?: (text: string) => void; /** Exit notices for the turn's background jobs, drained into the next tool result. */ readonly jobNotices?: SteeringChannel; /** * Background jobs the model said it is waiting on, which is the only kind * the loop holds a finishing run open for. * * Absent means the loop behaves exactly as it did before this existed: a * job's exit still reaches the model as a notice on the next tool result, * and a turn whose model stopped calling tools settles without waiting. */ readonly awaitedJobs?: AwaitedJobs; readonly checkpointMgr: CheckpointManager; readonly planManager: PlanManager; readonly taskGateway?: TaskScheduler; /** * Completions no call is waiting for, on their way to the transcript. * * Absent means the loop behaves exactly as it did before this existed: * a blocking `create_task` still delivers its own result, and a * completion nobody awaited is simply never mentioned. */ readonly completionInbox?: CompletionInbox; readonly taskStore?: TaskStore; /** * Approvals a human granted earlier in this turn, at a scope they chose. * * Consulted before a tool-review park so an already-approved call is not * asked about again. Absent on paths that do not review tools. */ readonly toolGrants?: ToolGrantSet; /** * Absent when the host opted out with `repeatCallAdvisory: false`. The * opt-out is the ABSENCE, not a flag read at every call site, so a code * path that forgets to check the flag cannot advise anyway. */ readonly repeatCalls?: RepeatCallTracker; /** Per-task model overrides. Consulted for the compaction summary call. */ readonly taskRouter?: TaskRouterConfig; readonly compactionConfig?: CompactionConfig; /** * What the driver said this model's context window is, resolved once. * * Carried rather than asked for, because both readers are synchronous * and in the hot loop — turning either into an await would put a network * round trip on every iteration of every turn. `undefined` covers both * "the driver has no such member" and "it asked and does not know", * which are different facts to the DRIVER and the same fact here: fall * through to the table. */ readonly providerContextWindow?: number; /** Selected request model; its window must not reuse another model's metadata. */ contextModel?: string; activeProviderContextWindow?: number; /** Bounded, run-cached provider metadata lookup for a newly selected model. */ readonly resolveModelContextWindow?: (model: string) => Promise; /** * Text queued for this turn since its last turn. * * Drained at the iteration boundary — the same seam `completionInbox` * uses, which is the established place for putting a user message in * after tool results and before the next turn. */ readonly inboundMessages?: () => readonly import('../../../../types/message/index.js').Message[]; /** Known topic-queue arrivals appended after the restored checkpoint history. */ readonly resumedInput?: readonly import('../../../../types/message/index.js').Message[]; /** Observes pending input without draining it; abort releases the waiter. */ readonly waitForInbound?: (signal: AbortSignal) => Promise; /** Live project policy; separate from human inbound continuation. */ readonly projectInstructionContext?: ProjectInstructionContext; readonly workingStateManager?: WorkingStateManager; /** * Host-supplied context reduction. Outranks `compactionConfig.strategy` * and replaces the structured pass for this turn. */ readonly contextReducer?: ContextReducer; readonly workingMemoryProvider?: WorkingMemoryProvider; readonly advisoryCtx?: AdvisoryContext; readonly agentBus?: AgentBus; readonly verificationGate?: import('../../../../authorization/gate.js').AuthorizationGate; readonly pluginManager?: import('../../../../plugin/lifecycle.js').PluginLifecycleManager; /** * Override for {@link PARK_RECORD_DELAY_MS}. Internal; tests set `0` to * observe a recorded park without waiting out the real threshold. */ readonly parkRecordDelayMs?: number; /** Host hook that shapes each step before the model call. */ readonly prepareStep?: PrepareStepChain; readonly captureSessionEvidence?: PrepareStepContext['captureSessionEvidence']; readonly beforeStep?: BeforeStep; } export type PhaseSignal = 'continue' | 'stop'; /** * How long a decision may take before the park is written to the store. * * A park is only worth persisting if a human is actually looking at it. An * `autoApproveHandler` — or any programmatic handler — answers in well * under a millisecond, and the iteration gate runs on EVERY iteration by * default, so recording every one unconditionally would take a long turn * from one full-history checkpoint write per iteration to three. This * threshold buys the durability where it matters and costs nothing where * it does not. */ export declare const PARK_RECORD_DELAY_MS = 250; /** * Await a HITL decision, recording the park durably if it turns out to be * a real one. * * The park used to exist only as a suspended `await` inside one process: * kill the process and the request vanished, so a host could not rebuild * an approval queue and a resumed turn silently re-asked the model instead * of honoring an approval a human had already granted. */ export declare function awaitDecisionDurably(ctx: IterationContext, checkpoint: { readonly id: CheckpointId; }, request: Parameters[0]): Promise; /** * Await a HITL `resumeHandler` decision, but RACE it against the turn's abort * signal. A Stop that arrives while the turn is parked on a tool-review or * iteration checkpoint used to do nothing until the host eventually answered * (the park await was not cancellable). Racing the signal lets a Stop resolve * the park immediately as an `abort` decision, which `handleHITLDecision` * turns into `setStopReason('cancelled') + markCancelled + stop`. Fails closed: * a resume-handler rejection also resolves to `abort` rather than hanging. */ export declare function awaitDecisionOrAbort(ctx: IterationContext, request: Parameters[0]): Promise; export declare function handleHITLDecision(ctx: IterationContext, decision: HITLResumeDecision, checkpointId: CheckpointId, context: string): AsyncGenerator; //# sourceMappingURL=context.d.ts.map