veryfront 0.1.170 → 0.1.173

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 (28) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/agent/runtime/model-tool-converter.d.ts.map +1 -1
  3. package/esm/src/agent/runtime/model-tool-converter.js +6 -3
  4. package/esm/src/agent/runtime/provider-native-tools.d.ts +1 -0
  5. package/esm/src/agent/runtime/provider-native-tools.d.ts.map +1 -1
  6. package/esm/src/agent/runtime/provider-native-tools.js +66 -0
  7. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts +1 -0
  8. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
  9. package/esm/src/platform/adapters/fs/veryfront/read-operations.js +10 -16
  10. package/esm/src/provider/runtime-loader.d.ts.map +1 -1
  11. package/esm/src/provider/runtime-loader.js +21 -0
  12. package/esm/src/rendering/orchestrator/html-head.d.ts +18 -0
  13. package/esm/src/rendering/orchestrator/html-head.d.ts.map +1 -0
  14. package/esm/src/rendering/orchestrator/html-head.js +63 -0
  15. package/esm/src/rendering/orchestrator/html.d.ts +0 -2
  16. package/esm/src/rendering/orchestrator/html.d.ts.map +1 -1
  17. package/esm/src/rendering/orchestrator/html.js +5 -69
  18. package/esm/src/utils/version-constant.d.ts +1 -1
  19. package/esm/src/utils/version-constant.js +1 -1
  20. package/package.json +1 -1
  21. package/src/deno.js +1 -1
  22. package/src/src/agent/runtime/model-tool-converter.ts +13 -3
  23. package/src/src/agent/runtime/provider-native-tools.ts +69 -0
  24. package/src/src/platform/adapters/fs/veryfront/read-operations.ts +14 -12
  25. package/src/src/provider/runtime-loader.ts +27 -0
  26. package/src/src/rendering/orchestrator/html-head.ts +74 -0
  27. package/src/src/rendering/orchestrator/html.ts +8 -72
  28. package/src/src/utils/version-constant.ts +1 -1
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.170",
3
+ "version": "0.1.173",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -1 +1 @@
1
- {"version":3,"file":"model-tool-converter.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/model-tool-converter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAQ9D,MAAM,WAAW,iCAAiC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AA4BD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,CAAC,EAAE,iCAAiC,GAC1C,cAAc,GAAG,SAAS,CAwB5B"}
1
+ {"version":3,"file":"model-tool-converter.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/model-tool-converter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAW9D,MAAM,WAAW,iCAAiC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAmCD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,CAAC,EAAE,iCAAiC,GAC1C,cAAc,GAAG,SAAS,CAwB5B"}
@@ -1,5 +1,5 @@
1
1
  import { addRuntimeTool, createRuntimeJsonSchema, createRuntimeTool, } from "./runtime-tool-builder.js";
