import { Registry } from "../classes/registry"; import { Tokenizable } from "../classes/tokenizable"; import { ToolRegistry } from "../classes/tool_registry"; import type { Tool } from "../classes/tool"; import type { Memory } from "../classes/memory"; import type { Message } from "../classes/message"; import type { Thought } from "../classes/thought"; import type { SpoolReader } from "./spool_reader"; import type { MediaReader } from "./media_reader"; import type { ToolCall } from "../classes/tool_call"; import type { Retrievable } from "../classes/retrievable"; import type { DispatchContextHookRegistrations } from "../types/dispatch_context"; import type { EmitMessageFn, EmitThoughtFn, EmitToolCallFn, EmitToolExecutionStartFn, EmitToolExecutionEndFn, OpenGateFn } from "../types/turn_runner"; /** Payload accepted by the byte-persistence conduits — text, raw bytes, or a stream. */ export type ConduitBytes = string | Uint8Array | ReadableStream; /** Retrieves memories for an LLM execution context. */ export type DispatchMemoryRetrievalFn = (ctx: DispatchContext) => Memory[] | Promise; /** Retrieves messages for an LLM execution context. */ export type DispatchMessageRetrievalFn = (ctx: DispatchContext) => Message[] | Promise; /** Retrieves thoughts for an LLM execution context. */ export type DispatchThoughtRetrievalFn = (ctx: DispatchContext) => Thought[] | Promise; /** Retrieves tool calls for an LLM execution context. */ export type DispatchToolCallRetrievalFn = (ctx: DispatchContext) => ToolCall[] | Promise; /** Retrieves tools for an LLM execution context. */ export type DispatchToolsRetrievalFn = (ctx: DispatchContext) => Tool[] | Promise; /** Refreshes and returns standing instructions for an LLM execution context. */ export type DispatchStandingInstructionsRefreshFn = (ctx: DispatchContext) => (string | Tokenizable)[] | Promise<(string | Tokenizable)[]>; /** Stores a new standing instruction (LLM execution context variant). */ export type DispatchStandingInstructionStoreFn = (ctx: DispatchContext, v: string | Tokenizable) => void | Promise; /** Updates an existing standing instruction (LLM execution context variant). */ export type DispatchStandingInstructionMutateFn = (ctx: DispatchContext, v: string | Tokenizable) => void | Promise; /** Removes a standing instruction (LLM execution context variant). */ export type DispatchStandingInstructionDeleteFn = (ctx: DispatchContext, v: string | Tokenizable) => void | Promise; /** Stores a new memory (LLM execution context variant). */ export type DispatchMemoryStoreFn = (ctx: DispatchContext, v: Memory) => void | Promise; /** Updates an existing memory (LLM execution context variant). */ export type DispatchMemoryMutateFn = (ctx: DispatchContext, v: Memory) => void | Promise; /** Removes a memory by ID (LLM execution context variant). */ export type DispatchMemoryDeleteFn = (ctx: DispatchContext, id: string) => void | Promise; /** Retrieves retrievable records for an LLM execution context. */ export type DispatchRetrievableRetrievalFn = (ctx: DispatchContext) => Retrievable[] | Promise; /** Stores a new retrievable record (LLM execution context variant). */ export type DispatchRetrievableStoreFn = (ctx: DispatchContext, v: Retrievable) => void | Promise; /** Updates an existing retrievable record (LLM execution context variant). */ export type DispatchRetrievableMutateFn = (ctx: DispatchContext, v: Retrievable) => void | Promise; /** Removes a retrievable record by ID (LLM execution context variant). */ export type DispatchRetrievableDeleteFn = (ctx: DispatchContext, id: string) => void | Promise; /** Stores a new message (LLM execution context variant). */ export type DispatchMessageStoreFn = (ctx: DispatchContext, v: Message) => void | Promise; /** Updates an existing message (LLM execution context variant). */ export type DispatchMessageMutateFn = (ctx: DispatchContext, v: Message) => void | Promise; /** Removes a message by ID (LLM execution context variant). */ export type DispatchMessageDeleteFn = (ctx: DispatchContext, id: string) => void | Promise; /** Stores a new thought (LLM execution context variant). */ export type DispatchThoughtStoreFn = (ctx: DispatchContext, v: Thought) => void | Promise; /** Updates an existing thought (LLM execution context variant). */ export type DispatchThoughtMutateFn = (ctx: DispatchContext, v: Thought) => void | Promise; /** Removes a thought by ID (LLM execution context variant). */ export type DispatchThoughtDeleteFn = (ctx: DispatchContext, id: string) => void | Promise; /** Stores a new tool call (LLM execution context variant). */ export type DispatchToolCallStoreFn = (ctx: DispatchContext, v: ToolCall) => void | Promise; /** Updates an existing tool call (LLM execution context variant). */ export type DispatchToolCallMutateFn = (ctx: DispatchContext, v: ToolCall) => void | Promise; /** Removes a tool call by ID (LLM execution context variant). */ export type DispatchToolCallDeleteFn = (ctx: DispatchContext, id: string) => void | Promise; /** Atomically persists a replacement for a complete group of colliding tool calls. */ export type ToolCallGroupReplaceFn = (ctx: DispatchContext, removedIds: readonly string[], replacements: readonly ToolCall[]) => void | Promise; /** * Persists tool-generated media bytes into consumer storage and returns a {@link @nhtio/adk!MediaReader} * (LLM execution context variant). Unlike the `store*` mutation callbacks this returns a value and * does NOT add anything to the turn Sets — the handler builds a {@link @nhtio/adk!Media} from the reader * and persists it via `storeMessage`/`storeToolCall` separately. */ export type DispatchMediaBytesStoreFn = (ctx: DispatchContext, id: string, bytes: ConduitBytes) => MediaReader | Promise; /** * Persists extracted retrievable text bytes into consumer storage and returns a * {@link @nhtio/adk!SpoolReader} (LLM execution context variant). The handler wraps the reader in a * {@link @nhtio/adk!SpooledArtifact} for `new Retrievable({ content })` and persists the record via * `storeRetrievable` separately. Returns a value; does NOT touch the turn Sets. */ export type DispatchRetrievableBytesStoreFn = (ctx: DispatchContext, id: string, bytes: ConduitBytes) => SpoolReader | Promise; /** * Plain input object supplied to {@link DispatchContext} at construction time. * * @remarks * All fetch and mutation callbacks are required — every execution context must have a persistence * layer wired up, even in standalone mode. Optional pre-fetched arrays populate the context's Sets * at construction time without replacing the callbacks (the callbacks are still invoked on * subsequent fetch calls). */ export interface RawDispatchContext { /** `AbortController` whose signal can cancel execution mid-flight. */ turnAbortController?: AbortController; /** Arbitrary key-value store for cross-step state. */ stash?: Record; /** The system prompt for this execution. */ systemPrompt: string | Tokenizable; /** Standing instructions for this execution. */ standingInstructions?: (string | Tokenizable)[]; /** Pre-fetched memories to populate the context at construction. */ memories?: Memory[]; /** Pre-fetched retrievable records to populate the context at construction. */ retrievables?: Retrievable[]; /** Pre-fetched messages to populate the context at construction. */ messages?: Message[]; /** Pre-fetched thoughts to populate the context at construction. */ thoughts?: Thought[]; /** Pre-fetched tool calls to populate the context at construction. */ toolCalls?: ToolCall[]; /** Pre-fetched tools to populate the tool registry at construction. */ tools?: Tool[]; /** Retrieves memories for this execution. */ fetchMemories: DispatchMemoryRetrievalFn; /** Retrieves retrievable records for this execution. */ fetchRetrievables: DispatchRetrievableRetrievalFn; /** Retrieves messages for this execution. */ fetchMessages: DispatchMessageRetrievalFn; /** Retrieves thoughts for this execution. */ fetchThoughts: DispatchThoughtRetrievalFn; /** Retrieves tool calls for this execution. */ fetchToolCalls: DispatchToolCallRetrievalFn; /** Retrieves tools for this execution. */ fetchTools: DispatchToolsRetrievalFn; /** Refreshes and returns standing instructions for this execution. */ refreshStandingInstructions: DispatchStandingInstructionsRefreshFn; /** Stores a new standing instruction. */ storeStandingInstruction: DispatchStandingInstructionStoreFn; /** Updates an existing standing instruction. */ mutateStandingInstruction: DispatchStandingInstructionMutateFn; /** Removes a standing instruction. */ deleteStandingInstruction: DispatchStandingInstructionDeleteFn; /** Stores a new memory. */ storeMemory: DispatchMemoryStoreFn; /** Updates an existing memory. */ mutateMemory: DispatchMemoryMutateFn; /** Removes a memory by ID. */ deleteMemory: DispatchMemoryDeleteFn; /** Stores a new retrievable record. */ storeRetrievable: DispatchRetrievableStoreFn; /** Updates an existing retrievable record. */ mutateRetrievable: DispatchRetrievableMutateFn; /** Removes a retrievable record by ID. */ deleteRetrievable: DispatchRetrievableDeleteFn; /** Stores a new message. */ storeMessage: DispatchMessageStoreFn; /** Updates an existing message. */ mutateMessage: DispatchMessageMutateFn; /** Removes a message by ID. */ deleteMessage: DispatchMessageDeleteFn; /** Stores a new thought. */ storeThought: DispatchThoughtStoreFn; /** Updates an existing thought. */ mutateThought: DispatchThoughtMutateFn; /** Removes a thought by ID. */ deleteThought: DispatchThoughtDeleteFn; /** Stores a new tool call. */ storeToolCall: DispatchToolCallStoreFn; /** Updates an existing tool call. */ mutateToolCall: DispatchToolCallMutateFn; /** Removes a tool call by ID. */ deleteToolCall: DispatchToolCallDeleteFn; /** Optionally replaces a complete tool-call id group in one transaction. */ replaceToolCallGroup?: ToolCallGroupReplaceFn; /** Persists tool-generated media bytes; returns a `MediaReader`. */ storeMediaBytes: DispatchMediaBytesStoreFn; /** Persists extracted retrievable text bytes; returns a `SpoolReader`. */ storeRetrievableBytes: DispatchRetrievableBytesStoreFn; /** Optional hook registrations for emit events. */ hooks?: DispatchContextHookRegistrations; /** Optional gate suspension function. When absent, `waitFor` rejects with {@link @nhtio/adk!E_LLM_EXECUTION_GATE_NOT_SUPPORTED}. */ waitFor?: OpenGateFn; } /** * Context object for a single LLM execution call. * * @remarks * Mirrors the surface of {@link @nhtio/adk!TurnContext} but is path-agnostic — it knows nothing about a * parent context. Mutations apply to local Sets immediately, call persistence callbacks * immediately, and fire the corresponding mutation hook (`storedMemory`, `mutatedMemory`, * `deletedMemory`, etc.) in both standalone and derived dispatches. * * The {@link @nhtio/adk!DispatchRunner} is the only thing that creates a context with a parent * relationship: when dispatched with a `source: TurnContext`, the runner subscribes to the * mutation hooks, queues deltas internally, and flushes them to the parent's Sets at the end of * each iteration. The context itself remains unaware of the parent. * * Middleware/executor signals termination via {@link DispatchContext.ack} (clean completion) * or {@link DispatchContext.nack} (failure). Both set an internal flag the runner reads at * end-of-iteration to decide whether to loop or exit. {@link DispatchContext.isSignalled}, * {@link DispatchContext.isAcked}, and {@link DispatchContext.nackError} are publicly * readable getters so middleware can inspect signal state and bail early. */ export declare class DispatchContext { #private; /** * @param raw - Raw input validated against the schema. * @throws {@link @nhtio/adk!E_INVALID_LLM_EXECUTION_CONTEXT} when `raw` does not satisfy the schema. */ constructor(raw: RawDispatchContext); /** * Returns how many times a tool call with the given checksum has been stored in this execution. * * @remarks * Checksums are computed over `tool + args` (see {@link @nhtio/adk!ToolCall.checksum}). This count lets * the executor detect repeat invocations of the same call without scanning the full Set. * Returns `0` when the checksum has not been seen. * * @param checksum - The `ToolCall.checksum` value to look up. */ toolCallCount(checksum: string): number; /** * Signals successful completion of this execution. * * @remarks * Sets the context's internal signal flag. The {@link @nhtio/adk!DispatchRunner} reads the flag at the * end of each iteration to decide whether to loop or exit. Calling `ack()` does NOT abort the * current iteration — the current pipeline and flush complete first. * * @throws {@link @nhtio/adk!E_LLM_EXECUTION_ALREADY_SIGNALLED} when the context has already been signalled * (whether via `ack()` or `nack()`). */ ack(): void; /** * Registers a handler to run when this context completes successfully via {@link ack}. * * @remarks * The handler does NOT fire on {@link nack} — failed executor runs should leave any * ack-tied subscriptions alone so the consumer can inspect what was registered when * debugging the failure. Returns an unsubscribe function; subscriptions are short-lived * and die with the context regardless. * * The canonical consumer is `ToolRegistry.bindContext(ctx)`, which uses this hook to drop * ephemeral tools (notably forged artifact-query tools from `SpooledArtifact.forgeTools(ctx)`) * at ctx-completion. Consumers may also register custom handlers here for any per-executor * cleanup. * * @param handler - Callback invoked when `ack()` is called. * @returns An unsubscribe function that removes the handler. * * @see {@link @nhtio/adk!ToolRegistry.bindContext} * @see {@link @nhtio/adk!SpooledArtifact.forgeTools} */ onAck(handler: () => void): () => void; /** * Signals failed completion of this execution, optionally with an error. * * @remarks * Sets the context's internal signal flag and stores the error. The {@link @nhtio/adk!DispatchRunner} * reads the flag at the end of each iteration and surfaces the error via the `dispatchEnd` * observability payload and as the rejection reason of `dispatch()`. Calling `nack()` does NOT * abort the current iteration — the current pipeline and flush complete first. * * @param error - Optional error describing the failure. If omitted, a generic Error is used. * @throws {@link @nhtio/adk!E_LLM_EXECUTION_ALREADY_SIGNALLED} when the context has already been signalled. */ nack(error?: Error): void; /** * Returns `true` if `value` is a {@link DispatchContext} instance. * * @remarks * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety. The ADK does not export the * `DispatchContext` class itself as a constructable value — use this guard plus the * {@link DispatchContext} type for runtime detection and TypeScript narrowing. * * @param value - The value to test. * @returns `true` when `value` is a {@link DispatchContext} instance. */ static isDispatchContext(value: unknown): value is DispatchContext; /** Unique identifier for this execution context, generated as UUIDv6 at construction time. */ readonly id: string; /** Stable identifier for the dispatch this context belongs to; set by `DispatchRunner`. */ readonly dispatchId: string; /** 0-based iteration count within the current dispatch; updated by `DispatchRunner`. */ readonly iteration: number; /** `true` when the abort controller signal has fired. */ readonly aborted: boolean; /** The `AbortSignal` from the execution's `AbortController`. */ readonly abortSignal: AbortSignal; /** * Aborts the dispatch's `AbortController` with the supplied reason. Middleware should call this * when refusing to proceed — the runner short-circuits cleanly, `dispatchEnd.status` resolves * to `'aborted'`, and no `error` event is emitted. */ readonly abort: (reason?: unknown) => void; /** `true` once {@link DispatchContext.ack} or {@link DispatchContext.nack} has been called. */ readonly isSignalled: boolean; /** `true` when the context was signalled via {@link DispatchContext.ack}. */ readonly isAcked: boolean; /** The error stored by {@link DispatchContext.nack}, or `undefined` if not nacked. */ readonly nackError: Error | undefined; /** Arbitrary key-value store for cross-step state. */ readonly stash: Registry; /** The system prompt for this execution. */ readonly systemPrompt: Tokenizable; /** Standing instructions for this execution, in insertion order. */ readonly standingInstructions: Set; /** Memories loaded for this execution. */ readonly turnMemories: Set; /** Retrievable records loaded for this execution. */ readonly turnRetrievables: Set; /** Messages loaded for this execution. */ readonly turnMessages: Set; /** Thoughts loaded for this execution. */ readonly turnThoughts: Set; /** Tool calls loaded for this execution. */ readonly turnToolCalls: Set; /** Tool registry for this execution. */ readonly tools: ToolRegistry; /** Fetches memories; delegates to the callback supplied at construction. */ readonly fetchMemories: () => Memory[] | Promise; /** Fetches retrievable records; delegates to the callback supplied at construction. */ readonly fetchRetrievables: () => Retrievable[] | Promise; /** Fetches messages; delegates to the callback supplied at construction. */ readonly fetchMessages: () => Message[] | Promise; /** Fetches thoughts; delegates to the callback supplied at construction. */ readonly fetchThoughts: () => Thought[] | Promise; /** Fetches tool calls; delegates to the callback supplied at construction. */ readonly fetchToolCalls: () => ToolCall[] | Promise; /** Fetches tools; delegates to the callback supplied at construction. */ readonly fetchTools: () => Tool[] | Promise; /** Refreshes and returns standing instructions. */ readonly refreshStandingInstructions: () => (string | Tokenizable)[] | Promise<(string | Tokenizable)[]>; /** Stores a new standing instruction in the local Set and persistence layer. */ readonly storeStandingInstruction: (v: string | Tokenizable) => Promise; /** Updates an existing standing instruction in the local Set and persistence layer. */ readonly mutateStandingInstruction: (v: string | Tokenizable) => Promise; /** Removes a standing instruction from the local Set and persistence layer. */ readonly deleteStandingInstruction: (v: string | Tokenizable) => Promise; /** Stores a new memory in the local Set and persistence layer. */ readonly storeMemory: (v: Memory) => Promise; /** Updates an existing memory in the local Set and persistence layer. */ readonly mutateMemory: (v: Memory) => Promise; /** Removes a memory from the local Set and persistence layer by ID. */ readonly deleteMemory: (id: string) => Promise; /** Stores a new retrievable record in the local Set and persistence layer. */ readonly storeRetrievable: (v: Retrievable) => Promise; /** Updates an existing retrievable record in the local Set and persistence layer. */ readonly mutateRetrievable: (v: Retrievable) => Promise; /** Removes a retrievable record from the local Set and persistence layer by ID. */ readonly deleteRetrievable: (id: string) => Promise; /** Stores a new message in the local Set and persistence layer. */ readonly storeMessage: (v: Message) => Promise; /** Updates an existing message in the local Set and persistence layer. */ readonly mutateMessage: (v: Message) => Promise; /** Removes a message from the local Set and persistence layer by ID. */ readonly deleteMessage: (id: string) => Promise; /** Stores a new thought in the local Set and persistence layer. */ readonly storeThought: (v: Thought) => Promise; /** Updates an existing thought in the local Set and persistence layer. */ readonly mutateThought: (v: Thought) => Promise; /** Removes a thought from the local Set and persistence layer by ID. */ readonly deleteThought: (id: string) => Promise; /** Stores a new tool call in the local Set and persistence layer. */ readonly storeToolCall: (v: ToolCall) => Promise; /** Updates an existing tool call in the local Set and persistence layer. */ readonly mutateToolCall: (v: ToolCall) => Promise; /** Removes a tool call from the local Set and persistence layer by ID. */ readonly deleteToolCall: (id: string) => Promise; /** Replaces a complete colliding tool-call group and persists the replacement. */ readonly replaceToolCallGroup: (ids: readonly string[], replacements: readonly ToolCall[]) => Promise; /** * Persists tool-generated media bytes into consumer storage and returns a {@link @nhtio/adk!MediaReader}. * * @remarks * This is a low-level persistence conduit, NOT a mutation: it does not add to `turnMessages`/ * `turnToolCalls` or fire a `stored*` hook. The handler builds a {@link @nhtio/adk!Media} from the * returned reader (`Media.toolGenerated({ reader })`) and stores the owning primitive — a * {@link @nhtio/adk!Message} attachment or {@link @nhtio/adk!ToolCall} result — via the relevant * `store*` method separately. Persisting bytes without storing the primitive means the framework * never sees the media. */ readonly storeMediaBytes: (id: string, bytes: ConduitBytes) => MediaReader | Promise; /** * Persists extracted retrievable text bytes into consumer storage and returns a * {@link @nhtio/adk!SpoolReader}. * * @remarks * Low-level persistence conduit, same posture as {@link DispatchContext.storeMediaBytes}: returns a * value, touches no Sets, fires no hook. Wrap the reader in a {@link @nhtio/adk!SpooledArtifact} and * pass it as `Retrievable.content`, then persist the record via {@link DispatchContext.storeRetrievable}. */ readonly storeRetrievableBytes: (id: string, bytes: ConduitBytes) => SpoolReader | Promise; /** Emits a `message` hook; fires registered handlers synchronously. */ readonly emitMessage: EmitMessageFn; /** Emits a `thought` hook; fires registered handlers synchronously. */ readonly emitThought: EmitThoughtFn; /** Emits a `toolCall` hook; fires registered handlers synchronously. */ readonly emitToolCall: EmitToolCallFn; /** Emits a `toolExecutionStart` hook; fires registered handlers synchronously. */ readonly emitToolExecutionStart: EmitToolExecutionStartFn; /** Emits a `toolExecutionEnd` hook; fires registered handlers synchronously. */ readonly emitToolExecutionEnd: EmitToolExecutionEndFn; /** Opens a gate and suspends until it resolves, rejects, times out, or is aborted. */ readonly waitFor: OpenGateFn; }