veryfront 0.1.644 → 0.1.646

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.
Files changed (65) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/agent/factory.js +7 -7
  3. package/esm/src/agent/hosted/chat-preparation.d.ts +4 -1
  4. package/esm/src/agent/hosted/chat-preparation.d.ts.map +1 -1
  5. package/esm/src/agent/hosted/chat-preparation.js +8 -0
  6. package/esm/src/agent/hosted/chat-runtime-tool-assembly.d.ts +1 -0
  7. package/esm/src/agent/hosted/chat-runtime-tool-assembly.d.ts.map +1 -1
  8. package/esm/src/agent/hosted/chat-runtime-tool-assembly.js +4 -1
  9. package/esm/src/agent/hosted/default-chat-runtime.d.ts.map +1 -1
  10. package/esm/src/agent/hosted/default-chat-runtime.js +5 -3
  11. package/esm/src/agent/hosted/project-remote-tool-source.d.ts.map +1 -1
  12. package/esm/src/agent/hosted/project-remote-tool-source.js +25 -1
  13. package/esm/src/agent/hosted/veryfront-cloud-agent-service.d.ts +5 -4
  14. package/esm/src/agent/hosted/veryfront-cloud-agent-service.d.ts.map +1 -1
  15. package/esm/src/agent/hosted/veryfront-cloud-agent-service.js +7 -6
  16. package/esm/src/agent/index.d.ts +2 -2
  17. package/esm/src/agent/index.d.ts.map +1 -1
  18. package/esm/src/agent/index.js +1 -1
  19. package/esm/src/agent/runtime/index.d.ts +1 -1
  20. package/esm/src/agent/runtime/index.d.ts.map +1 -1
  21. package/esm/src/agent/runtime/index.js +25 -20
  22. package/esm/src/agent/runtime/mcp-server-tool-sources.d.ts +9 -0
  23. package/esm/src/agent/runtime/mcp-server-tool-sources.d.ts.map +1 -0
  24. package/esm/src/agent/runtime/mcp-server-tool-sources.js +59 -0
  25. package/esm/src/agent/runtime/message-preparation.d.ts +1 -0
  26. package/esm/src/agent/runtime/message-preparation.d.ts.map +1 -1
  27. package/esm/src/agent/runtime/message-preparation.js +3 -1
  28. package/esm/src/agent/runtime/model-tool-converter.d.ts +1 -1
  29. package/esm/src/agent/runtime/model-tool-converter.d.ts.map +1 -1
  30. package/esm/src/agent/runtime/model-tool-converter.js +1 -1
  31. package/esm/src/agent/service/mcp-server-config.d.ts +4 -0
  32. package/esm/src/agent/service/mcp-server-config.d.ts.map +1 -1
  33. package/esm/src/agent/streaming/fork-runtime-stream.js +1 -1
  34. package/esm/src/agent/types.d.ts +44 -5
  35. package/esm/src/agent/types.d.ts.map +1 -1
  36. package/esm/src/chat/message-prep.d.ts +5 -1
  37. package/esm/src/chat/message-prep.d.ts.map +1 -1
  38. package/esm/src/chat/message-prep.js +55 -2
  39. package/esm/src/discovery/transpiler.d.ts.map +1 -1
  40. package/esm/src/discovery/transpiler.js +3 -1
  41. package/esm/src/internal-agents/run-stream.d.ts.map +1 -1
  42. package/esm/src/internal-agents/run-stream.js +2 -2
  43. package/esm/src/react/components/chat/chat/components/skill-badge.d.ts +1 -1
  44. package/esm/src/react/components/chat/chat/components/skill-badge.js +3 -3
  45. package/esm/src/react/components/chat/chat/utils/message-parts.d.ts +1 -1
  46. package/esm/src/react/components/chat/chat/utils/message-parts.d.ts.map +1 -1
  47. package/esm/src/react/components/chat/chat/utils/message-parts.js +4 -4
  48. package/esm/src/rendering/orchestrator/module-loader/index.d.ts +7 -0
  49. package/esm/src/rendering/orchestrator/module-loader/index.d.ts.map +1 -1
  50. package/esm/src/rendering/orchestrator/module-loader/index.js +33 -1
  51. package/esm/src/server/handlers/dev/framework-candidates.generated.js +7 -7
  52. package/esm/src/server/handlers/request/agent-stream.handler.d.ts.map +1 -1
  53. package/esm/src/server/handlers/request/agent-stream.handler.js +35 -10
  54. package/esm/src/skill/prompt-augmentation.d.ts +1 -1
  55. package/esm/src/skill/prompt-augmentation.js +5 -5
  56. package/esm/src/skill/tools.d.ts +6 -6
  57. package/esm/src/skill/tools.js +13 -13
  58. package/esm/src/skill/types.d.ts +1 -1
  59. package/esm/src/skill/types.js +3 -3
  60. package/esm/src/transforms/mdx/esm-module-loader/cache/index.d.ts +23 -0
  61. package/esm/src/transforms/mdx/esm-module-loader/cache/index.d.ts.map +1 -1
  62. package/esm/src/transforms/mdx/esm-module-loader/cache/index.js +85 -2
  63. package/esm/src/utils/version-constant.d.ts +1 -1
  64. package/esm/src/utils/version-constant.js +1 -1
  65. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"message-parts.d.ts","sourceRoot":"","sources":["../../../../../../../src/src/react/components/chat/chat/utils/message-parts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,YAAY,EACb,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAQ3D;AAED,qCAAqC;AACrC,wBAAgB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,IAAI,YAAY,GAAG,mBAAmB,CAG5F;AAQD,4GAA4G;AAC5G,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB,GAAG,OAAO,CAEjF;AAED,0CAA0C;AAC1C,wBAAgB,eAAe,CAC7B,IAAI,EAAE,eAAe,GACpB,IAAI,IAAI;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;CAAE,CAE3E;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE,CAkDvE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAiC1E"}
