@agent-native/core 0.68.2 → 0.69.0

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 (41) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +12 -0
  3. package/corpus/core/docs/content/template-clips.md +12 -7
  4. package/corpus/core/package.json +1 -1
  5. package/corpus/core/src/client/AgentPanel.tsx +2 -4
  6. package/corpus/core/src/extensions/content-patch.ts +12 -2
  7. package/corpus/core/src/extensions/web-search-tool.ts +45 -4
  8. package/corpus/core/src/secrets/register-framework-secrets.ts +7 -0
  9. package/corpus/core/src/server/social-og-image.ts +6 -1
  10. package/corpus/core/src/vite/client.ts +83 -1
  11. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +69 -13
  12. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +38 -2
  13. package/corpus/templates/clips/app/lib/capture-install-options.ts +2 -1
  14. package/corpus/templates/clips/app/lib/recorder-preferences.ts +67 -0
  15. package/corpus/templates/clips/app/routes/_app.trash.tsx +21 -0
  16. package/corpus/templates/clips/app/routes/record.tsx +14 -3
  17. package/corpus/templates/clips/chrome-extension/STORE_DRAFT.md +5 -2
  18. package/corpus/templates/content/vite.config.ts +37 -1
  19. package/corpus/templates/content/vitest.config.ts +3 -0
  20. package/dist/client/AgentPanel.d.ts +1 -1
  21. package/dist/client/AgentPanel.d.ts.map +1 -1
  22. package/dist/client/AgentPanel.js +1 -1
  23. package/dist/client/AgentPanel.js.map +1 -1
  24. package/dist/extensions/content-patch.d.ts.map +1 -1
  25. package/dist/extensions/content-patch.js +10 -2
  26. package/dist/extensions/content-patch.js.map +1 -1
  27. package/dist/extensions/web-search-tool.d.ts +5 -3
  28. package/dist/extensions/web-search-tool.d.ts.map +1 -1
  29. package/dist/extensions/web-search-tool.js +36 -4
  30. package/dist/extensions/web-search-tool.js.map +1 -1
  31. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  32. package/dist/secrets/register-framework-secrets.js +6 -0
  33. package/dist/secrets/register-framework-secrets.js.map +1 -1
  34. package/dist/server/social-og-image.d.ts.map +1 -1
  35. package/dist/server/social-og-image.js +5 -1
  36. package/dist/server/social-og-image.js.map +1 -1
  37. package/dist/vite/client.d.ts.map +1 -1
  38. package/dist/vite/client.js +83 -1
  39. package/dist/vite/client.js.map +1 -1
  40. package/docs/content/template-clips.md +12 -7
  41. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"content-patch.d.ts","sourceRoot":"","sources":["../../src/extensions/content-patch.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAC5B;IACE,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,eAAe,GAAG,cAAc,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,iBAAiB,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,iBAAiB,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,cAAc,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,gBAAgB,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,eAAe,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEN,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,2BAA2B,CAC/C,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,4BAA4B,CAAC,CA+BvC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY1E"}
