@dudousxd/nestjs-agent 1.31.1 → 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.
@@ -183,8 +183,9 @@ function mergeSandboxClients(clients) {
183
183
  for (const client of clients) {
184
184
  const one = client();
185
185
  merged.theme ||= one.theme;
186
- if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
187
186
  if (one.kit !== void 0) merged.kit ??= one.kit;
187
+ if (one.css !== void 0) merged.css ??= one.css;
188
+ if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
188
189
  }
189
190
  return merged;
190
191
  }
@@ -207,7 +208,7 @@ async function resolveGenui(options) {
207
208
  }, "resolveSandbox");
208
209
  const sandbox = await resolveSandbox(asked);
209
210
  const own = options.catalog?.components.find((each) => (0, import_genui.sandboxPolicyOf)(each) !== void 0);
210
- const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && (own.sandboxView?.kit === true || own.sandboxView?.tailwind === true) ? await resolveSandbox({
211
+ const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && own.sandboxView?.kit === true ? await resolveSandbox({
211
212
  ...own.sandboxOptions,
212
213
  name: own.name
213
214
  }) : void 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vite/index.ts","../../src/genui/kit.ts","../../src/genui/index.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/genui` — generative UI for NestJS: {@link AgentGenuiModule} registers the\n * tools that push catalog components, `GENUI_CATALOG` / `@InjectGenuiCatalog()` expose the catalog,\n * and {@link GenuiCatalogResolver} serves per-request (per-tenant) catalogs. The catalog itself —\n * `defineComponent`, `defineCatalog`, validation, text fallbacks — is re-exported from\n * `@dudousxd/nestjs-agent-core/genui`, the isomorphic entry a browser imports too.\n */\nexport {\n AGENT_GENUI,\n AgentGenui,\n AgentGenuiModule,\n type AgentGenuiModuleAsyncOptions,\n type AgentGenuiModuleOptions,\n type AgentGenuiOptions,\n type AgentGenuiSandboxKitOptions,\n GENUI_CATALOG,\n GENUI_OPTIONS,\n GenuiCatalogResolver,\n InjectGenuiCatalog,\n} from './agent-genui.module.js';\nexport * from '@dudousxd/nestjs-agent-core/genui';\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":["NEST_SANDBOX_KIT_DESCRIPTOR","nestSandboxKitDiscovery","options","manifest","NEST_SANDBOX_KIT_MANIFEST","sandboxKitDiscovery","root","resolve","process","cwd","descriptor","NEST_SANDBOX_KIT_DESCRIPTOR","file","outDir","kitUrl","undefined","production","import_kit","Object","freeze","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","InjectGenuiCatalog","Inject","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","useFactory","inject","AGENT_GENUI","resolverInstance","AgentGenui","mode","streaming","token","optional","provideAgentTools","perRequestResolver","genuiTools","EXPORTS","AgentGenuiModule","forRoot","module","global","providers","exports","forRootAsync","imports"]}
1
+ {"version":3,"sources":["../../src/vite/index.ts","../../src/genui/kit.ts","../../src/genui/index.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/genui` — generative UI for NestJS: {@link AgentGenuiModule} registers the\n * tools that push catalog components, `GENUI_CATALOG` / `@InjectGenuiCatalog()` expose the catalog,\n * and {@link GenuiCatalogResolver} serves per-request (per-tenant) catalogs. The catalog itself —\n * `defineComponent`, `defineCatalog`, validation, text fallbacks — is re-exported from\n * `@dudousxd/nestjs-agent-core/genui`, the isomorphic entry a browser imports too.\n */\nexport {\n AGENT_GENUI,\n AgentGenui,\n AgentGenuiModule,\n type AgentGenuiModuleAsyncOptions,\n type AgentGenuiModuleOptions,\n type AgentGenuiOptions,\n type AgentGenuiSandboxKitOptions,\n GENUI_CATALOG,\n GENUI_OPTIONS,\n GenuiCatalogResolver,\n InjectGenuiCatalog,\n} from './agent-genui.module.js';\nexport * from '@dudousxd/nestjs-agent-core/genui';\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":["NEST_SANDBOX_KIT_DESCRIPTOR","nestSandboxKitDiscovery","options","manifest","NEST_SANDBOX_KIT_MANIFEST","sandboxKitDiscovery","root","resolve","process","cwd","descriptor","NEST_SANDBOX_KIT_DESCRIPTOR","file","outDir","kitUrl","undefined","production","import_kit","Object","freeze","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","InjectGenuiCatalog","Inject","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","useFactory","inject","AGENT_GENUI","resolverInstance","AgentGenui","mode","streaming","token","optional","provideAgentTools","perRequestResolver","genuiTools","EXPORTS","AgentGenuiModule","forRoot","module","global","providers","exports","forRootAsync","imports"]}
@@ -1,5 +1,5 @@
1
1
  import { ToolPresentation } from '@dudousxd/nestjs-agent-core';
2
- import { Catalog, GenuiCatalogScope, GenuiChannels, GenuiChannelBase, SandboxClientConfig, TreeSchemaMode, GenuiStreaming, TreeLimits, DefineSandboxOptions } from '@dudousxd/nestjs-agent-core/genui';
2
+ import { Catalog, GenuiCatalogScope, GenuiChannels, GenuiChannelBase, SandboxClientConfig, TreeSchemaMode, GenuiStreaming, TreeLimits, GenuiAbility, DefineSandboxOptions } from '@dudousxd/nestjs-agent-core/genui';
3
3
  export * from '@dudousxd/nestjs-agent-core/genui';
4
4
  import { Type, DynamicModule, ModuleMetadata, FactoryProvider } from '@nestjs/common';
5
5
 
@@ -98,6 +98,13 @@ interface AgentGenuiOptions {
98
98
  showInstructions?: string;
99
99
  /** Roles allowed to call the tools. Undefined → the roles policy default. */
100
100
  roles?: string[];
101
+ /**
102
+ * The authorization ability the UI tools declare (`ToolSpec.ability`), for an ability-aware
103
+ * authorizer such as `authzToolAuthorizer`, which denies a tool with none. A string for every
104
+ * tool; a map by tool name (`{ ui__render: 'genui.render', ui__sandbox: 'genui.sandbox' }`, a tool
105
+ * left out declares none); or a function of `{ name, component }`. The authorizer decides.
106
+ */
107
+ ability?: GenuiAbility;
101
108
  /** Override the generated presentation per component (or per tree / show tool name). */
102
109
  presentation?: (component: string) => ToolPresentation | undefined;
103
110
  /**
@@ -107,8 +114,9 @@ interface AgentGenuiOptions {
107
114
  * The browser's catalog should carry the same definition (`defineSandbox(...)` in the shared
108
115
  * catalog file) so the renderer enforces the same policy.
109
116
  *
110
- * `theme` (default on), `tailwind` and `kit` put the app's design system in the frame. `kit: true`
111
- * (and the theme's variable names) are found through `sandboxKit`: the descriptor
117
+ * `theme` (default on) and `kit` put the app's design system in the frame: `kit: true` turns on
118
+ * whatever `genuiSandboxKit()` built (styles, Tailwind, components, wrapper, docs), found through
119
+ * `sandboxKit`: the descriptor
112
120
  * `genuiSandboxKit()` (`@dudousxd/nestjs-agent/vite`) writes in dev, the Vite manifest in
113
121
  * production — and `GET <base>/config` tells the renderer where the assets are.
114
122
  */
@@ -122,9 +130,9 @@ interface AgentGenuiOptions {
122
130
  */
123
131
  channels?: GenuiChannels;
124
132
  /**
125
- * Where the sandbox kit is found (with `sandbox: { kit: true }`, `tailwind: true` or the theme's
126
- * names). No Vite runs in the Nest process, so: the descriptor the dev plugin writes, else the
127
- * production Vite manifest (read first when `NODE_ENV=production`).
133
+ * Where the sandbox kit is found (with `sandbox: { kit: true }` or the theme's names). No Vite
134
+ * runs in the Nest process, so: the descriptor the dev plugin writes, or the production Vite
135
+ * manifest — in production the manifest first, otherwise whichever was written last.
128
136
  */
129
137
  sandboxKit?: AgentGenuiSandboxKitOptions;
130
138
  }
@@ -144,7 +152,7 @@ interface AgentGenuiSandboxKitOptions {
144
152
  } | false;
145
153
  /** An explicit kit url (an SPA served from elsewhere), over what is found. */
146
154
  kitUrl?: string;
147
- /** Read the manifest first. Default: `NODE_ENV === 'production'`. */
155
+ /** Read the manifest first (else the freshest of the two). Default: `NODE_ENV === 'production'`. */
148
156
  production?: boolean;
149
157
  }
150
158
  type ResolverOption = Type<GenuiCatalogResolver> | GenuiCatalogResolver;
@@ -1,5 +1,5 @@
1
1
  import { ToolPresentation } from '@dudousxd/nestjs-agent-core';
2
- import { Catalog, GenuiCatalogScope, GenuiChannels, GenuiChannelBase, SandboxClientConfig, TreeSchemaMode, GenuiStreaming, TreeLimits, DefineSandboxOptions } from '@dudousxd/nestjs-agent-core/genui';
2
+ import { Catalog, GenuiCatalogScope, GenuiChannels, GenuiChannelBase, SandboxClientConfig, TreeSchemaMode, GenuiStreaming, TreeLimits, GenuiAbility, DefineSandboxOptions } from '@dudousxd/nestjs-agent-core/genui';
3
3
  export * from '@dudousxd/nestjs-agent-core/genui';
4
4
  import { Type, DynamicModule, ModuleMetadata, FactoryProvider } from '@nestjs/common';
5
5
 
@@ -98,6 +98,13 @@ interface AgentGenuiOptions {
98
98
  showInstructions?: string;
99
99
  /** Roles allowed to call the tools. Undefined → the roles policy default. */
100
100
  roles?: string[];
101
+ /**
102
+ * The authorization ability the UI tools declare (`ToolSpec.ability`), for an ability-aware
103
+ * authorizer such as `authzToolAuthorizer`, which denies a tool with none. A string for every
104
+ * tool; a map by tool name (`{ ui__render: 'genui.render', ui__sandbox: 'genui.sandbox' }`, a tool
105
+ * left out declares none); or a function of `{ name, component }`. The authorizer decides.
106
+ */
107
+ ability?: GenuiAbility;
101
108
  /** Override the generated presentation per component (or per tree / show tool name). */
102
109
  presentation?: (component: string) => ToolPresentation | undefined;
103
110
  /**
@@ -107,8 +114,9 @@ interface AgentGenuiOptions {
107
114
  * The browser's catalog should carry the same definition (`defineSandbox(...)` in the shared
108
115
  * catalog file) so the renderer enforces the same policy.
109
116
  *
110
- * `theme` (default on), `tailwind` and `kit` put the app's design system in the frame. `kit: true`
111
- * (and the theme's variable names) are found through `sandboxKit`: the descriptor
117
+ * `theme` (default on) and `kit` put the app's design system in the frame: `kit: true` turns on
118
+ * whatever `genuiSandboxKit()` built (styles, Tailwind, components, wrapper, docs), found through
119
+ * `sandboxKit`: the descriptor
112
120
  * `genuiSandboxKit()` (`@dudousxd/nestjs-agent/vite`) writes in dev, the Vite manifest in
113
121
  * production — and `GET <base>/config` tells the renderer where the assets are.
114
122
  */
@@ -122,9 +130,9 @@ interface AgentGenuiOptions {
122
130
  */
123
131
  channels?: GenuiChannels;
124
132
  /**
125
- * Where the sandbox kit is found (with `sandbox: { kit: true }`, `tailwind: true` or the theme's
126
- * names). No Vite runs in the Nest process, so: the descriptor the dev plugin writes, else the
127
- * production Vite manifest (read first when `NODE_ENV=production`).
133
+ * Where the sandbox kit is found (with `sandbox: { kit: true }` or the theme's names). No Vite
134
+ * runs in the Nest process, so: the descriptor the dev plugin writes, or the production Vite
135
+ * manifest — in production the manifest first, otherwise whichever was written last.
128
136
  */
129
137
  sandboxKit?: AgentGenuiSandboxKitOptions;
130
138
  }
@@ -144,7 +152,7 @@ interface AgentGenuiSandboxKitOptions {
144
152
  } | false;
145
153
  /** An explicit kit url (an SPA served from elsewhere), over what is found. */
146
154
  kitUrl?: string;
147
- /** Read the manifest first. Default: `NODE_ENV === 'production'`. */
155
+ /** Read the manifest first (else the freshest of the two). Default: `NODE_ENV === 'production'`. */
148
156
  production?: boolean;
149
157
  }
150
158
  type ResolverOption = Type<GenuiCatalogResolver> | GenuiCatalogResolver;
@@ -147,8 +147,9 @@ function mergeSandboxClients(clients) {
147
147
  for (const client of clients) {
148
148
  const one = client();
149
149
  merged.theme ||= one.theme;
150
- if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
151
150
  if (one.kit !== void 0) merged.kit ??= one.kit;
151
+ if (one.css !== void 0) merged.css ??= one.css;
152
+ if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
152
153
  }
153
154
  return merged;
154
155
  }
@@ -171,7 +172,7 @@ async function resolveGenui(options) {
171
172
  }, "resolveSandbox");
172
173
  const sandbox = await resolveSandbox(asked);
173
174
  const own = options.catalog?.components.find((each) => sandboxPolicyOf(each) !== void 0);
174
- const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && (own.sandboxView?.kit === true || own.sandboxView?.tailwind === true) ? await resolveSandbox({
175
+ const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && own.sandboxView?.kit === true ? await resolveSandbox({
175
176
  ...own.sandboxOptions,
176
177
  name: own.name
177
178
  }) : void 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vite/index.ts","../../src/genui/kit.ts","../../src/genui/agent-genui.module.ts","../../src/functional-tool.ts","../../src/genui/agent-genui.token.ts","../../src/genui/index.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","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","/**\n * `@dudousxd/nestjs-agent/genui` — generative UI for NestJS: {@link AgentGenuiModule} registers the\n * tools that push catalog components, `GENUI_CATALOG` / `@InjectGenuiCatalog()` expose the catalog,\n * and {@link GenuiCatalogResolver} serves per-request (per-tenant) catalogs. The catalog itself —\n * `defineComponent`, `defineCatalog`, validation, text fallbacks — is re-exported from\n * `@dudousxd/nestjs-agent-core/genui`, the isomorphic entry a browser imports too.\n */\nexport {\n AGENT_GENUI,\n AgentGenui,\n AgentGenuiModule,\n type AgentGenuiModuleAsyncOptions,\n type AgentGenuiModuleOptions,\n type AgentGenuiOptions,\n type AgentGenuiSandboxKitOptions,\n GENUI_CATALOG,\n GENUI_OPTIONS,\n GenuiCatalogResolver,\n InjectGenuiCatalog,\n} from './agent-genui.module.js';\nexport * from '@dudousxd/nestjs-agent-core/genui';\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","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","InjectGenuiCatalog","Inject","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","useFactory","inject","AGENT_GENUI","resolverInstance","AgentGenui","mode","streaming","token","optional","provideAgentTools","perRequestResolver","genuiTools","EXPORTS","AgentGenuiModule","forRoot","module","global","providers","exports","forRootAsync","imports"]}
1
+ {"version":3,"sources":["../../src/vite/index.ts","../../src/genui/kit.ts","../../src/genui/agent-genui.module.ts","../../src/functional-tool.ts","../../src/genui/agent-genui.token.ts","../../src/genui/index.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","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","/**\n * `@dudousxd/nestjs-agent/genui` — generative UI for NestJS: {@link AgentGenuiModule} registers the\n * tools that push catalog components, `GENUI_CATALOG` / `@InjectGenuiCatalog()` expose the catalog,\n * and {@link GenuiCatalogResolver} serves per-request (per-tenant) catalogs. The catalog itself —\n * `defineComponent`, `defineCatalog`, validation, text fallbacks — is re-exported from\n * `@dudousxd/nestjs-agent-core/genui`, the isomorphic entry a browser imports too.\n */\nexport {\n AGENT_GENUI,\n AgentGenui,\n AgentGenuiModule,\n type AgentGenuiModuleAsyncOptions,\n type AgentGenuiModuleOptions,\n type AgentGenuiOptions,\n type AgentGenuiSandboxKitOptions,\n GENUI_CATALOG,\n GENUI_OPTIONS,\n GenuiCatalogResolver,\n InjectGenuiCatalog,\n} from './agent-genui.module.js';\nexport * from '@dudousxd/nestjs-agent-core/genui';\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","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","InjectGenuiCatalog","Inject","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","useFactory","inject","AGENT_GENUI","resolverInstance","AgentGenui","mode","streaming","token","optional","provideAgentTools","perRequestResolver","genuiTools","EXPORTS","AgentGenuiModule","forRoot","module","global","providers","exports","forRootAsync","imports"]}
package/dist/index.cjs CHANGED
@@ -269,8 +269,9 @@ function mergeSandboxClients(clients) {
269
269
  for (const client of clients) {
270
270
  const one = client();
271
271
  merged.theme ||= one.theme;
272
- if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
273
272
  if (one.kit !== void 0) merged.kit ??= one.kit;
273
+ if (one.css !== void 0) merged.css ??= one.css;
274
+ if (one.tailwind !== void 0) merged.tailwind ??= one.tailwind;
274
275
  }
275
276
  return merged;
276
277
  }
@@ -293,7 +294,7 @@ async function resolveGenui(options) {
293
294
  }, "resolveSandbox");
294
295
  const sandbox = await resolveSandbox(asked);
295
296
  const own = options.catalog?.components.find((each) => (0, import_genui.sandboxPolicyOf)(each) !== void 0);
296
- const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && (own.sandboxView?.kit === true || own.sandboxView?.tailwind === true) ? await resolveSandbox({
297
+ const ownOptions = asked === void 0 && own?.sandboxOptions !== void 0 && own.sandboxView?.kit === true ? await resolveSandbox({
297
298
  ...own.sandboxOptions,
298
299
  name: own.name
299
300
  }) : void 0;