@dudousxd/nestjs-agent 1.33.0 → 1.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a2ui/index.cjs.map +1 -1
- package/dist/a2ui/index.js.map +1 -1
- package/dist/durable/index.cjs.map +1 -1
- package/dist/durable/index.js.map +1 -1
- package/dist/genui/index.cjs.map +1 -1
- package/dist/genui/index.d.cts +9 -1
- package/dist/genui/index.d.ts +9 -1
- package/dist/genui/index.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vite/index.ts","../src/genui/kit.ts","../src/index.ts","../src/agent.module.ts","../src/agent-deps.factory.ts","../src/genui/agent-genui.module.ts","../src/functional-tool.ts","../src/genui/agent-genui.token.ts","../src/agent-service.token.ts","../src/agent.service.ts","../src/agent-deps.ts","../src/attachment-limits.ts","../src/proposals/action-proposal.service.ts","../src/queue/chat-queue.service.ts","../src/quota-exceeded.ts","../src/thread-persona.ts","../src/run-not-active.exception.ts","../src/approval-port.adapter.ts","../src/controller/agents.controller.ts","../src/controller/attachments.controller.ts","../src/controller/chat.controller.ts","../src/controller/config.controller.ts","../src/resolver/anonymous-actor-resolver.ts","../src/controller/memories.controller.ts","../src/controller/messages.controller.ts","../src/controller/models.controller.ts","../src/controller/queue.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/discovery/skill-discovery.service.ts","../src/decorator/skill.decorator.ts","../src/in-process-sink.ts","../src/ledger-quota-provider.ts","../src/pricing-boot.service.ts","../src/proposals/action-proposal-worker.service.ts","../src/proposals/action-proposal.controller.ts","../src/queue/chat-queue.token.ts","../src/runner/inline-agent-runner.ts","../src/skills-config.ts","../src/ag-ui/ag-ui.adapter.ts","../src/a2ui/a2ui.adapter.ts","../src/resolver/header-actor-resolver.ts","../src/resolver/request-user-actor-resolver.ts"],"sourcesContent":["/**\n * `@dudousxd/nestjs-agent/vite` — `genuiSandboxKit()`, the Vite plugin that puts the app's design\n * system (its styles, its components, its providers) inside the sandbox, whatever the stack:\n *\n * ```ts\n * // vite.config.ts (the SPA that talks to the agent)\n * import { genuiSandboxKit } from '@dudousxd/nestjs-agent/vite'\n * export default defineConfig({\n * plugins: [react(), genuiSandboxKit({ styles: 'src/index.css', components: 'src/components/ui' })],\n * })\n * ```\n *\n * Then `AgentGenuiModule.forRoot({ sandbox: { kit: true } })` finds what it built: the descriptor\n * the dev server writes (`.genui/sandbox-kit.json`) in dev, the Vite manifest in production (see\n * `AgentGenuiOptions.sandboxKit`).\n */\nimport {\n type GenuiSandboxKitApi,\n type GenuiSandboxKitOptions,\n type GenuiSandboxKitPlugin,\n SANDBOX_KIT_DEV_PREFIX,\n SANDBOX_KIT_MANIFEST_KEYS,\n SANDBOX_KIT_UPDATE_EVENT,\n createGenuiSandboxKitPlugin,\n} from '@dudousxd/nestjs-agent-core/genui/kit';\n\n/**\n * Where the dev descriptor is written, relative to the Vite root — and where the server reads it,\n * relative to its working directory (run both from the project root, or point\n * `sandboxKit.descriptor` at it). Add `.genui/` to `.gitignore`.\n */\nexport const NEST_SANDBOX_KIT_DESCRIPTOR = '.genui/sandbox-kit.json';\n\n/**\n * The sandbox kit plugin: `styles` (the app's style entries — default, the stylesheets among its\n * Vite entrypoints or `index.html`), `components` (modules or globs exporting React components —\n * default, the first `components/ui` folder), `wrapper` (a module whose default export wraps the\n * model's App). See {@link GenuiSandboxKitOptions}.\n */\nexport function genuiSandboxKit(options: GenuiSandboxKitOptions = {}): GenuiSandboxKitPlugin {\n return createGenuiSandboxKitPlugin(options, {\n descriptor: NEST_SANDBOX_KIT_DESCRIPTOR,\n rendererImport: /@dudousxd\\/nestjs-agent-react/,\n });\n}\n\nexport {\n type GenuiSandboxKitApi,\n type GenuiSandboxKitOptions,\n type GenuiSandboxKitPlugin,\n SANDBOX_KIT_DEV_PREFIX,\n SANDBOX_KIT_MANIFEST_KEYS,\n SANDBOX_KIT_UPDATE_EVENT,\n};\n","/**\n * The sandbox kit in a Nest app. No Vite runs in the Nest process, so the kit is found in files:\n * the descriptor `genuiSandboxKit()` (`@dudousxd/nestjs-agent/vite`) writes while the dev server\n * runs, and in production the Vite manifest the build wrote (`genui-sandbox-kit.json` and the assets\n * it names). Node-only: loaded by {@link AgentGenuiModule} only when a sandbox is configured.\n */\nimport { resolve } from 'node:path';\nimport {\n type SandboxKitDiscovery,\n sandboxKitDescriptorPath,\n sandboxKitDiscovery,\n} from '@dudousxd/nestjs-agent-core/genui/kit';\nimport { NEST_SANDBOX_KIT_DESCRIPTOR } from '../vite/index.js';\nimport type { AgentGenuiSandboxKitOptions } from './agent-genui.module.js';\n\n/** Where the production Vite manifest is looked for by default, and the directory it is relative to. */\nexport const NEST_SANDBOX_KIT_MANIFEST = Object.freeze({\n file: 'public/.vite/manifest.json',\n outDir: 'public',\n});\n\n/**\n * Find the kit for `AgentGenuiModule.forRoot({ sandbox: { kit: true } })` — a named kit's\n * (`genuiSandboxKit({ name })`, `sandbox: { kit: true, kitName }`) with `name`.\n */\nexport function nestSandboxKitDiscovery(\n options: AgentGenuiSandboxKitOptions = {},\n name?: string,\n): SandboxKitDiscovery {\n const manifest = options.manifest ?? NEST_SANDBOX_KIT_MANIFEST;\n return sandboxKitDiscovery({\n root: resolve(options.root ?? process.cwd()),\n ...(name !== undefined ? { name } : {}),\n descriptor: sandboxKitDescriptorPath(options.descriptor ?? NEST_SANDBOX_KIT_DESCRIPTOR, name),\n ...(manifest !== false ? { manifest: { file: manifest.file, outDir: manifest.outDir } } : {}),\n ...(options.kitUrl !== undefined ? { kitUrl: options.kitUrl } : {}),\n ...(options.cssUrl !== undefined ? { cssUrl: options.cssUrl } : {}),\n ...(options.tailwindUrl !== undefined ? { tailwindUrl: options.tailwindUrl } : {}),\n ...(options.production !== undefined ? { production: options.production } : {}),\n });\n}\n","export { AgentModule } from './agent.module.js';\nexport { type AgUiAdapterOptions, AgUiRunHandler, agUiAdapter } from './ag-ui/index.js';\nexport { type A2uiAdapterOptions, A2uiRunHandler, a2uiAdapter } from './a2ui/a2ui.adapter.js';\nexport type { AgentProtocolAdapter } from './protocol-adapter.js';\nexport type { AgentEngine } from './engine.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 NO_USER_MESSAGE_CODE,\n type ChatParams,\n type ChatSendMode,\n type ChatSendResult,\n type QueuedSend,\n type ThreadDefaultAgentReader,\n type ThreadModelReader,\n} from './agent.service.js';\nexport { type ThreadPersonaReader, threadPersona } from './thread-persona.js';\nexport {\n AttachmentsController,\n ATTACHMENT_PAGE_SIZE,\n} from './controller/attachments.controller.js';\nexport {\n type AttachmentLimits,\n attachmentLimits,\n DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,\n DEFAULT_MAX_ATTACHMENT_BYTES,\n MAX_ATTACHMENTS_PER_MESSAGE,\n} from './attachment-limits.js';\nexport { ConfigController } from './controller/config.controller.js';\nexport {\n AiTool,\n type AiToolOptions,\n AI_TOOL_METADATA,\n readAiToolMetadata,\n type ResolvedAiToolOptions,\n toolNameFromClass,\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 { MessagesController } from './controller/messages.controller.js';\nexport { ModelsController } from './controller/models.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 defineTool,\n type FunctionalToolDefinition,\n provideAgentTool,\n provideAgentTools,\n AGENT_TOOL_BRAND,\n type FunctionalTool,\n} from './functional-tool.js';\nexport { InlineAgentRunner } from './runner/inline-agent-runner.js';\nexport { QueueController } from './controller/queue.controller.js';\nexport {\n ChatQueueService,\n type QueuePlan,\n type QueueSettleOutcome,\n type QueuedTurn,\n type QueuedTurnStarter,\n} from './queue/chat-queue.service.js';\nexport { AGENT_CHAT_QUEUE } from './queue/chat-queue.token.js';\nexport { AGENT_SERVICE } from './agent-service.token.js';\nexport { InProcessTokenStreamSink } from './in-process-sink.js';\nexport {\n LedgerQuotaProvider,\n type QuotaLimits,\n type QuotaWindowLimits,\n} from './ledger-quota-provider.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';\nexport {\n AnonymousActorResolver,\n type AnonymousActorOptions,\n} from './resolver/anonymous-actor-resolver.js';\nexport {\n defaultRequestUserMapper,\n requestUserActorResolver,\n type RequestUserMapper,\n} from './resolver/request-user-actor-resolver.js';\n\n// Re-export the core surface so consumers import tools/types from one place.\nexport * from '@dudousxd/nestjs-agent-core';\nexport { RunNotActiveException } from './run-not-active.exception.js';\nexport { ActionProposalService } from './proposals/action-proposal.service.js';\nexport { ActionProposalController } from './proposals/action-proposal.controller.js';\nexport {\n type ActionProposalSettledListener,\n ActionProposalWorkerService,\n} from './proposals/action-proposal-worker.service.js';\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_MODEL_CATALOG,\n AGENT_OPTIONS,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_PROVIDER,\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 ClosedRolesPolicy,\n DefaultRolesPolicy,\n InMemoryAgentStore,\n type ModelCatalog,\n type ModelProvider,\n type QuotaProvider,\n type RolesPolicy,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n type CanActivate,\n type DynamicModule,\n Global,\n Logger,\n Module,\n type Provider,\n type Type,\n} from '@nestjs/common';\nimport { DiscoveryModule, ModulesContainer, RouterModule } from '@nestjs/core';\nimport { AgentDepsFactory } from './agent-deps.factory.js';\nimport { AGENT_SERVICE } from './agent-service.token.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 { ConfigController } from './controller/config.controller.js';\nimport { MemoriesController } from './controller/memories.controller.js';\nimport { MessagesController } from './controller/messages.controller.js';\nimport { ModelsController } from './controller/models.controller.js';\nimport { QueueController } from './controller/queue.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 type { AgentEngine } from './engine.js';\nimport { InProcessTokenStreamSink } from './in-process-sink.js';\nimport { LedgerQuotaProvider } from './ledger-quota-provider.js';\nimport { PricingBootService } from './pricing-boot.service.js';\nimport { ActionProposalWorkerService } from './proposals/action-proposal-worker.service.js';\nimport { ActionProposalController } from './proposals/action-proposal.controller.js';\nimport { ActionProposalService } from './proposals/action-proposal.service.js';\nimport type { AgentProtocolAdapter } from './protocol-adapter.js';\nimport { ChatQueueService } from './queue/chat-queue.service.js';\nimport { AGENT_CHAT_QUEUE } from './queue/chat-queue.token.js';\nimport { AnonymousActorResolver } from './resolver/anonymous-actor-resolver.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\nconst logger = new Logger('AgentModule');\n\n/**\n * `AGENT_STORE` as some OTHER module binds it — a store module (`MikroOrmAgentStoreModule`,\n * `DrizzleAgentStoreModule`, a host's own), found by scanning the container. Scanning sees every\n * module's providers before any is instantiated, so the answer is complete whatever the import\n * order; the instance itself is read lazily, at first use.\n */\nfunction externalWrapper(\n modules: ModulesContainer,\n token: symbol,\n): { instance: unknown } | undefined {\n for (const module of modules.values()) {\n if (module.metatype === AgentModule) continue;\n const wrapper = module.providers.get(token);\n if (wrapper !== undefined) return wrapper as { instance: unknown };\n }\n return undefined;\n}\n\n/** A store that forwards to another module's `AGENT_STORE`, resolved on first use. */\nfunction forwardingStore(wrapper: { instance: unknown }): AgentStore {\n const target = (): Record<PropertyKey, unknown> => {\n const instance = wrapper.instance;\n if (instance === undefined || instance === null) {\n throw new Error('AgentModule: the AGENT_STORE bound by another module is not ready yet');\n }\n return instance as Record<PropertyKey, unknown>;\n };\n return new Proxy({} as AgentStore, {\n get(_, property) {\n const store = target();\n const value = store[property];\n return typeof value === 'function' ? value.bind(store) : value;\n },\n has(_, property) {\n return property in target();\n },\n });\n}\n\n/**\n * The store: the `store` option, else one another module binds, else the in-memory default — which\n * is loud about not being for production.\n */\nfunction resolveStore(options: AgentModuleOptions, modules: ModulesContainer): AgentStore {\n if (options.store !== undefined) return options.store;\n const external = externalWrapper(modules, AGENT_STORE);\n if (external !== undefined) return forwardingStore(external);\n logger.warn(\n 'No `store` configured and no store module imported — using the in-memory store. Threads are ' +\n 'lost on restart and not shared between processes: not for production. Pass `store`, or ' +\n 'import a store module (e.g. MikroOrmAgentStoreModule.forFeature()).',\n );\n return new InMemoryAgentStore();\n}\n\n/**\n * The roles policy: the `rolesPolicy` option, else one another module binds (`AgentAuthzModule`, a\n * host's own), else the role-based default. The same scan as the store, for the same reason: Nest\n * resolves a module's own provider before a global one, so a policy bound elsewhere under\n * `AGENT_ROLES_POLICY` would otherwise never reach the agent — and the role-based default, which\n * has no notion of abilities, would silently stand in for it.\n */\nfunction resolveRolesPolicy(options: AgentModuleOptions, modules: ModulesContainer): RolesPolicy {\n const external = externalWrapper(modules, AGENT_ROLES_POLICY);\n if (options.rolesPolicy !== undefined) {\n if (external !== undefined) {\n logger.warn(\n 'Both a `rolesPolicy` option and a module binding AGENT_ROLES_POLICY (e.g. ' +\n 'AgentAuthzModule) are configured — the `rolesPolicy` option wins.',\n );\n }\n return options.rolesPolicy;\n }\n if (external !== undefined) return forwardingPolicy(external);\n return options.emptyRoles === 'deny'\n ? new ClosedRolesPolicy(options.defaultRoles)\n : new DefaultRolesPolicy(options.defaultRoles);\n}\n\n/** A policy that forwards to another module's `AGENT_ROLES_POLICY`, resolved on first use. */\nfunction forwardingPolicy(wrapper: { instance: unknown }): RolesPolicy {\n return {\n can(actor, tool) {\n const policy = wrapper.instance as RolesPolicy | undefined | null;\n if (policy === undefined || policy === null) {\n throw new Error(\n 'AgentModule: the AGENT_ROLES_POLICY bound by another module is not ready yet',\n );\n }\n return policy.can(actor, tool);\n },\n };\n}\n\nfunction isQuotaProvider(quota: AgentModuleOptions['quota']): quota is QuotaProvider {\n return quota !== undefined && typeof (quota as QuotaProvider).report === 'function';\n}\n\n/** The model catalog: the `models` option, else the one the model provider carries (`aiSdkModels`). */\nfunction resolveCatalog(options: AgentModuleOptions): ModelCatalog | undefined {\n if (options.models !== undefined) return options.models;\n const carried = (options.model as (ModelProvider & { catalog?: ModelCatalog }) | undefined)\n ?.catalog;\n return carried !== undefined && typeof carried.list === 'function' ? carried : undefined;\n}\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, engine: AgentEngine | undefined): 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, modules: ModulesContainer) =>\n resolveRolesPolicy(options, modules),\n inject: [AGENT_OPTIONS, ModulesContainer],\n },\n {\n provide: AGENT_ACTOR_RESOLVER,\n useFactory: (options: AgentModuleOptions) => {\n if (options.actorResolver !== undefined) return options.actorResolver;\n logger.warn(\n 'No `actorResolver` configured — the agent endpoints are PUBLIC: every browser gets its ' +\n 'own anonymous identity (an HttpOnly cookie). Set `actorResolver: ' +\n 'requestUserActorResolver()` (or your own) to require login.',\n );\n return new AnonymousActorResolver();\n },\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_MODEL,\n useFactory: (o: AgentModuleOptions) => o.model,\n inject: [AGENT_OPTIONS],\n },\n {\n // `quota` is either a provider of the host's own or ceilings for the built-in ledger one;\n // omitted, the ledger provider still reports usage, with no ceiling to block on.\n provide: AGENT_QUOTA_PROVIDER,\n useFactory: (o: AgentModuleOptions, store: AgentStore) =>\n isQuotaProvider(o.quota)\n ? o.quota\n : new LedgerQuotaProvider(store, o.quota?.limits, {\n ...(o.quota?.warnAt !== undefined ? { warnAt: o.quota.warnAt } : {}),\n ...(o.quota?.countEstimatedCost !== undefined\n ? { countEstimatedCost: o.quota.countEstimatedCost }\n : {}),\n }),\n inject: [AGENT_OPTIONS, AGENT_STORE],\n },\n {\n provide: AGENT_MODEL_CATALOG,\n useFactory: (o: AgentModuleOptions) => resolveCatalog(o),\n inject: [AGENT_OPTIONS],\n },\n AgentDepsFactory,\n { provide: AGENT_DEPS_FACTORY, useExisting: AgentDepsFactory },\n // Seeds a configured model's missing price row from models.dev and warns about one that would\n // record no cost (`priceCatalog`), once the app has bootstrapped.\n PricingBootService,\n // Populates the registry + contributors (onModuleInit) BEFORE AiToolDiscoveryService synthesizes\n // handoff tools (onApplicationBootstrap) reads the registry.\n AgentDiscoveryService,\n AiToolDiscoveryService,\n SkillDiscoveryService,\n // The thread message queue — every surface, since both runners and the durable workflow settle\n // into it, and the chat routes enqueue into it.\n ChatQueueService,\n { provide: AGENT_CHAT_QUEUE, useExisting: ChatQueueService },\n InlineAgentRunner,\n AgentService,\n { provide: AGENT_SERVICE, useExisting: AgentService },\n ActionProposalService,\n ActionProposalWorkerService,\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 providers.push({\n provide: AGENT_STORE,\n useFactory: (o: AgentModuleOptions, modules: ModulesContainer) => resolveStore(o, modules),\n inject: [AGENT_OPTIONS, ModulesContainer],\n });\n if (engine !== undefined) {\n // The engine runs the turns; its providers bring the runner AGENT_RUNNER points at.\n providers.push(...engine.providers, { provide: AGENT_RUNNER, useExisting: engine.runner });\n } else 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/** The module's public tokens. */\nfunction exportsFor(engine?: AgentEngine): NonNullable<DynamicModule['exports']> {\n return [\n ...(engine?.exports ?? []),\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 AGENT_STORE,\n AGENT_MODEL_CATALOG,\n AGENT_QUOTA_PROVIDER,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_SKILLS,\n AGENT_MEMORY,\n AGENT_DEPS_FACTORY,\n AgentDepsFactory,\n AgentService,\n AGENT_SERVICE,\n ActionProposalService,\n ActionProposalWorkerService,\n ChatQueueService,\n AGENT_CHAT_QUEUE,\n InlineAgentRunner,\n AGENT_APPROVAL_PORT,\n ];\n}\n\nconst BASE_CONTROLLERS = [\n ActionProposalController,\n ChatController,\n QueueController,\n ThreadsController,\n ToolCallController,\n QuotaController,\n AgentsController,\n SkillsController,\n MemoriesController,\n ToolsController,\n MessagesController,\n ModelsController,\n ConfigController,\n AttachmentsController,\n];\n\n/** The controllers the configured protocol adapters contribute. */\nfunction adapterControllers(adapters: AgentProtocolAdapter[] | undefined): Type<object>[] {\n return (adapters ?? []).flatMap((adapter) => adapter.controllers);\n}\n\n/** The providers the configured protocol adapters contribute. */\nfunction adapterProviders(adapters: AgentProtocolAdapter[] | undefined): Provider[] {\n return (adapters ?? []).flatMap((adapter) => adapter.providers ?? []);\n}\n\n/**\n * `surface: 'engine'` mounts NO controllers — a worker pod never receives HTTP traffic. Otherwise\n * the native ones, whatever the protocol adapters contribute, and the engine's own.\n */\nfunction controllersForSurface(\n surface: AgentSurface | undefined,\n adapters: AgentProtocolAdapter[] | undefined,\n engine?: AgentEngine,\n): Type<object>[] {\n return surface === 'engine'\n ? []\n : [...BASE_CONTROLLERS, ...adapterControllers(adapters), ...(engine?.controllers ?? [])];\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(\n guards: Type<CanActivate>[] | undefined,\n adapters: AgentProtocolAdapter[] | undefined,\n): void {\n const resolved = guards ?? [];\n for (const controller of [...BASE_CONTROLLERS, ...adapterControllers(adapters)]) {\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/**\n * Refuse a wiring that cannot run a turn, at boot rather than on the first message: no `model` and\n * no `engine` leaves the loop nothing to call, and `durable` names the loop's own durable runner,\n * which an engine replaces (an engine that wants durability brings it).\n */\nfunction assertRunnable(options: Pick<AgentModuleOptions, 'model' | 'engine' | 'durable'>): void {\n if (options.engine !== undefined && options.durable === true) {\n throw new Error(\n `AgentModule: \\`durable: true\\` runs turns on the library's loop, but the \\`${options.engine.name}\\` engine runs them instead. Drop \\`durable\\` (the engine decides how its turns survive a restart).`,\n );\n }\n if (options.engine === undefined && options.model === undefined) {\n throw new Error(\n 'AgentModule: set `model` (the loop runs the turns) or `engine` (something else does).',\n );\n }\n}\n\n@Global()\n@Module({})\nexport class AgentModule {\n static forRoot(options: AgentModuleOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n assertRunnable(options);\n applyGuards(options.guards, options.adapters);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path)],\n controllers: controllersForSurface(options.surface, options.adapters, options.engine),\n providers: [\n { provide: AGENT_OPTIONS, useValue: options },\n ...sharedProviders(options.durable ?? false, options.engine),\n ...guardProviders(options.guards),\n ...adapterProviders(options.adapters),\n ],\n exports: exportsFor(options.engine),\n };\n }\n\n static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n if (options.engine !== undefined) {\n assertRunnable({ engine: options.engine, durable: options.durable ?? false });\n }\n applyGuards(options.guards, options.adapters);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path), ...(options.imports ?? [])],\n controllers: controllersForSurface(options.surface, options.adapters, options.engine),\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 const resolved: AgentModuleOptions = {\n ...(await options.useFactory(...args)),\n durable: options.durable ?? false,\n surface: options.surface ?? 'both',\n ...(options.engine !== undefined ? { engine: options.engine } : {}),\n };\n assertRunnable(resolved);\n return resolved;\n },\n inject: options.inject ?? [],\n },\n ...sharedProviders(options.durable ?? false, options.engine),\n ...guardProviders(options.guards),\n ...adapterProviders(options.adapters),\n ],\n exports: exportsFor(options.engine),\n };\n }\n}\n","import {\n type ActionProposal,\n type Actor,\n type ToolUiChannelGuide,\n assertIndependentActionCapabilities,\n createToolUiChannelGuide,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n AGENT_MEMORY,\n AGENT_MODEL,\n AGENT_PRICING_STORE,\n AGENT_PROMPT_CONTRIBUTORS,\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 Persona,\n type PersonaCatalogEntry,\n type PromptBuilder,\n type PromptContext,\n type PromptContributor,\n type RolesPolicy,\n type SkillsConfig,\n type TokenStreamSink,\n ToolRegistry,\n findPersona,\n intersectAllowLists,\n normalizeDelegation,\n personaCatalogEntry,\n resolvePersonaAlias,\n summarizeWithModel,\n windowHistory,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_OPTIONS } from '@dudousxd/nestjs-agent-core';\nimport type { Catalog } from '@dudousxd/nestjs-agent-core/genui';\nimport { BadRequestException, Inject, Injectable, Optional } from '@nestjs/common';\nimport type { AgentDeps } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\nimport {\n AGENT_GENUI,\n type AgentGenui,\n GENUI_CATALOG,\n GenuiCatalogResolver,\n} from './genui/agent-genui.module.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 // Optional: AGENT_PRICING_STORE has no local provider in this module — it's bound externally\n // (e.g. by a store module), so a 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 @Optional() @Inject(GENUI_CATALOG) private readonly uiCatalog?: Catalog,\n @Optional() private readonly uiCatalogResolver?: GenuiCatalogResolver,\n @Optional() @Inject(AGENT_GENUI) private readonly genui?: AgentGenui,\n ) {\n if (options.actionApprovalMode === 'independent')\n assertIndependentActionCapabilities(store, options.backgroundActorResolver);\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 /**\n * The agent a name stands for: itself when it is a registered agent (or unknown — the bare\n * assistant), else the agent whose persona took the name over (`Persona.aliases`) and that persona.\n */\n resolveAgent(name: string): { agentName: string; persona?: string } {\n if (this.agents.has(name)) {\n return { agentName: name };\n }\n const alias = resolvePersonaAlias(this.agents.list(), name);\n return alias === undefined\n ? { agentName: name }\n : { agentName: alias.agent, persona: alias.persona };\n }\n\n /** `agentName`'s personas as a picker reads them. Empty when it declares none. */\n personaCatalog(agentName: string): PersonaCatalogEntry[] {\n return (this.agents.get(agentName)?.personas ?? []).map(personaCatalogEntry);\n }\n\n /** The persona `agentName` runs under when nothing names one. Undefined → none. */\n defaultPersona(agentName: string): string | undefined {\n return this.agents.get(agentName)?.defaultPersona;\n }\n\n /**\n * The persona a turn of `agentName` runs under, most specific first: the one the send names\n * (refused with `400 persona_not_found` when the agent does not declare it), else the thread's\n * pinned one when this agent declares it, else the agent's default. Undefined → none.\n */\n resolvePersona(args: {\n agentName: string;\n requested?: string;\n threadPersona?: string | null;\n }): string | undefined {\n const definition = this.agents.get(args.agentName);\n if (args.requested !== undefined) {\n if (findPersona(definition, args.requested) === undefined) {\n throw new BadRequestException({\n statusCode: 400,\n code: 'persona_not_found',\n message: `agent \"${args.agentName}\" has no persona \"${args.requested}\"`,\n });\n }\n return args.requested;\n }\n const pinned = args.threadPersona ?? undefined;\n if (pinned !== undefined && findPersona(definition, pinned) !== undefined) {\n return pinned;\n }\n return definition?.defaultPersona;\n }\n\n forProposal(proposal: ActionProposal, _actor: Actor): AgentDeps {\n const name = proposal.executionContext?.agentName;\n if (\n name !== undefined &&\n !this.agents.has(name) &&\n !(\n name === 'default' &&\n this.defaultAgentName() === 'default' &&\n this.agents.list().length === 0\n )\n )\n throw new Error(`Recorded agent ${name} no longer exists`);\n const deps = this.forAgent(name);\n const id = proposal.executionContext?.persona;\n if (id !== undefined) {\n const persona = deps.personas?.find((persona) => persona.id === id);\n if (!persona) throw new Error(`Recorded persona ${id} no longer exists`);\n return this.withPersona(deps, persona);\n }\n return deps;\n }\n /** The turn's UI catalog: the per-request resolver's, else the app's. */\n private readonly resolveUiCatalog = (\n scope: import('@dudousxd/nestjs-agent-core').ToolDescribeScope,\n ) => {\n const catalog =\n this.uiCatalogResolver?.resolve({\n ...scope,\n ...(scope.actor.tenantRef !== undefined ? { tenant: scope.actor.tenantRef } : {}),\n }) ?? this.uiCatalog;\n if (!catalog) throw new Error('UI catalog unavailable');\n return catalog;\n };\n\n #uiChannelGuide: ToolUiChannelGuide | null | undefined;\n /** genui `channels`: what the model is told per channel. Built once; `undefined` without channels. */\n private uiChannelGuide(): ToolUiChannelGuide | undefined {\n if (this.#uiChannelGuide === undefined) {\n const channels = this.genui?.channels;\n this.#uiChannelGuide =\n channels === undefined ||\n (this.uiCatalog === undefined && this.uiCatalogResolver === undefined)\n ? null\n : createToolUiChannelGuide({\n channels,\n base: this.genui?.base ?? {},\n resolveCatalog: this.resolveUiCatalog,\n });\n }\n return this.#uiChannelGuide ?? undefined;\n }\n\n forAgent(agentName?: string): AgentDeps {\n const name = agentName ?? this.defaultAgentName();\n if (agentName !== undefined && !this.agents.has(agentName)) {\n const alias = resolvePersonaAlias(this.agents.list(), agentName);\n const persona =\n alias === undefined ? undefined : findPersona(this.agents.get(alias.agent), alias.persona);\n if (alias !== undefined && persona !== undefined) {\n return this.withPersona(this.forAgent(alias.agent), persona);\n }\n }\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 const uiChannelGuide = this.uiChannelGuide();\n return {\n model: this.model,\n store: this.store,\n ...(this.options.actionApprovalMode !== undefined\n ? { actionApprovalMode: this.options.actionApprovalMode }\n : {}),\n sink: this.sink,\n rolesPolicy: this.rolesPolicy,\n ...(this.options.approvalPolicy !== undefined\n ? { approvalPolicy: this.options.approvalPolicy }\n : {}),\n registry: this.registry,\n ...(this.uiCatalog !== undefined || this.uiCatalogResolver !== undefined\n ? { resolveUiCatalog: this.resolveUiCatalog }\n : {}),\n ...(uiChannelGuide !== undefined ? { uiChannelGuide } : {}),\n promptContributors: this.promptContributors,\n systemPrompt:\n definition?.systemPrompt ?? this.options.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.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 ...(definition?.personas !== undefined ? { personas: definition.personas } : {}),\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 * A persona baked into an agent's deps — how a run journaled under an agent name that a persona\n * has since taken over (`Persona.aliases`) is served. That run names no persona of its own (it\n * predates them, and its input cannot change), so the persona applies the way the old agent's own\n * config did: as config, re-read on every replay, with no checkpoint of its own.\n */\n private withPersona(deps: AgentDeps, persona: Persona): AgentDeps {\n const base = deps.systemPrompt;\n const ref = { id: persona.id, label: persona.label };\n const resolve = async (prompt: string | PromptBuilder, ctx: PromptContext) =>\n typeof prompt === 'function' ? prompt(ctx) : prompt;\n const own = persona.systemPrompt;\n const systemPrompt: PromptBuilder = async (ctx) => {\n const scoped: PromptContext = { ...ctx, persona: ref };\n if (own === undefined) {\n return resolve(base, scoped);\n }\n const basePrompt = typeof own === 'function' ? await resolve(base, scoped) : undefined;\n return resolve(own, { ...scoped, ...(basePrompt !== undefined ? { basePrompt } : {}) });\n };\n const toolAllowList = intersectAllowLists(deps.toolAllowList, persona.allowedTools);\n return { ...deps, systemPrompt, ...(toolAllowList !== undefined ? { toolAllowList } : {}) };\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 type { ToolPresentation } from '@dudousxd/nestjs-agent-core';\nimport type {\n Catalog,\n GenuiAbility,\n GenuiCatalogScope,\n GenuiChannels,\n GenuiStreaming,\n GenuiToolsOptions,\n SandboxClientConfig,\n TreeLimits,\n TreeSchemaMode,\n} from '@dudousxd/nestjs-agent-core/genui';\nimport {\n type DefineSandboxOptions,\n type SandboxDefinition,\n assertGenuiChannels,\n defineCatalog,\n defineSandbox,\n genuiTools,\n sandboxPolicyOf,\n} from '@dudousxd/nestjs-agent-core/genui';\nimport {\n type DynamicModule,\n type FactoryProvider,\n Inject,\n Module,\n type ModuleMetadata,\n type Provider,\n type Type,\n} from '@nestjs/common';\nimport { provideAgentTools } from '../functional-tool.js';\nimport { AGENT_GENUI, AgentGenui } from './agent-genui.token.js';\n\nexport { AGENT_GENUI, AgentGenui } from './agent-genui.token.js';\n\n/** The app's genui catalog — `@InjectGenuiCatalog()` it anywhere; `overrideProvider` it in tests. */\nexport const GENUI_CATALOG = Symbol.for('@dudousxd/nestjs-agent:genui-catalog');\n\n/** The resolved {@link AgentGenuiOptions} (without the resolver). */\nexport const GENUI_OPTIONS = Symbol.for('@dudousxd/nestjs-agent:genui-options');\n\n/** The sandbox and channels as boot resolved them (kit, Tailwind and theme found). Internal. */\nconst GENUI_RESOLVED = Symbol.for('@dudousxd/nestjs-agent:genui-resolved');\n\n/** Inject the app's genui catalog ({@link GENUI_CATALOG}). */\nexport const InjectGenuiCatalog = (): ParameterDecorator & PropertyDecorator =>\n Inject(GENUI_CATALOG);\n\n/**\n * Picks the catalog for ONE request — a tenant's own, versioned components. Consulted when a genui\n * call is validated and when the turn's tool list is described to the model, so components can\n * change without rebuilding tools at boot. Cache in here if resolving costs a round trip: it runs\n * once per turn per genui tool, and once per call.\n *\n * Provide it through `AgentGenuiModule.forRoot({ resolver })` (a class, resolved with DI, or an\n * instance); it is then injectable, and replaceable in a test with\n * `overrideProvider(GenuiCatalogResolver)`.\n */\nexport abstract class GenuiCatalogResolver {\n abstract resolve(scope: GenuiCatalogScope): Catalog | Promise<Catalog>;\n}\n\n/** What {@link AgentGenuiModule} builds tools from. */\nexport interface AgentGenuiOptions {\n /**\n * The catalog. With a {@link GenuiCatalogResolver} it is the boot-time one — it names the\n * per-component tools — and may be empty. Default: an empty catalog.\n */\n catalog?: Catalog;\n /**\n * `tree` (default): one `ui__render` tool taking a composed tree (a single node is pushed as that\n * component). `per-component`: one `ui__show_<snake>` tool per component.\n */\n mode?: 'per-component' | 'tree';\n /** `ui__render`'s input schema: `'strict'` (default, a `$defs` union per component) or `'loose'`. */\n treeSchema?: TreeSchemaMode;\n /**\n * Tree mode: `'complete'` (default) draws the tree once the call has run; `'partial'` streams it\n * as `partial` ui frames while the model writes it. A component's own `streaming` overrides it.\n */\n streaming?: GenuiStreaming;\n /** Least time between two partial tree frames of one call, in ms. Default 100. */\n streamingThrottleMs?: number;\n /** End the model's turn once a genui call succeeds (no narrating follow-up call). */\n terminal?: boolean;\n /** Tool name in `tree` mode. Default `ui__render`. */\n treeToolName?: string;\n /** Text prepended to the tree tool's description. */\n treeInstructions?: string;\n treeLimits?: TreeLimits;\n /**\n * Tree mode: components that ALSO get a flat tool whose input IS their props —\n * `componentTools: ['Sandbox']` adds `ui__sandbox`, so a model writing a big component on its own\n * has no `{ type, props }` envelope to leave out.\n */\n componentTools?: readonly string[];\n /** Tool-name prefix for `componentTools`. Default `ui__` (`Sandbox` → `ui__sandbox`). */\n componentToolPrefix?: string;\n /** Tool-name prefix in `per-component` mode. Default `ui__show_`. */\n namePrefix?: string;\n /**\n * Also register ONE generic tool taking `{ component, props }`, validated against the request's\n * catalog — how a model reaches a tenant's own components, which no boot-time tool names. `true`\n * names it `ui__show`.\n */\n showTool?: boolean | string;\n /** Text prepended to the show tool's description. */\n showInstructions?: string;\n /** Roles allowed to call the tools. Undefined → the roles policy default. */\n roles?: string[];\n /**\n * The authorization ability the UI tools declare (`ToolSpec.ability`), for an ability-aware\n * authorizer such as `authzToolAuthorizer`, which denies a tool with none. A string for every\n * tool; a map by tool name (`{ ui__render: 'genui.render', ui__sandbox: 'genui.sandbox' }`, a tool\n * left out declares none); or a function of `{ name, component }`. The authorizer decides.\n */\n ability?: GenuiAbility;\n /** Override the generated presentation per component (or per tree / show tool name). */\n presentation?: (component: string) => ToolPresentation | undefined;\n /**\n * Add the sandbox component (`Sandbox`): the model may write HTML, CSS and JS for a one-off\n * interactive answer when no catalog component fits. `true` for the defaults (no network), or\n * the {@link DefineSandboxOptions} (a policy listing origins, extra instructions). Off by default.\n * The browser's catalog should carry the same definition (`defineSandbox(...)` in the shared\n * catalog file) so the renderer enforces the same policy.\n *\n * `theme` (default on) and `kit` put the app's design system in the frame: `kit: true` turns on\n * whatever `genuiSandboxKit()` built (styles, Tailwind, components, wrapper, docs), found through\n * `sandboxKit`: the descriptor\n * `genuiSandboxKit()` (`@dudousxd/nestjs-agent/vite`) writes in dev, the Vite manifest in\n * production — and `GET <base>/config` tells the renderer where the assets are.\n */\n sandbox?: boolean | DefineSandboxOptions;\n /**\n * Per-channel generative UI: each entry sets the mode, streaming, sandbox and rendering of one\n * channel (`web`, `mobile`, `whatsapp`, `telegram`, `email`, or `default` for the rest), over the\n * top-level options. A text channel (`@dudousxd/nestjs-agent-channels`) configured here draws the\n * components natively (reply buttons, lists, images). Omitted → every channel is served by the\n * top-level options, as before.\n */\n channels?: GenuiChannels;\n /**\n * Where the sandbox kit is found (with `sandbox: { kit: true }` or the theme's names). No Vite\n * runs in the Nest process, so: the descriptor the dev plugin writes, or the production Vite\n * manifest — in production the manifest first, otherwise whichever was written last.\n */\n sandboxKit?: AgentGenuiSandboxKitOptions;\n}\n\n/** {@link AgentGenuiOptions.sandboxKit}. Relative paths resolve against `root`. */\nexport interface AgentGenuiSandboxKitOptions {\n /** Default `process.cwd()`. */\n root?: string;\n /**\n * The dev descriptor `genuiSandboxKit()` writes. Default `.genui/sandbox-kit.json` — for a named\n * kit (`genuiSandboxKit({ name })`, picked with `kitName`), `.genui/sandbox-kit.<name>.json`.\n */\n descriptor?: string;\n /**\n * The production Vite manifest, and the directory its `file`s are relative to. Default\n * `{ file: 'public/.vite/manifest.json', outDir: 'public' }`; `false` → none.\n */\n manifest?: { file: string; outDir: string } | false;\n /** An explicit kit url (an SPA served from elsewhere), over what is found. */\n kitUrl?: string;\n /** An explicit url of the compiled styles, over what is found (the same SPA case). */\n cssUrl?: string;\n /** An explicit url of the Tailwind browser runtime, over what is found (the same SPA case). */\n tailwindUrl?: string;\n /** Read the manifest first (else the freshest of the two). Default: `NODE_ENV === 'production'`. */\n production?: boolean;\n}\n\ntype ResolverOption = Type<GenuiCatalogResolver> | GenuiCatalogResolver;\n\nexport interface AgentGenuiModuleOptions extends AgentGenuiOptions {\n /** Per-request catalogs. A class is instantiated with DI (its dependencies must be global or exported to the root). */\n resolver?: ResolverOption;\n}\n\nexport interface AgentGenuiModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {\n inject?: FactoryProvider['inject'];\n useFactory: (...deps: any[]) => AgentGenuiOptions | Promise<AgentGenuiOptions>;\n /** Per-request catalogs. A class resolves its dependencies from `imports`. */\n resolver?: ResolverOption;\n}\n\nfunction resolverProviders(resolver: ResolverOption | undefined): Provider[] {\n if (resolver === undefined) return [];\n return [\n typeof resolver === 'function'\n ? { provide: GenuiCatalogResolver, useClass: resolver }\n : { provide: GenuiCatalogResolver, useValue: resolver },\n ];\n}\n\n/** The sandbox and channels with the kit and theme names found ({@link GENUI_RESOLVED}). */\ninterface ResolvedGenui {\n sandbox?: boolean | DefineSandboxOptions;\n /** A kit sandbox the catalog itself defines, resolved (under its own name). */\n catalogSandbox?: DefineSandboxOptions;\n channels?: GenuiChannels;\n sandboxClient?: () => SandboxClientConfig;\n}\n\n/** What every configured sandbox (top level and channels) needs from the browser, together. */\nfunction mergeSandboxClients(clients: Array<() => SandboxClientConfig>): SandboxClientConfig {\n const merged: SandboxClientConfig = { theme: false };\n for (const client of clients) {\n const one = client();\n merged.theme ||= one.theme;\n if (one.name !== undefined && merged.kit === undefined && one.kit !== undefined)\n merged.name = one.name;\n if (one.kit !== undefined) merged.kit ??= one.kit;\n if (one.css !== undefined) merged.css ??= one.css;\n if (one.tailwind !== undefined) merged.tailwind ??= one.tailwind;\n }\n return merged;\n}\n\n/** Resolve the sandbox (top level and per channel) against the kit discovery. */\nasync function resolveGenui(options: AgentGenuiOptions): Promise<ResolvedGenui> {\n const { sandbox: asked, channels: askedChannels } = options;\n assertGenuiChannels(askedChannels);\n // A sandbox's kit (styles, components, wrapper) and theme names are found through the app's Vite output.\n const clients: Array<() => SandboxClientConfig> = [];\n const discoveries = new Map<\n string,\n import('@dudousxd/nestjs-agent-core/genui/kit').SandboxKitDiscovery\n >();\n const resolveSandbox = async (\n value: boolean | DefineSandboxOptions | undefined,\n ): Promise<boolean | DefineSandboxOptions | undefined> => {\n if (value === undefined || value === false) return value;\n // Node-only, and only with a sandbox: loaded when one is configured.\n const [{ nestSandboxKitDiscovery }, { resolveSandboxServer }] = await Promise.all([\n import('./kit.js'),\n import('@dudousxd/nestjs-agent-core/genui/kit'),\n ]);\n const kitName = value === true ? undefined : value.kitName;\n let discovery = discoveries.get(kitName ?? '');\n if (discovery === undefined) {\n discovery = nestSandboxKitDiscovery(options.sandboxKit, kitName);\n discoveries.set(kitName ?? '', discovery);\n }\n const resolved = resolveSandboxServer(value, discovery);\n clients.push(resolved.client);\n return resolved.define;\n };\n const sandbox = await resolveSandbox(asked);\n // A kit sandbox defined in the (shared) catalog itself: found the same way, and put\n // back under its own name, so the browser's copy of the catalog validates what the model writes.\n const own = options.catalog?.components.find((each) => sandboxPolicyOf(each) !== undefined) as\n | SandboxDefinition\n | undefined;\n const ownOptions =\n asked === undefined && own?.sandboxOptions !== undefined && own.sandboxView?.kit === true\n ? await resolveSandbox({ ...own.sandboxOptions, name: own.name })\n : undefined;\n let channels: GenuiChannels | undefined;\n if (askedChannels !== undefined) {\n channels = {};\n for (const [name, entry] of Object.entries(askedChannels)) {\n if (entry === undefined) continue;\n const own = await resolveSandbox(entry.sandbox);\n channels[name] = { ...entry, ...(own !== undefined ? { sandbox: own } : {}) };\n }\n }\n return {\n ...(sandbox !== undefined ? { sandbox } : {}),\n ...(typeof ownOptions === 'object' ? { catalogSandbox: ownOptions } : {}),\n ...(channels !== undefined ? { channels } : {}),\n ...(clients.length > 0 ? { sandboxClient: () => mergeSandboxClients(clients) } : {}),\n };\n}\n\nfunction perRequest(\n resolver: GenuiCatalogResolver | undefined,\n): GenuiToolsOptions['resolveCatalog'] | undefined {\n return resolver === undefined ? undefined : (scope: GenuiCatalogScope) => resolver.resolve(scope);\n}\n\nfunction toolOptions(\n options: AgentGenuiOptions,\n resolved: ResolvedGenui,\n resolver: GenuiCatalogResolver | undefined,\n): GenuiToolsOptions {\n const {\n catalog: _catalog,\n sandbox: _sandbox,\n channels: _channels,\n sandboxKit: _sandboxKit,\n ...rest\n } = options;\n const resolveCatalog = perRequest(resolver);\n return {\n ...rest,\n ...(resolved.channels !== undefined ? { channels: resolved.channels } : {}),\n ...(resolved.sandbox !== undefined ? { sandbox: resolved.sandbox } : {}),\n ...(resolveCatalog !== undefined ? { resolveCatalog } : {}),\n };\n}\n\n/** The configured catalog, with the sandbox component added when `sandbox` asks for it. */\nfunction withSandbox(options: AgentGenuiOptions, resolved: ResolvedGenui): Catalog {\n const base = options.catalog ?? defineCatalog([]);\n const { sandbox, catalogSandbox } = resolved;\n if (sandbox === undefined || sandbox === false)\n return catalogSandbox !== undefined ? base.extend([defineSandbox(catalogSandbox)]) : base;\n return base.extend([defineSandbox(sandbox === true ? {} : sandbox)]);\n}\n\nfunction coreProviders(resolver: ResolverOption | undefined): Provider[] {\n return [\n {\n provide: GENUI_RESOLVED,\n useFactory: (options: AgentGenuiOptions) => resolveGenui(options),\n inject: [GENUI_OPTIONS],\n },\n {\n provide: GENUI_CATALOG,\n useFactory: (options: AgentGenuiOptions, resolved: ResolvedGenui) =>\n withSandbox(options, resolved),\n inject: [GENUI_OPTIONS, GENUI_RESOLVED],\n },\n {\n provide: AGENT_GENUI,\n useFactory: (\n options: AgentGenuiOptions,\n catalog: Catalog,\n resolved: ResolvedGenui,\n resolverInstance?: GenuiCatalogResolver,\n ) =>\n new AgentGenui(\n catalog,\n perRequest(resolverInstance),\n resolved.channels,\n {\n ...(options.mode !== undefined ? { mode: options.mode } : {}),\n ...(options.streaming !== undefined ? { streaming: options.streaming } : {}),\n ...(resolved.sandbox !== undefined ? { sandbox: resolved.sandbox } : {}),\n },\n resolved.sandboxClient,\n ),\n inject: [\n GENUI_OPTIONS,\n GENUI_CATALOG,\n GENUI_RESOLVED,\n { token: GenuiCatalogResolver, optional: true },\n ],\n },\n ...resolverProviders(resolver),\n // The generated tools, registered by the agent module's discovery like any `provideAgentTool`.\n // Built from the injected catalog, so `overrideProvider(GENUI_CATALOG)` changes them too.\n provideAgentTools(\n (\n options: AgentGenuiOptions,\n catalog: Catalog,\n resolved: ResolvedGenui,\n perRequestResolver?: GenuiCatalogResolver,\n ) => genuiTools(catalog, toolOptions(options, resolved, perRequestResolver)),\n [\n GENUI_OPTIONS,\n GENUI_CATALOG,\n GENUI_RESOLVED,\n { token: GenuiCatalogResolver, optional: true },\n ],\n ),\n ];\n}\n\nconst EXPORTS = [GENUI_CATALOG, GENUI_OPTIONS, AGENT_GENUI];\n\n/**\n * Generative UI for the agent: registers the tools that let the model push catalog components\n * (one `ui__render` tree tool, or `ui__show_<component>` per component, and/or the generic\n * `ui__show`), and makes the catalog\n * injectable. Global, like `AgentModule`; import it once, next to it.\n *\n * ```ts\n * AgentGenuiModule.forRoot({ catalog, mode: 'tree', terminal: true })\n * ```\n */\n@Module({})\nexport class AgentGenuiModule {\n static forRoot(options: AgentGenuiModuleOptions = {}): DynamicModule {\n const { resolver, ...rest } = options;\n return {\n module: AgentGenuiModule,\n global: true,\n providers: [{ provide: GENUI_OPTIONS, useValue: rest }, ...coreProviders(resolver)],\n exports: resolver === undefined ? EXPORTS : [...EXPORTS, GenuiCatalogResolver],\n };\n }\n\n static forRootAsync(options: AgentGenuiModuleAsyncOptions): DynamicModule {\n return {\n module: AgentGenuiModule,\n global: true,\n imports: options.imports ?? [],\n providers: [\n { provide: GENUI_OPTIONS, useFactory: options.useFactory, inject: options.inject ?? [] },\n ...coreProviders(options.resolver),\n ],\n exports: options.resolver === undefined ? EXPORTS : [...EXPORTS, GenuiCatalogResolver],\n };\n }\n}\n","import {\n type FunctionalToolDefinition,\n type ToolHandler,\n type ToolSpec,\n createFunctionalTool,\n} 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\n/**\n * Registers a LIST of functional tools from one factory — for a producer whose tool count is only\n * known once its dependencies resolve (a catalog loaded from config, one tool per entry). The\n * factory's result is branded element by element; `AiToolDiscoveryService` registers each.\n */\nexport function provideAgentTools(\n factory: (...deps: never[]) => readonly FunctionalTool[] | Promise<readonly FunctionalTool[]>,\n inject?: FactoryProvider['inject'],\n): Provider {\n return {\n provide: Symbol('nestjs-agent:functional-tool-list'),\n useFactory: async (...deps: never[]) => (await factory(...deps)).map(brand),\n inject: inject ?? [],\n };\n}\n\n/** Author a functional tool with inferred Standard Schema input and domain output. */\nexport const defineTool = createFunctionalTool;\nexport type { FunctionalToolDefinition };\n","import type {\n Catalog,\n GenuiCatalogScope,\n GenuiChannelBase,\n GenuiChannels,\n SandboxClientConfig,\n} from '@dudousxd/nestjs-agent-core/genui';\n\n/**\n * The app's genui setup ({@link AgentGenui}): the catalog, the per-channel options and what the\n * sandbox renderer is told — what the text channels (`@dudousxd/nestjs-agent-channels`) and\n * `GET <base>/config` read.\n */\nexport const AGENT_GENUI = Symbol.for('@dudousxd/nestjs-agent:genui');\n\n/**\n * The app's genui setup, bound to {@link AGENT_GENUI}: what a text channel draws with\n * (`catalog`, `channels`, `base`) and what the sandbox renderer is told (`sandboxClient`).\n */\nexport class AgentGenui {\n constructor(\n readonly catalog: Catalog,\n readonly resolveCatalog?: (scope: GenuiCatalogScope) => Catalog | Promise<Catalog>,\n /** `AgentGenuiModule.forRoot({ channels })`, when configured. */\n readonly channels?: GenuiChannels,\n /** The top-level options a channel falls back to. */\n readonly base: GenuiChannelBase = {},\n /** What the sandbox renderer is told, when a sandbox is configured. */\n readonly sandboxClient?: () => SandboxClientConfig,\n ) {}\n}\n","/**\n * `AgentService`, as the controllers of a secondary entry (`@dudousxd/nestjs-agent/a2ui`) ask for it.\n *\n * A token rather than the class: every entry is its own bundle with its own copy of every class it\n * imports, so the class used as an injection token there is not the one `AgentModule` provides.\n * `Symbol.for` is the same value in every bundle.\n */\nexport const AGENT_SERVICE = Symbol.for('@dudousxd/nestjs-agent:agent-service');\n","import {\n AGENT_ATTACHMENT_STAGING,\n AGENT_DEPS_FACTORY,\n AGENT_MODEL_CATALOG,\n AGENT_OPTIONS,\n AGENT_QUOTA_PROVIDER,\n AGENT_RUNNER,\n AGENT_STORE,\n type ActionApprovalMode,\n type ActionProposalMutationView,\n type ActionProposalView,\n type Actor,\n type AgentHostContext,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type AttachmentRef,\n type AttachmentStagingStore,\n type ChatQueueState,\n DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY,\n type Decision,\n type ElicitationReply,\n type HumanReply,\n type ListStagedAttachmentsInput,\n type MessageAttachment,\n type MessageFeedback,\n type MessageFeedbackValue,\n type ModelCatalog,\n type ModelCatalogView,\n type PageContext,\n type QuotaProvider,\n type QuotaReport,\n REQUESTER_APPROVER,\n type StagedAttachment,\n type StoredMessage,\n type TextActionProposalVocabulary,\n type ThreadDetail,\n type ThreadSummary,\n type UpdateThreadInput,\n findCatalogModel,\n mayDecideApproval,\n readElicitationQuestions,\n settleDeadRun,\n textActionProposalReply,\n validateElicitationAnswer,\n} from '@dudousxd/nestjs-agent-core';\nimport type { UiCapabilities } from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n ConflictException,\n ForbiddenException,\n GoneException,\n HttpException,\n HttpStatus,\n Inject,\n Injectable,\n NotFoundException,\n NotImplementedException,\n Optional,\n PayloadTooLargeException,\n UnsupportedMediaTypeException,\n} from '@nestjs/common';\nimport type { AgentDepsFactory } from './agent-deps.factory.js';\nimport { utcDay } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\nimport { type AttachmentLimits, attachmentLimits } from './attachment-limits.js';\nimport { ActionProposalService } from './proposals/action-proposal.service.js';\nimport { ChatQueueService } from './queue/chat-queue.service.js';\nimport { publishQuotaBlocked } from './quota-exceeded.js';\nimport { RunNotActiveException } from './run-not-active.exception.js';\nimport { threadPersona } from './thread-persona.js';\n\n/**\n * What a send does when its thread already has a turn running:\n * - `'auto'` (default) — run now when the thread is idle, else wait in the thread's queue.\n * - `'queue'` — always wait in the queue, behind whatever is already waiting (it still starts at\n * once when nothing is running and nothing is ahead of it).\n * - `'interrupt'` — cancel the running turn and run this one next, ahead of the queue.\n */\nexport type ChatSendMode = 'auto' | 'queue' | 'interrupt';\n\n/** A send that is waiting in its thread's queue instead of running. */\nexport interface QueuedSend {\n threadId: string;\n queued: true;\n /** The queued message's id — also the run id it will start under. */\n messageId: string;\n /** 0-based place in the queue at the time it was queued (`0` → next). */\n position: number;\n queue: ChatQueueState;\n /** The turn it started under, when it started straight away (an idle thread). */\n runId?: string;\n /** The run an interrupt cancelled to make room for it. */\n interrupting?: string;\n}\n\n/** What {@link AgentService.send} did: started a turn, or queued the message. */\nexport type ChatSendResult =\n | { runId: string; threadId: string; queued?: undefined }\n | QueuedSend\n | { threadId: string; proposalDecision: unknown; text: string; queued?: undefined };\n\n/** The code of the `400` a send with nothing to answer gets (also AG-UI's, for the same case). */\nexport const NO_USER_MESSAGE_CODE = 'no_user_message';\n\n/**\n * `params` with its message checked, or a `400`. A send must carry something to answer: text, an\n * attachment, or `regenerate` (which re-answers the thread's last message and adds none). A missing\n * message is the empty one — so an attachment-only send never reaches the run with no text at all.\n */\nfunction sendableParams(params: ChatParams): ChatParams {\n const message: unknown = params.message;\n if (message !== undefined && message !== null && typeof message !== 'string') {\n throw new BadRequestException({\n statusCode: 400,\n code: 'invalid_message',\n message: 'message must be a string',\n });\n }\n const text = typeof message === 'string' ? message : '';\n if (\n text.trim().length === 0 &&\n (params.attachments?.length ?? 0) === 0 &&\n params.regenerate !== true\n ) {\n throw new BadRequestException({\n statusCode: 400,\n code: NO_USER_MESSAGE_CODE,\n message: 'nothing to answer: send a non-empty message, an attachment, or regenerate',\n });\n }\n const { channel, ...rest } = params;\n const stamped: ChatParams =\n channel === undefined ? params : { ...rest, pageContext: { ...params.pageContext, channel } };\n return text === message ? stamped : { ...stamped, message: text };\n}\n\nexport interface ChatParams {\n uiCapabilities?: UiCapabilities;\n actor: Actor;\n message: string;\n /** The host's own facts about this send — see `AgentRunInput.hostContext`. */\n hostContext?: AgentHostContext;\n /**\n * The HOST already decided this actor may write this thread — a chat-app thread several people\n * share, where anyone in it may continue the conversation. Skips the thread-ownership check of a\n * send; never set it from a request's own claim.\n */\n authorized?: boolean;\n threadId?: string;\n agentName?: string;\n /**\n * Run this turn under one of the agent's personas (`@Agent({ personas })`), and pin it on the\n * thread so later sends that name none keep it. Refused (400 `persona_not_found`) unless the agent\n * declares it. Omitted → the thread's pinned persona, else the agent's `defaultPersona`, else none.\n */\n personaId?: 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 /**\n * The channel this turn runs on — `web`, `mobile`, `whatsapp`… — over whatever its page context\n * says. Stamped as `pageContext.channel`, which is what decides (`turnChannel`) which genui tools\n * the turn is offered (`AgentGenuiModule.forRoot({ channels })`). Omitted → the page context's,\n * else `web`.\n */\n channel?: string;\n /** Re-run the last exchange instead of adding a new message. Requires an existing `threadId`. */\n regenerate?: boolean;\n /**\n * Run this turn on a catalog model instead of the thread's pinned one (or the provider default).\n * Refused (400) unless the bound `ModelCatalog` lists it as available to this actor and agent.\n */\n model?: string;\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 /** What to do when the thread already has a turn running — see {@link ChatSendMode}. */\n mode?: ChatSendMode;\n /**\n * When creating a thread (no `threadId`), ask the store to create it under this id — the id an\n * AG-UI consumer named the conversation with. A store may ignore it (`CreateThreadInput.id`); the\n * thread's real id is always the one on the result.\n */\n newThreadId?: string;\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/** Like {@link ThreadDefaultAgentReader}, for the thread's pinned model. */\nexport interface ThreadModelReader {\n modelForThread(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 @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging?: AttachmentStagingStore,\n @Optional()\n @Inject(AGENT_MODEL_CATALOG)\n private readonly models?: ModelCatalog,\n @Optional()\n @Inject(AGENT_QUOTA_PROVIDER)\n private readonly quotaProvider?: QuotaProvider,\n @Optional()\n @Inject(AGENT_OPTIONS)\n private readonly options?: Pick<\n AgentModuleOptions,\n 'quota' | 'actionApprovalMode' | 'attachments'\n >,\n @Optional() private readonly queue?: ChatQueueService,\n @Optional() private readonly proposals?: ActionProposalService,\n ) {}\n\n /**\n * Decide one independent proposal through the scoped proposal service — what the native\n * `action-proposals/:id/approve|reject` routes call — and the reply to show for it. `404` when\n * proposals are not on, `403`/`404` when this actor may not decide it.\n */\n async decideActionProposal(\n actor: Actor,\n threadId: string,\n proposalId: string,\n command: {\n decision: 'approved' | 'rejected';\n remember?: boolean;\n reason?: string;\n via: string;\n },\n ): Promise<{ proposalDecision: ActionProposalMutationView; text: string }> {\n if (this.options?.actionApprovalMode !== 'independent' || !this.proposals) {\n throw new NotFoundException('Proposal not found');\n }\n const result = await this.proposals.decide(threadId, proposalId, actor, command);\n return { proposalDecision: result, text: this.proposals.reply(result, command.decision) };\n }\n\n async handleTextDecision(threadId: string, actor: Actor, text: string) {\n if (this.options?.actionApprovalMode !== 'independent' || !this.proposals)\n return { status: 'unmatched' as const };\n return this.proposals.handleTextDecision(threadId, actor, text);\n }\n\n /** How `action` tools wait for their approval here — `AgentModule.forRoot({ actionApprovalMode })`. */\n actionApprovalMode(): ActionApprovalMode {\n return this.options?.actionApprovalMode ?? 'blocking';\n }\n\n /**\n * The words a text decision is made of (`actionProposalText.vocabulary`, English by default) — what\n * a surface without buttons tells the person to reply.\n */\n actionProposalVocabulary(): TextActionProposalVocabulary {\n return this.proposals?.textVocabulary() ?? DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY;\n }\n\n /** The configured reply (`actionProposalText.replies`) to a decision the store answered with `result`. */\n actionProposalReply(\n result: Pick<ActionProposalMutationView, 'status' | 'proposal'>,\n decision: 'approved' | 'rejected',\n ): string {\n return this.proposals?.reply(result, decision) ?? textActionProposalReply(result, decision);\n }\n\n /**\n * The proposals of a thread this actor may see — the thread's own actor, or one the policy lets\n * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page).\n * Without independent approvals (the default blocking mode) there are none, so the read answers an\n * empty list rather than refusing; deciding one still refuses.\n */\n async listActionProposals(actor: Actor, threadId: string): Promise<ActionProposalView[]> {\n if (this.options?.actionApprovalMode !== 'independent' || !this.proposals) {\n return [];\n }\n return this.proposals.list(threadId, actor);\n }\n\n /**\n * The attachment rules in force — what `GET <base>/config` serves and `POST <base>/attachments`\n * enforces. `enabled: false` when no `AGENT_ATTACHMENT_STAGING` provider is bound.\n */\n attachmentLimits(): AttachmentLimits {\n return attachmentLimits(this.options, this.staging);\n }\n\n /**\n * Stage a file for a later turn, held to the same limits as `POST <base>/attachments` — for a\n * surface that receives files itself (a messaging webhook). Refuses with `501` when attachments are\n * off, `415` for a type outside the allowlist and `413` past the size cap; send the returned\n * `mediaId` as `attachments: [{ mediaId }]`.\n */\n async stageAttachment(\n actor: Actor,\n file: { data: Buffer; contentType: string; filename: string },\n ): Promise<MessageAttachment> {\n if (this.staging === undefined) {\n throw new NotImplementedException(\n 'Attachments are not configured on this server: bind AGENT_ATTACHMENT_STAGING ' +\n '(e.g. import AgentMediaAttachmentsModule).',\n );\n }\n const { allowedContentTypes, maxBytes } = this.attachmentLimits();\n const contentType = file.contentType.split(';')[0]?.trim().toLowerCase() ?? '';\n if (!allowedContentTypes.includes(contentType)) {\n throw new UnsupportedMediaTypeException(\n `content type \"${contentType}\" is not allowed (allowed: ${allowedContentTypes.join(', ')})`,\n );\n }\n if (file.data.byteLength > maxBytes) {\n throw new PayloadTooLargeException(`file exceeds the ${maxBytes}-byte limit`);\n }\n return this.staging.stage({\n data: file.data,\n filename: file.filename,\n contentType,\n sizeBytes: file.data.byteLength,\n actor,\n });\n }\n /** The queue service when the bound store can hold a queue, else `undefined`. */\n private queueing(): ChatQueueService | undefined {\n return this.queue?.supported === true ? this.queue : undefined;\n }\n\n /** The queue service, or a 501 naming what is missing. */\n private requireQueue(): ChatQueueService {\n const queue = this.queueing();\n if (queue === undefined) {\n throw new NotImplementedException(\n 'Queueing messages requires an AgentStore that implements ChatQueueStore; the bound store ' +\n 'does not.',\n );\n }\n return queue;\n }\n\n /**\n * The actor's budget across windows (`GET <base>/quota`) — the bound {@link QuotaProvider}'s\n * report. Without one (a service built outside the module), a day window from the ledger.\n */\n async quotaReport(actor: Actor): Promise<QuotaReport> {\n if (this.quotaProvider !== undefined) {\n return this.quotaProvider.report({ actor });\n }\n const { usedTokens, costUsd } = await this.store.quotaToday(actor.id, utcDay());\n return { windows: [{ period: 'day', usedTokens, usedUsd: costUsd }] };\n }\n\n /**\n * Refuse a turn the actor's budget no longer covers — only when the host configured one\n * (`quota`): the default report is informational.\n */\n private async assertWithinQuota(actor: Actor): Promise<void> {\n if (this.options?.quota === undefined || this.quotaProvider === undefined) {\n return;\n }\n const report = await this.quotaProvider.report({ actor });\n const { blocked } = report;\n if (blocked !== undefined) {\n publishQuotaBlocked(actor, report, blocked);\n throw new HttpException(\n {\n statusCode: HttpStatus.TOO_MANY_REQUESTS,\n code: 'quota_exceeded',\n period: blocked.period,\n message:\n blocked.reason ??\n `The ${blocked.period === 'day' ? 'daily' : 'monthly'} quota is used up`,\n },\n HttpStatus.TOO_MANY_REQUESTS,\n );\n }\n }\n\n /**\n * The models `actor` may pick for `agent` (`GET <base>/models`). An empty catalog when none is\n * bound, so a picker simply has nothing to offer.\n */\n async listModels(actor: Actor, agent?: string): Promise<ModelCatalogView> {\n if (this.models === undefined) {\n return { providers: [], default: null };\n }\n return this.models.list({ actor, ...(agent !== undefined ? { agent } : {}) });\n }\n\n /**\n * `model` if the catalog offers it to this actor and agent right now, else a 400 naming why. The\n * one gate every model choice passes — a send's own, and a thread's pinned one at the moment it is\n * pinned and again at every turn that runs on it (availability can change in between).\n */\n private async assertModelAllowed(actor: Actor, agent: string, model: string): Promise<string> {\n if (this.models === undefined) {\n throw new BadRequestException(\n `model \"${model}\" cannot be selected: no ModelCatalog is configured (AgentModule.forRoot({ models }))`,\n );\n }\n const entry = findCatalogModel(await this.models.list({ actor, agent }), model);\n if (entry === undefined) {\n throw new BadRequestException(`model \"${model}\" is not offered`);\n }\n if (!entry.available) {\n throw new BadRequestException(\n `model \"${model}\" is not available${entry.unavailableReason ? `: ${entry.unavailableReason}` : ''}`,\n );\n }\n return entry.id;\n }\n\n /**\n * The model a turn runs on: the send's own (that turn only — it is never stored on the thread),\n * else the thread's pinned one, else none. An agent the catalog locks to one model runs on it\n * whatever was sent or pinned, and a send naming another model is refused.\n */\n private async resolveModel(\n actor: Actor,\n agent: string,\n requested: string | undefined,\n threadId: string | undefined,\n ): Promise<string | undefined> {\n const locked =\n this.models !== undefined ? (await this.models.list({ actor, agent })).locked : undefined;\n if (locked !== undefined) {\n if (requested !== undefined && requested !== locked.model) {\n throw new BadRequestException(\n `model \"${requested}\" cannot be selected: ${locked.reason ?? `this agent always uses \"${locked.model}\"`}`,\n );\n }\n return locked.model;\n }\n const model = requested ?? (threadId !== undefined ? await this.threadModel(threadId) : null);\n if (model === null || model === undefined) {\n return undefined;\n }\n return this.assertModelAllowed(actor, agent, model);\n }\n\n private async threadModel(threadId: string): Promise<string | null> {\n const projecting = this.store as Partial<ThreadModelReader>;\n if (typeof projecting.modelForThread === 'function') {\n return projecting.modelForThread(threadId);\n }\n return (await this.store.getThread(threadId))?.model ?? null;\n }\n\n /**\n * Start a turn — for in-process callers that need a run id back. A send that would have to wait\n * (its thread already has a turn running) is refused with `409` instead; {@link send} is the form\n * that queues it.\n */\n async chat(params: ChatParams): Promise<{ runId: string; threadId: string }> {\n const result = await this.send({ ...params, mode: 'auto' }, { textDecisions: false });\n if ('proposalDecision' in result) throw new Error('Unexpected text decision in run-only API');\n if (result.queued !== true) {\n return result;\n }\n if (result.runId !== undefined) {\n // The thread freed up while it was being queued, and it started straight away.\n return { runId: result.runId, threadId: result.threadId };\n }\n // Take it back out, so this call has no effect — unless it started in the meantime.\n const store = this.requireQueue().queueStore();\n if (!(await store.removeQueuedMessage(result.messageId))) {\n return { runId: result.messageId, threadId: result.threadId };\n }\n await this.requireQueue().publish(result.threadId);\n throw new ConflictException({\n statusCode: 409,\n code: 'run_active',\n message: `thread ${result.threadId} already has a turn running`,\n });\n }\n\n /**\n * Send a message: start a turn, or — when its thread already has one running — queue the message\n * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.\n */\n async send(\n claimed: ChatParams,\n sendOptions: { textDecisions?: boolean } = {},\n ): Promise<ChatSendResult> {\n // Before anything else — a text decision, the quota, a thread — so a send with nothing to answer\n // is a 400 that leaves nothing behind, instead of a run that crashes on the missing text.\n const params = sendableParams(claimed);\n if (\n sendOptions.textDecisions !== false &&\n this.options?.actionApprovalMode === 'independent' &&\n params.threadId !== undefined &&\n params.regenerate !== true &&\n this.proposals\n ) {\n const decision = await this.proposals.handleTextDecision(\n params.threadId,\n params.actor,\n params.message,\n );\n if ('proposalDecision' in decision) return decision;\n }\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 await this.assertWithinQuota(params.actor);\n // A name a persona took over (`Persona.aliases`) runs as the agent that owns it, under it.\n const target = this.deps.resolveAgent(\n await this.resolveAgentName(params.agentName, params.threadId),\n );\n const agentName = target.agentName;\n const persona = await this.resolvePersona(\n agentName,\n params.personaId ?? target.persona,\n params.threadId,\n );\n const model = await this.resolveModel(params.actor, agentName, params.model, 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 ...(agentName !== undefined ? { agentName } : {}),\n ...(params.transient === true ? { transient: true } : {}),\n ...(params.newThreadId !== undefined ? { id: params.newThreadId } : {}),\n ...(params.personaId !== undefined ? { persona: params.personaId } : {}),\n });\n threadId = created.id;\n } else {\n // Every send onto an existing thread is gated by ownership: a regenerate rewinds the thread,\n // and a queued message would otherwise land in someone else's conversation.\n if (params.authorized !== true) await this.assertOwnsThread(params.actor, threadId);\n // A persona a send NAMES is the person's pick for this conversation: pinned, so the next send\n // (and a reopened thread's picker) keeps it. One the send fell back to is not pinned.\n if (params.personaId !== undefined) {\n await this.pinThreadPersona(threadId, params.personaId);\n }\n }\n\n const input: AgentRunInput = {\n threadId,\n actor: params.actor,\n userText: params.message,\n day: utcDay(),\n agentName,\n ...(persona !== undefined ? { persona } : {}),\n ...(params.regenerate === true ? { regenerate: true } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n ...(params.pageContext !== undefined ? { pageContext: params.pageContext } : {}),\n ...(params.uiCapabilities !== undefined ? { uiCapabilities: params.uiCapabilities } : {}),\n ...(params.hostContext !== undefined ? { hostContext: params.hostContext } : {}),\n ...(model !== undefined ? { model } : {}),\n };\n\n const queue = this.queueing();\n if (queue === undefined) {\n if (this.options?.actionApprovalMode === 'independent')\n throw new Error('Independent actions require queued thread admission');\n // No admission to take: a store that predates the queue starts every send at once.\n const { runId } = await this.runner.start(input);\n await this.store.setActiveStream(threadId, runId);\n return { runId, threadId };\n }\n\n const mode = params.mode ?? 'auto';\n const { live, stale } = await queue.holder(threadId, this.runner);\n if (stale !== null) {\n // The thread is still pointed at a run that is gone: settle the calls it left showing an\n // approval card before another turn reads the thread.\n await settleDeadRun(this.store, { runId: stale });\n }\n // `queue` always answers as a queued send (202), so a client that asked for it handles one\n // shape; an idle thread starts it straight away all the same (`enqueue` kicks the queue).\n if (live === null && mode !== 'queue') {\n const runId = this.runner.runIdFor?.(input) ?? crypto.randomUUID();\n if (\n await queue\n .queueStore()\n .claimActiveStream(threadId, runId, stale !== null ? { replacing: stale } : {})\n ) {\n return { runId: await this.startClaimed(input, runId), threadId };\n }\n // Lost the race for the thread to another send: fall through and queue behind it.\n }\n if (params.regenerate === true) {\n throw new ConflictException({\n statusCode: 409,\n code: 'run_active',\n message: 'cannot regenerate while a turn is running on this thread',\n });\n }\n return this.enqueue(queue, input, mode, live);\n }\n\n /**\n * Start a turn the thread is already claimed for, under the claimed id. A runner that minted an\n * id of its own anyway gets the thread re-pointed at it; one that fails to start frees the thread.\n */\n private async startClaimed(input: AgentRunInput, runId: string): Promise<string> {\n const store = this.requireQueue().queueStore();\n let started: string;\n try {\n started = (await this.runner.start(input, { runId })).runId;\n } catch (error) {\n await store.releaseActiveStream(input.threadId, runId);\n throw error;\n }\n if (started !== runId) {\n await store.claimActiveStream(input.threadId, started, { replacing: runId });\n }\n return started;\n }\n\n /** Put a send in its thread's queue, then drain it if the thread turned out to be free. */\n private async enqueue(\n queue: ChatQueueService,\n input: AgentRunInput,\n mode: ChatSendMode,\n live: string | null,\n ): Promise<QueuedSend> {\n const store = queue.queueStore();\n const threadId = input.threadId;\n const interrupting = mode === 'interrupt' && live !== null ? live : undefined;\n const queued = await store.enqueueMessage({\n threadId,\n actor: input.actor,\n content: input.userText,\n ...(input.attachments !== undefined ? { attachments: input.attachments } : {}),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.persona !== undefined ? { persona: input.persona } : {}),\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),\n ...(input.uiCapabilities !== undefined ? { uiCapabilities: input.uiCapabilities } : {}),\n ...(input.hostContext !== undefined ? { hostContext: input.hostContext } : {}),\n ...(interrupting !== undefined ? { interrupt: true, at: 'head' as const } : {}),\n });\n let runId: string | undefined;\n if (interrupting !== undefined) {\n // An interrupt is a person choosing to run this now: whatever paused the queue, they are\n // overriding it. The cancel settles into the queue, which starts this message.\n await store.setQueuePause(threadId, null);\n await queue.publish(threadId);\n await this.runner.cancel(interrupting);\n } else {\n // The run holding the thread may have settled between our look and our enqueue — its drain\n // then found nothing. Starting the head here covers that; with a live holder it does nothing.\n runId = await queue.kick(threadId, this.runner);\n if (runId === undefined) {\n await queue.publish(threadId);\n }\n }\n const state = await queue.state(threadId);\n const position = state.items.findIndex((item) => item.id === queued.id);\n return {\n threadId,\n queued: true,\n messageId: queued.id,\n position: position === -1 ? 0 : position,\n queue: state,\n ...(runId !== undefined && runId === queued.id ? { runId } : {}),\n ...(interrupting !== undefined ? { interrupting } : {}),\n };\n }\n\n /** `GET <base>/threads/:id/queue` — the thread's waiting messages and whether it drains. */\n async getQueue(actor: Actor, threadId: string): Promise<ChatQueueState> {\n await this.assertOwnsThread(actor, threadId);\n return this.requireQueue().state(threadId);\n }\n\n /**\n * `PATCH <base>/queue/:messageId` — change a waiting message's text and/or attachments, and/or move\n * it to `position` in the queue. Answers the thread's queue.\n */\n async updateQueuedMessage(\n actor: Actor,\n messageId: string,\n patch: { message?: string; attachments?: AttachmentRef[] | null; position?: number },\n ): Promise<ChatQueueState> {\n const queue = this.requireQueue();\n const store = queue.queueStore();\n const threadId = await this.assertOwnsQueuedMessage(actor, messageId);\n if (patch.message !== undefined && patch.message.trim().length === 0) {\n throw new BadRequestException('message must not be empty');\n }\n const attachments =\n patch.attachments === undefined || patch.attachments === null\n ? patch.attachments\n : await this.resolveAttachments(actor, patch.attachments);\n if (patch.message !== undefined || attachments !== undefined) {\n const updated = await store.updateQueuedMessage(messageId, {\n ...(patch.message !== undefined ? { content: patch.message } : {}),\n ...(attachments !== undefined ? { attachments } : {}),\n });\n if (updated === null) {\n throw new GoneException(`queued message ${messageId} already started or was removed`);\n }\n }\n if (patch.position !== undefined) {\n if (!Number.isInteger(patch.position) || patch.position < 0) {\n throw new BadRequestException('position must be a non-negative integer');\n }\n if (!(await store.moveQueuedMessage(messageId, patch.position))) {\n throw new GoneException(`queued message ${messageId} already started or was removed`);\n }\n }\n return queue.publish(threadId);\n }\n\n /** `DELETE <base>/queue/:messageId` — drop a waiting message. Answers the thread's queue. */\n async removeQueuedMessage(actor: Actor, messageId: string): Promise<ChatQueueState> {\n const queue = this.requireQueue();\n const threadId = await this.assertOwnsQueuedMessage(actor, messageId);\n if (!(await queue.queueStore().removeQueuedMessage(messageId))) {\n throw new GoneException(`queued message ${messageId} already started or was removed`);\n }\n return queue.publish(threadId);\n }\n\n /**\n * `POST <base>/queue/:messageId/interrupt` — run a message that is already waiting NOW: it moves\n * to the head of its queue marked as an interrupt, any pause is lifted, and the running turn is\n * cancelled (its settle starts this message — the same path a `mode: 'interrupt'` send takes).\n * With nothing running, the message starts at once.\n *\n * One request, and the message never leaves the queue: a client that removed it and sent it again\n * would lose it if the second call failed, and would run it twice if another tab's drain started\n * it in between. Answers the queue, plus `interrupting` (the run that was cancelled) or `runId`\n * (the run this message started).\n */\n async interruptQueuedMessage(\n actor: Actor,\n messageId: string,\n ): Promise<ChatQueueState & { runId?: string; interrupting?: string }> {\n const queue = this.requireQueue();\n const store = queue.queueStore();\n const threadId = await this.assertOwnsQueuedMessage(actor, messageId);\n const gone = () =>\n new GoneException(`queued message ${messageId} already started or was removed`);\n const marked = await store.updateQueuedMessage(messageId, { interrupt: true });\n if (marked === null) {\n throw gone();\n }\n if (marked.interrupt !== true) {\n // Cancelling for a message the store did not mark would pause the queue behind the cancel\n // instead of starting it — refuse before anything is cancelled.\n throw new NotImplementedException(\n 'Interrupting a queued message requires a ChatQueueStore whose updateQueuedMessage stores ' +\n '`interrupt`; the bound store ignored it.',\n );\n }\n if (!(await store.moveQueuedMessage(messageId, 0))) {\n throw gone();\n }\n // A person choosing to run this now overrides whatever paused the queue.\n await store.setQueuePause(threadId, null);\n const { live } = await queue.holder(threadId, this.runner);\n if (live !== null && live !== messageId && (await store.getQueuedMessage(messageId)) !== null) {\n const state = await queue.publish(threadId);\n await this.runner.cancel(live);\n return { ...state, interrupting: live };\n }\n if (live !== null) {\n // The drain started it while this request was on its way: it is the running turn already.\n return { ...(await queue.state(threadId)), runId: messageId };\n }\n const runId = await queue.kick(threadId, this.runner);\n const state = runId === undefined ? await queue.publish(threadId) : await queue.state(threadId);\n return { ...state, ...(runId !== undefined ? { runId } : {}) };\n }\n\n /** `DELETE <base>/threads/:id/queue` — drop every waiting message (and any pause). */\n async clearQueue(actor: Actor, threadId: string): Promise<ChatQueueState> {\n await this.assertOwnsThread(actor, threadId);\n const queue = this.requireQueue();\n await queue.queueStore().clearQueue(threadId);\n await queue.queueStore().setQueuePause(threadId, null);\n return queue.publish(threadId);\n }\n\n /**\n * `POST <base>/threads/:id/queue/resume` — lift a pause and start the head when nothing is\n * running. Answers the queue, and the run the head started under, if it did.\n */\n async resumeQueue(actor: Actor, threadId: string): Promise<ChatQueueState & { runId?: string }> {\n await this.assertOwnsThread(actor, threadId);\n const queue = this.requireQueue();\n await queue.queueStore().setQueuePause(threadId, null);\n const runId = await queue.kick(threadId, this.runner);\n const state = runId === undefined ? await queue.publish(threadId) : await queue.state(threadId);\n return { ...state, ...(runId !== undefined ? { runId } : {}) };\n }\n\n /** The thread a queued message waits on, once the caller is shown to own it. */\n private async assertOwnsQueuedMessage(actor: Actor, messageId: string): Promise<string> {\n const message = await this.requireQueue().queueStore().getQueuedMessage(messageId);\n if (message === null) {\n throw new NotFoundException(`queued message ${messageId} not found`);\n }\n await this.assertOwnsThread(actor, message.threadId);\n return message.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 /**\n * Approve a parked action call as `actor`. Who may is the call's recorded approver's business\n * (see {@link assertMayDecide}); `remember` approves later calls of the same tool in the same\n * thread, and `via` names the surface the decision came through (`'web'`, `'slack'`, …) — both\n * persisted with the call.\n */\n async approve(\n actor: Actor,\n toolCallId: string,\n opts: { remember?: boolean; via?: string } = {},\n ): Promise<void> {\n await this.assertMayDecide(actor, toolCallId);\n return this.signalToolCall(toolCallId, {\n approved: true,\n executedByRef: actor.id,\n ...(opts.remember === true ? { remember: true } : {}),\n ...(opts.via !== undefined ? { decidedVia: opts.via } : {}),\n });\n }\n\n async reject(\n actor: Actor,\n toolCallId: string,\n reason?: string,\n opts: { via?: string } = {},\n ): Promise<void> {\n await this.assertMayDecide(actor, toolCallId);\n return this.signalToolCall(toolCallId, {\n approved: false,\n executedByRef: actor.id,\n ...(reason !== undefined ? { reason } : {}),\n ...(opts.via !== undefined ? { decidedVia: opts.via } : {}),\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 opts: { via?: string } = {},\n ): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n await this.assertAnswersFit(toolCallId, answers);\n const reply: ElicitationReply = {\n answers,\n answeredByRef: actor.id,\n ...(opts.via !== undefined ? { answeredVia: opts.via } : {}),\n };\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, opts: { via?: string } = {}): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n const reply: ElicitationReply = {\n answers: {},\n skipped: true,\n answeredByRef: actor.id,\n ...(opts.via !== undefined ? { answeredVia: opts.via } : {}),\n };\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 if ((await this.store.toolCallApproval?.(toolCallId))?.status === 'proposed')\n throw new ConflictException(\n 'Independent proposals require the scoped proposal decision route',\n );\n await this.assertNotExpired(toolCallId);\n const runId = await this.resolveRunForToolCall(toolCallId);\n await this.assertRunWaiting(runId);\n return this.runner.signal(runId, toolCallId, reply);\n }\n\n /**\n * Refuse a decision addressed at a run that is over (`409 run_not_active`). The runtime would take\n * the signal and buffer it for a run that never comes back — the person's \"yes\" is accepted, the\n * card says so, and nothing runs. Settles the calls the dead run left awaiting a decision on the\n * way out, so the card stops asking. A runner that cannot say whether a run is alive is taken at\n * its word that it is, and so is one that fails to answer.\n */\n private async assertRunWaiting(runId: string): Promise<void> {\n if (typeof this.runner.isRunActive !== 'function') {\n return;\n }\n const active = await this.runner.isRunActive(runId).catch(() => true);\n if (active) {\n return;\n }\n await settleDeadRun(this.store, { runId });\n throw new RunNotActiveException(runId);\n }\n\n /** Who owns the thread, or `null` when there is no such (live) thread. */\n async threadOwner(threadId: string): Promise<string | null> {\n return this.store.ownerOfThread(threadId);\n }\n\n /**\n * May `actor` continue the run whose stream is `runId` — the AG-UI resume? Only the actor whose\n * thread is streaming it (`403` otherwise), and only while it still is: a run that is over is\n * waiting on no one (`409 run_not_active`), whatever an old interrupt id says.\n */\n async assertResumable(actor: Actor, runId: string): Promise<void> {\n const owner = await this.store.ownerOfActiveStream(runId);\n if (owner === null) {\n throw new RunNotActiveException(runId);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('run belongs to another actor');\n }\n }\n\n /**\n * Everything {@link approve} / {@link reject} check before they signal — who may decide, and\n * that the request has not lapsed — without signalling. For a caller that settles several\n * decisions at once and must refuse all of them if one is refused (an AG-UI resume).\n */\n async checkDecision(actor: Actor, toolCallId: string): Promise<void> {\n await this.assertMayDecide(actor, toolCallId);\n await this.assertNotExpired(toolCallId);\n }\n\n /** Everything {@link answer} checks before it signals, without signalling — see {@link checkDecision}. */\n async checkAnswer(\n actor: Actor,\n toolCallId: string,\n answers: Record<string, string[]>,\n ): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n await this.assertAnswersFit(toolCallId, answers);\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, actor);\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 (\n patch.defaultAgent === undefined &&\n patch.model === undefined &&\n patch.persona === undefined\n ) {\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, model or persona requires an AgentStore that implements \" +\n 'updateThread(); the bound store does not support it.',\n );\n }\n // Pinned against the agent the thread's next turn will run as — the one the patch sets, else\n // the thread's own default, else the module's.\n const model =\n patch.model === undefined || patch.model === null\n ? patch.model\n : await this.assertModelAllowed(\n actor,\n patch.defaultAgent ?? (await this.resolveAgentName(undefined, threadId)),\n patch.model,\n );\n // Validated against the agent the thread's next turn will run as, like the model above.\n if (patch.persona !== undefined && patch.persona !== null) {\n this.deps.resolvePersona({\n agentName: this.deps.resolveAgent(\n patch.defaultAgent ?? (await this.resolveAgentName(undefined, threadId)),\n ).agentName,\n requested: patch.persona,\n });\n }\n await this.store.updateThread(threadId, {\n ...(title !== undefined ? { title } : {}),\n ...(patch.defaultAgent !== undefined ? { defaultAgent: patch.defaultAgent } : {}),\n ...(model !== undefined ? { model } : {}),\n ...(patch.persona !== undefined ? { persona: patch.persona } : {}),\n });\n }\n\n /**\n * The persona this send runs under — see {@link AgentDepsFactory.resolvePersona}. The thread's\n * pinned persona is read only when the send names none AND the agent has personas to pick from.\n */\n private async resolvePersona(\n agentName: string,\n requested: string | undefined,\n threadId: string | undefined,\n ): Promise<string | undefined> {\n const needsThread =\n requested === undefined &&\n threadId !== undefined &&\n this.deps.personaCatalog(agentName).length > 0;\n return this.deps.resolvePersona({\n agentName,\n ...(requested !== undefined ? { requested } : {}),\n ...(needsThread ? { threadPersona: await threadPersona(this.store, threadId) } : {}),\n });\n }\n\n /** Pin `persona` on the thread when it is not already — a no-op on a store that cannot. */\n private async pinThreadPersona(threadId: string, persona: string): Promise<void> {\n if (this.store.updateThread === undefined) {\n return;\n }\n if ((await threadPersona(this.store, threadId)) !== persona) {\n await this.store.updateThread(threadId, { persona });\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 model: thread.model ?? null,\n persona: thread.persona ?? null,\n activeRunId: (await this.store.activeRunForThread?.(thread.id)) ?? thread.activeRunId ?? null,\n };\n }\n\n private async toDetailView(thread: ThreadDetail, actor: Actor): Promise<ThreadDetail> {\n const summary = await this.toSummaryView(thread);\n const queue = this.queueing();\n return {\n ...summary,\n messages: await this.freshAttachmentUrls(thread.messages, actor),\n ...(queue !== undefined ? { queue: await queue.state(thread.id) } : {}),\n };\n }\n\n /**\n * Re-mint each replayed attachment's url from the staging store, by `mediaId`: the url persisted\n * with the message was minted for THAT turn (a presigned url with an expiry), so an old turn would\n * otherwise show a dead link. The store's own access check applies — an attachment it will not\n * resolve for this actor keeps the url it was stored with.\n */\n private async freshAttachmentUrls(\n messages: StoredMessage[],\n actor: Actor,\n ): Promise<StoredMessage[]> {\n const staging = this.staging;\n if (staging === undefined || !messages.some((message) => message.attachments?.length)) {\n return messages;\n }\n return Promise.all(\n messages.map(async (message) => {\n if (message.attachments === undefined || message.attachments.length === 0) return message;\n const attachments = await Promise.all(\n message.attachments.map(async (attachment) => {\n try {\n const fresh = await staging.resolve({ mediaId: attachment.mediaId, actor });\n return fresh ?? attachment;\n } catch {\n return attachment;\n }\n }),\n );\n return { ...message, attachments };\n }),\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 * Rate a message in one of `actor`'s threads: `'up'`/`'down'` with an optional comment, or `null`\n * to clear the rating. Answers `404` for an unknown message, `403` for another actor's, and `501`\n * on a store without `threadOfMessage` + `setMessageFeedback`.\n */\n async setMessageFeedback(\n actor: Actor,\n messageId: string,\n input: { value: MessageFeedbackValue | null; comment?: string },\n ): Promise<MessageFeedback | null> {\n if (input.value !== null && input.value !== 'up' && input.value !== 'down') {\n throw new BadRequestException(\"value must be 'up', 'down' or null\");\n }\n if (input.comment !== undefined && typeof input.comment !== 'string') {\n throw new BadRequestException('comment must be a string');\n }\n const comment = input.comment?.trim();\n if (comment !== undefined && comment.length > 2000) {\n throw new BadRequestException('comment must be at most 2000 characters');\n }\n if (this.store.threadOfMessage === undefined || this.store.setMessageFeedback === undefined) {\n throw new NotImplementedException(\n 'Message feedback requires an AgentStore that implements threadOfMessage() and ' +\n 'setMessageFeedback(); the bound store does not support it.',\n );\n }\n const threadId = await this.store.threadOfMessage(messageId);\n if (threadId === null) {\n throw new NotFoundException(`message ${messageId} not found`);\n }\n await this.assertOwnsThread(actor, threadId);\n const feedback: MessageFeedback | null =\n input.value === null\n ? null\n : {\n value: input.value,\n ...(comment !== undefined && comment.length > 0 ? { comment } : {}),\n updatedAt: new Date().toISOString(),\n };\n await this.store.setMessageFeedback(messageId, feedback);\n return feedback;\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 * 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 * Check a reply against the questions it answers before it is signalled: every submitted value a\n * question's own rules accept (a typed input's type, bounds and pattern; a pick from the offered\n * options), and every `required` question answered — by the reply, or by the defaults an omitted\n * question falls back to. A reply the loop would have to drop parts of is refused here instead, so\n * the person who typed it hears why. Needs the store to hand back the call's recorded questions;\n * without that seam the loop's own filtering is the only check.\n */\n private async assertAnswersFit(\n toolCallId: string,\n answers: Record<string, string[]>,\n ): Promise<void> {\n if (this.store.toolCallInput === undefined) {\n return;\n }\n const questions = readElicitationQuestions(await this.store.toolCallInput(toolCallId));\n for (const question of questions) {\n const submitted = Object.hasOwn(answers, question.id) ? answers[question.id] : undefined;\n const problem = validateElicitationAnswer(question, submitted ?? question.defaults ?? []);\n if (problem !== null) {\n throw new BadRequestException(`answers[\"${question.id}\"] ${problem}`);\n }\n }\n }\n\n /**\n * Authorization seam for approve/reject. The call's recorded approver decides who may settle it:\n * the requester (the default, and every call recorded before approvers existed) is the thread's\n * own actor — the ownership check this always was; any other approver goes through the policy's\n * `canDecide`, which by default asks whether the actor holds that role.\n */\n private async assertMayDecide(actor: Actor, toolCallId: string): Promise<void> {\n const approval = await this.store.toolCallApproval?.(toolCallId);\n const approver = approval?.approver ?? REQUESTER_APPROVER;\n if (approver === REQUESTER_APPROVER) {\n return this.assertOwnsToolCall(actor, toolCallId);\n }\n const requesterRef = await this.store.ownerOfToolCall(toolCallId);\n if (requesterRef === null) {\n throw new NotFoundException(`tool call ${toolCallId} not found`);\n }\n const allowed = await mayDecideApproval(this.deps.forAgent().approvalPolicy, actor, {\n toolCallId,\n approver,\n requesterRef,\n });\n if (!allowed) {\n throw new ForbiddenException(`this approval is for ${approver}`);\n }\n }\n\n /**\n * Refuse a decision on a request that has already lapsed — recorded `expired`, or past its\n * `expiresAt` with the run's own timer about to fire. Signalling it anyway would race the timeout:\n * a durable runtime buffers a signal nobody is waiting on, and a late approval must not be what a\n * later replay of the run reads back.\n */\n private async assertNotExpired(toolCallId: string): Promise<void> {\n const approval = await this.store.toolCallApproval?.(toolCallId);\n if (approval === null || approval === undefined) {\n return;\n }\n const lapsed =\n approval.status === 'expired' ||\n (approval.status === 'pending_approval' &&\n approval.expiresAt !== null &&\n Date.parse(approval.expiresAt) <= Date.now());\n if (lapsed) {\n throw new GoneException(`the approval request for tool call ${toolCallId} has expired`);\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 { ResolveToolUiCatalog, ToolUiChannelGuide } from '@dudousxd/nestjs-agent-core';\nimport type {\n AgentIntake,\n AgentPricingStore,\n AgentStore,\n ApprovalPolicy,\n HistoryPolicy,\n InputProcessor,\n MemoryConfig,\n ModelProvider,\n OutputProcessor,\n Persona,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n SkillsConfig,\n TokenStreamSink,\n ToolRegistry,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n resolveUiCatalog?: ResolveToolUiCatalog;\n /** genui `channels`: the channel's prompt block, and what tool pushes were delivered as. */\n uiChannelGuide?: ToolUiChannelGuide;\n actionApprovalMode?: 'blocking' | 'independent';\n model: ModelProvider;\n store: AgentStore;\n registry: ToolRegistry;\n rolesPolicy: RolesPolicy;\n /** Who approves an action call, and for how long (from `forRoot({ approvalPolicy })`). Undefined → the requester, no expiry. */\n approvalPolicy?: ApprovalPolicy;\n quota?: QuotaStore;\n sink: TokenStreamSink;\n /** Fallback accounting label; the provider's turn result overrides it when set. */\n modelId?: string;\n systemPrompt: string | PromptBuilder;\n /** App-wide `@SystemPromptContributor()` sections appended after the agent's base prompt. */\n promptContributors: PromptContributor[];\n maxSteps: number;\n /** Nesting ceiling for delegation below this agent. Undefined → the loop's default. */\n maxDelegationDepth?: number;\n /** How many times one agent may appear on a chain. Undefined → the loop's default. */\n maxAgentAppearances?: number;\n /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** The agent's personas (`@Agent({ personas })`) — read by the loop only for a run that names one. */\n personas?: Persona[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\n /**\n * Transient-tool-error retry policy (from module options). Undefined → default ON\n * (`{ attempts: 2, backoffMs: 150 }` with the default classifier); `false` → disabled.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /** How many follow-up suggestions to generate after the final turn. Undefined/0 → off. */\n followUpsCount?: number;\n /** Inject-mode retriever (from `forRoot({ retrieval })`). Undefined → no prompt augmentation. */\n retriever?: Retriever;\n /** Passages inject-mode retrieval requests. Undefined → loop default (5). */\n retrievalTopK?: number;\n /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */\n pricingStore?: AgentPricingStore;\n /** The agent's history ceiling, resolved from `@Agent({ history })` / module options. Undefined → unbounded. */\n historyPolicy?: HistoryPolicy;\n /** Module-wide prompt rewriters, applied before every model call. Empty → none. */\n inputProcessors: InputProcessor[];\n /** Module-wide answer gates. NON-EMPTY MEANS THE TURN'S MODEL OUTPUT IS BUFFERED, not streamed. */\n outputProcessors: OutputProcessor[];\n /** The agent's `@Agent({ outputSchema })`, resolved from DI — never over the wire. Undefined → free text. */\n outputSchema?: StandardSchemaV1;\n /** Extra model calls allowed to repair an answer that failed `outputSchema`. Undefined → 1. */\n outputRepairAttempts?: number;\n /** The agent's `@Agent({ intake })` question set, asked before the turn starts. Undefined → none. */\n intake?: AgentIntake;\n /** Whether the model may call the built-in `ask` tool this turn. Undefined/false → it never sees it. */\n ask?: boolean;\n /**\n * The resolved skills seam (`forRoot({ skills })` + discovered `@Skill` providers). Undefined →\n * no catalog, no `skill` tool, and the turn spends no checkpoint on either.\n */\n skills?: SkillsConfig;\n /**\n * The resolved memory seam (`forRoot({ memory })`). Undefined → no block, no `remember` tool, and\n * the turn spends no checkpoint on either.\n */\n memory?: MemoryConfig;\n}\n\nexport function utcDay(date = new Date()): string {\n return date.toISOString().slice(0, 10);\n}\n\n/**\n * Wraps a parent run's sink writer for a sub-agent: `write` forwards (so the sub-agent's tokens and\n * pending action-tool frames reach the human's live stream), but `end` / `fail` are swallowed — the\n * top-level run owns the stream's lifecycle, so a finished/failed child must not close or error the\n * shared stream out from under the parent that is still running. They do `flush` it: a sink that\n * gathers frames (the SQL sink) writes out what the child left, so the parent's next frame —\n * possibly written on another replica — lands after it.\n */\nexport function childSinkWriter(writer: SinkWriter): SinkWriter {\n return {\n write: (chunk) => writer.write(chunk),\n // The top-level run owns end/fail — but what the child wrote must not be held back past it.\n end: async () => {\n await writer.flush?.();\n },\n fail: async () => {\n await writer.flush?.();\n },\n flush: async () => {\n await writer.flush?.();\n },\n };\n}\n","import type { AgentAttachmentConfig, AttachmentStagingStore } from '@dudousxd/nestjs-agent-core';\nimport type { AgentModuleOptions } from './agent.options.js';\n\n/** Default per-file size cap (20 MiB). */\nexport const DEFAULT_MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024;\n\n/** Default allowlist: what multimodal model providers commonly accept as native image/file parts. */\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/** How many attachments one message may name. */\nexport const MAX_ATTACHMENTS_PER_MESSAGE = 10;\n\n/** The attachment rules in force — `AgentAttachmentConfig`, as `GET <base>/config` serves it. */\nexport type AttachmentLimits = AgentAttachmentConfig;\n\n/**\n * One source for attachment limits: the staging store's own `describe()` when it declares them\n * (`AgentMediaAttachmentsModule` does), else `AgentModule`'s `attachments` option, else the defaults.\n */\nexport function attachmentLimits(\n options: Pick<AgentModuleOptions, 'attachments'> | undefined,\n staging: AttachmentStagingStore | undefined,\n): AttachmentLimits {\n const declared = staging?.describe?.();\n const own = options?.attachments;\n return {\n enabled: staging !== undefined,\n upload: staging === undefined ? null : (declared?.upload ?? 'multipart'),\n maxBytes: declared?.maxBytes ?? own?.maxBytes ?? DEFAULT_MAX_ATTACHMENT_BYTES,\n allowedContentTypes:\n declared?.allowedContentTypes ??\n own?.allowedContentTypes ??\n DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,\n maxPerMessage: MAX_ATTACHMENTS_PER_MESSAGE,\n };\n}\n","import {\n AGENT_OPTIONS,\n AGENT_STORE,\n type ActionProposalMutationView,\n type ActionProposalOutcomeStore,\n type ActionProposalScope,\n type ActionProposalStore,\n type ActionProposalView,\n type Actor,\n type AgentStore,\n DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES,\n DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY,\n type ListActionProposals,\n type TextActionProposalReplies,\n type TextActionProposalVocabulary,\n mayDecideApproval,\n parseTextActionProposalCommand,\n resolveTextActionProposalDecision,\n textActionProposalReply,\n toActionProposalMutationView,\n toActionProposalView,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n ForbiddenException,\n Inject,\n Injectable,\n NotFoundException,\n NotImplementedException,\n} from '@nestjs/common';\nimport type { AgentModuleOptions } from '../agent.options.js';\n\n@Injectable()\nexport class ActionProposalService {\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_OPTIONS)\n private readonly options: Pick<AgentModuleOptions, 'approvalPolicy' | 'actionProposalText'>,\n ) {\n const text = options.actionProposalText;\n this.vocabulary = { ...DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY, ...text?.vocabulary };\n this.replies = { ...DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES, ...text?.replies };\n }\n /** The words a text decision is made of, and what the agent answers — English unless configured. */\n private readonly vocabulary: TextActionProposalVocabulary;\n private readonly replies: TextActionProposalReplies;\n private hasCapability(): boolean {\n const store = this.store as Partial<ActionProposalStore & ActionProposalOutcomeStore>;\n return (\n typeof store.getThreadActionProposalScope === 'function' &&\n typeof store.listActionProposals === 'function'\n );\n }\n private capability(): AgentStore & ActionProposalStore & ActionProposalOutcomeStore {\n const store = this.store as AgentStore & ActionProposalStore & ActionProposalOutcomeStore;\n if (!this.hasCapability())\n throw new NotImplementedException('Action proposals are unavailable');\n return store;\n }\n private async scope(threadId: string, actor: Actor): Promise<ActionProposalScope> {\n const scope = await this.capability().getThreadActionProposalScope(threadId);\n if (!scope) throw new NotFoundException('Thread not found');\n if (scope.tenantRef !== (actor.tenantRef ?? null))\n throw new ForbiddenException('Wrong proposal tenant');\n return scope;\n }\n private mayDecide(\n actor: Actor,\n proposal: { originToolCallId: string; approver: string; actorRef: string },\n ) {\n return mayDecideApproval(this.options.approvalPolicy, actor, {\n toolCallId: proposal.originToolCallId,\n approver: proposal.approver,\n requesterRef: proposal.actorRef,\n });\n }\n /**\n * One page of a thread's proposals this actor may see. A store without the proposal capability\n * can only run blocking approvals, so a thread there has no proposals: an empty, final page rather\n * than `501` — a client that lists by default (React's `useAgentChat`) needs no flag. Deciding one\n * still answers `501`.\n */\n async listPage(\n threadId: string,\n actor: Actor,\n query: Pick<ListActionProposals, 'after'> = {},\n ): Promise<{ items: ActionProposalView[]; next?: NonNullable<ListActionProposals['after']> }> {\n if (!this.hasCapability()) return { items: [] };\n const scope = await this.scope(threadId, actor);\n const rows = await this.capability().listActionProposals(scope, { limit: 1000, ...query });\n const visible = [];\n for (const row of rows)\n if (scope.actorRef === actor.id || (await this.mayDecide(actor, row))) visible.push(row);\n const last = rows.at(-1);\n return {\n // The public view: a row carries the worker's lease token and the tool's idempotency key.\n items: visible.map(toActionProposalView),\n ...(rows.length === 1000 && last ? { next: { createdAt: last.createdAt, id: last.id } } : {}),\n };\n }\n async list(threadId: string, actor: Actor) {\n return (await this.listPage(threadId, actor)).items;\n }\n async decide(\n threadId: string,\n proposalId: string,\n actor: Actor,\n command: {\n decision: 'approved' | 'rejected';\n remember?: boolean;\n reason?: string;\n via?: string;\n },\n ): Promise<ActionProposalMutationView> {\n const scope = await this.scope(threadId, actor);\n const proposal = await this.capability().getActionProposal(scope, proposalId);\n if (!proposal) throw new NotFoundException('Proposal not found');\n if (!(await this.mayDecide(actor, proposal)))\n throw new ForbiddenException('May not decide this proposal');\n const result = await this.capability().decideActionProposal(scope, proposalId, {\n decision: command.decision,\n actorRef: actor.id,\n via: command.via ?? 'web',\n ...(command.remember !== undefined ? { remember: command.remember } : {}),\n ...(command.reason !== undefined ? { reason: command.reason } : {}),\n });\n return toActionProposalMutationView(result);\n }\n async handleTextDecision(threadId: string, actor: Actor, text: string) {\n const command = parseTextActionProposalCommand(text, this.vocabulary);\n if (command.status === 'unmatched') return command;\n if (command.proposalId !== undefined) {\n const result = await this.decide(threadId, command.proposalId, actor, {\n decision: command.decision,\n remember: command.remember,\n via: 'text',\n });\n return this.textReceipt(threadId, result, command.decision);\n }\n const candidates = [];\n const scope = await this.scope(threadId, actor);\n const pending = await this.capability().listActionProposals(scope, {\n decision: 'pending',\n limit: 1000,\n });\n for (const proposal of pending)\n if (await this.mayDecide(actor, proposal)) candidates.push(proposal);\n const resolution = resolveTextActionProposalDecision(text, candidates, this.vocabulary);\n if (resolution.status === 'unmatched') return resolution;\n // A saturated page may hide other candidates: a bare command cannot safely pick one.\n const saturated = pending.length === 1000 && !text.includes('#');\n if (resolution.status === 'ambiguous' || saturated) {\n const proposalIds = candidates.map(({ id }) => id);\n return {\n threadId,\n proposalDecision: { status: 'ambiguous' as const, proposalIds },\n text: saturated ? this.replies.tooMany : this.replies.ambiguous(proposalIds),\n };\n }\n const result = await this.decide(threadId, resolution.proposalId, actor, {\n decision: resolution.decision,\n remember: resolution.remember,\n via: 'text',\n });\n return this.textReceipt(threadId, result, resolution.decision);\n }\n private textReceipt(\n threadId: string,\n result: ActionProposalMutationView,\n decision: 'approved' | 'rejected',\n ) {\n return { threadId, proposalDecision: result, text: this.reply(result, decision) };\n }\n /** The configured words a text decision is made of (`actionProposalText.vocabulary`). */\n textVocabulary(): TextActionProposalVocabulary {\n return this.vocabulary;\n }\n /** The configured reply to a decision the store answered with `result`. */\n reply(\n result: Pick<ActionProposalMutationView, 'status' | 'proposal'>,\n decision: 'approved' | 'rejected',\n ): string {\n return textActionProposalReply(result, decision, this.replies);\n }\n}\n","import {\n AGENT_ATTACHMENT_STAGING,\n AGENT_DEPS_FACTORY,\n AGENT_OPTIONS,\n AGENT_QUOTA_PROVIDER,\n AGENT_SINK,\n AGENT_STORE,\n type Actor,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type AgentStreamEvent,\n type AttachmentStagingStore,\n type ChatQueueState,\n type ChatQueueStore,\n type MessageAttachment,\n type QueuePause,\n type QueuePauseReason,\n type QueuedMessage,\n type QuotaProvider,\n type TokenStreamSink,\n encodeStreamEvent,\n isChatQueueStore,\n queuedMessageView,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, NotImplementedException, Optional } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { utcDay } from '../agent-deps.js';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { publishQuotaBlocked } from '../quota-exceeded.js';\nimport { threadPersona } from '../thread-persona.js';\n\n/** How the run that held a thread ended. */\nexport type QueueSettleOutcome = 'completed' | 'failed' | 'cancelled';\n\n/** The next queued message a settling run handed the thread to — the caller starts it. */\nexport interface QueuedTurn {\n /** The run id the thread is already claimed for: the queued message's own id. */\n runId: string;\n input: AgentRunInput;\n messageId: string;\n}\n\n/**\n * What {@link ChatQueueService.plan} decided. Plain data, so a durable workflow can journal it in a\n * `localStep` and start `next` itself (`ctx.startChild`) — replay-safe, and never twice.\n */\nexport interface QueuePlan {\n next?: QueuedTurn;\n /** The `queue` frame to write into the settling run's stream, before its terminal. */\n frame?: AgentStreamEvent;\n}\n\n/** Starts a run under a pre-claimed id — a runner's own `start`, bound. */\nexport type QueuedTurnStarter = (input: AgentRunInput, runId: string) => Promise<unknown>;\n\n/** How many times a drain retries when the head it picked is removed under it. */\nconst MAX_DRAIN_ATTEMPTS = 8;\n\n/**\n * The thread-level message queue: messages a person sends while a turn is running wait here, and\n * the next one starts as soon as the running turn settles.\n *\n * Everything that decides WHICH run holds a thread goes through the store's compare-and-set\n * admission (`claimActiveStream` / `releaseActiveStream`), so two processes that both try to start\n * the next turn — a settling run on a worker and a send on an API pod — cannot both win. The next\n * run's id is the queued message's own id, which makes every step here idempotent: a retried claim\n * for the same message succeeds again, and a durable start under the same id is a no-op.\n *\n * Policy, per outcome of the run that held the thread:\n * - `completed` → the head starts.\n * - `failed` → the queue pauses (`run_failed`), keeping every message.\n * - `cancelled` → the queue pauses (`cancelled`), unless the head was queued by an interrupt — the\n * cancel was made for it, so it starts.\n * A paused queue starts nothing until it is resumed. A head whose actor is over quota pauses it\n * (`quota_exceeded`) instead of starting.\n */\n@Injectable()\nexport class ChatQueueService {\n private readonly logger = new Logger(ChatQueueService.name);\n /**\n * Runs this process claimed a thread for and has not handed to a runner yet. A holder in here is\n * alive whatever the runner says — it simply has not registered the run yet.\n */\n private readonly starting = new Set<string>();\n\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_SINK) private readonly sink: TokenStreamSink,\n @Optional()\n @Inject(AGENT_QUOTA_PROVIDER)\n private readonly quotaProvider?: QuotaProvider,\n @Optional()\n @Inject(AGENT_OPTIONS)\n private readonly options?: Pick<AgentModuleOptions, 'quota'>,\n @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging?: AttachmentStagingStore,\n // Optional: a queue built outside the module (a test, a host's own wiring) resolves no persona\n // for a message that did not carry one, which is how such a message always started.\n @Optional()\n @Inject(AGENT_DEPS_FACTORY)\n private readonly deps?: AgentDepsFactory,\n ) {}\n\n /** Whether the bound store can hold a queue. Without one, a busy thread is not queued. */\n get supported(): boolean {\n return isChatQueueStore(this.store);\n }\n\n /** The bound store as a queue store, or a 501 naming what is missing. */\n queueStore(): AgentStore & ChatQueueStore {\n if (!isChatQueueStore(this.store)) {\n throw new NotImplementedException(\n 'Queueing messages requires an AgentStore that implements ChatQueueStore (enqueueMessage, ' +\n 'listQueue, …, claimActiveStream, releaseActiveStream); the bound store does not.',\n );\n }\n return this.store;\n }\n\n async state(threadId: string): Promise<ChatQueueState> {\n const store = this.queueStore();\n const [items, paused] = await Promise.all([\n store.listQueue(threadId),\n store.queuePause(threadId),\n ]);\n return { items: items.map(queuedMessageView), paused };\n }\n\n /**\n * Whether `holder` is still running. A run this process is about to start is; otherwise the\n * runner decides, and a runner that cannot tell says yes.\n */\n async isAlive(holder: string, runner: AgentRunner): Promise<boolean> {\n if (this.starting.has(holder)) {\n return true;\n }\n if (typeof runner.isRunActive !== 'function') {\n return true;\n }\n try {\n return await runner.isRunActive(holder);\n } catch {\n return true;\n }\n }\n\n /**\n * The run holding `threadId`, or `null` when it is free — a holder the runner reports dead counts\n * as free, and is returned as `stale` so the caller can claim over it.\n */\n async holder(\n threadId: string,\n runner: AgentRunner,\n ): Promise<{ live: string | null; stale: string | null }> {\n const holder = await this.queueStore().activeRunForThread(threadId);\n if (holder === null) {\n return { live: null, stale: null };\n }\n return (await this.isAlive(holder, runner))\n ? { live: holder, stale: null }\n : { live: null, stale: holder };\n }\n\n /**\n * Decide what follows a TOP-LEVEL run that is settling on `threadId`, and move the thread there:\n * hand it to the next queued message (claimed and popped here, started by the caller), or pause\n * the queue, or release the thread. Call it BEFORE the run's terminal frame, so a client reading\n * the stream learns what comes next from the `queue` frame, and so the thread is already free\n * when the client sees the run end.\n *\n * A no-op returning `{}` on a store without a queue.\n */\n async plan(args: {\n threadId: string;\n /** The run that is settling; `null` when the thread is idle (a kick). */\n runId: string | null;\n outcome: QueueSettleOutcome;\n error?: string;\n }): Promise<QueuePlan> {\n if (!isChatQueueStore(this.store)) {\n return {};\n }\n const store = this.store;\n const { threadId, outcome } = args;\n // Only the run holding the thread moves it on. One that already handed it over (a durable\n // cancel settles from outside the body, and the body may still settle after it) has nothing\n // left to decide — deciding again would pause a queue the handover just started.\n if ((await store.activeRunForThread(threadId)) !== args.runId) {\n return {};\n }\n // The id holding the thread right now, as far as this drain knows: the settling run, until it\n // is released, then nobody.\n let holding: string | null = args.runId;\n for (let attempt = 0; attempt < MAX_DRAIN_ATTEMPTS; attempt += 1) {\n const items = await store.listQueue(threadId);\n const head = items[0];\n if (head === undefined) {\n if (holding !== null) {\n await store.releaseActiveStream(threadId, holding);\n holding = null;\n // An enqueue that landed between the read above and this release saw the thread held and\n // left its message for this drain — read once more now that the thread is free.\n continue;\n }\n return {};\n }\n let pause = await store.queuePause(threadId);\n if (pause === null) {\n const reason = pauseReasonFor(outcome, head);\n if (reason !== null) {\n pause = {\n reason,\n ...(outcome === 'failed' && args.error !== undefined ? { message: args.error } : {}),\n at: new Date().toISOString(),\n };\n await store.setQueuePause(threadId, pause);\n }\n }\n if (pause === null) {\n const blocked = await this.quotaBlock(head.actor);\n if (blocked !== null) {\n pause = { reason: 'quota_exceeded', message: blocked, at: new Date().toISOString() };\n await store.setQueuePause(threadId, pause);\n }\n }\n if (pause !== null) {\n if (holding !== null) {\n await store.releaseActiveStream(threadId, holding);\n }\n return { frame: queueFrame(items, pause) };\n }\n const claimed = await store.claimActiveStream(\n threadId,\n head.id,\n holding !== null ? { replacing: holding } : {},\n );\n if (!claimed) {\n // Someone else holds the thread now (a send that got in first); its own settle drains.\n return {};\n }\n holding = head.id;\n if (!(await store.removeQueuedMessage(head.id))) {\n // Removed (or started) under us between the read and the claim: give the claim back and\n // look at the new head.\n await store.releaseActiveStream(threadId, head.id);\n holding = null;\n continue;\n }\n const next: QueuedTurn = {\n runId: head.id,\n messageId: head.id,\n input: await this.inputFor(head),\n };\n return {\n next,\n frame: queueFrame(items.slice(1), null, { messageId: head.id, runId: head.id }),\n };\n }\n // Pathological churn (every head removed under us): leave the thread free rather than spin.\n if (holding !== null) {\n await store.releaseActiveStream(threadId, holding);\n }\n return {};\n }\n\n /**\n * {@link plan}, then start what it picked with `start`. What an in-process settle (the inline\n * runner, a durable cancel issued outside a workflow) calls; answers the frame to write.\n */\n async handoff(\n args: { threadId: string; runId: string; outcome: QueueSettleOutcome; error?: string },\n start: QueuedTurnStarter,\n ): Promise<AgentStreamEvent | undefined> {\n const plan = await this.plan(args);\n if (plan.next === undefined) {\n return plan.frame;\n }\n return (await this.launch(args.threadId, plan.next, start))\n ? plan.frame\n : this.pausedFrame(args.threadId);\n }\n\n /**\n * Start the head of an IDLE thread's queue — after a send queued behind a run that turned out to\n * be gone, after a resume, after a stale holder. Does nothing while a live run holds the thread\n * (its settle drains) or while the queue is paused. Answers the started run's id, if any.\n */\n async kick(threadId: string, runner: AgentRunner): Promise<string | undefined> {\n if (!isChatQueueStore(this.store)) {\n return undefined;\n }\n const { live, stale } = await this.holder(threadId, runner);\n if (live !== null) {\n return undefined;\n }\n if (stale !== null) {\n this.logger.warn(`thread ${threadId} was held by run ${stale}, which is no longer running`);\n }\n // Planned as if the stale holder completed: nothing it did pauses the queue.\n const plan = await this.plan({ threadId, runId: stale, outcome: 'completed' });\n if (plan.next === undefined) {\n return undefined;\n }\n const started = await this.launch(threadId, plan.next, (input, runId) =>\n runner.start(input, { runId }),\n );\n if (started && plan.frame !== undefined) {\n // The new run's own stream is where a client attached to nothing yet learns about it.\n await this.write(plan.next.runId, plan.frame);\n }\n return started ? plan.next.runId : undefined;\n }\n\n /**\n * Start a turn the thread is already claimed for. On failure the message goes back to the head of\n * the queue, the queue pauses (`start_failed`), and the claim is released — nothing is lost and\n * nothing is left holding the thread.\n */\n async launch(threadId: string, next: QueuedTurn, start: QueuedTurnStarter): Promise<boolean> {\n this.starting.add(next.runId);\n try {\n await start(next.input, next.runId);\n return true;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.logger.error(`queued message ${next.messageId} could not start: ${message}`);\n await this.restore(threadId, next, 'start_failed', message);\n return false;\n } finally {\n this.starting.delete(next.runId);\n }\n }\n\n /** Put a turn that never started back at the head of its queue, paused, and free the thread. */\n async restore(\n threadId: string,\n next: QueuedTurn,\n reason: QueuePauseReason,\n message: string,\n ): Promise<void> {\n const store = this.queueStore();\n const { input } = next;\n await store.enqueueMessage({\n threadId,\n actor: input.actor,\n content: input.userText,\n at: 'head',\n ...(input.attachments !== undefined ? { attachments: input.attachments } : {}),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),\n ...(input.uiCapabilities !== undefined ? { uiCapabilities: input.uiCapabilities } : {}),\n ...(input.hostContext !== undefined ? { hostContext: input.hostContext } : {}),\n });\n await store.setQueuePause(threadId, { reason, message, at: new Date().toISOString() });\n await store.releaseActiveStream(threadId, next.runId);\n }\n\n /** A `queue` frame with the thread's current state. */\n async pausedFrame(threadId: string): Promise<AgentStreamEvent> {\n return { kind: 'queue', queue: await this.state(threadId) };\n }\n\n /**\n * Tell whoever is watching the thread that its queue changed: a `queue` frame into the stream of\n * the run holding it. Best-effort — a thread nobody is streaming has no one to tell, and the next\n * read of the thread carries the queue anyway.\n */\n async publish(threadId: string): Promise<ChatQueueState> {\n const state = await this.state(threadId);\n const holder = await this.queueStore().activeRunForThread(threadId);\n if (holder !== null) {\n await this.write(holder, { kind: 'queue', queue: state }).catch((error: unknown) => {\n this.logger.warn(\n `could not publish the queue of thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`,\n );\n });\n }\n return state;\n }\n\n private async write(runId: string, frame: AgentStreamEvent): Promise<void> {\n const writer = await this.sink.open(runId);\n await writer.write(encodeStreamEvent(frame));\n }\n\n /** Why `actor` may not start a turn now (the quota message), or `null`. */\n async quotaBlock(actor: Actor): Promise<string | null> {\n if (this.options?.quota === undefined || this.quotaProvider === undefined) {\n return null;\n }\n try {\n const report = await this.quotaProvider.report({ actor });\n const { blocked } = report;\n if (blocked === undefined) {\n return null;\n }\n publishQuotaBlocked(actor, report, blocked);\n return (\n blocked.reason ?? `The ${blocked.period === 'day' ? 'daily' : 'monthly'} quota is used up`\n );\n } catch {\n // Failing to ask is not a verdict; the turn's own quota gate still runs.\n return null;\n }\n }\n\n /**\n * The turn a queued message starts: everything it was queued with, today's date, and its\n * attachments' urls minted afresh — the ones stored at enqueue time may have expired while it\n * waited. An attachment the staging store no longer resolves keeps its stored url.\n */\n private async inputFor(message: QueuedMessage): Promise<AgentRunInput> {\n const attachments = await this.freshAttachments(message.actor, message.attachments ?? []);\n const { agentName, persona } = await this.targetFor(message);\n return {\n threadId: message.threadId,\n actor: message.actor,\n userText: message.content,\n day: utcDay(),\n ...(agentName !== undefined ? { agentName } : {}),\n ...(persona !== undefined ? { persona } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n ...(message.pageContext !== undefined ? { pageContext: message.pageContext } : {}),\n ...(message.uiCapabilities !== undefined ? { uiCapabilities: message.uiCapabilities } : {}),\n ...(message.hostContext !== undefined ? { hostContext: message.hostContext } : {}),\n ...(message.model !== undefined ? { model: message.model } : {}),\n };\n }\n\n /**\n * The agent and persona a queued message starts as. A message carries the persona its send\n * resolved; one that carries none — queued before personas existed, or by a host that sets none —\n * resolves it now, exactly as a send would: an agent name a persona took over, then the thread's\n * pinned persona, then the agent's default. Never refused here: nobody is waiting on a 400.\n */\n private async targetFor(\n message: QueuedMessage,\n ): Promise<{ agentName?: string; persona?: string }> {\n const deps = this.deps;\n if (message.persona !== undefined || deps === undefined || message.agentName === undefined) {\n return {\n ...(message.agentName !== undefined ? { agentName: message.agentName } : {}),\n ...(message.persona !== undefined ? { persona: message.persona } : {}),\n };\n }\n const target = deps.resolveAgent(message.agentName);\n const hasPersonas = deps.personaCatalog(target.agentName).length > 0;\n const persona =\n target.persona ??\n (hasPersonas\n ? deps.resolvePersona({\n agentName: target.agentName,\n threadPersona: await threadPersona(this.store, message.threadId),\n })\n : undefined);\n return { agentName: target.agentName, ...(persona !== undefined ? { persona } : {}) };\n }\n\n private async freshAttachments(\n actor: Actor,\n attachments: MessageAttachment[],\n ): Promise<MessageAttachment[]> {\n const staging = this.staging;\n if (\n attachments.length === 0 ||\n staging === undefined ||\n typeof staging.resolve !== 'function'\n ) {\n return attachments;\n }\n return Promise.all(\n attachments.map(async (attachment) => {\n try {\n return (await staging.resolve({ mediaId: attachment.mediaId, actor })) ?? attachment;\n } catch {\n return attachment;\n }\n }),\n );\n }\n}\n\n/** The pause a settling run's outcome imposes on a non-empty queue, or `null` to keep draining. */\nfunction pauseReasonFor(outcome: QueueSettleOutcome, head: QueuedMessage): QueuePauseReason | null {\n if (outcome === 'failed') {\n return 'run_failed';\n }\n if (outcome === 'cancelled' && head.interrupt !== true) {\n return 'cancelled';\n }\n return null;\n}\n\nfunction queueFrame(\n items: QueuedMessage[],\n paused: QueuePause | null,\n started?: { messageId: string; runId: string },\n): AgentStreamEvent {\n return {\n kind: 'queue',\n queue: { items: items.map(queuedMessageView), paused },\n ...(started !== undefined ? { started } : {}),\n };\n}\n","import {\n type Actor,\n type AgentQuotaExceeded,\n type QuotaBlock,\n type QuotaReport,\n publishAgentQuotaExceeded,\n} from '@dudousxd/nestjs-agent-core';\n\n/**\n * Publish `aviary:agent:quota.exceeded` for a turn refused on `report.blocked`, with the exhausted\n * window's figures — what the dashboard's live feed and Telescope read. Whoever refuses the turn\n * calls this: the send gate and the message queue.\n */\nexport function publishQuotaBlocked(actor: Actor, report: QuotaReport, blocked: QuotaBlock): void {\n const window = report.windows.find((candidate) => candidate.period === blocked.period);\n const payload: AgentQuotaExceeded = {\n actorId: actor.id,\n period: blocked.period,\n ...(blocked.reason !== undefined ? { reason: blocked.reason } : {}),\n ...(window?.usedTokens !== undefined ? { usedTokens: window.usedTokens } : {}),\n ...(window?.limitTokens !== undefined ? { limitTokens: window.limitTokens } : {}),\n ...(window !== undefined ? { usedUsd: window.usedUsd } : {}),\n ...(window?.limitUsd !== undefined ? { limitUsd: window.limitUsd } : {}),\n };\n publishAgentQuotaExceeded(payload);\n}\n","import type { AgentStore } from '@dudousxd/nestjs-agent-core';\n\n/**\n * A store that can answer a thread's pinned persona on its own, without materializing the thread —\n * probed structurally, like `ThreadDefaultAgentReader`.\n */\nexport interface ThreadPersonaReader {\n personaForThread(threadId: string): Promise<string | null>;\n}\n\n/**\n * The thread's pinned persona: one column when the store projects it ({@link ThreadPersonaReader}),\n * else through the full read.\n */\nexport async function threadPersona(store: AgentStore, threadId: string): Promise<string | null> {\n const projecting = store as Partial<ThreadPersonaReader>;\n if (typeof projecting.personaForThread === 'function') {\n return projecting.personaForThread(threadId);\n }\n return (await store.getThread(threadId))?.persona ?? null;\n}\n","import { RUN_NOT_ACTIVE_CODE, RUN_NOT_ACTIVE_MESSAGE } from '@dudousxd/nestjs-agent-core';\nimport { ConflictException } from '@nestjs/common';\n\n/**\n * `approve` / `reject` / `answer` / `skip` addressed at a run that is no longer running — answered\n * `409 { code: 'run_not_active', message }`.\n *\n * The runtime would take the signal and buffer it for a run that never comes back: the person's\n * \"yes\" is accepted, the card says so, and nothing runs. Refusing it is what lets a client say so.\n */\nexport class RunNotActiveException extends ConflictException {\n readonly code = RUN_NOT_ACTIVE_CODE;\n\n constructor(readonly runId: string) {\n super({ statusCode: 409, code: RUN_NOT_ACTIVE_CODE, message: RUN_NOT_ACTIVE_MESSAGE });\n }\n}\n","import type { Actor, AgentApprovalPort } from '@dudousxd/nestjs-agent-core';\nimport { Injectable, NotImplementedException, Optional } from '@nestjs/common';\nimport { AgentService } from './agent.service.js';\nimport { ActionProposalService } from './proposals/action-proposal.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(\n private readonly agent: AgentService,\n @Optional() private readonly proposals?: ActionProposalService,\n ) {}\n async approveActionProposal(\n actor: Actor,\n target: { kind: 'proposal'; threadId: string; proposalId: string },\n opts?: { remember?: boolean; decidedVia?: string },\n ) {\n if (!this.proposals) throw new NotImplementedException('Action proposals unavailable');\n return this.proposals.decide(target.threadId, target.proposalId, actor, {\n decision: 'approved',\n ...(opts?.remember !== undefined ? { remember: opts.remember } : {}),\n via: opts?.decidedVia ?? 'console',\n });\n }\n async rejectActionProposal(\n actor: Actor,\n target: { kind: 'proposal'; threadId: string; proposalId: string },\n opts?: { reason?: string; decidedVia?: string },\n ) {\n if (!this.proposals) throw new NotImplementedException('Action proposals unavailable');\n return this.proposals.decide(target.threadId, target.proposalId, actor, {\n decision: 'rejected',\n ...(opts?.reason !== undefined ? { reason: opts.reason } : {}),\n via: opts?.decidedVia ?? 'console',\n });\n }\n\n async approve(\n toolCallId: string,\n opts?: { executedByRef?: string; remember?: boolean; decidedVia?: string },\n ): Promise<void> {\n await this.agent.signalToolCall(toolCallId, {\n approved: true,\n ...(opts?.executedByRef !== undefined ? { executedByRef: opts.executedByRef } : {}),\n ...(opts?.remember === true ? { remember: true } : {}),\n ...(opts?.decidedVia !== undefined ? { decidedVia: opts.decidedVia } : {}),\n });\n }\n\n async reject(\n toolCallId: string,\n opts?: { executedByRef?: string; reason?: string; decidedVia?: 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 ...(opts?.decidedVia !== undefined ? { decidedVia: opts.decidedVia } : {}),\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/**\n * Lists the registered `@Agent`s — and each one's personas — so a host can render an agent or\n * persona picker instead of hardcoding one.\n */\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 const personas = this.depsFactory.personaCatalog(definition.name);\n return {\n name: definition.name,\n description: definition.description ?? '',\n ...(definition.name === defaultAgentName ? { isDefault: true } : {}),\n ...(personas.length > 0 ? { personas } : {}),\n ...(definition.defaultPersona !== undefined\n ? { defaultPersona: definition.defaultPersona }\n : {}),\n };\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 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';\nimport { attachmentLimits } from '../attachment-limits.js';\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 * `POST <base>/attachments` — the multipart upload route, live whenever an\n * `AGENT_ATTACHMENT_STAGING` provider is bound (`501` otherwise). 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 {\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 * 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 throw new NotImplementedException(\n 'Attachment upload is not configured on this server: bind AGENT_ATTACHMENT_STAGING ' +\n '(e.g. import AgentMediaAttachmentsModule).',\n );\n }\n if (file === undefined) {\n throw new BadRequestException('multipart field \"file\" is required');\n }\n const { allowedContentTypes, maxBytes } = attachmentLimits(this.options, this.staging);\n if (!allowedContentTypes.includes(file.mimetype)) {\n throw new UnsupportedMediaTypeException(\n `content type \"${file.mimetype}\" is not allowed (allowed: ${allowedContentTypes.join(', ')})`,\n );\n }\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 streamFailure,\n} from '@dudousxd/nestjs-agent-core';\nimport { type UiCapabilities, validateUiCapabilities } from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n Body,\n Controller,\n Get,\n Inject,\n Param,\n Post,\n Query,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AgentService, type ChatSendMode } from '../agent.service.js';\nimport { MAX_ATTACHMENTS_PER_MESSAGE } from '../attachment-limits.js';\n\ninterface ChatBody {\n uiCapabilities?: unknown;\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 * One of the agent's personas (`@Agent({ personas })`) to answer as — pinned on the thread. 400\n * `persona_not_found` when the agent declares none by that id.\n */\n persona?: 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 /** Run this turn on a catalog model (see `GET models`) instead of the thread's pinned one. */\n model?: string;\n /**\n * What to do when the thread already has a turn running: `'auto'` (default) queues it, `'queue'`\n * always queues it (behind anything already waiting), `'interrupt'` cancels the running turn and\n * runs this next. See `ChatSendMode`.\n */\n mode?: unknown;\n /** Shorthand for `mode: 'interrupt'`. */\n interrupt?: boolean;\n}\n\n/** The send mode a body asked for, or a 400. */\nfunction sendMode(body: ChatBody): ChatSendMode {\n if (body.interrupt === true) {\n return 'interrupt';\n }\n if (body.mode === undefined || body.mode === null) {\n return 'auto';\n }\n if (body.mode === 'auto' || body.mode === 'queue' || body.mode === 'interrupt') {\n return body.mode;\n }\n throw new BadRequestException(\"mode must be 'auto', 'queue' or 'interrupt'\");\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 */\nexport function 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 // One shape: a ref names an upload, nothing more. A full attachment (url, name, …) is refused\n // rather than trimmed, so a client that still sends one learns it instead of relying on it.\n if (Object.keys(entry).some((key) => key !== 'mediaId')) {\n throw new BadRequestException('attachments are { mediaId } refs — send nothing but the id');\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 /**\n * Start a turn and stream it — or, when the thread already has one running, queue the message and\n * answer `202 { queued: true, messageId, position, queue, … }` (JSON, no stream): it runs when the\n * turn ahead of it settles, and the stream of the run holding the thread announces it with a\n * `queue` frame.\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 mode = sendMode(body);\n let uiCapabilities: UiCapabilities | undefined;\n try {\n uiCapabilities =\n body.uiCapabilities === undefined ? undefined : validateUiCapabilities(body.uiCapabilities);\n } catch {\n throw new BadRequestException('Invalid UI capabilities');\n }\n const result = await this.agent.send({\n actor,\n message: body.message,\n ...(uiCapabilities !== undefined ? { uiCapabilities } : {}),\n ...(body.threadId !== undefined ? { threadId: body.threadId } : {}),\n ...(body.agent !== undefined ? { agentName: body.agent } : {}),\n ...(typeof body.persona === 'string' && body.persona.length > 0\n ? { personaId: body.persona }\n : {}),\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 ...(typeof body.model === 'string' && body.model.length > 0 ? { model: body.model } : {}),\n mode,\n });\n if ('proposalDecision' in result) {\n res.status(200).json(result);\n return;\n }\n if (result.queued === true) {\n res.status(202).json(result);\n return;\n }\n const { runId, threadId } = result;\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 /**\n * Attach to a run's stream: every buffered frame, then live ones. `?after=<seq>` (or the SSE\n * `Last-Event-ID` header a browser `EventSource` sends on its own) skips the frames a reconnecting\n * client already has — see {@link pipe} for how frames are numbered.\n */\n @Get('chat/:runId/stream')\n async stream(\n @Req() req: Request,\n @Param('runId') runId: string,\n @Res() res: Response,\n @Query('after') after?: string,\n ): Promise<void> {\n const actor = await this.actorResolver.resolve(req);\n const cursor = parseCursor(after) ?? parseCursor(req.headers['last-event-id']) ?? 0;\n await this.pipe(res, runId, await this.agent.subscribeAs(actor, runId), undefined, cursor);\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 /**\n * Every `data:` frame carries an SSE `id:` — its 1-based sequence number within the run. The\n * number is a pure function of the run's buffered stream (every sink replays a run from its first\n * chunk, in write order), so the same frame gets the same number on the POST that started the run\n * and on any later `GET …/stream`, whichever replica serves it. A reconnecting client passes the\n * last one it saw as `?after=`; frames at or below it are read off the sink but not re-sent.\n * `meta`, `done` and `error` carry no id: `meta` is re-sent on every attach, the terminals once.\n */\n private async pipe(\n res: Response,\n runId: string,\n events: AsyncIterable<Uint8Array>,\n threadId?: string,\n after = 0,\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 let seq = 0;\n const forward = (line: string) => {\n seq += 1;\n if (seq > after) {\n res.write(`id: ${seq}\\ndata: ${line}\\n\\n`);\n }\n };\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 forward(line);\n }\n newline = buffer.indexOf('\\n');\n }\n }\n if (buffer.length > 0) {\n forward(buffer);\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 : streamFailure(error);\n res.write(`event: error\\ndata: ${JSON.stringify(payload)}\\n\\n`);\n }\n res.end();\n }\n}\n\n/** A non-negative integer sequence cursor, or `undefined` for anything else (absent, malformed). */\nfunction parseCursor(raw: unknown): number | undefined {\n const value = Array.isArray(raw) ? raw[0] : raw;\n if (typeof value !== 'string' || !/^\\d+$/.test(value.trim())) {\n return undefined;\n }\n const parsed = Number(value.trim());\n return Number.isSafeInteger(parsed) ? parsed : undefined;\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_ATTACHMENT_STAGING,\n AGENT_MODEL_CATALOG,\n AGENT_OPTIONS,\n type ActorResolver,\n type AgentClientConfig,\n type AttachmentStagingStore,\n type ModelCatalog,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Optional, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { attachmentLimits } from '../attachment-limits.js';\nimport { AGENT_GENUI, type AgentGenui } from '../genui/agent-genui.token.js';\nimport { AnonymousActorResolver } from '../resolver/anonymous-actor-resolver.js';\n\n@Controller('config')\nexport class ConfigController {\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging: AttachmentStagingStore | undefined,\n @Optional()\n @Inject(AGENT_MODEL_CATALOG)\n private readonly models: ModelCatalog | undefined,\n @Optional()\n @Inject(AGENT_GENUI)\n private readonly genui: AgentGenui | undefined,\n ) {}\n\n @Get()\n async config(@Req() req: Request): Promise<AgentClientConfig> {\n // Resolved like every other route: the same guards apply, and an anonymous browser gets its\n // identity on the first request whichever route that is.\n await this.actorResolver.resolve(req);\n return {\n attachments: attachmentLimits(this.options, this.staging),\n models: { enabled: this.models !== undefined },\n quota: { enforced: this.options.quota !== undefined },\n identity: { anonymous: this.actorResolver instanceof AnonymousActorResolver },\n ...(this.genui?.sandboxClient !== undefined\n ? { genui: { sandbox: this.genui.sandboxClient() } }\n : {}),\n };\n }\n}\n","import { createHash, randomBytes } from 'node:crypto';\nimport type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\n\nexport interface AnonymousActorOptions {\n /** The cookie holding the browser's anonymous token. Default `agent_anon`. */\n cookieName?: string;\n /** How long a browser keeps its identity (and so its threads). Default 365 days. */\n maxAgeDays?: number;\n /**\n * `SameSite` of the cookie. Default `'lax'` — sent on same-site requests, not on cross-site\n * POSTs. A SPA on another SITE than the API needs `'none'` (which forces `Secure`) plus\n * `credentials: 'include'` on the client.\n */\n sameSite?: 'lax' | 'strict' | 'none';\n /**\n * `Secure` flag. Default `'auto'`: set when the request arrived over HTTPS (`req.secure`, or an\n * `x-forwarded-proto: https` from a proxy).\n */\n secure?: boolean | 'auto';\n /** Cookie path. Default `/`. */\n path?: string;\n /** Roles every anonymous actor carries. Default `['anonymous']`. */\n roles?: string[];\n}\n\nconst TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/;\n/** Where a token minted during this request is remembered, so two resolves in one request agree. */\nconst MINTED = Symbol('nestjs-agent:anonymous-token');\n\ninterface RequestLike {\n headers?: Record<string, string | string[] | undefined>;\n secure?: boolean;\n res?: {\n headersSent?: boolean;\n getHeader?: (name: string) => unknown;\n setHeader?: (name: string, value: string | string[]) => unknown;\n };\n [MINTED]?: string;\n}\n\nfunction readCookie(req: RequestLike, name: string): string | undefined {\n const header = req.headers?.cookie;\n const raw = Array.isArray(header) ? header.join('; ') : header;\n if (raw === undefined) return undefined;\n for (const pair of raw.split(';')) {\n const index = pair.indexOf('=');\n if (index === -1) continue;\n if (pair.slice(0, index).trim() === name) {\n try {\n return decodeURIComponent(pair.slice(index + 1).trim());\n } catch {\n return undefined;\n }\n }\n }\n return undefined;\n}\n\nfunction isHttps(req: RequestLike): boolean {\n if (req.secure === true) return true;\n const forwarded = req.headers?.['x-forwarded-proto'];\n const proto = Array.isArray(forwarded) ? forwarded[0] : forwarded;\n return proto?.split(',')[0]?.trim() === 'https';\n}\n\n/**\n * The zero-config identity: every browser is its own anonymous actor, so a login-less chat still\n * keeps each visitor's threads, quota and attachments apart from everyone else's.\n *\n * On a browser's first request the resolver mints 32 random bytes and sets them as an `HttpOnly`\n * cookie (`SameSite=Lax`, `Secure` over HTTPS). The actor id is a SHA-256 digest of that token —\n * `anon:<digest>` — never the token itself, so an id that surfaces anywhere (a thread row, a log, an\n * approval's `decidedBy`) cannot be replayed as the cookie.\n *\n * Why a server-minted cookie and not an id the client makes up and sends in a header: an\n * `HttpOnly` cookie is out of reach of page scripts (an XSS cannot lift it), the server — not the\n * client — decides the value, and it needs no client code at all. There is no signing secret to\n * configure: the token is unguessable on its own, and the digest works the same on every pod and\n * after a restart.\n *\n * Anonymous identities are per browser, not per person: clearing cookies starts over, and there is\n * nothing to recover them with. Require login with an `ActorResolver` that reads your session —\n * `requestUserActorResolver()` for `req.user` (Passport / cookie-session apps).\n */\nexport class AnonymousActorResolver implements ActorResolver {\n private readonly cookieName: string;\n private readonly roles: string[];\n\n constructor(private readonly options: AnonymousActorOptions = {}) {\n this.cookieName = options.cookieName ?? 'agent_anon';\n this.roles = options.roles ?? ['anonymous'];\n }\n\n resolve(request: unknown): Actor {\n const req = (typeof request === 'object' && request !== null ? request : {}) as RequestLike;\n let token = req[MINTED] ?? readCookie(req, this.cookieName);\n if (token === undefined || !TOKEN_PATTERN.test(token)) {\n token = randomBytes(32).toString('base64url');\n req[MINTED] = token;\n this.setCookie(req, token);\n }\n const digest = createHash('sha256').update(token).digest('base64url').slice(0, 32);\n return { id: `anon:${digest}`, roles: [...this.roles] };\n }\n\n private setCookie(req: RequestLike, token: string): void {\n const res = req.res;\n if (res?.setHeader === undefined || res.headersSent === true) return;\n const sameSite = this.options.sameSite ?? 'lax';\n const secureOption = this.options.secure ?? 'auto';\n const secure = sameSite === 'none' || (secureOption === 'auto' ? isHttps(req) : secureOption);\n const maxAge = Math.round((this.options.maxAgeDays ?? 365) * 24 * 60 * 60);\n const cookie = [\n `${this.cookieName}=${token}`,\n `Path=${this.options.path ?? '/'}`,\n `Max-Age=${maxAge}`,\n 'HttpOnly',\n `SameSite=${sameSite === 'none' ? 'None' : sameSite === 'strict' ? 'Strict' : 'Lax'}`,\n ...(secure ? ['Secure'] : []),\n ].join('; ');\n const existing = res.getHeader?.('Set-Cookie');\n const list = Array.isArray(existing)\n ? existing.map(String)\n : existing !== undefined\n ? [String(existing)]\n : [];\n res.setHeader('Set-Cookie', [...list, cookie]);\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 {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type MessageFeedback,\n type MessageFeedbackValue,\n} from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, HttpCode, Inject, Param, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface FeedbackBody {\n /** `null` clears the rating. */\n value: MessageFeedbackValue | null;\n comment?: string;\n}\n\n@Controller('messages')\nexport class MessagesController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n /**\n * Rate a message: `{ value: 'up' | 'down' | null, comment? }`. Answers the stored rating\n * (`{ feedback: null }` once cleared). Only the thread's owner may rate its messages.\n */\n @Post(':id/feedback')\n @HttpCode(200)\n async feedback(\n @Req() req: Request,\n @Param('id') id: string,\n @Body() body: FeedbackBody,\n ): Promise<{ feedback: MessageFeedback | null }> {\n const actor = await this.actorResolver.resolve(req);\n const feedback = await this.agent.setMessageFeedback(actor, id, {\n value: body?.value ?? null,\n ...(body?.comment !== undefined ? { comment: body.comment } : {}),\n });\n return { feedback };\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type ModelCatalogView,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Query, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n@Controller('models')\nexport class ModelsController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n /**\n * The models the caller may pick for `agent` (the default agent when omitted), grouped by\n * provider, with badges and availability — the bound `ModelCatalog`'s answer, or an empty one.\n */\n @Get()\n async list(@Req() req: Request, @Query('agent') agent?: string): Promise<ModelCatalogView> {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.listModels(actor, agent);\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type AttachmentRef,\n type ChatQueueState,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Body,\n Controller,\n Delete,\n Get,\n Inject,\n Param,\n Patch,\n Post,\n Req,\n} from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\nimport { attachmentRefs } from './chat.controller.js';\n\ninterface UpdateQueuedMessageBody {\n /** The new text. */\n message?: unknown;\n /** `[{ mediaId }]` refs replacing the message's attachments; `null` or `[]` drops them. */\n attachments?: unknown;\n /** Move the message to this 0-based place in the queue. */\n position?: unknown;\n}\n\n/**\n * The thread message queue: messages sent while a turn was running, waiting to run after it. Every\n * route is ownership-gated like the thread routes, and answers the thread's queue as it now stands\n * (`{ items, paused }`). A change is also announced to whoever is streaming the thread, as a `queue`\n * frame in the running turn's stream.\n */\n@Controller()\nexport class QueueController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Get('threads/:id/queue')\n async list(@Req() req: Request, @Param('id') id: string): Promise<ChatQueueState> {\n return this.agent.getQueue(await this.actorResolver.resolve(req), id);\n }\n\n @Delete('threads/:id/queue')\n async clear(@Req() req: Request, @Param('id') id: string): Promise<ChatQueueState> {\n return this.agent.clearQueue(await this.actorResolver.resolve(req), id);\n }\n\n /** Lift a pause; the head starts when nothing is running. Carries `runId` when it started. */\n @Post('threads/:id/queue/resume')\n async resume(\n @Req() req: Request,\n @Param('id') id: string,\n ): Promise<ChatQueueState & { runId?: string }> {\n return this.agent.resumeQueue(await this.actorResolver.resolve(req), id);\n }\n\n @Patch('queue/:messageId')\n async update(\n @Req() req: Request,\n @Param('messageId') messageId: string,\n @Body() body: UpdateQueuedMessageBody,\n ): Promise<ChatQueueState> {\n const actor = await this.actorResolver.resolve(req);\n if (body.message !== undefined && typeof body.message !== 'string') {\n throw new BadRequestException('message must be a string');\n }\n if (body.position !== undefined && typeof body.position !== 'number') {\n throw new BadRequestException('position must be a number');\n }\n const attachments: AttachmentRef[] | null | undefined =\n body.attachments === undefined\n ? undefined\n : body.attachments === null\n ? null\n : attachmentRefs(body.attachments);\n return this.agent.updateQueuedMessage(actor, messageId, {\n ...(body.message !== undefined ? { message: body.message } : {}),\n ...(attachments !== undefined ? { attachments } : {}),\n ...(body.position !== undefined ? { position: body.position } : {}),\n });\n }\n\n /**\n * Run a waiting message now: it moves to the head as an interrupt and the running turn is\n * cancelled for it. Carries `interrupting` (the cancelled run), or `runId` when nothing was\n * running and it started at once.\n */\n @Post('queue/:messageId/interrupt')\n async interrupt(\n @Req() req: Request,\n @Param('messageId') messageId: string,\n ): Promise<ChatQueueState & { runId?: string; interrupting?: string }> {\n return this.agent.interruptQueuedMessage(await this.actorResolver.resolve(req), messageId);\n }\n\n @Delete('queue/:messageId')\n async remove(\n @Req() req: Request,\n @Param('messageId') messageId: string,\n ): Promise<ChatQueueState> {\n return this.agent.removeQueuedMessage(await this.actorResolver.resolve(req), messageId);\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 /**\n * The caller's budget across windows — `{ windows: [{ period, usedTokens, limitTokens?, usedUsd,\n * limitUsd?, resetsAt? }], blocked?: { period, reason? } }` — from the bound `QuotaProvider`.\n */\n @Get()\n async report(@Req() req: Request) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.quotaReport(actor);\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 /** `null` unpins the thread's model. Omitted → left untouched. Must be offered by the catalog. */\n model?: string | null;\n /** `null` clears the thread's persona. Omitted → left untouched. Must be one the agent declares. */\n persona?: 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 ...('model' in body ? { model: body.model ?? null } : {}),\n ...('persona' in body ? { persona: body.persona ?? 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\n/** A `via` is provenance, persisted on the call — bounded like any other stored label. */\nconst MAX_VIA_LENGTH = 64;\n/** What an HTTP decision is recorded as having come through when the caller names nothing. */\nconst DEFAULT_VIA = 'web';\n\ninterface ApproveBody {\n toolCallId: unknown;\n /** Approve later calls of the same tool in the same thread without asking. */\n remember?: unknown;\n /** The surface the decision came through. Defaults to `'web'`. */\n via?: unknown;\n}\ninterface RejectBody {\n toolCallId: unknown;\n reason?: unknown;\n via?: unknown;\n}\ninterface AnswerBody {\n toolCallId: unknown;\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 /** The surface the answer came through. Defaults to `'web'`. */\n via?: 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\n/** A rejection reason, bounded — it is read back by the model as the tool's result. */\nexport function 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 remember(claimed: unknown): boolean {\n if (claimed === undefined) {\n return false;\n }\n if (typeof claimed !== 'boolean') {\n throw new BadRequestException('remember must be a boolean');\n }\n return claimed;\n}\n\nfunction via(claimed: unknown): string {\n if (claimed === undefined) {\n return DEFAULT_VIA;\n }\n if (typeof claimed !== 'string' || claimed.length === 0 || claimed.length > MAX_VIA_LENGTH) {\n throw new BadRequestException(`via must be a string of 1-${MAX_VIA_LENGTH} characters`);\n }\n return claimed;\n}\n\n/** A reply's answers, bounded and shape-checked before anything is signalled (`400` otherwise). */\nexport function 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 remember: remember(body.remember),\n via: via(body.via),\n });\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 via: via(body.via),\n });\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 via: via(body.via),\n });\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(\n @Req() req: Request,\n @Body() body: { toolCallId: unknown; via?: unknown },\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.skip(actor, toolCallId(body.toolCallId), { via: via(body.via) });\n return { ok: true };\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_DEPS_FACTORY,\n AGENT_REGISTRY,\n ALL_AGENTS,\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 /**\n * The agent whose tools to list. Omitted → the default agent, the one a turn naming none uses.\n * `*` → every agent's: the union of what this actor reaches through any of them, each tool once\n * — for a surface that shows several agents' conversations.\n */\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 && agent !== ALL_AGENTS && this.agents.get(agent) === undefined) {\n throw new NotFoundException(`No agent named \"${agent}\"`);\n }\n const actor = await this.actorResolver.resolve(req);\n const names =\n agent === ALL_AGENTS\n ? [undefined, ...this.agents.list().map((definition) => definition.name)]\n : [agent];\n const entries = new Map<string, ToolCatalogEntry>();\n for (const name of names) {\n const deps = this.depsFactory.forAgent(name);\n const specs = await deps.registry.visibleSpecs(actor, deps.rolesPolicy, deps.toolAllowList);\n for (const spec of specs) {\n if (entries.has(spec.name)) continue;\n entries.set(spec.name, {\n name: spec.name,\n kind: spec.kind,\n ...(spec.presentation !== undefined ? { presentation: spec.presentation } : {}),\n });\n }\n }\n return [...entries.values()];\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 this.assertPersonas(this.registry.list());\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 ...(meta.personas !== undefined ? { personas: meta.personas } : {}),\n ...(meta.defaultPersona !== undefined ? { defaultPersona: meta.defaultPersona } : {}),\n };\n }\n\n /**\n * Refuse to boot on a persona declaration that could only fail later, per request: a default that\n * names no persona, an id declared twice, an alias two personas claim, or an alias that is a real\n * agent's name (which would never be reached — a registered agent always wins).\n */\n private assertPersonas(definitions: AgentDefinition[]): void {\n const agentNames = new Set(definitions.map((definition) => definition.name));\n const aliasOwner = new Map<string, string>();\n for (const definition of definitions) {\n const ids = new Set<string>();\n for (const persona of definition.personas ?? []) {\n if (ids.has(persona.id)) {\n throw new Error(`Agent \"${definition.name}\" declares persona \"${persona.id}\" twice.`);\n }\n ids.add(persona.id);\n for (const alias of persona.aliases ?? []) {\n const owner = `${definition.name}/${persona.id}`;\n if (agentNames.has(alias)) {\n throw new Error(\n `Persona ${owner} claims the alias \"${alias}\", which is a registered agent's name.`,\n );\n }\n const previous = aliasOwner.get(alias);\n if (previous !== undefined) {\n throw new Error(`Personas ${previous} and ${owner} both claim the alias \"${alias}\".`);\n }\n aliasOwner.set(alias, owner);\n }\n }\n if (definition.defaultPersona !== undefined && !ids.has(definition.defaultPersona)) {\n throw new Error(\n `Agent \"${definition.name}\" names \"${definition.defaultPersona}\" as its default persona, but declares no persona with that id.`,\n );\n }\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, Persona } 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 * Named variants of THIS agent — a prompt and, optionally, a narrower tool allow-list — that a\n * caller picks per send (`POST <base>/chat { persona }`) and that pin onto the thread. Everything\n * else (model, access rules, handoffs, history) stays this agent's; a variant that needs those to\n * differ is another `@Agent`.\n *\n * A persona's `systemPrompt` is static data. For a prompt built from injected services, leave it\n * out and branch on `ctx.persona` in this class's `@SystemPrompt()` method instead.\n *\n * Omit → no personas, and nothing about a turn changes.\n */\n personas?: Persona[];\n /** The persona a send runs under when neither it nor its thread names one. Omit → none. */\n defaultPersona?: string;\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 ToolDescribeScope,\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 // `provideAgentTools` resolves to a list; only an all-branded one is ours.\n if (\n Array.isArray(instance) &&\n instance.length > 0 &&\n instance.every(\n (each) => typeof each === 'object' && each !== null && isBrandedFunctionalTool(each),\n )\n ) {\n for (const tool of instance as FunctionalTool[]) {\n if (this.registerFunctionalTool(tool)) {\n functional += 1;\n }\n }\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 ...(meta.terminal === true ? { terminal: true } : {}),\n ...(meta.replacementKey !== undefined ? { replacementKey: meta.replacementKey } : {}),\n },\n {\n execute: (input, ctx) => (instance as ToolHandler).execute(input, ctx),\n ...(typeof handler.present === 'function'\n ? { present: (output, ctx) => (instance as Required<ToolHandler>).present(output, ctx) }\n : {}),\n ...(typeof handler.preflight === 'function'\n ? {\n preflight: (input, ctx, options) =>\n (instance as Required<ToolHandler>).preflight(input, ctx, options),\n }\n : {}),\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 ...(typeof handler.describe === 'function'\n ? {\n describe: (scope: ToolDescribeScope) =>\n (instance as Required<ToolHandler>).describe(scope),\n }\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, ToolSpec } 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 replacementKey?: ToolSpec['replacementKey'];\n /**\n * What the model calls it. Omit → the class name, camelCased, with a trailing `Tool` dropped\n * (`GetWeatherTool` → `getWeather`).\n */\n name?: string;\n /**\n * `read` (the default) auto-executes; `action` requires HITL approval. (Core's `ToolKind` also\n * has `agent` for delegation, but that kind is synthesized from `delegatesTo` — never authored\n * 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 /**\n * Roles allowed to invoke. Omit → the module's `defaultRoles`, which by default restrict nobody:\n * any resolved actor — an anonymous visitor included, when no `actorResolver` is configured.\n */\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 * The turn ends once a call to this tool succeeds — no model call afterwards to narrate what the\n * tool already showed (a composed UI answer, a hand-off). See `ToolSpec.terminal`.\n */\n terminal?: boolean;\n}\n\n/** {@link AiToolOptions} with the defaults applied — what discovery reads. */\nexport interface ResolvedAiToolOptions extends AiToolOptions {\n name: string;\n kind: 'read' | 'action';\n}\n\n/** `GetWeatherTool` → `getWeather`; `SQLQueryTool` → `sqlQuery`. */\nexport function toolNameFromClass(className: string): string {\n const base = className.replace(/Tool$/, '') || className;\n const leadingCaps = /^[A-Z]+(?=[A-Z][a-z]|$)/.exec(base)?.[0];\n if (leadingCaps !== undefined && leadingCaps.length > 1) {\n return leadingCaps.toLowerCase() + base.slice(leadingCaps.length);\n }\n return base.charAt(0).toLowerCase() + base.slice(1);\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 * Only `description` and `input` are required:\n *\n * ```ts\n * @AiTool({ description: 'Current weather for a city', input: z.object({ city: z.string() }) })\n * class GetWeatherTool implements ToolHandler<{ city: string }> { // name: getWeather, kind: read\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 const resolved: ResolvedAiToolOptions = {\n ...options,\n name: options.name ?? toolNameFromClass(target.name),\n kind: options.kind ?? 'read',\n };\n Reflect.defineMetadata(AI_TOOL_METADATA, resolved, target);\n };\n}\n\nexport function readAiToolMetadata(target: object): ResolvedAiToolOptions | undefined {\n return Reflect.getMetadata(AI_TOOL_METADATA, target.constructor) as\n | ResolvedAiToolOptions\n | undefined;\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 {\n type AgentStore,\n type QuotaPeriod,\n type QuotaProvider,\n type QuotaQuery,\n type QuotaReport,\n type QuotaWindow,\n type UsageTotals,\n exhaustedWindow,\n quotaPeriodRange,\n quotaWarning,\n} from '@dudousxd/nestjs-agent-core';\n\n/** Ceilings for a {@link LedgerQuotaProvider} window. Either, both, or neither. */\nexport interface QuotaWindowLimits {\n tokens?: number;\n usd?: number;\n}\n\n/** Per-window ceilings: `AgentModule.forRoot({ quota: { limits } })`. */\nexport interface QuotaLimits {\n day?: QuotaWindowLimits;\n month?: QuotaWindowLimits;\n}\n\n/** {@link LedgerQuotaProvider}'s tuning beyond the ceilings. */\nexport interface LedgerQuotaOptions {\n /**\n * The soft limit: the share of a ceiling (`0..1`) past which the report carries a `warning`.\n * Stamped on every window that has a ceiling. Omit → no warnings.\n */\n warnAt?: number;\n /**\n * Whether the USD windows count ESTIMATED cost (tokens × the price row, for a provider that reports\n * none, e.g. Bedrock, OpenAI or Anthropic direct) as well as provider-reported cost. Default `true`:\n * a USD ceiling that ignored estimates would read $0 and never block for every such provider, which\n * is a budget that does not enforce. Set `false` to budget on provider-reported (gateway) cost only.\n */\n countEstimatedCost?: boolean;\n}\n\n/**\n * The default {@link QuotaProvider}: windows read off the usage ledger the loop already writes.\n *\n * - `day` — always.\n * - `month` — when the store implements `usageBetween`.\n *\n * `limits` add ceilings per window (tokens and/or USD). A window that reaches one makes the report\n * `blocked`.\n */\nexport class LedgerQuotaProvider implements QuotaProvider {\n constructor(\n private readonly store: AgentStore,\n private readonly limits: QuotaLimits = {},\n private readonly options: LedgerQuotaOptions = {},\n ) {}\n\n async report(query: QuotaQuery): Promise<QuotaReport> {\n const now = query.now ?? new Date();\n const actorRef = query.actor.id;\n const windows: QuotaWindow[] = [await this.dayWindow(actorRef, now)];\n if (this.store.usageBetween !== undefined) {\n const range = quotaPeriodRange('month', now);\n const used = await this.store.usageBetween(actorRef, range.fromDay, range.toDay);\n windows.push(this.window('month', used.usedTokens, this.usd(used), range.resetsAt));\n }\n const blocked = exhaustedWindow(windows);\n const warning = quotaWarning(windows);\n return {\n windows,\n ...(blocked !== undefined ? { blocked } : {}),\n ...(warning !== undefined ? { warning } : {}),\n };\n }\n\n private async dayWindow(actorRef: string, now: Date): Promise<QuotaWindow> {\n const range = quotaPeriodRange('day', now);\n const used = await this.store.quotaToday(actorRef, range.fromDay);\n return this.window('day', used.usedTokens, this.usd(used), range.resetsAt);\n }\n\n /** The window's USD: every priced row, or (with `countEstimatedCost: false`) reported cost only. */\n private usd(used: UsageTotals): number {\n if (this.options.countEstimatedCost === false) {\n return Math.max(0, used.costUsd - (used.estimatedCostUsd ?? 0));\n }\n return used.costUsd;\n }\n\n private window(\n period: QuotaPeriod,\n usedTokens: number,\n usedUsd: number,\n resetsAt: string,\n ): QuotaWindow {\n const limits = this.limits[period] ?? {};\n return {\n period,\n usedTokens,\n ...(limits.tokens !== undefined ? { limitTokens: limits.tokens } : {}),\n usedUsd,\n ...(limits.usd !== undefined ? { limitUsd: limits.usd } : {}),\n resetsAt,\n ...(this.options.warnAt !== undefined &&\n (limits.tokens !== undefined || limits.usd !== undefined)\n ? { warnAt: this.options.warnAt }\n : {}),\n };\n }\n}\n","import {\n AGENT_MODEL,\n AGENT_OPTIONS,\n AGENT_PRICING_STORE,\n type AgentPricingStore,\n type DescribedModel,\n type ModelProvider,\n ensureModelPricing,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n Inject,\n Injectable,\n Logger,\n type OnApplicationBootstrap,\n type OnApplicationShutdown,\n Optional,\n} from '@nestjs/common';\nimport type { AgentModuleOptions } from './agent.options.js';\n\nconst logger = new Logger('AgentPricing');\n\n/**\n * Makes sure every configured model records a cost, and says so when one will not (see\n * `AgentModuleOptions.priceCatalog`). Runs in the background once the app has bootstrapped — a slow\n * catalog must not hold the boot up — and never throws. Skipped under `NODE_ENV=test` unless\n * `priceCatalog` is set explicitly.\n */\n@Injectable()\nexport class PricingBootService implements OnApplicationBootstrap, OnApplicationShutdown {\n #run: Promise<unknown> | null = null;\n\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Optional() @Inject(AGENT_MODEL) private readonly model: ModelProvider | undefined,\n // Bound externally (a store module), so optional like in AgentDepsFactory.\n @Optional()\n @Inject(AGENT_PRICING_STORE)\n private readonly pricingStore: AgentPricingStore | undefined,\n ) {}\n\n onApplicationBootstrap(): void {\n this.#run = this.check();\n }\n\n /** Awaits a check still in flight, so a test (or a fast shutdown) never leaks it. */\n async onApplicationShutdown(): Promise<void> {\n await this.#run;\n this.#run = null;\n }\n\n /** The check itself; resolves once it is done (exposed for tests). */\n async check(): Promise<void> {\n let models: DescribedModel[];\n try {\n models = this.model?.describeModels?.() ?? [];\n } catch (error) {\n // Pricing is bookkeeping, never a reason for the app to stay down.\n logger.warn(`describeModels() threw; boot pricing skipped: ${String(error)}`);\n return;\n }\n if (models.length === 0) return;\n const catalog = this.options.priceCatalog;\n if (catalog === undefined && process.env.NODE_ENV === 'test') return;\n await ensureModelPricing({\n models,\n pricingStore: this.pricingStore,\n catalog: catalog ?? {},\n log: {\n info: (message) => logger.log(message),\n warn: (message) => logger.warn(message),\n },\n }).catch(() => undefined);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n AGENT_DEPS_FACTORY,\n AGENT_OPTIONS,\n AGENT_STORE,\n type ActionProposal,\n ActionProposalExecutor,\n ActionProposalWorker,\n type AgentStore,\n assertIndependentActionCapabilities,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n Inject,\n Injectable,\n Logger,\n type OnModuleDestroy,\n type OnModuleInit,\n} from '@nestjs/common';\nimport { AgentDepsFactory } from '../agent-deps.factory.js';\nimport type { AgentModuleOptions } from '../agent.options.js';\n/** Called with a proposal the worker just settled (executed, or failed executing). */\nexport type ActionProposalSettledListener = (proposal: ActionProposal) => void | Promise<void>;\n\n@Injectable()\nexport class ActionProposalWorkerService implements OnModuleInit, OnModuleDestroy {\n private worker: ActionProposalWorker | undefined;\n private readonly logger = new Logger(ActionProposalWorkerService.name);\n private readonly settledListeners = new Set<ActionProposalSettledListener>();\n\n /**\n * Run `listener` after every proposal this process's worker settles — how a module relays an\n * outcome somewhere the turn's stream no longer reaches (a text channel's conversation). Next to\n * `actionProposalWorker.onSettled`; a listener that throws is logged and does not stop the others.\n * Returns the unsubscribe. Only the replicas that run the worker (not `surface: 'http'`) call it.\n */\n onSettled(listener: ActionProposalSettledListener): () => void {\n this.settledListeners.add(listener);\n return () => {\n this.settledListeners.delete(listener);\n };\n }\n\n private async settled(proposal: ActionProposal): Promise<void> {\n const configured = this.options.actionProposalWorker?.onSettled;\n for (const listener of [...(configured ? [configured] : []), ...this.settledListeners]) {\n try {\n await listener(proposal);\n } catch (error) {\n this.logger.error(error);\n }\n }\n }\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_DEPS_FACTORY) private readonly deps: AgentDepsFactory,\n ) {}\n onModuleInit() {\n if (this.options.actionApprovalMode !== 'independent') return;\n assertIndependentActionCapabilities(this.store, this.options.backgroundActorResolver);\n if (this.options.surface === 'http') return;\n const resolver = this.options.backgroundActorResolver;\n if (!resolver) throw new Error('BackgroundActorResolver is required');\n this.worker = new ActionProposalWorker({\n store: this.store,\n workerId: randomUUID(),\n ...this.options.actionProposalWorker,\n onSettled: (proposal) => this.settled(proposal),\n executor: new ActionProposalExecutor({\n resolver,\n resolveExecution: async (proposal, actor) => {\n const deps = this.deps.forProposal(proposal, actor);\n return {\n registry: deps.registry,\n rolesPolicy: deps.rolesPolicy,\n ...(deps.resolveUiCatalog !== undefined\n ? { resolveUiCatalog: deps.resolveUiCatalog }\n : {}),\n ...(deps.toolAllowList !== undefined ? { allowedTools: deps.toolAllowList } : {}),\n };\n },\n }),\n onError: (error) => this.logger.error(error),\n });\n this.worker.start();\n }\n async onModuleDestroy() {\n await this.worker?.stop();\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type ListActionProposals,\n validateActionProposalListQuery,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Body,\n Controller,\n Get,\n Inject,\n Param,\n Post,\n Query,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { ActionProposalService } from './action-proposal.service.js';\nfunction bodyFields(body: unknown, field: 'remember' | 'reason'): Record<string, unknown> {\n if (body === undefined) return {};\n if (\n typeof body !== 'object' ||\n body === null ||\n Array.isArray(body) ||\n Object.keys(body).some((key) => key !== field)\n )\n throw new BadRequestException(`Only ${field} is accepted`);\n const value = body as Record<string, unknown>;\n if (\n value[field] !== undefined &&\n ((field === 'remember' && typeof value[field] !== 'boolean') ||\n (field === 'reason' && typeof value[field] !== 'string'))\n )\n throw new BadRequestException(`Invalid ${field}`);\n return value;\n}\n@Controller('threads/:threadId/action-proposals')\nexport class ActionProposalController {\n constructor(\n private readonly proposals: ActionProposalService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actors: ActorResolver,\n ) {}\n @Get() async list(\n @Param('threadId') threadId: string,\n @Req() request: Request,\n @Query('after') cursor: unknown,\n @Res({ passthrough: true }) response: Response,\n ) {\n let query: Pick<ListActionProposals, 'after'> = {};\n if (cursor !== undefined) {\n try {\n if (typeof cursor !== 'string') throw new Error('Invalid cursor');\n query = { after: JSON.parse(cursor) };\n validateActionProposalListQuery(query);\n } catch {\n throw new BadRequestException('Invalid action proposal cursor');\n }\n }\n const page = await this.proposals.listPage(threadId, await this.actors.resolve(request), query);\n if (page.next) {\n response.setHeader('X-Action-Proposals-Next', encodeURIComponent(JSON.stringify(page.next)));\n const exposed = response.getHeader('Access-Control-Expose-Headers');\n response.setHeader(\n 'Access-Control-Expose-Headers',\n `${exposed === undefined ? '' : `${String(exposed)}, `}X-Action-Proposals-Next`,\n );\n }\n return page.items;\n }\n @Post(':proposalId/approve') async approve(\n @Param('threadId') threadId: string,\n @Param('proposalId') proposalId: string,\n @Req() request: Request,\n @Body() body: unknown,\n ) {\n const value = bodyFields(body, 'remember');\n return this.proposals.decide(threadId, proposalId, await this.actors.resolve(request), {\n decision: 'approved',\n ...(typeof value.remember === 'boolean' ? { remember: value.remember } : {}),\n });\n }\n @Post(':proposalId/reject') async reject(\n @Param('threadId') threadId: string,\n @Param('proposalId') proposalId: string,\n @Req() request: Request,\n @Body() body: unknown,\n ) {\n const value = bodyFields(body, 'reason');\n return this.proposals.decide(threadId, proposalId, await this.actors.resolve(request), {\n decision: 'rejected',\n ...(typeof value.reason === 'string' ? { reason: value.reason } : {}),\n });\n }\n}\n","/**\n * The thread message queue, as the durable runner and the `agent.run` workflow ask for it.\n *\n * A token rather than the `ChatQueueService` class: `@dudousxd/nestjs-agent/durable` is a separate\n * bundle with its own copy of every class it imports, so a class used as an injection token there\n * is not the class `AgentModule` provides. `Symbol.for` is the same value in every bundle.\n */\nexport const AGENT_CHAT_QUEUE = Symbol.for('@dudousxd/nestjs-agent:chat-queue');\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_STORE,\n type Actor,\n type AgentLoopHooks,\n type AgentRunInput,\n type AgentRunStartOptions,\n type AgentRunner,\n type AgentStore,\n type Decision,\n type DetachedDelivery,\n type ElicitationReply,\n type HumanReply,\n RUN_ENDED_BEFORE_TOOL_CALL,\n RunCancelledError,\n type SinkWriter,\n agentFailureCode,\n encodeStreamEvent,\n publishAgentRunFailed,\n releaseThreadRun,\n runAgentLoop,\n settleAll,\n settleUnsettledDelegation,\n streamFailure,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, Optional } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { type AgentDeps, childSinkWriter, utcDay } from '../agent-deps.js';\nimport { ChatQueueService, type QueueSettleOutcome } from '../queue/chat-queue.service.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 * Aborted by {@link cancel}: what cuts short the model call or tool a stopped run is in (the\n * loop's `abortSignal` hook). Keyed like {@link cancelled}, and dropped with it.\n */\n private readonly aborts = new Map<string, AbortController>();\n /** Top-level runs this process is running now — what {@link isRunActive} answers from. */\n private readonly live = new Set<string>();\n\n constructor(\n @Inject(AGENT_DEPS_FACTORY) private readonly factory: AgentDepsFactory,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Optional() private readonly queue?: ChatQueueService,\n ) {}\n\n /**\n * In-process, so exact: a run this process is not running is not running anywhere — the process\n * that was running it is gone (a restart), and a thread it still holds is a stale claim.\n */\n async isRunActive(runId: string): Promise<boolean> {\n if (this.live.has(runId)) {\n return true;\n }\n // A delegated run is not in `live` (it holds no thread of its own turn), but one parked on a\n // person is as alive as its parent: its decision has somewhere to go.\n for (const key of this.pending.keys()) {\n if (key.startsWith(`${runId}:`)) {\n return true;\n }\n }\n return false;\n }\n\n async start(\n input: AgentRunInput,\n options: AgentRunStartOptions = {},\n ): Promise<{ runId: string }> {\n const runId = options.runId ?? crypto.randomUUID();\n const day = input.day ?? utcDay();\n const deps = this.factory.forAgent(input.agentName);\n this.live.add(runId);\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 input,\n });\n\n void runAgentLoop({ ...deps, day }, input, hooks)\n .then(() => releaseThreadRun(this.store, input.threadId, runId))\n .catch(async (error) => {\n if (error instanceof RunCancelledError) {\n await this.settleCancelled(runId, input, 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 // A call this run had put to a person is not waiting for anything any more.\n await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\n const writer = await deps.sink.open(runId);\n // The queue behind it pauses (a failed turn's next message would likely fail the same way),\n // told to the reader before the error frame.\n await this.settleQueue(writer, input, runId, 'failed', message);\n // Clear the thread's active run — a failed run isn't \"still running\" for `activeRunForThread`.\n await releaseThreadRun(this.store, input.threadId, runId);\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. The frame is for the person reading the\n // chat; the error itself went to the log and the run row above.\n await writer.fail(streamFailure(error));\n })\n .finally(() => {\n this.forgetCancel(runId);\n this.live.delete(runId);\n });\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. What the run is in right now is aborted (its `abortSignal`): the model call\n * streaming the answer ends at once and the step it was writing is not persisted, and a tool that\n * passes `ctx.abortSignal` on is cut short and recorded failed; a tool that ignores the signal is\n * left to finish, and its result is recorded 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 // The model call or tool the run is in, cut short now rather than at the end of its step.\n this.aborts.get(runId)?.abort(new RunCancelledError());\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 /** The signal {@link cancel} aborts for `runId` — one per run, shared by its awaited delegates. */\n private abortSignalFor(runId: string): AbortSignal {\n let controller = this.aborts.get(runId);\n if (controller === undefined) {\n controller = new AbortController();\n this.aborts.set(runId, controller);\n }\n return controller.signal;\n }\n\n /** Drop a settled run's Stop: its flag and its abort controller. */\n private forgetCancel(runId: string): void {\n this.cancelled.delete(runId);\n this.aborts.delete(runId);\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(\n runId: string,\n input: AgentRunInput,\n deps: AgentDeps,\n ): Promise<void> {\n this.logger.log(`agent run ${runId} cancelled`);\n const writer = await deps.sink.open(runId);\n // An interrupt's message starts now; otherwise the queue pauses behind the Stop.\n await this.settleQueue(writer, input, runId, 'cancelled');\n await releaseThreadRun(this.store, input.threadId, 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 * Move the thread past a settling TOP-LEVEL run — to the next queued message, which starts here,\n * or to a paused/empty queue — and write the resulting `queue` frame into this run's stream. A\n * no-op without a queue-capable store, and for a run that is not a thread's own turn.\n *\n * Never throws: the run is settling either way, and a queue that could not be advanced is picked\n * up by the next send or resume on the thread.\n */\n private async settleQueue(\n writer: SinkWriter,\n input: AgentRunInput,\n runId: string,\n outcome: QueueSettleOutcome,\n error?: string,\n ): Promise<void> {\n const queue = this.queue;\n if (queue === undefined || !queue.supported || !isThreadTurn(input)) {\n return;\n }\n // A Stop that arrived too late to interrupt anything (the turn's last model call was already\n // answering) still means stop: the queue behind it pauses as it would after a cancel.\n const settled = outcome === 'completed' && this.cancelled.has(runId) ? 'cancelled' : outcome;\n try {\n const frame = await queue.handoff(\n {\n threadId: input.threadId,\n runId,\n outcome: settled,\n ...(error !== undefined ? { error } : {}),\n },\n (next, nextRunId) => this.start(next, { runId: nextRunId }),\n );\n if (frame !== undefined) {\n await writer.write(encodeStreamEvent(frame));\n }\n } catch (failure) {\n this.logger.error(\n `could not advance the queue of thread ${input.threadId} after run ${runId}: ${\n failure instanceof Error ? failure.message : String(failure)\n }`,\n );\n }\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 /**\n * {@link park} for an approval, bounded by the policy's time to live when it has one: the timer\n * settles the wait as `expired` — the same Decision the durable runner builds from its signal\n * timeout — and a decision that arrives first disarms it.\n */\n private parkApproval(runId: string, toolCallId: string, timeoutMs?: number): Promise<Decision> {\n const waiting = this.park<Decision>(runId, toolCallId);\n if (timeoutMs === undefined) {\n return waiting;\n }\n const key = `${runId}:${toolCallId}`;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const lapse = new Promise<Decision>((resolve) => {\n timer = setTimeout(() => {\n const entry = this.pending.get(key);\n if (entry !== undefined) {\n this.pending.delete(key);\n resolve({ approved: false, expired: true });\n }\n }, timeoutMs);\n // A parked request must not keep the process alive on its own.\n timer.unref?.();\n });\n return Promise.race([waiting, lapse]).finally(() => clearTimeout(timer));\n }\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 input: AgentRunInput;\n }): AgentLoopHooks {\n const { runId, deps, actor, day, threadId, chainBelow, input } = args;\n return {\n runId,\n // The loop ends the stream when the turn completes. Just before, the thread passes to the next\n // queued message (or is released), and the reader is told which — so by the time a client\n // sees the run end, the thread is already free or already running what it queued.\n openSink: async () => {\n const writer = await deps.sink.open(runId);\n return this.queue === undefined\n ? writer\n : {\n write: (chunk) => writer.write(chunk),\n fail: (error) => writer.fail(error),\n end: async () => {\n await this.settleQueue(writer, input, runId, 'completed');\n await writer.end();\n },\n };\n },\n awaitApproval: (call, _ctx, opts) => this.parkApproval(runId, call.id, opts?.timeoutMs),\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 abortSignal: this.abortSignalFor(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, _ctx, opts) => this.parkApproval(runId, call.id, opts?.timeoutMs),\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 abortSignal: this.abortSignalFor(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 await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\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.forgetCancel(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, _ctx, opts) => this.parkApproval(runId, call.id, opts?.timeoutMs),\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 // Aborted by a Stop on the run the human is watching, which is the id a canceller names.\n abortSignal: this.abortSignalFor(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\n/**\n * A thread's own turn — not a sub-agent's run on a subthread, which neither holds its thread's\n * queue nor answers to it.\n */\nfunction isThreadTurn(input: AgentRunInput): boolean {\n return input.sinkRunId === undefined && input.deliverTo === undefined;\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 {\n AGENT_ACTOR_RESOLVER,\n AGENT_ATTACHMENT_STAGING,\n AGENT_OPTIONS,\n type Actor,\n type ActorResolver,\n type AttachmentRef,\n type AttachmentStagingStore,\n type PageContext,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n A2UI_LEGACY_BASIC_CATALOG_ID,\n type A2uiOptions,\n negotiateA2uiCatalog,\n readAgUiA2uiCatalogIds,\n} from '@dudousxd/nestjs-agent-core/a2ui';\nimport {\n AG_UI_CUSTOM,\n type AgUiEvent,\n type AgUiStreamOptions,\n type InlineMedia,\n type ResumeDecision,\n actionProposalDecisionEvents,\n agUiEvents,\n agUiFramesFromNdjson,\n agUiSse,\n parseRunInput,\n planResume,\n readAnswersPayload,\n readApprovalPayload,\n readContext,\n readForwardedProps,\n readUserTurn,\n} from '@dudousxd/nestjs-agent-core/ag-ui';\nimport { type Catalog, uiActionText } from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n Body,\n Controller,\n ForbiddenException,\n HttpCode,\n Inject,\n Optional,\n Post,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { AgentService, NO_USER_MESSAGE_CODE } from '../agent.service.js';\nimport { attachmentLimits } from '../attachment-limits.js';\nimport { answers as boundedAnswers, rejectReason } from '../controller/tool-call.controller.js';\nimport { GENUI_CATALOG } from '../genui/agent-genui.module.js';\nimport type { AgentProtocolAdapter } from '../protocol-adapter.js';\n\nexport interface AgUiAdapterOptions {\n /** Where the route mounts, under the agent's path. Default `'ag-ui'` → `POST <path>/ag-ui`. */\n path?: string;\n /**\n * How long a run that is waiting on a person AND still has other work announced may stay silent\n * before it is reported interrupted. Default 750 ms.\n */\n quietMs?: number;\n /**\n * A2UI over AG-UI: every generative-UI frame is also sent as an `ACTIVITY_SNAPSHOT` of type\n * `a2ui-surface` (the A2UI messages under `a2ui_operations`), so CopilotKit's A2UI renderer — or\n * any client of AG-UI's A2UI binding — draws it. `true` maps the library builtins onto A2UI's\n * basic catalog; pass {@link A2uiOptions} for the app's own mappings or catalog. Inbound,\n * `forwardedProps.a2uiAction.userAction` is always read: the action becomes the user's turn.\n *\n * The basic catalog goes under the id the client advertises — `forwardedProps\n * .a2uiClientCapabilities`, or the \"A2UI catalog capabilities\" context entry CopilotKit sends —\n * and, when it advertises none, under the id AG-UI's A2UI binding uses\n * (`A2UI_LEGACY_BASIC_CATALOG_ID`: CopilotKit 1.77, `@ag-ui/a2ui-middleware`).\n */\n a2ui?: boolean | A2uiOptions;\n}\n\n/** The surface an AG-UI resume decision is recorded as having come through. */\nconst AG_UI_VIA = 'ag-ui';\n\nfunction invalid(code: string, message: string): BadRequestException {\n return new BadRequestException({ statusCode: 400, code, message });\n}\n\n/** Input material the route could not use, as the events that say so. */\nfunction warningEvents(warnings: readonly string[]): AgUiEvent[] {\n return warnings.map((message) => ({\n type: 'CUSTOM' as const,\n name: AG_UI_CUSTOM.warning,\n value: { message },\n }));\n}\n\n/**\n * Serves the agent over AG-UI 1.0. Not mounted directly — {@link agUiAdapter} mounts a subclass at\n * the configured path — but exported so a host can extend it under a route of its own.\n */\nexport class AgUiRunHandler {\n constructor(\n protected readonly agent: AgentService,\n protected readonly actorResolver: ActorResolver,\n protected readonly options: AgentModuleOptions,\n protected readonly staging: AttachmentStagingStore | undefined,\n protected readonly quietMs: number | undefined,\n /** A2UI over AG-UI ({@link AgUiAdapterOptions.a2ui}), its catalog already filled in. Off when undefined. */\n protected readonly a2ui: A2uiOptions | undefined = undefined,\n ) {}\n\n async handle(req: Request, res: Response, body: unknown): Promise<void> {\n const input = parseRunInput(body);\n if (typeof input === 'string') {\n throw invalid('invalid_input', input);\n }\n const forwarded = readForwardedProps(input.forwardedProps);\n const actor = await this.actorResolver.resolve(req);\n const warnings: string[] = [];\n if (Array.isArray(input.tools) && input.tools.length > 0) {\n warnings.push('Frontend tools are not supported by this agent: the tools list was ignored.');\n }\n const quiet = this.quietMs !== undefined ? { quietMs: this.quietMs } : {};\n\n if (input.resume !== undefined && input.resume.length > 0) {\n const plan = planResume(input.resume);\n if (typeof plan === 'string') {\n throw invalid('invalid_resume', plan);\n }\n for (const id of plan.unrecognised) {\n warnings.push(`The resume entry ${id} answers an interrupt this agent did not raise.`);\n }\n const first = plan.decisions[0];\n // Independent proposals do not park their run: deciding them is the whole answer.\n if (first !== undefined && plan.decisions.every((d) => d.address.kind === 'proposal')) {\n const decided = await this.decideProposals(actor, plan.decisions);\n this.writeEvents(res, [\n ...warningEvents(warnings),\n ...decided.flatMap((outcome, index) =>\n actionProposalDecisionEvents({\n threadId: input.threadId,\n runId: index === 0 ? input.runId : `${input.runId}:${index}`,\n text: outcome.text,\n proposalDecision: outcome.proposalDecision,\n }),\n ),\n ]);\n return;\n }\n // A list that answers nothing this agent asked continues nothing: an ordinary run.\n if (first !== undefined) {\n const streamRunId = first.address.stream;\n await this.agent.assertResumable(actor, streamRunId);\n await this.settle(actor, plan.decisions);\n await this.pipe(res, streamRunId, {\n threadId: input.threadId,\n runId: input.runId,\n streamRunId,\n skip: first.address.position,\n answered: plan.decisions.map((decision) => decision.address.toolCallId),\n ...quiet,\n ...this.a2uiFor(input),\n preamble: warningEvents(warnings),\n });\n return;\n }\n }\n\n // A UI action (a sandbox's `agent.send`, an A2UI button) IS the turn: the messages only\n // restate the conversation so far.\n const action = forwarded.uiAction;\n if (typeof action === 'string') {\n throw invalid('invalid_ui_action', action);\n }\n const turn =\n action !== undefined\n ? { text: uiActionText(action), media: [], staged: [], dropped: [] }\n : readUserTurn(input.messages);\n if (turn === null) {\n throw invalid(NO_USER_MESSAGE_CODE, 'messages carries no user message to answer');\n }\n warnings.push(...turn.dropped);\n // The consumer names the conversation. A thread it already has is continued (its owner checked,\n // as on `chat`); one nobody has is created under that name.\n const owner = await this.agent.threadOwner(input.threadId);\n if (owner !== null && owner !== actor.id) {\n throw new ForbiddenException('thread belongs to another actor');\n }\n if (forwarded.regenerate === true && owner === null) {\n throw invalid('invalid_input', 'regenerate needs a thread that already has an exchange');\n }\n // A regenerate re-answers the last message: it is never a decision on a pending proposal.\n if (\n owner !== null &&\n forwarded.regenerate !== true &&\n action === undefined &&\n turn.media.length === 0 &&\n turn.staged.length === 0\n ) {\n const decision = await this.agent.handleTextDecision(input.threadId, actor, turn.text);\n if ('proposalDecision' in decision) {\n this.writeEvents(res, [\n ...warningEvents(warnings),\n ...actionProposalDecisionEvents({\n threadId: input.threadId,\n runId: input.runId,\n text: decision.text,\n proposalDecision: decision.proposalDecision,\n }),\n ]);\n return;\n }\n }\n // Attachments the consumer staged with this library already are named by mediaId; `chat`\n // resolves them for this actor and refuses one it does not own, as the native route does.\n const refs = await this.stage(actor, turn.media, warnings, turn.staged);\n // A regenerate re-answers the thread's last message and adds none, as on `chat`.\n if (turn.text.trim().length === 0 && refs.length === 0 && forwarded.regenerate !== true) {\n throw invalid(NO_USER_MESSAGE_CODE, 'the user message to answer is empty');\n }\n const context = readContext(input.context);\n const pageContext: PageContext | undefined =\n forwarded.pageContext !== undefined || context !== undefined\n ? {\n ...forwarded.pageContext,\n ...(context !== undefined ? { agUiContext: context } : {}),\n }\n : undefined;\n const started = await this.agent.chat({\n actor,\n message: turn.text,\n ...(owner !== null ? { threadId: input.threadId } : { newThreadId: input.threadId }),\n ...(forwarded.agent !== undefined ? { agentName: forwarded.agent } : {}),\n ...(forwarded.persona !== undefined ? { personaId: forwarded.persona } : {}),\n ...(forwarded.model !== undefined ? { model: forwarded.model } : {}),\n ...(forwarded.uiCapabilities !== undefined\n ? { uiCapabilities: forwarded.uiCapabilities }\n : {}),\n ...(pageContext !== undefined ? { pageContext } : {}),\n ...(refs.length > 0 ? { attachments: refs } : {}),\n ...(forwarded.regenerate === true ? { regenerate: true } : {}),\n });\n await this.pipe(res, started.runId, {\n threadId: input.threadId,\n runId: input.runId,\n streamRunId: started.runId,\n streamThreadId: started.threadId,\n ...quiet,\n ...this.a2uiFor(input),\n preamble: warningEvents(warnings),\n });\n }\n\n /**\n * The turn's attachments: the ones already staged (by mediaId), then its inline media staged\n * through the bound store — all within the store's limits; say what was not used.\n */\n private async stage(\n actor: Actor,\n media: readonly InlineMedia[],\n warnings: string[],\n staged: readonly AttachmentRef[] = [],\n ): Promise<AttachmentRef[]> {\n const refs: AttachmentRef[] = [];\n const limits = attachmentLimits(this.options, this.staging);\n for (const ref of staged) {\n const label = `The attachment ${ref.mediaId} was not used`;\n if (this.staging === undefined) {\n warnings.push(`${label}: attachments are not enabled on this agent.`);\n } else if (refs.length >= limits.maxPerMessage) {\n warnings.push(`${label}: a message carries at most ${limits.maxPerMessage} attachments.`);\n } else {\n refs.push({ mediaId: ref.mediaId });\n }\n }\n for (const item of media) {\n const label = `The ${item.kind} \"${item.filename}\" was not used`;\n if (this.staging === undefined) {\n warnings.push(`${label}: attachments are not enabled on this agent.`);\n } else if (refs.length >= limits.maxPerMessage) {\n warnings.push(`${label}: a message carries at most ${limits.maxPerMessage} attachments.`);\n } else if (!limits.allowedContentTypes.includes(item.contentType)) {\n warnings.push(`${label}: ${item.contentType} is not an accepted type.`);\n } else if (item.data.length > limits.maxBytes) {\n warnings.push(`${label}: it is larger than ${limits.maxBytes} bytes.`);\n } else {\n try {\n const staged = await this.staging.stage({\n data: item.data,\n filename: item.filename,\n contentType: item.contentType,\n sizeBytes: item.data.length,\n actor,\n });\n refs.push({ mediaId: staged.mediaId });\n } catch {\n warnings.push(`${label}: it could not be stored.`);\n }\n }\n }\n return refs;\n }\n\n /**\n * Deliver what a resume list decided, through the same calls the native decision routes make.\n * Everything that can refuse — who may decide, an answer a question's rules reject, a payload that\n * says nothing — is checked for EVERY entry before the first one is delivered, so a list with one\n * bad entry settles nothing.\n */\n private async settle(actor: Actor, decisions: ResumeDecision[]): Promise<void> {\n const deliveries: (() => Promise<void>)[] = [];\n const proposals = decisions.filter((decision) => decision.address.kind === 'proposal');\n for (const { address, entry } of decisions) {\n const { toolCallId } = address;\n const abandoned = entry.status === 'cancelled';\n if (address.kind === 'proposal') continue;\n if (address.kind === 'approval') {\n await this.agent.checkDecision(actor, toolCallId);\n const decision: { approved: boolean; reason?: string; remember?: boolean } | null =\n abandoned ? { approved: false } : readApprovalPayload(entry.payload);\n if (decision === null) {\n throw invalid(\n 'invalid_resume',\n 'an approval is answered with { approved: boolean, reason?, remember? }',\n );\n }\n const reason = rejectReason(decision.reason ?? (abandoned ? 'abandoned' : undefined));\n deliveries.push(() =>\n decision.approved\n ? this.agent.approve(actor, toolCallId, {\n via: AG_UI_VIA,\n ...(decision.remember === true ? { remember: true } : {}),\n })\n : this.agent.reject(actor, toolCallId, reason, { via: AG_UI_VIA }),\n );\n continue;\n }\n if (abandoned) {\n await this.agent.checkAnswer(actor, toolCallId, {});\n deliveries.push(() => this.agent.skip(actor, toolCallId, { via: AG_UI_VIA }));\n continue;\n }\n const read = readAnswersPayload(entry.payload);\n if (read === null) {\n throw invalid(\n 'invalid_resume',\n 'a question set is answered with { answers: { <questionId>: string[] } }',\n );\n }\n const answers = boundedAnswers(read) ?? {};\n await this.agent.checkAnswer(actor, toolCallId, answers);\n deliveries.push(() => this.agent.answer(actor, toolCallId, answers, { via: AG_UI_VIA }));\n }\n // Settled before the parked calls, like any other delivery: a refused one settles nothing more.\n if (proposals.length > 0) await this.decideProposals(actor, proposals);\n for (const deliver of deliveries) await deliver();\n }\n\n /**\n * Decide independent proposals through the proposal service — the call the native\n * `action-proposals/:id/approve|reject` routes make — never by signalling the origin run, which\n * is not waiting. Every payload is checked before the first decision; a refusal is the service's\n * own `403`/`404`.\n */\n private async decideProposals(\n actor: Actor,\n decisions: ResumeDecision[],\n ): Promise<{ proposalDecision: unknown; text: string }[]> {\n const planned = decisions.map(({ address, entry }) => {\n const decision =\n entry.status === 'cancelled' ? { approved: false } : readApprovalPayload(entry.payload);\n if (decision === null || address.proposalId === undefined || address.threadId === undefined) {\n throw invalid(\n 'invalid_resume',\n 'an approval is answered with { approved: boolean, reason?, remember? }',\n );\n }\n return { address, decision };\n });\n const outcomes: { proposalDecision: unknown; text: string }[] = [];\n for (const { address, decision } of planned) {\n outcomes.push(\n await this.agent.decideActionProposal(\n actor,\n address.threadId as string,\n address.proposalId as string,\n {\n decision: decision.approved ? 'approved' : 'rejected',\n via: AG_UI_VIA,\n ...(decision.remember !== undefined ? { remember: decision.remember } : {}),\n ...(decision.reason !== undefined ? { reason: decision.reason } : {}),\n },\n ),\n );\n }\n return outcomes;\n }\n\n /** Answer with a complete list of events, no run behind them. */\n private writeEvents(res: Response, events: AgUiEvent[]): void {\n res.status(200);\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.flushHeaders();\n for (const event of events) res.write(agUiSse(event));\n res.end();\n }\n\n /** A2UI for this request's client: the basic catalog under the id it advertises. Off when off. */\n private a2uiFor(input: { forwardedProps?: unknown; context?: readonly unknown[] }): {\n a2ui?: A2uiOptions;\n } {\n if (this.a2ui === undefined) return {};\n return {\n a2ui: negotiateA2uiCatalog(\n this.a2ui,\n readAgUiA2uiCatalogIds(input),\n A2UI_LEGACY_BASIC_CATALOG_ID,\n ),\n };\n }\n\n /**\n * Pipe a run to the client as AG-UI 1.0 over SSE: one event per `data:` line, from `RUN_STARTED`\n * to the run's terminal event. It ends when the run stops to ask — the library run stays parked,\n * and the request that answers re-attaches to it.\n */\n private async pipe(res: Response, runId: string, options: AgUiStreamOptions): Promise<void> {\n res.status(200);\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.setHeader('X-Agent-Run-Id', runId);\n res.flushHeaders();\n let terminal = false;\n // Every event goes out with the run's own sequence number as its SSE `id:`, so a consumer can\n // follow the rest of the run on `chat/:runId/stream?after=<id>` once this AG-UI run ends.\n const cursor = { seq: 0 };\n try {\n const frames = agUiFramesFromNdjson(this.agent.subscribe(runId));\n for await (const event of agUiEvents(frames, { ...options, cursor })) {\n if (event.type === 'RUN_FINISHED' || event.type === 'RUN_ERROR') terminal = true;\n res.write(agUiSse(event, cursor.seq));\n }\n } catch {\n // The stream under the run broke. The status line is long gone, so the failure travels\n // in-stream — and says nothing of what broke, which is the server's to know.\n if (!terminal) {\n res.write(\n agUiSse({\n type: 'RUN_ERROR',\n message: 'The run could not be followed.',\n code: 'run_failed',\n }),\n );\n }\n }\n res.end();\n }\n}\n\n/**\n * Serve the agent over AG-UI 1.0 (https://docs.ag-ui.com/spec/1.0): the body of\n * `POST <path>/ag-ui` is a `RunAgentInput`, the answer the run as AG-UI events. A run that stops to\n * ask ends with the interrupt outcome and is continued by a later request carrying `resume`.\n *\n * ```ts\n * AgentModule.forRoot({ model, adapters: [agUiAdapter()] })\n * ```\n *\n * Authenticated by the module's `actorResolver`, guarded by its `guards` and owner-scoped exactly\n * as `chat`, `chat/:runId/stream` and the `tool-call` routes are.\n */\nexport function agUiAdapter(options: AgUiAdapterOptions = {}): AgentProtocolAdapter {\n const path = (options.path ?? 'ag-ui').replace(/^\\/+|\\/+$/g, '');\n const quietMs = options.quietMs;\n const a2ui =\n options.a2ui === undefined || options.a2ui === false\n ? undefined\n : options.a2ui === true\n ? {}\n : options.a2ui;\n\n @Controller()\n class AgUiController extends AgUiRunHandler {\n constructor(\n @Inject(AgentService) agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) actorResolver: ActorResolver,\n @Inject(AGENT_OPTIONS) moduleOptions: AgentModuleOptions,\n @Optional() @Inject(AGENT_ATTACHMENT_STAGING) staging?: AttachmentStagingStore,\n @Optional() @Inject(GENUI_CATALOG) catalog?: Catalog,\n ) {\n super(\n agent,\n actorResolver,\n moduleOptions,\n staging,\n quietMs,\n a2ui !== undefined ? withCatalog(a2ui, catalog) : undefined,\n );\n }\n\n @Post(path)\n @HttpCode(200)\n run(@Req() req: Request, @Res() res: Response, @Body() body: unknown): Promise<void> {\n return this.handle(req, res, body);\n }\n }\n\n return { name: 'ag-ui', controllers: [AgUiController] };\n}\n\n/** The app's genui catalog under the A2UI options, for the text of components nothing maps. */\nfunction withCatalog(options: A2uiOptions, catalog: Catalog | undefined): A2uiOptions {\n if (options.catalog !== undefined || catalog === undefined) return options;\n return { ...options, catalog };\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport {\n A2UI_APPROVE_ACTION,\n A2UI_REJECT_ACTION,\n A2uiProjector,\n type A2uiServerMessage,\n type A2uiStreamOptions,\n a2uiThreadReplay,\n negotiateA2uiCatalog,\n readA2uiAction,\n readA2uiClientCapabilities,\n} from '@dudousxd/nestjs-agent-core/a2ui';\nimport {\n agUiEvents,\n agUiFramesFromNdjson,\n decodeInterruptId,\n} from '@dudousxd/nestjs-agent-core/ag-ui';\nimport {\n type Catalog,\n type UiAction,\n type UiCapabilities,\n uiActionText,\n validateUiCapabilities,\n} from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n Body,\n Controller,\n ForbiddenException,\n Get,\n HttpCode,\n Inject,\n Optional,\n Param,\n Post,\n Query,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AGENT_SERVICE } from '../agent-service.token.js';\nimport type { AgentService } from '../agent.service.js';\nimport { GENUI_CATALOG } from '../genui/agent-genui.module.js';\nimport type { AgentProtocolAdapter } from '../protocol-adapter.js';\n\nexport interface A2uiAdapterOptions extends A2uiStreamOptions {\n /** Where the route mounts, under the agent's path. Default `'a2ui'` → `POST <path>/a2ui`. */\n path?: string;\n /** As `agUiAdapter`'s: how long a run waiting on a person may stay silent before the stream ends. */\n quietMs?: number;\n /** Largest action accepted, as JSON, in bytes. Default 8192. */\n maxActionBytes?: number;\n /** Largest `a2uiClientDataModel` accepted, as JSON, in bytes. Default 32768. */\n maxDataModelBytes?: number;\n}\n\n/** The surface an A2UI decision is recorded as having come through. */\nconst A2UI_VIA = 'a2ui';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction invalid(code: string, message: string): BadRequestException {\n return new BadRequestException({ statusCode: 400, code, message });\n}\n\n/** A field of the body, or of its A2A-style `metadata` (where A2UI puts client capabilities). */\nfunction bodyField(body: Record<string, unknown>, key: string): unknown {\n if (body[key] !== undefined) return body[key];\n return isRecord(body.metadata) ? body.metadata[key] : undefined;\n}\n\n/** `a2uiClientDataModel` (`{ version, surfaces: { <surfaceId>: model } }`): its surfaces, or why not. */\nfunction readDataModel(\n raw: unknown,\n maxBytes: number,\n): Record<string, unknown> | undefined | string {\n if (raw === undefined) return undefined;\n if (!isRecord(raw) || !isRecord(raw.surfaces)) {\n return 'a2uiClientDataModel carries { version, surfaces }';\n }\n let size: number;\n try {\n size = new TextEncoder().encode(JSON.stringify(raw.surfaces)).length;\n } catch {\n return 'a2uiClientDataModel must be JSON';\n }\n if (size > maxBytes) {\n return `a2uiClientDataModel may be at most ${maxBytes} bytes (this one is ${size})`;\n }\n return Object.keys(raw.surfaces).length > 0 ? raw.surfaces : undefined;\n}\n\n/**\n * Serves the agent as an A2UI agent. Not mounted directly — {@link a2uiAdapter} mounts a subclass at\n * the configured path — but exported so a host can extend it under a route of its own.\n */\nexport class A2uiRunHandler {\n constructor(\n protected readonly agent: AgentService,\n protected readonly actorResolver: ActorResolver,\n protected readonly projection: A2uiStreamOptions,\n protected readonly quietMs: number | undefined,\n protected readonly maxActionBytes: number | undefined,\n protected readonly maxDataModelBytes: number | undefined = undefined,\n ) {}\n\n /**\n * `GET <path>/a2ui/threads/:threadId`: a stored thread as `{ threadId, entries }`\n * (`a2uiThreadReplay`) — what a client draws again after a reload. Owner-scoped; a thread nobody\n * has answers `{ entries: [] }`. `?catalog=<id>` names the client's basic catalog id.\n */\n async replay(\n req: Request,\n threadId: string,\n catalog: unknown,\n ): Promise<{ threadId: string; entries: ReturnType<typeof a2uiThreadReplay> }> {\n const actor = await this.actorResolver.resolve(req);\n const owner = await this.agent.threadOwner(threadId);\n if (owner === null) return { threadId, entries: [] };\n const thread = await this.agent.getThread(actor, threadId);\n const supported =\n typeof catalog === 'string'\n ? [catalog]\n : Array.isArray(catalog)\n ? catalog.filter((id): id is string => typeof id === 'string')\n : undefined;\n return {\n threadId,\n entries: a2uiThreadReplay(\n thread?.messages ?? [],\n negotiateA2uiCatalog(this.projection, supported),\n ),\n };\n }\n\n async handle(req: Request, res: Response, raw: unknown): Promise<void> {\n const body = isRecord(raw) ? raw : {};\n const agentName =\n typeof body.agent === 'string' && body.agent.length > 0 ? body.agent : undefined;\n const actor = await this.actorResolver.resolve(req);\n // The basic catalog under the id this client advertises (`a2uiClientCapabilities`).\n const projection = negotiateA2uiCatalog(\n this.projection,\n readA2uiClientCapabilities(bodyField(body, 'a2uiClientCapabilities')),\n );\n const dataModel = readDataModel(\n bodyField(body, 'a2uiClientDataModel'),\n this.maxDataModelBytes ?? 32768,\n );\n if (typeof dataModel === 'string') throw invalid('invalid_data_model', dataModel);\n\n let action: UiAction | undefined;\n if (body.action !== undefined) {\n const read = isRecord(body.action)\n ? readA2uiAction(body.action, {\n ...(this.maxActionBytes !== undefined ? { maxBytes: this.maxActionBytes } : {}),\n })\n : 'action must be an A2UI action message';\n if (typeof read === 'string') throw invalid('invalid_action', read);\n action = read;\n }\n\n // Deciding the approval a stream ended on: settle it, then stream the rest of the run.\n if (action?.name === A2UI_APPROVE_ACTION || action?.name === A2UI_REJECT_ACTION) {\n const interruptId = action.context.interruptId;\n const address = typeof interruptId === 'string' ? decodeInterruptId(interruptId) : undefined;\n if (address === undefined || address === null || address.kind === 'elicitation') {\n throw invalid('invalid_action', 'an approval action carries the interruptId it decides');\n }\n // An independent proposal: decided through the proposal service (its own run is not\n // waiting), as an AG-UI resume decides it, and answered with the configured reply.\n if (address.kind === 'proposal') {\n if (address.proposalId === undefined || address.threadId === undefined) {\n throw invalid('invalid_action', 'the interruptId names no proposal');\n }\n const decided = await this.agent.decideActionProposal(\n actor,\n address.threadId,\n address.proposalId,\n {\n decision: action.name === A2UI_APPROVE_ACTION ? 'approved' : 'rejected',\n via: A2UI_VIA,\n },\n );\n this.writeHead(res, { 'X-Agent-Thread-Id': address.threadId });\n const projector = new A2uiProjector(projection);\n const messageId = `proposal-${address.proposalId}`;\n for (const event of [\n { type: 'TEXT_MESSAGE_START' as const, messageId, role: 'assistant' as const },\n { type: 'TEXT_MESSAGE_CONTENT' as const, messageId, delta: decided.text },\n ]) {\n for (const message of projector.project(event)) res.write(`${JSON.stringify(message)}\\n`);\n }\n res.end();\n return;\n }\n // The same checks an AG-UI resume makes: the run is the actor's and still waiting, and the\n // actor may decide this call.\n await this.agent.assertResumable(actor, address.stream);\n await this.agent.checkDecision(actor, address.toolCallId);\n if (action.name === A2UI_APPROVE_ACTION) {\n await this.agent.approve(actor, address.toolCallId, { via: A2UI_VIA });\n } else {\n await this.agent.reject(actor, address.toolCallId, undefined, { via: A2UI_VIA });\n }\n await this.stream(res, address.stream, {\n skip: address.position,\n answered: [address.toolCallId],\n projection,\n });\n return;\n }\n\n const message = typeof body.message === 'string' ? body.message : '';\n const text = action !== undefined ? uiActionText(action) : message;\n if (text.trim().length === 0) {\n throw invalid('no_user_message', 'send a message or an action');\n }\n const threadId =\n typeof body.threadId === 'string' && body.threadId.length > 0 ? body.threadId : undefined;\n const owner = threadId !== undefined ? await this.agent.threadOwner(threadId) : null;\n if (owner !== null && owner !== actor.id) {\n throw new ForbiddenException('thread belongs to another actor');\n }\n let uiCapabilities: UiCapabilities | undefined;\n if (Object.hasOwn(body, 'uiCapabilities')) {\n try {\n uiCapabilities = validateUiCapabilities(body.uiCapabilities);\n } catch (error) {\n throw invalid('invalid_input', (error as Error).message);\n }\n }\n const started = await this.agent.chat({\n actor,\n message: text,\n ...(threadId === undefined ? {} : owner !== null ? { threadId } : { newThreadId: threadId }),\n ...(agentName !== undefined ? { agentName } : {}),\n ...(uiCapabilities !== undefined ? { uiCapabilities } : {}),\n ...(dataModel !== undefined ? { pageContext: { a2uiDataModel: dataModel } } : {}),\n });\n await this.stream(res, started.runId, { threadId: started.threadId, projection });\n }\n\n /** Open the JSON Lines response. */\n protected writeHead(res: Response, extra: Record<string, string>): void {\n res.status(200);\n res.setHeader('Content-Type', 'application/jsonl; charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n for (const [name, value] of Object.entries(extra)) res.setHeader(name, value);\n res.flushHeaders();\n }\n\n /** Write one run as A2UI JSON Lines, until it ends or stops to ask. */\n protected async stream(\n res: Response,\n runId: string,\n options: {\n threadId?: string;\n skip?: number;\n answered?: string[];\n projection?: A2uiStreamOptions;\n },\n ): Promise<void> {\n this.writeHead(res, {\n 'X-Agent-Run-Id': runId,\n ...(options.threadId !== undefined ? { 'X-Agent-Thread-Id': options.threadId } : {}),\n });\n const projector = new A2uiProjector(options.projection ?? this.projection);\n const write = (messages: A2uiServerMessage[]) => {\n for (const message of messages) res.write(`${JSON.stringify(message)}\\n`);\n };\n try {\n const frames = agUiFramesFromNdjson(this.agent.subscribe(runId));\n for await (const event of agUiEvents(frames, {\n threadId: options.threadId ?? runId,\n runId,\n streamRunId: runId,\n ...(options.threadId !== undefined ? { streamThreadId: options.threadId } : {}),\n ...(options.skip !== undefined ? { skip: options.skip } : {}),\n ...(options.answered !== undefined ? { answered: options.answered } : {}),\n ...(this.quietMs !== undefined ? { quietMs: this.quietMs } : {}),\n })) {\n write(projector.project(event));\n }\n } catch {\n write(projector.project({ type: 'RUN_ERROR', message: 'The run could not be followed.' }));\n }\n res.end();\n }\n}\n\n/**\n * Serve the agent as an A2UI (https://a2ui.org, v0.9) agent: `POST <path>/a2ui` answers with the\n * run as a JSON Lines stream of A2UI server-to-client messages — `createSurface`,\n * `updateComponents`, `updateDataModel`, `deleteSurface` — that any A2UI renderer draws.\n *\n * ```ts\n * import { a2uiAdapter } from '@dudousxd/nestjs-agent/a2ui'\n *\n * AgentModule.forRoot({ model, adapters: [a2uiAdapter()] })\n * ```\n *\n * The body is `{ threadId?, message?, action?, uiCapabilities?, a2uiClientCapabilities?,\n * a2uiClientDataModel?, agent? }` (the two A2UI fields also read from `metadata`, A2A-style):\n * - `message` — the user's text;\n * - `action` — an A2UI client message (`{ version: 'v0.9', action: { name, surfaceId,\n * sourceComponentId, timestamp, context } }`, or v0.8's `{ userAction }`): it becomes the turn\n * (`uiActionText`). `agora.approve` / `agora.reject` with `context.interruptId` decide the\n * approval a previous stream ended on, and stream the rest of that run (an independent\n * proposal is decided through the proposal service and answered with its reply);\n * - `threadId` — continue that thread (its owner is checked), or start one under that id;\n * - `a2uiClientCapabilities` — the catalogs the client draws (`{ 'v0.9': { supportedCatalogIds } }`,\n * what `MessageProcessor.getRendererCapabilities()` builds): the basic catalog is sent under the\n * id the client lists for it;\n * - `a2uiClientDataModel` — the data models of surfaces created with `sendDataModel`, handed to the\n * prompt builder as `pageContext.a2uiDataModel`.\n *\n * `GET <path>/a2ui/threads/:threadId` answers a stored thread as `{ threadId, entries }`\n * (`a2uiThreadReplay`): what a client draws again after a reload.\n *\n * Response headers name the library's ids: `X-Agent-Thread-Id`, `X-Agent-Run-Id`. Authenticated by\n * the module's `actorResolver`, guarded by its `guards` and owner-scoped exactly as `chat` is.\n * Components nothing maps are drawn as their text, from the `AgentGenuiModule` catalog when there\n * is one (or `catalog` here).\n */\nexport function a2uiAdapter(options: A2uiAdapterOptions = {}): AgentProtocolAdapter {\n const path = (options.path ?? 'a2ui').replace(/^\\/+|\\/+$/g, '');\n const { path: _path, quietMs, maxActionBytes, maxDataModelBytes, ...projection } = options;\n\n @Controller()\n class A2uiController extends A2uiRunHandler {\n constructor(\n // Tokens, never classes: this entry is its own bundle (see AGENT_SERVICE).\n @Inject(AGENT_SERVICE) agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) actorResolver: ActorResolver,\n @Optional() @Inject(GENUI_CATALOG) catalog?: Catalog,\n ) {\n super(\n agent,\n actorResolver,\n projection.catalog === undefined && catalog !== undefined\n ? { ...projection, catalog }\n : projection,\n quietMs,\n maxActionBytes,\n maxDataModelBytes,\n );\n }\n\n @Get(`${path}/threads/:threadId`)\n thread(\n @Req() req: Request,\n @Param('threadId') threadId: string,\n @Query('catalog') catalog: unknown,\n ): ReturnType<A2uiRunHandler['replay']> {\n return this.replay(req, threadId, catalog);\n }\n\n @Post(path)\n @HttpCode(200)\n run(@Req() req: Request, @Res() res: Response, @Body() body: unknown): Promise<void> {\n return this.handle(req, res, body);\n }\n }\n\n return { name: 'a2ui', controllers: [A2uiController] };\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","import type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { UnauthorizedException } from '@nestjs/common';\n\n/** Turns whatever your auth put on `req.user` into the agent's {@link Actor}. */\nexport type RequestUserMapper<TUser = Record<string, unknown>> = (\n user: TUser,\n req: unknown,\n) => Actor | Promise<Actor>;\n\nfunction field(user: Record<string, unknown>, ...names: string[]): unknown {\n for (const name of names) {\n const value = user[name];\n if (value !== undefined && value !== null && value !== '') return value;\n }\n return undefined;\n}\n\n/**\n * The default mapping: `id` from `id` / `sub` / `_id` / `userId`, `roles` from `roles` (an array)\n * or `role` (a string), `tenantRef` from `tenantRef` / `tenantId` / `orgId`.\n */\nexport function defaultRequestUserMapper(user: Record<string, unknown>): Actor {\n const id = field(user, 'id', 'sub', '_id', 'userId');\n if (id === undefined) {\n throw new UnauthorizedException(\n 'requestUserActorResolver: req.user has no id/sub/_id/userId — pass a mapper: ' +\n 'requestUserActorResolver((user) => ({ id: …, roles: … }))',\n );\n }\n const rawRoles = field(user, 'roles', 'role');\n const roles = Array.isArray(rawRoles)\n ? rawRoles.map(String)\n : typeof rawRoles === 'string'\n ? [rawRoles]\n : [];\n const tenant = field(user, 'tenantRef', 'tenantId', 'orgId');\n return {\n id: String(id),\n roles,\n ...(tenant !== undefined ? { tenantRef: String(tenant) } : {}),\n };\n}\n\n/**\n * Authenticated mode in one line, for apps whose auth already puts the principal on `req.user` —\n * Passport strategies, `express-session` / cookie-session middleware, a Nest guard that assigns it:\n *\n * ```ts\n * AgentModule.forRoot({ model, actorResolver: requestUserActorResolver() })\n * ```\n *\n * A request without `req.user` is refused with `401` — the agent never invents a caller. Pass a\n * mapper when your user object is shaped differently:\n *\n * ```ts\n * requestUserActorResolver((user: SessionUser) => ({ id: user.uuid, roles: user.permissions }))\n * ```\n */\nexport function requestUserActorResolver<TUser = Record<string, unknown>>(\n map?: RequestUserMapper<TUser>,\n): ActorResolver {\n return {\n async resolve(req: unknown): Promise<Actor> {\n const user =\n typeof req === 'object' && req !== null ? (req as { user?: unknown }).user : undefined;\n if (user === undefined || user === null || user === false) {\n throw new UnauthorizedException('Sign in to use the agent.');\n }\n if (map !== undefined) return map(user as TUser, req);\n return defaultRequestUserMapper(user as Record<string, unknown>);\n },\n };\n}\n"],"mappings":"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","names":["NEST_SANDBOX_KIT_DESCRIPTOR","nestSandboxKitDiscovery","options","name","manifest","NEST_SANDBOX_KIT_MANIFEST","sandboxKitDiscovery","root","resolve","process","cwd","undefined","descriptor","sandboxKitDescriptorPath","NEST_SANDBOX_KIT_DESCRIPTOR","file","outDir","kitUrl","cssUrl","tailwindUrl","production","import_kit","Object","freeze","AgentDepsFactory","AgentService","import_nestjs_agent_core","import_common","import_core","import_nestjs_agent_core","import_common","AGENT_TOOL_BRAND","Symbol","for","brand","tool","spec","handler","isBrandedFunctionalTool","value","provideAgentTool","factoryOrTool","inject","provide","useFactory","deps","useValue","provideAgentTools","factory","map","defineTool","createFunctionalTool","AGENT_GENUI","Symbol","for","AgentGenui","catalog","resolveCatalog","channels","base","sandboxClient","GENUI_CATALOG","Symbol","for","GENUI_OPTIONS","GENUI_RESOLVED","GenuiCatalogResolver","resolverProviders","resolver","undefined","provide","useClass","useValue","mergeSandboxClients","clients","merged","theme","client","one","name","kit","css","tailwind","resolveGenui","options","sandbox","asked","channels","askedChannels","assertGenuiChannels","discoveries","Map","resolveSandbox","value","nestSandboxKitDiscovery","resolveSandboxServer","Promise","all","kitName","discovery","get","sandboxKit","set","resolved","push","define","own","catalog","components","find","each","sandboxPolicyOf","ownOptions","sandboxOptions","sandboxView","entry","Object","entries","catalogSandbox","length","sandboxClient","perRequest","scope","resolve","toolOptions","_catalog","_sandbox","_channels","_sandboxKit","rest","resolveCatalog","withSandbox","base","defineCatalog","extend","defineSandbox","coreProviders","GENUI_RESOLVED","useFactory","inject","GENUI_OPTIONS","GENUI_CATALOG","AGENT_GENUI","resolverInstance","AgentGenui","mode","streaming","token","optional","provideAgentTools","perRequestResolver","genuiTools","EXPORTS","AgentGenuiModule","forRoot","module","global","providers","exports","forRootAsync","imports","delegateToolName","args","slug","target","replace","detached","AgentDepsFactory","options","model","store","sink","rolesPolicy","registry","agents","promptContributors","pricingStore","skills","memory","uiCatalog","uiCatalogResolver","genui","actionApprovalMode","assertIndependentActionCapabilities","backgroundActorResolver","memoryConfig","skillsConfig","defaultAgentName","defaultAgent","undefined","registered","list","length","name","effectiveTools","definition","delegated","delegatesTo","map","edge","agent","normalizeDelegation","tools","resolveAgent","has","agentName","alias","resolvePersonaAlias","persona","personaCatalog","get","personas","personaCatalogEntry","defaultPersona","resolvePersona","requested","findPersona","BadRequestException","statusCode","code","message","pinned","threadPersona","forProposal","proposal","_actor","executionContext","Error","deps","forAgent","id","find","withPersona","resolveUiCatalog","scope","catalog","resolve","actor","tenantRef","tenant","uiChannelGuide","channels","createToolUiChannelGuide","base","resolveCatalog","toolAllowList","followUpsCount","retrieval","historyPolicy","ask","approvalPolicy","systemPrompt","maxSteps","maxDelegationDepth","maxAgentAppearances","modelId","inputProcessors","outputProcessors","outputSchema","outputRepairAttempts","intake","toolTimeoutMs","toolTransientRetry","mode","retriever","topK","retrievalTopK","ref","label","prompt","ctx","own","scoped","basePrompt","intersectAllowLists","allowedTools","history","window","config","windowHistory","maxMessages","maxTokens","summarize","summarizeWithModel","followUps","count","AGENT_SERVICE","Symbol","for","import_nestjs_agent_core","import_common","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","flush","fail","DEFAULT_MAX_ATTACHMENT_BYTES","DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES","MAX_ATTACHMENTS_PER_MESSAGE","attachmentLimits","options","staging","declared","describe","own","attachments","enabled","undefined","upload","maxBytes","allowedContentTypes","maxPerMessage","import_nestjs_agent_core","import_common","ActionProposalService","store","options","text","actionProposalText","vocabulary","DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY","replies","DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES","hasCapability","getThreadActionProposalScope","listActionProposals","capability","NotImplementedException","scope","threadId","actor","NotFoundException","tenantRef","ForbiddenException","mayDecide","proposal","mayDecideApproval","approvalPolicy","toolCallId","originToolCallId","approver","requesterRef","actorRef","listPage","query","items","rows","limit","visible","row","id","push","last","at","map","toActionProposalView","length","next","createdAt","list","decide","proposalId","command","getActionProposal","result","decideActionProposal","decision","via","remember","undefined","reason","toActionProposalMutationView","handleTextDecision","parseTextActionProposalCommand","status","textReceipt","candidates","pending","resolution","resolveTextActionProposalDecision","saturated","includes","proposalIds","proposalDecision","tooMany","ambiguous","reply","textVocabulary","textActionProposalReply","import_nestjs_agent_core","import_common","import_nestjs_agent_core","publishQuotaBlocked","actor","report","blocked","window","windows","find","candidate","period","payload","actorId","id","reason","undefined","usedTokens","limitTokens","usedUsd","limitUsd","publishAgentQuotaExceeded","threadPersona","store","threadId","projecting","personaForThread","getThread","persona","MAX_DRAIN_ATTEMPTS","ChatQueueService","logger","Logger","name","starting","Set","store","sink","quotaProvider","options","staging","deps","supported","isChatQueueStore","queueStore","NotImplementedException","state","threadId","items","paused","Promise","all","listQueue","queuePause","map","queuedMessageView","isAlive","holder","runner","has","isRunActive","activeRunForThread","live","stale","plan","args","outcome","runId","holding","attempt","head","undefined","releaseActiveStream","pause","reason","pauseReasonFor","error","message","at","Date","toISOString","setQueuePause","blocked","quotaBlock","actor","frame","queueFrame","claimed","claimActiveStream","id","replacing","removeQueuedMessage","next","messageId","input","inputFor","slice","handoff","start","launch","pausedFrame","kick","warn","started","write","add","Error","String","restore","delete","enqueueMessage","content","userText","attachments","agentName","model","pageContext","uiCapabilities","hostContext","kind","queue","publish","catch","writer","open","encodeStreamEvent","quota","report","publishQuotaBlocked","period","freshAttachments","persona","targetFor","day","utcDay","length","target","resolveAgent","hasPersonas","personaCatalog","resolvePersona","threadPersona","resolve","attachment","mediaId","interrupt","import_nestjs_agent_core","import_common","RunNotActiveException","ConflictException","code","RUN_NOT_ACTIVE_CODE","runId","statusCode","message","RUN_NOT_ACTIVE_MESSAGE","NO_USER_MESSAGE_CODE","sendableParams","params","message","undefined","BadRequestException","statusCode","code","text","trim","length","attachments","regenerate","channel","rest","stamped","pageContext","AgentService","runner","store","deps","staging","models","quotaProvider","options","queue","proposals","decideActionProposal","actor","threadId","proposalId","command","actionApprovalMode","NotFoundException","result","decide","proposalDecision","reply","decision","handleTextDecision","status","actionProposalVocabulary","textVocabulary","DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY","actionProposalReply","textActionProposalReply","listActionProposals","list","attachmentLimits","stageAttachment","file","NotImplementedException","allowedContentTypes","maxBytes","contentType","split","toLowerCase","includes","UnsupportedMediaTypeException","join","data","byteLength","PayloadTooLargeException","stage","filename","sizeBytes","queueing","supported","requireQueue","quotaReport","report","usedTokens","costUsd","quotaToday","id","utcDay","windows","period","usedUsd","assertWithinQuota","quota","blocked","publishQuotaBlocked","HttpException","HttpStatus","TOO_MANY_REQUESTS","reason","listModels","agent","providers","default","assertModelAllowed","model","entry","findCatalogModel","available","unavailableReason","resolveModel","requested","locked","threadModel","projecting","modelForThread","getThread","chat","send","mode","textDecisions","Error","queued","runId","queueStore","removeQueuedMessage","messageId","publish","ConflictException","claimed","sendOptions","target","resolveAgent","resolveAgentName","agentName","persona","resolvePersona","personaId","resolveAttachments","created","createThread","transient","newThreadId","authorized","assertOwnsThread","pinThreadPersona","input","userText","day","uiCapabilities","hostContext","start","setActiveStream","live","stale","holder","settleDeadRun","runIdFor","crypto","randomUUID","claimActiveStream","replacing","startClaimed","enqueue","started","error","releaseActiveStream","interrupting","enqueueMessage","content","interrupt","at","setQueuePause","cancel","kick","state","position","items","findIndex","item","getQueue","updateQueuedMessage","patch","assertOwnsQueuedMessage","updated","GoneException","Number","isInteger","moveQueuedMessage","interruptQueuedMessage","gone","marked","getQueuedMessage","clearQueue","resumeQueue","refs","resolve","resolved","ref","attachment","mediaId","ForbiddenException","push","subscribe","forAgent","sink","subscribeAs","assertOwnsActiveStream","approve","toolCallId","opts","assertMayDecide","signalToolCall","approved","executedByRef","remember","via","decidedVia","reject","answer","answers","assertOwnsToolCall","assertAnswersFit","answeredByRef","answeredVia","skip","skipped","toolCallApproval","assertNotExpired","resolveRunForToolCall","assertRunWaiting","signal","isRunActive","active","catch","RunNotActiveException","threadOwner","ownerOfThread","assertResumable","owner","ownerOfActiveStream","checkDecision","checkAnswer","listThreads","actorRef","threads","Promise","all","map","thread","toSummaryView","toDetailView","deleteThread","softDeleteThread","forkThread","fromMessageId","renameThread","title","updateThread","validateTitle","defaultAgent","setTitle","needsThread","personaCatalog","threadPersona","trimmed","threadDefault","threadDefaultAgent","defaultAgentName","defaultAgentForThread","activeRunId","activeRunForThread","summary","messages","freshAttachmentUrls","some","fresh","promoteThread","truncateThreadFrom","truncateFrom","setMessageFeedback","value","comment","threadOfMessage","feedback","updatedAt","Date","toISOString","listAttachments","attachmentInventory","limit","collectableAttachments","referencedMediaIds","bind","stagedBefore","olderThan","inventory","aged","filter","createdAt","referenced","Set","has","ownerOfToolCall","toolCallInput","questions","readElicitationQuestions","question","submitted","Object","hasOwn","problem","validateElicitationAnswer","defaults","approval","approver","REQUESTER_APPROVER","requesterRef","allowed","mayDecideApproval","approvalPolicy","lapsed","expiresAt","parse","now","runForToolCall","import_common","AgentApprovalPortAdapter","agent","proposals","approveActionProposal","actor","target","opts","NotImplementedException","decide","threadId","proposalId","decision","remember","undefined","via","decidedVia","rejectActionProposal","reason","approve","toolCallId","signalToolCall","approved","executedByRef","reject","import_nestjs_agent_core","import_common","AgentsController","agents","depsFactory","list","defaultAgentName","map","definition","personas","personaCatalog","name","description","isDefault","length","defaultPersona","undefined","import_nestjs_agent_core","import_common","HARD_MAX_ATTACHMENT_BYTES","ATTACHMENT_PAGE_SIZE","AttachmentsController","options","actorResolver","agents","staging","list","req","actor","resolve","listAttachments","limit","upload","file","undefined","NotImplementedException","BadRequestException","allowedContentTypes","maxBytes","attachmentLimits","includes","mimetype","UnsupportedMediaTypeException","join","size","PayloadTooLargeException","stage","data","buffer","filename","originalname","contentType","sizeBytes","limits","fileSize","import_nestjs_agent_core","import_genui","import_common","sendMode","body","interrupt","mode","undefined","BadRequestException","attachmentRefs","claimed","Array","isArray","length","MAX_ATTACHMENTS_PER_MESSAGE","map","entry","Object","keys","some","key","mediaId","ChatController","agent","actorResolver","chat","req","res","actor","resolve","attachments","uiCapabilities","validateUiCapabilities","result","send","message","threadId","agentName","persona","personaId","pageContext","regenerate","transient","model","status","json","queued","runId","pipe","subscribe","stream","after","cursor","parseCursor","headers","subscribeAs","cancel","aborted","events","setHeader","write","JSON","stringify","decoder","TextDecoder","buffer","seq","forward","line","chunk","decode","newline","indexOf","slice","error","payload","AgentStreamError","code","streamFailure","end","raw","value","test","trim","parsed","Number","isSafeInteger","import_nestjs_agent_core","import_common","TOKEN_PATTERN","MINTED","Symbol","readCookie","req","name","header","headers","cookie","raw","Array","isArray","join","undefined","pair","split","index","indexOf","slice","trim","decodeURIComponent","isHttps","secure","forwarded","proto","AnonymousActorResolver","cookieName","roles","options","resolve","request","token","test","randomBytes","toString","setCookie","digest","createHash","update","id","res","setHeader","headersSent","sameSite","secureOption","maxAge","Math","round","maxAgeDays","path","existing","getHeader","list","map","String","ConfigController","options","actorResolver","staging","models","genui","config","req","resolve","attachments","attachmentLimits","enabled","undefined","quota","enforced","identity","anonymous","AnonymousActorResolver","sandboxClient","sandbox","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","MessagesController","agent","actorResolver","feedback","req","id","body","actor","resolve","setMessageFeedback","value","comment","undefined","import_nestjs_agent_core","import_common","ModelsController","agent","actorResolver","list","req","actor","resolve","listModels","import_nestjs_agent_core","import_common","QueueController","agent","actorResolver","list","req","id","getQueue","resolve","clear","clearQueue","resume","resumeQueue","update","messageId","body","actor","message","undefined","BadRequestException","position","attachments","attachmentRefs","updateQueuedMessage","interrupt","interruptQueuedMessage","remove","removeQueuedMessage","import_nestjs_agent_core","import_common","QuotaController","agent","actorResolver","report","req","actor","resolve","quotaReport","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","model","persona","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","MAX_VIA_LENGTH","DEFAULT_VIA","toolCallId","claimed","length","BadRequestException","rejectReason","undefined","remember","via","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","ALL_AGENTS","get","NotFoundException","actor","resolve","names","map","definition","name","entries","Map","deps","forAgent","specs","registry","visibleSpecs","rolesPolicy","toolAllowList","spec","has","set","kind","presentation","values","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","assertPersonas","list","promptMethod","methodWith","SYSTEM_PROMPT_METADATA","systemPrompt","ctx","description","tools","model","modelId","maxSteps","maxDelegationDepth","maxAgentAppearances","history","outputSchema","intake","ask","outputRepairAttempts","handoff","delegatesTo","handoffEdges","personas","defaultPersona","definitions","agentNames","Set","map","definition","aliasOwner","Map","ids","persona","has","id","Error","add","alias","aliases","owner","previous","get","set","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","toolNameFromClass","className","base","replace","leadingCaps","exec","undefined","length","toLowerCase","slice","charAt","AiTool","options","target","resolved","name","kind","Reflect","defineMetadata","readAiToolMetadata","getMetadata","AiToolDiscoveryService","logger","Logger","name","discovery","registry","agents","options","onApplicationBootstrap","count","functional","wrapper","getProviders","instance","undefined","Array","isArray","length","every","each","isBrandedFunctionalTool","tool","registerFunctionalTool","meta","readAiToolMetadata","handler","execute","warn","register","kind","description","inputSchema","input","roles","ability","enabled","presentation","terminal","replacementKey","ctx","present","output","preflight","isEnabled","canUse","actor","describe","scope","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","import_nestjs_agent_core","LedgerQuotaProvider","store","limits","options","report","query","now","Date","actorRef","actor","id","windows","dayWindow","usageBetween","undefined","range","quotaPeriodRange","used","fromDay","toDay","push","window","usedTokens","usd","resetsAt","blocked","exhaustedWindow","warning","quotaWarning","quotaToday","countEstimatedCost","Math","max","costUsd","estimatedCostUsd","period","usedUsd","tokens","limitTokens","limitUsd","warnAt","import_nestjs_agent_core","import_common","logger","Logger","PricingBootService","options","model","pricingStore","onApplicationBootstrap","check","onApplicationShutdown","models","describeModels","error","warn","String","length","catalog","priceCatalog","undefined","process","env","NODE_ENV","ensureModelPricing","log","info","message","catch","import_node_crypto","import_nestjs_agent_core","import_common","ActionProposalWorkerService","worker","logger","Logger","name","settledListeners","Set","onSettled","listener","add","delete","settled","proposal","configured","options","actionProposalWorker","error","store","deps","onModuleInit","actionApprovalMode","assertIndependentActionCapabilities","backgroundActorResolver","surface","resolver","Error","ActionProposalWorker","workerId","randomUUID","executor","ActionProposalExecutor","resolveExecution","actor","forProposal","registry","rolesPolicy","resolveUiCatalog","undefined","toolAllowList","allowedTools","onError","start","onModuleDestroy","stop","import_nestjs_agent_core","import_common","bodyFields","body","field","undefined","Array","isArray","Object","keys","some","key","BadRequestException","value","ActionProposalController","proposals","actors","list","threadId","request","cursor","response","query","Error","after","JSON","parse","validateActionProposalListQuery","page","listPage","resolve","next","setHeader","encodeURIComponent","stringify","exposed","getHeader","String","items","approve","proposalId","decide","decision","remember","reject","reason","passthrough","AGENT_CHAT_QUEUE","Symbol","for","import_nestjs_agent_core","import_common","InlineAgentRunner","logger","Logger","name","pending","Map","cancelled","Set","aborts","live","factory","store","queue","isRunActive","runId","has","key","keys","startsWith","start","input","options","crypto","randomUUID","day","utcDay","deps","forAgent","agentName","add","hooks","topLevelHooks","actor","threadId","chainBelow","delegationPath","undefined","runAgentLoop","then","releaseThreadRun","catch","error","RunCancelledError","settleCancelled","message","Error","String","code","agentFailureCode","publishAgentRunFailed","recordRunEnd","status","errorCode","errorMessage","Promise","resolve","failUnsettledToolCalls","RUN_ENDED_BEFORE_TOOL_CALL","writer","sink","open","settleQueue","fail","streamFailure","finally","forgetCancel","delete","signal","toolCallId","reply","waiter","get","cancel","abort","reject","abortSignalFor","controller","AbortController","set","log","write","encodeStreamEvent","kind","end","outcome","supported","isThreadTurn","settled","frame","handoff","next","nextRunId","failure","parkApproval","timeoutMs","waiting","park","timer","lapse","setTimeout","entry","approved","expired","unref","race","clearTimeout","args","openSink","chunk","awaitApproval","call","_ctx","opts","id","awaitAnswers","request","step","_name","fn","parallel","settleAll","abortSignal","runAgent","task","runNested","depth","path","sinkRunId","parentRunId","startAgent","startDetached","deliverTo","subThread","createThread","transient","setActiveStream","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","logger","Logger","externalWrapper","modules","token","module","values","metatype","AgentModule","wrapper","providers","get","undefined","forwardingStore","target","instance","Error","Proxy","_","property","store","value","bind","has","resolveStore","options","external","AGENT_STORE","warn","InMemoryAgentStore","resolveRolesPolicy","AGENT_ROLES_POLICY","rolesPolicy","forwardingPolicy","emptyRoles","ClosedRolesPolicy","defaultRoles","DefaultRolesPolicy","can","actor","tool","policy","isQuotaProvider","quota","report","resolveCatalog","models","carried","model","catalog","list","sharedProviders","durable","engine","provide","AGENT_TOOL_REGISTRY","useFactory","ToolRegistry","AGENT_REGISTRY","AgentRegistry","AGENT_PROMPT_CONTRIBUTORS","AGENT_SKILL_SOURCES","AGENT_SKILLS","declared","resolveSkillsConfig","skills","inject","AGENT_OPTIONS","AGENT_MEMORY","memory","AGENT_SINK","sink","InProcessTokenStreamSink","ModulesContainer","AGENT_ACTOR_RESOLVER","actorResolver","AnonymousActorResolver","AGENT_MODEL","o","AGENT_QUOTA_PROVIDER","LedgerQuotaProvider","limits","warnAt","countEstimatedCost","AGENT_MODEL_CATALOG","AgentDepsFactory","AGENT_DEPS_FACTORY","useExisting","PricingBootService","AgentDiscoveryService","AiToolDiscoveryService","SkillDiscoveryService","ChatQueueService","AGENT_CHAT_QUEUE","InlineAgentRunner","AgentService","AGENT_SERVICE","ActionProposalService","ActionProposalWorkerService","AgentApprovalPortAdapter","AGENT_APPROVAL_PORT","push","AGENT_RUNNER","runner","durableRunner","AGENT_DURABLE_RUNNER","optional","exportsFor","exports","BASE_CONTROLLERS","ActionProposalController","ChatController","QueueController","ThreadsController","ToolCallController","QuotaController","AgentsController","SkillsController","MemoriesController","ToolsController","MessagesController","ModelsController","ConfigController","AttachmentsController","adapterControllers","adapters","flatMap","adapter","controllers","adapterProviders","controllersForSurface","surface","GUARDS_METADATA","applyGuards","guards","resolved","controller","Reflect","defineMetadata","guardProviders","Set","routerFor","path","RouterModule","register","assertRunnable","name","forRoot","global","imports","DiscoveryModule","useValue","forRootAsync","args","import_nestjs_agent_core","import_genui","import_common","AG_UI_VIA","invalid","code","message","BadRequestException","statusCode","warningEvents","warnings","map","type","name","AG_UI_CUSTOM","warning","value","AgUiRunHandler","agent","actorResolver","options","staging","quietMs","a2ui","undefined","handle","req","res","body","input","parseRunInput","forwarded","readForwardedProps","forwardedProps","actor","resolve","Array","isArray","tools","length","push","quiet","resume","plan","planResume","id","unrecognised","first","decisions","every","d","address","kind","decided","decideProposals","writeEvents","flatMap","outcome","index","actionProposalDecisionEvents","threadId","runId","text","proposalDecision","streamRunId","stream","assertResumable","settle","pipe","skip","position","answered","decision","toolCallId","a2uiFor","preamble","action","uiAction","turn","uiActionText","media","staged","dropped","readUserTurn","messages","NO_USER_MESSAGE_CODE","owner","threadOwner","ForbiddenException","regenerate","handleTextDecision","refs","stage","trim","context","readContext","pageContext","agUiContext","started","chat","newThreadId","agentName","persona","personaId","model","uiCapabilities","attachments","streamThreadId","limits","attachmentLimits","ref","label","mediaId","maxPerMessage","item","filename","allowedContentTypes","includes","contentType","data","maxBytes","sizeBytes","deliveries","proposals","filter","entry","abandoned","status","checkDecision","approved","readApprovalPayload","payload","reason","rejectReason","approve","via","remember","reject","checkAnswer","read","readAnswersPayload","answers","boundedAnswers","answer","deliver","planned","proposalId","outcomes","decideActionProposal","events","setHeader","flushHeaders","event","write","agUiSse","end","negotiateA2uiCatalog","readAgUiA2uiCatalogIds","A2UI_LEGACY_BASIC_CATALOG_ID","terminal","cursor","seq","frames","agUiFramesFromNdjson","subscribe","agUiEvents","agUiAdapter","path","replace","AgUiController","moduleOptions","catalog","withCatalog","run","controllers","import_nestjs_agent_core","import_a2ui","import_ag_ui","import_genui","import_common","A2UI_VIA","isRecord","value","Array","isArray","invalid","code","message","BadRequestException","statusCode","bodyField","body","key","undefined","metadata","readDataModel","raw","maxBytes","surfaces","size","TextEncoder","encode","JSON","stringify","length","Object","keys","A2uiRunHandler","agent","actorResolver","projection","quietMs","maxActionBytes","maxDataModelBytes","replay","req","threadId","catalog","actor","resolve","owner","threadOwner","entries","thread","getThread","supported","filter","id","a2uiThreadReplay","messages","negotiateA2uiCatalog","handle","res","agentName","readA2uiClientCapabilities","dataModel","action","read","readA2uiAction","name","A2UI_APPROVE_ACTION","A2UI_REJECT_ACTION","interruptId","context","address","decodeInterruptId","kind","proposalId","decided","decideActionProposal","decision","via","writeHead","projector","A2uiProjector","messageId","event","type","role","delta","text","project","write","end","assertResumable","stream","checkDecision","toolCallId","approve","reject","skip","position","answered","uiActionText","trim","ForbiddenException","uiCapabilities","hasOwn","validateUiCapabilities","error","started","chat","newThreadId","pageContext","a2uiDataModel","runId","extra","status","setHeader","flushHeaders","options","frames","agUiFramesFromNdjson","subscribe","agUiEvents","streamRunId","streamThreadId","a2uiAdapter","path","replace","_path","A2uiController","run","controllers","import_common","readHeader","req","name","undefined","headers","value","Reflect","get","HeaderActorResolver","resolve","id","length","UnauthorizedException","roles","split","map","role","trim","filter","tenantRef","import_common","field","user","names","name","value","undefined","defaultRequestUserMapper","id","UnauthorizedException","rawRoles","roles","Array","isArray","map","String","tenant","tenantRef","requestUserActorResolver","resolve","req"]}
|
|
1
|
+
{"version":3,"sources":["../src/vite/index.ts","../src/genui/kit.ts","../src/index.ts","../src/agent.module.ts","../src/agent-deps.factory.ts","../src/genui/agent-genui.module.ts","../src/functional-tool.ts","../src/genui/agent-genui.token.ts","../src/agent-service.token.ts","../src/agent.service.ts","../src/agent-deps.ts","../src/attachment-limits.ts","../src/proposals/action-proposal.service.ts","../src/queue/chat-queue.service.ts","../src/quota-exceeded.ts","../src/thread-persona.ts","../src/run-not-active.exception.ts","../src/approval-port.adapter.ts","../src/controller/agents.controller.ts","../src/controller/attachments.controller.ts","../src/controller/chat.controller.ts","../src/controller/config.controller.ts","../src/resolver/anonymous-actor-resolver.ts","../src/controller/memories.controller.ts","../src/controller/messages.controller.ts","../src/controller/models.controller.ts","../src/controller/queue.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/discovery/skill-discovery.service.ts","../src/decorator/skill.decorator.ts","../src/in-process-sink.ts","../src/ledger-quota-provider.ts","../src/pricing-boot.service.ts","../src/proposals/action-proposal-worker.service.ts","../src/proposals/action-proposal.controller.ts","../src/queue/chat-queue.token.ts","../src/runner/inline-agent-runner.ts","../src/skills-config.ts","../src/ag-ui/ag-ui.adapter.ts","../src/a2ui/a2ui.adapter.ts","../src/resolver/header-actor-resolver.ts","../src/resolver/request-user-actor-resolver.ts"],"sourcesContent":["/**\n * `@dudousxd/nestjs-agent/vite` — `genuiSandboxKit()`, the Vite plugin that puts the app's design\n * system (its styles, its components, its providers) inside the sandbox, whatever the stack:\n *\n * ```ts\n * // vite.config.ts (the SPA that talks to the agent)\n * import { genuiSandboxKit } from '@dudousxd/nestjs-agent/vite'\n * export default defineConfig({\n * plugins: [react(), genuiSandboxKit({ styles: 'src/index.css', components: 'src/components/ui' })],\n * })\n * ```\n *\n * Then `AgentGenuiModule.forRoot({ sandbox: { kit: true } })` finds what it built: the descriptor\n * the dev server writes (`.genui/sandbox-kit.json`) in dev, the Vite manifest in production (see\n * `AgentGenuiOptions.sandboxKit`).\n */\nimport {\n type GenuiSandboxKitApi,\n type GenuiSandboxKitOptions,\n type GenuiSandboxKitPlugin,\n SANDBOX_KIT_DEV_PREFIX,\n SANDBOX_KIT_MANIFEST_KEYS,\n SANDBOX_KIT_UPDATE_EVENT,\n createGenuiSandboxKitPlugin,\n} from '@dudousxd/nestjs-agent-core/genui/kit';\n\n/**\n * Where the dev descriptor is written, relative to the Vite root — and where the server reads it,\n * relative to its working directory (run both from the project root, or point\n * `sandboxKit.descriptor` at it). Add `.genui/` to `.gitignore`.\n */\nexport const NEST_SANDBOX_KIT_DESCRIPTOR = '.genui/sandbox-kit.json';\n\n/**\n * The sandbox kit plugin: `styles` (the app's style entries — default, the stylesheets among its\n * Vite entrypoints or `index.html`), `components` (modules or globs exporting React components —\n * default, the first `components/ui` folder), `wrapper` (a module whose default export wraps the\n * model's App). See {@link GenuiSandboxKitOptions}.\n */\nexport function genuiSandboxKit(options: GenuiSandboxKitOptions = {}): GenuiSandboxKitPlugin {\n return createGenuiSandboxKitPlugin(options, {\n descriptor: NEST_SANDBOX_KIT_DESCRIPTOR,\n rendererImport: /@dudousxd\\/nestjs-agent-react/,\n });\n}\n\nexport {\n type GenuiSandboxKitApi,\n type GenuiSandboxKitOptions,\n type GenuiSandboxKitPlugin,\n SANDBOX_KIT_DEV_PREFIX,\n SANDBOX_KIT_MANIFEST_KEYS,\n SANDBOX_KIT_UPDATE_EVENT,\n};\n","/**\n * The sandbox kit in a Nest app. No Vite runs in the Nest process, so the kit is found in files:\n * the descriptor `genuiSandboxKit()` (`@dudousxd/nestjs-agent/vite`) writes while the dev server\n * runs, and in production the Vite manifest the build wrote (`genui-sandbox-kit.json` and the assets\n * it names). Node-only: loaded by {@link AgentGenuiModule} only when a sandbox is configured.\n */\nimport { resolve } from 'node:path';\nimport {\n type SandboxKitDiscovery,\n sandboxKitDescriptorPath,\n sandboxKitDiscovery,\n} from '@dudousxd/nestjs-agent-core/genui/kit';\nimport { NEST_SANDBOX_KIT_DESCRIPTOR } from '../vite/index.js';\nimport type { AgentGenuiSandboxKitOptions } from './agent-genui.module.js';\n\n/** Where the production Vite manifest is looked for by default, and the directory it is relative to. */\nexport const NEST_SANDBOX_KIT_MANIFEST = Object.freeze({\n file: 'public/.vite/manifest.json',\n outDir: 'public',\n});\n\n/**\n * Find the kit for `AgentGenuiModule.forRoot({ sandbox: { kit: true } })` — a named kit's\n * (`genuiSandboxKit({ name })`, `sandbox: { kit: true, kitName }`) with `name`.\n */\nexport function nestSandboxKitDiscovery(\n options: AgentGenuiSandboxKitOptions = {},\n name?: string,\n): SandboxKitDiscovery {\n const manifest = options.manifest ?? NEST_SANDBOX_KIT_MANIFEST;\n return sandboxKitDiscovery({\n root: resolve(options.root ?? process.cwd()),\n ...(name !== undefined ? { name } : {}),\n descriptor: sandboxKitDescriptorPath(options.descriptor ?? NEST_SANDBOX_KIT_DESCRIPTOR, name),\n ...(manifest !== false ? { manifest: { file: manifest.file, outDir: manifest.outDir } } : {}),\n ...(options.kitUrl !== undefined ? { kitUrl: options.kitUrl } : {}),\n ...(options.cssUrl !== undefined ? { cssUrl: options.cssUrl } : {}),\n ...(options.tailwindUrl !== undefined ? { tailwindUrl: options.tailwindUrl } : {}),\n ...(options.production !== undefined ? { production: options.production } : {}),\n });\n}\n","export { AgentModule } from './agent.module.js';\nexport { type AgUiAdapterOptions, AgUiRunHandler, agUiAdapter } from './ag-ui/index.js';\nexport { type A2uiAdapterOptions, A2uiRunHandler, a2uiAdapter } from './a2ui/a2ui.adapter.js';\nexport type { AgentProtocolAdapter } from './protocol-adapter.js';\nexport type { AgentEngine } from './engine.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 NO_USER_MESSAGE_CODE,\n type ChatParams,\n type ChatSendMode,\n type ChatSendResult,\n type QueuedSend,\n type ThreadDefaultAgentReader,\n type ThreadModelReader,\n} from './agent.service.js';\nexport { type ThreadPersonaReader, threadPersona } from './thread-persona.js';\nexport {\n AttachmentsController,\n ATTACHMENT_PAGE_SIZE,\n} from './controller/attachments.controller.js';\nexport {\n type AttachmentLimits,\n attachmentLimits,\n DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,\n DEFAULT_MAX_ATTACHMENT_BYTES,\n MAX_ATTACHMENTS_PER_MESSAGE,\n} from './attachment-limits.js';\nexport { ConfigController } from './controller/config.controller.js';\nexport {\n AiTool,\n type AiToolOptions,\n AI_TOOL_METADATA,\n readAiToolMetadata,\n type ResolvedAiToolOptions,\n toolNameFromClass,\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 { MessagesController } from './controller/messages.controller.js';\nexport { ModelsController } from './controller/models.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 defineTool,\n type FunctionalToolDefinition,\n provideAgentTool,\n provideAgentTools,\n AGENT_TOOL_BRAND,\n type FunctionalTool,\n} from './functional-tool.js';\nexport { InlineAgentRunner } from './runner/inline-agent-runner.js';\nexport { QueueController } from './controller/queue.controller.js';\nexport {\n ChatQueueService,\n type QueuePlan,\n type QueueSettleOutcome,\n type QueuedTurn,\n type QueuedTurnStarter,\n} from './queue/chat-queue.service.js';\nexport { AGENT_CHAT_QUEUE } from './queue/chat-queue.token.js';\nexport { AGENT_SERVICE } from './agent-service.token.js';\nexport { InProcessTokenStreamSink } from './in-process-sink.js';\nexport {\n LedgerQuotaProvider,\n type QuotaLimits,\n type QuotaWindowLimits,\n} from './ledger-quota-provider.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';\nexport {\n AnonymousActorResolver,\n type AnonymousActorOptions,\n} from './resolver/anonymous-actor-resolver.js';\nexport {\n defaultRequestUserMapper,\n requestUserActorResolver,\n type RequestUserMapper,\n} from './resolver/request-user-actor-resolver.js';\n\n// Re-export the core surface so consumers import tools/types from one place.\nexport * from '@dudousxd/nestjs-agent-core';\nexport { RunNotActiveException } from './run-not-active.exception.js';\nexport { ActionProposalService } from './proposals/action-proposal.service.js';\nexport { ActionProposalController } from './proposals/action-proposal.controller.js';\nexport {\n type ActionProposalSettledListener,\n ActionProposalWorkerService,\n} from './proposals/action-proposal-worker.service.js';\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_MODEL_CATALOG,\n AGENT_OPTIONS,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_QUOTA_PROVIDER,\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 ClosedRolesPolicy,\n DefaultRolesPolicy,\n InMemoryAgentStore,\n type ModelCatalog,\n type ModelProvider,\n type QuotaProvider,\n type RolesPolicy,\n ToolRegistry,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n type CanActivate,\n type DynamicModule,\n Global,\n Logger,\n Module,\n type Provider,\n type Type,\n} from '@nestjs/common';\nimport { DiscoveryModule, ModulesContainer, RouterModule } from '@nestjs/core';\nimport { AgentDepsFactory } from './agent-deps.factory.js';\nimport { AGENT_SERVICE } from './agent-service.token.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 { ConfigController } from './controller/config.controller.js';\nimport { MemoriesController } from './controller/memories.controller.js';\nimport { MessagesController } from './controller/messages.controller.js';\nimport { ModelsController } from './controller/models.controller.js';\nimport { QueueController } from './controller/queue.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 type { AgentEngine } from './engine.js';\nimport { InProcessTokenStreamSink } from './in-process-sink.js';\nimport { LedgerQuotaProvider } from './ledger-quota-provider.js';\nimport { PricingBootService } from './pricing-boot.service.js';\nimport { ActionProposalWorkerService } from './proposals/action-proposal-worker.service.js';\nimport { ActionProposalController } from './proposals/action-proposal.controller.js';\nimport { ActionProposalService } from './proposals/action-proposal.service.js';\nimport type { AgentProtocolAdapter } from './protocol-adapter.js';\nimport { ChatQueueService } from './queue/chat-queue.service.js';\nimport { AGENT_CHAT_QUEUE } from './queue/chat-queue.token.js';\nimport { AnonymousActorResolver } from './resolver/anonymous-actor-resolver.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\nconst logger = new Logger('AgentModule');\n\n/**\n * `AGENT_STORE` as some OTHER module binds it — a store module (`MikroOrmAgentStoreModule`,\n * `DrizzleAgentStoreModule`, a host's own), found by scanning the container. Scanning sees every\n * module's providers before any is instantiated, so the answer is complete whatever the import\n * order; the instance itself is read lazily, at first use.\n */\nfunction externalWrapper(\n modules: ModulesContainer,\n token: symbol,\n): { instance: unknown } | undefined {\n for (const module of modules.values()) {\n if (module.metatype === AgentModule) continue;\n const wrapper = module.providers.get(token);\n if (wrapper !== undefined) return wrapper as { instance: unknown };\n }\n return undefined;\n}\n\n/** A store that forwards to another module's `AGENT_STORE`, resolved on first use. */\nfunction forwardingStore(wrapper: { instance: unknown }): AgentStore {\n const target = (): Record<PropertyKey, unknown> => {\n const instance = wrapper.instance;\n if (instance === undefined || instance === null) {\n throw new Error('AgentModule: the AGENT_STORE bound by another module is not ready yet');\n }\n return instance as Record<PropertyKey, unknown>;\n };\n return new Proxy({} as AgentStore, {\n get(_, property) {\n const store = target();\n const value = store[property];\n return typeof value === 'function' ? value.bind(store) : value;\n },\n has(_, property) {\n return property in target();\n },\n });\n}\n\n/**\n * The store: the `store` option, else one another module binds, else the in-memory default — which\n * is loud about not being for production.\n */\nfunction resolveStore(options: AgentModuleOptions, modules: ModulesContainer): AgentStore {\n if (options.store !== undefined) return options.store;\n const external = externalWrapper(modules, AGENT_STORE);\n if (external !== undefined) return forwardingStore(external);\n logger.warn(\n 'No `store` configured and no store module imported — using the in-memory store. Threads are ' +\n 'lost on restart and not shared between processes: not for production. Pass `store`, or ' +\n 'import a store module (e.g. MikroOrmAgentStoreModule.forFeature()).',\n );\n return new InMemoryAgentStore();\n}\n\n/**\n * The roles policy: the `rolesPolicy` option, else one another module binds (`AgentAuthzModule`, a\n * host's own), else the role-based default. The same scan as the store, for the same reason: Nest\n * resolves a module's own provider before a global one, so a policy bound elsewhere under\n * `AGENT_ROLES_POLICY` would otherwise never reach the agent — and the role-based default, which\n * has no notion of abilities, would silently stand in for it.\n */\nfunction resolveRolesPolicy(options: AgentModuleOptions, modules: ModulesContainer): RolesPolicy {\n const external = externalWrapper(modules, AGENT_ROLES_POLICY);\n if (options.rolesPolicy !== undefined) {\n if (external !== undefined) {\n logger.warn(\n 'Both a `rolesPolicy` option and a module binding AGENT_ROLES_POLICY (e.g. ' +\n 'AgentAuthzModule) are configured — the `rolesPolicy` option wins.',\n );\n }\n return options.rolesPolicy;\n }\n if (external !== undefined) return forwardingPolicy(external);\n return options.emptyRoles === 'deny'\n ? new ClosedRolesPolicy(options.defaultRoles)\n : new DefaultRolesPolicy(options.defaultRoles);\n}\n\n/** A policy that forwards to another module's `AGENT_ROLES_POLICY`, resolved on first use. */\nfunction forwardingPolicy(wrapper: { instance: unknown }): RolesPolicy {\n return {\n can(actor, tool) {\n const policy = wrapper.instance as RolesPolicy | undefined | null;\n if (policy === undefined || policy === null) {\n throw new Error(\n 'AgentModule: the AGENT_ROLES_POLICY bound by another module is not ready yet',\n );\n }\n return policy.can(actor, tool);\n },\n };\n}\n\nfunction isQuotaProvider(quota: AgentModuleOptions['quota']): quota is QuotaProvider {\n return quota !== undefined && typeof (quota as QuotaProvider).report === 'function';\n}\n\n/** The model catalog: the `models` option, else the one the model provider carries (`aiSdkModels`). */\nfunction resolveCatalog(options: AgentModuleOptions): ModelCatalog | undefined {\n if (options.models !== undefined) return options.models;\n const carried = (options.model as (ModelProvider & { catalog?: ModelCatalog }) | undefined)\n ?.catalog;\n return carried !== undefined && typeof carried.list === 'function' ? carried : undefined;\n}\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, engine: AgentEngine | undefined): 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, modules: ModulesContainer) =>\n resolveRolesPolicy(options, modules),\n inject: [AGENT_OPTIONS, ModulesContainer],\n },\n {\n provide: AGENT_ACTOR_RESOLVER,\n useFactory: (options: AgentModuleOptions) => {\n if (options.actorResolver !== undefined) return options.actorResolver;\n logger.warn(\n 'No `actorResolver` configured — the agent endpoints are PUBLIC: every browser gets its ' +\n 'own anonymous identity (an HttpOnly cookie). Set `actorResolver: ' +\n 'requestUserActorResolver()` (or your own) to require login.',\n );\n return new AnonymousActorResolver();\n },\n inject: [AGENT_OPTIONS],\n },\n {\n provide: AGENT_MODEL,\n useFactory: (o: AgentModuleOptions) => o.model,\n inject: [AGENT_OPTIONS],\n },\n {\n // `quota` is either a provider of the host's own or ceilings for the built-in ledger one;\n // omitted, the ledger provider still reports usage, with no ceiling to block on.\n provide: AGENT_QUOTA_PROVIDER,\n useFactory: (o: AgentModuleOptions, store: AgentStore) =>\n isQuotaProvider(o.quota)\n ? o.quota\n : new LedgerQuotaProvider(store, o.quota?.limits, {\n ...(o.quota?.warnAt !== undefined ? { warnAt: o.quota.warnAt } : {}),\n ...(o.quota?.countEstimatedCost !== undefined\n ? { countEstimatedCost: o.quota.countEstimatedCost }\n : {}),\n }),\n inject: [AGENT_OPTIONS, AGENT_STORE],\n },\n {\n provide: AGENT_MODEL_CATALOG,\n useFactory: (o: AgentModuleOptions) => resolveCatalog(o),\n inject: [AGENT_OPTIONS],\n },\n AgentDepsFactory,\n { provide: AGENT_DEPS_FACTORY, useExisting: AgentDepsFactory },\n // Seeds a configured model's missing price row from models.dev and warns about one that would\n // record no cost (`priceCatalog`), once the app has bootstrapped.\n PricingBootService,\n // Populates the registry + contributors (onModuleInit) BEFORE AiToolDiscoveryService synthesizes\n // handoff tools (onApplicationBootstrap) reads the registry.\n AgentDiscoveryService,\n AiToolDiscoveryService,\n SkillDiscoveryService,\n // The thread message queue — every surface, since both runners and the durable workflow settle\n // into it, and the chat routes enqueue into it.\n ChatQueueService,\n { provide: AGENT_CHAT_QUEUE, useExisting: ChatQueueService },\n InlineAgentRunner,\n AgentService,\n { provide: AGENT_SERVICE, useExisting: AgentService },\n ActionProposalService,\n ActionProposalWorkerService,\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 providers.push({\n provide: AGENT_STORE,\n useFactory: (o: AgentModuleOptions, modules: ModulesContainer) => resolveStore(o, modules),\n inject: [AGENT_OPTIONS, ModulesContainer],\n });\n if (engine !== undefined) {\n // The engine runs the turns; its providers bring the runner AGENT_RUNNER points at.\n providers.push(...engine.providers, { provide: AGENT_RUNNER, useExisting: engine.runner });\n } else 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/** The module's public tokens. */\nfunction exportsFor(engine?: AgentEngine): NonNullable<DynamicModule['exports']> {\n return [\n ...(engine?.exports ?? []),\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 AGENT_STORE,\n AGENT_MODEL_CATALOG,\n AGENT_QUOTA_PROVIDER,\n AGENT_PROMPT_CONTRIBUTORS,\n AGENT_SKILLS,\n AGENT_MEMORY,\n AGENT_DEPS_FACTORY,\n AgentDepsFactory,\n AgentService,\n AGENT_SERVICE,\n ActionProposalService,\n ActionProposalWorkerService,\n ChatQueueService,\n AGENT_CHAT_QUEUE,\n InlineAgentRunner,\n AGENT_APPROVAL_PORT,\n ];\n}\n\nconst BASE_CONTROLLERS = [\n ActionProposalController,\n ChatController,\n QueueController,\n ThreadsController,\n ToolCallController,\n QuotaController,\n AgentsController,\n SkillsController,\n MemoriesController,\n ToolsController,\n MessagesController,\n ModelsController,\n ConfigController,\n AttachmentsController,\n];\n\n/** The controllers the configured protocol adapters contribute. */\nfunction adapterControllers(adapters: AgentProtocolAdapter[] | undefined): Type<object>[] {\n return (adapters ?? []).flatMap((adapter) => adapter.controllers);\n}\n\n/** The providers the configured protocol adapters contribute. */\nfunction adapterProviders(adapters: AgentProtocolAdapter[] | undefined): Provider[] {\n return (adapters ?? []).flatMap((adapter) => adapter.providers ?? []);\n}\n\n/**\n * `surface: 'engine'` mounts NO controllers — a worker pod never receives HTTP traffic. Otherwise\n * the native ones, whatever the protocol adapters contribute, and the engine's own.\n */\nfunction controllersForSurface(\n surface: AgentSurface | undefined,\n adapters: AgentProtocolAdapter[] | undefined,\n engine?: AgentEngine,\n): Type<object>[] {\n return surface === 'engine'\n ? []\n : [...BASE_CONTROLLERS, ...adapterControllers(adapters), ...(engine?.controllers ?? [])];\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(\n guards: Type<CanActivate>[] | undefined,\n adapters: AgentProtocolAdapter[] | undefined,\n): void {\n const resolved = guards ?? [];\n for (const controller of [...BASE_CONTROLLERS, ...adapterControllers(adapters)]) {\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/**\n * Refuse a wiring that cannot run a turn, at boot rather than on the first message: no `model` and\n * no `engine` leaves the loop nothing to call, and `durable` names the loop's own durable runner,\n * which an engine replaces (an engine that wants durability brings it).\n */\nfunction assertRunnable(options: Pick<AgentModuleOptions, 'model' | 'engine' | 'durable'>): void {\n if (options.engine !== undefined && options.durable === true) {\n throw new Error(\n `AgentModule: \\`durable: true\\` runs turns on the library's loop, but the \\`${options.engine.name}\\` engine runs them instead. Drop \\`durable\\` (the engine decides how its turns survive a restart).`,\n );\n }\n if (options.engine === undefined && options.model === undefined) {\n throw new Error(\n 'AgentModule: set `model` (the loop runs the turns) or `engine` (something else does).',\n );\n }\n}\n\n@Global()\n@Module({})\nexport class AgentModule {\n static forRoot(options: AgentModuleOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n assertRunnable(options);\n applyGuards(options.guards, options.adapters);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path)],\n controllers: controllersForSurface(options.surface, options.adapters, options.engine),\n providers: [\n { provide: AGENT_OPTIONS, useValue: options },\n ...sharedProviders(options.durable ?? false, options.engine),\n ...guardProviders(options.guards),\n ...adapterProviders(options.adapters),\n ],\n exports: exportsFor(options.engine),\n };\n }\n\n static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule {\n const path = options.path ?? DEFAULT_PATH;\n if (options.engine !== undefined) {\n assertRunnable({ engine: options.engine, durable: options.durable ?? false });\n }\n applyGuards(options.guards, options.adapters);\n return {\n module: AgentModule,\n global: true,\n imports: [DiscoveryModule, routerFor(path), ...(options.imports ?? [])],\n controllers: controllersForSurface(options.surface, options.adapters, options.engine),\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 const resolved: AgentModuleOptions = {\n ...(await options.useFactory(...args)),\n durable: options.durable ?? false,\n surface: options.surface ?? 'both',\n ...(options.engine !== undefined ? { engine: options.engine } : {}),\n };\n assertRunnable(resolved);\n return resolved;\n },\n inject: options.inject ?? [],\n },\n ...sharedProviders(options.durable ?? false, options.engine),\n ...guardProviders(options.guards),\n ...adapterProviders(options.adapters),\n ],\n exports: exportsFor(options.engine),\n };\n }\n}\n","import {\n type ActionProposal,\n type Actor,\n type ToolUiChannelGuide,\n assertIndependentActionCapabilities,\n createToolUiChannelGuide,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n AGENT_MEMORY,\n AGENT_MODEL,\n AGENT_PRICING_STORE,\n AGENT_PROMPT_CONTRIBUTORS,\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 Persona,\n type PersonaCatalogEntry,\n type PromptBuilder,\n type PromptContext,\n type PromptContributor,\n type RolesPolicy,\n type SkillsConfig,\n type TokenStreamSink,\n ToolRegistry,\n findPersona,\n intersectAllowLists,\n normalizeDelegation,\n personaCatalogEntry,\n resolvePersonaAlias,\n summarizeWithModel,\n windowHistory,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_OPTIONS } from '@dudousxd/nestjs-agent-core';\nimport type { Catalog } from '@dudousxd/nestjs-agent-core/genui';\nimport { BadRequestException, Inject, Injectable, Optional } from '@nestjs/common';\nimport type { AgentDeps } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\nimport {\n AGENT_GENUI,\n type AgentGenui,\n GENUI_CATALOG,\n GenuiCatalogResolver,\n} from './genui/agent-genui.module.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 // Optional: AGENT_PRICING_STORE has no local provider in this module — it's bound externally\n // (e.g. by a store module), so a 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 @Optional() @Inject(GENUI_CATALOG) private readonly uiCatalog?: Catalog,\n @Optional() private readonly uiCatalogResolver?: GenuiCatalogResolver,\n @Optional() @Inject(AGENT_GENUI) private readonly genui?: AgentGenui,\n ) {\n if (options.actionApprovalMode === 'independent')\n assertIndependentActionCapabilities(store, options.backgroundActorResolver);\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 /**\n * The agent a name stands for: itself when it is a registered agent (or unknown — the bare\n * assistant), else the agent whose persona took the name over (`Persona.aliases`) and that persona.\n */\n resolveAgent(name: string): { agentName: string; persona?: string } {\n if (this.agents.has(name)) {\n return { agentName: name };\n }\n const alias = resolvePersonaAlias(this.agents.list(), name);\n return alias === undefined\n ? { agentName: name }\n : { agentName: alias.agent, persona: alias.persona };\n }\n\n /** `agentName`'s personas as a picker reads them. Empty when it declares none. */\n personaCatalog(agentName: string): PersonaCatalogEntry[] {\n return (this.agents.get(agentName)?.personas ?? []).map(personaCatalogEntry);\n }\n\n /** The persona `agentName` runs under when nothing names one. Undefined → none. */\n defaultPersona(agentName: string): string | undefined {\n return this.agents.get(agentName)?.defaultPersona;\n }\n\n /**\n * The persona a turn of `agentName` runs under, most specific first: the one the send names\n * (refused with `400 persona_not_found` when the agent does not declare it), else the thread's\n * pinned one when this agent declares it, else the agent's default. Undefined → none.\n */\n resolvePersona(args: {\n agentName: string;\n requested?: string;\n threadPersona?: string | null;\n }): string | undefined {\n const definition = this.agents.get(args.agentName);\n if (args.requested !== undefined) {\n if (findPersona(definition, args.requested) === undefined) {\n throw new BadRequestException({\n statusCode: 400,\n code: 'persona_not_found',\n message: `agent \"${args.agentName}\" has no persona \"${args.requested}\"`,\n });\n }\n return args.requested;\n }\n const pinned = args.threadPersona ?? undefined;\n if (pinned !== undefined && findPersona(definition, pinned) !== undefined) {\n return pinned;\n }\n return definition?.defaultPersona;\n }\n\n forProposal(proposal: ActionProposal, _actor: Actor): AgentDeps {\n const name = proposal.executionContext?.agentName;\n if (\n name !== undefined &&\n !this.agents.has(name) &&\n !(\n name === 'default' &&\n this.defaultAgentName() === 'default' &&\n this.agents.list().length === 0\n )\n )\n throw new Error(`Recorded agent ${name} no longer exists`);\n const deps = this.forAgent(name);\n const id = proposal.executionContext?.persona;\n if (id !== undefined) {\n const persona = deps.personas?.find((persona) => persona.id === id);\n if (!persona) throw new Error(`Recorded persona ${id} no longer exists`);\n return this.withPersona(deps, persona);\n }\n return deps;\n }\n /** The turn's UI catalog: the per-request resolver's, else the app's. */\n private readonly resolveUiCatalog = (\n scope: import('@dudousxd/nestjs-agent-core').ToolDescribeScope,\n ) => {\n const catalog =\n this.uiCatalogResolver?.resolve({\n ...scope,\n ...(scope.actor.tenantRef !== undefined ? { tenant: scope.actor.tenantRef } : {}),\n }) ?? this.uiCatalog;\n if (!catalog) throw new Error('UI catalog unavailable');\n return catalog;\n };\n\n #uiChannelGuide: ToolUiChannelGuide | null | undefined;\n /** genui `channels`: what the model is told per channel. Built once; `undefined` without channels. */\n private uiChannelGuide(): ToolUiChannelGuide | undefined {\n if (this.#uiChannelGuide === undefined) {\n const channels = this.genui?.channels;\n this.#uiChannelGuide =\n channels === undefined ||\n (this.uiCatalog === undefined && this.uiCatalogResolver === undefined)\n ? null\n : createToolUiChannelGuide({\n channels,\n base: this.genui?.base ?? {},\n resolveCatalog: this.resolveUiCatalog,\n });\n }\n return this.#uiChannelGuide ?? undefined;\n }\n\n forAgent(agentName?: string): AgentDeps {\n const name = agentName ?? this.defaultAgentName();\n if (agentName !== undefined && !this.agents.has(agentName)) {\n const alias = resolvePersonaAlias(this.agents.list(), agentName);\n const persona =\n alias === undefined ? undefined : findPersona(this.agents.get(alias.agent), alias.persona);\n if (alias !== undefined && persona !== undefined) {\n return this.withPersona(this.forAgent(alias.agent), persona);\n }\n }\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 const uiChannelGuide = this.uiChannelGuide();\n return {\n model: this.model,\n store: this.store,\n ...(this.options.actionApprovalMode !== undefined\n ? { actionApprovalMode: this.options.actionApprovalMode }\n : {}),\n sink: this.sink,\n rolesPolicy: this.rolesPolicy,\n ...(this.options.approvalPolicy !== undefined\n ? { approvalPolicy: this.options.approvalPolicy }\n : {}),\n registry: this.registry,\n ...(this.uiCatalog !== undefined || this.uiCatalogResolver !== undefined\n ? { resolveUiCatalog: this.resolveUiCatalog }\n : {}),\n ...(uiChannelGuide !== undefined ? { uiChannelGuide } : {}),\n promptContributors: this.promptContributors,\n systemPrompt:\n definition?.systemPrompt ?? this.options.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.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 ...(definition?.personas !== undefined ? { personas: definition.personas } : {}),\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 * A persona baked into an agent's deps — how a run journaled under an agent name that a persona\n * has since taken over (`Persona.aliases`) is served. That run names no persona of its own (it\n * predates them, and its input cannot change), so the persona applies the way the old agent's own\n * config did: as config, re-read on every replay, with no checkpoint of its own.\n */\n private withPersona(deps: AgentDeps, persona: Persona): AgentDeps {\n const base = deps.systemPrompt;\n const ref = { id: persona.id, label: persona.label };\n const resolve = async (prompt: string | PromptBuilder, ctx: PromptContext) =>\n typeof prompt === 'function' ? prompt(ctx) : prompt;\n const own = persona.systemPrompt;\n const systemPrompt: PromptBuilder = async (ctx) => {\n const scoped: PromptContext = { ...ctx, persona: ref };\n if (own === undefined) {\n return resolve(base, scoped);\n }\n const basePrompt = typeof own === 'function' ? await resolve(base, scoped) : undefined;\n return resolve(own, { ...scoped, ...(basePrompt !== undefined ? { basePrompt } : {}) });\n };\n const toolAllowList = intersectAllowLists(deps.toolAllowList, persona.allowedTools);\n return { ...deps, systemPrompt, ...(toolAllowList !== undefined ? { toolAllowList } : {}) };\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 type { ToolPresentation } from '@dudousxd/nestjs-agent-core';\nimport type {\n Catalog,\n GenuiAbility,\n GenuiCatalogScope,\n GenuiChannels,\n GenuiStreaming,\n GenuiTelemetryOptions,\n GenuiToolsOptions,\n SandboxClientConfig,\n TreeLimits,\n TreeSchemaMode,\n} from '@dudousxd/nestjs-agent-core/genui';\nimport {\n type DefineSandboxOptions,\n type SandboxDefinition,\n assertGenuiChannels,\n defineCatalog,\n defineSandbox,\n genuiTools,\n sandboxPolicyOf,\n} from '@dudousxd/nestjs-agent-core/genui';\nimport {\n type DynamicModule,\n type FactoryProvider,\n Inject,\n Module,\n type ModuleMetadata,\n type Provider,\n type Type,\n} from '@nestjs/common';\nimport { provideAgentTools } from '../functional-tool.js';\nimport { AGENT_GENUI, AgentGenui } from './agent-genui.token.js';\n\nexport { AGENT_GENUI, AgentGenui } from './agent-genui.token.js';\n\n/** The app's genui catalog — `@InjectGenuiCatalog()` it anywhere; `overrideProvider` it in tests. */\nexport const GENUI_CATALOG = Symbol.for('@dudousxd/nestjs-agent:genui-catalog');\n\n/** The resolved {@link AgentGenuiOptions} (without the resolver). */\nexport const GENUI_OPTIONS = Symbol.for('@dudousxd/nestjs-agent:genui-options');\n\n/** The sandbox and channels as boot resolved them (kit, Tailwind and theme found). Internal. */\nconst GENUI_RESOLVED = Symbol.for('@dudousxd/nestjs-agent:genui-resolved');\n\n/** Inject the app's genui catalog ({@link GENUI_CATALOG}). */\nexport const InjectGenuiCatalog = (): ParameterDecorator & PropertyDecorator =>\n Inject(GENUI_CATALOG);\n\n/**\n * Picks the catalog for ONE request — a tenant's own, versioned components. Consulted when a genui\n * call is validated and when the turn's tool list is described to the model, so components can\n * change without rebuilding tools at boot. Cache in here if resolving costs a round trip: it runs\n * once per turn per genui tool, and once per call.\n *\n * Provide it through `AgentGenuiModule.forRoot({ resolver })` (a class, resolved with DI, or an\n * instance); it is then injectable, and replaceable in a test with\n * `overrideProvider(GenuiCatalogResolver)`.\n */\nexport abstract class GenuiCatalogResolver {\n abstract resolve(scope: GenuiCatalogScope): Catalog | Promise<Catalog>;\n}\n\n/** What {@link AgentGenuiModule} builds tools from. */\nexport interface AgentGenuiOptions {\n /**\n * The catalog. With a {@link GenuiCatalogResolver} it is the boot-time one — it names the\n * per-component tools — and may be empty. Default: an empty catalog.\n */\n catalog?: Catalog;\n /**\n * `tree` (default): one `ui__render` tool taking a composed tree (a single node is pushed as that\n * component). `per-component`: one `ui__show_<snake>` tool per component.\n */\n mode?: 'per-component' | 'tree';\n /** `ui__render`'s input schema: `'strict'` (default, a `$defs` union per component) or `'loose'`. */\n treeSchema?: TreeSchemaMode;\n /**\n * Tree mode: `'complete'` (default) draws the tree once the call has run; `'partial'` streams it\n * as `partial` ui frames while the model writes it. A component's own `streaming` overrides it.\n */\n streaming?: GenuiStreaming;\n /** Least time between two partial tree frames of one call, in ms. Default 100. */\n streamingThrottleMs?: number;\n /** End the model's turn once a genui call succeeds (no narrating follow-up call). */\n terminal?: boolean;\n /** Tool name in `tree` mode. Default `ui__render`. */\n treeToolName?: string;\n /** Text prepended to the tree tool's description. */\n treeInstructions?: string;\n treeLimits?: TreeLimits;\n /**\n * Tree mode: components that ALSO get a flat tool whose input IS their props —\n * `componentTools: ['Sandbox']` adds `ui__sandbox`, so a model writing a big component on its own\n * has no `{ type, props }` envelope to leave out.\n */\n componentTools?: readonly string[];\n /** Tool-name prefix for `componentTools`. Default `ui__` (`Sandbox` → `ui__sandbox`). */\n componentToolPrefix?: string;\n /** Tool-name prefix in `per-component` mode. Default `ui__show_`. */\n namePrefix?: string;\n /**\n * Also register ONE generic tool taking `{ component, props }`, validated against the request's\n * catalog — how a model reaches a tenant's own components, which no boot-time tool names. `true`\n * names it `ui__show`.\n */\n showTool?: boolean | string;\n /** Text prepended to the show tool's description. */\n showInstructions?: string;\n /** Roles allowed to call the tools. Undefined → the roles policy default. */\n roles?: string[];\n /**\n * The authorization ability the UI tools declare (`ToolSpec.ability`), for an ability-aware\n * authorizer such as `authzToolAuthorizer`, which denies a tool with none. A string for every\n * tool; a map by tool name (`{ ui__render: 'genui.render', ui__sandbox: 'genui.sandbox' }`, a tool\n * left out declares none); or a function of `{ name, component }`. The authorizer decides.\n */\n ability?: GenuiAbility;\n /** Override the generated presentation per component (or per tree / show tool name). */\n presentation?: (component: string) => ToolPresentation | undefined;\n /**\n * Add the sandbox component (`Sandbox`): the model may write HTML, CSS and JS for a one-off\n * interactive answer when no catalog component fits. `true` for the defaults (no network), or\n * the {@link DefineSandboxOptions} (a policy listing origins, extra instructions). Off by default.\n * The browser's catalog should carry the same definition (`defineSandbox(...)` in the shared\n * catalog file) so the renderer enforces the same policy.\n *\n * `theme` (default on) and `kit` put the app's design system in the frame: `kit: true` turns on\n * whatever `genuiSandboxKit()` built (styles, Tailwind, components, wrapper, docs), found through\n * `sandboxKit`: the descriptor\n * `genuiSandboxKit()` (`@dudousxd/nestjs-agent/vite`) writes in dev, the Vite manifest in\n * production — and `GET <base>/config` tells the renderer where the assets are.\n */\n sandbox?: boolean | DefineSandboxOptions;\n /**\n * Per-channel generative UI: each entry sets the mode, streaming, sandbox and rendering of one\n * channel (`web`, `mobile`, `whatsapp`, `telegram`, `email`, or `default` for the rest), over the\n * top-level options. A text channel (`@dudousxd/nestjs-agent-channels`) configured here draws the\n * components natively (reply buttons, lists, images). Omitted → every channel is served by the\n * top-level options, as before.\n */\n channels?: GenuiChannels;\n /**\n * Where the sandbox kit is found (with `sandbox: { kit: true }` or the theme's names). No Vite\n * runs in the Nest process, so: the descriptor the dev plugin writes, or the production Vite\n * manifest — in production the manifest first, otherwise whichever was written last.\n */\n sandboxKit?: AgentGenuiSandboxKitOptions;\n /**\n * Generative-UI telemetry, recorded by the loop for every UI call (the dashboard's \"Generative UI\"\n * page): tool, channel, mode, attempt, validity, error category, tokens and cost, time to first and\n * complete frame. Metadata only by default — the generated HTML/JSX and props are NEVER stored\n * unless `samplePayloads: true` (debugging; keep it off where a view may show personal data).\n * `false` records nothing. Needs a store that records it (`recordGenuiCalls`).\n */\n telemetry?: GenuiTelemetryOptions | false;\n}\n\n/** {@link AgentGenuiOptions.sandboxKit}. Relative paths resolve against `root`. */\nexport interface AgentGenuiSandboxKitOptions {\n /** Default `process.cwd()`. */\n root?: string;\n /**\n * The dev descriptor `genuiSandboxKit()` writes. Default `.genui/sandbox-kit.json` — for a named\n * kit (`genuiSandboxKit({ name })`, picked with `kitName`), `.genui/sandbox-kit.<name>.json`.\n */\n descriptor?: string;\n /**\n * The production Vite manifest, and the directory its `file`s are relative to. Default\n * `{ file: 'public/.vite/manifest.json', outDir: 'public' }`; `false` → none.\n */\n manifest?: { file: string; outDir: string } | false;\n /** An explicit kit url (an SPA served from elsewhere), over what is found. */\n kitUrl?: string;\n /** An explicit url of the compiled styles, over what is found (the same SPA case). */\n cssUrl?: string;\n /** An explicit url of the Tailwind browser runtime, over what is found (the same SPA case). */\n tailwindUrl?: string;\n /** Read the manifest first (else the freshest of the two). Default: `NODE_ENV === 'production'`. */\n production?: boolean;\n}\n\ntype ResolverOption = Type<GenuiCatalogResolver> | GenuiCatalogResolver;\n\nexport interface AgentGenuiModuleOptions extends AgentGenuiOptions {\n /** Per-request catalogs. A class is instantiated with DI (its dependencies must be global or exported to the root). */\n resolver?: ResolverOption;\n}\n\nexport interface AgentGenuiModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {\n inject?: FactoryProvider['inject'];\n useFactory: (...deps: any[]) => AgentGenuiOptions | Promise<AgentGenuiOptions>;\n /** Per-request catalogs. A class resolves its dependencies from `imports`. */\n resolver?: ResolverOption;\n}\n\nfunction resolverProviders(resolver: ResolverOption | undefined): Provider[] {\n if (resolver === undefined) return [];\n return [\n typeof resolver === 'function'\n ? { provide: GenuiCatalogResolver, useClass: resolver }\n : { provide: GenuiCatalogResolver, useValue: resolver },\n ];\n}\n\n/** The sandbox and channels with the kit and theme names found ({@link GENUI_RESOLVED}). */\ninterface ResolvedGenui {\n sandbox?: boolean | DefineSandboxOptions;\n /** A kit sandbox the catalog itself defines, resolved (under its own name). */\n catalogSandbox?: DefineSandboxOptions;\n channels?: GenuiChannels;\n sandboxClient?: () => SandboxClientConfig;\n}\n\n/** What every configured sandbox (top level and channels) needs from the browser, together. */\nfunction mergeSandboxClients(clients: Array<() => SandboxClientConfig>): SandboxClientConfig {\n const merged: SandboxClientConfig = { theme: false };\n for (const client of clients) {\n const one = client();\n merged.theme ||= one.theme;\n if (one.name !== undefined && merged.kit === undefined && one.kit !== undefined)\n merged.name = one.name;\n if (one.kit !== undefined) merged.kit ??= one.kit;\n if (one.css !== undefined) merged.css ??= one.css;\n if (one.tailwind !== undefined) merged.tailwind ??= one.tailwind;\n }\n return merged;\n}\n\n/** Resolve the sandbox (top level and per channel) against the kit discovery. */\nasync function resolveGenui(options: AgentGenuiOptions): Promise<ResolvedGenui> {\n const { sandbox: asked, channels: askedChannels } = options;\n assertGenuiChannels(askedChannels);\n // A sandbox's kit (styles, components, wrapper) and theme names are found through the app's Vite output.\n const clients: Array<() => SandboxClientConfig> = [];\n const discoveries = new Map<\n string,\n import('@dudousxd/nestjs-agent-core/genui/kit').SandboxKitDiscovery\n >();\n const resolveSandbox = async (\n value: boolean | DefineSandboxOptions | undefined,\n ): Promise<boolean | DefineSandboxOptions | undefined> => {\n if (value === undefined || value === false) return value;\n // Node-only, and only with a sandbox: loaded when one is configured.\n const [{ nestSandboxKitDiscovery }, { resolveSandboxServer }] = await Promise.all([\n import('./kit.js'),\n import('@dudousxd/nestjs-agent-core/genui/kit'),\n ]);\n const kitName = value === true ? undefined : value.kitName;\n let discovery = discoveries.get(kitName ?? '');\n if (discovery === undefined) {\n discovery = nestSandboxKitDiscovery(options.sandboxKit, kitName);\n discoveries.set(kitName ?? '', discovery);\n }\n const resolved = resolveSandboxServer(value, discovery);\n clients.push(resolved.client);\n return resolved.define;\n };\n const sandbox = await resolveSandbox(asked);\n // A kit sandbox defined in the (shared) catalog itself: found the same way, and put\n // back under its own name, so the browser's copy of the catalog validates what the model writes.\n const own = options.catalog?.components.find((each) => sandboxPolicyOf(each) !== undefined) as\n | SandboxDefinition\n | undefined;\n const ownOptions =\n asked === undefined && own?.sandboxOptions !== undefined && own.sandboxView?.kit === true\n ? await resolveSandbox({ ...own.sandboxOptions, name: own.name })\n : undefined;\n let channels: GenuiChannels | undefined;\n if (askedChannels !== undefined) {\n channels = {};\n for (const [name, entry] of Object.entries(askedChannels)) {\n if (entry === undefined) continue;\n const own = await resolveSandbox(entry.sandbox);\n channels[name] = { ...entry, ...(own !== undefined ? { sandbox: own } : {}) };\n }\n }\n return {\n ...(sandbox !== undefined ? { sandbox } : {}),\n ...(typeof ownOptions === 'object' ? { catalogSandbox: ownOptions } : {}),\n ...(channels !== undefined ? { channels } : {}),\n ...(clients.length > 0 ? { sandboxClient: () => mergeSandboxClients(clients) } : {}),\n };\n}\n\nfunction perRequest(\n resolver: GenuiCatalogResolver | undefined,\n): GenuiToolsOptions['resolveCatalog'] | undefined {\n return resolver === undefined ? undefined : (scope: GenuiCatalogScope) => resolver.resolve(scope);\n}\n\nfunction toolOptions(\n options: AgentGenuiOptions,\n resolved: ResolvedGenui,\n resolver: GenuiCatalogResolver | undefined,\n): GenuiToolsOptions {\n const {\n catalog: _catalog,\n sandbox: _sandbox,\n channels: _channels,\n sandboxKit: _sandboxKit,\n ...rest\n } = options;\n const resolveCatalog = perRequest(resolver);\n return {\n ...rest,\n ...(resolved.channels !== undefined ? { channels: resolved.channels } : {}),\n ...(resolved.sandbox !== undefined ? { sandbox: resolved.sandbox } : {}),\n ...(resolveCatalog !== undefined ? { resolveCatalog } : {}),\n };\n}\n\n/** The configured catalog, with the sandbox component added when `sandbox` asks for it. */\nfunction withSandbox(options: AgentGenuiOptions, resolved: ResolvedGenui): Catalog {\n const base = options.catalog ?? defineCatalog([]);\n const { sandbox, catalogSandbox } = resolved;\n if (sandbox === undefined || sandbox === false)\n return catalogSandbox !== undefined ? base.extend([defineSandbox(catalogSandbox)]) : base;\n return base.extend([defineSandbox(sandbox === true ? {} : sandbox)]);\n}\n\nfunction coreProviders(resolver: ResolverOption | undefined): Provider[] {\n return [\n {\n provide: GENUI_RESOLVED,\n useFactory: (options: AgentGenuiOptions) => resolveGenui(options),\n inject: [GENUI_OPTIONS],\n },\n {\n provide: GENUI_CATALOG,\n useFactory: (options: AgentGenuiOptions, resolved: ResolvedGenui) =>\n withSandbox(options, resolved),\n inject: [GENUI_OPTIONS, GENUI_RESOLVED],\n },\n {\n provide: AGENT_GENUI,\n useFactory: (\n options: AgentGenuiOptions,\n catalog: Catalog,\n resolved: ResolvedGenui,\n resolverInstance?: GenuiCatalogResolver,\n ) =>\n new AgentGenui(\n catalog,\n perRequest(resolverInstance),\n resolved.channels,\n {\n ...(options.mode !== undefined ? { mode: options.mode } : {}),\n ...(options.streaming !== undefined ? { streaming: options.streaming } : {}),\n ...(resolved.sandbox !== undefined ? { sandbox: resolved.sandbox } : {}),\n },\n resolved.sandboxClient,\n ),\n inject: [\n GENUI_OPTIONS,\n GENUI_CATALOG,\n GENUI_RESOLVED,\n { token: GenuiCatalogResolver, optional: true },\n ],\n },\n ...resolverProviders(resolver),\n // The generated tools, registered by the agent module's discovery like any `provideAgentTool`.\n // Built from the injected catalog, so `overrideProvider(GENUI_CATALOG)` changes them too.\n provideAgentTools(\n (\n options: AgentGenuiOptions,\n catalog: Catalog,\n resolved: ResolvedGenui,\n perRequestResolver?: GenuiCatalogResolver,\n ) => genuiTools(catalog, toolOptions(options, resolved, perRequestResolver)),\n [\n GENUI_OPTIONS,\n GENUI_CATALOG,\n GENUI_RESOLVED,\n { token: GenuiCatalogResolver, optional: true },\n ],\n ),\n ];\n}\n\nconst EXPORTS = [GENUI_CATALOG, GENUI_OPTIONS, AGENT_GENUI];\n\n/**\n * Generative UI for the agent: registers the tools that let the model push catalog components\n * (one `ui__render` tree tool, or `ui__show_<component>` per component, and/or the generic\n * `ui__show`), and makes the catalog\n * injectable. Global, like `AgentModule`; import it once, next to it.\n *\n * ```ts\n * AgentGenuiModule.forRoot({ catalog, mode: 'tree', terminal: true })\n * ```\n */\n@Module({})\nexport class AgentGenuiModule {\n static forRoot(options: AgentGenuiModuleOptions = {}): DynamicModule {\n const { resolver, ...rest } = options;\n return {\n module: AgentGenuiModule,\n global: true,\n providers: [{ provide: GENUI_OPTIONS, useValue: rest }, ...coreProviders(resolver)],\n exports: resolver === undefined ? EXPORTS : [...EXPORTS, GenuiCatalogResolver],\n };\n }\n\n static forRootAsync(options: AgentGenuiModuleAsyncOptions): DynamicModule {\n return {\n module: AgentGenuiModule,\n global: true,\n imports: options.imports ?? [],\n providers: [\n { provide: GENUI_OPTIONS, useFactory: options.useFactory, inject: options.inject ?? [] },\n ...coreProviders(options.resolver),\n ],\n exports: options.resolver === undefined ? EXPORTS : [...EXPORTS, GenuiCatalogResolver],\n };\n }\n}\n","import {\n type FunctionalToolDefinition,\n type ToolHandler,\n type ToolSpec,\n createFunctionalTool,\n} 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\n/**\n * Registers a LIST of functional tools from one factory — for a producer whose tool count is only\n * known once its dependencies resolve (a catalog loaded from config, one tool per entry). The\n * factory's result is branded element by element; `AiToolDiscoveryService` registers each.\n */\nexport function provideAgentTools(\n factory: (...deps: never[]) => readonly FunctionalTool[] | Promise<readonly FunctionalTool[]>,\n inject?: FactoryProvider['inject'],\n): Provider {\n return {\n provide: Symbol('nestjs-agent:functional-tool-list'),\n useFactory: async (...deps: never[]) => (await factory(...deps)).map(brand),\n inject: inject ?? [],\n };\n}\n\n/** Author a functional tool with inferred Standard Schema input and domain output. */\nexport const defineTool = createFunctionalTool;\nexport type { FunctionalToolDefinition };\n","import type {\n Catalog,\n GenuiCatalogScope,\n GenuiChannelBase,\n GenuiChannels,\n SandboxClientConfig,\n} from '@dudousxd/nestjs-agent-core/genui';\n\n/**\n * The app's genui setup ({@link AgentGenui}): the catalog, the per-channel options and what the\n * sandbox renderer is told — what the text channels (`@dudousxd/nestjs-agent-channels`) and\n * `GET <base>/config` read.\n */\nexport const AGENT_GENUI = Symbol.for('@dudousxd/nestjs-agent:genui');\n\n/**\n * The app's genui setup, bound to {@link AGENT_GENUI}: what a text channel draws with\n * (`catalog`, `channels`, `base`) and what the sandbox renderer is told (`sandboxClient`).\n */\nexport class AgentGenui {\n constructor(\n readonly catalog: Catalog,\n readonly resolveCatalog?: (scope: GenuiCatalogScope) => Catalog | Promise<Catalog>,\n /** `AgentGenuiModule.forRoot({ channels })`, when configured. */\n readonly channels?: GenuiChannels,\n /** The top-level options a channel falls back to. */\n readonly base: GenuiChannelBase = {},\n /** What the sandbox renderer is told, when a sandbox is configured. */\n readonly sandboxClient?: () => SandboxClientConfig,\n ) {}\n}\n","/**\n * `AgentService`, as the controllers of a secondary entry (`@dudousxd/nestjs-agent/a2ui`) ask for it.\n *\n * A token rather than the class: every entry is its own bundle with its own copy of every class it\n * imports, so the class used as an injection token there is not the one `AgentModule` provides.\n * `Symbol.for` is the same value in every bundle.\n */\nexport const AGENT_SERVICE = Symbol.for('@dudousxd/nestjs-agent:agent-service');\n","import {\n AGENT_ATTACHMENT_STAGING,\n AGENT_DEPS_FACTORY,\n AGENT_MODEL_CATALOG,\n AGENT_OPTIONS,\n AGENT_QUOTA_PROVIDER,\n AGENT_RUNNER,\n AGENT_STORE,\n type ActionApprovalMode,\n type ActionProposalMutationView,\n type ActionProposalView,\n type Actor,\n type AgentHostContext,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type AttachmentRef,\n type AttachmentStagingStore,\n type ChatQueueState,\n DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY,\n type Decision,\n type ElicitationReply,\n type HumanReply,\n type ListStagedAttachmentsInput,\n type MessageAttachment,\n type MessageFeedback,\n type MessageFeedbackValue,\n type ModelCatalog,\n type ModelCatalogView,\n type PageContext,\n type QuotaProvider,\n type QuotaReport,\n REQUESTER_APPROVER,\n type StagedAttachment,\n type StoredMessage,\n type TextActionProposalVocabulary,\n type ThreadDetail,\n type ThreadSummary,\n type UpdateThreadInput,\n findCatalogModel,\n mayDecideApproval,\n readElicitationQuestions,\n settleDeadRun,\n textActionProposalReply,\n validateElicitationAnswer,\n} from '@dudousxd/nestjs-agent-core';\nimport type { UiCapabilities } from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n ConflictException,\n ForbiddenException,\n GoneException,\n HttpException,\n HttpStatus,\n Inject,\n Injectable,\n NotFoundException,\n NotImplementedException,\n Optional,\n PayloadTooLargeException,\n UnsupportedMediaTypeException,\n} from '@nestjs/common';\nimport type { AgentDepsFactory } from './agent-deps.factory.js';\nimport { utcDay } from './agent-deps.js';\nimport type { AgentModuleOptions } from './agent.options.js';\nimport { type AttachmentLimits, attachmentLimits } from './attachment-limits.js';\nimport { ActionProposalService } from './proposals/action-proposal.service.js';\nimport { ChatQueueService } from './queue/chat-queue.service.js';\nimport { publishQuotaBlocked } from './quota-exceeded.js';\nimport { RunNotActiveException } from './run-not-active.exception.js';\nimport { threadPersona } from './thread-persona.js';\n\n/**\n * What a send does when its thread already has a turn running:\n * - `'auto'` (default) — run now when the thread is idle, else wait in the thread's queue.\n * - `'queue'` — always wait in the queue, behind whatever is already waiting (it still starts at\n * once when nothing is running and nothing is ahead of it).\n * - `'interrupt'` — cancel the running turn and run this one next, ahead of the queue.\n */\nexport type ChatSendMode = 'auto' | 'queue' | 'interrupt';\n\n/** A send that is waiting in its thread's queue instead of running. */\nexport interface QueuedSend {\n threadId: string;\n queued: true;\n /** The queued message's id — also the run id it will start under. */\n messageId: string;\n /** 0-based place in the queue at the time it was queued (`0` → next). */\n position: number;\n queue: ChatQueueState;\n /** The turn it started under, when it started straight away (an idle thread). */\n runId?: string;\n /** The run an interrupt cancelled to make room for it. */\n interrupting?: string;\n}\n\n/** What {@link AgentService.send} did: started a turn, or queued the message. */\nexport type ChatSendResult =\n | { runId: string; threadId: string; queued?: undefined }\n | QueuedSend\n | { threadId: string; proposalDecision: unknown; text: string; queued?: undefined };\n\n/** The code of the `400` a send with nothing to answer gets (also AG-UI's, for the same case). */\nexport const NO_USER_MESSAGE_CODE = 'no_user_message';\n\n/**\n * `params` with its message checked, or a `400`. A send must carry something to answer: text, an\n * attachment, or `regenerate` (which re-answers the thread's last message and adds none). A missing\n * message is the empty one — so an attachment-only send never reaches the run with no text at all.\n */\nfunction sendableParams(params: ChatParams): ChatParams {\n const message: unknown = params.message;\n if (message !== undefined && message !== null && typeof message !== 'string') {\n throw new BadRequestException({\n statusCode: 400,\n code: 'invalid_message',\n message: 'message must be a string',\n });\n }\n const text = typeof message === 'string' ? message : '';\n if (\n text.trim().length === 0 &&\n (params.attachments?.length ?? 0) === 0 &&\n params.regenerate !== true\n ) {\n throw new BadRequestException({\n statusCode: 400,\n code: NO_USER_MESSAGE_CODE,\n message: 'nothing to answer: send a non-empty message, an attachment, or regenerate',\n });\n }\n const { channel, ...rest } = params;\n const stamped: ChatParams =\n channel === undefined ? params : { ...rest, pageContext: { ...params.pageContext, channel } };\n return text === message ? stamped : { ...stamped, message: text };\n}\n\nexport interface ChatParams {\n uiCapabilities?: UiCapabilities;\n actor: Actor;\n message: string;\n /** The host's own facts about this send — see `AgentRunInput.hostContext`. */\n hostContext?: AgentHostContext;\n /**\n * The HOST already decided this actor may write this thread — a chat-app thread several people\n * share, where anyone in it may continue the conversation. Skips the thread-ownership check of a\n * send; never set it from a request's own claim.\n */\n authorized?: boolean;\n threadId?: string;\n agentName?: string;\n /**\n * Run this turn under one of the agent's personas (`@Agent({ personas })`), and pin it on the\n * thread so later sends that name none keep it. Refused (400 `persona_not_found`) unless the agent\n * declares it. Omitted → the thread's pinned persona, else the agent's `defaultPersona`, else none.\n */\n personaId?: 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 /**\n * The channel this turn runs on — `web`, `mobile`, `whatsapp`… — over whatever its page context\n * says. Stamped as `pageContext.channel`, which is what decides (`turnChannel`) which genui tools\n * the turn is offered (`AgentGenuiModule.forRoot({ channels })`). Omitted → the page context's,\n * else `web`.\n */\n channel?: string;\n /** Re-run the last exchange instead of adding a new message. Requires an existing `threadId`. */\n regenerate?: boolean;\n /**\n * Run this turn on a catalog model instead of the thread's pinned one (or the provider default).\n * Refused (400) unless the bound `ModelCatalog` lists it as available to this actor and agent.\n */\n model?: string;\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 /** What to do when the thread already has a turn running — see {@link ChatSendMode}. */\n mode?: ChatSendMode;\n /**\n * When creating a thread (no `threadId`), ask the store to create it under this id — the id an\n * AG-UI consumer named the conversation with. A store may ignore it (`CreateThreadInput.id`); the\n * thread's real id is always the one on the result.\n */\n newThreadId?: string;\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/** Like {@link ThreadDefaultAgentReader}, for the thread's pinned model. */\nexport interface ThreadModelReader {\n modelForThread(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 @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging?: AttachmentStagingStore,\n @Optional()\n @Inject(AGENT_MODEL_CATALOG)\n private readonly models?: ModelCatalog,\n @Optional()\n @Inject(AGENT_QUOTA_PROVIDER)\n private readonly quotaProvider?: QuotaProvider,\n @Optional()\n @Inject(AGENT_OPTIONS)\n private readonly options?: Pick<\n AgentModuleOptions,\n 'quota' | 'actionApprovalMode' | 'attachments'\n >,\n @Optional() private readonly queue?: ChatQueueService,\n @Optional() private readonly proposals?: ActionProposalService,\n ) {}\n\n /**\n * Decide one independent proposal through the scoped proposal service — what the native\n * `action-proposals/:id/approve|reject` routes call — and the reply to show for it. `404` when\n * proposals are not on, `403`/`404` when this actor may not decide it.\n */\n async decideActionProposal(\n actor: Actor,\n threadId: string,\n proposalId: string,\n command: {\n decision: 'approved' | 'rejected';\n remember?: boolean;\n reason?: string;\n via: string;\n },\n ): Promise<{ proposalDecision: ActionProposalMutationView; text: string }> {\n if (this.options?.actionApprovalMode !== 'independent' || !this.proposals) {\n throw new NotFoundException('Proposal not found');\n }\n const result = await this.proposals.decide(threadId, proposalId, actor, command);\n return { proposalDecision: result, text: this.proposals.reply(result, command.decision) };\n }\n\n async handleTextDecision(threadId: string, actor: Actor, text: string) {\n if (this.options?.actionApprovalMode !== 'independent' || !this.proposals)\n return { status: 'unmatched' as const };\n return this.proposals.handleTextDecision(threadId, actor, text);\n }\n\n /** How `action` tools wait for their approval here — `AgentModule.forRoot({ actionApprovalMode })`. */\n actionApprovalMode(): ActionApprovalMode {\n return this.options?.actionApprovalMode ?? 'blocking';\n }\n\n /**\n * The words a text decision is made of (`actionProposalText.vocabulary`, English by default) — what\n * a surface without buttons tells the person to reply.\n */\n actionProposalVocabulary(): TextActionProposalVocabulary {\n return this.proposals?.textVocabulary() ?? DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY;\n }\n\n /** The configured reply (`actionProposalText.replies`) to a decision the store answered with `result`. */\n actionProposalReply(\n result: Pick<ActionProposalMutationView, 'status' | 'proposal'>,\n decision: 'approved' | 'rejected',\n ): string {\n return this.proposals?.reply(result, decision) ?? textActionProposalReply(result, decision);\n }\n\n /**\n * The proposals of a thread this actor may see — the thread's own actor, or one the policy lets\n * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page).\n * Without independent approvals (the default blocking mode) there are none, so the read answers an\n * empty list rather than refusing; deciding one still refuses.\n */\n async listActionProposals(actor: Actor, threadId: string): Promise<ActionProposalView[]> {\n if (this.options?.actionApprovalMode !== 'independent' || !this.proposals) {\n return [];\n }\n return this.proposals.list(threadId, actor);\n }\n\n /**\n * The attachment rules in force — what `GET <base>/config` serves and `POST <base>/attachments`\n * enforces. `enabled: false` when no `AGENT_ATTACHMENT_STAGING` provider is bound.\n */\n attachmentLimits(): AttachmentLimits {\n return attachmentLimits(this.options, this.staging);\n }\n\n /**\n * Stage a file for a later turn, held to the same limits as `POST <base>/attachments` — for a\n * surface that receives files itself (a messaging webhook). Refuses with `501` when attachments are\n * off, `415` for a type outside the allowlist and `413` past the size cap; send the returned\n * `mediaId` as `attachments: [{ mediaId }]`.\n */\n async stageAttachment(\n actor: Actor,\n file: { data: Buffer; contentType: string; filename: string },\n ): Promise<MessageAttachment> {\n if (this.staging === undefined) {\n throw new NotImplementedException(\n 'Attachments are not configured on this server: bind AGENT_ATTACHMENT_STAGING ' +\n '(e.g. import AgentMediaAttachmentsModule).',\n );\n }\n const { allowedContentTypes, maxBytes } = this.attachmentLimits();\n const contentType = file.contentType.split(';')[0]?.trim().toLowerCase() ?? '';\n if (!allowedContentTypes.includes(contentType)) {\n throw new UnsupportedMediaTypeException(\n `content type \"${contentType}\" is not allowed (allowed: ${allowedContentTypes.join(', ')})`,\n );\n }\n if (file.data.byteLength > maxBytes) {\n throw new PayloadTooLargeException(`file exceeds the ${maxBytes}-byte limit`);\n }\n return this.staging.stage({\n data: file.data,\n filename: file.filename,\n contentType,\n sizeBytes: file.data.byteLength,\n actor,\n });\n }\n /** The queue service when the bound store can hold a queue, else `undefined`. */\n private queueing(): ChatQueueService | undefined {\n return this.queue?.supported === true ? this.queue : undefined;\n }\n\n /** The queue service, or a 501 naming what is missing. */\n private requireQueue(): ChatQueueService {\n const queue = this.queueing();\n if (queue === undefined) {\n throw new NotImplementedException(\n 'Queueing messages requires an AgentStore that implements ChatQueueStore; the bound store ' +\n 'does not.',\n );\n }\n return queue;\n }\n\n /**\n * The actor's budget across windows (`GET <base>/quota`) — the bound {@link QuotaProvider}'s\n * report. Without one (a service built outside the module), a day window from the ledger.\n */\n async quotaReport(actor: Actor): Promise<QuotaReport> {\n if (this.quotaProvider !== undefined) {\n return this.quotaProvider.report({ actor });\n }\n const { usedTokens, costUsd } = await this.store.quotaToday(actor.id, utcDay());\n return { windows: [{ period: 'day', usedTokens, usedUsd: costUsd }] };\n }\n\n /**\n * Refuse a turn the actor's budget no longer covers — only when the host configured one\n * (`quota`): the default report is informational.\n */\n private async assertWithinQuota(actor: Actor): Promise<void> {\n if (this.options?.quota === undefined || this.quotaProvider === undefined) {\n return;\n }\n const report = await this.quotaProvider.report({ actor });\n const { blocked } = report;\n if (blocked !== undefined) {\n publishQuotaBlocked(actor, report, blocked);\n throw new HttpException(\n {\n statusCode: HttpStatus.TOO_MANY_REQUESTS,\n code: 'quota_exceeded',\n period: blocked.period,\n message:\n blocked.reason ??\n `The ${blocked.period === 'day' ? 'daily' : 'monthly'} quota is used up`,\n },\n HttpStatus.TOO_MANY_REQUESTS,\n );\n }\n }\n\n /**\n * The models `actor` may pick for `agent` (`GET <base>/models`). An empty catalog when none is\n * bound, so a picker simply has nothing to offer.\n */\n async listModels(actor: Actor, agent?: string): Promise<ModelCatalogView> {\n if (this.models === undefined) {\n return { providers: [], default: null };\n }\n return this.models.list({ actor, ...(agent !== undefined ? { agent } : {}) });\n }\n\n /**\n * `model` if the catalog offers it to this actor and agent right now, else a 400 naming why. The\n * one gate every model choice passes — a send's own, and a thread's pinned one at the moment it is\n * pinned and again at every turn that runs on it (availability can change in between).\n */\n private async assertModelAllowed(actor: Actor, agent: string, model: string): Promise<string> {\n if (this.models === undefined) {\n throw new BadRequestException(\n `model \"${model}\" cannot be selected: no ModelCatalog is configured (AgentModule.forRoot({ models }))`,\n );\n }\n const entry = findCatalogModel(await this.models.list({ actor, agent }), model);\n if (entry === undefined) {\n throw new BadRequestException(`model \"${model}\" is not offered`);\n }\n if (!entry.available) {\n throw new BadRequestException(\n `model \"${model}\" is not available${entry.unavailableReason ? `: ${entry.unavailableReason}` : ''}`,\n );\n }\n return entry.id;\n }\n\n /**\n * The model a turn runs on: the send's own (that turn only — it is never stored on the thread),\n * else the thread's pinned one, else none. An agent the catalog locks to one model runs on it\n * whatever was sent or pinned, and a send naming another model is refused.\n */\n private async resolveModel(\n actor: Actor,\n agent: string,\n requested: string | undefined,\n threadId: string | undefined,\n ): Promise<string | undefined> {\n const locked =\n this.models !== undefined ? (await this.models.list({ actor, agent })).locked : undefined;\n if (locked !== undefined) {\n if (requested !== undefined && requested !== locked.model) {\n throw new BadRequestException(\n `model \"${requested}\" cannot be selected: ${locked.reason ?? `this agent always uses \"${locked.model}\"`}`,\n );\n }\n return locked.model;\n }\n const model = requested ?? (threadId !== undefined ? await this.threadModel(threadId) : null);\n if (model === null || model === undefined) {\n return undefined;\n }\n return this.assertModelAllowed(actor, agent, model);\n }\n\n private async threadModel(threadId: string): Promise<string | null> {\n const projecting = this.store as Partial<ThreadModelReader>;\n if (typeof projecting.modelForThread === 'function') {\n return projecting.modelForThread(threadId);\n }\n return (await this.store.getThread(threadId))?.model ?? null;\n }\n\n /**\n * Start a turn — for in-process callers that need a run id back. A send that would have to wait\n * (its thread already has a turn running) is refused with `409` instead; {@link send} is the form\n * that queues it.\n */\n async chat(params: ChatParams): Promise<{ runId: string; threadId: string }> {\n const result = await this.send({ ...params, mode: 'auto' }, { textDecisions: false });\n if ('proposalDecision' in result) throw new Error('Unexpected text decision in run-only API');\n if (result.queued !== true) {\n return result;\n }\n if (result.runId !== undefined) {\n // The thread freed up while it was being queued, and it started straight away.\n return { runId: result.runId, threadId: result.threadId };\n }\n // Take it back out, so this call has no effect — unless it started in the meantime.\n const store = this.requireQueue().queueStore();\n if (!(await store.removeQueuedMessage(result.messageId))) {\n return { runId: result.messageId, threadId: result.threadId };\n }\n await this.requireQueue().publish(result.threadId);\n throw new ConflictException({\n statusCode: 409,\n code: 'run_active',\n message: `thread ${result.threadId} already has a turn running`,\n });\n }\n\n /**\n * Send a message: start a turn, or — when its thread already has one running — queue the message\n * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.\n */\n async send(\n claimed: ChatParams,\n sendOptions: { textDecisions?: boolean } = {},\n ): Promise<ChatSendResult> {\n // Before anything else — a text decision, the quota, a thread — so a send with nothing to answer\n // is a 400 that leaves nothing behind, instead of a run that crashes on the missing text.\n const params = sendableParams(claimed);\n if (\n sendOptions.textDecisions !== false &&\n this.options?.actionApprovalMode === 'independent' &&\n params.threadId !== undefined &&\n params.regenerate !== true &&\n this.proposals\n ) {\n const decision = await this.proposals.handleTextDecision(\n params.threadId,\n params.actor,\n params.message,\n );\n if ('proposalDecision' in decision) return decision;\n }\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 await this.assertWithinQuota(params.actor);\n // A name a persona took over (`Persona.aliases`) runs as the agent that owns it, under it.\n const target = this.deps.resolveAgent(\n await this.resolveAgentName(params.agentName, params.threadId),\n );\n const agentName = target.agentName;\n const persona = await this.resolvePersona(\n agentName,\n params.personaId ?? target.persona,\n params.threadId,\n );\n const model = await this.resolveModel(params.actor, agentName, params.model, 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 ...(agentName !== undefined ? { agentName } : {}),\n ...(params.transient === true ? { transient: true } : {}),\n ...(params.newThreadId !== undefined ? { id: params.newThreadId } : {}),\n ...(params.personaId !== undefined ? { persona: params.personaId } : {}),\n });\n threadId = created.id;\n } else {\n // Every send onto an existing thread is gated by ownership: a regenerate rewinds the thread,\n // and a queued message would otherwise land in someone else's conversation.\n if (params.authorized !== true) await this.assertOwnsThread(params.actor, threadId);\n // A persona a send NAMES is the person's pick for this conversation: pinned, so the next send\n // (and a reopened thread's picker) keeps it. One the send fell back to is not pinned.\n if (params.personaId !== undefined) {\n await this.pinThreadPersona(threadId, params.personaId);\n }\n }\n\n const input: AgentRunInput = {\n threadId,\n actor: params.actor,\n userText: params.message,\n day: utcDay(),\n agentName,\n ...(persona !== undefined ? { persona } : {}),\n ...(params.regenerate === true ? { regenerate: true } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n ...(params.pageContext !== undefined ? { pageContext: params.pageContext } : {}),\n ...(params.uiCapabilities !== undefined ? { uiCapabilities: params.uiCapabilities } : {}),\n ...(params.hostContext !== undefined ? { hostContext: params.hostContext } : {}),\n ...(model !== undefined ? { model } : {}),\n };\n\n const queue = this.queueing();\n if (queue === undefined) {\n if (this.options?.actionApprovalMode === 'independent')\n throw new Error('Independent actions require queued thread admission');\n // No admission to take: a store that predates the queue starts every send at once.\n const { runId } = await this.runner.start(input);\n await this.store.setActiveStream(threadId, runId);\n return { runId, threadId };\n }\n\n const mode = params.mode ?? 'auto';\n const { live, stale } = await queue.holder(threadId, this.runner);\n if (stale !== null) {\n // The thread is still pointed at a run that is gone: settle the calls it left showing an\n // approval card before another turn reads the thread.\n await settleDeadRun(this.store, { runId: stale });\n }\n // `queue` always answers as a queued send (202), so a client that asked for it handles one\n // shape; an idle thread starts it straight away all the same (`enqueue` kicks the queue).\n if (live === null && mode !== 'queue') {\n const runId = this.runner.runIdFor?.(input) ?? crypto.randomUUID();\n if (\n await queue\n .queueStore()\n .claimActiveStream(threadId, runId, stale !== null ? { replacing: stale } : {})\n ) {\n return { runId: await this.startClaimed(input, runId), threadId };\n }\n // Lost the race for the thread to another send: fall through and queue behind it.\n }\n if (params.regenerate === true) {\n throw new ConflictException({\n statusCode: 409,\n code: 'run_active',\n message: 'cannot regenerate while a turn is running on this thread',\n });\n }\n return this.enqueue(queue, input, mode, live);\n }\n\n /**\n * Start a turn the thread is already claimed for, under the claimed id. A runner that minted an\n * id of its own anyway gets the thread re-pointed at it; one that fails to start frees the thread.\n */\n private async startClaimed(input: AgentRunInput, runId: string): Promise<string> {\n const store = this.requireQueue().queueStore();\n let started: string;\n try {\n started = (await this.runner.start(input, { runId })).runId;\n } catch (error) {\n await store.releaseActiveStream(input.threadId, runId);\n throw error;\n }\n if (started !== runId) {\n await store.claimActiveStream(input.threadId, started, { replacing: runId });\n }\n return started;\n }\n\n /** Put a send in its thread's queue, then drain it if the thread turned out to be free. */\n private async enqueue(\n queue: ChatQueueService,\n input: AgentRunInput,\n mode: ChatSendMode,\n live: string | null,\n ): Promise<QueuedSend> {\n const store = queue.queueStore();\n const threadId = input.threadId;\n const interrupting = mode === 'interrupt' && live !== null ? live : undefined;\n const queued = await store.enqueueMessage({\n threadId,\n actor: input.actor,\n content: input.userText,\n ...(input.attachments !== undefined ? { attachments: input.attachments } : {}),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.persona !== undefined ? { persona: input.persona } : {}),\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),\n ...(input.uiCapabilities !== undefined ? { uiCapabilities: input.uiCapabilities } : {}),\n ...(input.hostContext !== undefined ? { hostContext: input.hostContext } : {}),\n ...(interrupting !== undefined ? { interrupt: true, at: 'head' as const } : {}),\n });\n let runId: string | undefined;\n if (interrupting !== undefined) {\n // An interrupt is a person choosing to run this now: whatever paused the queue, they are\n // overriding it. The cancel settles into the queue, which starts this message.\n await store.setQueuePause(threadId, null);\n await queue.publish(threadId);\n await this.runner.cancel(interrupting);\n } else {\n // The run holding the thread may have settled between our look and our enqueue — its drain\n // then found nothing. Starting the head here covers that; with a live holder it does nothing.\n runId = await queue.kick(threadId, this.runner);\n if (runId === undefined) {\n await queue.publish(threadId);\n }\n }\n const state = await queue.state(threadId);\n const position = state.items.findIndex((item) => item.id === queued.id);\n return {\n threadId,\n queued: true,\n messageId: queued.id,\n position: position === -1 ? 0 : position,\n queue: state,\n ...(runId !== undefined && runId === queued.id ? { runId } : {}),\n ...(interrupting !== undefined ? { interrupting } : {}),\n };\n }\n\n /** `GET <base>/threads/:id/queue` — the thread's waiting messages and whether it drains. */\n async getQueue(actor: Actor, threadId: string): Promise<ChatQueueState> {\n await this.assertOwnsThread(actor, threadId);\n return this.requireQueue().state(threadId);\n }\n\n /**\n * `PATCH <base>/queue/:messageId` — change a waiting message's text and/or attachments, and/or move\n * it to `position` in the queue. Answers the thread's queue.\n */\n async updateQueuedMessage(\n actor: Actor,\n messageId: string,\n patch: { message?: string; attachments?: AttachmentRef[] | null; position?: number },\n ): Promise<ChatQueueState> {\n const queue = this.requireQueue();\n const store = queue.queueStore();\n const threadId = await this.assertOwnsQueuedMessage(actor, messageId);\n if (patch.message !== undefined && patch.message.trim().length === 0) {\n throw new BadRequestException('message must not be empty');\n }\n const attachments =\n patch.attachments === undefined || patch.attachments === null\n ? patch.attachments\n : await this.resolveAttachments(actor, patch.attachments);\n if (patch.message !== undefined || attachments !== undefined) {\n const updated = await store.updateQueuedMessage(messageId, {\n ...(patch.message !== undefined ? { content: patch.message } : {}),\n ...(attachments !== undefined ? { attachments } : {}),\n });\n if (updated === null) {\n throw new GoneException(`queued message ${messageId} already started or was removed`);\n }\n }\n if (patch.position !== undefined) {\n if (!Number.isInteger(patch.position) || patch.position < 0) {\n throw new BadRequestException('position must be a non-negative integer');\n }\n if (!(await store.moveQueuedMessage(messageId, patch.position))) {\n throw new GoneException(`queued message ${messageId} already started or was removed`);\n }\n }\n return queue.publish(threadId);\n }\n\n /** `DELETE <base>/queue/:messageId` — drop a waiting message. Answers the thread's queue. */\n async removeQueuedMessage(actor: Actor, messageId: string): Promise<ChatQueueState> {\n const queue = this.requireQueue();\n const threadId = await this.assertOwnsQueuedMessage(actor, messageId);\n if (!(await queue.queueStore().removeQueuedMessage(messageId))) {\n throw new GoneException(`queued message ${messageId} already started or was removed`);\n }\n return queue.publish(threadId);\n }\n\n /**\n * `POST <base>/queue/:messageId/interrupt` — run a message that is already waiting NOW: it moves\n * to the head of its queue marked as an interrupt, any pause is lifted, and the running turn is\n * cancelled (its settle starts this message — the same path a `mode: 'interrupt'` send takes).\n * With nothing running, the message starts at once.\n *\n * One request, and the message never leaves the queue: a client that removed it and sent it again\n * would lose it if the second call failed, and would run it twice if another tab's drain started\n * it in between. Answers the queue, plus `interrupting` (the run that was cancelled) or `runId`\n * (the run this message started).\n */\n async interruptQueuedMessage(\n actor: Actor,\n messageId: string,\n ): Promise<ChatQueueState & { runId?: string; interrupting?: string }> {\n const queue = this.requireQueue();\n const store = queue.queueStore();\n const threadId = await this.assertOwnsQueuedMessage(actor, messageId);\n const gone = () =>\n new GoneException(`queued message ${messageId} already started or was removed`);\n const marked = await store.updateQueuedMessage(messageId, { interrupt: true });\n if (marked === null) {\n throw gone();\n }\n if (marked.interrupt !== true) {\n // Cancelling for a message the store did not mark would pause the queue behind the cancel\n // instead of starting it — refuse before anything is cancelled.\n throw new NotImplementedException(\n 'Interrupting a queued message requires a ChatQueueStore whose updateQueuedMessage stores ' +\n '`interrupt`; the bound store ignored it.',\n );\n }\n if (!(await store.moveQueuedMessage(messageId, 0))) {\n throw gone();\n }\n // A person choosing to run this now overrides whatever paused the queue.\n await store.setQueuePause(threadId, null);\n const { live } = await queue.holder(threadId, this.runner);\n if (live !== null && live !== messageId && (await store.getQueuedMessage(messageId)) !== null) {\n const state = await queue.publish(threadId);\n await this.runner.cancel(live);\n return { ...state, interrupting: live };\n }\n if (live !== null) {\n // The drain started it while this request was on its way: it is the running turn already.\n return { ...(await queue.state(threadId)), runId: messageId };\n }\n const runId = await queue.kick(threadId, this.runner);\n const state = runId === undefined ? await queue.publish(threadId) : await queue.state(threadId);\n return { ...state, ...(runId !== undefined ? { runId } : {}) };\n }\n\n /** `DELETE <base>/threads/:id/queue` — drop every waiting message (and any pause). */\n async clearQueue(actor: Actor, threadId: string): Promise<ChatQueueState> {\n await this.assertOwnsThread(actor, threadId);\n const queue = this.requireQueue();\n await queue.queueStore().clearQueue(threadId);\n await queue.queueStore().setQueuePause(threadId, null);\n return queue.publish(threadId);\n }\n\n /**\n * `POST <base>/threads/:id/queue/resume` — lift a pause and start the head when nothing is\n * running. Answers the queue, and the run the head started under, if it did.\n */\n async resumeQueue(actor: Actor, threadId: string): Promise<ChatQueueState & { runId?: string }> {\n await this.assertOwnsThread(actor, threadId);\n const queue = this.requireQueue();\n await queue.queueStore().setQueuePause(threadId, null);\n const runId = await queue.kick(threadId, this.runner);\n const state = runId === undefined ? await queue.publish(threadId) : await queue.state(threadId);\n return { ...state, ...(runId !== undefined ? { runId } : {}) };\n }\n\n /** The thread a queued message waits on, once the caller is shown to own it. */\n private async assertOwnsQueuedMessage(actor: Actor, messageId: string): Promise<string> {\n const message = await this.requireQueue().queueStore().getQueuedMessage(messageId);\n if (message === null) {\n throw new NotFoundException(`queued message ${messageId} not found`);\n }\n await this.assertOwnsThread(actor, message.threadId);\n return message.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 /**\n * Approve a parked action call as `actor`. Who may is the call's recorded approver's business\n * (see {@link assertMayDecide}); `remember` approves later calls of the same tool in the same\n * thread, and `via` names the surface the decision came through (`'web'`, `'slack'`, …) — both\n * persisted with the call.\n */\n async approve(\n actor: Actor,\n toolCallId: string,\n opts: { remember?: boolean; via?: string } = {},\n ): Promise<void> {\n await this.assertMayDecide(actor, toolCallId);\n return this.signalToolCall(toolCallId, {\n approved: true,\n executedByRef: actor.id,\n ...(opts.remember === true ? { remember: true } : {}),\n ...(opts.via !== undefined ? { decidedVia: opts.via } : {}),\n });\n }\n\n async reject(\n actor: Actor,\n toolCallId: string,\n reason?: string,\n opts: { via?: string } = {},\n ): Promise<void> {\n await this.assertMayDecide(actor, toolCallId);\n return this.signalToolCall(toolCallId, {\n approved: false,\n executedByRef: actor.id,\n ...(reason !== undefined ? { reason } : {}),\n ...(opts.via !== undefined ? { decidedVia: opts.via } : {}),\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 opts: { via?: string } = {},\n ): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n await this.assertAnswersFit(toolCallId, answers);\n const reply: ElicitationReply = {\n answers,\n answeredByRef: actor.id,\n ...(opts.via !== undefined ? { answeredVia: opts.via } : {}),\n };\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, opts: { via?: string } = {}): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n const reply: ElicitationReply = {\n answers: {},\n skipped: true,\n answeredByRef: actor.id,\n ...(opts.via !== undefined ? { answeredVia: opts.via } : {}),\n };\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 if ((await this.store.toolCallApproval?.(toolCallId))?.status === 'proposed')\n throw new ConflictException(\n 'Independent proposals require the scoped proposal decision route',\n );\n await this.assertNotExpired(toolCallId);\n const runId = await this.resolveRunForToolCall(toolCallId);\n await this.assertRunWaiting(runId);\n return this.runner.signal(runId, toolCallId, reply);\n }\n\n /**\n * Refuse a decision addressed at a run that is over (`409 run_not_active`). The runtime would take\n * the signal and buffer it for a run that never comes back — the person's \"yes\" is accepted, the\n * card says so, and nothing runs. Settles the calls the dead run left awaiting a decision on the\n * way out, so the card stops asking. A runner that cannot say whether a run is alive is taken at\n * its word that it is, and so is one that fails to answer.\n */\n private async assertRunWaiting(runId: string): Promise<void> {\n if (typeof this.runner.isRunActive !== 'function') {\n return;\n }\n const active = await this.runner.isRunActive(runId).catch(() => true);\n if (active) {\n return;\n }\n await settleDeadRun(this.store, { runId });\n throw new RunNotActiveException(runId);\n }\n\n /** Who owns the thread, or `null` when there is no such (live) thread. */\n async threadOwner(threadId: string): Promise<string | null> {\n return this.store.ownerOfThread(threadId);\n }\n\n /**\n * May `actor` continue the run whose stream is `runId` — the AG-UI resume? Only the actor whose\n * thread is streaming it (`403` otherwise), and only while it still is: a run that is over is\n * waiting on no one (`409 run_not_active`), whatever an old interrupt id says.\n */\n async assertResumable(actor: Actor, runId: string): Promise<void> {\n const owner = await this.store.ownerOfActiveStream(runId);\n if (owner === null) {\n throw new RunNotActiveException(runId);\n }\n if (owner !== actor.id) {\n throw new ForbiddenException('run belongs to another actor');\n }\n }\n\n /**\n * Everything {@link approve} / {@link reject} check before they signal — who may decide, and\n * that the request has not lapsed — without signalling. For a caller that settles several\n * decisions at once and must refuse all of them if one is refused (an AG-UI resume).\n */\n async checkDecision(actor: Actor, toolCallId: string): Promise<void> {\n await this.assertMayDecide(actor, toolCallId);\n await this.assertNotExpired(toolCallId);\n }\n\n /** Everything {@link answer} checks before it signals, without signalling — see {@link checkDecision}. */\n async checkAnswer(\n actor: Actor,\n toolCallId: string,\n answers: Record<string, string[]>,\n ): Promise<void> {\n await this.assertOwnsToolCall(actor, toolCallId);\n await this.assertAnswersFit(toolCallId, answers);\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, actor);\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 (\n patch.defaultAgent === undefined &&\n patch.model === undefined &&\n patch.persona === undefined\n ) {\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, model or persona requires an AgentStore that implements \" +\n 'updateThread(); the bound store does not support it.',\n );\n }\n // Pinned against the agent the thread's next turn will run as — the one the patch sets, else\n // the thread's own default, else the module's.\n const model =\n patch.model === undefined || patch.model === null\n ? patch.model\n : await this.assertModelAllowed(\n actor,\n patch.defaultAgent ?? (await this.resolveAgentName(undefined, threadId)),\n patch.model,\n );\n // Validated against the agent the thread's next turn will run as, like the model above.\n if (patch.persona !== undefined && patch.persona !== null) {\n this.deps.resolvePersona({\n agentName: this.deps.resolveAgent(\n patch.defaultAgent ?? (await this.resolveAgentName(undefined, threadId)),\n ).agentName,\n requested: patch.persona,\n });\n }\n await this.store.updateThread(threadId, {\n ...(title !== undefined ? { title } : {}),\n ...(patch.defaultAgent !== undefined ? { defaultAgent: patch.defaultAgent } : {}),\n ...(model !== undefined ? { model } : {}),\n ...(patch.persona !== undefined ? { persona: patch.persona } : {}),\n });\n }\n\n /**\n * The persona this send runs under — see {@link AgentDepsFactory.resolvePersona}. The thread's\n * pinned persona is read only when the send names none AND the agent has personas to pick from.\n */\n private async resolvePersona(\n agentName: string,\n requested: string | undefined,\n threadId: string | undefined,\n ): Promise<string | undefined> {\n const needsThread =\n requested === undefined &&\n threadId !== undefined &&\n this.deps.personaCatalog(agentName).length > 0;\n return this.deps.resolvePersona({\n agentName,\n ...(requested !== undefined ? { requested } : {}),\n ...(needsThread ? { threadPersona: await threadPersona(this.store, threadId) } : {}),\n });\n }\n\n /** Pin `persona` on the thread when it is not already — a no-op on a store that cannot. */\n private async pinThreadPersona(threadId: string, persona: string): Promise<void> {\n if (this.store.updateThread === undefined) {\n return;\n }\n if ((await threadPersona(this.store, threadId)) !== persona) {\n await this.store.updateThread(threadId, { persona });\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 model: thread.model ?? null,\n persona: thread.persona ?? null,\n activeRunId: (await this.store.activeRunForThread?.(thread.id)) ?? thread.activeRunId ?? null,\n };\n }\n\n private async toDetailView(thread: ThreadDetail, actor: Actor): Promise<ThreadDetail> {\n const summary = await this.toSummaryView(thread);\n const queue = this.queueing();\n return {\n ...summary,\n messages: await this.freshAttachmentUrls(thread.messages, actor),\n ...(queue !== undefined ? { queue: await queue.state(thread.id) } : {}),\n };\n }\n\n /**\n * Re-mint each replayed attachment's url from the staging store, by `mediaId`: the url persisted\n * with the message was minted for THAT turn (a presigned url with an expiry), so an old turn would\n * otherwise show a dead link. The store's own access check applies — an attachment it will not\n * resolve for this actor keeps the url it was stored with.\n */\n private async freshAttachmentUrls(\n messages: StoredMessage[],\n actor: Actor,\n ): Promise<StoredMessage[]> {\n const staging = this.staging;\n if (staging === undefined || !messages.some((message) => message.attachments?.length)) {\n return messages;\n }\n return Promise.all(\n messages.map(async (message) => {\n if (message.attachments === undefined || message.attachments.length === 0) return message;\n const attachments = await Promise.all(\n message.attachments.map(async (attachment) => {\n try {\n const fresh = await staging.resolve({ mediaId: attachment.mediaId, actor });\n return fresh ?? attachment;\n } catch {\n return attachment;\n }\n }),\n );\n return { ...message, attachments };\n }),\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 * Rate a message in one of `actor`'s threads: `'up'`/`'down'` with an optional comment, or `null`\n * to clear the rating. Answers `404` for an unknown message, `403` for another actor's, and `501`\n * on a store without `threadOfMessage` + `setMessageFeedback`.\n */\n async setMessageFeedback(\n actor: Actor,\n messageId: string,\n input: { value: MessageFeedbackValue | null; comment?: string },\n ): Promise<MessageFeedback | null> {\n if (input.value !== null && input.value !== 'up' && input.value !== 'down') {\n throw new BadRequestException(\"value must be 'up', 'down' or null\");\n }\n if (input.comment !== undefined && typeof input.comment !== 'string') {\n throw new BadRequestException('comment must be a string');\n }\n const comment = input.comment?.trim();\n if (comment !== undefined && comment.length > 2000) {\n throw new BadRequestException('comment must be at most 2000 characters');\n }\n if (this.store.threadOfMessage === undefined || this.store.setMessageFeedback === undefined) {\n throw new NotImplementedException(\n 'Message feedback requires an AgentStore that implements threadOfMessage() and ' +\n 'setMessageFeedback(); the bound store does not support it.',\n );\n }\n const threadId = await this.store.threadOfMessage(messageId);\n if (threadId === null) {\n throw new NotFoundException(`message ${messageId} not found`);\n }\n await this.assertOwnsThread(actor, threadId);\n const feedback: MessageFeedback | null =\n input.value === null\n ? null\n : {\n value: input.value,\n ...(comment !== undefined && comment.length > 0 ? { comment } : {}),\n updatedAt: new Date().toISOString(),\n };\n await this.store.setMessageFeedback(messageId, feedback);\n return feedback;\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 * 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 * Check a reply against the questions it answers before it is signalled: every submitted value a\n * question's own rules accept (a typed input's type, bounds and pattern; a pick from the offered\n * options), and every `required` question answered — by the reply, or by the defaults an omitted\n * question falls back to. A reply the loop would have to drop parts of is refused here instead, so\n * the person who typed it hears why. Needs the store to hand back the call's recorded questions;\n * without that seam the loop's own filtering is the only check.\n */\n private async assertAnswersFit(\n toolCallId: string,\n answers: Record<string, string[]>,\n ): Promise<void> {\n if (this.store.toolCallInput === undefined) {\n return;\n }\n const questions = readElicitationQuestions(await this.store.toolCallInput(toolCallId));\n for (const question of questions) {\n const submitted = Object.hasOwn(answers, question.id) ? answers[question.id] : undefined;\n const problem = validateElicitationAnswer(question, submitted ?? question.defaults ?? []);\n if (problem !== null) {\n throw new BadRequestException(`answers[\"${question.id}\"] ${problem}`);\n }\n }\n }\n\n /**\n * Authorization seam for approve/reject. The call's recorded approver decides who may settle it:\n * the requester (the default, and every call recorded before approvers existed) is the thread's\n * own actor — the ownership check this always was; any other approver goes through the policy's\n * `canDecide`, which by default asks whether the actor holds that role.\n */\n private async assertMayDecide(actor: Actor, toolCallId: string): Promise<void> {\n const approval = await this.store.toolCallApproval?.(toolCallId);\n const approver = approval?.approver ?? REQUESTER_APPROVER;\n if (approver === REQUESTER_APPROVER) {\n return this.assertOwnsToolCall(actor, toolCallId);\n }\n const requesterRef = await this.store.ownerOfToolCall(toolCallId);\n if (requesterRef === null) {\n throw new NotFoundException(`tool call ${toolCallId} not found`);\n }\n const allowed = await mayDecideApproval(this.deps.forAgent().approvalPolicy, actor, {\n toolCallId,\n approver,\n requesterRef,\n });\n if (!allowed) {\n throw new ForbiddenException(`this approval is for ${approver}`);\n }\n }\n\n /**\n * Refuse a decision on a request that has already lapsed — recorded `expired`, or past its\n * `expiresAt` with the run's own timer about to fire. Signalling it anyway would race the timeout:\n * a durable runtime buffers a signal nobody is waiting on, and a late approval must not be what a\n * later replay of the run reads back.\n */\n private async assertNotExpired(toolCallId: string): Promise<void> {\n const approval = await this.store.toolCallApproval?.(toolCallId);\n if (approval === null || approval === undefined) {\n return;\n }\n const lapsed =\n approval.status === 'expired' ||\n (approval.status === 'pending_approval' &&\n approval.expiresAt !== null &&\n Date.parse(approval.expiresAt) <= Date.now());\n if (lapsed) {\n throw new GoneException(`the approval request for tool call ${toolCallId} has expired`);\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 { ResolveToolUiCatalog, ToolUiChannelGuide } from '@dudousxd/nestjs-agent-core';\nimport type {\n AgentIntake,\n AgentPricingStore,\n AgentStore,\n ApprovalPolicy,\n HistoryPolicy,\n InputProcessor,\n MemoryConfig,\n ModelProvider,\n OutputProcessor,\n Persona,\n PromptBuilder,\n PromptContributor,\n QuotaStore,\n Retriever,\n RolesPolicy,\n SinkWriter,\n SkillsConfig,\n TokenStreamSink,\n ToolRegistry,\n ToolTransientRetrySetting,\n} from '@dudousxd/nestjs-agent-core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\n/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */\nexport interface AgentDeps {\n resolveUiCatalog?: ResolveToolUiCatalog;\n /** genui `channels`: the channel's prompt block, and what tool pushes were delivered as. */\n uiChannelGuide?: ToolUiChannelGuide;\n actionApprovalMode?: 'blocking' | 'independent';\n model: ModelProvider;\n store: AgentStore;\n registry: ToolRegistry;\n rolesPolicy: RolesPolicy;\n /** Who approves an action call, and for how long (from `forRoot({ approvalPolicy })`). Undefined → the requester, no expiry. */\n approvalPolicy?: ApprovalPolicy;\n quota?: QuotaStore;\n sink: TokenStreamSink;\n /** Fallback accounting label; the provider's turn result overrides it when set. */\n modelId?: string;\n systemPrompt: string | PromptBuilder;\n /** App-wide `@SystemPromptContributor()` sections appended after the agent's base prompt. */\n promptContributors: PromptContributor[];\n maxSteps: number;\n /** Nesting ceiling for delegation below this agent. Undefined → the loop's default. */\n maxDelegationDepth?: number;\n /** How many times one agent may appear on a chain. Undefined → the loop's default. */\n maxAgentAppearances?: number;\n /** Agent-level tool allow-list. Undefined → all tools (after role filtering). */\n toolAllowList?: string[];\n /** The agent's personas (`@Agent({ personas })`) — read by the loop only for a run that names one. */\n personas?: Persona[];\n /** Per-tool execution timeout in ms (from module options). Undefined → no timeout. */\n toolTimeoutMs?: number;\n /**\n * Transient-tool-error retry policy (from module options). Undefined → default ON\n * (`{ attempts: 2, backoffMs: 150 }` with the default classifier); `false` → disabled.\n */\n toolTransientRetry?: ToolTransientRetrySetting;\n /** How many follow-up suggestions to generate after the final turn. Undefined/0 → off. */\n followUpsCount?: number;\n /** Inject-mode retriever (from `forRoot({ retrieval })`). Undefined → no prompt augmentation. */\n retriever?: Retriever;\n /** Passages inject-mode retrieval requests. Undefined → loop default (5). */\n retrievalTopK?: number;\n /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */\n pricingStore?: AgentPricingStore;\n /** The agent's history ceiling, resolved from `@Agent({ history })` / module options. Undefined → unbounded. */\n historyPolicy?: HistoryPolicy;\n /** Module-wide prompt rewriters, applied before every model call. Empty → none. */\n inputProcessors: InputProcessor[];\n /** Module-wide answer gates. NON-EMPTY MEANS THE TURN'S MODEL OUTPUT IS BUFFERED, not streamed. */\n outputProcessors: OutputProcessor[];\n /** The agent's `@Agent({ outputSchema })`, resolved from DI — never over the wire. Undefined → free text. */\n outputSchema?: StandardSchemaV1;\n /** Extra model calls allowed to repair an answer that failed `outputSchema`. Undefined → 1. */\n outputRepairAttempts?: number;\n /** The agent's `@Agent({ intake })` question set, asked before the turn starts. Undefined → none. */\n intake?: AgentIntake;\n /** Whether the model may call the built-in `ask` tool this turn. Undefined/false → it never sees it. */\n ask?: boolean;\n /**\n * The resolved skills seam (`forRoot({ skills })` + discovered `@Skill` providers). Undefined →\n * no catalog, no `skill` tool, and the turn spends no checkpoint on either.\n */\n skills?: SkillsConfig;\n /**\n * The resolved memory seam (`forRoot({ memory })`). Undefined → no block, no `remember` tool, and\n * the turn spends no checkpoint on either.\n */\n memory?: MemoryConfig;\n}\n\nexport function utcDay(date = new Date()): string {\n return date.toISOString().slice(0, 10);\n}\n\n/**\n * Wraps a parent run's sink writer for a sub-agent: `write` forwards (so the sub-agent's tokens and\n * pending action-tool frames reach the human's live stream), but `end` / `fail` are swallowed — the\n * top-level run owns the stream's lifecycle, so a finished/failed child must not close or error the\n * shared stream out from under the parent that is still running. They do `flush` it: a sink that\n * gathers frames (the SQL sink) writes out what the child left, so the parent's next frame —\n * possibly written on another replica — lands after it.\n */\nexport function childSinkWriter(writer: SinkWriter): SinkWriter {\n return {\n write: (chunk) => writer.write(chunk),\n // The top-level run owns end/fail — but what the child wrote must not be held back past it.\n end: async () => {\n await writer.flush?.();\n },\n fail: async () => {\n await writer.flush?.();\n },\n flush: async () => {\n await writer.flush?.();\n },\n };\n}\n","import type { AgentAttachmentConfig, AttachmentStagingStore } from '@dudousxd/nestjs-agent-core';\nimport type { AgentModuleOptions } from './agent.options.js';\n\n/** Default per-file size cap (20 MiB). */\nexport const DEFAULT_MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024;\n\n/** Default allowlist: what multimodal model providers commonly accept as native image/file parts. */\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/** How many attachments one message may name. */\nexport const MAX_ATTACHMENTS_PER_MESSAGE = 10;\n\n/** The attachment rules in force — `AgentAttachmentConfig`, as `GET <base>/config` serves it. */\nexport type AttachmentLimits = AgentAttachmentConfig;\n\n/**\n * One source for attachment limits: the staging store's own `describe()` when it declares them\n * (`AgentMediaAttachmentsModule` does), else `AgentModule`'s `attachments` option, else the defaults.\n */\nexport function attachmentLimits(\n options: Pick<AgentModuleOptions, 'attachments'> | undefined,\n staging: AttachmentStagingStore | undefined,\n): AttachmentLimits {\n const declared = staging?.describe?.();\n const own = options?.attachments;\n return {\n enabled: staging !== undefined,\n upload: staging === undefined ? null : (declared?.upload ?? 'multipart'),\n maxBytes: declared?.maxBytes ?? own?.maxBytes ?? DEFAULT_MAX_ATTACHMENT_BYTES,\n allowedContentTypes:\n declared?.allowedContentTypes ??\n own?.allowedContentTypes ??\n DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES,\n maxPerMessage: MAX_ATTACHMENTS_PER_MESSAGE,\n };\n}\n","import {\n AGENT_OPTIONS,\n AGENT_STORE,\n type ActionProposalMutationView,\n type ActionProposalOutcomeStore,\n type ActionProposalScope,\n type ActionProposalStore,\n type ActionProposalView,\n type Actor,\n type AgentStore,\n DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES,\n DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY,\n type ListActionProposals,\n type TextActionProposalReplies,\n type TextActionProposalVocabulary,\n mayDecideApproval,\n parseTextActionProposalCommand,\n resolveTextActionProposalDecision,\n textActionProposalReply,\n toActionProposalMutationView,\n toActionProposalView,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n ForbiddenException,\n Inject,\n Injectable,\n NotFoundException,\n NotImplementedException,\n} from '@nestjs/common';\nimport type { AgentModuleOptions } from '../agent.options.js';\n\n@Injectable()\nexport class ActionProposalService {\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_OPTIONS)\n private readonly options: Pick<AgentModuleOptions, 'approvalPolicy' | 'actionProposalText'>,\n ) {\n const text = options.actionProposalText;\n this.vocabulary = { ...DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY, ...text?.vocabulary };\n this.replies = { ...DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES, ...text?.replies };\n }\n /** The words a text decision is made of, and what the agent answers — English unless configured. */\n private readonly vocabulary: TextActionProposalVocabulary;\n private readonly replies: TextActionProposalReplies;\n private hasCapability(): boolean {\n const store = this.store as Partial<ActionProposalStore & ActionProposalOutcomeStore>;\n return (\n typeof store.getThreadActionProposalScope === 'function' &&\n typeof store.listActionProposals === 'function'\n );\n }\n private capability(): AgentStore & ActionProposalStore & ActionProposalOutcomeStore {\n const store = this.store as AgentStore & ActionProposalStore & ActionProposalOutcomeStore;\n if (!this.hasCapability())\n throw new NotImplementedException('Action proposals are unavailable');\n return store;\n }\n private async scope(threadId: string, actor: Actor): Promise<ActionProposalScope> {\n const scope = await this.capability().getThreadActionProposalScope(threadId);\n if (!scope) throw new NotFoundException('Thread not found');\n if (scope.tenantRef !== (actor.tenantRef ?? null))\n throw new ForbiddenException('Wrong proposal tenant');\n return scope;\n }\n private mayDecide(\n actor: Actor,\n proposal: { originToolCallId: string; approver: string; actorRef: string },\n ) {\n return mayDecideApproval(this.options.approvalPolicy, actor, {\n toolCallId: proposal.originToolCallId,\n approver: proposal.approver,\n requesterRef: proposal.actorRef,\n });\n }\n /**\n * One page of a thread's proposals this actor may see. A store without the proposal capability\n * can only run blocking approvals, so a thread there has no proposals: an empty, final page rather\n * than `501` — a client that lists by default (React's `useAgentChat`) needs no flag. Deciding one\n * still answers `501`.\n */\n async listPage(\n threadId: string,\n actor: Actor,\n query: Pick<ListActionProposals, 'after'> = {},\n ): Promise<{ items: ActionProposalView[]; next?: NonNullable<ListActionProposals['after']> }> {\n if (!this.hasCapability()) return { items: [] };\n const scope = await this.scope(threadId, actor);\n const rows = await this.capability().listActionProposals(scope, { limit: 1000, ...query });\n const visible = [];\n for (const row of rows)\n if (scope.actorRef === actor.id || (await this.mayDecide(actor, row))) visible.push(row);\n const last = rows.at(-1);\n return {\n // The public view: a row carries the worker's lease token and the tool's idempotency key.\n items: visible.map(toActionProposalView),\n ...(rows.length === 1000 && last ? { next: { createdAt: last.createdAt, id: last.id } } : {}),\n };\n }\n async list(threadId: string, actor: Actor) {\n return (await this.listPage(threadId, actor)).items;\n }\n async decide(\n threadId: string,\n proposalId: string,\n actor: Actor,\n command: {\n decision: 'approved' | 'rejected';\n remember?: boolean;\n reason?: string;\n via?: string;\n },\n ): Promise<ActionProposalMutationView> {\n const scope = await this.scope(threadId, actor);\n const proposal = await this.capability().getActionProposal(scope, proposalId);\n if (!proposal) throw new NotFoundException('Proposal not found');\n if (!(await this.mayDecide(actor, proposal)))\n throw new ForbiddenException('May not decide this proposal');\n const result = await this.capability().decideActionProposal(scope, proposalId, {\n decision: command.decision,\n actorRef: actor.id,\n via: command.via ?? 'web',\n ...(command.remember !== undefined ? { remember: command.remember } : {}),\n ...(command.reason !== undefined ? { reason: command.reason } : {}),\n });\n return toActionProposalMutationView(result);\n }\n async handleTextDecision(threadId: string, actor: Actor, text: string) {\n const command = parseTextActionProposalCommand(text, this.vocabulary);\n if (command.status === 'unmatched') return command;\n if (command.proposalId !== undefined) {\n const result = await this.decide(threadId, command.proposalId, actor, {\n decision: command.decision,\n remember: command.remember,\n via: 'text',\n });\n return this.textReceipt(threadId, result, command.decision);\n }\n const candidates = [];\n const scope = await this.scope(threadId, actor);\n const pending = await this.capability().listActionProposals(scope, {\n decision: 'pending',\n limit: 1000,\n });\n for (const proposal of pending)\n if (await this.mayDecide(actor, proposal)) candidates.push(proposal);\n const resolution = resolveTextActionProposalDecision(text, candidates, this.vocabulary);\n if (resolution.status === 'unmatched') return resolution;\n // A saturated page may hide other candidates: a bare command cannot safely pick one.\n const saturated = pending.length === 1000 && !text.includes('#');\n if (resolution.status === 'ambiguous' || saturated) {\n const proposalIds = candidates.map(({ id }) => id);\n return {\n threadId,\n proposalDecision: { status: 'ambiguous' as const, proposalIds },\n text: saturated ? this.replies.tooMany : this.replies.ambiguous(proposalIds),\n };\n }\n const result = await this.decide(threadId, resolution.proposalId, actor, {\n decision: resolution.decision,\n remember: resolution.remember,\n via: 'text',\n });\n return this.textReceipt(threadId, result, resolution.decision);\n }\n private textReceipt(\n threadId: string,\n result: ActionProposalMutationView,\n decision: 'approved' | 'rejected',\n ) {\n return { threadId, proposalDecision: result, text: this.reply(result, decision) };\n }\n /** The configured words a text decision is made of (`actionProposalText.vocabulary`). */\n textVocabulary(): TextActionProposalVocabulary {\n return this.vocabulary;\n }\n /** The configured reply to a decision the store answered with `result`. */\n reply(\n result: Pick<ActionProposalMutationView, 'status' | 'proposal'>,\n decision: 'approved' | 'rejected',\n ): string {\n return textActionProposalReply(result, decision, this.replies);\n }\n}\n","import {\n AGENT_ATTACHMENT_STAGING,\n AGENT_DEPS_FACTORY,\n AGENT_OPTIONS,\n AGENT_QUOTA_PROVIDER,\n AGENT_SINK,\n AGENT_STORE,\n type Actor,\n type AgentRunInput,\n type AgentRunner,\n type AgentStore,\n type AgentStreamEvent,\n type AttachmentStagingStore,\n type ChatQueueState,\n type ChatQueueStore,\n type MessageAttachment,\n type QueuePause,\n type QueuePauseReason,\n type QueuedMessage,\n type QuotaProvider,\n type TokenStreamSink,\n encodeStreamEvent,\n isChatQueueStore,\n queuedMessageView,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, NotImplementedException, Optional } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { utcDay } from '../agent-deps.js';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { publishQuotaBlocked } from '../quota-exceeded.js';\nimport { threadPersona } from '../thread-persona.js';\n\n/** How the run that held a thread ended. */\nexport type QueueSettleOutcome = 'completed' | 'failed' | 'cancelled';\n\n/** The next queued message a settling run handed the thread to — the caller starts it. */\nexport interface QueuedTurn {\n /** The run id the thread is already claimed for: the queued message's own id. */\n runId: string;\n input: AgentRunInput;\n messageId: string;\n}\n\n/**\n * What {@link ChatQueueService.plan} decided. Plain data, so a durable workflow can journal it in a\n * `localStep` and start `next` itself (`ctx.startChild`) — replay-safe, and never twice.\n */\nexport interface QueuePlan {\n next?: QueuedTurn;\n /** The `queue` frame to write into the settling run's stream, before its terminal. */\n frame?: AgentStreamEvent;\n}\n\n/** Starts a run under a pre-claimed id — a runner's own `start`, bound. */\nexport type QueuedTurnStarter = (input: AgentRunInput, runId: string) => Promise<unknown>;\n\n/** How many times a drain retries when the head it picked is removed under it. */\nconst MAX_DRAIN_ATTEMPTS = 8;\n\n/**\n * The thread-level message queue: messages a person sends while a turn is running wait here, and\n * the next one starts as soon as the running turn settles.\n *\n * Everything that decides WHICH run holds a thread goes through the store's compare-and-set\n * admission (`claimActiveStream` / `releaseActiveStream`), so two processes that both try to start\n * the next turn — a settling run on a worker and a send on an API pod — cannot both win. The next\n * run's id is the queued message's own id, which makes every step here idempotent: a retried claim\n * for the same message succeeds again, and a durable start under the same id is a no-op.\n *\n * Policy, per outcome of the run that held the thread:\n * - `completed` → the head starts.\n * - `failed` → the queue pauses (`run_failed`), keeping every message.\n * - `cancelled` → the queue pauses (`cancelled`), unless the head was queued by an interrupt — the\n * cancel was made for it, so it starts.\n * A paused queue starts nothing until it is resumed. A head whose actor is over quota pauses it\n * (`quota_exceeded`) instead of starting.\n */\n@Injectable()\nexport class ChatQueueService {\n private readonly logger = new Logger(ChatQueueService.name);\n /**\n * Runs this process claimed a thread for and has not handed to a runner yet. A holder in here is\n * alive whatever the runner says — it simply has not registered the run yet.\n */\n private readonly starting = new Set<string>();\n\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_SINK) private readonly sink: TokenStreamSink,\n @Optional()\n @Inject(AGENT_QUOTA_PROVIDER)\n private readonly quotaProvider?: QuotaProvider,\n @Optional()\n @Inject(AGENT_OPTIONS)\n private readonly options?: Pick<AgentModuleOptions, 'quota'>,\n @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging?: AttachmentStagingStore,\n // Optional: a queue built outside the module (a test, a host's own wiring) resolves no persona\n // for a message that did not carry one, which is how such a message always started.\n @Optional()\n @Inject(AGENT_DEPS_FACTORY)\n private readonly deps?: AgentDepsFactory,\n ) {}\n\n /** Whether the bound store can hold a queue. Without one, a busy thread is not queued. */\n get supported(): boolean {\n return isChatQueueStore(this.store);\n }\n\n /** The bound store as a queue store, or a 501 naming what is missing. */\n queueStore(): AgentStore & ChatQueueStore {\n if (!isChatQueueStore(this.store)) {\n throw new NotImplementedException(\n 'Queueing messages requires an AgentStore that implements ChatQueueStore (enqueueMessage, ' +\n 'listQueue, …, claimActiveStream, releaseActiveStream); the bound store does not.',\n );\n }\n return this.store;\n }\n\n async state(threadId: string): Promise<ChatQueueState> {\n const store = this.queueStore();\n const [items, paused] = await Promise.all([\n store.listQueue(threadId),\n store.queuePause(threadId),\n ]);\n return { items: items.map(queuedMessageView), paused };\n }\n\n /**\n * Whether `holder` is still running. A run this process is about to start is; otherwise the\n * runner decides, and a runner that cannot tell says yes.\n */\n async isAlive(holder: string, runner: AgentRunner): Promise<boolean> {\n if (this.starting.has(holder)) {\n return true;\n }\n if (typeof runner.isRunActive !== 'function') {\n return true;\n }\n try {\n return await runner.isRunActive(holder);\n } catch {\n return true;\n }\n }\n\n /**\n * The run holding `threadId`, or `null` when it is free — a holder the runner reports dead counts\n * as free, and is returned as `stale` so the caller can claim over it.\n */\n async holder(\n threadId: string,\n runner: AgentRunner,\n ): Promise<{ live: string | null; stale: string | null }> {\n const holder = await this.queueStore().activeRunForThread(threadId);\n if (holder === null) {\n return { live: null, stale: null };\n }\n return (await this.isAlive(holder, runner))\n ? { live: holder, stale: null }\n : { live: null, stale: holder };\n }\n\n /**\n * Decide what follows a TOP-LEVEL run that is settling on `threadId`, and move the thread there:\n * hand it to the next queued message (claimed and popped here, started by the caller), or pause\n * the queue, or release the thread. Call it BEFORE the run's terminal frame, so a client reading\n * the stream learns what comes next from the `queue` frame, and so the thread is already free\n * when the client sees the run end.\n *\n * A no-op returning `{}` on a store without a queue.\n */\n async plan(args: {\n threadId: string;\n /** The run that is settling; `null` when the thread is idle (a kick). */\n runId: string | null;\n outcome: QueueSettleOutcome;\n error?: string;\n }): Promise<QueuePlan> {\n if (!isChatQueueStore(this.store)) {\n return {};\n }\n const store = this.store;\n const { threadId, outcome } = args;\n // Only the run holding the thread moves it on. One that already handed it over (a durable\n // cancel settles from outside the body, and the body may still settle after it) has nothing\n // left to decide — deciding again would pause a queue the handover just started.\n if ((await store.activeRunForThread(threadId)) !== args.runId) {\n return {};\n }\n // The id holding the thread right now, as far as this drain knows: the settling run, until it\n // is released, then nobody.\n let holding: string | null = args.runId;\n for (let attempt = 0; attempt < MAX_DRAIN_ATTEMPTS; attempt += 1) {\n const items = await store.listQueue(threadId);\n const head = items[0];\n if (head === undefined) {\n if (holding !== null) {\n await store.releaseActiveStream(threadId, holding);\n holding = null;\n // An enqueue that landed between the read above and this release saw the thread held and\n // left its message for this drain — read once more now that the thread is free.\n continue;\n }\n return {};\n }\n let pause = await store.queuePause(threadId);\n if (pause === null) {\n const reason = pauseReasonFor(outcome, head);\n if (reason !== null) {\n pause = {\n reason,\n ...(outcome === 'failed' && args.error !== undefined ? { message: args.error } : {}),\n at: new Date().toISOString(),\n };\n await store.setQueuePause(threadId, pause);\n }\n }\n if (pause === null) {\n const blocked = await this.quotaBlock(head.actor);\n if (blocked !== null) {\n pause = { reason: 'quota_exceeded', message: blocked, at: new Date().toISOString() };\n await store.setQueuePause(threadId, pause);\n }\n }\n if (pause !== null) {\n if (holding !== null) {\n await store.releaseActiveStream(threadId, holding);\n }\n return { frame: queueFrame(items, pause) };\n }\n const claimed = await store.claimActiveStream(\n threadId,\n head.id,\n holding !== null ? { replacing: holding } : {},\n );\n if (!claimed) {\n // Someone else holds the thread now (a send that got in first); its own settle drains.\n return {};\n }\n holding = head.id;\n if (!(await store.removeQueuedMessage(head.id))) {\n // Removed (or started) under us between the read and the claim: give the claim back and\n // look at the new head.\n await store.releaseActiveStream(threadId, head.id);\n holding = null;\n continue;\n }\n const next: QueuedTurn = {\n runId: head.id,\n messageId: head.id,\n input: await this.inputFor(head),\n };\n return {\n next,\n frame: queueFrame(items.slice(1), null, { messageId: head.id, runId: head.id }),\n };\n }\n // Pathological churn (every head removed under us): leave the thread free rather than spin.\n if (holding !== null) {\n await store.releaseActiveStream(threadId, holding);\n }\n return {};\n }\n\n /**\n * {@link plan}, then start what it picked with `start`. What an in-process settle (the inline\n * runner, a durable cancel issued outside a workflow) calls; answers the frame to write.\n */\n async handoff(\n args: { threadId: string; runId: string; outcome: QueueSettleOutcome; error?: string },\n start: QueuedTurnStarter,\n ): Promise<AgentStreamEvent | undefined> {\n const plan = await this.plan(args);\n if (plan.next === undefined) {\n return plan.frame;\n }\n return (await this.launch(args.threadId, plan.next, start))\n ? plan.frame\n : this.pausedFrame(args.threadId);\n }\n\n /**\n * Start the head of an IDLE thread's queue — after a send queued behind a run that turned out to\n * be gone, after a resume, after a stale holder. Does nothing while a live run holds the thread\n * (its settle drains) or while the queue is paused. Answers the started run's id, if any.\n */\n async kick(threadId: string, runner: AgentRunner): Promise<string | undefined> {\n if (!isChatQueueStore(this.store)) {\n return undefined;\n }\n const { live, stale } = await this.holder(threadId, runner);\n if (live !== null) {\n return undefined;\n }\n if (stale !== null) {\n this.logger.warn(`thread ${threadId} was held by run ${stale}, which is no longer running`);\n }\n // Planned as if the stale holder completed: nothing it did pauses the queue.\n const plan = await this.plan({ threadId, runId: stale, outcome: 'completed' });\n if (plan.next === undefined) {\n return undefined;\n }\n const started = await this.launch(threadId, plan.next, (input, runId) =>\n runner.start(input, { runId }),\n );\n if (started && plan.frame !== undefined) {\n // The new run's own stream is where a client attached to nothing yet learns about it.\n await this.write(plan.next.runId, plan.frame);\n }\n return started ? plan.next.runId : undefined;\n }\n\n /**\n * Start a turn the thread is already claimed for. On failure the message goes back to the head of\n * the queue, the queue pauses (`start_failed`), and the claim is released — nothing is lost and\n * nothing is left holding the thread.\n */\n async launch(threadId: string, next: QueuedTurn, start: QueuedTurnStarter): Promise<boolean> {\n this.starting.add(next.runId);\n try {\n await start(next.input, next.runId);\n return true;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.logger.error(`queued message ${next.messageId} could not start: ${message}`);\n await this.restore(threadId, next, 'start_failed', message);\n return false;\n } finally {\n this.starting.delete(next.runId);\n }\n }\n\n /** Put a turn that never started back at the head of its queue, paused, and free the thread. */\n async restore(\n threadId: string,\n next: QueuedTurn,\n reason: QueuePauseReason,\n message: string,\n ): Promise<void> {\n const store = this.queueStore();\n const { input } = next;\n await store.enqueueMessage({\n threadId,\n actor: input.actor,\n content: input.userText,\n at: 'head',\n ...(input.attachments !== undefined ? { attachments: input.attachments } : {}),\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),\n ...(input.uiCapabilities !== undefined ? { uiCapabilities: input.uiCapabilities } : {}),\n ...(input.hostContext !== undefined ? { hostContext: input.hostContext } : {}),\n });\n await store.setQueuePause(threadId, { reason, message, at: new Date().toISOString() });\n await store.releaseActiveStream(threadId, next.runId);\n }\n\n /** A `queue` frame with the thread's current state. */\n async pausedFrame(threadId: string): Promise<AgentStreamEvent> {\n return { kind: 'queue', queue: await this.state(threadId) };\n }\n\n /**\n * Tell whoever is watching the thread that its queue changed: a `queue` frame into the stream of\n * the run holding it. Best-effort — a thread nobody is streaming has no one to tell, and the next\n * read of the thread carries the queue anyway.\n */\n async publish(threadId: string): Promise<ChatQueueState> {\n const state = await this.state(threadId);\n const holder = await this.queueStore().activeRunForThread(threadId);\n if (holder !== null) {\n await this.write(holder, { kind: 'queue', queue: state }).catch((error: unknown) => {\n this.logger.warn(\n `could not publish the queue of thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`,\n );\n });\n }\n return state;\n }\n\n private async write(runId: string, frame: AgentStreamEvent): Promise<void> {\n const writer = await this.sink.open(runId);\n await writer.write(encodeStreamEvent(frame));\n }\n\n /** Why `actor` may not start a turn now (the quota message), or `null`. */\n async quotaBlock(actor: Actor): Promise<string | null> {\n if (this.options?.quota === undefined || this.quotaProvider === undefined) {\n return null;\n }\n try {\n const report = await this.quotaProvider.report({ actor });\n const { blocked } = report;\n if (blocked === undefined) {\n return null;\n }\n publishQuotaBlocked(actor, report, blocked);\n return (\n blocked.reason ?? `The ${blocked.period === 'day' ? 'daily' : 'monthly'} quota is used up`\n );\n } catch {\n // Failing to ask is not a verdict; the turn's own quota gate still runs.\n return null;\n }\n }\n\n /**\n * The turn a queued message starts: everything it was queued with, today's date, and its\n * attachments' urls minted afresh — the ones stored at enqueue time may have expired while it\n * waited. An attachment the staging store no longer resolves keeps its stored url.\n */\n private async inputFor(message: QueuedMessage): Promise<AgentRunInput> {\n const attachments = await this.freshAttachments(message.actor, message.attachments ?? []);\n const { agentName, persona } = await this.targetFor(message);\n return {\n threadId: message.threadId,\n actor: message.actor,\n userText: message.content,\n day: utcDay(),\n ...(agentName !== undefined ? { agentName } : {}),\n ...(persona !== undefined ? { persona } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n ...(message.pageContext !== undefined ? { pageContext: message.pageContext } : {}),\n ...(message.uiCapabilities !== undefined ? { uiCapabilities: message.uiCapabilities } : {}),\n ...(message.hostContext !== undefined ? { hostContext: message.hostContext } : {}),\n ...(message.model !== undefined ? { model: message.model } : {}),\n };\n }\n\n /**\n * The agent and persona a queued message starts as. A message carries the persona its send\n * resolved; one that carries none — queued before personas existed, or by a host that sets none —\n * resolves it now, exactly as a send would: an agent name a persona took over, then the thread's\n * pinned persona, then the agent's default. Never refused here: nobody is waiting on a 400.\n */\n private async targetFor(\n message: QueuedMessage,\n ): Promise<{ agentName?: string; persona?: string }> {\n const deps = this.deps;\n if (message.persona !== undefined || deps === undefined || message.agentName === undefined) {\n return {\n ...(message.agentName !== undefined ? { agentName: message.agentName } : {}),\n ...(message.persona !== undefined ? { persona: message.persona } : {}),\n };\n }\n const target = deps.resolveAgent(message.agentName);\n const hasPersonas = deps.personaCatalog(target.agentName).length > 0;\n const persona =\n target.persona ??\n (hasPersonas\n ? deps.resolvePersona({\n agentName: target.agentName,\n threadPersona: await threadPersona(this.store, message.threadId),\n })\n : undefined);\n return { agentName: target.agentName, ...(persona !== undefined ? { persona } : {}) };\n }\n\n private async freshAttachments(\n actor: Actor,\n attachments: MessageAttachment[],\n ): Promise<MessageAttachment[]> {\n const staging = this.staging;\n if (\n attachments.length === 0 ||\n staging === undefined ||\n typeof staging.resolve !== 'function'\n ) {\n return attachments;\n }\n return Promise.all(\n attachments.map(async (attachment) => {\n try {\n return (await staging.resolve({ mediaId: attachment.mediaId, actor })) ?? attachment;\n } catch {\n return attachment;\n }\n }),\n );\n }\n}\n\n/** The pause a settling run's outcome imposes on a non-empty queue, or `null` to keep draining. */\nfunction pauseReasonFor(outcome: QueueSettleOutcome, head: QueuedMessage): QueuePauseReason | null {\n if (outcome === 'failed') {\n return 'run_failed';\n }\n if (outcome === 'cancelled' && head.interrupt !== true) {\n return 'cancelled';\n }\n return null;\n}\n\nfunction queueFrame(\n items: QueuedMessage[],\n paused: QueuePause | null,\n started?: { messageId: string; runId: string },\n): AgentStreamEvent {\n return {\n kind: 'queue',\n queue: { items: items.map(queuedMessageView), paused },\n ...(started !== undefined ? { started } : {}),\n };\n}\n","import {\n type Actor,\n type AgentQuotaExceeded,\n type QuotaBlock,\n type QuotaReport,\n publishAgentQuotaExceeded,\n} from '@dudousxd/nestjs-agent-core';\n\n/**\n * Publish `aviary:agent:quota.exceeded` for a turn refused on `report.blocked`, with the exhausted\n * window's figures — what the dashboard's live feed and Telescope read. Whoever refuses the turn\n * calls this: the send gate and the message queue.\n */\nexport function publishQuotaBlocked(actor: Actor, report: QuotaReport, blocked: QuotaBlock): void {\n const window = report.windows.find((candidate) => candidate.period === blocked.period);\n const payload: AgentQuotaExceeded = {\n actorId: actor.id,\n period: blocked.period,\n ...(blocked.reason !== undefined ? { reason: blocked.reason } : {}),\n ...(window?.usedTokens !== undefined ? { usedTokens: window.usedTokens } : {}),\n ...(window?.limitTokens !== undefined ? { limitTokens: window.limitTokens } : {}),\n ...(window !== undefined ? { usedUsd: window.usedUsd } : {}),\n ...(window?.limitUsd !== undefined ? { limitUsd: window.limitUsd } : {}),\n };\n publishAgentQuotaExceeded(payload);\n}\n","import type { AgentStore } from '@dudousxd/nestjs-agent-core';\n\n/**\n * A store that can answer a thread's pinned persona on its own, without materializing the thread —\n * probed structurally, like `ThreadDefaultAgentReader`.\n */\nexport interface ThreadPersonaReader {\n personaForThread(threadId: string): Promise<string | null>;\n}\n\n/**\n * The thread's pinned persona: one column when the store projects it ({@link ThreadPersonaReader}),\n * else through the full read.\n */\nexport async function threadPersona(store: AgentStore, threadId: string): Promise<string | null> {\n const projecting = store as Partial<ThreadPersonaReader>;\n if (typeof projecting.personaForThread === 'function') {\n return projecting.personaForThread(threadId);\n }\n return (await store.getThread(threadId))?.persona ?? null;\n}\n","import { RUN_NOT_ACTIVE_CODE, RUN_NOT_ACTIVE_MESSAGE } from '@dudousxd/nestjs-agent-core';\nimport { ConflictException } from '@nestjs/common';\n\n/**\n * `approve` / `reject` / `answer` / `skip` addressed at a run that is no longer running — answered\n * `409 { code: 'run_not_active', message }`.\n *\n * The runtime would take the signal and buffer it for a run that never comes back: the person's\n * \"yes\" is accepted, the card says so, and nothing runs. Refusing it is what lets a client say so.\n */\nexport class RunNotActiveException extends ConflictException {\n readonly code = RUN_NOT_ACTIVE_CODE;\n\n constructor(readonly runId: string) {\n super({ statusCode: 409, code: RUN_NOT_ACTIVE_CODE, message: RUN_NOT_ACTIVE_MESSAGE });\n }\n}\n","import type { Actor, AgentApprovalPort } from '@dudousxd/nestjs-agent-core';\nimport { Injectable, NotImplementedException, Optional } from '@nestjs/common';\nimport { AgentService } from './agent.service.js';\nimport { ActionProposalService } from './proposals/action-proposal.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(\n private readonly agent: AgentService,\n @Optional() private readonly proposals?: ActionProposalService,\n ) {}\n async approveActionProposal(\n actor: Actor,\n target: { kind: 'proposal'; threadId: string; proposalId: string },\n opts?: { remember?: boolean; decidedVia?: string },\n ) {\n if (!this.proposals) throw new NotImplementedException('Action proposals unavailable');\n return this.proposals.decide(target.threadId, target.proposalId, actor, {\n decision: 'approved',\n ...(opts?.remember !== undefined ? { remember: opts.remember } : {}),\n via: opts?.decidedVia ?? 'console',\n });\n }\n async rejectActionProposal(\n actor: Actor,\n target: { kind: 'proposal'; threadId: string; proposalId: string },\n opts?: { reason?: string; decidedVia?: string },\n ) {\n if (!this.proposals) throw new NotImplementedException('Action proposals unavailable');\n return this.proposals.decide(target.threadId, target.proposalId, actor, {\n decision: 'rejected',\n ...(opts?.reason !== undefined ? { reason: opts.reason } : {}),\n via: opts?.decidedVia ?? 'console',\n });\n }\n\n async approve(\n toolCallId: string,\n opts?: { executedByRef?: string; remember?: boolean; decidedVia?: string },\n ): Promise<void> {\n await this.agent.signalToolCall(toolCallId, {\n approved: true,\n ...(opts?.executedByRef !== undefined ? { executedByRef: opts.executedByRef } : {}),\n ...(opts?.remember === true ? { remember: true } : {}),\n ...(opts?.decidedVia !== undefined ? { decidedVia: opts.decidedVia } : {}),\n });\n }\n\n async reject(\n toolCallId: string,\n opts?: { executedByRef?: string; reason?: string; decidedVia?: 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 ...(opts?.decidedVia !== undefined ? { decidedVia: opts.decidedVia } : {}),\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/**\n * Lists the registered `@Agent`s — and each one's personas — so a host can render an agent or\n * persona picker instead of hardcoding one.\n */\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 const personas = this.depsFactory.personaCatalog(definition.name);\n return {\n name: definition.name,\n description: definition.description ?? '',\n ...(definition.name === defaultAgentName ? { isDefault: true } : {}),\n ...(personas.length > 0 ? { personas } : {}),\n ...(definition.defaultPersona !== undefined\n ? { defaultPersona: definition.defaultPersona }\n : {}),\n };\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 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';\nimport { attachmentLimits } from '../attachment-limits.js';\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 * `POST <base>/attachments` — the multipart upload route, live whenever an\n * `AGENT_ATTACHMENT_STAGING` provider is bound (`501` otherwise). 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 {\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 * 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 throw new NotImplementedException(\n 'Attachment upload is not configured on this server: bind AGENT_ATTACHMENT_STAGING ' +\n '(e.g. import AgentMediaAttachmentsModule).',\n );\n }\n if (file === undefined) {\n throw new BadRequestException('multipart field \"file\" is required');\n }\n const { allowedContentTypes, maxBytes } = attachmentLimits(this.options, this.staging);\n if (!allowedContentTypes.includes(file.mimetype)) {\n throw new UnsupportedMediaTypeException(\n `content type \"${file.mimetype}\" is not allowed (allowed: ${allowedContentTypes.join(', ')})`,\n );\n }\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 streamFailure,\n} from '@dudousxd/nestjs-agent-core';\nimport { type UiCapabilities, validateUiCapabilities } from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n Body,\n Controller,\n Get,\n Inject,\n Param,\n Post,\n Query,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AgentService, type ChatSendMode } from '../agent.service.js';\nimport { MAX_ATTACHMENTS_PER_MESSAGE } from '../attachment-limits.js';\n\ninterface ChatBody {\n uiCapabilities?: unknown;\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 * One of the agent's personas (`@Agent({ personas })`) to answer as — pinned on the thread. 400\n * `persona_not_found` when the agent declares none by that id.\n */\n persona?: 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 /** Run this turn on a catalog model (see `GET models`) instead of the thread's pinned one. */\n model?: string;\n /**\n * What to do when the thread already has a turn running: `'auto'` (default) queues it, `'queue'`\n * always queues it (behind anything already waiting), `'interrupt'` cancels the running turn and\n * runs this next. See `ChatSendMode`.\n */\n mode?: unknown;\n /** Shorthand for `mode: 'interrupt'`. */\n interrupt?: boolean;\n}\n\n/** The send mode a body asked for, or a 400. */\nfunction sendMode(body: ChatBody): ChatSendMode {\n if (body.interrupt === true) {\n return 'interrupt';\n }\n if (body.mode === undefined || body.mode === null) {\n return 'auto';\n }\n if (body.mode === 'auto' || body.mode === 'queue' || body.mode === 'interrupt') {\n return body.mode;\n }\n throw new BadRequestException(\"mode must be 'auto', 'queue' or 'interrupt'\");\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 */\nexport function 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 // One shape: a ref names an upload, nothing more. A full attachment (url, name, …) is refused\n // rather than trimmed, so a client that still sends one learns it instead of relying on it.\n if (Object.keys(entry).some((key) => key !== 'mediaId')) {\n throw new BadRequestException('attachments are { mediaId } refs — send nothing but the id');\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 /**\n * Start a turn and stream it — or, when the thread already has one running, queue the message and\n * answer `202 { queued: true, messageId, position, queue, … }` (JSON, no stream): it runs when the\n * turn ahead of it settles, and the stream of the run holding the thread announces it with a\n * `queue` frame.\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 mode = sendMode(body);\n let uiCapabilities: UiCapabilities | undefined;\n try {\n uiCapabilities =\n body.uiCapabilities === undefined ? undefined : validateUiCapabilities(body.uiCapabilities);\n } catch {\n throw new BadRequestException('Invalid UI capabilities');\n }\n const result = await this.agent.send({\n actor,\n message: body.message,\n ...(uiCapabilities !== undefined ? { uiCapabilities } : {}),\n ...(body.threadId !== undefined ? { threadId: body.threadId } : {}),\n ...(body.agent !== undefined ? { agentName: body.agent } : {}),\n ...(typeof body.persona === 'string' && body.persona.length > 0\n ? { personaId: body.persona }\n : {}),\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 ...(typeof body.model === 'string' && body.model.length > 0 ? { model: body.model } : {}),\n mode,\n });\n if ('proposalDecision' in result) {\n res.status(200).json(result);\n return;\n }\n if (result.queued === true) {\n res.status(202).json(result);\n return;\n }\n const { runId, threadId } = result;\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 /**\n * Attach to a run's stream: every buffered frame, then live ones. `?after=<seq>` (or the SSE\n * `Last-Event-ID` header a browser `EventSource` sends on its own) skips the frames a reconnecting\n * client already has — see {@link pipe} for how frames are numbered.\n */\n @Get('chat/:runId/stream')\n async stream(\n @Req() req: Request,\n @Param('runId') runId: string,\n @Res() res: Response,\n @Query('after') after?: string,\n ): Promise<void> {\n const actor = await this.actorResolver.resolve(req);\n const cursor = parseCursor(after) ?? parseCursor(req.headers['last-event-id']) ?? 0;\n await this.pipe(res, runId, await this.agent.subscribeAs(actor, runId), undefined, cursor);\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 /**\n * Every `data:` frame carries an SSE `id:` — its 1-based sequence number within the run. The\n * number is a pure function of the run's buffered stream (every sink replays a run from its first\n * chunk, in write order), so the same frame gets the same number on the POST that started the run\n * and on any later `GET …/stream`, whichever replica serves it. A reconnecting client passes the\n * last one it saw as `?after=`; frames at or below it are read off the sink but not re-sent.\n * `meta`, `done` and `error` carry no id: `meta` is re-sent on every attach, the terminals once.\n */\n private async pipe(\n res: Response,\n runId: string,\n events: AsyncIterable<Uint8Array>,\n threadId?: string,\n after = 0,\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 let seq = 0;\n const forward = (line: string) => {\n seq += 1;\n if (seq > after) {\n res.write(`id: ${seq}\\ndata: ${line}\\n\\n`);\n }\n };\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 forward(line);\n }\n newline = buffer.indexOf('\\n');\n }\n }\n if (buffer.length > 0) {\n forward(buffer);\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 : streamFailure(error);\n res.write(`event: error\\ndata: ${JSON.stringify(payload)}\\n\\n`);\n }\n res.end();\n }\n}\n\n/** A non-negative integer sequence cursor, or `undefined` for anything else (absent, malformed). */\nfunction parseCursor(raw: unknown): number | undefined {\n const value = Array.isArray(raw) ? raw[0] : raw;\n if (typeof value !== 'string' || !/^\\d+$/.test(value.trim())) {\n return undefined;\n }\n const parsed = Number(value.trim());\n return Number.isSafeInteger(parsed) ? parsed : undefined;\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_ATTACHMENT_STAGING,\n AGENT_MODEL_CATALOG,\n AGENT_OPTIONS,\n type ActorResolver,\n type AgentClientConfig,\n type AttachmentStagingStore,\n type ModelCatalog,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Optional, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { attachmentLimits } from '../attachment-limits.js';\nimport { AGENT_GENUI, type AgentGenui } from '../genui/agent-genui.token.js';\nimport { AnonymousActorResolver } from '../resolver/anonymous-actor-resolver.js';\n\n@Controller('config')\nexport class ConfigController {\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n @Optional()\n @Inject(AGENT_ATTACHMENT_STAGING)\n private readonly staging: AttachmentStagingStore | undefined,\n @Optional()\n @Inject(AGENT_MODEL_CATALOG)\n private readonly models: ModelCatalog | undefined,\n @Optional()\n @Inject(AGENT_GENUI)\n private readonly genui: AgentGenui | undefined,\n ) {}\n\n @Get()\n async config(@Req() req: Request): Promise<AgentClientConfig> {\n // Resolved like every other route: the same guards apply, and an anonymous browser gets its\n // identity on the first request whichever route that is.\n await this.actorResolver.resolve(req);\n return {\n attachments: attachmentLimits(this.options, this.staging),\n models: { enabled: this.models !== undefined },\n quota: { enforced: this.options.quota !== undefined },\n identity: { anonymous: this.actorResolver instanceof AnonymousActorResolver },\n ...(this.genui?.sandboxClient !== undefined\n ? { genui: { sandbox: this.genui.sandboxClient() } }\n : {}),\n };\n }\n}\n","import { createHash, randomBytes } from 'node:crypto';\nimport type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\n\nexport interface AnonymousActorOptions {\n /** The cookie holding the browser's anonymous token. Default `agent_anon`. */\n cookieName?: string;\n /** How long a browser keeps its identity (and so its threads). Default 365 days. */\n maxAgeDays?: number;\n /**\n * `SameSite` of the cookie. Default `'lax'` — sent on same-site requests, not on cross-site\n * POSTs. A SPA on another SITE than the API needs `'none'` (which forces `Secure`) plus\n * `credentials: 'include'` on the client.\n */\n sameSite?: 'lax' | 'strict' | 'none';\n /**\n * `Secure` flag. Default `'auto'`: set when the request arrived over HTTPS (`req.secure`, or an\n * `x-forwarded-proto: https` from a proxy).\n */\n secure?: boolean | 'auto';\n /** Cookie path. Default `/`. */\n path?: string;\n /** Roles every anonymous actor carries. Default `['anonymous']`. */\n roles?: string[];\n}\n\nconst TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/;\n/** Where a token minted during this request is remembered, so two resolves in one request agree. */\nconst MINTED = Symbol('nestjs-agent:anonymous-token');\n\ninterface RequestLike {\n headers?: Record<string, string | string[] | undefined>;\n secure?: boolean;\n res?: {\n headersSent?: boolean;\n getHeader?: (name: string) => unknown;\n setHeader?: (name: string, value: string | string[]) => unknown;\n };\n [MINTED]?: string;\n}\n\nfunction readCookie(req: RequestLike, name: string): string | undefined {\n const header = req.headers?.cookie;\n const raw = Array.isArray(header) ? header.join('; ') : header;\n if (raw === undefined) return undefined;\n for (const pair of raw.split(';')) {\n const index = pair.indexOf('=');\n if (index === -1) continue;\n if (pair.slice(0, index).trim() === name) {\n try {\n return decodeURIComponent(pair.slice(index + 1).trim());\n } catch {\n return undefined;\n }\n }\n }\n return undefined;\n}\n\nfunction isHttps(req: RequestLike): boolean {\n if (req.secure === true) return true;\n const forwarded = req.headers?.['x-forwarded-proto'];\n const proto = Array.isArray(forwarded) ? forwarded[0] : forwarded;\n return proto?.split(',')[0]?.trim() === 'https';\n}\n\n/**\n * The zero-config identity: every browser is its own anonymous actor, so a login-less chat still\n * keeps each visitor's threads, quota and attachments apart from everyone else's.\n *\n * On a browser's first request the resolver mints 32 random bytes and sets them as an `HttpOnly`\n * cookie (`SameSite=Lax`, `Secure` over HTTPS). The actor id is a SHA-256 digest of that token —\n * `anon:<digest>` — never the token itself, so an id that surfaces anywhere (a thread row, a log, an\n * approval's `decidedBy`) cannot be replayed as the cookie.\n *\n * Why a server-minted cookie and not an id the client makes up and sends in a header: an\n * `HttpOnly` cookie is out of reach of page scripts (an XSS cannot lift it), the server — not the\n * client — decides the value, and it needs no client code at all. There is no signing secret to\n * configure: the token is unguessable on its own, and the digest works the same on every pod and\n * after a restart.\n *\n * Anonymous identities are per browser, not per person: clearing cookies starts over, and there is\n * nothing to recover them with. Require login with an `ActorResolver` that reads your session —\n * `requestUserActorResolver()` for `req.user` (Passport / cookie-session apps).\n */\nexport class AnonymousActorResolver implements ActorResolver {\n private readonly cookieName: string;\n private readonly roles: string[];\n\n constructor(private readonly options: AnonymousActorOptions = {}) {\n this.cookieName = options.cookieName ?? 'agent_anon';\n this.roles = options.roles ?? ['anonymous'];\n }\n\n resolve(request: unknown): Actor {\n const req = (typeof request === 'object' && request !== null ? request : {}) as RequestLike;\n let token = req[MINTED] ?? readCookie(req, this.cookieName);\n if (token === undefined || !TOKEN_PATTERN.test(token)) {\n token = randomBytes(32).toString('base64url');\n req[MINTED] = token;\n this.setCookie(req, token);\n }\n const digest = createHash('sha256').update(token).digest('base64url').slice(0, 32);\n return { id: `anon:${digest}`, roles: [...this.roles] };\n }\n\n private setCookie(req: RequestLike, token: string): void {\n const res = req.res;\n if (res?.setHeader === undefined || res.headersSent === true) return;\n const sameSite = this.options.sameSite ?? 'lax';\n const secureOption = this.options.secure ?? 'auto';\n const secure = sameSite === 'none' || (secureOption === 'auto' ? isHttps(req) : secureOption);\n const maxAge = Math.round((this.options.maxAgeDays ?? 365) * 24 * 60 * 60);\n const cookie = [\n `${this.cookieName}=${token}`,\n `Path=${this.options.path ?? '/'}`,\n `Max-Age=${maxAge}`,\n 'HttpOnly',\n `SameSite=${sameSite === 'none' ? 'None' : sameSite === 'strict' ? 'Strict' : 'Lax'}`,\n ...(secure ? ['Secure'] : []),\n ].join('; ');\n const existing = res.getHeader?.('Set-Cookie');\n const list = Array.isArray(existing)\n ? existing.map(String)\n : existing !== undefined\n ? [String(existing)]\n : [];\n res.setHeader('Set-Cookie', [...list, cookie]);\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 {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type MessageFeedback,\n type MessageFeedbackValue,\n} from '@dudousxd/nestjs-agent-core';\nimport { Body, Controller, HttpCode, Inject, Param, Post, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\ninterface FeedbackBody {\n /** `null` clears the rating. */\n value: MessageFeedbackValue | null;\n comment?: string;\n}\n\n@Controller('messages')\nexport class MessagesController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n /**\n * Rate a message: `{ value: 'up' | 'down' | null, comment? }`. Answers the stored rating\n * (`{ feedback: null }` once cleared). Only the thread's owner may rate its messages.\n */\n @Post(':id/feedback')\n @HttpCode(200)\n async feedback(\n @Req() req: Request,\n @Param('id') id: string,\n @Body() body: FeedbackBody,\n ): Promise<{ feedback: MessageFeedback | null }> {\n const actor = await this.actorResolver.resolve(req);\n const feedback = await this.agent.setMessageFeedback(actor, id, {\n value: body?.value ?? null,\n ...(body?.comment !== undefined ? { comment: body.comment } : {}),\n });\n return { feedback };\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type ModelCatalogView,\n} from '@dudousxd/nestjs-agent-core';\nimport { Controller, Get, Inject, Query, Req } from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\n\n@Controller('models')\nexport class ModelsController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n /**\n * The models the caller may pick for `agent` (the default agent when omitted), grouped by\n * provider, with badges and availability — the bound `ModelCatalog`'s answer, or an empty one.\n */\n @Get()\n async list(@Req() req: Request, @Query('agent') agent?: string): Promise<ModelCatalogView> {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.listModels(actor, agent);\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type AttachmentRef,\n type ChatQueueState,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Body,\n Controller,\n Delete,\n Get,\n Inject,\n Param,\n Patch,\n Post,\n Req,\n} from '@nestjs/common';\nimport type { Request } from 'express';\nimport { AgentService } from '../agent.service.js';\nimport { attachmentRefs } from './chat.controller.js';\n\ninterface UpdateQueuedMessageBody {\n /** The new text. */\n message?: unknown;\n /** `[{ mediaId }]` refs replacing the message's attachments; `null` or `[]` drops them. */\n attachments?: unknown;\n /** Move the message to this 0-based place in the queue. */\n position?: unknown;\n}\n\n/**\n * The thread message queue: messages sent while a turn was running, waiting to run after it. Every\n * route is ownership-gated like the thread routes, and answers the thread's queue as it now stands\n * (`{ items, paused }`). A change is also announced to whoever is streaming the thread, as a `queue`\n * frame in the running turn's stream.\n */\n@Controller()\nexport class QueueController {\n constructor(\n private readonly agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actorResolver: ActorResolver,\n ) {}\n\n @Get('threads/:id/queue')\n async list(@Req() req: Request, @Param('id') id: string): Promise<ChatQueueState> {\n return this.agent.getQueue(await this.actorResolver.resolve(req), id);\n }\n\n @Delete('threads/:id/queue')\n async clear(@Req() req: Request, @Param('id') id: string): Promise<ChatQueueState> {\n return this.agent.clearQueue(await this.actorResolver.resolve(req), id);\n }\n\n /** Lift a pause; the head starts when nothing is running. Carries `runId` when it started. */\n @Post('threads/:id/queue/resume')\n async resume(\n @Req() req: Request,\n @Param('id') id: string,\n ): Promise<ChatQueueState & { runId?: string }> {\n return this.agent.resumeQueue(await this.actorResolver.resolve(req), id);\n }\n\n @Patch('queue/:messageId')\n async update(\n @Req() req: Request,\n @Param('messageId') messageId: string,\n @Body() body: UpdateQueuedMessageBody,\n ): Promise<ChatQueueState> {\n const actor = await this.actorResolver.resolve(req);\n if (body.message !== undefined && typeof body.message !== 'string') {\n throw new BadRequestException('message must be a string');\n }\n if (body.position !== undefined && typeof body.position !== 'number') {\n throw new BadRequestException('position must be a number');\n }\n const attachments: AttachmentRef[] | null | undefined =\n body.attachments === undefined\n ? undefined\n : body.attachments === null\n ? null\n : attachmentRefs(body.attachments);\n return this.agent.updateQueuedMessage(actor, messageId, {\n ...(body.message !== undefined ? { message: body.message } : {}),\n ...(attachments !== undefined ? { attachments } : {}),\n ...(body.position !== undefined ? { position: body.position } : {}),\n });\n }\n\n /**\n * Run a waiting message now: it moves to the head as an interrupt and the running turn is\n * cancelled for it. Carries `interrupting` (the cancelled run), or `runId` when nothing was\n * running and it started at once.\n */\n @Post('queue/:messageId/interrupt')\n async interrupt(\n @Req() req: Request,\n @Param('messageId') messageId: string,\n ): Promise<ChatQueueState & { runId?: string; interrupting?: string }> {\n return this.agent.interruptQueuedMessage(await this.actorResolver.resolve(req), messageId);\n }\n\n @Delete('queue/:messageId')\n async remove(\n @Req() req: Request,\n @Param('messageId') messageId: string,\n ): Promise<ChatQueueState> {\n return this.agent.removeQueuedMessage(await this.actorResolver.resolve(req), messageId);\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 /**\n * The caller's budget across windows — `{ windows: [{ period, usedTokens, limitTokens?, usedUsd,\n * limitUsd?, resetsAt? }], blocked?: { period, reason? } }` — from the bound `QuotaProvider`.\n */\n @Get()\n async report(@Req() req: Request) {\n const actor = await this.actorResolver.resolve(req);\n return this.agent.quotaReport(actor);\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 /** `null` unpins the thread's model. Omitted → left untouched. Must be offered by the catalog. */\n model?: string | null;\n /** `null` clears the thread's persona. Omitted → left untouched. Must be one the agent declares. */\n persona?: 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 ...('model' in body ? { model: body.model ?? null } : {}),\n ...('persona' in body ? { persona: body.persona ?? 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\n/** A `via` is provenance, persisted on the call — bounded like any other stored label. */\nconst MAX_VIA_LENGTH = 64;\n/** What an HTTP decision is recorded as having come through when the caller names nothing. */\nconst DEFAULT_VIA = 'web';\n\ninterface ApproveBody {\n toolCallId: unknown;\n /** Approve later calls of the same tool in the same thread without asking. */\n remember?: unknown;\n /** The surface the decision came through. Defaults to `'web'`. */\n via?: unknown;\n}\ninterface RejectBody {\n toolCallId: unknown;\n reason?: unknown;\n via?: unknown;\n}\ninterface AnswerBody {\n toolCallId: unknown;\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 /** The surface the answer came through. Defaults to `'web'`. */\n via?: 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\n/** A rejection reason, bounded — it is read back by the model as the tool's result. */\nexport function 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 remember(claimed: unknown): boolean {\n if (claimed === undefined) {\n return false;\n }\n if (typeof claimed !== 'boolean') {\n throw new BadRequestException('remember must be a boolean');\n }\n return claimed;\n}\n\nfunction via(claimed: unknown): string {\n if (claimed === undefined) {\n return DEFAULT_VIA;\n }\n if (typeof claimed !== 'string' || claimed.length === 0 || claimed.length > MAX_VIA_LENGTH) {\n throw new BadRequestException(`via must be a string of 1-${MAX_VIA_LENGTH} characters`);\n }\n return claimed;\n}\n\n/** A reply's answers, bounded and shape-checked before anything is signalled (`400` otherwise). */\nexport function 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 remember: remember(body.remember),\n via: via(body.via),\n });\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 via: via(body.via),\n });\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 via: via(body.via),\n });\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(\n @Req() req: Request,\n @Body() body: { toolCallId: unknown; via?: unknown },\n ): Promise<{ ok: boolean }> {\n const actor = await this.actorResolver.resolve(req);\n await this.agent.skip(actor, toolCallId(body.toolCallId), { via: via(body.via) });\n return { ok: true };\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n AGENT_DEPS_FACTORY,\n AGENT_REGISTRY,\n ALL_AGENTS,\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 /**\n * The agent whose tools to list. Omitted → the default agent, the one a turn naming none uses.\n * `*` → every agent's: the union of what this actor reaches through any of them, each tool once\n * — for a surface that shows several agents' conversations.\n */\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 && agent !== ALL_AGENTS && this.agents.get(agent) === undefined) {\n throw new NotFoundException(`No agent named \"${agent}\"`);\n }\n const actor = await this.actorResolver.resolve(req);\n const names =\n agent === ALL_AGENTS\n ? [undefined, ...this.agents.list().map((definition) => definition.name)]\n : [agent];\n const entries = new Map<string, ToolCatalogEntry>();\n for (const name of names) {\n const deps = this.depsFactory.forAgent(name);\n const specs = await deps.registry.visibleSpecs(actor, deps.rolesPolicy, deps.toolAllowList);\n for (const spec of specs) {\n if (entries.has(spec.name)) continue;\n entries.set(spec.name, {\n name: spec.name,\n kind: spec.kind,\n ...(spec.presentation !== undefined ? { presentation: spec.presentation } : {}),\n });\n }\n }\n return [...entries.values()];\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 this.assertPersonas(this.registry.list());\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 ...(meta.personas !== undefined ? { personas: meta.personas } : {}),\n ...(meta.defaultPersona !== undefined ? { defaultPersona: meta.defaultPersona } : {}),\n };\n }\n\n /**\n * Refuse to boot on a persona declaration that could only fail later, per request: a default that\n * names no persona, an id declared twice, an alias two personas claim, or an alias that is a real\n * agent's name (which would never be reached — a registered agent always wins).\n */\n private assertPersonas(definitions: AgentDefinition[]): void {\n const agentNames = new Set(definitions.map((definition) => definition.name));\n const aliasOwner = new Map<string, string>();\n for (const definition of definitions) {\n const ids = new Set<string>();\n for (const persona of definition.personas ?? []) {\n if (ids.has(persona.id)) {\n throw new Error(`Agent \"${definition.name}\" declares persona \"${persona.id}\" twice.`);\n }\n ids.add(persona.id);\n for (const alias of persona.aliases ?? []) {\n const owner = `${definition.name}/${persona.id}`;\n if (agentNames.has(alias)) {\n throw new Error(\n `Persona ${owner} claims the alias \"${alias}\", which is a registered agent's name.`,\n );\n }\n const previous = aliasOwner.get(alias);\n if (previous !== undefined) {\n throw new Error(`Personas ${previous} and ${owner} both claim the alias \"${alias}\".`);\n }\n aliasOwner.set(alias, owner);\n }\n }\n if (definition.defaultPersona !== undefined && !ids.has(definition.defaultPersona)) {\n throw new Error(\n `Agent \"${definition.name}\" names \"${definition.defaultPersona}\" as its default persona, but declares no persona with that id.`,\n );\n }\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, Persona } 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 * Named variants of THIS agent — a prompt and, optionally, a narrower tool allow-list — that a\n * caller picks per send (`POST <base>/chat { persona }`) and that pin onto the thread. Everything\n * else (model, access rules, handoffs, history) stays this agent's; a variant that needs those to\n * differ is another `@Agent`.\n *\n * A persona's `systemPrompt` is static data. For a prompt built from injected services, leave it\n * out and branch on `ctx.persona` in this class's `@SystemPrompt()` method instead.\n *\n * Omit → no personas, and nothing about a turn changes.\n */\n personas?: Persona[];\n /** The persona a send runs under when neither it nor its thread names one. Omit → none. */\n defaultPersona?: string;\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 ToolDescribeScope,\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 // `provideAgentTools` resolves to a list; only an all-branded one is ours.\n if (\n Array.isArray(instance) &&\n instance.length > 0 &&\n instance.every(\n (each) => typeof each === 'object' && each !== null && isBrandedFunctionalTool(each),\n )\n ) {\n for (const tool of instance as FunctionalTool[]) {\n if (this.registerFunctionalTool(tool)) {\n functional += 1;\n }\n }\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 ...(meta.terminal === true ? { terminal: true } : {}),\n ...(meta.replacementKey !== undefined ? { replacementKey: meta.replacementKey } : {}),\n },\n {\n execute: (input, ctx) => (instance as ToolHandler).execute(input, ctx),\n ...(typeof handler.present === 'function'\n ? { present: (output, ctx) => (instance as Required<ToolHandler>).present(output, ctx) }\n : {}),\n ...(typeof handler.preflight === 'function'\n ? {\n preflight: (input, ctx, options) =>\n (instance as Required<ToolHandler>).preflight(input, ctx, options),\n }\n : {}),\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 ...(typeof handler.describe === 'function'\n ? {\n describe: (scope: ToolDescribeScope) =>\n (instance as Required<ToolHandler>).describe(scope),\n }\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, ToolSpec } 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 replacementKey?: ToolSpec['replacementKey'];\n /**\n * What the model calls it. Omit → the class name, camelCased, with a trailing `Tool` dropped\n * (`GetWeatherTool` → `getWeather`).\n */\n name?: string;\n /**\n * `read` (the default) auto-executes; `action` requires HITL approval. (Core's `ToolKind` also\n * has `agent` for delegation, but that kind is synthesized from `delegatesTo` — never authored\n * 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 /**\n * Roles allowed to invoke. Omit → the module's `defaultRoles`, which by default restrict nobody:\n * any resolved actor — an anonymous visitor included, when no `actorResolver` is configured.\n */\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 * The turn ends once a call to this tool succeeds — no model call afterwards to narrate what the\n * tool already showed (a composed UI answer, a hand-off). See `ToolSpec.terminal`.\n */\n terminal?: boolean;\n}\n\n/** {@link AiToolOptions} with the defaults applied — what discovery reads. */\nexport interface ResolvedAiToolOptions extends AiToolOptions {\n name: string;\n kind: 'read' | 'action';\n}\n\n/** `GetWeatherTool` → `getWeather`; `SQLQueryTool` → `sqlQuery`. */\nexport function toolNameFromClass(className: string): string {\n const base = className.replace(/Tool$/, '') || className;\n const leadingCaps = /^[A-Z]+(?=[A-Z][a-z]|$)/.exec(base)?.[0];\n if (leadingCaps !== undefined && leadingCaps.length > 1) {\n return leadingCaps.toLowerCase() + base.slice(leadingCaps.length);\n }\n return base.charAt(0).toLowerCase() + base.slice(1);\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 * Only `description` and `input` are required:\n *\n * ```ts\n * @AiTool({ description: 'Current weather for a city', input: z.object({ city: z.string() }) })\n * class GetWeatherTool implements ToolHandler<{ city: string }> { // name: getWeather, kind: read\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 const resolved: ResolvedAiToolOptions = {\n ...options,\n name: options.name ?? toolNameFromClass(target.name),\n kind: options.kind ?? 'read',\n };\n Reflect.defineMetadata(AI_TOOL_METADATA, resolved, target);\n };\n}\n\nexport function readAiToolMetadata(target: object): ResolvedAiToolOptions | undefined {\n return Reflect.getMetadata(AI_TOOL_METADATA, target.constructor) as\n | ResolvedAiToolOptions\n | undefined;\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 {\n type AgentStore,\n type QuotaPeriod,\n type QuotaProvider,\n type QuotaQuery,\n type QuotaReport,\n type QuotaWindow,\n type UsageTotals,\n exhaustedWindow,\n quotaPeriodRange,\n quotaWarning,\n} from '@dudousxd/nestjs-agent-core';\n\n/** Ceilings for a {@link LedgerQuotaProvider} window. Either, both, or neither. */\nexport interface QuotaWindowLimits {\n tokens?: number;\n usd?: number;\n}\n\n/** Per-window ceilings: `AgentModule.forRoot({ quota: { limits } })`. */\nexport interface QuotaLimits {\n day?: QuotaWindowLimits;\n month?: QuotaWindowLimits;\n}\n\n/** {@link LedgerQuotaProvider}'s tuning beyond the ceilings. */\nexport interface LedgerQuotaOptions {\n /**\n * The soft limit: the share of a ceiling (`0..1`) past which the report carries a `warning`.\n * Stamped on every window that has a ceiling. Omit → no warnings.\n */\n warnAt?: number;\n /**\n * Whether the USD windows count ESTIMATED cost (tokens × the price row, for a provider that reports\n * none, e.g. Bedrock, OpenAI or Anthropic direct) as well as provider-reported cost. Default `true`:\n * a USD ceiling that ignored estimates would read $0 and never block for every such provider, which\n * is a budget that does not enforce. Set `false` to budget on provider-reported (gateway) cost only.\n */\n countEstimatedCost?: boolean;\n}\n\n/**\n * The default {@link QuotaProvider}: windows read off the usage ledger the loop already writes.\n *\n * - `day` — always.\n * - `month` — when the store implements `usageBetween`.\n *\n * `limits` add ceilings per window (tokens and/or USD). A window that reaches one makes the report\n * `blocked`.\n */\nexport class LedgerQuotaProvider implements QuotaProvider {\n constructor(\n private readonly store: AgentStore,\n private readonly limits: QuotaLimits = {},\n private readonly options: LedgerQuotaOptions = {},\n ) {}\n\n async report(query: QuotaQuery): Promise<QuotaReport> {\n const now = query.now ?? new Date();\n const actorRef = query.actor.id;\n const windows: QuotaWindow[] = [await this.dayWindow(actorRef, now)];\n if (this.store.usageBetween !== undefined) {\n const range = quotaPeriodRange('month', now);\n const used = await this.store.usageBetween(actorRef, range.fromDay, range.toDay);\n windows.push(this.window('month', used.usedTokens, this.usd(used), range.resetsAt));\n }\n const blocked = exhaustedWindow(windows);\n const warning = quotaWarning(windows);\n return {\n windows,\n ...(blocked !== undefined ? { blocked } : {}),\n ...(warning !== undefined ? { warning } : {}),\n };\n }\n\n private async dayWindow(actorRef: string, now: Date): Promise<QuotaWindow> {\n const range = quotaPeriodRange('day', now);\n const used = await this.store.quotaToday(actorRef, range.fromDay);\n return this.window('day', used.usedTokens, this.usd(used), range.resetsAt);\n }\n\n /** The window's USD: every priced row, or (with `countEstimatedCost: false`) reported cost only. */\n private usd(used: UsageTotals): number {\n if (this.options.countEstimatedCost === false) {\n return Math.max(0, used.costUsd - (used.estimatedCostUsd ?? 0));\n }\n return used.costUsd;\n }\n\n private window(\n period: QuotaPeriod,\n usedTokens: number,\n usedUsd: number,\n resetsAt: string,\n ): QuotaWindow {\n const limits = this.limits[period] ?? {};\n return {\n period,\n usedTokens,\n ...(limits.tokens !== undefined ? { limitTokens: limits.tokens } : {}),\n usedUsd,\n ...(limits.usd !== undefined ? { limitUsd: limits.usd } : {}),\n resetsAt,\n ...(this.options.warnAt !== undefined &&\n (limits.tokens !== undefined || limits.usd !== undefined)\n ? { warnAt: this.options.warnAt }\n : {}),\n };\n }\n}\n","import {\n AGENT_MODEL,\n AGENT_OPTIONS,\n AGENT_PRICING_STORE,\n type AgentPricingStore,\n type DescribedModel,\n type ModelProvider,\n ensureModelPricing,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n Inject,\n Injectable,\n Logger,\n type OnApplicationBootstrap,\n type OnApplicationShutdown,\n Optional,\n} from '@nestjs/common';\nimport type { AgentModuleOptions } from './agent.options.js';\n\nconst logger = new Logger('AgentPricing');\n\n/**\n * Makes sure every configured model records a cost, and says so when one will not (see\n * `AgentModuleOptions.priceCatalog`). Runs in the background once the app has bootstrapped — a slow\n * catalog must not hold the boot up — and never throws. Skipped under `NODE_ENV=test` unless\n * `priceCatalog` is set explicitly.\n */\n@Injectable()\nexport class PricingBootService implements OnApplicationBootstrap, OnApplicationShutdown {\n #run: Promise<unknown> | null = null;\n\n constructor(\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Optional() @Inject(AGENT_MODEL) private readonly model: ModelProvider | undefined,\n // Bound externally (a store module), so optional like in AgentDepsFactory.\n @Optional()\n @Inject(AGENT_PRICING_STORE)\n private readonly pricingStore: AgentPricingStore | undefined,\n ) {}\n\n onApplicationBootstrap(): void {\n this.#run = this.check();\n }\n\n /** Awaits a check still in flight, so a test (or a fast shutdown) never leaks it. */\n async onApplicationShutdown(): Promise<void> {\n await this.#run;\n this.#run = null;\n }\n\n /** The check itself; resolves once it is done (exposed for tests). */\n async check(): Promise<void> {\n let models: DescribedModel[];\n try {\n models = this.model?.describeModels?.() ?? [];\n } catch (error) {\n // Pricing is bookkeeping, never a reason for the app to stay down.\n logger.warn(`describeModels() threw; boot pricing skipped: ${String(error)}`);\n return;\n }\n if (models.length === 0) return;\n const catalog = this.options.priceCatalog;\n if (catalog === undefined && process.env.NODE_ENV === 'test') return;\n await ensureModelPricing({\n models,\n pricingStore: this.pricingStore,\n catalog: catalog ?? {},\n log: {\n info: (message) => logger.log(message),\n warn: (message) => logger.warn(message),\n },\n }).catch(() => undefined);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n AGENT_DEPS_FACTORY,\n AGENT_OPTIONS,\n AGENT_STORE,\n type ActionProposal,\n ActionProposalExecutor,\n ActionProposalWorker,\n type AgentStore,\n assertIndependentActionCapabilities,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n Inject,\n Injectable,\n Logger,\n type OnModuleDestroy,\n type OnModuleInit,\n} from '@nestjs/common';\nimport { AgentDepsFactory } from '../agent-deps.factory.js';\nimport type { AgentModuleOptions } from '../agent.options.js';\n/** Called with a proposal the worker just settled (executed, or failed executing). */\nexport type ActionProposalSettledListener = (proposal: ActionProposal) => void | Promise<void>;\n\n@Injectable()\nexport class ActionProposalWorkerService implements OnModuleInit, OnModuleDestroy {\n private worker: ActionProposalWorker | undefined;\n private readonly logger = new Logger(ActionProposalWorkerService.name);\n private readonly settledListeners = new Set<ActionProposalSettledListener>();\n\n /**\n * Run `listener` after every proposal this process's worker settles — how a module relays an\n * outcome somewhere the turn's stream no longer reaches (a text channel's conversation). Next to\n * `actionProposalWorker.onSettled`; a listener that throws is logged and does not stop the others.\n * Returns the unsubscribe. Only the replicas that run the worker (not `surface: 'http'`) call it.\n */\n onSettled(listener: ActionProposalSettledListener): () => void {\n this.settledListeners.add(listener);\n return () => {\n this.settledListeners.delete(listener);\n };\n }\n\n private async settled(proposal: ActionProposal): Promise<void> {\n const configured = this.options.actionProposalWorker?.onSettled;\n for (const listener of [...(configured ? [configured] : []), ...this.settledListeners]) {\n try {\n await listener(proposal);\n } catch (error) {\n this.logger.error(error);\n }\n }\n }\n constructor(\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_OPTIONS) private readonly options: AgentModuleOptions,\n @Inject(AGENT_DEPS_FACTORY) private readonly deps: AgentDepsFactory,\n ) {}\n onModuleInit() {\n if (this.options.actionApprovalMode !== 'independent') return;\n assertIndependentActionCapabilities(this.store, this.options.backgroundActorResolver);\n if (this.options.surface === 'http') return;\n const resolver = this.options.backgroundActorResolver;\n if (!resolver) throw new Error('BackgroundActorResolver is required');\n this.worker = new ActionProposalWorker({\n store: this.store,\n workerId: randomUUID(),\n ...this.options.actionProposalWorker,\n onSettled: (proposal) => this.settled(proposal),\n executor: new ActionProposalExecutor({\n resolver,\n resolveExecution: async (proposal, actor) => {\n const deps = this.deps.forProposal(proposal, actor);\n return {\n registry: deps.registry,\n rolesPolicy: deps.rolesPolicy,\n ...(deps.resolveUiCatalog !== undefined\n ? { resolveUiCatalog: deps.resolveUiCatalog }\n : {}),\n ...(deps.toolAllowList !== undefined ? { allowedTools: deps.toolAllowList } : {}),\n };\n },\n }),\n onError: (error) => this.logger.error(error),\n });\n this.worker.start();\n }\n async onModuleDestroy() {\n await this.worker?.stop();\n }\n}\n","import {\n AGENT_ACTOR_RESOLVER,\n type ActorResolver,\n type ListActionProposals,\n validateActionProposalListQuery,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n BadRequestException,\n Body,\n Controller,\n Get,\n Inject,\n Param,\n Post,\n Query,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { ActionProposalService } from './action-proposal.service.js';\nfunction bodyFields(body: unknown, field: 'remember' | 'reason'): Record<string, unknown> {\n if (body === undefined) return {};\n if (\n typeof body !== 'object' ||\n body === null ||\n Array.isArray(body) ||\n Object.keys(body).some((key) => key !== field)\n )\n throw new BadRequestException(`Only ${field} is accepted`);\n const value = body as Record<string, unknown>;\n if (\n value[field] !== undefined &&\n ((field === 'remember' && typeof value[field] !== 'boolean') ||\n (field === 'reason' && typeof value[field] !== 'string'))\n )\n throw new BadRequestException(`Invalid ${field}`);\n return value;\n}\n@Controller('threads/:threadId/action-proposals')\nexport class ActionProposalController {\n constructor(\n private readonly proposals: ActionProposalService,\n @Inject(AGENT_ACTOR_RESOLVER) private readonly actors: ActorResolver,\n ) {}\n @Get() async list(\n @Param('threadId') threadId: string,\n @Req() request: Request,\n @Query('after') cursor: unknown,\n @Res({ passthrough: true }) response: Response,\n ) {\n let query: Pick<ListActionProposals, 'after'> = {};\n if (cursor !== undefined) {\n try {\n if (typeof cursor !== 'string') throw new Error('Invalid cursor');\n query = { after: JSON.parse(cursor) };\n validateActionProposalListQuery(query);\n } catch {\n throw new BadRequestException('Invalid action proposal cursor');\n }\n }\n const page = await this.proposals.listPage(threadId, await this.actors.resolve(request), query);\n if (page.next) {\n response.setHeader('X-Action-Proposals-Next', encodeURIComponent(JSON.stringify(page.next)));\n const exposed = response.getHeader('Access-Control-Expose-Headers');\n response.setHeader(\n 'Access-Control-Expose-Headers',\n `${exposed === undefined ? '' : `${String(exposed)}, `}X-Action-Proposals-Next`,\n );\n }\n return page.items;\n }\n @Post(':proposalId/approve') async approve(\n @Param('threadId') threadId: string,\n @Param('proposalId') proposalId: string,\n @Req() request: Request,\n @Body() body: unknown,\n ) {\n const value = bodyFields(body, 'remember');\n return this.proposals.decide(threadId, proposalId, await this.actors.resolve(request), {\n decision: 'approved',\n ...(typeof value.remember === 'boolean' ? { remember: value.remember } : {}),\n });\n }\n @Post(':proposalId/reject') async reject(\n @Param('threadId') threadId: string,\n @Param('proposalId') proposalId: string,\n @Req() request: Request,\n @Body() body: unknown,\n ) {\n const value = bodyFields(body, 'reason');\n return this.proposals.decide(threadId, proposalId, await this.actors.resolve(request), {\n decision: 'rejected',\n ...(typeof value.reason === 'string' ? { reason: value.reason } : {}),\n });\n }\n}\n","/**\n * The thread message queue, as the durable runner and the `agent.run` workflow ask for it.\n *\n * A token rather than the `ChatQueueService` class: `@dudousxd/nestjs-agent/durable` is a separate\n * bundle with its own copy of every class it imports, so a class used as an injection token there\n * is not the class `AgentModule` provides. `Symbol.for` is the same value in every bundle.\n */\nexport const AGENT_CHAT_QUEUE = Symbol.for('@dudousxd/nestjs-agent:chat-queue');\n","import {\n AGENT_DEPS_FACTORY,\n AGENT_STORE,\n type Actor,\n type AgentLoopHooks,\n type AgentRunInput,\n type AgentRunStartOptions,\n type AgentRunner,\n type AgentStore,\n type Decision,\n type DetachedDelivery,\n type ElicitationReply,\n type HumanReply,\n RUN_ENDED_BEFORE_TOOL_CALL,\n RunCancelledError,\n type SinkWriter,\n agentFailureCode,\n encodeStreamEvent,\n publishAgentRunFailed,\n releaseThreadRun,\n runAgentLoop,\n settleAll,\n settleUnsettledDelegation,\n streamFailure,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, Optional } from '@nestjs/common';\nimport type { AgentDepsFactory } from '../agent-deps.factory.js';\nimport { type AgentDeps, childSinkWriter, utcDay } from '../agent-deps.js';\nimport { ChatQueueService, type QueueSettleOutcome } from '../queue/chat-queue.service.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 * Aborted by {@link cancel}: what cuts short the model call or tool a stopped run is in (the\n * loop's `abortSignal` hook). Keyed like {@link cancelled}, and dropped with it.\n */\n private readonly aborts = new Map<string, AbortController>();\n /** Top-level runs this process is running now — what {@link isRunActive} answers from. */\n private readonly live = new Set<string>();\n\n constructor(\n @Inject(AGENT_DEPS_FACTORY) private readonly factory: AgentDepsFactory,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Optional() private readonly queue?: ChatQueueService,\n ) {}\n\n /**\n * In-process, so exact: a run this process is not running is not running anywhere — the process\n * that was running it is gone (a restart), and a thread it still holds is a stale claim.\n */\n async isRunActive(runId: string): Promise<boolean> {\n if (this.live.has(runId)) {\n return true;\n }\n // A delegated run is not in `live` (it holds no thread of its own turn), but one parked on a\n // person is as alive as its parent: its decision has somewhere to go.\n for (const key of this.pending.keys()) {\n if (key.startsWith(`${runId}:`)) {\n return true;\n }\n }\n return false;\n }\n\n async start(\n input: AgentRunInput,\n options: AgentRunStartOptions = {},\n ): Promise<{ runId: string }> {\n const runId = options.runId ?? crypto.randomUUID();\n const day = input.day ?? utcDay();\n const deps = this.factory.forAgent(input.agentName);\n this.live.add(runId);\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 input,\n });\n\n void runAgentLoop({ ...deps, day }, input, hooks)\n .then(() => releaseThreadRun(this.store, input.threadId, runId))\n .catch(async (error) => {\n if (error instanceof RunCancelledError) {\n await this.settleCancelled(runId, input, 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 // A call this run had put to a person is not waiting for anything any more.\n await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\n const writer = await deps.sink.open(runId);\n // The queue behind it pauses (a failed turn's next message would likely fail the same way),\n // told to the reader before the error frame.\n await this.settleQueue(writer, input, runId, 'failed', message);\n // Clear the thread's active run — a failed run isn't \"still running\" for `activeRunForThread`.\n await releaseThreadRun(this.store, input.threadId, runId);\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. The frame is for the person reading the\n // chat; the error itself went to the log and the run row above.\n await writer.fail(streamFailure(error));\n })\n .finally(() => {\n this.forgetCancel(runId);\n this.live.delete(runId);\n });\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. What the run is in right now is aborted (its `abortSignal`): the model call\n * streaming the answer ends at once and the step it was writing is not persisted, and a tool that\n * passes `ctx.abortSignal` on is cut short and recorded failed; a tool that ignores the signal is\n * left to finish, and its result is recorded 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 // The model call or tool the run is in, cut short now rather than at the end of its step.\n this.aborts.get(runId)?.abort(new RunCancelledError());\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 /** The signal {@link cancel} aborts for `runId` — one per run, shared by its awaited delegates. */\n private abortSignalFor(runId: string): AbortSignal {\n let controller = this.aborts.get(runId);\n if (controller === undefined) {\n controller = new AbortController();\n this.aborts.set(runId, controller);\n }\n return controller.signal;\n }\n\n /** Drop a settled run's Stop: its flag and its abort controller. */\n private forgetCancel(runId: string): void {\n this.cancelled.delete(runId);\n this.aborts.delete(runId);\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(\n runId: string,\n input: AgentRunInput,\n deps: AgentDeps,\n ): Promise<void> {\n this.logger.log(`agent run ${runId} cancelled`);\n const writer = await deps.sink.open(runId);\n // An interrupt's message starts now; otherwise the queue pauses behind the Stop.\n await this.settleQueue(writer, input, runId, 'cancelled');\n await releaseThreadRun(this.store, input.threadId, 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 * Move the thread past a settling TOP-LEVEL run — to the next queued message, which starts here,\n * or to a paused/empty queue — and write the resulting `queue` frame into this run's stream. A\n * no-op without a queue-capable store, and for a run that is not a thread's own turn.\n *\n * Never throws: the run is settling either way, and a queue that could not be advanced is picked\n * up by the next send or resume on the thread.\n */\n private async settleQueue(\n writer: SinkWriter,\n input: AgentRunInput,\n runId: string,\n outcome: QueueSettleOutcome,\n error?: string,\n ): Promise<void> {\n const queue = this.queue;\n if (queue === undefined || !queue.supported || !isThreadTurn(input)) {\n return;\n }\n // A Stop that arrived too late to interrupt anything (the turn's last model call was already\n // answering) still means stop: the queue behind it pauses as it would after a cancel.\n const settled = outcome === 'completed' && this.cancelled.has(runId) ? 'cancelled' : outcome;\n try {\n const frame = await queue.handoff(\n {\n threadId: input.threadId,\n runId,\n outcome: settled,\n ...(error !== undefined ? { error } : {}),\n },\n (next, nextRunId) => this.start(next, { runId: nextRunId }),\n );\n if (frame !== undefined) {\n await writer.write(encodeStreamEvent(frame));\n }\n } catch (failure) {\n this.logger.error(\n `could not advance the queue of thread ${input.threadId} after run ${runId}: ${\n failure instanceof Error ? failure.message : String(failure)\n }`,\n );\n }\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 /**\n * {@link park} for an approval, bounded by the policy's time to live when it has one: the timer\n * settles the wait as `expired` — the same Decision the durable runner builds from its signal\n * timeout — and a decision that arrives first disarms it.\n */\n private parkApproval(runId: string, toolCallId: string, timeoutMs?: number): Promise<Decision> {\n const waiting = this.park<Decision>(runId, toolCallId);\n if (timeoutMs === undefined) {\n return waiting;\n }\n const key = `${runId}:${toolCallId}`;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const lapse = new Promise<Decision>((resolve) => {\n timer = setTimeout(() => {\n const entry = this.pending.get(key);\n if (entry !== undefined) {\n this.pending.delete(key);\n resolve({ approved: false, expired: true });\n }\n }, timeoutMs);\n // A parked request must not keep the process alive on its own.\n timer.unref?.();\n });\n return Promise.race([waiting, lapse]).finally(() => clearTimeout(timer));\n }\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 input: AgentRunInput;\n }): AgentLoopHooks {\n const { runId, deps, actor, day, threadId, chainBelow, input } = args;\n return {\n runId,\n // The loop ends the stream when the turn completes. Just before, the thread passes to the next\n // queued message (or is released), and the reader is told which — so by the time a client\n // sees the run end, the thread is already free or already running what it queued.\n openSink: async () => {\n const writer = await deps.sink.open(runId);\n return this.queue === undefined\n ? writer\n : {\n write: (chunk) => writer.write(chunk),\n fail: (error) => writer.fail(error),\n end: async () => {\n await this.settleQueue(writer, input, runId, 'completed');\n await writer.end();\n },\n };\n },\n awaitApproval: (call, _ctx, opts) => this.parkApproval(runId, call.id, opts?.timeoutMs),\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 abortSignal: this.abortSignalFor(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, _ctx, opts) => this.parkApproval(runId, call.id, opts?.timeoutMs),\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 abortSignal: this.abortSignalFor(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 await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\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.forgetCancel(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, _ctx, opts) => this.parkApproval(runId, call.id, opts?.timeoutMs),\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 // Aborted by a Stop on the run the human is watching, which is the id a canceller names.\n abortSignal: this.abortSignalFor(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\n/**\n * A thread's own turn — not a sub-agent's run on a subthread, which neither holds its thread's\n * queue nor answers to it.\n */\nfunction isThreadTurn(input: AgentRunInput): boolean {\n return input.sinkRunId === undefined && input.deliverTo === undefined;\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 {\n AGENT_ACTOR_RESOLVER,\n AGENT_ATTACHMENT_STAGING,\n AGENT_OPTIONS,\n type Actor,\n type ActorResolver,\n type AttachmentRef,\n type AttachmentStagingStore,\n type PageContext,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n A2UI_LEGACY_BASIC_CATALOG_ID,\n type A2uiOptions,\n negotiateA2uiCatalog,\n readAgUiA2uiCatalogIds,\n} from '@dudousxd/nestjs-agent-core/a2ui';\nimport {\n AG_UI_CUSTOM,\n type AgUiEvent,\n type AgUiStreamOptions,\n type InlineMedia,\n type ResumeDecision,\n actionProposalDecisionEvents,\n agUiEvents,\n agUiFramesFromNdjson,\n agUiSse,\n parseRunInput,\n planResume,\n readAnswersPayload,\n readApprovalPayload,\n readContext,\n readForwardedProps,\n readUserTurn,\n} from '@dudousxd/nestjs-agent-core/ag-ui';\nimport { type Catalog, uiActionText } from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n Body,\n Controller,\n ForbiddenException,\n HttpCode,\n Inject,\n Optional,\n Post,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport type { AgentModuleOptions } from '../agent.options.js';\nimport { AgentService, NO_USER_MESSAGE_CODE } from '../agent.service.js';\nimport { attachmentLimits } from '../attachment-limits.js';\nimport { answers as boundedAnswers, rejectReason } from '../controller/tool-call.controller.js';\nimport { GENUI_CATALOG } from '../genui/agent-genui.module.js';\nimport type { AgentProtocolAdapter } from '../protocol-adapter.js';\n\nexport interface AgUiAdapterOptions {\n /** Where the route mounts, under the agent's path. Default `'ag-ui'` → `POST <path>/ag-ui`. */\n path?: string;\n /**\n * How long a run that is waiting on a person AND still has other work announced may stay silent\n * before it is reported interrupted. Default 750 ms.\n */\n quietMs?: number;\n /**\n * A2UI over AG-UI: every generative-UI frame is also sent as an `ACTIVITY_SNAPSHOT` of type\n * `a2ui-surface` (the A2UI messages under `a2ui_operations`), so CopilotKit's A2UI renderer — or\n * any client of AG-UI's A2UI binding — draws it. `true` maps the library builtins onto A2UI's\n * basic catalog; pass {@link A2uiOptions} for the app's own mappings or catalog. Inbound,\n * `forwardedProps.a2uiAction.userAction` is always read: the action becomes the user's turn.\n *\n * The basic catalog goes under the id the client advertises — `forwardedProps\n * .a2uiClientCapabilities`, or the \"A2UI catalog capabilities\" context entry CopilotKit sends —\n * and, when it advertises none, under the id AG-UI's A2UI binding uses\n * (`A2UI_LEGACY_BASIC_CATALOG_ID`: CopilotKit 1.77, `@ag-ui/a2ui-middleware`).\n */\n a2ui?: boolean | A2uiOptions;\n}\n\n/** The surface an AG-UI resume decision is recorded as having come through. */\nconst AG_UI_VIA = 'ag-ui';\n\nfunction invalid(code: string, message: string): BadRequestException {\n return new BadRequestException({ statusCode: 400, code, message });\n}\n\n/** Input material the route could not use, as the events that say so. */\nfunction warningEvents(warnings: readonly string[]): AgUiEvent[] {\n return warnings.map((message) => ({\n type: 'CUSTOM' as const,\n name: AG_UI_CUSTOM.warning,\n value: { message },\n }));\n}\n\n/**\n * Serves the agent over AG-UI 1.0. Not mounted directly — {@link agUiAdapter} mounts a subclass at\n * the configured path — but exported so a host can extend it under a route of its own.\n */\nexport class AgUiRunHandler {\n constructor(\n protected readonly agent: AgentService,\n protected readonly actorResolver: ActorResolver,\n protected readonly options: AgentModuleOptions,\n protected readonly staging: AttachmentStagingStore | undefined,\n protected readonly quietMs: number | undefined,\n /** A2UI over AG-UI ({@link AgUiAdapterOptions.a2ui}), its catalog already filled in. Off when undefined. */\n protected readonly a2ui: A2uiOptions | undefined = undefined,\n ) {}\n\n async handle(req: Request, res: Response, body: unknown): Promise<void> {\n const input = parseRunInput(body);\n if (typeof input === 'string') {\n throw invalid('invalid_input', input);\n }\n const forwarded = readForwardedProps(input.forwardedProps);\n const actor = await this.actorResolver.resolve(req);\n const warnings: string[] = [];\n if (Array.isArray(input.tools) && input.tools.length > 0) {\n warnings.push('Frontend tools are not supported by this agent: the tools list was ignored.');\n }\n const quiet = this.quietMs !== undefined ? { quietMs: this.quietMs } : {};\n\n if (input.resume !== undefined && input.resume.length > 0) {\n const plan = planResume(input.resume);\n if (typeof plan === 'string') {\n throw invalid('invalid_resume', plan);\n }\n for (const id of plan.unrecognised) {\n warnings.push(`The resume entry ${id} answers an interrupt this agent did not raise.`);\n }\n const first = plan.decisions[0];\n // Independent proposals do not park their run: deciding them is the whole answer.\n if (first !== undefined && plan.decisions.every((d) => d.address.kind === 'proposal')) {\n const decided = await this.decideProposals(actor, plan.decisions);\n this.writeEvents(res, [\n ...warningEvents(warnings),\n ...decided.flatMap((outcome, index) =>\n actionProposalDecisionEvents({\n threadId: input.threadId,\n runId: index === 0 ? input.runId : `${input.runId}:${index}`,\n text: outcome.text,\n proposalDecision: outcome.proposalDecision,\n }),\n ),\n ]);\n return;\n }\n // A list that answers nothing this agent asked continues nothing: an ordinary run.\n if (first !== undefined) {\n const streamRunId = first.address.stream;\n await this.agent.assertResumable(actor, streamRunId);\n await this.settle(actor, plan.decisions);\n await this.pipe(res, streamRunId, {\n threadId: input.threadId,\n runId: input.runId,\n streamRunId,\n skip: first.address.position,\n answered: plan.decisions.map((decision) => decision.address.toolCallId),\n ...quiet,\n ...this.a2uiFor(input),\n preamble: warningEvents(warnings),\n });\n return;\n }\n }\n\n // A UI action (a sandbox's `agent.send`, an A2UI button) IS the turn: the messages only\n // restate the conversation so far.\n const action = forwarded.uiAction;\n if (typeof action === 'string') {\n throw invalid('invalid_ui_action', action);\n }\n const turn =\n action !== undefined\n ? { text: uiActionText(action), media: [], staged: [], dropped: [] }\n : readUserTurn(input.messages);\n if (turn === null) {\n throw invalid(NO_USER_MESSAGE_CODE, 'messages carries no user message to answer');\n }\n warnings.push(...turn.dropped);\n // The consumer names the conversation. A thread it already has is continued (its owner checked,\n // as on `chat`); one nobody has is created under that name.\n const owner = await this.agent.threadOwner(input.threadId);\n if (owner !== null && owner !== actor.id) {\n throw new ForbiddenException('thread belongs to another actor');\n }\n if (forwarded.regenerate === true && owner === null) {\n throw invalid('invalid_input', 'regenerate needs a thread that already has an exchange');\n }\n // A regenerate re-answers the last message: it is never a decision on a pending proposal.\n if (\n owner !== null &&\n forwarded.regenerate !== true &&\n action === undefined &&\n turn.media.length === 0 &&\n turn.staged.length === 0\n ) {\n const decision = await this.agent.handleTextDecision(input.threadId, actor, turn.text);\n if ('proposalDecision' in decision) {\n this.writeEvents(res, [\n ...warningEvents(warnings),\n ...actionProposalDecisionEvents({\n threadId: input.threadId,\n runId: input.runId,\n text: decision.text,\n proposalDecision: decision.proposalDecision,\n }),\n ]);\n return;\n }\n }\n // Attachments the consumer staged with this library already are named by mediaId; `chat`\n // resolves them for this actor and refuses one it does not own, as the native route does.\n const refs = await this.stage(actor, turn.media, warnings, turn.staged);\n // A regenerate re-answers the thread's last message and adds none, as on `chat`.\n if (turn.text.trim().length === 0 && refs.length === 0 && forwarded.regenerate !== true) {\n throw invalid(NO_USER_MESSAGE_CODE, 'the user message to answer is empty');\n }\n const context = readContext(input.context);\n const pageContext: PageContext | undefined =\n forwarded.pageContext !== undefined || context !== undefined\n ? {\n ...forwarded.pageContext,\n ...(context !== undefined ? { agUiContext: context } : {}),\n }\n : undefined;\n const started = await this.agent.chat({\n actor,\n message: turn.text,\n ...(owner !== null ? { threadId: input.threadId } : { newThreadId: input.threadId }),\n ...(forwarded.agent !== undefined ? { agentName: forwarded.agent } : {}),\n ...(forwarded.persona !== undefined ? { personaId: forwarded.persona } : {}),\n ...(forwarded.model !== undefined ? { model: forwarded.model } : {}),\n ...(forwarded.uiCapabilities !== undefined\n ? { uiCapabilities: forwarded.uiCapabilities }\n : {}),\n ...(pageContext !== undefined ? { pageContext } : {}),\n ...(refs.length > 0 ? { attachments: refs } : {}),\n ...(forwarded.regenerate === true ? { regenerate: true } : {}),\n });\n await this.pipe(res, started.runId, {\n threadId: input.threadId,\n runId: input.runId,\n streamRunId: started.runId,\n streamThreadId: started.threadId,\n ...quiet,\n ...this.a2uiFor(input),\n preamble: warningEvents(warnings),\n });\n }\n\n /**\n * The turn's attachments: the ones already staged (by mediaId), then its inline media staged\n * through the bound store — all within the store's limits; say what was not used.\n */\n private async stage(\n actor: Actor,\n media: readonly InlineMedia[],\n warnings: string[],\n staged: readonly AttachmentRef[] = [],\n ): Promise<AttachmentRef[]> {\n const refs: AttachmentRef[] = [];\n const limits = attachmentLimits(this.options, this.staging);\n for (const ref of staged) {\n const label = `The attachment ${ref.mediaId} was not used`;\n if (this.staging === undefined) {\n warnings.push(`${label}: attachments are not enabled on this agent.`);\n } else if (refs.length >= limits.maxPerMessage) {\n warnings.push(`${label}: a message carries at most ${limits.maxPerMessage} attachments.`);\n } else {\n refs.push({ mediaId: ref.mediaId });\n }\n }\n for (const item of media) {\n const label = `The ${item.kind} \"${item.filename}\" was not used`;\n if (this.staging === undefined) {\n warnings.push(`${label}: attachments are not enabled on this agent.`);\n } else if (refs.length >= limits.maxPerMessage) {\n warnings.push(`${label}: a message carries at most ${limits.maxPerMessage} attachments.`);\n } else if (!limits.allowedContentTypes.includes(item.contentType)) {\n warnings.push(`${label}: ${item.contentType} is not an accepted type.`);\n } else if (item.data.length > limits.maxBytes) {\n warnings.push(`${label}: it is larger than ${limits.maxBytes} bytes.`);\n } else {\n try {\n const staged = await this.staging.stage({\n data: item.data,\n filename: item.filename,\n contentType: item.contentType,\n sizeBytes: item.data.length,\n actor,\n });\n refs.push({ mediaId: staged.mediaId });\n } catch {\n warnings.push(`${label}: it could not be stored.`);\n }\n }\n }\n return refs;\n }\n\n /**\n * Deliver what a resume list decided, through the same calls the native decision routes make.\n * Everything that can refuse — who may decide, an answer a question's rules reject, a payload that\n * says nothing — is checked for EVERY entry before the first one is delivered, so a list with one\n * bad entry settles nothing.\n */\n private async settle(actor: Actor, decisions: ResumeDecision[]): Promise<void> {\n const deliveries: (() => Promise<void>)[] = [];\n const proposals = decisions.filter((decision) => decision.address.kind === 'proposal');\n for (const { address, entry } of decisions) {\n const { toolCallId } = address;\n const abandoned = entry.status === 'cancelled';\n if (address.kind === 'proposal') continue;\n if (address.kind === 'approval') {\n await this.agent.checkDecision(actor, toolCallId);\n const decision: { approved: boolean; reason?: string; remember?: boolean } | null =\n abandoned ? { approved: false } : readApprovalPayload(entry.payload);\n if (decision === null) {\n throw invalid(\n 'invalid_resume',\n 'an approval is answered with { approved: boolean, reason?, remember? }',\n );\n }\n const reason = rejectReason(decision.reason ?? (abandoned ? 'abandoned' : undefined));\n deliveries.push(() =>\n decision.approved\n ? this.agent.approve(actor, toolCallId, {\n via: AG_UI_VIA,\n ...(decision.remember === true ? { remember: true } : {}),\n })\n : this.agent.reject(actor, toolCallId, reason, { via: AG_UI_VIA }),\n );\n continue;\n }\n if (abandoned) {\n await this.agent.checkAnswer(actor, toolCallId, {});\n deliveries.push(() => this.agent.skip(actor, toolCallId, { via: AG_UI_VIA }));\n continue;\n }\n const read = readAnswersPayload(entry.payload);\n if (read === null) {\n throw invalid(\n 'invalid_resume',\n 'a question set is answered with { answers: { <questionId>: string[] } }',\n );\n }\n const answers = boundedAnswers(read) ?? {};\n await this.agent.checkAnswer(actor, toolCallId, answers);\n deliveries.push(() => this.agent.answer(actor, toolCallId, answers, { via: AG_UI_VIA }));\n }\n // Settled before the parked calls, like any other delivery: a refused one settles nothing more.\n if (proposals.length > 0) await this.decideProposals(actor, proposals);\n for (const deliver of deliveries) await deliver();\n }\n\n /**\n * Decide independent proposals through the proposal service — the call the native\n * `action-proposals/:id/approve|reject` routes make — never by signalling the origin run, which\n * is not waiting. Every payload is checked before the first decision; a refusal is the service's\n * own `403`/`404`.\n */\n private async decideProposals(\n actor: Actor,\n decisions: ResumeDecision[],\n ): Promise<{ proposalDecision: unknown; text: string }[]> {\n const planned = decisions.map(({ address, entry }) => {\n const decision =\n entry.status === 'cancelled' ? { approved: false } : readApprovalPayload(entry.payload);\n if (decision === null || address.proposalId === undefined || address.threadId === undefined) {\n throw invalid(\n 'invalid_resume',\n 'an approval is answered with { approved: boolean, reason?, remember? }',\n );\n }\n return { address, decision };\n });\n const outcomes: { proposalDecision: unknown; text: string }[] = [];\n for (const { address, decision } of planned) {\n outcomes.push(\n await this.agent.decideActionProposal(\n actor,\n address.threadId as string,\n address.proposalId as string,\n {\n decision: decision.approved ? 'approved' : 'rejected',\n via: AG_UI_VIA,\n ...(decision.remember !== undefined ? { remember: decision.remember } : {}),\n ...(decision.reason !== undefined ? { reason: decision.reason } : {}),\n },\n ),\n );\n }\n return outcomes;\n }\n\n /** Answer with a complete list of events, no run behind them. */\n private writeEvents(res: Response, events: AgUiEvent[]): void {\n res.status(200);\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.flushHeaders();\n for (const event of events) res.write(agUiSse(event));\n res.end();\n }\n\n /** A2UI for this request's client: the basic catalog under the id it advertises. Off when off. */\n private a2uiFor(input: { forwardedProps?: unknown; context?: readonly unknown[] }): {\n a2ui?: A2uiOptions;\n } {\n if (this.a2ui === undefined) return {};\n return {\n a2ui: negotiateA2uiCatalog(\n this.a2ui,\n readAgUiA2uiCatalogIds(input),\n A2UI_LEGACY_BASIC_CATALOG_ID,\n ),\n };\n }\n\n /**\n * Pipe a run to the client as AG-UI 1.0 over SSE: one event per `data:` line, from `RUN_STARTED`\n * to the run's terminal event. It ends when the run stops to ask — the library run stays parked,\n * and the request that answers re-attaches to it.\n */\n private async pipe(res: Response, runId: string, options: AgUiStreamOptions): Promise<void> {\n res.status(200);\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.setHeader('X-Agent-Run-Id', runId);\n res.flushHeaders();\n let terminal = false;\n // Every event goes out with the run's own sequence number as its SSE `id:`, so a consumer can\n // follow the rest of the run on `chat/:runId/stream?after=<id>` once this AG-UI run ends.\n const cursor = { seq: 0 };\n try {\n const frames = agUiFramesFromNdjson(this.agent.subscribe(runId));\n for await (const event of agUiEvents(frames, { ...options, cursor })) {\n if (event.type === 'RUN_FINISHED' || event.type === 'RUN_ERROR') terminal = true;\n res.write(agUiSse(event, cursor.seq));\n }\n } catch {\n // The stream under the run broke. The status line is long gone, so the failure travels\n // in-stream — and says nothing of what broke, which is the server's to know.\n if (!terminal) {\n res.write(\n agUiSse({\n type: 'RUN_ERROR',\n message: 'The run could not be followed.',\n code: 'run_failed',\n }),\n );\n }\n }\n res.end();\n }\n}\n\n/**\n * Serve the agent over AG-UI 1.0 (https://docs.ag-ui.com/spec/1.0): the body of\n * `POST <path>/ag-ui` is a `RunAgentInput`, the answer the run as AG-UI events. A run that stops to\n * ask ends with the interrupt outcome and is continued by a later request carrying `resume`.\n *\n * ```ts\n * AgentModule.forRoot({ model, adapters: [agUiAdapter()] })\n * ```\n *\n * Authenticated by the module's `actorResolver`, guarded by its `guards` and owner-scoped exactly\n * as `chat`, `chat/:runId/stream` and the `tool-call` routes are.\n */\nexport function agUiAdapter(options: AgUiAdapterOptions = {}): AgentProtocolAdapter {\n const path = (options.path ?? 'ag-ui').replace(/^\\/+|\\/+$/g, '');\n const quietMs = options.quietMs;\n const a2ui =\n options.a2ui === undefined || options.a2ui === false\n ? undefined\n : options.a2ui === true\n ? {}\n : options.a2ui;\n\n @Controller()\n class AgUiController extends AgUiRunHandler {\n constructor(\n @Inject(AgentService) agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) actorResolver: ActorResolver,\n @Inject(AGENT_OPTIONS) moduleOptions: AgentModuleOptions,\n @Optional() @Inject(AGENT_ATTACHMENT_STAGING) staging?: AttachmentStagingStore,\n @Optional() @Inject(GENUI_CATALOG) catalog?: Catalog,\n ) {\n super(\n agent,\n actorResolver,\n moduleOptions,\n staging,\n quietMs,\n a2ui !== undefined ? withCatalog(a2ui, catalog) : undefined,\n );\n }\n\n @Post(path)\n @HttpCode(200)\n run(@Req() req: Request, @Res() res: Response, @Body() body: unknown): Promise<void> {\n return this.handle(req, res, body);\n }\n }\n\n return { name: 'ag-ui', controllers: [AgUiController] };\n}\n\n/** The app's genui catalog under the A2UI options, for the text of components nothing maps. */\nfunction withCatalog(options: A2uiOptions, catalog: Catalog | undefined): A2uiOptions {\n if (options.catalog !== undefined || catalog === undefined) return options;\n return { ...options, catalog };\n}\n","import { AGENT_ACTOR_RESOLVER, type ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport {\n A2UI_APPROVE_ACTION,\n A2UI_REJECT_ACTION,\n A2uiProjector,\n type A2uiServerMessage,\n type A2uiStreamOptions,\n a2uiThreadReplay,\n negotiateA2uiCatalog,\n readA2uiAction,\n readA2uiClientCapabilities,\n} from '@dudousxd/nestjs-agent-core/a2ui';\nimport {\n agUiEvents,\n agUiFramesFromNdjson,\n decodeInterruptId,\n} from '@dudousxd/nestjs-agent-core/ag-ui';\nimport {\n type Catalog,\n type UiAction,\n type UiCapabilities,\n uiActionText,\n validateUiCapabilities,\n} from '@dudousxd/nestjs-agent-core/genui';\nimport {\n BadRequestException,\n Body,\n Controller,\n ForbiddenException,\n Get,\n HttpCode,\n Inject,\n Optional,\n Param,\n Post,\n Query,\n Req,\n Res,\n} from '@nestjs/common';\nimport type { Request, Response } from 'express';\nimport { AGENT_SERVICE } from '../agent-service.token.js';\nimport type { AgentService } from '../agent.service.js';\nimport { GENUI_CATALOG } from '../genui/agent-genui.module.js';\nimport type { AgentProtocolAdapter } from '../protocol-adapter.js';\n\nexport interface A2uiAdapterOptions extends A2uiStreamOptions {\n /** Where the route mounts, under the agent's path. Default `'a2ui'` → `POST <path>/a2ui`. */\n path?: string;\n /** As `agUiAdapter`'s: how long a run waiting on a person may stay silent before the stream ends. */\n quietMs?: number;\n /** Largest action accepted, as JSON, in bytes. Default 8192. */\n maxActionBytes?: number;\n /** Largest `a2uiClientDataModel` accepted, as JSON, in bytes. Default 32768. */\n maxDataModelBytes?: number;\n}\n\n/** The surface an A2UI decision is recorded as having come through. */\nconst A2UI_VIA = 'a2ui';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction invalid(code: string, message: string): BadRequestException {\n return new BadRequestException({ statusCode: 400, code, message });\n}\n\n/** A field of the body, or of its A2A-style `metadata` (where A2UI puts client capabilities). */\nfunction bodyField(body: Record<string, unknown>, key: string): unknown {\n if (body[key] !== undefined) return body[key];\n return isRecord(body.metadata) ? body.metadata[key] : undefined;\n}\n\n/** `a2uiClientDataModel` (`{ version, surfaces: { <surfaceId>: model } }`): its surfaces, or why not. */\nfunction readDataModel(\n raw: unknown,\n maxBytes: number,\n): Record<string, unknown> | undefined | string {\n if (raw === undefined) return undefined;\n if (!isRecord(raw) || !isRecord(raw.surfaces)) {\n return 'a2uiClientDataModel carries { version, surfaces }';\n }\n let size: number;\n try {\n size = new TextEncoder().encode(JSON.stringify(raw.surfaces)).length;\n } catch {\n return 'a2uiClientDataModel must be JSON';\n }\n if (size > maxBytes) {\n return `a2uiClientDataModel may be at most ${maxBytes} bytes (this one is ${size})`;\n }\n return Object.keys(raw.surfaces).length > 0 ? raw.surfaces : undefined;\n}\n\n/**\n * Serves the agent as an A2UI agent. Not mounted directly — {@link a2uiAdapter} mounts a subclass at\n * the configured path — but exported so a host can extend it under a route of its own.\n */\nexport class A2uiRunHandler {\n constructor(\n protected readonly agent: AgentService,\n protected readonly actorResolver: ActorResolver,\n protected readonly projection: A2uiStreamOptions,\n protected readonly quietMs: number | undefined,\n protected readonly maxActionBytes: number | undefined,\n protected readonly maxDataModelBytes: number | undefined = undefined,\n ) {}\n\n /**\n * `GET <path>/a2ui/threads/:threadId`: a stored thread as `{ threadId, entries }`\n * (`a2uiThreadReplay`) — what a client draws again after a reload. Owner-scoped; a thread nobody\n * has answers `{ entries: [] }`. `?catalog=<id>` names the client's basic catalog id.\n */\n async replay(\n req: Request,\n threadId: string,\n catalog: unknown,\n ): Promise<{ threadId: string; entries: ReturnType<typeof a2uiThreadReplay> }> {\n const actor = await this.actorResolver.resolve(req);\n const owner = await this.agent.threadOwner(threadId);\n if (owner === null) return { threadId, entries: [] };\n const thread = await this.agent.getThread(actor, threadId);\n const supported =\n typeof catalog === 'string'\n ? [catalog]\n : Array.isArray(catalog)\n ? catalog.filter((id): id is string => typeof id === 'string')\n : undefined;\n return {\n threadId,\n entries: a2uiThreadReplay(\n thread?.messages ?? [],\n negotiateA2uiCatalog(this.projection, supported),\n ),\n };\n }\n\n async handle(req: Request, res: Response, raw: unknown): Promise<void> {\n const body = isRecord(raw) ? raw : {};\n const agentName =\n typeof body.agent === 'string' && body.agent.length > 0 ? body.agent : undefined;\n const actor = await this.actorResolver.resolve(req);\n // The basic catalog under the id this client advertises (`a2uiClientCapabilities`).\n const projection = negotiateA2uiCatalog(\n this.projection,\n readA2uiClientCapabilities(bodyField(body, 'a2uiClientCapabilities')),\n );\n const dataModel = readDataModel(\n bodyField(body, 'a2uiClientDataModel'),\n this.maxDataModelBytes ?? 32768,\n );\n if (typeof dataModel === 'string') throw invalid('invalid_data_model', dataModel);\n\n let action: UiAction | undefined;\n if (body.action !== undefined) {\n const read = isRecord(body.action)\n ? readA2uiAction(body.action, {\n ...(this.maxActionBytes !== undefined ? { maxBytes: this.maxActionBytes } : {}),\n })\n : 'action must be an A2UI action message';\n if (typeof read === 'string') throw invalid('invalid_action', read);\n action = read;\n }\n\n // Deciding the approval a stream ended on: settle it, then stream the rest of the run.\n if (action?.name === A2UI_APPROVE_ACTION || action?.name === A2UI_REJECT_ACTION) {\n const interruptId = action.context.interruptId;\n const address = typeof interruptId === 'string' ? decodeInterruptId(interruptId) : undefined;\n if (address === undefined || address === null || address.kind === 'elicitation') {\n throw invalid('invalid_action', 'an approval action carries the interruptId it decides');\n }\n // An independent proposal: decided through the proposal service (its own run is not\n // waiting), as an AG-UI resume decides it, and answered with the configured reply.\n if (address.kind === 'proposal') {\n if (address.proposalId === undefined || address.threadId === undefined) {\n throw invalid('invalid_action', 'the interruptId names no proposal');\n }\n const decided = await this.agent.decideActionProposal(\n actor,\n address.threadId,\n address.proposalId,\n {\n decision: action.name === A2UI_APPROVE_ACTION ? 'approved' : 'rejected',\n via: A2UI_VIA,\n },\n );\n this.writeHead(res, { 'X-Agent-Thread-Id': address.threadId });\n const projector = new A2uiProjector(projection);\n const messageId = `proposal-${address.proposalId}`;\n for (const event of [\n { type: 'TEXT_MESSAGE_START' as const, messageId, role: 'assistant' as const },\n { type: 'TEXT_MESSAGE_CONTENT' as const, messageId, delta: decided.text },\n ]) {\n for (const message of projector.project(event)) res.write(`${JSON.stringify(message)}\\n`);\n }\n res.end();\n return;\n }\n // The same checks an AG-UI resume makes: the run is the actor's and still waiting, and the\n // actor may decide this call.\n await this.agent.assertResumable(actor, address.stream);\n await this.agent.checkDecision(actor, address.toolCallId);\n if (action.name === A2UI_APPROVE_ACTION) {\n await this.agent.approve(actor, address.toolCallId, { via: A2UI_VIA });\n } else {\n await this.agent.reject(actor, address.toolCallId, undefined, { via: A2UI_VIA });\n }\n await this.stream(res, address.stream, {\n skip: address.position,\n answered: [address.toolCallId],\n projection,\n });\n return;\n }\n\n const message = typeof body.message === 'string' ? body.message : '';\n const text = action !== undefined ? uiActionText(action) : message;\n if (text.trim().length === 0) {\n throw invalid('no_user_message', 'send a message or an action');\n }\n const threadId =\n typeof body.threadId === 'string' && body.threadId.length > 0 ? body.threadId : undefined;\n const owner = threadId !== undefined ? await this.agent.threadOwner(threadId) : null;\n if (owner !== null && owner !== actor.id) {\n throw new ForbiddenException('thread belongs to another actor');\n }\n let uiCapabilities: UiCapabilities | undefined;\n if (Object.hasOwn(body, 'uiCapabilities')) {\n try {\n uiCapabilities = validateUiCapabilities(body.uiCapabilities);\n } catch (error) {\n throw invalid('invalid_input', (error as Error).message);\n }\n }\n const started = await this.agent.chat({\n actor,\n message: text,\n ...(threadId === undefined ? {} : owner !== null ? { threadId } : { newThreadId: threadId }),\n ...(agentName !== undefined ? { agentName } : {}),\n ...(uiCapabilities !== undefined ? { uiCapabilities } : {}),\n ...(dataModel !== undefined ? { pageContext: { a2uiDataModel: dataModel } } : {}),\n });\n await this.stream(res, started.runId, { threadId: started.threadId, projection });\n }\n\n /** Open the JSON Lines response. */\n protected writeHead(res: Response, extra: Record<string, string>): void {\n res.status(200);\n res.setHeader('Content-Type', 'application/jsonl; charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache, no-transform');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n for (const [name, value] of Object.entries(extra)) res.setHeader(name, value);\n res.flushHeaders();\n }\n\n /** Write one run as A2UI JSON Lines, until it ends or stops to ask. */\n protected async stream(\n res: Response,\n runId: string,\n options: {\n threadId?: string;\n skip?: number;\n answered?: string[];\n projection?: A2uiStreamOptions;\n },\n ): Promise<void> {\n this.writeHead(res, {\n 'X-Agent-Run-Id': runId,\n ...(options.threadId !== undefined ? { 'X-Agent-Thread-Id': options.threadId } : {}),\n });\n const projector = new A2uiProjector(options.projection ?? this.projection);\n const write = (messages: A2uiServerMessage[]) => {\n for (const message of messages) res.write(`${JSON.stringify(message)}\\n`);\n };\n try {\n const frames = agUiFramesFromNdjson(this.agent.subscribe(runId));\n for await (const event of agUiEvents(frames, {\n threadId: options.threadId ?? runId,\n runId,\n streamRunId: runId,\n ...(options.threadId !== undefined ? { streamThreadId: options.threadId } : {}),\n ...(options.skip !== undefined ? { skip: options.skip } : {}),\n ...(options.answered !== undefined ? { answered: options.answered } : {}),\n ...(this.quietMs !== undefined ? { quietMs: this.quietMs } : {}),\n })) {\n write(projector.project(event));\n }\n } catch {\n write(projector.project({ type: 'RUN_ERROR', message: 'The run could not be followed.' }));\n }\n res.end();\n }\n}\n\n/**\n * Serve the agent as an A2UI (https://a2ui.org, v0.9) agent: `POST <path>/a2ui` answers with the\n * run as a JSON Lines stream of A2UI server-to-client messages — `createSurface`,\n * `updateComponents`, `updateDataModel`, `deleteSurface` — that any A2UI renderer draws.\n *\n * ```ts\n * import { a2uiAdapter } from '@dudousxd/nestjs-agent/a2ui'\n *\n * AgentModule.forRoot({ model, adapters: [a2uiAdapter()] })\n * ```\n *\n * The body is `{ threadId?, message?, action?, uiCapabilities?, a2uiClientCapabilities?,\n * a2uiClientDataModel?, agent? }` (the two A2UI fields also read from `metadata`, A2A-style):\n * - `message` — the user's text;\n * - `action` — an A2UI client message (`{ version: 'v0.9', action: { name, surfaceId,\n * sourceComponentId, timestamp, context } }`, or v0.8's `{ userAction }`): it becomes the turn\n * (`uiActionText`). `agora.approve` / `agora.reject` with `context.interruptId` decide the\n * approval a previous stream ended on, and stream the rest of that run (an independent\n * proposal is decided through the proposal service and answered with its reply);\n * - `threadId` — continue that thread (its owner is checked), or start one under that id;\n * - `a2uiClientCapabilities` — the catalogs the client draws (`{ 'v0.9': { supportedCatalogIds } }`,\n * what `MessageProcessor.getRendererCapabilities()` builds): the basic catalog is sent under the\n * id the client lists for it;\n * - `a2uiClientDataModel` — the data models of surfaces created with `sendDataModel`, handed to the\n * prompt builder as `pageContext.a2uiDataModel`.\n *\n * `GET <path>/a2ui/threads/:threadId` answers a stored thread as `{ threadId, entries }`\n * (`a2uiThreadReplay`): what a client draws again after a reload.\n *\n * Response headers name the library's ids: `X-Agent-Thread-Id`, `X-Agent-Run-Id`. Authenticated by\n * the module's `actorResolver`, guarded by its `guards` and owner-scoped exactly as `chat` is.\n * Components nothing maps are drawn as their text, from the `AgentGenuiModule` catalog when there\n * is one (or `catalog` here).\n */\nexport function a2uiAdapter(options: A2uiAdapterOptions = {}): AgentProtocolAdapter {\n const path = (options.path ?? 'a2ui').replace(/^\\/+|\\/+$/g, '');\n const { path: _path, quietMs, maxActionBytes, maxDataModelBytes, ...projection } = options;\n\n @Controller()\n class A2uiController extends A2uiRunHandler {\n constructor(\n // Tokens, never classes: this entry is its own bundle (see AGENT_SERVICE).\n @Inject(AGENT_SERVICE) agent: AgentService,\n @Inject(AGENT_ACTOR_RESOLVER) actorResolver: ActorResolver,\n @Optional() @Inject(GENUI_CATALOG) catalog?: Catalog,\n ) {\n super(\n agent,\n actorResolver,\n projection.catalog === undefined && catalog !== undefined\n ? { ...projection, catalog }\n : projection,\n quietMs,\n maxActionBytes,\n maxDataModelBytes,\n );\n }\n\n @Get(`${path}/threads/:threadId`)\n thread(\n @Req() req: Request,\n @Param('threadId') threadId: string,\n @Query('catalog') catalog: unknown,\n ): ReturnType<A2uiRunHandler['replay']> {\n return this.replay(req, threadId, catalog);\n }\n\n @Post(path)\n @HttpCode(200)\n run(@Req() req: Request, @Res() res: Response, @Body() body: unknown): Promise<void> {\n return this.handle(req, res, body);\n }\n }\n\n return { name: 'a2ui', controllers: [A2uiController] };\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","import type { Actor, ActorResolver } from '@dudousxd/nestjs-agent-core';\nimport { UnauthorizedException } from '@nestjs/common';\n\n/** Turns whatever your auth put on `req.user` into the agent's {@link Actor}. */\nexport type RequestUserMapper<TUser = Record<string, unknown>> = (\n user: TUser,\n req: unknown,\n) => Actor | Promise<Actor>;\n\nfunction field(user: Record<string, unknown>, ...names: string[]): unknown {\n for (const name of names) {\n const value = user[name];\n if (value !== undefined && value !== null && value !== '') return value;\n }\n return undefined;\n}\n\n/**\n * The default mapping: `id` from `id` / `sub` / `_id` / `userId`, `roles` from `roles` (an array)\n * or `role` (a string), `tenantRef` from `tenantRef` / `tenantId` / `orgId`.\n */\nexport function defaultRequestUserMapper(user: Record<string, unknown>): Actor {\n const id = field(user, 'id', 'sub', '_id', 'userId');\n if (id === undefined) {\n throw new UnauthorizedException(\n 'requestUserActorResolver: req.user has no id/sub/_id/userId — pass a mapper: ' +\n 'requestUserActorResolver((user) => ({ id: …, roles: … }))',\n );\n }\n const rawRoles = field(user, 'roles', 'role');\n const roles = Array.isArray(rawRoles)\n ? rawRoles.map(String)\n : typeof rawRoles === 'string'\n ? [rawRoles]\n : [];\n const tenant = field(user, 'tenantRef', 'tenantId', 'orgId');\n return {\n id: String(id),\n roles,\n ...(tenant !== undefined ? { tenantRef: String(tenant) } : {}),\n };\n}\n\n/**\n * Authenticated mode in one line, for apps whose auth already puts the principal on `req.user` —\n * Passport strategies, `express-session` / cookie-session middleware, a Nest guard that assigns it:\n *\n * ```ts\n * AgentModule.forRoot({ model, actorResolver: requestUserActorResolver() })\n * ```\n *\n * A request without `req.user` is refused with `401` — the agent never invents a caller. Pass a\n * mapper when your user object is shaped differently:\n *\n * ```ts\n * requestUserActorResolver((user: SessionUser) => ({ id: user.uuid, roles: user.permissions }))\n * ```\n */\nexport function requestUserActorResolver<TUser = Record<string, unknown>>(\n map?: RequestUserMapper<TUser>,\n): ActorResolver {\n return {\n async resolve(req: unknown): Promise<Actor> {\n const user =\n typeof req === 'object' && req !== null ? (req as { user?: unknown }).user : undefined;\n if (user === undefined || user === null || user === false) {\n throw new UnauthorizedException('Sign in to use the agent.');\n }\n if (map !== undefined) return map(user as TUser, req);\n return defaultRequestUserMapper(user as Record<string, unknown>);\n },\n };\n}\n"],"mappings":"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","names":["NEST_SANDBOX_KIT_DESCRIPTOR","nestSandboxKitDiscovery","options","name","manifest","NEST_SANDBOX_KIT_MANIFEST","sandboxKitDiscovery","root","resolve","process","cwd","undefined","descriptor","sandboxKitDescriptorPath","NEST_SANDBOX_KIT_DESCRIPTOR","file","outDir","kitUrl","cssUrl","tailwindUrl","production","import_kit","Object","freeze","AgentDepsFactory","AgentService","import_nestjs_agent_core","import_common","import_core","import_nestjs_agent_core","import_common","AGENT_TOOL_BRAND","Symbol","for","brand","tool","spec","handler","isBrandedFunctionalTool","value","provideAgentTool","factoryOrTool","inject","provide","useFactory","deps","useValue","provideAgentTools","factory","map","defineTool","createFunctionalTool","AGENT_GENUI","Symbol","for","AgentGenui","catalog","resolveCatalog","channels","base","sandboxClient","GENUI_CATALOG","Symbol","for","GENUI_OPTIONS","GENUI_RESOLVED","GenuiCatalogResolver","resolverProviders","resolver","undefined","provide","useClass","useValue","mergeSandboxClients","clients","merged","theme","client","one","name","kit","css","tailwind","resolveGenui","options","sandbox","asked","channels","askedChannels","assertGenuiChannels","discoveries","Map","resolveSandbox","value","nestSandboxKitDiscovery","resolveSandboxServer","Promise","all","kitName","discovery","get","sandboxKit","set","resolved","push","define","own","catalog","components","find","each","sandboxPolicyOf","ownOptions","sandboxOptions","sandboxView","entry","Object","entries","catalogSandbox","length","sandboxClient","perRequest","scope","resolve","toolOptions","_catalog","_sandbox","_channels","_sandboxKit","rest","resolveCatalog","withSandbox","base","defineCatalog","extend","defineSandbox","coreProviders","GENUI_RESOLVED","useFactory","inject","GENUI_OPTIONS","GENUI_CATALOG","AGENT_GENUI","resolverInstance","AgentGenui","mode","streaming","token","optional","provideAgentTools","perRequestResolver","genuiTools","EXPORTS","AgentGenuiModule","forRoot","module","global","providers","exports","forRootAsync","imports","delegateToolName","args","slug","target","replace","detached","AgentDepsFactory","options","model","store","sink","rolesPolicy","registry","agents","promptContributors","pricingStore","skills","memory","uiCatalog","uiCatalogResolver","genui","actionApprovalMode","assertIndependentActionCapabilities","backgroundActorResolver","memoryConfig","skillsConfig","defaultAgentName","defaultAgent","undefined","registered","list","length","name","effectiveTools","definition","delegated","delegatesTo","map","edge","agent","normalizeDelegation","tools","resolveAgent","has","agentName","alias","resolvePersonaAlias","persona","personaCatalog","get","personas","personaCatalogEntry","defaultPersona","resolvePersona","requested","findPersona","BadRequestException","statusCode","code","message","pinned","threadPersona","forProposal","proposal","_actor","executionContext","Error","deps","forAgent","id","find","withPersona","resolveUiCatalog","scope","catalog","resolve","actor","tenantRef","tenant","uiChannelGuide","channels","createToolUiChannelGuide","base","resolveCatalog","toolAllowList","followUpsCount","retrieval","historyPolicy","ask","approvalPolicy","systemPrompt","maxSteps","maxDelegationDepth","maxAgentAppearances","modelId","inputProcessors","outputProcessors","outputSchema","outputRepairAttempts","intake","toolTimeoutMs","toolTransientRetry","mode","retriever","topK","retrievalTopK","ref","label","prompt","ctx","own","scoped","basePrompt","intersectAllowLists","allowedTools","history","window","config","windowHistory","maxMessages","maxTokens","summarize","summarizeWithModel","followUps","count","AGENT_SERVICE","Symbol","for","import_nestjs_agent_core","import_common","utcDay","date","Date","toISOString","slice","childSinkWriter","writer","write","chunk","end","flush","fail","DEFAULT_MAX_ATTACHMENT_BYTES","DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES","MAX_ATTACHMENTS_PER_MESSAGE","attachmentLimits","options","staging","declared","describe","own","attachments","enabled","undefined","upload","maxBytes","allowedContentTypes","maxPerMessage","import_nestjs_agent_core","import_common","ActionProposalService","store","options","text","actionProposalText","vocabulary","DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY","replies","DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES","hasCapability","getThreadActionProposalScope","listActionProposals","capability","NotImplementedException","scope","threadId","actor","NotFoundException","tenantRef","ForbiddenException","mayDecide","proposal","mayDecideApproval","approvalPolicy","toolCallId","originToolCallId","approver","requesterRef","actorRef","listPage","query","items","rows","limit","visible","row","id","push","last","at","map","toActionProposalView","length","next","createdAt","list","decide","proposalId","command","getActionProposal","result","decideActionProposal","decision","via","remember","undefined","reason","toActionProposalMutationView","handleTextDecision","parseTextActionProposalCommand","status","textReceipt","candidates","pending","resolution","resolveTextActionProposalDecision","saturated","includes","proposalIds","proposalDecision","tooMany","ambiguous","reply","textVocabulary","textActionProposalReply","import_nestjs_agent_core","import_common","import_nestjs_agent_core","publishQuotaBlocked","actor","report","blocked","window","windows","find","candidate","period","payload","actorId","id","reason","undefined","usedTokens","limitTokens","usedUsd","limitUsd","publishAgentQuotaExceeded","threadPersona","store","threadId","projecting","personaForThread","getThread","persona","MAX_DRAIN_ATTEMPTS","ChatQueueService","logger","Logger","name","starting","Set","store","sink","quotaProvider","options","staging","deps","supported","isChatQueueStore","queueStore","NotImplementedException","state","threadId","items","paused","Promise","all","listQueue","queuePause","map","queuedMessageView","isAlive","holder","runner","has","isRunActive","activeRunForThread","live","stale","plan","args","outcome","runId","holding","attempt","head","undefined","releaseActiveStream","pause","reason","pauseReasonFor","error","message","at","Date","toISOString","setQueuePause","blocked","quotaBlock","actor","frame","queueFrame","claimed","claimActiveStream","id","replacing","removeQueuedMessage","next","messageId","input","inputFor","slice","handoff","start","launch","pausedFrame","kick","warn","started","write","add","Error","String","restore","delete","enqueueMessage","content","userText","attachments","agentName","model","pageContext","uiCapabilities","hostContext","kind","queue","publish","catch","writer","open","encodeStreamEvent","quota","report","publishQuotaBlocked","period","freshAttachments","persona","targetFor","day","utcDay","length","target","resolveAgent","hasPersonas","personaCatalog","resolvePersona","threadPersona","resolve","attachment","mediaId","interrupt","import_nestjs_agent_core","import_common","RunNotActiveException","ConflictException","code","RUN_NOT_ACTIVE_CODE","runId","statusCode","message","RUN_NOT_ACTIVE_MESSAGE","NO_USER_MESSAGE_CODE","sendableParams","params","message","undefined","BadRequestException","statusCode","code","text","trim","length","attachments","regenerate","channel","rest","stamped","pageContext","AgentService","runner","store","deps","staging","models","quotaProvider","options","queue","proposals","decideActionProposal","actor","threadId","proposalId","command","actionApprovalMode","NotFoundException","result","decide","proposalDecision","reply","decision","handleTextDecision","status","actionProposalVocabulary","textVocabulary","DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY","actionProposalReply","textActionProposalReply","listActionProposals","list","attachmentLimits","stageAttachment","file","NotImplementedException","allowedContentTypes","maxBytes","contentType","split","toLowerCase","includes","UnsupportedMediaTypeException","join","data","byteLength","PayloadTooLargeException","stage","filename","sizeBytes","queueing","supported","requireQueue","quotaReport","report","usedTokens","costUsd","quotaToday","id","utcDay","windows","period","usedUsd","assertWithinQuota","quota","blocked","publishQuotaBlocked","HttpException","HttpStatus","TOO_MANY_REQUESTS","reason","listModels","agent","providers","default","assertModelAllowed","model","entry","findCatalogModel","available","unavailableReason","resolveModel","requested","locked","threadModel","projecting","modelForThread","getThread","chat","send","mode","textDecisions","Error","queued","runId","queueStore","removeQueuedMessage","messageId","publish","ConflictException","claimed","sendOptions","target","resolveAgent","resolveAgentName","agentName","persona","resolvePersona","personaId","resolveAttachments","created","createThread","transient","newThreadId","authorized","assertOwnsThread","pinThreadPersona","input","userText","day","uiCapabilities","hostContext","start","setActiveStream","live","stale","holder","settleDeadRun","runIdFor","crypto","randomUUID","claimActiveStream","replacing","startClaimed","enqueue","started","error","releaseActiveStream","interrupting","enqueueMessage","content","interrupt","at","setQueuePause","cancel","kick","state","position","items","findIndex","item","getQueue","updateQueuedMessage","patch","assertOwnsQueuedMessage","updated","GoneException","Number","isInteger","moveQueuedMessage","interruptQueuedMessage","gone","marked","getQueuedMessage","clearQueue","resumeQueue","refs","resolve","resolved","ref","attachment","mediaId","ForbiddenException","push","subscribe","forAgent","sink","subscribeAs","assertOwnsActiveStream","approve","toolCallId","opts","assertMayDecide","signalToolCall","approved","executedByRef","remember","via","decidedVia","reject","answer","answers","assertOwnsToolCall","assertAnswersFit","answeredByRef","answeredVia","skip","skipped","toolCallApproval","assertNotExpired","resolveRunForToolCall","assertRunWaiting","signal","isRunActive","active","catch","RunNotActiveException","threadOwner","ownerOfThread","assertResumable","owner","ownerOfActiveStream","checkDecision","checkAnswer","listThreads","actorRef","threads","Promise","all","map","thread","toSummaryView","toDetailView","deleteThread","softDeleteThread","forkThread","fromMessageId","renameThread","title","updateThread","validateTitle","defaultAgent","setTitle","needsThread","personaCatalog","threadPersona","trimmed","threadDefault","threadDefaultAgent","defaultAgentName","defaultAgentForThread","activeRunId","activeRunForThread","summary","messages","freshAttachmentUrls","some","fresh","promoteThread","truncateThreadFrom","truncateFrom","setMessageFeedback","value","comment","threadOfMessage","feedback","updatedAt","Date","toISOString","listAttachments","attachmentInventory","limit","collectableAttachments","referencedMediaIds","bind","stagedBefore","olderThan","inventory","aged","filter","createdAt","referenced","Set","has","ownerOfToolCall","toolCallInput","questions","readElicitationQuestions","question","submitted","Object","hasOwn","problem","validateElicitationAnswer","defaults","approval","approver","REQUESTER_APPROVER","requesterRef","allowed","mayDecideApproval","approvalPolicy","lapsed","expiresAt","parse","now","runForToolCall","import_common","AgentApprovalPortAdapter","agent","proposals","approveActionProposal","actor","target","opts","NotImplementedException","decide","threadId","proposalId","decision","remember","undefined","via","decidedVia","rejectActionProposal","reason","approve","toolCallId","signalToolCall","approved","executedByRef","reject","import_nestjs_agent_core","import_common","AgentsController","agents","depsFactory","list","defaultAgentName","map","definition","personas","personaCatalog","name","description","isDefault","length","defaultPersona","undefined","import_nestjs_agent_core","import_common","HARD_MAX_ATTACHMENT_BYTES","ATTACHMENT_PAGE_SIZE","AttachmentsController","options","actorResolver","agents","staging","list","req","actor","resolve","listAttachments","limit","upload","file","undefined","NotImplementedException","BadRequestException","allowedContentTypes","maxBytes","attachmentLimits","includes","mimetype","UnsupportedMediaTypeException","join","size","PayloadTooLargeException","stage","data","buffer","filename","originalname","contentType","sizeBytes","limits","fileSize","import_nestjs_agent_core","import_genui","import_common","sendMode","body","interrupt","mode","undefined","BadRequestException","attachmentRefs","claimed","Array","isArray","length","MAX_ATTACHMENTS_PER_MESSAGE","map","entry","Object","keys","some","key","mediaId","ChatController","agent","actorResolver","chat","req","res","actor","resolve","attachments","uiCapabilities","validateUiCapabilities","result","send","message","threadId","agentName","persona","personaId","pageContext","regenerate","transient","model","status","json","queued","runId","pipe","subscribe","stream","after","cursor","parseCursor","headers","subscribeAs","cancel","aborted","events","setHeader","write","JSON","stringify","decoder","TextDecoder","buffer","seq","forward","line","chunk","decode","newline","indexOf","slice","error","payload","AgentStreamError","code","streamFailure","end","raw","value","test","trim","parsed","Number","isSafeInteger","import_nestjs_agent_core","import_common","TOKEN_PATTERN","MINTED","Symbol","readCookie","req","name","header","headers","cookie","raw","Array","isArray","join","undefined","pair","split","index","indexOf","slice","trim","decodeURIComponent","isHttps","secure","forwarded","proto","AnonymousActorResolver","cookieName","roles","options","resolve","request","token","test","randomBytes","toString","setCookie","digest","createHash","update","id","res","setHeader","headersSent","sameSite","secureOption","maxAge","Math","round","maxAgeDays","path","existing","getHeader","list","map","String","ConfigController","options","actorResolver","staging","models","genui","config","req","resolve","attachments","attachmentLimits","enabled","undefined","quota","enforced","identity","anonymous","AnonymousActorResolver","sandboxClient","sandbox","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","MessagesController","agent","actorResolver","feedback","req","id","body","actor","resolve","setMessageFeedback","value","comment","undefined","import_nestjs_agent_core","import_common","ModelsController","agent","actorResolver","list","req","actor","resolve","listModels","import_nestjs_agent_core","import_common","QueueController","agent","actorResolver","list","req","id","getQueue","resolve","clear","clearQueue","resume","resumeQueue","update","messageId","body","actor","message","undefined","BadRequestException","position","attachments","attachmentRefs","updateQueuedMessage","interrupt","interruptQueuedMessage","remove","removeQueuedMessage","import_nestjs_agent_core","import_common","QuotaController","agent","actorResolver","report","req","actor","resolve","quotaReport","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","model","persona","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","MAX_VIA_LENGTH","DEFAULT_VIA","toolCallId","claimed","length","BadRequestException","rejectReason","undefined","remember","via","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","ALL_AGENTS","get","NotFoundException","actor","resolve","names","map","definition","name","entries","Map","deps","forAgent","specs","registry","visibleSpecs","rolesPolicy","toolAllowList","spec","has","set","kind","presentation","values","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","assertPersonas","list","promptMethod","methodWith","SYSTEM_PROMPT_METADATA","systemPrompt","ctx","description","tools","model","modelId","maxSteps","maxDelegationDepth","maxAgentAppearances","history","outputSchema","intake","ask","outputRepairAttempts","handoff","delegatesTo","handoffEdges","personas","defaultPersona","definitions","agentNames","Set","map","definition","aliasOwner","Map","ids","persona","has","id","Error","add","alias","aliases","owner","previous","get","set","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","toolNameFromClass","className","base","replace","leadingCaps","exec","undefined","length","toLowerCase","slice","charAt","AiTool","options","target","resolved","name","kind","Reflect","defineMetadata","readAiToolMetadata","getMetadata","AiToolDiscoveryService","logger","Logger","name","discovery","registry","agents","options","onApplicationBootstrap","count","functional","wrapper","getProviders","instance","undefined","Array","isArray","length","every","each","isBrandedFunctionalTool","tool","registerFunctionalTool","meta","readAiToolMetadata","handler","execute","warn","register","kind","description","inputSchema","input","roles","ability","enabled","presentation","terminal","replacementKey","ctx","present","output","preflight","isEnabled","canUse","actor","describe","scope","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","import_nestjs_agent_core","LedgerQuotaProvider","store","limits","options","report","query","now","Date","actorRef","actor","id","windows","dayWindow","usageBetween","undefined","range","quotaPeriodRange","used","fromDay","toDay","push","window","usedTokens","usd","resetsAt","blocked","exhaustedWindow","warning","quotaWarning","quotaToday","countEstimatedCost","Math","max","costUsd","estimatedCostUsd","period","usedUsd","tokens","limitTokens","limitUsd","warnAt","import_nestjs_agent_core","import_common","logger","Logger","PricingBootService","options","model","pricingStore","onApplicationBootstrap","check","onApplicationShutdown","models","describeModels","error","warn","String","length","catalog","priceCatalog","undefined","process","env","NODE_ENV","ensureModelPricing","log","info","message","catch","import_node_crypto","import_nestjs_agent_core","import_common","ActionProposalWorkerService","worker","logger","Logger","name","settledListeners","Set","onSettled","listener","add","delete","settled","proposal","configured","options","actionProposalWorker","error","store","deps","onModuleInit","actionApprovalMode","assertIndependentActionCapabilities","backgroundActorResolver","surface","resolver","Error","ActionProposalWorker","workerId","randomUUID","executor","ActionProposalExecutor","resolveExecution","actor","forProposal","registry","rolesPolicy","resolveUiCatalog","undefined","toolAllowList","allowedTools","onError","start","onModuleDestroy","stop","import_nestjs_agent_core","import_common","bodyFields","body","field","undefined","Array","isArray","Object","keys","some","key","BadRequestException","value","ActionProposalController","proposals","actors","list","threadId","request","cursor","response","query","Error","after","JSON","parse","validateActionProposalListQuery","page","listPage","resolve","next","setHeader","encodeURIComponent","stringify","exposed","getHeader","String","items","approve","proposalId","decide","decision","remember","reject","reason","passthrough","AGENT_CHAT_QUEUE","Symbol","for","import_nestjs_agent_core","import_common","InlineAgentRunner","logger","Logger","name","pending","Map","cancelled","Set","aborts","live","factory","store","queue","isRunActive","runId","has","key","keys","startsWith","start","input","options","crypto","randomUUID","day","utcDay","deps","forAgent","agentName","add","hooks","topLevelHooks","actor","threadId","chainBelow","delegationPath","undefined","runAgentLoop","then","releaseThreadRun","catch","error","RunCancelledError","settleCancelled","message","Error","String","code","agentFailureCode","publishAgentRunFailed","recordRunEnd","status","errorCode","errorMessage","Promise","resolve","failUnsettledToolCalls","RUN_ENDED_BEFORE_TOOL_CALL","writer","sink","open","settleQueue","fail","streamFailure","finally","forgetCancel","delete","signal","toolCallId","reply","waiter","get","cancel","abort","reject","abortSignalFor","controller","AbortController","set","log","write","encodeStreamEvent","kind","end","outcome","supported","isThreadTurn","settled","frame","handoff","next","nextRunId","failure","parkApproval","timeoutMs","waiting","park","timer","lapse","setTimeout","entry","approved","expired","unref","race","clearTimeout","args","openSink","chunk","awaitApproval","call","_ctx","opts","id","awaitAnswers","request","step","_name","fn","parallel","settleAll","abortSignal","runAgent","task","runNested","depth","path","sinkRunId","parentRunId","startAgent","startDetached","deliverTo","subThread","createThread","transient","setActiveStream","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","logger","Logger","externalWrapper","modules","token","module","values","metatype","AgentModule","wrapper","providers","get","undefined","forwardingStore","target","instance","Error","Proxy","_","property","store","value","bind","has","resolveStore","options","external","AGENT_STORE","warn","InMemoryAgentStore","resolveRolesPolicy","AGENT_ROLES_POLICY","rolesPolicy","forwardingPolicy","emptyRoles","ClosedRolesPolicy","defaultRoles","DefaultRolesPolicy","can","actor","tool","policy","isQuotaProvider","quota","report","resolveCatalog","models","carried","model","catalog","list","sharedProviders","durable","engine","provide","AGENT_TOOL_REGISTRY","useFactory","ToolRegistry","AGENT_REGISTRY","AgentRegistry","AGENT_PROMPT_CONTRIBUTORS","AGENT_SKILL_SOURCES","AGENT_SKILLS","declared","resolveSkillsConfig","skills","inject","AGENT_OPTIONS","AGENT_MEMORY","memory","AGENT_SINK","sink","InProcessTokenStreamSink","ModulesContainer","AGENT_ACTOR_RESOLVER","actorResolver","AnonymousActorResolver","AGENT_MODEL","o","AGENT_QUOTA_PROVIDER","LedgerQuotaProvider","limits","warnAt","countEstimatedCost","AGENT_MODEL_CATALOG","AgentDepsFactory","AGENT_DEPS_FACTORY","useExisting","PricingBootService","AgentDiscoveryService","AiToolDiscoveryService","SkillDiscoveryService","ChatQueueService","AGENT_CHAT_QUEUE","InlineAgentRunner","AgentService","AGENT_SERVICE","ActionProposalService","ActionProposalWorkerService","AgentApprovalPortAdapter","AGENT_APPROVAL_PORT","push","AGENT_RUNNER","runner","durableRunner","AGENT_DURABLE_RUNNER","optional","exportsFor","exports","BASE_CONTROLLERS","ActionProposalController","ChatController","QueueController","ThreadsController","ToolCallController","QuotaController","AgentsController","SkillsController","MemoriesController","ToolsController","MessagesController","ModelsController","ConfigController","AttachmentsController","adapterControllers","adapters","flatMap","adapter","controllers","adapterProviders","controllersForSurface","surface","GUARDS_METADATA","applyGuards","guards","resolved","controller","Reflect","defineMetadata","guardProviders","Set","routerFor","path","RouterModule","register","assertRunnable","name","forRoot","global","imports","DiscoveryModule","useValue","forRootAsync","args","import_nestjs_agent_core","import_genui","import_common","AG_UI_VIA","invalid","code","message","BadRequestException","statusCode","warningEvents","warnings","map","type","name","AG_UI_CUSTOM","warning","value","AgUiRunHandler","agent","actorResolver","options","staging","quietMs","a2ui","undefined","handle","req","res","body","input","parseRunInput","forwarded","readForwardedProps","forwardedProps","actor","resolve","Array","isArray","tools","length","push","quiet","resume","plan","planResume","id","unrecognised","first","decisions","every","d","address","kind","decided","decideProposals","writeEvents","flatMap","outcome","index","actionProposalDecisionEvents","threadId","runId","text","proposalDecision","streamRunId","stream","assertResumable","settle","pipe","skip","position","answered","decision","toolCallId","a2uiFor","preamble","action","uiAction","turn","uiActionText","media","staged","dropped","readUserTurn","messages","NO_USER_MESSAGE_CODE","owner","threadOwner","ForbiddenException","regenerate","handleTextDecision","refs","stage","trim","context","readContext","pageContext","agUiContext","started","chat","newThreadId","agentName","persona","personaId","model","uiCapabilities","attachments","streamThreadId","limits","attachmentLimits","ref","label","mediaId","maxPerMessage","item","filename","allowedContentTypes","includes","contentType","data","maxBytes","sizeBytes","deliveries","proposals","filter","entry","abandoned","status","checkDecision","approved","readApprovalPayload","payload","reason","rejectReason","approve","via","remember","reject","checkAnswer","read","readAnswersPayload","answers","boundedAnswers","answer","deliver","planned","proposalId","outcomes","decideActionProposal","events","setHeader","flushHeaders","event","write","agUiSse","end","negotiateA2uiCatalog","readAgUiA2uiCatalogIds","A2UI_LEGACY_BASIC_CATALOG_ID","terminal","cursor","seq","frames","agUiFramesFromNdjson","subscribe","agUiEvents","agUiAdapter","path","replace","AgUiController","moduleOptions","catalog","withCatalog","run","controllers","import_nestjs_agent_core","import_a2ui","import_ag_ui","import_genui","import_common","A2UI_VIA","isRecord","value","Array","isArray","invalid","code","message","BadRequestException","statusCode","bodyField","body","key","undefined","metadata","readDataModel","raw","maxBytes","surfaces","size","TextEncoder","encode","JSON","stringify","length","Object","keys","A2uiRunHandler","agent","actorResolver","projection","quietMs","maxActionBytes","maxDataModelBytes","replay","req","threadId","catalog","actor","resolve","owner","threadOwner","entries","thread","getThread","supported","filter","id","a2uiThreadReplay","messages","negotiateA2uiCatalog","handle","res","agentName","readA2uiClientCapabilities","dataModel","action","read","readA2uiAction","name","A2UI_APPROVE_ACTION","A2UI_REJECT_ACTION","interruptId","context","address","decodeInterruptId","kind","proposalId","decided","decideActionProposal","decision","via","writeHead","projector","A2uiProjector","messageId","event","type","role","delta","text","project","write","end","assertResumable","stream","checkDecision","toolCallId","approve","reject","skip","position","answered","uiActionText","trim","ForbiddenException","uiCapabilities","hasOwn","validateUiCapabilities","error","started","chat","newThreadId","pageContext","a2uiDataModel","runId","extra","status","setHeader","flushHeaders","options","frames","agUiFramesFromNdjson","subscribe","agUiEvents","streamRunId","streamThreadId","a2uiAdapter","path","replace","_path","A2uiController","run","controllers","import_common","readHeader","req","name","undefined","headers","value","Reflect","get","HeaderActorResolver","resolve","id","length","UnauthorizedException","roles","split","map","role","trim","filter","tenantRef","import_common","field","user","names","name","value","undefined","defaultRequestUserMapper","id","UnauthorizedException","rawRoles","roles","Array","isArray","map","String","tenant","tenantRef","requestUserActorResolver","resolve","req"]}
|