@dudousxd/nestjs-agent 0.3.0 → 0.3.1

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/agent.module.ts","../src/agent-deps.factory.ts","../src/agent.service.ts","../src/agent-deps.ts","../src/controller/chat.controller.ts","../src/controller/quota.controller.ts","../src/controller/threads.controller.ts","../src/controller/tool-call.controller.ts","../src/discovery/agent-discovery.service.ts","../src/decorator/agent.decorator.ts","../src/decorator/system-prompt.decorator.ts","../src/discovery/ai-tool-discovery.service.ts","../src/decorator/ai-tool.decorator.ts","../src/functional-tool.ts","../src/in-process-sink.ts","../src/ledger-quota-store.ts","../src/runner/inline-agent-runner.ts","../src/resolver/header-actor-resolver.ts","../src/index.ts"],"sourcesContent":["import {\n AGENT_ACTOR_RESOLVER,\n AGENT_DEPS_FACTORY,\n AGENT_DURABLE_RUNNER,\n AGENT_MODEL,\n AGENT_OPTIONS,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_STORE,\n AGENT_REGISTRY,\n AGENT_ROLES_POLICY,\n AGENT_RUNNER,\n AGENT_SINK,\n AGENT_STORE,\n AGENT_TOOL_REGISTRY,\n AgentRegistry,\n type AgentRunner,\n type AgentStore,\n DefaultRolesPolicy,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { type DynamicModule, Global, Module, type Provider } from '@nestjs/common';\nimport { DiscoveryModule, RouterModule } from '@nestjs/core';\nimport { AgentDepsFactory } from './agent-deps.factory.js';\nimport type { AgentModuleAsyncOptions, AgentModuleOptions } from './agent.options.js';\nimport { AgentService } from './agent.service.js';\nimport { ChatController } from './controller/chat.controller.js';\nimport { QuotaController } from './controller/quota.controller.js';\nimport { ThreadsController } from './controller/threads.controller.js';\nimport { ToolCallController } from './controller/tool-call.controller.js';\nimport { AgentDiscoveryService } from './discovery/agent-discovery.service.js';\nimport { AiToolDiscoveryService } from './discovery/ai-tool-discovery.service.js';\nimport { InProcessTokenStreamSink } from './in-process-sink.js';\nimport { LedgerQuotaStore } from './ledger-quota-store.js';\nimport { InlineAgentRunner } from './runner/inline-agent-runner.js';\n\n/** Default route prefix the controllers mount under. */\nconst DEFAULT_PATH = 'agent';\n\n/**\n * The core wiring shared by `forRoot` / `forRootAsync`. `includeStore` controls whether we bind\n * `AGENT_STORE` locally: when the host omits `options.store` we leave it unbound so a globally-bound\n * store module (which binds `AGENT_STORE` app-wide) satisfies the dependency instead.\n */\nfunction sharedProviders(durable: boolean, includeStore: boolean): Provider[] {\n const providers: Provider[] = [\n { provide: AGENT_TOOL_REGISTRY, useFactory: () => new ToolRegistry() },\n // Starts empty; AgentDiscoveryService populates it from `@Agent`-decorated providers at boot.\n { provide: AGENT_REGISTRY, useFactory: () => new AgentRegistry() },\n // A shared, mutable list AgentDiscoveryService fills with `@SystemPromptContributor()` methods.\n { provide: AGENT_PROMPT_CONTRIBUTORS, useFactory: () => [] },\n {\n provide: AGENT_SINK,\n useFactory: (options: AgentModuleOptions) => options.sink ?? new InProcessTokenStreamSink(),\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_ROLES_POLICY,\n useFactory: (options: AgentModuleOptions) =>\n options.rolesPolicy ?? new DefaultRolesPolicy(options.defaultRoles),\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_ACTOR_RESOLVER,\n useFactory: (options: AgentModuleOptions) => options.actorResolver,\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_MODEL,\n useFactory: (o: AgentModuleOptions) => o.model,\n inject: [AGENT_OPTIONS],\n },\n {\n // An explicit `quota` wins; otherwise `quotaLimitTokens` binds the built-in ledger-backed\n // store; otherwise quotas are off (undefined). The ledger store reads the same usage rows\n // the loop already writes, so enforcement needs no extra shared state across replicas.\n provide: AGENT_QUOTA_STORE,\n useFactory: (o: AgentModuleOptions, store: AgentStore) =>\n o.quota ??\n (o.quotaLimitTokens !== undefined\n ? new LedgerQuotaStore(store, o.quotaLimitTokens)\n : undefined),\n inject: [AGENT_OPTIONS, AGENT_STORE],\n },\n AgentDepsFactory,\n { provide: AGENT_DEPS_FACTORY, useExisting: AgentDepsFactory },\n // Populates the registry + contributors (onModuleInit) BEFORE AiToolDiscoveryService synthesizes\n // handoff tools (onApplicationBootstrap) reads the registry.\n AgentDiscoveryService,\n AiToolDiscoveryService,\n InlineAgentRunner,\n AgentService,\n ];\n if (includeStore) {\n providers.push({\n provide: AGENT_STORE,\n useFactory: (o: AgentModuleOptions) => o.store,\n inject: [AGENT_OPTIONS],\n });\n }\n if (durable) {\n // Bind AGENT_RUNNER to the durable runner AgentDurableModule provides. Optional injection turns\n // a forgotten `AgentDurableModule` import into a clear error instead of an unresolved-dep crash.\n providers.push({\n provide: AGENT_RUNNER,\n useFactory: (durableRunner: AgentRunner | undefined) => {\n if (durableRunner === undefined) {\n throw new Error(\n 'AgentModule.forRoot({ durable: true }) requires importing AgentDurableModule from ' +\n \"'@dudousxd/nestjs-agent/durable' (alongside a configured DurableModule). It was not found.\",\n );\n }\n return durableRunner;\n },\n inject: [{ token: AGENT_DURABLE_RUNNER, optional: true }],\n });\n } else {\n providers.push({ provide: AGENT_RUNNER, useExisting: InlineAgentRunner });\n }\n return providers;\n}\n\n/**\n * The module's public tokens. `AGENT_STORE` is only re-exported when we bind it locally — a module\n * cannot export a token it neither provides nor imports (the store module binds it globally instead).\n */\nfunction exportsFor(includeStore: boolean): NonNullable<DynamicModule['exports']> {\n return [\n AGENT_OPTIONS,\n AGENT_TOOL_REGISTRY,\n AGENT_REGISTRY,\n AGENT_SINK,\n AGENT_ROLES_POLICY,\n AGENT_ACTOR_RESOLVER,\n AGENT_MODEL,\n ...(includeStore ? [AGENT_STORE] : []),\n AGENT_QUOTA_STORE,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_DEPS_FACTORY,\n AgentDepsFactory,\n AgentService,\n InlineAgentRunner,\n ];\n}\n\nconst CONTROLLERS = [ChatController, ThreadsController, ToolCallController, QuotaController];\n\n/** Mount the controllers under `path` (Nest applies the prefix to their relative routes). */\nfunction routerFor(path: string): DynamicModule {\n return RouterModule.register([{ path, module: AgentModule }]);\n}\n\n@Global()\n@Module({})\nexport class AgentModule {\n static forRoot(options: AgentModuleOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n // Bind AGENT_STORE locally only when the host passes a store; otherwise defer to a global one.\n const includeStore = options.store !== undefined;\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path)],\n controllers: CONTROLLERS,\n providers: [\n { provide: AGENT_OPTIONS, useValue: options },\n ...sharedProviders(options.durable ?? false, includeStore),\n ],\n exports: exportsFor(includeStore),\n };\n }\n\n static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path), ...(options.imports ?? [])],\n controllers: CONTROLLERS,\n providers: [\n {\n provide: AGENT_OPTIONS,\n useFactory: options.useFactory,\n inject: options.inject ?? [],\n },\n // The async factory resolves too late to inspect `store`, so we always bind AGENT_STORE here\n // (its factory reads the resolved options). Omit-and-import-a-store-module is a `forRoot` path.\n ...sharedProviders(options.durable ?? false, true),\n ],\n exports: exportsFor(true),\n };\n }\n}\n","import {\n AGENT_MODEL,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_STORE,\n AGENT_REGISTRY,\n AGENT_ROLES_POLICY,\n AGENT_SINK,\n AGENT_STORE,\n AGENT_TOOL_REGISTRY,\n type AgentDefinition,\n AgentRegistry,\n type AgentStore,\n type ModelProvider,\n type PromptContributor,\n type QuotaStore,\n type RolesPolicy,\n type TokenStreamSink,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_OPTIONS } from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable } from '@nestjs/common';\nimport type { AgentDeps } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\n\n/** The synthesized `agent`-kind tool name an orchestrator uses to hand off to `target`. */\nexport function delegateToolName(target: string): string {\n return `ask_${target.replace(/[^a-zA-Z0-9]+/g, '_')}`;\n}\n\n/** Builds the per-agent loop deps. The single-agent case is just the one registered `@Agent`. */\n@Injectable()\nexport class AgentDepsFactory {\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_MODEL) private readonly model: ModelProvider,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_SINK) private readonly sink: TokenStreamSink,\n @Inject(AGENT_ROLES_POLICY) private readonly rolesPolicy: RolesPolicy,\n @Inject(AGENT_TOOL_REGISTRY) private readonly registry: ToolRegistry,\n @Inject(AGENT_REGISTRY) private readonly agents: AgentRegistry,\n @Inject(AGENT_PROMPT_CONTRIBUTORS) private readonly promptContributors: PromptContributor[],\n @Inject(AGENT_QUOTA_STORE) private readonly quota: QuotaStore | undefined,\n ) {}\n\n /**\n * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the\n * sole registered `@Agent` when there is exactly one, else `'default'` (a bare assistant).\n */\n defaultAgentName(): string {\n if (this.options.defaultAgent !== undefined) {\n return this.options.defaultAgent;\n }\n const registered = this.agents.list();\n return registered.length === 1 ? (registered[0]?.name ?? 'default') : 'default';\n }\n\n private effectiveTools(definition: AgentDefinition | undefined): string[] | undefined {\n if (definition === undefined) {\n return undefined;\n }\n const delegated = (definition.delegatesTo ?? []).map(delegateToolName);\n if (definition.tools === undefined && delegated.length === 0) {\n return undefined; // no restriction\n }\n return [...(definition.tools ?? []), ...delegated];\n }\n\n forAgent(agentName?: string): AgentDeps {\n const name = agentName ?? this.defaultAgentName();\n const definition = this.agents.get(name);\n const toolAllowList = this.effectiveTools(definition);\n const followUpsCount = this.followUpsCount();\n const retrieval = this.options.retrieval;\n return {\n model: this.model,\n store: this.store,\n sink: this.sink,\n rolesPolicy: this.rolesPolicy,\n registry: this.registry,\n promptContributors: this.promptContributors,\n systemPrompt: definition?.systemPrompt ?? 'You are a helpful assistant.',\n maxSteps: definition?.maxSteps ?? 8,\n ...(definition?.modelId !== undefined ? { modelId: definition.modelId } : {}),\n ...(this.quota !== undefined ? { quota: this.quota } : {}),\n ...(toolAllowList !== undefined ? { toolAllowList } : {}),\n ...(this.options.toolTimeoutMs !== undefined\n ? { toolTimeoutMs: this.options.toolTimeoutMs }\n : {}),\n ...(followUpsCount !== undefined ? { followUpsCount } : {}),\n ...(retrieval?.mode === 'inject'\n ? {\n retriever: retrieval.retriever,\n ...(retrieval.topK !== undefined ? { retrievalTopK: retrieval.topK } : {}),\n }\n : {}),\n };\n }\n\n /** Normalize the `followUps` option (`true` → 3, `{ count }` → count) to a number, or undefined. */\n private followUpsCount(): number | undefined {\n const followUps = this.options.followUps;\n if (followUps === true) {\n return 3;\n }\n if (typeof followUps === 'object') {\n return followUps.count;\n }\n return undefined;\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_QUOTA_STORE,\n AGENT_RUNNER,\n AGENT_STORE,\n type Actor,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type PageContext,\n type QuotaStore,\n type QuotaView,\n type ThreadDetail,\n type ThreadSummary,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n ForbiddenException,\n Inject,\n Injectable,\n NotFoundException,\n} from '@nestjs/common';\nimport type { AgentDepsFactory } from './agent-deps.factory.js';\nimport { utcDay } from './agent-deps.js';\n\nexport interface ChatParams {\n actor: Actor;\n message: string;\n threadId?: string;\n agentName?: string;\n pageContext?: PageContext;\n /** Re-run the last exchange instead of adding a new message. Requires an existing `threadId`. */\n regenerate?: boolean;\n /**\n * When creating a thread (no `threadId`), start it transient — a scratch conversation hidden from\n * the thread list until the caller promotes it. Ignored when `threadId` is set.\n */\n transient?: boolean;\n}\n\n/** The orchestration facade the controllers call. */\n@Injectable()\nexport class AgentService {\n constructor(\n @Inject(AGENT_RUNNER) private readonly runner: AgentRunner,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_DEPS_FACTORY) private readonly deps: AgentDepsFactory,\n @Inject(AGENT_QUOTA_STORE) private readonly quota: QuotaStore | undefined,\n ) {}\n\n async chat(params: ChatParams): Promise<{ runId: string; threadId: string }> {\n const agentName = params.agentName ?? this.deps.defaultAgentName();\n let threadId = params.threadId;\n if (threadId === undefined) {\n if (params.regenerate === true) {\n throw new BadRequestException('regenerate requires an existing threadId');\n }\n const created = await this.store.createThread({\n actor: params.actor,\n ...(params.transient === true ? { transient: true } : {}),\n });\n threadId = created.id;\n } else if (params.regenerate === true) {\n // Regenerate re-runs a run on an existing thread — gate it by ownership like the other\n // thread-scoped actions so one actor can't rewind another's conversation.\n await this.assertOwnsThread(params.actor, threadId);\n }\n\n const input: AgentRunInput = {\n threadId,\n actor: params.actor,\n userText: params.message,\n day: utcDay(),\n agentName,\n ...(params.regenerate === true ? { regenerate: true } : {}),\n ...(params.pageContext !== undefined ? { pageContext: params.pageContext } : {}),\n };\n\n const { runId } = await this.runner.start(input);\n await this.store.setActiveStream(threadId, runId);\n return { runId, threadId };\n }\n\n subscribe(runId: string): AsyncIterable<Uint8Array> {\n return this.deps.forAgent().sink.subscribe(runId);\n }\n\n async approve(actor: Actor, toolCallId: string): Promise<void> {\n const runId = await this.runForOwnedToolCall(actor, toolCallId);\n return this.runner.signal(runId, toolCallId, { approved: true });\n }\n\n async reject(actor: Actor, toolCallId: string, reason?: string): Promise<void> {\n const runId = await this.runForOwnedToolCall(actor, toolCallId);\n return this.runner.signal(runId, toolCallId, {\n approved: false,\n ...(reason !== undefined ? { reason } : {}),\n });\n }\n\n async cancel(actor: Actor, runId: string): Promise<void> {\n await this.assertOwnsActiveStream(actor, runId);\n return this.runner.cancel(runId);\n }\n\n listThreads(actorRef: string): Promise<ThreadSummary[]> {\n return this.store.listThreads(actorRef);\n }\n\n async getThread(actor: Actor, threadId: string): Promise<ThreadDetail | null> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.getThread(threadId);\n }\n\n async deleteThread(actor: Actor, threadId: string): Promise<void> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.softDeleteThread(threadId);\n }\n\n async forkThread(actor: Actor, threadId: string, fromMessageId: string): Promise<ThreadSummary> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.forkThread(threadId, fromMessageId);\n }\n\n async renameThread(actor: Actor, threadId: string, title: string): Promise<void> {\n const trimmed = title.trim();\n if (trimmed.length === 0) {\n throw new BadRequestException('title must not be empty');\n }\n if (trimmed.length > 200) {\n throw new BadRequestException('title must be at most 200 characters');\n }\n await this.assertOwnsThread(actor, threadId);\n return this.store.setTitle(threadId, trimmed);\n }\n\n async promoteThread(actor: Actor, threadId: string): Promise<void> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.promoteThread(threadId);\n }\n\n /**\n * Drop a message and everything after it — the \"edit and resend\" / \"delete from here\" primitive.\n * The client then sends a fresh turn on the truncated thread. Ownership-gated like the other\n * thread-scoped mutations.\n */\n async truncateThreadFrom(actor: Actor, threadId: string, messageId: string): Promise<void> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.truncateFrom(threadId, messageId);\n }\n\n /**\n * The day's usage for the badge: tokens + summed USD cost from the store, and the configured\n * limit from the quota store (null → unlimited). `withinLimit` comes from the quota store so it\n * can never drift from what enforcement uses.\n */\n async quotaToday(actorRef: string): Promise<QuotaView> {\n const day = utcDay();\n const { usedTokens, costUsd } = await this.store.quotaToday(actorRef, day);\n if (this.quota === undefined) {\n return { usedTokens, costUsd, limitTokens: null, withinLimit: true };\n }\n const state = await this.quota.check(actorRef, day);\n return {\n usedTokens: state.usedTokens,\n costUsd,\n limitTokens: state.limitTokens,\n withinLimit: state.withinLimit,\n };\n }\n\n /**\n * Authorization seam for thread-scoped endpoints: the caller must own the thread. A missing\n * thread is a 404; someone else's thread is a 403 — one actor never touches another's thread.\n */\n private async assertOwnsThread(actor: Actor, threadId: string): Promise<void> {\n const owner = await this.store.ownerOfThread(threadId);\n if (owner === null) {\n throw new NotFoundException(`thread ${threadId} not found`);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('thread belongs to another actor');\n }\n }\n\n /**\n * Authorization + routing seam for HITL approve/reject: assert the caller owns the tool call's\n * thread, then resolve the run currently awaiting that call (its thread's active stream). That run\n * is the sub-agent's own child run when the pending call belongs to a delegated agent — the client\n * never knows or supplies a runId; it is derived here from the tool call alone.\n */\n private async runForOwnedToolCall(actor: Actor, toolCallId: string): Promise<string> {\n const owner = await this.store.ownerOfToolCall(toolCallId);\n if (owner === null) {\n throw new NotFoundException(`tool call ${toolCallId} not found`);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('tool call belongs to another actor');\n }\n const runId = await this.store.runForToolCall(toolCallId);\n if (runId === null) {\n throw new NotFoundException(`tool call ${toolCallId} has no active run to signal`);\n }\n return runId;\n }\n\n /** Authorization seam for `cancel`: the caller must own the thread currently streaming this run. */\n private async assertOwnsActiveStream(actor: Actor, runId: string): Promise<void> {\n const owner = await this.store.ownerOfActiveStream(runId);\n if (owner === null) {\n throw new NotFoundException(`no active run ${runId}`);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('run belongs to another actor');\n }\n }\n}\n","import type {\n AgentStore,\n ModelProvider,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n TokenStreamSink,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n model: ModelProvider;\n store: AgentStore;\n registry: ToolRegistry;\n rolesPolicy: RolesPolicy;\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 /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\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}\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.\n */\nexport function childSinkWriter(writer: SinkWriter): SinkWriter {\n return {\n write: (chunk) => writer.write(chunk),\n end: async () => {},\n fail: async () => {},\n };\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n AgentStreamError,\n type PageContext,\n} from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, Get, Inject, Param, Post, Req, Res } from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface ChatBody {\n message: string;\n threadId?: string;\n /** Name of the agent to run (orchestrator or a sub-agent). Defaults to the module's default. */\n agent?: string;\n pageContext?: PageContext;\n /** Re-run the last exchange on `threadId` instead of adding a new message. */\n regenerate?: boolean;\n /** Start a new thread transient (hidden from history until promoted). Ignored with `threadId`. */\n transient?: boolean;\n}\n\n@Controller()\nexport class ChatController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Post('chat')\n async chat(@Req() req: Request, @Res() res: Response, @Body() body: ChatBody): Promise<void> {\n const actor = await this.actorResolver.resolve(req);\n const { runId, threadId } = await this.agent.chat({\n actor,\n message: body.message,\n ...(body.threadId !== undefined ? { threadId: body.threadId } : {}),\n ...(body.agent !== undefined ? { agentName: body.agent } : {}),\n ...(body.pageContext !== undefined ? { pageContext: body.pageContext } : {}),\n ...(body.regenerate === true ? { regenerate: true } : {}),\n ...(body.transient === true ? { transient: true } : {}),\n });\n await this.pipe(res, runId, threadId);\n }\n\n @Get('chat/:runId/stream')\n async stream(@Param('runId') runId: string, @Res() res: Response): Promise<void> {\n await this.pipe(res, runId);\n }\n\n @Post('chat/:runId/cancel')\n async cancel(@Req() req: Request, @Param('runId') runId: string): Promise<{ aborted: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.cancel(actor, runId);\n return { aborted: true };\n }\n\n private async pipe(res: Response, runId: string, threadId?: string): Promise<void> {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Agent-Run-Id', runId);\n if (threadId !== undefined) {\n res.setHeader('X-Agent-Thread-Id', threadId);\n }\n res.write(`event: meta\\ndata: ${JSON.stringify({ runId, threadId })}\\n\\n`);\n const decoder = new TextDecoder();\n try {\n for await (const chunk of this.agent.subscribe(runId)) {\n res.write(`data: ${JSON.stringify({ delta: decoder.decode(chunk) })}\\n\\n`);\n }\n res.write('event: done\\ndata: {}\\n\\n');\n } catch (error) {\n // A run that failed terminates the sink with an AgentStreamError; surface it as a typed\n // error frame so the client can render a failure state instead of parsing it as a token.\n const payload =\n error instanceof AgentStreamError\n ? { code: error.code, message: error.message }\n : {\n code: 'run_failed',\n message: error instanceof Error ? error.message : 'stream error',\n };\n res.write(`event: error\\ndata: ${JSON.stringify(payload)}\\n\\n`);\n }\n res.end();\n }\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n@Controller('quota')\nexport class QuotaController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Get('today')\n async today(@Req() req: Request) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.quotaToday(actor.id);\n }\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, Delete, Get, Inject, Param, Patch, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface RenameThreadBody {\n title: string;\n}\n\n@Controller('threads')\nexport class ThreadsController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Get()\n async list(@Req() req: Request) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.listThreads(actor.id);\n }\n\n @Get(':id')\n async detail(@Req() req: Request, @Param('id') id: string) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.getThread(actor, id);\n }\n\n @Delete(':id')\n async remove(@Req() req: Request, @Param('id') id: string): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.deleteThread(actor, id);\n return { ok: true };\n }\n\n @Post(':id/fork-from/:messageId')\n async fork(@Req() req: Request, @Param('id') id: string, @Param('messageId') messageId: string) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.forkThread(actor, id, messageId);\n }\n\n @Patch(':id')\n async rename(\n @Req() req: Request,\n @Param('id') id: string,\n @Body() body: RenameThreadBody,\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.renameThread(actor, id, body.title);\n return { ok: true };\n }\n\n @Post(':id/promote')\n async promote(@Req() req: Request, @Param('id') id: string): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.promoteThread(actor, id);\n return { ok: true };\n }\n\n @Delete(':id/from/:messageId')\n async truncateFrom(\n @Req() req: Request,\n @Param('id') id: string,\n @Param('messageId') messageId: string,\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.truncateThreadFrom(actor, id, messageId);\n return { ok: true };\n }\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, Inject, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface ApproveBody {\n toolCallId: string;\n}\ninterface RejectBody extends ApproveBody {\n reason?: string;\n}\n\n@Controller('tool-call')\nexport class ToolCallController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Post('approve')\n async approve(@Req() req: Request, @Body() body: ApproveBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.approve(actor, body.toolCallId);\n return { ok: true };\n }\n\n @Post('reject')\n async reject(@Req() req: Request, @Body() body: RejectBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.reject(actor, body.toolCallId, body.reason);\n return { ok: true };\n }\n}\n","import {\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_REGISTRY,\n type AgentDefinition,\n AgentRegistry,\n type PromptBuilder,\n type PromptContext,\n type PromptContributor,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, type OnModuleInit } from '@nestjs/common';\nimport { DiscoveryService, MetadataScanner } from '@nestjs/core';\nimport { type AgentOptions, readAgentMetadata } from '../decorator/agent.decorator.js';\nimport {\n SYSTEM_PROMPT_CONTRIBUTOR_METADATA,\n SYSTEM_PROMPT_METADATA,\n} from '../decorator/system-prompt.decorator.js';\n\n/**\n * Populates the {@link AgentRegistry} from `@Agent`-decorated providers and collects every\n * `@SystemPromptContributor()` method into the app-wide contributor list — the discovery counterpart\n * to authoring agents as config objects. Runs on `onModuleInit`, so agents/contributors are in place\n * before `AiToolDiscoveryService` (which synthesizes handoff tools) runs its `onApplicationBootstrap`.\n */\n@Injectable()\nexport class AgentDiscoveryService implements OnModuleInit {\n private readonly logger = new Logger(AgentDiscoveryService.name);\n\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly scanner: MetadataScanner,\n @Inject(AGENT_REGISTRY) private readonly registry: AgentRegistry,\n @Inject(AGENT_PROMPT_CONTRIBUTORS) private readonly contributors: PromptContributor[],\n ) {}\n\n onModuleInit(): void {\n for (const wrapper of this.discovery.getProviders()) {\n const instance = wrapper.instance;\n if (instance === null || typeof instance !== 'object') {\n continue;\n }\n const meta = readAgentMetadata(instance.constructor);\n if (meta !== undefined) {\n this.registry.register(this.definitionFrom(instance, meta));\n }\n this.collectContributors(instance);\n }\n }\n\n /** Build the internal {@link AgentDefinition} from an `@Agent` instance and its options. */\n private definitionFrom(instance: object, meta: AgentOptions): AgentDefinition {\n const promptMethod = this.methodWith(instance, SYSTEM_PROMPT_METADATA);\n const systemPrompt: string | PromptBuilder =\n promptMethod !== undefined\n ? (ctx: PromptContext) => promptMethod(ctx) as string | Promise<string>\n : (meta.systemPrompt ?? 'You are a helpful assistant.');\n return {\n name: meta.name,\n systemPrompt,\n ...(meta.tools !== undefined ? { tools: meta.tools } : {}),\n ...(meta.model !== undefined ? { modelId: meta.model } : {}),\n ...(meta.maxSteps !== undefined ? { maxSteps: meta.maxSteps } : {}),\n ...(meta.handoff !== undefined ? { delegatesTo: this.handoffNames(meta) } : {}),\n };\n }\n\n /** Resolve each handoff `@Agent` class to its registered name (skipping non-agent classes). */\n private handoffNames(meta: AgentOptions): string[] {\n const names: string[] = [];\n for (const target of meta.handoff ?? []) {\n const targetMeta = readAgentMetadata(target);\n if (targetMeta === undefined) {\n this.logger.warn(\n `Agent \"${meta.name}\" hands off to ${target.name}, which is not an @Agent — skipped.`,\n );\n continue;\n }\n names.push(targetMeta.name);\n }\n return names;\n }\n\n /** Push every `@SystemPromptContributor()` method on `instance` (bound) into the contributor list. */\n private collectContributors(instance: object): void {\n const prototype = Object.getPrototypeOf(instance) as object;\n for (const name of this.scanner.getAllMethodNames(prototype)) {\n if (Reflect.getMetadata(SYSTEM_PROMPT_CONTRIBUTOR_METADATA, prototype, name) === true) {\n const method = this.boundMethod(instance, name);\n if (method !== undefined) {\n this.contributors.push(\n (ctx: PromptContext) => method(ctx) as ReturnType<PromptContributor>,\n );\n }\n }\n }\n }\n\n /** The single method on `instance` carrying `metadataKey`, bound to the instance, or undefined. */\n private methodWith(\n instance: object,\n metadataKey: symbol,\n ): ((ctx: PromptContext) => unknown) | undefined {\n const prototype = Object.getPrototypeOf(instance) as object;\n for (const name of this.scanner.getAllMethodNames(prototype)) {\n if (Reflect.getMetadata(metadataKey, prototype, name) === true) {\n return this.boundMethod(instance, name);\n }\n }\n return undefined;\n }\n\n /** Bind a named method to its instance, guarding that it is actually a function. */\n private boundMethod(\n instance: object,\n name: string,\n ): ((ctx: PromptContext) => unknown) | undefined {\n const candidate = (instance as Record<string, unknown>)[name];\n if (typeof candidate !== 'function') {\n return undefined;\n }\n return (ctx: PromptContext) =>\n (candidate as (ctx: PromptContext) => unknown).call(instance, ctx);\n }\n}\n","import 'reflect-metadata';\nimport type { Type } from '@nestjs/common';\n\n/**\n * Declares a class as an agent. The class is discovered at boot (via `DiscoveryService`) and\n * registered into the `AgentRegistry` — its name, base prompt, tool allow-list, and handoff targets\n * become an internal `AgentDefinition` the loop consumes. The class is an ordinary provider, so it\n * gets constructor DI (its retriever, schema service, policy) — the reason an agent is a class and\n * not a config object.\n *\n * The base prompt is either the `systemPrompt` string here or, for a dynamic prompt, a\n * `@SystemPrompt()` method on the class (which may inject services and read the turn's\n * `PromptContext`). Tools are the global `@AiTool` providers named in `tools` (omit → all tools the\n * actor's role allows); handoff targets are other `@Agent` classes.\n */\nexport interface AgentOptions {\n /** Unique agent name — how a turn selects it and how a message records its provenance. */\n name: string;\n /** Human-readable summary (shown to an orchestrator that may hand off to this agent). */\n description?: string;\n /** A flat base prompt. For a dynamic prompt, add a `@SystemPrompt()` method instead. */\n systemPrompt?: string;\n /** Accounting label for the model this agent uses (the model provider itself is shared). */\n model?: string;\n /** Max model→tool iterations for this agent's turn. Default 8. */\n maxSteps?: number;\n /** Allow-list of global tool names this agent may use. Omit → every tool its role allows. */\n tools?: string[];\n /** Other `@Agent` classes this agent may hand off to (auto-exposed as handoff tools). */\n handoff?: Type[];\n}\n\nexport const AGENT_METADATA = Symbol.for('@dudousxd/nestjs-agent:agent-metadata');\n\n/** Marks a provider class as an agent. See {@link AgentOptions}. */\nexport function Agent(options: AgentOptions): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(AGENT_METADATA, options, target);\n };\n}\n\n/** Reads {@link AgentOptions} off a class (its constructor), or `undefined` if not an `@Agent`. */\nexport function readAgentMetadata(target: Type | Function): AgentOptions | undefined {\n return Reflect.getMetadata(AGENT_METADATA, target) as AgentOptions | undefined;\n}\n","import 'reflect-metadata';\n\n/**\n * Marks the method on an `@Agent` class that builds the agent's base system prompt. The method\n * receives the turn's `PromptContext` and returns a string (optionally async); because it lives on a\n * provider, it can inject services (e.g. describe a schema, read the actor). Exactly one per agent —\n * it takes precedence over the `@Agent({ systemPrompt })` string.\n */\nexport const SYSTEM_PROMPT_METADATA = Symbol.for('@dudousxd/nestjs-agent:system-prompt');\n\n/**\n * Marks a method on any provider as a cross-agent system-prompt contributor: it returns an ordered\n * section appended to the composed prompt (after the selected agent's base), or `null` to contribute\n * nothing this turn. This is the seam an app uses to inject domain sections (base scope, a mentions\n * legend, schema hints) across every agent without forking the loop.\n */\nexport const SYSTEM_PROMPT_CONTRIBUTOR_METADATA = Symbol.for(\n '@dudousxd/nestjs-agent:system-prompt-contributor',\n);\n\n/** Marks an `@Agent` method as the agent's dynamic base prompt. See {@link SYSTEM_PROMPT_METADATA}. */\nexport function SystemPrompt(): MethodDecorator {\n return (target, key) => {\n Reflect.defineMetadata(SYSTEM_PROMPT_METADATA, true, target, key);\n };\n}\n\n/** Marks a provider method as a cross-agent prompt contributor. See {@link SYSTEM_PROMPT_CONTRIBUTOR_METADATA}. */\nexport function SystemPromptContributor(): MethodDecorator {\n return (target, key) => {\n Reflect.defineMetadata(SYSTEM_PROMPT_CONTRIBUTOR_METADATA, true, target, key);\n };\n}\n","import {\n AGENT_OPTIONS,\n AGENT_REGISTRY,\n AGENT_TOOL_REGISTRY,\n type AgentRegistry,\n type ToolHandler,\n type ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, type OnApplicationBootstrap } from '@nestjs/common';\nimport { DiscoveryService } from '@nestjs/core';\nimport { z } from 'zod';\nimport { delegateToolName } from '../agent-deps.factory.js';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { readAiToolMetadata } from '../decorator/ai-tool.decorator.js';\nimport { type FunctionalTool, isBrandedFunctionalTool } from '../functional-tool.js';\n\n/** Walks every provider at boot and registers `@AiTool` classes into the shared registry. */\n@Injectable()\nexport class AiToolDiscoveryService implements OnApplicationBootstrap {\n private readonly logger = new Logger(AiToolDiscoveryService.name);\n\n constructor(\n private readonly discovery: DiscoveryService,\n @Inject(AGENT_TOOL_REGISTRY) private readonly registry: ToolRegistry,\n @Inject(AGENT_REGISTRY) private readonly agents: AgentRegistry,\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n ) {}\n\n onApplicationBootstrap(): void {\n let count = 0;\n let functional = 0;\n for (const wrapper of this.discovery.getProviders()) {\n const instance = wrapper.instance;\n if (instance === null || instance === undefined || typeof instance !== 'object') {\n continue;\n }\n // Functional tools registered via `provideAgentTool` resolve to a branded { spec, handler }.\n if (isBrandedFunctionalTool(instance)) {\n if (this.registerFunctionalTool(instance)) {\n functional += 1;\n }\n continue;\n }\n const meta = readAiToolMetadata(instance);\n if (meta === undefined) {\n continue;\n }\n const handler = instance as Partial<ToolHandler>;\n if (typeof handler.execute !== 'function') {\n this.logger.warn(`@AiTool \"${meta.name}\" has no execute() method — skipped`);\n continue;\n }\n this.registry.register(\n {\n name: meta.name,\n kind: meta.kind,\n description: meta.description,\n inputSchema: meta.input,\n // Leave roles unset when the tool didn't declare any — the RolesPolicy owns the default\n // (its `defaultRoles`). Baking it in here too would leak it into custom policies.\n ...(meta.roles !== undefined ? { roles: meta.roles } : {}),\n ...(meta.ability !== undefined ? { ability: meta.ability } : {}),\n },\n { execute: (input, ctx) => (instance as ToolHandler).execute(input, ctx) },\n );\n count += 1;\n }\n\n // Static functional tools passed straight to `forRoot({ tools })`.\n for (const tool of this.options.tools ?? []) {\n if (this.registerFunctionalTool(tool)) {\n functional += 1;\n }\n }\n\n // Synthesize an `agent`-kind delegate tool for each agent->agent edge declared via `delegatesTo`.\n let delegates = 0;\n for (const definition of this.agents.list()) {\n for (const target of definition.delegatesTo ?? []) {\n const targetDefinition = this.agents.get(target);\n // A dangling handoff target (a `@Agent({ handoff })` class that isn't itself an `@Agent`)\n // would otherwise synthesize a delegate to a phantom agent that resolves to an UNRESTRICTED\n // default agent at runtime — a privilege-escalation footgun. Fail the boot instead.\n if (targetDefinition === undefined) {\n throw new Error(\n `Agent \"${definition.name}\" hands off to \"${target}\", which is not a registered @Agent. Declare it as an @Agent provider or fix the reference.`,\n );\n }\n const name = delegateToolName(target);\n if (this.registry.has(name)) {\n continue;\n }\n // Only a flat string prompt is worth surfacing in the tool description; a PromptBuilder is\n // per-request and would stringify to source, so skip it.\n const targetBlurb =\n typeof targetDefinition.systemPrompt === 'string'\n ? ` It is: ${targetDefinition.systemPrompt}`\n : '';\n this.registry.register(\n {\n name,\n kind: 'agent',\n targetAgent: target,\n description: `Delegate a task to the \"${target}\" agent and get its answer.${targetBlurb}`,\n inputSchema: z.object({ task: z.string() }),\n },\n // Loop-handled (kind 'agent'); the handler is never called.\n { execute: async () => ({}) },\n );\n delegates += 1;\n }\n }\n this.logger.log(\n `registered ${count} AI tool(s), ${functional} functional tool(s) and ${delegates} delegate tool(s)`,\n );\n }\n\n /**\n * Registers a functional tool's `{ spec, handler }`, skipping it if a tool of the same name is\n * already registered. Returns whether it was newly registered.\n */\n private registerFunctionalTool(tool: FunctionalTool): boolean {\n if (this.registry.has(tool.spec.name)) {\n this.logger.warn(\n `functional tool \"${tool.spec.name}\" duplicates a registered name — skipped`,\n );\n return false;\n }\n this.registry.register(tool.spec, tool.handler);\n return true;\n }\n}\n","import 'reflect-metadata';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport const AI_TOOL_METADATA = Symbol('nestjs-agent:ai-tool');\n\nexport interface AiToolOptions {\n name: string;\n /**\n * `read` auto-executes; `action` requires HITL approval. (Core's `ToolKind` also has `agent`\n * for delegation, but that kind is synthesized from `delegatesTo` — never authored here.)\n */\n kind: 'read' | 'action';\n description: string;\n /**\n * Input schema as a [Standard Schema](https://standardschema.dev) — Zod, Valibot, or ArkType.\n * Validated before the handler runs.\n */\n input: StandardSchemaV1;\n /** Roles allowed to invoke. Omit to inherit the module's default roles. */\n roles?: string[];\n /**\n * Authz ability checked by an ability-aware RolesPolicy (e.g. `AgentAuthzModule`'s\n * `AuthzRolesPolicy` → `gate.forUser(actor).allows(ability)`). Ignored by the default\n * role-based policy, which uses `roles`.\n */\n ability?: string;\n}\n\n/**\n * Marks a provider class as an AI tool. The class must implement `execute(input, ctx)`.\n * `AiToolDiscoveryService` registers every `@AiTool` provider into the `ToolRegistry` at boot.\n *\n * ```ts\n * @AiTool({ name: 'getWeather', kind: 'read', description: '...', input: z.object({ city: z.string() }) })\n * class GetWeatherTool implements ToolHandler<{ city: string }> {\n * async execute(input, ctx) { return { tempC: 21 }; }\n * }\n * ```\n */\nexport function AiTool(options: AiToolOptions): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(AI_TOOL_METADATA, options, target);\n };\n}\n\nexport function readAiToolMetadata(target: object): AiToolOptions | undefined {\n return Reflect.getMetadata(AI_TOOL_METADATA, target.constructor) as AiToolOptions | undefined;\n}\n","import type { ToolHandler, ToolSpec } from '@dudousxd/nestjs-agent-core';\nimport type { FactoryProvider, Provider } from '@nestjs/common';\n\n/**\n * Brand stamped onto a functional-tool provider instance so `AiToolDiscoveryService` picks it up\n * when it walks every provider at boot — the declarative alternative to a manual `registry.register`.\n */\nexport const AGENT_TOOL_BRAND = Symbol.for('@dudousxd/nestjs-agent:functional-tool');\n\n/** A tool expressed as data + handler (e.g. from `createExecuteSqlTool`), not an `@AiTool` class. */\nexport interface FunctionalTool {\n spec: ToolSpec;\n handler: ToolHandler;\n}\n\n/** A {@link FunctionalTool} carrying {@link AGENT_TOOL_BRAND} — what a provider resolves to. */\nexport interface BrandedFunctionalTool extends FunctionalTool {\n readonly [AGENT_TOOL_BRAND]: true;\n}\n\nfunction brand(tool: FunctionalTool): BrandedFunctionalTool {\n return { [AGENT_TOOL_BRAND]: true, spec: tool.spec, handler: tool.handler };\n}\n\n/** Narrows a provider instance to a branded functional tool for boot-time registration. */\nexport function isBrandedFunctionalTool(value: object): value is BrandedFunctionalTool {\n return AGENT_TOOL_BRAND in value && 'spec' in value && 'handler' in value;\n}\n\n/**\n * Registers a functional tool declaratively — drop the returned provider in a module's `providers`\n * and `AiToolDiscoveryService` auto-registers it at boot. Each call uses a fresh, unique provide\n * token so the same tool can be provided many times without collisions.\n *\n * Two forms: a static tool (`useValue`) or a factory with `inject` for DI-resolved dependencies\n * (`useFactory`). Either way the resolved instance is branded with {@link AGENT_TOOL_BRAND}.\n */\nexport function provideAgentTool(tool: FunctionalTool): Provider;\nexport function provideAgentTool(\n factory: (...deps: never[]) => FunctionalTool,\n inject?: FactoryProvider['inject'],\n): Provider;\nexport function provideAgentTool(\n factoryOrTool: FunctionalTool | ((...deps: never[]) => FunctionalTool),\n inject?: FactoryProvider['inject'],\n): Provider {\n const provide = Symbol('nestjs-agent:functional-tool-instance');\n if (typeof factoryOrTool === 'function') {\n return {\n provide,\n useFactory: (...deps: never[]) => brand(factoryOrTool(...deps)),\n inject: inject ?? [],\n };\n }\n return { provide, useValue: brand(factoryOrTool) };\n}\n","import {\n AgentStreamError,\n type SinkWriter,\n type StreamError,\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}\n\n/**\n * The default `TokenStreamSink`: buffers chunks per run in-process so a reconnecting subscriber\n * replays everything so far, then follows live.\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\n private buffer(runId: string): RunBuffer {\n let buf = this.runs.get(runId);\n if (buf === undefined) {\n buf = { chunks: [], ended: false, notify: new Set() };\n this.runs.set(runId, buf);\n }\n return 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 open(runId: string): SinkWriter {\n const buf = this.buffer(runId);\n return {\n write: (chunk: Uint8Array) => {\n buf.chunks.push(chunk);\n this.wake(buf);\n },\n end: () => {\n buf.ended = true;\n this.wake(buf);\n },\n fail: (error: StreamError) => {\n buf.failure = error;\n buf.ended = true;\n this.wake(buf);\n },\n };\n }\n\n async *subscribe(runId: string): AsyncIterable<Uint8Array> {\n const buf = this.buffer(runId);\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 await new Promise<void>((resolve) => buf.notify.add(resolve));\n }\n }\n\n close(runId: string): void {\n this.runs.delete(runId);\n }\n}\n","import type { AgentStore, QuotaState, QuotaStore } from '@dudousxd/nestjs-agent-core';\n\n/**\n * A production {@link QuotaStore} backed by the persisted usage ledger. `check` reads the actor's\n * tokens-so-far for the day straight from {@link AgentStore.quotaToday} and compares it to a fixed\n * daily limit; `bump` is a deliberate no-op because the loop's `recordUsage` already writes every\n * turn's tokens to that same ledger. One source of truth — so enforcement and what the dashboard\n * reports can never drift, and it works across replicas with no extra shared state.\n */\nexport class LedgerQuotaStore implements QuotaStore {\n constructor(\n private readonly store: AgentStore,\n private readonly limitTokens: number,\n ) {}\n\n async check(actorRef: string, day: string): Promise<QuotaState> {\n const { usedTokens } = await this.store.quotaToday(actorRef, day);\n return {\n usedTokens,\n limitTokens: this.limitTokens,\n withinLimit: usedTokens < this.limitTokens,\n };\n }\n\n async bump(): Promise<void> {\n // No-op: the ledger is the source of truth — recordUsage already persisted this turn's tokens.\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_STORE,\n type Actor,\n type AgentLoopHooks,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type Decision,\n QuotaExceededError,\n publishAgentRunFailed,\n runAgentLoop,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { type AgentDeps, childSinkWriter, utcDay } from '../agent-deps.js';\n\n/**\n * Runs the agent turn in-process. HITL approval resolves a pending promise keyed by\n * `runId:toolCallId`. Sub-agent delegation runs a nested loop that streams into the top-level run's\n * sink (so a human sees it) and shares the same approval mechanism — a sub-agent's action tools go\n * through the same human gate, keyed by the sub-agent's own runId. Single-replica only (the pending\n * map is in-process); durable is the scaled path.\n */\n@Injectable()\nexport class InlineAgentRunner implements AgentRunner {\n private readonly logger = new Logger(InlineAgentRunner.name);\n private readonly pending = new Map<string, (decision: Decision) => void>();\n\n constructor(\n @Inject(AGENT_DEPS_FACTORY) private readonly factory: AgentDepsFactory,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n ) {}\n\n async start(input: AgentRunInput): Promise<{ runId: string }> {\n const runId = crypto.randomUUID();\n const day = input.day ?? utcDay();\n const deps = this.factory.forAgent(input.agentName);\n const hooks = this.topLevelHooks(runId, deps, input.actor, day);\n\n void runAgentLoop({ ...deps, day }, input, hooks).catch(async (error) => {\n const message = error instanceof Error ? error.message : String(error);\n const code = error instanceof QuotaExceededError ? 'quota_exceeded' : 'run_failed';\n this.logger.error(`agent run ${runId} failed (${code}): ${message}`);\n publishAgentRunFailed({ runId, code, message });\n // Terminate the live stream with a typed failure so the transport emits an error frame\n // instead of leaking the message as assistant text.\n const writer = await deps.sink.open(runId);\n await writer.fail({ code, message });\n });\n\n return { runId };\n }\n\n async signal(runId: string, toolCallId: string, decision: Decision): Promise<void> {\n const key = `${runId}:${toolCallId}`;\n const resolve = this.pending.get(key);\n if (resolve !== undefined) {\n this.pending.delete(key);\n resolve(decision);\n }\n }\n\n async cancel(runId: string): Promise<void> {\n const deps = this.factory.forAgent();\n const writer = await deps.sink.open(runId);\n await writer.end();\n }\n\n private topLevelHooks(runId: string, deps: AgentDeps, actor: Actor, day: string): AgentLoopHooks {\n return {\n runId,\n openSink: () => deps.sink.open(runId),\n awaitApproval: (call) =>\n new Promise<Decision>((resolve) => {\n this.pending.set(`${runId}:${call.id}`, resolve);\n }),\n step: (_name, fn) => fn(),\n runAgent: (agentName, task) => this.runNested(agentName, task, actor, day, 1, runId),\n };\n }\n\n /**\n * Delegate to another agent as a nested in-process run. The sub-agent streams into `sinkRunId`\n * (the top-level run the human is watching) so its output and any pending action tool are visible,\n * and its own approvals resolve through the shared pending map keyed by its own runId.\n */\n private async runNested(\n agentName: string,\n task: string,\n actor: Actor,\n day: string,\n depth: number,\n sinkRunId: string,\n ): Promise<{ text: string }> {\n const subThread = await this.store.createThread({ actor, transient: true });\n const runId = crypto.randomUUID();\n // Mark the subthread as streaming THIS sub-run so a human approval routes back here\n // (runForToolCall → subthread.activeStreamId → this runId).\n await this.store.setActiveStream(subThread.id, runId);\n const deps = this.factory.forAgent(agentName);\n const hooks: AgentLoopHooks = {\n runId,\n // Forward into the top-level stream; the top-level run owns end/fail on that shared sink.\n openSink: async () => childSinkWriter(await deps.sink.open(sinkRunId)),\n awaitApproval: (call) =>\n new Promise<Decision>((resolve) => {\n this.pending.set(`${runId}:${call.id}`, resolve);\n }),\n step: (_name, fn) => fn(),\n runAgent: (childName, childTask) =>\n this.runNested(childName, childTask, actor, day, depth + 1, sinkRunId),\n };\n return runAgentLoop(\n { ...deps, day },\n {\n threadId: subThread.id,\n actor,\n userText: task,\n agentName,\n day,\n delegationDepth: depth,\n sinkRunId,\n },\n hooks,\n );\n }\n}\n","import type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\n\n/** Read a string header off an unknown transport request, narrowing without trusting its shape. */\nfunction readHeader(req: unknown, name: string): string | undefined {\n if (typeof req !== 'object' || req === null || !('headers' in req)) return undefined;\n const { headers } = req;\n if (typeof headers !== 'object' || headers === null || !(name in headers)) return undefined;\n const value: unknown = Reflect.get(headers, name);\n return typeof value === 'string' ? value : undefined;\n}\n\n/**\n * A development / gateway {@link ActorResolver} that trusts request headers:\n * `x-actor-id` (required), `x-actor-role` (comma-separated → `roles`), `x-tenant-ref`.\n *\n * **Security:** it throws when `x-actor-id` is absent — it never fabricates an identity\n * and never grants a default role (an actor with no `x-actor-role` gets `roles: []`, i.e.\n * no tools). Trusting client headers is only safe behind a gateway that strips and re-sets\n * them from an authenticated principal. Real deployments should provide their own resolver\n * that reads a verified session/JWT instead of installing this one.\n */\nexport class HeaderActorResolver implements ActorResolver {\n resolve(req: unknown): Actor {\n const id = readHeader(req, 'x-actor-id');\n if (id === undefined || id.length === 0) {\n throw new Error(\n 'HeaderActorResolver: missing x-actor-id header. No default actor is fabricated. ' +\n 'Send x-actor-id from a trusted gateway, or configure ' +\n 'AgentModule.forRoot({ actorResolver }) with a resolver that reads your ' +\n 'authenticated principal.',\n );\n }\n const roles = (readHeader(req, 'x-actor-role') ?? '')\n .split(',')\n .map((role) => role.trim())\n .filter((role) => role.length > 0);\n const tenantRef = readHeader(req, 'x-tenant-ref');\n return {\n id,\n roles,\n ...(tenantRef !== undefined ? { tenantRef } : {}),\n };\n }\n}\n","export { AgentModule } from './agent.module.js';\nexport type { AgentModuleOptions, AgentModuleAsyncOptions } from './agent.options.js';\nexport { AgentService, type ChatParams } from './agent.service.js';\nexport {\n AiTool,\n type AiToolOptions,\n AI_TOOL_METADATA,\n readAiToolMetadata,\n} from './decorator/ai-tool.decorator.js';\nexport {\n Agent,\n type AgentOptions,\n AGENT_METADATA,\n readAgentMetadata,\n} from './decorator/agent.decorator.js';\nexport {\n SystemPrompt,\n SystemPromptContributor,\n SYSTEM_PROMPT_METADATA,\n SYSTEM_PROMPT_CONTRIBUTOR_METADATA,\n} from './decorator/system-prompt.decorator.js';\nexport { AiToolDiscoveryService } from './discovery/ai-tool-discovery.service.js';\nexport { AgentDiscoveryService } from './discovery/agent-discovery.service.js';\nexport {\n provideAgentTool,\n AGENT_TOOL_BRAND,\n type FunctionalTool,\n} from './functional-tool.js';\nexport { InlineAgentRunner } from './runner/inline-agent-runner.js';\nexport { InProcessTokenStreamSink } from './in-process-sink.js';\nexport { LedgerQuotaStore } from './ledger-quota-store.js';\nexport { type AgentDeps, utcDay } from './agent-deps.js';\nexport { AgentDepsFactory, delegateToolName } from './agent-deps.factory.js';\nexport { HeaderActorResolver } from './resolver/header-actor-resolver.js';\n\n// Re-export the core surface so consumers import tools/types from one place.\nexport * from '@dudousxd/nestjs-agent-core';\n"],"mappings":"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","names":["AGENT_ACTOR_RESOLVER","AGENT_DEPS_FACTORY","AGENT_DURABLE_RUNNER","AGENT_MODEL","AGENT_OPTIONS","AGENT_PROMPT_CONTRIBUTORS","AGENT_QUOTA_STORE","AGENT_REGISTRY","AGENT_ROLES_POLICY","AGENT_RUNNER","AGENT_SINK","AGENT_STORE","AGENT_TOOL_REGISTRY","AgentRegistry","DefaultRolesPolicy","ToolRegistry","Global","Module","DiscoveryModule","RouterModule","AGENT_MODEL","AGENT_PROMPT_CONTRIBUTORS","AGENT_QUOTA_STORE","AGENT_REGISTRY","AGENT_ROLES_POLICY","AGENT_SINK","AGENT_STORE","AGENT_TOOL_REGISTRY","AgentRegistry","ToolRegistry","AGENT_OPTIONS","Inject","Injectable","delegateToolName","target","replace","AgentDepsFactory","options","model","store","sink","rolesPolicy","registry","agents","promptContributors","quota","defaultAgentName","defaultAgent","undefined","registered","list","length","name","effectiveTools","definition","delegated","delegatesTo","map","tools","forAgent","agentName","get","toolAllowList","followUpsCount","retrieval","systemPrompt","maxSteps","modelId","toolTimeoutMs","mode","retriever","topK","retrievalTopK","followUps","count","AGENT_DEPS_FACTORY","AGENT_QUOTA_STORE","AGENT_RUNNER","AGENT_STORE","BadRequestException","ForbiddenException","Inject","Injectable","NotFoundException","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","fail","AgentService","runner","store","deps","quota","chat","params","agentName","defaultAgentName","threadId","undefined","regenerate","BadRequestException","created","createThread","actor","transient","id","assertOwnsThread","input","userText","message","day","utcDay","pageContext","runId","start","setActiveStream","subscribe","forAgent","sink","approve","toolCallId","runForOwnedToolCall","signal","approved","reject","reason","cancel","assertOwnsActiveStream","listThreads","actorRef","getThread","deleteThread","softDeleteThread","forkThread","fromMessageId","renameThread","title","trimmed","trim","length","setTitle","promoteThread","truncateThreadFrom","messageId","truncateFrom","quotaToday","usedTokens","costUsd","limitTokens","withinLimit","state","check","owner","ownerOfThread","NotFoundException","ForbiddenException","ownerOfToolCall","runForToolCall","ownerOfActiveStream","AGENT_ACTOR_RESOLVER","AgentStreamError","Body","Controller","Get","Inject","Param","Post","Req","Res","ChatController","agent","actorResolver","chat","req","res","body","actor","resolve","runId","threadId","message","undefined","agentName","pageContext","regenerate","transient","pipe","stream","cancel","aborted","setHeader","write","JSON","stringify","decoder","TextDecoder","chunk","subscribe","delta","decode","error","payload","AgentStreamError","code","Error","end","AGENT_ACTOR_RESOLVER","Controller","Get","Inject","Req","QuotaController","agent","actorResolver","today","req","actor","resolve","quotaToday","id","AGENT_ACTOR_RESOLVER","Body","Controller","Delete","Get","Inject","Param","Patch","Post","Req","ThreadsController","agent","actorResolver","list","req","actor","resolve","listThreads","id","detail","getThread","remove","deleteThread","ok","fork","messageId","forkThread","rename","body","renameThread","title","promote","promoteThread","truncateFrom","truncateThreadFrom","AGENT_ACTOR_RESOLVER","Body","Controller","Inject","Post","Req","ToolCallController","agent","actorResolver","approve","req","body","actor","resolve","toolCallId","ok","reject","reason","AGENT_PROMPT_CONTRIBUTORS","AGENT_REGISTRY","AgentRegistry","Inject","Injectable","Logger","DiscoveryService","MetadataScanner","AGENT_METADATA","Symbol","for","Agent","options","target","Reflect","defineMetadata","readAgentMetadata","getMetadata","SYSTEM_PROMPT_METADATA","Symbol","for","SYSTEM_PROMPT_CONTRIBUTOR_METADATA","SystemPrompt","target","key","Reflect","defineMetadata","SystemPromptContributor","AgentDiscoveryService","logger","Logger","name","discovery","scanner","registry","contributors","onModuleInit","wrapper","getProviders","instance","meta","readAgentMetadata","undefined","register","definitionFrom","collectContributors","promptMethod","methodWith","SYSTEM_PROMPT_METADATA","systemPrompt","ctx","tools","model","modelId","maxSteps","handoff","delegatesTo","handoffNames","names","target","targetMeta","warn","push","prototype","Object","getPrototypeOf","getAllMethodNames","Reflect","getMetadata","SYSTEM_PROMPT_CONTRIBUTOR_METADATA","method","boundMethod","metadataKey","candidate","call","AGENT_OPTIONS","AGENT_REGISTRY","AGENT_TOOL_REGISTRY","Inject","Injectable","Logger","DiscoveryService","z","AI_TOOL_METADATA","Symbol","AiTool","options","target","Reflect","defineMetadata","readAiToolMetadata","getMetadata","AGENT_TOOL_BRAND","Symbol","for","brand","tool","spec","handler","isBrandedFunctionalTool","value","provideAgentTool","factoryOrTool","inject","provide","useFactory","deps","useValue","AiToolDiscoveryService","logger","Logger","name","discovery","registry","agents","options","onApplicationBootstrap","count","functional","wrapper","getProviders","instance","undefined","isBrandedFunctionalTool","registerFunctionalTool","meta","readAiToolMetadata","handler","execute","warn","register","kind","description","inputSchema","input","roles","ability","ctx","tool","tools","delegates","definition","list","target","delegatesTo","targetDefinition","get","Error","delegateToolName","has","targetBlurb","systemPrompt","targetAgent","z","object","task","string","log","spec","AgentStreamError","InProcessTokenStreamSink","runs","Map","buffer","runId","buf","get","undefined","chunks","ended","notify","Set","set","wake","resolve","clear","open","write","chunk","push","end","fail","error","failure","subscribe","index","length","AgentStreamError","Promise","add","close","delete","LedgerQuotaStore","store","limitTokens","check","actorRef","day","usedTokens","quotaToday","withinLimit","bump","AGENT_DEPS_FACTORY","AGENT_STORE","QuotaExceededError","publishAgentRunFailed","runAgentLoop","Inject","Injectable","Logger","InlineAgentRunner","logger","Logger","name","pending","Map","factory","store","start","input","runId","crypto","randomUUID","day","utcDay","deps","forAgent","agentName","hooks","topLevelHooks","actor","runAgentLoop","catch","error","message","Error","String","code","QuotaExceededError","publishAgentRunFailed","writer","sink","open","fail","signal","toolCallId","decision","key","resolve","get","undefined","delete","cancel","end","openSink","awaitApproval","call","Promise","set","id","step","_name","fn","runAgent","task","runNested","depth","sinkRunId","subThread","createThread","transient","setActiveStream","childSinkWriter","childName","childTask","threadId","userText","delegationDepth","DEFAULT_PATH","sharedProviders","durable","includeStore","providers","provide","AGENT_TOOL_REGISTRY","useFactory","ToolRegistry","AGENT_REGISTRY","AgentRegistry","AGENT_PROMPT_CONTRIBUTORS","AGENT_SINK","options","sink","InProcessTokenStreamSink","inject","AGENT_OPTIONS","AGENT_ROLES_POLICY","rolesPolicy","DefaultRolesPolicy","defaultRoles","AGENT_ACTOR_RESOLVER","actorResolver","AGENT_MODEL","o","model","AGENT_QUOTA_STORE","store","quota","quotaLimitTokens","undefined","LedgerQuotaStore","AGENT_STORE","AgentDepsFactory","AGENT_DEPS_FACTORY","useExisting","AgentDiscoveryService","AiToolDiscoveryService","InlineAgentRunner","AgentService","push","AGENT_RUNNER","durableRunner","Error","token","AGENT_DURABLE_RUNNER","optional","exportsFor","CONTROLLERS","ChatController","ThreadsController","ToolCallController","QuotaController","routerFor","path","RouterModule","register","module","AgentModule","forRoot","global","imports","DiscoveryModule","controllers","useValue","exports","forRootAsync","readHeader","req","name","undefined","headers","value","Reflect","get","HeaderActorResolver","resolve","id","length","Error","roles","split","map","role","trim","filter","tenantRef"]}
1
+ {"version":3,"sources":["../src/agent.module.ts","../src/agent-deps.factory.ts","../src/agent.service.ts","../src/agent-deps.ts","../src/controller/chat.controller.ts","../src/controller/quota.controller.ts","../src/controller/threads.controller.ts","../src/controller/tool-call.controller.ts","../src/discovery/agent-discovery.service.ts","../src/decorator/agent.decorator.ts","../src/decorator/system-prompt.decorator.ts","../src/discovery/ai-tool-discovery.service.ts","../src/decorator/ai-tool.decorator.ts","../src/functional-tool.ts","../src/in-process-sink.ts","../src/ledger-quota-store.ts","../src/runner/inline-agent-runner.ts","../src/resolver/header-actor-resolver.ts","../src/index.ts"],"sourcesContent":["import {\n AGENT_ACTOR_RESOLVER,\n AGENT_DEPS_FACTORY,\n AGENT_DURABLE_RUNNER,\n AGENT_MODEL,\n AGENT_OPTIONS,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_STORE,\n AGENT_REGISTRY,\n AGENT_ROLES_POLICY,\n AGENT_RUNNER,\n AGENT_SINK,\n AGENT_STORE,\n AGENT_TOOL_REGISTRY,\n AgentRegistry,\n type AgentRunner,\n type AgentStore,\n DefaultRolesPolicy,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { type DynamicModule, Global, Module, type Provider } from '@nestjs/common';\nimport { DiscoveryModule, RouterModule } from '@nestjs/core';\nimport { AgentDepsFactory } from './agent-deps.factory.js';\nimport type { AgentModuleAsyncOptions, AgentModuleOptions } from './agent.options.js';\nimport { AgentService } from './agent.service.js';\nimport { ChatController } from './controller/chat.controller.js';\nimport { QuotaController } from './controller/quota.controller.js';\nimport { ThreadsController } from './controller/threads.controller.js';\nimport { ToolCallController } from './controller/tool-call.controller.js';\nimport { AgentDiscoveryService } from './discovery/agent-discovery.service.js';\nimport { AiToolDiscoveryService } from './discovery/ai-tool-discovery.service.js';\nimport { InProcessTokenStreamSink } from './in-process-sink.js';\nimport { LedgerQuotaStore } from './ledger-quota-store.js';\nimport { InlineAgentRunner } from './runner/inline-agent-runner.js';\n\n/** Default route prefix the controllers mount under. */\nconst DEFAULT_PATH = 'agent';\n\n/**\n * The core wiring shared by `forRoot` / `forRootAsync`. `includeStore` controls whether we bind\n * `AGENT_STORE` locally: when the host omits `options.store` we leave it unbound so a globally-bound\n * store module (which binds `AGENT_STORE` app-wide) satisfies the dependency instead.\n */\nfunction sharedProviders(durable: boolean, includeStore: boolean): Provider[] {\n const providers: Provider[] = [\n { provide: AGENT_TOOL_REGISTRY, useFactory: () => new ToolRegistry() },\n // Starts empty; AgentDiscoveryService populates it from `@Agent`-decorated providers at boot.\n { provide: AGENT_REGISTRY, useFactory: () => new AgentRegistry() },\n // A shared, mutable list AgentDiscoveryService fills with `@SystemPromptContributor()` methods.\n { provide: AGENT_PROMPT_CONTRIBUTORS, useFactory: () => [] },\n {\n provide: AGENT_SINK,\n useFactory: (options: AgentModuleOptions) => options.sink ?? new InProcessTokenStreamSink(),\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_ROLES_POLICY,\n useFactory: (options: AgentModuleOptions) =>\n options.rolesPolicy ?? new DefaultRolesPolicy(options.defaultRoles),\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_ACTOR_RESOLVER,\n useFactory: (options: AgentModuleOptions) => options.actorResolver,\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_MODEL,\n useFactory: (o: AgentModuleOptions) => o.model,\n inject: [AGENT_OPTIONS],\n },\n {\n // An explicit `quota` wins; otherwise `quotaLimitTokens` binds the built-in ledger-backed\n // store; otherwise quotas are off (undefined). The ledger store reads the same usage rows\n // the loop already writes, so enforcement needs no extra shared state across replicas.\n provide: AGENT_QUOTA_STORE,\n useFactory: (o: AgentModuleOptions, store: AgentStore) =>\n o.quota ??\n (o.quotaLimitTokens !== undefined\n ? new LedgerQuotaStore(store, o.quotaLimitTokens)\n : undefined),\n inject: [AGENT_OPTIONS, AGENT_STORE],\n },\n AgentDepsFactory,\n { provide: AGENT_DEPS_FACTORY, useExisting: AgentDepsFactory },\n // Populates the registry + contributors (onModuleInit) BEFORE AiToolDiscoveryService synthesizes\n // handoff tools (onApplicationBootstrap) reads the registry.\n AgentDiscoveryService,\n AiToolDiscoveryService,\n InlineAgentRunner,\n AgentService,\n ];\n if (includeStore) {\n providers.push({\n provide: AGENT_STORE,\n useFactory: (o: AgentModuleOptions) => o.store,\n inject: [AGENT_OPTIONS],\n });\n }\n if (durable) {\n // Bind AGENT_RUNNER to the durable runner AgentDurableModule provides. Optional injection turns\n // a forgotten `AgentDurableModule` import into a clear error instead of an unresolved-dep crash.\n providers.push({\n provide: AGENT_RUNNER,\n useFactory: (durableRunner: AgentRunner | undefined) => {\n if (durableRunner === undefined) {\n throw new Error(\n 'AgentModule.forRoot({ durable: true }) requires importing AgentDurableModule from ' +\n \"'@dudousxd/nestjs-agent/durable' (alongside a configured DurableModule). It was not found.\",\n );\n }\n return durableRunner;\n },\n inject: [{ token: AGENT_DURABLE_RUNNER, optional: true }],\n });\n } else {\n providers.push({ provide: AGENT_RUNNER, useExisting: InlineAgentRunner });\n }\n return providers;\n}\n\n/**\n * The module's public tokens. `AGENT_STORE` is only re-exported when we bind it locally — a module\n * cannot export a token it neither provides nor imports (the store module binds it globally instead).\n */\nfunction exportsFor(includeStore: boolean): NonNullable<DynamicModule['exports']> {\n return [\n AGENT_OPTIONS,\n AGENT_TOOL_REGISTRY,\n AGENT_REGISTRY,\n AGENT_SINK,\n AGENT_ROLES_POLICY,\n AGENT_ACTOR_RESOLVER,\n AGENT_MODEL,\n ...(includeStore ? [AGENT_STORE] : []),\n AGENT_QUOTA_STORE,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_DEPS_FACTORY,\n AgentDepsFactory,\n AgentService,\n InlineAgentRunner,\n ];\n}\n\nconst CONTROLLERS = [ChatController, ThreadsController, ToolCallController, QuotaController];\n\n/** Mount the controllers under `path` (Nest applies the prefix to their relative routes). */\nfunction routerFor(path: string): DynamicModule {\n return RouterModule.register([{ path, module: AgentModule }]);\n}\n\n@Global()\n@Module({})\nexport class AgentModule {\n static forRoot(options: AgentModuleOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n // Bind AGENT_STORE locally only when the host passes a store; otherwise defer to a global one.\n const includeStore = options.store !== undefined;\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path)],\n controllers: CONTROLLERS,\n providers: [\n { provide: AGENT_OPTIONS, useValue: options },\n ...sharedProviders(options.durable ?? false, includeStore),\n ],\n exports: exportsFor(includeStore),\n };\n }\n\n static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path), ...(options.imports ?? [])],\n controllers: CONTROLLERS,\n providers: [\n {\n provide: AGENT_OPTIONS,\n useFactory: options.useFactory,\n inject: options.inject ?? [],\n },\n // The async factory resolves too late to inspect `store`, so we always bind AGENT_STORE here\n // (its factory reads the resolved options). Omit-and-import-a-store-module is a `forRoot` path.\n ...sharedProviders(options.durable ?? false, true),\n ],\n exports: exportsFor(true),\n };\n }\n}\n","import {\n AGENT_MODEL,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_STORE,\n AGENT_REGISTRY,\n AGENT_ROLES_POLICY,\n AGENT_SINK,\n AGENT_STORE,\n AGENT_TOOL_REGISTRY,\n type AgentDefinition,\n AgentRegistry,\n type AgentStore,\n type ModelProvider,\n type PromptContributor,\n type QuotaStore,\n type RolesPolicy,\n type TokenStreamSink,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_OPTIONS } from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable } from '@nestjs/common';\nimport type { AgentDeps } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\n\n/** The synthesized `agent`-kind tool name an orchestrator uses to hand off to `target`. */\nexport function delegateToolName(target: string): string {\n return `ask_${target.replace(/[^a-zA-Z0-9]+/g, '_')}`;\n}\n\n/** Builds the per-agent loop deps. The single-agent case is just the one registered `@Agent`. */\n@Injectable()\nexport class AgentDepsFactory {\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_MODEL) private readonly model: ModelProvider,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_SINK) private readonly sink: TokenStreamSink,\n @Inject(AGENT_ROLES_POLICY) private readonly rolesPolicy: RolesPolicy,\n @Inject(AGENT_TOOL_REGISTRY) private readonly registry: ToolRegistry,\n @Inject(AGENT_REGISTRY) private readonly agents: AgentRegistry,\n @Inject(AGENT_PROMPT_CONTRIBUTORS) private readonly promptContributors: PromptContributor[],\n @Inject(AGENT_QUOTA_STORE) private readonly quota: QuotaStore | undefined,\n ) {}\n\n /**\n * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the\n * sole registered `@Agent` when there is exactly one, else `'default'` (a bare assistant).\n */\n defaultAgentName(): string {\n if (this.options.defaultAgent !== undefined) {\n return this.options.defaultAgent;\n }\n const registered = this.agents.list();\n return registered.length === 1 ? (registered[0]?.name ?? 'default') : 'default';\n }\n\n private effectiveTools(definition: AgentDefinition | undefined): string[] | undefined {\n if (definition === undefined) {\n return undefined;\n }\n const delegated = (definition.delegatesTo ?? []).map(delegateToolName);\n if (definition.tools === undefined && delegated.length === 0) {\n return undefined; // no restriction\n }\n return [...(definition.tools ?? []), ...delegated];\n }\n\n forAgent(agentName?: string): AgentDeps {\n const name = agentName ?? this.defaultAgentName();\n const definition = this.agents.get(name);\n const toolAllowList = this.effectiveTools(definition);\n const followUpsCount = this.followUpsCount();\n const retrieval = this.options.retrieval;\n return {\n model: this.model,\n store: this.store,\n sink: this.sink,\n rolesPolicy: this.rolesPolicy,\n registry: this.registry,\n promptContributors: this.promptContributors,\n systemPrompt: definition?.systemPrompt ?? 'You are a helpful assistant.',\n maxSteps: definition?.maxSteps ?? 8,\n ...(definition?.modelId !== undefined ? { modelId: definition.modelId } : {}),\n ...(this.quota !== undefined ? { quota: this.quota } : {}),\n ...(toolAllowList !== undefined ? { toolAllowList } : {}),\n ...(this.options.toolTimeoutMs !== undefined\n ? { toolTimeoutMs: this.options.toolTimeoutMs }\n : {}),\n ...(followUpsCount !== undefined ? { followUpsCount } : {}),\n ...(retrieval?.mode === 'inject'\n ? {\n retriever: retrieval.retriever,\n ...(retrieval.topK !== undefined ? { retrievalTopK: retrieval.topK } : {}),\n }\n : {}),\n };\n }\n\n /** Normalize the `followUps` option (`true` → 3, `{ count }` → count) to a number, or undefined. */\n private followUpsCount(): number | undefined {\n const followUps = this.options.followUps;\n if (followUps === true) {\n return 3;\n }\n if (typeof followUps === 'object') {\n return followUps.count;\n }\n return undefined;\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_QUOTA_STORE,\n AGENT_RUNNER,\n AGENT_STORE,\n type Actor,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type PageContext,\n type QuotaStore,\n type QuotaView,\n type ThreadDetail,\n type ThreadSummary,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n ForbiddenException,\n Inject,\n Injectable,\n NotFoundException,\n} from '@nestjs/common';\nimport type { AgentDepsFactory } from './agent-deps.factory.js';\nimport { utcDay } from './agent-deps.js';\n\nexport interface ChatParams {\n actor: Actor;\n message: string;\n threadId?: string;\n agentName?: string;\n pageContext?: PageContext;\n /** Re-run the last exchange instead of adding a new message. Requires an existing `threadId`. */\n regenerate?: boolean;\n /**\n * When creating a thread (no `threadId`), start it transient — a scratch conversation hidden from\n * the thread list until the caller promotes it. Ignored when `threadId` is set.\n */\n transient?: boolean;\n}\n\n/** The orchestration facade the controllers call. */\n@Injectable()\nexport class AgentService {\n constructor(\n @Inject(AGENT_RUNNER) private readonly runner: AgentRunner,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_DEPS_FACTORY) private readonly deps: AgentDepsFactory,\n @Inject(AGENT_QUOTA_STORE) private readonly quota: QuotaStore | undefined,\n ) {}\n\n async chat(params: ChatParams): Promise<{ runId: string; threadId: string }> {\n const agentName = params.agentName ?? this.deps.defaultAgentName();\n let threadId = params.threadId;\n if (threadId === undefined) {\n if (params.regenerate === true) {\n throw new BadRequestException('regenerate requires an existing threadId');\n }\n const created = await this.store.createThread({\n actor: params.actor,\n ...(params.transient === true ? { transient: true } : {}),\n });\n threadId = created.id;\n } else if (params.regenerate === true) {\n // Regenerate re-runs a run on an existing thread — gate it by ownership like the other\n // thread-scoped actions so one actor can't rewind another's conversation.\n await this.assertOwnsThread(params.actor, threadId);\n }\n\n const input: AgentRunInput = {\n threadId,\n actor: params.actor,\n userText: params.message,\n day: utcDay(),\n agentName,\n ...(params.regenerate === true ? { regenerate: true } : {}),\n ...(params.pageContext !== undefined ? { pageContext: params.pageContext } : {}),\n };\n\n const { runId } = await this.runner.start(input);\n await this.store.setActiveStream(threadId, runId);\n return { runId, threadId };\n }\n\n subscribe(runId: string): AsyncIterable<Uint8Array> {\n return this.deps.forAgent().sink.subscribe(runId);\n }\n\n async approve(actor: Actor, toolCallId: string): Promise<void> {\n const runId = await this.runForOwnedToolCall(actor, toolCallId);\n return this.runner.signal(runId, toolCallId, { approved: true });\n }\n\n async reject(actor: Actor, toolCallId: string, reason?: string): Promise<void> {\n const runId = await this.runForOwnedToolCall(actor, toolCallId);\n return this.runner.signal(runId, toolCallId, {\n approved: false,\n ...(reason !== undefined ? { reason } : {}),\n });\n }\n\n async cancel(actor: Actor, runId: string): Promise<void> {\n await this.assertOwnsActiveStream(actor, runId);\n return this.runner.cancel(runId);\n }\n\n listThreads(actorRef: string): Promise<ThreadSummary[]> {\n return this.store.listThreads(actorRef);\n }\n\n async getThread(actor: Actor, threadId: string): Promise<ThreadDetail | null> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.getThread(threadId);\n }\n\n async deleteThread(actor: Actor, threadId: string): Promise<void> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.softDeleteThread(threadId);\n }\n\n async forkThread(actor: Actor, threadId: string, fromMessageId: string): Promise<ThreadSummary> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.forkThread(threadId, fromMessageId);\n }\n\n async renameThread(actor: Actor, threadId: string, title: string): Promise<void> {\n const trimmed = title.trim();\n if (trimmed.length === 0) {\n throw new BadRequestException('title must not be empty');\n }\n if (trimmed.length > 200) {\n throw new BadRequestException('title must be at most 200 characters');\n }\n await this.assertOwnsThread(actor, threadId);\n return this.store.setTitle(threadId, trimmed);\n }\n\n async promoteThread(actor: Actor, threadId: string): Promise<void> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.promoteThread(threadId);\n }\n\n /**\n * Drop a message and everything after it — the \"edit and resend\" / \"delete from here\" primitive.\n * The client then sends a fresh turn on the truncated thread. Ownership-gated like the other\n * thread-scoped mutations.\n */\n async truncateThreadFrom(actor: Actor, threadId: string, messageId: string): Promise<void> {\n await this.assertOwnsThread(actor, threadId);\n return this.store.truncateFrom(threadId, messageId);\n }\n\n /**\n * The day's usage for the badge: tokens + summed USD cost from the store, and the configured\n * limit from the quota store (null → unlimited). `withinLimit` comes from the quota store so it\n * can never drift from what enforcement uses.\n */\n async quotaToday(actorRef: string): Promise<QuotaView> {\n const day = utcDay();\n const { usedTokens, costUsd } = await this.store.quotaToday(actorRef, day);\n if (this.quota === undefined) {\n return { usedTokens, costUsd, limitTokens: null, withinLimit: true };\n }\n const state = await this.quota.check(actorRef, day);\n return {\n usedTokens: state.usedTokens,\n costUsd,\n limitTokens: state.limitTokens,\n withinLimit: state.withinLimit,\n };\n }\n\n /**\n * Authorization seam for thread-scoped endpoints: the caller must own the thread. A missing\n * thread is a 404; someone else's thread is a 403 — one actor never touches another's thread.\n */\n private async assertOwnsThread(actor: Actor, threadId: string): Promise<void> {\n const owner = await this.store.ownerOfThread(threadId);\n if (owner === null) {\n throw new NotFoundException(`thread ${threadId} not found`);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('thread belongs to another actor');\n }\n }\n\n /**\n * Authorization + routing seam for HITL approve/reject: assert the caller owns the tool call's\n * thread, then resolve the run currently awaiting that call (its thread's active stream). That run\n * is the sub-agent's own child run when the pending call belongs to a delegated agent — the client\n * never knows or supplies a runId; it is derived here from the tool call alone.\n */\n private async runForOwnedToolCall(actor: Actor, toolCallId: string): Promise<string> {\n const owner = await this.store.ownerOfToolCall(toolCallId);\n if (owner === null) {\n throw new NotFoundException(`tool call ${toolCallId} not found`);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('tool call belongs to another actor');\n }\n const runId = await this.store.runForToolCall(toolCallId);\n if (runId === null) {\n throw new NotFoundException(`tool call ${toolCallId} has no active run to signal`);\n }\n return runId;\n }\n\n /** Authorization seam for `cancel`: the caller must own the thread currently streaming this run. */\n private async assertOwnsActiveStream(actor: Actor, runId: string): Promise<void> {\n const owner = await this.store.ownerOfActiveStream(runId);\n if (owner === null) {\n throw new NotFoundException(`no active run ${runId}`);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('run belongs to another actor');\n }\n }\n}\n","import type {\n AgentStore,\n ModelProvider,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n TokenStreamSink,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n model: ModelProvider;\n store: AgentStore;\n registry: ToolRegistry;\n rolesPolicy: RolesPolicy;\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 /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\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}\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.\n */\nexport function childSinkWriter(writer: SinkWriter): SinkWriter {\n return {\n write: (chunk) => writer.write(chunk),\n end: async () => {},\n fail: async () => {},\n };\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n AgentStreamError,\n type PageContext,\n} from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, Get, Inject, Param, Post, Req, Res } from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface ChatBody {\n message: string;\n threadId?: string;\n /** Name of the agent to run (orchestrator or a sub-agent). Defaults to the module's default. */\n agent?: string;\n pageContext?: PageContext;\n /** Re-run the last exchange on `threadId` instead of adding a new message. */\n regenerate?: boolean;\n /** Start a new thread transient (hidden from history until promoted). Ignored with `threadId`. */\n transient?: boolean;\n}\n\n@Controller()\nexport class ChatController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Post('chat')\n async chat(@Req() req: Request, @Res() res: Response, @Body() body: ChatBody): Promise<void> {\n const actor = await this.actorResolver.resolve(req);\n const { runId, threadId } = await this.agent.chat({\n actor,\n message: body.message,\n ...(body.threadId !== undefined ? { threadId: body.threadId } : {}),\n ...(body.agent !== undefined ? { agentName: body.agent } : {}),\n ...(body.pageContext !== undefined ? { pageContext: body.pageContext } : {}),\n ...(body.regenerate === true ? { regenerate: true } : {}),\n ...(body.transient === true ? { transient: true } : {}),\n });\n await this.pipe(res, runId, threadId);\n }\n\n @Get('chat/:runId/stream')\n async stream(@Param('runId') runId: string, @Res() res: Response): Promise<void> {\n await this.pipe(res, runId);\n }\n\n @Post('chat/:runId/cancel')\n async cancel(@Req() req: Request, @Param('runId') runId: string): Promise<{ aborted: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.cancel(actor, runId);\n return { aborted: true };\n }\n\n private async pipe(res: Response, runId: string, threadId?: string): Promise<void> {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Agent-Run-Id', runId);\n if (threadId !== undefined) {\n res.setHeader('X-Agent-Thread-Id', threadId);\n }\n res.write(`event: meta\\ndata: ${JSON.stringify({ runId, threadId })}\\n\\n`);\n const decoder = new TextDecoder();\n try {\n for await (const chunk of this.agent.subscribe(runId)) {\n res.write(`data: ${JSON.stringify({ delta: decoder.decode(chunk) })}\\n\\n`);\n }\n res.write('event: done\\ndata: {}\\n\\n');\n } catch (error) {\n // A run that failed terminates the sink with an AgentStreamError; surface it as a typed\n // error frame so the client can render a failure state instead of parsing it as a token.\n const payload =\n error instanceof AgentStreamError\n ? { code: error.code, message: error.message }\n : {\n code: 'run_failed',\n message: error instanceof Error ? error.message : 'stream error',\n };\n res.write(`event: error\\ndata: ${JSON.stringify(payload)}\\n\\n`);\n }\n res.end();\n }\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n@Controller('quota')\nexport class QuotaController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Get('today')\n async today(@Req() req: Request) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.quotaToday(actor.id);\n }\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, Delete, Get, Inject, Param, Patch, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface RenameThreadBody {\n title: string;\n}\n\n@Controller('threads')\nexport class ThreadsController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Get()\n async list(@Req() req: Request) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.listThreads(actor.id);\n }\n\n @Get(':id')\n async detail(@Req() req: Request, @Param('id') id: string) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.getThread(actor, id);\n }\n\n @Delete(':id')\n async remove(@Req() req: Request, @Param('id') id: string): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.deleteThread(actor, id);\n return { ok: true };\n }\n\n @Post(':id/fork-from/:messageId')\n async fork(@Req() req: Request, @Param('id') id: string, @Param('messageId') messageId: string) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.forkThread(actor, id, messageId);\n }\n\n @Patch(':id')\n async rename(\n @Req() req: Request,\n @Param('id') id: string,\n @Body() body: RenameThreadBody,\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.renameThread(actor, id, body.title);\n return { ok: true };\n }\n\n @Post(':id/promote')\n async promote(@Req() req: Request, @Param('id') id: string): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.promoteThread(actor, id);\n return { ok: true };\n }\n\n @Delete(':id/from/:messageId')\n async truncateFrom(\n @Req() req: Request,\n @Param('id') id: string,\n @Param('messageId') messageId: string,\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.truncateThreadFrom(actor, id, messageId);\n return { ok: true };\n }\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, Inject, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface ApproveBody {\n toolCallId: string;\n}\ninterface RejectBody extends ApproveBody {\n reason?: string;\n}\n\n@Controller('tool-call')\nexport class ToolCallController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Post('approve')\n async approve(@Req() req: Request, @Body() body: ApproveBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.approve(actor, body.toolCallId);\n return { ok: true };\n }\n\n @Post('reject')\n async reject(@Req() req: Request, @Body() body: RejectBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.reject(actor, body.toolCallId, body.reason);\n return { ok: true };\n }\n}\n","import {\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_REGISTRY,\n type AgentDefinition,\n AgentRegistry,\n type PromptBuilder,\n type PromptContext,\n type PromptContributor,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, type OnModuleInit } from '@nestjs/common';\nimport { DiscoveryService, MetadataScanner } from '@nestjs/core';\nimport { type AgentOptions, readAgentMetadata } from '../decorator/agent.decorator.js';\nimport {\n SYSTEM_PROMPT_CONTRIBUTOR_METADATA,\n SYSTEM_PROMPT_METADATA,\n} from '../decorator/system-prompt.decorator.js';\n\n/**\n * Populates the {@link AgentRegistry} from `@Agent`-decorated providers and collects every\n * `@SystemPromptContributor()` method into the app-wide contributor list — the discovery counterpart\n * to authoring agents as config objects. Runs on `onModuleInit`, so agents/contributors are in place\n * before `AiToolDiscoveryService` (which synthesizes handoff tools) runs its `onApplicationBootstrap`.\n */\n@Injectable()\nexport class AgentDiscoveryService implements OnModuleInit {\n private readonly logger = new Logger(AgentDiscoveryService.name);\n\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly scanner: MetadataScanner,\n @Inject(AGENT_REGISTRY) private readonly registry: AgentRegistry,\n @Inject(AGENT_PROMPT_CONTRIBUTORS) private readonly contributors: PromptContributor[],\n ) {}\n\n onModuleInit(): void {\n for (const wrapper of this.discovery.getProviders()) {\n const instance = wrapper.instance;\n if (instance === null || typeof instance !== 'object') {\n continue;\n }\n const meta = readAgentMetadata(instance.constructor);\n if (meta !== undefined) {\n this.registry.register(this.definitionFrom(instance, meta));\n }\n this.collectContributors(instance);\n }\n }\n\n /** Build the internal {@link AgentDefinition} from an `@Agent` instance and its options. */\n private definitionFrom(instance: object, meta: AgentOptions): AgentDefinition {\n const promptMethod = this.methodWith(instance, SYSTEM_PROMPT_METADATA);\n const systemPrompt: string | PromptBuilder =\n promptMethod !== undefined\n ? (ctx: PromptContext) => promptMethod(ctx) as string | Promise<string>\n : (meta.systemPrompt ?? 'You are a helpful assistant.');\n return {\n name: meta.name,\n systemPrompt,\n ...(meta.tools !== undefined ? { tools: meta.tools } : {}),\n ...(meta.model !== undefined ? { modelId: meta.model } : {}),\n ...(meta.maxSteps !== undefined ? { maxSteps: meta.maxSteps } : {}),\n ...(meta.handoff !== undefined ? { delegatesTo: this.handoffNames(meta) } : {}),\n };\n }\n\n /** Resolve each handoff `@Agent` class to its registered name (skipping non-agent classes). */\n private handoffNames(meta: AgentOptions): string[] {\n const names: string[] = [];\n for (const target of meta.handoff ?? []) {\n const targetMeta = readAgentMetadata(target);\n if (targetMeta === undefined) {\n this.logger.warn(\n `Agent \"${meta.name}\" hands off to ${target.name}, which is not an @Agent — skipped.`,\n );\n continue;\n }\n names.push(targetMeta.name);\n }\n return names;\n }\n\n /** Push every `@SystemPromptContributor()` method on `instance` (bound) into the contributor list. */\n private collectContributors(instance: object): void {\n const prototype = Object.getPrototypeOf(instance) as object;\n for (const name of this.scanner.getAllMethodNames(prototype)) {\n if (Reflect.getMetadata(SYSTEM_PROMPT_CONTRIBUTOR_METADATA, prototype, name) === true) {\n const method = this.boundMethod(instance, name);\n if (method !== undefined) {\n this.contributors.push(\n (ctx: PromptContext) => method(ctx) as ReturnType<PromptContributor>,\n );\n }\n }\n }\n }\n\n /** The single method on `instance` carrying `metadataKey`, bound to the instance, or undefined. */\n private methodWith(\n instance: object,\n metadataKey: symbol,\n ): ((ctx: PromptContext) => unknown) | undefined {\n const prototype = Object.getPrototypeOf(instance) as object;\n for (const name of this.scanner.getAllMethodNames(prototype)) {\n if (Reflect.getMetadata(metadataKey, prototype, name) === true) {\n return this.boundMethod(instance, name);\n }\n }\n return undefined;\n }\n\n /** Bind a named method to its instance, guarding that it is actually a function. */\n private boundMethod(\n instance: object,\n name: string,\n ): ((ctx: PromptContext) => unknown) | undefined {\n const candidate = (instance as Record<string, unknown>)[name];\n if (typeof candidate !== 'function') {\n return undefined;\n }\n return (ctx: PromptContext) =>\n (candidate as (ctx: PromptContext) => unknown).call(instance, ctx);\n }\n}\n","import 'reflect-metadata';\nimport type { Type } from '@nestjs/common';\n\n/**\n * Declares a class as an agent. The class is discovered at boot (via `DiscoveryService`) and\n * registered into the `AgentRegistry` — its name, base prompt, tool allow-list, and handoff targets\n * become an internal `AgentDefinition` the loop consumes. The class is an ordinary provider, so it\n * gets constructor DI (its retriever, schema service, policy) — the reason an agent is a class and\n * not a config object.\n *\n * The base prompt is either the `systemPrompt` string here or, for a dynamic prompt, a\n * `@SystemPrompt()` method on the class (which may inject services and read the turn's\n * `PromptContext`). Tools are the global `@AiTool` providers named in `tools` (omit → all tools the\n * actor's role allows); handoff targets are other `@Agent` classes.\n */\nexport interface AgentOptions {\n /** Unique agent name — how a turn selects it and how a message records its provenance. */\n name: string;\n /** Human-readable summary (shown to an orchestrator that may hand off to this agent). */\n description?: string;\n /** A flat base prompt. For a dynamic prompt, add a `@SystemPrompt()` method instead. */\n systemPrompt?: string;\n /** Accounting label for the model this agent uses (the model provider itself is shared). */\n model?: string;\n /** Max model→tool iterations for this agent's turn. Default 8. */\n maxSteps?: number;\n /** Allow-list of global tool names this agent may use. Omit → every tool its role allows. */\n tools?: string[];\n /** Other `@Agent` classes this agent may hand off to (auto-exposed as handoff tools). */\n handoff?: Type[];\n}\n\nexport const AGENT_METADATA = Symbol.for('@dudousxd/nestjs-agent:agent-metadata');\n\n/** Marks a provider class as an agent. See {@link AgentOptions}. */\nexport function Agent(options: AgentOptions): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(AGENT_METADATA, options, target);\n };\n}\n\n/**\n * Reads {@link AgentOptions} off a class (its constructor), or `undefined` if not an `@Agent`. The\n * reflection target is a class or Nest's provider `metatype`, whose type is precisely `Type |\n * Function`; narrowing it away from `Function` would reject valid callers.\n */\n// biome-ignore lint/complexity/noBannedTypes: the reflection target's type is precisely `Type | Function`.\nexport function readAgentMetadata(target: Type | Function): AgentOptions | undefined {\n return Reflect.getMetadata(AGENT_METADATA, target) as AgentOptions | undefined;\n}\n","import 'reflect-metadata';\n\n/**\n * Marks the method on an `@Agent` class that builds the agent's base system prompt. The method\n * receives the turn's `PromptContext` and returns a string (optionally async); because it lives on a\n * provider, it can inject services (e.g. describe a schema, read the actor). Exactly one per agent —\n * it takes precedence over the `@Agent({ systemPrompt })` string.\n */\nexport const SYSTEM_PROMPT_METADATA = Symbol.for('@dudousxd/nestjs-agent:system-prompt');\n\n/**\n * Marks a method on any provider as a cross-agent system-prompt contributor: it returns an ordered\n * section appended to the composed prompt (after the selected agent's base), or `null` to contribute\n * nothing this turn. This is the seam an app uses to inject domain sections (base scope, a mentions\n * legend, schema hints) across every agent without forking the loop.\n */\nexport const SYSTEM_PROMPT_CONTRIBUTOR_METADATA = Symbol.for(\n '@dudousxd/nestjs-agent:system-prompt-contributor',\n);\n\n/** Marks an `@Agent` method as the agent's dynamic base prompt. See {@link SYSTEM_PROMPT_METADATA}. */\nexport function SystemPrompt(): MethodDecorator {\n return (target, key) => {\n Reflect.defineMetadata(SYSTEM_PROMPT_METADATA, true, target, key);\n };\n}\n\n/** Marks a provider method as a cross-agent prompt contributor. See {@link SYSTEM_PROMPT_CONTRIBUTOR_METADATA}. */\nexport function SystemPromptContributor(): MethodDecorator {\n return (target, key) => {\n Reflect.defineMetadata(SYSTEM_PROMPT_CONTRIBUTOR_METADATA, true, target, key);\n };\n}\n","import {\n AGENT_OPTIONS,\n AGENT_REGISTRY,\n AGENT_TOOL_REGISTRY,\n type AgentRegistry,\n type ToolHandler,\n type ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, type OnApplicationBootstrap } from '@nestjs/common';\nimport { DiscoveryService } from '@nestjs/core';\nimport { z } from 'zod';\nimport { delegateToolName } from '../agent-deps.factory.js';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { readAiToolMetadata } from '../decorator/ai-tool.decorator.js';\nimport { type FunctionalTool, isBrandedFunctionalTool } from '../functional-tool.js';\n\n/** Walks every provider at boot and registers `@AiTool` classes into the shared registry. */\n@Injectable()\nexport class AiToolDiscoveryService implements OnApplicationBootstrap {\n private readonly logger = new Logger(AiToolDiscoveryService.name);\n\n constructor(\n private readonly discovery: DiscoveryService,\n @Inject(AGENT_TOOL_REGISTRY) private readonly registry: ToolRegistry,\n @Inject(AGENT_REGISTRY) private readonly agents: AgentRegistry,\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n ) {}\n\n onApplicationBootstrap(): void {\n let count = 0;\n let functional = 0;\n for (const wrapper of this.discovery.getProviders()) {\n const instance = wrapper.instance;\n if (instance === null || instance === undefined || typeof instance !== 'object') {\n continue;\n }\n // Functional tools registered via `provideAgentTool` resolve to a branded { spec, handler }.\n if (isBrandedFunctionalTool(instance)) {\n if (this.registerFunctionalTool(instance)) {\n functional += 1;\n }\n continue;\n }\n const meta = readAiToolMetadata(instance);\n if (meta === undefined) {\n continue;\n }\n const handler = instance as Partial<ToolHandler>;\n if (typeof handler.execute !== 'function') {\n this.logger.warn(`@AiTool \"${meta.name}\" has no execute() method — skipped`);\n continue;\n }\n this.registry.register(\n {\n name: meta.name,\n kind: meta.kind,\n description: meta.description,\n inputSchema: meta.input,\n // Leave roles unset when the tool didn't declare any — the RolesPolicy owns the default\n // (its `defaultRoles`). Baking it in here too would leak it into custom policies.\n ...(meta.roles !== undefined ? { roles: meta.roles } : {}),\n ...(meta.ability !== undefined ? { ability: meta.ability } : {}),\n },\n { execute: (input, ctx) => (instance as ToolHandler).execute(input, ctx) },\n );\n count += 1;\n }\n\n // Static functional tools passed straight to `forRoot({ tools })`.\n for (const tool of this.options.tools ?? []) {\n if (this.registerFunctionalTool(tool)) {\n functional += 1;\n }\n }\n\n // Synthesize an `agent`-kind delegate tool for each agent->agent edge declared via `delegatesTo`.\n let delegates = 0;\n for (const definition of this.agents.list()) {\n for (const target of definition.delegatesTo ?? []) {\n const targetDefinition = this.agents.get(target);\n // A dangling handoff target (a `@Agent({ handoff })` class that isn't itself an `@Agent`)\n // would otherwise synthesize a delegate to a phantom agent that resolves to an UNRESTRICTED\n // default agent at runtime — a privilege-escalation footgun. Fail the boot instead.\n if (targetDefinition === undefined) {\n throw new Error(\n `Agent \"${definition.name}\" hands off to \"${target}\", which is not a registered @Agent. Declare it as an @Agent provider or fix the reference.`,\n );\n }\n const name = delegateToolName(target);\n if (this.registry.has(name)) {\n continue;\n }\n // Only a flat string prompt is worth surfacing in the tool description; a PromptBuilder is\n // per-request and would stringify to source, so skip it.\n const targetBlurb =\n typeof targetDefinition.systemPrompt === 'string'\n ? ` It is: ${targetDefinition.systemPrompt}`\n : '';\n this.registry.register(\n {\n name,\n kind: 'agent',\n targetAgent: target,\n description: `Delegate a task to the \"${target}\" agent and get its answer.${targetBlurb}`,\n inputSchema: z.object({ task: z.string() }),\n },\n // Loop-handled (kind 'agent'); the handler is never called.\n { execute: async () => ({}) },\n );\n delegates += 1;\n }\n }\n this.logger.log(\n `registered ${count} AI tool(s), ${functional} functional tool(s) and ${delegates} delegate tool(s)`,\n );\n }\n\n /**\n * Registers a functional tool's `{ spec, handler }`, skipping it if a tool of the same name is\n * already registered. Returns whether it was newly registered.\n */\n private registerFunctionalTool(tool: FunctionalTool): boolean {\n if (this.registry.has(tool.spec.name)) {\n this.logger.warn(\n `functional tool \"${tool.spec.name}\" duplicates a registered name — skipped`,\n );\n return false;\n }\n this.registry.register(tool.spec, tool.handler);\n return true;\n }\n}\n","import 'reflect-metadata';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport const AI_TOOL_METADATA = Symbol('nestjs-agent:ai-tool');\n\nexport interface AiToolOptions {\n name: string;\n /**\n * `read` auto-executes; `action` requires HITL approval. (Core's `ToolKind` also has `agent`\n * for delegation, but that kind is synthesized from `delegatesTo` — never authored here.)\n */\n kind: 'read' | 'action';\n description: string;\n /**\n * Input schema as a [Standard Schema](https://standardschema.dev) — Zod, Valibot, or ArkType.\n * Validated before the handler runs.\n */\n input: StandardSchemaV1;\n /** Roles allowed to invoke. Omit to inherit the module's default roles. */\n roles?: string[];\n /**\n * Authz ability checked by an ability-aware RolesPolicy (e.g. `AgentAuthzModule`'s\n * `AuthzRolesPolicy` → `gate.forUser(actor).allows(ability)`). Ignored by the default\n * role-based policy, which uses `roles`.\n */\n ability?: string;\n}\n\n/**\n * Marks a provider class as an AI tool. The class must implement `execute(input, ctx)`.\n * `AiToolDiscoveryService` registers every `@AiTool` provider into the `ToolRegistry` at boot.\n *\n * ```ts\n * @AiTool({ name: 'getWeather', kind: 'read', description: '...', input: z.object({ city: z.string() }) })\n * class GetWeatherTool implements ToolHandler<{ city: string }> {\n * async execute(input, ctx) { return { tempC: 21 }; }\n * }\n * ```\n */\nexport function AiTool(options: AiToolOptions): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(AI_TOOL_METADATA, options, target);\n };\n}\n\nexport function readAiToolMetadata(target: object): AiToolOptions | undefined {\n return Reflect.getMetadata(AI_TOOL_METADATA, target.constructor) as AiToolOptions | undefined;\n}\n","import type { ToolHandler, ToolSpec } from '@dudousxd/nestjs-agent-core';\nimport type { FactoryProvider, Provider } from '@nestjs/common';\n\n/**\n * Brand stamped onto a functional-tool provider instance so `AiToolDiscoveryService` picks it up\n * when it walks every provider at boot — the declarative alternative to a manual `registry.register`.\n */\nexport const AGENT_TOOL_BRAND = Symbol.for('@dudousxd/nestjs-agent:functional-tool');\n\n/** A tool expressed as data + handler (e.g. from `createExecuteSqlTool`), not an `@AiTool` class. */\nexport interface FunctionalTool {\n spec: ToolSpec;\n handler: ToolHandler;\n}\n\n/** A {@link FunctionalTool} carrying {@link AGENT_TOOL_BRAND} — what a provider resolves to. */\nexport interface BrandedFunctionalTool extends FunctionalTool {\n readonly [AGENT_TOOL_BRAND]: true;\n}\n\nfunction brand(tool: FunctionalTool): BrandedFunctionalTool {\n return { [AGENT_TOOL_BRAND]: true, spec: tool.spec, handler: tool.handler };\n}\n\n/** Narrows a provider instance to a branded functional tool for boot-time registration. */\nexport function isBrandedFunctionalTool(value: object): value is BrandedFunctionalTool {\n return AGENT_TOOL_BRAND in value && 'spec' in value && 'handler' in value;\n}\n\n/**\n * Registers a functional tool declaratively — drop the returned provider in a module's `providers`\n * and `AiToolDiscoveryService` auto-registers it at boot. Each call uses a fresh, unique provide\n * token so the same tool can be provided many times without collisions.\n *\n * Two forms: a static tool (`useValue`) or a factory with `inject` for DI-resolved dependencies\n * (`useFactory`). Either way the resolved instance is branded with {@link AGENT_TOOL_BRAND}.\n */\nexport function provideAgentTool(tool: FunctionalTool): Provider;\nexport function provideAgentTool(\n factory: (...deps: never[]) => FunctionalTool,\n inject?: FactoryProvider['inject'],\n): Provider;\nexport function provideAgentTool(\n factoryOrTool: FunctionalTool | ((...deps: never[]) => FunctionalTool),\n inject?: FactoryProvider['inject'],\n): Provider {\n const provide = Symbol('nestjs-agent:functional-tool-instance');\n if (typeof factoryOrTool === 'function') {\n return {\n provide,\n useFactory: (...deps: never[]) => brand(factoryOrTool(...deps)),\n inject: inject ?? [],\n };\n }\n return { provide, useValue: brand(factoryOrTool) };\n}\n","import {\n AgentStreamError,\n type SinkWriter,\n type StreamError,\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}\n\n/**\n * The default `TokenStreamSink`: buffers chunks per run in-process so a reconnecting subscriber\n * replays everything so far, then follows live.\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\n private buffer(runId: string): RunBuffer {\n let buf = this.runs.get(runId);\n if (buf === undefined) {\n buf = { chunks: [], ended: false, notify: new Set() };\n this.runs.set(runId, buf);\n }\n return 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 open(runId: string): SinkWriter {\n const buf = this.buffer(runId);\n return {\n write: (chunk: Uint8Array) => {\n buf.chunks.push(chunk);\n this.wake(buf);\n },\n end: () => {\n buf.ended = true;\n this.wake(buf);\n },\n fail: (error: StreamError) => {\n buf.failure = error;\n buf.ended = true;\n this.wake(buf);\n },\n };\n }\n\n async *subscribe(runId: string): AsyncIterable<Uint8Array> {\n const buf = this.buffer(runId);\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 await new Promise<void>((resolve) => buf.notify.add(resolve));\n }\n }\n\n close(runId: string): void {\n this.runs.delete(runId);\n }\n}\n","import type { AgentStore, QuotaState, QuotaStore } from '@dudousxd/nestjs-agent-core';\n\n/**\n * A production {@link QuotaStore} backed by the persisted usage ledger. `check` reads the actor's\n * tokens-so-far for the day straight from {@link AgentStore.quotaToday} and compares it to a fixed\n * daily limit; `bump` is a deliberate no-op because the loop's `recordUsage` already writes every\n * turn's tokens to that same ledger. One source of truth — so enforcement and what the dashboard\n * reports can never drift, and it works across replicas with no extra shared state.\n */\nexport class LedgerQuotaStore implements QuotaStore {\n constructor(\n private readonly store: AgentStore,\n private readonly limitTokens: number,\n ) {}\n\n async check(actorRef: string, day: string): Promise<QuotaState> {\n const { usedTokens } = await this.store.quotaToday(actorRef, day);\n return {\n usedTokens,\n limitTokens: this.limitTokens,\n withinLimit: usedTokens < this.limitTokens,\n };\n }\n\n async bump(): Promise<void> {\n // No-op: the ledger is the source of truth — recordUsage already persisted this turn's tokens.\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_STORE,\n type Actor,\n type AgentLoopHooks,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type Decision,\n QuotaExceededError,\n publishAgentRunFailed,\n runAgentLoop,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { type AgentDeps, childSinkWriter, utcDay } from '../agent-deps.js';\n\n/**\n * Runs the agent turn in-process. HITL approval resolves a pending promise keyed by\n * `runId:toolCallId`. Sub-agent delegation runs a nested loop that streams into the top-level run's\n * sink (so a human sees it) and shares the same approval mechanism — a sub-agent's action tools go\n * through the same human gate, keyed by the sub-agent's own runId. Single-replica only (the pending\n * map is in-process); durable is the scaled path.\n */\n@Injectable()\nexport class InlineAgentRunner implements AgentRunner {\n private readonly logger = new Logger(InlineAgentRunner.name);\n private readonly pending = new Map<string, (decision: Decision) => void>();\n\n constructor(\n @Inject(AGENT_DEPS_FACTORY) private readonly factory: AgentDepsFactory,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n ) {}\n\n async start(input: AgentRunInput): Promise<{ runId: string }> {\n const runId = crypto.randomUUID();\n const day = input.day ?? utcDay();\n const deps = this.factory.forAgent(input.agentName);\n const hooks = this.topLevelHooks(runId, deps, input.actor, day);\n\n void runAgentLoop({ ...deps, day }, input, hooks).catch(async (error) => {\n const message = error instanceof Error ? error.message : String(error);\n const code = error instanceof QuotaExceededError ? 'quota_exceeded' : 'run_failed';\n this.logger.error(`agent run ${runId} failed (${code}): ${message}`);\n publishAgentRunFailed({ runId, code, message });\n // Terminate the live stream with a typed failure so the transport emits an error frame\n // instead of leaking the message as assistant text.\n const writer = await deps.sink.open(runId);\n await writer.fail({ code, message });\n });\n\n return { runId };\n }\n\n async signal(runId: string, toolCallId: string, decision: Decision): Promise<void> {\n const key = `${runId}:${toolCallId}`;\n const resolve = this.pending.get(key);\n if (resolve !== undefined) {\n this.pending.delete(key);\n resolve(decision);\n }\n }\n\n async cancel(runId: string): Promise<void> {\n const deps = this.factory.forAgent();\n const writer = await deps.sink.open(runId);\n await writer.end();\n }\n\n private topLevelHooks(runId: string, deps: AgentDeps, actor: Actor, day: string): AgentLoopHooks {\n return {\n runId,\n openSink: () => deps.sink.open(runId),\n awaitApproval: (call) =>\n new Promise<Decision>((resolve) => {\n this.pending.set(`${runId}:${call.id}`, resolve);\n }),\n step: (_name, fn) => fn(),\n runAgent: (agentName, task) => this.runNested(agentName, task, actor, day, 1, runId),\n };\n }\n\n /**\n * Delegate to another agent as a nested in-process run. The sub-agent streams into `sinkRunId`\n * (the top-level run the human is watching) so its output and any pending action tool are visible,\n * and its own approvals resolve through the shared pending map keyed by its own runId.\n */\n private async runNested(\n agentName: string,\n task: string,\n actor: Actor,\n day: string,\n depth: number,\n sinkRunId: string,\n ): Promise<{ text: string }> {\n const subThread = await this.store.createThread({ actor, transient: true });\n const runId = crypto.randomUUID();\n // Mark the subthread as streaming THIS sub-run so a human approval routes back here\n // (runForToolCall → subthread.activeStreamId → this runId).\n await this.store.setActiveStream(subThread.id, runId);\n const deps = this.factory.forAgent(agentName);\n const hooks: AgentLoopHooks = {\n runId,\n // Forward into the top-level stream; the top-level run owns end/fail on that shared sink.\n openSink: async () => childSinkWriter(await deps.sink.open(sinkRunId)),\n awaitApproval: (call) =>\n new Promise<Decision>((resolve) => {\n this.pending.set(`${runId}:${call.id}`, resolve);\n }),\n step: (_name, fn) => fn(),\n runAgent: (childName, childTask) =>\n this.runNested(childName, childTask, actor, day, depth + 1, sinkRunId),\n };\n return runAgentLoop(\n { ...deps, day },\n {\n threadId: subThread.id,\n actor,\n userText: task,\n agentName,\n day,\n delegationDepth: depth,\n sinkRunId,\n },\n hooks,\n );\n }\n}\n","import type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\n\n/** Read a string header off an unknown transport request, narrowing without trusting its shape. */\nfunction readHeader(req: unknown, name: string): string | undefined {\n if (typeof req !== 'object' || req === null || !('headers' in req)) return undefined;\n const { headers } = req;\n if (typeof headers !== 'object' || headers === null || !(name in headers)) return undefined;\n const value: unknown = Reflect.get(headers, name);\n return typeof value === 'string' ? value : undefined;\n}\n\n/**\n * A development / gateway {@link ActorResolver} that trusts request headers:\n * `x-actor-id` (required), `x-actor-role` (comma-separated → `roles`), `x-tenant-ref`.\n *\n * **Security:** it throws when `x-actor-id` is absent — it never fabricates an identity\n * and never grants a default role (an actor with no `x-actor-role` gets `roles: []`, i.e.\n * no tools). Trusting client headers is only safe behind a gateway that strips and re-sets\n * them from an authenticated principal. Real deployments should provide their own resolver\n * that reads a verified session/JWT instead of installing this one.\n */\nexport class HeaderActorResolver implements ActorResolver {\n resolve(req: unknown): Actor {\n const id = readHeader(req, 'x-actor-id');\n if (id === undefined || id.length === 0) {\n throw new Error(\n 'HeaderActorResolver: missing x-actor-id header. No default actor is fabricated. ' +\n 'Send x-actor-id from a trusted gateway, or configure ' +\n 'AgentModule.forRoot({ actorResolver }) with a resolver that reads your ' +\n 'authenticated principal.',\n );\n }\n const roles = (readHeader(req, 'x-actor-role') ?? '')\n .split(',')\n .map((role) => role.trim())\n .filter((role) => role.length > 0);\n const tenantRef = readHeader(req, 'x-tenant-ref');\n return {\n id,\n roles,\n ...(tenantRef !== undefined ? { tenantRef } : {}),\n };\n }\n}\n","export { AgentModule } from './agent.module.js';\nexport type { AgentModuleOptions, AgentModuleAsyncOptions } from './agent.options.js';\nexport { AgentService, type ChatParams } from './agent.service.js';\nexport {\n AiTool,\n type AiToolOptions,\n AI_TOOL_METADATA,\n readAiToolMetadata,\n} from './decorator/ai-tool.decorator.js';\nexport {\n Agent,\n type AgentOptions,\n AGENT_METADATA,\n readAgentMetadata,\n} from './decorator/agent.decorator.js';\nexport {\n SystemPrompt,\n SystemPromptContributor,\n SYSTEM_PROMPT_METADATA,\n SYSTEM_PROMPT_CONTRIBUTOR_METADATA,\n} from './decorator/system-prompt.decorator.js';\nexport { AiToolDiscoveryService } from './discovery/ai-tool-discovery.service.js';\nexport { AgentDiscoveryService } from './discovery/agent-discovery.service.js';\nexport {\n provideAgentTool,\n AGENT_TOOL_BRAND,\n type FunctionalTool,\n} from './functional-tool.js';\nexport { InlineAgentRunner } from './runner/inline-agent-runner.js';\nexport { InProcessTokenStreamSink } from './in-process-sink.js';\nexport { LedgerQuotaStore } from './ledger-quota-store.js';\nexport { type AgentDeps, utcDay } from './agent-deps.js';\nexport { AgentDepsFactory, delegateToolName } from './agent-deps.factory.js';\nexport { HeaderActorResolver } from './resolver/header-actor-resolver.js';\n\n// Re-export the core surface so consumers import tools/types from one place.\nexport * from '@dudousxd/nestjs-agent-core';\n"],"mappings":"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","names":["AGENT_ACTOR_RESOLVER","AGENT_DEPS_FACTORY","AGENT_DURABLE_RUNNER","AGENT_MODEL","AGENT_OPTIONS","AGENT_PROMPT_CONTRIBUTORS","AGENT_QUOTA_STORE","AGENT_REGISTRY","AGENT_ROLES_POLICY","AGENT_RUNNER","AGENT_SINK","AGENT_STORE","AGENT_TOOL_REGISTRY","AgentRegistry","DefaultRolesPolicy","ToolRegistry","Global","Module","DiscoveryModule","RouterModule","AGENT_MODEL","AGENT_PROMPT_CONTRIBUTORS","AGENT_QUOTA_STORE","AGENT_REGISTRY","AGENT_ROLES_POLICY","AGENT_SINK","AGENT_STORE","AGENT_TOOL_REGISTRY","AgentRegistry","ToolRegistry","AGENT_OPTIONS","Inject","Injectable","delegateToolName","target","replace","AgentDepsFactory","options","model","store","sink","rolesPolicy","registry","agents","promptContributors","quota","defaultAgentName","defaultAgent","undefined","registered","list","length","name","effectiveTools","definition","delegated","delegatesTo","map","tools","forAgent","agentName","get","toolAllowList","followUpsCount","retrieval","systemPrompt","maxSteps","modelId","toolTimeoutMs","mode","retriever","topK","retrievalTopK","followUps","count","AGENT_DEPS_FACTORY","AGENT_QUOTA_STORE","AGENT_RUNNER","AGENT_STORE","BadRequestException","ForbiddenException","Inject","Injectable","NotFoundException","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","fail","AgentService","runner","store","deps","quota","chat","params","agentName","defaultAgentName","threadId","undefined","regenerate","BadRequestException","created","createThread","actor","transient","id","assertOwnsThread","input","userText","message","day","utcDay","pageContext","runId","start","setActiveStream","subscribe","forAgent","sink","approve","toolCallId","runForOwnedToolCall","signal","approved","reject","reason","cancel","assertOwnsActiveStream","listThreads","actorRef","getThread","deleteThread","softDeleteThread","forkThread","fromMessageId","renameThread","title","trimmed","trim","length","setTitle","promoteThread","truncateThreadFrom","messageId","truncateFrom","quotaToday","usedTokens","costUsd","limitTokens","withinLimit","state","check","owner","ownerOfThread","NotFoundException","ForbiddenException","ownerOfToolCall","runForToolCall","ownerOfActiveStream","AGENT_ACTOR_RESOLVER","AgentStreamError","Body","Controller","Get","Inject","Param","Post","Req","Res","ChatController","agent","actorResolver","chat","req","res","body","actor","resolve","runId","threadId","message","undefined","agentName","pageContext","regenerate","transient","pipe","stream","cancel","aborted","setHeader","write","JSON","stringify","decoder","TextDecoder","chunk","subscribe","delta","decode","error","payload","AgentStreamError","code","Error","end","AGENT_ACTOR_RESOLVER","Controller","Get","Inject","Req","QuotaController","agent","actorResolver","today","req","actor","resolve","quotaToday","id","AGENT_ACTOR_RESOLVER","Body","Controller","Delete","Get","Inject","Param","Patch","Post","Req","ThreadsController","agent","actorResolver","list","req","actor","resolve","listThreads","id","detail","getThread","remove","deleteThread","ok","fork","messageId","forkThread","rename","body","renameThread","title","promote","promoteThread","truncateFrom","truncateThreadFrom","AGENT_ACTOR_RESOLVER","Body","Controller","Inject","Post","Req","ToolCallController","agent","actorResolver","approve","req","body","actor","resolve","toolCallId","ok","reject","reason","AGENT_PROMPT_CONTRIBUTORS","AGENT_REGISTRY","AgentRegistry","Inject","Injectable","Logger","DiscoveryService","MetadataScanner","AGENT_METADATA","Symbol","for","Agent","options","target","Reflect","defineMetadata","readAgentMetadata","getMetadata","SYSTEM_PROMPT_METADATA","Symbol","for","SYSTEM_PROMPT_CONTRIBUTOR_METADATA","SystemPrompt","target","key","Reflect","defineMetadata","SystemPromptContributor","AgentDiscoveryService","logger","Logger","name","discovery","scanner","registry","contributors","onModuleInit","wrapper","getProviders","instance","meta","readAgentMetadata","undefined","register","definitionFrom","collectContributors","promptMethod","methodWith","SYSTEM_PROMPT_METADATA","systemPrompt","ctx","tools","model","modelId","maxSteps","handoff","delegatesTo","handoffNames","names","target","targetMeta","warn","push","prototype","Object","getPrototypeOf","getAllMethodNames","Reflect","getMetadata","SYSTEM_PROMPT_CONTRIBUTOR_METADATA","method","boundMethod","metadataKey","candidate","call","AGENT_OPTIONS","AGENT_REGISTRY","AGENT_TOOL_REGISTRY","Inject","Injectable","Logger","DiscoveryService","z","AI_TOOL_METADATA","Symbol","AiTool","options","target","Reflect","defineMetadata","readAiToolMetadata","getMetadata","AGENT_TOOL_BRAND","Symbol","for","brand","tool","spec","handler","isBrandedFunctionalTool","value","provideAgentTool","factoryOrTool","inject","provide","useFactory","deps","useValue","AiToolDiscoveryService","logger","Logger","name","discovery","registry","agents","options","onApplicationBootstrap","count","functional","wrapper","getProviders","instance","undefined","isBrandedFunctionalTool","registerFunctionalTool","meta","readAiToolMetadata","handler","execute","warn","register","kind","description","inputSchema","input","roles","ability","ctx","tool","tools","delegates","definition","list","target","delegatesTo","targetDefinition","get","Error","delegateToolName","has","targetBlurb","systemPrompt","targetAgent","z","object","task","string","log","spec","AgentStreamError","InProcessTokenStreamSink","runs","Map","buffer","runId","buf","get","undefined","chunks","ended","notify","Set","set","wake","resolve","clear","open","write","chunk","push","end","fail","error","failure","subscribe","index","length","AgentStreamError","Promise","add","close","delete","LedgerQuotaStore","store","limitTokens","check","actorRef","day","usedTokens","quotaToday","withinLimit","bump","AGENT_DEPS_FACTORY","AGENT_STORE","QuotaExceededError","publishAgentRunFailed","runAgentLoop","Inject","Injectable","Logger","InlineAgentRunner","logger","Logger","name","pending","Map","factory","store","start","input","runId","crypto","randomUUID","day","utcDay","deps","forAgent","agentName","hooks","topLevelHooks","actor","runAgentLoop","catch","error","message","Error","String","code","QuotaExceededError","publishAgentRunFailed","writer","sink","open","fail","signal","toolCallId","decision","key","resolve","get","undefined","delete","cancel","end","openSink","awaitApproval","call","Promise","set","id","step","_name","fn","runAgent","task","runNested","depth","sinkRunId","subThread","createThread","transient","setActiveStream","childSinkWriter","childName","childTask","threadId","userText","delegationDepth","DEFAULT_PATH","sharedProviders","durable","includeStore","providers","provide","AGENT_TOOL_REGISTRY","useFactory","ToolRegistry","AGENT_REGISTRY","AgentRegistry","AGENT_PROMPT_CONTRIBUTORS","AGENT_SINK","options","sink","InProcessTokenStreamSink","inject","AGENT_OPTIONS","AGENT_ROLES_POLICY","rolesPolicy","DefaultRolesPolicy","defaultRoles","AGENT_ACTOR_RESOLVER","actorResolver","AGENT_MODEL","o","model","AGENT_QUOTA_STORE","store","quota","quotaLimitTokens","undefined","LedgerQuotaStore","AGENT_STORE","AgentDepsFactory","AGENT_DEPS_FACTORY","useExisting","AgentDiscoveryService","AiToolDiscoveryService","InlineAgentRunner","AgentService","push","AGENT_RUNNER","durableRunner","Error","token","AGENT_DURABLE_RUNNER","optional","exportsFor","CONTROLLERS","ChatController","ThreadsController","ToolCallController","QuotaController","routerFor","path","RouterModule","register","module","AgentModule","forRoot","global","imports","DiscoveryModule","controllers","useValue","exports","forRootAsync","readHeader","req","name","undefined","headers","value","Reflect","get","HeaderActorResolver","resolve","id","length","Error","roles","split","map","role","trim","filter","tenantRef"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-agent",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Governed, durable-backed AI agent for NestJS — @AiTool, discovery, /agent controllers",
5
5
  "license": "MIT",
6
6
  "author": "Davide Carvalho",
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "@standard-schema/spec": "1.1.0",
38
38
  "zod": "3.25.76",
39
- "@dudousxd/nestjs-agent-core": "0.3.0"
39
+ "@dudousxd/nestjs-agent-core": "0.3.1"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@nestjs/common": "^10.0.0 || ^11.0.0",
@@ -71,7 +71,7 @@
71
71
  "tsup": "8.3.5",
72
72
  "typescript": "5.9.3",
73
73
  "zod": "3.25.76",
74
- "@dudousxd/nestjs-agent-testing": "0.3.0"
74
+ "@dudousxd/nestjs-agent-testing": "0.3.1"
75
75
  },
76
76
  "scripts": {
77
77
  "build": "tsup",