1
+ {"version":3,"file":"message-parts.d.ts","sourceRoot":"","sources":["../../../../../../../src/src/react/components/chat/chat/utils/message-parts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,YAAY,EACb,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAQ3D;AAED,qCAAqC;AACrC,wBAAgB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,IAAI,YAAY,GAAG,mBAAmB,CAG5F;AAQD,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB,GAAG,OAAO,CAEjF;AAED,0CAA0C;AAC1C,wBAAgB,eAAe,CAC7B,IAAI,EAAE,eAAe,GACpB,IAAI,IAAI;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;CAAE,CAE3E;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE,CAkDvE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAiC1E"}
@@ -18,11 +18,11 @@ export function isToolPart(part) {
18
18
  return part.type.startsWith("tool-") && part.type !== "tool-result";
19
19
  }
20
20
  const SKILL_TOOL_NAMES = new Set([
21
- "load-skill",
22
- "load-skill-reference",
23
- "execute-skill-script",
21
+ "load_skill",
22
+ "load_skill_reference",
23
+ "execute_skill_script",
24
24
  ]);
25
- /** Check if a tool part is a skill-related tool (load-skill, load-skill-reference, execute-skill-script) */
25
+ /** Check if a tool part is a skill-related tool. */
26
26
  export function isSkillToolPart(tool) {
27
27
  return SKILL_TOOL_NAMES.has(tool.toolName);
28
28
  }
@@ -21,6 +21,13 @@ export interface ModuleLoaderConfig {
21
21
  /** React version for transforms (from project config) */
22
22
  reactVersion?: string;
23
23
  }
24
+ /**
25
+ * Detect a dynamic `import()` failure caused by a module file that is missing on
26
+ * disk (e.g. a stale/evicted cached page module). Matches Node/Deno's
27
+ * `ERR_MODULE_NOT_FOUND` as well as the "Cannot find module" / "Module not found"
28
+ * message variants the runtimes surface for a missing `import()` target.
29
+ */
30
+ export declare function isMissingModuleError(error: unknown): boolean;
24
31
  /**
25
32
  * Load a module by path, transforming it and its dependencies.
26
33
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA2BzE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAkJpE,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,eAAe,UAAQ,GACtB,OAAO,CAAC,MAAM,CAAC,CAsSjB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAqClC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA4BzE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAkJpE,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,eAAe,UAAQ,GACtB,OAAO,CAAC,MAAM,CAAC,CAsSjB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI5D;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA6DlC"}
@@ -18,7 +18,7 @@ import { validateCachedBundlesByManifestOrCode } from "../../../transforms/esm/c
18
18
  import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../utils/cache-dir.js";
19
19
  import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
20
20
  import { hashCodeHex } from "../../../utils/hash-utils.js";
21
- import { getModulePathCache, lookupMdxEsmCache, saveModulePathCache, } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
21
+ import { getModulePathCache, invalidateMdxEsmModule, lookupMdxEsmCache, saveModulePathCache, } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
22
22
  import { buildMdxEsmPathCacheKey } from "../../../transforms/mdx/esm-module-loader/cache-format.js";
23
23
  const logger = rendererLogger.component("module-loader");
24
24
  // Re-export utilities
@@ -363,6 +363,19 @@ async function getModuleCacheDir(config) {
363
363
  }
364
364
  return getProjectTmpDir(projectId ?? projectDir);
365
365
  }
366
+ /**
367
+ * Detect a dynamic `import()` failure caused by a module file that is missing on
368
+ * disk (e.g. a stale/evicted cached page module). Matches Node/Deno's
369
+ * `ERR_MODULE_NOT_FOUND` as well as the "Cannot find module" / "Module not found"
370
+ * message variants the runtimes surface for a missing `import()` target.
371
+ */
372
+ export function isMissingModuleError(error) {
373
+ if (!(error instanceof Error))
374
+ return false;
375
+ if (error.code === "ERR_MODULE_NOT_FOUND")
376
+ return true;
377
+ return /cannot find module|module not found/i.test(error.message);
378
+ }
366
379
  /**
367
380
  * Load a module by path, transforming it and its dependencies.
368
381
  *
@@ -395,6 +408,25 @@ export async function loadModule(filePath, config) {
395
408
  return await import(`file://${tempFilePath}?t=${Date.now()}&retry=1`);
396
409
  }
397
410
  }
411
+ // Self-heal: the cached module artifact resolved to a path that no longer
412
+ // exists on disk (evicted, or rebuilt under a different content hash by a
413
+ // racing write). Rather than hard-failing the whole page render (#2077),
414
+ // treat it as a cache miss: drop the stale cache pointers so we don't get
415
+ // handed the same dead path, rebuild the module from source, and retry the
416
+ // import once. Skip HTTP-bundle misses, which have dedicated recovery above.
417
+ if (!bundleMatch && isMissingModuleError(error)) {
418
+ logger.warn("Cached module missing on disk, rebuilding and retrying import", {
419
+ filePath,
420
+ tempFilePath,
421
+ });
422
+ config.moduleCache.delete(getModuleCacheKey(filePath, config.projectId, config.projectDir, config.contentSourceId));
423
+ // tmpDir is the exact cache dir this module was registered under, so the
424
+ // invalidation stays scoped to this tenant (the path-cache key is not
425
+ // project-scoped — see invalidateMdxEsmModule).
426
+ invalidateMdxEsmModule(tmpDir, filePath, config.projectDir, config.reactVersion);
427
+ const rebuiltPath = await transformModuleWithDeps(filePath, tmpDir, localAdapter, config);
428
+ return await import(`file://${rebuiltPath}?t=${Date.now()}&rebuilt=1`);
429
+ }
398
430
  logger.error("Failed to import module:", {
399
431
  filePath,
400
432
  tempFilePath,
@@ -2934,9 +2934,8 @@ export const FRAMEWORK_CANDIDATES = [
2934
2934
  "etc.,",
2935
2935
  "event:",
2936
2936
  "event?.preventDefault()}",
2937
- "execute-skill-script",
2938
- "execute-skill-script)",
2939
- "execute-skill-script).",
2937
+ "execute_skill_script",
2938
+ "execute_skill_script).",
2940
2939
  "exist",
2941
2940
  "expected:",
2942
2941
  "export",
@@ -3607,16 +3606,16 @@ export const FRAMEWORK_CANDIDATES = [
3607
3606
  "listboxId",
3608
3607
  "load():",
3609
3608
  "load();",
3610
- "load-skill",
3611
- "load-skill,",
3612
- "load-skill-reference",
3613
- "load-skill-reference,",
3614
3609
  "loadIndex(key:",
3615
3610
  "loadIndex(storageKey);",
3616
3611
  "loadMermaid():",
3617
3612
  "loadMermaid();",
3618
3613
  "loadThread(key:",
3619
3614
  "loadThread(storageKey,",
3615
+ "load_skill",
3616
+ "load_skill,",
3617
+ "load_skill_reference",
3618
+ "load_skill_reference,",
3620
3619
  "loaded.length",
3621
3620
  "loaded.push(thread);",
3622
3621
  "loaded.sort((a,",
@@ -5338,6 +5337,7 @@ export const FRAMEWORK_CANDIDATES = [
5338
5337
  "tool-primitives.tsx",
5339
5338
  "tool-result",
5340
5339
  "tool-search",
5340
+ "tool.",
5341
5341
  "tool.error",
5342
5342
  "tool.errorText}",
5343
5343
  "tool.error}",
@@ -1 +1 @@
1
- {"version":3,"file":"agent-stream.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/agent-stream.handler.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,4BAA4B,EAE7B,MAAM,2CAA2C,CAAC;AAwBnD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAUnG,MAAM,WAAW,sBACf,SAAQ,yBAAyB,EAAE,+BAA+B;IAClE,4BAA4B,CAAC,EAAE,OAAO,4BAA4B,CAAC;CACpE;AAyQD,qBAAa,kBAAmB,SAAQ,WAAW;IASrC,OAAO,CAAC,QAAQ,CAAC,IAAI;IARjC,QAAQ,EAAE,eAAe,CAMvB;gBAE2B,IAAI,GAAE,sBAAoC;IAIvE,OAAO,CAAC,sBAAsB;IAwBxB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAiKxE"}
1
+ {"version":3,"file":"agent-stream.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/agent-stream.handler.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EACL,4BAA4B,EAE7B,MAAM,2CAA2C,CAAC;AAwBnD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAUnG,MAAM,WAAW,sBACf,SAAQ,yBAAyB,EAAE,+BAA+B;IAClE,4BAA4B,CAAC,EAAE,OAAO,4BAA4B,CAAC;CACpE;AA2SD,qBAAa,kBAAmB,SAAQ,WAAW;IASrC,OAAO,CAAC,QAAQ,CAAC,IAAI;IARjC,QAAQ,EAAE,eAAe,CAMvB;gBAE2B,IAAI,GAAE,sBAAoC;IAIvE,OAAO,CAAC,sBAAsB;IAwBxB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAiKxE"}
@@ -73,6 +73,28 @@ function mergeAllowedRemoteTools(current, requestedToolNames) {
73
73
  }
74
74
  return [...allowed].sort();
75
75
  }
76
+ function getVeryfrontApiMcpPolicy(agent) {
77
+ const requestedToolNames = new Set();
78
+ const deniedToolNames = new Set();
79
+ let allowAll = false;
80
+ for (const server of agent.config.mcpServers ?? []) {
81
+ if (!("kind" in server) || server.kind !== "veryfront-api") {
82
+ continue;
83
+ }
84
+ for (const toolName of server.toolPolicy?.deny ?? []) {
85
+ deniedToolNames.add(toolName);
86
+ }
87
+ if (server.toolPolicy?.allow) {
88
+ for (const toolName of server.toolPolicy.allow) {
89
+ requestedToolNames.add(toolName);
90
+ }
91
+ }
92
+ else {
93
+ allowAll = true;
94
+ }
95
+ }
96
+ return { allowAll, requestedToolNames: [...requestedToolNames], deniedToolNames };
97
+ }
76
98
  function hasVeryfrontPlatformRemoteToolSource(remoteTools) {
77
99
  return remoteTools?.some((source) => source.id === VERYFRONT_PLATFORM_REMOTE_TOOL_SOURCE_ID) ??
78
100
  false;
@@ -85,11 +107,12 @@ function createStaticRemoteToolSource(source, toolDefinitions) {
85
107
  };
86
108
  }
87
109
  async function withVeryfrontPlatformRemoteTools(input) {
110
+ const veryfrontApiMcpPolicy = getVeryfrontApiMcpPolicy(input.agent);
88
111
  const requestedToolNames = getRequestedUnresolvedBooleanToolNames({
89
112
  agent: input.agent,
90
113
  availableToolNames: input.availableToolNames,
91
- });
92
- if (requestedToolNames.length === 0 || !input.token) {
114
+ }).concat(veryfrontApiMcpPolicy.requestedToolNames);
115
+ if ((!veryfrontApiMcpPolicy.allowAll && requestedToolNames.length === 0) || !input.token) {
93
116
  return input.agent;
94
117
  }
95
118
  const apiUrl = getHostEnv("VERYFRONT_API_URL") ?? "https://api.veryfront.com";
@@ -114,24 +137,26 @@ async function withVeryfrontPlatformRemoteTools(input) {
114
137
  ? new Set(platformToolDefinitions.map((tool) => tool.name))
115
138
  : null;
116
139
  const requestedPlatformToolNames = platformToolNames
117
- ? requestedToolNames.filter((toolName) => platformToolNames.has(toolName))
118
- : requestedToolNames;
140
+ ? (veryfrontApiMcpPolicy.allowAll ? [...platformToolNames] : requestedToolNames).filter((toolName) => platformToolNames.has(toolName) && !veryfrontApiMcpPolicy.deniedToolNames.has(toolName))
141
+ : requestedToolNames.filter((toolName) => !veryfrontApiMcpPolicy.deniedToolNames.has(toolName));
119
142
  if (requestedPlatformToolNames.length === 0) {
120
143
  return input.agent;
121
144
  }
122
- const remoteTools = input.agent.config.remoteTools ?? [];
145
+ const runtimeRemoteToolConfig = input.agent.config;
146
+ const remoteTools = runtimeRemoteToolConfig.__vfRemoteToolSources ?? [];
123
147
  const platformRemoteToolSources = hasVeryfrontPlatformRemoteToolSource(remoteTools) ? [] : [
124
148
  platformToolDefinitions
125
149
  ? createStaticRemoteToolSource(platformRemoteToolSource, platformToolDefinitions)
126
150
  : platformRemoteToolSource,
127
151
  ];
152
+ const runtimeConfig = {
153
+ ...input.agent.config,
154
+ __vfAllowedRemoteTools: mergeAllowedRemoteTools(runtimeRemoteToolConfig.__vfAllowedRemoteTools, requestedPlatformToolNames),
155
+ __vfRemoteToolSources: [...remoteTools, ...platformRemoteToolSources],
156
+ };
128
157
  return {
129
158
  ...input.agent,
130
- config: {
131
- ...input.agent.config,
132
- allowedRemoteTools: mergeAllowedRemoteTools(input.agent.config.allowedRemoteTools, requestedPlatformToolNames),
133
- remoteTools: [...remoteTools, ...platformRemoteToolSources],
134
- },
159
+ config: runtimeConfig,
135
160
  };
136
161
  }
137
162
  function buildAgentStreamEnv(input) {
@@ -10,7 +10,7 @@ import type { Skill } from "./types.js";
10
10
  * Build the skill manifest prompt section for an agent's system prompt.
11
11
  *
12
12
  * Lists all available skills with their descriptions and instructions
13
- * on how to use the skill tools (load-skill, load-skill-reference, execute-skill-script).
13
+ * on how to use the skill tools (load_skill, load_skill_reference, execute_skill_script).
14
14
  *
15
15
  * @param skills - Map of resolved skills for the agent
16
16
  * @returns Prompt section string, or empty string if no skills
@@ -9,7 +9,7 @@
9
9
  * Build the skill manifest prompt section for an agent's system prompt.
10
10
  *
11
11
  * Lists all available skills with their descriptions and instructions
12
- * on how to use the skill tools (load-skill, load-skill-reference, execute-skill-script).
12
+ * on how to use the skill tools (load_skill, load_skill_reference, execute_skill_script).
13
13
  *
14
14
  * @param skills - Map of resolved skills for the agent
15
15
  * @returns Prompt section string, or empty string if no skills
@@ -20,7 +20,7 @@ export function buildSkillManifestPrompt(skills) {
20
20
  const lines = [
21
21
  "## Available Skills",
22
22
  "",
23
- "You have access to skills via tool calling. IMPORTANT: You MUST call the load-skill tool (not write it as text) to activate a skill before performing skill-related tasks.",
23
+ "You have access to skills via tool calling. IMPORTANT: You MUST call the load_skill tool (not write it as text) to activate a skill before performing skill-related tasks.",
24
24
  "",
25
25
  ];
26
26
  for (const [id, skill] of skills) {
@@ -29,8 +29,8 @@ export function buildSkillManifestPrompt(skills) {
29
29
  lines.push("");
30
30
  lines.push("### Skill Tools (call these as tools, never write them as text)");
31
31
  lines.push("");
32
- lines.push("- load-skill: Call with { skillId } to load a skill's full instructions and available references/resources/scripts");
33
- lines.push("- load-skill-reference: Call with { skillId, reference } to read a file from the skill's references/, resources/, or assets/ directory");
34
- lines.push("- execute-skill-script: Call with { skillId, script, args?, env?, timeoutMs? } to execute a script");
32
+ lines.push("- load_skill: Call with { skillId } to load a skill's full instructions and available references/resources/scripts");
33
+ lines.push("- load_skill_reference: Call with { skillId, reference } to read a file from the skill's references/, resources/, or assets/ directory");
34
+ lines.push("- execute_skill_script: Call with { skillId, script, args?, env?, timeoutMs? } to execute a script");
35
35
  return lines.join("\n");
36
36
  }
@@ -2,25 +2,25 @@
2
2
  * Skill Tools
3
3
  *
4
4
  * Three tools exposed to agents for interacting with skills:
5
- * - load-skill: Load a skill's full instructions
6
- * - load-skill-reference: Read a reference file from a skill
7
- * - execute-skill-script: Execute a script from a skill
5
+ * - load_skill: Load a skill's full instructions
6
+ * - load_skill_reference: Read a reference file from a skill
7
+ * - execute_skill_script: Execute a script from a skill
8
8
  *
9
9
  * @module
10
10
  */
11
11
  import type { Tool } from "../tool/index.js";
12
12
  /**
13
- * Create the load-skill tool.
13
+ * Create the load_skill tool.
14
14
  * Loads a skill's full instructions, available references, and scripts.
15
15
  */
16
16
  export declare function createLoadSkillTool(): Tool;
17
17
  /**
18
- * Create the load-skill-reference tool.
18
+ * Create the load_skill_reference tool.
19
19
  * Reads a reference file from a skill's references/, resources/, or assets/ directory.
20
20
  */
21
21
  export declare function createLoadSkillReferenceTool(): Tool;
22
22
  /**
23
- * Create the execute-skill-script tool.
23
+ * Create the execute_skill_script tool.
24
24
  * Executes a script from a skill's scripts/ directory.
25
25
  */
26
26
  export declare function createExecuteSkillScriptTool(): Tool;
@@ -2,9 +2,9 @@
2
2
  * Skill Tools
3
3
  *
4
4
  * Three tools exposed to agents for interacting with skills:
5
- * - load-skill: Load a skill's full instructions
6
- * - load-skill-reference: Read a reference file from a skill
7
- * - execute-skill-script: Execute a script from a skill
5
+ * - load_skill: Load a skill's full instructions
6
+ * - load_skill_reference: Read a reference file from a skill
7
+ * - execute_skill_script: Execute a script from a skill
8
8
  *
9
9
  * @module
10
10
  */
@@ -52,23 +52,23 @@ async function readSkillFile(skill, path) {
52
52
  }
53
53
  function buildSkillAvailabilityNote(references, scripts) {
54
54
  if (scripts.length === 0 && references.length === 0) {
55
- return "This skill has no scripts or reference files. Do NOT call execute-skill-script or load-skill-reference.";
55
+ return "This skill has no scripts or reference files. Do NOT call execute_skill_script or load_skill_reference.";
56
56
  }
57
57
  if (scripts.length === 0) {
58
- return "This skill has no scripts. Do NOT call execute-skill-script.";
58
+ return "This skill has no scripts. Do NOT call execute_skill_script.";
59
59
  }
60
60
  if (references.length === 0) {
61
- return "This skill has no reference files. Do NOT call load-skill-reference.";
61
+ return "This skill has no reference files. Do NOT call load_skill_reference.";
62
62
  }
63
63
  return undefined;
64
64
  }
65
65
  /**
66
- * Create the load-skill tool.
66
+ * Create the load_skill tool.
67
67
  * Loads a skill's full instructions, available references, and scripts.
68
68
  */
69
69
  export function createLoadSkillTool() {
70
70
  return tool({
71
- id: "load-skill",
71
+ id: "load_skill",
72
72
  description: "Load a skill's full instructions. Returns the skill's markdown instructions, " +
73
73
  "allowed tools policy, and lists of available reference files and scripts.",
74
74
  inputSchema: getLoadSkillInputSchema(),
@@ -86,7 +86,7 @@ export function createLoadSkillTool() {
86
86
  const content = await readSkillFile(skill, skillMdPath);
87
87
  // Parse frontmatter to get instructions
88
88
  const parsed = await parseSkillFrontmatter(content);
89
- // List available files the agent can load through load-skill-reference.
89
+ // List available files the agent can load through load_skill_reference.
90
90
  const [references, resources, scripts] = await Promise.all([
91
91
  listSkillSubdir(skill.rootPath, SKILL_REFERENCES_DIR, skill.fsAdapter),
92
92
  listSkillSubdir(skill.rootPath, SKILL_RESOURCES_DIR, skill.fsAdapter),
@@ -105,12 +105,12 @@ export function createLoadSkillTool() {
105
105
  });
106
106
  }
107
107
  /**
108
- * Create the load-skill-reference tool.
108
+ * Create the load_skill_reference tool.
109
109
  * Reads a reference file from a skill's references/, resources/, or assets/ directory.
110
110
  */
111
111
  export function createLoadSkillReferenceTool() {
112
112
  return tool({
113
- id: "load-skill-reference",
113
+ id: "load_skill_reference",
114
114
  description: "Read a reference file from a skill. Only files in the skill's " +
115
115
  "references/, resources/, and assets/ directories are accessible.",
116
116
  inputSchema: getLoadSkillReferenceInputSchema(),
@@ -130,12 +130,12 @@ export function createLoadSkillReferenceTool() {
130
130
  });
131
131
  }
132
132
  /**
133
- * Create the execute-skill-script tool.
133
+ * Create the execute_skill_script tool.
134
134
  * Executes a script from a skill's scripts/ directory.
135
135
  */
136
136
  export function createExecuteSkillScriptTool() {
137
137
  return tool({
138
- id: "execute-skill-script",
138
+ id: "execute_skill_script",
139
139
  description: "Execute a script from a skill's scripts/ directory. Returns stdout, stderr, and exit code.",
140
140
  inputSchema: getExecuteSkillScriptInputSchema(),
141
141
  execute: async (input) => {
@@ -37,7 +37,7 @@ export interface SkillMetadata {
37
37
  /** Arbitrary key-value metadata */
38
38
  metadata?: Record<string, string>;
39
39
  }
40
- /** Full skill content returned by load-skill tool */
40
+ /** Full skill content returned by load_skill tool */
41
41
  export interface SkillContent {
42
42
  /** Markdown instructions (body after frontmatter) */
43
43
  instructions: string;
@@ -17,9 +17,9 @@ export const SKILL_DESCRIPTION_MAX_LENGTH = 1024;
17
17
  export const SKILL_MD_FILENAME = "SKILL.md";
18
18
  /** Tool IDs that belong to the skill system (single source of truth) */
19
19
  export const SKILL_TOOL_IDS = new Set([
20
- "load-skill",
21
- "load-skill-reference",
22
- "execute-skill-script",
20
+ "load_skill",
21
+ "load_skill_reference",
22
+ "execute_skill_script",
23
23
  ]);
24
24
  /** Conventional subdirectory names */
25
25
  export const SKILL_SCRIPTS_DIR = "scripts";
@@ -24,6 +24,29 @@ export declare function clearModulePathCache(): void;
24
24
  /** Await any in-flight disk cleanup (for testing only). */
25
25
  export declare function waitForDiskCleanup(): Promise<void>;
26
26
  export declare function invalidateModulePaths(changedPaths: string[]): void;
27
+ /**
28
+ * Invalidate the cached module path for a single source file in a single cache dir.
29
+ *
30
+ * Unlike {@link invalidateModulePaths} (driven by the file watcher on source
31
+ * edits, which also deletes the stale `.mjs` from disk), this is a targeted,
32
+ * synchronous self-heal for the case where a cached module artifact has already
33
+ * gone missing on disk — evicted, or rebuilt under a different content hash by a
34
+ * racing write — while the in-memory path cache and its verified-deps fast-path
35
+ * still point at the stale path. Clearing both forces the next
36
+ * {@link lookupMdxEsmCache} to report a miss so the module is rebuilt instead of
37
+ * handing back a path whose `import()` fails with ERR_MODULE_NOT_FOUND (#2077).
38
+ *
39
+ * `cacheDir` MUST be the dir that produced the missing path. The path-cache key
40
+ * is scoped only by React version + relative module path (not project/source),
41
+ * so two tenants that both have e.g. `app/page.tsx` share the same key in their
42
+ * separate cache dirs — scanning every dir would evict another tenant's valid
43
+ * entry, so the invalidation is confined to the failing dir.
44
+ *
45
+ * The deletion is also persisted to `_index.json` (fire-and-forget, chained onto
46
+ * the shared disk-cleanup queue like {@link invalidateModulePaths}) so the stale
47
+ * pointer does not resurrect from disk on the next process start.
48
+ */
49
+ export declare function invalidateMdxEsmModule(cacheDir: string, filePath: string, projectDir?: string, reactVersion?: string): void;
27
50
  export declare function clearESMDiskCache(): Promise<void>;
28
51
  export declare function clearHttpBundleCache(): Promise<void>;
29
52
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAI5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAI9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;AA2HH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBvF;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAezE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAQD,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CA0ElE;AAOD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAevD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAmBD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EAAE,oDAAoD;AAC3E,eAAe,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,EAChE,YAAY,SAAwB,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAwH5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAI5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAI9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;AA2HH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBvF;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAezE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAQD,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAuBD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CA0ElE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,SAAwB,GACnC,IAAI,CAgBN;AAOD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAevD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAmBD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EAAE,oDAAoD;AAC3E,eAAe,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,EAChE,YAAY,SAAwB,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAmJ5B"}
@@ -184,6 +184,27 @@ let _pendingDiskCleanup = Promise.resolve();
184
184
  export function waitForDiskCleanup() {
185
185
  return _pendingDiskCleanup;
186
186
  }
187
+ /**
188
+ * Persist the given cache dirs' `_index.json` fire-and-forget, chained onto the
189
+ * shared disk-cleanup queue so concurrent invalidations don't clobber each
190
+ * other. Used after an in-memory eviction so the stale pointer does not
191
+ * resurrect from disk on the next process start — callers that drop an entry
192
+ * (e.g. an SSR-only path) may never re-register and re-save it themselves.
193
+ */
194
+ function queueIndexPersist(cacheDirs) {
195
+ if (cacheDirs.length === 0)
196
+ return;
197
+ const cleanup = async () => {
198
+ for (const cacheDir of cacheDirs) {
199
+ await saveModulePathCache(cacheDir);
200
+ }
201
+ };
202
+ _pendingDiskCleanup = _pendingDiskCleanup.then(cleanup, cleanup).catch((error) => {
203
+ logger.warn(`${LOG_PREFIX_MDX_LOADER} Failed to persist _index.json`, {
204
+ error: error instanceof Error ? error.message : String(error),
205
+ });
206
+ });
207
+ }
187
208
  export function invalidateModulePaths(changedPaths) {
188
209
  if (modulePathCaches.size === 0)
189
210
  return;
@@ -250,6 +271,44 @@ export function invalidateModulePaths(changedPaths) {
250
271
  });
251
272
  });
252
273
  }
274
+ /**
275
+ * Invalidate the cached module path for a single source file in a single cache dir.
276
+ *
277
+ * Unlike {@link invalidateModulePaths} (driven by the file watcher on source
278
+ * edits, which also deletes the stale `.mjs` from disk), this is a targeted,
279
+ * synchronous self-heal for the case where a cached module artifact has already
280
+ * gone missing on disk — evicted, or rebuilt under a different content hash by a
281
+ * racing write — while the in-memory path cache and its verified-deps fast-path
282
+ * still point at the stale path. Clearing both forces the next
283
+ * {@link lookupMdxEsmCache} to report a miss so the module is rebuilt instead of
284
+ * handing back a path whose `import()` fails with ERR_MODULE_NOT_FOUND (#2077).
285
+ *
286
+ * `cacheDir` MUST be the dir that produced the missing path. The path-cache key
287
+ * is scoped only by React version + relative module path (not project/source),
288
+ * so two tenants that both have e.g. `app/page.tsx` share the same key in their
289
+ * separate cache dirs — scanning every dir would evict another tenant's valid
290
+ * entry, so the invalidation is confined to the failing dir.
291
+ *
292
+ * The deletion is also persisted to `_index.json` (fire-and-forget, chained onto
293
+ * the shared disk-cleanup queue like {@link invalidateModulePaths}) so the stale
294
+ * pointer does not resurrect from disk on the next process start.
295
+ */
296
+ export function invalidateMdxEsmModule(cacheDir, filePath, projectDir, reactVersion = REACT_DEFAULT_VERSION) {
297
+ const cache = modulePathCaches.get(cacheDir);
298
+ if (!cache)
299
+ return;
300
+ const cacheKey = toMdxEsmCacheKey(filePath, projectDir, reactVersion);
301
+ const cachedPath = cache.get(cacheKey);
302
+ if (cachedPath === undefined)
303
+ return;
304
+ cache.delete(cacheKey);
305
+ verifiedModuleDeps.delete(`${cachedPath}:${cacheKey}`);
306
+ logger.debug(`${LOG_PREFIX_MDX_LOADER} Self-heal invalidated missing module`, {
307
+ filePath,
308
+ cachedPath,
309
+ });
310
+ queueIndexPersist([cacheDir]);
311
+ }
253
312
  function extractNormalizedCachedModulePath(cachedKey) {
254
313
  const normalizedPath = cachedKey.match(/(?:^|:)(_vf_modules\/[^:]+)$/)?.[1] ?? cachedKey;
255
314
  return normalizedPath.replace(/^_vf_modules\//, "").replace(/\.js$/, "");
@@ -312,8 +371,32 @@ recoveryOptions, reactVersion = REACT_DEFAULT_VERSION) {
312
371
  return { status: "miss" };
313
372
  const verifyKey = `${cachedPath}:${cacheKey}`;
314
373
  if (verifiedModuleDeps.get(verifyKey)) {
315
- logger.debug(`${LOG_PREFIX_MDX_LOADER} SSR reusing MDX-ESM cache (verified): ${filePath} -> ${cachedPath}`);
316
- return { status: "hit", path: cachedPath };
374
+ // Fast-path: skip the expensive read + content scans for already-verified
375
+ // modules, but still confirm the artifact is present on disk. A cached module
376
+ // can be evicted or rebuilt under a different content hash out from under us
377
+ // (disk-cache eviction, or a racing rebuild) without going through
378
+ // invalidateModulePaths — which is the only thing that clears this marker.
379
+ // Returning the stale path here makes the SSR loader import() a file that no
380
+ // longer exists and hard-fail the whole page render (#2077), so a single stat
381
+ // (far cheaper than the read + regex scans below) guards correctness.
382
+ try {
383
+ const stat = await getLocalFs().stat(cachedPath);
384
+ if (stat?.isFile) {
385
+ logger.debug(`${LOG_PREFIX_MDX_LOADER} SSR reusing MDX-ESM cache (verified): ${filePath} -> ${cachedPath}`);
386
+ return { status: "hit", path: cachedPath };
387
+ }
388
+ }
389
+ catch (_) {
390
+ /* expected: verified artifact was evicted/rebuilt; fall through to invalidate */
391
+ }
392
+ // Artifact is gone — drop the stale markers so the caller rebuilds it, and
393
+ // persist the deletion so it can't resurrect from _index.json on restart
394
+ // (an SSR-only caller may never re-register and re-save this entry itself).
395
+ logger.debug(`${LOG_PREFIX_MDX_LOADER} Verified MDX-ESM artifact missing on disk, invalidating`, { filePath, cachedPath });
396
+ verifiedModuleDeps.delete(verifyKey);
397
+ cache.delete(cacheKey);
398
+ queueIndexPersist([cacheDir]);
399
+ return { status: "miss" };
317
400
  }
318
401
  try {
319
402
  const stat = await getLocalFs().stat(cachedPath);
@@ -1,3 +1,3 @@
1
1
  /** Shared version value. */
2
- export declare const VERSION = "0.1.644";
2
+ export declare const VERSION = "0.1.646";
3
3
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
3
  /** Shared version value. */
4
- export const VERSION = "0.1.644";
4
+ export const VERSION = "0.1.646";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.644",
3
+ "version": "0.1.646",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",