2
- import { createAnthropicWebSearchToolSet } from "./provider-native-tools.js";
2
+ import { createAnthropicWebFetchToolSet, createAnthropicWebSearchToolSet, } from "./provider-native-tools.js";
3
3
  function resolveHostedProvider(model) {
4
4
  if (!model)
5
5
  return undefined;
@@ -12,13 +12,16 @@ function resolveHostedProvider(model) {
12
12
  return provider;
13
13
  }
14
14
  function resolveProviderNativeTools(options) {
15
- if (!options?.allowedToolNames?.includes("web_search")) {
15
+ if (!options?.allowedToolNames?.some((toolName) => toolName === "web_search" || toolName === "web_fetch")) {
16
16
  return undefined;
17
17
  }
18
18
  if (resolveHostedProvider(options.model) !== "anthropic") {
19
19
  return undefined;
20
20
  }
21
- return createAnthropicWebSearchToolSet();
21
+ return {
22
+ ...createAnthropicWebSearchToolSet(),
23
+ ...createAnthropicWebFetchToolSet(),
24
+ };
22
25
  }
23
26
  /**
24
27
  * Convert veryfront tool definitions to the current model-runtime ToolSet.
@@ -1,3 +1,4 @@
1
1
  import type { RuntimeToolSet } from "./runtime-tool-types.js";
2
2
  export declare function createAnthropicWebSearchToolSet(): RuntimeToolSet;
3
+ export declare function createAnthropicWebFetchToolSet(): RuntimeToolSet;
3
4
  //# sourceMappingURL=provider-native-tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider-native-tools.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/provider-native-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AA8C9D,wBAAgB,+BAA+B,IAAI,cAAc,CAYhE"}
1
+ {"version":3,"file":"provider-native-tools.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/provider-native-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAuG9D,wBAAgB,+BAA+B,IAAI,cAAc,CAYhE;AAED,wBAAgB,8BAA8B,IAAI,cAAc,CAU/D"}
@@ -41,6 +41,61 @@ const WEB_SEARCH_OUTPUT_SCHEMA = {
41
41
  additionalProperties: false,
42
42
  },
43
43
  };
44
+ const WEB_FETCH_INPUT_SCHEMA = {
45
+ type: "object",
46
+ properties: {
47
+ url: {
48
+ type: "string",
49
+ },
50
+ },
51
+ required: ["url"],
52
+ additionalProperties: false,
53
+ };
54
+ const WEB_FETCH_OUTPUT_SCHEMA = {
55
+ type: "object",
56
+ properties: {
57
+ type: {
58
+ type: "string",
59
+ const: "web_fetch_result",
60
+ },
61
+ url: {
62
+ type: "string",
63
+ },
64
+ content: {
65
+ type: "object",
66
+ properties: {
67
+ type: {
68
+ type: "string",
69
+ const: "document",
70
+ },
71
+ source: {
72
+ type: "object",
73
+ properties: {
74
+ type: {
75
+ type: "string",
76
+ enum: ["text", "base64"],
77
+ },
78
+ mediaType: {
79
+ type: "string",
80
+ },
81
+ data: {
82
+ type: "string",
83
+ },
84
+ },
85
+ required: ["type", "mediaType", "data"],
86
+ additionalProperties: true,
87
+ },
88
+ },
89
+ required: ["type", "source"],
90
+ additionalProperties: true,
91
+ },
92
+ retrievedAt: {
93
+ type: "string",
94
+ },
95
+ },
96
+ required: ["type", "url", "content", "retrievedAt"],
97
+ additionalProperties: false,
98
+ };
44
99
  export function createAnthropicWebSearchToolSet() {
45
100
  return {
46
101
  web_search: createRuntimeProviderTool({
@@ -54,3 +109,14 @@ export function createAnthropicWebSearchToolSet() {
54
109
  }),
55
110
  };
56
111
  }
112
+ export function createAnthropicWebFetchToolSet() {
113
+ return {
114
+ web_fetch: createRuntimeProviderTool({
115
+ id: "anthropic.web_fetch_20250910",
116
+ args: {},
117
+ inputSchema: createLazyRuntimeJsonSchema(WEB_FETCH_INPUT_SCHEMA),
118
+ outputSchema: createLazyRuntimeJsonSchema(WEB_FETCH_OUTPUT_SCHEMA),
119
+ supportsDeferredResults: true,
120
+ }),
121
+ };
122
+ }
@@ -29,6 +29,7 @@ export declare class ReadOperations {
29
29
  private tryResolveExtensionlessPath;
30
30
  private tryResolveExtensionlessPathFromFileList;
31
31
  private cacheResolvedContent;
32
+ private storeFetchedContent;
32
33
  private fetchContent;
33
34
  private fetchPublishedContent;
34
35
  private tryFallbackExtensions;
@@ -1 +1 @@
1
- {"version":3,"file":"read-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAapE,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAY9B,qBAAa,cAAc;IAWvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAfpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAI9B;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,mGAAmG;IACnG,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA6B;gBAGnD,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,cAAc,EAC1B,eAAe,CAAC,EAAE,sBAAsB,YAAA,EACxC,kBAAkB,CAAC,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,aAAA,EAC7C,gBAAgB,CAAC,GAAE,MAAM,OAAO,CAC/C,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CACtD,aAAA;IAKH,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIrD,kBAAkB,IAAI,IAAI;IAK1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAY3C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY3C,OAAO,CAAC,mBAAmB;YAsBb,+BAA+B;YA0C/B,mBAAmB;IA0CjC,OAAO,CAAC,kBAAkB;YAoFZ,2BAA2B;YA8D3B,uCAAuC;IAmCrD,OAAO,CAAC,oBAAoB;YAgBd,YAAY;YA6JZ,qBAAqB;YA8DrB,qBAAqB;YAgDrB,+BAA+B;YA8D/B,iBAAiB;CAyBhC"}
1
+ {"version":3,"file":"read-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAapE,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAY9B,qBAAa,cAAc;IAWvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAfpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAI9B;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,mGAAmG;IACnG,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA6B;gBAGnD,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,cAAc,EAC1B,eAAe,CAAC,EAAE,sBAAsB,YAAA,EACxC,kBAAkB,CAAC,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,aAAA,EAC7C,gBAAgB,CAAC,GAAE,MAAM,OAAO,CAC/C,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CACtD,aAAA;IAKH,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIrD,kBAAkB,IAAI,IAAI;IAK1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAY3C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY3C,OAAO,CAAC,mBAAmB;YAsBb,+BAA+B;YA0C/B,mBAAmB;IA0CjC,OAAO,CAAC,kBAAkB;YAoFZ,2BAA2B;YA8D3B,uCAAuC;IAmCrD,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,mBAAmB;YAUb,YAAY;YA6JZ,qBAAqB;YA4DrB,qBAAqB;YA8CrB,+BAA+B;YA4D/B,iBAAiB;CAuBhC"}
@@ -273,6 +273,12 @@ export class ReadOperations {
273
273
  setRequestScopedFile(resolvedCacheKey, content);
274
274
  }
275
275
  }
276
+ storeFetchedContent(cacheKey, content, shouldCache) {
277
+ if (shouldCache)
278
+ this.cache.set(cacheKey, content);
279
+ setRequestScopedFile(cacheKey, content);
280
+ return content;
281
+ }
276
282
  async fetchContent(normalizedPath) {
277
283
  // Framework paths should NEVER be fetched from API - they must be read from local filesystem.
278
284
  // If we reach here for a framework path, the module server's local resolution failed.
@@ -357,10 +363,7 @@ export class ReadOperations {
357
363
  contentLength: content.length,
358
364
  releaseId,
359
365
  });
360
- if (shouldCache)
361
- this.cache.set(cacheKey, content);
362
- setRequestScopedFile(cacheKey, content);
363
- return content;
366
+ return this.storeFetchedContent(cacheKey, content, shouldCache);
364
367
  }
365
368
  catch (error) {
366
369
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -402,10 +405,7 @@ export class ReadOperations {
402
405
  foundPath: result.path,
403
406
  contentLength: result.content.length,
404
407
  });
405
- if (shouldCache)
406
- this.cache.set(cacheKey, result.content);
407
- setRequestScopedFile(cacheKey, result.content);
408
- return result.content;
408
+ return this.storeFetchedContent(cacheKey, result.content, shouldCache);
409
409
  }
410
410
  catch (error) {
411
411
  logger.debug("Pattern search failed, trying sequential fallback", {
@@ -448,10 +448,7 @@ export class ReadOperations {
448
448
  durationMs,
449
449
  candidateCount: candidates.length,
450
450
  });
451
- if (shouldCache)
452
- this.cache.set(cacheKey, content);
453
- setRequestScopedFile(cacheKey, content);
454
- return content;
451
+ return this.storeFetchedContent(cacheKey, content, shouldCache);
455
452
  }
456
453
  catch (_) {
457
454
  /* expected: this extension variant does not exist, try next priority */
@@ -473,9 +470,6 @@ export class ReadOperations {
473
470
  preview: previewText(content).replace(/\n/g, "\\n"),
474
471
  willCache: shouldCache,
475
472
  });
476
- if (shouldCache)
477
- this.cache.set(cacheKey, content);
478
- setRequestScopedFile(cacheKey, content);
479
- return content;
473
+ return this.storeFetchedContent(cacheKey, content, shouldCache);
480
474
  }
