@dudousxd/nestjs-agent 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/agent.module.ts","../src/agent-deps.factory.ts","../src/agent.service.ts","../src/agent-deps.ts","../src/approval-port.adapter.ts","../src/controller/agents.controller.ts","../src/controller/attachments.controller.ts","../src/controller/chat.controller.ts","../src/controller/memories.controller.ts","../src/controller/quota.controller.ts","../src/controller/skills.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/discovery/skill-discovery.service.ts","../src/decorator/skill.decorator.ts","../src/in-process-sink.ts","../src/ledger-quota-store.ts","../src/runner/inline-agent-runner.ts","../src/skills-config.ts","../src/resolver/header-actor-resolver.ts"],"sourcesContent":["export { AgentModule } from './agent.module.js';\nexport { AgentApprovalPortAdapter } from './approval-port.adapter.js';\nexport type {\n AgentModuleOptions,\n AgentModuleAsyncOptions,\n AgentAttachmentsOptions,\n AgentSkillsOptions,\n AgentMemoryOptions,\n AgentSurface,\n} from './agent.options.js';\nexport {\n AgentService,\n type ChatParams,\n type ThreadDefaultAgentReader,\n} from './agent.service.js';\nexport {\n AttachmentsController,\n ATTACHMENT_PAGE_SIZE,\n DEFAULT_MAX_ATTACHMENT_BYTES,\n DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,\n} from './controller/attachments.controller.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 Skill,\n type SkillOptions,\n type SkillBody,\n SKILL_METADATA,\n readSkillMetadata,\n skillScope,\n} from './decorator/skill.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 SkillDiscoveryService,\n type DeclaredSkill,\n} from './discovery/skill-discovery.service.js';\nexport { SkillsController } from './controller/skills.controller.js';\nexport { MemoriesController } from './controller/memories.controller.js';\nexport { declaredSkillProvider, resolveSkillsConfig } from './skills-config.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","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_APPROVAL_PORT,\n AGENT_DEPS_FACTORY,\n AGENT_DURABLE_RUNNER,\n AGENT_MEMORY,\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_SKILLS,\n AGENT_SKILL_SOURCES,\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 {\n type CanActivate,\n type DynamicModule,\n Global,\n Module,\n type Provider,\n type Type,\n} from '@nestjs/common';\nimport { DiscoveryModule, RouterModule } from '@nestjs/core';\nimport { AgentDepsFactory } from './agent-deps.factory.js';\nimport type { AgentModuleAsyncOptions, AgentModuleOptions, AgentSurface } from './agent.options.js';\nimport { AgentService } from './agent.service.js';\nimport { AgentApprovalPortAdapter } from './approval-port.adapter.js';\nimport { AgentsController } from './controller/agents.controller.js';\nimport { AttachmentsController } from './controller/attachments.controller.js';\nimport { ChatController } from './controller/chat.controller.js';\nimport { MemoriesController } from './controller/memories.controller.js';\nimport { QuotaController } from './controller/quota.controller.js';\nimport { SkillsController } from './controller/skills.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 { type DeclaredSkill, SkillDiscoveryService } from './discovery/skill-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';\nimport { resolveSkillsConfig } from './skills-config.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 // Likewise for `@Skill`-decorated providers — filled by SkillDiscoveryService at onModuleInit,\n // read lazily by the AGENT_SKILLS provider below (which DI builds before discovery has run).\n { provide: AGENT_SKILL_SOURCES, useFactory: () => [] },\n {\n // One resolution, shared by the loop's deps and the listing endpoint: a second one would\n // drift, and a user would be offered a skill the agent cannot reach. `undefined` when the\n // host configured none — which is what keeps the turn's checkpoint sequence unchanged.\n provide: AGENT_SKILLS,\n useFactory: (options: AgentModuleOptions, declared: DeclaredSkill[]) =>\n resolveSkillsConfig(options.skills, declared),\n inject: [AGENT_OPTIONS, AGENT_SKILL_SOURCES],\n },\n {\n // One resolution, shared by the loop's deps and the read-back endpoint: a person has to be\n // shown what the model was shown, and two resolutions would eventually disagree about that.\n provide: AGENT_MEMORY,\n useFactory: (options: AgentModuleOptions) => options.memory,\n inject: [AGENT_OPTIONS],\n },\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 SkillDiscoveryService,\n InlineAgentRunner,\n AgentService,\n // Bound ALWAYS (durable or inline) — the console's cross-thread approvals inbox routes decisions\n // through AgentService.signalToolCall, which reaches whichever AGENT_RUNNER is bound above.\n AgentApprovalPortAdapter,\n { provide: AGENT_APPROVAL_PORT, useExisting: AgentApprovalPortAdapter },\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_SKILLS,\n AGENT_MEMORY,\n AGENT_DEPS_FACTORY,\n AgentDepsFactory,\n AgentService,\n InlineAgentRunner,\n AGENT_APPROVAL_PORT,\n ];\n}\n\nconst BASE_CONTROLLERS = [\n ChatController,\n ThreadsController,\n ToolCallController,\n QuotaController,\n AgentsController,\n SkillsController,\n MemoriesController,\n];\n\n/** Every controller class `guards` may ever target — stamped uniformly regardless of which of them are actually mounted this build (harmless: metadata on an unregistered class is simply unused). */\nconst GUARDABLE_CONTROLLERS = [...BASE_CONTROLLERS, AttachmentsController];\n\n/** The controllers to mount: the base six, plus attachments when the host opted into uploads. */\nfunction controllersFor(mountAttachments: boolean): Type<object>[] {\n return mountAttachments ? [...BASE_CONTROLLERS, AttachmentsController] : BASE_CONTROLLERS;\n}\n\n/**\n * `surface: 'engine'` mounts NO controllers — a worker pod never receives HTTP traffic, so its\n * routes (and whatever guards they'd carry) have no business existing there. `'http'`/`'both'`\n * (and the omitted default) mount the same set `controllersFor` always has.\n */\nfunction controllersForSurface(\n surface: AgentSurface | undefined,\n mountAttachments: boolean,\n): Type<object>[] {\n return surface === 'engine' ? [] : controllersFor(mountAttachments);\n}\n\n/**\n * Nest's `GUARDS_METADATA` key (`@nestjs/common/constants`), inlined as a literal: `@nestjs/common`\n * has no `exports` map and its ESM-facing files are CJS, so a deep `import ... from\n * '@nestjs/common/constants'` in our ESM build is emitted extensionless and rejected by Node's\n * strict ESM resolver (surfaced by a consumer's bundler/test runner externalizing this package).\n * `agent-guards.spec.ts` asserts this literal still matches the real constant, so upstream drift\n * fails loudly instead of silently stamping a dead metadata key.\n */\nconst GUARDS_METADATA = '__guards__';\n\n/**\n * Stamp (or clear) `@UseGuards`-equivalent metadata on every controller this module MIGHT mount.\n *\n * Mechanism: `@UseGuards(...guards)` on a controller just does `Reflect.defineMetadata(GUARDS_METADATA,\n * guards, ControllerClass)` (via Nest's `extendArrayMetadata`, which *appends* to any existing array).\n * We call `Reflect.defineMetadata` directly instead, so each `forRoot`/`forRootAsync` call REPLACES\n * the metadata rather than appending to it — appending would leak guards across repeated module\n * registrations in the same process (every test file that calls `forRoot` more than once, say) since\n * these controller classes are module-level singletons shared by every registration. Nest's\n * `GuardsConsumer` reads this metadata per-request via `Reflector`, not once at boot, so the LAST call\n * to stamp it before a request is served wins for that controller class in this process.\n */\nfunction applyGuards(guards: Type<CanActivate>[] | undefined): void {\n const resolved = guards ?? [];\n for (const controller of GUARDABLE_CONTROLLERS) {\n Reflect.defineMetadata(GUARDS_METADATA, resolved, controller);\n }\n}\n\n/** Distinct guard classes for the module's `providers`, so Nest can DI-instantiate them. */\nfunction guardProviders(guards: Type<CanActivate>[] | undefined): Type<CanActivate>[] {\n return [...new Set(guards ?? [])];\n}\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 applyGuards(options.guards);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path)],\n controllers: controllersForSurface(options.surface, options.attachments?.upload === true),\n providers: [\n { provide: AGENT_OPTIONS, useValue: options },\n ...sharedProviders(options.durable ?? false, includeStore),\n ...guardProviders(options.guards),\n ],\n exports: exportsFor(includeStore),\n };\n }\n\n static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n // The async factory resolves too late to inspect `store`, so `forRootAsync` binds AGENT_STORE\n // locally from the factory result by default. `externalStore: true` opts out — deferring to a\n // globally-imported store module (e.g. `MikroOrmAgentStoreModule.forFeature()`) so the host\n // doesn't have to inject that store just to hand it back as `store`.\n const includeStore = options.externalStore !== true;\n applyGuards(options.guards);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path), ...(options.imports ?? [])],\n controllers: controllersForSurface(options.surface, options.attachmentsUpload === true),\n providers: [\n {\n provide: AGENT_OPTIONS,\n // Stamp the STATIC wiring flags onto the factory result: `durable`/`surface` are\n // authoritative on the async config object (they decided the actual wiring above), and\n // the durable module reads `durable` back off AGENT_OPTIONS. `surface` isn't read back by\n // anything today (AgentDurableModule takes its own mirror option — see its doc for why),\n // but it's stamped here too so the EFFECTIVE value is always observable off\n // AGENT_OPTIONS, sync or async alike.\n useFactory: async (...args: never[]) => ({\n ...(await options.useFactory(...args)),\n durable: options.durable ?? false,\n surface: options.surface ?? 'both',\n }),\n inject: options.inject ?? [],\n },\n ...sharedProviders(options.durable ?? false, includeStore),\n ...guardProviders(options.guards),\n ],\n exports: exportsFor(includeStore),\n };\n }\n}\n","import {\n AGENT_MEMORY,\n AGENT_MODEL,\n AGENT_PRICING_STORE,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_STORE,\n AGENT_REGISTRY,\n AGENT_ROLES_POLICY,\n AGENT_SINK,\n AGENT_SKILLS,\n AGENT_STORE,\n AGENT_TOOL_REGISTRY,\n type AgentDefinition,\n type AgentHistoryWindow,\n type AgentPricingStore,\n AgentRegistry,\n type AgentStore,\n type HistoryPolicy,\n type MemoryConfig,\n type ModelProvider,\n type PromptContributor,\n type QuotaStore,\n type RolesPolicy,\n type SkillsConfig,\n type TokenStreamSink,\n ToolRegistry,\n normalizeDelegation,\n summarizeWithModel,\n windowHistory,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_OPTIONS } from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport type { AgentDeps } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\n\n/**\n * The synthesized `agent`-kind tool name an orchestrator uses to hand off to `target`.\n *\n * A detached edge gets its own verb — `start_research` next to `ask_research` — for two reasons.\n * One agent can be both awaited AND backgrounded by the same orchestrator, and one name cannot\n * carry both. And the name is the part of a tool the model reads first: `ask` promises an answer,\n * `start` does not.\n */\nexport function delegateToolName(args: { target: string; detached?: boolean }): string {\n const slug = args.target.replace(/[^a-zA-Z0-9]+/g, '_');\n return args.detached === true ? `start_${slug}` : `ask_${slug}`;\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 // Optional: AGENT_PRICING_STORE has no local provider in this module (unlike AGENT_QUOTA_STORE,\n // which is always a registered factory) — it's bound externally (e.g. by a store module), so a\n // plain @Inject would throw when nothing binds it.\n @Optional()\n @Inject(AGENT_PRICING_STORE)\n private readonly pricingStore: AgentPricingStore | undefined,\n // Optional for the same reason, plus one of its own: `undefined` is the CONFIGURED state for a\n // host that declared no skills, not an unbound dependency.\n @Optional()\n @Inject(AGENT_SKILLS)\n private readonly skills: SkillsConfig | undefined,\n // Optional for the same reason: `undefined` is the CONFIGURED state for a host that wired no\n // memory, not an unbound dependency.\n @Optional()\n @Inject(AGENT_MEMORY)\n private readonly memory: MemoryConfig | undefined,\n ) {}\n\n /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */\n memoryConfig(): MemoryConfig | undefined {\n return this.memory;\n }\n\n /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */\n skillsConfig(): SkillsConfig | undefined {\n return this.skills;\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((edge) => {\n const { agent, detached } = normalizeDelegation(edge);\n return delegateToolName({ target: agent, detached });\n });\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 const historyPolicy = this.historyPolicy(definition);\n const ask = definition?.ask ?? this.options.ask;\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?.maxDelegationDepth !== undefined\n ? { maxDelegationDepth: definition.maxDelegationDepth }\n : {}),\n ...(definition?.maxAgentAppearances !== undefined\n ? { maxAgentAppearances: definition.maxAgentAppearances }\n : {}),\n ...(definition?.modelId !== undefined ? { modelId: definition.modelId } : {}),\n ...(this.quota !== undefined ? { quota: this.quota } : {}),\n ...(this.pricingStore !== undefined ? { pricingStore: this.pricingStore } : {}),\n ...(historyPolicy !== undefined ? { historyPolicy } : {}),\n inputProcessors: this.options.inputProcessors ?? [],\n outputProcessors: this.options.outputProcessors ?? [],\n ...(definition?.outputSchema !== undefined ? { outputSchema: definition.outputSchema } : {}),\n ...(definition?.outputRepairAttempts !== undefined\n ? { outputRepairAttempts: definition.outputRepairAttempts }\n : {}),\n ...(definition?.intake !== undefined ? { intake: definition.intake } : {}),\n // Most specific wins, exactly as `historyPolicy` resolves: the agent's own `@Agent({ ask })`,\n // else the module-wide flag. Both are module config, so every process of a deployment agrees.\n ...(ask === true ? { ask: true } : {}),\n // Module-wide, never per-agent: a skill is a procedure, not a persona, and an agent that could\n // opt out of one would make the catalog depend on which agent a turn happened to select — a\n // per-turn fact the worker re-deriving the tool list cannot see.\n ...(this.skills !== undefined ? { skills: this.skills } : {}),\n // Module-wide, never per-agent, for the same reason skills are: which memories a turn carries\n // cannot depend on which persona answered it, or the worker re-deriving a dispatched turn's\n // tool list would disagree with the loop about whether `remember` was offered.\n ...(this.memory !== undefined ? { memory: this.memory } : {}),\n ...(toolAllowList !== undefined ? { toolAllowList } : {}),\n ...(this.options.toolTimeoutMs !== undefined\n ? { toolTimeoutMs: this.options.toolTimeoutMs }\n : {}),\n ...(this.options.toolTransientRetry !== undefined\n ? { toolTransientRetry: this.options.toolTransientRetry }\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 /**\n * The ceiling on how much of a thread this agent's turns carry, most specific wins: the agent's\n * own `@Agent({ history })`, else a module-wide custom `historyPolicy`, else the module-wide\n * `history` window. Undefined → unbounded, the behaviour of a module that configures none.\n */\n private historyPolicy(definition: AgentDefinition | undefined): HistoryPolicy | undefined {\n if (definition?.history !== undefined) {\n return this.window(definition.history);\n }\n if (this.options.historyPolicy !== undefined) {\n return this.options.historyPolicy;\n }\n return this.options.history === undefined ? undefined : this.window(this.options.history);\n }\n\n /** Build the built-in window policy from the declarative `{ maxMessages, maxTokens, summarize }`. */\n private window(config: AgentHistoryWindow): HistoryPolicy {\n return windowHistory({\n ...(config.maxMessages !== undefined ? { maxMessages: config.maxMessages } : {}),\n ...(config.maxTokens !== undefined ? { maxTokens: config.maxTokens } : {}),\n // The shared module model, not a per-agent one: an agent's `modelId` is an accounting label,\n // and only one provider is ever bound.\n ...(config.summarize === true ? { summarize: summarizeWithModel(this.model) } : {}),\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_ATTACHMENT_STAGING,\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 AttachmentRef,\n type AttachmentStagingStore,\n type Decision,\n type ElicitationReply,\n type HumanReply,\n type ListStagedAttachmentsInput,\n type MessageAttachment,\n type PageContext,\n type QuotaStore,\n type QuotaView,\n type StagedAttachment,\n type ThreadDetail,\n type ThreadSummary,\n type UpdateThreadInput,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n ForbiddenException,\n Inject,\n Injectable,\n NotFoundException,\n NotImplementedException,\n Optional,\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 /**\n * Files attached to this message (image/PDF) for a vision-capable model, named by the `mediaId`\n * the upload returned. Only the id is read: the url, content type and name are resolved from the\n * bound {@link AttachmentStagingStore}, so nothing a caller says decides what the model fetches.\n */\n attachments?: AttachmentRef[];\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/**\n * A store that can answer a thread's default agent on its own, without materializing the thread.\n *\n * Probed STRUCTURALLY rather than declared on `AgentStore`: the projection is an optimization a\n * store either offers or doesn't, and a store that predates it still answers correctly through\n * `getThread`. Every adapter in this repo implements it.\n */\nexport interface ThreadDefaultAgentReader {\n defaultAgentForThread(threadId: string): Promise<string | null>;\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 @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging?: AttachmentStagingStore,\n ) {}\n\n async chat(params: ChatParams): Promise<{ runId: string; threadId: string }> {\n // Precedence: explicit agentName > the thread's own defaultAgent (set via updateThread) > the\n // module's configured default. Resolved up front (before thread creation) so a brand-new thread\n // — which has no defaultAgent yet — falls straight through to the module default.\n const agentName = await this.resolveAgentName(params.agentName, params.threadId);\n // Before the thread exists, so a turn that names an attachment it may not have leaves nothing\n // behind.\n const attachments = await this.resolveAttachments(params.actor, params.attachments ?? []);\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 ...(attachments.length > 0 ? { attachments } : {}),\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 /**\n * Rebuild this turn's attachments from the staging store, keyed by the ids the caller claimed.\n * The model provider fetches {@link MessageAttachment.url} verbatim, so that url is only ever\n * allowed to come from the host's own store — a caller that could name it could point the server\n * at anything it can reach (cloud metadata, internal services) and read the response back out of\n * the model's answer.\n *\n * No store bound means no way to tell an id the actor owns from one they don't, so a turn simply\n * cannot carry attachments: 501 rather than trusting the request.\n */\n private async resolveAttachments(\n actor: Actor,\n refs: AttachmentRef[],\n ): Promise<MessageAttachment[]> {\n if (refs.length === 0) {\n return [];\n }\n const staging = this.staging;\n if (staging === undefined || typeof staging.resolve !== 'function') {\n throw new NotImplementedException(\n 'Message attachments require an AGENT_ATTACHMENT_STAGING provider implementing resolve(); ' +\n 'attachment urls are never taken from the request.',\n );\n }\n const resolved: MessageAttachment[] = [];\n for (const ref of refs) {\n const attachment = await staging.resolve({ mediaId: ref.mediaId, actor });\n if (attachment === null) {\n throw new ForbiddenException(`attachment ${ref.mediaId} is not available to this actor`);\n }\n resolved.push(attachment);\n }\n return resolved;\n }\n\n /**\n * The run's live token stream, WITHOUT an ownership check — for in-process callers that are\n * already authorized (the MCP bridge, a host's own job code), the same split as\n * {@link signalToolCall} vs {@link approve}. Anything reachable from a request must go through\n * {@link subscribeAs} instead: a runId is the only thing standing between a caller and another\n * actor's answer, tool arguments and tool results.\n */\n subscribe(runId: string): AsyncIterable<Uint8Array> {\n return this.deps.forAgent().sink.subscribe(runId);\n }\n\n /**\n * {@link subscribe}, gated the way {@link cancel} is: only the actor whose thread is currently\n * streaming this run may read it. A run that has already finished is reported missing rather than\n * replayed — the runner clears the thread's active stream as the run ends, and that field is what\n * ownership is derived from.\n */\n async subscribeAs(actor: Actor, runId: string): Promise<AsyncIterable<Uint8Array>> {\n await this.assertOwnsActiveStream(actor, runId);\n return this.subscribe(runId);\n }\n\n async approve(actor: Actor, toolCallId: string): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n return this.signalToolCall(toolCallId, { approved: true });\n }\n\n async reject(actor: Actor, toolCallId: string, reason?: string): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n return this.signalToolCall(toolCallId, {\n approved: false,\n ...(reason !== undefined ? { reason } : {}),\n });\n }\n\n /**\n * Answer a parked question set. An omitted question takes the request's own pre-picked default —\n * resolved by the LOOP against the request it already holds, so \"the user just submitted\" and\n * \"the user picked exactly the defaults\" persist as the same answers, and no client has to\n * re-send what it was shown.\n */\n async answer(\n actor: Actor,\n toolCallId: string,\n answers: Record<string, string[]> = {},\n ): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n const reply: ElicitationReply = { answers, answeredByRef: actor.id };\n return this.signalToolCall(toolCallId, reply);\n }\n\n /**\n * Decline to answer and let the agent proceed on its own assumptions. NOT the same as confirming\n * them: the run records this as a rejection, so a reader auditing what the agent was told can\n * tell a choice the user made from one they refused to make.\n */\n async skip(actor: Actor, toolCallId: string): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n const reply: ElicitationReply = { answers: {}, skipped: true, answeredByRef: actor.id };\n return this.signalToolCall(toolCallId, reply);\n }\n\n /**\n * The decision core behind approve/reject, WITHOUT an ownership check: resolves the run\n * currently awaiting `toolCallId` and signals it. `approve`/`reject` above call this after their\n * own `assertOwnsToolCall` gate; the console `AgentApprovalPort` adapter (bound by `AgentModule`)\n * calls it directly — a console caller is already authorized by the dashboard's own guards, and\n * re-deriving thread ownership here would reject a legitimate operator decision (an operator is\n * not the thread's own actor).\n */\n async signalToolCall(toolCallId: string, reply: HumanReply): Promise<void> {\n const runId = await this.resolveRunForToolCall(toolCallId);\n return this.runner.signal(runId, toolCallId, reply);\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 async listThreads(actorRef: string): Promise<ThreadSummary[]> {\n const threads = await this.store.listThreads(actorRef);\n return Promise.all(threads.map((thread) => this.toSummaryView(thread)));\n }\n\n async getThread(actor: Actor, threadId: string): Promise<ThreadDetail | null> {\n await this.assertOwnsThread(actor, threadId);\n const thread = await this.store.getThread(threadId);\n return thread === null ? null : this.toDetailView(thread);\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 /** Kept for source compatibility — a thin wrapper over the more general `updateThread`. */\n async renameThread(actor: Actor, threadId: string, title: string): Promise<void> {\n return this.updateThread(actor, threadId, { title });\n }\n\n /**\n * Rename a thread and/or set its default agent. Title-only patches work against ANY store (via\n * the required `setTitle`); a `defaultAgent` change requires the bound store to implement the\n * optional `updateThread` — 501 with a clear message when it doesn't, rather than silently\n * dropping the field.\n */\n async updateThread(actor: Actor, threadId: string, patch: UpdateThreadInput): Promise<void> {\n const title = patch.title !== undefined ? this.validateTitle(patch.title) : undefined;\n await this.assertOwnsThread(actor, threadId);\n if (patch.defaultAgent === undefined) {\n if (title !== undefined) {\n await this.store.setTitle(threadId, title);\n }\n return;\n }\n if (this.store.updateThread === undefined) {\n throw new NotImplementedException(\n \"Setting a thread's defaultAgent requires an AgentStore that implements updateThread(); \" +\n 'the bound store does not support it.',\n );\n }\n await this.store.updateThread(threadId, {\n ...(title !== undefined ? { title } : {}),\n defaultAgent: patch.defaultAgent,\n });\n }\n\n private validateTitle(title: string): string {\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 return trimmed;\n }\n\n /**\n * Agent-selection precedence for a `chat()` call with no explicit `agentName`: the thread's own\n * `defaultAgent` (if the thread exists and one is set) wins over the module's configured default.\n * Skips the store entirely when the caller already named an agent or there's no thread yet.\n *\n * What this needs is one nullable scalar, so it asks for one. `getThread` returns the entire\n * transcript — every message, every persisted tool output — and this discards all of it; on a\n * long thread with large tool results that is hundreds of kilobytes read per turn, outside the\n * workflow, for a string. A store predating {@link ThreadDefaultAgentReader} still answers, via\n * the full read.\n */\n private async resolveAgentName(\n agentName: string | undefined,\n threadId: string | undefined,\n ): Promise<string> {\n if (agentName !== undefined) {\n return agentName;\n }\n if (threadId !== undefined) {\n const threadDefault = await this.threadDefaultAgent(threadId);\n if (threadDefault !== null) {\n return threadDefault;\n }\n }\n return this.deps.defaultAgentName();\n }\n\n private async threadDefaultAgent(threadId: string): Promise<string | null> {\n const projecting = this.store as Partial<ThreadDefaultAgentReader>;\n if (typeof projecting.defaultAgentForThread === 'function') {\n return projecting.defaultAgentForThread(threadId);\n }\n return (await this.store.getThread(threadId))?.defaultAgent ?? null;\n }\n\n private async toSummaryView(thread: ThreadSummary): Promise<ThreadSummary> {\n return {\n ...thread,\n defaultAgent: thread.defaultAgent ?? null,\n activeRunId: (await this.store.activeRunForThread?.(thread.id)) ?? null,\n };\n }\n\n private async toDetailView(thread: ThreadDetail): Promise<ThreadDetail> {\n const summary = await this.toSummaryView(thread);\n return {\n ...summary,\n messages: thread.messages,\n ...(thread.activeStreamId !== undefined ? { activeStreamId: thread.activeStreamId } : {}),\n };\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 * Every file this actor has staged, newest first — across threads, including uploads that were\n * never sent, which nothing else on this surface can see.\n *\n * Metadata only. A url is minted per turn by `resolve` so it can be short-lived, and handing one\n * back per entry would undo that for the price of rendering a list.\n */\n async listAttachments(\n actor: Actor,\n options: { limit?: number } = {},\n ): Promise<StagedAttachment[]> {\n const list = this.attachmentInventory();\n return list({ actor, ...(options.limit !== undefined ? { limit: options.limit } : {}) });\n }\n\n /**\n * This actor's staged media that no live message references and that is old enough not to be an\n * upload in flight — the candidate set for a sweep. Returns them; never deletes them. The bytes\n * are the host's, and so is the decision.\n *\n * `olderThan` is required and has no default. How long a composer may sit open with a file\n * attached is the host's knowledge, and a library-chosen grace period would eventually delete a\n * file someone was about to send. The staging store is asked to apply it, and the result is\n * filtered again here: a store that ignores the hint would otherwise turn this into exactly that\n * bug, silently.\n *\n * Both halves must be answerable or this refuses. An unanswerable reference query means \"cannot\n * tell\", and treating it as \"nothing is referenced\" would hand back every attachment the actor\n * ever sent, marked safe to delete.\n */\n async collectableAttachments(\n actor: Actor,\n options: { olderThan: Date; limit?: number },\n ): Promise<StagedAttachment[]> {\n const list = this.attachmentInventory();\n const referencedMediaIds = this.store.referencedMediaIds?.bind(this.store);\n if (referencedMediaIds === undefined) {\n throw new NotImplementedException(\n 'Collecting attachments requires an AgentStore that implements referencedMediaIds(); the ' +\n 'bound store cannot say which media a message still references, and guessing would ' +\n 'delete files that are in use.',\n );\n }\n const stagedBefore = options.olderThan.toISOString();\n const inventory = await list({\n actor,\n stagedBefore,\n ...(options.limit !== undefined ? { limit: options.limit } : {}),\n });\n const aged = inventory.filter((entry) => entry.createdAt < stagedBefore);\n const referenced = new Set(\n await referencedMediaIds(\n actor.id,\n aged.map((entry) => entry.mediaId),\n ),\n );\n return aged.filter((entry) => !referenced.has(entry.mediaId));\n }\n\n /**\n * The bound staging store's `list`, or a refusal. Absence is never answered with an empty list:\n * \"this host keeps no inventory\" and \"this actor has no files\" are opposite facts that would\n * otherwise render identically — as a clean file list, and as a sweep that collects nothing.\n */\n private attachmentInventory(): (\n input: ListStagedAttachmentsInput,\n ) => Promise<StagedAttachment[]> {\n const list = this.staging?.list?.bind(this.staging);\n if (list === undefined) {\n throw new NotImplementedException(\n 'Listing attachments requires an AGENT_ATTACHMENT_STAGING provider implementing list(); ' +\n 'the host owns the staged bytes, so only it can enumerate them.',\n );\n }\n return list;\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 seam for HITL approve/reject: the caller must own the tool call's thread. Split\n * out from run resolution (see {@link resolveRunForToolCall}) so the console `AgentApprovalPort`\n * adapter can resolve+signal a decision WITHOUT this check — it is authorized upstream instead.\n */\n private async assertOwnsToolCall(actor: Actor, toolCallId: string): Promise<void> {\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 }\n\n /**\n * Resolve the run awaiting `toolCallId`. Derived server-side from the tool call alone — the client\n * never knows or supplies a runId, and that run is the sub-agent's own child run when the pending\n * call belongs to a delegated agent. The store answers from the CALL'S OWN `runId` where it has\n * one; see `AgentStore.runForToolCall` for why that matters once a thread can hold more than one\n * live run.\n */\n private async resolveRunForToolCall(toolCallId: string): Promise<string> {\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 AgentIntake,\n AgentPricingStore,\n AgentStore,\n HistoryPolicy,\n InputProcessor,\n MemoryConfig,\n ModelProvider,\n OutputProcessor,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n SkillsConfig,\n TokenStreamSink,\n ToolRegistry,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n 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 /** Nesting ceiling for delegation below this agent. Undefined → the loop's default. */\n maxDelegationDepth?: number;\n /** How many times one agent may appear on a chain. Undefined → the loop's default. */\n maxAgentAppearances?: number;\n /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\n /**\n * Transient-tool-error retry policy (from module options). Undefined → default ON\n * (`{ attempts: 2, backoffMs: 150 }` with the default classifier); `false` → disabled.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /** How many follow-up suggestions to generate after the final turn. Undefined/0 → off. */\n followUpsCount?: number;\n /** Inject-mode retriever (from `forRoot({ retrieval })`). Undefined → no prompt augmentation. */\n retriever?: Retriever;\n /** Passages inject-mode retrieval requests. Undefined → loop default (5). */\n retrievalTopK?: number;\n /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */\n pricingStore?: AgentPricingStore;\n /** The agent's history ceiling, resolved from `@Agent({ history })` / module options. Undefined → unbounded. */\n historyPolicy?: HistoryPolicy;\n /** Module-wide prompt rewriters, applied before every model call. Empty → none. */\n inputProcessors: InputProcessor[];\n /** Module-wide answer gates. NON-EMPTY MEANS THE TURN'S MODEL OUTPUT IS BUFFERED, not streamed. */\n outputProcessors: OutputProcessor[];\n /** The agent's `@Agent({ outputSchema })`, resolved from DI — never over the wire. Undefined → free text. */\n outputSchema?: StandardSchemaV1;\n /** Extra model calls allowed to repair an answer that failed `outputSchema`. Undefined → 1. */\n outputRepairAttempts?: number;\n /** The agent's `@Agent({ intake })` question set, asked before the turn starts. Undefined → none. */\n intake?: AgentIntake;\n /** Whether the model may call the built-in `ask` tool this turn. Undefined/false → it never sees it. */\n ask?: boolean;\n /**\n * The resolved skills seam (`forRoot({ skills })` + discovered `@Skill` providers). Undefined →\n * no catalog, no `skill` tool, and the turn spends no checkpoint on either.\n */\n skills?: SkillsConfig;\n /**\n * The resolved memory seam (`forRoot({ memory })`). Undefined → no block, no `remember` tool, and\n * the turn spends no checkpoint on either.\n */\n memory?: MemoryConfig;\n}\n\nexport function utcDay(date = new Date()): string {\n return date.toISOString().slice(0, 10);\n}\n\n/**\n * Wraps a parent run's sink writer for a sub-agent: `write` forwards (so the sub-agent's tokens and\n * pending action-tool frames reach the human's live stream), but `end` / `fail` are swallowed — the\n * top-level run owns the stream's lifecycle, so a finished/failed child must not close or error the\n * shared stream out from under the parent that is still running.\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 type { AgentApprovalPort } from '@dudousxd/nestjs-agent-core';\nimport { Injectable } from '@nestjs/common';\nimport { AgentService } from './agent.service.js';\n\n/**\n * Binds `AGENT_APPROVAL_PORT` for the console's cross-thread approvals inbox to the SAME decision\n * path chat approvals use — `AgentService.signalToolCall` (resolve the run awaiting `toolCallId`,\n * then `AgentRunner.signal`, which is either the inline pending-promise map or the durable signal\n * `tool:<runId>:<callId>`, depending on how the host configured `AgentModule`).\n *\n * Deliberately WITHOUT `AgentService.approve`/`reject`'s ownership check: a console caller reaches\n * this port only through the dashboard's own guards (already authorized), not as the thread's own\n * actor — re-deriving \"does this actor own the thread\" here would reject a legitimate operator\n * decision. `opts.executedByRef` is an OPAQUE decider ref, not re-authorized against anything: it\n * rides the `Decision` and the loop records it as the tool call's decider\n * (`decision.executedByRef ?? input.actor.id`, on both the executed and rejected paths).\n */\n@Injectable()\nexport class AgentApprovalPortAdapter implements AgentApprovalPort {\n constructor(private readonly agent: AgentService) {}\n\n async approve(toolCallId: string, opts?: { executedByRef?: string }): Promise<void> {\n await this.agent.signalToolCall(toolCallId, {\n approved: true,\n ...(opts?.executedByRef !== undefined ? { executedByRef: opts.executedByRef } : {}),\n });\n }\n\n async reject(\n toolCallId: string,\n opts?: { executedByRef?: string; reason?: string },\n ): Promise<void> {\n await this.agent.signalToolCall(toolCallId, {\n approved: false,\n ...(opts?.executedByRef !== undefined ? { executedByRef: opts.executedByRef } : {}),\n ...(opts?.reason !== undefined ? { reason: opts.reason } : {}),\n });\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_REGISTRY,\n type AgentCatalogEntry,\n AgentRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\n\n/** Lists the registered `@Agent`s so a host can render a persona picker instead of hardcoding one. */\n@Controller('agents')\nexport class AgentsController {\n constructor(\n @Inject(AGENT_REGISTRY) private readonly agents: AgentRegistry,\n @Inject(AGENT_DEPS_FACTORY) private readonly depsFactory: AgentDepsFactory,\n ) {}\n\n @Get()\n list(): AgentCatalogEntry[] {\n const defaultAgentName = this.depsFactory.defaultAgentName();\n return this.agents.list().map((definition) => ({\n name: definition.name,\n description: definition.description ?? '',\n ...(definition.name === defaultAgentName ? { isDefault: true } : {}),\n }));\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_ATTACHMENT_STAGING,\n AGENT_OPTIONS,\n type ActorResolver,\n type AttachmentStagingStore,\n type MessageAttachment,\n type StagedAttachment,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Controller,\n Get,\n Inject,\n NotImplementedException,\n type OnModuleInit,\n Optional,\n PayloadTooLargeException,\n Post,\n Req,\n UnsupportedMediaTypeException,\n UploadedFile,\n UseInterceptors,\n} from '@nestjs/common';\nimport { FileInterceptor } from '@nestjs/platform-express';\nimport type { Request } from 'express';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { AgentService } from '../agent.service.js';\n\n/** Default per-file size cap when `AgentModuleOptions.attachments.maxBytes` is omitted (20 MiB). */\nexport const DEFAULT_MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024;\n\n/**\n * The most this route will ever read into memory, enforced by multer while the body streams (32\n * MiB — above the default cap, and above what any mainstream multimodal provider accepts as a\n * single file part). `attachments.maxBytes` is per-instance config and so cannot be known when the\n * interceptor is declared; it narrows this ceiling at request time but can never raise it.\n */\nexport const HARD_MAX_ATTACHMENT_BYTES = 32 * 1024 * 1024;\n\n/**\n * How many entries `GET /agent/attachments` returns. Fixed rather than caller-supplied: this route\n * exists so a composer can show the files someone has uploaded, and a host that needs real paging\n * over a large inventory has `AgentService.listAttachments` and its own store's `list` to page with.\n */\nexport const ATTACHMENT_PAGE_SIZE = 50;\n\n/**\n * Default allowlist: what multimodal model providers commonly accept as native image/file parts.\n */\nexport const DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES: readonly string[] = [\n 'image/png',\n 'image/jpeg',\n 'image/gif',\n 'image/webp',\n 'application/pdf',\n 'text/plain',\n 'text/csv',\n];\n\n/**\n * Optional `POST /agent/attachments` upload surface — mounted only when `AgentModuleOptions\n * .attachments.upload` (or the async config's `attachmentsUpload`) is `true` (see `agent.module.ts`).\n * Multipart single file field `'file'`, buffered in memory (no disk write — `FileInterceptor`'s\n * default storage) up to {@link HARD_MAX_ATTACHMENT_BYTES}, then validated against the configured\n * size cap + content-type allowlist and handed to the bound {@link AttachmentStagingStore} to\n * persist and turn into a model-fetchable URL. Both size gates answer `413`: the ceiling aborts the\n * upload mid-stream, the configured cap rejects what was read.\n *\n * `GET /agent/attachments` rides the same flag and returns the caller's own staged files as\n * metadata. Collection is NOT a route: a sweep needs a host-chosen age threshold and ends in the\n * host deleting bytes, so it stays an in-process call (`AgentService.collectableAttachments`)\n * rather than something reachable with a session cookie.\n */\n@Controller('attachments')\nexport class AttachmentsController implements OnModuleInit {\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n private readonly agents: AgentService,\n @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging: AttachmentStagingStore | undefined,\n ) {}\n\n /**\n * `attachments.upload: true` is what mounts this controller at all (see `agent.module.ts`), so by\n * the time an instance exists the host clearly intends uploads to work. Fail boot loudly rather\n * than mounting a controller that would 501 on every single request because nobody bound\n * `AGENT_ATTACHMENT_STAGING`.\n */\n onModuleInit(): void {\n if (this.options.attachments?.upload === true && this.staging === undefined) {\n throw new Error(\n 'AgentModule: attachments.upload is true but no AGENT_ATTACHMENT_STAGING provider is bound. ' +\n 'Bind one (e.g. `{ provide: AGENT_ATTACHMENT_STAGING, useClass: MyStagingStore }`) in a ' +\n 'module imported alongside AgentModule, or set attachments.upload to false.',\n );\n }\n }\n\n /**\n * The caller's own staged files, newest first — the one question `GET /agent/threads/:id` cannot\n * answer, since an upload that was never sent belongs to no thread.\n *\n * Scoped by the RESOLVED actor and nothing else. There is deliberately no `threadId` filter: a\n * thread's attachments already ride on its messages in the thread payload, and re-serving them\n * from here would add a second ownership path to get wrong for information the client already\n * holds. Metadata only — see {@link StagedAttachment}.\n */\n @Get()\n async list(@Req() req: Request): Promise<StagedAttachment[]> {\n const actor = await this.actorResolver.resolve(req);\n return this.agents.listAttachments(actor, { limit: ATTACHMENT_PAGE_SIZE });\n }\n\n @Post()\n @UseInterceptors(FileInterceptor('file', { limits: { fileSize: HARD_MAX_ATTACHMENT_BYTES } }))\n async upload(\n @Req() req: Request,\n @UploadedFile() file: Express.Multer.File | undefined,\n ): Promise<MessageAttachment> {\n if (this.staging === undefined) {\n // Reachable only if the module was built with attachments.upload left false/omitted while\n // this controller was somehow still wired up by hand — the normal boot path prevents this via\n // onModuleInit above. Kept as defense in depth with a precise status instead of a stack trace.\n throw new NotImplementedException('Attachment upload is not configured on this server.');\n }\n if (file === undefined) {\n throw new BadRequestException('multipart field \"file\" is required');\n }\n const allowedContentTypes =\n this.options.attachments?.allowedContentTypes ?? DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES;\n if (!allowedContentTypes.includes(file.mimetype)) {\n throw new UnsupportedMediaTypeException(\n `content type \"${file.mimetype}\" is not allowed (allowed: ${allowedContentTypes.join(', ')})`,\n );\n }\n const maxBytes = this.options.attachments?.maxBytes ?? DEFAULT_MAX_ATTACHMENT_BYTES;\n if (file.size > maxBytes) {\n throw new PayloadTooLargeException(`file exceeds the ${maxBytes}-byte limit`);\n }\n const actor = await this.actorResolver.resolve(req);\n return this.staging.stage({\n data: file.buffer,\n filename: file.originalname,\n contentType: file.mimetype,\n sizeBytes: file.size,\n actor,\n });\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n AgentStreamError,\n type AttachmentRef,\n type PageContext,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Body,\n Controller,\n Get,\n Inject,\n Param,\n Post,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n/**\n * How many attachments one turn may name. Each costs a staging-store read before the run starts,\n * and no model provider accepts anywhere near this many parts in a single message.\n */\nexport const MAX_ATTACHMENTS_PER_MESSAGE = 10;\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 /**\n * Files attached to this message (image/PDF), named by the `mediaId` `POST /agent/attachments`\n * (or the host's own upload) returned. Any other field sent alongside it is ignored.\n */\n attachments?: unknown;\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/**\n * Reduce whatever the body sent to the ids alone. A client cannot describe an attachment, only\n * point at one it staged: the url the model provider will fetch is resolved server-side from the\n * id (see `AgentService.chat`), so anything else here would be an SSRF the caller writes.\n */\nfunction attachmentRefs(claimed: unknown): AttachmentRef[] {\n if (claimed === undefined) {\n return [];\n }\n if (!Array.isArray(claimed)) {\n throw new BadRequestException('attachments must be an array of { mediaId }');\n }\n if (claimed.length > MAX_ATTACHMENTS_PER_MESSAGE) {\n throw new BadRequestException(\n `a message may carry at most ${MAX_ATTACHMENTS_PER_MESSAGE} attachments`,\n );\n }\n return claimed.map((entry: unknown) => {\n if (typeof entry !== 'object' || entry === null || !('mediaId' in entry)) {\n throw new BadRequestException('each attachment must be an object with a mediaId');\n }\n const { mediaId } = entry as { mediaId: unknown };\n if (typeof mediaId !== 'string' || mediaId.length === 0) {\n throw new BadRequestException('each attachment must carry a non-empty string mediaId');\n }\n return { mediaId };\n });\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 attachments = attachmentRefs(body.attachments);\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 ...(attachments.length > 0 ? { attachments } : {}),\n ...(body.pageContext !== undefined ? { pageContext: body.pageContext } : {}),\n ...(body.regenerate === true ? { regenerate: true } : {}),\n ...(body.transient === true ? { transient: true } : {}),\n });\n // The run was just started for this actor, so no ownership read is needed — and one would race\n // the run itself, which clears the thread's active stream (what ownership is derived from) the\n // moment it finishes.\n await this.pipe(res, runId, this.agent.subscribe(runId), threadId);\n }\n\n @Get('chat/:runId/stream')\n async stream(\n @Req() req: Request,\n @Param('runId') runId: string,\n @Res() res: Response,\n ): Promise<void> {\n const actor = await this.actorResolver.resolve(req);\n await this.pipe(res, runId, await this.agent.subscribeAs(actor, 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(\n res: Response,\n runId: string,\n events: AsyncIterable<Uint8Array>,\n threadId?: string,\n ): 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 // The sink now carries NDJSON `AgentStreamEvent`s (one `{...}\\n` per write). Forward each line\n // as an SSE `data:` frame verbatim — the client transport maps them to the AI SDK UI-message\n // chunk protocol. Buffer across chunk boundaries in case a transport batches multiple writes.\n const decoder = new TextDecoder();\n let buffer = '';\n try {\n for await (const chunk of events) {\n buffer += decoder.decode(chunk, { stream: true });\n let newline = buffer.indexOf('\\n');\n while (newline !== -1) {\n const line = buffer.slice(0, newline);\n buffer = buffer.slice(newline + 1);\n if (line.length > 0) {\n res.write(`data: ${line}\\n\\n`);\n }\n newline = buffer.indexOf('\\n');\n }\n }\n if (buffer.length > 0) {\n res.write(`data: ${buffer}\\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 {\n AGENT_ACTOR_RESOLVER,\n AGENT_MEMORY,\n type ActorResolver,\n type MemoryConfig,\n type MemoryDigestEntry,\n memoryForgetVerdict,\n offerMemories,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n Controller,\n Delete,\n ForbiddenException,\n Get,\n Inject,\n NotFoundException,\n Optional,\n Param,\n Query,\n Req,\n} from '@nestjs/common';\nimport type { Request } from 'express';\n\n/**\n * What the assistant believes about THIS caller — and how they take one of those beliefs back.\n *\n * WHY THIS EXISTS WHERE `GET /agent/skills` HAS NO WRITE SIBLING. A skill is authored by a person\n * who already knows it exists; a memory is written by the agent, about someone who does not. So the\n * read-back is not a convenience on top of the feature, it IS half of the feature: a belief nobody\n * can inspect is one nobody can correct, and a belief nobody can delete is one the deployment keeps\n * whether or not it is true. That is also why `MemoryProvider.forget` is required rather than\n * optional — see `memory.ts`.\n */\n@Controller('memories')\nexport class MemoriesController {\n constructor(\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n // Optional: bound to `undefined` when the host configured no memory, which is a valid wiring\n // rather than a missing dependency — the endpoints then answer with an empty list.\n @Optional() @Inject(AGENT_MEMORY) private readonly memory: MemoryConfig | undefined,\n ) {}\n\n /**\n * Every memory this actor can reach, most specific first, each carrying its origin and whatever\n * wider value it outranks.\n *\n * DELIBERATELY IGNORES `maxMemories`. That ceiling is a budget on what one TURN carries; applying\n * it here would mean a person could not see — and so could not delete — a belief the assistant is\n * one write away from acting on again. Showing someone more than the model sees is harmless;\n * showing them less is the failure this endpoint exists to prevent.\n */\n @Get()\n async list(\n @Req() req: Request,\n /** Only ever handed to the host's own resolver and provider; nothing here reads the thread. */\n @Query('threadId') threadId?: string,\n ): Promise<MemoryDigestEntry[]> {\n if (this.memory === undefined) {\n return [];\n }\n const actor = await this.actorResolver.resolve(req);\n return (await this.unbounded(threadId ?? '', actor)).entries;\n }\n\n /**\n * Forget one. Authorized against the actor's OWN resolved list, the same way a `skill` load is\n * authorized against the turn's catalog: an id this actor cannot see is answered as missing rather\n * than refused, so the endpoint cannot be used to find out which memories exist about other people.\n */\n @Delete(':id')\n async forget(@Req() req: Request, @Param('id') id: string): Promise<{ forgotten: boolean }> {\n if (this.memory === undefined) {\n throw new NotFoundException('No memory is configured in this deployment.');\n }\n const actor = await this.actorResolver.resolve(req);\n const digest = await this.unbounded('', actor);\n const entry = digest.entries.find((candidate) => candidate.id === id);\n if (entry === undefined) {\n throw new NotFoundException(`No memory with id \"${id}\".`);\n }\n const verdict = memoryForgetVerdict({ record: entry, actor });\n if (!verdict.allowed) {\n throw new ForbiddenException(verdict.reason);\n }\n return {\n forgotten: await this.memory.provider.forget({ id: entry.id, ctx: { actor, threadId: '' } }),\n };\n }\n\n private async unbounded(threadId: string, actor: Awaited<ReturnType<ActorResolver['resolve']>>) {\n // biome-ignore lint/style/noNonNullAssertion: every caller checks `memory` first.\n const config = this.memory!;\n return await offerMemories({\n config: { ...config, maxMemories: Number.POSITIVE_INFINITY },\n ctx: { actor, threadId },\n });\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 {\n AGENT_ACTOR_RESOLVER,\n AGENT_SKILLS,\n type ActorResolver,\n type SkillCatalogEntry,\n type SkillsConfig,\n offerSkills,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Optional, Query, Req } from '@nestjs/common';\nimport type { Request } from 'express';\n\n/**\n * Lists the skills available to THIS caller right now, scope-resolved — so a composer can offer them\n * after a `/` instead of hardcoding a list, and a settings screen can show which scope each came\n * from.\n *\n * THE SAME LIST THE MODEL IS OFFERED, built by the same call (`offerSkills`) against the same\n * provider and the same resolver. A second implementation of \"which skills apply\" would drift the\n * first time either was edited, and the drift would read to a user as a skill they can invoke that\n * the agent then says it has never heard of.\n *\n * Ownership posture mirrors `GET /agent/agents`: a plain array, no envelope, and nothing the caller\n * can pass to widen it — the actor comes from the resolver, never from a parameter.\n */\n@Controller('skills')\nexport class SkillsController {\n constructor(\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n // Optional: bound to `undefined` when the host configured no skills, which is a valid wiring\n // rather than a missing dependency — the endpoint then answers with an empty list.\n @Optional() @Inject(AGENT_SKILLS) private readonly skills: SkillsConfig | undefined,\n ) {}\n\n @Get()\n async list(\n @Req() req: Request,\n /**\n * The thread this list is for. Only ever handed to the host's own resolver and provider, which\n * may scope a skill to a conversation; nothing here reads the thread, so an unknown id widens\n * nothing. Omitted → the empty string, the same value a turn on a brand-new thread carries.\n */\n @Query('threadId') threadId?: string,\n ): Promise<SkillCatalogEntry[]> {\n if (this.skills === undefined) {\n return [];\n }\n const actor = await this.actorResolver.resolve(req);\n const offer = await offerSkills(this.skills, { actor, threadId: threadId ?? '' });\n return offer.entries;\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 UpdateThreadBody {\n title?: string;\n /** `null` clears the thread's default agent. Omitted → left untouched. */\n defaultAgent?: string | null;\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 /**\n * Renames the thread and/or sets its default agent. `defaultAgent` is only present in the request\n * body when the client actually sent the key (JSON has no `undefined`), so `'defaultAgent' in body`\n * distinguishes \"leave it alone\" from \"set it to null\" (clear it) unambiguously.\n */\n @Patch(':id')\n async update(\n @Req() req: Request,\n @Param('id') id: string,\n @Body() body: UpdateThreadBody,\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.updateThread(actor, id, {\n ...(body.title !== undefined ? { title: body.title } : {}),\n ...('defaultAgent' in body ? { defaultAgent: body.defaultAgent ?? null } : {}),\n });\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 { BadRequestException, Body, Controller, Inject, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n/**\n * Bounds on a human reply. A reply is journaled and re-read on every replay of the run it settles,\n * so a payload the loop cannot read is not a failed request — it is a run that fails identically\n * forever, burning its retries. Nothing here is signalled until it has been checked.\n */\nconst MAX_ANSWERED_QUESTIONS = 100;\nconst MAX_VALUES_PER_QUESTION = 100;\nconst MAX_ANSWER_VALUE_LENGTH = 4096;\n/** A rejection reason is read back by the model as the tool's result, so it is prompt input. */\nconst MAX_REJECT_REASON_LENGTH = 4096;\n\ninterface ApproveBody {\n toolCallId: unknown;\n}\ninterface RejectBody extends ApproveBody {\n reason?: unknown;\n}\ninterface AnswerBody extends ApproveBody {\n /**\n * questionId → chosen option values. Omit a question (or the whole object) to take the pre-picked\n * default the request was shown with — confirming is meant to be enough, so an empty body is a\n * valid submission rather than an error.\n */\n answers?: unknown;\n}\n\nfunction toolCallId(claimed: unknown): string {\n if (typeof claimed !== 'string' || claimed.length === 0) {\n throw new BadRequestException('toolCallId must be a non-empty string');\n }\n return claimed;\n}\n\nfunction rejectReason(claimed: unknown): string | undefined {\n if (claimed === undefined) {\n return undefined;\n }\n if (typeof claimed !== 'string') {\n throw new BadRequestException('reason must be a string');\n }\n if (claimed.length > MAX_REJECT_REASON_LENGTH) {\n throw new BadRequestException(`reason must be at most ${MAX_REJECT_REASON_LENGTH} characters`);\n }\n return claimed;\n}\n\nfunction answers(claimed: unknown): Record<string, string[]> | undefined {\n if (claimed === undefined) {\n return undefined;\n }\n if (typeof claimed !== 'object' || claimed === null || Array.isArray(claimed)) {\n throw new BadRequestException('answers must be an object of questionId → chosen values');\n }\n const entries = Object.entries(claimed);\n if (entries.length > MAX_ANSWERED_QUESTIONS) {\n throw new BadRequestException(`answers may cover at most ${MAX_ANSWERED_QUESTIONS} questions`);\n }\n // Null-prototype accumulator: a JSON body's own `__proto__` key would otherwise reach\n // Object.prototype's setter and silently drop the answer instead of carrying it.\n const validated: Record<string, string[]> = Object.create(null);\n for (const [questionId, values] of entries) {\n if (!Array.isArray(values)) {\n throw new BadRequestException(`answers[\"${questionId}\"] must be an array of chosen values`);\n }\n if (values.length > MAX_VALUES_PER_QUESTION) {\n throw new BadRequestException(\n `answers[\"${questionId}\"] may carry at most ${MAX_VALUES_PER_QUESTION} values`,\n );\n }\n for (const value of values) {\n if (typeof value !== 'string') {\n throw new BadRequestException(`answers[\"${questionId}\"] must contain only strings`);\n }\n if (value.length > MAX_ANSWER_VALUE_LENGTH) {\n throw new BadRequestException(\n `answers[\"${questionId}\"] values must be at most ${MAX_ANSWER_VALUE_LENGTH} characters`,\n );\n }\n }\n validated[questionId] = values as string[];\n }\n return validated;\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, toolCallId(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, toolCallId(body.toolCallId), rejectReason(body.reason));\n return { ok: true };\n }\n\n /**\n * Settle a parked question set. Alongside `approve`/`reject` rather than under a surface of its\n * own: an elicitation IS a parked tool call, gated by the same ownership check and delivered\n * through the same signal.\n */\n @Post('answer')\n async answer(@Req() req: Request, @Body() body: AnswerBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers));\n return { ok: true };\n }\n\n /** Decline to answer and let the agent proceed on the answers it pre-picked. */\n @Post('skip')\n async skip(@Req() req: Request, @Body() body: ApproveBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.skip(actor, toolCallId(body.toolCallId));\n return { ok: true };\n }\n}\n","import {\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_REGISTRY,\n type AgentDefinition,\n type AgentDelegation,\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 ...(meta.description !== undefined ? { description: meta.description } : {}),\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.maxDelegationDepth !== undefined\n ? { maxDelegationDepth: meta.maxDelegationDepth }\n : {}),\n ...(meta.maxAgentAppearances !== undefined\n ? { maxAgentAppearances: meta.maxAgentAppearances }\n : {}),\n ...(meta.history !== undefined ? { history: meta.history } : {}),\n ...(meta.outputSchema !== undefined ? { outputSchema: meta.outputSchema } : {}),\n ...(meta.intake !== undefined ? { intake: meta.intake } : {}),\n ...(meta.ask !== undefined ? { ask: meta.ask } : {}),\n ...(meta.outputRepairAttempts !== undefined\n ? { outputRepairAttempts: meta.outputRepairAttempts }\n : {}),\n ...(meta.handoff !== undefined ? { delegatesTo: this.handoffEdges(meta) } : {}),\n };\n }\n\n /**\n * Resolve each handoff entry to an {@link AgentDelegation} — its target's registered name, plus\n * whether that edge detaches (skipping non-agent classes). A bare name is kept for a plain edge\n * rather than an always-object form, so a definition an older host built by hand still reads.\n */\n private handoffEdges(meta: AgentOptions): AgentDelegation[] {\n const edges: AgentDelegation[] = [];\n for (const entry of meta.handoff ?? []) {\n const target = typeof entry === 'function' ? entry : entry.agent;\n const detached = typeof entry === 'function' ? false : entry.detached === true;\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 edges.push(detached ? { agent: targetMeta.name, detached: true } : targetMeta.name);\n }\n return edges;\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 { AgentHistoryWindow, AgentIntake } from '@dudousxd/nestjs-agent-core';\nimport type { Type } from '@nestjs/common';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\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 /**\n * How deep delegation may nest below this agent before further hops are refused. Default 5.\n *\n * Not a budget for how MANY agents a turn delegates to — that is the model's, one tool call each,\n * and nothing caps it. This bounds the chain a `delegatesTo` cycle would otherwise run forever.\n */\n maxDelegationDepth?: number;\n /**\n * How many times one agent may appear on a single delegation chain below this one. Default 1.\n *\n * This is the exact form of what {@link maxDelegationDepth} approximates: the loop compares a\n * delegation target against the chain that reached it, so a repeat is a cycle by inspection.\n * It counts APPEARANCES, so 2 admits exactly one deliberate return to an earlier agent.\n */\n maxAgentAppearances?: number;\n /** Allow-list of global tool names this agent may use. Omit → every tool its role allows. */\n tools?: string[];\n /**\n * Other `@Agent` classes this agent may hand off to (auto-exposed as handoff tools). A bare class\n * is the delegation that has always existed: this agent's turn waits for the answer.\n *\n * `{ agent, detached: true }` is the other shape — the delegate is STARTED and this agent's turn\n * ends without its answer, which arrives in the conversation later as its own message. Declared\n * per edge, by the author, and never by the model: the same worker is worth waiting for in one\n * orchestrator and worth backgrounding in another, and only the person wiring the edge knows\n * which side of that the user is sitting on.\n */\n handoff?: (Type | { agent: Type; detached?: boolean })[];\n /**\n * How much of the thread this agent's turns carry, overriding `AgentModule.forRoot({ history })`.\n * `{ maxMessages }` and/or `{ maxTokens }` keep the newest that fit; `{ summarize: true }` folds\n * the rest into a leading summary, at one extra model call per run. Omit → the module-wide\n * ceiling, or none.\n */\n history?: AgentHistoryWindow;\n /**\n * Constrain this agent's final answer to a schema (any [Standard Schema](https://standardschema.dev)\n * — Zod, Valibot, ArkType). The turn calls its tools exactly as it would without one; the schema is\n * satisfied by one extra formatting call afterwards, so it works on providers that refuse a\n * response format and a tool set in the same request. The validated value comes back as `object`\n * on the run's result and is recorded on the assistant message as a `structured_output` tool call.\n *\n * Declared HERE rather than per request: a schema is a live object, and `AgentRunInput` crosses a\n * JSON boundary on its way into a durable workflow.\n */\n outputSchema?: StandardSchemaV1;\n /**\n * Extra model calls allowed to fix an answer that failed {@link outputSchema}, each shown the\n * previous attempt's validation issues. Omit → 1; `0` → fail on the first invalid reply with a\n * `StructuredOutputError`.\n */\n outputRepairAttempts?: number;\n /**\n * Questions this agent puts to the user BEFORE it starts working — the scope it needs, collected\n * up front rather than guessed. Authored here, so the turn spends no model call producing them\n * and a client knows the total (\"Question 1 of 3\") the moment the form appears. Every question\n * should pre-pick a default: the claim the surface makes is that confirming is enough.\n *\n * `when: 'thread-start'` (the default) asks once per thread; `'every-turn'` asks before each turn.\n * Omit → no intake.\n */\n intake?: AgentIntake;\n /**\n * Let the model ask its OWN clarifying question set, via the built-in `ask` tool, when it judges\n * the scope is missing. Overrides `AgentModule.forRoot({ ask })` for this agent. Omit → the\n * module-wide setting.\n */\n ask?: boolean;\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 Actor,\n type AgentRegistry,\n type ToolHandler,\n type ToolRegistry,\n normalizeDelegation,\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 ...(meta.enabled !== undefined ? { enabled: meta.enabled } : {}),\n },\n {\n execute: (input, ctx) => (instance as ToolHandler).execute(input, ctx),\n // Forwarded, not copied: the registry holds this wrapper rather than the provider, so an\n // `isEnabled()`/`canUse()` left behind here would be a gate that silently never applies.\n // Called through `instance` so each keeps its `this` (and its injected deps).\n ...(typeof handler.isEnabled === 'function'\n ? { isEnabled: () => (instance as Required<ToolHandler>).isEnabled() }\n : {}),\n ...(typeof handler.canUse === 'function'\n ? { canUse: (actor: Actor) => (instance as Required<ToolHandler>).canUse(actor) }\n : {}),\n },\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 edge of definition.delegatesTo ?? []) {\n const { agent: target, detached } = normalizeDelegation(edge);\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, detached });\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 // A detached edge's description is the model's only warning that this call hands back a\n // receipt: a tool advertised as returning an answer, which then returns something else, is\n // a model that reports an answer it was never given.\n const description = detached\n ? `Start the \"${target}\" agent working on a task in the BACKGROUND. Returns immediately with a receipt, NOT an answer — the answer is delivered to this conversation as a separate message later. Use it for work the user does not need to sit and wait for.${targetBlurb}`\n : `Delegate a task to the \"${target}\" agent and get its answer.${targetBlurb}`;\n this.registry.register(\n {\n name,\n kind: 'agent',\n targetAgent: target,\n ...(detached ? { detached: true } : {}),\n description,\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 * Whether this tool exists in this deployment. `false` — or a predicate returning `false`, which\n * is re-evaluated every turn — drops it before the role filter, so the model is never shown it.\n * Omit → enabled.\n *\n * Use this for availability that is knowable without DI (a constant, `process.env`, a closure\n * over something the app already holds). When the answer lives in an injected service, implement\n * `isEnabled()` on the class instead: this object is built while the decorator is evaluated, at\n * import time, and can't reach the container.\n */\n enabled?: boolean | (() => boolean | Promise<boolean>);\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 *\n * A tool the deployment can turn off — the flag read through DI, so `.env` and a config service\n * both work:\n *\n * ```ts\n * @AiTool({ name: 'searchDocs', kind: 'read', description: '...', input: schema })\n * class SearchDocsTool implements ToolHandler<Input> {\n * constructor(private readonly config: ConfigService) {}\n * isEnabled() { return this.config.get('DOCS_SEARCH_ENABLED') === 'true'; }\n * async execute(input, ctx) { ... }\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 { AGENT_SKILL_SOURCES, type SkillContext } from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, type OnModuleInit } from '@nestjs/common';\nimport { DiscoveryService } from '@nestjs/core';\nimport { readSkillMetadata, skillScope } from '../decorator/skill.decorator.js';\n\n/**\n * One `@Skill`-decorated provider, reduced to what a `SkillProvider` needs: its catalog line, and a\n * bound function that produces its body for a turn.\n */\nexport interface DeclaredSkill {\n name: string;\n description: string;\n scope: string;\n body(ctx: SkillContext): string | Promise<string>;\n}\n\n/**\n * Collects every `@Skill`-decorated provider into the shared list the module's skill provider reads\n * — the discovery counterpart to authoring skills as rows in the host's own table. Both sources feed\n * one catalog; see `AgentModuleOptions.skills`.\n *\n * A class with neither a flat `body` nor a `body()` method is skipped with a warning rather than\n * offered: a skill the model can see and load, that then returns nothing, reads to it as an\n * instruction to do nothing in particular — which is worse than the skill not existing.\n */\n@Injectable()\nexport class SkillDiscoveryService implements OnModuleInit {\n private readonly logger = new Logger(SkillDiscoveryService.name);\n\n constructor(\n private readonly discovery: DiscoveryService,\n @Inject(AGENT_SKILL_SOURCES) private readonly declared: DeclaredSkill[],\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 = readSkillMetadata(instance.constructor);\n if (meta === undefined) {\n continue;\n }\n const body = this.bodyOf(instance, meta.body);\n if (body === undefined) {\n this.logger.warn(\n `Skill \"${meta.name}\" declares no body — add a \\`body()\\` method or \\`@Skill({ body })\\`. Skipped.`,\n );\n continue;\n }\n this.declared.push({\n name: meta.name,\n description: meta.description,\n scope: skillScope(meta),\n body,\n });\n }\n }\n\n /** The instance's `body()` method (bound), else the flat string, else nothing to offer. */\n private bodyOf(\n instance: object,\n flat: string | undefined,\n ): ((ctx: SkillContext) => string | Promise<string>) | undefined {\n const candidate = (instance as { body?: unknown }).body;\n if (typeof candidate === 'function') {\n return (ctx: SkillContext) =>\n (candidate as (ctx: SkillContext) => string | Promise<string>).call(instance, ctx);\n }\n return flat === undefined ? undefined : () => flat;\n }\n}\n","import 'reflect-metadata';\nimport { GLOBAL_SCOPE, type SkillContext } from '@dudousxd/nestjs-agent-core';\nimport type { Type } from '@nestjs/common';\n\n/**\n * Declares a provider class as a skill: an authored procedure any agent may pull in when a task\n * calls for it. Discovered at boot and offered to every turn whose scopes include its `scope`.\n *\n * NOT AN AGENT. An `@Agent` is who is answering — its model, its tools, its history ceiling. A skill\n * is how one task is done, and carries none of those: what it contributes is text, at a scope, under\n * a name the model can ask for. An instruction that should apply to EVERY turn of an agent is that\n * agent's `systemPrompt` (or a `@SystemPromptContributor()`), not a skill — a skill is for the ones\n * that should apply only when the work calls for them, which is what stops them costing a prompt.\n *\n * The class is an ordinary provider, so it gets constructor DI — the reason a skill is a class and\n * not a config entry. The body is either the flat `body` string here or a `body(ctx)` method on the\n * class (which may read the turn's {@link SkillContext} and inject services); implement\n * {@link SkillBody} to have the compiler hold you to its shape.\n */\nexport interface SkillOptions {\n /** Unique within its scope. What the model passes to the `skill` tool, and the `/` handle a UI offers. */\n name: string;\n /**\n * One line: what task this covers. Read by the MODEL to decide whether to load it, and by a person\n * choosing from an autocomplete — so write what it is FOR, not what it contains.\n */\n description: string;\n /**\n * The scope token this skill is published at. Omit → `'global'`, the deployment-wide default. Any\n * string a host's `ScopeResolver` can return works: `'tenant:berlin'`, `'sector:logistics'`.\n */\n scope?: string;\n /** A flat body. For one built per actor or per page, add a `body()` method instead. */\n body?: string;\n}\n\n/** The shape a `@Skill` class's body method takes. Implement it to be held to it at compile time. */\nexport interface SkillBody {\n body(ctx: SkillContext): string | Promise<string>;\n}\n\nexport const SKILL_METADATA = Symbol.for('@dudousxd/nestjs-agent:skill-metadata');\n\n/** Marks a provider class as a skill. See {@link SkillOptions}. */\nexport function Skill(options: SkillOptions): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(SKILL_METADATA, options, target);\n };\n}\n\n/** Reads {@link SkillOptions} off a class, or `undefined` if it is not a `@Skill`. */\n// biome-ignore lint/complexity/noBannedTypes: the reflection target's type is precisely `Type | Function`.\nexport function readSkillMetadata(target: Type | Function): SkillOptions | undefined {\n return Reflect.getMetadata(SKILL_METADATA, target) as SkillOptions | undefined;\n}\n\n/** The scope a `@Skill` publishes at — its own, or the deployment-wide default. */\nexport function skillScope(options: SkillOptions): string {\n return options.scope ?? GLOBAL_SCOPE;\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(_actorRef: string, _day: string, _tokens: number): 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 type DetachedDelivery,\n type ElicitationReply,\n type HumanReply,\n RunCancelledError,\n agentFailureCode,\n encodeStreamEvent,\n publishAgentRunFailed,\n runAgentLoop,\n settleAll,\n settleUnsettledDelegation,\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<\n string,\n { resolve: (reply: HumanReply) => void; reject: (error: unknown) => void }\n >();\n /**\n * Runs someone has asked to stop. In-process, like `pending`, and for the same reason: this runner\n * is single-replica by construction, so the request is readable by the only loop that could be\n * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.\n */\n private readonly cancelled = new Set<string>();\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({\n runId,\n deps,\n actor: input.actor,\n day,\n threadId: input.threadId,\n chainBelow: [\n ...(input.delegationPath ?? []),\n ...(input.agentName !== undefined ? [input.agentName] : []),\n ],\n });\n\n void runAgentLoop({ ...deps, day }, input, hooks)\n .then(() => this.store.setActiveStream(input.threadId, null))\n .catch(async (error) => {\n if (error instanceof RunCancelledError) {\n await this.settleCancelled(runId, input.threadId, deps);\n return;\n }\n const message = error instanceof Error ? error.message : String(error);\n const code = agentFailureCode(error);\n this.logger.error(`agent run ${runId} failed (${code}): ${message}`);\n publishAgentRunFailed({ runId, code, message });\n // Settle the run's persisted outcome (the loop only records completions — it can't catch\n // its own crash). Optional-call: a store without run recording skips reliability metrics.\n await this.store.recordRunEnd?.({\n runId,\n status: 'failed',\n errorCode: code,\n errorMessage: message,\n });\n // Clear the thread's active run — a failed run isn't \"still running\" for `activeRunForThread`.\n await this.store.setActiveStream(input.threadId, null);\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 .finally(() => this.cancelled.delete(runId));\n\n return { runId };\n }\n\n async signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void> {\n const key = `${runId}:${toolCallId}`;\n const waiter = this.pending.get(key);\n if (waiter !== undefined) {\n this.pending.delete(key);\n waiter.resolve(reply);\n }\n }\n\n /**\n * Ask a run to stop, and settle whatever it was parked on.\n *\n * The loop observes the request at its next safe point (between steps, before the turn's tools) and\n * unwinds from there — so a tool already executing is left to finish, and its result is recorded\n * exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait\n * is a promise nobody is going to resolve, so it is REJECTED here with the same\n * {@link RunCancelledError} the loop would have thrown, and the run unwinds through the identical\n * path.\n *\n * Settlement — the run row, the thread's active stream, the stream's terminal — belongs to the\n * `RunCancelledError` catch in `start`, so a cancel and an ordinary failure settle in one place\n * each and can never both write.\n */\n async cancel(runId: string): Promise<void> {\n this.cancelled.add(runId);\n for (const [key, waiter] of this.pending) {\n if (key.startsWith(`${runId}:`)) {\n this.pending.delete(key);\n waiter.reject(new RunCancelledError());\n }\n }\n await Promise.resolve();\n }\n\n /**\n * The single place a cancelled run's state is settled: recorded as its own terminal (never\n * `failed` — a user pressing Stop must not land in someone's error rate), the thread released, and\n * the stream ENDED after a `cancelled` frame rather than failed, so a client that retries failed\n * streams does not retry this one.\n */\n private async settleCancelled(runId: string, threadId: string, deps: AgentDeps): Promise<void> {\n this.logger.log(`agent run ${runId} cancelled`);\n await this.store.setActiveStream(threadId, null);\n const writer = await deps.sink.open(runId);\n await writer.write(encodeStreamEvent({ kind: 'cancelled' }));\n await writer.end();\n // Last, so the reader is released before the bookkeeping: everything above is what someone is\n // waiting on, and the run row is what someone reads afterwards.\n await this.store.recordRunEnd?.({ runId, status: 'cancelled' });\n }\n\n /**\n * Park a run on a human, keyed by run + tool call. One map for approvals and for question-set\n * answers alike: both wait on the same key, and `signal` cannot tell (or need to tell) which\n * shape it is delivering — the loop asked for one and only ever gets what the caller sent. A\n * cancel settles the wait too, by rejecting it.\n */\n private park<T extends HumanReply>(runId: string, toolCallId: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this.pending.set(`${runId}:${toolCallId}`, {\n resolve: resolve as (reply: HumanReply) => void,\n reject,\n });\n });\n }\n\n private topLevelHooks(args: {\n runId: string;\n deps: AgentDeps;\n actor: Actor;\n day: string;\n threadId: string;\n /** This run's delegation chain with its own agent appended — see `AgentRunInput.delegationPath`. */\n chainBelow: readonly string[];\n }): AgentLoopHooks {\n const { runId, deps, actor, day, threadId, chainBelow } = args;\n return {\n runId,\n openSink: () => deps.sink.open(runId),\n awaitApproval: (call) => this.park<Decision>(runId, call.id),\n awaitAnswers: (request) => this.park<ElicitationReply>(runId, request.id),\n step: (_name, fn) => fn(),\n parallel: settleAll,\n cancelled: async () => this.cancelled.has(runId),\n runAgent: (agentName, task) =>\n this.runNested({\n agentName,\n task,\n actor,\n day,\n depth: 1,\n path: chainBelow,\n sinkRunId: runId,\n parentRunId: runId,\n }),\n startAgent: ({ agentName, task, toolCallId }) =>\n this.startDetached({\n agentName,\n task,\n actor,\n day,\n depth: 1,\n path: chainBelow,\n parentRunId: runId,\n deliverTo: { threadId, toolCallId },\n }),\n };\n }\n\n /**\n * Delegate WITHOUT waiting: a nested loop nobody awaits, on its own thread and its own sink, which\n * posts its answer back into the delegating thread when it lands (`deliverTo`, settled by the\n * loop). The calling turn gets the run id straight back and finishes.\n *\n * No `sinkRunId`, unlike {@link runNested}: forwarding into the stream the human is watching would\n * write into a turn that has already ended. Its own approvals resolve through the shared pending\n * map keyed by its own runId — which is what the pending-approvals surface routes to.\n */\n private async startDetached(args: {\n agentName: string;\n task: string;\n actor: Actor;\n day: string;\n depth: number;\n /** The chain that reached this child, root first. */\n path: readonly string[];\n parentRunId: string;\n deliverTo: DetachedDelivery;\n }): Promise<{ runId: string }> {\n const { agentName, task, actor, day, depth, path, parentRunId, deliverTo } = args;\n const subThread = await this.store.createThread({ actor, transient: true });\n const runId = crypto.randomUUID();\n // Marks the subthread as streaming this run, exactly as a sub-agent's does: it is what routes a\n // human decision on its action tools back to it, and what lets a client attach to its stream.\n await this.store.setActiveStream(subThread.id, runId);\n const deps = this.factory.forAgent(agentName);\n const hooks: AgentLoopHooks = {\n runId,\n openSink: () => deps.sink.open(runId),\n awaitApproval: (call) => this.park<Decision>(runId, call.id),\n awaitAnswers: (request) => this.park<ElicitationReply>(runId, request.id),\n step: (_name, fn) => fn(),\n parallel: settleAll,\n cancelled: async () => this.cancelled.has(runId),\n runAgent: (childName, childTask) =>\n this.runNested({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n // A detached run owns a stream of its own, so ITS sub-agents forward into that one.\n sinkRunId: runId,\n parentRunId: runId,\n }),\n startAgent: ({ agentName: childName, task: childTask, toolCallId }) =>\n this.startDetached({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n parentRunId: runId,\n deliverTo: { threadId: subThread.id, toolCallId },\n }),\n };\n void runAgentLoop(\n { ...deps, day },\n {\n threadId: subThread.id,\n actor,\n userText: task,\n agentName,\n day,\n delegationDepth: depth,\n delegationPath: path,\n parentRunId,\n deliverTo,\n },\n hooks,\n )\n .catch(async (error: unknown) => {\n const cancelled = error instanceof RunCancelledError;\n const message = error instanceof Error ? error.message : String(error);\n if (!cancelled) {\n this.logger.error(`detached agent run ${runId} failed: ${message}`);\n publishAgentRunFailed({ runId, code: agentFailureCode(error), message });\n }\n await this.store.recordRunEnd?.({\n runId,\n status: cancelled ? 'cancelled' : 'failed',\n ...(cancelled ? {} : { errorCode: agentFailureCode(error), errorMessage: message }),\n });\n // The loop delivers its own success; a run that never produced an answer has to settle the\n // delegation itself, or the calling conversation shows \"started\" for ever.\n await settleUnsettledDelegation({\n store: this.store,\n delivery: deliverTo,\n agent: agentName,\n runId,\n status: cancelled ? 'cancelled' : 'failed',\n ...(cancelled ? {} : { error: message }),\n });\n })\n .finally(async () => {\n this.cancelled.delete(runId);\n await this.store.setActiveStream(subThread.id, null);\n });\n return { runId };\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(args: {\n agentName: string;\n task: string;\n actor: Actor;\n day: string;\n depth: number;\n /** The chain that reached this child, root first. */\n path: readonly string[];\n sinkRunId: string;\n parentRunId: string;\n }): Promise<{ text: string }> {\n const { agentName, task, actor, day, depth, path, sinkRunId, parentRunId } = args;\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) => this.park<Decision>(runId, call.id),\n awaitAnswers: (request) => this.park<ElicitationReply>(runId, request.id),\n step: (_name, fn) => fn(),\n parallel: settleAll,\n // A child stops when it is cancelled OR when the run a human is actually watching is: the\n // canceller names the top-level run, which is the only id that ever left the server.\n cancelled: async () => this.cancelled.has(runId) || this.cancelled.has(sinkRunId),\n runAgent: (childName, childTask) =>\n this.runNested({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n sinkRunId,\n parentRunId: runId,\n }),\n startAgent: ({ agentName: childName, task: childTask, toolCallId }) =>\n this.startDetached({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n parentRunId: runId,\n deliverTo: { threadId: subThread.id, toolCallId },\n }),\n };\n try {\n return await runAgentLoop(\n { ...deps, day },\n {\n threadId: subThread.id,\n actor,\n userText: task,\n agentName,\n day,\n delegationDepth: depth,\n delegationPath: path,\n parentRunId,\n sinkRunId,\n },\n hooks,\n );\n } finally {\n // No durable-style suspend to worry about here (inline runs to completion synchronously from\n // this call's point of view) — always clear so `activeRunForThread` reflects reality.\n await this.store.setActiveStream(subThread.id, null);\n }\n }\n}\n","import {\n type SkillContext,\n type SkillProvider,\n type SkillsConfig,\n compositeSkillProvider,\n} from '@dudousxd/nestjs-agent-core';\nimport type { AgentSkillsOptions } from './agent.options.js';\nimport type { DeclaredSkill } from './discovery/skill-discovery.service.js';\n\n/**\n * The `@Skill`-decorated classes as a `SkillProvider`. Reads `declared` on every call rather than\n * capturing its contents: DI builds the provider before `SkillDiscoveryService` has filled the list.\n */\nexport function declaredSkillProvider(declared: readonly DeclaredSkill[]): SkillProvider {\n return {\n list: ({ scopes }) =>\n declared\n .filter((skill) => scopes.includes(skill.scope))\n .map(({ name, description, scope }) => ({ name, description, scope })),\n load: async ({ name, scope, ctx }) => {\n const match = declared.find((skill) => skill.name === name && skill.scope === scope);\n return match === undefined ? null : await match.body(ctx);\n },\n };\n}\n\n/**\n * The turn's skills seam, or `undefined` where the host configured none — which is also what keeps\n * a deployment that declares no skills from spending the `skills:catalog` checkpoint.\n *\n * DISCOVERED `@Skill` CLASSES ALONE DO NOT TURN SKILLS ON. Adding a decorated class would otherwise\n * insert a checkpoint into every turn, and a run already in flight when that deployment rolled would\n * replay against a sequence one position short. `skills: {}` is the opt-in; a class discovered\n * without it is reported at boot rather than silently inert.\n */\nexport function resolveSkillsConfig(\n options: AgentSkillsOptions | undefined,\n declared: readonly DeclaredSkill[],\n): SkillsConfig | undefined {\n if (options === undefined) {\n return undefined;\n }\n // The host's own provider first: between two skills of the same name AT THE SAME SCOPE, the one\n // it can edit without a deploy is the better answer. Scope still outranks source for everything\n // else — see `compositeSkillProvider`.\n const providers =\n options.provider === undefined\n ? [declaredSkillProvider(declared)]\n : [options.provider, declaredSkillProvider(declared)];\n return {\n provider:\n providers.length === 1 ? (providers[0] as SkillProvider) : compositeSkillProvider(providers),\n ...(options.scopes !== undefined ? { scopes: options.scopes } : {}),\n ...(options.maxSkills !== undefined ? { maxSkills: options.maxSkills } : {}),\n };\n}\n","import type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { UnauthorizedException } from '@nestjs/common';\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 rejects with `UnauthorizedException` when `x-actor-id` is absent — it never\n * fabricates an identity, and never grants a default role (an actor with no `x-actor-role` gets\n * `roles: []`, i.e. no tools). Trusting client headers is only safe behind a gateway that strips\n * and re-sets them from an authenticated principal. Real deployments should provide their own resolver\n * that reads a verified session/JWT instead of installing this one. A custom resolver should\n * reject the same way: a plain `Error` surfaces to the caller as a 500 with a logged stack, which\n * both misreports an unauthenticated request and turns anonymous probes into error noise.\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 UnauthorizedException(\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"],"mappings":"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","names":["AgentDepsFactory","import_nestjs_agent_core","import_common","import_core","import_nestjs_agent_core","delegateToolName","args","slug","target","replace","detached","AgentDepsFactory","options","model","store","sink","rolesPolicy","registry","agents","promptContributors","quota","pricingStore","skills","memory","memoryConfig","skillsConfig","defaultAgentName","defaultAgent","undefined","registered","list","length","name","effectiveTools","definition","delegated","delegatesTo","map","edge","agent","normalizeDelegation","tools","forAgent","agentName","get","toolAllowList","followUpsCount","retrieval","historyPolicy","ask","systemPrompt","maxSteps","maxDelegationDepth","maxAgentAppearances","modelId","inputProcessors","outputProcessors","outputSchema","outputRepairAttempts","intake","toolTimeoutMs","toolTransientRetry","mode","retriever","topK","retrievalTopK","history","window","config","windowHistory","maxMessages","maxTokens","summarize","summarizeWithModel","followUps","count","import_nestjs_agent_core","import_common","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","fail","AgentService","runner","store","deps","quota","staging","chat","params","agentName","resolveAgentName","threadId","attachments","resolveAttachments","actor","undefined","regenerate","BadRequestException","created","createThread","transient","id","assertOwnsThread","input","userText","message","day","utcDay","length","pageContext","runId","start","setActiveStream","refs","resolve","NotImplementedException","resolved","ref","attachment","mediaId","ForbiddenException","push","subscribe","forAgent","sink","subscribeAs","assertOwnsActiveStream","approve","toolCallId","assertOwnsToolCall","signalToolCall","approved","reject","reason","answer","answers","reply","answeredByRef","skip","skipped","resolveRunForToolCall","signal","cancel","listThreads","actorRef","threads","Promise","all","map","thread","toSummaryView","getThread","toDetailView","deleteThread","softDeleteThread","forkThread","fromMessageId","renameThread","title","updateThread","patch","validateTitle","defaultAgent","setTitle","trimmed","trim","threadDefault","threadDefaultAgent","defaultAgentName","projecting","defaultAgentForThread","activeRunId","activeRunForThread","summary","messages","activeStreamId","promoteThread","truncateThreadFrom","messageId","truncateFrom","listAttachments","options","list","attachmentInventory","limit","collectableAttachments","referencedMediaIds","bind","stagedBefore","olderThan","toISOString","inventory","aged","filter","entry","createdAt","referenced","Set","has","quotaToday","usedTokens","costUsd","limitTokens","withinLimit","state","check","owner","ownerOfThread","NotFoundException","ownerOfToolCall","runForToolCall","ownerOfActiveStream","import_common","AgentApprovalPortAdapter","agent","approve","toolCallId","opts","signalToolCall","approved","executedByRef","undefined","reject","reason","import_nestjs_agent_core","import_common","AgentsController","agents","depsFactory","list","defaultAgentName","map","definition","name","description","isDefault","import_nestjs_agent_core","import_common","DEFAULT_MAX_ATTACHMENT_BYTES","HARD_MAX_ATTACHMENT_BYTES","ATTACHMENT_PAGE_SIZE","DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES","AttachmentsController","options","actorResolver","agents","staging","onModuleInit","attachments","upload","undefined","Error","list","req","actor","resolve","listAttachments","limit","file","NotImplementedException","BadRequestException","allowedContentTypes","includes","mimetype","UnsupportedMediaTypeException","join","maxBytes","size","PayloadTooLargeException","stage","data","buffer","filename","originalname","contentType","sizeBytes","limits","fileSize","import_nestjs_agent_core","import_common","MAX_ATTACHMENTS_PER_MESSAGE","attachmentRefs","claimed","undefined","Array","isArray","BadRequestException","length","map","entry","mediaId","ChatController","agent","actorResolver","chat","req","res","body","actor","resolve","attachments","runId","threadId","message","agentName","pageContext","regenerate","transient","pipe","subscribe","stream","subscribeAs","cancel","aborted","events","setHeader","write","JSON","stringify","decoder","TextDecoder","buffer","chunk","decode","newline","indexOf","line","slice","error","payload","AgentStreamError","code","Error","end","import_nestjs_agent_core","import_common","MemoriesController","actorResolver","memory","list","req","threadId","undefined","actor","resolve","unbounded","entries","forget","id","NotFoundException","digest","entry","find","candidate","verdict","memoryForgetVerdict","record","allowed","ForbiddenException","reason","forgotten","provider","ctx","config","offerMemories","maxMemories","Number","POSITIVE_INFINITY","import_nestjs_agent_core","import_common","QuotaController","agent","actorResolver","today","req","actor","resolve","quotaToday","id","import_nestjs_agent_core","import_common","SkillsController","actorResolver","skills","list","req","threadId","undefined","actor","resolve","offer","offerSkills","entries","import_nestjs_agent_core","import_common","ThreadsController","agent","actorResolver","list","req","actor","resolve","listThreads","id","detail","getThread","remove","deleteThread","ok","fork","messageId","forkThread","update","body","updateThread","title","undefined","defaultAgent","promote","promoteThread","truncateFrom","truncateThreadFrom","import_nestjs_agent_core","import_common","MAX_ANSWERED_QUESTIONS","MAX_VALUES_PER_QUESTION","MAX_ANSWER_VALUE_LENGTH","MAX_REJECT_REASON_LENGTH","toolCallId","claimed","length","BadRequestException","rejectReason","undefined","answers","Array","isArray","entries","Object","validated","create","questionId","values","value","ToolCallController","agent","actorResolver","approve","req","body","actor","resolve","ok","reject","reason","answer","skip","import_nestjs_agent_core","import_common","AGENT_METADATA","Symbol","for","Agent","options","target","Reflect","defineMetadata","readAgentMetadata","getMetadata","import_reflect_metadata","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","description","tools","model","modelId","maxSteps","maxDelegationDepth","maxAgentAppearances","history","outputSchema","intake","ask","outputRepairAttempts","handoff","delegatesTo","handoffEdges","edges","entry","target","agent","detached","targetMeta","warn","push","prototype","Object","getPrototypeOf","getAllMethodNames","Reflect","getMetadata","SYSTEM_PROMPT_CONTRIBUTOR_METADATA","method","boundMethod","metadataKey","candidate","call","import_nestjs_agent_core","import_common","import_core","import_reflect_metadata","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","enabled","ctx","isEnabled","canUse","actor","tool","tools","delegates","definition","list","edge","delegatesTo","agent","target","detached","normalizeDelegation","targetDefinition","get","Error","delegateToolName","has","targetBlurb","systemPrompt","targetAgent","z","object","task","string","log","spec","import_nestjs_agent_core","import_common","import_core","import_reflect_metadata","import_nestjs_agent_core","SKILL_METADATA","Symbol","for","Skill","options","target","Reflect","defineMetadata","readSkillMetadata","getMetadata","skillScope","scope","GLOBAL_SCOPE","SkillDiscoveryService","logger","Logger","name","discovery","declared","onModuleInit","wrapper","getProviders","instance","meta","readSkillMetadata","undefined","body","bodyOf","warn","push","description","scope","skillScope","flat","candidate","ctx","call","import_nestjs_agent_core","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","_actorRef","_day","_tokens","import_nestjs_agent_core","import_common","InlineAgentRunner","logger","Logger","name","pending","Map","cancelled","Set","factory","store","start","input","runId","crypto","randomUUID","day","utcDay","deps","forAgent","agentName","hooks","topLevelHooks","actor","threadId","chainBelow","delegationPath","undefined","runAgentLoop","then","setActiveStream","catch","error","RunCancelledError","settleCancelled","message","Error","String","code","agentFailureCode","publishAgentRunFailed","recordRunEnd","status","errorCode","errorMessage","writer","sink","open","fail","finally","delete","signal","toolCallId","reply","key","waiter","get","resolve","cancel","add","startsWith","reject","Promise","log","write","encodeStreamEvent","kind","end","park","set","args","openSink","awaitApproval","call","id","awaitAnswers","request","step","_name","fn","parallel","settleAll","has","runAgent","task","runNested","depth","path","sinkRunId","parentRunId","startAgent","startDetached","deliverTo","subThread","createThread","transient","childName","childTask","userText","delegationDepth","settleUnsettledDelegation","delivery","agent","childSinkWriter","import_nestjs_agent_core","declaredSkillProvider","declared","list","scopes","filter","skill","includes","scope","map","name","description","load","ctx","match","find","undefined","body","resolveSkillsConfig","options","providers","provider","length","compositeSkillProvider","maxSkills","DEFAULT_PATH","sharedProviders","durable","includeStore","providers","provide","AGENT_TOOL_REGISTRY","useFactory","ToolRegistry","AGENT_REGISTRY","AgentRegistry","AGENT_PROMPT_CONTRIBUTORS","AGENT_SKILL_SOURCES","AGENT_SKILLS","options","declared","resolveSkillsConfig","skills","inject","AGENT_OPTIONS","AGENT_MEMORY","memory","AGENT_SINK","sink","InProcessTokenStreamSink","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","SkillDiscoveryService","InlineAgentRunner","AgentService","AgentApprovalPortAdapter","AGENT_APPROVAL_PORT","push","AGENT_RUNNER","durableRunner","Error","token","AGENT_DURABLE_RUNNER","optional","exportsFor","BASE_CONTROLLERS","ChatController","ThreadsController","ToolCallController","QuotaController","AgentsController","SkillsController","MemoriesController","GUARDABLE_CONTROLLERS","AttachmentsController","controllersFor","mountAttachments","controllersForSurface","surface","GUARDS_METADATA","applyGuards","guards","resolved","controller","Reflect","defineMetadata","guardProviders","Set","routerFor","path","RouterModule","register","module","AgentModule","forRoot","global","imports","DiscoveryModule","controllers","attachments","upload","useValue","exports","forRootAsync","externalStore","attachmentsUpload","args","import_common","readHeader","req","name","undefined","headers","value","Reflect","get","HeaderActorResolver","resolve","id","length","UnauthorizedException","roles","split","map","role","trim","filter","tenantRef"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/agent.module.ts","../src/agent-deps.factory.ts","../src/agent.service.ts","../src/agent-deps.ts","../src/approval-port.adapter.ts","../src/controller/agents.controller.ts","../src/controller/attachments.controller.ts","../src/controller/chat.controller.ts","../src/controller/memories.controller.ts","../src/controller/quota.controller.ts","../src/controller/skills.controller.ts","../src/controller/threads.controller.ts","../src/controller/tool-call.controller.ts","../src/controller/tools.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/discovery/skill-discovery.service.ts","../src/decorator/skill.decorator.ts","../src/in-process-sink.ts","../src/ledger-quota-store.ts","../src/runner/inline-agent-runner.ts","../src/skills-config.ts","../src/resolver/header-actor-resolver.ts"],"sourcesContent":["export { AgentModule } from './agent.module.js';\nexport { AgentApprovalPortAdapter } from './approval-port.adapter.js';\nexport type {\n AgentModuleOptions,\n AgentModuleAsyncOptions,\n AgentAttachmentsOptions,\n AgentSkillsOptions,\n AgentMemoryOptions,\n AgentSurface,\n} from './agent.options.js';\nexport {\n AgentService,\n type ChatParams,\n type ThreadDefaultAgentReader,\n} from './agent.service.js';\nexport {\n AttachmentsController,\n ATTACHMENT_PAGE_SIZE,\n DEFAULT_MAX_ATTACHMENT_BYTES,\n DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,\n} from './controller/attachments.controller.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 Skill,\n type SkillOptions,\n type SkillBody,\n SKILL_METADATA,\n readSkillMetadata,\n skillScope,\n} from './decorator/skill.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 SkillDiscoveryService,\n type DeclaredSkill,\n} from './discovery/skill-discovery.service.js';\nexport { SkillsController } from './controller/skills.controller.js';\nexport { ToolsController } from './controller/tools.controller.js';\nexport { MemoriesController } from './controller/memories.controller.js';\nexport { declaredSkillProvider, resolveSkillsConfig } from './skills-config.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","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_APPROVAL_PORT,\n AGENT_DEPS_FACTORY,\n AGENT_DURABLE_RUNNER,\n AGENT_MEMORY,\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_SKILLS,\n AGENT_SKILL_SOURCES,\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 {\n type CanActivate,\n type DynamicModule,\n Global,\n Module,\n type Provider,\n type Type,\n} from '@nestjs/common';\nimport { DiscoveryModule, RouterModule } from '@nestjs/core';\nimport { AgentDepsFactory } from './agent-deps.factory.js';\nimport type { AgentModuleAsyncOptions, AgentModuleOptions, AgentSurface } from './agent.options.js';\nimport { AgentService } from './agent.service.js';\nimport { AgentApprovalPortAdapter } from './approval-port.adapter.js';\nimport { AgentsController } from './controller/agents.controller.js';\nimport { AttachmentsController } from './controller/attachments.controller.js';\nimport { ChatController } from './controller/chat.controller.js';\nimport { MemoriesController } from './controller/memories.controller.js';\nimport { QuotaController } from './controller/quota.controller.js';\nimport { SkillsController } from './controller/skills.controller.js';\nimport { ThreadsController } from './controller/threads.controller.js';\nimport { ToolCallController } from './controller/tool-call.controller.js';\nimport { ToolsController } from './controller/tools.controller.js';\nimport { AgentDiscoveryService } from './discovery/agent-discovery.service.js';\nimport { AiToolDiscoveryService } from './discovery/ai-tool-discovery.service.js';\nimport { type DeclaredSkill, SkillDiscoveryService } from './discovery/skill-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';\nimport { resolveSkillsConfig } from './skills-config.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 // Likewise for `@Skill`-decorated providers — filled by SkillDiscoveryService at onModuleInit,\n // read lazily by the AGENT_SKILLS provider below (which DI builds before discovery has run).\n { provide: AGENT_SKILL_SOURCES, useFactory: () => [] },\n {\n // One resolution, shared by the loop's deps and the listing endpoint: a second one would\n // drift, and a user would be offered a skill the agent cannot reach. `undefined` when the\n // host configured none — which is what keeps the turn's checkpoint sequence unchanged.\n provide: AGENT_SKILLS,\n useFactory: (options: AgentModuleOptions, declared: DeclaredSkill[]) =>\n resolveSkillsConfig(options.skills, declared),\n inject: [AGENT_OPTIONS, AGENT_SKILL_SOURCES],\n },\n {\n // One resolution, shared by the loop's deps and the read-back endpoint: a person has to be\n // shown what the model was shown, and two resolutions would eventually disagree about that.\n provide: AGENT_MEMORY,\n useFactory: (options: AgentModuleOptions) => options.memory,\n inject: [AGENT_OPTIONS],\n },\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 SkillDiscoveryService,\n InlineAgentRunner,\n AgentService,\n // Bound ALWAYS (durable or inline) — the console's cross-thread approvals inbox routes decisions\n // through AgentService.signalToolCall, which reaches whichever AGENT_RUNNER is bound above.\n AgentApprovalPortAdapter,\n { provide: AGENT_APPROVAL_PORT, useExisting: AgentApprovalPortAdapter },\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_SKILLS,\n AGENT_MEMORY,\n AGENT_DEPS_FACTORY,\n AgentDepsFactory,\n AgentService,\n InlineAgentRunner,\n AGENT_APPROVAL_PORT,\n ];\n}\n\nconst BASE_CONTROLLERS = [\n ChatController,\n ThreadsController,\n ToolCallController,\n QuotaController,\n AgentsController,\n SkillsController,\n MemoriesController,\n ToolsController,\n];\n\n/** Every controller class `guards` may ever target — stamped uniformly regardless of which of them are actually mounted this build (harmless: metadata on an unregistered class is simply unused). */\nconst GUARDABLE_CONTROLLERS = [...BASE_CONTROLLERS, AttachmentsController];\n\n/** The controllers to mount: the base six, plus attachments when the host opted into uploads. */\nfunction controllersFor(mountAttachments: boolean): Type<object>[] {\n return mountAttachments ? [...BASE_CONTROLLERS, AttachmentsController] : BASE_CONTROLLERS;\n}\n\n/**\n * `surface: 'engine'` mounts NO controllers — a worker pod never receives HTTP traffic, so its\n * routes (and whatever guards they'd carry) have no business existing there. `'http'`/`'both'`\n * (and the omitted default) mount the same set `controllersFor` always has.\n */\nfunction controllersForSurface(\n surface: AgentSurface | undefined,\n mountAttachments: boolean,\n): Type<object>[] {\n return surface === 'engine' ? [] : controllersFor(mountAttachments);\n}\n\n/**\n * Nest's `GUARDS_METADATA` key (`@nestjs/common/constants`), inlined as a literal: `@nestjs/common`\n * has no `exports` map and its ESM-facing files are CJS, so a deep `import ... from\n * '@nestjs/common/constants'` in our ESM build is emitted extensionless and rejected by Node's\n * strict ESM resolver (surfaced by a consumer's bundler/test runner externalizing this package).\n * `agent-guards.spec.ts` asserts this literal still matches the real constant, so upstream drift\n * fails loudly instead of silently stamping a dead metadata key.\n */\nconst GUARDS_METADATA = '__guards__';\n\n/**\n * Stamp (or clear) `@UseGuards`-equivalent metadata on every controller this module MIGHT mount.\n *\n * Mechanism: `@UseGuards(...guards)` on a controller just does `Reflect.defineMetadata(GUARDS_METADATA,\n * guards, ControllerClass)` (via Nest's `extendArrayMetadata`, which *appends* to any existing array).\n * We call `Reflect.defineMetadata` directly instead, so each `forRoot`/`forRootAsync` call REPLACES\n * the metadata rather than appending to it — appending would leak guards across repeated module\n * registrations in the same process (every test file that calls `forRoot` more than once, say) since\n * these controller classes are module-level singletons shared by every registration. Nest's\n * `GuardsConsumer` reads this metadata per-request via `Reflector`, not once at boot, so the LAST call\n * to stamp it before a request is served wins for that controller class in this process.\n */\nfunction applyGuards(guards: Type<CanActivate>[] | undefined): void {\n const resolved = guards ?? [];\n for (const controller of GUARDABLE_CONTROLLERS) {\n Reflect.defineMetadata(GUARDS_METADATA, resolved, controller);\n }\n}\n\n/** Distinct guard classes for the module's `providers`, so Nest can DI-instantiate them. */\nfunction guardProviders(guards: Type<CanActivate>[] | undefined): Type<CanActivate>[] {\n return [...new Set(guards ?? [])];\n}\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 applyGuards(options.guards);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path)],\n controllers: controllersForSurface(options.surface, options.attachments?.upload === true),\n providers: [\n { provide: AGENT_OPTIONS, useValue: options },\n ...sharedProviders(options.durable ?? false, includeStore),\n ...guardProviders(options.guards),\n ],\n exports: exportsFor(includeStore),\n };\n }\n\n static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n // The async factory resolves too late to inspect `store`, so `forRootAsync` binds AGENT_STORE\n // locally from the factory result by default. `externalStore: true` opts out — deferring to a\n // globally-imported store module (e.g. `MikroOrmAgentStoreModule.forFeature()`) so the host\n // doesn't have to inject that store just to hand it back as `store`.\n const includeStore = options.externalStore !== true;\n applyGuards(options.guards);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path), ...(options.imports ?? [])],\n controllers: controllersForSurface(options.surface, options.attachmentsUpload === true),\n providers: [\n {\n provide: AGENT_OPTIONS,\n // Stamp the STATIC wiring flags onto the factory result: `durable`/`surface` are\n // authoritative on the async config object (they decided the actual wiring above), and\n // the durable module reads `durable` back off AGENT_OPTIONS. `surface` isn't read back by\n // anything today (AgentDurableModule takes its own mirror option — see its doc for why),\n // but it's stamped here too so the EFFECTIVE value is always observable off\n // AGENT_OPTIONS, sync or async alike.\n useFactory: async (...args: never[]) => ({\n ...(await options.useFactory(...args)),\n durable: options.durable ?? false,\n surface: options.surface ?? 'both',\n }),\n inject: options.inject ?? [],\n },\n ...sharedProviders(options.durable ?? false, includeStore),\n ...guardProviders(options.guards),\n ],\n exports: exportsFor(includeStore),\n };\n }\n}\n","import {\n AGENT_MEMORY,\n AGENT_MODEL,\n AGENT_PRICING_STORE,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_STORE,\n AGENT_REGISTRY,\n AGENT_ROLES_POLICY,\n AGENT_SINK,\n AGENT_SKILLS,\n AGENT_STORE,\n AGENT_TOOL_REGISTRY,\n type AgentDefinition,\n type AgentHistoryWindow,\n type AgentPricingStore,\n AgentRegistry,\n type AgentStore,\n type HistoryPolicy,\n type MemoryConfig,\n type ModelProvider,\n type PromptContributor,\n type QuotaStore,\n type RolesPolicy,\n type SkillsConfig,\n type TokenStreamSink,\n ToolRegistry,\n normalizeDelegation,\n summarizeWithModel,\n windowHistory,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_OPTIONS } from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport type { AgentDeps } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\n\n/**\n * The synthesized `agent`-kind tool name an orchestrator uses to hand off to `target`.\n *\n * A detached edge gets its own verb — `start_research` next to `ask_research` — for two reasons.\n * One agent can be both awaited AND backgrounded by the same orchestrator, and one name cannot\n * carry both. And the name is the part of a tool the model reads first: `ask` promises an answer,\n * `start` does not.\n */\nexport function delegateToolName(args: { target: string; detached?: boolean }): string {\n const slug = args.target.replace(/[^a-zA-Z0-9]+/g, '_');\n return args.detached === true ? `start_${slug}` : `ask_${slug}`;\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 // Optional: AGENT_PRICING_STORE has no local provider in this module (unlike AGENT_QUOTA_STORE,\n // which is always a registered factory) — it's bound externally (e.g. by a store module), so a\n // plain @Inject would throw when nothing binds it.\n @Optional()\n @Inject(AGENT_PRICING_STORE)\n private readonly pricingStore: AgentPricingStore | undefined,\n // Optional for the same reason, plus one of its own: `undefined` is the CONFIGURED state for a\n // host that declared no skills, not an unbound dependency.\n @Optional()\n @Inject(AGENT_SKILLS)\n private readonly skills: SkillsConfig | undefined,\n // Optional for the same reason: `undefined` is the CONFIGURED state for a host that wired no\n // memory, not an unbound dependency.\n @Optional()\n @Inject(AGENT_MEMORY)\n private readonly memory: MemoryConfig | undefined,\n ) {}\n\n /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */\n memoryConfig(): MemoryConfig | undefined {\n return this.memory;\n }\n\n /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */\n skillsConfig(): SkillsConfig | undefined {\n return this.skills;\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((edge) => {\n const { agent, detached } = normalizeDelegation(edge);\n return delegateToolName({ target: agent, detached });\n });\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 const historyPolicy = this.historyPolicy(definition);\n const ask = definition?.ask ?? this.options.ask;\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?.maxDelegationDepth !== undefined\n ? { maxDelegationDepth: definition.maxDelegationDepth }\n : {}),\n ...(definition?.maxAgentAppearances !== undefined\n ? { maxAgentAppearances: definition.maxAgentAppearances }\n : {}),\n ...(definition?.modelId !== undefined ? { modelId: definition.modelId } : {}),\n ...(this.quota !== undefined ? { quota: this.quota } : {}),\n ...(this.pricingStore !== undefined ? { pricingStore: this.pricingStore } : {}),\n ...(historyPolicy !== undefined ? { historyPolicy } : {}),\n inputProcessors: this.options.inputProcessors ?? [],\n outputProcessors: this.options.outputProcessors ?? [],\n ...(definition?.outputSchema !== undefined ? { outputSchema: definition.outputSchema } : {}),\n ...(definition?.outputRepairAttempts !== undefined\n ? { outputRepairAttempts: definition.outputRepairAttempts }\n : {}),\n ...(definition?.intake !== undefined ? { intake: definition.intake } : {}),\n // Most specific wins, exactly as `historyPolicy` resolves: the agent's own `@Agent({ ask })`,\n // else the module-wide flag. Both are module config, so every process of a deployment agrees.\n ...(ask === true ? { ask: true } : {}),\n // Module-wide, never per-agent: a skill is a procedure, not a persona, and an agent that could\n // opt out of one would make the catalog depend on which agent a turn happened to select — a\n // per-turn fact the worker re-deriving the tool list cannot see.\n ...(this.skills !== undefined ? { skills: this.skills } : {}),\n // Module-wide, never per-agent, for the same reason skills are: which memories a turn carries\n // cannot depend on which persona answered it, or the worker re-deriving a dispatched turn's\n // tool list would disagree with the loop about whether `remember` was offered.\n ...(this.memory !== undefined ? { memory: this.memory } : {}),\n ...(toolAllowList !== undefined ? { toolAllowList } : {}),\n ...(this.options.toolTimeoutMs !== undefined\n ? { toolTimeoutMs: this.options.toolTimeoutMs }\n : {}),\n ...(this.options.toolTransientRetry !== undefined\n ? { toolTransientRetry: this.options.toolTransientRetry }\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 /**\n * The ceiling on how much of a thread this agent's turns carry, most specific wins: the agent's\n * own `@Agent({ history })`, else a module-wide custom `historyPolicy`, else the module-wide\n * `history` window. Undefined → unbounded, the behaviour of a module that configures none.\n */\n private historyPolicy(definition: AgentDefinition | undefined): HistoryPolicy | undefined {\n if (definition?.history !== undefined) {\n return this.window(definition.history);\n }\n if (this.options.historyPolicy !== undefined) {\n return this.options.historyPolicy;\n }\n return this.options.history === undefined ? undefined : this.window(this.options.history);\n }\n\n /** Build the built-in window policy from the declarative `{ maxMessages, maxTokens, summarize }`. */\n private window(config: AgentHistoryWindow): HistoryPolicy {\n return windowHistory({\n ...(config.maxMessages !== undefined ? { maxMessages: config.maxMessages } : {}),\n ...(config.maxTokens !== undefined ? { maxTokens: config.maxTokens } : {}),\n // The shared module model, not a per-agent one: an agent's `modelId` is an accounting label,\n // and only one provider is ever bound.\n ...(config.summarize === true ? { summarize: summarizeWithModel(this.model) } : {}),\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_ATTACHMENT_STAGING,\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 AttachmentRef,\n type AttachmentStagingStore,\n type Decision,\n type ElicitationReply,\n type HumanReply,\n type ListStagedAttachmentsInput,\n type MessageAttachment,\n type PageContext,\n type QuotaStore,\n type QuotaView,\n type StagedAttachment,\n type ThreadDetail,\n type ThreadSummary,\n type UpdateThreadInput,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n ForbiddenException,\n Inject,\n Injectable,\n NotFoundException,\n NotImplementedException,\n Optional,\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 /**\n * Files attached to this message (image/PDF) for a vision-capable model, named by the `mediaId`\n * the upload returned. Only the id is read: the url, content type and name are resolved from the\n * bound {@link AttachmentStagingStore}, so nothing a caller says decides what the model fetches.\n */\n attachments?: AttachmentRef[];\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/**\n * A store that can answer a thread's default agent on its own, without materializing the thread.\n *\n * Probed STRUCTURALLY rather than declared on `AgentStore`: the projection is an optimization a\n * store either offers or doesn't, and a store that predates it still answers correctly through\n * `getThread`. Every adapter in this repo implements it.\n */\nexport interface ThreadDefaultAgentReader {\n defaultAgentForThread(threadId: string): Promise<string | null>;\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 @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging?: AttachmentStagingStore,\n ) {}\n\n async chat(params: ChatParams): Promise<{ runId: string; threadId: string }> {\n // Precedence: explicit agentName > the thread's own defaultAgent (set via updateThread) > the\n // module's configured default. Resolved up front (before thread creation) so a brand-new thread\n // — which has no defaultAgent yet — falls straight through to the module default.\n const agentName = await this.resolveAgentName(params.agentName, params.threadId);\n // Before the thread exists, so a turn that names an attachment it may not have leaves nothing\n // behind.\n const attachments = await this.resolveAttachments(params.actor, params.attachments ?? []);\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 ...(attachments.length > 0 ? { attachments } : {}),\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 /**\n * Rebuild this turn's attachments from the staging store, keyed by the ids the caller claimed.\n * The model provider fetches {@link MessageAttachment.url} verbatim, so that url is only ever\n * allowed to come from the host's own store — a caller that could name it could point the server\n * at anything it can reach (cloud metadata, internal services) and read the response back out of\n * the model's answer.\n *\n * No store bound means no way to tell an id the actor owns from one they don't, so a turn simply\n * cannot carry attachments: 501 rather than trusting the request.\n */\n private async resolveAttachments(\n actor: Actor,\n refs: AttachmentRef[],\n ): Promise<MessageAttachment[]> {\n if (refs.length === 0) {\n return [];\n }\n const staging = this.staging;\n if (staging === undefined || typeof staging.resolve !== 'function') {\n throw new NotImplementedException(\n 'Message attachments require an AGENT_ATTACHMENT_STAGING provider implementing resolve(); ' +\n 'attachment urls are never taken from the request.',\n );\n }\n const resolved: MessageAttachment[] = [];\n for (const ref of refs) {\n const attachment = await staging.resolve({ mediaId: ref.mediaId, actor });\n if (attachment === null) {\n throw new ForbiddenException(`attachment ${ref.mediaId} is not available to this actor`);\n }\n resolved.push(attachment);\n }\n return resolved;\n }\n\n /**\n * The run's live token stream, WITHOUT an ownership check — for in-process callers that are\n * already authorized (the MCP bridge, a host's own job code), the same split as\n * {@link signalToolCall} vs {@link approve}. Anything reachable from a request must go through\n * {@link subscribeAs} instead: a runId is the only thing standing between a caller and another\n * actor's answer, tool arguments and tool results.\n */\n subscribe(runId: string): AsyncIterable<Uint8Array> {\n return this.deps.forAgent().sink.subscribe(runId);\n }\n\n /**\n * {@link subscribe}, gated the way {@link cancel} is: only the actor whose thread is currently\n * streaming this run may read it. A run that has already finished is reported missing rather than\n * replayed — the runner clears the thread's active stream as the run ends, and that field is what\n * ownership is derived from.\n */\n async subscribeAs(actor: Actor, runId: string): Promise<AsyncIterable<Uint8Array>> {\n await this.assertOwnsActiveStream(actor, runId);\n return this.subscribe(runId);\n }\n\n async approve(actor: Actor, toolCallId: string): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n return this.signalToolCall(toolCallId, { approved: true });\n }\n\n async reject(actor: Actor, toolCallId: string, reason?: string): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n return this.signalToolCall(toolCallId, {\n approved: false,\n ...(reason !== undefined ? { reason } : {}),\n });\n }\n\n /**\n * Answer a parked question set. An omitted question takes the request's own pre-picked default —\n * resolved by the LOOP against the request it already holds, so \"the user just submitted\" and\n * \"the user picked exactly the defaults\" persist as the same answers, and no client has to\n * re-send what it was shown.\n */\n async answer(\n actor: Actor,\n toolCallId: string,\n answers: Record<string, string[]> = {},\n ): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n const reply: ElicitationReply = { answers, answeredByRef: actor.id };\n return this.signalToolCall(toolCallId, reply);\n }\n\n /**\n * Decline to answer and let the agent proceed on its own assumptions. NOT the same as confirming\n * them: the run records this as a rejection, so a reader auditing what the agent was told can\n * tell a choice the user made from one they refused to make.\n */\n async skip(actor: Actor, toolCallId: string): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n const reply: ElicitationReply = { answers: {}, skipped: true, answeredByRef: actor.id };\n return this.signalToolCall(toolCallId, reply);\n }\n\n /**\n * The decision core behind approve/reject, WITHOUT an ownership check: resolves the run\n * currently awaiting `toolCallId` and signals it. `approve`/`reject` above call this after their\n * own `assertOwnsToolCall` gate; the console `AgentApprovalPort` adapter (bound by `AgentModule`)\n * calls it directly — a console caller is already authorized by the dashboard's own guards, and\n * re-deriving thread ownership here would reject a legitimate operator decision (an operator is\n * not the thread's own actor).\n */\n async signalToolCall(toolCallId: string, reply: HumanReply): Promise<void> {\n const runId = await this.resolveRunForToolCall(toolCallId);\n return this.runner.signal(runId, toolCallId, reply);\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 async listThreads(actorRef: string): Promise<ThreadSummary[]> {\n const threads = await this.store.listThreads(actorRef);\n return Promise.all(threads.map((thread) => this.toSummaryView(thread)));\n }\n\n async getThread(actor: Actor, threadId: string): Promise<ThreadDetail | null> {\n await this.assertOwnsThread(actor, threadId);\n const thread = await this.store.getThread(threadId);\n return thread === null ? null : this.toDetailView(thread);\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 /** Kept for source compatibility — a thin wrapper over the more general `updateThread`. */\n async renameThread(actor: Actor, threadId: string, title: string): Promise<void> {\n return this.updateThread(actor, threadId, { title });\n }\n\n /**\n * Rename a thread and/or set its default agent. Title-only patches work against ANY store (via\n * the required `setTitle`); a `defaultAgent` change requires the bound store to implement the\n * optional `updateThread` — 501 with a clear message when it doesn't, rather than silently\n * dropping the field.\n */\n async updateThread(actor: Actor, threadId: string, patch: UpdateThreadInput): Promise<void> {\n const title = patch.title !== undefined ? this.validateTitle(patch.title) : undefined;\n await this.assertOwnsThread(actor, threadId);\n if (patch.defaultAgent === undefined) {\n if (title !== undefined) {\n await this.store.setTitle(threadId, title);\n }\n return;\n }\n if (this.store.updateThread === undefined) {\n throw new NotImplementedException(\n \"Setting a thread's defaultAgent requires an AgentStore that implements updateThread(); \" +\n 'the bound store does not support it.',\n );\n }\n await this.store.updateThread(threadId, {\n ...(title !== undefined ? { title } : {}),\n defaultAgent: patch.defaultAgent,\n });\n }\n\n private validateTitle(title: string): string {\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 return trimmed;\n }\n\n /**\n * Agent-selection precedence for a `chat()` call with no explicit `agentName`: the thread's own\n * `defaultAgent` (if the thread exists and one is set) wins over the module's configured default.\n * Skips the store entirely when the caller already named an agent or there's no thread yet.\n *\n * What this needs is one nullable scalar, so it asks for one. `getThread` returns the entire\n * transcript — every message, every persisted tool output — and this discards all of it; on a\n * long thread with large tool results that is hundreds of kilobytes read per turn, outside the\n * workflow, for a string. A store predating {@link ThreadDefaultAgentReader} still answers, via\n * the full read.\n */\n private async resolveAgentName(\n agentName: string | undefined,\n threadId: string | undefined,\n ): Promise<string> {\n if (agentName !== undefined) {\n return agentName;\n }\n if (threadId !== undefined) {\n const threadDefault = await this.threadDefaultAgent(threadId);\n if (threadDefault !== null) {\n return threadDefault;\n }\n }\n return this.deps.defaultAgentName();\n }\n\n private async threadDefaultAgent(threadId: string): Promise<string | null> {\n const projecting = this.store as Partial<ThreadDefaultAgentReader>;\n if (typeof projecting.defaultAgentForThread === 'function') {\n return projecting.defaultAgentForThread(threadId);\n }\n return (await this.store.getThread(threadId))?.defaultAgent ?? null;\n }\n\n private async toSummaryView(thread: ThreadSummary): Promise<ThreadSummary> {\n return {\n ...thread,\n defaultAgent: thread.defaultAgent ?? null,\n activeRunId: (await this.store.activeRunForThread?.(thread.id)) ?? null,\n };\n }\n\n private async toDetailView(thread: ThreadDetail): Promise<ThreadDetail> {\n const summary = await this.toSummaryView(thread);\n return {\n ...summary,\n messages: thread.messages,\n ...(thread.activeStreamId !== undefined ? { activeStreamId: thread.activeStreamId } : {}),\n };\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 * Every file this actor has staged, newest first — across threads, including uploads that were\n * never sent, which nothing else on this surface can see.\n *\n * Metadata only. A url is minted per turn by `resolve` so it can be short-lived, and handing one\n * back per entry would undo that for the price of rendering a list.\n */\n async listAttachments(\n actor: Actor,\n options: { limit?: number } = {},\n ): Promise<StagedAttachment[]> {\n const list = this.attachmentInventory();\n return list({ actor, ...(options.limit !== undefined ? { limit: options.limit } : {}) });\n }\n\n /**\n * This actor's staged media that no live message references and that is old enough not to be an\n * upload in flight — the candidate set for a sweep. Returns them; never deletes them. The bytes\n * are the host's, and so is the decision.\n *\n * `olderThan` is required and has no default. How long a composer may sit open with a file\n * attached is the host's knowledge, and a library-chosen grace period would eventually delete a\n * file someone was about to send. The staging store is asked to apply it, and the result is\n * filtered again here: a store that ignores the hint would otherwise turn this into exactly that\n * bug, silently.\n *\n * Both halves must be answerable or this refuses. An unanswerable reference query means \"cannot\n * tell\", and treating it as \"nothing is referenced\" would hand back every attachment the actor\n * ever sent, marked safe to delete.\n */\n async collectableAttachments(\n actor: Actor,\n options: { olderThan: Date; limit?: number },\n ): Promise<StagedAttachment[]> {\n const list = this.attachmentInventory();\n const referencedMediaIds = this.store.referencedMediaIds?.bind(this.store);\n if (referencedMediaIds === undefined) {\n throw new NotImplementedException(\n 'Collecting attachments requires an AgentStore that implements referencedMediaIds(); the ' +\n 'bound store cannot say which media a message still references, and guessing would ' +\n 'delete files that are in use.',\n );\n }\n const stagedBefore = options.olderThan.toISOString();\n const inventory = await list({\n actor,\n stagedBefore,\n ...(options.limit !== undefined ? { limit: options.limit } : {}),\n });\n const aged = inventory.filter((entry) => entry.createdAt < stagedBefore);\n const referenced = new Set(\n await referencedMediaIds(\n actor.id,\n aged.map((entry) => entry.mediaId),\n ),\n );\n return aged.filter((entry) => !referenced.has(entry.mediaId));\n }\n\n /**\n * The bound staging store's `list`, or a refusal. Absence is never answered with an empty list:\n * \"this host keeps no inventory\" and \"this actor has no files\" are opposite facts that would\n * otherwise render identically — as a clean file list, and as a sweep that collects nothing.\n */\n private attachmentInventory(): (\n input: ListStagedAttachmentsInput,\n ) => Promise<StagedAttachment[]> {\n const list = this.staging?.list?.bind(this.staging);\n if (list === undefined) {\n throw new NotImplementedException(\n 'Listing attachments requires an AGENT_ATTACHMENT_STAGING provider implementing list(); ' +\n 'the host owns the staged bytes, so only it can enumerate them.',\n );\n }\n return list;\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 seam for HITL approve/reject: the caller must own the tool call's thread. Split\n * out from run resolution (see {@link resolveRunForToolCall}) so the console `AgentApprovalPort`\n * adapter can resolve+signal a decision WITHOUT this check — it is authorized upstream instead.\n */\n private async assertOwnsToolCall(actor: Actor, toolCallId: string): Promise<void> {\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 }\n\n /**\n * Resolve the run awaiting `toolCallId`. Derived server-side from the tool call alone — the client\n * never knows or supplies a runId, and that run is the sub-agent's own child run when the pending\n * call belongs to a delegated agent. The store answers from the CALL'S OWN `runId` where it has\n * one; see `AgentStore.runForToolCall` for why that matters once a thread can hold more than one\n * live run.\n */\n private async resolveRunForToolCall(toolCallId: string): Promise<string> {\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 AgentIntake,\n AgentPricingStore,\n AgentStore,\n HistoryPolicy,\n InputProcessor,\n MemoryConfig,\n ModelProvider,\n OutputProcessor,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n SkillsConfig,\n TokenStreamSink,\n ToolRegistry,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n 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 /** Nesting ceiling for delegation below this agent. Undefined → the loop's default. */\n maxDelegationDepth?: number;\n /** How many times one agent may appear on a chain. Undefined → the loop's default. */\n maxAgentAppearances?: number;\n /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\n /**\n * Transient-tool-error retry policy (from module options). Undefined → default ON\n * (`{ attempts: 2, backoffMs: 150 }` with the default classifier); `false` → disabled.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /** How many follow-up suggestions to generate after the final turn. Undefined/0 → off. */\n followUpsCount?: number;\n /** Inject-mode retriever (from `forRoot({ retrieval })`). Undefined → no prompt augmentation. */\n retriever?: Retriever;\n /** Passages inject-mode retrieval requests. Undefined → loop default (5). */\n retrievalTopK?: number;\n /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */\n pricingStore?: AgentPricingStore;\n /** The agent's history ceiling, resolved from `@Agent({ history })` / module options. Undefined → unbounded. */\n historyPolicy?: HistoryPolicy;\n /** Module-wide prompt rewriters, applied before every model call. Empty → none. */\n inputProcessors: InputProcessor[];\n /** Module-wide answer gates. NON-EMPTY MEANS THE TURN'S MODEL OUTPUT IS BUFFERED, not streamed. */\n outputProcessors: OutputProcessor[];\n /** The agent's `@Agent({ outputSchema })`, resolved from DI — never over the wire. Undefined → free text. */\n outputSchema?: StandardSchemaV1;\n /** Extra model calls allowed to repair an answer that failed `outputSchema`. Undefined → 1. */\n outputRepairAttempts?: number;\n /** The agent's `@Agent({ intake })` question set, asked before the turn starts. Undefined → none. */\n intake?: AgentIntake;\n /** Whether the model may call the built-in `ask` tool this turn. Undefined/false → it never sees it. */\n ask?: boolean;\n /**\n * The resolved skills seam (`forRoot({ skills })` + discovered `@Skill` providers). Undefined →\n * no catalog, no `skill` tool, and the turn spends no checkpoint on either.\n */\n skills?: SkillsConfig;\n /**\n * The resolved memory seam (`forRoot({ memory })`). Undefined → no block, no `remember` tool, and\n * the turn spends no checkpoint on either.\n */\n memory?: MemoryConfig;\n}\n\nexport function utcDay(date = new Date()): string {\n return date.toISOString().slice(0, 10);\n}\n\n/**\n * Wraps a parent run's sink writer for a sub-agent: `write` forwards (so the sub-agent's tokens and\n * pending action-tool frames reach the human's live stream), but `end` / `fail` are swallowed — the\n * top-level run owns the stream's lifecycle, so a finished/failed child must not close or error the\n * shared stream out from under the parent that is still running.\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 type { AgentApprovalPort } from '@dudousxd/nestjs-agent-core';\nimport { Injectable } from '@nestjs/common';\nimport { AgentService } from './agent.service.js';\n\n/**\n * Binds `AGENT_APPROVAL_PORT` for the console's cross-thread approvals inbox to the SAME decision\n * path chat approvals use — `AgentService.signalToolCall` (resolve the run awaiting `toolCallId`,\n * then `AgentRunner.signal`, which is either the inline pending-promise map or the durable signal\n * `tool:<runId>:<callId>`, depending on how the host configured `AgentModule`).\n *\n * Deliberately WITHOUT `AgentService.approve`/`reject`'s ownership check: a console caller reaches\n * this port only through the dashboard's own guards (already authorized), not as the thread's own\n * actor — re-deriving \"does this actor own the thread\" here would reject a legitimate operator\n * decision. `opts.executedByRef` is an OPAQUE decider ref, not re-authorized against anything: it\n * rides the `Decision` and the loop records it as the tool call's decider\n * (`decision.executedByRef ?? input.actor.id`, on both the executed and rejected paths).\n */\n@Injectable()\nexport class AgentApprovalPortAdapter implements AgentApprovalPort {\n constructor(private readonly agent: AgentService) {}\n\n async approve(toolCallId: string, opts?: { executedByRef?: string }): Promise<void> {\n await this.agent.signalToolCall(toolCallId, {\n approved: true,\n ...(opts?.executedByRef !== undefined ? { executedByRef: opts.executedByRef } : {}),\n });\n }\n\n async reject(\n toolCallId: string,\n opts?: { executedByRef?: string; reason?: string },\n ): Promise<void> {\n await this.agent.signalToolCall(toolCallId, {\n approved: false,\n ...(opts?.executedByRef !== undefined ? { executedByRef: opts.executedByRef } : {}),\n ...(opts?.reason !== undefined ? { reason: opts.reason } : {}),\n });\n }\n}\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_REGISTRY,\n type AgentCatalogEntry,\n AgentRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\n\n/** Lists the registered `@Agent`s so a host can render a persona picker instead of hardcoding one. */\n@Controller('agents')\nexport class AgentsController {\n constructor(\n @Inject(AGENT_REGISTRY) private readonly agents: AgentRegistry,\n @Inject(AGENT_DEPS_FACTORY) private readonly depsFactory: AgentDepsFactory,\n ) {}\n\n @Get()\n list(): AgentCatalogEntry[] {\n const defaultAgentName = this.depsFactory.defaultAgentName();\n return this.agents.list().map((definition) => ({\n name: definition.name,\n description: definition.description ?? '',\n ...(definition.name === defaultAgentName ? { isDefault: true } : {}),\n }));\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_ATTACHMENT_STAGING,\n AGENT_OPTIONS,\n type ActorResolver,\n type AttachmentStagingStore,\n type MessageAttachment,\n type StagedAttachment,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Controller,\n Get,\n Inject,\n NotImplementedException,\n type OnModuleInit,\n Optional,\n PayloadTooLargeException,\n Post,\n Req,\n UnsupportedMediaTypeException,\n UploadedFile,\n UseInterceptors,\n} from '@nestjs/common';\nimport { FileInterceptor } from '@nestjs/platform-express';\nimport type { Request } from 'express';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { AgentService } from '../agent.service.js';\n\n/** Default per-file size cap when `AgentModuleOptions.attachments.maxBytes` is omitted (20 MiB). */\nexport const DEFAULT_MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024;\n\n/**\n * The most this route will ever read into memory, enforced by multer while the body streams (32\n * MiB — above the default cap, and above what any mainstream multimodal provider accepts as a\n * single file part). `attachments.maxBytes` is per-instance config and so cannot be known when the\n * interceptor is declared; it narrows this ceiling at request time but can never raise it.\n */\nexport const HARD_MAX_ATTACHMENT_BYTES = 32 * 1024 * 1024;\n\n/**\n * How many entries `GET /agent/attachments` returns. Fixed rather than caller-supplied: this route\n * exists so a composer can show the files someone has uploaded, and a host that needs real paging\n * over a large inventory has `AgentService.listAttachments` and its own store's `list` to page with.\n */\nexport const ATTACHMENT_PAGE_SIZE = 50;\n\n/**\n * Default allowlist: what multimodal model providers commonly accept as native image/file parts.\n */\nexport const DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES: readonly string[] = [\n 'image/png',\n 'image/jpeg',\n 'image/gif',\n 'image/webp',\n 'application/pdf',\n 'text/plain',\n 'text/csv',\n];\n\n/**\n * Optional `POST /agent/attachments` upload surface — mounted only when `AgentModuleOptions\n * .attachments.upload` (or the async config's `attachmentsUpload`) is `true` (see `agent.module.ts`).\n * Multipart single file field `'file'`, buffered in memory (no disk write — `FileInterceptor`'s\n * default storage) up to {@link HARD_MAX_ATTACHMENT_BYTES}, then validated against the configured\n * size cap + content-type allowlist and handed to the bound {@link AttachmentStagingStore} to\n * persist and turn into a model-fetchable URL. Both size gates answer `413`: the ceiling aborts the\n * upload mid-stream, the configured cap rejects what was read.\n *\n * `GET /agent/attachments` rides the same flag and returns the caller's own staged files as\n * metadata. Collection is NOT a route: a sweep needs a host-chosen age threshold and ends in the\n * host deleting bytes, so it stays an in-process call (`AgentService.collectableAttachments`)\n * rather than something reachable with a session cookie.\n */\n@Controller('attachments')\nexport class AttachmentsController implements OnModuleInit {\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n private readonly agents: AgentService,\n @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging: AttachmentStagingStore | undefined,\n ) {}\n\n /**\n * `attachments.upload: true` is what mounts this controller at all (see `agent.module.ts`), so by\n * the time an instance exists the host clearly intends uploads to work. Fail boot loudly rather\n * than mounting a controller that would 501 on every single request because nobody bound\n * `AGENT_ATTACHMENT_STAGING`.\n */\n onModuleInit(): void {\n if (this.options.attachments?.upload === true && this.staging === undefined) {\n throw new Error(\n 'AgentModule: attachments.upload is true but no AGENT_ATTACHMENT_STAGING provider is bound. ' +\n 'Bind one (e.g. `{ provide: AGENT_ATTACHMENT_STAGING, useClass: MyStagingStore }`) in a ' +\n 'module imported alongside AgentModule, or set attachments.upload to false.',\n );\n }\n }\n\n /**\n * The caller's own staged files, newest first — the one question `GET /agent/threads/:id` cannot\n * answer, since an upload that was never sent belongs to no thread.\n *\n * Scoped by the RESOLVED actor and nothing else. There is deliberately no `threadId` filter: a\n * thread's attachments already ride on its messages in the thread payload, and re-serving them\n * from here would add a second ownership path to get wrong for information the client already\n * holds. Metadata only — see {@link StagedAttachment}.\n */\n @Get()\n async list(@Req() req: Request): Promise<StagedAttachment[]> {\n const actor = await this.actorResolver.resolve(req);\n return this.agents.listAttachments(actor, { limit: ATTACHMENT_PAGE_SIZE });\n }\n\n @Post()\n @UseInterceptors(FileInterceptor('file', { limits: { fileSize: HARD_MAX_ATTACHMENT_BYTES } }))\n async upload(\n @Req() req: Request,\n @UploadedFile() file: Express.Multer.File | undefined,\n ): Promise<MessageAttachment> {\n if (this.staging === undefined) {\n // Reachable only if the module was built with attachments.upload left false/omitted while\n // this controller was somehow still wired up by hand — the normal boot path prevents this via\n // onModuleInit above. Kept as defense in depth with a precise status instead of a stack trace.\n throw new NotImplementedException('Attachment upload is not configured on this server.');\n }\n if (file === undefined) {\n throw new BadRequestException('multipart field \"file\" is required');\n }\n const allowedContentTypes =\n this.options.attachments?.allowedContentTypes ?? DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES;\n if (!allowedContentTypes.includes(file.mimetype)) {\n throw new UnsupportedMediaTypeException(\n `content type \"${file.mimetype}\" is not allowed (allowed: ${allowedContentTypes.join(', ')})`,\n );\n }\n const maxBytes = this.options.attachments?.maxBytes ?? DEFAULT_MAX_ATTACHMENT_BYTES;\n if (file.size > maxBytes) {\n throw new PayloadTooLargeException(`file exceeds the ${maxBytes}-byte limit`);\n }\n const actor = await this.actorResolver.resolve(req);\n return this.staging.stage({\n data: file.buffer,\n filename: file.originalname,\n contentType: file.mimetype,\n sizeBytes: file.size,\n actor,\n });\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n AgentStreamError,\n type AttachmentRef,\n type PageContext,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Body,\n Controller,\n Get,\n Inject,\n Param,\n Post,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n/**\n * How many attachments one turn may name. Each costs a staging-store read before the run starts,\n * and no model provider accepts anywhere near this many parts in a single message.\n */\nexport const MAX_ATTACHMENTS_PER_MESSAGE = 10;\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 /**\n * Files attached to this message (image/PDF), named by the `mediaId` `POST /agent/attachments`\n * (or the host's own upload) returned. Any other field sent alongside it is ignored.\n */\n attachments?: unknown;\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/**\n * Reduce whatever the body sent to the ids alone. A client cannot describe an attachment, only\n * point at one it staged: the url the model provider will fetch is resolved server-side from the\n * id (see `AgentService.chat`), so anything else here would be an SSRF the caller writes.\n */\nfunction attachmentRefs(claimed: unknown): AttachmentRef[] {\n if (claimed === undefined) {\n return [];\n }\n if (!Array.isArray(claimed)) {\n throw new BadRequestException('attachments must be an array of { mediaId }');\n }\n if (claimed.length > MAX_ATTACHMENTS_PER_MESSAGE) {\n throw new BadRequestException(\n `a message may carry at most ${MAX_ATTACHMENTS_PER_MESSAGE} attachments`,\n );\n }\n return claimed.map((entry: unknown) => {\n if (typeof entry !== 'object' || entry === null || !('mediaId' in entry)) {\n throw new BadRequestException('each attachment must be an object with a mediaId');\n }\n const { mediaId } = entry as { mediaId: unknown };\n if (typeof mediaId !== 'string' || mediaId.length === 0) {\n throw new BadRequestException('each attachment must carry a non-empty string mediaId');\n }\n return { mediaId };\n });\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 attachments = attachmentRefs(body.attachments);\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 ...(attachments.length > 0 ? { attachments } : {}),\n ...(body.pageContext !== undefined ? { pageContext: body.pageContext } : {}),\n ...(body.regenerate === true ? { regenerate: true } : {}),\n ...(body.transient === true ? { transient: true } : {}),\n });\n // The run was just started for this actor, so no ownership read is needed — and one would race\n // the run itself, which clears the thread's active stream (what ownership is derived from) the\n // moment it finishes.\n await this.pipe(res, runId, this.agent.subscribe(runId), threadId);\n }\n\n @Get('chat/:runId/stream')\n async stream(\n @Req() req: Request,\n @Param('runId') runId: string,\n @Res() res: Response,\n ): Promise<void> {\n const actor = await this.actorResolver.resolve(req);\n await this.pipe(res, runId, await this.agent.subscribeAs(actor, 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(\n res: Response,\n runId: string,\n events: AsyncIterable<Uint8Array>,\n threadId?: string,\n ): 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 // The sink now carries NDJSON `AgentStreamEvent`s (one `{...}\\n` per write). Forward each line\n // as an SSE `data:` frame verbatim — the client transport maps them to the AI SDK UI-message\n // chunk protocol. Buffer across chunk boundaries in case a transport batches multiple writes.\n const decoder = new TextDecoder();\n let buffer = '';\n try {\n for await (const chunk of events) {\n buffer += decoder.decode(chunk, { stream: true });\n let newline = buffer.indexOf('\\n');\n while (newline !== -1) {\n const line = buffer.slice(0, newline);\n buffer = buffer.slice(newline + 1);\n if (line.length > 0) {\n res.write(`data: ${line}\\n\\n`);\n }\n newline = buffer.indexOf('\\n');\n }\n }\n if (buffer.length > 0) {\n res.write(`data: ${buffer}\\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 {\n AGENT_ACTOR_RESOLVER,\n AGENT_MEMORY,\n type ActorResolver,\n type MemoryConfig,\n type MemoryDigestEntry,\n memoryForgetVerdict,\n offerMemories,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n Controller,\n Delete,\n ForbiddenException,\n Get,\n Inject,\n NotFoundException,\n Optional,\n Param,\n Query,\n Req,\n} from '@nestjs/common';\nimport type { Request } from 'express';\n\n/**\n * What the assistant believes about THIS caller — and how they take one of those beliefs back.\n *\n * WHY THIS EXISTS WHERE `GET /agent/skills` HAS NO WRITE SIBLING. A skill is authored by a person\n * who already knows it exists; a memory is written by the agent, about someone who does not. So the\n * read-back is not a convenience on top of the feature, it IS half of the feature: a belief nobody\n * can inspect is one nobody can correct, and a belief nobody can delete is one the deployment keeps\n * whether or not it is true. That is also why `MemoryProvider.forget` is required rather than\n * optional — see `memory.ts`.\n */\n@Controller('memories')\nexport class MemoriesController {\n constructor(\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n // Optional: bound to `undefined` when the host configured no memory, which is a valid wiring\n // rather than a missing dependency — the endpoints then answer with an empty list.\n @Optional() @Inject(AGENT_MEMORY) private readonly memory: MemoryConfig | undefined,\n ) {}\n\n /**\n * Every memory this actor can reach, most specific first, each carrying its origin and whatever\n * wider value it outranks.\n *\n * DELIBERATELY IGNORES `maxMemories`. That ceiling is a budget on what one TURN carries; applying\n * it here would mean a person could not see — and so could not delete — a belief the assistant is\n * one write away from acting on again. Showing someone more than the model sees is harmless;\n * showing them less is the failure this endpoint exists to prevent.\n */\n @Get()\n async list(\n @Req() req: Request,\n /** Only ever handed to the host's own resolver and provider; nothing here reads the thread. */\n @Query('threadId') threadId?: string,\n ): Promise<MemoryDigestEntry[]> {\n if (this.memory === undefined) {\n return [];\n }\n const actor = await this.actorResolver.resolve(req);\n return (await this.unbounded(threadId ?? '', actor)).entries;\n }\n\n /**\n * Forget one. Authorized against the actor's OWN resolved list, the same way a `skill` load is\n * authorized against the turn's catalog: an id this actor cannot see is answered as missing rather\n * than refused, so the endpoint cannot be used to find out which memories exist about other people.\n */\n @Delete(':id')\n async forget(@Req() req: Request, @Param('id') id: string): Promise<{ forgotten: boolean }> {\n if (this.memory === undefined) {\n throw new NotFoundException('No memory is configured in this deployment.');\n }\n const actor = await this.actorResolver.resolve(req);\n const digest = await this.unbounded('', actor);\n const entry = digest.entries.find((candidate) => candidate.id === id);\n if (entry === undefined) {\n throw new NotFoundException(`No memory with id \"${id}\".`);\n }\n const verdict = memoryForgetVerdict({ record: entry, actor });\n if (!verdict.allowed) {\n throw new ForbiddenException(verdict.reason);\n }\n return {\n forgotten: await this.memory.provider.forget({ id: entry.id, ctx: { actor, threadId: '' } }),\n };\n }\n\n private async unbounded(threadId: string, actor: Awaited<ReturnType<ActorResolver['resolve']>>) {\n // biome-ignore lint/style/noNonNullAssertion: every caller checks `memory` first.\n const config = this.memory!;\n return await offerMemories({\n config: { ...config, maxMemories: Number.POSITIVE_INFINITY },\n ctx: { actor, threadId },\n });\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 {\n AGENT_ACTOR_RESOLVER,\n AGENT_SKILLS,\n type ActorResolver,\n type SkillCatalogEntry,\n type SkillsConfig,\n offerSkills,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Optional, Query, Req } from '@nestjs/common';\nimport type { Request } from 'express';\n\n/**\n * Lists the skills available to THIS caller right now, scope-resolved — so a composer can offer them\n * after a `/` instead of hardcoding a list, and a settings screen can show which scope each came\n * from.\n *\n * THE SAME LIST THE MODEL IS OFFERED, built by the same call (`offerSkills`) against the same\n * provider and the same resolver. A second implementation of \"which skills apply\" would drift the\n * first time either was edited, and the drift would read to a user as a skill they can invoke that\n * the agent then says it has never heard of.\n *\n * Ownership posture mirrors `GET /agent/agents`: a plain array, no envelope, and nothing the caller\n * can pass to widen it — the actor comes from the resolver, never from a parameter.\n */\n@Controller('skills')\nexport class SkillsController {\n constructor(\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n // Optional: bound to `undefined` when the host configured no skills, which is a valid wiring\n // rather than a missing dependency — the endpoint then answers with an empty list.\n @Optional() @Inject(AGENT_SKILLS) private readonly skills: SkillsConfig | undefined,\n ) {}\n\n @Get()\n async list(\n @Req() req: Request,\n /**\n * The thread this list is for. Only ever handed to the host's own resolver and provider, which\n * may scope a skill to a conversation; nothing here reads the thread, so an unknown id widens\n * nothing. Omitted → the empty string, the same value a turn on a brand-new thread carries.\n */\n @Query('threadId') threadId?: string,\n ): Promise<SkillCatalogEntry[]> {\n if (this.skills === undefined) {\n return [];\n }\n const actor = await this.actorResolver.resolve(req);\n const offer = await offerSkills(this.skills, { actor, threadId: threadId ?? '' });\n return offer.entries;\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 UpdateThreadBody {\n title?: string;\n /** `null` clears the thread's default agent. Omitted → left untouched. */\n defaultAgent?: string | null;\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 /**\n * Renames the thread and/or sets its default agent. `defaultAgent` is only present in the request\n * body when the client actually sent the key (JSON has no `undefined`), so `'defaultAgent' in body`\n * distinguishes \"leave it alone\" from \"set it to null\" (clear it) unambiguously.\n */\n @Patch(':id')\n async update(\n @Req() req: Request,\n @Param('id') id: string,\n @Body() body: UpdateThreadBody,\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.updateThread(actor, id, {\n ...(body.title !== undefined ? { title: body.title } : {}),\n ...('defaultAgent' in body ? { defaultAgent: body.defaultAgent ?? null } : {}),\n });\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 { BadRequestException, Body, Controller, Inject, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n/**\n * Bounds on a human reply. A reply is journaled and re-read on every replay of the run it settles,\n * so a payload the loop cannot read is not a failed request — it is a run that fails identically\n * forever, burning its retries. Nothing here is signalled until it has been checked.\n */\nconst MAX_ANSWERED_QUESTIONS = 100;\nconst MAX_VALUES_PER_QUESTION = 100;\nconst MAX_ANSWER_VALUE_LENGTH = 4096;\n/** A rejection reason is read back by the model as the tool's result, so it is prompt input. */\nconst MAX_REJECT_REASON_LENGTH = 4096;\n\ninterface ApproveBody {\n toolCallId: unknown;\n}\ninterface RejectBody extends ApproveBody {\n reason?: unknown;\n}\ninterface AnswerBody extends ApproveBody {\n /**\n * questionId → chosen option values. Omit a question (or the whole object) to take the pre-picked\n * default the request was shown with — confirming is meant to be enough, so an empty body is a\n * valid submission rather than an error.\n */\n answers?: unknown;\n}\n\nfunction toolCallId(claimed: unknown): string {\n if (typeof claimed !== 'string' || claimed.length === 0) {\n throw new BadRequestException('toolCallId must be a non-empty string');\n }\n return claimed;\n}\n\nfunction rejectReason(claimed: unknown): string | undefined {\n if (claimed === undefined) {\n return undefined;\n }\n if (typeof claimed !== 'string') {\n throw new BadRequestException('reason must be a string');\n }\n if (claimed.length > MAX_REJECT_REASON_LENGTH) {\n throw new BadRequestException(`reason must be at most ${MAX_REJECT_REASON_LENGTH} characters`);\n }\n return claimed;\n}\n\nfunction answers(claimed: unknown): Record<string, string[]> | undefined {\n if (claimed === undefined) {\n return undefined;\n }\n if (typeof claimed !== 'object' || claimed === null || Array.isArray(claimed)) {\n throw new BadRequestException('answers must be an object of questionId → chosen values');\n }\n const entries = Object.entries(claimed);\n if (entries.length > MAX_ANSWERED_QUESTIONS) {\n throw new BadRequestException(`answers may cover at most ${MAX_ANSWERED_QUESTIONS} questions`);\n }\n // Null-prototype accumulator: a JSON body's own `__proto__` key would otherwise reach\n // Object.prototype's setter and silently drop the answer instead of carrying it.\n const validated: Record<string, string[]> = Object.create(null);\n for (const [questionId, values] of entries) {\n if (!Array.isArray(values)) {\n throw new BadRequestException(`answers[\"${questionId}\"] must be an array of chosen values`);\n }\n if (values.length > MAX_VALUES_PER_QUESTION) {\n throw new BadRequestException(\n `answers[\"${questionId}\"] may carry at most ${MAX_VALUES_PER_QUESTION} values`,\n );\n }\n for (const value of values) {\n if (typeof value !== 'string') {\n throw new BadRequestException(`answers[\"${questionId}\"] must contain only strings`);\n }\n if (value.length > MAX_ANSWER_VALUE_LENGTH) {\n throw new BadRequestException(\n `answers[\"${questionId}\"] values must be at most ${MAX_ANSWER_VALUE_LENGTH} characters`,\n );\n }\n }\n validated[questionId] = values as string[];\n }\n return validated;\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, toolCallId(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, toolCallId(body.toolCallId), rejectReason(body.reason));\n return { ok: true };\n }\n\n /**\n * Settle a parked question set. Alongside `approve`/`reject` rather than under a surface of its\n * own: an elicitation IS a parked tool call, gated by the same ownership check and delivered\n * through the same signal.\n */\n @Post('answer')\n async answer(@Req() req: Request, @Body() body: AnswerBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers));\n return { ok: true };\n }\n\n /** Decline to answer and let the agent proceed on the answers it pre-picked. */\n @Post('skip')\n async skip(@Req() req: Request, @Body() body: ApproveBody): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.skip(actor, toolCallId(body.toolCallId));\n return { ok: true };\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_DEPS_FACTORY,\n AGENT_REGISTRY,\n type ActorResolver,\n AgentRegistry,\n type ToolCatalogEntry,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, NotFoundException, Query, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\n\n/**\n * The tools THIS caller can reach through an agent, with how a chat surface should talk about each\n * one (`@AiTool({ presentation })`) — so a client narrates \"Querying orders\" instead of printing\n * `executeSql`, from words declared beside the tool's input schema rather than a client-side map\n * that goes stale on the next rename.\n *\n * THE SAME LIST THE MODEL IS OFFERED: built by `ToolRegistry.visibleSpecs`, the call behind\n * `definitionsFor`, against the agent's own allow-list, the roles policy and each tool's\n * `isEnabled`/`canUse`. Built-in tools the loop serves itself (`ask`, `skill`, `remember`) are not\n * registry tools and are not listed.\n *\n * Posture mirrors `GET /agent/skills`: a plain array, and nothing the caller can pass to widen it —\n * the actor comes from the resolver, and `agent` only ever narrows to that agent's allow-list.\n */\n@Controller('tools')\nexport class ToolsController {\n constructor(\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n @Inject(AGENT_DEPS_FACTORY) private readonly depsFactory: AgentDepsFactory,\n @Inject(AGENT_REGISTRY) private readonly agents: AgentRegistry,\n ) {}\n\n @Get()\n async list(\n @Req() req: Request,\n /** The agent whose tools to list. Omitted → the default agent, the one a turn naming none uses. */\n @Query('agent') agent?: string,\n ): Promise<ToolCatalogEntry[]> {\n // An unknown name would otherwise resolve to NO allow-list — every tool — which is the widest\n // answer this endpoint can give, for a typo.\n if (agent !== undefined && this.agents.get(agent) === undefined) {\n throw new NotFoundException(`No agent named \"${agent}\"`);\n }\n const actor = await this.actorResolver.resolve(req);\n const deps = this.depsFactory.forAgent(agent);\n const specs = await deps.registry.visibleSpecs(actor, deps.rolesPolicy, deps.toolAllowList);\n return specs.map((spec) => ({\n name: spec.name,\n kind: spec.kind,\n ...(spec.presentation !== undefined ? { presentation: spec.presentation } : {}),\n }));\n }\n}\n","import {\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_REGISTRY,\n type AgentDefinition,\n type AgentDelegation,\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 ...(meta.description !== undefined ? { description: meta.description } : {}),\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.maxDelegationDepth !== undefined\n ? { maxDelegationDepth: meta.maxDelegationDepth }\n : {}),\n ...(meta.maxAgentAppearances !== undefined\n ? { maxAgentAppearances: meta.maxAgentAppearances }\n : {}),\n ...(meta.history !== undefined ? { history: meta.history } : {}),\n ...(meta.outputSchema !== undefined ? { outputSchema: meta.outputSchema } : {}),\n ...(meta.intake !== undefined ? { intake: meta.intake } : {}),\n ...(meta.ask !== undefined ? { ask: meta.ask } : {}),\n ...(meta.outputRepairAttempts !== undefined\n ? { outputRepairAttempts: meta.outputRepairAttempts }\n : {}),\n ...(meta.handoff !== undefined ? { delegatesTo: this.handoffEdges(meta) } : {}),\n };\n }\n\n /**\n * Resolve each handoff entry to an {@link AgentDelegation} — its target's registered name, plus\n * whether that edge detaches (skipping non-agent classes). A bare name is kept for a plain edge\n * rather than an always-object form, so a definition an older host built by hand still reads.\n */\n private handoffEdges(meta: AgentOptions): AgentDelegation[] {\n const edges: AgentDelegation[] = [];\n for (const entry of meta.handoff ?? []) {\n const target = typeof entry === 'function' ? entry : entry.agent;\n const detached = typeof entry === 'function' ? false : entry.detached === true;\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 edges.push(detached ? { agent: targetMeta.name, detached: true } : targetMeta.name);\n }\n return edges;\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 { AgentHistoryWindow, AgentIntake } from '@dudousxd/nestjs-agent-core';\nimport type { Type } from '@nestjs/common';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\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 /**\n * How deep delegation may nest below this agent before further hops are refused. Default 5.\n *\n * Not a budget for how MANY agents a turn delegates to — that is the model's, one tool call each,\n * and nothing caps it. This bounds the chain a `delegatesTo` cycle would otherwise run forever.\n */\n maxDelegationDepth?: number;\n /**\n * How many times one agent may appear on a single delegation chain below this one. Default 1.\n *\n * This is the exact form of what {@link maxDelegationDepth} approximates: the loop compares a\n * delegation target against the chain that reached it, so a repeat is a cycle by inspection.\n * It counts APPEARANCES, so 2 admits exactly one deliberate return to an earlier agent.\n */\n maxAgentAppearances?: number;\n /** Allow-list of global tool names this agent may use. Omit → every tool its role allows. */\n tools?: string[];\n /**\n * Other `@Agent` classes this agent may hand off to (auto-exposed as handoff tools). A bare class\n * is the delegation that has always existed: this agent's turn waits for the answer.\n *\n * `{ agent, detached: true }` is the other shape — the delegate is STARTED and this agent's turn\n * ends without its answer, which arrives in the conversation later as its own message. Declared\n * per edge, by the author, and never by the model: the same worker is worth waiting for in one\n * orchestrator and worth backgrounding in another, and only the person wiring the edge knows\n * which side of that the user is sitting on.\n */\n handoff?: (Type | { agent: Type; detached?: boolean })[];\n /**\n * How much of the thread this agent's turns carry, overriding `AgentModule.forRoot({ history })`.\n * `{ maxMessages }` and/or `{ maxTokens }` keep the newest that fit; `{ summarize: true }` folds\n * the rest into a leading summary, at one extra model call per run. Omit → the module-wide\n * ceiling, or none.\n */\n history?: AgentHistoryWindow;\n /**\n * Constrain this agent's final answer to a schema (any [Standard Schema](https://standardschema.dev)\n * — Zod, Valibot, ArkType). The turn calls its tools exactly as it would without one; the schema is\n * satisfied by one extra formatting call afterwards, so it works on providers that refuse a\n * response format and a tool set in the same request. The validated value comes back as `object`\n * on the run's result and is recorded on the assistant message as a `structured_output` tool call.\n *\n * Declared HERE rather than per request: a schema is a live object, and `AgentRunInput` crosses a\n * JSON boundary on its way into a durable workflow.\n */\n outputSchema?: StandardSchemaV1;\n /**\n * Extra model calls allowed to fix an answer that failed {@link outputSchema}, each shown the\n * previous attempt's validation issues. Omit → 1; `0` → fail on the first invalid reply with a\n * `StructuredOutputError`.\n */\n outputRepairAttempts?: number;\n /**\n * Questions this agent puts to the user BEFORE it starts working — the scope it needs, collected\n * up front rather than guessed. Authored here, so the turn spends no model call producing them\n * and a client knows the total (\"Question 1 of 3\") the moment the form appears. Every question\n * should pre-pick a default: the claim the surface makes is that confirming is enough.\n *\n * `when: 'thread-start'` (the default) asks once per thread; `'every-turn'` asks before each turn.\n * Omit → no intake.\n */\n intake?: AgentIntake;\n /**\n * Let the model ask its OWN clarifying question set, via the built-in `ask` tool, when it judges\n * the scope is missing. Overrides `AgentModule.forRoot({ ask })` for this agent. Omit → the\n * module-wide setting.\n */\n ask?: boolean;\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 Actor,\n type AgentRegistry,\n type ToolHandler,\n type ToolRegistry,\n normalizeDelegation,\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 ...(meta.enabled !== undefined ? { enabled: meta.enabled } : {}),\n ...(meta.presentation !== undefined ? { presentation: meta.presentation } : {}),\n },\n {\n execute: (input, ctx) => (instance as ToolHandler).execute(input, ctx),\n // Forwarded, not copied: the registry holds this wrapper rather than the provider, so an\n // `isEnabled()`/`canUse()` left behind here would be a gate that silently never applies.\n // Called through `instance` so each keeps its `this` (and its injected deps).\n ...(typeof handler.isEnabled === 'function'\n ? { isEnabled: () => (instance as Required<ToolHandler>).isEnabled() }\n : {}),\n ...(typeof handler.canUse === 'function'\n ? { canUse: (actor: Actor) => (instance as Required<ToolHandler>).canUse(actor) }\n : {}),\n },\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 edge of definition.delegatesTo ?? []) {\n const { agent: target, detached } = normalizeDelegation(edge);\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, detached });\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 // A detached edge's description is the model's only warning that this call hands back a\n // receipt: a tool advertised as returning an answer, which then returns something else, is\n // a model that reports an answer it was never given.\n const description = detached\n ? `Start the \"${target}\" agent working on a task in the BACKGROUND. Returns immediately with a receipt, NOT an answer — the answer is delivered to this conversation as a separate message later. Use it for work the user does not need to sit and wait for.${targetBlurb}`\n : `Delegate a task to the \"${target}\" agent and get its answer.${targetBlurb}`;\n this.registry.register(\n {\n name,\n kind: 'agent',\n targetAgent: target,\n ...(detached ? { detached: true } : {}),\n description,\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 { ToolPresentation } from '@dudousxd/nestjs-agent-core';\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 * Whether this tool exists in this deployment. `false` — or a predicate returning `false`, which\n * is re-evaluated every turn — drops it before the role filter, so the model is never shown it.\n * Omit → enabled.\n *\n * Use this for availability that is knowable without DI (a constant, `process.env`, a closure\n * over something the app already holds). When the answer lives in an injected service, implement\n * `isEnabled()` on the class instead: this object is built while the decorator is evaluated, at\n * import time, and can't reach the container.\n */\n enabled?: boolean | (() => boolean | Promise<boolean>);\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 * How a chat surface talks about this tool without naming it — sentence templates over the\n * call's input, an icon key, the approval prompt's wording, and how its output reads. Never shown\n * to the model. Served by `GET <base>/tools` to the actors who can reach the tool:\n *\n * ```ts\n * @AiTool({\n * name: 'purgeCache', kind: 'action', description: '…', input,\n * presentation: {\n * label: 'Cache purge', running: 'Purging {key}', done: 'Purged {key}', icon: 'cache',\n * tone: 'destructive', confirm: { title: 'Purge {key}?', verb: 'Purge' },\n * },\n * })\n * ```\n */\n presentation?: ToolPresentation;\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 *\n * A tool the deployment can turn off — the flag read through DI, so `.env` and a config service\n * both work:\n *\n * ```ts\n * @AiTool({ name: 'searchDocs', kind: 'read', description: '...', input: schema })\n * class SearchDocsTool implements ToolHandler<Input> {\n * constructor(private readonly config: ConfigService) {}\n * isEnabled() { return this.config.get('DOCS_SEARCH_ENABLED') === 'true'; }\n * async execute(input, ctx) { ... }\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 { AGENT_SKILL_SOURCES, type SkillContext } from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, type OnModuleInit } from '@nestjs/common';\nimport { DiscoveryService } from '@nestjs/core';\nimport { readSkillMetadata, skillScope } from '../decorator/skill.decorator.js';\n\n/**\n * One `@Skill`-decorated provider, reduced to what a `SkillProvider` needs: its catalog line, and a\n * bound function that produces its body for a turn.\n */\nexport interface DeclaredSkill {\n name: string;\n description: string;\n scope: string;\n body(ctx: SkillContext): string | Promise<string>;\n}\n\n/**\n * Collects every `@Skill`-decorated provider into the shared list the module's skill provider reads\n * — the discovery counterpart to authoring skills as rows in the host's own table. Both sources feed\n * one catalog; see `AgentModuleOptions.skills`.\n *\n * A class with neither a flat `body` nor a `body()` method is skipped with a warning rather than\n * offered: a skill the model can see and load, that then returns nothing, reads to it as an\n * instruction to do nothing in particular — which is worse than the skill not existing.\n */\n@Injectable()\nexport class SkillDiscoveryService implements OnModuleInit {\n private readonly logger = new Logger(SkillDiscoveryService.name);\n\n constructor(\n private readonly discovery: DiscoveryService,\n @Inject(AGENT_SKILL_SOURCES) private readonly declared: DeclaredSkill[],\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 = readSkillMetadata(instance.constructor);\n if (meta === undefined) {\n continue;\n }\n const body = this.bodyOf(instance, meta.body);\n if (body === undefined) {\n this.logger.warn(\n `Skill \"${meta.name}\" declares no body — add a \\`body()\\` method or \\`@Skill({ body })\\`. Skipped.`,\n );\n continue;\n }\n this.declared.push({\n name: meta.name,\n description: meta.description,\n scope: skillScope(meta),\n body,\n });\n }\n }\n\n /** The instance's `body()` method (bound), else the flat string, else nothing to offer. */\n private bodyOf(\n instance: object,\n flat: string | undefined,\n ): ((ctx: SkillContext) => string | Promise<string>) | undefined {\n const candidate = (instance as { body?: unknown }).body;\n if (typeof candidate === 'function') {\n return (ctx: SkillContext) =>\n (candidate as (ctx: SkillContext) => string | Promise<string>).call(instance, ctx);\n }\n return flat === undefined ? undefined : () => flat;\n }\n}\n","import 'reflect-metadata';\nimport { GLOBAL_SCOPE, type SkillContext } from '@dudousxd/nestjs-agent-core';\nimport type { Type } from '@nestjs/common';\n\n/**\n * Declares a provider class as a skill: an authored procedure any agent may pull in when a task\n * calls for it. Discovered at boot and offered to every turn whose scopes include its `scope`.\n *\n * NOT AN AGENT. An `@Agent` is who is answering — its model, its tools, its history ceiling. A skill\n * is how one task is done, and carries none of those: what it contributes is text, at a scope, under\n * a name the model can ask for. An instruction that should apply to EVERY turn of an agent is that\n * agent's `systemPrompt` (or a `@SystemPromptContributor()`), not a skill — a skill is for the ones\n * that should apply only when the work calls for them, which is what stops them costing a prompt.\n *\n * The class is an ordinary provider, so it gets constructor DI — the reason a skill is a class and\n * not a config entry. The body is either the flat `body` string here or a `body(ctx)` method on the\n * class (which may read the turn's {@link SkillContext} and inject services); implement\n * {@link SkillBody} to have the compiler hold you to its shape.\n */\nexport interface SkillOptions {\n /** Unique within its scope. What the model passes to the `skill` tool, and the `/` handle a UI offers. */\n name: string;\n /**\n * One line: what task this covers. Read by the MODEL to decide whether to load it, and by a person\n * choosing from an autocomplete — so write what it is FOR, not what it contains.\n */\n description: string;\n /**\n * The scope token this skill is published at. Omit → `'global'`, the deployment-wide default. Any\n * string a host's `ScopeResolver` can return works: `'tenant:berlin'`, `'sector:logistics'`.\n */\n scope?: string;\n /** A flat body. For one built per actor or per page, add a `body()` method instead. */\n body?: string;\n}\n\n/** The shape a `@Skill` class's body method takes. Implement it to be held to it at compile time. */\nexport interface SkillBody {\n body(ctx: SkillContext): string | Promise<string>;\n}\n\nexport const SKILL_METADATA = Symbol.for('@dudousxd/nestjs-agent:skill-metadata');\n\n/** Marks a provider class as a skill. See {@link SkillOptions}. */\nexport function Skill(options: SkillOptions): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(SKILL_METADATA, options, target);\n };\n}\n\n/** Reads {@link SkillOptions} off a class, or `undefined` if it is not a `@Skill`. */\n// biome-ignore lint/complexity/noBannedTypes: the reflection target's type is precisely `Type | Function`.\nexport function readSkillMetadata(target: Type | Function): SkillOptions | undefined {\n return Reflect.getMetadata(SKILL_METADATA, target) as SkillOptions | undefined;\n}\n\n/** The scope a `@Skill` publishes at — its own, or the deployment-wide default. */\nexport function skillScope(options: SkillOptions): string {\n return options.scope ?? GLOBAL_SCOPE;\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(_actorRef: string, _day: string, _tokens: number): 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 type DetachedDelivery,\n type ElicitationReply,\n type HumanReply,\n RunCancelledError,\n agentFailureCode,\n encodeStreamEvent,\n publishAgentRunFailed,\n runAgentLoop,\n settleAll,\n settleUnsettledDelegation,\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<\n string,\n { resolve: (reply: HumanReply) => void; reject: (error: unknown) => void }\n >();\n /**\n * Runs someone has asked to stop. In-process, like `pending`, and for the same reason: this runner\n * is single-replica by construction, so the request is readable by the only loop that could be\n * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.\n */\n private readonly cancelled = new Set<string>();\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({\n runId,\n deps,\n actor: input.actor,\n day,\n threadId: input.threadId,\n chainBelow: [\n ...(input.delegationPath ?? []),\n ...(input.agentName !== undefined ? [input.agentName] : []),\n ],\n });\n\n void runAgentLoop({ ...deps, day }, input, hooks)\n .then(() => this.store.setActiveStream(input.threadId, null))\n .catch(async (error) => {\n if (error instanceof RunCancelledError) {\n await this.settleCancelled(runId, input.threadId, deps);\n return;\n }\n const message = error instanceof Error ? error.message : String(error);\n const code = agentFailureCode(error);\n this.logger.error(`agent run ${runId} failed (${code}): ${message}`);\n publishAgentRunFailed({ runId, code, message });\n // Settle the run's persisted outcome (the loop only records completions — it can't catch\n // its own crash). Optional-call: a store without run recording skips reliability metrics.\n await this.store.recordRunEnd?.({\n runId,\n status: 'failed',\n errorCode: code,\n errorMessage: message,\n });\n // Clear the thread's active run — a failed run isn't \"still running\" for `activeRunForThread`.\n await this.store.setActiveStream(input.threadId, null);\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 .finally(() => this.cancelled.delete(runId));\n\n return { runId };\n }\n\n async signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void> {\n const key = `${runId}:${toolCallId}`;\n const waiter = this.pending.get(key);\n if (waiter !== undefined) {\n this.pending.delete(key);\n waiter.resolve(reply);\n }\n }\n\n /**\n * Ask a run to stop, and settle whatever it was parked on.\n *\n * The loop observes the request at its next safe point (between steps, before the turn's tools) and\n * unwinds from there — so a tool already executing is left to finish, and its result is recorded\n * exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait\n * is a promise nobody is going to resolve, so it is REJECTED here with the same\n * {@link RunCancelledError} the loop would have thrown, and the run unwinds through the identical\n * path.\n *\n * Settlement — the run row, the thread's active stream, the stream's terminal — belongs to the\n * `RunCancelledError` catch in `start`, so a cancel and an ordinary failure settle in one place\n * each and can never both write.\n */\n async cancel(runId: string): Promise<void> {\n this.cancelled.add(runId);\n for (const [key, waiter] of this.pending) {\n if (key.startsWith(`${runId}:`)) {\n this.pending.delete(key);\n waiter.reject(new RunCancelledError());\n }\n }\n await Promise.resolve();\n }\n\n /**\n * The single place a cancelled run's state is settled: recorded as its own terminal (never\n * `failed` — a user pressing Stop must not land in someone's error rate), the thread released, and\n * the stream ENDED after a `cancelled` frame rather than failed, so a client that retries failed\n * streams does not retry this one.\n */\n private async settleCancelled(runId: string, threadId: string, deps: AgentDeps): Promise<void> {\n this.logger.log(`agent run ${runId} cancelled`);\n await this.store.setActiveStream(threadId, null);\n const writer = await deps.sink.open(runId);\n await writer.write(encodeStreamEvent({ kind: 'cancelled' }));\n await writer.end();\n // Last, so the reader is released before the bookkeeping: everything above is what someone is\n // waiting on, and the run row is what someone reads afterwards.\n await this.store.recordRunEnd?.({ runId, status: 'cancelled' });\n }\n\n /**\n * Park a run on a human, keyed by run + tool call. One map for approvals and for question-set\n * answers alike: both wait on the same key, and `signal` cannot tell (or need to tell) which\n * shape it is delivering — the loop asked for one and only ever gets what the caller sent. A\n * cancel settles the wait too, by rejecting it.\n */\n private park<T extends HumanReply>(runId: string, toolCallId: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this.pending.set(`${runId}:${toolCallId}`, {\n resolve: resolve as (reply: HumanReply) => void,\n reject,\n });\n });\n }\n\n private topLevelHooks(args: {\n runId: string;\n deps: AgentDeps;\n actor: Actor;\n day: string;\n threadId: string;\n /** This run's delegation chain with its own agent appended — see `AgentRunInput.delegationPath`. */\n chainBelow: readonly string[];\n }): AgentLoopHooks {\n const { runId, deps, actor, day, threadId, chainBelow } = args;\n return {\n runId,\n openSink: () => deps.sink.open(runId),\n awaitApproval: (call) => this.park<Decision>(runId, call.id),\n awaitAnswers: (request) => this.park<ElicitationReply>(runId, request.id),\n step: (_name, fn) => fn(),\n parallel: settleAll,\n cancelled: async () => this.cancelled.has(runId),\n runAgent: (agentName, task) =>\n this.runNested({\n agentName,\n task,\n actor,\n day,\n depth: 1,\n path: chainBelow,\n sinkRunId: runId,\n parentRunId: runId,\n }),\n startAgent: ({ agentName, task, toolCallId }) =>\n this.startDetached({\n agentName,\n task,\n actor,\n day,\n depth: 1,\n path: chainBelow,\n parentRunId: runId,\n deliverTo: { threadId, toolCallId },\n }),\n };\n }\n\n /**\n * Delegate WITHOUT waiting: a nested loop nobody awaits, on its own thread and its own sink, which\n * posts its answer back into the delegating thread when it lands (`deliverTo`, settled by the\n * loop). The calling turn gets the run id straight back and finishes.\n *\n * No `sinkRunId`, unlike {@link runNested}: forwarding into the stream the human is watching would\n * write into a turn that has already ended. Its own approvals resolve through the shared pending\n * map keyed by its own runId — which is what the pending-approvals surface routes to.\n */\n private async startDetached(args: {\n agentName: string;\n task: string;\n actor: Actor;\n day: string;\n depth: number;\n /** The chain that reached this child, root first. */\n path: readonly string[];\n parentRunId: string;\n deliverTo: DetachedDelivery;\n }): Promise<{ runId: string }> {\n const { agentName, task, actor, day, depth, path, parentRunId, deliverTo } = args;\n const subThread = await this.store.createThread({ actor, transient: true });\n const runId = crypto.randomUUID();\n // Marks the subthread as streaming this run, exactly as a sub-agent's does: it is what routes a\n // human decision on its action tools back to it, and what lets a client attach to its stream.\n await this.store.setActiveStream(subThread.id, runId);\n const deps = this.factory.forAgent(agentName);\n const hooks: AgentLoopHooks = {\n runId,\n openSink: () => deps.sink.open(runId),\n awaitApproval: (call) => this.park<Decision>(runId, call.id),\n awaitAnswers: (request) => this.park<ElicitationReply>(runId, request.id),\n step: (_name, fn) => fn(),\n parallel: settleAll,\n cancelled: async () => this.cancelled.has(runId),\n runAgent: (childName, childTask) =>\n this.runNested({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n // A detached run owns a stream of its own, so ITS sub-agents forward into that one.\n sinkRunId: runId,\n parentRunId: runId,\n }),\n startAgent: ({ agentName: childName, task: childTask, toolCallId }) =>\n this.startDetached({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n parentRunId: runId,\n deliverTo: { threadId: subThread.id, toolCallId },\n }),\n };\n void runAgentLoop(\n { ...deps, day },\n {\n threadId: subThread.id,\n actor,\n userText: task,\n agentName,\n day,\n delegationDepth: depth,\n delegationPath: path,\n parentRunId,\n deliverTo,\n },\n hooks,\n )\n .catch(async (error: unknown) => {\n const cancelled = error instanceof RunCancelledError;\n const message = error instanceof Error ? error.message : String(error);\n if (!cancelled) {\n this.logger.error(`detached agent run ${runId} failed: ${message}`);\n publishAgentRunFailed({ runId, code: agentFailureCode(error), message });\n }\n await this.store.recordRunEnd?.({\n runId,\n status: cancelled ? 'cancelled' : 'failed',\n ...(cancelled ? {} : { errorCode: agentFailureCode(error), errorMessage: message }),\n });\n // The loop delivers its own success; a run that never produced an answer has to settle the\n // delegation itself, or the calling conversation shows \"started\" for ever.\n await settleUnsettledDelegation({\n store: this.store,\n delivery: deliverTo,\n agent: agentName,\n runId,\n status: cancelled ? 'cancelled' : 'failed',\n ...(cancelled ? {} : { error: message }),\n });\n })\n .finally(async () => {\n this.cancelled.delete(runId);\n await this.store.setActiveStream(subThread.id, null);\n });\n return { runId };\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(args: {\n agentName: string;\n task: string;\n actor: Actor;\n day: string;\n depth: number;\n /** The chain that reached this child, root first. */\n path: readonly string[];\n sinkRunId: string;\n parentRunId: string;\n }): Promise<{ text: string }> {\n const { agentName, task, actor, day, depth, path, sinkRunId, parentRunId } = args;\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) => this.park<Decision>(runId, call.id),\n awaitAnswers: (request) => this.park<ElicitationReply>(runId, request.id),\n step: (_name, fn) => fn(),\n parallel: settleAll,\n // A child stops when it is cancelled OR when the run a human is actually watching is: the\n // canceller names the top-level run, which is the only id that ever left the server.\n cancelled: async () => this.cancelled.has(runId) || this.cancelled.has(sinkRunId),\n runAgent: (childName, childTask) =>\n this.runNested({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n sinkRunId,\n parentRunId: runId,\n }),\n startAgent: ({ agentName: childName, task: childTask, toolCallId }) =>\n this.startDetached({\n agentName: childName,\n task: childTask,\n actor,\n day,\n depth: depth + 1,\n path: [...path, agentName],\n parentRunId: runId,\n deliverTo: { threadId: subThread.id, toolCallId },\n }),\n };\n try {\n return await runAgentLoop(\n { ...deps, day },\n {\n threadId: subThread.id,\n actor,\n userText: task,\n agentName,\n day,\n delegationDepth: depth,\n delegationPath: path,\n parentRunId,\n sinkRunId,\n },\n hooks,\n );\n } finally {\n // No durable-style suspend to worry about here (inline runs to completion synchronously from\n // this call's point of view) — always clear so `activeRunForThread` reflects reality.\n await this.store.setActiveStream(subThread.id, null);\n }\n }\n}\n","import {\n type SkillContext,\n type SkillProvider,\n type SkillsConfig,\n compositeSkillProvider,\n} from '@dudousxd/nestjs-agent-core';\nimport type { AgentSkillsOptions } from './agent.options.js';\nimport type { DeclaredSkill } from './discovery/skill-discovery.service.js';\n\n/**\n * The `@Skill`-decorated classes as a `SkillProvider`. Reads `declared` on every call rather than\n * capturing its contents: DI builds the provider before `SkillDiscoveryService` has filled the list.\n */\nexport function declaredSkillProvider(declared: readonly DeclaredSkill[]): SkillProvider {\n return {\n list: ({ scopes }) =>\n declared\n .filter((skill) => scopes.includes(skill.scope))\n .map(({ name, description, scope }) => ({ name, description, scope })),\n load: async ({ name, scope, ctx }) => {\n const match = declared.find((skill) => skill.name === name && skill.scope === scope);\n return match === undefined ? null : await match.body(ctx);\n },\n };\n}\n\n/**\n * The turn's skills seam, or `undefined` where the host configured none — which is also what keeps\n * a deployment that declares no skills from spending the `skills:catalog` checkpoint.\n *\n * DISCOVERED `@Skill` CLASSES ALONE DO NOT TURN SKILLS ON. Adding a decorated class would otherwise\n * insert a checkpoint into every turn, and a run already in flight when that deployment rolled would\n * replay against a sequence one position short. `skills: {}` is the opt-in; a class discovered\n * without it is reported at boot rather than silently inert.\n */\nexport function resolveSkillsConfig(\n options: AgentSkillsOptions | undefined,\n declared: readonly DeclaredSkill[],\n): SkillsConfig | undefined {\n if (options === undefined) {\n return undefined;\n }\n // The host's own provider first: between two skills of the same name AT THE SAME SCOPE, the one\n // it can edit without a deploy is the better answer. Scope still outranks source for everything\n // else — see `compositeSkillProvider`.\n const providers =\n options.provider === undefined\n ? [declaredSkillProvider(declared)]\n : [options.provider, declaredSkillProvider(declared)];\n return {\n provider:\n providers.length === 1 ? (providers[0] as SkillProvider) : compositeSkillProvider(providers),\n ...(options.scopes !== undefined ? { scopes: options.scopes } : {}),\n ...(options.maxSkills !== undefined ? { maxSkills: options.maxSkills } : {}),\n };\n}\n","import type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { UnauthorizedException } from '@nestjs/common';\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 rejects with `UnauthorizedException` when `x-actor-id` is absent — it never\n * fabricates an identity, and never grants a default role (an actor with no `x-actor-role` gets\n * `roles: []`, i.e. no tools). Trusting client headers is only safe behind a gateway that strips\n * and re-sets them from an authenticated principal. Real deployments should provide their own resolver\n * that reads a verified session/JWT instead of installing this one. A custom resolver should\n * reject the same way: a plain `Error` surfaces to the caller as a 500 with a logged stack, which\n * both misreports an unauthenticated request and turns anonymous probes into error noise.\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 UnauthorizedException(\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"],"mappings":"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","names":["AgentDepsFactory","import_nestjs_agent_core","import_common","import_core","import_nestjs_agent_core","delegateToolName","args","slug","target","replace","detached","AgentDepsFactory","options","model","store","sink","rolesPolicy","registry","agents","promptContributors","quota","pricingStore","skills","memory","memoryConfig","skillsConfig","defaultAgentName","defaultAgent","undefined","registered","list","length","name","effectiveTools","definition","delegated","delegatesTo","map","edge","agent","normalizeDelegation","tools","forAgent","agentName","get","toolAllowList","followUpsCount","retrieval","historyPolicy","ask","systemPrompt","maxSteps","maxDelegationDepth","maxAgentAppearances","modelId","inputProcessors","outputProcessors","outputSchema","outputRepairAttempts","intake","toolTimeoutMs","toolTransientRetry","mode","retriever","topK","retrievalTopK","history","window","config","windowHistory","maxMessages","maxTokens","summarize","summarizeWithModel","followUps","count","import_nestjs_agent_core","import_common","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","fail","AgentService","runner","store","deps","quota","staging","chat","params","agentName","resolveAgentName","threadId","attachments","resolveAttachments","actor","undefined","regenerate","BadRequestException","created","createThread","transient","id","assertOwnsThread","input","userText","message","day","utcDay","length","pageContext","runId","start","setActiveStream","refs","resolve","NotImplementedException","resolved","ref","attachment","mediaId","ForbiddenException","push","subscribe","forAgent","sink","subscribeAs","assertOwnsActiveStream","approve","toolCallId","assertOwnsToolCall","signalToolCall","approved","reject","reason","answer","answers","reply","answeredByRef","skip","skipped","resolveRunForToolCall","signal","cancel","listThreads","actorRef","threads","Promise","all","map","thread","toSummaryView","getThread","toDetailView","deleteThread","softDeleteThread","forkThread","fromMessageId","renameThread","title","updateThread","patch","validateTitle","defaultAgent","setTitle","trimmed","trim","threadDefault","threadDefaultAgent","defaultAgentName","projecting","defaultAgentForThread","activeRunId","activeRunForThread","summary","messages","activeStreamId","promoteThread","truncateThreadFrom","messageId","truncateFrom","listAttachments","options","list","attachmentInventory","limit","collectableAttachments","referencedMediaIds","bind","stagedBefore","olderThan","toISOString","inventory","aged","filter","entry","createdAt","referenced","Set","has","quotaToday","usedTokens","costUsd","limitTokens","withinLimit","state","check","owner","ownerOfThread","NotFoundException","ownerOfToolCall","runForToolCall","ownerOfActiveStream","import_common","AgentApprovalPortAdapter","agent","approve","toolCallId","opts","signalToolCall","approved","executedByRef","undefined","reject","reason","import_nestjs_agent_core","import_common","AgentsController","agents","depsFactory","list","defaultAgentName","map","definition","name","description","isDefault","import_nestjs_agent_core","import_common","DEFAULT_MAX_ATTACHMENT_BYTES","HARD_MAX_ATTACHMENT_BYTES","ATTACHMENT_PAGE_SIZE","DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES","AttachmentsController","options","actorResolver","agents","staging","onModuleInit","attachments","upload","undefined","Error","list","req","actor","resolve","listAttachments","limit","file","NotImplementedException","BadRequestException","allowedContentTypes","includes","mimetype","UnsupportedMediaTypeException","join","maxBytes","size","PayloadTooLargeException","stage","data","buffer","filename","originalname","contentType","sizeBytes","limits","fileSize","import_nestjs_agent_core","import_common","MAX_ATTACHMENTS_PER_MESSAGE","attachmentRefs","claimed","undefined","Array","isArray","BadRequestException","length","map","entry","mediaId","ChatController","agent","actorResolver","chat","req","res","body","actor","resolve","attachments","runId","threadId","message","agentName","pageContext","regenerate","transient","pipe","subscribe","stream","subscribeAs","cancel","aborted","events","setHeader","write","JSON","stringify","decoder","TextDecoder","buffer","chunk","decode","newline","indexOf","line","slice","error","payload","AgentStreamError","code","Error","end","import_nestjs_agent_core","import_common","MemoriesController","actorResolver","memory","list","req","threadId","undefined","actor","resolve","unbounded","entries","forget","id","NotFoundException","digest","entry","find","candidate","verdict","memoryForgetVerdict","record","allowed","ForbiddenException","reason","forgotten","provider","ctx","config","offerMemories","maxMemories","Number","POSITIVE_INFINITY","import_nestjs_agent_core","import_common","QuotaController","agent","actorResolver","today","req","actor","resolve","quotaToday","id","import_nestjs_agent_core","import_common","SkillsController","actorResolver","skills","list","req","threadId","undefined","actor","resolve","offer","offerSkills","entries","import_nestjs_agent_core","import_common","ThreadsController","agent","actorResolver","list","req","actor","resolve","listThreads","id","detail","getThread","remove","deleteThread","ok","fork","messageId","forkThread","update","body","updateThread","title","undefined","defaultAgent","promote","promoteThread","truncateFrom","truncateThreadFrom","import_nestjs_agent_core","import_common","MAX_ANSWERED_QUESTIONS","MAX_VALUES_PER_QUESTION","MAX_ANSWER_VALUE_LENGTH","MAX_REJECT_REASON_LENGTH","toolCallId","claimed","length","BadRequestException","rejectReason","undefined","answers","Array","isArray","entries","Object","validated","create","questionId","values","value","ToolCallController","agent","actorResolver","approve","req","body","actor","resolve","ok","reject","reason","answer","skip","import_nestjs_agent_core","import_common","ToolsController","actorResolver","depsFactory","agents","list","req","agent","undefined","get","NotFoundException","actor","resolve","deps","forAgent","specs","registry","visibleSpecs","rolesPolicy","toolAllowList","map","spec","name","kind","presentation","import_nestjs_agent_core","import_common","AGENT_METADATA","Symbol","for","Agent","options","target","Reflect","defineMetadata","readAgentMetadata","getMetadata","import_reflect_metadata","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","description","tools","model","modelId","maxSteps","maxDelegationDepth","maxAgentAppearances","history","outputSchema","intake","ask","outputRepairAttempts","handoff","delegatesTo","handoffEdges","edges","entry","target","agent","detached","targetMeta","warn","push","prototype","Object","getPrototypeOf","getAllMethodNames","Reflect","getMetadata","SYSTEM_PROMPT_CONTRIBUTOR_METADATA","method","boundMethod","metadataKey","candidate","call","import_nestjs_agent_core","import_common","import_core","import_reflect_metadata","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","enabled","presentation","ctx","isEnabled","canUse","actor","tool","tools","delegates","definition","list","edge","delegatesTo","agent","target","detached","normalizeDelegation","targetDefinition","get","Error","delegateToolName","has","targetBlurb","systemPrompt","targetAgent","z","object","task","string","log","spec","import_nestjs_agent_core","import_common","import_core","import_reflect_metadata","import_nestjs_agent_core","SKILL_METADATA","Symbol","for","Skill","options","target","Reflect","defineMetadata","readSkillMetadata","getMetadata","skillScope","scope","GLOBAL_SCOPE","SkillDiscoveryService","logger","Logger","name","discovery","declared","onModuleInit","wrapper","getProviders","instance","meta","readSkillMetadata","undefined","body","bodyOf","warn","push","description","scope","skillScope","flat","candidate","ctx","call","import_nestjs_agent_core","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","_actorRef","_day","_tokens","import_nestjs_agent_core","import_common","InlineAgentRunner","logger","Logger","name","pending","Map","cancelled","Set","factory","store","start","input","runId","crypto","randomUUID","day","utcDay","deps","forAgent","agentName","hooks","topLevelHooks","actor","threadId","chainBelow","delegationPath","undefined","runAgentLoop","then","setActiveStream","catch","error","RunCancelledError","settleCancelled","message","Error","String","code","agentFailureCode","publishAgentRunFailed","recordRunEnd","status","errorCode","errorMessage","writer","sink","open","fail","finally","delete","signal","toolCallId","reply","key","waiter","get","resolve","cancel","add","startsWith","reject","Promise","log","write","encodeStreamEvent","kind","end","park","set","args","openSink","awaitApproval","call","id","awaitAnswers","request","step","_name","fn","parallel","settleAll","has","runAgent","task","runNested","depth","path","sinkRunId","parentRunId","startAgent","startDetached","deliverTo","subThread","createThread","transient","childName","childTask","userText","delegationDepth","settleUnsettledDelegation","delivery","agent","childSinkWriter","import_nestjs_agent_core","declaredSkillProvider","declared","list","scopes","filter","skill","includes","scope","map","name","description","load","ctx","match","find","undefined","body","resolveSkillsConfig","options","providers","provider","length","compositeSkillProvider","maxSkills","DEFAULT_PATH","sharedProviders","durable","includeStore","providers","provide","AGENT_TOOL_REGISTRY","useFactory","ToolRegistry","AGENT_REGISTRY","AgentRegistry","AGENT_PROMPT_CONTRIBUTORS","AGENT_SKILL_SOURCES","AGENT_SKILLS","options","declared","resolveSkillsConfig","skills","inject","AGENT_OPTIONS","AGENT_MEMORY","memory","AGENT_SINK","sink","InProcessTokenStreamSink","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","SkillDiscoveryService","InlineAgentRunner","AgentService","AgentApprovalPortAdapter","AGENT_APPROVAL_PORT","push","AGENT_RUNNER","durableRunner","Error","token","AGENT_DURABLE_RUNNER","optional","exportsFor","BASE_CONTROLLERS","ChatController","ThreadsController","ToolCallController","QuotaController","AgentsController","SkillsController","MemoriesController","ToolsController","GUARDABLE_CONTROLLERS","AttachmentsController","controllersFor","mountAttachments","controllersForSurface","surface","GUARDS_METADATA","applyGuards","guards","resolved","controller","Reflect","defineMetadata","guardProviders","Set","routerFor","path","RouterModule","register","module","AgentModule","forRoot","global","imports","DiscoveryModule","controllers","attachments","upload","useValue","exports","forRootAsync","externalStore","attachmentsUpload","args","import_common","readHeader","req","name","undefined","headers","value","Reflect","get","HeaderActorResolver","resolve","id","length","UnauthorizedException","roles","split","map","role","trim","filter","tenantRef"]}