1
+ {"version":3,"file":"content-patch.d.ts","sourceRoot":"","sources":["../../src/extensions/content-patch.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAC5B;IACE,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,eAAe,GAAG,cAAc,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,iBAAiB,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,iBAAiB,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,cAAc,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,gBAAgB,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,EAAE,EAAE,eAAe,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEN,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,2BAA2B,CAC/C,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,4BAA4B,CAAC,CA+BvC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB1E"}
@@ -29,13 +29,21 @@ export async function applyExtensionContentUpdate(currentContent, opts) {
29
29
  export async function formatExtensionHtml(content) {
30
30
  try {
31
31
  const prettier = await import("prettier");
32
- return await prettier.format(content, {
32
+ const formatted = await prettier.format(content, {
33
33
  parser: "html",
34
34
  htmlWhitespaceSensitivity: "ignore",
35
35
  });
36
+ return typeof formatted === "string" ? formatted : content;
36
37
  }
37
38
  catch (err) {
38
- throw new Error(`Unable to format extension HTML with Prettier: ${err?.message ?? err}`);
39
+ const message = String(err?.message ?? err);
40
+ if (message.includes("Cannot find package 'prettier'") ||
41
+ message.includes('Cannot find package "prettier"') ||
42
+ message.includes("Cannot find module 'prettier'") ||
43
+ message.includes('Cannot find module "prettier"')) {
44
+ return content;
45
+ }
46
+ throw new Error(`Unable to format extension HTML with Prettier: ${message}`);
39
47
  }
40
48
  }
41
49
  function applyEdit(content, edit) {
@@ -1 +1 @@
1
- {"version":3,"file":"content-patch.js","sourceRoot":"","sources":["../../src/extensions/content-patch.ts"],"names":[],"mappings":"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","sourcesContent":["export type ExtensionLegacyPatch = {\n find: string;\n replace: string;\n all?: boolean;\n expectedMatches?: number;\n required?: boolean;\n};\n\nexport type ExtensionContentEdit =\n | {\n op?: \"replace\";\n find: string;\n replace: string;\n all?: boolean;\n occurrence?: number;\n expectedMatches?: number;\n required?: boolean;\n }\n | {\n op: \"insert-before\" | \"insert-after\";\n marker: string;\n content: string;\n occurrence?: number;\n expectedMatches?: number;\n required?: boolean;\n }\n | {\n op: \"replace-between\";\n start: string;\n end: string;\n content: string;\n includeDelimiters?: boolean;\n expectedMatches?: number;\n required?: boolean;\n }\n | {\n op: \"replace-section\";\n section: string;\n content: string;\n keepMarkers?: boolean;\n required?: boolean;\n }\n | {\n op: \"wrap-section\";\n section: string;\n before: string;\n after: string;\n keepMarkers?: boolean;\n required?: boolean;\n }\n | {\n op: \"remove-section\";\n section: string;\n keepMarkers?: boolean;\n required?: boolean;\n }\n | {\n op: \"regex-replace\";\n pattern: string;\n replace: string;\n flags?: string;\n all?: boolean;\n expectedMatches?: number;\n required?: boolean;\n };\n\nexport interface ExtensionContentUpdateOpts {\n content?: string;\n patches?: ExtensionLegacyPatch[];\n edits?: ExtensionContentEdit[];\n format?: boolean;\n}\n\nexport interface ExtensionContentUpdateResult {\n content: string;\n applied: string[];\n formatted: boolean;\n}\n\nexport async function applyExtensionContentUpdate(\n currentContent: string,\n opts: ExtensionContentUpdateOpts,\n): Promise<ExtensionContentUpdateResult> {\n let content = opts.content ?? currentContent;\n const applied: string[] = [];\n\n for (const patch of opts.patches ?? []) {\n const edit: ExtensionContentEdit = {\n op: \"replace\",\n find: patch.find,\n replace: patch.replace,\n all: patch.all,\n expectedMatches: patch.expectedMatches,\n required: patch.required,\n };\n const result = applyEdit(content, edit);\n content = result.content;\n applied.push(result.summary);\n }\n\n for (const edit of opts.edits ?? []) {\n const result = applyEdit(content, edit);\n content = result.content;\n applied.push(result.summary);\n }\n\n let formatted = false;\n if (opts.format) {\n content = await formatExtensionHtml(content);\n formatted = true;\n }\n\n return { content, applied, formatted };\n}\n\nexport async function formatExtensionHtml(content: string): Promise<string> {\n try {\n const prettier = await import(\"prettier\");\n return await prettier.format(content, {\n parser: \"html\",\n htmlWhitespaceSensitivity: \"ignore\",\n });\n } catch (err: any) {\n throw new Error(\n `Unable to format extension HTML with Prettier: ${err?.message ?? err}`,\n );\n }\n}\n\nfunction applyEdit(\n content: string,\n edit: ExtensionContentEdit,\n): { content: string; summary: string } {\n const op = edit.op ?? \"replace\";\n switch (op) {\n case \"replace\":\n return applyLiteralReplace(\n content,\n edit as Extract<ExtensionContentEdit, { op?: \"replace\" }>,\n );\n case \"insert-before\":\n case \"insert-after\":\n return applyInsert(\n content,\n edit as Extract<\n ExtensionContentEdit,\n { op: \"insert-before\" | \"insert-after\" }\n >,\n );\n case \"replace-between\":\n return applyReplaceBetween(\n content,\n edit as Extract<ExtensionContentEdit, { op: \"replace-between\" }>,\n );\n case \"replace-section\":\n case \"wrap-section\":\n case \"remove-section\":\n return applySectionEdit(\n content,\n edit as Extract<\n ExtensionContentEdit,\n { op: \"replace-section\" | \"wrap-section\" | \"remove-section\" }\n >,\n );\n case \"regex-replace\":\n return applyRegexReplace(\n content,\n edit as Extract<ExtensionContentEdit, { op: \"regex-replace\" }>,\n );\n default:\n throw new Error(`Unsupported extension edit operation: ${op}`);\n }\n}\n\nfunction applyLiteralReplace(\n content: string,\n edit: Extract<ExtensionContentEdit, { op?: \"replace\" }>,\n): { content: string; summary: string } {\n const matches = countOccurrences(content, edit.find);\n assertMatchCount(\"replace\", matches, edit.expectedMatches, edit.required);\n if (matches === 0) return { content, summary: \"replace:0\" };\n\n if (edit.occurrence !== undefined) {\n return {\n content: replaceNth(content, edit.find, edit.replace, edit.occurrence),\n summary: `replace:nth:${edit.occurrence}`,\n };\n }\n\n if (edit.all) {\n return {\n content: content.split(edit.find).join(edit.replace),\n summary: `replace:all:${matches}`,\n };\n }\n\n return {\n content: content.replace(edit.find, edit.replace),\n summary: \"replace:first\",\n };\n}\n\nfunction applyInsert(\n content: string,\n edit: Extract<ExtensionContentEdit, { op: \"insert-before\" | \"insert-after\" }>,\n): { content: string; summary: string } {\n const matches = countOccurrences(content, edit.marker);\n assertMatchCount(edit.op, matches, edit.expectedMatches, edit.required);\n if (matches === 0) return { content, summary: `${edit.op}:0` };\n\n const occurrence = edit.occurrence ?? 1;\n const index = nthIndexOf(content, edit.marker, occurrence);\n if (index < 0) {\n throw new Error(`${edit.op} could not find occurrence ${occurrence}`);\n }\n const insertAt =\n edit.op === \"insert-before\" ? index : index + edit.marker.length;\n return {\n content:\n content.slice(0, insertAt) + edit.content + content.slice(insertAt),\n summary: `${edit.op}:${occurrence}`,\n };\n}\n\nfunction applyReplaceBetween(\n content: string,\n edit: Extract<ExtensionContentEdit, { op: \"replace-between\" }>,\n): { content: string; summary: string } {\n const ranges = findBetweenRanges(content, edit.start, edit.end);\n assertMatchCount(\n \"replace-between\",\n ranges.length,\n edit.expectedMatches,\n edit.required,\n );\n if (!ranges.length) return { content, summary: \"replace-between:0\" };\n if (ranges.length > 1 && edit.expectedMatches === undefined) {\n throw new Error(\n `replace-between matched ${ranges.length} ranges; pass expectedMatches to confirm`,\n );\n }\n\n let next = content;\n for (const range of ranges.slice().reverse()) {\n const start = edit.includeDelimiters ? range.start : range.innerStart;\n const end = edit.includeDelimiters ? range.end : range.innerEnd;\n next = next.slice(0, start) + edit.content + next.slice(end);\n }\n return { content: next, summary: `replace-between:${ranges.length}` };\n}\n\nfunction applySectionEdit(\n content: string,\n edit: Extract<\n ExtensionContentEdit,\n { op: \"replace-section\" | \"wrap-section\" | \"remove-section\" }\n >,\n): { content: string; summary: string } {\n const section = findSection(content, edit.section);\n const required = edit.required !== false;\n if (!section) {\n if (required) throw new Error(`Section not found: ${edit.section}`);\n return { content, summary: `${edit.op}:0` };\n }\n\n const keepMarkers = edit.keepMarkers !== false;\n const replaceStart = keepMarkers ? section.innerStart : section.start;\n const replaceEnd = keepMarkers ? section.innerEnd : section.end;\n const inner = content.slice(section.innerStart, section.innerEnd);\n let replacement = \"\";\n\n if (edit.op === \"replace-section\") {\n replacement = edit.content;\n } else if (edit.op === \"wrap-section\") {\n replacement = edit.before + inner + edit.after;\n } else {\n replacement = \"\";\n }\n\n return {\n content:\n content.slice(0, replaceStart) + replacement + content.slice(replaceEnd),\n summary: `${edit.op}:${edit.section}`,\n };\n}\n\nfunction applyRegexReplace(\n content: string,\n edit: Extract<ExtensionContentEdit, { op: \"regex-replace\" }>,\n): { content: string; summary: string } {\n const flags = normalizeRegexFlags(edit.flags, edit.all);\n const regex = new RegExp(edit.pattern, flags);\n const countRegex = new RegExp(edit.pattern, ensureGlobal(flags));\n const matches = Array.from(content.matchAll(countRegex)).length;\n assertMatchCount(\n \"regex-replace\",\n matches,\n edit.expectedMatches,\n edit.required,\n );\n if (matches === 0) return { content, summary: \"regex-replace:0\" };\n return {\n content: content.replace(regex, edit.replace),\n summary: `regex-replace:${edit.all ? \"all\" : \"first\"}:${matches}`,\n };\n}\n\nfunction assertMatchCount(\n op: string,\n actual: number,\n expected: number | undefined,\n required: boolean | undefined,\n): void {\n if (expected !== undefined && actual !== expected) {\n throw new Error(`${op} expected ${expected} match(es), found ${actual}`);\n }\n if (expected === undefined && required !== false && actual === 0) {\n throw new Error(`${op} found no matches`);\n }\n}\n\nfunction countOccurrences(content: string, needle: string): number {\n if (!needle) throw new Error(\"Patch find/marker text cannot be empty\");\n let count = 0;\n let index = 0;\n while (true) {\n index = content.indexOf(needle, index);\n if (index < 0) return count;\n count += 1;\n index += needle.length;\n }\n}\n\nfunction nthIndexOf(\n content: string,\n needle: string,\n occurrence: number,\n): number {\n if (!Number.isInteger(occurrence) || occurrence < 1) {\n throw new Error(\"occurrence must be a positive integer\");\n }\n let index = -1;\n let from = 0;\n for (let i = 0; i < occurrence; i += 1) {\n index = content.indexOf(needle, from);\n if (index < 0) return -1;\n from = index + needle.length;\n }\n return index;\n}\n\nfunction replaceNth(\n content: string,\n find: string,\n replace: string,\n occurrence: number,\n): string {\n const index = nthIndexOf(content, find, occurrence);\n if (index < 0) {\n throw new Error(`replace could not find occurrence ${occurrence}`);\n }\n return content.slice(0, index) + replace + content.slice(index + find.length);\n}\n\nfunction findBetweenRanges(\n content: string,\n startMarker: string,\n endMarker: string,\n): Array<{ start: number; innerStart: number; innerEnd: number; end: number }> {\n if (!startMarker || !endMarker) {\n throw new Error(\"replace-between requires non-empty start and end markers\");\n }\n const ranges: Array<{\n start: number;\n innerStart: number;\n innerEnd: number;\n end: number;\n }> = [];\n let cursor = 0;\n while (cursor < content.length) {\n const start = content.indexOf(startMarker, cursor);\n if (start < 0) break;\n const innerStart = start + startMarker.length;\n const innerEnd = content.indexOf(endMarker, innerStart);\n if (innerEnd < 0) {\n throw new Error(\"replace-between found a start marker without an end\");\n }\n const end = innerEnd + endMarker.length;\n ranges.push({ start, innerStart, innerEnd, end });\n cursor = end;\n }\n return ranges;\n}\n\nfunction findSection(\n content: string,\n sectionId: string,\n): { start: number; innerStart: number; innerEnd: number; end: number } | null {\n if (!sectionId.trim()) throw new Error(\"section id cannot be empty\");\n const escaped = escapeRegex(sectionId.trim());\n const startRe = new RegExp(\n `<!--\\\\s*(?:agent-native:section\\\\s+${escaped}|section:${escaped}|section\\\\s+${escaped})\\\\s*-->`,\n );\n const startMatch = startRe.exec(content);\n if (!startMatch || startMatch.index === undefined) return null;\n\n const endRe = new RegExp(\n `<!--\\\\s*/(?:agent-native:section\\\\s+${escaped}|section:${escaped}|section\\\\s+${escaped})\\\\s*-->`,\n );\n endRe.lastIndex = startMatch.index + startMatch[0].length;\n const rest = content.slice(startMatch.index + startMatch[0].length);\n const endMatch = endRe.exec(rest);\n if (!endMatch || endMatch.index === undefined) {\n throw new Error(`Section ${sectionId} has a start marker without an end`);\n }\n\n const start = startMatch.index;\n const innerStart = startMatch.index + startMatch[0].length;\n const innerEnd = innerStart + endMatch.index;\n const end = innerEnd + endMatch[0].length;\n return { start, innerStart, innerEnd, end };\n}\n\nfunction normalizeRegexFlags(flags: string | undefined, all?: boolean): string {\n const unique = new Set((flags ?? \"\").split(\"\").filter(Boolean));\n if (all) unique.add(\"g\");\n return Array.from(unique).join(\"\");\n}\n\nfunction ensureGlobal(flags: string): string {\n return flags.includes(\"g\") ? flags : `${flags}g`;\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"]}
1
+ {"version":3,"file":"content-patch.js","sourceRoot":"","sources":["../../src/extensions/content-patch.ts"],"names":[],"mappings":"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","sourcesContent":["export type ExtensionLegacyPatch = {\n find: string;\n replace: string;\n all?: boolean;\n expectedMatches?: number;\n required?: boolean;\n};\n\nexport type ExtensionContentEdit =\n | {\n op?: \"replace\";\n find: string;\n replace: string;\n all?: boolean;\n occurrence?: number;\n expectedMatches?: number;\n required?: boolean;\n }\n | {\n op: \"insert-before\" | \"insert-after\";\n marker: string;\n content: string;\n occurrence?: number;\n expectedMatches?: number;\n required?: boolean;\n }\n | {\n op: \"replace-between\";\n start: string;\n end: string;\n content: string;\n includeDelimiters?: boolean;\n expectedMatches?: number;\n required?: boolean;\n }\n | {\n op: \"replace-section\";\n section: string;\n content: string;\n keepMarkers?: boolean;\n required?: boolean;\n }\n | {\n op: \"wrap-section\";\n section: string;\n before: string;\n after: string;\n keepMarkers?: boolean;\n required?: boolean;\n }\n | {\n op: \"remove-section\";\n section: string;\n keepMarkers?: boolean;\n required?: boolean;\n }\n | {\n op: \"regex-replace\";\n pattern: string;\n replace: string;\n flags?: string;\n all?: boolean;\n expectedMatches?: number;\n required?: boolean;\n };\n\nexport interface ExtensionContentUpdateOpts {\n content?: string;\n patches?: ExtensionLegacyPatch[];\n edits?: ExtensionContentEdit[];\n format?: boolean;\n}\n\nexport interface ExtensionContentUpdateResult {\n content: string;\n applied: string[];\n formatted: boolean;\n}\n\nexport async function applyExtensionContentUpdate(\n currentContent: string,\n opts: ExtensionContentUpdateOpts,\n): Promise<ExtensionContentUpdateResult> {\n let content = opts.content ?? currentContent;\n const applied: string[] = [];\n\n for (const patch of opts.patches ?? []) {\n const edit: ExtensionContentEdit = {\n op: \"replace\",\n find: patch.find,\n replace: patch.replace,\n all: patch.all,\n expectedMatches: patch.expectedMatches,\n required: patch.required,\n };\n const result = applyEdit(content, edit);\n content = result.content;\n applied.push(result.summary);\n }\n\n for (const edit of opts.edits ?? []) {\n const result = applyEdit(content, edit);\n content = result.content;\n applied.push(result.summary);\n }\n\n let formatted = false;\n if (opts.format) {\n content = await formatExtensionHtml(content);\n formatted = true;\n }\n\n return { content, applied, formatted };\n}\n\nexport async function formatExtensionHtml(content: string): Promise<string> {\n try {\n const prettier = await import(\"prettier\");\n const formatted = await prettier.format(content, {\n parser: \"html\",\n htmlWhitespaceSensitivity: \"ignore\",\n });\n return typeof formatted === \"string\" ? formatted : content;\n } catch (err: any) {\n const message = String(err?.message ?? err);\n if (\n message.includes(\"Cannot find package 'prettier'\") ||\n message.includes('Cannot find package \"prettier\"') ||\n message.includes(\"Cannot find module 'prettier'\") ||\n message.includes('Cannot find module \"prettier\"')\n ) {\n return content;\n }\n throw new Error(\n `Unable to format extension HTML with Prettier: ${message}`,\n );\n }\n}\n\nfunction applyEdit(\n content: string,\n edit: ExtensionContentEdit,\n): { content: string; summary: string } {\n const op = edit.op ?? \"replace\";\n switch (op) {\n case \"replace\":\n return applyLiteralReplace(\n content,\n edit as Extract<ExtensionContentEdit, { op?: \"replace\" }>,\n );\n case \"insert-before\":\n case \"insert-after\":\n return applyInsert(\n content,\n edit as Extract<\n ExtensionContentEdit,\n { op: \"insert-before\" | \"insert-after\" }\n >,\n );\n case \"replace-between\":\n return applyReplaceBetween(\n content,\n edit as Extract<ExtensionContentEdit, { op: \"replace-between\" }>,\n );\n case \"replace-section\":\n case \"wrap-section\":\n case \"remove-section\":\n return applySectionEdit(\n content,\n edit as Extract<\n ExtensionContentEdit,\n { op: \"replace-section\" | \"wrap-section\" | \"remove-section\" }\n >,\n );\n case \"regex-replace\":\n return applyRegexReplace(\n content,\n edit as Extract<ExtensionContentEdit, { op: \"regex-replace\" }>,\n );\n default:\n throw new Error(`Unsupported extension edit operation: ${op}`);\n }\n}\n\nfunction applyLiteralReplace(\n content: string,\n edit: Extract<ExtensionContentEdit, { op?: \"replace\" }>,\n): { content: string; summary: string } {\n const matches = countOccurrences(content, edit.find);\n assertMatchCount(\"replace\", matches, edit.expectedMatches, edit.required);\n if (matches === 0) return { content, summary: \"replace:0\" };\n\n if (edit.occurrence !== undefined) {\n return {\n content: replaceNth(content, edit.find, edit.replace, edit.occurrence),\n summary: `replace:nth:${edit.occurrence}`,\n };\n }\n\n if (edit.all) {\n return {\n content: content.split(edit.find).join(edit.replace),\n summary: `replace:all:${matches}`,\n };\n }\n\n return {\n content: content.replace(edit.find, edit.replace),\n summary: \"replace:first\",\n };\n}\n\nfunction applyInsert(\n content: string,\n edit: Extract<ExtensionContentEdit, { op: \"insert-before\" | \"insert-after\" }>,\n): { content: string; summary: string } {\n const matches = countOccurrences(content, edit.marker);\n assertMatchCount(edit.op, matches, edit.expectedMatches, edit.required);\n if (matches === 0) return { content, summary: `${edit.op}:0` };\n\n const occurrence = edit.occurrence ?? 1;\n const index = nthIndexOf(content, edit.marker, occurrence);\n if (index < 0) {\n throw new Error(`${edit.op} could not find occurrence ${occurrence}`);\n }\n const insertAt =\n edit.op === \"insert-before\" ? index : index + edit.marker.length;\n return {\n content:\n content.slice(0, insertAt) + edit.content + content.slice(insertAt),\n summary: `${edit.op}:${occurrence}`,\n };\n}\n\nfunction applyReplaceBetween(\n content: string,\n edit: Extract<ExtensionContentEdit, { op: \"replace-between\" }>,\n): { content: string; summary: string } {\n const ranges = findBetweenRanges(content, edit.start, edit.end);\n assertMatchCount(\n \"replace-between\",\n ranges.length,\n edit.expectedMatches,\n edit.required,\n );\n if (!ranges.length) return { content, summary: \"replace-between:0\" };\n if (ranges.length > 1 && edit.expectedMatches === undefined) {\n throw new Error(\n `replace-between matched ${ranges.length} ranges; pass expectedMatches to confirm`,\n );\n }\n\n let next = content;\n for (const range of ranges.slice().reverse()) {\n const start = edit.includeDelimiters ? range.start : range.innerStart;\n const end = edit.includeDelimiters ? range.end : range.innerEnd;\n next = next.slice(0, start) + edit.content + next.slice(end);\n }\n return { content: next, summary: `replace-between:${ranges.length}` };\n}\n\nfunction applySectionEdit(\n content: string,\n edit: Extract<\n ExtensionContentEdit,\n { op: \"replace-section\" | \"wrap-section\" | \"remove-section\" }\n >,\n): { content: string; summary: string } {\n const section = findSection(content, edit.section);\n const required = edit.required !== false;\n if (!section) {\n if (required) throw new Error(`Section not found: ${edit.section}`);\n return { content, summary: `${edit.op}:0` };\n }\n\n const keepMarkers = edit.keepMarkers !== false;\n const replaceStart = keepMarkers ? section.innerStart : section.start;\n const replaceEnd = keepMarkers ? section.innerEnd : section.end;\n const inner = content.slice(section.innerStart, section.innerEnd);\n let replacement = \"\";\n\n if (edit.op === \"replace-section\") {\n replacement = edit.content;\n } else if (edit.op === \"wrap-section\") {\n replacement = edit.before + inner + edit.after;\n } else {\n replacement = \"\";\n }\n\n return {\n content:\n content.slice(0, replaceStart) + replacement + content.slice(replaceEnd),\n summary: `${edit.op}:${edit.section}`,\n };\n}\n\nfunction applyRegexReplace(\n content: string,\n edit: Extract<ExtensionContentEdit, { op: \"regex-replace\" }>,\n): { content: string; summary: string } {\n const flags = normalizeRegexFlags(edit.flags, edit.all);\n const regex = new RegExp(edit.pattern, flags);\n const countRegex = new RegExp(edit.pattern, ensureGlobal(flags));\n const matches = Array.from(content.matchAll(countRegex)).length;\n assertMatchCount(\n \"regex-replace\",\n matches,\n edit.expectedMatches,\n edit.required,\n );\n if (matches === 0) return { content, summary: \"regex-replace:0\" };\n return {\n content: content.replace(regex, edit.replace),\n summary: `regex-replace:${edit.all ? \"all\" : \"first\"}:${matches}`,\n };\n}\n\nfunction assertMatchCount(\n op: string,\n actual: number,\n expected: number | undefined,\n required: boolean | undefined,\n): void {\n if (expected !== undefined && actual !== expected) {\n throw new Error(`${op} expected ${expected} match(es), found ${actual}`);\n }\n if (expected === undefined && required !== false && actual === 0) {\n throw new Error(`${op} found no matches`);\n }\n}\n\nfunction countOccurrences(content: string, needle: string): number {\n if (!needle) throw new Error(\"Patch find/marker text cannot be empty\");\n let count = 0;\n let index = 0;\n while (true) {\n index = content.indexOf(needle, index);\n if (index < 0) return count;\n count += 1;\n index += needle.length;\n }\n}\n\nfunction nthIndexOf(\n content: string,\n needle: string,\n occurrence: number,\n): number {\n if (!Number.isInteger(occurrence) || occurrence < 1) {\n throw new Error(\"occurrence must be a positive integer\");\n }\n let index = -1;\n let from = 0;\n for (let i = 0; i < occurrence; i += 1) {\n index = content.indexOf(needle, from);\n if (index < 0) return -1;\n from = index + needle.length;\n }\n return index;\n}\n\nfunction replaceNth(\n content: string,\n find: string,\n replace: string,\n occurrence: number,\n): string {\n const index = nthIndexOf(content, find, occurrence);\n if (index < 0) {\n throw new Error(`replace could not find occurrence ${occurrence}`);\n }\n return content.slice(0, index) + replace + content.slice(index + find.length);\n}\n\nfunction findBetweenRanges(\n content: string,\n startMarker: string,\n endMarker: string,\n): Array<{ start: number; innerStart: number; innerEnd: number; end: number }> {\n if (!startMarker || !endMarker) {\n throw new Error(\"replace-between requires non-empty start and end markers\");\n }\n const ranges: Array<{\n start: number;\n innerStart: number;\n innerEnd: number;\n end: number;\n }> = [];\n let cursor = 0;\n while (cursor < content.length) {\n const start = content.indexOf(startMarker, cursor);\n if (start < 0) break;\n const innerStart = start + startMarker.length;\n const innerEnd = content.indexOf(endMarker, innerStart);\n if (innerEnd < 0) {\n throw new Error(\"replace-between found a start marker without an end\");\n }\n const end = innerEnd + endMarker.length;\n ranges.push({ start, innerStart, innerEnd, end });\n cursor = end;\n }\n return ranges;\n}\n\nfunction findSection(\n content: string,\n sectionId: string,\n): { start: number; innerStart: number; innerEnd: number; end: number } | null {\n if (!sectionId.trim()) throw new Error(\"section id cannot be empty\");\n const escaped = escapeRegex(sectionId.trim());\n const startRe = new RegExp(\n `<!--\\\\s*(?:agent-native:section\\\\s+${escaped}|section:${escaped}|section\\\\s+${escaped})\\\\s*-->`,\n );\n const startMatch = startRe.exec(content);\n if (!startMatch || startMatch.index === undefined) return null;\n\n const endRe = new RegExp(\n `<!--\\\\s*/(?:agent-native:section\\\\s+${escaped}|section:${escaped}|section\\\\s+${escaped})\\\\s*-->`,\n );\n endRe.lastIndex = startMatch.index + startMatch[0].length;\n const rest = content.slice(startMatch.index + startMatch[0].length);\n const endMatch = endRe.exec(rest);\n if (!endMatch || endMatch.index === undefined) {\n throw new Error(`Section ${sectionId} has a start marker without an end`);\n }\n\n const start = startMatch.index;\n const innerStart = startMatch.index + startMatch[0].length;\n const innerEnd = innerStart + endMatch.index;\n const end = innerEnd + endMatch[0].length;\n return { start, innerStart, innerEnd, end };\n}\n\nfunction normalizeRegexFlags(flags: string | undefined, all?: boolean): string {\n const unique = new Set((flags ?? \"\").split(\"\").filter(Boolean));\n if (all) unique.add(\"g\");\n return Array.from(unique).join(\"\");\n}\n\nfunction ensureGlobal(flags: string): string {\n return flags.includes(\"g\") ? flags : `${flags}g`;\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"]}
@@ -7,13 +7,15 @@
7
7
  * 1. Brave Search API (BRAVE_SEARCH_API_KEY)
8
8
  * 2. Tavily (TAVILY_API_KEY)
9
9
  * 3. Exa (EXA_API_KEY)
10
- * 4. Builder.io (connected Builder credentials)
10
+ * 4. Firecrawl (FIRECRAWL_API_KEY)
11
+ * 5. Builder.io (connected Builder credentials)
11
12
  *
12
13
  * The first configured backend wins. If none is configured, the tool
13
14
  * returns a helpful message telling the user which keys to add.
14
15
  *
15
- * Connect Builder.io or register BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, or
16
- * EXA_API_KEY via app secrets settings or environment variables.
16
+ * Connect Builder.io or register BRAVE_SEARCH_API_KEY, TAVILY_API_KEY,
17
+ * EXA_API_KEY, or FIRECRAWL_API_KEY via app secrets settings or environment
18
+ * variables.
17
19
  */
18
20
  import type { ActionEntry } from "../agent/production-agent.js";
19
21
  import type { CredentialContext } from "../credentials/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"web-search-tool.d.ts","sourceRoot":"","sources":["../../src/extensions/web-search-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAClB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,iBAAiB,KACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjC;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAC;IACtD;;OAEG;IACH,yBAAyB,CAAC,EAAE,MAAM,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACvE;;OAEG;IACH,0BAA0B,CAAC,EAAE,MAAM,MAAM,CAAC;IAC1C;;OAEG;IACH,wBAAwB,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD;AAKD,UAAU,2BAA2B;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAsND;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,GAAE,oBAAyB,GAC9B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA+G7B"}
1
+ {"version":3,"file":"web-search-tool.d.ts","sourceRoot":"","sources":["../../src/extensions/web-search-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAClB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,iBAAiB,KACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjC;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAC;IACtD;;OAEG;IACH,yBAAyB,CAAC,EAAE,MAAM,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACvE;;OAEG;IACH,0BAA0B,CAAC,EAAE,MAAM,MAAM,CAAC;IAC1C;;OAEG;IACH,wBAAwB,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD;AAKD,UAAU,2BAA2B;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAwPD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,GAAE,oBAAyB,GAC9B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAoH7B"}
@@ -7,13 +7,15 @@
7
7
  * 1. Brave Search API (BRAVE_SEARCH_API_KEY)
8
8
  * 2. Tavily (TAVILY_API_KEY)
9
9
  * 3. Exa (EXA_API_KEY)
10
- * 4. Builder.io (connected Builder credentials)
10
+ * 4. Firecrawl (FIRECRAWL_API_KEY)
11
+ * 5. Builder.io (connected Builder credentials)
11
12
  *
12
13
  * The first configured backend wins. If none is configured, the tool
13
14
  * returns a helpful message telling the user which keys to add.
14
15
  *
15
- * Connect Builder.io or register BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, or
16
- * EXA_API_KEY via app secrets settings or environment variables.
16
+ * Connect Builder.io or register BRAVE_SEARCH_API_KEY, TAVILY_API_KEY,
17
+ * EXA_API_KEY, or FIRECRAWL_API_KEY via app secrets settings or environment
18
+ * variables.
17
19
  */
18
20
  const DEFAULT_COUNT = 5;
19
21
  const MAX_COUNT = 10;
@@ -136,6 +138,30 @@ async function searchExa(query, count, apiKey) {
136
138
  snippet: r.text ?? "",
137
139
  }));
138
140
  }
141
+ async function searchFirecrawl(query, count, apiKey) {
142
+ const res = await fetch("https://api.firecrawl.dev/v2/search", {
143
+ method: "POST",
144
+ headers: {
145
+ "Content-Type": "application/json",
146
+ Authorization: `Bearer ${apiKey}`,
147
+ },
148
+ body: JSON.stringify({
149
+ query,
150
+ limit: count,
151
+ }),
152
+ signal: AbortSignal.timeout(15_000),
153
+ });
154
+ if (!res.ok) {
155
+ throw new Error(`Firecrawl error ${res.status}: ${await res.text()}`);
156
+ }
157
+ const data = (await res.json());
158
+ const results = Array.isArray(data.data) ? data.data : (data.data?.web ?? []);
159
+ return results.map((r) => ({
160
+ title: r.title ?? "",
161
+ url: r.url ?? "",
162
+ snippet: r.description ?? "",
163
+ }));
164
+ }
139
165
  async function searchBuilderManaged(query, count, credentials, opts) {
140
166
  const baseUrl = opts.getBuilderWebSearchBaseUrl?.() ??
141
167
  process.env.BUILDER_WEB_SEARCH_BASE_URL ??
@@ -183,7 +209,7 @@ export function createWebSearchToolEntry(opts = {}) {
183
209
  return {
184
210
  "web-search": {
185
211
  tool: {
186
- description: "Search the public web. Use to find API documentation, endpoints, current information, or any topic. Returns ranked results from BYOK providers or a grounded Builder-managed summary. Follow up with web-request or provider-api-docs using responseMode:'markdown' or responseMode:'matches' to fetch clean text, links, or compact snippets from promising URLs. Requires either Connect Builder.io or one of: BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, or EXA_API_KEY.",
212
+ description: "Search the public web. Use to find API documentation, endpoints, current information, or any topic. Returns ranked results from BYOK providers or a grounded Builder-managed summary. Follow up with web-request or provider-api-docs using responseMode:'markdown' or responseMode:'matches' to fetch clean text, links, or compact snippets from promising URLs. Requires either Connect Builder.io or one of: BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, EXA_API_KEY, or FIRECRAWL_API_KEY.",
187
213
  parameters: {
188
214
  type: "object",
189
215
  properties: {
@@ -211,6 +237,7 @@ export function createWebSearchToolEntry(opts = {}) {
211
237
  const braveKey = await resolveSearchKey("BRAVE_SEARCH_API_KEY", opts);
212
238
  const tavilyKey = await resolveSearchKey("TAVILY_API_KEY", opts);
213
239
  const exaKey = await resolveSearchKey("EXA_API_KEY", opts);
240
+ const firecrawlKey = await resolveSearchKey("FIRECRAWL_API_KEY", opts);
214
241
  const builderCredentials = await resolveBuilderSearchCredentials(opts);
215
242
  let results;
216
243
  let backend;
@@ -228,6 +255,10 @@ export function createWebSearchToolEntry(opts = {}) {
228
255
  results = await searchExa(query, count, exaKey);
229
256
  backend = "Exa";
230
257
  }
258
+ else if (firecrawlKey) {
259
+ results = await searchFirecrawl(query, count, firecrawlKey);
260
+ backend = "Firecrawl";
261
+ }
231
262
  else if (builderCredentials) {
232
263
  managedText = await searchBuilderManaged(query, count, builderCredentials, opts);
233
264
  results = [];
@@ -240,6 +271,7 @@ export function createWebSearchToolEntry(opts = {}) {
240
271
  " • BRAVE_SEARCH_API_KEY — https://brave.com/search/api/",
241
272
  " • TAVILY_API_KEY — https://tavily.com/",
242
273
  " • EXA_API_KEY — https://exa.ai/",
274
+ " • FIRECRAWL_API_KEY — https://firecrawl.dev/",
243
275
  ].join("\n");
244
276
  }
245
277
  }
@@ -1 +1 @@
1
- {"version":3,"file":"web-search-tool.js","sourceRoot":"","sources":["../../src/extensions/web-search-tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Web-search tool — agent tool for searching the public web.\n *\n * Pluggable backends resolved at call time based on which API key is\n * configured (env var or secrets/credentials store):\n *\n * 1. Brave Search API (BRAVE_SEARCH_API_KEY)\n * 2. Tavily (TAVILY_API_KEY)\n * 3. Exa (EXA_API_KEY)\n * 4. Builder.io (connected Builder credentials)\n *\n * The first configured backend wins. If none is configured, the tool\n * returns a helpful message telling the user which keys to add.\n *\n * Connect Builder.io or register BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, or\n * EXA_API_KEY via app secrets settings or environment variables.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport type { CredentialContext } from \"../credentials/index.js\";\n\nexport interface WebSearchResult {\n title: string;\n url: string;\n snippet: string;\n}\n\nexport interface WebSearchToolOptions {\n /**\n * Resolve a request-scoped secret by key. When not provided the tool falls\n * back to env-var lookup only.\n */\n resolveSecret?: (key: string) => Promise<string | null>;\n /**\n * Legacy credential resolver retained for older callers.\n */\n resolveCredential?: (\n key: string,\n ctx: CredentialContext,\n ) => Promise<string | undefined>;\n /**\n * Legacy credential context callback retained for older callers.\n */\n getCredentialContext?: () => CredentialContext | null;\n /**\n * Resolve connected Builder credentials for managed web search.\n */\n resolveBuilderCredentials?: () => Promise<BuilderWebSearchCredentials>;\n /**\n * Base URL for Builder-managed web search.\n */\n getBuilderWebSearchBaseUrl?: () => string;\n /**\n * Stable attribution headers for Builder-managed API calls.\n */\n getBuilderRequestHeaders?: () => Record<string, string>;\n}\n\nconst DEFAULT_COUNT = 5;\nconst MAX_COUNT = 10;\n\ninterface BuilderWebSearchCredentials {\n privateKey: string | null;\n publicKey: string | null;\n userId?: string | null;\n}\n\nasync function resolveSearchKey(\n key: string,\n opts: WebSearchToolOptions,\n): Promise<string | undefined> {\n let usedRequestScopedResolver = false;\n // 1. Try request-scoped app secrets (user/org/workspace stored key).\n if (opts.resolveSecret) {\n usedRequestScopedResolver = true;\n try {\n const value = await opts.resolveSecret(key);\n if (value) return value;\n } catch {\n // Secret lookup failures are non-fatal; fall through to legacy/env.\n }\n }\n\n // 2. Try legacy per-request credential context.\n if (opts.resolveCredential && opts.getCredentialContext) {\n const ctx = opts.getCredentialContext();\n if (ctx) {\n try {\n const value = await opts.resolveCredential(key, ctx);\n if (value) return value;\n } catch {\n // Credential lookup failures are non-fatal; fall through to env.\n }\n }\n }\n\n if (usedRequestScopedResolver) return undefined;\n\n // 3. Fall back to env var.\n return process.env[key] || undefined;\n}\n\nasync function resolveBuilderSearchCredentials(\n opts: WebSearchToolOptions,\n): Promise<BuilderWebSearchCredentials | null> {\n if (!opts.resolveBuilderCredentials) return null;\n try {\n const creds = await opts.resolveBuilderCredentials();\n if (creds.privateKey && creds.publicKey) return creds;\n } catch {\n // Builder credential lookup failures are non-fatal; BYOK backends or the\n // setup hint below can still handle the tool call.\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Backend implementations\n// ---------------------------------------------------------------------------\n\nasync function searchBrave(\n query: string,\n count: number,\n apiKey: string,\n): Promise<WebSearchResult[]> {\n const url = `https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(query)}&count=${count}`;\n const res = await fetch(url, {\n headers: {\n Accept: \"application/json\",\n \"Accept-Encoding\": \"gzip\",\n \"X-Subscription-Token\": apiKey,\n },\n signal: AbortSignal.timeout(15_000),\n });\n if (!res.ok) {\n throw new Error(`Brave Search error ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n web?: {\n results?: Array<{\n title?: string;\n url?: string;\n description?: string;\n }>;\n };\n };\n return (data.web?.results ?? []).map((r) => ({\n title: r.title ?? \"\",\n url: r.url ?? \"\",\n snippet: r.description ?? \"\",\n }));\n}\n\nasync function searchTavily(\n query: string,\n count: number,\n apiKey: string,\n): Promise<WebSearchResult[]> {\n const res = await fetch(\"https://api.tavily.com/search\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n api_key: apiKey,\n query,\n max_results: count,\n search_depth: \"basic\",\n }),\n signal: AbortSignal.timeout(15_000),\n });\n if (!res.ok) {\n throw new Error(`Tavily error ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n results?: Array<{\n title?: string;\n url?: string;\n content?: string;\n }>;\n };\n return (data.results ?? []).map((r) => ({\n title: r.title ?? \"\",\n url: r.url ?? \"\",\n snippet: r.content ?? \"\",\n }));\n}\n\nasync function searchExa(\n query: string,\n count: number,\n apiKey: string,\n): Promise<WebSearchResult[]> {\n const res = await fetch(\"https://api.exa.ai/search\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n },\n body: JSON.stringify({\n query,\n numResults: count,\n type: \"auto\",\n contents: { text: { maxCharacters: 400 } },\n }),\n signal: AbortSignal.timeout(15_000),\n });\n if (!res.ok) {\n throw new Error(`Exa error ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n results?: Array<{\n title?: string;\n url?: string;\n text?: string;\n }>;\n };\n return (data.results ?? []).map((r) => ({\n title: r.title ?? \"\",\n url: r.url ?? \"\",\n snippet: r.text ?? \"\",\n }));\n}\n\nasync function searchBuilderManaged(\n query: string,\n count: number,\n credentials: BuilderWebSearchCredentials,\n opts: WebSearchToolOptions,\n): Promise<string> {\n const baseUrl =\n opts.getBuilderWebSearchBaseUrl?.() ??\n process.env.BUILDER_WEB_SEARCH_BASE_URL ??\n \"https://api.builder.io/agent-native/web-search/v1\";\n const url = new URL(\n \"search\",\n baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`,\n );\n const res = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${credentials.privateKey}`,\n \"x-builder-api-key\": credentials.publicKey ?? \"\",\n ...(credentials.userId\n ? { \"x-builder-user-id\": credentials.userId }\n : {}),\n ...(opts.getBuilderRequestHeaders?.() ?? {}),\n },\n body: JSON.stringify({\n query,\n count,\n source: {\n appId: \"agent-native\",\n feature: \"web-search-tool\",\n },\n }),\n signal: AbortSignal.timeout(45_000),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(\n `Builder web search error ${res.status}${text ? `: ${text.slice(0, 300)}` : \"\"}`,\n );\n }\n const data = (await res.json()) as {\n text?: string;\n };\n const text = data.text?.trim();\n if (!text) {\n throw new Error(\"Builder web search returned no text.\");\n }\n return text;\n}\n\n// ---------------------------------------------------------------------------\n// Tool entry factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create the web-search tool entry for the agent tool registry.\n */\nexport function createWebSearchToolEntry(\n opts: WebSearchToolOptions = {},\n): Record<string, ActionEntry> {\n return {\n \"web-search\": {\n tool: {\n description:\n \"Search the public web. Use to find API documentation, endpoints, current information, or any topic. Returns ranked results from BYOK providers or a grounded Builder-managed summary. Follow up with web-request or provider-api-docs using responseMode:'markdown' or responseMode:'matches' to fetch clean text, links, or compact snippets from promising URLs. Requires either Connect Builder.io or one of: BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, or EXA_API_KEY.\",\n parameters: {\n type: \"object\" as const,\n properties: {\n query: {\n type: \"string\",\n description:\n \"Search query. Be specific — include API name, version, and what you need (e.g. 'Stripe API list subscriptions endpoint').\",\n },\n count: {\n type: \"number\",\n description: `Number of results to return. Default ${DEFAULT_COUNT}, max ${MAX_COUNT}.`,\n },\n },\n required: [\"query\"],\n },\n },\n run: async (args: Record<string, string>) => {\n const query = (args.query ?? \"\").trim();\n if (!query) return \"query is required.\";\n\n const rawCount = Number(args.count);\n const count =\n Number.isFinite(rawCount) && rawCount > 0\n ? Math.min(Math.floor(rawCount), MAX_COUNT)\n : DEFAULT_COUNT;\n\n // Backend selection — first configured wins.\n const braveKey = await resolveSearchKey(\"BRAVE_SEARCH_API_KEY\", opts);\n const tavilyKey = await resolveSearchKey(\"TAVILY_API_KEY\", opts);\n const exaKey = await resolveSearchKey(\"EXA_API_KEY\", opts);\n const builderCredentials = await resolveBuilderSearchCredentials(opts);\n\n let results: WebSearchResult[];\n let backend: string;\n let managedText: string | null = null;\n\n try {\n if (braveKey) {\n results = await searchBrave(query, count, braveKey);\n backend = \"Brave Search\";\n } else if (tavilyKey) {\n results = await searchTavily(query, count, tavilyKey);\n backend = \"Tavily\";\n } else if (exaKey) {\n results = await searchExa(query, count, exaKey);\n backend = \"Exa\";\n } else if (builderCredentials) {\n managedText = await searchBuilderManaged(\n query,\n count,\n builderCredentials,\n opts,\n );\n results = [];\n backend = \"Builder.io\";\n } else {\n return [\n \"No web-search backend configured.\",\n \"Connect Builder.io in Settings, or add one of the following keys via app settings or environment variables:\",\n \" • BRAVE_SEARCH_API_KEY — https://brave.com/search/api/\",\n \" • TAVILY_API_KEY — https://tavily.com/\",\n \" • EXA_API_KEY — https://exa.ai/\",\n ].join(\"\\n\");\n }\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return `Web search failed (${msg}). Try web-request to fetch a specific URL directly.`;\n }\n\n if (managedText) {\n return [\n `Web search results for \"${query}\" (backend: ${backend}):`,\n \"\",\n managedText,\n \"\",\n \"Use web-request or provider-api-docs with responseMode:'markdown' for readable docs or responseMode:'matches' plus search for compact snippets.\",\n ].join(\"\\n\");\n }\n\n if (results.length === 0) {\n return `No results found for \"${query}\" (backend: ${backend}).`;\n }\n\n const lines: string[] = [\n `Web search results for \"${query}\" (backend: ${backend}):`,\n \"\",\n ];\n for (let i = 0; i < results.length; i++) {\n const r = results[i];\n lines.push(`${i + 1}. ${r.title}`);\n lines.push(` URL: ${r.url}`);\n if (r.snippet) {\n const snippet = r.snippet.slice(0, 300).replace(/\\n+/g, \" \");\n lines.push(` ${snippet}`);\n }\n lines.push(\"\");\n }\n lines.push(\n \"Use web-request or provider-api-docs with responseMode:'markdown' for readable docs or responseMode:'matches' plus search for compact snippets.\",\n );\n return lines.join(\"\\n\");\n },\n readOnly: true,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"web-search-tool.js","sourceRoot":"","sources":["../../src/extensions/web-search-tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Web-search tool — agent tool for searching the public web.\n *\n * Pluggable backends resolved at call time based on which API key is\n * configured (env var or secrets/credentials store):\n *\n * 1. Brave Search API (BRAVE_SEARCH_API_KEY)\n * 2. Tavily (TAVILY_API_KEY)\n * 3. Exa (EXA_API_KEY)\n * 4. Firecrawl (FIRECRAWL_API_KEY)\n * 5. Builder.io (connected Builder credentials)\n *\n * The first configured backend wins. If none is configured, the tool\n * returns a helpful message telling the user which keys to add.\n *\n * Connect Builder.io or register BRAVE_SEARCH_API_KEY, TAVILY_API_KEY,\n * EXA_API_KEY, or FIRECRAWL_API_KEY via app secrets settings or environment\n * variables.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport type { CredentialContext } from \"../credentials/index.js\";\n\nexport interface WebSearchResult {\n title: string;\n url: string;\n snippet: string;\n}\n\nexport interface WebSearchToolOptions {\n /**\n * Resolve a request-scoped secret by key. When not provided the tool falls\n * back to env-var lookup only.\n */\n resolveSecret?: (key: string) => Promise<string | null>;\n /**\n * Legacy credential resolver retained for older callers.\n */\n resolveCredential?: (\n key: string,\n ctx: CredentialContext,\n ) => Promise<string | undefined>;\n /**\n * Legacy credential context callback retained for older callers.\n */\n getCredentialContext?: () => CredentialContext | null;\n /**\n * Resolve connected Builder credentials for managed web search.\n */\n resolveBuilderCredentials?: () => Promise<BuilderWebSearchCredentials>;\n /**\n * Base URL for Builder-managed web search.\n */\n getBuilderWebSearchBaseUrl?: () => string;\n /**\n * Stable attribution headers for Builder-managed API calls.\n */\n getBuilderRequestHeaders?: () => Record<string, string>;\n}\n\nconst DEFAULT_COUNT = 5;\nconst MAX_COUNT = 10;\n\ninterface BuilderWebSearchCredentials {\n privateKey: string | null;\n publicKey: string | null;\n userId?: string | null;\n}\n\nasync function resolveSearchKey(\n key: string,\n opts: WebSearchToolOptions,\n): Promise<string | undefined> {\n let usedRequestScopedResolver = false;\n // 1. Try request-scoped app secrets (user/org/workspace stored key).\n if (opts.resolveSecret) {\n usedRequestScopedResolver = true;\n try {\n const value = await opts.resolveSecret(key);\n if (value) return value;\n } catch {\n // Secret lookup failures are non-fatal; fall through to legacy/env.\n }\n }\n\n // 2. Try legacy per-request credential context.\n if (opts.resolveCredential && opts.getCredentialContext) {\n const ctx = opts.getCredentialContext();\n if (ctx) {\n try {\n const value = await opts.resolveCredential(key, ctx);\n if (value) return value;\n } catch {\n // Credential lookup failures are non-fatal; fall through to env.\n }\n }\n }\n\n if (usedRequestScopedResolver) return undefined;\n\n // 3. Fall back to env var.\n return process.env[key] || undefined;\n}\n\nasync function resolveBuilderSearchCredentials(\n opts: WebSearchToolOptions,\n): Promise<BuilderWebSearchCredentials | null> {\n if (!opts.resolveBuilderCredentials) return null;\n try {\n const creds = await opts.resolveBuilderCredentials();\n if (creds.privateKey && creds.publicKey) return creds;\n } catch {\n // Builder credential lookup failures are non-fatal; BYOK backends or the\n // setup hint below can still handle the tool call.\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Backend implementations\n// ---------------------------------------------------------------------------\n\nasync function searchBrave(\n query: string,\n count: number,\n apiKey: string,\n): Promise<WebSearchResult[]> {\n const url = `https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(query)}&count=${count}`;\n const res = await fetch(url, {\n headers: {\n Accept: \"application/json\",\n \"Accept-Encoding\": \"gzip\",\n \"X-Subscription-Token\": apiKey,\n },\n signal: AbortSignal.timeout(15_000),\n });\n if (!res.ok) {\n throw new Error(`Brave Search error ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n web?: {\n results?: Array<{\n title?: string;\n url?: string;\n description?: string;\n }>;\n };\n };\n return (data.web?.results ?? []).map((r) => ({\n title: r.title ?? \"\",\n url: r.url ?? \"\",\n snippet: r.description ?? \"\",\n }));\n}\n\nasync function searchTavily(\n query: string,\n count: number,\n apiKey: string,\n): Promise<WebSearchResult[]> {\n const res = await fetch(\"https://api.tavily.com/search\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n api_key: apiKey,\n query,\n max_results: count,\n search_depth: \"basic\",\n }),\n signal: AbortSignal.timeout(15_000),\n });\n if (!res.ok) {\n throw new Error(`Tavily error ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n results?: Array<{\n title?: string;\n url?: string;\n content?: string;\n }>;\n };\n return (data.results ?? []).map((r) => ({\n title: r.title ?? \"\",\n url: r.url ?? \"\",\n snippet: r.content ?? \"\",\n }));\n}\n\nasync function searchExa(\n query: string,\n count: number,\n apiKey: string,\n): Promise<WebSearchResult[]> {\n const res = await fetch(\"https://api.exa.ai/search\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n },\n body: JSON.stringify({\n query,\n numResults: count,\n type: \"auto\",\n contents: { text: { maxCharacters: 400 } },\n }),\n signal: AbortSignal.timeout(15_000),\n });\n if (!res.ok) {\n throw new Error(`Exa error ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n results?: Array<{\n title?: string;\n url?: string;\n text?: string;\n }>;\n };\n return (data.results ?? []).map((r) => ({\n title: r.title ?? \"\",\n url: r.url ?? \"\",\n snippet: r.text ?? \"\",\n }));\n}\n\nasync function searchFirecrawl(\n query: string,\n count: number,\n apiKey: string,\n): Promise<WebSearchResult[]> {\n const res = await fetch(\"https://api.firecrawl.dev/v2/search\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n query,\n limit: count,\n }),\n signal: AbortSignal.timeout(15_000),\n });\n if (!res.ok) {\n throw new Error(`Firecrawl error ${res.status}: ${await res.text()}`);\n }\n // v2 groups results by source ({ data: { web: [...] } }); older shapes\n // return a flat array ({ data: [...] }). Accept both defensively.\n type FirecrawlResult = { title?: string; url?: string; description?: string };\n const data = (await res.json()) as {\n data?: FirecrawlResult[] | { web?: FirecrawlResult[] };\n };\n const results = Array.isArray(data.data) ? data.data : (data.data?.web ?? []);\n return results.map((r) => ({\n title: r.title ?? \"\",\n url: r.url ?? \"\",\n snippet: r.description ?? \"\",\n }));\n}\n\nasync function searchBuilderManaged(\n query: string,\n count: number,\n credentials: BuilderWebSearchCredentials,\n opts: WebSearchToolOptions,\n): Promise<string> {\n const baseUrl =\n opts.getBuilderWebSearchBaseUrl?.() ??\n process.env.BUILDER_WEB_SEARCH_BASE_URL ??\n \"https://api.builder.io/agent-native/web-search/v1\";\n const url = new URL(\n \"search\",\n baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`,\n );\n const res = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${credentials.privateKey}`,\n \"x-builder-api-key\": credentials.publicKey ?? \"\",\n ...(credentials.userId\n ? { \"x-builder-user-id\": credentials.userId }\n : {}),\n ...(opts.getBuilderRequestHeaders?.() ?? {}),\n },\n body: JSON.stringify({\n query,\n count,\n source: {\n appId: \"agent-native\",\n feature: \"web-search-tool\",\n },\n }),\n signal: AbortSignal.timeout(45_000),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(\n `Builder web search error ${res.status}${text ? `: ${text.slice(0, 300)}` : \"\"}`,\n );\n }\n const data = (await res.json()) as {\n text?: string;\n };\n const text = data.text?.trim();\n if (!text) {\n throw new Error(\"Builder web search returned no text.\");\n }\n return text;\n}\n\n// ---------------------------------------------------------------------------\n// Tool entry factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create the web-search tool entry for the agent tool registry.\n */\nexport function createWebSearchToolEntry(\n opts: WebSearchToolOptions = {},\n): Record<string, ActionEntry> {\n return {\n \"web-search\": {\n tool: {\n description:\n \"Search the public web. Use to find API documentation, endpoints, current information, or any topic. Returns ranked results from BYOK providers or a grounded Builder-managed summary. Follow up with web-request or provider-api-docs using responseMode:'markdown' or responseMode:'matches' to fetch clean text, links, or compact snippets from promising URLs. Requires either Connect Builder.io or one of: BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, EXA_API_KEY, or FIRECRAWL_API_KEY.\",\n parameters: {\n type: \"object\" as const,\n properties: {\n query: {\n type: \"string\",\n description:\n \"Search query. Be specific — include API name, version, and what you need (e.g. 'Stripe API list subscriptions endpoint').\",\n },\n count: {\n type: \"number\",\n description: `Number of results to return. Default ${DEFAULT_COUNT}, max ${MAX_COUNT}.`,\n },\n },\n required: [\"query\"],\n },\n },\n run: async (args: Record<string, string>) => {\n const query = (args.query ?? \"\").trim();\n if (!query) return \"query is required.\";\n\n const rawCount = Number(args.count);\n const count =\n Number.isFinite(rawCount) && rawCount > 0\n ? Math.min(Math.floor(rawCount), MAX_COUNT)\n : DEFAULT_COUNT;\n\n // Backend selection — first configured wins.\n const braveKey = await resolveSearchKey(\"BRAVE_SEARCH_API_KEY\", opts);\n const tavilyKey = await resolveSearchKey(\"TAVILY_API_KEY\", opts);\n const exaKey = await resolveSearchKey(\"EXA_API_KEY\", opts);\n const firecrawlKey = await resolveSearchKey(\"FIRECRAWL_API_KEY\", opts);\n const builderCredentials = await resolveBuilderSearchCredentials(opts);\n\n let results: WebSearchResult[];\n let backend: string;\n let managedText: string | null = null;\n\n try {\n if (braveKey) {\n results = await searchBrave(query, count, braveKey);\n backend = \"Brave Search\";\n } else if (tavilyKey) {\n results = await searchTavily(query, count, tavilyKey);\n backend = \"Tavily\";\n } else if (exaKey) {\n results = await searchExa(query, count, exaKey);\n backend = \"Exa\";\n } else if (firecrawlKey) {\n results = await searchFirecrawl(query, count, firecrawlKey);\n backend = \"Firecrawl\";\n } else if (builderCredentials) {\n managedText = await searchBuilderManaged(\n query,\n count,\n builderCredentials,\n opts,\n );\n results = [];\n backend = \"Builder.io\";\n } else {\n return [\n \"No web-search backend configured.\",\n \"Connect Builder.io in Settings, or add one of the following keys via app settings or environment variables:\",\n \" • BRAVE_SEARCH_API_KEY — https://brave.com/search/api/\",\n \" • TAVILY_API_KEY — https://tavily.com/\",\n \" • EXA_API_KEY — https://exa.ai/\",\n \" • FIRECRAWL_API_KEY — https://firecrawl.dev/\",\n ].join(\"\\n\");\n }\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return `Web search failed (${msg}). Try web-request to fetch a specific URL directly.`;\n }\n\n if (managedText) {\n return [\n `Web search results for \"${query}\" (backend: ${backend}):`,\n \"\",\n managedText,\n \"\",\n \"Use web-request or provider-api-docs with responseMode:'markdown' for readable docs or responseMode:'matches' plus search for compact snippets.\",\n ].join(\"\\n\");\n }\n\n if (results.length === 0) {\n return `No results found for \"${query}\" (backend: ${backend}).`;\n }\n\n const lines: string[] = [\n `Web search results for \"${query}\" (backend: ${backend}):`,\n \"\",\n ];\n for (let i = 0; i < results.length; i++) {\n const r = results[i];\n lines.push(`${i + 1}. ${r.title}`);\n lines.push(` URL: ${r.url}`);\n if (r.snippet) {\n const snippet = r.snippet.slice(0, 300).replace(/\\n+/g, \" \");\n lines.push(` ${snippet}`);\n }\n lines.push(\"\");\n }\n lines.push(\n \"Use web-request or provider-api-docs with responseMode:'markdown' for readable docs or responseMode:'matches' plus search for compact snippets.\",\n );\n return lines.join(\"\\n\");\n },\n readOnly: true,\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,wBAAgB,wBAAwB,IAAI,IAAI,CA2D/C"}
1
+ {"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,wBAAgB,wBAAwB,IAAI,IAAI,CAkE/C"}
@@ -37,6 +37,12 @@ export function registerFrameworkSecrets() {
37
37
  description: "Enables the web-search agent tool via Exa. Used as fallback when Brave and Tavily are not set and before Builder-managed search.",
38
38
  docsUrl: "https://exa.ai/",
39
39
  },
40
+ {
41
+ key: "FIRECRAWL_API_KEY",
42
+ label: "Firecrawl API Key",
43
+ description: "Enables the web-search agent tool via Firecrawl. Used as fallback when Brave, Tavily, and Exa are not set and before Builder-managed search.",
44
+ docsUrl: "https://firecrawl.dev/",
45
+ },
40
46
  ];
41
47
  for (const entry of webSearchKeys) {
42
48
  if (!getRequiredSecret(entry.key)) {
@@ -1 +1 @@
1
- {"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,UAAU,wBAAwB;IACtC,kEAAkE;IAClE,0EAA0E;IAC1E,MAAM,aAAa,GAKd;QACH;YACE,GAAG,EAAE,sBAAsB;YAC3B,KAAK,EAAE,sBAAsB;YAC7B,WAAW,EACT,mHAAmH;YACrH,OAAO,EAAE,+BAA+B;SACzC;QACD;YACE,GAAG,EAAE,gBAAgB;YACrB,KAAK,EAAE,gBAAgB;YACvB,WAAW,EACT,wIAAwI;YAC1I,OAAO,EAAE,qBAAqB;SAC/B;QACD;YACE,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,aAAa;YACpB,WAAW,EACT,kIAAkI;YACpI,OAAO,EAAE,iBAAiB;SAC3B;KACF,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,sBAAsB,CAAC;gBACrB,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,WAAW;gBAClB,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,EAAE,CAAC;QACvC,sBAAsB,CAAC;YACrB,GAAG,EAAE,cAAc;YACnB,KAAK,EAAE,cAAc;YACrB,WAAW,EACT,0FAA0F;YAC5F,OAAO,EACL,kHAAkH;YACpH,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["/**\n * Framework-level secret registrations.\n *\n * Side-effect module — imported by the core-routes plugin at boot so the\n * sidebar settings UI and the `/_agent-native/secrets` list route surface the\n * relevant keys in every template.\n *\n * Each call uses a `getRequiredSecret` guard so a template that has already\n * registered the same key (often with stricter settings like `required: true`)\n * wins — the framework registration is a fallback, not an override.\n *\n * NOTE: The framework previously registered OPENAI_API_KEY here for Whisper\n * voice transcription. Voice transcription now routes through the Builder.io\n * gateway (or Groq as a BYOK fallback), so the framework no longer registers\n * the OpenAI key. Templates that need it (e.g. Clips) register it themselves.\n */\n\nimport { getRequiredSecret, registerRequiredSecret } from \"./register.js\";\n\nexport function registerFrameworkSecrets(): void {\n // Web-search tool backends — optional; the tool selects the first\n // configured manual key at call time, then falls back to Builder Connect.\n const webSearchKeys: Array<{\n key: string;\n label: string;\n description: string;\n docsUrl: string;\n }> = [\n {\n key: \"BRAVE_SEARCH_API_KEY\",\n label: \"Brave Search API Key\",\n description:\n \"Enables the web-search agent tool via Brave Search. Optional when Builder.io is connected for managed web search.\",\n docsUrl: \"https://brave.com/search/api/\",\n },\n {\n key: \"TAVILY_API_KEY\",\n label: \"Tavily API Key\",\n description:\n \"Enables the web-search agent tool via Tavily. Used as fallback when BRAVE_SEARCH_API_KEY is not set and before Builder-managed search.\",\n docsUrl: \"https://tavily.com/\",\n },\n {\n key: \"EXA_API_KEY\",\n label: \"Exa API Key\",\n description:\n \"Enables the web-search agent tool via Exa. Used as fallback when Brave and Tavily are not set and before Builder-managed search.\",\n docsUrl: \"https://exa.ai/\",\n },\n ];\n\n for (const entry of webSearchKeys) {\n if (!getRequiredSecret(entry.key)) {\n registerRequiredSecret({\n key: entry.key,\n label: entry.label,\n description: entry.description,\n docsUrl: entry.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n if (!getRequiredSecret(\"GITHUB_TOKEN\")) {\n registerRequiredSecret({\n key: \"GITHUB_TOKEN\",\n label: \"GitHub token\",\n description:\n \"Enables connector-scoped repository file reads and writes for headless/cloud agent runs.\",\n docsUrl:\n \"https://docs.github.com/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\",\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,UAAU,wBAAwB;IACtC,kEAAkE;IAClE,0EAA0E;IAC1E,MAAM,aAAa,GAKd;QACH;YACE,GAAG,EAAE,sBAAsB;YAC3B,KAAK,EAAE,sBAAsB;YAC7B,WAAW,EACT,mHAAmH;YACrH,OAAO,EAAE,+BAA+B;SACzC;QACD;YACE,GAAG,EAAE,gBAAgB;YACrB,KAAK,EAAE,gBAAgB;YACvB,WAAW,EACT,wIAAwI;YAC1I,OAAO,EAAE,qBAAqB;SAC/B;QACD;YACE,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,aAAa;YACpB,WAAW,EACT,kIAAkI;YACpI,OAAO,EAAE,iBAAiB;SAC3B;QACD;YACE,GAAG,EAAE,mBAAmB;YACxB,KAAK,EAAE,mBAAmB;YAC1B,WAAW,EACT,8IAA8I;YAChJ,OAAO,EAAE,wBAAwB;SAClC;KACF,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,sBAAsB,CAAC;gBACrB,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,WAAW;gBAClB,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,EAAE,CAAC;QACvC,sBAAsB,CAAC;YACrB,GAAG,EAAE,cAAc;YACnB,KAAK,EAAE,cAAc;YACrB,WAAW,EACT,0FAA0F;YAC5F,OAAO,EACL,kHAAkH;YACpH,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["/**\n * Framework-level secret registrations.\n *\n * Side-effect module — imported by the core-routes plugin at boot so the\n * sidebar settings UI and the `/_agent-native/secrets` list route surface the\n * relevant keys in every template.\n *\n * Each call uses a `getRequiredSecret` guard so a template that has already\n * registered the same key (often with stricter settings like `required: true`)\n * wins — the framework registration is a fallback, not an override.\n *\n * NOTE: The framework previously registered OPENAI_API_KEY here for Whisper\n * voice transcription. Voice transcription now routes through the Builder.io\n * gateway (or Groq as a BYOK fallback), so the framework no longer registers\n * the OpenAI key. Templates that need it (e.g. Clips) register it themselves.\n */\n\nimport { getRequiredSecret, registerRequiredSecret } from \"./register.js\";\n\nexport function registerFrameworkSecrets(): void {\n // Web-search tool backends — optional; the tool selects the first\n // configured manual key at call time, then falls back to Builder Connect.\n const webSearchKeys: Array<{\n key: string;\n label: string;\n description: string;\n docsUrl: string;\n }> = [\n {\n key: \"BRAVE_SEARCH_API_KEY\",\n label: \"Brave Search API Key\",\n description:\n \"Enables the web-search agent tool via Brave Search. Optional when Builder.io is connected for managed web search.\",\n docsUrl: \"https://brave.com/search/api/\",\n },\n {\n key: \"TAVILY_API_KEY\",\n label: \"Tavily API Key\",\n description:\n \"Enables the web-search agent tool via Tavily. Used as fallback when BRAVE_SEARCH_API_KEY is not set and before Builder-managed search.\",\n docsUrl: \"https://tavily.com/\",\n },\n {\n key: \"EXA_API_KEY\",\n label: \"Exa API Key\",\n description:\n \"Enables the web-search agent tool via Exa. Used as fallback when Brave and Tavily are not set and before Builder-managed search.\",\n docsUrl: \"https://exa.ai/\",\n },\n {\n key: \"FIRECRAWL_API_KEY\",\n label: \"Firecrawl API Key\",\n description:\n \"Enables the web-search agent tool via Firecrawl. Used as fallback when Brave, Tavily, and Exa are not set and before Builder-managed search.\",\n docsUrl: \"https://firecrawl.dev/\",\n },\n ];\n\n for (const entry of webSearchKeys) {\n if (!getRequiredSecret(entry.key)) {\n registerRequiredSecret({\n key: entry.key,\n label: entry.label,\n description: entry.description,\n docsUrl: entry.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n if (!getRequiredSecret(\"GITHUB_TOKEN\")) {\n registerRequiredSecret({\n key: \"GITHUB_TOKEN\",\n label: \"GitHub token\",\n description:\n \"Enables connector-scoped repository file reads and writes for headless/cloud agent runs.\",\n docsUrl:\n \"https://docs.github.com/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\",\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"social-og-image.d.ts","sourceRoot":"","sources":["../../src/server/social-og-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAQZ,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,mCAAmC,2EAC0B,CAAC;AAC3E,eAAO,MAAM,2CAA2C,oFAC2B,CAAC;AAuMpF,wBAAgB,gCAAgC,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAyBxE;AAqBD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAUtE;AAED,wBAAgB,2BAA2B,CACzC,KAAK,GAAE,uBAA4B,GAClC,MAAM,CA0CR;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,GAAE,uBAA4B,GAClC,OAAO,CAAC,UAAU,CAAC,CAkBrB;AAED,wBAAgB,iCAAiC,CAC/C,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,SAAc,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,uBAA4B,2FAsCtC"}
1
+ {"version":3,"file":"social-og-image.d.ts","sourceRoot":"","sources":["../../src/server/social-og-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAQZ,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,mCAAmC,2EAC0B,CAAC;AAC3E,eAAO,MAAM,2CAA2C,oFAC2B,CAAC;AAuMpF,wBAAgB,gCAAgC,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAyBxE;AAqBD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAUtE;AAED,wBAAgB,2BAA2B,CACzC,KAAK,GAAE,uBAA4B,GAClC,MAAM,CA0CR;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,GAAE,uBAA4B,GAClC,OAAO,CAAC,UAAU,CAAC,CAuBrB;AAED,wBAAgB,iCAAiC,CAC/C,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,SAAc,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,uBAA4B,2FAsCtC"}
@@ -231,7 +231,11 @@ export function renderAgentNativeOgImageSvg(input = {}) {
231
231
  </svg>`;
232
232
  }
233
233
  export async function renderAgentNativeOgImagePng(input = {}) {
234
- const { Resvg } = await import(/* @vite-ignore */ "@resvg/resvg-js");
234
+ const overridePackage = typeof process !== "undefined"
235
+ ? process.env.AGENT_NATIVE_RESVG_PACKAGE
236
+ : undefined;
237
+ const resvgPackage = overridePackage || "@resvg/resvg-js";
238
+ const { Resvg } = await import(/* @vite-ignore */ resvgPackage);
235
239
  // Feed resvg the embedded Liberation Sans font explicitly. System fonts can't
236
240
  // be relied on: Linux serverless runtimes (Netlify/Lambda) ship neither Arial
237
241
  // nor Inter, so without a bundled font every `<text>` rendered blank.
@@ -1 +1 @@
1
- {"version":3,"file":"social-og-image.js","sourceRoot":"","sources":["../../src/server/social-og-image.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineEventHandler,\n getHeader,\n getMethod,\n getQuery,\n getRequestURL,\n type H3Event,\n} from \"h3\";\nimport {\n resolveBuiltInAuthMarketing,\n resolveBuiltInAuthMarketingByName,\n} from \"./auth-marketing.js\";\nimport { getAppName } from \"./app-name.js\";\nimport { OG_FONT_FAMILY, resolveOgFontFiles } from \"./og-fonts.js\";\n\nexport interface AgentNativeOgImageInput {\n appName?: string | null;\n title?: string | null;\n accentText?: string | null;\n}\n\nexport const AGENT_NATIVE_OG_IMAGE_WIDTH = 1200;\nexport const AGENT_NATIVE_OG_IMAGE_HEIGHT = 630;\nexport const AGENT_NATIVE_OG_IMAGE_CACHE_CONTROL =\n \"public, max-age=60, stale-while-revalidate=604800, stale-if-error=3600\";\nexport const AGENT_NATIVE_OG_IMAGE_NETLIFY_CACHE_CONTROL =\n \"public, durable, max-age=60, stale-while-revalidate=604800, stale-if-error=3600\";\n\nconst WIDTH = AGENT_NATIVE_OG_IMAGE_WIDTH;\nconst HEIGHT = AGENT_NATIVE_OG_IMAGE_HEIGHT;\nconst BRAND_BLUE = \"#00B5FF\";\nconst BRAND_MINT = \"#48FFE4\";\nconst BG = \"#000000\";\nconst FG = \"#f5f5f5\";\nconst FONT_FAMILY = `${OG_FONT_FAMILY}, Arial, Helvetica, system-ui, sans-serif`;\nconst DEFAULT_ACCENT_TEXT = \"100% free and open source\";\n\nconst LOGO_MARK = `\n <path d=\"M24.5537 65.7695H0L15.0859 39.4619L37.708 0L60.4912 39.4619H39.6396L24.5537 65.7695Z\" fill=\"white\"/>\n <path d=\"M89.446 0H114L76.2921 65.7704H51.7383L89.446 0Z\" fill=\"url(#brand)\"/>\n`;\n\nfunction escapeSvg(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nfunction cleanText(value: string | null | undefined): string {\n return String(value ?? \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction titleCase(value: string): string {\n return value\n .split(/[\\s._-]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join(\" \");\n}\n\nfunction titleFromAppName(appName: string): string {\n if (appName) return appName;\n const basePath =\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH || \"\";\n const slug = basePath.split(\"/\").filter(Boolean)[0] || \"\";\n return titleCase(slug) || \"Agent-Native\";\n}\n\ninterface WrappedText {\n lines: string[];\n truncated: boolean;\n}\n\ninterface TitleLayout {\n lines: string[];\n fontSize: number;\n lineHeight: number;\n}\n\nfunction estimateTextWidth(value: string, fontSize: number): number {\n let units = 0;\n for (const char of value) {\n if (char === \" \") {\n units += 0.28;\n } else if (/[MW@#%&]/.test(char)) {\n units += 0.86;\n } else if (/[A-Z]/.test(char)) {\n units += 0.64;\n } else if (/[ilI.,:;|!']/u.test(char)) {\n units += 0.26;\n } else if (/[0-9]/.test(char)) {\n units += 0.56;\n } else {\n units += 0.54;\n }\n }\n return units * fontSize;\n}\n\nfunction trimTextToWidth(\n value: string,\n fontSize: number,\n maxWidth: number,\n): string {\n const ellipsis = \"...\";\n let trimmed = value.trim();\n while (\n trimmed.length > 0 &&\n estimateTextWidth(`${trimmed}${ellipsis}`, fontSize) > maxWidth\n ) {\n trimmed = trimmed.slice(0, -1).trimEnd();\n }\n return trimmed ? `${trimmed}${ellipsis}` : ellipsis;\n}\n\nfunction wrapTextToWidth(\n value: string,\n fontSize: number,\n maxWidth: number,\n maxLines: number,\n): WrappedText {\n const words = value.split(/\\s+/).filter(Boolean);\n const lines: string[] = [];\n let current = \"\";\n let truncated = false;\n\n for (const word of words) {\n const next = current ? `${current} ${word}` : word;\n if (estimateTextWidth(next, fontSize) <= maxWidth) {\n current = next;\n continue;\n }\n if (!current) {\n lines.push(trimTextToWidth(word, fontSize, maxWidth));\n truncated = true;\n current = \"\";\n } else {\n lines.push(current);\n current = word;\n }\n if (lines.length === maxLines) {\n truncated = true;\n break;\n }\n }\n if (current && lines.length < maxLines) lines.push(current);\n\n const usedWordCount = lines.join(\" \").split(/\\s+/).filter(Boolean).length;\n if (usedWordCount < words.length && lines.length > 0) {\n lines[lines.length - 1] = trimTextToWidth(\n lines[lines.length - 1],\n fontSize,\n maxWidth,\n );\n truncated = true;\n }\n\n return {\n lines: lines.length ? lines : [trimTextToWidth(value, fontSize, maxWidth)],\n truncated,\n };\n}\n\nfunction getTitleLayout(title: string): TitleLayout {\n const maxTitleWidth = 900;\n if (estimateTextWidth(title, 88) <= maxTitleWidth) {\n return {\n lines: [title],\n fontSize: 88,\n lineHeight: 96,\n };\n }\n\n for (const fontSize of [76, 70, 64, 58, 52]) {\n const wrapped = wrapTextToWidth(title, fontSize, maxTitleWidth, 2);\n if (!wrapped.truncated) {\n const lineHeight = Math.round(fontSize * 1.1);\n return {\n lines: wrapped.lines,\n fontSize,\n lineHeight,\n };\n }\n }\n\n const fallbackFontSize = 52;\n const wrapped = wrapTextToWidth(title, fallbackFontSize, maxTitleWidth, 2);\n return {\n lines: wrapped.lines,\n fontSize: fallbackFontSize,\n lineHeight: 60,\n };\n}\n\nfunction textBlock({\n lines,\n x,\n y,\n fontSize,\n lineHeight,\n weight,\n fill,\n anchor = \"start\",\n}: {\n lines: string[];\n x: number;\n y: number;\n fontSize: number;\n lineHeight: number;\n weight: number;\n fill: string;\n anchor?: \"start\" | \"middle\";\n}): string {\n return `<text x=\"${x}\" y=\"${y}\" text-anchor=\"${anchor}\" font-family=\"${FONT_FAMILY}\" font-size=\"${fontSize}\" font-weight=\"${weight}\" fill=\"${fill}\">${lines\n .map(\n (line, index) =>\n `<tspan x=\"${x}\" dy=\"${index === 0 ? 0 : lineHeight}\">${escapeSvg(line)}</tspan>`,\n )\n .join(\"\")}</text>`;\n}\n\nexport function resolveAgentNativeOgImageAppName(event?: H3Event): string {\n const explicitAppName = cleanText(process.env.APP_NAME);\n if (explicitAppName) {\n return (\n resolveBuiltInAuthMarketingByName(explicitAppName)?.appName ??\n explicitAppName\n );\n }\n\n const requestHost = event\n ? (getHeader(event, \"x-forwarded-host\") ?? getHeader(event, \"host\"))\n : undefined;\n const requestPath = event ? getRequestURL(event).pathname : undefined;\n const builtInAppName = resolveBuiltInAuthMarketing({\n requestHost,\n requestPath,\n })?.appName;\n if (builtInAppName) return builtInAppName;\n\n const appName = getAppName();\n if (appName) {\n return resolveBuiltInAuthMarketingByName(appName)?.appName ?? appName;\n }\n\n return \"Agent-Native\";\n}\n\nfunction queryStringValue(\n value: unknown,\n maxLength: number,\n): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const clean = cleanText(value).slice(0, maxLength);\n return clean || undefined;\n}\n\nfunction pngBody(bytes: Uint8Array): ArrayBuffer {\n const body = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(body).set(bytes);\n return body;\n}\n\nfunction textByteLength(value: string): number {\n return new TextEncoder().encode(value).byteLength;\n}\n\nexport function isResvgRuntimeUnavailableError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n return (\n /@resvg\\/resvg-js|resvgjs\\.[\\w-]+\\.node|native binding/i.test(message) &&\n // \"no such module\" is workerd's wording when the package is externalized\n // out of the Cloudflare worker bundle.\n /cannot find|no such module|err_module_not_found|dlopen|invalid elf|wrong architecture|not a valid win32|native binding/i.test(\n message,\n )\n );\n}\n\nexport function renderAgentNativeOgImageSvg(\n input: AgentNativeOgImageInput = {},\n): string {\n const appName =\n cleanText(input.appName) || resolveAgentNativeOgImageAppName();\n const title = cleanText(input.title) || titleFromAppName(appName);\n const accentText = cleanText(input.accentText) || DEFAULT_ACCENT_TEXT;\n const titleLayout = getTitleLayout(title);\n const titleY = titleLayout.lines.length > 1 ? 288 : 330;\n const accentY =\n titleY + titleLayout.lineHeight * (titleLayout.lines.length - 1) + 70;\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${WIDTH}\" height=\"${HEIGHT}\" viewBox=\"0 0 ${WIDTH} ${HEIGHT}\">\n <title>${escapeSvg(title)} - Agent-Native preview</title>\n <defs>\n <linearGradient id=\"brand\" x1=\"101.702\" y1=\"67.4791\" x2=\"113.672\" y2=\"-37.4275\" gradientUnits=\"userSpaceOnUse\">\n <stop stop-color=\"${BRAND_BLUE}\"/>\n <stop offset=\"1\" stop-color=\"${BRAND_MINT}\"/>\n </linearGradient>\n <pattern id=\"grid\" width=\"48\" height=\"48\" patternUnits=\"userSpaceOnUse\">\n <path d=\"M 48 0 L 0 0 0 48\" fill=\"none\" stroke=\"#ffffff\" stroke-opacity=\"0.07\" stroke-width=\"1\"/>\n </pattern>\n </defs>\n <rect width=\"${WIDTH}\" height=\"${HEIGHT}\" fill=\"${BG}\"/>\n <rect width=\"${WIDTH}\" height=\"${HEIGHT}\" fill=\"url(#grid)\"/>\n <g transform=\"translate(80 116) scale(0.94)\">\n ${LOGO_MARK}\n </g>\n <g>\n ${textBlock({\n lines: titleLayout.lines,\n x: 80,\n y: titleY,\n fontSize: titleLayout.fontSize,\n lineHeight: titleLayout.lineHeight,\n // resvg's fontdb maps font-weight 850 to the Regular face (only 400/700\n // exist for Liberation Sans); 800 resolves to Bold, the heaviest face we\n // bundle, which is the intended look for the display title.\n weight: 800,\n fill: FG,\n })}\n <text x=\"84\" y=\"${accentY}\" font-family=\"${FONT_FAMILY}\" font-size=\"34\" font-weight=\"800\" fill=\"${BRAND_BLUE}\">${escapeSvg(accentText)}</text>\n </g>\n</svg>`;\n}\n\nexport async function renderAgentNativeOgImagePng(\n input: AgentNativeOgImageInput = {},\n): Promise<Uint8Array> {\n const { Resvg } = await import(/* @vite-ignore */ \"@resvg/resvg-js\");\n // Feed resvg the embedded Liberation Sans font explicitly. System fonts can't\n // be relied on: Linux serverless runtimes (Netlify/Lambda) ship neither Arial\n // nor Inter, so without a bundled font every `<text>` rendered blank.\n const fontFiles = resolveOgFontFiles();\n const hasBundledFonts = Boolean(fontFiles?.length);\n const image = new Resvg(renderAgentNativeOgImageSvg(input), {\n fitTo: { mode: \"width\", value: WIDTH },\n font: {\n loadSystemFonts: !hasBundledFonts,\n ...(hasBundledFonts ? { fontFiles } : {}),\n defaultFontFamily: OG_FONT_FAMILY,\n serifFamily: OG_FONT_FAMILY,\n sansSerifFamily: OG_FONT_FAMILY,\n },\n }).render();\n return image.asPng();\n}\n\nexport function agentNativeOgImageResponseHeaders(\n byteLength?: number,\n contentType = \"image/png\",\n): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": contentType,\n \"Cache-Control\": AGENT_NATIVE_OG_IMAGE_CACHE_CONTROL,\n \"CDN-Cache-Control\": AGENT_NATIVE_OG_IMAGE_CACHE_CONTROL,\n \"Netlify-CDN-Cache-Control\": AGENT_NATIVE_OG_IMAGE_NETLIFY_CACHE_CONTROL,\n \"Cross-Origin-Resource-Policy\": \"cross-origin\",\n };\n if (typeof byteLength === \"number\") {\n headers[\"Content-Length\"] = String(byteLength);\n }\n return headers;\n}\n\nexport function createAgentNativeOgImageHandler(\n options: AgentNativeOgImageInput = {},\n) {\n return defineEventHandler(async (event) => {\n if (getMethod(event) === \"HEAD\") {\n return new Response(null, {\n headers: agentNativeOgImageResponseHeaders(),\n });\n }\n\n const query = getQuery(event);\n const appName =\n cleanText(options.appName) || resolveAgentNativeOgImageAppName(event);\n const input = {\n ...options,\n appName,\n title: cleanText(options.title) || queryStringValue(query.title, 140),\n accentText:\n cleanText(options.accentText) || queryStringValue(query.accentText, 80),\n };\n\n let png: Uint8Array;\n try {\n png = await renderAgentNativeOgImagePng(input);\n } catch (error) {\n if (!isResvgRuntimeUnavailableError(error)) throw error;\n const svg = renderAgentNativeOgImageSvg(input);\n return new Response(svg, {\n headers: agentNativeOgImageResponseHeaders(\n textByteLength(svg),\n \"image/svg+xml; charset=utf-8\",\n ),\n });\n }\n\n return new Response(pngBody(png), {\n headers: agentNativeOgImageResponseHeaders(png.byteLength),\n });\n });\n}\n"]}
1
+ {"version":3,"file":"social-og-image.js","sourceRoot":"","sources":["../../src/server/social-og-image.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineEventHandler,\n getHeader,\n getMethod,\n getQuery,\n getRequestURL,\n type H3Event,\n} from \"h3\";\nimport {\n resolveBuiltInAuthMarketing,\n resolveBuiltInAuthMarketingByName,\n} from \"./auth-marketing.js\";\nimport { getAppName } from \"./app-name.js\";\nimport { OG_FONT_FAMILY, resolveOgFontFiles } from \"./og-fonts.js\";\n\nexport interface AgentNativeOgImageInput {\n appName?: string | null;\n title?: string | null;\n accentText?: string | null;\n}\n\nexport const AGENT_NATIVE_OG_IMAGE_WIDTH = 1200;\nexport const AGENT_NATIVE_OG_IMAGE_HEIGHT = 630;\nexport const AGENT_NATIVE_OG_IMAGE_CACHE_CONTROL =\n \"public, max-age=60, stale-while-revalidate=604800, stale-if-error=3600\";\nexport const AGENT_NATIVE_OG_IMAGE_NETLIFY_CACHE_CONTROL =\n \"public, durable, max-age=60, stale-while-revalidate=604800, stale-if-error=3600\";\n\nconst WIDTH = AGENT_NATIVE_OG_IMAGE_WIDTH;\nconst HEIGHT = AGENT_NATIVE_OG_IMAGE_HEIGHT;\nconst BRAND_BLUE = \"#00B5FF\";\nconst BRAND_MINT = \"#48FFE4\";\nconst BG = \"#000000\";\nconst FG = \"#f5f5f5\";\nconst FONT_FAMILY = `${OG_FONT_FAMILY}, Arial, Helvetica, system-ui, sans-serif`;\nconst DEFAULT_ACCENT_TEXT = \"100% free and open source\";\n\nconst LOGO_MARK = `\n <path d=\"M24.5537 65.7695H0L15.0859 39.4619L37.708 0L60.4912 39.4619H39.6396L24.5537 65.7695Z\" fill=\"white\"/>\n <path d=\"M89.446 0H114L76.2921 65.7704H51.7383L89.446 0Z\" fill=\"url(#brand)\"/>\n`;\n\nfunction escapeSvg(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nfunction cleanText(value: string | null | undefined): string {\n return String(value ?? \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction titleCase(value: string): string {\n return value\n .split(/[\\s._-]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join(\" \");\n}\n\nfunction titleFromAppName(appName: string): string {\n if (appName) return appName;\n const basePath =\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH || \"\";\n const slug = basePath.split(\"/\").filter(Boolean)[0] || \"\";\n return titleCase(slug) || \"Agent-Native\";\n}\n\ninterface WrappedText {\n lines: string[];\n truncated: boolean;\n}\n\ninterface TitleLayout {\n lines: string[];\n fontSize: number;\n lineHeight: number;\n}\n\nfunction estimateTextWidth(value: string, fontSize: number): number {\n let units = 0;\n for (const char of value) {\n if (char === \" \") {\n units += 0.28;\n } else if (/[MW@#%&]/.test(char)) {\n units += 0.86;\n } else if (/[A-Z]/.test(char)) {\n units += 0.64;\n } else if (/[ilI.,:;|!']/u.test(char)) {\n units += 0.26;\n } else if (/[0-9]/.test(char)) {\n units += 0.56;\n } else {\n units += 0.54;\n }\n }\n return units * fontSize;\n}\n\nfunction trimTextToWidth(\n value: string,\n fontSize: number,\n maxWidth: number,\n): string {\n const ellipsis = \"...\";\n let trimmed = value.trim();\n while (\n trimmed.length > 0 &&\n estimateTextWidth(`${trimmed}${ellipsis}`, fontSize) > maxWidth\n ) {\n trimmed = trimmed.slice(0, -1).trimEnd();\n }\n return trimmed ? `${trimmed}${ellipsis}` : ellipsis;\n}\n\nfunction wrapTextToWidth(\n value: string,\n fontSize: number,\n maxWidth: number,\n maxLines: number,\n): WrappedText {\n const words = value.split(/\\s+/).filter(Boolean);\n const lines: string[] = [];\n let current = \"\";\n let truncated = false;\n\n for (const word of words) {\n const next = current ? `${current} ${word}` : word;\n if (estimateTextWidth(next, fontSize) <= maxWidth) {\n current = next;\n continue;\n }\n if (!current) {\n lines.push(trimTextToWidth(word, fontSize, maxWidth));\n truncated = true;\n current = \"\";\n } else {\n lines.push(current);\n current = word;\n }\n if (lines.length === maxLines) {\n truncated = true;\n break;\n }\n }\n if (current && lines.length < maxLines) lines.push(current);\n\n const usedWordCount = lines.join(\" \").split(/\\s+/).filter(Boolean).length;\n if (usedWordCount < words.length && lines.length > 0) {\n lines[lines.length - 1] = trimTextToWidth(\n lines[lines.length - 1],\n fontSize,\n maxWidth,\n );\n truncated = true;\n }\n\n return {\n lines: lines.length ? lines : [trimTextToWidth(value, fontSize, maxWidth)],\n truncated,\n };\n}\n\nfunction getTitleLayout(title: string): TitleLayout {\n const maxTitleWidth = 900;\n if (estimateTextWidth(title, 88) <= maxTitleWidth) {\n return {\n lines: [title],\n fontSize: 88,\n lineHeight: 96,\n };\n }\n\n for (const fontSize of [76, 70, 64, 58, 52]) {\n const wrapped = wrapTextToWidth(title, fontSize, maxTitleWidth, 2);\n if (!wrapped.truncated) {\n const lineHeight = Math.round(fontSize * 1.1);\n return {\n lines: wrapped.lines,\n fontSize,\n lineHeight,\n };\n }\n }\n\n const fallbackFontSize = 52;\n const wrapped = wrapTextToWidth(title, fallbackFontSize, maxTitleWidth, 2);\n return {\n lines: wrapped.lines,\n fontSize: fallbackFontSize,\n lineHeight: 60,\n };\n}\n\nfunction textBlock({\n lines,\n x,\n y,\n fontSize,\n lineHeight,\n weight,\n fill,\n anchor = \"start\",\n}: {\n lines: string[];\n x: number;\n y: number;\n fontSize: number;\n lineHeight: number;\n weight: number;\n fill: string;\n anchor?: \"start\" | \"middle\";\n}): string {\n return `<text x=\"${x}\" y=\"${y}\" text-anchor=\"${anchor}\" font-family=\"${FONT_FAMILY}\" font-size=\"${fontSize}\" font-weight=\"${weight}\" fill=\"${fill}\">${lines\n .map(\n (line, index) =>\n `<tspan x=\"${x}\" dy=\"${index === 0 ? 0 : lineHeight}\">${escapeSvg(line)}</tspan>`,\n )\n .join(\"\")}</text>`;\n}\n\nexport function resolveAgentNativeOgImageAppName(event?: H3Event): string {\n const explicitAppName = cleanText(process.env.APP_NAME);\n if (explicitAppName) {\n return (\n resolveBuiltInAuthMarketingByName(explicitAppName)?.appName ??\n explicitAppName\n );\n }\n\n const requestHost = event\n ? (getHeader(event, \"x-forwarded-host\") ?? getHeader(event, \"host\"))\n : undefined;\n const requestPath = event ? getRequestURL(event).pathname : undefined;\n const builtInAppName = resolveBuiltInAuthMarketing({\n requestHost,\n requestPath,\n })?.appName;\n if (builtInAppName) return builtInAppName;\n\n const appName = getAppName();\n if (appName) {\n return resolveBuiltInAuthMarketingByName(appName)?.appName ?? appName;\n }\n\n return \"Agent-Native\";\n}\n\nfunction queryStringValue(\n value: unknown,\n maxLength: number,\n): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const clean = cleanText(value).slice(0, maxLength);\n return clean || undefined;\n}\n\nfunction pngBody(bytes: Uint8Array): ArrayBuffer {\n const body = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(body).set(bytes);\n return body;\n}\n\nfunction textByteLength(value: string): number {\n return new TextEncoder().encode(value).byteLength;\n}\n\nexport function isResvgRuntimeUnavailableError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n return (\n /@resvg\\/resvg-js|resvgjs\\.[\\w-]+\\.node|native binding/i.test(message) &&\n // \"no such module\" is workerd's wording when the package is externalized\n // out of the Cloudflare worker bundle.\n /cannot find|no such module|err_module_not_found|dlopen|invalid elf|wrong architecture|not a valid win32|native binding/i.test(\n message,\n )\n );\n}\n\nexport function renderAgentNativeOgImageSvg(\n input: AgentNativeOgImageInput = {},\n): string {\n const appName =\n cleanText(input.appName) || resolveAgentNativeOgImageAppName();\n const title = cleanText(input.title) || titleFromAppName(appName);\n const accentText = cleanText(input.accentText) || DEFAULT_ACCENT_TEXT;\n const titleLayout = getTitleLayout(title);\n const titleY = titleLayout.lines.length > 1 ? 288 : 330;\n const accentY =\n titleY + titleLayout.lineHeight * (titleLayout.lines.length - 1) + 70;\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${WIDTH}\" height=\"${HEIGHT}\" viewBox=\"0 0 ${WIDTH} ${HEIGHT}\">\n <title>${escapeSvg(title)} - Agent-Native preview</title>\n <defs>\n <linearGradient id=\"brand\" x1=\"101.702\" y1=\"67.4791\" x2=\"113.672\" y2=\"-37.4275\" gradientUnits=\"userSpaceOnUse\">\n <stop stop-color=\"${BRAND_BLUE}\"/>\n <stop offset=\"1\" stop-color=\"${BRAND_MINT}\"/>\n </linearGradient>\n <pattern id=\"grid\" width=\"48\" height=\"48\" patternUnits=\"userSpaceOnUse\">\n <path d=\"M 48 0 L 0 0 0 48\" fill=\"none\" stroke=\"#ffffff\" stroke-opacity=\"0.07\" stroke-width=\"1\"/>\n </pattern>\n </defs>\n <rect width=\"${WIDTH}\" height=\"${HEIGHT}\" fill=\"${BG}\"/>\n <rect width=\"${WIDTH}\" height=\"${HEIGHT}\" fill=\"url(#grid)\"/>\n <g transform=\"translate(80 116) scale(0.94)\">\n ${LOGO_MARK}\n </g>\n <g>\n ${textBlock({\n lines: titleLayout.lines,\n x: 80,\n y: titleY,\n fontSize: titleLayout.fontSize,\n lineHeight: titleLayout.lineHeight,\n // resvg's fontdb maps font-weight 850 to the Regular face (only 400/700\n // exist for Liberation Sans); 800 resolves to Bold, the heaviest face we\n // bundle, which is the intended look for the display title.\n weight: 800,\n fill: FG,\n })}\n <text x=\"84\" y=\"${accentY}\" font-family=\"${FONT_FAMILY}\" font-size=\"34\" font-weight=\"800\" fill=\"${BRAND_BLUE}\">${escapeSvg(accentText)}</text>\n </g>\n</svg>`;\n}\n\nexport async function renderAgentNativeOgImagePng(\n input: AgentNativeOgImageInput = {},\n): Promise<Uint8Array> {\n const overridePackage =\n typeof process !== \"undefined\"\n ? process.env.AGENT_NATIVE_RESVG_PACKAGE\n : undefined;\n const resvgPackage = overridePackage || \"@resvg/resvg-js\";\n const { Resvg } = await import(/* @vite-ignore */ resvgPackage);\n // Feed resvg the embedded Liberation Sans font explicitly. System fonts can't\n // be relied on: Linux serverless runtimes (Netlify/Lambda) ship neither Arial\n // nor Inter, so without a bundled font every `<text>` rendered blank.\n const fontFiles = resolveOgFontFiles();\n const hasBundledFonts = Boolean(fontFiles?.length);\n const image = new Resvg(renderAgentNativeOgImageSvg(input), {\n fitTo: { mode: \"width\", value: WIDTH },\n font: {\n loadSystemFonts: !hasBundledFonts,\n ...(hasBundledFonts ? { fontFiles } : {}),\n defaultFontFamily: OG_FONT_FAMILY,\n serifFamily: OG_FONT_FAMILY,\n sansSerifFamily: OG_FONT_FAMILY,\n },\n }).render();\n return image.asPng();\n}\n\nexport function agentNativeOgImageResponseHeaders(\n byteLength?: number,\n contentType = \"image/png\",\n): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": contentType,\n \"Cache-Control\": AGENT_NATIVE_OG_IMAGE_CACHE_CONTROL,\n \"CDN-Cache-Control\": AGENT_NATIVE_OG_IMAGE_CACHE_CONTROL,\n \"Netlify-CDN-Cache-Control\": AGENT_NATIVE_OG_IMAGE_NETLIFY_CACHE_CONTROL,\n \"Cross-Origin-Resource-Policy\": \"cross-origin\",\n };\n if (typeof byteLength === \"number\") {\n headers[\"Content-Length\"] = String(byteLength);\n }\n return headers;\n}\n\nexport function createAgentNativeOgImageHandler(\n options: AgentNativeOgImageInput = {},\n) {\n return defineEventHandler(async (event) => {\n if (getMethod(event) === \"HEAD\") {\n return new Response(null, {\n headers: agentNativeOgImageResponseHeaders(),\n });\n }\n\n const query = getQuery(event);\n const appName =\n cleanText(options.appName) || resolveAgentNativeOgImageAppName(event);\n const input = {\n ...options,\n appName,\n title: cleanText(options.title) || queryStringValue(query.title, 140),\n accentText:\n cleanText(options.accentText) || queryStringValue(query.accentText, 80),\n };\n\n let png: Uint8Array;\n try {\n png = await renderAgentNativeOgImagePng(input);\n } catch (error) {\n if (!isResvgRuntimeUnavailableError(error)) throw error;\n const svg = renderAgentNativeOgImageSvg(input);\n return new Response(svg, {\n headers: agentNativeOgImageResponseHeaders(\n textByteLength(svg),\n \"image/svg+xml; charset=utf-8\",\n ),\n });\n }\n\n return new Response(pngBody(png), {\n headers: agentNativeOgImageResponseHeaders(png.byteLength),\n });\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAU,UAAU,EAAE,MAAM,MAAM,CAAC;AAmB/C,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,kCAAkC,CAAC;AA0H1C;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgE9C;AAED;;;;;;GAMG;AACH,iBAAS,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCvD;AAOD;;;;;GAKG;AACH,iBAAS,qBAAqB,CAC5B,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAc9C;AAoCD,iBAAS,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAmNrD;AAsKD,MAAM,WAAW,YAAY;IAC3B,sGAAsG;IACtG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,YAAY,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;IAC9E,oGAAoG;IACpG,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAClC,8BAA8B;IAC9B,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iDAAiD;IACjD,YAAY,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;IACvD,wCAAwC;IACxC,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9B;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,iCAAiC,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjD;AA+dD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,MAAM,GAAG,SAAS,CAMpB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,OAAO,CAWT;AAoMD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,UAAU,CAuS1E;AAED,OAAO,EACL,eAAe,IAAI,gBAAgB,EACnC,sBAAsB,IAAI,uBAAuB,EACjD,mBAAmB,IAAI,oBAAoB,EAC3C,qBAAqB,IAAI,sBAAsB,GAChD,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAU,UAAU,EAAE,MAAM,MAAM,CAAC;AAmB/C,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,kCAAkC,CAAC;AA0H1C;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgE9C;AAED;;;;;;GAMG;AACH,iBAAS,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCvD;AAOD;;;;;GAKG;AACH,iBAAS,qBAAqB,CAC5B,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAc9C;AAoCD,iBAAS,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAmNrD;AAsKD,MAAM,WAAW,YAAY;IAC3B,sGAAsG;IACtG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,YAAY,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;IAC9E,oGAAoG;IACpG,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAClC,8BAA8B;IAC9B,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iDAAiD;IACjD,YAAY,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;IACvD,wCAAwC;IACxC,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9B;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,iCAAiC,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjD;AA+dD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,MAAM,GAAG,SAAS,CAMpB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,OAAO,CAWT;AAsRD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,UAAU,CAuS1E;AAED,OAAO,EACL,eAAe,IAAI,gBAAgB,EACnC,sBAAsB,IAAI,uBAAuB,EACjD,mBAAmB,IAAI,oBAAoB,EAC3C,qBAAqB,IAAI,sBAAsB,GAChD,CAAC"}