@happyvertical/smrt-core 0.51.6 → 0.51.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/agents/build-knowledge.md +13 -0
- package/dist/consumer-plugin/index.d.ts.map +1 -1
- package/dist/consumer-plugin/index.js +141 -49
- package/dist/consumer-plugin/index.js.map +1 -1
- package/dist/manifest/discover-smrt-packages.d.ts +3 -2
- package/dist/manifest/discover-smrt-packages.d.ts.map +1 -1
- package/dist/manifest/discover-smrt-packages.js +34 -15
- package/dist/manifest/discover-smrt-packages.js.map +1 -1
- package/dist/manifest/package-manifest-exports.d.ts +34 -0
- package/dist/manifest/package-manifest-exports.d.ts.map +1 -0
- package/dist/manifest/package-manifest-exports.js +144 -0
- package/dist/manifest/package-manifest-exports.js.map +1 -0
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/migrations/differ.d.ts.map +1 -1
- package/dist/migrations/differ.js +19 -27
- package/dist/migrations/differ.js.map +1 -1
- package/dist/schema/column-data-probes.d.ts +71 -0
- package/dist/schema/column-data-probes.d.ts.map +1 -1
- package/dist/schema/column-data-probes.js +79 -1
- package/dist/schema/column-data-probes.js.map +1 -1
- package/dist/schema/live-parity.d.ts.map +1 -1
- package/dist/schema/live-parity.js +10 -12
- package/dist/schema/live-parity.js.map +1 -1
- package/dist/smrt-knowledge.json +5 -5
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +93 -3
- package/dist/vite-plugin/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/vite-plugin/index.ts"],"sourcesContent":["/**\n * Vite plugin for automatic SMRT service generation\n * Provides virtual modules for REST, MCP, and other services\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type {\n DomainKnowledgeAgentSurface,\n DomainKnowledgeConfig,\n DomainKnowledgeManifest,\n} from '@happyvertical/smrt-types';\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';\nimport {\n loadVerifiedSmrtGenerationSnapshot,\n type SmrtGenerationSnapshotOptions,\n} from '../generation-snapshot.js';\nimport { CRUD_OPERATIONS } from '../generators/custom-action.js';\nimport { buildDomainKnowledgeManifest } from '../knowledge.js';\nimport {\n mergeKnowledgeConfig,\n resolveFileKnowledgeConfig,\n} from '../knowledge-config.js';\nimport { discoverSmrtPackages } from '../manifest/discover-smrt-packages.js';\nimport {\n DETERMINISTIC_GENERATED_AT,\n type SmartObjectManifest,\n} from '../scanner/types.js';\nimport { importWorkspaceModule } from '../utils/import-workspace-module.js';\nimport type {\n ScannerAgentSurface,\n ScannerModule,\n} from '../utils/scanner-module.js';\nimport {\n renderApiClientCrudType,\n renderApiClientCustomMethodParameters,\n selectApiClientEntries,\n} from './api-client-entries.js';\nimport {\n GENERATED_CLIENT_BASE_METHODS,\n GENERATED_CLIENT_CRUD_METHODS,\n generateClientModule,\n} from './generated-client.js';\nimport { importBuildAwareModule } from './import-build-aware.js';\nimport {\n findCliApiCoherenceViolations,\n generateSvelteKitRoutes,\n validateCliIncludeAgainstApi,\n} from './sveltekit-generator.js';\nimport {\n assertSvelteKitRouteCoordinationComplete,\n contributeSvelteKitRoutes,\n expectedSvelteKitRouteOwners,\n markSvelteKitRouteParticipant,\n} from './sveltekit-route-coordinator.js';\nimport {\n buildWebMcpToolDefinitions,\n compareText,\n generateWebModule,\n selectWebCollectionEntries,\n} from './web-collections.js';\n\nexport {\n loadVerifiedSmrtGenerationSnapshot,\n type SerializeSmrtGenerationSnapshotOptions,\n type SmrtGenerationSnapshotArtifact,\n type SmrtGenerationSnapshotOptions,\n type SmrtGenerationSnapshotView,\n serializeSmrtGenerationSnapshot,\n sha256SmrtGenerationSnapshot,\n} from '../generation-snapshot.js';\nexport type {\n CliApiCoherenceViolation,\n SvelteKitOptions,\n} from './sveltekit-generator.js';\n// Re-export SvelteKit route generator for CLI usage\nexport {\n findCliApiCoherenceViolations,\n generateSvelteKitRoutes,\n methodNameToKebab,\n resolveApiActionRouteConfig,\n resolveApiActionSet,\n validateCliIncludeAgainstApi,\n} from './sveltekit-generator.js';\nexport { buildWebMcpToolDefinitions } from './web-collections.js';\n\n/**\n * Minimal structural shape of a parsed `package.json`. Only the fields the\n * plugin reads are typed; the index signature keeps the rest accessible (e.g.\n * `exports`, consumed downstream by agent-manifest generation).\n */\ninterface PackageJsonShape {\n name?: string;\n version?: string;\n [key: string]: unknown;\n}\n\nexport interface SmrtPluginOptions {\n /** Root directory that owns generated manifests and SvelteKit routes. */\n projectRoot?: string;\n /**\n * Reuse an immutable, verified manifest instead of scanning sources or\n * writing manifest files. Generated routes, virtual modules, and type\n * declarations still consume the verified manifest.\n */\n generationSnapshot?: SmrtGenerationSnapshotOptions;\n /** Glob patterns for SMRT source files */\n include?: string[];\n /** Patterns to exclude */\n exclude?: string[];\n /**\n * Follow symbolic links while discovering sources. Defaults to `false`: a\n * pnpm `node_modules` is a symlink graph with cycles, so a link-following\n * walk does not terminate on a real install (#2275). Enable it only for a\n * project that genuinely keeps sources behind a link.\n */\n followSymbolicLinks?: boolean;\n /** Output directory for generated files */\n outDir?: string;\n /** Enable hot module replacement */\n hmr?: boolean;\n /** Watch for file changes */\n watch?: boolean;\n /** Generate types */\n generateTypes?: boolean;\n /** Custom base classes to scan for */\n baseClasses?: string[];\n /** Follow import chains to detect inheritance (e.g., Event extends SmrtObject) */\n followImports?: boolean;\n /** Directory to write TypeScript declarations (relative to project root) */\n typeDeclarationsPath?: string;\n /** Plugin execution mode - controls Node.js vs browser compatibility */\n mode?: 'server' | 'client' | 'auto';\n /**\n * @deprecated OXC scanner is now the only scanner. This option is ignored.\n */\n experimentalFastScanner?: boolean;\n /** SvelteKit route auto-generation options */\n svelteKit?: {\n /** Enable SvelteKit route generation (default: false) */\n enabled: boolean;\n /** Output directory for generated routes (default: 'src/routes/api') */\n routesDir?: string;\n /** Directory containing SMRT objects (default: 'src/lib/objects') */\n objectsDir?: string;\n /** Directory for configuration file (default: 'src/lib/server') */\n configPath?: string;\n /** Configuration file name (default: 'smrt.ts') */\n configFileName?: string;\n /**\n * Apply kebab-case to custom-method URL segments (e.g. `discoverFromUrl`\n * becomes `/discover-from-url`). Opt-in for one minor; default flips in\n * the next major. An explicit `api.routes[name].path` always wins.\n */\n kebabRoutes?: boolean;\n /**\n * Change-feed `_changes` route generation (#1758). Enabled by default\n * (the route is auth-guarded fail-closed); `{ enabled: false }` skips it.\n */\n changesRoute?: { enabled?: boolean };\n /**\n * Live `_events` SSE route generation (#1763). Enabled by default (the\n * route is auth-guarded fail-closed, same-origin only); `{ enabled: false }`\n * skips it. `maxSubscribers` caps active streams per process (#1860).\n */\n eventsRoute?: { enabled?: boolean; maxSubscribers?: number };\n /**\n * CLI discovery `_resources` route generation (#2663). Enabled by\n * default, but only ever emitted when `@happyvertical/smrt-users` is\n * resolvable from the consumer; `{ enabled: false }` opts out even when\n * it is present. A pre-existing hand-written `_resources` route is\n * always preserved.\n */\n resourcesRoute?: { enabled?: boolean };\n };\n /** Domain-scoped agent/developer knowledge artifact generation. */\n knowledge?: DomainKnowledgeConfig | false;\n /**\n * Validate that every method in `cli.include` is exposed via the API\n * (so HTTP-based CLI consumers can actually reach them). Default: true.\n * Per-class opt-out via `cli: { skipApiCheck: true }` (whole class) or\n * `cli: { skipApiCheck: ['methodName'] }` (only the named methods,\n * smrt#2857).\n */\n validateCliApiCoherence?: boolean;\n}\n\n/**\n * Producer configuration exposed to companion Vite plugins.\n *\n * The consumer uses this rather than reconstructing knowledge precedence from\n * the filesystem, so inline `smrtPlugin({ knowledge })` options remain in\n * force while it refreshes the aggregate artifact.\n */\nexport interface SmrtPluginApi {\n options: {\n projectRoot?: string;\n generationSnapshot?: SmrtGenerationSnapshotOptions;\n baseClasses: string[];\n followImports: boolean;\n include: string[];\n exclude: string[];\n };\n resolveKnowledgeConfig(\n manifest: SmartObjectManifest,\n ): Promise<DomainKnowledgeConfig>;\n /**\n * Return declarations produced by this plugin's current build. This waits\n * until that build has published its local manifest, so companion plugins\n * never merge an older manifest with declarations from a newer scan.\n */\n resolveKnowledgeAgentSurface(): Promise<\n DomainKnowledgeAgentSurface | undefined\n >;\n}\n\nconst VIRTUAL_MODULES = {\n '@happyvertical/smrt-virt-routes': 'smrt:routes',\n '@happyvertical/smrt-virt-client': 'smrt:client',\n '@happyvertical/smrt-virt-mcp': 'smrt:mcp',\n '@happyvertical/smrt-virt-types': 'smrt:types',\n '@happyvertical/smrt-virt-manifest': 'smrt:manifest',\n '@happyvertical/smrt-virt-ui': 'smrt:ui',\n '@happyvertical/smrt-virt-web': 'smrt:web',\n};\n\n/**\n * Project a scanner agent surface into the knowledge-artifact shape (#2591).\n *\n * The two shapes are deliberately separate: the scanner cannot depend on\n * `@happyvertical/smrt-types` (core depends on the scanner, and importing back\n * would close the cycle), so it mirrors the vocabulary structurally and this\n * function is the one place the mirror is reconciled. `filePath` becomes\n * `sourceFile` here because the artifact records a package-relative path, not a\n * scan path.\n */\nexport function toKnowledgeAgentSurface(\n surface: ScannerAgentSurface | undefined,\n): DomainKnowledgeAgentSurface | undefined {\n if (!surface) return undefined;\n return {\n intents: surface.intents.map(({ kind: _kind, filePath, ...rest }) => ({\n ...rest,\n sourceFile: filePath,\n })),\n playbooks: surface.playbooks.map(({ kind: _kind, filePath, ...rest }) => ({\n ...rest,\n sourceFile: filePath,\n })),\n diagnostics: surface.diagnostics.map(({ filePath, ...rest }) => ({\n ...rest,\n sourceFile: filePath,\n })),\n };\n}\n\n/**\n * Print every declaration the matcher recognized but could not emit.\n *\n * A warning rather than a build failure: a computed tool set is a legitimate\n * choice, and `useWebMcpTool` is its supported path. What is NOT acceptable is\n * the declaration disappearing without a word, so the surface records it and\n * the build says so.\n */\nfunction reportAgentSurfaceDiagnostics(\n surface: DomainKnowledgeAgentSurface | undefined,\n): void {\n if (!surface || surface.diagnostics.length === 0) return;\n console.warn(\n `[smrt] ⚠️ ${surface.diagnostics.length} declaration(s) are not statically emittable and were excluded from the agent surface:`,\n );\n for (const diagnostic of surface.diagnostics) {\n const where = diagnostic.line\n ? `${diagnostic.sourceFile}:${diagnostic.line}`\n : diagnostic.sourceFile;\n console.warn(` ${where} — ${diagnostic.message}`);\n }\n}\n\n/**\n * Compare the emitted intents against the tool names this build will really\n * register, and project the result into the knowledge-artifact shape (#2725).\n *\n * The rule lives in the scanner, which owns the tool-name derivation. The INPUT\n * lives here, because only core resolves the exposure policy:\n * {@link buildWebMcpToolDefinitions} is the function that emits the runtime\n * `webMcpToolDefinitions`, so its output is the set that actually registers.\n * Handing the scanner every verb a class COULD expose would report collisions\n * with tools nobody mounts.\n *\n * The check is passed in rather than imported: core reaches the scanner through\n * {@link importScanner}, which resolves src or dist depending on how core itself\n * was built, and a static import here would defeat that.\n *\n * `declaredBy` is `Class.action` — the same identity `smrt doctor` prints beside\n * a generated model tool — so a reader can find the other side of the collision\n * without cross-referencing anything.\n */\nexport function collectAgentSurfaceToolNameCollisions(input: {\n surface: ScannerAgentSurface;\n manifest: SmartObjectManifest;\n checkAgentSurfaceToolNames: ScannerModule['checkAgentSurfaceToolNames'];\n kebabRoutes?: boolean;\n /**\n * Prefixes the fixed UI tools mount under. Nothing in a build knows this —\n * `ui.prefix` is a runtime `<Provider webmcp={{ ui: { prefix } }}>` prop, and\n * the scanner's default of `smrt_ui_` is correct for every app that leaves it\n * alone. Threaded anyway so the seam is complete: the day a build-time source\n * exists, only this call site changes.\n */\n uiToolPrefixes?: readonly string[];\n}): DomainKnowledgeAgentSurface['diagnostics'] {\n return input\n .checkAgentSurfaceToolNames(input.surface, {\n generatedToolNames: buildWebMcpToolDefinitions(input.manifest, {\n kebabRoutes: input.kebabRoutes ?? false,\n }).map((definition) => ({\n name: definition.name,\n declaredBy: `${definition.className}.${definition.action}`,\n })),\n ...(input.uiToolPrefixes ? { uiToolPrefixes: input.uiToolPrefixes } : {}),\n })\n .map(({ filePath, ...rest }) => ({ ...rest, sourceFile: filePath }));\n}\n\n/**\n * Print every emitted intent whose WebMCP tool name something else also claims\n * (#2725).\n *\n * \"Also claims\", not \"is already taken\", for the same reason `smrt doctor`'s\n * header says so: a build cannot see the provider's WebMCP `namespace` or\n * `effects` policy, either of which separates the pair outright. This line runs\n * on every build and every watch rebuild, so it is the surface an author sees\n * most; each message beneath states the condition, and the header must not\n * assert past it.\n *\n * Separate from {@link reportAgentSurfaceDiagnostics} because it says\n * something different: those declarations were EXCLUDED, these are emitted and\n * merely at risk. Folding them into that header would tell an author their\n * intent had been dropped when it had not.\n */\nfunction reportAgentSurfaceToolNameCollisions(\n diagnostics: readonly DomainKnowledgeAgentSurface['diagnostics'][number][],\n): void {\n if (diagnostics.length === 0) return;\n console.warn(\n `[smrt] ⚠️ ${diagnostics.length} declared intent(s) derive a WebMCP tool name something else also claims:`,\n );\n for (const diagnostic of diagnostics) {\n const where = diagnostic.line\n ? `${diagnostic.sourceFile}:${diagnostic.line}`\n : diagnostic.sourceFile;\n console.warn(` ${where} — ${diagnostic.message}`);\n }\n}\n\n/**\n * Order the emitted diagnostics the way the scanner's own merge does, so\n * appending the manifest-derived collisions cannot make the artifact depend on\n * when they were computed.\n */\nfunction sortKnowledgeAgentSurfaceDiagnostics(\n diagnostics: DomainKnowledgeAgentSurface['diagnostics'],\n): DomainKnowledgeAgentSurface['diagnostics'] {\n const compare = (a: string, b: string): number =>\n a < b ? -1 : a > b ? 1 : 0;\n return [...diagnostics].sort(\n (a, b) =>\n compare(a.sourceFile, b.sourceFile) ||\n (a.line ?? 0) - (b.line ?? 0) ||\n (a.column ?? 0) - (b.column ?? 0) ||\n compare(a.code, b.code) ||\n compare(a.message, b.message),\n );\n}\n\nasync function importScanner() {\n return importWorkspaceModule<ScannerModule>({\n packageName: '@happyvertical/smrt-scanner',\n distEntry: 'packages/scanner/dist/index.js',\n sourceEntry: 'packages/scanner/src/index.ts',\n purpose: 'Vite manifest scanning',\n });\n}\n\n/**\n * Matches a package's `__smrt-register__` self-registration shim by module id\n * (query strings stripped). node_modules is excluded: only the package's OWN\n * shim is rewritten during its library build, never a dependency's compiled\n * output.\n */\nconst REGISTER_SHIM_RE = /[\\\\/]__smrt-register__\\.(?:ts|mts|js|mjs)$/;\n\nexport function isRegisterShimModuleId(id: string): boolean {\n const cleanId = id.split('?')[0];\n return REGISTER_SHIM_RE.test(cleanId) && !cleanId.includes('node_modules');\n}\n\n/**\n * Generate the replacement `__smrt-register__` module with the build-time\n * manifest inlined as data (issues #1506/#1507).\n *\n * The source shim resolves `new URL('./manifest.json', import.meta.url)` at\n * runtime, which assumes the compiled module ends up next to\n * `dist/manifest.json`. That held for the package's own dist (with the #1331\n * upward-search recovery), but breaks once a CONSUMER bundles the package\n * into its own output — e.g. a SvelteKit server build relocates the module\n * into `build/server/chunks/`, the URL resolves to a manifest that does not\n * exist, registration silently no-ops, and every plain (undecorated) field is\n * dropped from INSERTs and rejected by WHERE validation. Inlining the\n * manifest at library-build time removes the runtime filesystem lookup\n * entirely, so no downstream bundler layout can break registration.\n *\n * `JSON.parse('<literal>')` is used instead of an object literal: it parses\n * faster for large payloads and sidesteps identifier/keyword edge cases.\n */\nexport function generateInlineRegisterModule(\n manifest: SmartObjectManifest,\n): string {\n const manifestLiteral = JSON.stringify(JSON.stringify(manifest));\n return [\n '// Generated by @happyvertical/smrt-core smrtPlugin at library build time.',\n '// The package manifest is inlined so self-registration cannot miss when a',\n '// downstream bundler relocates this module away from dist/manifest.json',\n '// (https://github.com/happyvertical/smrt/issues/1506,',\n '// https://github.com/happyvertical/smrt/issues/1507).',\n \"import { ObjectRegistry } from '@happyvertical/smrt-core';\",\n '',\n `ObjectRegistry.registerPackageManifest(JSON.parse(${manifestLiteral}));`,\n '',\n ].join('\\n');\n}\n\nexport function smrtPlugin(options: SmrtPluginOptions = {}): Plugin {\n const {\n projectRoot: configuredProjectRoot,\n generationSnapshot,\n include = ['src/**/*.ts', 'src/**/*.js'],\n exclude = ['**/*.test.ts', '**/*.spec.ts', '**/node_modules/**'],\n followSymbolicLinks = false,\n hmr = true,\n watch = true,\n generateTypes = true,\n baseClasses = ['SmrtObject', 'SmartObject'],\n followImports = true, // Default true: needed for multi-package inheritance\n typeDeclarationsPath = 'src/types',\n mode = 'auto',\n svelteKit = {\n enabled: false,\n routesDir: 'src/routes/api',\n objectsDir: 'src/lib/objects',\n configPath: 'src/lib/server',\n configFileName: 'smrt.ts',\n },\n knowledge,\n validateCliApiCoherence = true,\n } = options;\n\n /**\n * Dev-watcher variant of the cli↔api coherence lint: warn instead of throw,\n * so an in-flight decorator edit doesn't kill the dev server. Uses the same\n * remediation text as the strict build-time gate (`validateCliIncludeAgainstApi`)\n * so the dev-server message is as actionable as the build failure.\n *\n * `findCliApiCoherenceViolations` (#2638) now reports a violation for any\n * `cli` config shape, including a bare `cli: true`/`cli: {}` default, but\n * `validateCliIncludeAgainstApi` only THROWS for a class with a non-empty,\n * explicit `cli.include` (see that function's doc comment for why: the\n * broader default-surface population is real but unrelated pre-existing\n * over-exposure this repo hasn't triaged, not a #2638 defect). So this\n * warning must not unconditionally claim the build will fail — only an\n * explicit `cli.include` naming the action makes that true today.\n */\n function warnCliApiCoherenceViolations(m: SmartObjectManifest): void {\n if (!validateCliApiCoherence) return;\n const violations = findCliApiCoherenceViolations(m);\n if (violations.length === 0) return;\n for (const { className, unreachable, invalidSkipApiCheck } of violations) {\n for (const name of invalidSkipApiCheck ?? []) {\n console.warn(\n `[smrt] ${className}: cli.skipApiCheck names '${name}', which isn't a ` +\n `CRUD verb or a scanned public method on this class, or isn't part of ` +\n `its current cli.include/cli.exclude surface (a typo, or a stale entry ` +\n `left behind after the command was dropped from cli.include). Build ` +\n `will fail until this is resolved.\\n` +\n ` Fix the typo, or remove '${name}' from cli.skipApiCheck -- an\\n` +\n ` unrecognized or stale name grants no exemption at all.`,\n );\n }\n const cliConfig = m.objects[className]?.decoratorConfig?.cli;\n const isEnforced =\n typeof cliConfig === 'object' &&\n cliConfig !== null &&\n Array.isArray(cliConfig.include) &&\n cliConfig.include.length > 0;\n const methods = m.objects[className]?.methods ?? {};\n const isRealCommandName = (name: string) =>\n (CRUD_OPERATIONS as readonly string[]).includes(name) ||\n methods[name]?.isPublic === true;\n for (const action of unreachable) {\n const skipApiCheckSuggestion = isRealCommandName(action)\n ? ` (or \\`skipApiCheck: ['${action}']\\` to acknowledge only this command)`\n : '';\n console.warn(\n `[smrt] ${className}.${action} is exposed as a CLI command but is not ` +\n `exposed via the api.` +\n (isEnforced\n ? ' Build will fail until this is resolved.\\n'\n : ' (Not yet build-blocking for this cli:true/{} class -- see #2638.)\\n') +\n ` Either:\\n` +\n ` - Decorate '${action}' with @method({ expose: true }) to route it, or\\n` +\n ` - Add '${action}' to api.include, or\\n` +\n ` - Remove '${action}' from cli.include / add it to cli.exclude.\\n` +\n ` The CLI invokes methods over HTTP; methods without API routes are unreachable.\\n` +\n ` A public method is routed by default only when every parameter can be\\n` +\n ` built from JSON; see withheldSurfaces in the knowledge artifact for the\\n` +\n ` reason this one was withheld (#2686).\\n` +\n ` If this CLI is intentionally invoked in-process (no HTTP), set\\n` +\n ` \\`cli: { skipApiCheck: true }\\`${skipApiCheckSuggestion} on the\\n` +\n ` @smrt() decorator.`,\n );\n }\n }\n }\n\n let server: ViteDevServer | undefined;\n let manifest: SmartObjectManifest | null = null;\n /**\n * The declared agent surface from the most recent OXC scan (#2591). Held\n * beside `manifest` rather than on it, because `manifest.json` is the runtime\n * manifest and stays runtime-focused; this belongs to the knowledge artifact.\n */\n let agentSurface: DomainKnowledgeAgentSurface | undefined;\n let activeManifestScan: Promise<SmartObjectManifest> | undefined;\n let activeBuildStart: Promise<void> | undefined;\n let pluginMode: 'server' | 'client' = 'server';\n let projectRoot: string = process.cwd();\n let config: ResolvedConfig | null = null; // Store resolved config for closeBundle hook\n let resolvedPluginNames: string[] = [];\n let hasFreshConfigResolvedManifest = false;\n let configHookManifest: SmartObjectManifest | null = null;\n let generatedRoutesDuringConfig = false;\n let routeLifecycleConfig: object | undefined;\n let routeExpectedOwners: Array<'producer' | 'consumer'> = ['producer'];\n\n async function generateConfiguredSvelteKitRoutes(\n rootDir: string,\n currentManifest: SmartObjectManifest,\n ): Promise<void> {\n const routeOptions = {\n enabled: svelteKit.enabled,\n routesDir: svelteKit.routesDir || 'src/routes/api',\n objectsDir: svelteKit.objectsDir || 'src/lib/objects',\n configPath: svelteKit.configPath || 'src/lib/server',\n configFileName: svelteKit.configFileName || 'smrt.ts',\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n changesRoute: svelteKit.changesRoute,\n eventsRoute: svelteKit.eventsRoute,\n resourcesRoute: svelteKit.resourcesRoute,\n knowledge: await resolveKnowledgeConfig(rootDir, currentManifest),\n };\n if (routeLifecycleConfig) {\n await contributeSvelteKitRoutes(\n routeLifecycleConfig,\n routeExpectedOwners,\n rootDir,\n {\n owner: 'producer',\n routeManifest: currentManifest,\n semanticManifest: currentManifest,\n options: routeOptions,\n },\n );\n return;\n }\n await generateSvelteKitRoutes(rootDir, currentManifest, routeOptions);\n }\n\n /**\n * Write manifest to .smrt/manifest.json for CLI discovery.\n * This ensures `smrt db:migrate`, `smrt db:status`, etc. can find\n * locally-defined SMRT objects in non-library builds (Issue #963).\n */\n async function writeLocalManifest(\n m: SmartObjectManifest,\n rootDir: string,\n ): Promise<void> {\n try {\n const { writeFileSync, mkdirSync } = await import('node:fs');\n const { resolve } = await import('node:path');\n\n const smrtDir = resolve(rootDir, '.smrt');\n mkdirSync(smrtDir, { recursive: true });\n\n const manifestPath = resolve(smrtDir, 'manifest.json');\n writeFileSync(manifestPath, JSON.stringify(m, null, 2), 'utf-8');\n await writeDomainKnowledgeArtifact(\n m,\n rootDir,\n resolve(smrtDir, 'smrt-knowledge.json'),\n manifestPath,\n );\n\n const objectCount = Object.keys(m.objects).length;\n console.log(\n `[smrt] Wrote local manifest with ${objectCount} objects to .smrt/manifest.json`,\n );\n } catch (error) {\n console.error('[smrt] Error writing local manifest:', error);\n }\n }\n\n /**\n * @param deterministic - Emit a fixed `generatedAt` instead of the clock.\n * Set for artifacts written into the build output directory: `dist/` is\n * compared byte-for-byte by downstream caches, and a fresh checkout has no\n * previous file for {@link preserveKnowledgeGeneratedAt} to carry a value\n * forward from, so every build would otherwise emit different bytes\n * (#2223). The working copy under `.smrt/` keeps a real timestamp, which\n * is where it is useful to a human and where preservation already works.\n */\n async function writeDomainKnowledgeArtifact(\n m: SmartObjectManifest,\n rootDir: string,\n outputPath: string,\n manifestPath: string,\n deterministic = false,\n ): Promise<void> {\n const resolvedKnowledge = await resolveKnowledgeConfig(rootDir, m);\n if (resolvedKnowledge.enabled === false) {\n return;\n }\n\n const { mkdirSync, writeFileSync } = await import('node:fs');\n const { dirname } = await import('node:path');\n mkdirSync(dirname(outputPath), { recursive: true });\n const artifact = buildDomainKnowledgeManifest({\n manifest: m,\n rootDir,\n manifestPath,\n config: resolvedKnowledge,\n agentSurface,\n });\n const emitted = deterministic\n ? { ...artifact, generatedAt: DETERMINISTIC_GENERATED_AT }\n : preserveKnowledgeGeneratedAt(outputPath, artifact);\n writeFileSync(outputPath, JSON.stringify(emitted, null, 2), 'utf-8');\n }\n\n async function resolveKnowledgeConfig(\n rootDir: string,\n m: SmartObjectManifest,\n ): Promise<DomainKnowledgeConfig> {\n if (knowledge === false) return { enabled: false };\n const packageName = m.packageName ?? readPackageName(rootDir);\n return mergeKnowledgeConfig(\n await resolveFileKnowledgeConfig(rootDir, packageName),\n knowledge || {},\n );\n }\n\n function preserveKnowledgeGeneratedAt(\n outputPath: string,\n nextKnowledge: DomainKnowledgeManifest,\n ): DomainKnowledgeManifest {\n if (!existsSync(outputPath)) return nextKnowledge;\n\n try {\n const current = JSON.parse(\n readFileSync(outputPath, 'utf8'),\n ) as Partial<DomainKnowledgeManifest>;\n if (\n semanticKnowledgeJson(current) === semanticKnowledgeJson(nextKnowledge)\n ) {\n return {\n ...nextKnowledge,\n generatedAt: current.generatedAt ?? nextKnowledge.generatedAt,\n };\n }\n } catch {\n // Replace malformed artifacts.\n }\n\n return nextKnowledge;\n }\n\n function semanticKnowledgeJson(\n artifact: Partial<DomainKnowledgeManifest>,\n ): string {\n const { generatedAt: _generatedAt, ...rest } = artifact ?? {};\n return JSON.stringify(sortJson(rest));\n }\n\n function sortJson(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortJson);\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, entry]) => [key, sortJson(entry)]),\n );\n }\n return value;\n }\n\n function readPackageName(rootDir: string): string | undefined {\n try {\n const pkg = JSON.parse(\n readFileSync(join(rootDir, 'package.json'), 'utf8'),\n );\n return typeof pkg.name === 'string' ? pkg.name : undefined;\n } catch {\n return undefined;\n }\n }\n\n function validateConsumerPluginSetup(\n m: SmartObjectManifest,\n context: 'configResolved' | 'buildStart',\n ): void {\n if (config?.mode === 'test') {\n return;\n }\n\n if (config?.build?.lib) {\n return;\n }\n\n const consumerDependencies = (m.smrtDependencies || []).filter(\n (dependency) => dependency !== '@happyvertical/smrt-core',\n );\n if (consumerDependencies.length === 0) {\n return;\n }\n\n const hasConsumerPlugin = resolvedPluginNames.some(\n (name) => name === 'smrt-consumer',\n );\n if (hasConsumerPlugin) {\n return;\n }\n\n const dependencySummary =\n consumerDependencies.length <= 4\n ? consumerDependencies.join(', ')\n : `${consumerDependencies.slice(0, 4).join(', ')}, +${consumerDependencies.length - 4} more`;\n\n throw new Error(\n `[smrt] Consumer project misconfiguration detected during ${context}: found external SMRT dependencies (${dependencySummary}) but vite.config is missing smrtConsumer(). Add \"import { smrtConsumer } from '@happyvertical/smrt-core/consumer-plugin'\" and register it alongside smrtPlugin() so .smrt/register.js is generated for CLI/runtime class loading.`,\n );\n }\n\n function validateLibraryMinifySetup(\n m: SmartObjectManifest,\n context: 'configResolved' | 'buildStart',\n ): void {\n if (!config?.build?.lib) {\n return;\n }\n\n if (Object.keys(m.objects || {}).length === 0) {\n return;\n }\n\n if (config.build.minify === false) {\n return;\n }\n\n throw new Error(\n `[smrt] Library package misconfiguration detected during ${context}: packages that publish SMRT objects must set Vite build.minify = false. Minification rewrites runtime class names and breaks manifest registration, STI resolution, and collection queries in downstream apps.`,\n );\n }\n\n async function runBuildStart(): Promise<void> {\n if (hasFreshConfigResolvedManifest) {\n hasFreshConfigResolvedManifest = false;\n // configureServer may be attached between configResolved and buildStart.\n // Emit declarations from the reused manifest even though the scanner\n // itself does not need to run again.\n if (generateTypes && server && manifest) {\n await generateTypeDeclarationFile(\n manifest,\n projectRoot,\n typeDeclarationsPath,\n );\n }\n return;\n }\n\n // Rescan files on build start in all modes.\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963).\n if (manifest && !generationSnapshot) {\n await writeLocalManifest(manifest, projectRoot);\n }\n if (manifest) {\n validateLibraryMinifySetup(manifest, 'buildStart');\n validateConsumerPluginSetup(manifest, 'buildStart');\n if (validateCliApiCoherence) {\n validateCliIncludeAgainstApi(manifest);\n }\n }\n }\n\n const plugin: Plugin = {\n name: 'smrt-auto-service',\n // SvelteKit inventories routes in a `config.order = 'pre'` hook. Put SMRT\n // in Vite's earlier plugin tier so this plugin's own pre hook runs first\n // even when the documented plugin array lists sveltekit() before us.\n enforce: 'pre',\n\n // SvelteKit inventories filesystem routes in its config hook. Generate\n // SMRT routes in an earlier config hook so a clean checkout's first build\n // sees them; configResolved is too late because Vite runs those hooks\n // concurrently (#2313).\n config: {\n order: 'pre',\n async handler(userConfig, env) {\n if (!svelteKit.enabled) return;\n\n projectRoot =\n configuredProjectRoot ??\n resolve(process.cwd(), userConfig.root ?? '.');\n routeLifecycleConfig = env ?? userConfig;\n routeExpectedOwners = await expectedSvelteKitRouteOwners(\n userConfig,\n projectRoot,\n svelteKit.routesDir || 'src/routes/api',\n env,\n );\n configHookManifest = await scanAndGenerateManifest(projectRoot);\n await generateConfiguredSvelteKitRoutes(\n projectRoot,\n configHookManifest,\n );\n generatedRoutesDuringConfig = true;\n },\n },\n\n // Expose options for external access (e.g., test manifest generation)\n api: {\n options: {\n ...(configuredProjectRoot === undefined\n ? {}\n : { projectRoot: configuredProjectRoot }),\n ...(generationSnapshot === undefined ? {} : { generationSnapshot }),\n baseClasses,\n followImports,\n include,\n exclude,\n },\n resolveKnowledgeConfig: (currentManifest: SmartObjectManifest) =>\n resolveKnowledgeConfig(projectRoot, currentManifest),\n async resolveKnowledgeAgentSurface() {\n await (activeBuildStart ?? activeManifestScan);\n return agentSurface;\n },\n } satisfies SmrtPluginApi,\n\n async configResolved(resolvedConfig) {\n hasFreshConfigResolvedManifest = false;\n // Store config for closeBundle hook\n config = resolvedConfig;\n resolvedPluginNames = (resolvedConfig.plugins || []).map(\n (plugin) => plugin?.name || '',\n );\n\n // Store project root for file scanning\n projectRoot = configuredProjectRoot ?? resolvedConfig.root;\n if (svelteKit.enabled && routeLifecycleConfig) {\n assertSvelteKitRouteCoordinationComplete(routeLifecycleConfig);\n }\n\n // Detect plugin mode based on build configuration\n if (mode === 'auto') {\n const isSSRBuild = resolvedConfig.build?.ssr;\n const isFederationBuild = resolvedConfig.plugins.some((p) =>\n p.name?.includes('federation'),\n );\n const isClientBuild =\n isFederationBuild ||\n (!isSSRBuild && resolvedConfig.build?.target === 'esnext');\n\n pluginMode = isClientBuild ? 'client' : 'server';\n } else {\n pluginMode = mode;\n }\n\n console.log(`[smrt] Running in ${pluginMode} mode`);\n\n // Scan files and generate initial manifest in all modes\n manifest =\n configHookManifest ?? (await scanAndGenerateManifest(projectRoot));\n configHookManifest = null;\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest && !generationSnapshot) {\n await writeLocalManifest(manifest, projectRoot);\n }\n if (manifest) {\n validateLibraryMinifySetup(manifest, 'configResolved');\n validateConsumerPluginSetup(manifest, 'configResolved');\n if (validateCliApiCoherence) {\n validateCliIncludeAgainstApi(manifest);\n }\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && !generatedRoutesDuringConfig) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n generatedRoutesDuringConfig = false;\n\n // Vite calls buildStart immediately after configResolved for the initial\n // build. The manifest already reflects the same source tree, so let that\n // first hook reuse it. Later buildStart calls are watch rebuilds and must\n // rescan changed classes.\n hasFreshConfigResolvedManifest = true;\n },\n\n async buildStart() {\n const build = runBuildStart();\n activeBuildStart = build;\n try {\n await build;\n } finally {\n if (activeBuildStart === build) {\n activeBuildStart = undefined;\n }\n }\n },\n\n transform(_code, id) {\n // Library builds only: inline the scanned manifest into the package's\n // __smrt-register__ shim so the published dist registers field metadata\n // as data instead of resolving ./manifest.json at runtime. Runtime URL\n // resolution silently no-ops when a consumer's bundler (e.g. a\n // SvelteKit server build) relocates the module into its own chunks\n // directory, dropping every plain field from the registry (#1506,\n // #1507). Dev/test flows are untouched: the vitest plugin populates\n // manifests through its own path, and non-library builds keep the\n // original shim.\n if (!config?.build?.lib || !manifest) {\n return null;\n }\n if (!isRegisterShimModuleId(id)) {\n return null;\n }\n return {\n code: generateInlineRegisterModule(manifest),\n map: null,\n };\n },\n\n shouldTransformCachedModule({ id }) {\n // In `vite build --watch`, rollup caches transform results keyed on the\n // module's own code. The inlined register shim depends on the manifest\n // (rescanned each buildStart), not on the shim's unchanged source — so\n // force a re-transform or a field edit elsewhere in the package would\n // ship a stale inlined manifest.\n if (config?.build?.lib && isRegisterShimModuleId(id)) {\n return true;\n }\n return null;\n },\n\n configureServer(devServer) {\n server = devServer;\n\n // Serve default HTML when no index.html exists\n // Skip for SvelteKit projects (they use src/app.html and handle routing themselves)\n devServer.middlewares.use(async (req, res, next) => {\n // Skip default UI entirely for SvelteKit projects\n if (svelteKit.enabled) {\n return next();\n }\n\n if (req.url === '/' || req.url === '/index.html') {\n try {\n const { existsSync } = await import('node:fs');\n const { join } = await import('node:path');\n\n const projectRoot = devServer.config.root;\n const indexPath = join(projectRoot, 'index.html');\n\n // If index.html exists, let Vite handle it\n if (existsSync(indexPath)) {\n return next();\n }\n\n // Otherwise, serve default SMRT UI\n console.log('[smrt] Serving default UI (no index.html found)');\n let html = getDefaultHTML();\n\n // Apply Vite's HTML transformation to process module imports\n html = await devServer.transformIndexHtml('/', html);\n\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n return;\n } catch (error) {\n console.error('[smrt] Error serving default HTML:', error);\n return next();\n }\n }\n next();\n });\n\n // Set up file watching in all modes when enabled\n if (watch && hmr && !generationSnapshot) {\n // Watch for file changes\n const watcher = devServer.watcher;\n\n // Guard each watcher handler: scanAndGenerateManifest re-throws on a\n // mid-edit scan error, and an unhandled rejection in a watcher callback\n // can crash the dev server. Log and keep the previous manifest (#1378).\n watcher.on('change', async (file) => {\n try {\n if (await shouldRescan(file)) {\n console.log(`[smrt] Rescanning due to change in ${file}`);\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest) {\n await writeLocalManifest(manifest, projectRoot);\n warnCliApiCoherenceViolations(manifest);\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && server) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n\n // Invalidate virtual modules\n Object.values(VIRTUAL_MODULES).forEach((id) => {\n const module = server?.moduleGraph.getModuleById(id);\n if (module) {\n server?.reloadModule(module);\n }\n });\n }\n } catch (error) {\n console.error(\n `[smrt] Failed to rescan after change in ${file}:`,\n error,\n );\n }\n });\n\n watcher.on('add', async (file) => {\n try {\n if (await shouldRescan(file)) {\n console.log(`[smrt] Rescanning due to new file ${file}`);\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest) {\n await writeLocalManifest(manifest, projectRoot);\n warnCliApiCoherenceViolations(manifest);\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && server) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n }\n } catch (error) {\n console.error(\n `[smrt] Failed to rescan after adding ${file}:`,\n error,\n );\n }\n });\n\n watcher.on('unlink', async (file) => {\n try {\n if (await shouldRescan(file)) {\n console.log(`[smrt] Rescanning due to removed file ${file}`);\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest) {\n await writeLocalManifest(manifest, projectRoot);\n warnCliApiCoherenceViolations(manifest);\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && server) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n }\n } catch (error) {\n console.error(\n `[smrt] Failed to rescan after removing ${file}:`,\n error,\n );\n }\n });\n }\n },\n\n resolveId(id) {\n // Resolve virtual module imports\n if (id in VIRTUAL_MODULES) {\n return `\\0${VIRTUAL_MODULES[id as keyof typeof VIRTUAL_MODULES]}`;\n }\n\n // Resolve virtual index.html for dev UI (only in dev mode)\n if (id === '/index.html' && server) {\n return `\\0smrt:index-html`;\n }\n\n return null;\n },\n\n async load(id) {\n // Load virtual modules (strip the \\0 prefix)\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (!manifest) {\n manifest = await scanAndGenerateManifest(projectRoot);\n }\n\n switch (cleanId) {\n case 'smrt:routes':\n // Routes module available in all modes\n return await generateRoutesModule(manifest);\n\n case 'smrt:client':\n // Client module available in both modes\n return generateClientModule(manifest, {\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n });\n\n case 'smrt:mcp':\n // MCP module available in all modes\n return await generateMCPModule(manifest);\n\n case 'smrt:types':\n // Types module available in both modes\n return await generateTypesModule(manifest, pluginMode);\n\n case 'smrt:manifest':\n // Manifest module available in both modes\n return generateManifestModule(manifest);\n\n case 'smrt:ui':\n // UI module for default development interface\n return await loadDefaultUI();\n\n case 'smrt:index-html':\n // Virtual index.html for projects without one\n return await loadDefaultHTML();\n\n case 'smrt:web':\n // Web collection definitions for the browser client data runtime\n // (@happyvertical/smrt-web, #1761)\n return generateWebModule(manifest, {\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n });\n\n default:\n return null;\n }\n },\n\n transformIndexHtml: {\n order: 'pre',\n handler: async (html, _ctx) => {\n // Only provide default HTML if no index.html exists in project\n if (!server) return html;\n\n try {\n const { existsSync } = await import('node:fs');\n const { join } = await import('node:path');\n\n const projectRoot = server.config.root;\n const indexPath = join(projectRoot, 'index.html');\n\n // If index.html exists, use it as-is\n if (existsSync(indexPath)) {\n return html;\n }\n\n // Otherwise, provide default SMRT UI\n return await loadDefaultHTML();\n } catch (error) {\n console.error('[smrt] Error checking for index.html:', error);\n return html;\n }\n },\n },\n\n async closeBundle() {\n // Write manifest to disk during library builds\n // This allows published packages to include their manifest\n if (!manifest || !config?.build?.lib || generationSnapshot) {\n return;\n }\n\n try {\n const { writeFileSync, mkdirSync } = await import('node:fs');\n const { resolve, dirname } = await import('node:path');\n\n // Determine output directory.\n // `rollupOptions.output` may be a single object or an array; mirror the\n // prior runtime behavior where reading `.dir` off an array yields\n // undefined and falls through to `build.outDir`.\n const rollupOutput = config.build?.rollupOptions?.output;\n const rollupOutputDir = Array.isArray(rollupOutput)\n ? undefined\n : rollupOutput?.dir;\n const outDir = rollupOutputDir || config.build?.outDir || 'dist';\n const manifestPath = resolve(projectRoot, outDir, 'manifest.json');\n const knowledgePath = resolve(\n projectRoot,\n outDir,\n 'smrt-knowledge.json',\n );\n\n // Ensure directory exists\n mkdirSync(dirname(manifestPath), { recursive: true });\n\n // Write manifest file\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n await writeDomainKnowledgeArtifact(\n manifest,\n projectRoot,\n knowledgePath,\n manifestPath,\n true,\n );\n\n const objectCount = Object.keys(manifest.objects).length;\n console.log(\n `[smrt] Wrote manifest with ${objectCount} objects to ${manifestPath}`,\n );\n } catch (error) {\n console.error('[smrt] Error writing manifest file:', error);\n }\n },\n };\n markSvelteKitRouteParticipant(\n plugin,\n 'producer',\n svelteKit.enabled,\n svelteKit.routesDir || 'src/routes/api',\n async (rootDir) =>\n resolveKnowledgeConfig(rootDir, { objects: {} } as SmartObjectManifest),\n (userConfig) =>\n configuredProjectRoot ??\n resolve(\n process.cwd(),\n (userConfig as { root?: string } | undefined)?.root ?? '.',\n ),\n );\n return plugin;\n\n function scanAndGenerateManifest(\n rootDir: string,\n ): Promise<SmartObjectManifest> {\n const scan = scanAndGenerateManifestImpl(rootDir);\n const tracked = scan.finally(() => {\n if (activeManifestScan === tracked) {\n activeManifestScan = undefined;\n }\n });\n activeManifestScan = tracked;\n return tracked;\n }\n\n async function scanAndGenerateManifestImpl(\n rootDir: string,\n ): Promise<SmartObjectManifest> {\n if (generationSnapshot) {\n const verified = loadVerifiedSmrtGenerationSnapshot<SmartObjectManifest>(\n generationSnapshot,\n rootDir,\n 'project',\n );\n console.log(\n `[smrt] Reusing verified generation snapshot (${generationSnapshot.provenance})`,\n );\n if (generateTypes && server) {\n await generateTypeDeclarationFile(\n verified,\n rootDir,\n typeDeclarationsPath,\n );\n }\n return verified;\n }\n\n // NOTE: We do NOT use the framework's static manifest here\n // The static manifest JSON that core emits at build time\n // contains framework objects (like 'pleb') which should not be included\n // when scanning user code in consuming applications.\n //\n // smrtPlugin is designed to scan USER code dynamically, not load\n // framework objects. For consuming apps that need framework objects,\n // they should use smrtConsumer plugin instead.\n\n // Always use OXC-based scanner (consolidated in Issue #951)\n try {\n return await scanWithOxc(rootDir);\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('Cannot find package')\n ) {\n console.error(\n '[smrt] @happyvertical/smrt-scanner is required but not installed.',\n );\n console.error(\n '[smrt] Install it: pnpm add @happyvertical/smrt-scanner',\n );\n }\n console.error('[smrt] Error scanning files:', error);\n // Re-throw to fail the build - don't silently continue with empty manifest\n throw error;\n }\n }\n\n /**\n * Scan files using OXC-based scanner (experimental fast path)\n * Uses Rust-based oxc-parser for 2-3x faster parsing\n */\n async function scanWithOxc(rootDir: string): Promise<SmartObjectManifest> {\n const startTime = performance.now();\n\n try {\n // Import the OXC scanner package\n const scannerModule = await importScanner();\n const { OxcScanner, ManifestAdapter } = scannerModule;\n\n console.log(`[smrt] Using experimental OXC scanner for faster builds`);\n\n // Create scanner with options. Always exclude .svelte files as OXC barfs on <style> tags\n const safeExclude = [...(exclude || []), '**/*.svelte'];\n const scanner = new OxcScanner({\n cwd: rootDir,\n include,\n exclude: safeExclude,\n followSymbolicLinks,\n });\n\n // Scan and resolve inheritance\n const { results, resolved } = await scanner.scanAndResolve();\n\n // The same scan already read every module-scope `defineIntent()` /\n // `definePlaybook()` declaration (#2591). Hold it for the knowledge\n // artifact rather than scanning a second time; it never reaches the\n // runtime manifest, which stays runtime-focused.\n agentSurface = toKnowledgeAgentSurface(results.agentSurface);\n reportAgentSurfaceDiagnostics(agentSurface);\n\n // Check for errors\n if (results.errors.length > 0) {\n console.error(\n `\\n[smrt] ❌ Build failed: ${results.errors.length} error(s) during scanning:\\n`,\n );\n for (const error of results.errors) {\n console.error(\n ` ${error.filePath}:${error.line || '?'}: ${error.message}\\n`,\n );\n }\n throw new Error(\n '[smrt] Build aborted due to scan errors. See above for details.',\n );\n }\n\n // Read package.json for metadata BEFORE creating manifest (Issue #713)\n // This ensures qualified names are generated correctly for namespace isolation\n // packageJson is also needed for agent manifest generation (component discovery)\n let packageName: string | undefined;\n let packageVersion: string | undefined;\n let packageJson: PackageJsonShape | undefined;\n try {\n const { readFileSync } = await import('node:fs');\n const { join } = await import('node:path');\n const pkgPath = join(rootDir, 'package.json');\n const pkgContent = readFileSync(pkgPath, 'utf-8');\n packageJson = JSON.parse(pkgContent) as PackageJsonShape;\n packageName = packageJson.name || undefined;\n packageVersion = packageJson.version || undefined;\n } catch {\n // package.json not found or invalid - continue without packageName\n console.warn(\n '[smrt] Warning: package.json not found. Qualified names will not be generated.',\n );\n }\n\n // Convert to manifest format with packageName for qualified names (Issue #713)\n const adapter = new ManifestAdapter();\n const newManifest = adapter.toManifest(resolved, {\n packageName,\n packageVersion,\n typeAliases: results.typeAliases,\n });\n\n // Add moduleType identifier\n newManifest.moduleType = 'smrt';\n\n // Keep this as a normal module import: dynamic source imports with a\n // `.js` specifier do not reliably resolve through tsx during publish-time\n // workspace builds, even though the compiled dist path exists.\n const smrtDependencies = discoverSmrtPackages({ baseDir: rootDir });\n if (smrtDependencies.length > 0) {\n newManifest.smrtDependencies = smrtDependencies;\n console.log(\n `[smrt] Found ${smrtDependencies.length} SMRT dependencies: ${smrtDependencies.join(', ')}`,\n );\n }\n\n // Run all manifest generation passes (same as TypeScript scanner path)\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const manifestGen = new ManifestGenerator();\n // THE pass sequence — shared with generateManifest() and\n // ManifestBuilder so the three producers cannot drift (#2360).\n manifestGen.applyGenerationPasses(newManifest, {\n packageName,\n packageJson,\n });\n\n // The declared surface and the generated one are only comparable once\n // the manifest exists, which is why this runs here and not beside the\n // scan (#2725). `buildWebMcpToolDefinitions` is the same function that\n // emits `webMcpToolDefinitions` into the `smrt:web` virtual module, so\n // the comparison is against the exposure-policy-filtered set that will\n // really register — not against every verb a class could expose, which\n // would invent collisions with tools nobody mounts.\n if (agentSurface && results.agentSurface) {\n try {\n const collisions = collectAgentSurfaceToolNameCollisions({\n surface: results.agentSurface,\n manifest: newManifest,\n checkAgentSurfaceToolNames:\n scannerModule.checkAgentSurfaceToolNames,\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n });\n if (collisions.length > 0) {\n reportAgentSurfaceToolNameCollisions(collisions);\n agentSurface.diagnostics = sortKnowledgeAgentSurfaceDiagnostics([\n ...agentSurface.diagnostics,\n ...collisions,\n ]);\n }\n } catch (error) {\n // Advisory only. A manifest this cannot build definitions for fails\n // loudly where they are actually emitted; losing a warning must\n // never be the thing that breaks a build.\n console.warn(\n '[smrt] Skipped the agent-surface tool-name collision check:',\n error,\n );\n }\n }\n\n const elapsed = performance.now() - startTime;\n\n // Log results\n const objectCount = Object.keys(newManifest.objects).length;\n if (objectCount > 0) {\n const names = Object.keys(newManifest.objects).join(', ');\n console.log(`[smrt] Found ${objectCount} SMRT objects: ${names}`);\n } else {\n console.log('[smrt] No SMRT objects found');\n }\n console.log(`[smrt] OXC scan completed in ${elapsed.toFixed(2)}ms`);\n\n // Generate TypeScript declarations if enabled\n if (generateTypes && server) {\n await generateTypeDeclarationFile(\n newManifest,\n rootDir,\n typeDeclarationsPath,\n );\n }\n\n return newManifest;\n } catch (error) {\n console.error('[smrt] Error in OXC scanner:', error);\n throw error;\n }\n }\n\n async function shouldRescan(file: string): Promise<boolean> {\n // Only rescan in server mode\n if (pluginMode === 'client') {\n return false;\n }\n\n try {\n // Conditionally import minimatch\n const { minimatch } = await import('minimatch');\n\n const isIncluded = include.some((pattern) => minimatch(file, pattern));\n const isExcluded = exclude.some((pattern) => minimatch(file, pattern));\n\n return isIncluded && !isExcluded;\n } catch (error) {\n console.warn('[smrt] Error checking file patterns:', error);\n return false;\n }\n }\n}\n\n/**\n * Generate virtual routes module\n */\nasync function generateRoutesModule(\n manifest: SmartObjectManifest,\n): Promise<string> {\n try {\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const generator = new ManifestGenerator();\n const routes = generator.generateRestEndpoints(manifest);\n\n return `\n// Auto-generated REST routes from SMRT objects\n// This file is generated automatically - do not edit\n\n/**\n * Setup routes on an Express-like app\n *\n * NOTE: This virtual module function is for documentation only.\n * For actual route registration, use:\n * - import { startRestServer } from '@happyvertical/smrt-core'\n * - Or APIGenerator from '@happyvertical/smrt-core/generators'\n *\n * @param app - Express-like app instance\n * @param options - Route configuration options\n * @param options.basePath - Base path for all routes (default: '/api/v1')\n */\nexport function setupRoutes(app, options = {}) {\n const basePath = options.basePath || '/api/v1';\n\n console.warn('[smrt] setupRoutes is a documentation function only.');\n console.warn('[smrt] Use startRestServer() or APIGenerator for actual route registration.');\n console.warn('[smrt] Available endpoints:');\n${routes\n .split('\\\\n')\n .map((line) => ` console.warn(\\` \\${basePath}${line.trim()}\\`);`)\n .join('\\\\n')}\n}\n\nexport { setupRoutes as default };\n`;\n } catch (error) {\n console.warn('[smrt] Error generating routes module:', error);\n return 'export function setupRoutes(app, options = {}) { console.warn(\"Routes generation failed\"); }';\n }\n}\n\n/**\n * Generate virtual MCP module\n */\nasync function generateMCPModule(\n manifest: SmartObjectManifest,\n): Promise<string> {\n try {\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const generator = new ManifestGenerator();\n // Tool *definitions* (a JSON array), not `generateMCPTools()`'s\n // newline-joined name list, which is not a valid expression (#2631).\n const tools = generator.generateMCPToolsCode(manifest);\n\n return `\n// Auto-generated MCP tools from SMRT objects\n// This file is generated automatically - do not edit\n\nimport { SmrtMCPServer } from '@happyvertical/smrt-core/runtime';\n\nexport const tools = ${tools};\n\nexport function createMCPServer(options = {}) {\n const server = new SmrtMCPServer({\n name: options.name || 'smrt-auto-generated',\n version: options.version || '1.0.0',\n ...options\n });\n\n // Add all generated tools to the server. A handler supplied through the\n // documented \\`createMCPServer({ handlers })\\` option wins; the throwing\n // placeholder is only for tools the application did not wire up (#2631).\n const handlers = options.handlers || {};\n for (const tool of tools) {\n const handler = handlers[tool.name];\n server.addTool(\n tool,\n handler ||\n (async () => {\n throw new Error(\\`Tool '\\${tool.name}' handler must be provided by application\\`);\n }),\n );\n }\n\n return server;\n}\n\nexport { createMCPServer as default };\n`;\n } catch (error) {\n console.warn('[smrt] Error generating MCP module:', error);\n return `\nimport { SmrtMCPServer } from '@happyvertical/smrt-core/runtime';\nexport const tools = [];\nexport function createMCPServer(options = {}) {\n console.warn(\"MCP generation failed\");\n return new SmrtMCPServer({\n name: options.name || 'smrt-client',\n version: options.version || '1.0.0',\n ...options\n });\n}\n`;\n }\n}\n\n/**\n * Generate client-mode types without server dependencies\n */\nfunction generateClientModeTypes(manifest: SmartObjectManifest): string {\n const typeDefinitions: string[] = [];\n\n // Generate interfaces for each object in the manifest. Manifest key order\n // follows scan/discovery order, which is not stable across runs (#2749),\n // so sort deterministically before emitting.\n const sortedClientModeObjects = Object.entries(manifest.objects)\n .sort(\n ([leftKey, left], [rightKey, right]) =>\n compareText(\n left.qualifiedName || leftKey,\n right.qualifiedName || rightKey,\n ) || compareText(leftKey, rightKey),\n )\n .map(([, obj]) => obj);\n for (const objectMeta of sortedClientModeObjects) {\n // Manifest keys are qualified names; only the simple class name is a valid\n // TypeScript identifier (#2631). `className` is required on\n // `SmartObjectDefinition`, so there is deliberately no manifest-key\n // fallback here — one would reintroduce invalid emitted TypeScript.\n const interfaceName = objectMeta.className;\n const fields = objectMeta.fields || {};\n const propertyLines: string[] = [];\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n let type = 'any';\n\n // Map SMRT field types to TypeScript types\n switch (fieldDef.type) {\n case 'text':\n type = 'string';\n break;\n case 'decimal':\n case 'integer':\n type = 'number';\n break;\n case 'boolean':\n type = 'boolean';\n break;\n case 'datetime':\n type = 'string';\n break;\n case 'json':\n type = 'any';\n break;\n case 'foreignKey':\n type = 'string';\n break;\n default:\n type = 'any';\n }\n\n const optional = !fieldDef.required ? '?' : '';\n propertyLines.push(` ${fieldName}${optional}: ${type};`);\n }\n\n // Add common SmrtObject properties\n propertyLines.unshift(\n ' id?: string;',\n ' created_at?: string;',\n ' updated_at?: string;',\n );\n\n const interfaceDef = `export interface ${interfaceName}Data {\\n${propertyLines.join('\\n')}\\n}`;\n typeDefinitions.push(interfaceDef);\n }\n\n return typeDefinitions.join('\\n\\n');\n}\n\n/**\n * Generate virtual types module\n */\nasync function generateTypesModule(\n manifest: SmartObjectManifest,\n mode: 'server' | 'client' = 'server',\n): Promise<string> {\n let interfaces = '';\n\n try {\n // Only use scanner in server mode to avoid Node.js dependencies in browser builds\n if (mode !== 'client') {\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const generator = new ManifestGenerator();\n interfaces = generator.generateTypeDefinitions(manifest);\n } else {\n // In client mode, generate basic interfaces directly from manifest\n interfaces = generateClientModeTypes(manifest);\n }\n\n return `\n// Auto-generated TypeScript types from SMRT objects\n// This file is generated automatically - do not edit\n\n${interfaces}\n\nexport interface Request {\n params: Record<string, string>;\n query: Record<string, any>;\n json(): Promise<any>;\n}\n\nexport interface Response {\n json(data: any, init?: { status?: number }): Response;\n status(code: number): Response;\n}\n`;\n } catch (error) {\n console.warn('[smrt] Error generating types module:', error);\n return `\n// Auto-generated TypeScript types from SMRT objects (fallback)\n// This file is generated automatically - do not edit\n\nexport interface Request {\n params: Record<string, string>;\n query: Record<string, any>;\n json(): Promise<any>;\n}\n\nexport interface Response {\n json(data: any, init?: { status?: number }): Response;\n status(code: number): Response;\n}\n`;\n }\n}\n\n/**\n * Generate virtual manifest module\n */\nfunction generateManifestModule(manifest: SmartObjectManifest): string {\n return `\n// Auto-generated manifest from SMRT objects\n// This file is generated automatically - do not edit\n\nexport const manifest = ${JSON.stringify(manifest, null, 2)};\n\nexport { manifest as default };\n`;\n}\n\n/**\n * Generate TypeScript declaration file for virtual modules\n * This eliminates the need for manual type maintenance\n */\nexport async function generateTypeDeclarationFile(\n manifest: SmartObjectManifest,\n projectRoot: string,\n typeDeclarationsPath: string,\n): Promise<void> {\n try {\n // Conditionally import path and fs modules\n const [{ join }, { existsSync, mkdirSync, writeFileSync }] =\n await Promise.all([import('node:path'), import('node:fs')]);\n\n const declarationsDir = join(projectRoot, typeDeclarationsPath);\n const declarationsFile = join(declarationsDir, 'virtual-modules.d.ts');\n\n // Create directory if it doesn't exist\n if (!existsSync(declarationsDir)) {\n mkdirSync(declarationsDir, { recursive: true });\n }\n\n // Generate interface definitions for each discovered SMRT object. Sorted\n // for the same reason as generateClientModeTypes (#2749).\n const objectInterfaces = Object.entries(manifest.objects)\n .sort(\n ([leftKey, left], [rightKey, right]) =>\n compareText(\n left.qualifiedName || leftKey,\n right.qualifiedName || rightKey,\n ) || compareText(leftKey, rightKey),\n )\n .map(([_name, obj]) => {\n const interfaceName = `${obj.className}Data`;\n const fields = Object.entries(obj.fields)\n .map(([fieldName, field]) => {\n const optional = field.required === false ? '?' : '';\n const type = mapTypeScriptType(field.type);\n return ` ${fieldName}${optional}: ${type};`;\n })\n .join('\\n');\n\n // Timestamps are snake_case on the wire (#1797): the server returns\n // `created_at`/`updated_at` exactly as SmrtObject.toJSON() emits them,\n // matching the prebuild + client-mode type paths.\n return ` export interface ${interfaceName} {\n id?: string;\n${fields}\n created_at?: string;\n updated_at?: string;\n }`;\n })\n .join('\\n\\n');\n\n // Generate API client interface for each object\n // Always use plural collection names (standard REST convention).\n // Filter custom methods through resolveApiActionSet so the declared\n // type surface matches what generateClientModule actually emits at\n // runtime — otherwise consumers see methods in autocomplete that are\n // undefined at runtime.\n const apiClientInterface = selectApiClientEntries(manifest)\n .map(\n ({\n obj,\n clientKey,\n dataInterfaceName,\n crudMethods,\n customMethods: exposedMethods,\n }) => {\n const { methods = {} } = obj;\n const interfaceName = dataInterfaceName;\n const exposedActionNames = new Set(\n exposedMethods.map((method) => method.name),\n );\n const customMethods = Object.entries(methods).filter(\n ([name, method]) =>\n !GENERATED_CLIENT_CRUD_METHODS.has(name) &&\n method.isPublic &&\n exposedActionNames.has(name),\n );\n\n // Generate custom method signatures\n const customMethodSignatures = customMethods\n .map(([methodName]) => {\n const exposedMethod = exposedMethods.find(\n ({ name }) => name === methodName,\n );\n if (!exposedMethod) return '';\n const signature = renderApiClientCustomMethodParameters(\n exposedMethod,\n mapTypeScriptType,\n );\n return ` ${methodName}(${signature}): Promise<any>;`;\n })\n .join('\\n');\n\n const overriddenBaseMethods = customMethods\n .map(([methodName]) => methodName)\n .filter((methodName) =>\n GENERATED_CLIENT_BASE_METHODS.has(methodName),\n );\n const crudOperationsType = renderApiClientCrudType(\n interfaceName,\n crudMethods,\n overriddenBaseMethods,\n );\n\n if (customMethods.length > 0) {\n const intersection = crudOperationsType\n ? `${crudOperationsType} & `\n : '';\n return ` ${JSON.stringify(clientKey)}: ${intersection}{\\n${customMethodSignatures}\\n };`;\n }\n\n return ` ${JSON.stringify(clientKey)}: ${crudOperationsType ?? 'Record<string, never>'};`;\n },\n )\n .join('\\n');\n\n // Typed web collection definitions (#1761): one entry per REST collection,\n // with the row type threaded through the phantom `_row` carrier so\n // downstream factories (`@happyvertical/smrt-web`) can infer it. Selection\n // shares selectWebCollectionEntries with the runtime module so the declared\n // types and the emitted values cannot drift.\n const webCollectionInterface = selectWebCollectionEntries(manifest)\n .map(\n ({ collection, obj }) =>\n ` ${JSON.stringify(collection)}: SmrtWebCollectionDefinition<import('@happyvertical/smrt-virt-types').${obj.className}Data>;`,\n )\n .join('\\n');\n\n // Generate MCP tool interfaces based on discovered methods\n const _mcpTools = Object.entries(manifest.objects).flatMap(([_name, obj]) =>\n Object.entries(obj.methods).map(([methodName, method]) => ({\n name: `${methodName}_${obj.collection}`,\n description: `${method.name} operation on ${obj.collection}`,\n inputSchema: {\n type: 'object',\n properties: Object.fromEntries(\n method.parameters.map((param) => [\n param.name,\n { type: mapJsonSchemaType(param.type) },\n ]),\n ),\n required: method.parameters\n .filter((p) => p.optional !== true)\n .map((p) => p.name),\n },\n })),\n );\n\n const typeDeclarations = `/**\n * Auto-generated TypeScript declarations for SMRT virtual modules\n * Generated from discovered @smrt() decorated classes\n * \n * DO NOT EDIT THIS FILE MANUALLY\n * This file is automatically regenerated when SMRT objects change\n */\n\n// Manifest module - Contains discovered SMRT objects metadata\ndeclare module '@happyvertical/smrt-virt-manifest' {\n export interface SmrtObjectField {\n type: string;\n required?: boolean;\n default?: any;\n }\n\n export interface SmrtObjectMethod {\n name: string;\n parameters: Array<{\n name: string;\n type: string;\n required?: boolean;\n }>;\n returnType: string;\n isAsync: boolean;\n }\n\n export interface SmrtObjectDefinition {\n className: string;\n collection: string;\n fields: Record<string, SmrtObjectField>;\n methods: Record<string, SmrtObjectMethod>;\n decoratorConfig: any;\n }\n\n export interface SmrtManifest {\n version: string;\n timestamp: number;\n objects: Record<string, SmrtObjectDefinition>;\n }\n\n export const manifest: SmrtManifest;\n}\n\n// Routes module - Auto-generated REST route setup\ndeclare module '@happyvertical/smrt-virt-routes' {\n export interface RouteApp {\n get(path: string, handler: (req: any, res: any) => void): void;\n post(path: string, handler: (req: any, res: any) => void): void;\n put(path: string, handler: (req: any, res: any) => void): void;\n delete(path: string, handler: (req: any, res: any) => void): void;\n }\n\n export interface RouteOptions {\n basePath?: string;\n [key: string]: any;\n }\n\n export function setupRoutes(app: RouteApp, options?: RouteOptions): void;\n export default setupRoutes;\n}\n\n// Client module - Auto-generated API client\n// Wire-shape policy (#1797): the server returns BARE JSON — a bare array for\n// list/search, a bare object for get/create/update — with snake_case field\n// names (created_at, updated_at). These declarations match that shape (no\n// envelope, no camelCase). Fetchers reject on non-2xx with a SmrtClientError\n// (#1796). Shared CRUD wire types stay aligned with the prebuild declaration\n// path; Vite-only custom action declarations are layered onto them below.\ndeclare module '@happyvertical/smrt-virt-client' {\n /** Structured custom-action failure nested under an API error body's \\`error\\` key. */\n export interface SmrtClientFailure {\n ok: false;\n code: string;\n message: string;\n status?: number;\n }\n\n /** Shape of a JSON error body carried by a rejected request (SmrtClientError.body). */\n export interface ApiError {\n error?: string | SmrtClientFailure;\n message?: string;\n }\n\n /** Typed error thrown by every fetcher on a non-2xx response (#1796). */\n export interface SmrtClientError extends Error {\n name: 'SmrtClientError';\n status: number;\n /** Machine-readable code from a structured custom-action failure, when present. */\n code?: string;\n body?: ApiError | string;\n }\n\n export interface CrudOperations<T = any> {\n list(params?: Record<string, any>): Promise<T[]>;\n get(id: string): Promise<T>;\n create(data: Partial<T>): Promise<T>;\n update(id: string, data: Partial<T>): Promise<T>;\n delete(id: string): Promise<boolean>;\n search(query: string): Promise<T[]>;\n }\n\n export interface ApiClient {\n${apiClientInterface}\n }\n\n export function createClient(basePath?: string): ApiClient;\n export default createClient;\n}\n\n// MCP module - Auto-generated Model Context Protocol tools\ndeclare module '@happyvertical/smrt-virt-mcp' {\n import type { SmrtMCPServer, MCPServerOptions } from '@happyvertical/smrt-core/runtime';\n\n export interface McpTool {\n name: string;\n description: string;\n inputSchema: {\n type: string;\n properties: Record<string, any>;\n required?: string[];\n };\n }\n\n export const tools: McpTool[];\n export function createMCPServer(options?: MCPServerOptions): SmrtMCPServer;\n export default createMCPServer;\n}\n\n// Types module - Auto-generated TypeScript interfaces\ndeclare module '@happyvertical/smrt-virt-types' {\n export const types: string;\n\n // Auto-generated interfaces for discovered SMRT objects\n${objectInterfaces}\n\n export default types;\n}\n\n// Web module - Typed collection definitions for the browser client data\n// runtime (@happyvertical/smrt-web, #1761)\ndeclare module '@happyvertical/smrt-virt-web' {\n export type SmrtWebFieldType =\n | 'text'\n | 'decimal'\n | 'boolean'\n | 'integer'\n | 'datetime'\n | 'json'\n | 'foreignKey'\n | 'crossPackageRef';\n\n /** Static \\`@field({ ui })\\` hints (#2046) — the field-policy rail seed. */\n export interface SmrtWebFieldUIHints {\n basic?: boolean;\n group?: string;\n order?: number;\n locked?: boolean;\n }\n\n export interface SmrtWebFieldDefinition {\n type: SmrtWebFieldType;\n required?: boolean;\n nullable?: boolean;\n default?: unknown;\n /** Developer-authored \\`@field({ description })\\` (#2046) — end-user help seed. */\n description?: string;\n /** Static \\`@field({ ui })\\` hints (#2046). */\n ui?: SmrtWebFieldUIHints;\n }\n\n export type SmrtWebRelationshipKind =\n | 'foreignKey'\n | 'crossPackageRef'\n | 'oneToMany'\n | 'manyToMany';\n\n /**\n * A manifest-derived edge to a sibling REST collection. Mutating this\n * collection invalidates the caches of the collections named by these edges\n * (#1761 relationship-derived invalidation).\n */\n export interface SmrtWebRelationship {\n field: string;\n kind: SmrtWebRelationshipKind;\n relatedCollection: string;\n }\n\n export interface WebToolRouteDescriptor {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n scope: 'item' | 'collection';\n path: string[];\n parameterAliases?: Record<string, string>;\n optionsBag?: boolean;\n }\n\n /** A WebMCP/MCP tool descriptor for one collection action (#1812). */\n export interface WebToolDescriptor {\n action: string;\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n readOnly: boolean;\n effect: 'read' | 'write' | 'destructive';\n idempotent: boolean;\n openWorld: boolean;\n route?: WebToolRouteDescriptor;\n }\n\n /** Canonical data-only definition for one generated browser tool. */\n export interface WebMcpToolDefinition extends WebToolDescriptor {\n collection: string;\n objectRef: string;\n className: string;\n endpoint: string;\n idField: string;\n idType: 'uuid' | 'text';\n route: WebToolRouteDescriptor;\n relationships: SmrtWebRelationship[];\n }\n\n export interface SmrtWebCollectionDefinition<TData = Record<string, unknown>> {\n name: string;\n /** Canonical qualified model identity (\\`@package/name:ClassName\\`) for policy APIs. */\n objectRef: string;\n className: string;\n endpoint: string;\n idField: string;\n actions: string[];\n fields: Record<string, SmrtWebFieldDefinition>;\n /** Manifest-derived relationship edges to sibling REST collections. */\n relationships: SmrtWebRelationship[];\n /** WebMCP/MCP tool descriptors for the exposed actions (#1812). */\n toolDescriptors: WebToolDescriptor[];\n /** Phantom row-type carrier for inference — never present at runtime. */\n _row?: TData;\n }\n\n export interface SmrtWebCollectionDefinitions {\n${webCollectionInterface}\n }\n\n export const collectionDefinitions: SmrtWebCollectionDefinitions;\n /** Every API-backed WebMCP tool, independent of list materialization. */\n export const webMcpToolDefinitions: readonly WebMcpToolDefinition[];\n export function getCollectionDefinition<\n K extends keyof SmrtWebCollectionDefinitions,\n >(name: K): SmrtWebCollectionDefinitions[K];\n /**\n * Build-time web-collection shape digest (#1764). A deterministic,\n * replica-stable hash of the emitted collection definitions; a change means\n * old persisted client rows may mis-hydrate. Consumers fold it into the\n * durable persistence namespace and the version-awareness updateAvailable\n * contract signal. One of the co-managed emission sites that must not drift —\n * the runtime value, this ambient d.ts, the physical @smrt/web d.ts, and the\n * hand-written @happyvertical/smrt-web type mirror.\n */\n export const manifestHash: string;\n export default collectionDefinitions;\n}\n`;\n\n // Write the declarations file\n writeFileSync(declarationsFile, typeDeclarations);\n console.log(\n `[smrt] Generated TypeScript declarations: ${declarationsFile}`,\n );\n } catch (error) {\n console.error('[smrt] Error generating TypeScript declarations:', error);\n }\n}\n\n/**\n * Map SMRT field types to TypeScript types\n */\nfunction mapTypeScriptType(smrtType: string): string {\n const typeMap: Record<string, string> = {\n text: 'string',\n integer: 'number',\n decimal: 'number',\n datetime: 'string',\n json: 'any',\n foreignKey: 'string',\n crossPackageRef: 'string',\n oneToMany: 'any[]',\n manyToMany: 'any[]',\n meta: 'any',\n string: 'string',\n number: 'number',\n boolean: 'boolean',\n array: 'any[]',\n object: 'Record<string, any>',\n date: 'string',\n Date: 'string',\n };\n return typeMap[smrtType] || 'any';\n}\n\n/**\n * Map TypeScript types to JSON Schema types for MCP tools\n */\nfunction mapJsonSchemaType(tsType: string): string {\n const typeMap: Record<string, string> = {\n string: 'string',\n number: 'number',\n boolean: 'boolean',\n array: 'array',\n object: 'object',\n any: 'string',\n };\n return typeMap[tsType] || 'string';\n}\n\n/**\n * Get default HTML template with inlined JavaScript (inlined for distribution)\n */\nfunction getDefaultHTML(): string {\n const uiScript = getDefaultUIModule();\n\n // Build HTML without template literals to avoid escaping issues\n return (\n '<!DOCTYPE html>\\n' +\n '<html lang=\"en\">\\n' +\n '<head>\\n' +\n ' <meta charset=\"UTF-8\">\\n' +\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\\n' +\n ' <title>SMRT Development UI</title>\\n' +\n ' <style>\\n' +\n ' * { margin: 0; padding: 0; box-sizing: border-box; }\\n' +\n ' body {\\n' +\n ' font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\\n' +\n ' background: #f5f5f5;\\n' +\n ' color: #333;\\n' +\n ' }\\n' +\n ' .container { max-width: 1200px; margin: 0 auto; padding: 20px; }\\n' +\n ' header {\\n' +\n ' background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\\n' +\n ' color: white;\\n' +\n ' padding: 40px 0;\\n' +\n ' margin-bottom: 40px;\\n' +\n ' box-shadow: 0 4px 6px rgba(0,0,0,0.1);\\n' +\n ' }\\n' +\n ' header h1 { font-size: 2.5em; font-weight: 700; margin-bottom: 10px; }\\n' +\n ' .subtitle { font-size: 1.1em; opacity: 0.9; }\\n' +\n ' .stats {\\n' +\n ' display: grid;\\n' +\n ' grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\\n' +\n ' gap: 20px;\\n' +\n ' margin-bottom: 40px;\\n' +\n ' }\\n' +\n ' .stat-card {\\n' +\n ' background: white;\\n' +\n ' padding: 20px;\\n' +\n ' border-radius: 8px;\\n' +\n ' box-shadow: 0 2px 4px rgba(0,0,0,0.1);\\n' +\n ' text-align: center;\\n' +\n ' }\\n' +\n ' .stat-value { font-size: 2.5em; font-weight: 700; color: #667eea; margin-bottom: 5px; }\\n' +\n ' .stat-label { font-size: 0.9em; color: #666; text-transform: uppercase; letter-spacing: 1px; }\\n' +\n ' .collections { display: grid; gap: 30px; }\\n' +\n ' .collection-card {\\n' +\n ' background: white;\\n' +\n ' border-radius: 8px;\\n' +\n ' box-shadow: 0 2px 4px rgba(0,0,0,0.1);\\n' +\n ' overflow: hidden;\\n' +\n ' }\\n' +\n ' .collection-header {\\n' +\n ' background: #667eea;\\n' +\n ' color: white;\\n' +\n ' padding: 15px 20px;\\n' +\n ' display: flex;\\n' +\n ' justify-content: space-between;\\n' +\n ' align-items: center;\\n' +\n ' }\\n' +\n ' .collection-title { font-size: 1.3em; font-weight: 600; }\\n' +\n ' .collection-count {\\n' +\n ' background: rgba(255,255,255,0.2);\\n' +\n ' padding: 5px 15px;\\n' +\n ' border-radius: 20px;\\n' +\n ' font-size: 0.9em;\\n' +\n ' }\\n' +\n ' .collection-body { padding: 20px; }\\n' +\n ' .field-list {\\n' +\n ' display: grid;\\n' +\n ' grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\\n' +\n ' gap: 15px;\\n' +\n ' margin-bottom: 20px;\\n' +\n ' }\\n' +\n ' .field {\\n' +\n ' padding: 10px;\\n' +\n ' background: #f8f9fa;\\n' +\n ' border-radius: 4px;\\n' +\n ' border-left: 3px solid #667eea;\\n' +\n ' }\\n' +\n ' .field-name { font-weight: 600; color: #333; margin-bottom: 3px; }\\n' +\n ' .field-type { font-size: 0.85em; color: #666; }\\n' +\n ' .actions { display: flex; gap: 10px; flex-wrap: wrap; }\\n' +\n ' .btn {\\n' +\n ' padding: 10px 20px;\\n' +\n ' border: none;\\n' +\n ' border-radius: 4px;\\n' +\n ' font-size: 0.9em;\\n' +\n ' cursor: pointer;\\n' +\n ' transition: all 0.2s;\\n' +\n ' text-decoration: none;\\n' +\n ' display: inline-block;\\n' +\n ' }\\n' +\n ' .btn-primary { background: #667eea; color: white; }\\n' +\n ' .btn-primary:hover { background: #5568d3; transform: translateY(-1px); }\\n' +\n ' .btn-secondary { background: #e0e0e0; color: #333; }\\n' +\n ' .btn-secondary:hover { background: #d0d0d0; }\\n' +\n ' .loading { text-align: center; padding: 40px; color: #666; }\\n' +\n ' .error {\\n' +\n ' background: #fee;\\n' +\n ' border: 1px solid #fcc;\\n' +\n ' color: #c33;\\n' +\n ' padding: 15px;\\n' +\n ' border-radius: 4px;\\n' +\n ' margin-bottom: 20px;\\n' +\n ' }\\n' +\n ' .empty-state { text-align: center; padding: 60px 20px; color: #999; }\\n' +\n ' .empty-state svg { width: 100px; height: 100px; margin-bottom: 20px; opacity: 0.3; }\\n' +\n ' </style>\\n' +\n '</head>\\n' +\n '<body>\\n' +\n ' <div id=\"app\">\\n' +\n ' <div class=\"loading\">Loading SMRT UI...</div>\\n' +\n ' </div>\\n' +\n ' <script type=\"module\">\\n' +\n uiScript +\n '\\n </script>\\n' +\n '</body>\\n' +\n '</html>'\n );\n}\n\n/**\n * Get default UI module from template file\n * Loads the JavaScript template\n */\nfunction getDefaultUIModule(): string {\n try {\n // Get current file directory\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n // Load template file (works in both src and dist)\n const templatePath = join(__dirname, 'templates/default-ui.js');\n\n return readFileSync(templatePath, 'utf-8').trim();\n } catch (error) {\n console.error('[smrt] Error loading UI template:', error);\n // Fallback to minimal UI\n return `\nasync function createUI() {\n const app = document.getElementById('app');\n if (!app) return;\n app.innerHTML = '<div class=\"container\" style=\"padding:40px;text-align:center;\"><h1>🎯 SMRT Development UI</h1><p>Template file not found. UI code could not be loaded.</p></div>';\n}\ncreateUI();\n`;\n }\n}\n\n/**\n * Load default HTML template for projects without index.html\n */\nasync function loadDefaultHTML(): Promise<string> {\n return getDefaultHTML();\n}\n\n/**\n * Load default UI module\n */\nasync function loadDefaultUI(): Promise<string> {\n return getDefaultUIModule();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/vite-plugin/index.ts"],"sourcesContent":["/**\n * Vite plugin for automatic SMRT service generation\n * Provides virtual modules for REST, MCP, and other services\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type {\n DomainKnowledgeAgentSurface,\n DomainKnowledgeConfig,\n DomainKnowledgeManifest,\n} from '@happyvertical/smrt-types';\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';\nimport {\n loadVerifiedSmrtGenerationSnapshot,\n type SmrtGenerationSnapshotOptions,\n} from '../generation-snapshot.js';\nimport { CRUD_OPERATIONS } from '../generators/custom-action.js';\nimport { buildDomainKnowledgeManifest } from '../knowledge.js';\nimport {\n mergeKnowledgeConfig,\n resolveFileKnowledgeConfig,\n} from '../knowledge-config.js';\nimport { discoverSmrtPackages } from '../manifest/discover-smrt-packages.js';\nimport {\n DETERMINISTIC_GENERATED_AT,\n type SmartObjectManifest,\n} from '../scanner/types.js';\nimport { importWorkspaceModule } from '../utils/import-workspace-module.js';\nimport type {\n ScannerAgentSurface,\n ScannerModule,\n} from '../utils/scanner-module.js';\nimport {\n renderApiClientCrudType,\n renderApiClientCustomMethodParameters,\n selectApiClientEntries,\n} from './api-client-entries.js';\nimport {\n GENERATED_CLIENT_BASE_METHODS,\n GENERATED_CLIENT_CRUD_METHODS,\n generateClientModule,\n} from './generated-client.js';\nimport { importBuildAwareModule } from './import-build-aware.js';\nimport {\n findCliApiCoherenceViolations,\n generateSvelteKitRoutes,\n validateCliIncludeAgainstApi,\n} from './sveltekit-generator.js';\nimport {\n assertSvelteKitRouteCoordinationComplete,\n contributeSvelteKitRoutes,\n expectedSvelteKitRouteOwners,\n markSvelteKitRouteParticipant,\n} from './sveltekit-route-coordinator.js';\nimport {\n buildWebMcpToolDefinitions,\n compareText,\n generateWebModule,\n selectWebCollectionEntries,\n} from './web-collections.js';\n\nexport {\n loadVerifiedSmrtGenerationSnapshot,\n type SerializeSmrtGenerationSnapshotOptions,\n type SmrtGenerationSnapshotArtifact,\n type SmrtGenerationSnapshotOptions,\n type SmrtGenerationSnapshotView,\n serializeSmrtGenerationSnapshot,\n sha256SmrtGenerationSnapshot,\n} from '../generation-snapshot.js';\nexport type {\n CliApiCoherenceViolation,\n SvelteKitOptions,\n} from './sveltekit-generator.js';\n// Re-export SvelteKit route generator for CLI usage\nexport {\n findCliApiCoherenceViolations,\n generateSvelteKitRoutes,\n methodNameToKebab,\n resolveApiActionRouteConfig,\n resolveApiActionSet,\n validateCliIncludeAgainstApi,\n} from './sveltekit-generator.js';\nexport { buildWebMcpToolDefinitions } from './web-collections.js';\n\n/**\n * Minimal structural shape of a parsed `package.json`. Only the fields the\n * plugin reads are typed; the index signature keeps the rest accessible (e.g.\n * `exports`, consumed downstream by agent-manifest generation).\n */\ninterface PackageJsonShape {\n name?: string;\n version?: string;\n [key: string]: unknown;\n}\n\nexport interface SmrtPluginOptions {\n /** Root directory that owns generated manifests and SvelteKit routes. */\n projectRoot?: string;\n /**\n * Reuse an immutable, verified manifest instead of scanning sources or\n * writing manifest files. Generated routes, virtual modules, and type\n * declarations still consume the verified manifest.\n */\n generationSnapshot?: SmrtGenerationSnapshotOptions;\n /** Glob patterns for SMRT source files */\n include?: string[];\n /** Patterns to exclude */\n exclude?: string[];\n /**\n * Follow symbolic links while discovering sources. Defaults to `false`: a\n * pnpm `node_modules` is a symlink graph with cycles, so a link-following\n * walk does not terminate on a real install (#2275). Enable it only for a\n * project that genuinely keeps sources behind a link.\n */\n followSymbolicLinks?: boolean;\n /** Output directory for generated files */\n outDir?: string;\n /** Enable hot module replacement */\n hmr?: boolean;\n /** Watch for file changes */\n watch?: boolean;\n /** Generate types */\n generateTypes?: boolean;\n /** Custom base classes to scan for */\n baseClasses?: string[];\n /** Follow import chains to detect inheritance (e.g., Event extends SmrtObject) */\n followImports?: boolean;\n /** Directory to write TypeScript declarations (relative to project root) */\n typeDeclarationsPath?: string;\n /** Plugin execution mode - controls Node.js vs browser compatibility */\n mode?: 'server' | 'client' | 'auto';\n /**\n * @deprecated OXC scanner is now the only scanner. This option is ignored.\n */\n experimentalFastScanner?: boolean;\n /** SvelteKit route auto-generation options */\n svelteKit?: {\n /** Enable SvelteKit route generation (default: false) */\n enabled: boolean;\n /** Output directory for generated routes (default: 'src/routes/api') */\n routesDir?: string;\n /** Directory containing SMRT objects (default: 'src/lib/objects') */\n objectsDir?: string;\n /** Directory for configuration file (default: 'src/lib/server') */\n configPath?: string;\n /** Configuration file name (default: 'smrt.ts') */\n configFileName?: string;\n /**\n * Apply kebab-case to custom-method URL segments (e.g. `discoverFromUrl`\n * becomes `/discover-from-url`). Opt-in for one minor; default flips in\n * the next major. An explicit `api.routes[name].path` always wins.\n */\n kebabRoutes?: boolean;\n /**\n * Change-feed `_changes` route generation (#1758). Enabled by default\n * (the route is auth-guarded fail-closed); `{ enabled: false }` skips it.\n */\n changesRoute?: { enabled?: boolean };\n /**\n * Live `_events` SSE route generation (#1763). Enabled by default (the\n * route is auth-guarded fail-closed, same-origin only); `{ enabled: false }`\n * skips it. `maxSubscribers` caps active streams per process (#1860).\n */\n eventsRoute?: { enabled?: boolean; maxSubscribers?: number };\n /**\n * CLI discovery `_resources` route generation (#2663). Enabled by\n * default, but only ever emitted when `@happyvertical/smrt-users` is\n * resolvable from the consumer; `{ enabled: false }` opts out even when\n * it is present. A pre-existing hand-written `_resources` route is\n * always preserved.\n */\n resourcesRoute?: { enabled?: boolean };\n };\n /** Domain-scoped agent/developer knowledge artifact generation. */\n knowledge?: DomainKnowledgeConfig | false;\n /**\n * Validate that every method in `cli.include` is exposed via the API\n * (so HTTP-based CLI consumers can actually reach them). Default: true.\n * Per-class opt-out via `cli: { skipApiCheck: true }` (whole class) or\n * `cli: { skipApiCheck: ['methodName'] }` (only the named methods,\n * smrt#2857).\n */\n validateCliApiCoherence?: boolean;\n}\n\n/**\n * Producer configuration exposed to companion Vite plugins.\n *\n * The consumer uses this rather than reconstructing knowledge precedence from\n * the filesystem, so inline `smrtPlugin({ knowledge })` options remain in\n * force while it refreshes the aggregate artifact.\n */\nexport interface SmrtPluginApi {\n options: {\n projectRoot?: string;\n generationSnapshot?: SmrtGenerationSnapshotOptions;\n baseClasses: string[];\n followImports: boolean;\n include: string[];\n exclude: string[];\n };\n resolveKnowledgeConfig(\n manifest: SmartObjectManifest,\n ): Promise<DomainKnowledgeConfig>;\n /**\n * Return declarations produced by this plugin's current build. This waits\n * until that build has published its local manifest, so companion plugins\n * never merge an older manifest with declarations from a newer scan.\n */\n resolveKnowledgeAgentSurface(): Promise<\n DomainKnowledgeAgentSurface | undefined\n >;\n}\n\nconst VIRTUAL_MODULES = {\n '@happyvertical/smrt-virt-routes': 'smrt:routes',\n '@happyvertical/smrt-virt-client': 'smrt:client',\n '@happyvertical/smrt-virt-mcp': 'smrt:mcp',\n '@happyvertical/smrt-virt-types': 'smrt:types',\n '@happyvertical/smrt-virt-manifest': 'smrt:manifest',\n '@happyvertical/smrt-virt-ui': 'smrt:ui',\n '@happyvertical/smrt-virt-web': 'smrt:web',\n};\n\n/**\n * Project a scanner agent surface into the knowledge-artifact shape (#2591).\n *\n * The two shapes are deliberately separate: the scanner cannot depend on\n * `@happyvertical/smrt-types` (core depends on the scanner, and importing back\n * would close the cycle), so it mirrors the vocabulary structurally and this\n * function is the one place the mirror is reconciled. `filePath` becomes\n * `sourceFile` here because the artifact records a package-relative path, not a\n * scan path.\n */\nexport function toKnowledgeAgentSurface(\n surface: ScannerAgentSurface | undefined,\n): DomainKnowledgeAgentSurface | undefined {\n if (!surface) return undefined;\n return {\n intents: surface.intents.map(({ kind: _kind, filePath, ...rest }) => ({\n ...rest,\n sourceFile: filePath,\n })),\n playbooks: surface.playbooks.map(({ kind: _kind, filePath, ...rest }) => ({\n ...rest,\n sourceFile: filePath,\n })),\n diagnostics: surface.diagnostics.map(({ filePath, ...rest }) => ({\n ...rest,\n sourceFile: filePath,\n })),\n };\n}\n\n/**\n * Print every declaration the matcher recognized but could not emit.\n *\n * A warning rather than a build failure: a computed tool set is a legitimate\n * choice, and `useWebMcpTool` is its supported path. What is NOT acceptable is\n * the declaration disappearing without a word, so the surface records it and\n * the build says so.\n */\nfunction reportAgentSurfaceDiagnostics(\n surface: DomainKnowledgeAgentSurface | undefined,\n): void {\n if (!surface || surface.diagnostics.length === 0) return;\n console.warn(\n `[smrt] ⚠️ ${surface.diagnostics.length} declaration(s) are not statically emittable and were excluded from the agent surface:`,\n );\n for (const diagnostic of surface.diagnostics) {\n const where = diagnostic.line\n ? `${diagnostic.sourceFile}:${diagnostic.line}`\n : diagnostic.sourceFile;\n console.warn(` ${where} — ${diagnostic.message}`);\n }\n}\n\n/**\n * Compare the emitted intents against the tool names this build will really\n * register, and project the result into the knowledge-artifact shape (#2725).\n *\n * The rule lives in the scanner, which owns the tool-name derivation. The INPUT\n * lives here, because only core resolves the exposure policy:\n * {@link buildWebMcpToolDefinitions} is the function that emits the runtime\n * `webMcpToolDefinitions`, so its output is the set that actually registers.\n * Handing the scanner every verb a class COULD expose would report collisions\n * with tools nobody mounts.\n *\n * The check is passed in rather than imported: core reaches the scanner through\n * {@link importScanner}, which resolves src or dist depending on how core itself\n * was built, and a static import here would defeat that.\n *\n * `declaredBy` is `Class.action` — the same identity `smrt doctor` prints beside\n * a generated model tool — so a reader can find the other side of the collision\n * without cross-referencing anything.\n */\nexport function collectAgentSurfaceToolNameCollisions(input: {\n surface: ScannerAgentSurface;\n manifest: SmartObjectManifest;\n checkAgentSurfaceToolNames: ScannerModule['checkAgentSurfaceToolNames'];\n kebabRoutes?: boolean;\n /**\n * Prefixes the fixed UI tools mount under. Nothing in a build knows this —\n * `ui.prefix` is a runtime `<Provider webmcp={{ ui: { prefix } }}>` prop, and\n * the scanner's default of `smrt_ui_` is correct for every app that leaves it\n * alone. Threaded anyway so the seam is complete: the day a build-time source\n * exists, only this call site changes.\n */\n uiToolPrefixes?: readonly string[];\n}): DomainKnowledgeAgentSurface['diagnostics'] {\n return input\n .checkAgentSurfaceToolNames(input.surface, {\n generatedToolNames: buildWebMcpToolDefinitions(input.manifest, {\n kebabRoutes: input.kebabRoutes ?? false,\n }).map((definition) => ({\n name: definition.name,\n declaredBy: `${definition.className}.${definition.action}`,\n })),\n ...(input.uiToolPrefixes ? { uiToolPrefixes: input.uiToolPrefixes } : {}),\n })\n .map(({ filePath, ...rest }) => ({ ...rest, sourceFile: filePath }));\n}\n\n/**\n * Print every emitted intent whose WebMCP tool name something else also claims\n * (#2725).\n *\n * \"Also claims\", not \"is already taken\", for the same reason `smrt doctor`'s\n * header says so: a build cannot see the provider's WebMCP `namespace` or\n * `effects` policy, either of which separates the pair outright. This line runs\n * on every build and every watch rebuild, so it is the surface an author sees\n * most; each message beneath states the condition, and the header must not\n * assert past it.\n *\n * Separate from {@link reportAgentSurfaceDiagnostics} because it says\n * something different: those declarations were EXCLUDED, these are emitted and\n * merely at risk. Folding them into that header would tell an author their\n * intent had been dropped when it had not.\n */\nfunction reportAgentSurfaceToolNameCollisions(\n diagnostics: readonly DomainKnowledgeAgentSurface['diagnostics'][number][],\n): void {\n if (diagnostics.length === 0) return;\n console.warn(\n `[smrt] ⚠️ ${diagnostics.length} declared intent(s) derive a WebMCP tool name something else also claims:`,\n );\n for (const diagnostic of diagnostics) {\n const where = diagnostic.line\n ? `${diagnostic.sourceFile}:${diagnostic.line}`\n : diagnostic.sourceFile;\n console.warn(` ${where} — ${diagnostic.message}`);\n }\n}\n\n/**\n * Order the emitted diagnostics the way the scanner's own merge does, so\n * appending the manifest-derived collisions cannot make the artifact depend on\n * when they were computed.\n */\nfunction sortKnowledgeAgentSurfaceDiagnostics(\n diagnostics: DomainKnowledgeAgentSurface['diagnostics'],\n): DomainKnowledgeAgentSurface['diagnostics'] {\n const compare = (a: string, b: string): number =>\n a < b ? -1 : a > b ? 1 : 0;\n return [...diagnostics].sort(\n (a, b) =>\n compare(a.sourceFile, b.sourceFile) ||\n (a.line ?? 0) - (b.line ?? 0) ||\n (a.column ?? 0) - (b.column ?? 0) ||\n compare(a.code, b.code) ||\n compare(a.message, b.message),\n );\n}\n\nasync function importScanner() {\n return importWorkspaceModule<ScannerModule>({\n packageName: '@happyvertical/smrt-scanner',\n distEntry: 'packages/scanner/dist/index.js',\n sourceEntry: 'packages/scanner/src/index.ts',\n purpose: 'Vite manifest scanning',\n });\n}\n\n/**\n * Matches a package's `__smrt-register__` self-registration shim by module id\n * (query strings stripped). node_modules is excluded: only the package's OWN\n * shim is rewritten during its library build, never a dependency's compiled\n * output.\n */\nconst REGISTER_SHIM_RE = /[\\\\/]__smrt-register__\\.(?:ts|mts|js|mjs)$/;\n\nexport function isRegisterShimModuleId(id: string): boolean {\n const cleanId = id.split('?')[0];\n return REGISTER_SHIM_RE.test(cleanId) && !cleanId.includes('node_modules');\n}\n\n/**\n * Generate the replacement `__smrt-register__` module with the build-time\n * manifest inlined as data (issues #1506/#1507).\n *\n * The source shim resolves `new URL('./manifest.json', import.meta.url)` at\n * runtime, which assumes the compiled module ends up next to\n * `dist/manifest.json`. That held for the package's own dist (with the #1331\n * upward-search recovery), but breaks once a CONSUMER bundles the package\n * into its own output — e.g. a SvelteKit server build relocates the module\n * into `build/server/chunks/`, the URL resolves to a manifest that does not\n * exist, registration silently no-ops, and every plain (undecorated) field is\n * dropped from INSERTs and rejected by WHERE validation. Inlining the\n * manifest at library-build time removes the runtime filesystem lookup\n * entirely, so no downstream bundler layout can break registration.\n *\n * `JSON.parse('<literal>')` is used instead of an object literal: it parses\n * faster for large payloads and sidesteps identifier/keyword edge cases.\n */\nexport function generateInlineRegisterModule(\n manifest: SmartObjectManifest,\n): string {\n const manifestLiteral = JSON.stringify(JSON.stringify(manifest));\n return [\n '// Generated by @happyvertical/smrt-core smrtPlugin at library build time.',\n '// The package manifest is inlined so self-registration cannot miss when a',\n '// downstream bundler relocates this module away from dist/manifest.json',\n '// (https://github.com/happyvertical/smrt/issues/1506,',\n '// https://github.com/happyvertical/smrt/issues/1507).',\n \"import { ObjectRegistry } from '@happyvertical/smrt-core';\",\n '',\n `ObjectRegistry.registerPackageManifest(JSON.parse(${manifestLiteral}));`,\n '',\n ].join('\\n');\n}\n\n/**\n * Decide whether a `.smrt/manifest.json` entry belongs to this project's own\n * scan rather than to a consumed package aggregated into the same file by\n * `smrtConsumer()`.\n *\n * Ownership is read from the entry's recorded `packageName`: the scanner\n * stamps every locally scanned object with the project's own package name\n * (issue #713), and the consumer plugin stamps every aggregated entry with\n * its source package. An entry with no recorded owner can only have come from\n * the local write, because the consumer always records one.\n *\n * `localPackageNames` carries every name this project has written under, not\n * just its current one. Renaming the project's `package.json#name` would\n * otherwise orphan the entries stamped with the old name: they stop matching\n * the current name, get classified as another package's, and survive every\n * later write — so a local object deleted or renamed in the same change stays\n * in the manifest schema commands read. The previous write's own top-level\n * `packageName` supplies that prior name (`saveAggregatedManifest()` keeps it\n * as the local project's), and it is the only other name a local entry can\n * carry.\n */\nfunction isLocallyOwnedManifestEntry(\n entry: unknown,\n localPackageNames: ReadonlySet<string>,\n): boolean {\n const owner = (entry as { packageName?: unknown } | null | undefined)\n ?.packageName;\n if (typeof owner !== 'string' || owner.length === 0) {\n return true;\n }\n return localPackageNames.has(owner);\n}\n\n/** Read a manifest's `smrtDependencies`, tolerating an untrusted on-disk shape. */\nfunction readManifestDependencies(\n manifest: Partial<SmartObjectManifest> | undefined,\n): string[] {\n if (!Array.isArray(manifest?.smrtDependencies)) {\n return [];\n }\n return manifest.smrtDependencies.filter(\n (dependency): dependency is string =>\n typeof dependency === 'string' && dependency.length > 0,\n );\n}\n\n/**\n * Union a freshly scanned local manifest with the consumed-package state\n * already present in `.smrt/manifest.json` (issue #2925).\n *\n * The local scan is authoritative for the objects it owns — a deleted local\n * object must disappear from the file — so only entries owned by another\n * package are carried forward, and a local entry wins any key collision. As\n * with the consumer plugin's merge, `.smrt/` is a build cache: dropping a\n * package from `smrtConsumer()` leaves its stale entries until the directory\n * is removed and the project rebuilt.\n *\n * `smrtDependencies` is merged the same way and for the same reason. The\n * consumer writer owns that list too — `aggregateTypeManifests()` seeds it\n * from `smrtConsumer()`'s explicit `packages` — while the local scan derives\n * its own from the dependency tree, and the two need not agree: a configured\n * package the local discovery does not return would keep its objects here but\n * lose its declaration. The CLI's schema gate reads exactly that list to\n * admit a zero-local-object project, so dropping it reintroduces the\n * `missing_local_manifest` failure this change fixes.\n */\nfunction mergeExternalManifestEntries(\n manifest: SmartObjectManifest,\n manifestPath: string,\n): SmartObjectManifest {\n if (!existsSync(manifestPath)) {\n return manifest;\n }\n\n let existing: Partial<SmartObjectManifest> | undefined;\n try {\n existing = JSON.parse(\n readFileSync(manifestPath, 'utf-8'),\n ) as Partial<SmartObjectManifest>;\n } catch {\n // Unreadable/corrupt existing file — fall back to a plain write.\n return manifest;\n }\n\n if (!existing?.objects || typeof existing.objects !== 'object') {\n return manifest;\n }\n\n const localPackageNames = new Set<string>();\n if (manifest.packageName) {\n localPackageNames.add(manifest.packageName);\n }\n if (typeof existing.packageName === 'string' && existing.packageName) {\n localPackageNames.add(existing.packageName);\n }\n\n const preserved: SmartObjectManifest['objects'] = {};\n for (const [name, entry] of Object.entries(existing.objects)) {\n if (!isLocallyOwnedManifestEntry(entry, localPackageNames)) {\n preserved[name] = entry;\n }\n }\n\n const scannedDependencies = new Set(readManifestDependencies(manifest));\n const mergedDependencies = new Set([\n ...scannedDependencies,\n ...readManifestDependencies(existing),\n ]);\n // The union can only grow, so equal sizes mean the scan already covers it.\n const carriesExtraDependency =\n mergedDependencies.size > scannedDependencies.size;\n\n if (Object.keys(preserved).length === 0 && !carriesExtraDependency) {\n return manifest;\n }\n\n return {\n ...manifest,\n objects: { ...preserved, ...manifest.objects },\n ...(mergedDependencies.size > 0\n ? { smrtDependencies: [...mergedDependencies].sort() }\n : {}),\n };\n}\n\nexport function smrtPlugin(options: SmrtPluginOptions = {}): Plugin {\n const {\n projectRoot: configuredProjectRoot,\n generationSnapshot,\n include = ['src/**/*.ts', 'src/**/*.js'],\n exclude = ['**/*.test.ts', '**/*.spec.ts', '**/node_modules/**'],\n followSymbolicLinks = false,\n hmr = true,\n watch = true,\n generateTypes = true,\n baseClasses = ['SmrtObject', 'SmartObject'],\n followImports = true, // Default true: needed for multi-package inheritance\n typeDeclarationsPath = 'src/types',\n mode = 'auto',\n svelteKit = {\n enabled: false,\n routesDir: 'src/routes/api',\n objectsDir: 'src/lib/objects',\n configPath: 'src/lib/server',\n configFileName: 'smrt.ts',\n },\n knowledge,\n validateCliApiCoherence = true,\n } = options;\n\n /**\n * Dev-watcher variant of the cli↔api coherence lint: warn instead of throw,\n * so an in-flight decorator edit doesn't kill the dev server. Uses the same\n * remediation text as the strict build-time gate (`validateCliIncludeAgainstApi`)\n * so the dev-server message is as actionable as the build failure.\n *\n * `findCliApiCoherenceViolations` (#2638) now reports a violation for any\n * `cli` config shape, including a bare `cli: true`/`cli: {}` default, but\n * `validateCliIncludeAgainstApi` only THROWS for a class with a non-empty,\n * explicit `cli.include` (see that function's doc comment for why: the\n * broader default-surface population is real but unrelated pre-existing\n * over-exposure this repo hasn't triaged, not a #2638 defect). So this\n * warning must not unconditionally claim the build will fail — only an\n * explicit `cli.include` naming the action makes that true today.\n */\n function warnCliApiCoherenceViolations(m: SmartObjectManifest): void {\n if (!validateCliApiCoherence) return;\n const violations = findCliApiCoherenceViolations(m);\n if (violations.length === 0) return;\n for (const { className, unreachable, invalidSkipApiCheck } of violations) {\n for (const name of invalidSkipApiCheck ?? []) {\n console.warn(\n `[smrt] ${className}: cli.skipApiCheck names '${name}', which isn't a ` +\n `CRUD verb or a scanned public method on this class, or isn't part of ` +\n `its current cli.include/cli.exclude surface (a typo, or a stale entry ` +\n `left behind after the command was dropped from cli.include). Build ` +\n `will fail until this is resolved.\\n` +\n ` Fix the typo, or remove '${name}' from cli.skipApiCheck -- an\\n` +\n ` unrecognized or stale name grants no exemption at all.`,\n );\n }\n const cliConfig = m.objects[className]?.decoratorConfig?.cli;\n const isEnforced =\n typeof cliConfig === 'object' &&\n cliConfig !== null &&\n Array.isArray(cliConfig.include) &&\n cliConfig.include.length > 0;\n const methods = m.objects[className]?.methods ?? {};\n const isRealCommandName = (name: string) =>\n (CRUD_OPERATIONS as readonly string[]).includes(name) ||\n methods[name]?.isPublic === true;\n for (const action of unreachable) {\n const skipApiCheckSuggestion = isRealCommandName(action)\n ? ` (or \\`skipApiCheck: ['${action}']\\` to acknowledge only this command)`\n : '';\n console.warn(\n `[smrt] ${className}.${action} is exposed as a CLI command but is not ` +\n `exposed via the api.` +\n (isEnforced\n ? ' Build will fail until this is resolved.\\n'\n : ' (Not yet build-blocking for this cli:true/{} class -- see #2638.)\\n') +\n ` Either:\\n` +\n ` - Decorate '${action}' with @method({ expose: true }) to route it, or\\n` +\n ` - Add '${action}' to api.include, or\\n` +\n ` - Remove '${action}' from cli.include / add it to cli.exclude.\\n` +\n ` The CLI invokes methods over HTTP; methods without API routes are unreachable.\\n` +\n ` A public method is routed by default only when every parameter can be\\n` +\n ` built from JSON; see withheldSurfaces in the knowledge artifact for the\\n` +\n ` reason this one was withheld (#2686).\\n` +\n ` If this CLI is intentionally invoked in-process (no HTTP), set\\n` +\n ` \\`cli: { skipApiCheck: true }\\`${skipApiCheckSuggestion} on the\\n` +\n ` @smrt() decorator.`,\n );\n }\n }\n }\n\n let server: ViteDevServer | undefined;\n let manifest: SmartObjectManifest | null = null;\n /**\n * The declared agent surface from the most recent OXC scan (#2591). Held\n * beside `manifest` rather than on it, because `manifest.json` is the runtime\n * manifest and stays runtime-focused; this belongs to the knowledge artifact.\n */\n let agentSurface: DomainKnowledgeAgentSurface | undefined;\n let activeManifestScan: Promise<SmartObjectManifest> | undefined;\n let activeBuildStart: Promise<void> | undefined;\n let pluginMode: 'server' | 'client' = 'server';\n let projectRoot: string = process.cwd();\n let config: ResolvedConfig | null = null; // Store resolved config for closeBundle hook\n let resolvedPluginNames: string[] = [];\n let hasFreshConfigResolvedManifest = false;\n let configHookManifest: SmartObjectManifest | null = null;\n let generatedRoutesDuringConfig = false;\n let routeLifecycleConfig: object | undefined;\n let routeExpectedOwners: Array<'producer' | 'consumer'> = ['producer'];\n\n async function generateConfiguredSvelteKitRoutes(\n rootDir: string,\n currentManifest: SmartObjectManifest,\n ): Promise<void> {\n const routeOptions = {\n enabled: svelteKit.enabled,\n routesDir: svelteKit.routesDir || 'src/routes/api',\n objectsDir: svelteKit.objectsDir || 'src/lib/objects',\n configPath: svelteKit.configPath || 'src/lib/server',\n configFileName: svelteKit.configFileName || 'smrt.ts',\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n changesRoute: svelteKit.changesRoute,\n eventsRoute: svelteKit.eventsRoute,\n resourcesRoute: svelteKit.resourcesRoute,\n knowledge: await resolveKnowledgeConfig(rootDir, currentManifest),\n };\n if (routeLifecycleConfig) {\n await contributeSvelteKitRoutes(\n routeLifecycleConfig,\n routeExpectedOwners,\n rootDir,\n {\n owner: 'producer',\n routeManifest: currentManifest,\n semanticManifest: currentManifest,\n options: routeOptions,\n },\n );\n return;\n }\n await generateSvelteKitRoutes(rootDir, currentManifest, routeOptions);\n }\n\n /**\n * Write manifest to .smrt/manifest.json for CLI discovery.\n * This ensures `smrt db:migrate`, `smrt db:status`, etc. can find\n * locally-defined SMRT objects in non-library builds (Issue #963).\n *\n * Merge-preserving, symmetrically with `smrtConsumer()`'s\n * `saveAggregatedManifest()` (issue #1760): both plugins write this one\n * file, and neither owns all of it. This hook runs once per Vite build\n * pass/environment, while the consumer's aggregation runs in `buildStart`\n * and does not run on every pass — so a SvelteKit `adapter-node` build ends\n * with this write, and a plain overwrite here drops every consumed\n * package's objects from the file the CLI then reads (issue #2925). For a\n * pure-consumer app (0 local objects, the shape `template-sveltekit`\n * documents) that left `objects: {}` on disk and broke `smrt db:migrate`.\n */\n async function writeLocalManifest(\n m: SmartObjectManifest,\n rootDir: string,\n ): Promise<void> {\n try {\n const { writeFileSync, mkdirSync } = await import('node:fs');\n const { resolve } = await import('node:path');\n\n const smrtDir = resolve(rootDir, '.smrt');\n mkdirSync(smrtDir, { recursive: true });\n\n const manifestPath = resolve(smrtDir, 'manifest.json');\n const merged = mergeExternalManifestEntries(m, manifestPath);\n writeFileSync(manifestPath, JSON.stringify(merged, null, 2), 'utf-8');\n await writeDomainKnowledgeArtifact(\n merged,\n rootDir,\n resolve(smrtDir, 'smrt-knowledge.json'),\n manifestPath,\n );\n\n const objectCount = Object.keys(m.objects).length;\n const preservedCount = Object.keys(merged.objects).length - objectCount;\n console.log(\n preservedCount > 0\n ? `[smrt] Wrote local manifest with ${objectCount} objects to .smrt/manifest.json (preserved ${preservedCount} consumed package objects)`\n : `[smrt] Wrote local manifest with ${objectCount} objects to .smrt/manifest.json`,\n );\n } catch (error) {\n console.error('[smrt] Error writing local manifest:', error);\n }\n }\n\n /**\n * @param deterministic - Emit a fixed `generatedAt` instead of the clock.\n * Set for artifacts written into the build output directory: `dist/` is\n * compared byte-for-byte by downstream caches, and a fresh checkout has no\n * previous file for {@link preserveKnowledgeGeneratedAt} to carry a value\n * forward from, so every build would otherwise emit different bytes\n * (#2223). The working copy under `.smrt/` keeps a real timestamp, which\n * is where it is useful to a human and where preservation already works.\n */\n async function writeDomainKnowledgeArtifact(\n m: SmartObjectManifest,\n rootDir: string,\n outputPath: string,\n manifestPath: string,\n deterministic = false,\n ): Promise<void> {\n const resolvedKnowledge = await resolveKnowledgeConfig(rootDir, m);\n if (resolvedKnowledge.enabled === false) {\n return;\n }\n\n const { mkdirSync, writeFileSync } = await import('node:fs');\n const { dirname } = await import('node:path');\n mkdirSync(dirname(outputPath), { recursive: true });\n const artifact = buildDomainKnowledgeManifest({\n manifest: m,\n rootDir,\n manifestPath,\n config: resolvedKnowledge,\n agentSurface,\n });\n const emitted = deterministic\n ? { ...artifact, generatedAt: DETERMINISTIC_GENERATED_AT }\n : preserveKnowledgeGeneratedAt(outputPath, artifact);\n writeFileSync(outputPath, JSON.stringify(emitted, null, 2), 'utf-8');\n }\n\n async function resolveKnowledgeConfig(\n rootDir: string,\n m: SmartObjectManifest,\n ): Promise<DomainKnowledgeConfig> {\n if (knowledge === false) return { enabled: false };\n const packageName = m.packageName ?? readPackageName(rootDir);\n return mergeKnowledgeConfig(\n await resolveFileKnowledgeConfig(rootDir, packageName),\n knowledge || {},\n );\n }\n\n function preserveKnowledgeGeneratedAt(\n outputPath: string,\n nextKnowledge: DomainKnowledgeManifest,\n ): DomainKnowledgeManifest {\n if (!existsSync(outputPath)) return nextKnowledge;\n\n try {\n const current = JSON.parse(\n readFileSync(outputPath, 'utf8'),\n ) as Partial<DomainKnowledgeManifest>;\n if (\n semanticKnowledgeJson(current) === semanticKnowledgeJson(nextKnowledge)\n ) {\n return {\n ...nextKnowledge,\n generatedAt: current.generatedAt ?? nextKnowledge.generatedAt,\n };\n }\n } catch {\n // Replace malformed artifacts.\n }\n\n return nextKnowledge;\n }\n\n function semanticKnowledgeJson(\n artifact: Partial<DomainKnowledgeManifest>,\n ): string {\n const { generatedAt: _generatedAt, ...rest } = artifact ?? {};\n return JSON.stringify(sortJson(rest));\n }\n\n function sortJson(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortJson);\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, entry]) => [key, sortJson(entry)]),\n );\n }\n return value;\n }\n\n function readPackageName(rootDir: string): string | undefined {\n try {\n const pkg = JSON.parse(\n readFileSync(join(rootDir, 'package.json'), 'utf8'),\n );\n return typeof pkg.name === 'string' ? pkg.name : undefined;\n } catch {\n return undefined;\n }\n }\n\n function validateConsumerPluginSetup(\n m: SmartObjectManifest,\n context: 'configResolved' | 'buildStart',\n ): void {\n if (config?.mode === 'test') {\n return;\n }\n\n if (config?.build?.lib) {\n return;\n }\n\n const consumerDependencies = (m.smrtDependencies || []).filter(\n (dependency) => dependency !== '@happyvertical/smrt-core',\n );\n if (consumerDependencies.length === 0) {\n return;\n }\n\n const hasConsumerPlugin = resolvedPluginNames.some(\n (name) => name === 'smrt-consumer',\n );\n if (hasConsumerPlugin) {\n return;\n }\n\n const dependencySummary =\n consumerDependencies.length <= 4\n ? consumerDependencies.join(', ')\n : `${consumerDependencies.slice(0, 4).join(', ')}, +${consumerDependencies.length - 4} more`;\n\n throw new Error(\n `[smrt] Consumer project misconfiguration detected during ${context}: found external SMRT dependencies (${dependencySummary}) but vite.config is missing smrtConsumer(). Add \"import { smrtConsumer } from '@happyvertical/smrt-core/consumer-plugin'\" and register it alongside smrtPlugin() so .smrt/register.js is generated for CLI/runtime class loading.`,\n );\n }\n\n function validateLibraryMinifySetup(\n m: SmartObjectManifest,\n context: 'configResolved' | 'buildStart',\n ): void {\n if (!config?.build?.lib) {\n return;\n }\n\n if (Object.keys(m.objects || {}).length === 0) {\n return;\n }\n\n if (config.build.minify === false) {\n return;\n }\n\n throw new Error(\n `[smrt] Library package misconfiguration detected during ${context}: packages that publish SMRT objects must set Vite build.minify = false. Minification rewrites runtime class names and breaks manifest registration, STI resolution, and collection queries in downstream apps.`,\n );\n }\n\n async function runBuildStart(): Promise<void> {\n if (hasFreshConfigResolvedManifest) {\n hasFreshConfigResolvedManifest = false;\n // configureServer may be attached between configResolved and buildStart.\n // Emit declarations from the reused manifest even though the scanner\n // itself does not need to run again.\n if (generateTypes && server && manifest) {\n await generateTypeDeclarationFile(\n manifest,\n projectRoot,\n typeDeclarationsPath,\n );\n }\n return;\n }\n\n // Rescan files on build start in all modes.\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963).\n if (manifest && !generationSnapshot) {\n await writeLocalManifest(manifest, projectRoot);\n }\n if (manifest) {\n validateLibraryMinifySetup(manifest, 'buildStart');\n validateConsumerPluginSetup(manifest, 'buildStart');\n if (validateCliApiCoherence) {\n validateCliIncludeAgainstApi(manifest);\n }\n }\n }\n\n const plugin: Plugin = {\n name: 'smrt-auto-service',\n // SvelteKit inventories routes in a `config.order = 'pre'` hook. Put SMRT\n // in Vite's earlier plugin tier so this plugin's own pre hook runs first\n // even when the documented plugin array lists sveltekit() before us.\n enforce: 'pre',\n\n // SvelteKit inventories filesystem routes in its config hook. Generate\n // SMRT routes in an earlier config hook so a clean checkout's first build\n // sees them; configResolved is too late because Vite runs those hooks\n // concurrently (#2313).\n config: {\n order: 'pre',\n async handler(userConfig, env) {\n if (!svelteKit.enabled) return;\n\n projectRoot =\n configuredProjectRoot ??\n resolve(process.cwd(), userConfig.root ?? '.');\n routeLifecycleConfig = env ?? userConfig;\n routeExpectedOwners = await expectedSvelteKitRouteOwners(\n userConfig,\n projectRoot,\n svelteKit.routesDir || 'src/routes/api',\n env,\n );\n configHookManifest = await scanAndGenerateManifest(projectRoot);\n await generateConfiguredSvelteKitRoutes(\n projectRoot,\n configHookManifest,\n );\n generatedRoutesDuringConfig = true;\n },\n },\n\n // Expose options for external access (e.g., test manifest generation)\n api: {\n options: {\n ...(configuredProjectRoot === undefined\n ? {}\n : { projectRoot: configuredProjectRoot }),\n ...(generationSnapshot === undefined ? {} : { generationSnapshot }),\n baseClasses,\n followImports,\n include,\n exclude,\n },\n resolveKnowledgeConfig: (currentManifest: SmartObjectManifest) =>\n resolveKnowledgeConfig(projectRoot, currentManifest),\n async resolveKnowledgeAgentSurface() {\n await (activeBuildStart ?? activeManifestScan);\n return agentSurface;\n },\n } satisfies SmrtPluginApi,\n\n async configResolved(resolvedConfig) {\n hasFreshConfigResolvedManifest = false;\n // Store config for closeBundle hook\n config = resolvedConfig;\n resolvedPluginNames = (resolvedConfig.plugins || []).map(\n (plugin) => plugin?.name || '',\n );\n\n // Store project root for file scanning\n projectRoot = configuredProjectRoot ?? resolvedConfig.root;\n if (svelteKit.enabled && routeLifecycleConfig) {\n assertSvelteKitRouteCoordinationComplete(routeLifecycleConfig);\n }\n\n // Detect plugin mode based on build configuration\n if (mode === 'auto') {\n const isSSRBuild = resolvedConfig.build?.ssr;\n const isFederationBuild = resolvedConfig.plugins.some((p) =>\n p.name?.includes('federation'),\n );\n const isClientBuild =\n isFederationBuild ||\n (!isSSRBuild && resolvedConfig.build?.target === 'esnext');\n\n pluginMode = isClientBuild ? 'client' : 'server';\n } else {\n pluginMode = mode;\n }\n\n console.log(`[smrt] Running in ${pluginMode} mode`);\n\n // Scan files and generate initial manifest in all modes\n manifest =\n configHookManifest ?? (await scanAndGenerateManifest(projectRoot));\n configHookManifest = null;\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest && !generationSnapshot) {\n await writeLocalManifest(manifest, projectRoot);\n }\n if (manifest) {\n validateLibraryMinifySetup(manifest, 'configResolved');\n validateConsumerPluginSetup(manifest, 'configResolved');\n if (validateCliApiCoherence) {\n validateCliIncludeAgainstApi(manifest);\n }\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && !generatedRoutesDuringConfig) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n generatedRoutesDuringConfig = false;\n\n // Vite calls buildStart immediately after configResolved for the initial\n // build. The manifest already reflects the same source tree, so let that\n // first hook reuse it. Later buildStart calls are watch rebuilds and must\n // rescan changed classes.\n hasFreshConfigResolvedManifest = true;\n },\n\n async buildStart() {\n const build = runBuildStart();\n activeBuildStart = build;\n try {\n await build;\n } finally {\n if (activeBuildStart === build) {\n activeBuildStart = undefined;\n }\n }\n },\n\n transform(_code, id) {\n // Library builds only: inline the scanned manifest into the package's\n // __smrt-register__ shim so the published dist registers field metadata\n // as data instead of resolving ./manifest.json at runtime. Runtime URL\n // resolution silently no-ops when a consumer's bundler (e.g. a\n // SvelteKit server build) relocates the module into its own chunks\n // directory, dropping every plain field from the registry (#1506,\n // #1507). Dev/test flows are untouched: the vitest plugin populates\n // manifests through its own path, and non-library builds keep the\n // original shim.\n if (!config?.build?.lib || !manifest) {\n return null;\n }\n if (!isRegisterShimModuleId(id)) {\n return null;\n }\n return {\n code: generateInlineRegisterModule(manifest),\n map: null,\n };\n },\n\n shouldTransformCachedModule({ id }) {\n // In `vite build --watch`, rollup caches transform results keyed on the\n // module's own code. The inlined register shim depends on the manifest\n // (rescanned each buildStart), not on the shim's unchanged source — so\n // force a re-transform or a field edit elsewhere in the package would\n // ship a stale inlined manifest.\n if (config?.build?.lib && isRegisterShimModuleId(id)) {\n return true;\n }\n return null;\n },\n\n configureServer(devServer) {\n server = devServer;\n\n // Serve default HTML when no index.html exists\n // Skip for SvelteKit projects (they use src/app.html and handle routing themselves)\n devServer.middlewares.use(async (req, res, next) => {\n // Skip default UI entirely for SvelteKit projects\n if (svelteKit.enabled) {\n return next();\n }\n\n if (req.url === '/' || req.url === '/index.html') {\n try {\n const { existsSync } = await import('node:fs');\n const { join } = await import('node:path');\n\n const projectRoot = devServer.config.root;\n const indexPath = join(projectRoot, 'index.html');\n\n // If index.html exists, let Vite handle it\n if (existsSync(indexPath)) {\n return next();\n }\n\n // Otherwise, serve default SMRT UI\n console.log('[smrt] Serving default UI (no index.html found)');\n let html = getDefaultHTML();\n\n // Apply Vite's HTML transformation to process module imports\n html = await devServer.transformIndexHtml('/', html);\n\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n return;\n } catch (error) {\n console.error('[smrt] Error serving default HTML:', error);\n return next();\n }\n }\n next();\n });\n\n // Set up file watching in all modes when enabled\n if (watch && hmr && !generationSnapshot) {\n // Watch for file changes\n const watcher = devServer.watcher;\n\n // Guard each watcher handler: scanAndGenerateManifest re-throws on a\n // mid-edit scan error, and an unhandled rejection in a watcher callback\n // can crash the dev server. Log and keep the previous manifest (#1378).\n watcher.on('change', async (file) => {\n try {\n if (await shouldRescan(file)) {\n console.log(`[smrt] Rescanning due to change in ${file}`);\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest) {\n await writeLocalManifest(manifest, projectRoot);\n warnCliApiCoherenceViolations(manifest);\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && server) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n\n // Invalidate virtual modules\n Object.values(VIRTUAL_MODULES).forEach((id) => {\n const module = server?.moduleGraph.getModuleById(id);\n if (module) {\n server?.reloadModule(module);\n }\n });\n }\n } catch (error) {\n console.error(\n `[smrt] Failed to rescan after change in ${file}:`,\n error,\n );\n }\n });\n\n watcher.on('add', async (file) => {\n try {\n if (await shouldRescan(file)) {\n console.log(`[smrt] Rescanning due to new file ${file}`);\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest) {\n await writeLocalManifest(manifest, projectRoot);\n warnCliApiCoherenceViolations(manifest);\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && server) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n }\n } catch (error) {\n console.error(\n `[smrt] Failed to rescan after adding ${file}:`,\n error,\n );\n }\n });\n\n watcher.on('unlink', async (file) => {\n try {\n if (await shouldRescan(file)) {\n console.log(`[smrt] Rescanning due to removed file ${file}`);\n manifest = await scanAndGenerateManifest(projectRoot);\n\n // Write local manifest for CLI discovery (Issue #963)\n if (manifest) {\n await writeLocalManifest(manifest, projectRoot);\n warnCliApiCoherenceViolations(manifest);\n }\n\n // Generate SvelteKit routes if enabled\n if (svelteKit.enabled && manifest && server) {\n await generateConfiguredSvelteKitRoutes(projectRoot, manifest);\n }\n }\n } catch (error) {\n console.error(\n `[smrt] Failed to rescan after removing ${file}:`,\n error,\n );\n }\n });\n }\n },\n\n resolveId(id) {\n // Resolve virtual module imports\n if (id in VIRTUAL_MODULES) {\n return `\\0${VIRTUAL_MODULES[id as keyof typeof VIRTUAL_MODULES]}`;\n }\n\n // Resolve virtual index.html for dev UI (only in dev mode)\n if (id === '/index.html' && server) {\n return `\\0smrt:index-html`;\n }\n\n return null;\n },\n\n async load(id) {\n // Load virtual modules (strip the \\0 prefix)\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (!manifest) {\n manifest = await scanAndGenerateManifest(projectRoot);\n }\n\n switch (cleanId) {\n case 'smrt:routes':\n // Routes module available in all modes\n return await generateRoutesModule(manifest);\n\n case 'smrt:client':\n // Client module available in both modes\n return generateClientModule(manifest, {\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n });\n\n case 'smrt:mcp':\n // MCP module available in all modes\n return await generateMCPModule(manifest);\n\n case 'smrt:types':\n // Types module available in both modes\n return await generateTypesModule(manifest, pluginMode);\n\n case 'smrt:manifest':\n // Manifest module available in both modes\n return generateManifestModule(manifest);\n\n case 'smrt:ui':\n // UI module for default development interface\n return await loadDefaultUI();\n\n case 'smrt:index-html':\n // Virtual index.html for projects without one\n return await loadDefaultHTML();\n\n case 'smrt:web':\n // Web collection definitions for the browser client data runtime\n // (@happyvertical/smrt-web, #1761)\n return generateWebModule(manifest, {\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n });\n\n default:\n return null;\n }\n },\n\n transformIndexHtml: {\n order: 'pre',\n handler: async (html, _ctx) => {\n // Only provide default HTML if no index.html exists in project\n if (!server) return html;\n\n try {\n const { existsSync } = await import('node:fs');\n const { join } = await import('node:path');\n\n const projectRoot = server.config.root;\n const indexPath = join(projectRoot, 'index.html');\n\n // If index.html exists, use it as-is\n if (existsSync(indexPath)) {\n return html;\n }\n\n // Otherwise, provide default SMRT UI\n return await loadDefaultHTML();\n } catch (error) {\n console.error('[smrt] Error checking for index.html:', error);\n return html;\n }\n },\n },\n\n async closeBundle() {\n // Write manifest to disk during library builds\n // This allows published packages to include their manifest\n if (!manifest || !config?.build?.lib || generationSnapshot) {\n return;\n }\n\n try {\n const { writeFileSync, mkdirSync } = await import('node:fs');\n const { resolve, dirname } = await import('node:path');\n\n // Determine output directory.\n // `rollupOptions.output` may be a single object or an array; mirror the\n // prior runtime behavior where reading `.dir` off an array yields\n // undefined and falls through to `build.outDir`.\n const rollupOutput = config.build?.rollupOptions?.output;\n const rollupOutputDir = Array.isArray(rollupOutput)\n ? undefined\n : rollupOutput?.dir;\n const outDir = rollupOutputDir || config.build?.outDir || 'dist';\n const manifestPath = resolve(projectRoot, outDir, 'manifest.json');\n const knowledgePath = resolve(\n projectRoot,\n outDir,\n 'smrt-knowledge.json',\n );\n\n // Ensure directory exists\n mkdirSync(dirname(manifestPath), { recursive: true });\n\n // Write manifest file\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n await writeDomainKnowledgeArtifact(\n manifest,\n projectRoot,\n knowledgePath,\n manifestPath,\n true,\n );\n\n const objectCount = Object.keys(manifest.objects).length;\n console.log(\n `[smrt] Wrote manifest with ${objectCount} objects to ${manifestPath}`,\n );\n } catch (error) {\n console.error('[smrt] Error writing manifest file:', error);\n }\n },\n };\n markSvelteKitRouteParticipant(\n plugin,\n 'producer',\n svelteKit.enabled,\n svelteKit.routesDir || 'src/routes/api',\n async (rootDir) =>\n resolveKnowledgeConfig(rootDir, { objects: {} } as SmartObjectManifest),\n (userConfig) =>\n configuredProjectRoot ??\n resolve(\n process.cwd(),\n (userConfig as { root?: string } | undefined)?.root ?? '.',\n ),\n );\n return plugin;\n\n function scanAndGenerateManifest(\n rootDir: string,\n ): Promise<SmartObjectManifest> {\n const scan = scanAndGenerateManifestImpl(rootDir);\n const tracked = scan.finally(() => {\n if (activeManifestScan === tracked) {\n activeManifestScan = undefined;\n }\n });\n activeManifestScan = tracked;\n return tracked;\n }\n\n async function scanAndGenerateManifestImpl(\n rootDir: string,\n ): Promise<SmartObjectManifest> {\n if (generationSnapshot) {\n const verified = loadVerifiedSmrtGenerationSnapshot<SmartObjectManifest>(\n generationSnapshot,\n rootDir,\n 'project',\n );\n console.log(\n `[smrt] Reusing verified generation snapshot (${generationSnapshot.provenance})`,\n );\n if (generateTypes && server) {\n await generateTypeDeclarationFile(\n verified,\n rootDir,\n typeDeclarationsPath,\n );\n }\n return verified;\n }\n\n // NOTE: We do NOT use the framework's static manifest here\n // The static manifest JSON that core emits at build time\n // contains framework objects (like 'pleb') which should not be included\n // when scanning user code in consuming applications.\n //\n // smrtPlugin is designed to scan USER code dynamically, not load\n // framework objects. For consuming apps that need framework objects,\n // they should use smrtConsumer plugin instead.\n\n // Always use OXC-based scanner (consolidated in Issue #951)\n try {\n return await scanWithOxc(rootDir);\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('Cannot find package')\n ) {\n console.error(\n '[smrt] @happyvertical/smrt-scanner is required but not installed.',\n );\n console.error(\n '[smrt] Install it: pnpm add @happyvertical/smrt-scanner',\n );\n }\n console.error('[smrt] Error scanning files:', error);\n // Re-throw to fail the build - don't silently continue with empty manifest\n throw error;\n }\n }\n\n /**\n * Scan files using OXC-based scanner (experimental fast path)\n * Uses Rust-based oxc-parser for 2-3x faster parsing\n */\n async function scanWithOxc(rootDir: string): Promise<SmartObjectManifest> {\n const startTime = performance.now();\n\n try {\n // Import the OXC scanner package\n const scannerModule = await importScanner();\n const { OxcScanner, ManifestAdapter } = scannerModule;\n\n console.log(`[smrt] Using experimental OXC scanner for faster builds`);\n\n // Create scanner with options. Always exclude .svelte files as OXC barfs on <style> tags\n const safeExclude = [...(exclude || []), '**/*.svelte'];\n const scanner = new OxcScanner({\n cwd: rootDir,\n include,\n exclude: safeExclude,\n followSymbolicLinks,\n });\n\n // Scan and resolve inheritance\n const { results, resolved } = await scanner.scanAndResolve();\n\n // The same scan already read every module-scope `defineIntent()` /\n // `definePlaybook()` declaration (#2591). Hold it for the knowledge\n // artifact rather than scanning a second time; it never reaches the\n // runtime manifest, which stays runtime-focused.\n agentSurface = toKnowledgeAgentSurface(results.agentSurface);\n reportAgentSurfaceDiagnostics(agentSurface);\n\n // Check for errors\n if (results.errors.length > 0) {\n console.error(\n `\\n[smrt] ❌ Build failed: ${results.errors.length} error(s) during scanning:\\n`,\n );\n for (const error of results.errors) {\n console.error(\n ` ${error.filePath}:${error.line || '?'}: ${error.message}\\n`,\n );\n }\n throw new Error(\n '[smrt] Build aborted due to scan errors. See above for details.',\n );\n }\n\n // Read package.json for metadata BEFORE creating manifest (Issue #713)\n // This ensures qualified names are generated correctly for namespace isolation\n // packageJson is also needed for agent manifest generation (component discovery)\n let packageName: string | undefined;\n let packageVersion: string | undefined;\n let packageJson: PackageJsonShape | undefined;\n try {\n const { readFileSync } = await import('node:fs');\n const { join } = await import('node:path');\n const pkgPath = join(rootDir, 'package.json');\n const pkgContent = readFileSync(pkgPath, 'utf-8');\n packageJson = JSON.parse(pkgContent) as PackageJsonShape;\n packageName = packageJson.name || undefined;\n packageVersion = packageJson.version || undefined;\n } catch {\n // package.json not found or invalid - continue without packageName\n console.warn(\n '[smrt] Warning: package.json not found. Qualified names will not be generated.',\n );\n }\n\n // Convert to manifest format with packageName for qualified names (Issue #713)\n const adapter = new ManifestAdapter();\n const newManifest = adapter.toManifest(resolved, {\n packageName,\n packageVersion,\n typeAliases: results.typeAliases,\n });\n\n // Add moduleType identifier\n newManifest.moduleType = 'smrt';\n\n // Keep this as a normal module import: dynamic source imports with a\n // `.js` specifier do not reliably resolve through tsx during publish-time\n // workspace builds, even though the compiled dist path exists.\n const smrtDependencies = discoverSmrtPackages({ baseDir: rootDir });\n if (smrtDependencies.length > 0) {\n newManifest.smrtDependencies = smrtDependencies;\n console.log(\n `[smrt] Found ${smrtDependencies.length} SMRT dependencies: ${smrtDependencies.join(', ')}`,\n );\n }\n\n // Run all manifest generation passes (same as TypeScript scanner path)\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const manifestGen = new ManifestGenerator();\n // THE pass sequence — shared with generateManifest() and\n // ManifestBuilder so the three producers cannot drift (#2360).\n manifestGen.applyGenerationPasses(newManifest, {\n packageName,\n packageJson,\n });\n\n // The declared surface and the generated one are only comparable once\n // the manifest exists, which is why this runs here and not beside the\n // scan (#2725). `buildWebMcpToolDefinitions` is the same function that\n // emits `webMcpToolDefinitions` into the `smrt:web` virtual module, so\n // the comparison is against the exposure-policy-filtered set that will\n // really register — not against every verb a class could expose, which\n // would invent collisions with tools nobody mounts.\n if (agentSurface && results.agentSurface) {\n try {\n const collisions = collectAgentSurfaceToolNameCollisions({\n surface: results.agentSurface,\n manifest: newManifest,\n checkAgentSurfaceToolNames:\n scannerModule.checkAgentSurfaceToolNames,\n kebabRoutes: svelteKit.kebabRoutes ?? false,\n });\n if (collisions.length > 0) {\n reportAgentSurfaceToolNameCollisions(collisions);\n agentSurface.diagnostics = sortKnowledgeAgentSurfaceDiagnostics([\n ...agentSurface.diagnostics,\n ...collisions,\n ]);\n }\n } catch (error) {\n // Advisory only. A manifest this cannot build definitions for fails\n // loudly where they are actually emitted; losing a warning must\n // never be the thing that breaks a build.\n console.warn(\n '[smrt] Skipped the agent-surface tool-name collision check:',\n error,\n );\n }\n }\n\n const elapsed = performance.now() - startTime;\n\n // Log results\n const objectCount = Object.keys(newManifest.objects).length;\n if (objectCount > 0) {\n const names = Object.keys(newManifest.objects).join(', ');\n console.log(`[smrt] Found ${objectCount} SMRT objects: ${names}`);\n } else {\n console.log('[smrt] No SMRT objects found');\n }\n console.log(`[smrt] OXC scan completed in ${elapsed.toFixed(2)}ms`);\n\n // Generate TypeScript declarations if enabled\n if (generateTypes && server) {\n await generateTypeDeclarationFile(\n newManifest,\n rootDir,\n typeDeclarationsPath,\n );\n }\n\n return newManifest;\n } catch (error) {\n console.error('[smrt] Error in OXC scanner:', error);\n throw error;\n }\n }\n\n async function shouldRescan(file: string): Promise<boolean> {\n // Only rescan in server mode\n if (pluginMode === 'client') {\n return false;\n }\n\n try {\n // Conditionally import minimatch\n const { minimatch } = await import('minimatch');\n\n const isIncluded = include.some((pattern) => minimatch(file, pattern));\n const isExcluded = exclude.some((pattern) => minimatch(file, pattern));\n\n return isIncluded && !isExcluded;\n } catch (error) {\n console.warn('[smrt] Error checking file patterns:', error);\n return false;\n }\n }\n}\n\n/**\n * Generate virtual routes module\n */\nasync function generateRoutesModule(\n manifest: SmartObjectManifest,\n): Promise<string> {\n try {\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const generator = new ManifestGenerator();\n const routes = generator.generateRestEndpoints(manifest);\n\n return `\n// Auto-generated REST routes from SMRT objects\n// This file is generated automatically - do not edit\n\n/**\n * Setup routes on an Express-like app\n *\n * NOTE: This virtual module function is for documentation only.\n * For actual route registration, use:\n * - import { startRestServer } from '@happyvertical/smrt-core'\n * - Or APIGenerator from '@happyvertical/smrt-core/generators'\n *\n * @param app - Express-like app instance\n * @param options - Route configuration options\n * @param options.basePath - Base path for all routes (default: '/api/v1')\n */\nexport function setupRoutes(app, options = {}) {\n const basePath = options.basePath || '/api/v1';\n\n console.warn('[smrt] setupRoutes is a documentation function only.');\n console.warn('[smrt] Use startRestServer() or APIGenerator for actual route registration.');\n console.warn('[smrt] Available endpoints:');\n${routes\n .split('\\\\n')\n .map((line) => ` console.warn(\\` \\${basePath}${line.trim()}\\`);`)\n .join('\\\\n')}\n}\n\nexport { setupRoutes as default };\n`;\n } catch (error) {\n console.warn('[smrt] Error generating routes module:', error);\n return 'export function setupRoutes(app, options = {}) { console.warn(\"Routes generation failed\"); }';\n }\n}\n\n/**\n * Generate virtual MCP module\n */\nasync function generateMCPModule(\n manifest: SmartObjectManifest,\n): Promise<string> {\n try {\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const generator = new ManifestGenerator();\n // Tool *definitions* (a JSON array), not `generateMCPTools()`'s\n // newline-joined name list, which is not a valid expression (#2631).\n const tools = generator.generateMCPToolsCode(manifest);\n\n return `\n// Auto-generated MCP tools from SMRT objects\n// This file is generated automatically - do not edit\n\nimport { SmrtMCPServer } from '@happyvertical/smrt-core/runtime';\n\nexport const tools = ${tools};\n\nexport function createMCPServer(options = {}) {\n const server = new SmrtMCPServer({\n name: options.name || 'smrt-auto-generated',\n version: options.version || '1.0.0',\n ...options\n });\n\n // Add all generated tools to the server. A handler supplied through the\n // documented \\`createMCPServer({ handlers })\\` option wins; the throwing\n // placeholder is only for tools the application did not wire up (#2631).\n const handlers = options.handlers || {};\n for (const tool of tools) {\n const handler = handlers[tool.name];\n server.addTool(\n tool,\n handler ||\n (async () => {\n throw new Error(\\`Tool '\\${tool.name}' handler must be provided by application\\`);\n }),\n );\n }\n\n return server;\n}\n\nexport { createMCPServer as default };\n`;\n } catch (error) {\n console.warn('[smrt] Error generating MCP module:', error);\n return `\nimport { SmrtMCPServer } from '@happyvertical/smrt-core/runtime';\nexport const tools = [];\nexport function createMCPServer(options = {}) {\n console.warn(\"MCP generation failed\");\n return new SmrtMCPServer({\n name: options.name || 'smrt-client',\n version: options.version || '1.0.0',\n ...options\n });\n}\n`;\n }\n}\n\n/**\n * Generate client-mode types without server dependencies\n */\nfunction generateClientModeTypes(manifest: SmartObjectManifest): string {\n const typeDefinitions: string[] = [];\n\n // Generate interfaces for each object in the manifest. Manifest key order\n // follows scan/discovery order, which is not stable across runs (#2749),\n // so sort deterministically before emitting.\n const sortedClientModeObjects = Object.entries(manifest.objects)\n .sort(\n ([leftKey, left], [rightKey, right]) =>\n compareText(\n left.qualifiedName || leftKey,\n right.qualifiedName || rightKey,\n ) || compareText(leftKey, rightKey),\n )\n .map(([, obj]) => obj);\n for (const objectMeta of sortedClientModeObjects) {\n // Manifest keys are qualified names; only the simple class name is a valid\n // TypeScript identifier (#2631). `className` is required on\n // `SmartObjectDefinition`, so there is deliberately no manifest-key\n // fallback here — one would reintroduce invalid emitted TypeScript.\n const interfaceName = objectMeta.className;\n const fields = objectMeta.fields || {};\n const propertyLines: string[] = [];\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n let type = 'any';\n\n // Map SMRT field types to TypeScript types\n switch (fieldDef.type) {\n case 'text':\n type = 'string';\n break;\n case 'decimal':\n case 'integer':\n type = 'number';\n break;\n case 'boolean':\n type = 'boolean';\n break;\n case 'datetime':\n type = 'string';\n break;\n case 'json':\n type = 'any';\n break;\n case 'foreignKey':\n type = 'string';\n break;\n default:\n type = 'any';\n }\n\n const optional = !fieldDef.required ? '?' : '';\n propertyLines.push(` ${fieldName}${optional}: ${type};`);\n }\n\n // Add common SmrtObject properties\n propertyLines.unshift(\n ' id?: string;',\n ' created_at?: string;',\n ' updated_at?: string;',\n );\n\n const interfaceDef = `export interface ${interfaceName}Data {\\n${propertyLines.join('\\n')}\\n}`;\n typeDefinitions.push(interfaceDef);\n }\n\n return typeDefinitions.join('\\n\\n');\n}\n\n/**\n * Generate virtual types module\n */\nasync function generateTypesModule(\n manifest: SmartObjectManifest,\n mode: 'server' | 'client' = 'server',\n): Promise<string> {\n let interfaces = '';\n\n try {\n // Only use scanner in server mode to avoid Node.js dependencies in browser builds\n if (mode !== 'client') {\n const { ManifestGenerator } = await importBuildAwareModule<\n typeof import('../scanner/index.js')\n >({\n source: '../scanner/index.ts',\n dist: '../scanner.js',\n });\n const generator = new ManifestGenerator();\n interfaces = generator.generateTypeDefinitions(manifest);\n } else {\n // In client mode, generate basic interfaces directly from manifest\n interfaces = generateClientModeTypes(manifest);\n }\n\n return `\n// Auto-generated TypeScript types from SMRT objects\n// This file is generated automatically - do not edit\n\n${interfaces}\n\nexport interface Request {\n params: Record<string, string>;\n query: Record<string, any>;\n json(): Promise<any>;\n}\n\nexport interface Response {\n json(data: any, init?: { status?: number }): Response;\n status(code: number): Response;\n}\n`;\n } catch (error) {\n console.warn('[smrt] Error generating types module:', error);\n return `\n// Auto-generated TypeScript types from SMRT objects (fallback)\n// This file is generated automatically - do not edit\n\nexport interface Request {\n params: Record<string, string>;\n query: Record<string, any>;\n json(): Promise<any>;\n}\n\nexport interface Response {\n json(data: any, init?: { status?: number }): Response;\n status(code: number): Response;\n}\n`;\n }\n}\n\n/**\n * Generate virtual manifest module\n */\nfunction generateManifestModule(manifest: SmartObjectManifest): string {\n return `\n// Auto-generated manifest from SMRT objects\n// This file is generated automatically - do not edit\n\nexport const manifest = ${JSON.stringify(manifest, null, 2)};\n\nexport { manifest as default };\n`;\n}\n\n/**\n * Generate TypeScript declaration file for virtual modules\n * This eliminates the need for manual type maintenance\n */\nexport async function generateTypeDeclarationFile(\n manifest: SmartObjectManifest,\n projectRoot: string,\n typeDeclarationsPath: string,\n): Promise<void> {\n try {\n // Conditionally import path and fs modules\n const [{ join }, { existsSync, mkdirSync, writeFileSync }] =\n await Promise.all([import('node:path'), import('node:fs')]);\n\n const declarationsDir = join(projectRoot, typeDeclarationsPath);\n const declarationsFile = join(declarationsDir, 'virtual-modules.d.ts');\n\n // Create directory if it doesn't exist\n if (!existsSync(declarationsDir)) {\n mkdirSync(declarationsDir, { recursive: true });\n }\n\n // Generate interface definitions for each discovered SMRT object. Sorted\n // for the same reason as generateClientModeTypes (#2749).\n const objectInterfaces = Object.entries(manifest.objects)\n .sort(\n ([leftKey, left], [rightKey, right]) =>\n compareText(\n left.qualifiedName || leftKey,\n right.qualifiedName || rightKey,\n ) || compareText(leftKey, rightKey),\n )\n .map(([_name, obj]) => {\n const interfaceName = `${obj.className}Data`;\n const fields = Object.entries(obj.fields)\n .map(([fieldName, field]) => {\n const optional = field.required === false ? '?' : '';\n const type = mapTypeScriptType(field.type);\n return ` ${fieldName}${optional}: ${type};`;\n })\n .join('\\n');\n\n // Timestamps are snake_case on the wire (#1797): the server returns\n // `created_at`/`updated_at` exactly as SmrtObject.toJSON() emits them,\n // matching the prebuild + client-mode type paths.\n return ` export interface ${interfaceName} {\n id?: string;\n${fields}\n created_at?: string;\n updated_at?: string;\n }`;\n })\n .join('\\n\\n');\n\n // Generate API client interface for each object\n // Always use plural collection names (standard REST convention).\n // Filter custom methods through resolveApiActionSet so the declared\n // type surface matches what generateClientModule actually emits at\n // runtime — otherwise consumers see methods in autocomplete that are\n // undefined at runtime.\n const apiClientInterface = selectApiClientEntries(manifest)\n .map(\n ({\n obj,\n clientKey,\n dataInterfaceName,\n crudMethods,\n customMethods: exposedMethods,\n }) => {\n const { methods = {} } = obj;\n const interfaceName = dataInterfaceName;\n const exposedActionNames = new Set(\n exposedMethods.map((method) => method.name),\n );\n const customMethods = Object.entries(methods).filter(\n ([name, method]) =>\n !GENERATED_CLIENT_CRUD_METHODS.has(name) &&\n method.isPublic &&\n exposedActionNames.has(name),\n );\n\n // Generate custom method signatures\n const customMethodSignatures = customMethods\n .map(([methodName]) => {\n const exposedMethod = exposedMethods.find(\n ({ name }) => name === methodName,\n );\n if (!exposedMethod) return '';\n const signature = renderApiClientCustomMethodParameters(\n exposedMethod,\n mapTypeScriptType,\n );\n return ` ${methodName}(${signature}): Promise<any>;`;\n })\n .join('\\n');\n\n const overriddenBaseMethods = customMethods\n .map(([methodName]) => methodName)\n .filter((methodName) =>\n GENERATED_CLIENT_BASE_METHODS.has(methodName),\n );\n const crudOperationsType = renderApiClientCrudType(\n interfaceName,\n crudMethods,\n overriddenBaseMethods,\n );\n\n if (customMethods.length > 0) {\n const intersection = crudOperationsType\n ? `${crudOperationsType} & `\n : '';\n return ` ${JSON.stringify(clientKey)}: ${intersection}{\\n${customMethodSignatures}\\n };`;\n }\n\n return ` ${JSON.stringify(clientKey)}: ${crudOperationsType ?? 'Record<string, never>'};`;\n },\n )\n .join('\\n');\n\n // Typed web collection definitions (#1761): one entry per REST collection,\n // with the row type threaded through the phantom `_row` carrier so\n // downstream factories (`@happyvertical/smrt-web`) can infer it. Selection\n // shares selectWebCollectionEntries with the runtime module so the declared\n // types and the emitted values cannot drift.\n const webCollectionInterface = selectWebCollectionEntries(manifest)\n .map(\n ({ collection, obj }) =>\n ` ${JSON.stringify(collection)}: SmrtWebCollectionDefinition<import('@happyvertical/smrt-virt-types').${obj.className}Data>;`,\n )\n .join('\\n');\n\n // Generate MCP tool interfaces based on discovered methods\n const _mcpTools = Object.entries(manifest.objects).flatMap(([_name, obj]) =>\n Object.entries(obj.methods).map(([methodName, method]) => ({\n name: `${methodName}_${obj.collection}`,\n description: `${method.name} operation on ${obj.collection}`,\n inputSchema: {\n type: 'object',\n properties: Object.fromEntries(\n method.parameters.map((param) => [\n param.name,\n { type: mapJsonSchemaType(param.type) },\n ]),\n ),\n required: method.parameters\n .filter((p) => p.optional !== true)\n .map((p) => p.name),\n },\n })),\n );\n\n const typeDeclarations = `/**\n * Auto-generated TypeScript declarations for SMRT virtual modules\n * Generated from discovered @smrt() decorated classes\n * \n * DO NOT EDIT THIS FILE MANUALLY\n * This file is automatically regenerated when SMRT objects change\n */\n\n// Manifest module - Contains discovered SMRT objects metadata\ndeclare module '@happyvertical/smrt-virt-manifest' {\n export interface SmrtObjectField {\n type: string;\n required?: boolean;\n default?: any;\n }\n\n export interface SmrtObjectMethod {\n name: string;\n parameters: Array<{\n name: string;\n type: string;\n required?: boolean;\n }>;\n returnType: string;\n isAsync: boolean;\n }\n\n export interface SmrtObjectDefinition {\n className: string;\n collection: string;\n fields: Record<string, SmrtObjectField>;\n methods: Record<string, SmrtObjectMethod>;\n decoratorConfig: any;\n }\n\n export interface SmrtManifest {\n version: string;\n timestamp: number;\n objects: Record<string, SmrtObjectDefinition>;\n }\n\n export const manifest: SmrtManifest;\n}\n\n// Routes module - Auto-generated REST route setup\ndeclare module '@happyvertical/smrt-virt-routes' {\n export interface RouteApp {\n get(path: string, handler: (req: any, res: any) => void): void;\n post(path: string, handler: (req: any, res: any) => void): void;\n put(path: string, handler: (req: any, res: any) => void): void;\n delete(path: string, handler: (req: any, res: any) => void): void;\n }\n\n export interface RouteOptions {\n basePath?: string;\n [key: string]: any;\n }\n\n export function setupRoutes(app: RouteApp, options?: RouteOptions): void;\n export default setupRoutes;\n}\n\n// Client module - Auto-generated API client\n// Wire-shape policy (#1797): the server returns BARE JSON — a bare array for\n// list/search, a bare object for get/create/update — with snake_case field\n// names (created_at, updated_at). These declarations match that shape (no\n// envelope, no camelCase). Fetchers reject on non-2xx with a SmrtClientError\n// (#1796). Shared CRUD wire types stay aligned with the prebuild declaration\n// path; Vite-only custom action declarations are layered onto them below.\ndeclare module '@happyvertical/smrt-virt-client' {\n /** Structured custom-action failure nested under an API error body's \\`error\\` key. */\n export interface SmrtClientFailure {\n ok: false;\n code: string;\n message: string;\n status?: number;\n }\n\n /** Shape of a JSON error body carried by a rejected request (SmrtClientError.body). */\n export interface ApiError {\n error?: string | SmrtClientFailure;\n message?: string;\n }\n\n /** Typed error thrown by every fetcher on a non-2xx response (#1796). */\n export interface SmrtClientError extends Error {\n name: 'SmrtClientError';\n status: number;\n /** Machine-readable code from a structured custom-action failure, when present. */\n code?: string;\n body?: ApiError | string;\n }\n\n export interface CrudOperations<T = any> {\n list(params?: Record<string, any>): Promise<T[]>;\n get(id: string): Promise<T>;\n create(data: Partial<T>): Promise<T>;\n update(id: string, data: Partial<T>): Promise<T>;\n delete(id: string): Promise<boolean>;\n search(query: string): Promise<T[]>;\n }\n\n export interface ApiClient {\n${apiClientInterface}\n }\n\n export function createClient(basePath?: string): ApiClient;\n export default createClient;\n}\n\n// MCP module - Auto-generated Model Context Protocol tools\ndeclare module '@happyvertical/smrt-virt-mcp' {\n import type { SmrtMCPServer, MCPServerOptions } from '@happyvertical/smrt-core/runtime';\n\n export interface McpTool {\n name: string;\n description: string;\n inputSchema: {\n type: string;\n properties: Record<string, any>;\n required?: string[];\n };\n }\n\n export const tools: McpTool[];\n export function createMCPServer(options?: MCPServerOptions): SmrtMCPServer;\n export default createMCPServer;\n}\n\n// Types module - Auto-generated TypeScript interfaces\ndeclare module '@happyvertical/smrt-virt-types' {\n export const types: string;\n\n // Auto-generated interfaces for discovered SMRT objects\n${objectInterfaces}\n\n export default types;\n}\n\n// Web module - Typed collection definitions for the browser client data\n// runtime (@happyvertical/smrt-web, #1761)\ndeclare module '@happyvertical/smrt-virt-web' {\n export type SmrtWebFieldType =\n | 'text'\n | 'decimal'\n | 'boolean'\n | 'integer'\n | 'datetime'\n | 'json'\n | 'foreignKey'\n | 'crossPackageRef';\n\n /** Static \\`@field({ ui })\\` hints (#2046) — the field-policy rail seed. */\n export interface SmrtWebFieldUIHints {\n basic?: boolean;\n group?: string;\n order?: number;\n locked?: boolean;\n }\n\n export interface SmrtWebFieldDefinition {\n type: SmrtWebFieldType;\n required?: boolean;\n nullable?: boolean;\n default?: unknown;\n /** Developer-authored \\`@field({ description })\\` (#2046) — end-user help seed. */\n description?: string;\n /** Static \\`@field({ ui })\\` hints (#2046). */\n ui?: SmrtWebFieldUIHints;\n }\n\n export type SmrtWebRelationshipKind =\n | 'foreignKey'\n | 'crossPackageRef'\n | 'oneToMany'\n | 'manyToMany';\n\n /**\n * A manifest-derived edge to a sibling REST collection. Mutating this\n * collection invalidates the caches of the collections named by these edges\n * (#1761 relationship-derived invalidation).\n */\n export interface SmrtWebRelationship {\n field: string;\n kind: SmrtWebRelationshipKind;\n relatedCollection: string;\n }\n\n export interface WebToolRouteDescriptor {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n scope: 'item' | 'collection';\n path: string[];\n parameterAliases?: Record<string, string>;\n optionsBag?: boolean;\n }\n\n /** A WebMCP/MCP tool descriptor for one collection action (#1812). */\n export interface WebToolDescriptor {\n action: string;\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n readOnly: boolean;\n effect: 'read' | 'write' | 'destructive';\n idempotent: boolean;\n openWorld: boolean;\n route?: WebToolRouteDescriptor;\n }\n\n /** Canonical data-only definition for one generated browser tool. */\n export interface WebMcpToolDefinition extends WebToolDescriptor {\n collection: string;\n objectRef: string;\n className: string;\n endpoint: string;\n idField: string;\n idType: 'uuid' | 'text';\n route: WebToolRouteDescriptor;\n relationships: SmrtWebRelationship[];\n }\n\n export interface SmrtWebCollectionDefinition<TData = Record<string, unknown>> {\n name: string;\n /** Canonical qualified model identity (\\`@package/name:ClassName\\`) for policy APIs. */\n objectRef: string;\n className: string;\n endpoint: string;\n idField: string;\n actions: string[];\n fields: Record<string, SmrtWebFieldDefinition>;\n /** Manifest-derived relationship edges to sibling REST collections. */\n relationships: SmrtWebRelationship[];\n /** WebMCP/MCP tool descriptors for the exposed actions (#1812). */\n toolDescriptors: WebToolDescriptor[];\n /** Phantom row-type carrier for inference — never present at runtime. */\n _row?: TData;\n }\n\n export interface SmrtWebCollectionDefinitions {\n${webCollectionInterface}\n }\n\n export const collectionDefinitions: SmrtWebCollectionDefinitions;\n /** Every API-backed WebMCP tool, independent of list materialization. */\n export const webMcpToolDefinitions: readonly WebMcpToolDefinition[];\n export function getCollectionDefinition<\n K extends keyof SmrtWebCollectionDefinitions,\n >(name: K): SmrtWebCollectionDefinitions[K];\n /**\n * Build-time web-collection shape digest (#1764). A deterministic,\n * replica-stable hash of the emitted collection definitions; a change means\n * old persisted client rows may mis-hydrate. Consumers fold it into the\n * durable persistence namespace and the version-awareness updateAvailable\n * contract signal. One of the co-managed emission sites that must not drift —\n * the runtime value, this ambient d.ts, the physical @smrt/web d.ts, and the\n * hand-written @happyvertical/smrt-web type mirror.\n */\n export const manifestHash: string;\n export default collectionDefinitions;\n}\n`;\n\n // Write the declarations file\n writeFileSync(declarationsFile, typeDeclarations);\n console.log(\n `[smrt] Generated TypeScript declarations: ${declarationsFile}`,\n );\n } catch (error) {\n console.error('[smrt] Error generating TypeScript declarations:', error);\n }\n}\n\n/**\n * Map SMRT field types to TypeScript types\n */\nfunction mapTypeScriptType(smrtType: string): string {\n const typeMap: Record<string, string> = {\n text: 'string',\n integer: 'number',\n decimal: 'number',\n datetime: 'string',\n json: 'any',\n foreignKey: 'string',\n crossPackageRef: 'string',\n oneToMany: 'any[]',\n manyToMany: 'any[]',\n meta: 'any',\n string: 'string',\n number: 'number',\n boolean: 'boolean',\n array: 'any[]',\n object: 'Record<string, any>',\n date: 'string',\n Date: 'string',\n };\n return typeMap[smrtType] || 'any';\n}\n\n/**\n * Map TypeScript types to JSON Schema types for MCP tools\n */\nfunction mapJsonSchemaType(tsType: string): string {\n const typeMap: Record<string, string> = {\n string: 'string',\n number: 'number',\n boolean: 'boolean',\n array: 'array',\n object: 'object',\n any: 'string',\n };\n return typeMap[tsType] || 'string';\n}\n\n/**\n * Get default HTML template with inlined JavaScript (inlined for distribution)\n */\nfunction getDefaultHTML(): string {\n const uiScript = getDefaultUIModule();\n\n // Build HTML without template literals to avoid escaping issues\n return (\n '<!DOCTYPE html>\\n' +\n '<html lang=\"en\">\\n' +\n '<head>\\n' +\n ' <meta charset=\"UTF-8\">\\n' +\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\\n' +\n ' <title>SMRT Development UI</title>\\n' +\n ' <style>\\n' +\n ' * { margin: 0; padding: 0; box-sizing: border-box; }\\n' +\n ' body {\\n' +\n ' font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\\n' +\n ' background: #f5f5f5;\\n' +\n ' color: #333;\\n' +\n ' }\\n' +\n ' .container { max-width: 1200px; margin: 0 auto; padding: 20px; }\\n' +\n ' header {\\n' +\n ' background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\\n' +\n ' color: white;\\n' +\n ' padding: 40px 0;\\n' +\n ' margin-bottom: 40px;\\n' +\n ' box-shadow: 0 4px 6px rgba(0,0,0,0.1);\\n' +\n ' }\\n' +\n ' header h1 { font-size: 2.5em; font-weight: 700; margin-bottom: 10px; }\\n' +\n ' .subtitle { font-size: 1.1em; opacity: 0.9; }\\n' +\n ' .stats {\\n' +\n ' display: grid;\\n' +\n ' grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\\n' +\n ' gap: 20px;\\n' +\n ' margin-bottom: 40px;\\n' +\n ' }\\n' +\n ' .stat-card {\\n' +\n ' background: white;\\n' +\n ' padding: 20px;\\n' +\n ' border-radius: 8px;\\n' +\n ' box-shadow: 0 2px 4px rgba(0,0,0,0.1);\\n' +\n ' text-align: center;\\n' +\n ' }\\n' +\n ' .stat-value { font-size: 2.5em; font-weight: 700; color: #667eea; margin-bottom: 5px; }\\n' +\n ' .stat-label { font-size: 0.9em; color: #666; text-transform: uppercase; letter-spacing: 1px; }\\n' +\n ' .collections { display: grid; gap: 30px; }\\n' +\n ' .collection-card {\\n' +\n ' background: white;\\n' +\n ' border-radius: 8px;\\n' +\n ' box-shadow: 0 2px 4px rgba(0,0,0,0.1);\\n' +\n ' overflow: hidden;\\n' +\n ' }\\n' +\n ' .collection-header {\\n' +\n ' background: #667eea;\\n' +\n ' color: white;\\n' +\n ' padding: 15px 20px;\\n' +\n ' display: flex;\\n' +\n ' justify-content: space-between;\\n' +\n ' align-items: center;\\n' +\n ' }\\n' +\n ' .collection-title { font-size: 1.3em; font-weight: 600; }\\n' +\n ' .collection-count {\\n' +\n ' background: rgba(255,255,255,0.2);\\n' +\n ' padding: 5px 15px;\\n' +\n ' border-radius: 20px;\\n' +\n ' font-size: 0.9em;\\n' +\n ' }\\n' +\n ' .collection-body { padding: 20px; }\\n' +\n ' .field-list {\\n' +\n ' display: grid;\\n' +\n ' grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\\n' +\n ' gap: 15px;\\n' +\n ' margin-bottom: 20px;\\n' +\n ' }\\n' +\n ' .field {\\n' +\n ' padding: 10px;\\n' +\n ' background: #f8f9fa;\\n' +\n ' border-radius: 4px;\\n' +\n ' border-left: 3px solid #667eea;\\n' +\n ' }\\n' +\n ' .field-name { font-weight: 600; color: #333; margin-bottom: 3px; }\\n' +\n ' .field-type { font-size: 0.85em; color: #666; }\\n' +\n ' .actions { display: flex; gap: 10px; flex-wrap: wrap; }\\n' +\n ' .btn {\\n' +\n ' padding: 10px 20px;\\n' +\n ' border: none;\\n' +\n ' border-radius: 4px;\\n' +\n ' font-size: 0.9em;\\n' +\n ' cursor: pointer;\\n' +\n ' transition: all 0.2s;\\n' +\n ' text-decoration: none;\\n' +\n ' display: inline-block;\\n' +\n ' }\\n' +\n ' .btn-primary { background: #667eea; color: white; }\\n' +\n ' .btn-primary:hover { background: #5568d3; transform: translateY(-1px); }\\n' +\n ' .btn-secondary { background: #e0e0e0; color: #333; }\\n' +\n ' .btn-secondary:hover { background: #d0d0d0; }\\n' +\n ' .loading { text-align: center; padding: 40px; color: #666; }\\n' +\n ' .error {\\n' +\n ' background: #fee;\\n' +\n ' border: 1px solid #fcc;\\n' +\n ' color: #c33;\\n' +\n ' padding: 15px;\\n' +\n ' border-radius: 4px;\\n' +\n ' margin-bottom: 20px;\\n' +\n ' }\\n' +\n ' .empty-state { text-align: center; padding: 60px 20px; color: #999; }\\n' +\n ' .empty-state svg { width: 100px; height: 100px; margin-bottom: 20px; opacity: 0.3; }\\n' +\n ' </style>\\n' +\n '</head>\\n' +\n '<body>\\n' +\n ' <div id=\"app\">\\n' +\n ' <div class=\"loading\">Loading SMRT UI...</div>\\n' +\n ' </div>\\n' +\n ' <script type=\"module\">\\n' +\n uiScript +\n '\\n </script>\\n' +\n '</body>\\n' +\n '</html>'\n );\n}\n\n/**\n * Get default UI module from template file\n * Loads the JavaScript template\n */\nfunction getDefaultUIModule(): string {\n try {\n // Get current file directory\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n // Load template file (works in both src and dist)\n const templatePath = join(__dirname, 'templates/default-ui.js');\n\n return readFileSync(templatePath, 'utf-8').trim();\n } catch (error) {\n console.error('[smrt] Error loading UI template:', error);\n // Fallback to minimal UI\n return `\nasync function createUI() {\n const app = document.getElementById('app');\n if (!app) return;\n app.innerHTML = '<div class=\"container\" style=\"padding:40px;text-align:center;\"><h1>🎯 SMRT Development UI</h1><p>Template file not found. UI code could not be loaded.</p></div>';\n}\ncreateUI();\n`;\n }\n}\n\n/**\n * Load default HTML template for projects without index.html\n */\nasync function loadDefaultHTML(): Promise<string> {\n return getDefaultHTML();\n}\n\n/**\n * Load default UI module\n */\nasync function loadDefaultUI(): Promise<string> {\n return getDefaultUIModule();\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-core",
|
|
3
|
-
"version": "0.51.
|
|
3
|
+
"version": "0.51.8",
|
|
4
4
|
"description": "Core AI agent framework with standardized collections, object-relational mapping, and code generators",
|
|
5
5
|
"author": "HappyVertical",
|
|
6
6
|
"type": "module",
|
|
@@ -154,9 +154,9 @@
|
|
|
154
154
|
"@happyvertical/files": "^0.89.11",
|
|
155
155
|
"@happyvertical/json": "^0.89.11",
|
|
156
156
|
"@happyvertical/logger": "^0.89.11",
|
|
157
|
-
"@happyvertical/smrt-config": "0.51.
|
|
158
|
-
"@happyvertical/smrt-scanner": "0.51.
|
|
159
|
-
"@happyvertical/smrt-types": "0.51.
|
|
157
|
+
"@happyvertical/smrt-config": "0.51.8",
|
|
158
|
+
"@happyvertical/smrt-scanner": "0.51.8",
|
|
159
|
+
"@happyvertical/smrt-types": "0.51.8",
|
|
160
160
|
"@happyvertical/sql": "^0.89.11",
|
|
161
161
|
"@happyvertical/utils": "^0.89.11",
|
|
162
162
|
"@oxc-project/runtime": "^0.138.0",
|