@dudousxd/nestjs-agent 1.31.0 → 1.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vite/index.ts","../../src/genui/kit.ts","../../src/a2ui/index.ts","../../src/a2ui/a2ui.adapter.ts","../../src/agent-service.token.ts","../../src/genui/agent-genui.module.ts","../../src/functional-tool.ts","../../src/genui/agent-genui.token.ts"],"sourcesContent":["/**\n * `@dudousxd/nestjs-agent/vite` — `genuiSandboxKit()`, the Vite plugin that puts the app's design\n * system (its components, its theme, Tailwind) inside the sandbox:\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({ plugins: [react(), genuiSandboxKit({ include: 'src/components/ui/*.tsx' })] })\n * ```\n *\n * Then `AgentGenuiModule.forRoot({ sandbox: { kit: true, tailwind: true } })` finds the bundle and\n * the docs: the descriptor the dev server writes (`.genui/sandbox-kit.json`) in dev, the Vite\n * manifest in production (see `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. `entry` (a module exporting the kit) or `include` (a glob of component\n * files); neither → the first `components/ui` folder (`src/components/ui`…). See\n * {@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 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/** Find the kit for `AgentGenuiModule.forRoot({ sandbox: { kit: true } })`. */\nexport function nestSandboxKitDiscovery(\n options: AgentGenuiSandboxKitOptions = {},\n): SandboxKitDiscovery {\n const manifest = options.manifest ?? NEST_SANDBOX_KIT_MANIFEST;\n return sandboxKitDiscovery({\n root: resolve(options.root ?? process.cwd()),\n descriptor: options.descriptor ?? NEST_SANDBOX_KIT_DESCRIPTOR,\n ...(manifest !== false ? { manifest: { file: manifest.file, outDir: manifest.outDir } } : {}),\n ...(options.kitUrl !== undefined ? { kitUrl: options.kitUrl } : {}),\n ...(options.production !== undefined ? { production: options.production } : {}),\n });\n}\n","/**\n * `@dudousxd/nestjs-agent/a2ui` — A2UI (https://a2ui.org, v0.9) for the agent: the `a2uiAdapter()`\n * route (JSON Lines of A2UI messages), and the framework-free pieces it is built from (re-exported\n * from `@dudousxd/nestjs-agent-core/a2ui`) — the `ui` frame → A2UI converter, the builtin →\n * basic-catalog mappings, the catalog export, the inbound action reader. For A2UI over AG-UI, pass\n * `a2ui: true` to `agUiAdapter()`.\n */\n\nexport * from '@dudousxd/nestjs-agent-core/a2ui';\nexport { type A2uiAdapterOptions, A2uiRunHandler, a2uiAdapter } from './a2ui.adapter.js';\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","/**\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 type { ToolPresentation } from '@dudousxd/nestjs-agent-core';\nimport type {\n Catalog,\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 /** 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), `tailwind` and `kit` put the app's design system in the frame. `kit: true`\n * (and the theme's variable names) are found through `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 }`, `tailwind: true` or the theme's\n * names). No Vite runs in the Nest process, so: the descriptor the dev plugin writes, else the\n * production Vite manifest (read first when `NODE_ENV=production`).\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 /** The dev descriptor `genuiSandboxKit()` writes. Default `.genui/sandbox-kit.json`. */\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 /** Read the manifest first. 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, Tailwind and theme names found ({@link GENUI_RESOLVED}). */\ninterface ResolvedGenui {\n sandbox?: boolean | DefineSandboxOptions;\n /** A kit or Tailwind 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.tailwind !== undefined) merged.tailwind ??= one.tailwind;\n if (one.kit !== undefined) merged.kit ??= one.kit;\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, Tailwind and theme names are found through the app's Vite output.\n const clients: Array<() => SandboxClientConfig> = [];\n let discovery: import('@dudousxd/nestjs-agent-core/genui/kit').SandboxKitDiscovery | undefined;\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 discovery ??= nestSandboxKitDiscovery(options.sandboxKit);\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 or Tailwind 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 &&\n own?.sandboxOptions !== undefined &&\n (own.sandboxView?.kit === true || own.sandboxView?.tailwind === 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"],"mappings":"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","names":["SANDBOX_KIT_DEV_PREFIX","SANDBOX_KIT_MANIFEST_KEYS","SANDBOX_KIT_UPDATE_EVENT","createGenuiSandboxKitPlugin","NEST_SANDBOX_KIT_DESCRIPTOR","resolve","sandboxKitDiscovery","nestSandboxKitDiscovery","options","manifest","NEST_SANDBOX_KIT_MANIFEST","root","process","cwd","descriptor","NEST_SANDBOX_KIT_DESCRIPTOR","file","outDir","kitUrl","undefined","production","Object","freeze","AGENT_ACTOR_RESOLVER","A2UI_APPROVE_ACTION","A2UI_REJECT_ACTION","A2uiProjector","a2uiThreadReplay","negotiateA2uiCatalog","readA2uiAction","readA2uiClientCapabilities","agUiEvents","agUiFramesFromNdjson","decodeInterruptId","uiActionText","validateUiCapabilities","BadRequestException","Body","Controller","ForbiddenException","Get","HttpCode","Inject","Optional","Param","Post","Query","Req","Res","AGENT_SERVICE","Symbol","for","assertGenuiChannels","defineCatalog","defineSandbox","genuiTools","sandboxPolicyOf","Inject","Module","createFunctionalTool","AGENT_TOOL_BRAND","Symbol","for","brand","tool","spec","handler","provideAgentTools","factory","inject","provide","Symbol","useFactory","deps","map","brand","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","tailwind","kit","resolveGenui","options","sandbox","asked","channels","askedChannels","assertGenuiChannels","discovery","resolveSandbox","value","nestSandboxKitDiscovery","resolveSandboxServer","Promise","all","sandboxKit","resolved","push","define","own","catalog","components","find","each","sandboxPolicyOf","ownOptions","sandboxOptions","sandboxView","name","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","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"]}
1
+ {"version":3,"sources":["../../src/vite/index.ts","../../src/genui/kit.ts","../../src/a2ui/index.ts","../../src/a2ui/a2ui.adapter.ts","../../src/agent-service.token.ts","../../src/genui/agent-genui.module.ts","../../src/functional-tool.ts","../../src/genui/agent-genui.token.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 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/** Find the kit for `AgentGenuiModule.forRoot({ sandbox: { kit: true } })`. */\nexport function nestSandboxKitDiscovery(\n options: AgentGenuiSandboxKitOptions = {},\n): SandboxKitDiscovery {\n const manifest = options.manifest ?? NEST_SANDBOX_KIT_MANIFEST;\n return sandboxKitDiscovery({\n root: resolve(options.root ?? process.cwd()),\n descriptor: options.descriptor ?? NEST_SANDBOX_KIT_DESCRIPTOR,\n ...(manifest !== false ? { manifest: { file: manifest.file, outDir: manifest.outDir } } : {}),\n ...(options.kitUrl !== undefined ? { kitUrl: options.kitUrl } : {}),\n ...(options.production !== undefined ? { production: options.production } : {}),\n });\n}\n","/**\n * `@dudousxd/nestjs-agent/a2ui` — A2UI (https://a2ui.org, v0.9) for the agent: the `a2uiAdapter()`\n * route (JSON Lines of A2UI messages), and the framework-free pieces it is built from (re-exported\n * from `@dudousxd/nestjs-agent-core/a2ui`) — the `ui` frame → A2UI converter, the builtin →\n * basic-catalog mappings, the catalog export, the inbound action reader. For A2UI over AG-UI, pass\n * `a2ui: true` to `agUiAdapter()`.\n */\n\nexport * from '@dudousxd/nestjs-agent-core/a2ui';\nexport { type A2uiAdapterOptions, A2uiRunHandler, a2uiAdapter } from './a2ui.adapter.js';\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","/**\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 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 /** The dev descriptor `genuiSandboxKit()` writes. Default `.genui/sandbox-kit.json`. */\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 /** 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.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 let discovery: import('@dudousxd/nestjs-agent-core/genui/kit').SandboxKitDiscovery | undefined;\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 discovery ??= nestSandboxKitDiscovery(options.sandboxKit);\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"],"mappings":"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","names":["SANDBOX_KIT_DEV_PREFIX","SANDBOX_KIT_MANIFEST_KEYS","SANDBOX_KIT_UPDATE_EVENT","createGenuiSandboxKitPlugin","NEST_SANDBOX_KIT_DESCRIPTOR","resolve","sandboxKitDiscovery","nestSandboxKitDiscovery","options","manifest","NEST_SANDBOX_KIT_MANIFEST","root","process","cwd","descriptor","NEST_SANDBOX_KIT_DESCRIPTOR","file","outDir","kitUrl","undefined","production","Object","freeze","AGENT_ACTOR_RESOLVER","A2UI_APPROVE_ACTION","A2UI_REJECT_ACTION","A2uiProjector","a2uiThreadReplay","negotiateA2uiCatalog","readA2uiAction","readA2uiClientCapabilities","agUiEvents","agUiFramesFromNdjson","decodeInterruptId","uiActionText","validateUiCapabilities","BadRequestException","Body","Controller","ForbiddenException","Get","HttpCode","Inject","Optional","Param","Post","Query","Req","Res","AGENT_SERVICE","Symbol","for","assertGenuiChannels","defineCatalog","defineSandbox","genuiTools","sandboxPolicyOf","Inject","Module","createFunctionalTool","AGENT_TOOL_BRAND","Symbol","for","brand","tool","spec","handler","provideAgentTools","factory","inject","provide","Symbol","useFactory","deps","map","brand","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","kit","css","tailwind","resolveGenui","options","sandbox","asked","channels","askedChannels","assertGenuiChannels","discovery","resolveSandbox","value","nestSandboxKitDiscovery","resolveSandboxServer","Promise","all","sandboxKit","resolved","push","define","own","catalog","components","find","each","sandboxPolicyOf","ownOptions","sandboxOptions","sandboxView","name","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","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"]}
@@ -1,12 +1,14 @@
1
- import { ResolveToolUiCatalog, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
1
+ import { ResolveToolUiCatalog, ToolUiChannelGuide, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
2
2
  import { Catalog } from '@dudousxd/nestjs-agent-core/genui';
3
3
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
4
  import { Provider, InjectionToken, Type, FactoryProvider, CanActivate, ModuleMetadata, OptionalFactoryDependency } from '@nestjs/common';
5
- import { G as GenuiCatalogResolver } from './agent-genui.module-D0X3YnzO.cjs';
5
+ import { GenuiCatalogResolver, AgentGenui } from './genui/index.cjs';
6
6
 
7
7
  /** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */
8
8
  interface AgentDeps {
9
9
  resolveUiCatalog?: ResolveToolUiCatalog;
10
+ /** genui `channels`: the channel's prompt block, and what tool pushes were delivered as. */
11
+ uiChannelGuide?: ToolUiChannelGuide;
10
12
  actionApprovalMode?: 'blocking' | 'independent';
11
13
  model: ModelProvider;
12
14
  store: AgentStore;
@@ -644,6 +646,7 @@ declare function delegateToolName(args: {
644
646
  }): string;
645
647
  /** Builds the per-agent loop deps. The single-agent case is just the one registered `@Agent`. */
646
648
  declare class AgentDepsFactory {
649
+ #private;
647
650
  private readonly options;
648
651
  private readonly model;
649
652
  private readonly store;
@@ -657,7 +660,8 @@ declare class AgentDepsFactory {
657
660
  private readonly memory;
658
661
  private readonly uiCatalog?;
659
662
  private readonly uiCatalogResolver?;
660
- constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], pricingStore: AgentPricingStore | undefined, skills: SkillsConfig | undefined, memory: MemoryConfig | undefined, uiCatalog?: Catalog | undefined, uiCatalogResolver?: GenuiCatalogResolver | undefined);
663
+ private readonly genui?;
664
+ constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], pricingStore: AgentPricingStore | undefined, skills: SkillsConfig | undefined, memory: MemoryConfig | undefined, uiCatalog?: Catalog | undefined, uiCatalogResolver?: GenuiCatalogResolver | undefined, genui?: AgentGenui | undefined);
661
665
  /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
