@dudousxd/nestjs-agent 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a2ui/index.d.cts +3 -3
- package/dist/a2ui/index.d.ts +3 -3
- package/dist/{chat-queue.service-BjPCw4Pf.d.ts → chat-queue.service-MYNBAY3P.d.ts} +24 -2
- package/dist/{chat-queue.service-C49HIuEV.d.cts → chat-queue.service-OY6mUgB9.d.cts} +24 -2
- package/dist/durable/index.cjs +241 -111
- package/dist/durable/index.cjs.map +1 -1
- package/dist/durable/index.d.cts +1 -1
- package/dist/durable/index.d.ts +1 -1
- package/dist/durable/index.js +176 -46
- package/dist/durable/index.js.map +1 -1
- package/dist/{index-BBkyvNUi.d.cts → index-Ba_0o9Ze.d.ts} +33 -5
- package/dist/{index-CRCbsO6E.d.ts → index-QYQiIXCI.d.cts} +33 -5
- package/dist/index.cjs +249 -119
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +181 -51
- package/dist/index.js.map +1 -1
- package/dist/workflows/index.cjs.map +1 -1
- package/dist/workflows/index.d.cts +1 -1
- package/dist/workflows/index.d.ts +1 -1
- package/dist/workflows/index.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/workflows/agent-workflows.module.ts","../../src/workflows/agent-run.flow.ts","../../src/workflows/agent-turn.executor.ts","../../src/agent-deps.ts","../../src/agent.options.ts","../../src/queue/chat-queue.token.ts","../../src/runner/agent-step-bodies.ts","../../src/workflows/agent-reply.signal.ts","../../src/workflows/turn-journal.ts","../../src/workflows/workflows-agent-runner.ts","../../src/in-process-sink.ts"],"sourcesContent":["import { AGENT_WORKFLOWS_RUNNER } from '@dudousxd/nestjs-agent-core';\nimport { Global, Module } from '@nestjs/common';\nimport { AgentRunFlow, AgentRunSegmentFlow } from './agent-run.flow.js';\nimport { AgentTurnExecutor } from './agent-turn.executor.js';\nimport { WorkflowsAgentRunner } from './workflows-agent-runner.js';\n\n/**\n * Agent turns on NestJS's `@nestjs/workflows`. Import it next to `WorkflowsModule.forRoot()` and\n * `AgentModule.forRoot({ durable: true })`:\n *\n * ```ts\n * imports: [\n * WorkflowsModule.forRoot(),\n * AgentModule.forRoot({ model, store, durable: true }),\n * AgentWorkflowsModule,\n * ]\n * ```\n *\n * It registers the `aviary.agent.run` workflow (and the one a long turn goes on in) and provides the\n * runner `AgentModule` binds `AGENT_RUNNER` to. Every process registers them, so any process can\n * start a turn; which processes RUN turns is `WorkflowsModule`'s `worker` option: on an API pod\n * that must not, `WorkflowsModule.forRoot({ worker: false })`.\n */\n@Global()\n@Module({\n providers: [\n AgentTurnExecutor,\n AgentRunFlow,\n AgentRunSegmentFlow,\n WorkflowsAgentRunner,\n { provide: AGENT_WORKFLOWS_RUNNER, useExisting: WorkflowsAgentRunner },\n ],\n exports: [AGENT_WORKFLOWS_RUNNER, WorkflowsAgentRunner],\n})\nexport class AgentWorkflowsModule {}\n","import type { AgentLoopResult, AgentRunInput } from '@dudousxd/nestjs-agent-core';\nimport { Workflow, type WorkflowContext, type WorkflowRunner } from '@nestjs/workflows';\nimport {\n AGENT_RUN_SEGMENT_WORKFLOW,\n AGENT_RUN_WORKFLOW,\n type AgentRunSegmentInput,\n AgentTurnExecutor,\n} from './agent-turn.executor.js';\n\n/** An agent turn, as a `@nestjs/workflows` workflow (`aviary.agent.run`). The run id is its instance id. */\n@Workflow(AGENT_RUN_WORKFLOW)\nexport class AgentRunFlow implements WorkflowRunner<AgentRunInput, AgentLoopResult> {\n constructor(private readonly turns: AgentTurnExecutor) {}\n\n run(ctx: WorkflowContext, input: AgentRunInput): Promise<AgentLoopResult> {\n return this.turns.run(ctx, input);\n }\n}\n\n/** A turn going on in a child instance after `stepsPerInstance` model calls. Internal. */\n@Workflow(AGENT_RUN_SEGMENT_WORKFLOW)\nexport class AgentRunSegmentFlow implements WorkflowRunner<AgentRunSegmentInput, AgentLoopResult> {\n constructor(private readonly turns: AgentTurnExecutor) {}\n\n run(ctx: WorkflowContext, segment: AgentRunSegmentInput): Promise<AgentLoopResult> {\n return this.turns.execute(ctx, segment);\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_OPTIONS,\n AGENT_STORE,\n type AgentLoopHooks,\n type AgentLoopResult,\n type AgentRunInput,\n type AgentStore,\n type AgentStreamEvent,\n type BufferedModelTurnResult,\n type Decision,\n type ElicitationReply,\n type HumanReply,\n type LlmStepEnvelope,\n RUN_ENDED_BEFORE_TOOL_CALL,\n RunCancelledError,\n type ToolCallRequest,\n type ToolStepEnvelope,\n agentFailureCode,\n agentRunContext,\n encodeStreamEvent,\n isReplayIntegrityError,\n publishAgentRunFailed,\n releaseThreadRun,\n runAgentLoop,\n runDurationMs,\n runEndTimings,\n settleAll,\n settleDeadRun,\n settleUnsettledDelegation,\n streamFailure,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, Optional } from '@nestjs/common';\nimport {\n ChildWorkflowFailedError,\n NonRetryableStepError,\n StepFailedError,\n WORKFLOWS_MODULE_OPTIONS,\n WorkflowClient,\n type WorkflowContext,\n type WorkflowsModuleOptions,\n} from '@nestjs/workflows';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { childSinkWriter, utcDay } from '../agent-deps.js';\nimport { type AgentModuleOptions, durableEngineOf } from '../agent.options.js';\nimport type {\n ChatQueueService,\n QueuePlan,\n QueueSettleOutcome,\n} from '../queue/chat-queue.service.js';\nimport { AGENT_CHAT_QUEUE } from '../queue/chat-queue.token.js';\nimport { runLlmStep, runToolStep } from '../runner/agent-step-bodies.js';\nimport { AGENT_REPLY, type PendingReply, replyKey } from './agent-reply.signal.js';\nimport {\n SegmentBoundary,\n TurnJournal,\n type TurnOutcome,\n isEngineControlFlow,\n markControlFlow,\n rebuildTurnError,\n serializeTurnError,\n stepFailureCause,\n} from './turn-journal.js';\n\n/** The workflow a turn runs as. */\nexport const AGENT_RUN_WORKFLOW = 'aviary.agent.run';\n/** The workflow a turn goes on in after `stepsPerInstance` model calls. */\nexport const AGENT_RUN_SEGMENT_WORKFLOW = 'aviary.agent.run.segment';\n\nconst DEFAULT_STEPS_PER_INSTANCE = 10;\n\n/** What a segment instance starts from: the turn, its run id, and what the instances before it settled. */\nexport interface AgentRunSegmentInput {\n input: AgentRunInput;\n /** The turn's run id: the id of the instance it started in. */\n runId: string;\n /** 1 for the first child instance. */\n segment: number;\n carried: Record<string, TurnOutcome>;\n}\n\n/** A segment's failure, already settled by the segment that failed: its ancestors only pass it up. */\nclass SegmentFailed extends Error {\n constructor(override readonly cause: ChildWorkflowFailedError) {\n super(cause.message);\n this.name = 'SegmentFailed';\n }\n}\n\n/** A step body's outcome, as the journal keeps it: a step never fails for the loop's own errors. */\ntype StepEnvelope = { v?: unknown } | { e: ReturnType<typeof serializeTurnError> };\n\n/** Errors that fail the same way every attempt: not worth a durable retry. */\nfunction isConfigurationError(error: unknown): boolean {\n return (\n error instanceof Error &&\n (error.name === 'AiConfigurationError' || error.name === 'AgentConfigurationError')\n );\n}\n\n/** The engine refused the run's code (a duplicate name, a ctx call inside a step...): nothing more can be journaled. */\nfunction isFatalDefinitionError(error: unknown): boolean {\n return (\n isReplayIntegrityError(error) ||\n (error instanceof Error &&\n (error.name === 'WorkflowDefinitionError' || error.name === 'WorkflowJournalLimitError'))\n );\n}\n\n/**\n * The agent turn on `@nestjs/workflows`: what `AgentRunFlow` (`aviary.agent.run`) and\n * `AgentRunSegmentFlow` run. Each model call and each tool call is a `ctx.step`, the loop's\n * checkpoints are `ctx.step`s too, a human's reply is a `ctx.waitForSignal(AGENT_REPLY, { key })`,\n * a delegation is `ctx.executeChild`, a detached delegation and the thread's next queued message are\n * `ctx.startChild(..., { parentClose: 'abandon' })`. A cancel is the engine's: `WorkflowClient.cancel`\n * stops the turn at its next `ctx` call, and `WorkflowsAgentRunner.cancel` settles the agent's own\n * state, as it does on the `aviary` engine.\n */\n@Injectable()\nexport class AgentTurnExecutor {\n private readonly logger = new Logger('AgentRunFlow');\n private readonly stepsPerInstance: number;\n\n constructor(\n @Inject(AGENT_DEPS_FACTORY) private readonly factory: AgentDepsFactory,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Optional() @Inject(AGENT_OPTIONS) options?: AgentModuleOptions,\n // By token: this file ships in the `/workflows` bundle, whose copy of the `ChatQueueService`\n // class is not the one `AgentModule` provides.\n @Optional() @Inject(AGENT_CHAT_QUEUE) private readonly queue?: ChatQueueService,\n // `@Optional` so a missing WorkflowsModule reaches `WorkflowsAgentRunner`'s clear boot error.\n @Optional() private readonly client?: WorkflowClient,\n @Optional()\n @Inject(WORKFLOWS_MODULE_OPTIONS)\n private readonly workflowsOptions?: WorkflowsModuleOptions,\n ) {\n const durable = options?.durable;\n const configured =\n durableEngineOf(durable) === 'workflows' && typeof durable === 'object'\n ? durable.stepsPerInstance\n : undefined;\n this.stepsPerInstance =\n configured !== undefined && Number.isInteger(configured) && configured > 0\n ? configured\n : DEFAULT_STEPS_PER_INSTANCE;\n }\n\n /** A turn from its first instance. */\n run(ctx: WorkflowContext, input: AgentRunInput): Promise<AgentLoopResult> {\n return this.execute(ctx, { input, runId: ctx.workflowId, segment: 0, carried: {} });\n }\n\n async execute(ctx: WorkflowContext, segment: AgentRunSegmentInput): Promise<AgentLoopResult> {\n const { input, runId } = segment;\n const journal = new TurnJournal(segment.carried);\n const day = input.day ?? utcDay();\n const deps = this.factory.forAgent(input.agentName);\n const sinkRunId = input.sinkRunId ?? runId;\n const childSink = input.sinkRunId !== undefined;\n /** The original error of a checkpoint body that threw in THIS execution: rethrown as itself. */\n const originals = new Map<string, unknown>();\n /** The calls waiting for a person, shown as the instance's custom status. */\n const pending = new Map<string, PendingReply>();\n const showPending = () =>\n ctx.setStatus(pending.size > 0 ? { pendingReplies: [...pending.values()] } : null);\n\n /** A `ctx.step` whose body never fails the step: what it threw is journaled as its outcome. */\n const checkpoint = <T>(name: string, fn: () => Promise<T>): Promise<T> =>\n journal.op(name, async () => {\n const envelope = (await this.ctxCall(() =>\n ctx.step(name, async (): Promise<StepEnvelope> => {\n try {\n const value = await fn();\n return value === undefined ? {} : { v: value };\n } catch (error) {\n originals.set(name, error);\n return { e: serializeTurnError(error) };\n }\n }),\n )) as StepEnvelope;\n if ('e' in envelope) {\n throw originals.get(name) ?? rebuildTurnError(envelope.e);\n }\n return envelope.v as T;\n });\n const step = <T>(name: string, fn: () => Promise<T>): Promise<T> =>\n checkpoint(journal.unique(name), fn);\n\n /** Wait for a person's reply to call `id`, listed as pending meanwhile. */\n const awaitReply = async (\n call: { id: string; toolName: string; kind: PendingReply['kind'] },\n timeoutMs?: number,\n ): Promise<HumanReply | null> => {\n const name = journal.unique(`reply:${call.id}`);\n pending.set(call.id, {\n key: replyKey(runId, call.id),\n runId,\n toolCallId: call.id,\n toolName: call.toolName,\n kind: call.kind,\n });\n showPending();\n const reply = await journal.op(name, () =>\n this.ctxCall(() =>\n ctx.waitForSignal(name, AGENT_REPLY, {\n key: replyKey(runId, call.id),\n ...(timeoutMs !== undefined ? { timeout: timeoutMs } : {}),\n }),\n ),\n );\n // Not on a suspension: the status written as the instance parks must still list the call.\n pending.delete(call.id);\n showPending();\n return reply as HumanReply | null;\n };\n\n const chainBelow = [\n ...(input.delegationPath ?? []),\n ...(input.agentName !== undefined ? [input.agentName] : []),\n ];\n const subThread = (agentName: string) =>\n step(`subthread:${agentName}`, async () => {\n const thread = await this.store.createThread({ actor: input.actor, transient: true });\n return thread.id;\n });\n\n if (input.sinkRunId !== undefined || input.deliverTo !== undefined) {\n await step('activate', () => this.store.setActiveStream(input.threadId, runId));\n }\n\n const hooks: AgentLoopHooks = {\n runId,\n queueMs: async () => {\n const status = await this.client?.getStatus(runId);\n if (status === undefined || status === null) return undefined;\n const now = this.workflowsOptions?.clock?.now() ?? Date.now();\n const waited = now - status.createdAt;\n return Number.isFinite(waited) && waited >= 0 ? waited : undefined;\n },\n openSink: async () => {\n if (childSink) {\n return childSinkWriter(await deps.sink.open(sinkRunId));\n }\n const writer = await deps.sink.open(runId);\n return {\n write: (chunk) => writer.write(chunk),\n fail: (failure) => writer.fail(failure),\n end: async () => {\n const frame = await this.advanceQueue(ctx, step, journal, runId, input, 'completed');\n if (frame !== undefined) {\n await writer.write(encodeStreamEvent(frame));\n }\n await writer.end();\n },\n };\n },\n awaitApproval: async (call: ToolCallRequest, _toolCtx, opts) => {\n const reply = await awaitReply(\n { id: call.id, toolName: call.name, kind: 'approval' },\n opts?.timeoutMs,\n );\n return reply === null\n ? ({ approved: false, expired: true } satisfies Decision)\n : (reply as Decision);\n },\n awaitAnswers: async (request) => {\n const reply = await awaitReply({\n id: request.id,\n toolName: request.source,\n kind: 'elicitation',\n });\n return (reply ?? { approved: false }) as ElicitationReply | Decision;\n },\n step,\n parallel: settleAll,\n isControlFlowError: isEngineControlFlow,\n runAgent: async (agentName, task) => {\n // Named on the call, before any await: parallel delegations get the same names on a replay.\n const name = journal.unique(`delegate:${agentName}`);\n const subThreadId = await subThread(agentName);\n const child: AgentRunInput = {\n agentName,\n threadId: subThreadId,\n actor: input.actor,\n userText: task,\n day,\n delegationDepth: (input.delegationDepth ?? 0) + 1,\n delegationPath: chainBelow,\n parentRunId: runId,\n sinkRunId,\n };\n return journal.op(name, () =>\n this.ctxCall(() =>\n ctx.executeChild<{\n run(c: WorkflowContext, i: AgentRunInput): Promise<AgentLoopResult>;\n }>(AGENT_RUN_WORKFLOW, child, { id: `${ctx.workflowId}/${name}` }),\n ),\n ) as Promise<{ text: string }>;\n },\n // A detached delegation outlives the turn that started it, and a Stop on that turn: an\n // abandoned child, not a cancelled one.\n startAgent: async ({ agentName, task, toolCallId }) => {\n const name = journal.unique(`detach:${toolCallId}`);\n const subThreadId = await subThread(agentName);\n const child: AgentRunInput = {\n agentName,\n threadId: subThreadId,\n actor: input.actor,\n userText: task,\n day,\n delegationDepth: (input.delegationDepth ?? 0) + 1,\n delegationPath: chainBelow,\n parentRunId: runId,\n deliverTo: { threadId: input.threadId, toolCallId },\n };\n const childRunId = await journal.op(name, async () => {\n const handle = await this.ctxCall(() =>\n ctx.startChild(AGENT_RUN_WORKFLOW, child, {\n id: `${runId}.detached.${toolCallId}`,\n parentClose: 'abandon',\n }),\n );\n return handle.id;\n });\n return { runId: childRunId };\n },\n dispatchLlm: (index: number, envelope: LlmStepEnvelope) => {\n const name = journal.unique(`llm:${index}`);\n if (!journal.has(name)) {\n if (journal.liveModelCalls >= this.stepsPerInstance) {\n throw new SegmentBoundary();\n }\n journal.liveModelCalls += 1;\n }\n return journal.op(name, async () => {\n try {\n return (await this.ctxCall(() =>\n ctx.step(name, (attempt) =>\n runLlmStep(\n this.factory,\n { ...envelope, runId, step: index, sinkRunId, childSink },\n { abortSignal: attempt.signal },\n ).catch((error: unknown) => {\n if (!isConfigurationError(error)) throw error;\n const fatal = new NonRetryableStepError((error as Error).message);\n fatal.name = (error as Error).name;\n throw fatal;\n }),\n ),\n )) as BufferedModelTurnResult;\n } catch (error) {\n // The model's own failure, as the loop knows it: `No output generated`, a provider error.\n if (error instanceof StepFailedError) {\n throw rebuildTurnError(stepFailureCause(error));\n }\n throw error;\n }\n });\n },\n // A tool's failure is a result the model reads, not the step's: the step is retried only after\n // a crash, and the tool's `ctx.idempotencyKey` (`<runId>:<toolCallId>`) is the same on that\n // attempt, so a tool that passes it on does its side effect once.\n dispatchTool: (call: ToolCallRequest, envelope: ToolStepEnvelope) =>\n checkpointTool(journal.unique(`tool:${call.id}`), call, envelope),\n };\n\n const checkpointTool = (name: string, call: ToolCallRequest, envelope: ToolStepEnvelope) =>\n journal.op(name, async () => {\n const outcome = (await this.ctxCall(() =>\n ctx.step(name, async (attempt): Promise<StepEnvelope> => {\n try {\n const value = await runToolStep(\n this.factory,\n {\n ...envelope,\n toolCallId: call.id,\n toolType: call.kind === 'action' ? 'action' : 'read',\n sinkRunId,\n childSink,\n },\n { abortSignal: attempt.signal },\n );\n return value === undefined ? {} : { v: value };\n } catch (error) {\n originals.set(name, error);\n return { e: serializeTurnError(error) };\n }\n }),\n )) as StepEnvelope;\n if ('e' in outcome) throw originals.get(name) ?? rebuildTurnError(outcome.e);\n return outcome.v;\n });\n\n try {\n const result = await runAgentLoop({ ...deps, day }, input, hooks);\n await step('deactivate', () => releaseThreadRun(this.store, input.threadId, runId));\n return result;\n } catch (error) {\n if (error instanceof SegmentBoundary) {\n return this.continueInSegment(ctx, { ...segment, carried: journal.outcomes });\n }\n if (isEngineControlFlow(error) || error instanceof SegmentFailed) {\n throw error;\n }\n if (error instanceof RunCancelledError) {\n await step('deactivate', () => releaseThreadRun(this.store, input.threadId, runId));\n await this.settleDetachedParent(step, runId, input, { status: 'cancelled' });\n throw error;\n }\n const durationMs = runDurationMs(error);\n const timed = durationMs !== undefined ? { durationMs } : {};\n const measured = runEndTimings(error);\n const message = error instanceof Error ? error.message : String(error);\n const code = agentFailureCode(error);\n this.logger.error(`agent run ${runId} failed (${code}): ${message}`);\n publishAgentRunFailed({\n runId,\n threadId: input.threadId,\n code,\n message,\n ...timed,\n ...measured,\n context: agentRunContext(input),\n });\n if (isFatalDefinitionError(error)) {\n // The engine will journal nothing more for this run: settle it straight in the store.\n await settleDeadRun(this.store, {\n runId,\n threadId: input.threadId,\n failure: { code, message, ...timed },\n });\n await (await hooks.openSink()).fail(streamFailure(error));\n throw error;\n }\n try {\n await step('persist:run:fail', async () => {\n await this.store.recordRunEnd?.({\n runId,\n status: 'failed',\n ...timed,\n errorCode: code,\n errorMessage: message,\n });\n await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\n });\n const queueFrame = await this.advanceQueue(\n ctx,\n step,\n journal,\n runId,\n input,\n 'failed',\n message,\n );\n await step('deactivate', () => releaseThreadRun(this.store, input.threadId, runId));\n await this.settleDetachedParent(step, runId, input, { status: 'failed', error: message });\n const writer = await hooks.openSink();\n if (queueFrame !== undefined) {\n await writer.write(encodeStreamEvent(queueFrame));\n }\n await writer.fail(streamFailure(error));\n } catch (settling) {\n // A suspend while settling (a checkpoint's retry backoff) settles on the next execution.\n if (isEngineControlFlow(settling)) throw markControlFlow(settling);\n throw settling;\n }\n throw error;\n }\n }\n\n /** The turn goes on in a child instance, from what this one (and those before it) settled. */\n private async continueInSegment(\n ctx: WorkflowContext,\n segment: AgentRunSegmentInput,\n ): Promise<AgentLoopResult> {\n const next: AgentRunSegmentInput = { ...segment, segment: segment.segment + 1 };\n try {\n return (await this.ctxCall(() =>\n ctx.executeChild(AGENT_RUN_SEGMENT_WORKFLOW, next, {\n id: `${segment.runId}~${next.segment}`,\n }),\n )) as AgentLoopResult;\n } catch (error) {\n // The segment that failed settled the run (its row, its stream, its queue): pass it up.\n if (error instanceof ChildWorkflowFailedError) throw new SegmentFailed(error);\n throw error;\n }\n }\n\n /**\n * Hand the thread on past this settling turn, as the `aviary` engine does: the decision is one\n * checkpoint, and the next message starts as an abandoned child under its own id, so the turn\n * ending doesn't cancel it.\n */\n private async advanceQueue(\n ctx: WorkflowContext,\n step: <T>(name: string, fn: () => Promise<T>) => Promise<T>,\n journal: TurnJournal,\n runId: string,\n input: AgentRunInput,\n outcome: QueueSettleOutcome,\n error?: string,\n ): Promise<AgentStreamEvent | undefined> {\n const queue = this.queue;\n if (\n queue === undefined ||\n !queue.supported ||\n input.sinkRunId !== undefined ||\n input.deliverTo !== undefined\n ) {\n return undefined;\n }\n const plan = await step(`queue:${outcome}`, async (): Promise<QueuePlan> => {\n try {\n const settled =\n outcome === 'completed' && (await this.isCancelled(runId)) ? 'cancelled' : outcome;\n return await queue.plan({\n threadId: input.threadId,\n runId,\n outcome: settled,\n ...(error !== undefined ? { error } : {}),\n });\n } catch {\n return {};\n }\n });\n const next = plan.next;\n if (next === undefined) {\n return plan.frame;\n }\n try {\n await journal.op(journal.unique(`queue:start:${next.runId}`), async () => {\n const handle = await this.ctxCall(() =>\n ctx.startChild(AGENT_RUN_WORKFLOW, next.input, {\n id: next.runId,\n parentClose: 'abandon',\n }),\n );\n return handle.id;\n });\n return plan.frame;\n } catch (failure) {\n if (isEngineControlFlow(failure)) throw failure;\n const reason = failure instanceof Error ? failure.message : String(failure);\n return step('queue:restore', async () => {\n await queue.restore(input.threadId, next, 'start_failed', reason);\n return queue.pausedFrame(input.threadId);\n });\n }\n }\n\n private async isCancelled(runId: string): Promise<boolean> {\n try {\n return (await this.client?.getStatus(runId))?.cancelRequested === true;\n } catch {\n return false;\n }\n }\n\n private async settleDetachedParent(\n step: <T>(name: string, fn: () => Promise<T>) => Promise<T>,\n runId: string,\n input: AgentRunInput,\n outcome: { status: 'failed' | 'cancelled'; error?: string },\n ): Promise<void> {\n const delivery = input.deliverTo;\n if (delivery === undefined) return;\n await step('deliver:detached:unsettled', () =>\n settleUnsettledDelegation({\n store: this.store,\n delivery,\n agent: input.agentName ?? 'default',\n runId,\n status: outcome.status,\n ...(outcome.error !== undefined ? { error: outcome.error } : {}),\n }),\n );\n }\n\n /** A `ctx` call whose interrupt carries core's control-flow marker. */\n private async ctxCall<T>(call: () => Promise<T>): Promise<T> {\n try {\n return await call();\n } catch (error) {\n throw markControlFlow(error);\n }\n }\n}\n","import type { ResolveToolUiCatalog, ToolUiChannelGuide } from '@dudousxd/nestjs-agent-core';\nimport type {\n AgentIntake,\n AgentPricingStore,\n AgentStore,\n ApprovalPolicy,\n HistoryPolicy,\n InputProcessor,\n MemoryConfig,\n ModelProvider,\n OutputProcessor,\n Persona,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n SkillsConfig,\n TokenStreamSink,\n ToolRegistry,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n resolveUiCatalog?: ResolveToolUiCatalog;\n /** genui `channels`: the channel's prompt block, and what tool pushes were delivered as. */\n uiChannelGuide?: ToolUiChannelGuide;\n actionApprovalMode?: 'blocking' | 'independent';\n model: ModelProvider;\n store: AgentStore;\n registry: ToolRegistry;\n rolesPolicy: RolesPolicy;\n /** Who approves an action call, and for how long (from `forRoot({ approvalPolicy })`). Undefined → the requester, no expiry. */\n approvalPolicy?: ApprovalPolicy;\n quota?: QuotaStore;\n sink: TokenStreamSink;\n /** Fallback accounting label; the provider's turn result overrides it when set. */\n modelId?: string;\n systemPrompt: string | PromptBuilder;\n /** App-wide `@SystemPromptContributor()` sections appended after the agent's base prompt. */\n promptContributors: PromptContributor[];\n maxSteps: number;\n /** Nesting ceiling for delegation below this agent. Undefined → the loop's default. */\n maxDelegationDepth?: number;\n /** How many times one agent may appear on a chain. Undefined → the loop's default. */\n maxAgentAppearances?: number;\n /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** The agent's personas (`@Agent({ personas })`) — read by the loop only for a run that names one. */\n personas?: Persona[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\n /**\n * Transient-tool-error retry policy (from module options). Undefined → default ON\n * (`{ attempts: 2, backoffMs: 150 }` with the default classifier); `false` → disabled.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /** How many follow-up suggestions to generate after the final turn. Undefined/0 → off. */\n followUpsCount?: number;\n /** Inject-mode retriever (from `forRoot({ retrieval })`). Undefined → no prompt augmentation. */\n retriever?: Retriever;\n /** Passages inject-mode retrieval requests. Undefined → loop default (5). */\n retrievalTopK?: number;\n /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */\n pricingStore?: AgentPricingStore;\n /** The agent's history ceiling, resolved from `@Agent({ history })` / module options. Undefined → unbounded. */\n historyPolicy?: HistoryPolicy;\n /** Module-wide prompt rewriters, applied before every model call. Empty → none. */\n inputProcessors: InputProcessor[];\n /** Module-wide answer gates. NON-EMPTY MEANS THE TURN'S MODEL OUTPUT IS BUFFERED, not streamed. */\n outputProcessors: OutputProcessor[];\n /** The agent's `@Agent({ outputSchema })`, resolved from DI — never over the wire. Undefined → free text. */\n outputSchema?: StandardSchemaV1;\n /** Extra model calls allowed to repair an answer that failed `outputSchema`. Undefined → 1. */\n outputRepairAttempts?: number;\n /** The agent's `@Agent({ intake })` question set, asked before the turn starts. Undefined → none. */\n intake?: AgentIntake;\n /** Whether the model may call the built-in `ask` tool this turn. Undefined/false → it never sees it. */\n ask?: boolean;\n /**\n * The resolved skills seam (`forRoot({ skills })` + discovered `@Skill` providers). Undefined →\n * no catalog, no `skill` tool, and the turn spends no checkpoint on either.\n */\n skills?: SkillsConfig;\n /**\n * The resolved memory seam (`forRoot({ memory })`). Undefined → no block, no `remember` tool, and\n * the turn spends no checkpoint on either.\n */\n memory?: MemoryConfig;\n}\n\nexport function utcDay(date = new Date()): string {\n return date.toISOString().slice(0, 10);\n}\n\n/**\n * Wraps a parent run's sink writer for a sub-agent: `write` forwards (so the sub-agent's tokens and\n * pending action-tool frames reach the human's live stream), but `end` / `fail` are swallowed — the\n * top-level run owns the stream's lifecycle, so a finished/failed child must not close or error the\n * shared stream out from under the parent that is still running. They do `flush` it: a sink that\n * gathers frames (the SQL sink) writes out what the child left, so the parent's next frame —\n * possibly written on another replica — lands after it.\n */\nexport function childSinkWriter(writer: SinkWriter): SinkWriter {\n return {\n write: (chunk) => writer.write(chunk),\n // The top-level run owns end/fail — but what the child wrote must not be held back past it.\n end: async () => {\n await writer.flush?.();\n },\n fail: async () => {\n await writer.flush?.();\n },\n flush: async () => {\n await writer.flush?.();\n },\n };\n}\n","import type {\n ActionApprovalMode,\n ActionProposal,\n ActionProposalOutcome,\n BackgroundActorResolver,\n PriceCatalogOptions,\n TextActionProposalConfig,\n} from '@dudousxd/nestjs-agent-core';\nimport type {\n ActorResolver,\n AgentHistoryWindow,\n AgentStore,\n ApprovalPolicy,\n EmptyRoles,\n HistoryPolicy,\n InputProcessor,\n MemoryProvider,\n ModelCatalog,\n ModelProvider,\n OutputProcessor,\n PromptBuilder,\n QuotaProvider,\n Retriever,\n RolesPolicy,\n ScopeResolver,\n SkillProvider,\n TokenStreamSink,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type {\n CanActivate,\n InjectionToken,\n ModuleMetadata,\n OptionalFactoryDependency,\n Type,\n} from '@nestjs/common';\nimport type { AgentEngine } from './engine.js';\nimport type { FunctionalTool } from './functional-tool.js';\nimport type { QuotaLimits } from './ledger-quota-provider.js';\nimport type { AgentFunctionCaller } from './nest-ai/agent-functions.js';\nimport type { AgentProtocolAdapter } from './protocol-adapter.js';\n\n/**\n * Which half of the module this process mounts — the split that lets an API pod and a WORKER pod\n * each load `AgentModule` without either one doing the other's job:\n *\n * - `'both'` (default): today's behavior, unconditionally — every controller AND the full durable\n * engine wiring (when `durable` is on). Zero-config single-pod deployments never touch this.\n * - `'http'`: mounts every controller (chat/threads/tool-call/quota/agents/attachments) so the HTTP\n * surface is fully functional, but under `durable` this pod must never EXECUTE agent work. On the\n * `'workflows'` engine that is `WorkflowsModule.forRoot({ worker: false })`; on `'aviary'`,\n * `AgentDurableModuleOptions.surface` (`@dudousxd/nestjs-agent/durable`). This flag only controls\n * the controllers here.\n * - `'engine'`: mounts NO controllers (an API pod's routes have no business existing on a worker\n * pod that never receives HTTP traffic) — everything else (registry/tools/model/store/sinks, the\n * `agent.run` workflow, and its dispatched steps under `AgentDurableModule`) stays wired exactly\n * as `'both'`.\n *\n * A durable deployment mirrors this on `AgentDurableModule.forRoot({ surface })` too — see that\n * module's doc for why the split can't be inferred from this option alone (Nest's static module\n * metadata can't be computed from a runtime-injected value).\n */\nexport type AgentSurface = 'http' | 'engine' | 'both';\n\n/**\n * The durable engine `AgentModuleOptions.durable` runs turns on.\n *\n * - `'workflows'` (what `durable: true` means): NestJS's `@nestjs/workflows`. Import\n * `WorkflowsModule.forRoot()` and `AgentWorkflowsModule` (`@dudousxd/nestjs-agent/workflows`).\n * An API pod that must not run turns imports `WorkflowsModule.forRoot({ worker: false })`.\n * - `'aviary'`: `@dudousxd/nestjs-durable`. Import `DurableModule` and `AgentDurableModule`\n * (`@dudousxd/nestjs-agent/durable`). Choose it for what `@nestjs/workflows` does not do: steps\n * dispatched to a separate fleet over a transport (BullMQ, SQS, ...), Python workers, the\n * SQLite/MikroORM stores, `ctx.patched` for changing a running turn's code in place.\n */\nexport interface AgentDurableOptions {\n /** Default `'workflows'`. */\n engine?: 'workflows' | 'aviary';\n /**\n * `'workflows'` only: model calls per workflow instance. After that many, the turn goes on in a\n * child instance, so no instance's journal grows past what one segment writes (the same idea as\n * `@nestjs/ai`'s `AiAgents` `stepsPerInstance`). Default 10.\n */\n stepsPerInstance?: number;\n}\n\n/** Which durable engine `durable` names: `undefined` when the turns run in-process. */\nexport function durableEngineOf(\n durable: boolean | AgentDurableOptions | undefined,\n): 'workflows' | 'aviary' | undefined {\n if (durable === undefined || durable === false) return undefined;\n if (durable === true) return 'workflows';\n return durable.engine ?? 'workflows';\n}\n\n/**\n * `AgentModuleOptions.attachments` — limits for `POST <base>/attachments`, when the bound\n * `AGENT_ATTACHMENT_STAGING` store does not declare its own (`AgentMediaAttachmentsModule` does, and\n * then it is the only source). Served to clients by `GET <base>/config`.\n */\nexport interface AgentAttachmentsOptions {\n /** Per-file size cap. Defaults to 20 MiB. */\n maxBytes?: number;\n /**\n * Allowed multipart content types. Defaults to what multimodal model providers commonly accept:\n * `image/png`, `image/jpeg`, `image/gif`, `image/webp`, `application/pdf`, `text/plain`, `text/csv`.\n */\n allowedContentTypes?: string[];\n}\n\n/**\n * `AgentModuleOptions.skills` — where a turn's skills come from, and which scopes an actor draws\n * them from. Its PRESENCE turns skills on: `skills: {}` offers whatever the `@Skill`-decorated\n * providers declare, resolved against the actor's own, their tenant's and the deployment's scopes.\n */\nexport interface AgentSkillsOptions {\n /**\n * A provider of your own — skills a host stores and administers itself (per user, per sector, per\n * base). Merged with the discovered `@Skill` classes, and outranking them for a name published at\n * the same scope. Omit → the decorated classes are the whole catalog.\n */\n provider?: SkillProvider;\n /**\n * Which scope tokens an actor draws from, most specific first — the precedence order. Omit → the\n * actor's own (`actor:<id>`), their tenant's (`tenant:<ref>`, when they have one), and `global`.\n * Supply one to add an axis this library has no key for: a sector, a region, a shift.\n */\n scopes?: ScopeResolver;\n /**\n * How many skills the catalog block offers before it starts leaving the widest ones out. Omit →\n * 20. A ceiling on what the SYSTEM PROMPT carries, not on how many a deployment may hold.\n */\n maxSkills?: number;\n}\n\n/**\n * `AgentModuleOptions.memory` — where what the assistant concluded about a person is stored, and how\n * much of it a turn may carry. Its PRESENCE turns memory on.\n *\n * Unlike `skills`, there is no decorator and no zero-config form: a memory is by definition something\n * the agent worked out about someone, so a memory a developer wrote in a class would be an\n * instruction wearing a memory's clothes — which is what `@Skill` and `@SystemPromptContributor()`\n * are for. The rows are the host's from the start.\n */\nexport interface AgentMemoryOptions {\n /**\n * Where the rows live. `forget` is required on it; `write` is what decides the `remember` tool;\n * `search` is what decides whether a turn's block is selected by relevance or read whole. Supply\n * `search` once the applicable set outgrows `maxMemories` — without it the ceiling selects by\n * scope, and the widest scopes are the ones it starves.\n */\n provider: MemoryProvider;\n /**\n * Which scope tokens an actor draws from, most specific first — the precedence order, and the same\n * seam `skills` uses. Omit → the actor's own, their tenant's, and `global`.\n */\n scopes?: ScopeResolver;\n /**\n * How many memories the block carries. Omit → 20. A budget on the PROMPT, never on the store: with\n * a provider that can `search`, this is how many matter right now rather than how many a person\n * may have. Always-on (`pinned`) memories are taken from it first.\n */\n maxMemories?: number;\n /** How long one memory may be, checked when it is written. Omit → 240. */\n maxFactChars?: number;\n}\n\nexport interface AgentModuleOptions {\n /**\n * How an `action` tool waits for its approval. `'blocking'` (default): the turn parks on the\n * decision and resumes when it lands. `'independent'`: the call is recorded as an action proposal\n * and answered at once with a receipt (`{ proposalId, status: 'pending', executed: false }`), the\n * turn finishes, and a background worker runs the action once it is approved — decided through\n * `POST <base>/threads/:threadId/action-proposals/:proposalId/approve|reject`, the approval port or\n * a text command. Needs `backgroundActorResolver` and a store with the proposal capabilities\n * (both checked at boot). See `docs/independent-approvals.md`.\n */\n actionApprovalMode?: ActionApprovalMode;\n /**\n * Resolves the CURRENT actor (id, tenant, roles) for a proposal's recorded `actorRef`/`tenantRef`\n * when the worker runs it — there is no request to read an identity from. Return `null` for an\n * actor that no longer exists or no longer belongs to the tenant; the action then fails rather\n * than running. Required under `actionApprovalMode: 'independent'`.\n */\n backgroundActorResolver?: BackgroundActorResolver;\n /**\n * Tuning for the worker that runs approved proposals under `actionApprovalMode: 'independent'`\n * (started with the module unless `surface: 'http'`). `pollIntervalMs` — how often it looks for\n * queued work, default 1000; `leaseMs` — how long a claim holds before another worker may recover\n * it, default 30000; `maxConcurrency` — proposals claimed per poll, default 1. All positive\n * integers, and `pollIntervalMs` must stay below a third of `leaseMs`. `onSettled` runs after each\n * proposal the worker settles (executed or failed), with the stored proposal — its `outcome` and\n * `executionContext.pageContext` included; a module can subscribe the same way through\n * `ActionProposalWorkerService.onSettled`. `onAdmitted` runs once a settled proposal's outcome\n * was written to its thread — the moment to continue the conversation from it\n * (`ActionProposalWorkerService.onAdmitted` for a module).\n */\n actionProposalWorker?: {\n pollIntervalMs?: number;\n leaseMs?: number;\n maxConcurrency?: number;\n onSettled?(proposal: ActionProposal): void | Promise<void>;\n onAdmitted?(outcome: ActionProposalOutcome): void | Promise<void>;\n };\n /**\n * The words a chat message must consist of to approve or reject a proposal by text, and what the\n * agent answers. English by default (`yes`/`confirm`/`approve`, `no`/`cancel`/`reject`, …); pass\n * `ptBrActionProposalText` from `@dudousxd/nestjs-agent-core` for Portuguese, or your own — either\n * part replaces the default it names, field by field.\n */\n actionProposalText?: TextActionProposalConfig;\n // --- infrastructure ---\n /**\n * The LLM provider. Omit it to run on `@nestjs/ai`: the turns use the models of the application's\n * `AiModule.forRoot({ models })` (the picker lists them by name, `default` first), with each\n * model's settings, `retry` / `timeout` / `resilience`, `fallback`, `pricing` and `onUsage`. Set\n * it to replace them — a `FakeModelProvider` in tests, `aiSdkModel(…)` outside `AiModule`. Not\n * needed when an `engine` runs the turns.\n */\n model?: ModelProvider;\n /**\n * Offer the application's `@nestjs/ai` `@AgentFunction()` methods as agent tools (default), each\n * governed by this library's `@AgentFunction()` options and run through `AiTools.call`, so its guards, interceptors, pipes\n * and filters apply. `false` leaves them to `@nestjs/ai`'s own calls.\n */\n agentFunctions?: boolean;\n /**\n * Who an `@AgentFunction()` call acts for, from the turn's actor — what its guards read. Default:\n * `{ user: actor }`, with no `scopes` (the agent gates by roles); map the actor to scopes here for\n * functions that declare `scopes`.\n */\n agentFunctionCaller?: AgentFunctionCaller;\n /**\n * Where a configured model with no price row gets one, at boot. On application bootstrap every\n * model the `model` provider describes (`aiSdkModel` / `aiSdkModels`) that the bound\n * `AGENT_PRICING_STORE` does not price gets a row — only when it has none, so a price you set is\n * never overwritten — from, in order: `prices` (your own rate card), the built-in AWS GovCloud\n * Bedrock table (for a GovCloud model), then the current [models.dev](https://models.dev) list price\n * (commercial; never used for a GovCloud / China Bedrock model). A model that still has no price, and\n * whose provider reports no cost (anything but OpenRouter / the Vercel AI Gateway), is named in one\n * boot warning with the reason and the `prices` entry that fixes it.\n *\n * Bedrock ids are normalized: an entry for the base id or the `us-gov.` profile id also prices the\n * inference-profile ARN a turn reports. The AWS partition comes from the id (ARN, `us-gov.` prefix),\n * else `region`, else `AWS_REGION` / `AWS_DEFAULT_REGION`.\n *\n * ```ts\n * priceCatalog: {\n * region: 'us-gov-west-1',\n * prices: [\n * { model: 'us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0', input: 3.6, output: 18, cacheRead: 0.36, cacheWrite: 4.5 },\n * ],\n * }\n * ```\n *\n * Omit → models.dev, except under `NODE_ENV=test` (no network from a test suite unless asked).\n * `{ url, fetch }` points at a mirror; `modelsDev: false` never fetches; `false` turns off every\n * source but the built-in table (the warning still runs).\n */\n priceCatalog?: PriceCatalogOptions | false;\n /**\n * Run turns on something other than this library's loop — e.g. `openCode({ host })`. The engine\n * binds `AGENT_RUNNER`; the routes, store, sink, approvals and queue stay the library's. STATIC\n * wiring, like `durable` (see {@link AgentEngine}). Omit → the loop, on `model`.\n */\n engine?: AgentEngine;\n /**\n * The base prompt of the default agent (and of any `@Agent` that declares none) — a string, or a\n * function of the turn's `{ actor, agentName, pageContext }`. Omit → `'You are a helpful\n * assistant.'`.\n */\n systemPrompt?: string | PromptBuilder;\n /**\n * Persistence adapter. Omit it and either import a store module (e.g.\n * `MikroOrmAgentStoreModule.forFeature()`, which binds `AGENT_STORE` globally — it is found and\n * used), or run on the built-in in-memory store — fine for a demo, logged at boot as not for\n * production: threads vanish on restart and are not shared between processes.\n */\n store?: AgentStore;\n /** Live token transport. Defaults to a single-process in-memory sink. */\n sink?: TokenStreamSink;\n /**\n * The caller's budget. `{ limits: { day?: { tokens?, usd? }, month?: { tokens?, usd? } } }` puts\n * ceilings on the built-in ledger provider, and `warnAt` (`0..1`, e.g. `0.8`) a soft limit past\n * which the report carries a `warning`; a {@link QuotaProvider} of your own replaces it. Either\n * way `GET <base>/quota` reports it and a send whose report comes back `blocked` is refused with\n * `429` before the turn starts. Omit → reported (usage off the ledger), never enforced — for a\n * public (anonymous) deployment that means unbounded model spend, so set limits there; they apply\n * per actor, which is per browser in anonymous mode.\n *\n * The USD windows sum the ledger's `cost_usd`: provider-reported cost AND the loop's estimate for a\n * provider that reports none (marked `cost_source = 'estimate'`). `countEstimatedCost: false` counts\n * reported cost only. The default (`true`) is there because otherwise a USD ceiling on Bedrock /\n * OpenAI / Anthropic direct would read $0 and never block.\n */\n quota?: { limits: QuotaLimits; warnAt?: number; countEstimatedCost?: boolean } | QuotaProvider;\n /**\n * Which models a caller may pick — `GET <base>/models`, a send's `model`, a thread's pinned model\n * (`PATCH <base>/threads/:id { model }`). Omit → the catalog the model provider carries\n * (`aiSdkModels`), else none, and a request naming a model is refused.\n */\n models?: ModelCatalog;\n /** Tool authorization gate. Defaults to role-in-`defaultRoles`. */\n rolesPolicy?: RolesPolicy;\n /**\n * Who has to approve an `action` tool call, and how long the request stays open. Defaults to the\n * requester (the thread's own actor) with no expiry. A requirement naming another approver (a\n * role) is enforced by `POST tool-call/approve|reject` through `canDecide` — by default, the\n * deciding actor must hold that role. See `ApprovalPolicy`.\n */\n approvalPolicy?: ApprovalPolicy;\n /**\n * Roles a tool requires when its own `roles` is omitted. Default `[]` — no restriction: every\n * tool is callable by whoever `actorResolver` resolved (an anonymous visitor included, when none is\n * configured). `action` tools still park on approval regardless.\n */\n defaultRoles?: string[];\n /**\n * What an empty roles list means to the default `RolesPolicy`: `'allow'` (default) — no\n * restriction, so a tool that names no roles reaches every resolved actor; `'deny'` — nobody, so a\n * tool needs `roles` (or a non-empty `defaultRoles`) to be reachable. For an app where `[]` means\n * \"no one\" — a `roles` computed from permissions that can come out empty. Binds\n * `ClosedRolesPolicy`. Ignored when `rolesPolicy` is set.\n */\n emptyRoles?: EmptyRoles;\n /**\n * Resolves the acting actor for each request (the identity seam). Omit → the endpoints are public\n * and every browser is its own anonymous actor (`AnonymousActorResolver`: an `HttpOnly` cookie,\n * the actor id a digest of it), so visitors never see each other's threads, quota or attachments.\n * A boot notice says so. Require login with `requestUserActorResolver()` (reads `req.user`), or a\n * resolver of your own over your session / JWT / `nestjs-context`.\n */\n actorResolver?: ActorResolver;\n /** Route prefix the controllers mount under. Defaults to `'agent'` (→ `/agent/chat`, …). */\n path?: string;\n /**\n * Run each turn as a durable workflow instead of in-process: each model call and each tool call\n * is a journaled step, a turn parked on a person survives restarts, and a crashed turn resumes\n * where it was. See {@link AgentDurableOptions} for the two engines; `true` is\n * `{ engine: 'workflows' }`, NestJS's own `@nestjs/workflows`.\n *\n * A `@AiTool` handler runs in whichever worker runs the step rather than in the pod that took the\n * request. A handler that resolves anything per invocation from its caller's execution context (a\n * request-scoped ORM EntityManager, an AsyncLocalStorage tenant, a CLS transaction) must\n * establish that context itself.\n *\n * Multi-pod fleets MUST also wire a cross-process token sink (e.g. a Redis pub/sub\n * `TokenStreamSink`): the turn runs on whichever worker claims it, which may not be the pod\n * holding the SSE connection.\n */\n durable?: boolean | AgentDurableOptions;\n /**\n * Static functional tools (`{ spec, handler }`, e.g. from `createExecuteSqlTool`) to register at\n * boot. For tools that need DI-resolved dependencies, use `provideAgentTool(factory, inject)` in a\n * module's `providers` instead.\n */\n tools?: FunctionalTool[];\n /**\n * Per-tool execution timeout in ms. A tool that runs longer is aborted and recorded as failed (the\n * model receives the timeout as its result and can adapt) instead of hanging the turn. Omit → none.\n */\n toolTimeoutMs?: number;\n /**\n * Retries a tool's own invocation, in place, when it throws a classified-transient error (a DB\n * deadlock, a lock-wait timeout, a serialization failure) — never a new durable checkpoint, just\n * repeated attempts inside the same tool-call step. Default ON: `{ attempts: 2, backoffMs: 150 }`\n * with the default classifier. Set `{ classify }` to widen/narrow which errors count as transient\n * (checked in BOTH the inline and durable-dispatched execution paths via DI, since the classify\n * function itself can't ride a durable step's wire envelope), or `false` to disable entirely. A\n * tool's other (non-transient) failures are unaffected — they remain a one-shot business outcome.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /**\n * Suggest follow-up questions after the final turn. `true` → 3 suggestions; `{ count }` → that many.\n * Costs one extra model call per turn (recorded as `follow_ups` usage), stored on the assistant\n * message's `followUps`. Omit/`false` → disabled.\n */\n followUps?: boolean | { count: number };\n /**\n * Always-on (\"inject\") RAG: before each turn, retrieve passages for the user message and augment\n * the system prompt with them. For agentic retrieval (the model decides when to search) DON'T set\n * this — instead expose the tool: `provideAgentTool(createRetrievalTool(retriever))`. Omit → off.\n */\n retrieval?: { mode: 'inject'; retriever: Retriever; topK?: number };\n\n /**\n * Bounds how much of a thread rides into each turn. Omit and a turn carries EVERY message the\n * thread holds, so a long-lived thread costs more each time and eventually exceeds the model's\n * context limit outright. `{ maxMessages }` and/or `{ maxTokens }` keep the newest that fit;\n * `{ summarize: true }` folds what they left out into a leading summary, at the price of one extra\n * model call per run (recorded as `history_summary` usage). An agent can override this for itself\n * with `@Agent({ history })`.\n */\n history?: AgentHistoryWindow;\n /**\n * A {@link HistoryPolicy} of your own — for a window the built-in can't express (pinning the\n * thread's opening brief, keeping every message that carries a tool result, a budget that varies\n * by actor). A convenience-vs-custom pair: this outranks a\n * module-wide `history`, and `@Agent({ history })` outranks both for the agent that declares it.\n * `select` MUST be pure — see the SPI's determinism contract.\n */\n historyPolicy?: HistoryPolicy;\n\n /**\n * Rewrites the prompt before every model call — masking identifiers, stamping a policy preamble,\n * trimming an oversized tool result. Applies to EVERY agent: a transformation one persona can opt\n * out of is not a control. Transformation only; `history`/`historyPolicy` still own which messages\n * are there to transform. A processor needing DI-resolved dependencies is built in\n * `forRootAsync`'s `useFactory` (which has `inject`), the same way `retrieval.retriever` is.\n */\n inputProcessors?: InputProcessor[];\n /**\n * Gates every model answer before the stream, the store or the next step sees it — redact,\n * replace, or refuse the turn outright (which fails it with an `output_rejected` stream error).\n *\n * REGISTERING ONE TURNS OFF LIVE TOKEN STREAMING. Reading the whole answer and streaming it as it\n * is generated cannot both be true, so the turn's model output is buffered and released in one\n * frame once the chain passes. That is the price of a gate that actually gates; see\n * `AgentLoopDeps.outputProcessors` for exactly what a subscriber still receives live.\n */\n outputProcessors?: OutputProcessor[];\n\n /**\n * Offer every agent the built-in `ask` tool, so the model can put its own clarifying question set\n * to the user when it judges the scope is missing. The turn parks on the answers exactly as it\n * parks on a HITL approval, and they arrive through `POST /agent/tool-call/answer`.\n *\n * `ask` is not a registered tool and has no handler — the loop settles it against a person — so no\n * `RolesPolicy` gates it: asking a question performs nothing. An `@Agent({ ask })` overrides this\n * for one persona. Omit → the model never sees it, and nothing about a turn changes.\n */\n ask?: boolean;\n\n /**\n * Authored procedures any agent may pull in when a task calls for one — per-user, per-tenant or\n * deployment-wide, with the most specific winning. Declared as `@Skill`-decorated providers and/or\n * served by a `provider` of your own; offered to the model as a one-line-each catalog it loads\n * from on demand, so an instruction costs a prompt only on the turns that need it.\n *\n * Omit → no catalog, no `skill` tool, and a turn's checkpoint sequence is byte-identical to one\n * that never had the option. See {@link AgentSkillsOptions}.\n */\n skills?: AgentSkillsOptions;\n\n /**\n * What the assistant has concluded about the actor and their organisation, carried into every turn\n * as a bounded block of one-line facts and written by the model through a built-in `remember` tool.\n *\n * NOT the same thing as retrieval, and not a second name for it: `retrieval` answers from documents\n * a person curated and can fix at the source, memory answers from the agent's own inferences about\n * someone who never saw them written. That is why the rows carry an origin, why the block tells the\n * model they may be wrong, and why `GET /agent/memories` + `DELETE /agent/memories/:id` are part of\n * the feature rather than an optional console.\n *\n * Omit → no block, no `remember` tool, and a turn's checkpoint sequence is byte-identical to one\n * that never had the option. See {@link AgentMemoryOptions}.\n */\n memory?: AgentMemoryOptions;\n\n /**\n * The name of the agent a turn uses when the caller doesn't select one. Omit → the single\n * discovered `@Agent` (when there is exactly one), else `'default'` (a bare assistant if no\n * `@Agent` is registered). Agents themselves are declared as `@Agent`-decorated providers, not here.\n */\n defaultAgent?: string;\n\n /**\n * Class decorators applied to EVERY controller this module mounts — the ecosystem's convention,\n * like `@nestjs/mcp`'s own `decorators`: decide who reaches the agent's routes with the official\n * tools, e.g. `[UseGuards(AuthenticationGuard), Can(AgentPolicy, 'chat')]` from\n * `@nestjs/authentication` / `@nestjs/authorization`. Applied to a subclass of each controller made\n * for this registration, so nothing sticks to the shared classes. The controllers are open to\n * `@nestjs/authorization`'s deny-by-default guard otherwise (`CanAnyone()`), and a `@Can()` passed\n * here is still checked. Static wiring.\n *\n * A guard class in `UseGuards(...)` is built by Nest inside this module, so it needs no provider\n * entry, but what it injects must resolve here: from a global module, or (with `forRootAsync`)\n * from a module in `imports` that exports it. The removed `guards` option registered the guard\n * class itself as a provider; nothing does now.\n */\n decorators?: ClassDecorator[];\n\n /** Upload limits when the staging store declares none. Omit → 20 MiB and the default types. */\n attachments?: AgentAttachmentsOptions;\n\n /**\n * Which half of the module this process mounts (see {@link AgentSurface}). Omit → `'both'`,\n * today's behavior with zero change. STATIC top-level field (like `durable`/`path`) — it decides\n * which controllers exist at module-build time, not something a request can flip.\n */\n surface?: AgentSurface;\n\n /**\n * `false` mounts none of the agent's routes, while everything else runs — the way NestJS's own\n * packages leave routes to you (`@nestjs/authentication`'s \"routes of your own\"): serve them from\n * controllers of your own, protected with the official tools. Either call `AgentService` from\n * them, or extend the exported controllers under your own path and decorators:\n * `@Controller('ops/agent/threads') @Can(AgentPolicy, 'chat') class Threads extends ThreadsController {}`.\n * Static wiring, like `surface`.\n */\n routes?: boolean;\n\n /**\n * Wire protocols served alongside the native one, over the same runs — e.g. `[agUiAdapter()]`\n * mounts `POST <path>/ag-ui` (AG-UI 1.0). Their controllers mount under `path`, behind `decorators`,\n * and not at all on `surface: 'engine'`. STATIC, like `surface`.\n */\n adapters?: AgentProtocolAdapter[];\n}\n\nexport interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {\n inject?: Array<InjectionToken | OptionalFactoryDependency>;\n useFactory: (...args: never[]) => AgentModuleOptions | Promise<AgentModuleOptions>;\n /**\n * Route prefix the controllers mount under (default `'agent'`). Static routing metadata, so it\n * lives here rather than in the async factory result (which resolves too late to mount routes).\n */\n path?: string;\n /**\n * Run each turn as a durable workflow (see {@link AgentModuleOptions.durable}). Static wiring\n * metadata (which `AGENT_RUNNER` to bind), so it lives here rather than in the async factory\n * result: the factory resolves too late to swap the runner.\n */\n durable?: boolean | AgentDurableOptions;\n\n /** As {@link AgentModuleOptions.decorators}: static, so it lives here, not in `useFactory`'s result. */\n decorators?: ClassDecorator[];\n\n /**\n * Which half of the module this process mounts (see {@link AgentSurface}). Same static-wiring\n * reasoning as `durable` above — `useFactory` resolves too late to decide\n * which controllers exist. Omit → `'both'`, today's behavior with zero change.\n */\n surface?: AgentSurface;\n /** As {@link AgentModuleOptions.routes}: static, so it lives here. */\n routes?: boolean;\n /** Wire protocols served alongside the native one — see `AgentModuleOptions.adapters`. STATIC. */\n adapters?: AgentProtocolAdapter[];\n /**\n * What runs the turns instead of the loop — see `AgentModuleOptions.engine`. STATIC, like\n * `durable`: it decides which runner `AGENT_RUNNER` binds, before `useFactory` has resolved.\n */\n engine?: AgentEngine;\n}\n","/**\n * The thread message queue, as the durable runner and the `agent.run` workflow ask for it.\n *\n * A token rather than the `ChatQueueService` class: `@dudousxd/nestjs-agent/durable` is a separate\n * bundle with its own copy of every class it imports, so a class used as an injection token there\n * is not the class `AgentModule` provides. `Symbol.for` is the same value in every bundle.\n */\nexport const AGENT_CHAT_QUEUE = Symbol.for('@dudousxd/nestjs-agent:chat-queue');\n","import { createNegotiatedUiCollector } from '@dudousxd/nestjs-agent-core';\nimport { prepareActionProposal, resolveActionProposalApproval } from '@dudousxd/nestjs-agent-core';\nimport {\n type AiToolCtx,\n type BufferedModelTurnResult,\n type FirstTextObserver,\n type LlmStepEnvelope,\n type SinkWriter,\n type ToolStepEnvelope,\n type ToolTransientRetrySetting,\n announcedToolCalls,\n createFrameBuffer,\n createNoopEmitUi,\n createUiCollector,\n encodeStreamEvent,\n intersectAllowLists,\n invokeWithTransientRetry,\n isControlFlowSignal,\n isReplayIntegrityError,\n observeFirstText,\n observeTurnFrames,\n previewToolInputs,\n publishAgentToolRetry,\n registryInputPreviews,\n stampToolKinds,\n toolCallContext,\n traceLlmTurn,\n traceToolExecution,\n withAskTool,\n withChannelDelivery,\n withMemoryTool,\n withSkillTool,\n withToolTimeout,\n withTurnFrames,\n wrapToolPreflightDenied,\n wrapToolStepOutput,\n} from '@dudousxd/nestjs-agent-core';\nimport { turnChannel } from '@dudousxd/nestjs-agent-core/genui';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { childSinkWriter } from '../agent-deps.js';\n\n/**\n * Serializable input for the dispatched `llm` step: a {@link LlmStepEnvelope} plus the sink routing\n * only the durable runner knows (`sinkRunId`/`childSink`) — core's `AgentLoopHooks.dispatchLlm` stays\n * sink-topology-agnostic, so the workflow adds these two fields when it builds the envelope.\n */\nexport interface DispatchedLlmInput extends LlmStepEnvelope {\n /**\n * The dispatching workflow's own `ctx.runId` — the run this step's outcome accrues to for\n * reliability metrics (`bumpRunRetries`). Carried even though the handler cannot bump retries\n * today: the durable handler boundary (`runStepHandler`) hands a `@Step` method only\n * `(input, StepLogger)` — the wire task's `attempt` is not exposed — so there is no clean way to\n * detect a retry from inside the handler. Kept on the envelope so the bump can be wired without a\n * wire-contract change once the durable runtime exposes the attempt.\n */\n runId: string;\n /** The turn index within the run (`llm:<step>`) — the `llm.turn` span's `step` metadata. */\n step: number;\n /** The stream target: `input.sinkRunId ?? ctx.runId` of the dispatching workflow. */\n sinkRunId: string;\n /** True for a sub-agent run — wrap the writer with {@link childSinkWriter} (no end/fail). */\n childSink: boolean;\n}\n\n/**\n * Serializable input for the dispatched `tool` step: a {@link ToolStepEnvelope} plus the call\n * identity the `tool.execution` span needs (`toolCallId`/`toolType`) — core's\n * `AgentLoopHooks.dispatchTool` passes those on the separate `ToolCallRequest` argument, so the\n * workflow folds them into the wire payload when it dispatches (same pattern as\n * {@link DispatchedLlmInput}'s sink routing).\n */\nexport interface DispatchedToolInput extends ToolStepEnvelope {\n toolCallId: string;\n toolType: 'read' | 'action';\n /**\n * Where a component the tool pushes (`ctx.emitUi`) streams live — the same routing as\n * {@link DispatchedLlmInput}. Absent on a task enqueued by a workflow that predates it: the\n * components are then still collected and persisted, just not streamed.\n */\n sinkRunId?: string;\n childSink?: boolean;\n}\n\n/** What the engine running a step hands its body besides the input. */\nexport interface StepBodyOptions {\n /**\n * Aborted when the engine gives up on the attempt (a cancel, a shutdown, a lost lease): handed to\n * the model call and to the tool, so they stop instead of running to the end for nobody.\n */\n abortSignal?: AbortSignal;\n}\n\n/**\n * The model call of one turn, as a step body: re-resolves the agent's deps from THIS process's DI\n * (`AGENT_DEPS_FACTORY.forAgent`), streams to the run's sink, and returns what the loop journals.\n * Engine-neutral: the `@dudousxd/nestjs-durable` engine runs it as `AgentRunSteps.llm`, the\n * `@nestjs/workflows` engine as a `ctx.step`.\n *\n * Retryable: every side effect (persist/quota/stream markers) happens loop-side, so a retry only\n * re-runs the model call and re-streams its tokens. NEVER ends or fails the writer: the run owns\n * the stream's lifecycle.\n */\nexport async function runLlmStep(\n factory: AgentDepsFactory,\n input: DispatchedLlmInput,\n options: StepBodyOptions = {},\n): Promise<BufferedModelTurnResult> {\n const deps = factory.forAgent(input.agentName);\n // The envelope carries only wire-safe data — a `ToolDefinition` holds a live Zod/StandardSchema\n // instance that can't survive JSON transport, so this handler re-derives it from `input.actor`,\n // exactly like the loop's own non-dispatched branch does.\n // `withAskTool` from THIS worker's own resolved deps, not from the envelope: `ask` is module\n // config, uniform across a deployment, so the worker reaches the same list the loop would have\n // built locally without the wire contract having to carry the flag.\n // `withSkillTool` for the same reason as `withAskTool` below it: both are module config,\n // uniform across a deployment, so this worker reaches the same tool list the loop would have\n // built without the wire contract having to carry either flag. WHICH skills the model may load\n // is a different question, and it is answered by the catalog in the prompt this envelope\n // carries — never by this worker's own provider.\n // `withMemoryTool` on the same footing, and for the same reason: whether this deployment offers\n // `remember` is module config. WHICH memories the model was shown is a different question, and\n // it is answered by the block in the prompt this envelope carries — never by this worker's own\n // provider.\n const tools = withMemoryTool({\n tools: withSkillTool({\n tools: withAskTool({\n tools: await deps.registry.definitionsFor(\n input.actor,\n deps.rolesPolicy,\n // The persona narrowing the loop journaled in `persona:resolve` rides the envelope:\n // this worker's own persona config may already say something else.\n intersectAllowLists(deps.toolAllowList, input.personaAllowedTools),\n {\n ...(input.threadId !== undefined ? { threadId: input.threadId } : {}),\n ...(input.preflightContext?.uiCapabilities !== undefined\n ? { uiCapabilities: input.preflightContext.uiCapabilities }\n : {}),\n channel: turnChannel(input.preflightContext?.pageContext),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n },\n ),\n ask: deps.ask,\n }),\n enabled: deps.skills !== undefined && input.builtins?.skills !== false,\n }),\n enabled: deps.memory?.provider.write !== undefined && input.builtins?.memory !== false,\n });\n // `bufferOutput` means the dispatching loop has an output gate to run and this worker's sink is\n // on the far side of it: streaming here would put the answer in front of the reader before the\n // gate ever saw it. Hold the frames and hand them back on the result — the loop releases them\n // (or does not) from the checkpoint that carries the verdict. A durable retry of this step\n // simply re-buffers, so no half-gated turn can reach the sink.\n const buffer = input.bufferOutput === true ? createFrameBuffer() : undefined;\n let writer: SinkWriter;\n // When the reader first saw text, read where the text is written — this worker — and carried on\n // the result, so the run's time to first token survives the journal. A buffered turn reaches\n // the reader only when the loop's gate releases it, and the loop stamps it there.\n let firstText: FirstTextObserver | undefined;\n if (buffer !== undefined) {\n writer = buffer.writer;\n } else {\n const opened = await deps.sink.open(input.sinkRunId);\n firstText = observeFirstText(input.childSink ? childSinkWriter(opened) : opened);\n writer = firstText.writer;\n }\n // Span-wrapped HERE (the genuine execution site), emitting the identical `aviary:agent:llm.turn`\n // span core's non-dispatched branch emits — from whichever worker actually serves the step.\n // Replay-safe by construction: a dispatched step's handler only runs on genuine dispatch (replay\n // resolves the step from its checkpoint without re-invoking a worker), which is exactly why core\n // exports the helper instead of wrapping the `hooks.dispatchLlm` CALL site itself.\n // Reasoning and pushed UI are read off the frames here, where the model actually runs, so they\n // ride this step's result into the journal — the same derivation core's inline branch makes.\n // Streaming previews of a tool's input (genui's partial tree) are drawn here, where the model\n // streams, and ride the result as `previews` so the loop withdraws any the call does not replace.\n const announced = announcedToolCalls(writer);\n const previews = previewToolInputs(\n announced.writer,\n registryInputPreviews(deps.registry, tools, {\n actor: input.actor,\n ...(input.threadId !== undefined ? { threadId: input.threadId } : {}),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.preflightContext?.uiCapabilities !== undefined\n ? { uiCapabilities: input.preflightContext.uiCapabilities }\n : {}),\n channel: turnChannel(input.preflightContext?.pageContext),\n }),\n );\n const frames = observeTurnFrames(previews.writer);\n const turn = withTurnFrames(\n await traceLlmTurn(input.runId, input.step, () =>\n deps.model.runTurn({\n system: input.system,\n messages: input.messages,\n tools,\n sink: frames.writer,\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(options.abortSignal !== undefined ? { abortSignal: options.abortSignal } : {}),\n }),\n ),\n frames.summary(),\n );\n // Stamp each call's kind HERE, from the registry that just built `tools` — this handler is the\n // process that offered the tool, and the kind rides the step's result into the journal from\n // here. The loop that reads the result back may be a pod that registers no tool classes at all\n // (it serves HTTP and replays run bodies), and its own registry would answer `undefined` and\n // downgrade an action to a read — dispatching it, unapproved, to a worker that does know it.\n const stamped = stampToolKinds(turn, deps);\n // A provider that streams no tool frames still gets its calls announced (as the loop's inline\n // branch does) — an outcome for a call never announced cannot be attributed to its tool.\n await announced.announceRest(stamped.toolCalls, tools);\n // Prepare on the worker that owns the registry; a coordinator can have no tool providers.\n // This result rides the existing LLM step, then the coordinator's persist:toolcall checkpoint.\n const allowedTools = intersectAllowLists(deps.toolAllowList, input.personaAllowedTools);\n for (const call of stamped.toolCalls) {\n if (call.kind !== 'action') continue;\n try {\n const context = input.preflightContext ?? {\n actor: input.actor,\n threadId: input.threadId ?? '',\n runId: input.runId,\n requestId: input.runId,\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n };\n if (input.actionApprovalMode === 'independent') {\n const spec = deps.registry.spec(call.name);\n call.actionApproval = await resolveActionProposalApproval({\n actor: input.actor,\n store: deps.store,\n tool: { name: call.name, kind: 'action', ...(spec !== undefined ? { spec } : {}) },\n thread: {\n threadId: context.threadId,\n runId: input.runId,\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n },\n ...(deps.approvalPolicy !== undefined ? { policy: deps.approvalPolicy } : {}),\n });\n }\n if (call.actionApproval?.mode === 'ask') {\n call.prepared = await prepareActionProposal(\n deps.registry,\n call.name,\n call.input,\n { ...toolCallContext(context, call.id), emitUi: createNoopEmitUi(call.id) },\n deps.rolesPolicy,\n allowedTools === undefined ? {} : { allowedTools },\n );\n call.preflight = call.prepared.preflight;\n } else {\n call.preflight = await deps.registry.prepare(\n call.name,\n call.input,\n { ...toolCallContext(context, call.id), emitUi: createNoopEmitUi(call.id) },\n deps.rolesPolicy,\n allowedTools === undefined ? {} : { allowedTools },\n );\n }\n } catch (error) {\n if (isControlFlowSignal(error) || isReplayIntegrityError(error)) throw error;\n call.preflight = {\n status: 'failed',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n const shown = previews.shown();\n const previewed = shown.length > 0 ? { ...stamped, previews: shown } : stamped;\n const firstTextAt = firstText?.firstTextAt();\n if (buffer !== undefined) {\n return { ...previewed, bufferedFrames: buffer.frames() };\n }\n return firstTextAt === undefined ? previewed : { ...previewed, firstTextAt };\n}\n\n/**\n * One tool execution, as a step body (see {@link runLlmStep}). Applies the tool's timeout and its\n * classified-transient retry in place, inside this one step, and refuses an action tool that\n * reaches it without approval.\n */\nexport async function runToolStep(\n factory: AgentDepsFactory,\n input: DispatchedToolInput,\n options: StepBodyOptions = {},\n): Promise<unknown> {\n const deps = factory.forAgent(input.ctx.agentName);\n // The approval gate lives in the LOOP, which resolved this call's kind from the registry of the\n // process that ran the body. This worker has its own registry, and it is the process that\n // actually runs the tool — so if it knows the tool as an `action` while the envelope says the\n // loop auto-executed it, the loop resolved the kind against a registry that was missing it, and\n // running the tool here would perform an approved-only action nobody approved. Refuse: the loop\n // reports it as a tool failure the model can answer for, which is recoverable, unlike the side\n // effect.\n if (deps.registry.spec(input.toolName)?.kind === 'action' && input.toolType !== 'action') {\n throw new Error(\n `tool \"${input.toolName}\" is an action tool but was dispatched without approval: the dispatching process resolved its kind against a registry that does not have it`,\n );\n }\n // `ctx.emitUi` streams each push to the run's sink as it happens (opened on the first push, and\n // never ended — the workflow owns the stream) and collects it for the step's RESULT, which is\n // how the pushes reach the message: the dispatching loop persists them from its own checkpoint.\n const sinkRunId = input.sinkRunId;\n let opened: Promise<SinkWriter> | undefined;\n const ui = createNegotiatedUiCollector(\n input.toolCallId,\n input.ctx,\n deps.resolveUiCatalog,\n sinkRunId === undefined\n ? undefined\n : async (event) => {\n opened ??= Promise.resolve(deps.sink.open(sinkRunId)).then((writer) =>\n input.childSink === true ? childSinkWriter(writer) : writer,\n );\n await (await opened).write(encodeStreamEvent(event));\n },\n );\n // AgentDeps carries no `host` today (AgentDepsFactory never populates one), so the rebuilt ctx\n // is exactly `input.ctx` plus `emitUi` — no narrower than what the non-dispatched path threads.\n const ctx: AiToolCtx = {\n ...toolCallContext(input.ctx, input.toolCallId),\n emitUi: ui.emit,\n ...(options.abortSignal !== undefined ? { abortSignal: options.abortSignal } : {}),\n };\n // The envelope carries the numeric half (attempts/backoffMs) the dispatching loop already\n // resolved — the SAME policy as the non-dispatched path. `classify` isn't wire-safe, so it's\n // resolved from THIS worker's own local module options instead (same DI re-resolution as\n // `registry`/`rolesPolicy` above) — a custom classifier applies host-side in both processes.\n const localClassify =\n deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : undefined;\n const transientRetry: ToolTransientRetrySetting =\n input.transientRetry === false\n ? false\n : {\n attempts: input.transientRetry.attempts,\n backoffMs: input.transientRetry.backoffMs,\n ...(localClassify !== undefined ? { classify: localClassify } : {}),\n };\n // Span-wrapped HERE like `llm` above (same replay-safety-by-construction reasoning) — the\n // timeout AND the retry loop sit INSIDE the span so every attempt (and a timed-out attempt)\n // surfaces under the span's error phase.\n const allowedTools = intersectAllowLists(\n deps.toolAllowList,\n input.allowedTools === undefined ? undefined : [...input.allowedTools],\n );\n let output: unknown;\n // The tool's own time, measured here where it runs and carried on the result: the loop reads\n // this step back from the journal, so its own clock would time the read, not the tool.\n const toolStartedAt = Date.now();\n try {\n output = await traceToolExecution(\n input.ctx.runId,\n { toolCallId: input.toolCallId, toolName: input.toolName, toolType: input.toolType },\n () =>\n invokeWithTransientRetry(\n () => {\n // A retry is a new attempt of the same call: its pushes reuse the failed attempt's ids.\n ui.restart();\n const invocation = deps.registry.invoke(\n input.toolName,\n input.input,\n ctx,\n deps.rolesPolicy,\n allowedTools === undefined ? {} : { allowedTools },\n );\n return input.timeoutMs !== undefined\n ? withToolTimeout(invocation, input.timeoutMs, input.toolName)\n : invocation;\n },\n transientRetry,\n {\n onRetry: (attempt, error) => {\n publishAgentToolRetry({\n toolName: input.toolName,\n toolCallId: input.toolCallId,\n attempt,\n message: error instanceof Error ? error.message : String(error),\n });\n },\n },\n ),\n );\n } catch (error) {\n if (error instanceof Error && error.name === 'ToolPreflightDeniedError') {\n return wrapToolPreflightDenied(error.message);\n }\n throw error;\n }\n // Wrapped only when the dispatching loop asked for it (`collectUi`) — a loop that predates that\n // always reads the bare output it expects, and every loop that asks reads the envelope back,\n // which now always carries the tool's measured time.\n // On a channel the server draws for, the model reads what the user actually got there.\n const executionMs = Date.now() - toolStartedAt;\n output = await withChannelDelivery(deps, input.ctx, output, ui.components());\n return input.collectUi === true\n ? wrapToolStepOutput(output, ui.components(), ui.text(), executionMs)\n : output;\n}\n","import type { HumanReply } from '@dudousxd/nestjs-agent-core';\nimport { WorkflowSignal } from '@nestjs/workflows';\n\n/**\n * A person's reply to a call a turn is parked on: a `Decision` on an action tool, or the answers to\n * a question set. Keyed by {@link replyKey}, so a reply reaches only the call it answers.\n */\nexport const AGENT_REPLY = new WorkflowSignal<HumanReply>('aviary.agent.reply');\n\n/** The key a reply to call `toolCallId` of run `runId` is sent and awaited under. */\nexport function replyKey(runId: string, toolCallId: string): string {\n return `${runId}:${toolCallId}`;\n}\n\n/** A call waiting for a person, as `WorkflowsAgentRunner.pendingReplies()` lists it. */\nexport interface PendingReply {\n /** What the reply is signalled under ({@link replyKey}). */\n key: string;\n /** The turn's run id. */\n runId: string;\n toolCallId: string;\n /** The tool, or `'ask'` / `'intake'` for a question set. */\n toolName: string;\n kind: 'approval' | 'elicitation';\n}\n","import {\n OutputRejectedError,\n QuotaExceededError,\n RunCancelledError,\n StructuredOutputError,\n} from '@dudousxd/nestjs-agent-core';\nimport { isWorkflowInterrupt } from '@nestjs/workflows';\n\n/**\n * The marker core's loop reads to tell a runner unwinding the turn from a failure (see\n * `isControlFlowSignal` in core). `@nestjs/workflows` interrupts carry none, so every `ctx` call\n * this engine makes stamps it on the interrupt it throws: then every `catch` in the loop, the ones\n * that consult `isControlFlowError` and the ones that only read the marker, lets it through.\n */\nconst CONTROL_FLOW_SIGNAL = Symbol.for('aviary:durable:control-flow');\n\n/** Mark `error` as control flow when it is a `@nestjs/workflows` interrupt (a suspend, a cancel...). */\nexport function markControlFlow(error: unknown): unknown {\n if (isWorkflowInterrupt(error) && typeof error === 'object' && error !== null) {\n (error as { [CONTROL_FLOW_SIGNAL]?: boolean })[CONTROL_FLOW_SIGNAL] = true;\n }\n return error;\n}\n\n/**\n * Thrown when an instance has made its share of model calls (`stepsPerInstance`): the turn goes on\n * in a child instance. Control flow, never a failure.\n */\nexport class SegmentBoundary extends Error {\n constructor() {\n super('The turn goes on in a child workflow instance');\n this.name = 'SegmentBoundary';\n (this as unknown as { [CONTROL_FLOW_SIGNAL]: boolean })[CONTROL_FLOW_SIGNAL] = true;\n }\n}\n\n/** Is this the engine unwinding the turn rather than something the agent did? */\nexport function isEngineControlFlow(error: unknown): boolean {\n return isWorkflowInterrupt(error) || error instanceof SegmentBoundary;\n}\n\n/** An error as JSON: its name, its message and its own JSON-safe fields (a `code`, a `status`). */\nexport interface SerializedTurnError {\n name: string;\n message: string;\n props?: Record<string, unknown>;\n}\n\n/** What one journaled operation came to: its value, or the error it threw. */\nexport type TurnOutcome = { v?: unknown } | { e: SerializedTurnError };\n\nexport function serializeTurnError(error: unknown): SerializedTurnError {\n if (!(error instanceof Error)) {\n return { name: 'Error', message: String(error) };\n }\n const props: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(error)) {\n if (key === 'name' || key === 'message' || key === 'stack') continue;\n try {\n const json = JSON.stringify(value);\n if (json !== undefined) props[key] = JSON.parse(json);\n } catch {\n // Not JSON: left out, as a journal would.\n }\n }\n return {\n name: error.name,\n message: error.message,\n ...(Object.keys(props).length > 0 ? { props } : {}),\n };\n}\n\n/**\n * The failure a `StepFailedError` gave up on — its `cause`, the step's error as the journal kept it\n * (`{ name, message }`). Read defensively: a cause that is missing or not that shape (an older\n * journal, an engine change) falls back to the cause as text, or to the step error's own message,\n * rather than throwing a `TypeError` in place of the turn's real failure.\n */\nexport function stepFailureCause(error: { cause?: unknown; message: string }): SerializedTurnError {\n const cause = error.cause;\n if (typeof cause === 'object' && cause !== null) {\n const { name, message } = cause as { name?: unknown; message?: unknown };\n if (typeof message === 'string') {\n return { name: typeof name === 'string' ? name : 'Error', message };\n }\n }\n if (cause === undefined || cause === null) return { name: 'Error', message: error.message };\n return { name: 'Error', message: typeof cause === 'string' ? cause : safeString(cause) };\n}\n\nfunction safeString(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** Core's errors the runners branch on by class (`agentFailureCode`), rebuilt as themselves. */\nconst KNOWN_ERRORS: Record<string, { prototype: Error }> = {\n QuotaExceededError,\n RunCancelledError,\n OutputRejectedError,\n StructuredOutputError,\n};\n\n/** The error a journal recorded, as an `Error` again (of core's own class, when it is one). */\nexport function rebuildTurnError(serialized: SerializedTurnError): Error {\n const prototype = KNOWN_ERRORS[serialized.name]?.prototype ?? Error.prototype;\n const error = Object.create(prototype) as Error;\n Object.assign(error, serialized.props ?? {});\n Object.defineProperty(error, 'name', {\n value: serialized.name,\n writable: true,\n configurable: true,\n });\n Object.defineProperty(error, 'message', {\n value: serialized.message,\n writable: true,\n configurable: true,\n });\n Object.defineProperty(error, 'stack', {\n value: `${serialized.name}: ${serialized.message}`,\n writable: true,\n configurable: true,\n });\n return error;\n}\n\n/**\n * The turn's view of its journal, over `@nestjs/workflows`.\n *\n * NAMES. The engine wants every step, wait and child name unique per run; the loop's checkpoint\n * names are unique per call site, not per run (two delegations to one agent both create a\n * `subthread:<agent>`). {@link unique} numbers repeats in CALL order (`name`, `name#2`, ...): the\n * loop invokes its parallel tasks synchronously in list order, so the numbering is the same on every\n * replay.\n *\n * SEGMENTS. A turn that runs past `stepsPerInstance` model calls goes on in a child instance, which\n * replays the loop from the top. What the parent's operations came to is handed to the child as\n * `carried`, and {@link op} answers a carried name from it without touching the child's journal, so\n * each instance's journal holds only the operations of its own segment.\n */\nexport class TurnJournal {\n private readonly counts = new Map<string, number>();\n /** Every operation's outcome so far: the carried ones, then this instance's. */\n readonly outcomes: Record<string, TurnOutcome>;\n /** Model calls this instance made itself (not carried). */\n liveModelCalls = 0;\n\n constructor(carried: Record<string, TurnOutcome> = {}) {\n this.outcomes = { ...carried };\n }\n\n /** `base` the first time, `base#2` the second, ... */\n unique(base: string): string {\n const count = (this.counts.get(base) ?? 0) + 1;\n this.counts.set(base, count);\n return count === 1 ? base : `${base}#${count}`;\n }\n\n /** Was `name` carried from an earlier segment, or already settled in this one? */\n has(name: string): boolean {\n return name in this.outcomes;\n }\n\n /**\n * Run `live` (a `ctx` operation) once per run: a name an earlier segment settled answers from\n * `carried`. A failure is recorded too, so a later segment replays it as the same failure; the\n * engine's own control flow is not.\n */\n async op<T>(name: string, live: () => Promise<T>): Promise<T> {\n const known = this.outcomes[name];\n if (known !== undefined) {\n if ('e' in known) throw rebuildTurnError(known.e);\n return known.v as T;\n }\n try {\n const value = await live();\n this.outcomes[name] = value === undefined ? {} : { v: value };\n return value;\n } catch (error) {\n if (isEngineControlFlow(error)) throw markControlFlow(error);\n this.outcomes[name] = { e: serializeTurnError(error) };\n throw error;\n }\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n AGENT_SINK,\n AGENT_STORE,\n type AgentRunContext,\n type AgentRunInput,\n type AgentRunStartOptions,\n type AgentRunner,\n type AgentStore,\n type DetachedDelivery,\n type HumanReply,\n type TokenStreamSink,\n encodeStreamEvent,\n publishAgentRunCancelled,\n releaseThreadRun,\n settleUnsettledDelegation,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, Optional } from '@nestjs/common';\nimport {\n WorkflowClient,\n type WorkflowInstanceDetails,\n WorkflowNotFoundError,\n type WorkflowStatus,\n} from '@nestjs/workflows';\nimport { utcDay } from '../agent-deps.js';\nimport { InProcessTokenStreamSink } from '../in-process-sink.js';\nimport type { ChatQueueService } from '../queue/chat-queue.service.js';\nimport { AGENT_CHAT_QUEUE } from '../queue/chat-queue.token.js';\nimport { AGENT_REPLY, type PendingReply, replyKey } from './agent-reply.signal.js';\nimport { AgentRunFlow } from './agent-run.flow.js';\n\nconst ENDED: ReadonlySet<WorkflowStatus> = new Set([\n 'completed',\n 'failed',\n 'cancelled',\n 'compensation_failed',\n]);\n\n/** The fields of a recorded `AgentRunInput` this runner reads back, structurally. */\ninterface RecordedInput {\n threadId?: unknown;\n sinkRunId?: unknown;\n deliverTo?: unknown;\n agentName?: unknown;\n parentRunId?: unknown;\n actor?: { id?: unknown; tenantRef?: unknown };\n}\n\nfunction recorded(input: unknown): RecordedInput {\n return typeof input === 'object' && input !== null ? (input as RecordedInput) : {};\n}\n\nfunction deliveryOf(input: unknown): { delivery: DetachedDelivery; agent: string } | undefined {\n const { deliverTo, agentName } = recorded(input);\n if (\n typeof deliverTo !== 'object' ||\n deliverTo === null ||\n typeof (deliverTo as { threadId?: unknown }).threadId !== 'string' ||\n typeof (deliverTo as { toolCallId?: unknown }).toolCallId !== 'string'\n ) {\n return undefined;\n }\n return {\n delivery: deliverTo as DetachedDelivery,\n agent: typeof agentName === 'string' ? agentName : 'default',\n };\n}\n\nfunction runContextOf(input: unknown): AgentRunContext | undefined {\n const { actor, agentName, parentRunId } = recorded(input);\n if (typeof actor?.id !== 'string') return undefined;\n return {\n actorId: actor.id,\n ...(typeof agentName === 'string' ? { agentName } : {}),\n ...(typeof actor.tenantRef === 'string' ? { tenantRef: actor.tenantRef } : {}),\n ...(typeof parentRunId === 'string' ? { parentRunId } : {}),\n };\n}\n\n/**\n * Runs agent turns on NestJS's `@nestjs/workflows` (`durable: true`). `start` creates the\n * `aviary.agent.run` instance under the run id and returns; whichever worker claims it runs the turn\n * and streams to the sink. A person's reply to a parked call is the `AGENT_REPLY` signal keyed by\n * `<runId>:<toolCallId>`; a Stop is `WorkflowClient.cancel`.\n */\n@Injectable()\nexport class WorkflowsAgentRunner implements AgentRunner {\n private readonly logger = new Logger(WorkflowsAgentRunner.name);\n private readonly client: WorkflowClient;\n\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_SINK) private readonly sink: TokenStreamSink,\n @Optional() client?: WorkflowClient,\n @Optional() @Inject(AGENT_CHAT_QUEUE) private readonly queue?: ChatQueueService,\n ) {\n if (client === undefined) {\n throw new Error(\n \"AgentWorkflowsModule runs turns on @nestjs/workflows: import WorkflowsModule.forRoot() from '@nestjs/workflows' \" +\n '(WorkflowsModule.forRoot({ worker: false }) on a process that must not run turns, such as an API pod). ' +\n 'No WorkflowClient was found.',\n );\n }\n this.client = client;\n if (this.sink instanceof InProcessTokenStreamSink) {\n this.logger.warn(\n 'durable turns with the default InProcessTokenStreamSink, which only buffers tokens in this process: ' +\n 'fine while this process runs the workflow worker, but a turn claimed by another process cannot stream ' +\n 'to this one. Wire a cross-process TokenStreamSink (e.g. the Redis one) before running several processes.',\n );\n }\n }\n\n async start(\n input: AgentRunInput,\n options: AgentRunStartOptions = {},\n ): Promise<{ runId: string }> {\n const stamped: AgentRunInput = { ...input, day: input.day ?? utcDay() };\n const runId = options.runId ?? randomUUID();\n await this.client.start(AgentRunFlow, stamped, { id: runId });\n return { runId };\n }\n\n /** Not ended as far as the engine knows. An unknown run counts as running, and so does one it can't be asked about. */\n async isRunActive(runId: string): Promise<boolean> {\n try {\n const status = (await this.client.getStatus(runId))?.status;\n return status === undefined || !ENDED.has(status);\n } catch {\n return true;\n }\n }\n\n async signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void> {\n const key = replyKey(runId, toolCallId);\n // The first reply to a call counts: a repeat is stored once and never seen.\n await this.client.signal(AGENT_REPLY, reply, { key, id: key });\n }\n\n /** The engine's view of a run: status, custom status, waits, children. `null` for an unknown id. */\n getStatus(runId: string): Promise<WorkflowInstanceDetails | null> {\n return this.client.getStatus(runId, { children: true });\n }\n\n /**\n * The calls of run `runId` waiting for a person now, in the instance it started in, in the\n * instances it went on in, and in the sub-agent runs it delegated to.\n */\n async pendingReplies(runId: string): Promise<PendingReply[]> {\n const found: PendingReply[] = [];\n const visit = async (id: string): Promise<void> => {\n const details = await this.client.getStatus(id, { children: true });\n if (details === null) return;\n const status = details.customStatus as { pendingReplies?: PendingReply[] } | null;\n found.push(...(status?.pendingReplies ?? []));\n for (const child of details.children ?? []) {\n // A detached run is a run of its own: it lists its calls under its own id.\n if (!ENDED.has(child.status) && child.parentClose !== 'abandon') await visit(child.id);\n }\n };\n await visit(runId);\n return found;\n }\n\n /**\n * Stop a run: the engine stops the turn at its next `ctx` call (a parked turn at once), and\n * cancels the sub-agent runs it is waiting on. What the engine knows nothing about is settled\n * here, as on the `aviary` engine: the delegation a detached run answers, the thread's queue and\n * live stream, the subscriber's stream (a `cancelled` frame and a normal end), the run's row.\n */\n async cancel(runId: string): Promise<void> {\n this.logger.log(`cancelling agent run ${runId}`);\n const details = await this.client.getStatus(runId).catch(() => null);\n const input = details?.input;\n const { threadId, sinkRunId, deliverTo } = recorded(input);\n try {\n await this.client.cancel(runId, 'Stopped');\n } catch (error) {\n if (!(error instanceof WorkflowNotFoundError)) throw error;\n }\n const target = deliveryOf(input);\n if (target !== undefined) {\n await settleUnsettledDelegation({\n store: this.store,\n delivery: target.delivery,\n agent: target.agent,\n runId,\n status: 'cancelled',\n }).catch((error: unknown) =>\n this.logger.error(\n `could not settle the delegation of cancelled run ${runId}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n ),\n );\n }\n const writer = await this.sink.open(runId);\n if (typeof threadId === 'string') {\n const threadTurn = sinkRunId === undefined && deliverTo === undefined;\n if (this.queue?.supported === true && threadTurn) {\n try {\n const frame = await this.queue.handoff(\n { threadId, runId, outcome: 'cancelled' },\n (next, nextRunId) => this.start(next, { runId: nextRunId }),\n );\n if (frame !== undefined) await writer.write(encodeStreamEvent(frame));\n } catch (error) {\n this.logger.error(\n `could not advance the queue of thread ${threadId} after cancelling ${runId}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n await releaseThreadRun(this.store, threadId, runId);\n }\n await writer.write(encodeStreamEvent({ kind: 'cancelled' }));\n await writer.end();\n const durationMs =\n details !== null && details !== undefined\n ? Math.max(0, details.updatedAt - details.createdAt)\n : undefined;\n const context = runContextOf(input);\n publishAgentRunCancelled({\n runId,\n ...(typeof threadId === 'string' ? { threadId } : {}),\n ...(durationMs !== undefined ? { durationMs } : {}),\n ...(context !== undefined ? { context } : {}),\n });\n await this.store.recordRunEnd?.({\n runId,\n status: 'cancelled',\n ...(durationMs !== undefined ? { durationMs } : {}),\n });\n }\n}\n","import {\n AgentStreamError,\n type SinkWriter,\n type StreamError,\n type SubscribeOptions,\n type TokenStreamSink,\n} from '@dudousxd/nestjs-agent-core';\n\ninterface RunBuffer {\n chunks: Uint8Array[];\n ended: boolean;\n failure?: StreamError;\n notify: Set<() => void>;\n /** When the run last wrote anything, for the live-run TTL. */\n lastWriteAt: number;\n /** Drops the buffer: on the live-run TTL while the run streams, on the grace period once it ended. */\n expiry: ReturnType<typeof setTimeout> | undefined;\n}\n\n/**\n * How long a run that stopped writing without ending keeps its buffer — a turn on a crashed or\n * cancelled path that never reached `end()`. The same window the Redis sinks give a stream past its\n * last write.\n */\nconst LIVE_TTL_MS = 3_600_000;\n\n/**\n * How long an ended run's buffer outlives its `end()`/`fail()`, for a subscriber that attaches just\n * after the turn finished. Short, because nothing reached through a request replays a finished run:\n * the service only attaches a caller to a run that is still its thread's active stream.\n */\nconst ENDED_GRACE_MS = 60_000;\n\n/**\n * The default `TokenStreamSink`: buffers chunks per run in-process so a reconnecting subscriber\n * replays everything so far, then follows live. A run's buffer is dropped {@link ENDED_GRACE_MS}\n * after it ends, or {@link LIVE_TTL_MS} after its last write if it never does.\n *\n * Single-replica only. Because the buffer lives in one process's memory, a resume/reconnect that\n * lands on a different replica than the one running the turn finds an empty buffer — the stream\n * appears stalled. For multi-replica deployments, supply a shared-transport `TokenStreamSink`\n * (e.g. Redis pub/sub keyed by runId) via `AgentModule.forRoot({ sink })`.\n */\nexport class InProcessTokenStreamSink implements TokenStreamSink {\n private readonly runs = new Map<string, RunBuffer>();\n /** Subscribers of a run nothing has opened yet, woken by its `open()`. */\n private readonly waiting = new Map<string, Set<() => void>>();\n\n private buffer(runId: string): RunBuffer {\n let buf = this.runs.get(runId);\n if (buf === undefined) {\n buf = {\n chunks: [],\n ended: false,\n notify: new Set(),\n lastWriteAt: Date.now(),\n expiry: undefined,\n };\n this.runs.set(runId, buf);\n this.expireAfter(runId, buf, LIVE_TTL_MS);\n const waiters = this.waiting.get(runId);\n this.waiting.delete(runId);\n for (const resolve of waiters ?? []) {\n resolve();\n }\n }\n return buf;\n }\n\n private expireAfter(runId: string, buf: RunBuffer, ms: number): void {\n if (buf.expiry !== undefined) {\n clearTimeout(buf.expiry);\n }\n buf.expiry = setTimeout(() => {\n buf.expiry = undefined;\n const idle = Date.now() - buf.lastWriteAt;\n if (!buf.ended && idle < LIVE_TTL_MS) {\n this.expireAfter(runId, buf, LIVE_TTL_MS - idle);\n return;\n }\n this.drop(runId, buf);\n }, ms);\n buf.expiry.unref?.();\n }\n\n /** Forget the run, and let anyone still following it finish as if it had ended. */\n private drop(runId: string, buf: RunBuffer): void {\n if (buf.expiry !== undefined) {\n clearTimeout(buf.expiry);\n buf.expiry = undefined;\n }\n if (this.runs.get(runId) === buf) {\n this.runs.delete(runId);\n }\n buf.ended = true;\n this.wake(buf);\n }\n\n private wake(buf: RunBuffer): void {\n for (const resolve of buf.notify) {\n resolve();\n }\n buf.notify.clear();\n }\n\n private finish(runId: string, buf: RunBuffer): void {\n buf.ended = true;\n this.wake(buf);\n this.expireAfter(runId, buf, ENDED_GRACE_MS);\n }\n\n /**\n * The run's writer. Each call finds the run's buffer afresh, so a run that went quiet past the\n * live TTL (parked on a person) and then writes again starts a new buffer its next subscriber\n * follows, rather than writing into one nothing reads.\n */\n open(runId: string): SinkWriter {\n this.buffer(runId);\n return {\n write: (chunk: Uint8Array) => {\n const buf = this.buffer(runId);\n buf.chunks.push(chunk);\n buf.lastWriteAt = Date.now();\n this.wake(buf);\n },\n end: () => {\n this.finish(runId, this.buffer(runId));\n },\n fail: (error: StreamError) => {\n const buf = this.buffer(runId);\n buf.failure = error;\n this.finish(runId, buf);\n },\n };\n }\n\n async *subscribe(runId: string, options: SubscribeOptions = {}): AsyncIterable<Uint8Array> {\n const { signal } = options;\n let buf = this.runs.get(runId);\n while (buf === undefined) {\n // Not opened yet — the subscriber is early. Waits without creating the run, so a runId that\n // never streams leaves nothing behind once its subscriber goes.\n const waiters = this.waiting.get(runId) ?? new Set<() => void>();\n this.waiting.set(runId, waiters);\n let resolve: () => void = () => {};\n const opened = new Promise<void>((r) => {\n resolve = r;\n });\n waiters.add(resolve);\n try {\n if (!(await untilAborted(opened, signal))) {\n return;\n }\n } finally {\n waiters.delete(resolve);\n if (waiters.size === 0 && this.waiting.get(runId) === waiters) {\n this.waiting.delete(runId);\n }\n }\n buf = this.runs.get(runId);\n }\n let index = 0;\n while (true) {\n while (index < buf.chunks.length) {\n const chunk = buf.chunks[index];\n index += 1;\n if (chunk !== undefined) {\n yield chunk;\n }\n }\n if (buf.ended) {\n // Drain buffered chunks first, then raise the failure as a typed terminal.\n if (buf.failure !== undefined) {\n throw new AgentStreamError(buf.failure);\n }\n return;\n }\n const current = buf;\n let resolve: () => void = () => {};\n const woken = new Promise<void>((r) => {\n resolve = r;\n });\n current.notify.add(resolve);\n try {\n if (!(await untilAborted(woken, signal))) {\n return;\n }\n } finally {\n current.notify.delete(resolve);\n }\n }\n }\n\n close(runId: string): void {\n const buf = this.runs.get(runId);\n if (buf?.expiry !== undefined) {\n clearTimeout(buf.expiry);\n }\n this.runs.delete(runId);\n }\n}\n\n/** Resolves `true` once `promise` does, or `false` as soon as `signal` aborts. */\nasync function untilAborted(\n promise: Promise<void>,\n signal: AbortSignal | undefined,\n): Promise<boolean> {\n if (signal === undefined) {\n await promise;\n return true;\n }\n if (signal.aborted) {\n return false;\n }\n let onAbort: () => void = () => {};\n const aborted = new Promise<false>((resolve) => {\n onAbort = () => resolve(false);\n signal.addEventListener('abort', onAbort, { once: true });\n });\n try {\n return await Promise.race([promise.then(() => true as const), aborted]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n"],"mappings":"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","names":["AGENT_WORKFLOWS_RUNNER","Global","Module","Workflow","AGENT_DEPS_FACTORY","AGENT_OPTIONS","AGENT_STORE","RUN_ENDED_BEFORE_TOOL_CALL","RunCancelledError","agentFailureCode","agentRunContext","encodeStreamEvent","isReplayIntegrityError","publishAgentRunFailed","releaseThreadRun","runAgentLoop","runDurationMs","runEndTimings","settleAll","settleDeadRun","settleUnsettledDelegation","streamFailure","Inject","Injectable","Logger","Optional","ChildWorkflowFailedError","NonRetryableStepError","StepFailedError","WORKFLOWS_MODULE_OPTIONS","WorkflowClient","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","flush","fail","durableEngineOf","durable","undefined","engine","AGENT_CHAT_QUEUE","Symbol","for","createNegotiatedUiCollector","prepareActionProposal","resolveActionProposalApproval","announcedToolCalls","createFrameBuffer","createNoopEmitUi","encodeStreamEvent","intersectAllowLists","invokeWithTransientRetry","isControlFlowSignal","isReplayIntegrityError","observeFirstText","observeTurnFrames","previewToolInputs","publishAgentToolRetry","registryInputPreviews","stampToolKinds","toolCallContext","traceLlmTurn","traceToolExecution","withAskTool","withChannelDelivery","withMemoryTool","withSkillTool","withToolTimeout","withTurnFrames","wrapToolPreflightDenied","wrapToolStepOutput","turnChannel","runLlmStep","factory","input","options","deps","forAgent","agentName","tools","withMemoryTool","withSkillTool","withAskTool","registry","definitionsFor","actor","rolesPolicy","intersectAllowLists","toolAllowList","personaAllowedTools","threadId","undefined","preflightContext","uiCapabilities","channel","turnChannel","pageContext","ask","enabled","skills","builtins","memory","provider","write","buffer","bufferOutput","createFrameBuffer","writer","firstText","opened","sink","open","sinkRunId","observeFirstText","childSink","childSinkWriter","announced","announcedToolCalls","previews","previewToolInputs","registryInputPreviews","frames","observeTurnFrames","turn","withTurnFrames","traceLlmTurn","runId","step","model","runTurn","system","messages","abortSignal","summary","stamped","stampToolKinds","announceRest","toolCalls","allowedTools","call","kind","context","requestId","actionApprovalMode","spec","name","actionApproval","resolveActionProposalApproval","store","tool","thread","approvalPolicy","policy","mode","prepared","prepareActionProposal","toolCallContext","id","emitUi","createNoopEmitUi","preflight","prepare","error","isControlFlowSignal","isReplayIntegrityError","status","Error","message","String","shown","previewed","length","firstTextAt","bufferedFrames","runToolStep","ctx","toolName","toolType","ui","createNegotiatedUiCollector","toolCallId","resolveUiCatalog","event","Promise","resolve","then","encodeStreamEvent","emit","localClassify","toolTransientRetry","classify","transientRetry","attempts","backoffMs","output","toolStartedAt","Date","now","traceToolExecution","invokeWithTransientRetry","restart","invocation","invoke","timeoutMs","withToolTimeout","onRetry","attempt","publishAgentToolRetry","wrapToolPreflightDenied","executionMs","withChannelDelivery","components","collectUi","wrapToolStepOutput","text","WorkflowSignal","AGENT_REPLY","WorkflowSignal","replyKey","runId","toolCallId","OutputRejectedError","QuotaExceededError","RunCancelledError","StructuredOutputError","isWorkflowInterrupt","CONTROL_FLOW_SIGNAL","Symbol","for","markControlFlow","error","isWorkflowInterrupt","SegmentBoundary","Error","name","isEngineControlFlow","serializeTurnError","message","String","props","key","value","Object","entries","json","JSON","stringify","undefined","parse","keys","length","stepFailureCause","cause","safeString","KNOWN_ERRORS","QuotaExceededError","RunCancelledError","OutputRejectedError","StructuredOutputError","rebuildTurnError","serialized","prototype","create","assign","defineProperty","writable","configurable","TurnJournal","counts","Map","outcomes","liveModelCalls","carried","unique","base","count","get","set","has","op","live","known","e","v","AGENT_RUN_WORKFLOW","AGENT_RUN_SEGMENT_WORKFLOW","DEFAULT_STEPS_PER_INSTANCE","SegmentFailed","Error","cause","message","name","isConfigurationError","error","isFatalDefinitionError","isReplayIntegrityError","AgentTurnExecutor","logger","Logger","stepsPerInstance","factory","store","options","queue","client","workflowsOptions","durable","configured","durableEngineOf","undefined","Number","isInteger","run","ctx","input","execute","runId","workflowId","segment","carried","journal","TurnJournal","day","utcDay","deps","forAgent","agentName","sinkRunId","childSink","originals","Map","pending","showPending","setStatus","size","pendingReplies","values","checkpoint","fn","op","envelope","ctxCall","step","value","v","set","e","serializeTurnError","get","rebuildTurnError","unique","awaitReply","call","timeoutMs","id","key","replyKey","toolCallId","toolName","kind","reply","waitForSignal","AGENT_REPLY","timeout","delete","chainBelow","delegationPath","subThread","thread","createThread","actor","transient","deliverTo","setActiveStream","threadId","hooks","queueMs","status","getStatus","now","clock","Date","waited","createdAt","isFinite","openSink","childSinkWriter","sink","open","writer","write","chunk","fail","failure","end","frame","advanceQueue","encodeStreamEvent","awaitApproval","_toolCtx","opts","approved","expired","awaitAnswers","request","source","parallel","settleAll","isControlFlowError","isEngineControlFlow","runAgent","task","subThreadId","child","userText","delegationDepth","parentRunId","executeChild","startAgent","childRunId","handle","startChild","parentClose","dispatchLlm","index","has","liveModelCalls","SegmentBoundary","attempt","runLlmStep","abortSignal","signal","catch","fatal","NonRetryableStepError","StepFailedError","stepFailureCause","dispatchTool","checkpointTool","outcome","runToolStep","toolType","result","runAgentLoop","releaseThreadRun","continueInSegment","outcomes","RunCancelledError","settleDetachedParent","durationMs","runDurationMs","timed","measured","runEndTimings","String","code","agentFailureCode","publishAgentRunFailed","context","agentRunContext","settleDeadRun","streamFailure","recordRunEnd","errorCode","errorMessage","Promise","resolve","failUnsettledToolCalls","RUN_ENDED_BEFORE_TOOL_CALL","queueFrame","settling","markControlFlow","next","ChildWorkflowFailedError","supported","plan","settled","isCancelled","reason","restore","pausedFrame","cancelRequested","delivery","settleUnsettledDelegation","agent","AgentRunFlow","turns","run","ctx","input","AgentRunSegmentFlow","segment","execute","randomUUID","AGENT_SINK","AGENT_STORE","encodeStreamEvent","publishAgentRunCancelled","releaseThreadRun","settleUnsettledDelegation","Inject","Injectable","Logger","Optional","WorkflowClient","WorkflowNotFoundError","AgentStreamError","LIVE_TTL_MS","ENDED_GRACE_MS","InProcessTokenStreamSink","runs","Map","waiting","buffer","runId","buf","get","undefined","chunks","ended","notify","Set","lastWriteAt","Date","now","expiry","set","expireAfter","waiters","delete","resolve","ms","clearTimeout","setTimeout","idle","drop","unref","wake","clear","finish","open","write","chunk","push","end","fail","error","failure","subscribe","options","signal","opened","Promise","r","add","untilAborted","size","index","length","AgentStreamError","current","woken","close","promise","aborted","onAbort","addEventListener","once","race","then","removeEventListener","ENDED","Set","recorded","input","deliveryOf","deliverTo","agentName","threadId","toolCallId","undefined","delivery","agent","runContextOf","actor","parentRunId","id","actorId","tenantRef","WorkflowsAgentRunner","logger","Logger","name","client","store","sink","queue","Error","InProcessTokenStreamSink","warn","start","options","stamped","day","utcDay","runId","randomUUID","AgentRunFlow","isRunActive","status","getStatus","has","signal","reply","key","replyKey","AGENT_REPLY","children","pendingReplies","found","visit","details","customStatus","push","child","parentClose","cancel","log","catch","sinkRunId","error","WorkflowNotFoundError","target","settleUnsettledDelegation","message","String","writer","open","threadTurn","supported","frame","handoff","outcome","next","nextRunId","write","encodeStreamEvent","releaseThreadRun","kind","end","durationMs","Math","max","updatedAt","createdAt","context","publishAgentRunCancelled","recordRunEnd","AgentWorkflowsModule","providers","AgentTurnExecutor","AgentRunFlow","AgentRunSegmentFlow","WorkflowsAgentRunner","provide","AGENT_WORKFLOWS_RUNNER","useExisting","exports"]}
|
|
1
|
+
{"version":3,"sources":["../../src/workflows/agent-workflows.module.ts","../../src/workflows/agent-run.flow.ts","../../src/workflows/agent-turn.executor.ts","../../src/agent-deps.ts","../../src/agent.options.ts","../../src/queue/chat-queue.token.ts","../../src/runner/agent-step-bodies.ts","../../src/workflows/agent-reply.signal.ts","../../src/workflows/turn-journal.ts","../../src/workflows/workflows-agent-runner.ts","../../src/in-process-sink.ts"],"sourcesContent":["import { AGENT_WORKFLOWS_RUNNER } from '@dudousxd/nestjs-agent-core';\nimport { Global, Module } from '@nestjs/common';\nimport { AgentRunFlow, AgentRunSegmentFlow } from './agent-run.flow.js';\nimport { AgentTurnExecutor } from './agent-turn.executor.js';\nimport { WorkflowsAgentRunner } from './workflows-agent-runner.js';\n\n/**\n * Agent turns on NestJS's `@nestjs/workflows`. Import it next to `WorkflowsModule.forRoot()` and\n * `AgentModule.forRoot({ durable: true })`:\n *\n * ```ts\n * imports: [\n * WorkflowsModule.forRoot(),\n * AgentModule.forRoot({ model, store, durable: true }),\n * AgentWorkflowsModule,\n * ]\n * ```\n *\n * It registers the `aviary.agent.run` workflow (and the one a long turn goes on in) and provides the\n * runner `AgentModule` binds `AGENT_RUNNER` to. Every process registers them, so any process can\n * start a turn; which processes RUN turns is `WorkflowsModule`'s `worker` option: on an API pod\n * that must not, `WorkflowsModule.forRoot({ worker: false })`.\n */\n@Global()\n@Module({\n providers: [\n AgentTurnExecutor,\n AgentRunFlow,\n AgentRunSegmentFlow,\n WorkflowsAgentRunner,\n { provide: AGENT_WORKFLOWS_RUNNER, useExisting: WorkflowsAgentRunner },\n ],\n exports: [AGENT_WORKFLOWS_RUNNER, WorkflowsAgentRunner],\n})\nexport class AgentWorkflowsModule {}\n","import type { AgentLoopResult, AgentRunInput } from '@dudousxd/nestjs-agent-core';\nimport { Workflow, type WorkflowContext, type WorkflowRunner } from '@nestjs/workflows';\nimport {\n AGENT_RUN_SEGMENT_WORKFLOW,\n AGENT_RUN_WORKFLOW,\n type AgentRunSegmentInput,\n AgentTurnExecutor,\n} from './agent-turn.executor.js';\n\n/** An agent turn, as a `@nestjs/workflows` workflow (`aviary.agent.run`). The run id is its instance id. */\n@Workflow(AGENT_RUN_WORKFLOW)\nexport class AgentRunFlow implements WorkflowRunner<AgentRunInput, AgentLoopResult> {\n constructor(private readonly turns: AgentTurnExecutor) {}\n\n run(ctx: WorkflowContext, input: AgentRunInput): Promise<AgentLoopResult> {\n return this.turns.run(ctx, input);\n }\n}\n\n/** A turn going on in a child instance after `stepsPerInstance` model calls. Internal. */\n@Workflow(AGENT_RUN_SEGMENT_WORKFLOW)\nexport class AgentRunSegmentFlow implements WorkflowRunner<AgentRunSegmentInput, AgentLoopResult> {\n constructor(private readonly turns: AgentTurnExecutor) {}\n\n run(ctx: WorkflowContext, segment: AgentRunSegmentInput): Promise<AgentLoopResult> {\n return this.turns.execute(ctx, segment);\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_OPTIONS,\n AGENT_STORE,\n type AgentLoopHooks,\n type AgentLoopResult,\n type AgentRunInput,\n type AgentStore,\n type AgentStreamEvent,\n type BufferedModelTurnResult,\n type Decision,\n type ElicitationReply,\n type HumanReply,\n type LlmStepEnvelope,\n RUN_ENDED_BEFORE_TOOL_CALL,\n RunCancelledError,\n type ToolCallRequest,\n type ToolStepEnvelope,\n agentFailureCode,\n agentRunContext,\n encodeStreamEvent,\n isReplayIntegrityError,\n publishAgentRunFailed,\n releaseThreadRun,\n runAgentLoop,\n runDurationMs,\n runEndTimings,\n settleAll,\n settleDeadRun,\n settleUnsettledDelegation,\n streamFailure,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, Optional } from '@nestjs/common';\nimport {\n ChildWorkflowFailedError,\n NonRetryableStepError,\n StepFailedError,\n WORKFLOWS_MODULE_OPTIONS,\n WorkflowClient,\n type WorkflowContext,\n type WorkflowsModuleOptions,\n} from '@nestjs/workflows';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { childSinkWriter, utcDay } from '../agent-deps.js';\nimport { type AgentModuleOptions, durableEngineOf } from '../agent.options.js';\nimport type {\n ChatQueueService,\n QueuePlan,\n QueueSettleOutcome,\n} from '../queue/chat-queue.service.js';\nimport { AGENT_CHAT_QUEUE } from '../queue/chat-queue.token.js';\nimport { runLlmStep, runToolStep } from '../runner/agent-step-bodies.js';\nimport { AGENT_REPLY, type PendingReply, replyKey } from './agent-reply.signal.js';\nimport {\n SegmentBoundary,\n TurnJournal,\n type TurnOutcome,\n isEngineControlFlow,\n markControlFlow,\n rebuildTurnError,\n serializeTurnError,\n stepFailureCause,\n} from './turn-journal.js';\n\n/** The workflow a turn runs as. */\nexport const AGENT_RUN_WORKFLOW = 'aviary.agent.run';\n/** The workflow a turn goes on in after `stepsPerInstance` model calls. */\nexport const AGENT_RUN_SEGMENT_WORKFLOW = 'aviary.agent.run.segment';\n\nconst DEFAULT_STEPS_PER_INSTANCE = 10;\n\n/** What a segment instance starts from: the turn, its run id, and what the instances before it settled. */\nexport interface AgentRunSegmentInput {\n input: AgentRunInput;\n /** The turn's run id: the id of the instance it started in. */\n runId: string;\n /** 1 for the first child instance. */\n segment: number;\n carried: Record<string, TurnOutcome>;\n}\n\n/** A segment's failure, already settled by the segment that failed: its ancestors only pass it up. */\nclass SegmentFailed extends Error {\n constructor(override readonly cause: ChildWorkflowFailedError) {\n super(cause.message);\n this.name = 'SegmentFailed';\n }\n}\n\n/** A step body's outcome, as the journal keeps it: a step never fails for the loop's own errors. */\ntype StepEnvelope = { v?: unknown } | { e: ReturnType<typeof serializeTurnError> };\n\n/** Errors that fail the same way every attempt: not worth a durable retry. */\nfunction isConfigurationError(error: unknown): boolean {\n return (\n error instanceof Error &&\n (error.name === 'AiConfigurationError' || error.name === 'AgentConfigurationError')\n );\n}\n\n/** The engine refused the run's code (a duplicate name, a ctx call inside a step...): nothing more can be journaled. */\nfunction isFatalDefinitionError(error: unknown): boolean {\n return (\n isReplayIntegrityError(error) ||\n (error instanceof Error &&\n (error.name === 'WorkflowDefinitionError' || error.name === 'WorkflowJournalLimitError'))\n );\n}\n\n/**\n * The agent turn on `@nestjs/workflows`: what `AgentRunFlow` (`aviary.agent.run`) and\n * `AgentRunSegmentFlow` run. Each model call and each tool call is a `ctx.step`, the loop's\n * checkpoints are `ctx.step`s too, a human's reply is a `ctx.waitForSignal(AGENT_REPLY, { key })`,\n * a delegation is `ctx.executeChild`, a detached delegation and the thread's next queued message are\n * `ctx.startChild(..., { parentClose: 'abandon' })`. A cancel is the engine's: `WorkflowClient.cancel`\n * stops the turn at its next `ctx` call, and `WorkflowsAgentRunner.cancel` settles the agent's own\n * state, as it does on the `aviary` engine.\n */\n@Injectable()\nexport class AgentTurnExecutor {\n private readonly logger = new Logger('AgentRunFlow');\n private readonly stepsPerInstance: number;\n\n constructor(\n @Inject(AGENT_DEPS_FACTORY) private readonly factory: AgentDepsFactory,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Optional() @Inject(AGENT_OPTIONS) options?: AgentModuleOptions,\n // By token: this file ships in the `/workflows` bundle, whose copy of the `ChatQueueService`\n // class is not the one `AgentModule` provides.\n @Optional() @Inject(AGENT_CHAT_QUEUE) private readonly queue?: ChatQueueService,\n // `@Optional` so a missing WorkflowsModule reaches `WorkflowsAgentRunner`'s clear boot error.\n @Optional() private readonly client?: WorkflowClient,\n @Optional()\n @Inject(WORKFLOWS_MODULE_OPTIONS)\n private readonly workflowsOptions?: WorkflowsModuleOptions,\n ) {\n const durable = options?.durable;\n const configured =\n durableEngineOf(durable) === 'workflows' && typeof durable === 'object'\n ? durable.stepsPerInstance\n : undefined;\n this.stepsPerInstance =\n configured !== undefined && Number.isInteger(configured) && configured > 0\n ? configured\n : DEFAULT_STEPS_PER_INSTANCE;\n }\n\n /** A turn from its first instance. */\n run(ctx: WorkflowContext, input: AgentRunInput): Promise<AgentLoopResult> {\n return this.execute(ctx, { input, runId: ctx.workflowId, segment: 0, carried: {} });\n }\n\n async execute(ctx: WorkflowContext, segment: AgentRunSegmentInput): Promise<AgentLoopResult> {\n const { input, runId } = segment;\n const journal = new TurnJournal(segment.carried);\n const day = input.day ?? utcDay();\n const deps = this.factory.forAgent(input.agentName);\n const sinkRunId = input.sinkRunId ?? runId;\n const childSink = input.sinkRunId !== undefined;\n /** The original error of a checkpoint body that threw in THIS execution: rethrown as itself. */\n const originals = new Map<string, unknown>();\n /** The calls waiting for a person, shown as the instance's custom status. */\n const pending = new Map<string, PendingReply>();\n const showPending = () =>\n ctx.setStatus(pending.size > 0 ? { pendingReplies: [...pending.values()] } : null);\n\n /** A `ctx.step` whose body never fails the step: what it threw is journaled as its outcome. */\n const checkpoint = <T>(name: string, fn: () => Promise<T>): Promise<T> =>\n journal.op(name, async () => {\n const envelope = (await this.ctxCall(() =>\n ctx.step(name, async (): Promise<StepEnvelope> => {\n try {\n const value = await fn();\n return value === undefined ? {} : { v: value };\n } catch (error) {\n originals.set(name, error);\n return { e: serializeTurnError(error) };\n }\n }),\n )) as StepEnvelope;\n if ('e' in envelope) {\n throw originals.get(name) ?? rebuildTurnError(envelope.e);\n }\n return envelope.v as T;\n });\n const step = <T>(name: string, fn: () => Promise<T>): Promise<T> =>\n checkpoint(journal.unique(name), fn);\n\n /** Wait for a person's reply to call `id`, listed as pending meanwhile. */\n const awaitReply = async (\n call: { id: string; toolName: string; kind: PendingReply['kind'] },\n timeoutMs?: number,\n ): Promise<HumanReply | null> => {\n const name = journal.unique(`reply:${call.id}`);\n pending.set(call.id, {\n key: replyKey(runId, call.id),\n runId,\n toolCallId: call.id,\n toolName: call.toolName,\n kind: call.kind,\n });\n showPending();\n const reply = await journal.op(name, () =>\n this.ctxCall(() =>\n ctx.waitForSignal(name, AGENT_REPLY, {\n key: replyKey(runId, call.id),\n ...(timeoutMs !== undefined ? { timeout: timeoutMs } : {}),\n }),\n ),\n );\n // Not on a suspension: the status written as the instance parks must still list the call.\n pending.delete(call.id);\n showPending();\n return reply as HumanReply | null;\n };\n\n const chainBelow = [\n ...(input.delegationPath ?? []),\n ...(input.agentName !== undefined ? [input.agentName] : []),\n ];\n const subThread = (agentName: string) =>\n step(`subthread:${agentName}`, async () => {\n const thread = await this.store.createThread({ actor: input.actor, transient: true });\n return thread.id;\n });\n\n if (input.sinkRunId !== undefined || input.deliverTo !== undefined) {\n await step('activate', () => this.store.setActiveStream(input.threadId, runId));\n }\n\n const hooks: AgentLoopHooks = {\n runId,\n queueMs: async () => {\n const status = await this.client?.getStatus(runId);\n if (status === undefined || status === null) return undefined;\n const now = this.workflowsOptions?.clock?.now() ?? Date.now();\n const waited = now - status.createdAt;\n return Number.isFinite(waited) && waited >= 0 ? waited : undefined;\n },\n openSink: async () => {\n if (childSink) {\n return childSinkWriter(await deps.sink.open(sinkRunId));\n }\n const writer = await deps.sink.open(runId);\n return {\n write: (chunk) => writer.write(chunk),\n fail: (failure) => writer.fail(failure),\n end: async () => {\n const frame = await this.advanceQueue(ctx, step, journal, runId, input, 'completed');\n if (frame !== undefined) {\n await writer.write(encodeStreamEvent(frame));\n }\n await writer.end();\n },\n };\n },\n awaitApproval: async (call: ToolCallRequest, _toolCtx, opts) => {\n const reply = await awaitReply(\n { id: call.id, toolName: call.name, kind: 'approval' },\n opts?.timeoutMs,\n );\n return reply === null\n ? ({ approved: false, expired: true } satisfies Decision)\n : (reply as Decision);\n },\n awaitAnswers: async (request) => {\n const reply = await awaitReply({\n id: request.id,\n toolName: request.source,\n kind: 'elicitation',\n });\n return (reply ?? { approved: false }) as ElicitationReply | Decision;\n },\n step,\n parallel: settleAll,\n isControlFlowError: isEngineControlFlow,\n runAgent: async (agentName, task) => {\n // Named on the call, before any await: parallel delegations get the same names on a replay.\n const name = journal.unique(`delegate:${agentName}`);\n const subThreadId = await subThread(agentName);\n const child: AgentRunInput = {\n agentName,\n threadId: subThreadId,\n actor: input.actor,\n userText: task,\n day,\n delegationDepth: (input.delegationDepth ?? 0) + 1,\n delegationPath: chainBelow,\n parentRunId: runId,\n sinkRunId,\n };\n return journal.op(name, () =>\n this.ctxCall(() =>\n ctx.executeChild<{\n run(c: WorkflowContext, i: AgentRunInput): Promise<AgentLoopResult>;\n }>(AGENT_RUN_WORKFLOW, child, { id: `${ctx.workflowId}/${name}` }),\n ),\n ) as Promise<{ text: string }>;\n },\n // A detached delegation outlives the turn that started it, and a Stop on that turn: an\n // abandoned child, not a cancelled one.\n startAgent: async ({ agentName, task, toolCallId }) => {\n const name = journal.unique(`detach:${toolCallId}`);\n const subThreadId = await subThread(agentName);\n const child: AgentRunInput = {\n agentName,\n threadId: subThreadId,\n actor: input.actor,\n userText: task,\n day,\n delegationDepth: (input.delegationDepth ?? 0) + 1,\n delegationPath: chainBelow,\n parentRunId: runId,\n deliverTo: { threadId: input.threadId, toolCallId },\n };\n const childRunId = await journal.op(name, async () => {\n const handle = await this.ctxCall(() =>\n ctx.startChild(AGENT_RUN_WORKFLOW, child, {\n id: `${runId}.detached.${toolCallId}`,\n parentClose: 'abandon',\n }),\n );\n return handle.id;\n });\n return { runId: childRunId };\n },\n dispatchLlm: (index: number, envelope: LlmStepEnvelope) => {\n const name = journal.unique(`llm:${index}`);\n if (!journal.has(name)) {\n if (journal.liveModelCalls >= this.stepsPerInstance) {\n throw new SegmentBoundary();\n }\n journal.liveModelCalls += 1;\n }\n return journal.op(name, async () => {\n try {\n return (await this.ctxCall(() =>\n ctx.step(name, (attempt) =>\n runLlmStep(\n this.factory,\n { ...envelope, runId, step: index, sinkRunId, childSink },\n { abortSignal: attempt.signal },\n ).catch((error: unknown) => {\n if (!isConfigurationError(error)) throw error;\n const fatal = new NonRetryableStepError((error as Error).message);\n fatal.name = (error as Error).name;\n throw fatal;\n }),\n ),\n )) as BufferedModelTurnResult;\n } catch (error) {\n // The model's own failure, as the loop knows it: `No output generated`, a provider error.\n if (error instanceof StepFailedError) {\n throw rebuildTurnError(stepFailureCause(error));\n }\n throw error;\n }\n });\n },\n // A tool's failure is a result the model reads, not the step's: the step is retried only after\n // a crash, and the tool's `ctx.idempotencyKey` (`<runId>:<toolCallId>`) is the same on that\n // attempt, so a tool that passes it on does its side effect once.\n dispatchTool: (call: ToolCallRequest, envelope: ToolStepEnvelope) =>\n checkpointTool(journal.unique(`tool:${call.id}`), call, envelope),\n };\n\n const checkpointTool = (name: string, call: ToolCallRequest, envelope: ToolStepEnvelope) =>\n journal.op(name, async () => {\n const outcome = (await this.ctxCall(() =>\n ctx.step(name, async (attempt): Promise<StepEnvelope> => {\n try {\n const value = await runToolStep(\n this.factory,\n {\n ...envelope,\n toolCallId: call.id,\n toolType: call.kind === 'action' ? 'action' : 'read',\n sinkRunId,\n childSink,\n },\n { abortSignal: attempt.signal },\n );\n return value === undefined ? {} : { v: value };\n } catch (error) {\n originals.set(name, error);\n return { e: serializeTurnError(error) };\n }\n }),\n )) as StepEnvelope;\n if ('e' in outcome) throw originals.get(name) ?? rebuildTurnError(outcome.e);\n return outcome.v;\n });\n\n try {\n const result = await runAgentLoop({ ...deps, day }, input, hooks);\n await step('deactivate', () => releaseThreadRun(this.store, input.threadId, runId));\n return result;\n } catch (error) {\n if (error instanceof SegmentBoundary) {\n return this.continueInSegment(ctx, { ...segment, carried: journal.outcomes });\n }\n if (isEngineControlFlow(error) || error instanceof SegmentFailed) {\n throw error;\n }\n if (error instanceof RunCancelledError) {\n await step('deactivate', () => releaseThreadRun(this.store, input.threadId, runId));\n await this.settleDetachedParent(step, runId, input, { status: 'cancelled' });\n throw error;\n }\n const durationMs = runDurationMs(error);\n const timed = durationMs !== undefined ? { durationMs } : {};\n const measured = runEndTimings(error);\n const message = error instanceof Error ? error.message : String(error);\n const code = agentFailureCode(error);\n this.logger.error(`agent run ${runId} failed (${code}): ${message}`);\n publishAgentRunFailed({\n runId,\n threadId: input.threadId,\n code,\n message,\n ...timed,\n ...measured,\n context: agentRunContext(input),\n });\n if (isFatalDefinitionError(error)) {\n // The engine will journal nothing more for this run: settle it straight in the store.\n await settleDeadRun(this.store, {\n runId,\n threadId: input.threadId,\n failure: { code, message, ...timed },\n });\n await (await hooks.openSink()).fail(streamFailure(error));\n throw error;\n }\n try {\n await step('persist:run:fail', async () => {\n await this.store.recordRunEnd?.({\n runId,\n status: 'failed',\n ...timed,\n errorCode: code,\n errorMessage: message,\n });\n await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\n });\n const queueFrame = await this.advanceQueue(\n ctx,\n step,\n journal,\n runId,\n input,\n 'failed',\n message,\n );\n await step('deactivate', () => releaseThreadRun(this.store, input.threadId, runId));\n await this.settleDetachedParent(step, runId, input, { status: 'failed', error: message });\n const writer = await hooks.openSink();\n if (queueFrame !== undefined) {\n await writer.write(encodeStreamEvent(queueFrame));\n }\n await writer.fail(streamFailure(error));\n } catch (settling) {\n // A suspend while settling (a checkpoint's retry backoff) settles on the next execution.\n if (isEngineControlFlow(settling)) throw markControlFlow(settling);\n throw settling;\n }\n throw error;\n }\n }\n\n /** The turn goes on in a child instance, from what this one (and those before it) settled. */\n private async continueInSegment(\n ctx: WorkflowContext,\n segment: AgentRunSegmentInput,\n ): Promise<AgentLoopResult> {\n const next: AgentRunSegmentInput = { ...segment, segment: segment.segment + 1 };\n try {\n return (await this.ctxCall(() =>\n ctx.executeChild(AGENT_RUN_SEGMENT_WORKFLOW, next, {\n id: `${segment.runId}~${next.segment}`,\n }),\n )) as AgentLoopResult;\n } catch (error) {\n // The segment that failed settled the run (its row, its stream, its queue): pass it up.\n if (error instanceof ChildWorkflowFailedError) throw new SegmentFailed(error);\n throw error;\n }\n }\n\n /**\n * Hand the thread on past this settling turn, as the `aviary` engine does: the decision is one\n * checkpoint, and the next message starts as an abandoned child under its own id, so the turn\n * ending doesn't cancel it.\n */\n private async advanceQueue(\n ctx: WorkflowContext,\n step: <T>(name: string, fn: () => Promise<T>) => Promise<T>,\n journal: TurnJournal,\n runId: string,\n input: AgentRunInput,\n outcome: QueueSettleOutcome,\n error?: string,\n ): Promise<AgentStreamEvent | undefined> {\n const queue = this.queue;\n if (\n queue === undefined ||\n !queue.supported ||\n input.sinkRunId !== undefined ||\n input.deliverTo !== undefined\n ) {\n return undefined;\n }\n const plan = await step(`queue:${outcome}`, async (): Promise<QueuePlan> => {\n try {\n const settled =\n outcome === 'completed' && (await this.isCancelled(runId)) ? 'cancelled' : outcome;\n return await queue.plan({\n threadId: input.threadId,\n runId,\n outcome: settled,\n ...(error !== undefined ? { error } : {}),\n });\n } catch {\n return {};\n }\n });\n const next = plan.next;\n if (next === undefined) {\n return plan.frame;\n }\n try {\n await journal.op(journal.unique(`queue:start:${next.runId}`), async () => {\n const handle = await this.ctxCall(() =>\n ctx.startChild(AGENT_RUN_WORKFLOW, next.input, {\n id: next.runId,\n parentClose: 'abandon',\n }),\n );\n return handle.id;\n });\n return plan.frame;\n } catch (failure) {\n if (isEngineControlFlow(failure)) throw failure;\n const reason = failure instanceof Error ? failure.message : String(failure);\n return step('queue:restore', async () => {\n await queue.restore(input.threadId, next, 'start_failed', reason);\n return queue.pausedFrame(input.threadId);\n });\n }\n }\n\n private async isCancelled(runId: string): Promise<boolean> {\n try {\n return (await this.client?.getStatus(runId))?.cancelRequested === true;\n } catch {\n return false;\n }\n }\n\n private async settleDetachedParent(\n step: <T>(name: string, fn: () => Promise<T>) => Promise<T>,\n runId: string,\n input: AgentRunInput,\n outcome: { status: 'failed' | 'cancelled'; error?: string },\n ): Promise<void> {\n const delivery = input.deliverTo;\n if (delivery === undefined) return;\n await step('deliver:detached:unsettled', () =>\n settleUnsettledDelegation({\n store: this.store,\n delivery,\n agent: input.agentName ?? 'default',\n runId,\n status: outcome.status,\n ...(outcome.error !== undefined ? { error: outcome.error } : {}),\n }),\n );\n }\n\n /** A `ctx` call whose interrupt carries core's control-flow marker. */\n private async ctxCall<T>(call: () => Promise<T>): Promise<T> {\n try {\n return await call();\n } catch (error) {\n throw markControlFlow(error);\n }\n }\n}\n","import type { ResolveToolUiCatalog, ToolUiChannelGuide } from '@dudousxd/nestjs-agent-core';\nimport type {\n AgentIntake,\n AgentPricingStore,\n AgentStore,\n ApprovalPolicy,\n HistoryPolicy,\n InputProcessor,\n MemoryConfig,\n ModelProvider,\n OutputProcessor,\n Persona,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n SkillsConfig,\n TokenStreamSink,\n ToolRegistry,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n resolveUiCatalog?: ResolveToolUiCatalog;\n /** genui `channels`: the channel's prompt block, and what tool pushes were delivered as. */\n uiChannelGuide?: ToolUiChannelGuide;\n actionApprovalMode?: 'blocking' | 'independent';\n model: ModelProvider;\n store: AgentStore;\n registry: ToolRegistry;\n rolesPolicy: RolesPolicy;\n /** Who approves an action call, and for how long (from `forRoot({ approvalPolicy })`). Undefined → the requester, no expiry. */\n approvalPolicy?: ApprovalPolicy;\n quota?: QuotaStore;\n sink: TokenStreamSink;\n /** Fallback accounting label; the provider's turn result overrides it when set. */\n modelId?: string;\n systemPrompt: string | PromptBuilder;\n /** App-wide `@SystemPromptContributor()` sections appended after the agent's base prompt. */\n promptContributors: PromptContributor[];\n maxSteps: number;\n /** Nesting ceiling for delegation below this agent. Undefined → the loop's default. */\n maxDelegationDepth?: number;\n /** How many times one agent may appear on a chain. Undefined → the loop's default. */\n maxAgentAppearances?: number;\n /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** The agent's personas (`@Agent({ personas })`) — read by the loop only for a run that names one. */\n personas?: Persona[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\n /**\n * Transient-tool-error retry policy (from module options). Undefined → default ON\n * (`{ attempts: 2, backoffMs: 150 }` with the default classifier); `false` → disabled.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /** How many follow-up suggestions to generate after the final turn. Undefined/0 → off. */\n followUpsCount?: number;\n /** Inject-mode retriever (from `forRoot({ retrieval })`). Undefined → no prompt augmentation. */\n retriever?: Retriever;\n /** Passages inject-mode retrieval requests. Undefined → loop default (5). */\n retrievalTopK?: number;\n /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */\n pricingStore?: AgentPricingStore;\n /** The agent's history ceiling, resolved from `@Agent({ history })` / module options. Undefined → unbounded. */\n historyPolicy?: HistoryPolicy;\n /** Module-wide prompt rewriters, applied before every model call. Empty → none. */\n inputProcessors: InputProcessor[];\n /** Module-wide answer gates. NON-EMPTY MEANS THE TURN'S MODEL OUTPUT IS BUFFERED, not streamed. */\n outputProcessors: OutputProcessor[];\n /** The agent's `@Agent({ outputSchema })`, resolved from DI — never over the wire. Undefined → free text. */\n outputSchema?: StandardSchemaV1;\n /** Extra model calls allowed to repair an answer that failed `outputSchema`. Undefined → 1. */\n outputRepairAttempts?: number;\n /** The agent's `@Agent({ intake })` question set, asked before the turn starts. Undefined → none. */\n intake?: AgentIntake;\n /** Whether the model may call the built-in `ask` tool this turn. Undefined/false → it never sees it. */\n ask?: boolean;\n /**\n * The resolved skills seam (`forRoot({ skills })` + discovered `@Skill` providers). Undefined →\n * no catalog, no `skill` tool, and the turn spends no checkpoint on either.\n */\n skills?: SkillsConfig;\n /**\n * The resolved memory seam (`forRoot({ memory })`). Undefined → no block, no `remember` tool, and\n * the turn spends no checkpoint on either.\n */\n memory?: MemoryConfig;\n}\n\nexport function utcDay(date = new Date()): string {\n return date.toISOString().slice(0, 10);\n}\n\n/**\n * Wraps a parent run's sink writer for a sub-agent: `write` forwards (so the sub-agent's tokens and\n * pending action-tool frames reach the human's live stream), but `end` / `fail` are swallowed — the\n * top-level run owns the stream's lifecycle, so a finished/failed child must not close or error the\n * shared stream out from under the parent that is still running. They do `flush` it: a sink that\n * gathers frames (the SQL sink) writes out what the child left, so the parent's next frame —\n * possibly written on another replica — lands after it.\n */\nexport function childSinkWriter(writer: SinkWriter): SinkWriter {\n return {\n write: (chunk) => writer.write(chunk),\n // The top-level run owns end/fail — but what the child wrote must not be held back past it.\n end: async () => {\n await writer.flush?.();\n },\n fail: async () => {\n await writer.flush?.();\n },\n flush: async () => {\n await writer.flush?.();\n },\n };\n}\n","import type {\n ActionApprovalMode,\n ActionProposal,\n ActionProposalOutcome,\n BackgroundActorResolver,\n PriceCatalogOptions,\n TextActionProposalConfig,\n} from '@dudousxd/nestjs-agent-core';\nimport type {\n ActorResolver,\n AgentHistoryWindow,\n AgentStore,\n ApprovalPolicy,\n EmptyRoles,\n HistoryPolicy,\n InputProcessor,\n MemoryProvider,\n ModelCatalog,\n ModelProvider,\n OutputProcessor,\n PromptBuilder,\n QuotaProvider,\n Retriever,\n RolesPolicy,\n ScopeResolver,\n SkillProvider,\n TenancyOption,\n TokenStreamSink,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type {\n CanActivate,\n InjectionToken,\n ModuleMetadata,\n OptionalFactoryDependency,\n Type,\n} from '@nestjs/common';\nimport type { AgentEngine } from './engine.js';\nimport type { FunctionalTool } from './functional-tool.js';\nimport type { QuotaLimits, QuotaPer } from './ledger-quota-provider.js';\nimport type { AgentFunctionCaller } from './nest-ai/agent-functions.js';\nimport type { AgentProtocolAdapter } from './protocol-adapter.js';\n\n/**\n * Which half of the module this process mounts — the split that lets an API pod and a WORKER pod\n * each load `AgentModule` without either one doing the other's job:\n *\n * - `'both'` (default): today's behavior, unconditionally — every controller AND the full durable\n * engine wiring (when `durable` is on). Zero-config single-pod deployments never touch this.\n * - `'http'`: mounts every controller (chat/threads/tool-call/quota/agents/attachments) so the HTTP\n * surface is fully functional, but under `durable` this pod must never EXECUTE agent work. On the\n * `'workflows'` engine that is `WorkflowsModule.forRoot({ worker: false })`; on `'aviary'`,\n * `AgentDurableModuleOptions.surface` (`@dudousxd/nestjs-agent/durable`). This flag only controls\n * the controllers here.\n * - `'engine'`: mounts NO controllers (an API pod's routes have no business existing on a worker\n * pod that never receives HTTP traffic) — everything else (registry/tools/model/store/sinks, the\n * `agent.run` workflow, and its dispatched steps under `AgentDurableModule`) stays wired exactly\n * as `'both'`.\n *\n * A durable deployment mirrors this on `AgentDurableModule.forRoot({ surface })` too — see that\n * module's doc for why the split can't be inferred from this option alone (Nest's static module\n * metadata can't be computed from a runtime-injected value).\n */\nexport type AgentSurface = 'http' | 'engine' | 'both';\n\n/**\n * The durable engine `AgentModuleOptions.durable` runs turns on.\n *\n * - `'workflows'` (what `durable: true` means): NestJS's `@nestjs/workflows`. Import\n * `WorkflowsModule.forRoot()` and `AgentWorkflowsModule` (`@dudousxd/nestjs-agent/workflows`).\n * An API pod that must not run turns imports `WorkflowsModule.forRoot({ worker: false })`.\n * - `'aviary'`: `@dudousxd/nestjs-durable`. Import `DurableModule` and `AgentDurableModule`\n * (`@dudousxd/nestjs-agent/durable`). Choose it for what `@nestjs/workflows` does not do: steps\n * dispatched to a separate fleet over a transport (BullMQ, SQS, ...), Python workers, the\n * SQLite/MikroORM stores, `ctx.patched` for changing a running turn's code in place.\n */\nexport interface AgentDurableOptions {\n /** Default `'workflows'`. */\n engine?: 'workflows' | 'aviary';\n /**\n * `'workflows'` only: model calls per workflow instance. After that many, the turn goes on in a\n * child instance, so no instance's journal grows past what one segment writes (the same idea as\n * `@nestjs/ai`'s `AiAgents` `stepsPerInstance`). Default 10.\n */\n stepsPerInstance?: number;\n}\n\n/** Which durable engine `durable` names: `undefined` when the turns run in-process. */\nexport function durableEngineOf(\n durable: boolean | AgentDurableOptions | undefined,\n): 'workflows' | 'aviary' | undefined {\n if (durable === undefined || durable === false) return undefined;\n if (durable === true) return 'workflows';\n return durable.engine ?? 'workflows';\n}\n\n/**\n * `AgentModuleOptions.attachments` — limits for `POST <base>/attachments`, when the bound\n * `AGENT_ATTACHMENT_STAGING` store does not declare its own (`AgentMediaAttachmentsModule` does, and\n * then it is the only source). Served to clients by `GET <base>/config`.\n */\nexport interface AgentAttachmentsOptions {\n /** Per-file size cap. Defaults to 20 MiB. */\n maxBytes?: number;\n /**\n * Allowed multipart content types. Defaults to what multimodal model providers commonly accept:\n * `image/png`, `image/jpeg`, `image/gif`, `image/webp`, `application/pdf`, `text/plain`, `text/csv`.\n */\n allowedContentTypes?: string[];\n}\n\n/**\n * `AgentModuleOptions.skills` — where a turn's skills come from, and which scopes an actor draws\n * them from. Its PRESENCE turns skills on: `skills: {}` offers whatever the `@Skill`-decorated\n * providers declare, resolved against the actor's own, their tenant's and the deployment's scopes.\n */\nexport interface AgentSkillsOptions {\n /**\n * A provider of your own — skills a host stores and administers itself (per user, per sector, per\n * base). Merged with the discovered `@Skill` classes, and outranking them for a name published at\n * the same scope. Omit → the decorated classes are the whole catalog.\n */\n provider?: SkillProvider;\n /**\n * Which scope tokens an actor draws from, most specific first — the precedence order. Omit → the\n * actor's own (`actor:<id>`), their tenant's (`tenant:<ref>`, when they have one), and `global`.\n * Supply one to add an axis this library has no key for: a sector, a region, a shift.\n */\n scopes?: ScopeResolver;\n /**\n * How many skills the catalog block offers before it starts leaving the widest ones out. Omit →\n * 20. A ceiling on what the SYSTEM PROMPT carries, not on how many a deployment may hold.\n */\n maxSkills?: number;\n}\n\n/**\n * `AgentModuleOptions.memory` — where what the assistant concluded about a person is stored, and how\n * much of it a turn may carry. Its PRESENCE turns memory on.\n *\n * Unlike `skills`, there is no decorator and no zero-config form: a memory is by definition something\n * the agent worked out about someone, so a memory a developer wrote in a class would be an\n * instruction wearing a memory's clothes — which is what `@Skill` and `@SystemPromptContributor()`\n * are for. The rows are the host's from the start.\n */\nexport interface AgentMemoryOptions {\n /**\n * Where the rows live. `forget` is required on it; `write` is what decides the `remember` tool;\n * `search` is what decides whether a turn's block is selected by relevance or read whole. Supply\n * `search` once the applicable set outgrows `maxMemories` — without it the ceiling selects by\n * scope, and the widest scopes are the ones it starves.\n */\n provider: MemoryProvider;\n /**\n * Which scope tokens an actor draws from, most specific first — the precedence order, and the same\n * seam `skills` uses. Omit → the actor's own, their tenant's, and `global`.\n */\n scopes?: ScopeResolver;\n /**\n * How many memories the block carries. Omit → 20. A budget on the PROMPT, never on the store: with\n * a provider that can `search`, this is how many matter right now rather than how many a person\n * may have. Always-on (`pinned`) memories are taken from it first.\n */\n maxMemories?: number;\n /** How long one memory may be, checked when it is written. Omit → 240. */\n maxFactChars?: number;\n}\n\nexport interface AgentModuleOptions {\n /**\n * How an `action` tool waits for its approval. `'blocking'` (default): the turn parks on the\n * decision and resumes when it lands. `'independent'`: the call is recorded as an action proposal\n * and answered at once with a receipt (`{ proposalId, status: 'pending', executed: false }`), the\n * turn finishes, and a background worker runs the action once it is approved — decided through\n * `POST <base>/threads/:threadId/action-proposals/:proposalId/approve|reject`, the approval port or\n * a text command. Needs `backgroundActorResolver` and a store with the proposal capabilities\n * (both checked at boot). See `docs/independent-approvals.md`.\n */\n actionApprovalMode?: ActionApprovalMode;\n /**\n * Resolves the CURRENT actor (id, tenant, roles) for a proposal's recorded `actorRef`/`tenantRef`\n * when the worker runs it — there is no request to read an identity from. Return `null` for an\n * actor that no longer exists or no longer belongs to the tenant; the action then fails rather\n * than running. Required under `actionApprovalMode: 'independent'`.\n */\n backgroundActorResolver?: BackgroundActorResolver;\n /**\n * Tuning for the worker that runs approved proposals under `actionApprovalMode: 'independent'`\n * (started with the module unless `surface: 'http'`). `pollIntervalMs` — how often it looks for\n * queued work, default 1000; `leaseMs` — how long a claim holds before another worker may recover\n * it, default 30000; `maxConcurrency` — proposals claimed per poll, default 1. All positive\n * integers, and `pollIntervalMs` must stay below a third of `leaseMs`. `onSettled` runs after each\n * proposal the worker settles (executed or failed), with the stored proposal — its `outcome` and\n * `executionContext.pageContext` included; a module can subscribe the same way through\n * `ActionProposalWorkerService.onSettled`. `onAdmitted` runs once a settled proposal's outcome\n * was written to its thread — the moment to continue the conversation from it\n * (`ActionProposalWorkerService.onAdmitted` for a module).\n */\n actionProposalWorker?: {\n pollIntervalMs?: number;\n leaseMs?: number;\n maxConcurrency?: number;\n onSettled?(proposal: ActionProposal): void | Promise<void>;\n onAdmitted?(outcome: ActionProposalOutcome): void | Promise<void>;\n };\n /**\n * The words a chat message must consist of to approve or reject a proposal by text, and what the\n * agent answers. English by default (`yes`/`confirm`/`approve`, `no`/`cancel`/`reject`, …); pass\n * `ptBrActionProposalText` from `@dudousxd/nestjs-agent-core` for Portuguese, or your own — either\n * part replaces the default it names, field by field.\n */\n actionProposalText?: TextActionProposalConfig;\n // --- infrastructure ---\n /**\n * The LLM provider. Omit it to run on `@nestjs/ai`: the turns use the models of the application's\n * `AiModule.forRoot({ models })` (the picker lists them by name, `default` first), with each\n * model's settings, `retry` / `timeout` / `resilience`, `fallback`, `pricing` and `onUsage`. Set\n * it to replace them — a `FakeModelProvider` in tests, `aiSdkModel(…)` outside `AiModule`. Not\n * needed when an `engine` runs the turns.\n */\n model?: ModelProvider;\n /**\n * Offer the application's `@nestjs/ai` `@AgentFunction()` methods as agent tools (default), each\n * governed by this library's `@AgentFunction()` options and run through `AiTools.call`, so its guards, interceptors, pipes\n * and filters apply. `false` leaves them to `@nestjs/ai`'s own calls.\n */\n agentFunctions?: boolean;\n /**\n * Who an `@AgentFunction()` call acts for, from the turn's actor — what its guards read. Default:\n * `{ user: actor }`, with no `scopes` (the agent gates by roles); map the actor to scopes here for\n * functions that declare `scopes`.\n */\n agentFunctionCaller?: AgentFunctionCaller;\n /**\n * Where a configured model with no price row gets one, at boot. On application bootstrap every\n * model the `model` provider describes (`aiSdkModel` / `aiSdkModels`) that the bound\n * `AGENT_PRICING_STORE` does not price gets a row — only when it has none, so a price you set is\n * never overwritten — from, in order: `prices` (your own rate card), the built-in AWS GovCloud\n * Bedrock table (for a GovCloud model), then the current [models.dev](https://models.dev) list price\n * (commercial; never used for a GovCloud / China Bedrock model). A model that still has no price, and\n * whose provider reports no cost (anything but OpenRouter / the Vercel AI Gateway), is named in one\n * boot warning with the reason and the `prices` entry that fixes it.\n *\n * Bedrock ids are normalized: an entry for the base id or the `us-gov.` profile id also prices the\n * inference-profile ARN a turn reports. The AWS partition comes from the id (ARN, `us-gov.` prefix),\n * else `region`, else `AWS_REGION` / `AWS_DEFAULT_REGION`.\n *\n * ```ts\n * priceCatalog: {\n * region: 'us-gov-west-1',\n * prices: [\n * { model: 'us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0', input: 3.6, output: 18, cacheRead: 0.36, cacheWrite: 4.5 },\n * ],\n * }\n * ```\n *\n * Omit → models.dev, except under `NODE_ENV=test` (no network from a test suite unless asked).\n * `{ url, fetch }` points at a mirror; `modelsDev: false` never fetches; `false` turns off every\n * source but the built-in table (the warning still runs).\n */\n priceCatalog?: PriceCatalogOptions | false;\n /**\n * Run turns on something other than this library's loop — e.g. `openCode({ host })`. The engine\n * binds `AGENT_RUNNER`; the routes, store, sink, approvals and queue stay the library's. STATIC\n * wiring, like `durable` (see {@link AgentEngine}). Omit → the loop, on `model`.\n */\n engine?: AgentEngine;\n /**\n * The base prompt of the default agent (and of any `@Agent` that declares none) — a string, or a\n * function of the turn's `{ actor, agentName, pageContext }`. Omit → `'You are a helpful\n * assistant.'`.\n */\n systemPrompt?: string | PromptBuilder;\n /**\n * Persistence adapter. Omit it and either import a store module (e.g.\n * `MikroOrmAgentStoreModule.forFeature()`, which binds `AGENT_STORE` globally — it is found and\n * used), or run on the built-in in-memory store — fine for a demo, logged at boot as not for\n * production: threads vanish on restart and are not shared between processes.\n */\n store?: AgentStore;\n /** Live token transport. Defaults to a single-process in-memory sink. */\n sink?: TokenStreamSink;\n /**\n * The caller's budget. `{ limits: { day?: { tokens?, usd? }, month?: { tokens?, usd? } } }` puts\n * ceilings on the built-in ledger provider, and `warnAt` (`0..1`, e.g. `0.8`) a soft limit past\n * which the report carries a `warning`; a {@link QuotaProvider} of your own replaces it. Either\n * way `GET <base>/quota` reports it and a send whose report comes back `blocked` is refused with\n * `429` before the turn starts. Omit → reported (usage off the ledger), never enforced — for a\n * public (anonymous) deployment that means unbounded model spend, so set limits there; they apply\n * per actor, which is per browser in anonymous mode.\n *\n * The USD windows sum the ledger's `cost_usd`: provider-reported cost AND the loop's estimate for a\n * provider that reports none (marked `cost_source = 'estimate'`). `countEstimatedCost: false` counts\n * reported cost only. The default (`true`) is there because otherwise a USD ceiling on Bedrock /\n * OpenAI / Anthropic direct would read $0 and never block.\n *\n * `per` picks whose spend the windows sum: `'actor'` (default) the actor's own; `'tenant'` every\n * actor's in the actor's tenant (`Actor.tenantRef`); `'actor-in-tenant'` the actor's own within\n * that tenant. An actor with no tenant is counted per actor.\n */\n quota?:\n | { limits: QuotaLimits; warnAt?: number; countEstimatedCost?: boolean; per?: QuotaPer }\n | QuotaProvider;\n /**\n * Scope the agent by the request's tenant (from `@dudousxd/nestjs-context`). Default\n * `'inherit'`: follow `ContextModule`'s `tenancy.enabled`, which is off by default. With tenancy\n * on, an actor the `actorResolver` resolved without a `tenantRef` gets the context tenant's id,\n * `recordUsage` records it when the input names none, and thread and run reads (and the governance\n * dashboard) see only the request tenant's rows: another tenant's thread or run answers `404`.\n * A `tenantRef` your resolver sets always wins. `false` keeps the agent out of tenancy.\n */\n tenancy?: TenancyOption;\n /**\n * Which models a caller may pick — `GET <base>/models`, a send's `model`, a thread's pinned model\n * (`PATCH <base>/threads/:id { model }`). Omit → the catalog the model provider carries\n * (`aiSdkModels`), else none, and a request naming a model is refused.\n */\n models?: ModelCatalog;\n /** Tool authorization gate. Defaults to role-in-`defaultRoles`. */\n rolesPolicy?: RolesPolicy;\n /**\n * Who has to approve an `action` tool call, and how long the request stays open. Defaults to the\n * requester (the thread's own actor) with no expiry. A requirement naming another approver (a\n * role) is enforced by `POST tool-call/approve|reject` through `canDecide` — by default, the\n * deciding actor must hold that role. See `ApprovalPolicy`.\n */\n approvalPolicy?: ApprovalPolicy;\n /**\n * Roles a tool requires when its own `roles` is omitted. Default `[]` — no restriction: every\n * tool is callable by whoever `actorResolver` resolved (an anonymous visitor included, when none is\n * configured). `action` tools still park on approval regardless.\n */\n defaultRoles?: string[];\n /**\n * What an empty roles list means to the default `RolesPolicy`: `'allow'` (default) — no\n * restriction, so a tool that names no roles reaches every resolved actor; `'deny'` — nobody, so a\n * tool needs `roles` (or a non-empty `defaultRoles`) to be reachable. For an app where `[]` means\n * \"no one\" — a `roles` computed from permissions that can come out empty. Binds\n * `ClosedRolesPolicy`. Ignored when `rolesPolicy` is set.\n */\n emptyRoles?: EmptyRoles;\n /**\n * Resolves the acting actor for each request (the identity seam). Omit → the endpoints are public\n * and every browser is its own anonymous actor (`AnonymousActorResolver`: an `HttpOnly` cookie,\n * the actor id a digest of it), so visitors never see each other's threads, quota or attachments.\n * A boot notice says so. Require login with `requestUserActorResolver()` (reads `req.user`), or a\n * resolver of your own over your session / JWT / `nestjs-context`.\n */\n actorResolver?: ActorResolver;\n /** Route prefix the controllers mount under. Defaults to `'agent'` (→ `/agent/chat`, …). */\n path?: string;\n /**\n * Run each turn as a durable workflow instead of in-process: each model call and each tool call\n * is a journaled step, a turn parked on a person survives restarts, and a crashed turn resumes\n * where it was. See {@link AgentDurableOptions} for the two engines; `true` is\n * `{ engine: 'workflows' }`, NestJS's own `@nestjs/workflows`.\n *\n * A `@AiTool` handler runs in whichever worker runs the step rather than in the pod that took the\n * request. A handler that resolves anything per invocation from its caller's execution context (a\n * request-scoped ORM EntityManager, an AsyncLocalStorage tenant, a CLS transaction) must\n * establish that context itself.\n *\n * Multi-pod fleets MUST also wire a cross-process token sink (e.g. a Redis pub/sub\n * `TokenStreamSink`): the turn runs on whichever worker claims it, which may not be the pod\n * holding the SSE connection.\n */\n durable?: boolean | AgentDurableOptions;\n /**\n * Static functional tools (`{ spec, handler }`, e.g. from `createExecuteSqlTool`) to register at\n * boot. For tools that need DI-resolved dependencies, use `provideAgentTool(factory, inject)` in a\n * module's `providers` instead.\n */\n tools?: FunctionalTool[];\n /**\n * Per-tool execution timeout in ms. A tool that runs longer is aborted and recorded as failed (the\n * model receives the timeout as its result and can adapt) instead of hanging the turn. Omit → none.\n */\n toolTimeoutMs?: number;\n /**\n * Retries a tool's own invocation, in place, when it throws a classified-transient error (a DB\n * deadlock, a lock-wait timeout, a serialization failure) — never a new durable checkpoint, just\n * repeated attempts inside the same tool-call step. Default ON: `{ attempts: 2, backoffMs: 150 }`\n * with the default classifier. Set `{ classify }` to widen/narrow which errors count as transient\n * (checked in BOTH the inline and durable-dispatched execution paths via DI, since the classify\n * function itself can't ride a durable step's wire envelope), or `false` to disable entirely. A\n * tool's other (non-transient) failures are unaffected — they remain a one-shot business outcome.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /**\n * Suggest follow-up questions after the final turn. `true` → 3 suggestions; `{ count }` → that many.\n * Costs one extra model call per turn (recorded as `follow_ups` usage), stored on the assistant\n * message's `followUps`. Omit/`false` → disabled.\n */\n followUps?: boolean | { count: number };\n /**\n * Always-on (\"inject\") RAG: before each turn, retrieve passages for the user message and augment\n * the system prompt with them. For agentic retrieval (the model decides when to search) DON'T set\n * this — instead expose the tool: `provideAgentTool(createRetrievalTool(retriever))`. Omit → off.\n */\n retrieval?: { mode: 'inject'; retriever: Retriever; topK?: number };\n\n /**\n * Bounds how much of a thread rides into each turn. Omit and a turn carries EVERY message the\n * thread holds, so a long-lived thread costs more each time and eventually exceeds the model's\n * context limit outright. `{ maxMessages }` and/or `{ maxTokens }` keep the newest that fit;\n * `{ summarize: true }` folds what they left out into a leading summary, at the price of one extra\n * model call per run (recorded as `history_summary` usage). An agent can override this for itself\n * with `@Agent({ history })`.\n */\n history?: AgentHistoryWindow;\n /**\n * A {@link HistoryPolicy} of your own — for a window the built-in can't express (pinning the\n * thread's opening brief, keeping every message that carries a tool result, a budget that varies\n * by actor). A convenience-vs-custom pair: this outranks a\n * module-wide `history`, and `@Agent({ history })` outranks both for the agent that declares it.\n * `select` MUST be pure — see the SPI's determinism contract.\n */\n historyPolicy?: HistoryPolicy;\n\n /**\n * Rewrites the prompt before every model call — masking identifiers, stamping a policy preamble,\n * trimming an oversized tool result. Applies to EVERY agent: a transformation one persona can opt\n * out of is not a control. Transformation only; `history`/`historyPolicy` still own which messages\n * are there to transform. A processor needing DI-resolved dependencies is built in\n * `forRootAsync`'s `useFactory` (which has `inject`), the same way `retrieval.retriever` is.\n */\n inputProcessors?: InputProcessor[];\n /**\n * Gates every model answer before the stream, the store or the next step sees it — redact,\n * replace, or refuse the turn outright (which fails it with an `output_rejected` stream error).\n *\n * REGISTERING ONE TURNS OFF LIVE TOKEN STREAMING. Reading the whole answer and streaming it as it\n * is generated cannot both be true, so the turn's model output is buffered and released in one\n * frame once the chain passes. That is the price of a gate that actually gates; see\n * `AgentLoopDeps.outputProcessors` for exactly what a subscriber still receives live.\n */\n outputProcessors?: OutputProcessor[];\n\n /**\n * Offer every agent the built-in `ask` tool, so the model can put its own clarifying question set\n * to the user when it judges the scope is missing. The turn parks on the answers exactly as it\n * parks on a HITL approval, and they arrive through `POST /agent/tool-call/answer`.\n *\n * `ask` is not a registered tool and has no handler — the loop settles it against a person — so no\n * `RolesPolicy` gates it: asking a question performs nothing. An `@Agent({ ask })` overrides this\n * for one persona. Omit → the model never sees it, and nothing about a turn changes.\n */\n ask?: boolean;\n\n /**\n * Authored procedures any agent may pull in when a task calls for one — per-user, per-tenant or\n * deployment-wide, with the most specific winning. Declared as `@Skill`-decorated providers and/or\n * served by a `provider` of your own; offered to the model as a one-line-each catalog it loads\n * from on demand, so an instruction costs a prompt only on the turns that need it.\n *\n * Omit → no catalog, no `skill` tool, and a turn's checkpoint sequence is byte-identical to one\n * that never had the option. See {@link AgentSkillsOptions}.\n */\n skills?: AgentSkillsOptions;\n\n /**\n * What the assistant has concluded about the actor and their organisation, carried into every turn\n * as a bounded block of one-line facts and written by the model through a built-in `remember` tool.\n *\n * NOT the same thing as retrieval, and not a second name for it: `retrieval` answers from documents\n * a person curated and can fix at the source, memory answers from the agent's own inferences about\n * someone who never saw them written. That is why the rows carry an origin, why the block tells the\n * model they may be wrong, and why `GET /agent/memories` + `DELETE /agent/memories/:id` are part of\n * the feature rather than an optional console.\n *\n * Omit → no block, no `remember` tool, and a turn's checkpoint sequence is byte-identical to one\n * that never had the option. See {@link AgentMemoryOptions}.\n */\n memory?: AgentMemoryOptions;\n\n /**\n * The name of the agent a turn uses when the caller doesn't select one. Omit → the single\n * discovered `@Agent` (when there is exactly one), else `'default'` (a bare assistant if no\n * `@Agent` is registered). Agents themselves are declared as `@Agent`-decorated providers, not here.\n */\n defaultAgent?: string;\n\n /**\n * Class decorators applied to EVERY controller this module mounts — the ecosystem's convention,\n * like `@nestjs/mcp`'s own `decorators`: decide who reaches the agent's routes with the official\n * tools, e.g. `[UseGuards(AuthenticationGuard), Can(AgentPolicy, 'chat')]` from\n * `@nestjs/authentication` / `@nestjs/authorization`. Applied to a subclass of each controller made\n * for this registration, so nothing sticks to the shared classes. The controllers are open to\n * `@nestjs/authorization`'s deny-by-default guard otherwise (`CanAnyone()`), and a `@Can()` passed\n * here is still checked. Static wiring.\n *\n * A guard class in `UseGuards(...)` is built by Nest inside this module, so it needs no provider\n * entry, but what it injects must resolve here: from a global module, or (with `forRootAsync`)\n * from a module in `imports` that exports it. The removed `guards` option registered the guard\n * class itself as a provider; nothing does now.\n */\n decorators?: ClassDecorator[];\n\n /** Upload limits when the staging store declares none. Omit → 20 MiB and the default types. */\n attachments?: AgentAttachmentsOptions;\n\n /**\n * Which half of the module this process mounts (see {@link AgentSurface}). Omit → `'both'`,\n * today's behavior with zero change. STATIC top-level field (like `durable`/`path`) — it decides\n * which controllers exist at module-build time, not something a request can flip.\n */\n surface?: AgentSurface;\n\n /**\n * `false` mounts none of the agent's routes, while everything else runs — the way NestJS's own\n * packages leave routes to you (`@nestjs/authentication`'s \"routes of your own\"): serve them from\n * controllers of your own, protected with the official tools. Either call `AgentService` from\n * them, or extend the exported controllers under your own path and decorators:\n * `@Controller('ops/agent/threads') @Can(AgentPolicy, 'chat') class Threads extends ThreadsController {}`.\n * Static wiring, like `surface`.\n */\n routes?: boolean;\n\n /**\n * Wire protocols served alongside the native one, over the same runs — e.g. `[agUiAdapter()]`\n * mounts `POST <path>/ag-ui` (AG-UI 1.0). Their controllers mount under `path`, behind `decorators`,\n * and not at all on `surface: 'engine'`. STATIC, like `surface`.\n */\n adapters?: AgentProtocolAdapter[];\n}\n\nexport interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {\n inject?: Array<InjectionToken | OptionalFactoryDependency>;\n useFactory: (...args: never[]) => AgentModuleOptions | Promise<AgentModuleOptions>;\n /**\n * Route prefix the controllers mount under (default `'agent'`). Static routing metadata, so it\n * lives here rather than in the async factory result (which resolves too late to mount routes).\n */\n path?: string;\n /**\n * Run each turn as a durable workflow (see {@link AgentModuleOptions.durable}). Static wiring\n * metadata (which `AGENT_RUNNER` to bind), so it lives here rather than in the async factory\n * result: the factory resolves too late to swap the runner.\n */\n durable?: boolean | AgentDurableOptions;\n\n /** As {@link AgentModuleOptions.decorators}: static, so it lives here, not in `useFactory`'s result. */\n decorators?: ClassDecorator[];\n\n /**\n * Which half of the module this process mounts (see {@link AgentSurface}). Same static-wiring\n * reasoning as `durable` above — `useFactory` resolves too late to decide\n * which controllers exist. Omit → `'both'`, today's behavior with zero change.\n */\n surface?: AgentSurface;\n /** As {@link AgentModuleOptions.routes}: static, so it lives here. */\n routes?: boolean;\n /** Wire protocols served alongside the native one — see `AgentModuleOptions.adapters`. STATIC. */\n adapters?: AgentProtocolAdapter[];\n /**\n * What runs the turns instead of the loop — see `AgentModuleOptions.engine`. STATIC, like\n * `durable`: it decides which runner `AGENT_RUNNER` binds, before `useFactory` has resolved.\n */\n engine?: AgentEngine;\n}\n","/**\n * The thread message queue, as the durable runner and the `agent.run` workflow ask for it.\n *\n * A token rather than the `ChatQueueService` class: `@dudousxd/nestjs-agent/durable` is a separate\n * bundle with its own copy of every class it imports, so a class used as an injection token there\n * is not the class `AgentModule` provides. `Symbol.for` is the same value in every bundle.\n */\nexport const AGENT_CHAT_QUEUE = Symbol.for('@dudousxd/nestjs-agent:chat-queue');\n","import { createNegotiatedUiCollector } from '@dudousxd/nestjs-agent-core';\nimport { prepareActionProposal, resolveActionProposalApproval } from '@dudousxd/nestjs-agent-core';\nimport {\n type AiToolCtx,\n type BufferedModelTurnResult,\n type FirstTextObserver,\n type LlmStepEnvelope,\n type SinkWriter,\n type ToolStepEnvelope,\n type ToolTransientRetrySetting,\n announcedToolCalls,\n createFrameBuffer,\n createNoopEmitUi,\n createUiCollector,\n encodeStreamEvent,\n intersectAllowLists,\n invokeWithTransientRetry,\n isControlFlowSignal,\n isReplayIntegrityError,\n observeFirstText,\n observeTurnFrames,\n previewToolInputs,\n publishAgentToolRetry,\n registryInputPreviews,\n stampToolKinds,\n toolCallContext,\n traceLlmTurn,\n traceToolExecution,\n withAskTool,\n withChannelDelivery,\n withMemoryTool,\n withSkillTool,\n withToolTimeout,\n withTurnFrames,\n wrapToolPreflightDenied,\n wrapToolStepOutput,\n} from '@dudousxd/nestjs-agent-core';\nimport { turnChannel } from '@dudousxd/nestjs-agent-core/genui';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { childSinkWriter } from '../agent-deps.js';\n\n/**\n * Serializable input for the dispatched `llm` step: a {@link LlmStepEnvelope} plus the sink routing\n * only the durable runner knows (`sinkRunId`/`childSink`) — core's `AgentLoopHooks.dispatchLlm` stays\n * sink-topology-agnostic, so the workflow adds these two fields when it builds the envelope.\n */\nexport interface DispatchedLlmInput extends LlmStepEnvelope {\n /**\n * The dispatching workflow's own `ctx.runId` — the run this step's outcome accrues to for\n * reliability metrics (`bumpRunRetries`). Carried even though the handler cannot bump retries\n * today: the durable handler boundary (`runStepHandler`) hands a `@Step` method only\n * `(input, StepLogger)` — the wire task's `attempt` is not exposed — so there is no clean way to\n * detect a retry from inside the handler. Kept on the envelope so the bump can be wired without a\n * wire-contract change once the durable runtime exposes the attempt.\n */\n runId: string;\n /** The turn index within the run (`llm:<step>`) — the `llm.turn` span's `step` metadata. */\n step: number;\n /** The stream target: `input.sinkRunId ?? ctx.runId` of the dispatching workflow. */\n sinkRunId: string;\n /** True for a sub-agent run — wrap the writer with {@link childSinkWriter} (no end/fail). */\n childSink: boolean;\n}\n\n/**\n * Serializable input for the dispatched `tool` step: a {@link ToolStepEnvelope} plus the call\n * identity the `tool.execution` span needs (`toolCallId`/`toolType`) — core's\n * `AgentLoopHooks.dispatchTool` passes those on the separate `ToolCallRequest` argument, so the\n * workflow folds them into the wire payload when it dispatches (same pattern as\n * {@link DispatchedLlmInput}'s sink routing).\n */\nexport interface DispatchedToolInput extends ToolStepEnvelope {\n toolCallId: string;\n toolType: 'read' | 'action';\n /**\n * Where a component the tool pushes (`ctx.emitUi`) streams live — the same routing as\n * {@link DispatchedLlmInput}. Absent on a task enqueued by a workflow that predates it: the\n * components are then still collected and persisted, just not streamed.\n */\n sinkRunId?: string;\n childSink?: boolean;\n}\n\n/** What the engine running a step hands its body besides the input. */\nexport interface StepBodyOptions {\n /**\n * Aborted when the engine gives up on the attempt (a cancel, a shutdown, a lost lease): handed to\n * the model call and to the tool, so they stop instead of running to the end for nobody.\n */\n abortSignal?: AbortSignal;\n}\n\n/**\n * The model call of one turn, as a step body: re-resolves the agent's deps from THIS process's DI\n * (`AGENT_DEPS_FACTORY.forAgent`), streams to the run's sink, and returns what the loop journals.\n * Engine-neutral: the `@dudousxd/nestjs-durable` engine runs it as `AgentRunSteps.llm`, the\n * `@nestjs/workflows` engine as a `ctx.step`.\n *\n * Retryable: every side effect (persist/quota/stream markers) happens loop-side, so a retry only\n * re-runs the model call and re-streams its tokens. NEVER ends or fails the writer: the run owns\n * the stream's lifecycle.\n */\nexport async function runLlmStep(\n factory: AgentDepsFactory,\n input: DispatchedLlmInput,\n options: StepBodyOptions = {},\n): Promise<BufferedModelTurnResult> {\n const deps = factory.forAgent(input.agentName);\n // The envelope carries only wire-safe data — a `ToolDefinition` holds a live Zod/StandardSchema\n // instance that can't survive JSON transport, so this handler re-derives it from `input.actor`,\n // exactly like the loop's own non-dispatched branch does.\n // `withAskTool` from THIS worker's own resolved deps, not from the envelope: `ask` is module\n // config, uniform across a deployment, so the worker reaches the same list the loop would have\n // built locally without the wire contract having to carry the flag.\n // `withSkillTool` for the same reason as `withAskTool` below it: both are module config,\n // uniform across a deployment, so this worker reaches the same tool list the loop would have\n // built without the wire contract having to carry either flag. WHICH skills the model may load\n // is a different question, and it is answered by the catalog in the prompt this envelope\n // carries — never by this worker's own provider.\n // `withMemoryTool` on the same footing, and for the same reason: whether this deployment offers\n // `remember` is module config. WHICH memories the model was shown is a different question, and\n // it is answered by the block in the prompt this envelope carries — never by this worker's own\n // provider.\n const tools = withMemoryTool({\n tools: withSkillTool({\n tools: withAskTool({\n tools: await deps.registry.definitionsFor(\n input.actor,\n deps.rolesPolicy,\n // The persona narrowing the loop journaled in `persona:resolve` rides the envelope:\n // this worker's own persona config may already say something else.\n intersectAllowLists(deps.toolAllowList, input.personaAllowedTools),\n {\n ...(input.threadId !== undefined ? { threadId: input.threadId } : {}),\n ...(input.preflightContext?.uiCapabilities !== undefined\n ? { uiCapabilities: input.preflightContext.uiCapabilities }\n : {}),\n channel: turnChannel(input.preflightContext?.pageContext),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n },\n ),\n ask: deps.ask,\n }),\n enabled: deps.skills !== undefined && input.builtins?.skills !== false,\n }),\n enabled: deps.memory?.provider.write !== undefined && input.builtins?.memory !== false,\n });\n // `bufferOutput` means the dispatching loop has an output gate to run and this worker's sink is\n // on the far side of it: streaming here would put the answer in front of the reader before the\n // gate ever saw it. Hold the frames and hand them back on the result — the loop releases them\n // (or does not) from the checkpoint that carries the verdict. A durable retry of this step\n // simply re-buffers, so no half-gated turn can reach the sink.\n const buffer = input.bufferOutput === true ? createFrameBuffer() : undefined;\n let writer: SinkWriter;\n // When the reader first saw text, read where the text is written — this worker — and carried on\n // the result, so the run's time to first token survives the journal. A buffered turn reaches\n // the reader only when the loop's gate releases it, and the loop stamps it there.\n let firstText: FirstTextObserver | undefined;\n if (buffer !== undefined) {\n writer = buffer.writer;\n } else {\n const opened = await deps.sink.open(input.sinkRunId);\n firstText = observeFirstText(input.childSink ? childSinkWriter(opened) : opened);\n writer = firstText.writer;\n }\n // Span-wrapped HERE (the genuine execution site), emitting the identical `aviary:agent:llm.turn`\n // span core's non-dispatched branch emits — from whichever worker actually serves the step.\n // Replay-safe by construction: a dispatched step's handler only runs on genuine dispatch (replay\n // resolves the step from its checkpoint without re-invoking a worker), which is exactly why core\n // exports the helper instead of wrapping the `hooks.dispatchLlm` CALL site itself.\n // Reasoning and pushed UI are read off the frames here, where the model actually runs, so they\n // ride this step's result into the journal — the same derivation core's inline branch makes.\n // Streaming previews of a tool's input (genui's partial tree) are drawn here, where the model\n // streams, and ride the result as `previews` so the loop withdraws any the call does not replace.\n const announced = announcedToolCalls(writer);\n const previews = previewToolInputs(\n announced.writer,\n registryInputPreviews(deps.registry, tools, {\n actor: input.actor,\n ...(input.threadId !== undefined ? { threadId: input.threadId } : {}),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.preflightContext?.uiCapabilities !== undefined\n ? { uiCapabilities: input.preflightContext.uiCapabilities }\n : {}),\n channel: turnChannel(input.preflightContext?.pageContext),\n }),\n );\n const frames = observeTurnFrames(previews.writer);\n const turn = withTurnFrames(\n await traceLlmTurn(input.runId, input.step, () =>\n deps.model.runTurn({\n system: input.system,\n messages: input.messages,\n tools,\n sink: frames.writer,\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(options.abortSignal !== undefined ? { abortSignal: options.abortSignal } : {}),\n }),\n ),\n frames.summary(),\n );\n // Stamp each call's kind HERE, from the registry that just built `tools` — this handler is the\n // process that offered the tool, and the kind rides the step's result into the journal from\n // here. The loop that reads the result back may be a pod that registers no tool classes at all\n // (it serves HTTP and replays run bodies), and its own registry would answer `undefined` and\n // downgrade an action to a read — dispatching it, unapproved, to a worker that does know it.\n const stamped = stampToolKinds(turn, deps);\n // A provider that streams no tool frames still gets its calls announced (as the loop's inline\n // branch does) — an outcome for a call never announced cannot be attributed to its tool.\n await announced.announceRest(stamped.toolCalls, tools);\n // Prepare on the worker that owns the registry; a coordinator can have no tool providers.\n // This result rides the existing LLM step, then the coordinator's persist:toolcall checkpoint.\n const allowedTools = intersectAllowLists(deps.toolAllowList, input.personaAllowedTools);\n for (const call of stamped.toolCalls) {\n if (call.kind !== 'action') continue;\n try {\n const context = input.preflightContext ?? {\n actor: input.actor,\n threadId: input.threadId ?? '',\n runId: input.runId,\n requestId: input.runId,\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n };\n if (input.actionApprovalMode === 'independent') {\n const spec = deps.registry.spec(call.name);\n call.actionApproval = await resolveActionProposalApproval({\n actor: input.actor,\n store: deps.store,\n tool: { name: call.name, kind: 'action', ...(spec !== undefined ? { spec } : {}) },\n thread: {\n threadId: context.threadId,\n runId: input.runId,\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n },\n ...(deps.approvalPolicy !== undefined ? { policy: deps.approvalPolicy } : {}),\n });\n }\n if (call.actionApproval?.mode === 'ask') {\n call.prepared = await prepareActionProposal(\n deps.registry,\n call.name,\n call.input,\n { ...toolCallContext(context, call.id), emitUi: createNoopEmitUi(call.id) },\n deps.rolesPolicy,\n allowedTools === undefined ? {} : { allowedTools },\n );\n call.preflight = call.prepared.preflight;\n } else {\n call.preflight = await deps.registry.prepare(\n call.name,\n call.input,\n { ...toolCallContext(context, call.id), emitUi: createNoopEmitUi(call.id) },\n deps.rolesPolicy,\n allowedTools === undefined ? {} : { allowedTools },\n );\n }\n } catch (error) {\n if (isControlFlowSignal(error) || isReplayIntegrityError(error)) throw error;\n call.preflight = {\n status: 'failed',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n const shown = previews.shown();\n const previewed = shown.length > 0 ? { ...stamped, previews: shown } : stamped;\n const firstTextAt = firstText?.firstTextAt();\n if (buffer !== undefined) {\n return { ...previewed, bufferedFrames: buffer.frames() };\n }\n return firstTextAt === undefined ? previewed : { ...previewed, firstTextAt };\n}\n\n/**\n * One tool execution, as a step body (see {@link runLlmStep}). Applies the tool's timeout and its\n * classified-transient retry in place, inside this one step, and refuses an action tool that\n * reaches it without approval.\n */\nexport async function runToolStep(\n factory: AgentDepsFactory,\n input: DispatchedToolInput,\n options: StepBodyOptions = {},\n): Promise<unknown> {\n const deps = factory.forAgent(input.ctx.agentName);\n // The approval gate lives in the LOOP, which resolved this call's kind from the registry of the\n // process that ran the body. This worker has its own registry, and it is the process that\n // actually runs the tool — so if it knows the tool as an `action` while the envelope says the\n // loop auto-executed it, the loop resolved the kind against a registry that was missing it, and\n // running the tool here would perform an approved-only action nobody approved. Refuse: the loop\n // reports it as a tool failure the model can answer for, which is recoverable, unlike the side\n // effect.\n if (deps.registry.spec(input.toolName)?.kind === 'action' && input.toolType !== 'action') {\n throw new Error(\n `tool \"${input.toolName}\" is an action tool but was dispatched without approval: the dispatching process resolved its kind against a registry that does not have it`,\n );\n }\n // `ctx.emitUi` streams each push to the run's sink as it happens (opened on the first push, and\n // never ended — the workflow owns the stream) and collects it for the step's RESULT, which is\n // how the pushes reach the message: the dispatching loop persists them from its own checkpoint.\n const sinkRunId = input.sinkRunId;\n let opened: Promise<SinkWriter> | undefined;\n const ui = createNegotiatedUiCollector(\n input.toolCallId,\n input.ctx,\n deps.resolveUiCatalog,\n sinkRunId === undefined\n ? undefined\n : async (event) => {\n opened ??= Promise.resolve(deps.sink.open(sinkRunId)).then((writer) =>\n input.childSink === true ? childSinkWriter(writer) : writer,\n );\n await (await opened).write(encodeStreamEvent(event));\n },\n );\n // AgentDeps carries no `host` today (AgentDepsFactory never populates one), so the rebuilt ctx\n // is exactly `input.ctx` plus `emitUi` — no narrower than what the non-dispatched path threads.\n const ctx: AiToolCtx = {\n ...toolCallContext(input.ctx, input.toolCallId),\n emitUi: ui.emit,\n ...(options.abortSignal !== undefined ? { abortSignal: options.abortSignal } : {}),\n };\n // The envelope carries the numeric half (attempts/backoffMs) the dispatching loop already\n // resolved — the SAME policy as the non-dispatched path. `classify` isn't wire-safe, so it's\n // resolved from THIS worker's own local module options instead (same DI re-resolution as\n // `registry`/`rolesPolicy` above) — a custom classifier applies host-side in both processes.\n const localClassify =\n deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : undefined;\n const transientRetry: ToolTransientRetrySetting =\n input.transientRetry === false\n ? false\n : {\n attempts: input.transientRetry.attempts,\n backoffMs: input.transientRetry.backoffMs,\n ...(localClassify !== undefined ? { classify: localClassify } : {}),\n };\n // Span-wrapped HERE like `llm` above (same replay-safety-by-construction reasoning) — the\n // timeout AND the retry loop sit INSIDE the span so every attempt (and a timed-out attempt)\n // surfaces under the span's error phase.\n const allowedTools = intersectAllowLists(\n deps.toolAllowList,\n input.allowedTools === undefined ? undefined : [...input.allowedTools],\n );\n let output: unknown;\n // The tool's own time, measured here where it runs and carried on the result: the loop reads\n // this step back from the journal, so its own clock would time the read, not the tool.\n const toolStartedAt = Date.now();\n try {\n output = await traceToolExecution(\n input.ctx.runId,\n { toolCallId: input.toolCallId, toolName: input.toolName, toolType: input.toolType },\n () =>\n invokeWithTransientRetry(\n () => {\n // A retry is a new attempt of the same call: its pushes reuse the failed attempt's ids.\n ui.restart();\n const invocation = deps.registry.invoke(\n input.toolName,\n input.input,\n ctx,\n deps.rolesPolicy,\n allowedTools === undefined ? {} : { allowedTools },\n );\n return input.timeoutMs !== undefined\n ? withToolTimeout(invocation, input.timeoutMs, input.toolName)\n : invocation;\n },\n transientRetry,\n {\n onRetry: (attempt, error) => {\n publishAgentToolRetry({\n toolName: input.toolName,\n toolCallId: input.toolCallId,\n attempt,\n message: error instanceof Error ? error.message : String(error),\n });\n },\n },\n ),\n );\n } catch (error) {\n if (error instanceof Error && error.name === 'ToolPreflightDeniedError') {\n return wrapToolPreflightDenied(error.message);\n }\n throw error;\n }\n // Wrapped only when the dispatching loop asked for it (`collectUi`) — a loop that predates that\n // always reads the bare output it expects, and every loop that asks reads the envelope back,\n // which now always carries the tool's measured time.\n // On a channel the server draws for, the model reads what the user actually got there.\n const executionMs = Date.now() - toolStartedAt;\n output = await withChannelDelivery(deps, input.ctx, output, ui.components());\n return input.collectUi === true\n ? wrapToolStepOutput(output, ui.components(), ui.text(), executionMs)\n : output;\n}\n","import type { HumanReply } from '@dudousxd/nestjs-agent-core';\nimport { WorkflowSignal } from '@nestjs/workflows';\n\n/**\n * A person's reply to a call a turn is parked on: a `Decision` on an action tool, or the answers to\n * a question set. Keyed by {@link replyKey}, so a reply reaches only the call it answers.\n */\nexport const AGENT_REPLY = new WorkflowSignal<HumanReply>('aviary.agent.reply');\n\n/** The key a reply to call `toolCallId` of run `runId` is sent and awaited under. */\nexport function replyKey(runId: string, toolCallId: string): string {\n return `${runId}:${toolCallId}`;\n}\n\n/** A call waiting for a person, as `WorkflowsAgentRunner.pendingReplies()` lists it. */\nexport interface PendingReply {\n /** What the reply is signalled under ({@link replyKey}). */\n key: string;\n /** The turn's run id. */\n runId: string;\n toolCallId: string;\n /** The tool, or `'ask'` / `'intake'` for a question set. */\n toolName: string;\n kind: 'approval' | 'elicitation';\n}\n","import {\n OutputRejectedError,\n QuotaExceededError,\n RunCancelledError,\n StructuredOutputError,\n} from '@dudousxd/nestjs-agent-core';\nimport { isWorkflowInterrupt } from '@nestjs/workflows';\n\n/**\n * The marker core's loop reads to tell a runner unwinding the turn from a failure (see\n * `isControlFlowSignal` in core). `@nestjs/workflows` interrupts carry none, so every `ctx` call\n * this engine makes stamps it on the interrupt it throws: then every `catch` in the loop, the ones\n * that consult `isControlFlowError` and the ones that only read the marker, lets it through.\n */\nconst CONTROL_FLOW_SIGNAL = Symbol.for('aviary:durable:control-flow');\n\n/** Mark `error` as control flow when it is a `@nestjs/workflows` interrupt (a suspend, a cancel...). */\nexport function markControlFlow(error: unknown): unknown {\n if (isWorkflowInterrupt(error) && typeof error === 'object' && error !== null) {\n (error as { [CONTROL_FLOW_SIGNAL]?: boolean })[CONTROL_FLOW_SIGNAL] = true;\n }\n return error;\n}\n\n/**\n * Thrown when an instance has made its share of model calls (`stepsPerInstance`): the turn goes on\n * in a child instance. Control flow, never a failure.\n */\nexport class SegmentBoundary extends Error {\n constructor() {\n super('The turn goes on in a child workflow instance');\n this.name = 'SegmentBoundary';\n (this as unknown as { [CONTROL_FLOW_SIGNAL]: boolean })[CONTROL_FLOW_SIGNAL] = true;\n }\n}\n\n/** Is this the engine unwinding the turn rather than something the agent did? */\nexport function isEngineControlFlow(error: unknown): boolean {\n return isWorkflowInterrupt(error) || error instanceof SegmentBoundary;\n}\n\n/** An error as JSON: its name, its message and its own JSON-safe fields (a `code`, a `status`). */\nexport interface SerializedTurnError {\n name: string;\n message: string;\n props?: Record<string, unknown>;\n}\n\n/** What one journaled operation came to: its value, or the error it threw. */\nexport type TurnOutcome = { v?: unknown } | { e: SerializedTurnError };\n\nexport function serializeTurnError(error: unknown): SerializedTurnError {\n if (!(error instanceof Error)) {\n return { name: 'Error', message: String(error) };\n }\n const props: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(error)) {\n if (key === 'name' || key === 'message' || key === 'stack') continue;\n try {\n const json = JSON.stringify(value);\n if (json !== undefined) props[key] = JSON.parse(json);\n } catch {\n // Not JSON: left out, as a journal would.\n }\n }\n return {\n name: error.name,\n message: error.message,\n ...(Object.keys(props).length > 0 ? { props } : {}),\n };\n}\n\n/**\n * The failure a `StepFailedError` gave up on — its `cause`, the step's error as the journal kept it\n * (`{ name, message }`). Read defensively: a cause that is missing or not that shape (an older\n * journal, an engine change) falls back to the cause as text, or to the step error's own message,\n * rather than throwing a `TypeError` in place of the turn's real failure.\n */\nexport function stepFailureCause(error: { cause?: unknown; message: string }): SerializedTurnError {\n const cause = error.cause;\n if (typeof cause === 'object' && cause !== null) {\n const { name, message } = cause as { name?: unknown; message?: unknown };\n if (typeof message === 'string') {\n return { name: typeof name === 'string' ? name : 'Error', message };\n }\n }\n if (cause === undefined || cause === null) return { name: 'Error', message: error.message };\n return { name: 'Error', message: typeof cause === 'string' ? cause : safeString(cause) };\n}\n\nfunction safeString(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** Core's errors the runners branch on by class (`agentFailureCode`), rebuilt as themselves. */\nconst KNOWN_ERRORS: Record<string, { prototype: Error }> = {\n QuotaExceededError,\n RunCancelledError,\n OutputRejectedError,\n StructuredOutputError,\n};\n\n/** The error a journal recorded, as an `Error` again (of core's own class, when it is one). */\nexport function rebuildTurnError(serialized: SerializedTurnError): Error {\n const prototype = KNOWN_ERRORS[serialized.name]?.prototype ?? Error.prototype;\n const error = Object.create(prototype) as Error;\n Object.assign(error, serialized.props ?? {});\n Object.defineProperty(error, 'name', {\n value: serialized.name,\n writable: true,\n configurable: true,\n });\n Object.defineProperty(error, 'message', {\n value: serialized.message,\n writable: true,\n configurable: true,\n });\n Object.defineProperty(error, 'stack', {\n value: `${serialized.name}: ${serialized.message}`,\n writable: true,\n configurable: true,\n });\n return error;\n}\n\n/**\n * The turn's view of its journal, over `@nestjs/workflows`.\n *\n * NAMES. The engine wants every step, wait and child name unique per run; the loop's checkpoint\n * names are unique per call site, not per run (two delegations to one agent both create a\n * `subthread:<agent>`). {@link unique} numbers repeats in CALL order (`name`, `name#2`, ...): the\n * loop invokes its parallel tasks synchronously in list order, so the numbering is the same on every\n * replay.\n *\n * SEGMENTS. A turn that runs past `stepsPerInstance` model calls goes on in a child instance, which\n * replays the loop from the top. What the parent's operations came to is handed to the child as\n * `carried`, and {@link op} answers a carried name from it without touching the child's journal, so\n * each instance's journal holds only the operations of its own segment.\n */\nexport class TurnJournal {\n private readonly counts = new Map<string, number>();\n /** Every operation's outcome so far: the carried ones, then this instance's. */\n readonly outcomes: Record<string, TurnOutcome>;\n /** Model calls this instance made itself (not carried). */\n liveModelCalls = 0;\n\n constructor(carried: Record<string, TurnOutcome> = {}) {\n this.outcomes = { ...carried };\n }\n\n /** `base` the first time, `base#2` the second, ... */\n unique(base: string): string {\n const count = (this.counts.get(base) ?? 0) + 1;\n this.counts.set(base, count);\n return count === 1 ? base : `${base}#${count}`;\n }\n\n /** Was `name` carried from an earlier segment, or already settled in this one? */\n has(name: string): boolean {\n return name in this.outcomes;\n }\n\n /**\n * Run `live` (a `ctx` operation) once per run: a name an earlier segment settled answers from\n * `carried`. A failure is recorded too, so a later segment replays it as the same failure; the\n * engine's own control flow is not.\n */\n async op<T>(name: string, live: () => Promise<T>): Promise<T> {\n const known = this.outcomes[name];\n if (known !== undefined) {\n if ('e' in known) throw rebuildTurnError(known.e);\n return known.v as T;\n }\n try {\n const value = await live();\n this.outcomes[name] = value === undefined ? {} : { v: value };\n return value;\n } catch (error) {\n if (isEngineControlFlow(error)) throw markControlFlow(error);\n this.outcomes[name] = { e: serializeTurnError(error) };\n throw error;\n }\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n AGENT_SINK,\n AGENT_STORE,\n type AgentRunContext,\n type AgentRunInput,\n type AgentRunStartOptions,\n type AgentRunner,\n type AgentStore,\n type DetachedDelivery,\n type HumanReply,\n type TokenStreamSink,\n encodeStreamEvent,\n publishAgentRunCancelled,\n releaseThreadRun,\n settleUnsettledDelegation,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, Optional } from '@nestjs/common';\nimport {\n WorkflowClient,\n type WorkflowInstanceDetails,\n WorkflowNotFoundError,\n type WorkflowStatus,\n} from '@nestjs/workflows';\nimport { utcDay } from '../agent-deps.js';\nimport { InProcessTokenStreamSink } from '../in-process-sink.js';\nimport type { ChatQueueService } from '../queue/chat-queue.service.js';\nimport { AGENT_CHAT_QUEUE } from '../queue/chat-queue.token.js';\nimport { AGENT_REPLY, type PendingReply, replyKey } from './agent-reply.signal.js';\nimport { AgentRunFlow } from './agent-run.flow.js';\n\nconst ENDED: ReadonlySet<WorkflowStatus> = new Set([\n 'completed',\n 'failed',\n 'cancelled',\n 'compensation_failed',\n]);\n\n/** The fields of a recorded `AgentRunInput` this runner reads back, structurally. */\ninterface RecordedInput {\n threadId?: unknown;\n sinkRunId?: unknown;\n deliverTo?: unknown;\n agentName?: unknown;\n parentRunId?: unknown;\n actor?: { id?: unknown; tenantRef?: unknown };\n}\n\nfunction recorded(input: unknown): RecordedInput {\n return typeof input === 'object' && input !== null ? (input as RecordedInput) : {};\n}\n\nfunction deliveryOf(input: unknown): { delivery: DetachedDelivery; agent: string } | undefined {\n const { deliverTo, agentName } = recorded(input);\n if (\n typeof deliverTo !== 'object' ||\n deliverTo === null ||\n typeof (deliverTo as { threadId?: unknown }).threadId !== 'string' ||\n typeof (deliverTo as { toolCallId?: unknown }).toolCallId !== 'string'\n ) {\n return undefined;\n }\n return {\n delivery: deliverTo as DetachedDelivery,\n agent: typeof agentName === 'string' ? agentName : 'default',\n };\n}\n\nfunction runContextOf(input: unknown): AgentRunContext | undefined {\n const { actor, agentName, parentRunId } = recorded(input);\n if (typeof actor?.id !== 'string') return undefined;\n return {\n actorId: actor.id,\n ...(typeof agentName === 'string' ? { agentName } : {}),\n ...(typeof actor.tenantRef === 'string' ? { tenantRef: actor.tenantRef } : {}),\n ...(typeof parentRunId === 'string' ? { parentRunId } : {}),\n };\n}\n\n/**\n * Runs agent turns on NestJS's `@nestjs/workflows` (`durable: true`). `start` creates the\n * `aviary.agent.run` instance under the run id and returns; whichever worker claims it runs the turn\n * and streams to the sink. A person's reply to a parked call is the `AGENT_REPLY` signal keyed by\n * `<runId>:<toolCallId>`; a Stop is `WorkflowClient.cancel`.\n */\n@Injectable()\nexport class WorkflowsAgentRunner implements AgentRunner {\n private readonly logger = new Logger(WorkflowsAgentRunner.name);\n private readonly client: WorkflowClient;\n\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_SINK) private readonly sink: TokenStreamSink,\n @Optional() client?: WorkflowClient,\n @Optional() @Inject(AGENT_CHAT_QUEUE) private readonly queue?: ChatQueueService,\n ) {\n if (client === undefined) {\n throw new Error(\n \"AgentWorkflowsModule runs turns on @nestjs/workflows: import WorkflowsModule.forRoot() from '@nestjs/workflows' \" +\n '(WorkflowsModule.forRoot({ worker: false }) on a process that must not run turns, such as an API pod). ' +\n 'No WorkflowClient was found.',\n );\n }\n this.client = client;\n if (this.sink instanceof InProcessTokenStreamSink) {\n this.logger.warn(\n 'durable turns with the default InProcessTokenStreamSink, which only buffers tokens in this process: ' +\n 'fine while this process runs the workflow worker, but a turn claimed by another process cannot stream ' +\n 'to this one. Wire a cross-process TokenStreamSink (e.g. the Redis one) before running several processes.',\n );\n }\n }\n\n async start(\n input: AgentRunInput,\n options: AgentRunStartOptions = {},\n ): Promise<{ runId: string }> {\n const stamped: AgentRunInput = { ...input, day: input.day ?? utcDay() };\n const runId = options.runId ?? randomUUID();\n await this.client.start(AgentRunFlow, stamped, { id: runId });\n return { runId };\n }\n\n /** Not ended as far as the engine knows. An unknown run counts as running, and so does one it can't be asked about. */\n async isRunActive(runId: string): Promise<boolean> {\n try {\n const status = (await this.client.getStatus(runId))?.status;\n return status === undefined || !ENDED.has(status);\n } catch {\n return true;\n }\n }\n\n async signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void> {\n const key = replyKey(runId, toolCallId);\n // The first reply to a call counts: a repeat is stored once and never seen.\n await this.client.signal(AGENT_REPLY, reply, { key, id: key });\n }\n\n /** The engine's view of a run: status, custom status, waits, children. `null` for an unknown id. */\n getStatus(runId: string): Promise<WorkflowInstanceDetails | null> {\n return this.client.getStatus(runId, { children: true });\n }\n\n /**\n * The calls of run `runId` waiting for a person now, in the instance it started in, in the\n * instances it went on in, and in the sub-agent runs it delegated to.\n */\n async pendingReplies(runId: string): Promise<PendingReply[]> {\n const found: PendingReply[] = [];\n const visit = async (id: string): Promise<void> => {\n const details = await this.client.getStatus(id, { children: true });\n if (details === null) return;\n const status = details.customStatus as { pendingReplies?: PendingReply[] } | null;\n found.push(...(status?.pendingReplies ?? []));\n for (const child of details.children ?? []) {\n // A detached run is a run of its own: it lists its calls under its own id.\n if (!ENDED.has(child.status) && child.parentClose !== 'abandon') await visit(child.id);\n }\n };\n await visit(runId);\n return found;\n }\n\n /**\n * Stop a run: the engine stops the turn at its next `ctx` call (a parked turn at once), and\n * cancels the sub-agent runs it is waiting on. What the engine knows nothing about is settled\n * here, as on the `aviary` engine: the delegation a detached run answers, the thread's queue and\n * live stream, the subscriber's stream (a `cancelled` frame and a normal end), the run's row.\n */\n async cancel(runId: string): Promise<void> {\n this.logger.log(`cancelling agent run ${runId}`);\n const details = await this.client.getStatus(runId).catch(() => null);\n const input = details?.input;\n const { threadId, sinkRunId, deliverTo } = recorded(input);\n try {\n await this.client.cancel(runId, 'Stopped');\n } catch (error) {\n if (!(error instanceof WorkflowNotFoundError)) throw error;\n }\n const target = deliveryOf(input);\n if (target !== undefined) {\n await settleUnsettledDelegation({\n store: this.store,\n delivery: target.delivery,\n agent: target.agent,\n runId,\n status: 'cancelled',\n }).catch((error: unknown) =>\n this.logger.error(\n `could not settle the delegation of cancelled run ${runId}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n ),\n );\n }\n const writer = await this.sink.open(runId);\n if (typeof threadId === 'string') {\n const threadTurn = sinkRunId === undefined && deliverTo === undefined;\n if (this.queue?.supported === true && threadTurn) {\n try {\n const frame = await this.queue.handoff(\n { threadId, runId, outcome: 'cancelled' },\n (next, nextRunId) => this.start(next, { runId: nextRunId }),\n );\n if (frame !== undefined) await writer.write(encodeStreamEvent(frame));\n } catch (error) {\n this.logger.error(\n `could not advance the queue of thread ${threadId} after cancelling ${runId}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n await releaseThreadRun(this.store, threadId, runId);\n }\n await writer.write(encodeStreamEvent({ kind: 'cancelled' }));\n await writer.end();\n const durationMs =\n details !== null && details !== undefined\n ? Math.max(0, details.updatedAt - details.createdAt)\n : undefined;\n const context = runContextOf(input);\n publishAgentRunCancelled({\n runId,\n ...(typeof threadId === 'string' ? { threadId } : {}),\n ...(durationMs !== undefined ? { durationMs } : {}),\n ...(context !== undefined ? { context } : {}),\n });\n await this.store.recordRunEnd?.({\n runId,\n status: 'cancelled',\n ...(durationMs !== undefined ? { durationMs } : {}),\n });\n }\n}\n","import {\n AgentStreamError,\n type SinkWriter,\n type StreamError,\n type SubscribeOptions,\n type TokenStreamSink,\n} from '@dudousxd/nestjs-agent-core';\n\ninterface RunBuffer {\n chunks: Uint8Array[];\n ended: boolean;\n failure?: StreamError;\n notify: Set<() => void>;\n /** When the run last wrote anything, for the live-run TTL. */\n lastWriteAt: number;\n /** Drops the buffer: on the live-run TTL while the run streams, on the grace period once it ended. */\n expiry: ReturnType<typeof setTimeout> | undefined;\n}\n\n/**\n * How long a run that stopped writing without ending keeps its buffer — a turn on a crashed or\n * cancelled path that never reached `end()`. The same window the Redis sinks give a stream past its\n * last write.\n */\nconst LIVE_TTL_MS = 3_600_000;\n\n/**\n * How long an ended run's buffer outlives its `end()`/`fail()`, for a subscriber that attaches just\n * after the turn finished. Short, because nothing reached through a request replays a finished run:\n * the service only attaches a caller to a run that is still its thread's active stream.\n */\nconst ENDED_GRACE_MS = 60_000;\n\n/**\n * The default `TokenStreamSink`: buffers chunks per run in-process so a reconnecting subscriber\n * replays everything so far, then follows live. A run's buffer is dropped {@link ENDED_GRACE_MS}\n * after it ends, or {@link LIVE_TTL_MS} after its last write if it never does.\n *\n * Single-replica only. Because the buffer lives in one process's memory, a resume/reconnect that\n * lands on a different replica than the one running the turn finds an empty buffer — the stream\n * appears stalled. For multi-replica deployments, supply a shared-transport `TokenStreamSink`\n * (e.g. Redis pub/sub keyed by runId) via `AgentModule.forRoot({ sink })`.\n */\nexport class InProcessTokenStreamSink implements TokenStreamSink {\n private readonly runs = new Map<string, RunBuffer>();\n /** Subscribers of a run nothing has opened yet, woken by its `open()`. */\n private readonly waiting = new Map<string, Set<() => void>>();\n\n private buffer(runId: string): RunBuffer {\n let buf = this.runs.get(runId);\n if (buf === undefined) {\n buf = {\n chunks: [],\n ended: false,\n notify: new Set(),\n lastWriteAt: Date.now(),\n expiry: undefined,\n };\n this.runs.set(runId, buf);\n this.expireAfter(runId, buf, LIVE_TTL_MS);\n const waiters = this.waiting.get(runId);\n this.waiting.delete(runId);\n for (const resolve of waiters ?? []) {\n resolve();\n }\n }\n return buf;\n }\n\n private expireAfter(runId: string, buf: RunBuffer, ms: number): void {\n if (buf.expiry !== undefined) {\n clearTimeout(buf.expiry);\n }\n buf.expiry = setTimeout(() => {\n buf.expiry = undefined;\n const idle = Date.now() - buf.lastWriteAt;\n if (!buf.ended && idle < LIVE_TTL_MS) {\n this.expireAfter(runId, buf, LIVE_TTL_MS - idle);\n return;\n }\n this.drop(runId, buf);\n }, ms);\n buf.expiry.unref?.();\n }\n\n /** Forget the run, and let anyone still following it finish as if it had ended. */\n private drop(runId: string, buf: RunBuffer): void {\n if (buf.expiry !== undefined) {\n clearTimeout(buf.expiry);\n buf.expiry = undefined;\n }\n if (this.runs.get(runId) === buf) {\n this.runs.delete(runId);\n }\n buf.ended = true;\n this.wake(buf);\n }\n\n private wake(buf: RunBuffer): void {\n for (const resolve of buf.notify) {\n resolve();\n }\n buf.notify.clear();\n }\n\n private finish(runId: string, buf: RunBuffer): void {\n buf.ended = true;\n this.wake(buf);\n this.expireAfter(runId, buf, ENDED_GRACE_MS);\n }\n\n /**\n * The run's writer. Each call finds the run's buffer afresh, so a run that went quiet past the\n * live TTL (parked on a person) and then writes again starts a new buffer its next subscriber\n * follows, rather than writing into one nothing reads.\n */\n open(runId: string): SinkWriter {\n this.buffer(runId);\n return {\n write: (chunk: Uint8Array) => {\n const buf = this.buffer(runId);\n buf.chunks.push(chunk);\n buf.lastWriteAt = Date.now();\n this.wake(buf);\n },\n end: () => {\n this.finish(runId, this.buffer(runId));\n },\n fail: (error: StreamError) => {\n const buf = this.buffer(runId);\n buf.failure = error;\n this.finish(runId, buf);\n },\n };\n }\n\n async *subscribe(runId: string, options: SubscribeOptions = {}): AsyncIterable<Uint8Array> {\n const { signal } = options;\n let buf = this.runs.get(runId);\n while (buf === undefined) {\n // Not opened yet — the subscriber is early. Waits without creating the run, so a runId that\n // never streams leaves nothing behind once its subscriber goes.\n const waiters = this.waiting.get(runId) ?? new Set<() => void>();\n this.waiting.set(runId, waiters);\n let resolve: () => void = () => {};\n const opened = new Promise<void>((r) => {\n resolve = r;\n });\n waiters.add(resolve);\n try {\n if (!(await untilAborted(opened, signal))) {\n return;\n }\n } finally {\n waiters.delete(resolve);\n if (waiters.size === 0 && this.waiting.get(runId) === waiters) {\n this.waiting.delete(runId);\n }\n }\n buf = this.runs.get(runId);\n }\n let index = 0;\n while (true) {\n while (index < buf.chunks.length) {\n const chunk = buf.chunks[index];\n index += 1;\n if (chunk !== undefined) {\n yield chunk;\n }\n }\n if (buf.ended) {\n // Drain buffered chunks first, then raise the failure as a typed terminal.\n if (buf.failure !== undefined) {\n throw new AgentStreamError(buf.failure);\n }\n return;\n }\n const current = buf;\n let resolve: () => void = () => {};\n const woken = new Promise<void>((r) => {\n resolve = r;\n });\n current.notify.add(resolve);\n try {\n if (!(await untilAborted(woken, signal))) {\n return;\n }\n } finally {\n current.notify.delete(resolve);\n }\n }\n }\n\n close(runId: string): void {\n const buf = this.runs.get(runId);\n if (buf?.expiry !== undefined) {\n clearTimeout(buf.expiry);\n }\n this.runs.delete(runId);\n }\n}\n\n/** Resolves `true` once `promise` does, or `false` as soon as `signal` aborts. */\nasync function untilAborted(\n promise: Promise<void>,\n signal: AbortSignal | undefined,\n): Promise<boolean> {\n if (signal === undefined) {\n await promise;\n return true;\n }\n if (signal.aborted) {\n return false;\n }\n let onAbort: () => void = () => {};\n const aborted = new Promise<false>((resolve) => {\n onAbort = () => resolve(false);\n signal.addEventListener('abort', onAbort, { once: true });\n });\n try {\n return await Promise.race([promise.then(() => true as const), aborted]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n"],"mappings":"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","names":["AGENT_WORKFLOWS_RUNNER","Global","Module","Workflow","AGENT_DEPS_FACTORY","AGENT_OPTIONS","AGENT_STORE","RUN_ENDED_BEFORE_TOOL_CALL","RunCancelledError","agentFailureCode","agentRunContext","encodeStreamEvent","isReplayIntegrityError","publishAgentRunFailed","releaseThreadRun","runAgentLoop","runDurationMs","runEndTimings","settleAll","settleDeadRun","settleUnsettledDelegation","streamFailure","Inject","Injectable","Logger","Optional","ChildWorkflowFailedError","NonRetryableStepError","StepFailedError","WORKFLOWS_MODULE_OPTIONS","WorkflowClient","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","flush","fail","durableEngineOf","durable","undefined","engine","AGENT_CHAT_QUEUE","Symbol","for","createNegotiatedUiCollector","prepareActionProposal","resolveActionProposalApproval","announcedToolCalls","createFrameBuffer","createNoopEmitUi","encodeStreamEvent","intersectAllowLists","invokeWithTransientRetry","isControlFlowSignal","isReplayIntegrityError","observeFirstText","observeTurnFrames","previewToolInputs","publishAgentToolRetry","registryInputPreviews","stampToolKinds","toolCallContext","traceLlmTurn","traceToolExecution","withAskTool","withChannelDelivery","withMemoryTool","withSkillTool","withToolTimeout","withTurnFrames","wrapToolPreflightDenied","wrapToolStepOutput","turnChannel","runLlmStep","factory","input","options","deps","forAgent","agentName","tools","withMemoryTool","withSkillTool","withAskTool","registry","definitionsFor","actor","rolesPolicy","intersectAllowLists","toolAllowList","personaAllowedTools","threadId","undefined","preflightContext","uiCapabilities","channel","turnChannel","pageContext","ask","enabled","skills","builtins","memory","provider","write","buffer","bufferOutput","createFrameBuffer","writer","firstText","opened","sink","open","sinkRunId","observeFirstText","childSink","childSinkWriter","announced","announcedToolCalls","previews","previewToolInputs","registryInputPreviews","frames","observeTurnFrames","turn","withTurnFrames","traceLlmTurn","runId","step","model","runTurn","system","messages","abortSignal","summary","stamped","stampToolKinds","announceRest","toolCalls","allowedTools","call","kind","context","requestId","actionApprovalMode","spec","name","actionApproval","resolveActionProposalApproval","store","tool","thread","approvalPolicy","policy","mode","prepared","prepareActionProposal","toolCallContext","id","emitUi","createNoopEmitUi","preflight","prepare","error","isControlFlowSignal","isReplayIntegrityError","status","Error","message","String","shown","previewed","length","firstTextAt","bufferedFrames","runToolStep","ctx","toolName","toolType","ui","createNegotiatedUiCollector","toolCallId","resolveUiCatalog","event","Promise","resolve","then","encodeStreamEvent","emit","localClassify","toolTransientRetry","classify","transientRetry","attempts","backoffMs","output","toolStartedAt","Date","now","traceToolExecution","invokeWithTransientRetry","restart","invocation","invoke","timeoutMs","withToolTimeout","onRetry","attempt","publishAgentToolRetry","wrapToolPreflightDenied","executionMs","withChannelDelivery","components","collectUi","wrapToolStepOutput","text","WorkflowSignal","AGENT_REPLY","WorkflowSignal","replyKey","runId","toolCallId","OutputRejectedError","QuotaExceededError","RunCancelledError","StructuredOutputError","isWorkflowInterrupt","CONTROL_FLOW_SIGNAL","Symbol","for","markControlFlow","error","isWorkflowInterrupt","SegmentBoundary","Error","name","isEngineControlFlow","serializeTurnError","message","String","props","key","value","Object","entries","json","JSON","stringify","undefined","parse","keys","length","stepFailureCause","cause","safeString","KNOWN_ERRORS","QuotaExceededError","RunCancelledError","OutputRejectedError","StructuredOutputError","rebuildTurnError","serialized","prototype","create","assign","defineProperty","writable","configurable","TurnJournal","counts","Map","outcomes","liveModelCalls","carried","unique","base","count","get","set","has","op","live","known","e","v","AGENT_RUN_WORKFLOW","AGENT_RUN_SEGMENT_WORKFLOW","DEFAULT_STEPS_PER_INSTANCE","SegmentFailed","Error","cause","message","name","isConfigurationError","error","isFatalDefinitionError","isReplayIntegrityError","AgentTurnExecutor","logger","Logger","stepsPerInstance","factory","store","options","queue","client","workflowsOptions","durable","configured","durableEngineOf","undefined","Number","isInteger","run","ctx","input","execute","runId","workflowId","segment","carried","journal","TurnJournal","day","utcDay","deps","forAgent","agentName","sinkRunId","childSink","originals","Map","pending","showPending","setStatus","size","pendingReplies","values","checkpoint","fn","op","envelope","ctxCall","step","value","v","set","e","serializeTurnError","get","rebuildTurnError","unique","awaitReply","call","timeoutMs","id","key","replyKey","toolCallId","toolName","kind","reply","waitForSignal","AGENT_REPLY","timeout","delete","chainBelow","delegationPath","subThread","thread","createThread","actor","transient","deliverTo","setActiveStream","threadId","hooks","queueMs","status","getStatus","now","clock","Date","waited","createdAt","isFinite","openSink","childSinkWriter","sink","open","writer","write","chunk","fail","failure","end","frame","advanceQueue","encodeStreamEvent","awaitApproval","_toolCtx","opts","approved","expired","awaitAnswers","request","source","parallel","settleAll","isControlFlowError","isEngineControlFlow","runAgent","task","subThreadId","child","userText","delegationDepth","parentRunId","executeChild","startAgent","childRunId","handle","startChild","parentClose","dispatchLlm","index","has","liveModelCalls","SegmentBoundary","attempt","runLlmStep","abortSignal","signal","catch","fatal","NonRetryableStepError","StepFailedError","stepFailureCause","dispatchTool","checkpointTool","outcome","runToolStep","toolType","result","runAgentLoop","releaseThreadRun","continueInSegment","outcomes","RunCancelledError","settleDetachedParent","durationMs","runDurationMs","timed","measured","runEndTimings","String","code","agentFailureCode","publishAgentRunFailed","context","agentRunContext","settleDeadRun","streamFailure","recordRunEnd","errorCode","errorMessage","Promise","resolve","failUnsettledToolCalls","RUN_ENDED_BEFORE_TOOL_CALL","queueFrame","settling","markControlFlow","next","ChildWorkflowFailedError","supported","plan","settled","isCancelled","reason","restore","pausedFrame","cancelRequested","delivery","settleUnsettledDelegation","agent","AgentRunFlow","turns","run","ctx","input","AgentRunSegmentFlow","segment","execute","randomUUID","AGENT_SINK","AGENT_STORE","encodeStreamEvent","publishAgentRunCancelled","releaseThreadRun","settleUnsettledDelegation","Inject","Injectable","Logger","Optional","WorkflowClient","WorkflowNotFoundError","AgentStreamError","LIVE_TTL_MS","ENDED_GRACE_MS","InProcessTokenStreamSink","runs","Map","waiting","buffer","runId","buf","get","undefined","chunks","ended","notify","Set","lastWriteAt","Date","now","expiry","set","expireAfter","waiters","delete","resolve","ms","clearTimeout","setTimeout","idle","drop","unref","wake","clear","finish","open","write","chunk","push","end","fail","error","failure","subscribe","options","signal","opened","Promise","r","add","untilAborted","size","index","length","AgentStreamError","current","woken","close","promise","aborted","onAbort","addEventListener","once","race","then","removeEventListener","ENDED","Set","recorded","input","deliveryOf","deliverTo","agentName","threadId","toolCallId","undefined","delivery","agent","runContextOf","actor","parentRunId","id","actorId","tenantRef","WorkflowsAgentRunner","logger","Logger","name","client","store","sink","queue","Error","InProcessTokenStreamSink","warn","start","options","stamped","day","utcDay","runId","randomUUID","AgentRunFlow","isRunActive","status","getStatus","has","signal","reply","key","replyKey","AGENT_REPLY","children","pendingReplies","found","visit","details","customStatus","push","child","parentClose","cancel","log","catch","sinkRunId","error","WorkflowNotFoundError","target","settleUnsettledDelegation","message","String","writer","open","threadTurn","supported","frame","handoff","outcome","next","nextRunId","write","encodeStreamEvent","releaseThreadRun","kind","end","durationMs","Math","max","updatedAt","createdAt","context","publishAgentRunCancelled","recordRunEnd","AgentWorkflowsModule","providers","AgentTurnExecutor","AgentRunFlow","AgentRunSegmentFlow","WorkflowsAgentRunner","provide","AGENT_WORKFLOWS_RUNNER","useExisting","exports"]}
|