481
475
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-loader.d.ts","sourceRoot":"","sources":["../../../src/src/provider/runtime-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC;CAC9B;AAu/CD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,MAAM,GACd,YAAY,CA4Dd;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CA0ClB;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CAgDlB"}
1
+ {"version":3,"file":"runtime-loader.d.ts","sourceRoot":"","sources":["../../../src/src/provider/runtime-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC;CAC9B;AAkhDD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,MAAM,GACd,YAAY,CA4Dd;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CA0ClB;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CAgDlB"}
@@ -397,6 +397,16 @@ function buildAnthropicGenerateResult(payload) {
397
397
  result: block.content,
398
398
  });
399
399
  }
400
+ if (blockType === "web_fetch_tool_result" &&
401
+ typeof block?.tool_use_id === "string" &&
402
+ readRecord(block?.content)) {
403
+ normalized.push({
404
+ type: "tool-result",
405
+ toolCallId: block.tool_use_id,
406
+ toolName: "web_fetch",
407
+ result: block.content,
408
+ });
409
+ }
400
410
  }
401
411
  return {
402
412
  content: normalized,
@@ -497,6 +507,17 @@ async function* streamAnthropicCompatibleParts(stream) {
497
507
  providerExecuted: true,
498
508
  };
499
509
  }
510
+ if (blockType === "web_fetch_tool_result" &&
511
+ typeof contentBlock?.tool_use_id === "string" &&
512
+ readRecord(contentBlock?.content)) {
513
+ yield {
514
+ type: "tool-result",
515
+ toolCallId: contentBlock.tool_use_id,
516
+ toolName: "web_fetch",
517
+ result: contentBlock.content,
518
+ providerExecuted: true,
519
+ };
520
+ }
500
521
  continue;
501
522
  }