662
666
  memoryConfig(): MemoryConfig | undefined;
663
667
  /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */
@@ -691,6 +695,10 @@ declare class AgentDepsFactory {
691
695
  threadPersona?: string | null;
692
696
  }): string | undefined;
693
697
  forProposal(proposal: ActionProposal, _actor: Actor): AgentDeps;
698
+ /** The turn's UI catalog: the per-request resolver's, else the app's. */
699
+ private readonly resolveUiCatalog;
700
+ /** genui `channels`: what the model is told per channel. Built once; `undefined` without channels. */
701
+ private uiChannelGuide;
694
702
  forAgent(agentName?: string): AgentDeps;
695
703
  /**
696
704
  * A persona baked into an agent's deps — how a run journaled under an agent name that a persona
@@ -1,12 +1,14 @@
1
- import { ResolveToolUiCatalog, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
1
+ import { ResolveToolUiCatalog, ToolUiChannelGuide, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, createFunctionalTool, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ActionProposal, TextActionProposalConfig, PriceCatalogOptions, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
2
2
  import { Catalog } from '@dudousxd/nestjs-agent-core/genui';
3
3
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
4
  import { Provider, InjectionToken, Type, FactoryProvider, CanActivate, ModuleMetadata, OptionalFactoryDependency } from '@nestjs/common';
5
- import { G as GenuiCatalogResolver } from './agent-genui.module-D0X3YnzO.js';
5
+ import { GenuiCatalogResolver, AgentGenui } from './genui/index.js';
6
6
 
7
7
  /** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */
