import type { ContextReducer } from '../../compaction/reducer.js'; import { type CompactionConfig } from '../../config/runtime.js'; import type { ProviderChainMember } from '../../provider/fallback.js'; import type { ProviderRetryConfig } from '../../provider/retry.js'; import type { SessionPaths } from '../../session/paths.js'; import type { SessionTokenBudget, SessionTokenBudgetStore } from '../../store/budget/index.js'; import type { SessionCheckpointStore } from '../../store/checkpoint/index.js'; import type { SessionLease, SessionLog } from '../../store/session-log/index.js'; import type { AdvisoryConfig } from '../../types/advisory/index.js'; import type { AgentRuntimeContext, RuntimeToolOverrides } from '../../types/agent/base.js'; import type { AgentContextLevel } from '../../types/agent/factory.js'; import type { WorkingMemoryProvider } from '../../types/agent/working-memory.js'; import type { AuthorizationGateConfig } from '../../types/authorization/index.js'; import type { InputGuardrailSpec, OutputGuardrailSpec } from '../../types/guardrail/index.js'; import { type HITLResumeDecision, type ResumeHandler } from '../../types/hitl/index.js'; import type { CheckpointId, SessionId, TenantId } from '../../types/ids/index.js'; import type { InvocationState } from '../../types/invocation/index.js'; import type { MemoryStore } from '../../types/memory/index.js'; import { type Message } from '../../types/message/index.js'; import type { AgentPersona } from '../../types/persona/index.js'; import type { LLMProvider } from '../../types/provider/index.js'; import type { TaskRouterConfig } from '../../types/router/index.js'; import type { SandboxProvider } from '../../types/sandbox/index.js'; import type { ReviewAnswer } from '../../types/session/answer-review.js'; import type { ProjectId, TopicId } from '../../types/session/ids.js'; import type { BeforeStep, PrepareStepChain, StepResult, StopCondition } from '../../types/session/index.js'; import { type Origin, type SessionEvent, type SessionEventListener, type SessionLogCursor, type SessionLogReplay, type Turn, type TurnConfig, type TurnForkOrigin, type TurnId } from '../../types/session/index.js'; import type { PromoteMemory } from '../../types/session/memory-promotion.js'; import type { Skill } from '../../types/skills/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 { RepairToolCall } from '../../types/tool/repair.js'; import type { BackoffPolicy } from '../../utils/backoff.js'; import type { ModelPricing } from '../../utils/cost.js'; import type { BackgroundJobRegistry } from '../jobs/registry.js'; import { type SelectedResumeState } from './prepare-turn.js'; import type { ProjectInstructionContext } from './project-instructions.js'; import type { PromptCache } from './prompt-cache.js'; import { PendingAnswers, QuestionParkBinding } from './question-park.js'; import { type SteeringChannel } from './steering.js'; export interface QueryParams { /** Share observations across turns of one conversation and filesystem; otherwise run-local. */ fileReadTracker?: import('../../types/tool/index.js').FileReadTracker; /** One ledger shared with the task scheduler and descendant child sessions, keyed by (rootSessionId, rootTurnId). */ budget?: SessionTokenBudget; /** * Where root-turn ledgers are kept (`/budgets/.json`). * Absent: beside the session under {@link QueryParams.paths}, or in memory * for an in-memory {@link QueryParams.sessionLog}. */ tokenBudgetStore?: SessionTokenBudgetStore; /** * Notice when the model issues the identical tool call repeatedly, and * say so on the next `tool_result`. Defaults on. * * `false` removes the tracker entirely rather than gating a branch, so * an opted-out run produces byte-identical messages to one from before * this existed. */ repeatCallAdvisory?: boolean; /** * Tool names this turn may not use, subtracted from its effective list. * See {@link import('../../types/agent/base.js').BaseAgentConfig.deniedTools}. */ deniedTools?: readonly string[]; systemPrompt?: string; persona?: AgentPersona; skills?: Skill[]; basePrompt?: string; provider: LLMProvider; /** * Transient-failure policy for model calls. A single 429 or 503 used to * terminate a turn outright — no driver in the estate retries. Defaults * to {@link DEFAULT_PROVIDER_RETRY}; pass `false` to opt out (e.g. when * the host already wraps the provider with its own policy). * * Only failures that happen BEFORE the first content chunk are retried; * see `withProviderRetry`. */ retry?: Partial | false; /** * Members to fall over to, in order, when {@link provider} cannot serve. * * Absent means what it always meant: one provider, no failover. Each member * is tried at most once per call and the chain never rewinds, so the scope * of a swap is this `query()` — for a host whose call is one user turn, that * is turn scope with no reset to forget. See `withProviderFallback`. * * Two things this does NOT do, both deliberate. Capabilities are negotiated * once against {@link provider}, so a member that declares less will be sent * a request shaped for the head — refuse a disagreeing chain before you * build one. And a fallback loses the prompt cache: the replacement provider * has never seen this conversation, so the turn re-reads its whole context * at full price. */ fallbackProviders?: readonly ProviderChainMember[]; /** * Durability for questions raised by a tool that closed over its * binding before the turn existed. * * The built-in `ask_user_question` is built with the agent's tool * registry, so only whoever builds the tools can hand it one — that is * what lets a single tool instance be durable inside a turn and inert * outside one. Without it, THAT tool's park is only a suspended * `await`: kill the process while somebody is looking at the card and * the answer can never be applied. * * Not required for `ToolContext.requestPause`. The turn builds that * seam per call and binds its own recorder when none is passed, so a * pause raised from a host-authored tool is durable on every surface * rather than only on the one agent class that supplies this. */ questionParks?: QuestionParkBinding; /** * Channel a host uses to hand guidance to the running turn. * * Optional and additive: absent leaves the loop byte-identical. Present, * anything queued during a tool batch is appended to that batch's last * tool result — the only slot a provider will accept text in mid-batch, * and the one the model already reads for tool outcomes. */ steering?: SteeringChannel; /** * The registry a re-entered `ask_user_question` reads its answer from. * * Same shape, same reason and same limit as {@link questionParks}: it * exists for a tool that closed over the instance before the turn did, * and without it a resumed turn re-asks that tool's question. A pause * from `ToolContext.requestPause` needs none, because the turn fills * its own on the resume path. */ pendingAnswers?: PendingAnswers; /** Default per-tool execution deadline. See {@link ToolDefinition.timeoutMs}. */ toolTimeoutMs?: number; /** * Where background jobs this turn starts are held, and killed. * * Host-owned so it can outlive one turn — a registry built per turn could * never be the thing that kills a turn's jobs when the turn is already * gone. This turn's jobs are torn down in the `finally` below; another * run's are untouched. The registry launches host processes, so a turn * that also supplies a {@link sandboxProvider} does not expose it to tools: * background execution is refused rather than silently bypassing the sandbox. */ backgroundJobs?: BackgroundJobRegistry; /** * Which owner the turn's background jobs belong to. Absent, the turn id: * jobs are stopped when the turn ends. A host that wants a job to * outlive the turn that started it — a dev server started in one turn * and read in the next — passes its session id here and calls * `backgroundJobs.killOwner(sessionId)` when the session ends; the turn * then stops nothing at its end and still tells the model when a job * finishes. */ backgroundJobOwner?: string; /** * What else goes in this turn's prompt. * * `static` and `dynamic` contributions reach the system prompt through * `PromptBuilder`; `turn` contributions reach the ephemeral trailing * message once per iteration. A host registers once and the placement * decides where it lands. */ promptContributions?: import('../../prompt/contributions.js').PromptContributionRegistry; /** * Where the `skill` tool loads from. * * Separate from `skills`, which is the LIST that goes in the prompt * manifest. A turn can have the manifest without the tool — that is what * every turn did before the tool existed — and the two are wired * independently on purpose: a host may want the guidance visible without * granting a way to pull bodies in mid-run. */ skillRegistry?: import('../../types/tool/index.js').SkillRegistryRef; /** * Where a message's stored attachments are resolved from. * * Absent is fine for every turn whose attachments are inline, which is * every turn that existed before this. A message carrying a ref with no * store REFUSES rather than dropping the attachment. */ attachmentStore?: import('../../store/attachment/index.js').AttachmentStore; /** * Maximum wall-clock time for resolving the turn's stored attachments. * Defaults to one minute; `0` retains the prior unbounded wait. */ attachmentResolveTimeoutMs?: number; /** * How this turn reaches the web. * * `fetch` and `search` are independent, and this kernel ships only the * first — see `connector/web` for why choosing a search backend here * would choose it for every consumer. */ web?: import('../../types/tool/index.js').ToolContext['web']; /** * Wait between in-loop retries of a failed tool call, with full jitter. * Defaults to {@link DEFAULT_TOOL_RETRY_BACKOFF}. * * Only reached by a tool that opted into retrying * ({@link ToolDefinition.maxRetries}) or a `post_tool_use` hook that asked * for one. Set `initialDelayMs: 0` for the retry-immediately behaviour * this loop had before it had any backoff at all. */ toolRetryBackoff?: Partial; /** Max concurrently-executing concurrency-safe tools in one batch. */ maxToolConcurrency?: number; /** Per-turn cumulative tool attempt limit, including nested calls and retries. Unset is unlimited. Re-supply on resume; durable reservations are never refunded. */ maxToolCalls?: number; /** * Model-visible size cap for a single tool result. Over-budget output is * spilled to the turn directory and replaced with a head+tail preview * naming the path, so nothing is lost and tokens are paid only if the * agent decides the rest is worth re-reading. Set `0` to disable. */ maxToolOutputChars?: number; /** * Screens to run against every tool result, where the registry was not * built with its own. * * This is the turn's half of a boundary whose only other door is the * registry constructor — and a registry is usually the HOST's, assembled * before the turn exists, so a turn-config option is the only way a turn * screens a registry it did not build. A registry built WITH * `resultGuardrails` states its own policy and wins, `[]` included. * * Absent installs {@link DEFAULT_TOOL_RESULT_GUARDRAILS}; an empty array * installs none, which is how a caller turns the default off. */ toolResultGuardrails?: readonly import('../../types/guardrail/index.js').ToolResultGuardrailSpec[]; /** * Smaller preview for text that exceeded maxToolOutputChars, after its full * host output and integrity manifest have been saved. Unset/0 keeps the old * preview size. Does not change the spill threshold, rich blocks or ordinary * results. A failed spill/manifest or a cap too small for its recovery path * retains the ordinary output budget. Re-supply on resume. */ retainedToolPreviewChars?: number; /** * Cap on the RICH channel of a single tool result, in base64 characters. * `0` or absent disables it. Separate from {@link maxToolOutputChars}: * that one bounds characters the model reads, this one bounds the image * payload beside them, which no text budget ever touched. */ maxToolContentBytes?: number; /** * Last chance to fix a tool call the model got wrong, before the error * reaches it. * * A malformed call costs a full round trip otherwise: the error goes * back as a `tool_result`, the model re-reads the entire context, and * issues a second inference to add a missing brace. A host that can * repair the arguments locally — a cheap model handed the schema, or * plain string surgery — turns that into nothing. * * See {@link RepairToolCall}. Declining is normal and cheap: the * original error simply proceeds to the model as before. */ repairToolCall?: RepairToolCall; /** * Programmable halt condition, evaluated after each step's tools have * run so a predicate can see what they returned. * * Before this the only halt was `GuardCoordinator`, which sees four * numeric budgets and never the messages — so a terminal * `submit_answer` tool could not end a turn, and the model had to be * prompt-begged to stop with `maxIterations: 200` as the only backstop. * * Helpers: `stepCountIs`, `hasToolCall`, `anyOf`. */ stopWhen?: StopCondition; /** * Judge the answer the turn is about to settle with, and hand it back * with feedback when it is not good enough. * * `stopWhen` is only consulted after tools have run, so there was no * seam at the point the model stops calling them: the turn finalized * with whatever it had. Verify-then-fix — run the build, feed the * failure back, let it try again — meant starting a new turn and * re-supplying the context the first one had already assembled. * * Bounded by {@link maxAnswerReviews}. Never called on the forced-final * turn, which exists to extract a closing summary under pressure. * Exceptions or malformed verdicts fail the turn; cancellation stops waiting. */ reviewAnswer?: ReviewAnswer; /** * Decide what this turn should leave behind when it settles. * * See {@link PromoteMemory}. Absent means nothing is offered and the * run behaves exactly as it did. */ promoteMemory?: PromoteMemory; /** Corrections allowed before the turn stops. Nonnegative safe integer; default 3. Consumed rejections survive checkpoints. */ maxAnswerReviews?: number; /** Called with each completed step, as it completes. */ onStepFinish?: (step: StepResult) => void; /** * Shape each step before the model is called: narrow the tool surface, * swap the model, add one-step guidance, change sampling. * * `stopWhen` let a turn decide TO STOP from what its steps produced; * this is the other half — deciding how the next step should look. * Without it, the tool surface and model are fixed at `query()` time, * so a phased agent (research with search tools, write with file tools, * verify with a cheaper model) had to be three separate turns, each * starting blind to the last one's context. * * Narrowing `activeTools` costs a prompt-cache prefix, since tools * render at position 0 — worth it at a real phase boundary, not every * step. It does not touch `tool_choice`: not every provider has an * `allowed_tools`, and moving `tool_choice` invalidates cached MESSAGE * blocks too, which is a strictly worse trade for the same effect. * * Fails open — a throw leaves the step with the turn's configuration. */ prepareStep?: PrepareStepChain; /** * Refuse the next model call before it is made. See {@link BeforeStep}. * A throw fails CLOSED, opposite to `prepareStep` beside it. */ beforeStep?: BeforeStep; /** * Produce a locally validated structured result. Defaults to an output tool; * mode:'native' requests JSON Schema from an explicitly capable driver. * Host review and bounded corrections apply before publication. */ structuredOutput?: StructuredOutputConfig; /** * Checks run BEFORE the first model call. A block settles the turn as * `input_guardrail` having spent nothing. * * namzu's three tool gates all point one way — they protect the world * from the agent. These are the other direction. */ inputGuardrails?: readonly InputGuardrailSpec[]; /** * Checks run against the FINAL result. A block settles the turn as * `output_guardrail`; a `rewrite` replaces the text (so a PII policy * can redact rather than discard the whole answer). * * These gate the result, not the stream: `text_delta` events already * reached the host, so a rewrite arrives as a correction alongside a * `guardrail_triggered` event. */ outputGuardrails?: readonly OutputGuardrailSpec[]; tools: ToolRegistryContract; turnConfig: TurnConfig; allowedTools?: string[]; agentId: string; agentName: string; workingDirectory?: string; /** * Directories besides the working directory the file tools may reach, * absolute; a sandboxed turn binds each read-write. See * `ToolContext.additionalDirectories`. */ additionalDirectories?: readonly string[]; /** * What a file tool's path outside `workingDirectory` and * `additionalDirectories` becomes, on a turn with no sandbox. * * `'refuse'` (the default) keeps the boundary a refusal the tool returns. * `'review'` makes it a question asked before the call runs: the call is * marked (`ToolCallSummary.escalation.outsidePaths`), routed to the * turn's review even when its tool only reads and even where an `allow` * rule or a remembered grant would have covered it, and — once approved * — reaches exactly the named paths for that call alone. A `deny` rule * still refuses it. The review's own mode decides it, so a turn whose * policy approves everything approves these too, on the audit record. * * Only tools that declare `pathArgument` are looked at; a sandboxed turn * is never, because the path is not mounted there to be reached. */ outsideRootAccess?: 'refuse' | 'review'; /** * Whether a call may ask to run outside the turn's sandbox (the shipped * `bash` tool's `dangerously_disable_sandbox`). * * `'refuse'` (the default) refuses every such request. `'review'` routes * it to the turn's review every time; it runs unconfined only when the * decision confirms its id (`HITLResumeDecision.confirmedEscalations`), * which `createReviewHandler` does only after asking a person, or with * `unattendedSandboxEscape: 'allow'`. Every confirmation and refusal is * written to the audit trail. */ sandboxEscape?: 'refuse' | 'review'; pricing?: ModelPricing; enableActivityTracking?: boolean; messages: Message[]; signal?: AbortSignal; resumeHandler: ResumeHandler; resumeFromCheckpoint?: CheckpointId; /** * The answer to the decision the checkpoint parked on, collected * out-of-band — typically in a different process. * * Recording a park makes the request survive a restart; this is what * makes the ANSWER survive one. Without it a resumed turn repairs the * unanswered `tool_use` blocks away and lets the model re-decide, so a * human's "yes, delete that row" degrades into "ask the model again and * hope it asks for the same thing". * * Applies only to a `tool_review` park (the others leave no tool calls * to apply a decision to) and only when the checkpoint's tool calls * still match the ones the decision was made about — otherwise the * decision is ignored and the repair path runs, because consent to one * batch is not consent to a different one. */ pendingDecision?: HITLResumeDecision; /** * How long a HITL decision may take before the park is written to the * checkpoint store. Defaults to {@link PARK_RECORD_DELAY_MS}. * * A park is only worth persisting if a human is actually looking at it: * a programmatic handler answers in microseconds, and the iteration * gate runs on every iteration, so recording every park unconditionally * would take a long turn from one full-history checkpoint write per * iteration to three. Set `0` to record every park (tests, or a host * that wants an unconditional audit trail). */ parkRecordDelayMs?: number; /** * Span this turn should hang off, when it is a delegated one. * * A spawned sub-agent is part of its parent's work, and a trace that * shows the delegation is the whole reason to trace a supervisor at * all. Absent for a top-level turn, which correctly starts its own root. */ parentSpan?: import('@opentelemetry/api').Span; /** Session scope for the turn. Required — every turn is attributed to a Session. */ sessionId: SessionId; /** * Topic the Session lives under. Required — every turn carries the full * five-layer scope (Tenant → Project → Topic → Session → Turn). * Denormalized from `session.topicId`; callers build this alongside * `sessionId` so the query pipeline never needs a second SessionStore * round-trip to recover it. */ topicId: TopicId; /** Long-lived goal scope for the turn. Required. */ projectId: ProjectId; /** Isolation boundary (Convention #17). Required. */ tenantId: TenantId; /** * Where the session lives on disk (`/projects//…`). * Defaults to `SessionPaths` under `resolveNamzuHome()`. Namzu never writes * under the working directory. */ paths?: SessionPaths; /** * Optional checkpoint persistence override. Absent: checkpoint documents go * to `/checkpoints/`, or stay in memory for an in-memory * {@link QueryParams.sessionLog}. */ checkpointStore?: SessionCheckpointStore; /** * The lease this worker holds on the session, from `claimSession`. Every * record the turn appends carries its fence (`gen`), so a worker that * stalled past its lease is refused rather than writing into a session * somebody else has taken over. Absent: `query()` claims the lease itself * and releases it when the turn settles or parks. */ lease?: SessionLease; /** * The session log this turn appends to. Defaults to the log at * {@link QueryParams.paths}. An `InMemorySessionLog` with no `paths` keeps * the whole session in memory: its checkpoints, its ledger and its child * sessions. */ sessionLog?: SessionLog; /** * Where a reconnecting consumer left off, so this turn's stream can start by * handing back what it missed. * * The case this serves is the one that exists without a network hop: the * process holding the turn died, and the consumer watching it is coming back * to a turn that has to be resumed. Pair it with `resumeFromCheckpoint` — or * reach it through {@link import('./resume-session.js').resumeSession}, which is the * surface that does both — and the missed durable events are yielded, in * order, before the resumed turn emits anything of its own. * * On a turn with no log to catch up on the cursor is answered honestly rather * than ignored: a `sinceSeq` above what exists is `cursor_ahead`, not * silence. * * What comes back is message-granular. Streaming deltas are never persisted * — see {@link import('../../types/session/events.js').isEphemeralEvent} — * so a late subscriber recovers the assistant text, the tool results and the * lifecycle, not the keystroke cadence that produced them. */ eventCursor?: SessionLogCursor; /** * What became of {@link QueryParams.eventCursor}. * * A callback rather than an event on the stream, because the answer is about * the SUBSCRIPTION and not about the turn — and rather than a throw, because * a stale cursor is a client's problem and must not be able to stop a turn * from continuing. A host that receives `unavailable` re-derives from the * transcript; one that receives nothing at all would splice a hole into its * state and never know. * * Called once, before the turn's first event, and only when a cursor was * supplied. */ onEventReplay?: (replay: SessionLogReplay) => void; /** * Continue this turn (with `resumeFromCheckpoint`). Absent: a new turn is * begun, and refused with `TurnInProgressError` when the session already * has an active one. */ turnId?: TurnId; /** * Close an `interrupted` active turn — one whose process is gone — with * `turn_failed{interrupted}` before this turn begins, instead of refusing * with `TurnInProgressError`. A running or paused turn is never closed * this way. An interactive host that never resumes an interrupted turn * sets it. */ abandonInterrupted?: boolean; /** * Which protocol opened this turn, and the caller-side ids it used * (`turn_started.origin`). A protocol adapter records the client's own * turn id here (`externalTurnId`) rather than making it a namzu id. */ origin?: Origin; /** * Present when this session was forked from another session's checkpoint: * written into `session_started.forkedFrom` when the log is started, and * carried on the returned turn. See `prepareForkState`. */ forkedFrom?: TurnForkOrigin; /** Present on a child session: the session that delegated it. */ parentSessionId?: SessionId; /** Present on a child session: the parent turn whose tool call spawned it. */ parentTurnId?: TurnId; depth?: number; promptCache?: PromptCache; contextLevel?: AgentContextLevel; continuationMode?: boolean; taskStore?: TaskStore; runtimeToolOverrides?: RuntimeToolOverrides; runtimeContext?: AgentRuntimeContext; taskScheduler?: import('../../types/agent/scheduler.js').TaskScheduler; /** * Text queued for this turn since its last turn, drained at the boundary. * * A callback because the queue belongs to whoever accepts the messages, * and an array captured here would be whatever was queued before the turn * started. See `BaseAgentConfig.inboundMessages` for what it closes. */ inboundMessages?: () => import('../../types/message/index.js').Message[]; /** * Wake a background-task hold when operator input is available, without draining it. * Resolve immediately if input is already pending. Otherwise wait for its arrival; * the supplied signal ends the wait and must release any listeners. Messages are * still consumed only through `inboundMessages` at a provider-valid boundary. */ waitForInbound?: (signal: AbortSignal) => Promise; /** * Live project policy for this turn. Unlike `inboundMessages`, snapshot * replacement is durable state and never implies another model turn. */ projectInstructionContext?: ProjectInstructionContext; /** * Where this conversation's durable state lives. * * Supplies the permission mode when `turnConfig.permissionMode` names * none, and receives the flip when a plan is approved. Absent is the * ordinary case: a turn with no topic state behaves exactly as it did. */ topicStateStore?: import('../../store/topic/state.js').TopicStateStore; /** * The live permission-mode box, when the caller holds one too. * * Whoever builds the coordinator tools needs to flip this from the * approval hook, and that is not this function. Sharing the object is * what lets an approved plan leave plan mode in the SAME run. */ permissionModeRef?: { current: import('../../types/permission/index.js').PermissionMode; }; /** * A name for the policy `resumeHandler` implements. * * Only ever written to the durable log and shown to an operator, so it * costs nothing to omit — but omitting it means every entry about who * approved something says `host`, which is the answer that helps least. */ approvalPolicyName?: string; /** * Receive this turn's approval-policy box, so it can be swapped mid-run. * * The box is built HERE rather than passed in, unlike * {@link permissionModeRef}, because changing the policy emits a durable * event and only the turn holds the emitter. A host that constructed its * own box would be able to change the policy without recording it, which * is the one thing this must not allow. */ onApprovalPolicy?: (policy: import('../../types/hitl/policy.js').SessionApprovalPolicy) => void; /** * Where a worker completion goes when no tool call is waiting for it. * * Supplied by whoever built the coordinator tools, because the tools and * this loop have to share one inbox: the tools claim what they deliver, * and the loop delivers what is left. Omitted, the loop drains nothing and * the behaviour is exactly what it was before the inbox existed. */ completionInbox?: import('../../scheduler/completion-inbox.js').CompletionInbox; onContextCreated?: (ctx: { planManager: import('../../manager/plan/lifecycle.js').PlanManager; }) => void; taskRouter?: TaskRouterConfig; advisory?: AdvisoryConfig; compactionConfig?: CompactionConfig; /** * Where what the turn learned is written when it ends: its decisions, * discoveries and failures, as one entry tagged `learning`. Episodic * memory (the working state) dies with the turn; this is the bridge to * the semantic store a later turn searches. Absent means nothing is * written. A store that fails is logged and never fails the turn. */ consolidateInto?: MemoryStore; /** * Optional neutral working-memory seam. When set, the iteration loop * re-renders the provider's string into a single pinned leading system * message every turn (the primacy-edge, compaction-preserved slot). * Absent ⇒ `refreshWorkingMemory` early-returns and the turn path is * byte-identical. */ workingMemoryProvider?: WorkingMemoryProvider; /** * Replace context reduction for this turn. * * Outranks `compactionConfig.strategy`, and the built-in structured pass * does not also run: two mechanisms editing one history in the same pass * cannot both be reasoned about. See `ContextReducer` for the invariants a * reducer is expected to keep. */ contextReducer?: ContextReducer; agentBus?: import('../../bus/index.js').AgentBus; authorizationGate?: AuthorizationGateConfig; pluginManager?: import('../../plugin/lifecycle.js').PluginLifecycleManager; sandboxProvider?: SandboxProvider; /** * Maximum time the turn waits for sandbox teardown, in milliseconds. * * Defaults to 30 seconds. A fresh private signal is passed to `destroy()`; * the turn also races the returned promise so an implementation that ignores * cancellation cannot pin `drainQuery()`. Set `0` to retain an unbounded * teardown wait. */ sandboxTeardownTimeoutMs?: number; invocationState?: InvocationState; /** * Capability-mismatch handling. Default `false`: when the request asks * for something the provider driver declared it cannot do (tools * registered against a `supportsTools: false` driver, image * attachments against a `supportsVision: false` driver), the runtime * warns loudly, emits a `capability_warning` run event, and degrades * explicitly (tool surfaces stripped from prompt + request; * attachments left unmapped by the driver). The same policy is checked * immediately before every request for image/document blocks produced by a * tool, because those do not exist at turn setup. `true`: throw instead of * degrading. */ strictCapabilities?: boolean; } export declare function query(params: QueryParams): AsyncGenerator; type DrainQueryParams = Omit & { resumeHandler?: ResumeHandler; }; export declare function drainQuery(params: Omit & { resumeHandler?: ResumeHandler; }, listener?: SessionEventListener): Promise; /** @internal Canonical resume state already selected by `resumeSession`. */ export declare function drainQueryWithSelectedResumeState(params: DrainQueryParams, state: SelectedResumeState, listener?: SessionEventListener): Promise; export {}; //# sourceMappingURL=index.d.ts.map