502
523
  if (eventType === "content_block_delta") {
@@ -0,0 +1,18 @@
1
+ import type { CollectedHead } from "../../react/head-collector.js";
2
+ import type { MdxBundle, MDXFrontmatter } from "../../types/index.js";
3
+ interface FrontmatterContextLike {
4
+ pageInfo: {
5
+ entity: {
6
+ frontmatter?: Record<string, unknown>;
7
+ };
8
+ };
9
+ pageBundle: Pick<MdxBundle, "frontmatter">;
10
+ collectedMetadata?: Record<string, unknown>;
11
+ }
12
+ export declare function buildHeadElements(head?: CollectedHead): {
13
+ scripts: string;
14
+ other: string;
15
+ };
16
+ export declare function mergeFrontmatter(context: FrontmatterContextLike): MDXFrontmatter;
17
+ export {};
18
+ //# sourceMappingURL=html-head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-head.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html-head.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,UAAU,sBAAsB;IAC9B,QAAQ,EAAE;QAAE,MAAM,EAAE;YAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;IAChE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAwD1F;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAMhF"}
@@ -0,0 +1,63 @@
1
+ export function buildHeadElements(head) {
2
+ if (!head)
3
+ return { scripts: "", other: "" };
4
+ const scriptParts = [];
5
+ const otherParts = [];
6
+ for (const script of head.scripts ?? []) {
7
+ const { content, ...attrs } = script;
8
+ const attrPairs = [["data-vf-head", "true"]];
9
+ for (const [k, v] of Object.entries(attrs)) {
10
+ if (v != null)
11
+ attrPairs.push([k, v]);
12
+ }
13
+ if (content && !attrs.id) {
14
+ let sum = 0;
15
+ for (let i = 0; i < Math.min(content.length, 200); i++) {
16
+ sum = ((sum << 5) - sum + content.charCodeAt(i)) | 0;
17
+ }
18
+ attrPairs.push(["data-vf-hash", "vf" + Math.abs(sum).toString(36)]);
19
+ }
20
+ const attrStr = attrPairs.map(([k, v]) => `${k}="${v}"`).join(" ");
21
+ if (content) {
22
+ scriptParts.push(`<script ${attrStr}>${content}</script>`);
23
+ }
24
+ else if (attrs.src) {
25
+ scriptParts.push(`<script ${attrStr}></script>`);
26
+ }
27
+ }
28
+ for (const meta of head.metas) {
29
+ if (meta.name === "description")
30
+ continue;
31
+ const attrs = [];
32
+ if (meta.name)
33
+ attrs.push(`name="${meta.name}"`);
34
+ if (meta.property)
35
+ attrs.push(`property="${meta.property}"`);
36
+ if (meta.content)
37
+ attrs.push(`content="${meta.content}"`);
38
+ if (attrs.length)
39
+ otherParts.push(`<meta ${attrs.join(" ")}>`);
40
+ }
41
+ for (const link of head.links) {
42
+ const attrs = Object.entries(link)
43
+ .filter(([, v]) => v != null)
44
+ .map(([k, v]) => `${k}="${v}"`)
45
+ .join(" ");
46
+ if (attrs)
47
+ otherParts.push(`<link ${attrs}>`);
48
+ }
49
+ for (const style of head.styles) {
50
+ otherParts.push(`<style>${style}</style>`);
51
+ }
52
+ return {
53
+ scripts: scriptParts.join("\n "),
54
+ other: otherParts.join("\n "),
55
+ };
56
+ }
57
+ export function mergeFrontmatter(context) {
58
+ return {
59
+ ...context.pageInfo.entity.frontmatter,
60
+ ...context.pageBundle.frontmatter,
61
+ ...(context.collectedMetadata ?? {}),
62
+ };
63
+ }
@@ -33,8 +33,6 @@ export declare class HTMLGenerator {
33
33
  private detectUseClientDirective;
34
34
  private wrapHTMLFragment;
35
35
  private generateShellParts;
36
- private buildHeadElements;
37
- private mergeFrontmatter;
38
36
  private resolveAppPath;
39
37
  private loadProjectFile;
40
38
  private buildHTMLOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAS7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,SAAS,EAET,UAAU,EACX,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4EhD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;CACpC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,aAAa,EAAE,UAAU,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIjC,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAqEZ,sBAAsB;YAqDtB,4BAA4B;YAiB5B,wBAAwB;YAmBxB,gBAAgB;YAyBhB,kBAAkB;IAwDhC,OAAO,CAAC,iBAAiB;IA4DzB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,cAAc;YAQR,eAAe;YAaf,gBAAgB;IAgF9B;;;;OAIG;YACW,gBAAgB;CA0D/B"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAS7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,SAAS,EAET,UAAU,EACX,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgFhD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;CACpC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,aAAa,EAAE,UAAU,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIjC,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAqEZ,sBAAsB;YAqDtB,4BAA4B;YAiB5B,wBAAwB;YAmBxB,gBAAgB;YAyBhB,kBAAkB;IAwDhC,OAAO,CAAC,cAAc;YAQR,eAAe;YAaf,gBAAgB;IAgF9B;;;;OAIG;YACW,gBAAgB;CA0D/B"}
@@ -11,6 +11,7 @@ import { StreamTimeoutError, streamToString } from "../utils/stream-utils.js";
11
11
  import { profilePhase, profileSyncPhase } from "../../observability/request-profiler.js";
12
12
  import { normalizeCssModuleKey, rewriteCssModuleContent, } from "../../transforms/css-modules/naming.js";
13
13
  import { extractProjectClassesForRoute, startPreparedCSSWarmup, startProjectCSSPreparation, } from "./html-project-css.js";
14
+ import { buildHeadElements as buildCollectedHeadElements, mergeFrontmatter as mergeCollectedFrontmatter, } from "./html-head.js";
14
15
  const logger = rendererLogger.component("html-generator");
15
16
  function applyExplicitThemeToDocument(html, colorScheme, enabled) {
16
17
  if (!enabled || !colorScheme)
@@ -61,7 +62,7 @@ export class HTMLGenerator {
61
62
  if (isFullHTMLDocument(context.html)) {
62
63
  let projectCSSPromise;
63
64
  if (this.config.mode === "production" && context.options?.environment === "production") {
64
- const mergedFrontmatter = this.mergeFrontmatter(context);
65
+ const mergedFrontmatter = mergeCollectedFrontmatter(context);
65
66
  const htmlOptions = await profilePhase("html.build_options", () => this.buildHTMLOptions(context, mergedFrontmatter));
66
67
  projectCSSPromise = startProjectCSSPreparation(context, htmlOptions);
67
68
  }
@@ -78,7 +79,7 @@ export class HTMLGenerator {
78
79
  }
79
80
  async generateHTMLStream(reactStream, context) {
80
81
  const fullContext = context;
81
- const mergedFrontmatter = this.mergeFrontmatter(fullContext);
82
+ const mergedFrontmatter = mergeCollectedFrontmatter(fullContext);
82
83
  const htmlOptions = await profilePhase("html.build_options", () => this.buildHTMLOptions(fullContext, mergedFrontmatter));
83
84
  const projectCSSPromise = startProjectCSSPreparation(fullContext, htmlOptions);
84
85
  startPreparedCSSWarmup(this.config, fullContext, htmlOptions);
@@ -175,7 +176,7 @@ export class HTMLGenerator {
175
176
  }
176
177
  }
177
178
  async wrapHTMLFragment(context) {
178
- const mergedFrontmatter = this.mergeFrontmatter(context);
179
+ const mergedFrontmatter = mergeCollectedFrontmatter(context);
179
180
  const htmlOptions = await profilePhase("html.build_options", () => this.buildHTMLOptions(context, mergedFrontmatter));
180
181
  const projectCSSPromise = startProjectCSSPreparation(context, htmlOptions);
181
182
  startPreparedCSSWarmup(this.config, context, htmlOptions);
@@ -200,7 +201,7 @@ export class HTMLGenerator {
200
201
  layoutFrontmatter: context.layoutBundle?.frontmatter,
201
202
  ssrHash: context.ssrHash,
202
203
  }, htmlOptions, context.options?.params, context.options?.props, reactContent, projectCSSPromise);
203
- const { scripts, other } = this.buildHeadElements(head);
204
+ const { scripts, other } = buildCollectedHeadElements(head);
204
205
  if (!scripts && !other)
205
206
  return { start, end };
206
207
  let modifiedStart = start;
@@ -220,71 +221,6 @@ export class HTMLGenerator {
220
221
  }
221
222
  return { start: modifiedStart, end };
222
223
  }
223
- buildHeadElements(head) {
224
- if (!head)
225
- return { scripts: "", other: "" };
226
- const scriptParts = [];
227
- const otherParts = [];
228
- // Scripts go at TOP of head (before CSS) to prevent flash
229
- for (const script of head.scripts ?? []) {
230
- const { content, ...attrs } = script;
231
- const attrPairs = [["data-vf-head", "true"]];
232
- for (const [k, v] of Object.entries(attrs)) {
233
- if (v != null)
234
- attrPairs.push([k, v]);
235
- }
236
- // For inline scripts without id, add hash for client-side deduplication
237
- if (content && !attrs.id) {
238
- let sum = 0;
239
- for (let i = 0; i < Math.min(content.length, 200); i++) {
240
- sum = ((sum << 5) - sum + content.charCodeAt(i)) | 0;
241
- }
242
- attrPairs.push(["data-vf-hash", "vf" + Math.abs(sum).toString(36)]);
243
- }
244
- const attrStr = attrPairs.map(([k, v]) => `${k}="${v}"`).join(" ");
245
- if (content) {
246
- scriptParts.push(`<script ${attrStr}>${content}</script>`);
247
- }
248
- else if (attrs.src) {
249
- scriptParts.push(`<script ${attrStr}></script>`);
250
- }
251
- }
252
- for (const meta of head.metas) {
253
- if (meta.name === "description")
254
- continue;
255
- const attrs = [];
256
- if (meta.name)
257
- attrs.push(`name="${meta.name}"`);
258
- if (meta.property)
259
- attrs.push(`property="${meta.property}"`);
260
- if (meta.content)
261
- attrs.push(`content="${meta.content}"`);
262
- if (attrs.length)
263
- otherParts.push(`<meta ${attrs.join(" ")}>`);
264
- }
265
- for (const link of head.links) {
266
- const attrs = Object.entries(link)
267
- .filter(([, v]) => v != null)
268
- .map(([k, v]) => `${k}="${v}"`)
269
- .join(" ");
270
- if (attrs)
271
- otherParts.push(`<link ${attrs}>`);
272
- }
273
- for (const style of head.styles) {
274
- otherParts.push(`<style>${style}</style>`);
275
- }
276
- return {
277
- scripts: scriptParts.join("\n "),
278
- other: otherParts.join("\n "),
279
- };
280
- }
281
- mergeFrontmatter(context) {
282
- return {
283
- ...context.pageInfo.entity.frontmatter,
284
- ...context.pageBundle.frontmatter,
285
- ...(context.collectedMetadata || {}),
286
- };
287
- }
288
224
  resolveAppPath() {
289
225
  return resolveAppComponentPath(this.config.projectDir, this.config.adapter, this.config.config);
290
226
  }
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.170";
1
+ export declare const VERSION = "0.1.173";
2
2
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.170";
3
+ export const VERSION = "0.1.173";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.170",
3
+ "version": "0.1.173",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.170",
3
+ "version": "0.1.173",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -13,7 +13,10 @@ import {
13
13
  createRuntimeJsonSchema,
14
14
  createRuntimeTool,
15
15
  } from "./runtime-tool-builder.js";
16
- import { createAnthropicWebSearchToolSet } from "./provider-native-tools.js";
16
+ import {
17
+ createAnthropicWebFetchToolSet,
18
+ createAnthropicWebSearchToolSet,
19
+ } from "./provider-native-tools.js";
17
20
 
18
21
  export interface ConvertToolsToRuntimeToolsOptions {
19
22
  model?: string;
@@ -35,7 +38,11 @@ function resolveHostedProvider(model?: string): string | undefined {
35
38
  function resolveProviderNativeTools(
36
39
  options?: ConvertToolsToRuntimeToolsOptions,
37
40
  ): RuntimeToolSet | undefined {
38
- if (!options?.allowedToolNames?.includes("web_search")) {
41
+ if (
42
+ !options?.allowedToolNames?.some((toolName) =>
43
+ toolName === "web_search" || toolName === "web_fetch"
44
+ )
45
+ ) {
39
46
  return undefined;
40
47
  }
41
48
 
@@ -43,7 +50,10 @@ function resolveProviderNativeTools(
43
50
  return undefined;
44
51
  }
45
52
 
46
- return createAnthropicWebSearchToolSet();
53
+ return {
54
+ ...createAnthropicWebSearchToolSet(),
55
+ ...createAnthropicWebFetchToolSet(),
56
+ };
47
57
  }
48
58
 
49
59
  /**
@@ -46,6 +46,63 @@ const WEB_SEARCH_OUTPUT_SCHEMA: JsonSchema = {
46
46
  },
47
47
  };
48
48
 
49
+ const WEB_FETCH_INPUT_SCHEMA: JsonSchema = {
50
+ type: "object",
51
+ properties: {
52
+ url: {
53
+ type: "string",
54
+ },
55
+ },
56
+ required: ["url"],
57
+ additionalProperties: false,
58
+ };
59
+
60
+ const WEB_FETCH_OUTPUT_SCHEMA: JsonSchema = {
61
+ type: "object",
62
+ properties: {
63
+ type: {
64
+ type: "string",
65
+ const: "web_fetch_result",
66
+ },
67
+ url: {
68
+ type: "string",
69
+ },
70
+ content: {
71
+ type: "object",
72
+ properties: {
73
+ type: {
74
+ type: "string",
75
+ const: "document",
76
+ },
77
+ source: {
78
+ type: "object",
79
+ properties: {
80
+ type: {
81
+ type: "string",
82
+ enum: ["text", "base64"],
83
+ },
84
+ mediaType: {
85
+ type: "string",
86
+ },
87
+ data: {
88
+ type: "string",
89
+ },
90
+ },
91
+ required: ["type", "mediaType", "data"],
92
+ additionalProperties: true,
93
+ },
94
+ },
95
+ required: ["type", "source"],
96
+ additionalProperties: true,
97
+ },
98
+ retrievedAt: {
99
+ type: "string",
100
+ },
101
+ },
102
+ required: ["type", "url", "content", "retrievedAt"],
103
+ additionalProperties: false,
104
+ };
105
+
49
106
  export function createAnthropicWebSearchToolSet(): RuntimeToolSet {
50
107
  return {
51
108
  web_search: createRuntimeProviderTool({
@@ -59,3 +116,15 @@ export function createAnthropicWebSearchToolSet(): RuntimeToolSet {
59
116
  }),
60
117
  };
61
118
  }
119
+
120
+ export function createAnthropicWebFetchToolSet(): RuntimeToolSet {
121
+ return {
122
+ web_fetch: createRuntimeProviderTool({
123
+ id: "anthropic.web_fetch_20250910",
124
+ args: {},
125
+ inputSchema: createLazyRuntimeJsonSchema(WEB_FETCH_INPUT_SCHEMA),
126
+ outputSchema: createLazyRuntimeJsonSchema(WEB_FETCH_OUTPUT_SCHEMA),
127
+ supportsDeferredResults: true,
128
+ }),
129
+ };
130
+ }
@@ -396,6 +396,16 @@ export class ReadOperations {
396
396
  }
397
397
  }
398
398
 
399
+ private storeFetchedContent(
400
+ cacheKey: string,
401
+ content: string,
402
+ shouldCache: boolean,
403
+ ): string {
404
+ if (shouldCache) this.cache.set(cacheKey, content);
405
+ setRequestScopedFile(cacheKey, content);
406
+ return content;
407
+ }
408
+
399
409
  private async fetchContent(normalizedPath: string): Promise<string> {
400
410
  // Framework paths should NEVER be fetched from API - they must be read from local filesystem.
401
411
  // If we reach here for a framework path, the module server's local resolution failed.
@@ -581,9 +591,7 @@ export class ReadOperations {
581
591
  releaseId,
582
592
  });
583
593
 
584
- if (shouldCache) this.cache.set(cacheKey, content);
585
- setRequestScopedFile(cacheKey, content);
586
- return content;
594
+ return this.storeFetchedContent(cacheKey, content, shouldCache);
587
595
  } catch (error) {
588
596
  const errorMessage = error instanceof Error ? error.message : String(error);
589
597
  const is404Error = isNotFoundLikeError(error);
@@ -642,9 +650,7 @@ export class ReadOperations {
642
650
  contentLength: result.content.length,
643
651
  });
644
652
 
645
- if (shouldCache) this.cache.set(cacheKey, result.content);
646
- setRequestScopedFile(cacheKey, result.content);
647
- return result.content;
653
+ return this.storeFetchedContent(cacheKey, result.content, shouldCache);
648
654
  } catch (error) {
649
655
  logger.debug("Pattern search failed, trying sequential fallback", {
650
656
  originalPath: apiPath,
@@ -713,9 +719,7 @@ export class ReadOperations {
713
719
  candidateCount: candidates.length,
714
720
  });
715
721
 
716
- if (shouldCache) this.cache.set(cacheKey, content);
717
- setRequestScopedFile(cacheKey, content);
718
- return content;
722
+ return this.storeFetchedContent(cacheKey, content, shouldCache);
719
723
  } catch (_) {
720
724
  /* expected: this extension variant does not exist, try next priority */
721
725
  continue;
@@ -746,8 +750,6 @@ export class ReadOperations {
746
750
  willCache: shouldCache,
747
751
  });
748
752
 
749
- if (shouldCache) this.cache.set(cacheKey, content);
750
- setRequestScopedFile(cacheKey, content);
751
- return content;
753
+ return this.storeFetchedContent(cacheKey, content, shouldCache);
752
754
  }
753
755
  }
@@ -723,6 +723,19 @@ function buildAnthropicGenerateResult(payload: unknown): {
723
723
  result: block.content,
724
724
  });
725
725
  }
726
+
727
+ if (
728
+ blockType === "web_fetch_tool_result" &&
729
+ typeof block?.tool_use_id === "string" &&
730
+ readRecord(block?.content)
731
+ ) {
732
+ normalized.push({
733
+ type: "tool-result",
734
+ toolCallId: block.tool_use_id,
735
+ toolName: "web_fetch",
736
+ result: block.content,
737
+ });
738
+ }
726
739
  }
