@open-mercato/ai-assistant 0.6.8-develop.7082.1.f2a845b020 → 0.6.8-develop.7090.1.4dbca7b350
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/ai_assistant/lib/generated-registry-loader.js +10 -2
- package/dist/modules/ai_assistant/lib/generated-registry-loader.js.map +2 -2
- package/package.json +6 -6
- package/src/modules/ai_assistant/lib/__tests__/generated-registry-loader.test.ts +16 -0
- package/src/modules/ai_assistant/lib/generated-registry-loader.ts +10 -2
|
@@ -62,7 +62,11 @@ async function compileAndImportGenerated(tsPath) {
|
|
|
62
62
|
if (useJestCjsArtifact) {
|
|
63
63
|
return requireFromHere(jsPath);
|
|
64
64
|
}
|
|
65
|
-
return await import(
|
|
65
|
+
return await import(
|
|
66
|
+
/* webpackIgnore: true */
|
|
67
|
+
/* turbopackIgnore: true */
|
|
68
|
+
pathToFileURL(jsPath).href
|
|
69
|
+
);
|
|
66
70
|
}
|
|
67
71
|
function isJestRuntime() {
|
|
68
72
|
return typeof process.env.JEST_WORKER_ID === "string";
|
|
@@ -83,7 +87,11 @@ async function compileAppLocalModuleEntries(source, appRoot, runtime) {
|
|
|
83
87
|
const artifacts = /* @__PURE__ */ new Map();
|
|
84
88
|
if (specifiers.length === 0) return artifacts;
|
|
85
89
|
const generatedDir = path.join(appRoot, ".mercato", "generated");
|
|
86
|
-
const { compileAppSourceFile } = await import(
|
|
90
|
+
const { compileAppSourceFile } = await import(
|
|
91
|
+
/* webpackIgnore: true */
|
|
92
|
+
/* turbopackIgnore: true */
|
|
93
|
+
"@open-mercato/shared/lib/bootstrap/dynamicLoader"
|
|
94
|
+
);
|
|
87
95
|
for (const specifier of specifiers) {
|
|
88
96
|
const target = path.resolve(generatedDir, specifier);
|
|
89
97
|
const tsPath = fs.existsSync(`${target}.ts`) ? `${target}.ts` : fs.existsSync(target) && target.endsWith(".ts") ? target : null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/ai_assistant/lib/generated-registry-loader.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Runtime loader for `.mercato/generated/*.generated.ts` registry files.\n *\n * The generated registries import their entries through the `@/` path alias\n * (e.g. `@/.mercato/generated/ai-tools.generated`). That alias is only\n * understood by the Next.js bundler \u2014 in a standalone Node process (the\n * `mcp:dev` / `mcp:serve` MCP servers, the CLI tool-test runner) a raw\n * `import('@/.mercato/...')` throws `ERR_MODULE_NOT_FOUND: Cannot find\n * package '@/.mercato'` because Node treats `@/` as a package specifier.\n *\n * These helpers locate the generated `.ts` file on disk and compile-and-import\n * it with esbuild (transpile-only), rewriting `@/` aliases to absolute paths.\n * This mirrors `loadBootstrapData` in\n * `@open-mercato/shared/lib/bootstrap/dynamicLoader` and works in both the\n * monorepo and standalone apps.\n */\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport crypto from 'node:crypto'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\n\nconst logger = createLogger('ai_assistant')\n\nconst requireFromHere = createRequire(import.meta.url)\n\n/**\n * Locate a generated registry file (e.g. `ai-tools.generated.ts`) without\n * hardcoding the workspace layout. Searches upward from this module's compiled\n * location for a `apps/mercato/.mercato/generated/<fileName>` (monorepo), then\n * falls back to cwd-relative lookups (standalone apps run from the app dir).\n */\nexport function findGeneratedFile(fileName: string): string | null {\n const here = (() => {\n try {\n return fileURLToPath(import.meta.url)\n } catch {\n return null\n }\n })()\n\n if (here) {\n let cursor = path.dirname(here)\n for (let i = 0; i < 12; i++) {\n const candidate = path.join(cursor, 'apps', 'mercato', '.mercato', 'generated', fileName)\n if (fs.existsSync(candidate)) return candidate\n const next = path.dirname(cursor)\n if (next === cursor) break\n cursor = next\n }\n }\n // Fallbacks: cwd-based lookup (CLI invoked from apps/mercato, or a standalone\n // app whose root holds `.mercato/generated`).\n const fromCwd = path.resolve(process.cwd(), 'apps', 'mercato', '.mercato', 'generated', fileName)\n if (fs.existsSync(fromCwd)) return fromCwd\n const fromCwdDirect = path.resolve(process.cwd(), '.mercato', 'generated', fileName)\n if (fs.existsSync(fromCwdDirect)) return fromCwdDirect\n return null\n}\n\n/**\n * Compile-and-import a generated registry file on the fly. Rewrites the entry\n * specifiers Node can't resolve standalone (`@/...` aliases and the\n * `../../src/...` relative imports the generator emits for `@app` local\n * modules) to absolute file URLs, transpiles TS \u2192 ESM, and emits a sibling\n * `.mjs` we can `import()` from Node. Cached on mtime so repeat calls in the\n * same process don't recompile.\n *\n * Transpile-only (no bundling): the generated registries declare an array\n * literal whose entries are static `import(\"\u2026\")` arrow functions \u2014 we want\n * those `import()` strings to stay as runtime imports so Node resolves them\n * lazily through the workspace's normal module resolution. Eagerly bundling\n * pulls Next.js / route-handler internals into the `.mjs` and breaks at runtime\n * (e.g. `next/server` package-exports map).\n *\n * The `@app` local module entries are the one exception: those targets are raw\n * app TypeScript with no compiled sibling, so they are compiled separately\n * (see `compileAppLocalModuleEntries`) and the registry points at the artifact.\n */\nexport async function compileAndImportGenerated(tsPath: string): Promise<Record<string, unknown>> {\n const useJestCjsArtifact = isJestRuntime()\n const jsPath = tsPath.replace(/\\.ts$/, useJestCjsArtifact ? '.jest.cjs' : '.mjs')\n // appRoot is two directories up from `.mercato/generated/<file>.ts`.\n const appRoot = path.dirname(path.dirname(path.dirname(tsPath)))\n\n if (!fs.existsSync(tsPath)) {\n throw new Error(`Generated file not found: ${tsPath}`)\n }\n\n const runtime = useJestCjsArtifact ? 'cjs' : 'esm'\n const tsSource = fs.readFileSync(tsPath, 'utf-8')\n // Runs on every call, not only when the registry itself is stale: the\n // artifact path is stable, so a registry cache hit would otherwise pin an\n // app module's compiled output to whatever it was when the registry was\n // last regenerated.\n const appLocalArtifacts = await compileAppLocalModuleEntries(tsSource, appRoot, runtime)\n\n const jsExists = fs.existsSync(jsPath)\n const needsCompile =\n !jsExists || fs.statSync(tsPath).mtimeMs > fs.statSync(jsPath).mtimeMs\n\n if (needsCompile) {\n const esbuild = await import('esbuild')\n const aliasRewritten = rewriteGeneratedAliasImportsForRuntime(\n tsSource,\n appRoot,\n runtime,\n appLocalArtifacts,\n )\n const result = await esbuild.transform(aliasRewritten, {\n loader: 'ts',\n format: useJestCjsArtifact ? 'cjs' : 'esm',\n target: 'node18',\n sourcemap: false,\n sourcefile: tsPath,\n })\n fs.writeFileSync(jsPath, result.code)\n }\n\n if (useJestCjsArtifact) {\n return requireFromHere(jsPath) as Record<string, unknown>\n }\n return (await import(pathToFileURL(jsPath).href)) as Record<string, unknown>\n}\n\nfunction isJestRuntime(): boolean {\n return typeof process.env.JEST_WORKER_ID === 'string'\n}\n\n/** Every `../../src/...` specifier the generator emitted for `@app` local modules. */\nexport function collectAppLocalSpecifiers(source: string): string[] {\n const specifiers = new Set<string>()\n for (const [, specifier] of source.matchAll(APP_LOCAL_STATIC_IMPORT)) specifiers.add(specifier)\n for (const [, specifier] of source.matchAll(APP_LOCAL_DYNAMIC_IMPORT)) specifiers.add(specifier)\n return [...specifiers].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n}\n\n/** Stable, collision-free artifact name for one app-local specifier. */\nfunction appLocalArtifactName(specifier: string, runtime: 'esm' | 'cjs'): string {\n const slug = specifier.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-+|-+$/g, '')\n const digest = crypto.createHash('sha256').update(specifier).digest('hex').slice(0, 8)\n return `${slug}-${digest}.${runtime === 'cjs' ? 'cjs' : 'mjs'}`\n}\n\n/**\n * Compile every `@app` local module entry the generated registry references,\n * and map each specifier to its artifact.\n *\n * Package-backed modules (`@open-mercato/*`) never reach here \u2014 their bare\n * specifiers resolve through `node_modules` to compiled `.js`. App-local\n * modules have no compiled sibling, and Node cannot load their `.ts` source\n * directly: relative specifiers need explicit extensions under type stripping,\n * and the module's own graph (`./di`, `./data/entities`) carries decorator and\n * enum syntax that type stripping rejects outright. Bundling the entry with\n * every package import left external is what makes the source loadable.\n *\n * A module that fails to compile is logged and left pointing at its raw source,\n * which reproduces the pre-existing resolution error rather than silently\n * dropping the module's tools from the registry.\n */\nasync function compileAppLocalModuleEntries(\n source: string,\n appRoot: string,\n runtime: 'esm' | 'cjs',\n): Promise<Map<string, string>> {\n const specifiers = collectAppLocalSpecifiers(source)\n const artifacts = new Map<string, string>()\n if (specifiers.length === 0) return artifacts\n\n const generatedDir = path.join(appRoot, '.mercato', 'generated')\n const { compileAppSourceFile } = await import('@open-mercato/shared/lib/bootstrap/dynamicLoader')\n\n for (const specifier of specifiers) {\n const target = path.resolve(generatedDir, specifier)\n const tsPath = fs.existsSync(`${target}.ts`)\n ? `${target}.ts`\n : fs.existsSync(target) && target.endsWith('.ts')\n ? target\n : null\n if (tsPath === null) continue\n\n const outFile = path.join(generatedDir, 'app-modules', appLocalArtifactName(specifier, runtime))\n try {\n await compileAppSourceFile(tsPath, { appRoot, outFile, format: runtime })\n artifacts.set(specifier, outFile)\n } catch (error) {\n logger.warn('Could not compile an app-local module entry for the generated registry', {\n specifier,\n err: error,\n })\n }\n }\n\n return artifacts\n}\n\nconst UNSAFE_JS_STRING_CHAR_ESCAPES: Record<number, string> = {\n 0x3c: '\\\\u003C', // < \u2014 HTML/script-tag breakout\n 0x3e: '\\\\u003E', // > \u2014 HTML/script-tag breakout\n 0x2028: '\\\\u2028', // line separator \u2014 string content but a statement terminator pre-ES2019\n 0x2029: '\\\\u2029', // paragraph separator \u2014 same\n}\n\n/**\n * Escape characters that `JSON.stringify` leaves intact but which can still\n * break out of (or alter the meaning of) the JavaScript string literal that the\n * stringified value is embedded into \u2014 notably `<`/`>` (HTML/script-tag\n * breakout) and the U+2028 / U+2029 line separators (valid string content but\n * statement terminators in pre-ES2019 parsers). Apply this on top of\n * `JSON.stringify` so the emitted import source stays well-formed regardless of\n * the resolved path. Exported for unit testing.\n */\nexport function escapeUnsafeJsStringChars(value: string): string {\n return value.replace(\n /[<>\\u2028\\u2029]/g,\n (char) => UNSAFE_JS_STRING_CHAR_ESCAPES[char.charCodeAt(0)],\n )\n}\n\n/**\n * Stringify a resolved path into a JavaScript string literal that is safe to\n * embed in generated source: `JSON.stringify` handles quoting/standard escapes,\n * and `escapeUnsafeJsStringChars` neutralizes the characters it leaves intact.\n */\nfunction toSafeJsStringLiteral(value: string): string {\n return escapeUnsafeJsStringChars(JSON.stringify(value))\n}\n\n/**\n * Rewrite the two specifier shapes the generator emits for module entries in a\n * generated registry to absolute `file://` URLs Node can resolve in a\n * standalone process:\n *\n * 1. `@/...` path-alias imports (both `from \"@/x\"` and dynamic `import(\"@/x\")`).\n * The `@/` alias is a Next.js bundler convention; outside the bundler Node\n * treats `@/...` as a bare package specifier and throws\n * `ERR_MODULE_NOT_FOUND`. Resolved against `appRoot`.\n * 2. `../../src/...` relative imports the generator emits for `@app` local\n * modules (e.g. `from \"../../src/modules/<id>/ai-tools\"`). esbuild's\n * transform (transpile-only) leaves these untouched, so the compiled\n * `.mjs` keeps an extensionless relative specifier that resolves to a\n * `.ts` file with no compiled `.js`/`.mjs` sibling \u2014 Node ESM then throws\n * `ERR_MODULE_NOT_FOUND`. Resolved against the generated file's directory\n * (`<appRoot>/.mercato/generated`), the location the generator wrote them\n * relative to. Package-backed modules (`@open-mercato/*`) are unaffected \u2014\n * their bare specifiers resolve through `node_modules` to compiled `.js`.\n *\n * When `appLocalArtifacts` maps a shape-2 specifier to a compiled artifact, that\n * artifact wins: pointing Node at raw app TypeScript only works while the file\n * and its whole graph stay within what type stripping accepts, which app\n * modules do not (see `compileAppLocalModuleEntries`). Without a mapping both\n * shapes fall back to the same `.ts`-suffix probe. Other specifiers (bare\n * packages, sibling `./` imports) are left untouched. Exported for unit testing.\n */\nexport function rewriteGeneratedAliasImports(\n source: string,\n appRoot: string,\n appLocalArtifacts?: Map<string, string>,\n): string {\n return rewriteGeneratedAliasImportsForRuntime(source, appRoot, 'esm', appLocalArtifacts)\n}\n\nconst APP_LOCAL_STATIC_IMPORT = /from\\s+[\"']((?:\\.\\.\\/)+src\\/[^\"']+)[\"']/g\nconst APP_LOCAL_DYNAMIC_IMPORT = /import\\s*\\(\\s*[\"']((?:\\.\\.\\/)+src\\/[^\"']+)[\"']\\s*\\)/g\n\nfunction rewriteGeneratedAliasImportsForRuntime(\n source: string,\n appRoot: string,\n runtime: 'esm' | 'cjs',\n appLocalArtifacts: Map<string, string> = new Map(),\n): string {\n const generatedDir = path.join(appRoot, '.mercato', 'generated')\n const toRuntimeLiteral = (target: string): string =>\n toSafeJsStringLiteral(runtime === 'esm' ? pathToFileURL(target).href : target)\n const toResolvedLiteral = (target: string): string => {\n const candidate = fs.existsSync(target)\n ? target\n : fs.existsSync(target + '.ts')\n ? target + '.ts'\n : target\n return toRuntimeLiteral(candidate)\n }\n const resolveAlias = (relativePath: string): string =>\n toResolvedLiteral(path.join(appRoot, relativePath))\n const resolveRelative = (specifier: string): string => {\n const artifact = appLocalArtifacts.get(specifier)\n if (artifact !== undefined) return toRuntimeLiteral(artifact)\n return toResolvedLiteral(path.resolve(generatedDir, specifier))\n }\n return source\n .replace(/from\\s+[\"']@\\/([^\"']+)[\"']/g, (_match, relativePath: string) => {\n return `from ${resolveAlias(relativePath)}`\n })\n .replace(/import\\s*\\(\\s*[\"']@\\/([^\"']+)[\"']\\s*\\)/g, (_match, relativePath: string) => {\n return `import(${resolveAlias(relativePath)})`\n })\n .replace(APP_LOCAL_STATIC_IMPORT, (_match, specifier: string) => {\n return `from ${resolveRelative(specifier)}`\n })\n .replace(APP_LOCAL_DYNAMIC_IMPORT, (_match, specifier: string) => {\n return `import(${resolveRelative(specifier)})`\n })\n}\n\n/**\n * Compile-and-import `api-routes.generated.ts` and register its manifest with\n * the shared registry. Many module tools are \"API-backed\" \u2014 their handlers\n * delegate to `createAiApiOperationRunner`, which fails closed with\n * \"No API route manifest registered\" unless the manifest is present. In the\n * Next.js app this is wired at bootstrap, but the standalone MCP servers\n * (`mcp:dev` / `mcp:serve`) bootstrap DI without it, so we register it here.\n *\n * Idempotent: `registerApiRouteManifests` replaces the stored manifest, so\n * calling this repeatedly (e.g. per-request HTTP handlers) is safe. Returns the\n * number of registered routes (0 when the generated file is absent).\n */\nexport async function ensureApiRouteManifestsRegistered(): Promise<number> {\n const registry = await import('@open-mercato/shared/modules/registry')\n // Already wired (e.g. the Next.js app bootstrap, or a prior call). Leave the\n // existing manifest untouched so we never interfere with the in-app agents\n // framework, which registers it at bootstrap with its own override pipeline.\n const existing = registry.getApiRouteManifests()\n if (existing.length > 0) return existing.length\n\n const tsPath = findGeneratedFile('api-routes.generated.ts')\n if (!tsPath) return 0\n try {\n const mod = await compileAndImportGenerated(tsPath)\n const apiRoutes = (mod as { apiRoutes?: unknown }).apiRoutes\n if (!Array.isArray(apiRoutes)) return 0\n registry.registerApiRouteManifests(\n apiRoutes as Parameters<typeof registry.registerApiRouteManifests>[0],\n )\n return apiRoutes.length\n } catch (error) {\n logger.warn('Could not register api-routes manifest', { err: error })\n return 0\n }\n}\n"],
|
|
5
|
-
"mappings": "AAgBA,SAAS,oBAAoB;AAC7B,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,YAAY;AACnB,SAAS,qBAAqB;AAC9B,SAAS,eAAe,qBAAqB;AAE7C,MAAM,SAAS,aAAa,cAAc;AAE1C,MAAM,kBAAkB,cAAc,YAAY,GAAG;AAQ9C,SAAS,kBAAkB,UAAiC;AACjE,QAAM,QAAQ,MAAM;AAClB,QAAI;AACF,aAAO,cAAc,YAAY,GAAG;AAAA,IACtC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG;AAEH,MAAI,MAAM;AACR,QAAI,SAAS,KAAK,QAAQ,IAAI;AAC9B,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,YAAY,KAAK,KAAK,QAAQ,QAAQ,WAAW,YAAY,aAAa,QAAQ;AACxF,UAAI,GAAG,WAAW,SAAS,EAAG,QAAO;AACrC,YAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,UAAI,SAAS,OAAQ;AACrB,eAAS;AAAA,IACX;AAAA,EACF;AAGA,QAAM,UAAU,KAAK,QAAQ,QAAQ,IAAI,GAAG,QAAQ,WAAW,YAAY,aAAa,QAAQ;AAChG,MAAI,GAAG,WAAW,OAAO,EAAG,QAAO;AACnC,QAAM,gBAAgB,KAAK,QAAQ,QAAQ,IAAI,GAAG,YAAY,aAAa,QAAQ;AACnF,MAAI,GAAG,WAAW,aAAa,EAAG,QAAO;AACzC,SAAO;AACT;AAqBA,eAAsB,0BAA0B,QAAkD;AAChG,QAAM,qBAAqB,cAAc;AACzC,QAAM,SAAS,OAAO,QAAQ,SAAS,qBAAqB,cAAc,MAAM;AAEhF,QAAM,UAAU,KAAK,QAAQ,KAAK,QAAQ,KAAK,QAAQ,MAAM,CAAC,CAAC;AAE/D,MAAI,CAAC,GAAG,WAAW,MAAM,GAAG;AAC1B,UAAM,IAAI,MAAM,6BAA6B,MAAM,EAAE;AAAA,EACvD;AAEA,QAAM,UAAU,qBAAqB,QAAQ;AAC7C,QAAM,WAAW,GAAG,aAAa,QAAQ,OAAO;AAKhD,QAAM,oBAAoB,MAAM,6BAA6B,UAAU,SAAS,OAAO;AAEvF,QAAM,WAAW,GAAG,WAAW,MAAM;AACrC,QAAM,eACJ,CAAC,YAAY,GAAG,SAAS,MAAM,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE;AAEjE,MAAI,cAAc;AAChB,UAAM,UAAU,MAAM,OAAO,SAAS;AACtC,UAAM,iBAAiB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,SAAS,MAAM,QAAQ,UAAU,gBAAgB;AAAA,MACrD,QAAQ;AAAA,MACR,QAAQ,qBAAqB,QAAQ;AAAA,MACrC,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,IACd,CAAC;AACD,OAAG,cAAc,QAAQ,OAAO,IAAI;AAAA,EACtC;AAEA,MAAI,oBAAoB;AACtB,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AACA,SAAQ,MAAM,
|
|
4
|
+
"sourcesContent": ["/**\n * Runtime loader for `.mercato/generated/*.generated.ts` registry files.\n *\n * The generated registries import their entries through the `@/` path alias\n * (e.g. `@/.mercato/generated/ai-tools.generated`). That alias is only\n * understood by the Next.js bundler \u2014 in a standalone Node process (the\n * `mcp:dev` / `mcp:serve` MCP servers, the CLI tool-test runner) a raw\n * `import('@/.mercato/...')` throws `ERR_MODULE_NOT_FOUND: Cannot find\n * package '@/.mercato'` because Node treats `@/` as a package specifier.\n *\n * These helpers locate the generated `.ts` file on disk and compile-and-import\n * it with esbuild (transpile-only), rewriting `@/` aliases to absolute paths.\n * This mirrors `loadBootstrapData` in\n * `@open-mercato/shared/lib/bootstrap/dynamicLoader` and works in both the\n * monorepo and standalone apps.\n */\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport crypto from 'node:crypto'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\n\nconst logger = createLogger('ai_assistant')\n\nconst requireFromHere = createRequire(import.meta.url)\n\n/**\n * Locate a generated registry file (e.g. `ai-tools.generated.ts`) without\n * hardcoding the workspace layout. Searches upward from this module's compiled\n * location for a `apps/mercato/.mercato/generated/<fileName>` (monorepo), then\n * falls back to cwd-relative lookups (standalone apps run from the app dir).\n */\nexport function findGeneratedFile(fileName: string): string | null {\n const here = (() => {\n try {\n return fileURLToPath(import.meta.url)\n } catch {\n return null\n }\n })()\n\n if (here) {\n let cursor = path.dirname(here)\n for (let i = 0; i < 12; i++) {\n const candidate = path.join(cursor, 'apps', 'mercato', '.mercato', 'generated', fileName)\n if (fs.existsSync(candidate)) return candidate\n const next = path.dirname(cursor)\n if (next === cursor) break\n cursor = next\n }\n }\n // Fallbacks: cwd-based lookup (CLI invoked from apps/mercato, or a standalone\n // app whose root holds `.mercato/generated`).\n const fromCwd = path.resolve(process.cwd(), 'apps', 'mercato', '.mercato', 'generated', fileName)\n if (fs.existsSync(fromCwd)) return fromCwd\n const fromCwdDirect = path.resolve(process.cwd(), '.mercato', 'generated', fileName)\n if (fs.existsSync(fromCwdDirect)) return fromCwdDirect\n return null\n}\n\n/**\n * Compile-and-import a generated registry file on the fly. Rewrites the entry\n * specifiers Node can't resolve standalone (`@/...` aliases and the\n * `../../src/...` relative imports the generator emits for `@app` local\n * modules) to absolute file URLs, transpiles TS \u2192 ESM, and emits a sibling\n * `.mjs` we can `import()` from Node. Cached on mtime so repeat calls in the\n * same process don't recompile.\n *\n * Transpile-only (no bundling): the generated registries declare an array\n * literal whose entries are static `import(\"\u2026\")` arrow functions \u2014 we want\n * those `import()` strings to stay as runtime imports so Node resolves them\n * lazily through the workspace's normal module resolution. Eagerly bundling\n * pulls Next.js / route-handler internals into the `.mjs` and breaks at runtime\n * (e.g. `next/server` package-exports map).\n *\n * The `@app` local module entries are the one exception: those targets are raw\n * app TypeScript with no compiled sibling, so they are compiled separately\n * (see `compileAppLocalModuleEntries`) and the registry points at the artifact.\n */\nexport async function compileAndImportGenerated(tsPath: string): Promise<Record<string, unknown>> {\n const useJestCjsArtifact = isJestRuntime()\n const jsPath = tsPath.replace(/\\.ts$/, useJestCjsArtifact ? '.jest.cjs' : '.mjs')\n // appRoot is two directories up from `.mercato/generated/<file>.ts`.\n const appRoot = path.dirname(path.dirname(path.dirname(tsPath)))\n\n if (!fs.existsSync(tsPath)) {\n throw new Error(`Generated file not found: ${tsPath}`)\n }\n\n const runtime = useJestCjsArtifact ? 'cjs' : 'esm'\n const tsSource = fs.readFileSync(tsPath, 'utf-8')\n // Runs on every call, not only when the registry itself is stale: the\n // artifact path is stable, so a registry cache hit would otherwise pin an\n // app module's compiled output to whatever it was when the registry was\n // last regenerated.\n const appLocalArtifacts = await compileAppLocalModuleEntries(tsSource, appRoot, runtime)\n\n const jsExists = fs.existsSync(jsPath)\n const needsCompile =\n !jsExists || fs.statSync(tsPath).mtimeMs > fs.statSync(jsPath).mtimeMs\n\n if (needsCompile) {\n const esbuild = await import('esbuild')\n const aliasRewritten = rewriteGeneratedAliasImportsForRuntime(\n tsSource,\n appRoot,\n runtime,\n appLocalArtifacts,\n )\n const result = await esbuild.transform(aliasRewritten, {\n loader: 'ts',\n format: useJestCjsArtifact ? 'cjs' : 'esm',\n target: 'node18',\n sourcemap: false,\n sourcefile: tsPath,\n })\n fs.writeFileSync(jsPath, result.code)\n }\n\n if (useJestCjsArtifact) {\n return requireFromHere(jsPath) as Record<string, unknown>\n }\n return (await import(\n /* webpackIgnore: true */\n /* turbopackIgnore: true */\n pathToFileURL(jsPath).href\n )) as Record<string, unknown>\n}\n\nfunction isJestRuntime(): boolean {\n return typeof process.env.JEST_WORKER_ID === 'string'\n}\n\n/** Every `../../src/...` specifier the generator emitted for `@app` local modules. */\nexport function collectAppLocalSpecifiers(source: string): string[] {\n const specifiers = new Set<string>()\n for (const [, specifier] of source.matchAll(APP_LOCAL_STATIC_IMPORT)) specifiers.add(specifier)\n for (const [, specifier] of source.matchAll(APP_LOCAL_DYNAMIC_IMPORT)) specifiers.add(specifier)\n return [...specifiers].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n}\n\n/** Stable, collision-free artifact name for one app-local specifier. */\nfunction appLocalArtifactName(specifier: string, runtime: 'esm' | 'cjs'): string {\n const slug = specifier.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-+|-+$/g, '')\n const digest = crypto.createHash('sha256').update(specifier).digest('hex').slice(0, 8)\n return `${slug}-${digest}.${runtime === 'cjs' ? 'cjs' : 'mjs'}`\n}\n\n/**\n * Compile every `@app` local module entry the generated registry references,\n * and map each specifier to its artifact.\n *\n * Package-backed modules (`@open-mercato/*`) never reach here \u2014 their bare\n * specifiers resolve through `node_modules` to compiled `.js`. App-local\n * modules have no compiled sibling, and Node cannot load their `.ts` source\n * directly: relative specifiers need explicit extensions under type stripping,\n * and the module's own graph (`./di`, `./data/entities`) carries decorator and\n * enum syntax that type stripping rejects outright. Bundling the entry with\n * every package import left external is what makes the source loadable.\n *\n * A module that fails to compile is logged and left pointing at its raw source,\n * which reproduces the pre-existing resolution error rather than silently\n * dropping the module's tools from the registry.\n */\nasync function compileAppLocalModuleEntries(\n source: string,\n appRoot: string,\n runtime: 'esm' | 'cjs',\n): Promise<Map<string, string>> {\n const specifiers = collectAppLocalSpecifiers(source)\n const artifacts = new Map<string, string>()\n if (specifiers.length === 0) return artifacts\n\n const generatedDir = path.join(appRoot, '.mercato', 'generated')\n const { compileAppSourceFile } = await import(\n /* webpackIgnore: true */\n /* turbopackIgnore: true */\n '@open-mercato/shared/lib/bootstrap/dynamicLoader'\n )\n\n for (const specifier of specifiers) {\n const target = path.resolve(generatedDir, specifier)\n const tsPath = fs.existsSync(`${target}.ts`)\n ? `${target}.ts`\n : fs.existsSync(target) && target.endsWith('.ts')\n ? target\n : null\n if (tsPath === null) continue\n\n const outFile = path.join(generatedDir, 'app-modules', appLocalArtifactName(specifier, runtime))\n try {\n await compileAppSourceFile(tsPath, { appRoot, outFile, format: runtime })\n artifacts.set(specifier, outFile)\n } catch (error) {\n logger.warn('Could not compile an app-local module entry for the generated registry', {\n specifier,\n err: error,\n })\n }\n }\n\n return artifacts\n}\n\nconst UNSAFE_JS_STRING_CHAR_ESCAPES: Record<number, string> = {\n 0x3c: '\\\\u003C', // < \u2014 HTML/script-tag breakout\n 0x3e: '\\\\u003E', // > \u2014 HTML/script-tag breakout\n 0x2028: '\\\\u2028', // line separator \u2014 string content but a statement terminator pre-ES2019\n 0x2029: '\\\\u2029', // paragraph separator \u2014 same\n}\n\n/**\n * Escape characters that `JSON.stringify` leaves intact but which can still\n * break out of (or alter the meaning of) the JavaScript string literal that the\n * stringified value is embedded into \u2014 notably `<`/`>` (HTML/script-tag\n * breakout) and the U+2028 / U+2029 line separators (valid string content but\n * statement terminators in pre-ES2019 parsers). Apply this on top of\n * `JSON.stringify` so the emitted import source stays well-formed regardless of\n * the resolved path. Exported for unit testing.\n */\nexport function escapeUnsafeJsStringChars(value: string): string {\n return value.replace(\n /[<>\\u2028\\u2029]/g,\n (char) => UNSAFE_JS_STRING_CHAR_ESCAPES[char.charCodeAt(0)],\n )\n}\n\n/**\n * Stringify a resolved path into a JavaScript string literal that is safe to\n * embed in generated source: `JSON.stringify` handles quoting/standard escapes,\n * and `escapeUnsafeJsStringChars` neutralizes the characters it leaves intact.\n */\nfunction toSafeJsStringLiteral(value: string): string {\n return escapeUnsafeJsStringChars(JSON.stringify(value))\n}\n\n/**\n * Rewrite the two specifier shapes the generator emits for module entries in a\n * generated registry to absolute `file://` URLs Node can resolve in a\n * standalone process:\n *\n * 1. `@/...` path-alias imports (both `from \"@/x\"` and dynamic `import(\"@/x\")`).\n * The `@/` alias is a Next.js bundler convention; outside the bundler Node\n * treats `@/...` as a bare package specifier and throws\n * `ERR_MODULE_NOT_FOUND`. Resolved against `appRoot`.\n * 2. `../../src/...` relative imports the generator emits for `@app` local\n * modules (e.g. `from \"../../src/modules/<id>/ai-tools\"`). esbuild's\n * transform (transpile-only) leaves these untouched, so the compiled\n * `.mjs` keeps an extensionless relative specifier that resolves to a\n * `.ts` file with no compiled `.js`/`.mjs` sibling \u2014 Node ESM then throws\n * `ERR_MODULE_NOT_FOUND`. Resolved against the generated file's directory\n * (`<appRoot>/.mercato/generated`), the location the generator wrote them\n * relative to. Package-backed modules (`@open-mercato/*`) are unaffected \u2014\n * their bare specifiers resolve through `node_modules` to compiled `.js`.\n *\n * When `appLocalArtifacts` maps a shape-2 specifier to a compiled artifact, that\n * artifact wins: pointing Node at raw app TypeScript only works while the file\n * and its whole graph stay within what type stripping accepts, which app\n * modules do not (see `compileAppLocalModuleEntries`). Without a mapping both\n * shapes fall back to the same `.ts`-suffix probe. Other specifiers (bare\n * packages, sibling `./` imports) are left untouched. Exported for unit testing.\n */\nexport function rewriteGeneratedAliasImports(\n source: string,\n appRoot: string,\n appLocalArtifacts?: Map<string, string>,\n): string {\n return rewriteGeneratedAliasImportsForRuntime(source, appRoot, 'esm', appLocalArtifacts)\n}\n\nconst APP_LOCAL_STATIC_IMPORT = /from\\s+[\"']((?:\\.\\.\\/)+src\\/[^\"']+)[\"']/g\nconst APP_LOCAL_DYNAMIC_IMPORT = /import\\s*\\(\\s*[\"']((?:\\.\\.\\/)+src\\/[^\"']+)[\"']\\s*\\)/g\n\nfunction rewriteGeneratedAliasImportsForRuntime(\n source: string,\n appRoot: string,\n runtime: 'esm' | 'cjs',\n appLocalArtifacts: Map<string, string> = new Map(),\n): string {\n const generatedDir = path.join(appRoot, '.mercato', 'generated')\n const toRuntimeLiteral = (target: string): string =>\n toSafeJsStringLiteral(runtime === 'esm' ? pathToFileURL(target).href : target)\n const toResolvedLiteral = (target: string): string => {\n const candidate = fs.existsSync(target)\n ? target\n : fs.existsSync(target + '.ts')\n ? target + '.ts'\n : target\n return toRuntimeLiteral(candidate)\n }\n const resolveAlias = (relativePath: string): string =>\n toResolvedLiteral(path.join(appRoot, relativePath))\n const resolveRelative = (specifier: string): string => {\n const artifact = appLocalArtifacts.get(specifier)\n if (artifact !== undefined) return toRuntimeLiteral(artifact)\n return toResolvedLiteral(path.resolve(generatedDir, specifier))\n }\n return source\n .replace(/from\\s+[\"']@\\/([^\"']+)[\"']/g, (_match, relativePath: string) => {\n return `from ${resolveAlias(relativePath)}`\n })\n .replace(/import\\s*\\(\\s*[\"']@\\/([^\"']+)[\"']\\s*\\)/g, (_match, relativePath: string) => {\n return `import(${resolveAlias(relativePath)})`\n })\n .replace(APP_LOCAL_STATIC_IMPORT, (_match, specifier: string) => {\n return `from ${resolveRelative(specifier)}`\n })\n .replace(APP_LOCAL_DYNAMIC_IMPORT, (_match, specifier: string) => {\n return `import(${resolveRelative(specifier)})`\n })\n}\n\n/**\n * Compile-and-import `api-routes.generated.ts` and register its manifest with\n * the shared registry. Many module tools are \"API-backed\" \u2014 their handlers\n * delegate to `createAiApiOperationRunner`, which fails closed with\n * \"No API route manifest registered\" unless the manifest is present. In the\n * Next.js app this is wired at bootstrap, but the standalone MCP servers\n * (`mcp:dev` / `mcp:serve`) bootstrap DI without it, so we register it here.\n *\n * Idempotent: `registerApiRouteManifests` replaces the stored manifest, so\n * calling this repeatedly (e.g. per-request HTTP handlers) is safe. Returns the\n * number of registered routes (0 when the generated file is absent).\n */\nexport async function ensureApiRouteManifestsRegistered(): Promise<number> {\n const registry = await import('@open-mercato/shared/modules/registry')\n // Already wired (e.g. the Next.js app bootstrap, or a prior call). Leave the\n // existing manifest untouched so we never interfere with the in-app agents\n // framework, which registers it at bootstrap with its own override pipeline.\n const existing = registry.getApiRouteManifests()\n if (existing.length > 0) return existing.length\n\n const tsPath = findGeneratedFile('api-routes.generated.ts')\n if (!tsPath) return 0\n try {\n const mod = await compileAndImportGenerated(tsPath)\n const apiRoutes = (mod as { apiRoutes?: unknown }).apiRoutes\n if (!Array.isArray(apiRoutes)) return 0\n registry.registerApiRouteManifests(\n apiRoutes as Parameters<typeof registry.registerApiRouteManifests>[0],\n )\n return apiRoutes.length\n } catch (error) {\n logger.warn('Could not register api-routes manifest', { err: error })\n return 0\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/ai-assistant",
|
|
3
|
-
"version": "0.6.8-develop.
|
|
3
|
+
"version": "0.6.8-develop.7090.1.4dbca7b350",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -99,16 +99,16 @@
|
|
|
99
99
|
"zod-to-json-schema": "^3.25.2"
|
|
100
100
|
},
|
|
101
101
|
"peerDependencies": {
|
|
102
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
103
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
102
|
+
"@open-mercato/shared": "0.6.8-develop.7090.1.4dbca7b350",
|
|
103
|
+
"@open-mercato/ui": "0.6.8-develop.7090.1.4dbca7b350",
|
|
104
104
|
"react": "^19.0.0",
|
|
105
105
|
"react-dom": "^19.0.0",
|
|
106
106
|
"zod": ">=3.23.0"
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
|
-
"@open-mercato/cli": "0.6.8-develop.
|
|
110
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
111
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
109
|
+
"@open-mercato/cli": "0.6.8-develop.7090.1.4dbca7b350",
|
|
110
|
+
"@open-mercato/shared": "0.6.8-develop.7090.1.4dbca7b350",
|
|
111
|
+
"@open-mercato/ui": "0.6.8-develop.7090.1.4dbca7b350",
|
|
112
112
|
"@types/react": "^19.2.17",
|
|
113
113
|
"@types/react-dom": "^19.2.3",
|
|
114
114
|
"react": "19.2.8",
|
|
@@ -36,6 +36,22 @@ function safeJsLiteral(value: string): string {
|
|
|
36
36
|
return escapeUnsafeJsStringChars(JSON.stringify(value))
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
describe('Next.js bundle boundary', () => {
|
|
40
|
+
it('keeps runtime-only imports out of the Next.js bundle', () => {
|
|
41
|
+
const loaderSource = fs.readFileSync(
|
|
42
|
+
path.join(__dirname, '..', 'generated-registry-loader.ts'),
|
|
43
|
+
'utf8',
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
expect(loaderSource).toMatch(
|
|
47
|
+
/await import\(\s*\/\* webpackIgnore: true \*\/\s*\/\* turbopackIgnore: true \*\/\s*pathToFileURL\(jsPath\)\.href\s*\)/,
|
|
48
|
+
)
|
|
49
|
+
expect(loaderSource).toMatch(
|
|
50
|
+
/await import\(\s*\/\* webpackIgnore: true \*\/\s*\/\* turbopackIgnore: true \*\/\s*'@open-mercato\/shared\/lib\/bootstrap\/dynamicLoader'\s*\)/,
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
39
55
|
describe('rewriteGeneratedAliasImports', () => {
|
|
40
56
|
// Regression for the MCP dev-server crash:
|
|
41
57
|
// "Cannot find package '@/.mercato' imported from .../tool-loader.js"
|
|
@@ -121,7 +121,11 @@ export async function compileAndImportGenerated(tsPath: string): Promise<Record<
|
|
|
121
121
|
if (useJestCjsArtifact) {
|
|
122
122
|
return requireFromHere(jsPath) as Record<string, unknown>
|
|
123
123
|
}
|
|
124
|
-
return (await import(
|
|
124
|
+
return (await import(
|
|
125
|
+
/* webpackIgnore: true */
|
|
126
|
+
/* turbopackIgnore: true */
|
|
127
|
+
pathToFileURL(jsPath).href
|
|
128
|
+
)) as Record<string, unknown>
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
function isJestRuntime(): boolean {
|
|
@@ -169,7 +173,11 @@ async function compileAppLocalModuleEntries(
|
|
|
169
173
|
if (specifiers.length === 0) return artifacts
|
|
170
174
|
|
|
171
175
|
const generatedDir = path.join(appRoot, '.mercato', 'generated')
|
|
172
|
-
const { compileAppSourceFile } = await import(
|
|
176
|
+
const { compileAppSourceFile } = await import(
|
|
177
|
+
/* webpackIgnore: true */
|
|
178
|
+
/* turbopackIgnore: true */
|
|
179
|
+
'@open-mercato/shared/lib/bootstrap/dynamicLoader'
|
|
180
|
+
)
|
|
173
181
|
|
|
174
182
|
for (const specifier of specifiers) {
|
|
175
183
|
const target = path.resolve(generatedDir, specifier)
|