import { RawTurnContext } from "./contracts/turn_runner_context"; import type { TurnRunnerConfig } from "./contracts/turn_runner_config"; import type { TurnEvent, TurnEventListener, TurnObservabilityEvent, TurnObservabilityEventListener } from "./types/turn_runner"; export type { TurnPipelineMiddlewareFn, TurnStreamableContent, TurnToolCallContent, TurnStartEvent, TurnEndEvent, TurnGateClosedEvent, ToolExecutionStartEvent, ToolExecutionEndEvent, EmitMessageFn, EmitThoughtFn, EmitToolCallFn, EmitToolExecutionStartFn, EmitToolExecutionEndFn, OpenGateFn, TurnEvents, TurnEvent, TurnEventListener, TurnObservabilityEvents, TurnObservabilityEvent, TurnObservabilityEventListener, } from "./types/turn_runner"; /** * Executes a single agent turn through paired input and output middleware pipelines. * * @remarks * Construction validates `config` eagerly and throws {@link @nhtio/adk!E_INVALID_TURN_RUNNER_CONFIG} if it * does not satisfy the schema — fail-fast so misconfiguration surfaces before any turn runs. * * Each call to {@link TurnRunner.run} threads a {@link @nhtio/adk!TurnContext} through the input pipeline, * invokes the model, then threads the result through the output pipeline. Middleware on each side * can read and mutate the context for pre- and post-processing (e.g. message normalisation, tool * call dispatch, response filtering). * * **Two event buses:** * - Functional bus (`on` / `off` / `once`): `message`, `thought`, `toolCall` — pipeline-affecting * events that middleware raises throughout turn execution. * - Observability bus (`observe` / `unobserve` / `observeOnce`): `turnStart`, `turnEnd`, * `turnGateOpen`, `turnGateClosed`, `error` — instrumentation-only events that monitor execution * without participating in it. * * Streaming content is surfaced via `message` and `thought` events; tool call lifecycle via * `toolCall`; non-fatal pipeline errors via the observability `error` event; gate lifecycle via * `turnGateOpen` and `turnGateClosed` — all throughout execution. * * @example * ```ts * const runner = new TurnRunner({ * fetchMemoriesCallback: async (ctx) => memoryStore.query(ctx), * fetchMessagesCallback: async (ctx) => messageStore.history(ctx), * fetchThoughtsCallback: async (ctx) => thoughtStore.history(ctx), * fetchToolCallsCallback: async (ctx) => toolCallStore.history(ctx), * }) * // Functional bus — pipeline events * runner.on('message', (chunk) => process.stdout.write(chunk.aDelta)) * // Observability bus — instrumentation * runner.observe('error', (err) => console.error(err.toString())) * runner.observe('turnStart', ({ turnId }) => console.log('turn started', turnId)) * runner.observe('turnGateOpen', (gate) => { * if (gate.reason === 'tool_approval') { * gate.resolve(true) // approve immediately for this example * } * }) * await runner.run({ * turnAbortController: new AbortController(), * systemPrompt: 'You are a helpful assistant.', * standingInstructions: [], * }) * ``` */ export declare class TurnRunner { #private; /** * Returns `true` if `value` is a {@link TurnRunner} instance. * * @remarks * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety. * * @param value - The value to test. * @returns `true` when `value` is a {@link TurnRunner} instance. */ static isTurnRunner(value: unknown): value is TurnRunner; /** * @param config - Construction-time configuration validated against the turn-runner config schema. * @throws {@link @nhtio/adk!E_INVALID_TURN_RUNNER_CONFIG} when `config` does not satisfy the schema. */ constructor(config: TurnRunnerConfig); /** * Removes a previously registered functional listener for `event`. * * @param event - The event to stop listening to. * @param listener - The listener function to remove. * @returns `this` for chaining. */ off(event: TurnEvent, listener: TurnEventListener): this; /** * Registers a persistent functional listener for `event`. * * @param event - The event to listen to. * @param listener - The function to call on each emission. * @returns `this` for chaining. */ on(event: TurnEvent, listener: TurnEventListener): this; /** * Registers a one-time functional listener for `event` that is automatically removed after the * first emission. * * @param event - The event to listen to. * @param listener - The function to call on the next emission. * @returns `this` for chaining. */ once(event: TurnEvent, listener: TurnEventListener): this; /** * Removes a previously registered observability listener for `event`. * * @param event - The event to stop observing. * @param listener - The listener function to remove. * @returns `this` for chaining. */ unobserve(event: TurnObservabilityEvent, listener: TurnObservabilityEventListener): this; /** * Registers a persistent observability listener for `event`. * * @remarks * Use the observability bus (`observe` / `unobserve` / `observeOnce`) for instrumentation: * turn lifecycle, gate lifecycle, and non-fatal errors. Use the functional bus (`on` / `off` / * `once`) for pipeline-affecting events: `message`, `thought`, `toolCall`. * * @param event - The event to observe. * @param listener - The function to call on each emission. * @returns `this` for chaining. */ observe(event: TurnObservabilityEvent, listener: TurnObservabilityEventListener): this; /** * Registers a one-time observability listener for `event` that is automatically removed after * the first emission. * * @param event - The event to observe once. * @param listener - The function to call on the next emission. * @returns `this` for chaining. */ observeOnce(event: TurnObservabilityEvent, listener: TurnObservabilityEventListener): this; /** * Executes a single agent turn against the provided raw context. * * @remarks * Returns `Promise` intentionally — all meaningful output surfaces via events, not return * values. Register listeners before calling `run`: observability events (`turnStart`, `turnEnd`) * bracket execution; functional events (`message`, `thought`, `toolCall`) fire throughout; * observability `error` carries non-fatal pipeline failures; `turnGateOpen` and `turnGateClosed` * fire when middleware suspends via `ctx.waitFor()`. Awaiting this method only tells you the * pipeline has finished, not what it produced. * * Constructs a validated {@link @nhtio/adk!TurnContext} from `context` (throwing * {@link @nhtio/adk!E_INVALID_TURN_CONTEXT} on failure), then runs the input middleware pipeline. * Abort signals are silently swallowed. * * @param context - Raw input validated and wrapped into a {@link @nhtio/adk!TurnContext} before execution. * @throws {@link @nhtio/adk!E_INVALID_TURN_CONTEXT} when `context` does not satisfy the schema. */ run(context: RawTurnContext): Promise; }