727
740
 
728
741
  return {
@@ -851,6 +864,20 @@ async function* streamAnthropicCompatibleParts(
851
864
  };
852
865
  }
853
866
 
867
+ if (
868
+ blockType === "web_fetch_tool_result" &&
869
+ typeof contentBlock?.tool_use_id === "string" &&
870
+ readRecord(contentBlock?.content)
871
+ ) {
872
+ yield {
873
+ type: "tool-result",
874
+ toolCallId: contentBlock.tool_use_id,
875
+ toolName: "web_fetch",
876
+ result: contentBlock.content,
877
+ providerExecuted: true,
878
+ };
879
+ }
880
+
854
881
  continue;
855
882
  }
856
883
 
@@ -0,0 +1,74 @@
1
+ import type { CollectedHead } from "../../react/head-collector.js";
2
+ import type { MdxBundle, MDXFrontmatter } from "../../types/index.js";
3
+
4
+ interface FrontmatterContextLike {
5
+ pageInfo: { entity: { frontmatter?: Record<string, unknown> } };
6
+ pageBundle: Pick<MdxBundle, "frontmatter">;
7
+ collectedMetadata?: Record<string, unknown>;
8
+ }
9
+
10
+ export function buildHeadElements(head?: CollectedHead): { scripts: string; other: string } {
11
+ if (!head) return { scripts: "", other: "" };
12
+
13
+ const scriptParts: string[] = [];
14
+ const otherParts: string[] = [];
15
+
16
+ for (const script of head.scripts ?? []) {
17
+ const { content, ...attrs } = script;
18
+ const attrPairs: [string, string][] = [["data-vf-head", "true"]];
19
+
20
+ for (const [k, v] of Object.entries(attrs)) {
21
+ if (v != null) attrPairs.push([k, v]);
22
+ }
23
+
24
+ if (content && !attrs.id) {
25
+ let sum = 0;
26
+ for (let i = 0; i < Math.min(content.length, 200); i++) {
27
+ sum = ((sum << 5) - sum + content.charCodeAt(i)) | 0;
28
+ }
29
+ attrPairs.push(["data-vf-hash", "vf" + Math.abs(sum).toString(36)]);
30
+ }
31
+
32
+ const attrStr = attrPairs.map(([k, v]) => `${k}="${v}"`).join(" ");
33
+ if (content) {
34
+ scriptParts.push(`<script ${attrStr}>${content}</script>`);
35
+ } else if (attrs.src) {
36
+ scriptParts.push(`<script ${attrStr}></script>`);
37
+ }
38
+ }
39
+
40
+ for (const meta of head.metas) {
41
+ if (meta.name === "description") continue;
42
+
43
+ const attrs: string[] = [];
44
+ if (meta.name) attrs.push(`name="${meta.name}"`);
45
+ if (meta.property) attrs.push(`property="${meta.property}"`);
46
+ if (meta.content) attrs.push(`content="${meta.content}"`);
47
+ if (attrs.length) otherParts.push(`<meta ${attrs.join(" ")}>`);
48
+ }
49
+
50
+ for (const link of head.links) {
51
+ const attrs = Object.entries(link)
52
+ .filter(([, v]) => v != null)
53
+ .map(([k, v]) => `${k}="${v}"`)
54
+ .join(" ");
55
+ if (attrs) otherParts.push(`<link ${attrs}>`);
56
+ }
57
+
58
+ for (const style of head.styles) {
59
+ otherParts.push(`<style>${style}</style>`);
60
+ }
61
+
62
+ return {
63
+ scripts: scriptParts.join("\n "),
64
+ other: otherParts.join("\n "),
65
+ };
66
+ }
67
+
68
+ export function mergeFrontmatter(context: FrontmatterContextLike): MDXFrontmatter {
69
+ return {
70
+ ...context.pageInfo.entity.frontmatter,
71
+ ...context.pageBundle.frontmatter,
72
+ ...(context.collectedMetadata ?? {}),
73
+ } as MDXFrontmatter;
74
+ }
@@ -37,6 +37,10 @@ import {
37
37
  startPreparedCSSWarmup,
38
38
  startProjectCSSPreparation,
39
39
  } from "./html-project-css.js";
