veryfront 0.1.1098 → 0.1.1100

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 (49) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/data/helpers.d.ts +21 -0
  3. package/esm/src/data/helpers.d.ts.map +1 -1
  4. package/esm/src/data/helpers.js +35 -0
  5. package/esm/src/data/server-data-fetcher.d.ts.map +1 -1
  6. package/esm/src/data/server-data-fetcher.js +17 -3
  7. package/esm/src/data/static-data-fetcher.d.ts.map +1 -1
  8. package/esm/src/data/static-data-fetcher.js +15 -2
  9. package/esm/src/html/hydration-script-builder/templates/renderer.d.ts.map +1 -1
  10. package/esm/src/html/hydration-script-builder/templates/renderer.js +36 -2
  11. package/esm/src/internal-agents/run-stream.d.ts.map +1 -1
  12. package/esm/src/internal-agents/run-stream.js +8 -6
  13. package/esm/src/modules/server/module-server.d.ts +6 -0
  14. package/esm/src/modules/server/module-server.d.ts.map +1 -1
  15. package/esm/src/modules/server/module-server.js +15 -1
  16. package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.d.ts +2 -0
  17. package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.d.ts.map +1 -1
  18. package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.js +17 -16
  19. package/esm/src/rendering/orchestrator/module-loader/module-persistence.d.ts.map +1 -1
  20. package/esm/src/rendering/orchestrator/module-loader/module-persistence.js +39 -15
  21. package/esm/src/tool/host-tools.d.ts.map +1 -1
  22. package/esm/src/tool/host-tools.js +15 -5
  23. package/esm/src/transforms/esm/transform-utils.d.ts +12 -0
  24. package/esm/src/transforms/esm/transform-utils.d.ts.map +1 -1
  25. package/esm/src/transforms/esm/transform-utils.js +10 -0
  26. package/esm/src/transforms/import-rewriter/strategies/alias-strategy.d.ts.map +1 -1
  27. package/esm/src/transforms/import-rewriter/strategies/alias-strategy.js +3 -2
  28. package/esm/src/transforms/mdx/esm-module-loader/utils/source-spans.d.ts +11 -0
  29. package/esm/src/transforms/mdx/esm-module-loader/utils/source-spans.d.ts.map +1 -1
  30. package/esm/src/transforms/mdx/esm-module-loader/utils/source-spans.js +74 -0
  31. package/esm/src/transforms/pipeline/index.d.ts.map +1 -1
  32. package/esm/src/transforms/pipeline/index.js +3 -1
  33. package/esm/src/transforms/pipeline/stages/browser-node-builtin-imports.d.ts +33 -0
  34. package/esm/src/transforms/pipeline/stages/browser-node-builtin-imports.d.ts.map +1 -0
  35. package/esm/src/transforms/pipeline/stages/browser-node-builtin-imports.js +116 -0
  36. package/esm/src/transforms/pipeline/stages/browser-server-exports-strip.d.ts +45 -0
  37. package/esm/src/transforms/pipeline/stages/browser-server-exports-strip.d.ts.map +1 -0
  38. package/esm/src/transforms/pipeline/stages/browser-server-exports-strip.js +300 -0
  39. package/esm/src/transforms/pipeline/stages/compile.d.ts.map +1 -1
  40. package/esm/src/transforms/pipeline/stages/compile.js +2 -1
  41. package/esm/src/transforms/pipeline/stages/index.d.ts +2 -0
  42. package/esm/src/transforms/pipeline/stages/index.d.ts.map +1 -1
  43. package/esm/src/transforms/pipeline/stages/index.js +2 -0
  44. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts +11 -0
  45. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts.map +1 -1
  46. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.js +17 -0
  47. package/esm/src/utils/version-constant.d.ts +1 -1
  48. package/esm/src/utils/version-constant.js +1 -1
  49. package/package.json +5 -5
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.1098",
3
+ "version": "0.1.1100",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "minimumDependencyAge": {
@@ -3,4 +3,25 @@ import type { DataResult } from "./types.js";
3
3
  export declare function redirect(destination: string, permanent?: boolean): DataResult;
4
4
  /** Return a 404 result from a data loader. */
5
5
  export declare function notFound(): DataResult;
6
+ /**
7
+ * True when `value` is a control-flow result produced by {@link notFound} or
8
+ * {@link redirect}.
9
+ *
10
+ * These helpers are documented as return values, but `throw notFound()` reads
11
+ * naturally and is what people coming from other frameworks reach for. Thrown,
12
+ * the plain object is not an `Error`, so the SSR error handler stringified it
13
+ * to `[object Object]` and returned a 500 instead of the intended 404 or
14
+ * redirect. Recognising the shape lets a thrown result behave like a returned
15
+ * one.
16
+ */
17
+ export declare function isDataControlResult(value: unknown): value is DataResult;
18
+ /**
19
+ * Reduce a thrown control result to the shape a returned one produces.
20
+ *
21
+ * Callers apply this inside whatever wraps the data loader, not in an outer
22
+ * `catch`. A 404 is a routing decision, and a circuit breaker that sees it as a
23
+ * failure will open on the fifth legitimate one and fail every later data route
24
+ * for the project.
25
+ */
26
+ export declare function toDataControlResult(result: DataResult): DataResult;
6
27
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/src/data/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,mDAAmD;AACnD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,UAAU,CAE3E;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,IAAI,UAAU,CAErC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/src/data/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,mDAAmD;AACnD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,UAAU,CAE3E;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,IAAI,UAAU,CAErC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAUvE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAGlE"}
@@ -6,3 +6,38 @@ export function redirect(destination, permanent = false) {
6
6
  export function notFound() {
7
7
  return { notFound: true };
8
8
  }
9
+ /**
10
+ * True when `value` is a control-flow result produced by {@link notFound} or
11
+ * {@link redirect}.
12
+ *
13
+ * These helpers are documented as return values, but `throw notFound()` reads
14
+ * naturally and is what people coming from other frameworks reach for. Thrown,
15
+ * the plain object is not an `Error`, so the SSR error handler stringified it
16
+ * to `[object Object]` and returned a 500 instead of the intended 404 or
17
+ * redirect. Recognising the shape lets a thrown result behave like a returned
18
+ * one.
19
+ */
20
+ export function isDataControlResult(value) {
21
+ if (value === null || typeof value !== "object")
22
+ return false;
23
+ if (value instanceof Error)
24
+ return false;
25
+ const candidate = value;
26
+ if (candidate.notFound === true)
27
+ return true;
28
+ const destination = candidate.redirect?.destination;
29
+ return typeof destination === "string";
30
+ }
31
+ /**
32
+ * Reduce a thrown control result to the shape a returned one produces.
33
+ *
34
+ * Callers apply this inside whatever wraps the data loader, not in an outer
35
+ * `catch`. A 404 is a routing decision, and a circuit breaker that sees it as a
36
+ * failure will open on the fifth legitimate one and fail every later data route
37
+ * for the project.
38
+ */
39
+ export function toDataControlResult(result) {
40
+ if (result.redirect)
41
+ return { redirect: result.redirect };
42
+ return { notFound: true };
43
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"server-data-fetcher.d.ts","sourceRoot":"","sources":["../../../src/src/data/server-data-fetcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAaxE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,iBAAiB;IAC5B,KAAK,CACH,UAAU,EAAE,YAAY,EACxB,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,UAAU,CAAC;IA8EtB;;OAEG;YACW,aAAa;IAqE3B;;;OAGG;IACH,OAAO,CAAC,QAAQ;CAGjB"}
1
+ {"version":3,"file":"server-data-fetcher.d.ts","sourceRoot":"","sources":["../../../src/src/data/server-data-fetcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAcxE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,iBAAiB;IAC5B,KAAK,CACH,UAAU,EAAE,YAAY,EACxB,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,UAAU,CAAC;IAuFtB;;OAEG;YACW,aAAa;IAqE3B;;;OAGG;IACH,OAAO,CAAC,QAAQ;CAGjB"}
@@ -1,4 +1,5 @@
1
1
  import * as dntShim from "../../_dnt.shims.js";
2
+ import { isDataControlResult, toDataControlResult } from "./helpers.js";
2
3
  import { serverLogger } from "../utils/index.js";
3
4
  import { DATA_FETCH_TIMEOUT_MS } from "../config/defaults.js";
4
5
  import { TimeoutError, withTimeoutThrow } from "../rendering/utils/stream-utils.js";
@@ -26,9 +27,22 @@ export class ServerDataFetcher {
26
27
  return withSpan("data.fetch_server", async () => {
27
28
  const start = performance.now();
28
29
  try {
29
- const result = await circuitBreaker.execute(() => withTimeoutThrow(useIsolation
30
- ? this.fetchIsolated(options.modulePath, options.projectDir, context)
31
- : Promise.resolve(pageModule.getServerData(context)), DATA_FETCH_TIMEOUT_MS, `getServerData for ${pathname}`));
30
+ const result = await circuitBreaker.execute(async () => {
31
+ try {
32
+ return await withTimeoutThrow(useIsolation
33
+ ? this.fetchIsolated(options.modulePath, options.projectDir, context)
34
+ : Promise.resolve(pageModule.getServerData(context)), DATA_FETCH_TIMEOUT_MS, `getServerData for ${pathname}`);
35
+ }
36
+ catch (error) {
37
+ // `throw notFound()` / `throw redirect(...)`: treat a thrown
38
+ // control result exactly like a returned one. This has to happen
39
+ // inside the breaker, or five legitimate 404s on the same project
40
+ // open it and every data route after that fails fast for 30s.
41
+ if (isDataControlResult(error))
42
+ return toDataControlResult(error);
43
+ throw error;
44
+ }
45
+ });
32
46
  if (result.redirect)
33
47
  return { redirect: result.redirect };
34
48
  if (result.notFound)
@@ -1 +1 @@
1
- {"version":3,"file":"static-data-fetcher.d.ts","sourceRoot":"","sources":["../../../src/src/data/static-data-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA2DxE,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,YAAY;IAFhC,OAAO,CAAC,oBAAoB,CAAoC;gBAE5C,YAAY,EAAE,YAAY;IAExC,KAAK,CAAC,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IA4ChF,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,eAAe;YAQT,iBAAiB;YA+BjB,UAAU;YAqEV,sBAAsB;IAoEpC;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;CAIjB"}
1
+ {"version":3,"file":"static-data-fetcher.d.ts","sourceRoot":"","sources":["../../../src/src/data/static-data-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA2DxE,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,YAAY;IAFhC,OAAO,CAAC,oBAAoB,CAAoC;gBAE5C,YAAY,EAAE,YAAY;IAExC,KAAK,CAAC,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IA4ChF,OAAO,CAAC,uBAAuB;YAMjB,iBAAiB;IAuB/B,OAAO,CAAC,eAAe;YAQT,iBAAiB;YA+BjB,UAAU;YAqEV,sBAAsB;IAoEpC;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;CAIjB"}
@@ -1,3 +1,4 @@
1
+ import { isDataControlResult, toDataControlResult } from "./helpers.js";
1
2
  import { serverLogger } from "../utils/index.js";
2
3
  import { DATA_FETCH_TIMEOUT_MS } from "../config/defaults.js";
3
4
  import { TimeoutError, withTimeoutThrow } from "../rendering/utils/stream-utils.js";
@@ -78,8 +79,20 @@ export class StaticDataFetcher {
78
79
  createStaticDataContext(context) {
79
80
  return { params: context.params, url: context.url };
80
81
  }
81
- executeStaticData(getStaticData, context, timeoutMs, label) {
82
- return withTimeoutThrow(Promise.resolve(getStaticData(this.createStaticDataContext(context))), timeoutMs, label);
82
+ async executeStaticData(getStaticData, context, timeoutMs, label) {
83
+ try {
84
+ return await withTimeoutThrow(Promise.resolve(getStaticData(this.createStaticDataContext(context))), timeoutMs, label);
85
+ }
86
+ catch (error) {
87
+ // `throw notFound()` / `throw redirect(...)`: treat a thrown control
88
+ // result exactly like a returned one. Normalising at the one place every
89
+ // path runs the handler covers the cached path as well as the preview
90
+ // one, and keeps a 404 from counting against the caller's circuit
91
+ // breaker.
92
+ if (isDataControlResult(error))
93
+ return toDataControlResult(error);
94
+ throw error;
95
+ }
83
96
  }
84
97
  storeCacheEntry(cacheKey, result) {
85
98
  this.cacheManager.set(cacheKey, {
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/renderer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,cA0P7B,CAAC"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/renderer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,cA4R7B,CAAC"}
@@ -1,6 +1,19 @@
1
1
  export const getRendererScript = () => `
2
2
  // Note: DEBUG, log, logError are defined in router.ts which loads first
3
3
 
4
+ // True when a dynamic import failed because the module could not be
5
+ // fetched (404 / network), as opposed to being fetched and then failing to
6
+ // link or evaluate. Browsers report the former as a TypeError with a
7
+ // "dynamically imported module" message; link failures are SyntaxErrors and
8
+ // evaluation failures are whatever the module threw.
9
+ function isModuleNotFoundError(error) {
10
+ if (!error) return false;
11
+ if (error instanceof SyntaxError) return false;
12
+ const message = String((error && error.message) || error);
13
+ return /(?:Failed to fetch|error loading|Importing a module script failed|Failed to load)/i
14
+ .test(message);
15
+ }
16
+
4
17
  async function renderPage(pathname) {
5
18
  const resolvedPathname = (() => {
6
19
  const input = typeof pathname === 'string' ? pathname : window.location.pathname;
@@ -92,6 +105,8 @@ export const getRendererScript = () => `
92
105
  };
93
106
  }
94
107
 
108
+ let pageModuleError = null;
109
+
95
110
  if (data.pagePath) {
96
111
  const moduleUrl = shouldRenderRscClientPage
97
112
  ? '/_veryfront/rsc/module?rel=' + encodeURIComponent(data.pagePath)
@@ -101,6 +116,7 @@ export const getRendererScript = () => `
101
116
  try {
102
117
  pageModule = await import(moduleUrl);
103
118
  } catch (error) {
119
+ pageModuleError = error;
104
120
  logError('Failed to load page from hydration data:', error);
105
121
  }
106
122
  }
@@ -115,8 +131,26 @@ export const getRendererScript = () => `
115
131
  try {
116
132
  pageModule = await import(basePath + '.js');
117
133
  } catch (error) {
118
- if (pageSlug === 'index' || pageSlug.endsWith('/index')) throw error;
119
- pageModule = await import(basePath + '/index.js');
134
+ pageModuleError = pageModuleError || error;
135
+
136
+ // Only retry at <route>/index.js when the module genuinely could not
137
+ // be found. If it was found but failed to link or evaluate, retrying
138
+ // a path that does not exist replaces a precise error ("does not
139
+ // provide an export named 'createHash'") with a misleading 404.
140
+ const canRetryAsIndex = isModuleNotFoundError(error) &&
141
+ pageSlug !== 'index' && !pageSlug.endsWith('/index');
142
+
143
+ if (!canRetryAsIndex) throw pageModuleError;
144
+
145
+ try {
146
+ pageModule = await import(basePath + '/index.js');
147
+ } catch (indexError) {
148
+ // For a real <route>/index.tsx page, the first 404 was expected
149
+ // and this retry is the path that matters: if it reached a module
150
+ // and failed to link or evaluate, its error is the real one. Only
151
+ // when the retry 404s as well does the original describe more.
152
+ throw isModuleNotFoundError(indexError) ? pageModuleError : indexError;
153
+ }
120
154
  }
121
155
  }
122
156
 
@@ -1 +1 @@
1
- {"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../../src/src/internal-agents/run-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,YAAY,IAAI,OAAO,EAC5B,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAC;AAY3B,OAAO,KAAK,EACV,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,qBAAqB,CAAC;AAU7B,OAAO,EAEL,KAAK,IAAI,EAGV,MAAM,kBAAkB,CAAC;AAe1B,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAsCxD,MAAM,WAAW,+BAA+B;IAC9C,cAAc,EAAE,sBAAsB,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;IAC5C,mBAAmB,CAAC,EAAE;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,cAAc,CAAC,EAAE,+BAA+B,CAAC,gBAAgB,CAAC,CAAC;IACnE,8BAA8B,CAAC,EAAE,CAC/B,KAAK,EAAE,+BAA+B,KACnC,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,CACd,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAClC;QACH,MAAM,EAAE,CACN,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE;YACV,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;SAC9C,EACD,aAAa,CAAC,EAAE,MAAM,EACtB,uBAAuB,CAAC,EAAE,MAAM,EAChC,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;KAC1C,CAAC;CACH;AAoCD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,sBAAsB,EACtC,2BAA2B,CAAC,EAAE,MAAM,EAAE,EACtC,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;;cAsFrD;AAyVD,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,oBAAoB,EAC3B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,+BAA+B,GACpC,OAAO,CAAC,QAAQ,CAAC,CA2anB"}
1
+ {"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../../src/src/internal-agents/run-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,YAAY,IAAI,OAAO,EAC5B,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAC;AAY3B,OAAO,KAAK,EACV,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,qBAAqB,CAAC;AAU7B,OAAO,EAGL,KAAK,IAAI,EAGV,MAAM,kBAAkB,CAAC;AAe1B,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAsCxD,MAAM,WAAW,+BAA+B;IAC9C,cAAc,EAAE,sBAAsB,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;IAC5C,mBAAmB,CAAC,EAAE;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,cAAc,CAAC,EAAE,+BAA+B,CAAC,gBAAgB,CAAC,CAAC;IACnE,8BAA8B,CAAC,EAAE,CAC/B,KAAK,EAAE,+BAA+B,KACnC,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,CACd,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAClC;QACH,MAAM,EAAE,CACN,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE;YACV,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;SAC9C,EACD,aAAa,CAAC,EAAE,MAAM,EACtB,uBAAuB,CAAC,EAAE,MAAM,EAChC,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;KAC1C,CAAC;CACH;AAoCD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,sBAAsB,EACtC,2BAA2B,CAAC,EAAE,MAAM,EAAE,EACtC,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;;cAsFrD;AA6VD,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,oBAAoB,EAC3B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,+BAA+B,GACpC,OAAO,CAAC,QAAQ,CAAC,CA2anB"}
@@ -10,7 +10,7 @@ import { importFirstPartyExtensionModule } from "../extensions/first-party-impor
10
10
  import { SandboxShellToolsProviderName, } from "../extensions/sandbox/index.js";
11
11
  import { resolveHostedRuntimeAllowedToolNames } from "../agent/hosted/runtime-essential-tools.js";
12
12
  import { SKILL_TOOL_IDS } from "../skill/types.js";
13
- import { isToolVisibleTo, toolRegistry, } from "../tool/index.js";
13
+ import { createToolsFromHostDefinitions, isToolVisibleTo, toolRegistry, } from "../tool/index.js";
14
14
  import { addSpanEvent, setSpanAttributes, withSpan, } from "../observability/tracing/otlp-setup.js";
15
15
  import { defineSchema, lazySchema } from "../schemas/index.js";
16
16
  import { createStreamTransformState, finalizeRunEvents, formatAgUiEvent, mapRuntimeEventToAgUi, parseSseJsonEvents, } from "./ag-ui-sse.js";
@@ -210,15 +210,17 @@ async function buildProjectAgentSandboxTools(input) {
210
210
  : {}),
211
211
  getProjectId: () => sandboxConfig.projectId ?? input.deps.projectAgentSandbox?.projectId,
212
212
  });
213
- const bash = sandboxResult.tools[PROJECT_AGENT_SANDBOX_BASH_TOOL_NAME];
214
- if (!bash) {
213
+ const declaredTools = input.agent.config.tools;
214
+ const materializedTools = createToolsFromHostDefinitions(sandboxResult.tools);
215
+ const configuredTools = isRecord(declaredTools)
216
+ ? Object.fromEntries(Object.entries(materializedTools).filter(([toolName]) => declaredTools[toolName] === true))
217
+ : {};
218
+ if (!configuredTools[PROJECT_AGENT_SANDBOX_BASH_TOOL_NAME]) {
215
219
  await sandboxResult.closeSandbox();
216
220
  return {};
217
221
  }
218
222
  return {
219
- tools: {
220
- [PROJECT_AGENT_SANDBOX_BASH_TOOL_NAME]: bash,
221
- },
223
+ tools: configuredTools,
222
224
  closeSandbox: sandboxResult.closeSandbox,
223
225
  };
224
226
  }
@@ -47,4 +47,10 @@ export declare function serveModule(req: Request, options: ModuleServerOptions):
47
47
  * @returns true if request path starts with /_vf_modules/
48
48
  */
49
49
  export declare function isModuleRequest(req: Request): boolean;
50
+ /**
51
+ * Content type for a dev module response.
52
+ *
53
+ * Exported for testing.
54
+ */
55
+ export declare function getDevModuleContentType(modulePath: string): string;
50
56
  //# sourceMappingURL=module-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-server.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/module-server.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAG5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AA2DtE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAwDrD,CAAC;AAyEF,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB,uBAAuB;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqczF;AAwWD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGrD"}
1
+ {"version":3,"file":"module-server.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/module-server.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAG5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AA2DtE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAwDrD,CAAC;AAyEF,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB,uBAAuB;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqczF;AAwWD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGrD;AAiBD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAyBlE"}
@@ -786,7 +786,14 @@ function getModuleHeaders(modulePath, options = {}) {
786
786
  : "no-cache",
787
787
  };
788
788
  }
789
- function getDevModuleContentType(modulePath) {
789
+ /** Source extensions the module server compiles to JavaScript before serving. */
790
+ const COMPILED_TO_JS_EXTENSIONS = /\.(?:tsx?|jsx|mdx|md)$/;
791
+ /**
792
+ * Content type for a dev module response.
793
+ *
794
+ * Exported for testing.
795
+ */
796
+ export function getDevModuleContentType(modulePath) {
790
797
  const normalizedPath = modulePath.toLowerCase();
791
798
  if (normalizedPath.endsWith(".map") || normalizedPath.endsWith(".json")) {
792
799
  return "application/json; charset=utf-8";
@@ -794,6 +801,13 @@ function getDevModuleContentType(modulePath) {
794
801
  if (normalizedPath.endsWith(".css")) {
795
802
  return "text/css; charset=utf-8";
796
803
  }
804
+ // The request path carries the *source* extension, but the body we serve is
805
+ // always the compiled JavaScript. Typing the response from the source
806
+ // extension yields `application/typescript`, which browsers refuse to execute
807
+ // as a module under strict MIME checking.
808
+ if (COMPILED_TO_JS_EXTENSIONS.test(normalizedPath)) {
809
+ return "application/javascript; charset=utf-8";
810
+ }
797
811
  const detected = getContentTypeForPath(normalizedPath);
798
812
  if (detected === "application/octet-stream") {
799
813
  return "application/javascript; charset=utf-8";
@@ -8,6 +8,8 @@ export type ResolvedModuleDependency = {
8
8
  relativePath: string;
9
9
  depFilePath: string | null;
10
10
  isLocalLib: boolean;
11
+ /** True when discovered inside `import("…")` rather than a static import. */
12
+ isDynamic: boolean;
11
13
  };
12
14
  /** Resolved dependency after its source module has been transformed to a temp file. */
13
15
  export type TransformedModuleDependency = ResolvedModuleDependency & {
@@ -1 +1 @@
1
- {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/dependency-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAczE,sEAAsE;AACtE,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,GAAG;IACnE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;CACzB;AAgGD,yEAAyE;AACzE,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAuBrC;AAED,2EAA2E;AAC3E,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,2BAA2B,EAAE,GAC7C,MAAM,CAQR"}
1
+ {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/dependency-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA4BzE,sEAAsE;AACtE,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,GAAG;IACnE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;CACzB;AA4GD,yEAAyE;AACzE,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAuBrC;AAED,2EAA2E;AAC3E,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,2BAA2B,EAAE,GAC7C,MAAM,CAUR"}
@@ -1,25 +1,23 @@
1
1
  import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
2
2
  import { parallelMap, rendererLogger } from "../../../utils/index.js";
3
- import { findStaticImportFromSpans, replaceSourceSpans, } from "../../../transforms/mdx/esm-module-loader/utils/source-spans.js";
3
+ import { findDynamicImportSpans, findStaticImportFromSpans, replaceSourceSpans, } from "../../../transforms/mdx/esm-module-loader/utils/source-spans.js";
4
4
  import { findSourceFile } from "../file-resolver/index.js";
5
5
  const logger = rendererLogger.component("module-loader");
6
+ const matchAlias = (specifier) => specifier.startsWith("@/") ? specifier : null;
7
+ const matchRelative = (specifier) => specifier.match(/^(\.\.?\/[^?]+)(?:\?.*)?$/)?.[1];
6
8
  function collectAliasImports(fileContent) {
7
- return findStaticImportFromSpans(fileContent, (specifier) => specifier.startsWith("@/") ? specifier : null).map(({ original, path, start, end }) => ({
8
- full: original,
9
- path,
10
- start,
11
- end,
12
- }));
9
+ const toAlias = (isDynamic) => ({ original, path, start, end }) => ({ full: original, path, start, end, isDynamic });
10
+ return [
11
+ ...findStaticImportFromSpans(fileContent, matchAlias).map(toAlias(false)),
12
+ ...findDynamicImportSpans(fileContent, matchAlias).map(toAlias(true)),
13
+ ];
13
14
  }
14
15
  function collectRelativeImports(fileContent, fileDir) {
15
- return findStaticImportFromSpans(fileContent, (specifier) => specifier.match(/^(\.\.?\/[^?]+)(?:\?.*)?$/)?.[1])
16
- .map(({ original, path, start, end }) => ({
17
- full: original,
18
- path,
19
- fromDir: fileDir,
20
- start,
21
- end,
22
- }))
16
+ const toRelative = (isDynamic) => ({ original, path, start, end }) => ({ full: original, path, fromDir: fileDir, start, end, isDynamic });
17
+ return [
18
+ ...findStaticImportFromSpans(fileContent, matchRelative).map(toRelative(false)),
19
+ ...findDynamicImportSpans(fileContent, matchRelative).map(toRelative(true)),
20
+ ]
23
21
  // Ignore already-transformed file:// imports.
24
22
  .filter((imp) => !imp.path.includes("file://"));
25
23
  }
@@ -70,6 +68,7 @@ async function resolveRelativeImport(imp, adapter) {
70
68
  relativePath: imp.path,
71
69
  depFilePath,
72
70
  isLocalLib: false,
71
+ isDynamic: imp.isDynamic,
73
72
  };
74
73
  }
75
74
  /** Resolves @/ alias and relative local imports from a source module. */
@@ -94,7 +93,9 @@ export function rewriteResolvedDependencyImports(fileContent, transformedDeps) {
94
93
  start: dep.start,
95
94
  end: dep.end,
96
95
  expected: dep.full,
97
- replacement: `from "file://${dep.depTempPath}"`,
96
+ // A dynamic span covers only the quoted specifier; a static one covers the
97
+ // whole `from "…"` clause.
98
+ replacement: dep.isDynamic ? `"file://${dep.depTempPath}"` : `from "file://${dep.depTempPath}"`,
98
99
  }));
99
100
  return replaceSourceSpans(fileContent, replacements);
100
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"module-persistence.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/module-persistence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA6CzE,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,cAAc,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,uEAAuE;AACvE,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,MAAM,CAAC,CA2CjB"}
1
+ {"version":3,"file":"module-persistence.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/module-persistence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAuDzE,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,cAAc,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,uEAAuE;AACvE,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,MAAM,CAAC,CA+DjB"}
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { join } from "../../../platform/compat/path/index.js";
7
7
  import { rendererLogger } from "../../../utils/index.js";
8
+ import { isCacheWriteRaceError } from "../../../utils/cache-file-ops.js";
8
9
  import { hashCodeHex } from "../../../utils/hash-utils.js";
9
10
  import { getModulePathCache, saveModulePathCache, } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
10
11
  import { buildMdxEsmPathCacheKey } from "../../../transforms/mdx/esm-module-loader/cache-format.js";
@@ -26,19 +27,22 @@ function pruneCreatedDirs() {
26
27
  deleted++;
27
28
  }
28
29
  }
29
- async function ensureDir(adapter, dir) {
30
- if (createdDirs.has(dir))
30
+ async function ensureDir(adapter, dir, force = false) {
31
+ if (!force && createdDirs.has(dir))
31
32
  return;
32
33
  try {
33
34
  await adapter.fs.mkdir(dir, { recursive: true });
34
35
  }
35
- catch (_) {
36
- /* expected: directory might already exist */
37
- }
38
- finally {
39
- createdDirs.add(dir);
40
- pruneCreatedDirs();
36
+ catch (error) {
37
+ // `recursive: true` is a no-op on an existing directory, so a rejection here
38
+ // means the directory may genuinely be absent (EMFILE, EACCES, a racing
39
+ // sweep). Drop the memo so the next attempt retries instead of assuming the
40
+ // directory is present forever after.
41
+ createdDirs.delete(dir);
42
+ throw error;
41
43
  }
44
+ createdDirs.add(dir);
45
+ pruneCreatedDirs();
42
46
  }
43
47
  /** Write a transformed module artifact and register cache pointers. */
44
48
  export async function persistTransformedModule(input) {
@@ -49,17 +53,37 @@ export async function persistTransformedModule(input) {
49
53
  const jsPath = relativePath.replace(/\.(tsx?|jsx|mdx)$/, `.${transformedHash}.js`);
50
54
  const tempFilePath = join(input.tmpDir, jsPath);
51
55
  const tempDir = tempFilePath.substring(0, tempFilePath.lastIndexOf("/"));
52
- await ensureDir(input.localAdapter, tempDir);
56
+ await ensureDir(input.localAdapter, tempDir).catch(() => {
57
+ // Fall through to the write, which retries the mkdir on failure.
58
+ });
53
59
  try {
54
60
  await input.localAdapter.fs.writeFile(tempFilePath, input.transformedCode);
55
61
  }
56
62
  catch (error) {
57
- logger.error("Failed to write module:", {
58
- filePath: input.filePath,
59
- tempFilePath,
60
- error: error instanceof Error ? error.message : String(error),
61
- });
62
- throw error;
63
+ // The cache directory can vanish between mkdir and write a manual
64
+ // `rm -rf .cache`, a cache sweep, or a mkdir that never actually landed.
65
+ // Force the directory back into existence and retry once before failing.
66
+ if (!isCacheWriteRaceError(error)) {
67
+ logger.error("Failed to write module:", {
68
+ filePath: input.filePath,
69
+ tempFilePath,
70
+ error: error instanceof Error ? error.message : String(error),
71
+ });
72
+ throw error;
73
+ }
74
+ try {
75
+ await ensureDir(input.localAdapter, tempDir, true);
76
+ await input.localAdapter.fs.writeFile(tempFilePath, input.transformedCode);
77
+ logger.debug("Recreated module cache directory after failed write", { tempDir });
78
+ }
79
+ catch (retryError) {
80
+ logger.error("Failed to write module:", {
81
+ filePath: input.filePath,
82
+ tempFilePath,
83
+ error: retryError instanceof Error ? retryError.message : String(retryError),
84
+ });
85
+ throw retryError;
86
+ }
63
87
  }
64
88
  if (input.contentSourceId) {
65
89
  const normalizedPath = `_vf_modules/${relativePath.replace(/\.(tsx?|jsx|mdx)$/, ".js")}`;
@@ -1 +1 @@
1
- {"version":3,"file":"host-tools.d.ts","sourceRoot":"","sources":["../../../src/src/tool/host-tools.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAElF,KAAK,eAAe,GAAG;IACrB,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAChG,CAAC,gBAAgB,CAAC,CAAC;AAEpB,gCAAgC;AAChC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,eAAe,CAAC;IAC5C,GAAG,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CACzB,CAAC;AAEF,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAQ7D,qDAAqD;AACrD,MAAM,WAAW,8BAA8B;IAC7C,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AA4CD,0CAA0C;AAC1C,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,8BAA8B,GACvC,OAAO,CAAC;AACX,0CAA0C;AAC1C,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE,8BAA8B,GACvC,OAAO,CAAC"}
1
+ {"version":3,"file":"host-tools.d.ts","sourceRoot":"","sources":["../../../src/src/tool/host-tools.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAElF,KAAK,eAAe,GAAG;IACrB,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAChG,CAAC,gBAAgB,CAAC,CAAC;AAEpB,gCAAgC;AAChC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,eAAe,CAAC;IAC5C,GAAG,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CACzB,CAAC;AAEF,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAO7D,qDAAqD;AACrD,MAAM,WAAW,8BAA8B;IAC7C,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AA2DD,0CAA0C;AAC1C,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,8BAA8B,GACvC,OAAO,CAAC;AACX,0CAA0C;AAC1C,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE,8BAA8B,GACvC,OAAO,CAAC"}
@@ -16,10 +16,17 @@ function isSchemaLike(value) {
16
16
  // defineSchema wrapper without a brand yet — match on the contract surface.
17
17
  return "_output" in value && typeof value.safeParse === "function";
18
18
  }
19
+ function isParserBackedPrecomputedSchema(input) {
20
+ return (isRecord(input.inputSchema) &&
21
+ typeof input.inputSchema.parse === "function" &&
22
+ isRecord(input.inputSchemaJson));
23
+ }
19
24
  function isHostToolDefinition(value) {
20
25
  return (isRecord(value) &&
21
26
  typeof value.description === "string" &&
22
- isSchemaLike(value.inputSchema) &&
27
+ (isSchemaLike(value.inputSchema) ||
28
+ isParserBackedPrecomputedSchema(value) ||
29
+ (value.inputSchema === undefined && isRecord(value.inputSchemaJson))) &&
23
30
  typeof value.execute === "function");
24
31
  }
25
32
  function defaultToolCallId(toolName) {
@@ -42,22 +49,25 @@ export function createToolsFromHostDefinitions(definitions, options = {}) {
42
49
  continue;
43
50
  const execute = async (input, context) => await definition.execute(input, normalizeExecutionContext(toolName, context, options));
44
51
  try {
45
- tools[toolName] = definition.inputSchemaJson
46
- ? dynamicTool({
52
+ if (definition.inputSchemaJson) {
53
+ tools[toolName] = dynamicTool({
47
54
  id: toolName,
48
55
  description: definition.description,
49
56
  inputSchema: definition.inputSchema,
50
57
  inputSchemaJson: definition.inputSchemaJson,
51
58
  execute,
52
59
  mcp: definition.mcp,
53
- })
54
- : tool({
60
+ });
61
+ }
62
+ else if (isSchemaLike(definition.inputSchema)) {
63
+ tools[toolName] = tool({
55
64
  id: toolName,
56
65
  description: definition.description,
57
66
  inputSchema: definition.inputSchema,
58
67
  execute,
59
68
  mcp: definition.mcp,
60
69
  });
70
+ }
61
71
  }
62
72
  catch (error) {
63
73
  agentLogger.warn("Skipping host tool: schema conversion failed", {
@@ -4,6 +4,18 @@ import type { Loader } from "../../extensions/bundler/index.js";
4
4
  * Use this for transform cache keys where a compact hash is preferred.
5
5
  */
6
6
  export declare function computeShortContentHash(content: string): Promise<string>;
7
+ /**
8
+ * esbuild feature overrides shared by every source transform.
9
+ *
10
+ * Import attributes post-date the `es20xx` targets we lower to, so esbuild
11
+ * would silently *drop* `with { type: "json" }` rather than fail. Every runtime
12
+ * that consumes this output requires the attribute to load a JSON module, so
13
+ * dropping it turns a working import into a load-time error:
14
+ * `Attempted to load JSON module without specifying "type": "json"`.
15
+ */
16
+ export declare const ESBUILD_SUPPORTED_FEATURES: {
17
+ readonly "import-attributes": true;
18
+ };
7
19
  export declare function getLoaderFromPath(filePath: string): Loader;
8
20
  export declare function needsTransform(filePath: string): boolean;
9
21
  //# sourceMappingURL=transform-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform-utils.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/transform-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAGhE;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAExE;AAaD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD"}
1
+ {"version":3,"file":"transform-utils.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/transform-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAGhE;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAExE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B;;CAAyC,CAAC;AAajF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD"}
@@ -6,6 +6,16 @@ import { shortHash } from "../../utils/hash-utils.js";
6
6
  export function computeShortContentHash(content) {
7
7
  return shortHash(content);
8
8
  }
9
+ /**
10
+ * esbuild feature overrides shared by every source transform.
11
+ *
12
+ * Import attributes post-date the `es20xx` targets we lower to, so esbuild
13
+ * would silently *drop* `with { type: "json" }` rather than fail. Every runtime
14
+ * that consumes this output requires the attribute to load a JSON module, so
15
+ * dropping it turns a working import into a load-time error:
16
+ * `Attempted to load JSON module without specifying "type": "json"`.
17
+ */
18
+ export const ESBUILD_SUPPORTED_FEATURES = { "import-attributes": true };
9
19
  const EXTENSION_LOADERS = {
10
20
  ".tsx": "tsx",
11
21
  ".ts": "ts",
@@ -1 +1 @@
1
- {"version":3,"file":"alias-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/import-rewriter/strategies/alias-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACd,MAAM,aAAa,CAAC;AAGrB,qBAAa,aAAc,YAAW,qBAAqB;IACzD,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,QAAQ,KAAK;IAEtB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO;IAIzD,OAAO,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,cAAc,GAAG,aAAa;IAwCtE,OAAO,CAAC,mBAAmB;CAoB5B;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
1
+ {"version":3,"file":"alias-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/import-rewriter/strategies/alias-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACd,MAAM,aAAa,CAAC;AAGrB,qBAAa,aAAc,YAAW,qBAAqB;IACzD,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,QAAQ,KAAK;IAEtB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO;IAIzD,OAAO,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,cAAc,GAAG,aAAa;IAyCtE,OAAO,CAAC,mBAAmB;CAoB5B;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -32,8 +32,9 @@ export class AliasStrategy {
32
32
  const relativeFilePath = this.getRelativeFilePath(ctx.filePath, ctx.projectDir);
33
33
  const fileDir = relativeFilePath.substring(0, relativeFilePath.lastIndexOf("/"));
34
34
  const depth = fileDir.split("/").filter(Boolean).length;
35
- let relativePath = depth === 0 ? `./${path}` : `${"../".repeat(depth)}${path}`;
36
- if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css)$/.test(relativePath)) {
35
+ const prefix = depth === 0 ? "./" : "../".repeat(depth);
36
+ let relativePath = normalizeExtension(`${prefix}${path}`);
37
+ if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css|js)$/.test(relativePath)) {
37
38
  relativePath = `${relativePath}.js`;
38
39
  }
39
40
  return { specifier: relativePath };
@@ -18,6 +18,17 @@ export interface StaticImportSpan {
18
18
  type SpecifierMatcher = (specifier: string) => string | null | undefined;
19
19
  export declare function replaceSourceSpans(source: string, replacements: SourceSpanReplacement[]): string;
20
20
  export declare function findStaticImportFromSpans(source: string, matcher: SpecifierMatcher): StaticImportSpan[];
21
+ /**
22
+ * Find `import("…")` expressions with a literal specifier.
23
+ *
24
+ * The returned span covers the quoted specifier itself (quotes included), not
25
+ * the surrounding `import(...)`, so a replacement is a bare quoted string.
26
+ * Dynamic imports whose argument is not a string literal are skipped, since
27
+ * their target is only known at runtime. That includes an argument the literal
28
+ * merely starts: rewriting the `"./foo"` in `import("./foo" + suffix)` would
29
+ * build a path out of a resolved prefix and an unresolved tail.
30
+ */
31
+ export declare function findDynamicImportSpans(source: string, matcher: SpecifierMatcher): StaticImportSpan[];
21
32
  export declare function findStaticSideEffectImportSpans(source: string, matcher: SpecifierMatcher): StaticImportSpan[];
22
33
  export {};
23
34
  //# sourceMappingURL=source-spans.d.ts.map