8
8
  interface AgentDeps {
9
9
  resolveUiCatalog?: ResolveToolUiCatalog;
10
+ /** genui `channels`: the channel's prompt block, and what tool pushes were delivered as. */
11
+ uiChannelGuide?: ToolUiChannelGuide;
10
12
  actionApprovalMode?: 'blocking' | 'independent';
11
13
  model: ModelProvider;
12
14
  store: AgentStore;
@@ -644,6 +646,7 @@ declare function delegateToolName(args: {
644
646
  }): string;
645
647
  /** Builds the per-agent loop deps. The single-agent case is just the one registered `@Agent`. */
646
648
  declare class AgentDepsFactory {
649
+ #private;
647
650
  private readonly options;
648
651
  private readonly model;
649
652
  private readonly store;
@@ -657,7 +660,8 @@ declare class AgentDepsFactory {
657
660
  private readonly memory;
658
661
  private readonly uiCatalog?;
659
662
  private readonly uiCatalogResolver?;
660
- constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], pricingStore: AgentPricingStore | undefined, skills: SkillsConfig | undefined, memory: MemoryConfig | undefined, uiCatalog?: Catalog | undefined, uiCatalogResolver?: GenuiCatalogResolver | undefined);
663
+ private readonly genui?;
664
+ constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], pricingStore: AgentPricingStore | undefined, skills: SkillsConfig | undefined, memory: MemoryConfig | undefined, uiCatalog?: Catalog | undefined, uiCatalogResolver?: GenuiCatalogResolver | undefined, genui?: AgentGenui | undefined);
661
665
  /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