40
+ import {
41
+ buildHeadElements as buildCollectedHeadElements,
42
+ mergeFrontmatter as mergeCollectedFrontmatter,
43
+ } from "./html-head.js";
40
44
 
41
45
  const logger = rendererLogger.component("html-generator");
42
46
 
@@ -130,7 +134,7 @@ export class HTMLGenerator {
130
134
  if (isFullHTMLDocument(context.html)) {
131
135
  let projectCSSPromise: Promise<ProjectCSSResult> | undefined;
132
136
  if (this.config.mode === "production" && context.options?.environment === "production") {
133
- const mergedFrontmatter = this.mergeFrontmatter(context);
137
+ const mergedFrontmatter = mergeCollectedFrontmatter(context);
134
138
  const htmlOptions = await profilePhase(
135
139
  "html.build_options",
136
140
  () => this.buildHTMLOptions(context, mergedFrontmatter),
@@ -156,7 +160,7 @@ export class HTMLGenerator {
156
160
  context: Omit<HTMLGenerationContext, "html">,
157
161
  ): Promise<ReadableStream> {
158
162
  const fullContext = context as HTMLGenerationContext;
159
- const mergedFrontmatter = this.mergeFrontmatter(fullContext);
163
+ const mergedFrontmatter = mergeCollectedFrontmatter(fullContext);
160
164
  const htmlOptions = await profilePhase(
161
165
  "html.build_options",
162
166
  () => this.buildHTMLOptions(fullContext, mergedFrontmatter),
@@ -313,7 +317,7 @@ export class HTMLGenerator {
313
317
  }
314
318
 
315
319
  private async wrapHTMLFragment(context: HTMLGenerationContext): Promise<string> {
316
- const mergedFrontmatter = this.mergeFrontmatter(context);
320
+ const mergedFrontmatter = mergeCollectedFrontmatter(context);
317
321
  const htmlOptions = await profilePhase(
318
322
  "html.build_options",
319
323
  () => this.buildHTMLOptions(context, mergedFrontmatter),
@@ -369,7 +373,7 @@ export class HTMLGenerator {
369
373
  projectCSSPromise,
370
374
  );
371
375
 
372
- const { scripts, other } = this.buildHeadElements(head);
376
+ const { scripts, other } = buildCollectedHeadElements(head);
373
377
  if (!scripts && !other) return { start, end };
374
378
 
375
379
  let modifiedStart = start;
@@ -393,74 +397,6 @@ export class HTMLGenerator {
393
397
  return { start: modifiedStart, end };
394
398
  }
395
399
 
396
- private buildHeadElements(head?: CollectedHead): { scripts: string; other: string } {
397
- if (!head) return { scripts: "", other: "" };
398
-
399
- const scriptParts: string[] = [];
400
- const otherParts: string[] = [];
401
-
402
- // Scripts go at TOP of head (before CSS) to prevent flash
403
- for (const script of head.scripts ?? []) {
404
- const { content, ...attrs } = script;
405
- const attrPairs: [string, string][] = [["data-vf-head", "true"]];
406
-
407
- for (const [k, v] of Object.entries(attrs)) {
408
- if (v != null) attrPairs.push([k, v]);
409
- }
410
-
411
- // For inline scripts without id, add hash for client-side deduplication
412
- if (content && !attrs.id) {
413
- let sum = 0;
414
- for (let i = 0; i < Math.min(content.length, 200); i++) {
415
- sum = ((sum << 5) - sum + content.charCodeAt(i)) | 0;
416
- }
417
- attrPairs.push(["data-vf-hash", "vf" + Math.abs(sum).toString(36)]);
418
- }
419
-
420
- const attrStr = attrPairs.map(([k, v]) => `${k}="${v}"`).join(" ");
421
- if (content) {
422
- scriptParts.push(`<script ${attrStr}>${content}</script>`);
423
- } else if (attrs.src) {
424
- scriptParts.push(`<script ${attrStr}></script>`);
425
- }
426
- }
427
-
428
- for (const meta of head.metas) {
429
- if (meta.name === "description") continue;
430
-
431
- const attrs: string[] = [];
432
- if (meta.name) attrs.push(`name="${meta.name}"`);
433
- if (meta.property) attrs.push(`property="${meta.property}"`);
434
- if (meta.content) attrs.push(`content="${meta.content}"`);
435
- if (attrs.length) otherParts.push(`<meta ${attrs.join(" ")}>`);
436
- }
437
-
438
- for (const link of head.links) {
439
- const attrs = Object.entries(link)
440
- .filter(([, v]) => v != null)
441
- .map(([k, v]) => `${k}="${v}"`)
442
- .join(" ");
443
- if (attrs) otherParts.push(`<link ${attrs}>`);
444
- }
445
-
446
- for (const style of head.styles) {
447
- otherParts.push(`<style>${style}</style>`);
448
- }
449
-
450
- return {
451
- scripts: scriptParts.join("\n "),
452
- other: otherParts.join("\n "),
453
- };
454
- }
455
-
456
- private mergeFrontmatter(context: HTMLGenerationContext): MDXFrontmatter {
457
- return {
458
- ...context.pageInfo.entity.frontmatter,
459
- ...(context.pageBundle as MdxBundle).frontmatter,
460
- ...(context.collectedMetadata || {}),
461
- } as MDXFrontmatter;
462
- }
463
-
464
400
  private resolveAppPath(): Promise<string | null> {
465
401
  return resolveAppComponentPath(
466
402
  this.config.projectDir,
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.170";
3
+ export const VERSION = "0.1.173";