662
666
  memoryConfig(): MemoryConfig | undefined;
663
667
  /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */
@@ -691,6 +695,10 @@ declare class AgentDepsFactory {
691
695
  threadPersona?: string | null;
692
696
  }): string | undefined;
693
697
  forProposal(proposal: ActionProposal, _actor: Actor): AgentDeps;
698
+ /** The turn's UI catalog: the per-request resolver's, else the app's. */
699
+ private readonly resolveUiCatalog;
700
+ /** genui `channels`: what the model is told per channel. Built once; `undefined` without channels. */
701
+ private uiChannelGuide;
694
702
  forAgent(agentName?: string): AgentDeps;
695
703
  /**
696
704
  * A persona baked into an agent's deps — how a run journaled under an agent name that a persona
@@ -386,6 +386,7 @@ var AgentRunSteps = class {
386
386
  }
387
387
  throw error;
388
388
  }
389
+ output = await (0, import_nestjs_agent_core3.withChannelDelivery)(deps, input.ctx, output, ui.components());
389
390
  return input.collectUi === true ? (0, import_nestjs_agent_core3.wrapToolStepOutput)(output, ui.components(), ui.text()) : output;
390
391
  }
391
392
  };
@@ -1322,7 +1323,7 @@ __name(provideAgentTools, "provideAgentTools");
1322
1323
 
1323
1324
  // src/genui/agent-genui.token.ts
1324
1325
  var AGENT_GENUI = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:genui");
1325
- var AgentGenui = class {
1326
+ var AgentGenui2 = class {
1326
1327
  static {
1327
1328
  __name(this, "AgentGenui");
1328
1329
  }
@@ -1383,8 +1384,9 @@ function mergeSandboxClients(clients) {
1383
1384
  for (const client of clients) {
1384
1385
  const one = client();
1385
1386
  merged.theme ||= one.theme;
1386
- if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
1387
1387
  if (one.kit !== void 0) merged.kit ??= one.kit;
1388
+ if (one.css !== void 0) merged.css ??= one.css;
1389
+ if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
1388
1390
  }
1389
1391
  return merged;
1390
1392
  }
@@ -1407,7 +1409,7 @@ async function resolveGenui(options) {
1407
1409
  }, "resolveSandbox");
1408
1410
  const sandbox = await resolveSandbox(asked);
1409
1411
  const own = options.catalog?.components.find((each) => (0, import_genui2.sandboxPolicyOf)(each) !== void 0);
1410
- const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && (own.sandboxView?.kit === true || own.sandboxView?.tailwind === true) ? await resolveSandbox({
1412
+ const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && own.sandboxView?.kit === true ? await resolveSandbox({
1411
1413
  ...own.sandboxOptions,
1412
1414
  name: own.name
1413
1415
  }) : void 0;
@@ -1492,7 +1494,7 @@ function coreProviders(resolver) {
1492
1494
  },
1493
1495
  {
1494
1496
  provide: AGENT_GENUI,
1495
- useFactory: /* @__PURE__ */ __name((options, catalog, resolved, resolverInstance) => new AgentGenui(catalog, perRequest(resolverInstance), resolved.channels, {
1497
+ useFactory: /* @__PURE__ */ __name((options, catalog, resolved, resolverInstance) => new AgentGenui2(catalog, perRequest(resolverInstance), resolved.channels, {
1496
1498
  ...options.mode !== void 0 ? {
1497
1499
  mode: options.mode
1498
1500
  } : {},
@@ -1628,7 +1630,8 @@ var AgentDepsFactory2 = class {
1628
1630
  memory;
1629
1631
  uiCatalog;
1630
1632
  uiCatalogResolver;
1631
- constructor(options, model, store, sink, rolesPolicy, registry, agents, promptContributors, pricingStore, skills, memory, uiCatalog, uiCatalogResolver) {
1633
+ genui;
1634
+ constructor(options, model, store, sink, rolesPolicy, registry, agents, promptContributors, pricingStore, skills, memory, uiCatalog, uiCatalogResolver, genui) {
1632
1635
  this.options = options;
1633
1636
  this.model = model;
1634
1637
  this.store = store;
@@ -1642,6 +1645,7 @@ var AgentDepsFactory2 = class {
1642
1645
  this.memory = memory;
1643
1646
  this.uiCatalog = uiCatalog;
1644
1647
  this.uiCatalogResolver = uiCatalogResolver;
1648
+ this.genui = genui;
1645
1649
  if (options.actionApprovalMode === "independent") (0, import_nestjs_agent_core9.assertIndependentActionCapabilities)(store, options.backgroundActorResolver);
1646
1650
  }
1647
1651
  /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
@@ -1743,6 +1747,30 @@ var AgentDepsFactory2 = class {
1743
1747
  }
1744
1748
  return deps;
1745
1749
  }
1750
+ /** The turn's UI catalog: the per-request resolver's, else the app's. */
1751
+ resolveUiCatalog = /* @__PURE__ */ __name((scope) => {
1752
+ const catalog = this.uiCatalogResolver?.resolve({
1753
+ ...scope,
1754
+ ...scope.actor.tenantRef !== void 0 ? {
1755
+ tenant: scope.actor.tenantRef
1756
+ } : {}
1757
+ }) ?? this.uiCatalog;
1758
+ if (!catalog) throw new Error("UI catalog unavailable");
1759
+ return catalog;
1760
+ }, "resolveUiCatalog");
1761
+ #uiChannelGuide;
1762
+ /** genui `channels`: what the model is told per channel. Built once; `undefined` without channels. */
1763
+ uiChannelGuide() {
1764
+ if (this.#uiChannelGuide === void 0) {
1765
+ const channels = this.genui?.channels;
1766
+ this.#uiChannelGuide = channels === void 0 || this.uiCatalog === void 0 && this.uiCatalogResolver === void 0 ? null : (0, import_nestjs_agent_core9.createToolUiChannelGuide)({
1767
+ channels,
1768
+ base: this.genui?.base ?? {},
1769
+ resolveCatalog: this.resolveUiCatalog
1770
+ });
1771
+ }
1772
+ return this.#uiChannelGuide ?? void 0;
1773
+ }
1746
1774
  forAgent(agentName) {
1747
1775
  const name = agentName ?? this.defaultAgentName();
1748
1776
  if (agentName !== void 0 && !this.agents.has(agentName)) {
@@ -1758,6 +1786,7 @@ var AgentDepsFactory2 = class {
1758
1786
  const retrieval = this.options.retrieval;
1759
1787
  const historyPolicy = this.historyPolicy(definition);
1760
1788
  const ask = definition?.ask ?? this.options.ask;
1789
+ const uiChannelGuide = this.uiChannelGuide();
1761
1790
  return {
1762
1791
  model: this.model,
1763
1792
  store: this.store,
@@ -1771,16 +1800,10 @@ var AgentDepsFactory2 = class {
1771
1800
  } : {},
1772
1801
  registry: this.registry,
1773
1802
  ...this.uiCatalog !== void 0 || this.uiCatalogResolver !== void 0 ? {
1774
- resolveUiCatalog: /* @__PURE__ */ __name((scope) => {
1775
- const catalog = this.uiCatalogResolver?.resolve({
1776
- ...scope,
1777
- ...scope.actor.tenantRef !== void 0 ? {
1778
- tenant: scope.actor.tenantRef
1779
- } : {}
1780
- }) ?? this.uiCatalog;
1781
- if (!catalog) throw new Error("UI catalog unavailable");
1782
- return catalog;
1783
- }, "resolveUiCatalog")
1803
+ resolveUiCatalog: this.resolveUiCatalog
1804
+ } : {},
1805
+ ...uiChannelGuide !== void 0 ? {
1806
+ uiChannelGuide
1784
1807
  } : {},
1785
1808
  promptContributors: this.promptContributors,
1786
1809
  systemPrompt: definition?.systemPrompt ?? this.options.systemPrompt ?? "You are a helpful assistant.",
@@ -1951,6 +1974,8 @@ AgentDepsFactory2 = _ts_decorate6([
1951
1974
  _ts_param4(11, (0, import_common6.Optional)()),
1952
1975
  _ts_param4(11, (0, import_common6.Inject)(GENUI_CATALOG)),
1953
1976
  _ts_param4(12, (0, import_common6.Optional)()),
1977
+ _ts_param4(13, (0, import_common6.Optional)()),
1978
+ _ts_param4(13, (0, import_common6.Inject)(AGENT_GENUI)),
1954
1979
  _ts_metadata4("design:type", Function),
1955
1980
  _ts_metadata4("design:paramtypes", [
1956
1981
  typeof AgentModuleOptions === "undefined" ? Object : AgentModuleOptions,
@@ -1965,7 +1990,8 @@ AgentDepsFactory2 = _ts_decorate6([
1965
1990
  Object,
1966
1991
  Object,
1967
1992
  typeof Catalog === "undefined" ? Object : Catalog,
1968
- typeof GenuiCatalogResolver === "undefined" ? Object : GenuiCatalogResolver
1993
+ typeof GenuiCatalogResolver === "undefined" ? Object : GenuiCatalogResolver,
1994
+ typeof AgentGenui === "undefined" ? Object : AgentGenui
1969
1995
  ])
1970
1996
  ], AgentDepsFactory2);
1971
1997