@agent-native/core 0.106.2 → 0.107.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.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +19 -0
- package/corpus/core/docs/content/external-agents.mdx +8 -0
- package/corpus/core/docs/content/integrations.mdx +597 -0
- package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +7 -0
- package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
- package/corpus/core/docs/content/locales/ar-SA/mcp-protocol.mdx +7 -0
- package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +9 -0
- package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/de-DE/mcp-protocol.mdx +9 -0
- package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +9 -0
- package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
- package/corpus/core/docs/content/locales/es-ES/mcp-protocol.mdx +9 -0
- package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +9 -0
- package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
- package/corpus/core/docs/content/locales/fr-FR/mcp-protocol.mdx +9 -0
- package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +8 -0
- package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/hi-IN/mcp-protocol.mdx +8 -0
- package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +8 -0
- package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
- package/corpus/core/docs/content/locales/ja-JP/mcp-protocol.mdx +8 -0
- package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +8 -0
- package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
- package/corpus/core/docs/content/locales/ko-KR/mcp-protocol.mdx +8 -0
- package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +9 -0
- package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/pt-BR/mcp-protocol.mdx +9 -0
- package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +6 -0
- package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
- package/corpus/core/docs/content/locales/zh-CN/mcp-protocol.mdx +6 -0
- package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +6 -0
- package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
- package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.mdx +6 -0
- package/corpus/core/docs/content/mcp-clients.mdx +51 -1
- package/corpus/core/docs/content/mcp-protocol.mdx +8 -0
- package/corpus/core/docs/content/organizations-teams-permissions.mdx +413 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/AssistantChat.tsx +13 -1
- package/corpus/core/src/client/chat/message-components.tsx +41 -0
- package/corpus/core/src/client/composer/TiptapComposer.tsx +45 -8
- package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +30 -11
- package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +240 -0
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +159 -40
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +433 -4
- package/corpus/core/src/client/resources/mcp-integration-logos.ts +108 -0
- package/corpus/core/src/deploy/build.ts +32 -0
- package/corpus/core/src/extensions/html-shell.ts +33 -1
- package/corpus/core/src/ingestion/office.ts +1 -2
- package/corpus/core/src/ingestion/pptx.ts +2 -4
- package/corpus/core/src/localization/default-messages.ts +126 -1
- package/corpus/core/src/mcp/actions/call-mcp-tool.ts +1 -0
- package/corpus/core/src/mcp/builtin-tools.ts +115 -10
- package/corpus/core/src/server/index.ts +4 -0
- package/corpus/core/src/server/org-admin.ts +28 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
- package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +64 -0
- package/corpus/templates/analytics/AGENTS.md +5 -0
- package/corpus/templates/analytics/actions/clone-creative-context-dashboard.ts +86 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/analytics/app/i18n-data.ts +1 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +8 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +59 -0
- package/corpus/templates/analytics/app/routes/agent.tsx +7 -1
- package/corpus/templates/analytics/changelog/2026-07-17-library-now-flags-published-dashboards-with-newer-versions-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/analytics/package.json +1 -0
- package/corpus/templates/analytics/server/lib/native-creative-context.ts +158 -0
- package/corpus/templates/analytics/server/plugins/creative-context.ts +10 -0
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +12 -3
- package/corpus/templates/assets/AGENTS.md +5 -0
- package/corpus/templates/assets/actions/clone-creative-context-asset.ts +74 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +308 -178
- package/corpus/templates/assets/app/routes/library.tsx +5 -11
- package/corpus/templates/assets/changelog/2026-07-17-library-now-flags-published-assets-with-newer-versions-and-l.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/assets/server/lib/native-creative-context.ts +198 -0
- package/corpus/templates/assets/server/plugins/creative-context.ts +4 -0
- package/corpus/templates/brain/actions/provider-api-request.ts +1 -0
- package/corpus/templates/calendar/actions/provider-api-request.ts +1 -0
- package/corpus/templates/clips/actions/get-recording-insights.ts +7 -4
- package/corpus/templates/clips/actions/list-recordings.ts +48 -0
- package/corpus/templates/clips/actions/list-viewers.ts +2 -1
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +3 -1
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -3
- package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +11 -6
- package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -1
- package/corpus/templates/clips/app/lib/ffmpeg-export.ts +4 -2
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -3
- package/corpus/templates/clips/changelog/2026-07-17-dictation-keeps-sentence-spacing-and-no-longer-crashes-when-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-shared-clips-now-preserve-editor-access-and-show-editor-insi.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-stitching-clips-no-longer-fails-when-editor-media-metadata-i.md +6 -0
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -8
- package/corpus/templates/clips/shared/view-analytics.ts +4 -0
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +12 -3
- package/corpus/templates/content/AGENTS.md +5 -0
- package/corpus/templates/content/actions/clone-creative-context-document.ts +61 -0
- package/corpus/templates/content/actions/provider-api-request.ts +1 -0
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +21 -0
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +29 -0
- package/corpus/templates/content/changelog/2026-07-17-library-now-flags-published-documents-with-newer-versions-an.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +1 -0
- package/corpus/templates/content/server/lib/native-creative-context.ts +191 -0
- package/corpus/templates/content/server/plugins/creative-context.ts +8 -1
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -3
- package/corpus/templates/design/AGENTS.md +5 -0
- package/corpus/templates/design/actions/clone-creative-context-design-native.ts +111 -0
- package/corpus/templates/design/actions/provider-api-request.ts +1 -0
- package/corpus/templates/design/app/pages/Index.tsx +44 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +1 -0
- package/corpus/templates/design/changelog/2026-07-17-library-now-flags-published-designs-with-newer-versions-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/design/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/design/server/lib/native-creative-context.ts +265 -0
- package/corpus/templates/design/server/plugins/creative-context.ts +8 -1
- package/corpus/templates/dispatch/actions/provider-api-request.ts +1 -0
- package/corpus/templates/mail/actions/provider-api-request.ts +1 -0
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +11 -3
- package/corpus/templates/slides/AGENTS.md +5 -0
- package/corpus/templates/slides/actions/clone-creative-context-deck.ts +96 -0
- package/corpus/templates/slides/actions/extract-pdf.ts +3 -2
- package/corpus/templates/slides/actions/import-file.ts +3 -2
- package/corpus/templates/slides/actions/provider-api-request.ts +1 -0
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +27 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -0
- package/corpus/templates/slides/changelog/2026-07-17-library-now-flags-published-decks-with-newer-versions-and-le.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-pdf-and-powerpoint-imports-now-work-reliably-in-hosted-decks.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/slides/server/lib/native-creative-context.ts +288 -0
- package/corpus/templates/slides/server/plugins/creative-context.ts +4 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +8 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +35 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +7 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +37 -8
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js +3 -2
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts +9 -0
- package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -0
- package/dist/client/resources/McpConnectionSuggestion.js +115 -0
- package/dist/client/resources/McpConnectionSuggestion.js.map +1 -0
- package/dist/client/resources/McpIntegrationDialog.d.ts +2 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +48 -20
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +9 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +387 -4
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/resources/mcp-integration-logos.d.ts +2 -0
- package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -0
- package/dist/client/resources/mcp-integration-logos.js +109 -0
- package/dist/client/resources/mcp-integration-logos.js.map +1 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +23 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +33 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/ingestion/office.d.ts.map +1 -1
- package/dist/ingestion/office.js +1 -2
- package/dist/ingestion/office.js.map +1 -1
- package/dist/ingestion/pptx.js +2 -4
- package/dist/ingestion/pptx.js.map +1 -1
- package/dist/localization/default-messages.d.ts +98 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +99 -1
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/actions/call-mcp-tool.js +1 -0
- package/dist/mcp/actions/call-mcp-tool.js.map +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +87 -6
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/org-admin.d.ts +3 -0
- package/dist/server/org-admin.d.ts.map +1 -0
- package/dist/server/org-admin.js +24 -0
- package/dist/server/org-admin.js.map +1 -0
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
- package/docs/content/external-agents.mdx +8 -0
- package/docs/content/integrations.mdx +597 -0
- package/docs/content/locales/ar-SA/external-agents.mdx +7 -0
- package/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
- package/docs/content/locales/ar-SA/mcp-protocol.mdx +7 -0
- package/docs/content/locales/de-DE/external-agents.mdx +9 -0
- package/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
- package/docs/content/locales/de-DE/mcp-protocol.mdx +9 -0
- package/docs/content/locales/es-ES/external-agents.mdx +9 -0
- package/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
- package/docs/content/locales/es-ES/mcp-protocol.mdx +9 -0
- package/docs/content/locales/fr-FR/external-agents.mdx +9 -0
- package/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
- package/docs/content/locales/fr-FR/mcp-protocol.mdx +9 -0
- package/docs/content/locales/hi-IN/external-agents.mdx +8 -0
- package/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
- package/docs/content/locales/hi-IN/mcp-protocol.mdx +8 -0
- package/docs/content/locales/ja-JP/external-agents.mdx +8 -0
- package/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
- package/docs/content/locales/ja-JP/mcp-protocol.mdx +8 -0
- package/docs/content/locales/ko-KR/external-agents.mdx +8 -0
- package/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
- package/docs/content/locales/ko-KR/mcp-protocol.mdx +8 -0
- package/docs/content/locales/pt-BR/external-agents.mdx +9 -0
- package/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
- package/docs/content/locales/pt-BR/mcp-protocol.mdx +9 -0
- package/docs/content/locales/zh-CN/external-agents.mdx +6 -0
- package/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
- package/docs/content/locales/zh-CN/mcp-protocol.mdx +6 -0
- package/docs/content/locales/zh-TW/external-agents.mdx +6 -0
- package/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
- package/docs/content/locales/zh-TW/mcp-protocol.mdx +6 -0
- package/docs/content/mcp-clients.mdx +51 -1
- package/docs/content/mcp-protocol.mdx +8 -0
- package/docs/content/organizations-teams-permissions.mdx +413 -0
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-shell.d.ts","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB,QAQ3B,CAAC;AAEZ,eAAO,MAAM,oBAAoB,QAA+E,CAAC;AAEjH,eAAO,MAAM,yBAAyB,sXAA4B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;;OASG;IACH,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC9C,qFAAqF;IACrF,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,
|
|
1
|
+
{"version":3,"file":"html-shell.d.ts","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB,QAQ3B,CAAC;AAEZ,eAAO,MAAM,oBAAoB,QAA+E,CAAC;AAEjH,eAAO,MAAM,yBAAyB,sXAA4B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;;OASG;IACH,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC9C,qFAAqF;IACrF,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,CA8rBR"}
|
|
@@ -344,7 +344,33 @@ export function buildExtensionHtml(content, themeVars, isDark, extensionId, bind
|
|
|
344
344
|
return res.body;
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
-
|
|
347
|
+
var mcp = {
|
|
348
|
+
listTools: function(serverId) {
|
|
349
|
+
var params = serverId ? { serverId: String(serverId) } : {};
|
|
350
|
+
return appAction('list-mcp-tools', params);
|
|
351
|
+
},
|
|
352
|
+
callTool: function(serverId, toolName, args) {
|
|
353
|
+
if (!serverId || !toolName) {
|
|
354
|
+
return Promise.reject(new Error('MCP serverId and toolName are required'));
|
|
355
|
+
}
|
|
356
|
+
return appAction('call-mcp-tool', {
|
|
357
|
+
serverId: String(serverId),
|
|
358
|
+
toolName: String(toolName),
|
|
359
|
+
arguments: args || {},
|
|
360
|
+
});
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
var providerApi = {
|
|
365
|
+
catalog: function(params) {
|
|
366
|
+
return appAction('provider-api-catalog', params || {});
|
|
367
|
+
},
|
|
368
|
+
docs: function(params) {
|
|
369
|
+
return appAction('provider-api-docs', params || {});
|
|
370
|
+
},
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
async function appFetch(path, options) {
|
|
348
374
|
options = options || {};
|
|
349
375
|
var res = await hostRequest(path, {
|
|
350
376
|
...options,
|
|
@@ -511,6 +537,12 @@ export function buildExtensionHtml(content, themeVars, isDark, extensionId, bind
|
|
|
511
537
|
extensionFetch: extensionFetch,
|
|
512
538
|
extensionData: extensionData,
|
|
513
539
|
data: extensionData,
|
|
540
|
+
mcp: mcp,
|
|
541
|
+
providerApi: providerApi,
|
|
542
|
+
connectors: Object.assign({}, (window.agentNative && window.agentNative.connectors) || {}, {
|
|
543
|
+
mcp: mcp,
|
|
544
|
+
providerApi: providerApi,
|
|
545
|
+
}),
|
|
514
546
|
sendToChat: sendToChat,
|
|
515
547
|
chat: Object.assign({}, (window.agentNative && window.agentNative.chat) || {}, {
|
|
516
548
|
send: sendToChat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-shell.js","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAC;AAE/E,MAAM,yBAAyB,GAC7B,mXAAmX,CAAC;AAEtX,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,QAAQ;IACR,0BAA0B;IAC1B,4BAA4B;IAC5B,oBAAoB;IACpB,oBAAoB;IACpB,gCAAgC;IAChC,0CAA0C;CAC3C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,yBAAyB,oBAAoB,yBAAyB,GAAG,CAAC;AAEjH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAqEnE,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,SAAiB,EACjB,MAAe,EACf,WAAoB,EACpB,OAAgC;IAEhC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,mBAAmB,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAChC,OAAO,IAAI;QACT,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,OAAO;KACd,CACF,CAAC;IAEF,OAAO;iBACQ,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;;;;wDAIU,yBAAyB;IAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,uDAAuD,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmFlI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA4TK,eAAe;8BACV,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8OtC,iCAAiC,EAAE;;QAE9B,WAAW,CAAC,CAAC,CAAC,uBAAuB,eAAe,mBAAmB,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE;GACnG,OAAO;;;;;;;;;;SAUD,CAAC;AACV,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["import { buildSessionReplayIframeBootstrap } from \"./session-replay-iframe.js\";\n\nconst EXTENSION_IFRAME_CSP_BASE =\n \"default-src 'none'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; font-src https://fonts.gstatic.com; connect-src 'self'; img-src 'self' data: blob:; media-src 'self' data: blob:; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none';\";\n\nexport const EXTENSION_FRAME_ANCESTORS = [\n \"'self'\",\n \"https://agent-native.com\",\n \"https://*.agent-native.com\",\n \"http://localhost:*\",\n \"http://127.0.0.1:*\",\n \"https://*.claudemcpcontent.com\",\n \"https://*.web-sandbox.oaiusercontent.com\",\n].join(\" \");\n\nexport const EXTENSION_IFRAME_CSP = `${EXTENSION_IFRAME_CSP_BASE} frame-ancestors ${EXTENSION_FRAME_ANCESTORS};`;\n\nexport const EXTENSION_IFRAME_META_CSP = EXTENSION_IFRAME_CSP_BASE;\n\n/**\n * SECURITY — EXTENSION CONTENT IS UNTRUSTED.\n *\n * `${content}` (line ~Body) interpolates raw HTML/JS authored by a user. This\n * file is the boundary between framework-controlled HTML and user-controlled\n * HTML. Two non-negotiable invariants for every change here:\n *\n * 1. The iframe MUST be rendered with a `sandbox` attribute that does NOT\n * include `allow-same-origin`. The viewer (`ExtensionViewer.tsx`,\n * `EmbeddedExtension.tsx`) normalizes the sandbox through\n * `normalizeAgentNativeExtensionSandbox()`, which permits scripts, forms,\n * popups, and downloads but strips `allow-same-origin`. Adding\n * `allow-same-origin` would give the extension full DOM access to the\n * parent window via cross-frame script.\n *\n * 2. Every reachable parent action must treat the postMessage payload as\n * hostile. The bridge in `iframe-bridge.ts` enforces a path allowlist,\n * header sanitization, and method allowlist; do not relax those gates\n * for \"convenience\" in this file or any caller.\n *\n * For the trust model rationale, see audit 05-tools-sandbox.md (C1) and the\n * `extensions` skill. When in doubt, fail closed.\n *\n * BACKWARDS COMPAT — the iframe injects helpers under both their canonical\n * `extension*` names (`extensionFetch`, `extensionData`, `extensionId`,\n * `extensionBinding`) AND legacy `tool*` aliases (`toolFetch`, `toolData`,\n * `toolId`, `toolBinding`) so existing user-authored extension bodies that\n * pre-date the rename keep working. Same for layout opt-ins:\n * `data-extension-layout=\"full-bleed\"` / `data-extension-padding=\"none\"` /\n * class `agent-native-extension-bleed` / CSS var\n * `--agent-native-extension-padding` are canonical; the `data-tool-*`,\n * `agent-native-tool-bleed`, and `--agent-native-tool-padding` variants are\n * accepted as aliases.\n */\n\nexport interface ExtensionRenderBinding {\n /** Email of the user who authored / owns the extension. */\n authorEmail: string;\n /** Email of the user currently viewing/running the extension. */\n viewerEmail: string;\n /** True when viewer === author. */\n isAuthor: boolean;\n /**\n * Resolved role for the viewer (\"owner\" | \"admin\" | \"editor\" | \"viewer\").\n *\n * TODO(security, audit H4): the host-side bridge does not yet gate any\n * helper based on this value — every viewer gets the same powers as the\n * author. The role is plumbed through so a follow-up PR can constrain\n * `appAction` / `dbExec` / `extensionFetch` for non-author viewers (and\n * eventually require an explicit consent step before running a shared\n * extension, audit C1). For now this is metadata only.\n */\n role: \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n /** Where the extension definition came from. Database extensions are the default. */\n source?: \"database\" | \"local-files\";\n /**\n * Fine-grained helper permissions for local file extensions. Database-backed\n * extensions keep using the role table in the parent bridge.\n */\n permissions?: {\n appActions?: string[];\n extensionData?: boolean;\n sql?: boolean;\n externalFetch?: boolean;\n };\n}\n\nexport function buildExtensionHtml(\n content: string,\n themeVars: string,\n isDark: boolean,\n extensionId?: string,\n binding?: ExtensionRenderBinding,\n): string {\n const extensionIdJson = JSON.stringify(extensionId ?? \"\");\n const extensionIdAttr = escapeHtmlAttribute(extensionId ?? \"\");\n const bindingJson = JSON.stringify(\n binding ?? {\n authorEmail: \"\",\n viewerEmail: \"\",\n isAuthor: true,\n role: \"owner\",\n },\n );\n\n return `<!DOCTYPE html>\n<html lang=\"en\"${isDark ? ' class=\"dark\"' : \"\"}>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Security-Policy\" content=\"${EXTENSION_IFRAME_META_CSP}\" />\n ${binding && !binding.isAuthor ? `<meta name=\"agent-native-extension-author\" content=\"${escapeHtmlAttribute(binding.authorEmail)}\" />` : \"\"}\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300..700&display=swap\" rel=\"stylesheet\" />\n <script>\n var _extensionErrors = [];\n var _extensionErrorDetails = [];\n var _consoleLogs = [];\n var _networkLogs = [];\n\n var _origConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info };\n function _wrapConsole(level, orig) {\n return function() {\n var args = Array.prototype.slice.call(arguments);\n var msg = args.map(function(a) {\n try { return typeof a === 'object' ? JSON.stringify(a) : String(a); }\n catch(e) { return String(a); }\n }).join(' ');\n if (_consoleLogs.length >= 50) _consoleLogs.shift();\n _consoleLogs.push({ level: level, message: msg });\n orig.apply(console, arguments);\n };\n }\n console.log = _wrapConsole('log', _origConsole.log);\n console.warn = _wrapConsole('warn', _origConsole.warn);\n console.error = _wrapConsole('error', _origConsole.error);\n console.info = _wrapConsole('info', _origConsole.info);\n\n function _collectError(message, stack) {\n if (!message) return;\n if (message === 'Script error.' || message === 'Script error') message = 'Runtime error';\n if (_extensionErrors.indexOf(message) !== -1) return;\n _extensionErrors.push(message);\n _extensionErrorDetails.push({ message: message, stack: stack || '' });\n _renderErrorToast();\n }\n\n function _renderErrorToast() {\n var toast = document.getElementById('__extension-error-toast');\n if (!toast) return;\n var msg = document.getElementById('__extension-error-msg');\n if (!msg || _extensionErrors.length === 0) return;\n if (_extensionErrors.length === 1) {\n msg.textContent = _extensionErrors[0];\n } else {\n msg.textContent = _extensionErrors.length + ' errors — ' + _extensionErrors[_extensionErrors.length - 1];\n }\n toast.style.display = 'block';\n }\n\n window.addEventListener('error', function(event) {\n var msg = event.message || '';\n if (msg.indexOf('Alpine Expression Error') === 0) return;\n var stack = event.error && event.error.stack ? event.error.stack : '';\n _collectError(msg, stack);\n });\n\n window.addEventListener('unhandledrejection', function(event) {\n var msg = event.reason && event.reason.message ? event.reason.message : String(event.reason);\n var stack = event.reason && event.reason.stack ? event.reason.stack : '';\n _collectError(msg, stack);\n });\n </script>\n <!--\n SECURITY: pinned to exact patch versions + SRI integrity hashes. A\n malicious republish of @tailwindcss/browser@4.x or alpinejs@3.x would\n otherwise inject code into every extension. To bump these versions:\n 1. npm view @tailwindcss/browser version (or alpinejs)\n 2. curl -sL https://cdn.jsdelivr.net/npm/@tailwindcss/browser@<v> \\\\\n | openssl dgst -sha384 -binary | openssl base64 -A\n 3. Update the URL + integrity hash below in lockstep.\n -->\n <script\n src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.2.4\"\n integrity=\"sha384-yNSZBFvuOWcmww494a9+1zNuvgUGEXoWkein7cxP8wHUTi3iXCU4vJ7hr3tzBCml\"\n crossorigin=\"anonymous\"\n ></script>\n <script\n defer\n src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.15.11/dist/cdn.min.js\"\n integrity=\"sha384-WPtu0YHhJ3arcykfnv1JgUffWDSKRnqnDeTpJUbOc2os2moEmLkIdaeR0trPN4be\"\n crossorigin=\"anonymous\"\n ></script>\n <style>${themeVars}</style>\n <style type=\"text/tailwindcss\">\n @custom-variant dark (&:where(.dark, .dark *));\n @theme {\n --color-border: hsl(var(--border));\n --color-input: hsl(var(--input));\n --color-ring: hsl(var(--ring));\n --color-background: hsl(var(--background));\n --color-foreground: hsl(var(--foreground));\n --color-primary: hsl(var(--primary));\n --color-primary-foreground: hsl(var(--primary-foreground));\n --color-secondary: hsl(var(--secondary));\n --color-secondary-foreground: hsl(var(--secondary-foreground));\n --color-destructive: hsl(var(--destructive));\n --color-destructive-foreground: hsl(var(--destructive-foreground));\n --color-muted: hsl(var(--muted));\n --color-muted-foreground: hsl(var(--muted-foreground));\n --color-accent: hsl(var(--accent));\n --color-accent-foreground: hsl(var(--accent-foreground));\n --color-popover: hsl(var(--popover));\n --color-popover-foreground: hsl(var(--popover-foreground));\n --color-card: hsl(var(--card));\n --color-card-foreground: hsl(var(--card-foreground));\n --color-sidebar: hsl(var(--sidebar-background));\n --color-sidebar-foreground: hsl(var(--sidebar-foreground));\n --color-sidebar-primary: hsl(var(--sidebar-primary));\n --color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));\n --color-sidebar-accent: hsl(var(--sidebar-accent));\n --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));\n --color-sidebar-border: hsl(var(--sidebar-border));\n --color-sidebar-ring: hsl(var(--sidebar-ring));\n --radius-lg: var(--radius);\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n }\n </style>\n\t <style>\n\t *, *::before, *::after { border-color: hsl(var(--border)); }\n\t html, body {\n\t /* Transparent so the iframe inherits the host surface (dashboard panel,\n\t sidebar, chat) instead of painting the browser's default white canvas.\n\t The dark class still flips the theme vars; content paints its own\n\t bg-background / bg-card surfaces. */\n\t background: transparent;\n\t }\n\t body {\n\t --agent-native-extension-padding: clamp(16px, 2vw, 24px);\n\t /* Legacy alias for pre-rename extension content (do not remove). */\n\t --agent-native-tool-padding: var(--agent-native-extension-padding);\n\t box-sizing: border-box;\n\t color: hsl(var(--foreground));\n\t font-family: 'Inter', sans-serif;\n\t margin: 0;\n\t min-height: 100vh;\n\t padding: var(--agent-native-extension-padding);\n\t }\n\t body:has(> [data-extension-layout=\"full-bleed\"]),\n\t body:has(> [data-extension-padding=\"none\"]),\n\t body:has(> .agent-native-extension-bleed),\n\t /* Legacy aliases (do not remove). */\n\t body:has(> [data-tool-layout=\"full-bleed\"]),\n\t body:has(> [data-tool-padding=\"none\"]),\n\t body:has(> .agent-native-tool-bleed) {\n\t padding: 0;\n\t }\n\t </style>\n\t <script>\n\t var _extensionRequestSeq = 0;\n\t var _extensionPendingRequests = {};\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var message = event.data || {};\n\t if (\n\t message.type !== 'agent-native-extension-response' &&\n\t message.type !== 'agent-native-tool-response'\n\t ) return;\n\t var pending = _extensionPendingRequests[message.requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[message.requestId];\n\t if (message.error) {\n\t pending.reject(new Error(message.error));\n\t } else {\n\t pending.resolve(message.response);\n\t }\n\t });\n\n\t function hostRequest(path, options) {\n\t options = options || {};\n\t return new Promise(function(resolve, reject) {\n\t var requestId = 'extension-req-' + (++_extensionRequestSeq);\n\t _extensionPendingRequests[requestId] = { resolve: resolve, reject: reject };\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-request',\n\t requestId: requestId,\n\t path: path,\n\t options: {\n\t method: options.method || 'GET',\n\t headers: options.headers || {},\n\t body: options.body,\n\t },\n\t }, '*');\n\t setTimeout(function() {\n\t var pending = _extensionPendingRequests[requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[requestId];\n\t pending.reject(new Error('Extension host request timed out'));\n\t }, 30000);\n\t });\n\t }\n\n\t var _origHostRequest = hostRequest;\n\t hostRequest = function(path, options) {\n\t var entry = { path: path, method: (options && options.method) || 'GET' };\n\t return _origHostRequest(path, options).then(function(res) {\n\t entry.ok = res.ok;\n\t entry.status = res.status;\n\t if (!res.ok && res.body) {\n\t try { entry.error = typeof res.body === 'string' ? res.body.slice(0, 200) : JSON.stringify(res.body).slice(0, 200); } catch(e) {}\n\t }\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t return res;\n\t }, function(err) {\n\t entry.ok = false;\n\t entry.error = err.message;\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t throw err;\n\t });\n\t };\n\n\t function extensionFetch(url, options) {\n\t var opts = options || {};\n\t return hostRequest('/_agent-native/extensions/proxy', {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({\n\t url: url,\n method: opts.method || 'GET',\n headers: opts.headers,\n body: opts.body,\n }),\n\t }).then(function(res) {\n\t var data = res.body;\n\t if (data.error && data.status === undefined) {\n\t throw new Error(data.error);\n\t }\n return {\n ok: data.status >= 200 && data.status < 300,\n status: data.status,\n\t json: function() { return Promise.resolve(data.body); },\n\t text: function() { return Promise.resolve(typeof data.body === 'string' ? data.body : JSON.stringify(data.body)); },\n\t };\n\t });\n\t }\n\n\t function _appendActionQuery(path, params) {\n\t var search = new URLSearchParams();\n\t params = params || {};\n\t Object.keys(params).forEach(function(key) {\n\t var value = params[key];\n\t if (value === undefined || value === null) return;\n\t if (Array.isArray(value)) {\n\t value.forEach(function(item) {\n\t if (item !== undefined && item !== null) {\n\t search.append(key, String(item));\n\t }\n\t });\n\t return;\n\t }\n\t search.set(key, String(value));\n\t });\n\t var qs = search.toString();\n\t return qs ? path + '?' + qs : path;\n\t }\n\n\t function _methodHintFromActionResponse(res) {\n\t if (!res || res.status !== 405) return null;\n\t var body = res.body || {};\n\t var message = typeof body === 'string' ? body : body.error;\n\t if (!message) return null;\n\t var match = String(message).match(/Use (GET|POST|PUT|PATCH|DELETE|HEAD)\\\\.?/i);\n\t return match ? match[1].toUpperCase() : null;\n\t }\n\n\t async function appAction(name, params) {\n\t params = params || {};\n\t if (name === 'navigate') {\n\t var navRes = await hostRequest('/_agent-native/application-state/navigate', {\n\t method: 'PUT',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\t if (!navRes.ok) {\n\t var navErr = navRes.body || { error: navRes.statusText };\n\t throw new Error(navErr.error || 'Navigation failed: ' + navRes.status);\n\t }\n\t return navRes.body;\n\t }\n\t var path = '/_agent-native/actions/' + encodeURIComponent(name);\n\t var res = await hostRequest(path, {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\n\t var retryMethod = _methodHintFromActionResponse(res);\n\t if (!res.ok && retryMethod && retryMethod !== 'POST') {\n\t var retryPath = path;\n\t var retryOptions = {\n\t method: retryMethod,\n\t headers: { 'Content-Type': 'application/json' },\n\t };\n\t if (retryMethod === 'GET' || retryMethod === 'HEAD') {\n\t retryPath = _appendActionQuery(path, params);\n\t } else {\n\t retryOptions.body = JSON.stringify(params);\n\t }\n\t res = await hostRequest(retryPath, retryOptions);\n\t }\n\n\t if (!res.ok) {\n\t var err = res.body || {};\n\t var rawError = typeof err === 'string' ? err : err.error;\n\t var message = (typeof rawError === 'string' && rawError.trim())\n\t ? rawError\n\t : (res.status === 404\n\t ? \"Action '\" + name + \"' is not available over HTTP (404). It may be agent-only (http: false); expose it with an HTTP-mounted action to call it from an extension.\"\n\t : \"Action '\" + name + \"' failed (\" + (res.status || 'network error') + \")\");\n\t throw new Error(message);\n\t }\n\t return res.body;\n\t }\n\n\t async function appFetch(path, options) {\n\t options = options || {};\n\t var res = await hostRequest(path, {\n\t ...options,\n\t headers: {\n\t 'Content-Type': 'application/json',\n\t ...(options.headers || {}),\n\t },\n\t });\n\t if (!res.ok) {\n\t var err = typeof res.body === 'object' && res.body ? res.body : { error: res.statusText };\n\t throw new Error(err.error || 'Request failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n\t function sendToChat(message, options) {\n\t options = options || {};\n\t var text = typeof message === 'string' ? message : JSON.stringify(message);\n\t window.parent.postMessage({\n\t type: 'agent-native-send-to-chat',\n\t message: text,\n\t context: options.context,\n\t submit: options.submit !== false,\n\t openSidebar: options.openSidebar !== false,\n\t }, '*');\n\t return { ok: true };\n\t }\n\n\t function inlineUiOutputKey() {\n\t var safeId = String(_extensionId || 'unknown').replace(/[^A-Za-z0-9_:-]/g, '') || 'unknown';\n\t return 'inline-ui:' + safeId + ':output';\n\t }\n\n\t async function outputToUi(value, options) {\n\t options = options || {};\n\t var key = inlineUiOutputKey();\n\t var payload = {\n\t value: value,\n\t updatedAt: new Date().toISOString(),\n\t extensionId: _extensionId,\n\t source: 'inline-ui',\n\t };\n\t if (options.label !== undefined) payload.label = options.label;\n\t if (options.context !== undefined) payload.context = options.context;\n\t if (options.meta !== undefined) payload.meta = options.meta;\n\t var output = await appFetch('/_agent-native/application-state/' + key, {\n\t method: 'PUT',\n\t headers: { 'X-Request-Source': 'inline-ui' },\n\t body: JSON.stringify(payload),\n\t });\n\t try {\n\t window.parent.postMessage({\n\t type: 'agent-native-ui-output',\n\t extensionId: _extensionId,\n\t key: key,\n\t value: value,\n\t output: output,\n\t }, '*');\n\t } catch (_) {}\n\t return { ok: true, key: key, output: output };\n\t }\n\n async function dbQuery(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/query', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n async function dbExec(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/exec', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n var _extensionId = ${extensionIdJson};\n var _extensionBinding = ${bindingJson};\n window.extensionBinding = _extensionBinding;\n // Legacy alias for extension bodies authored before the rename.\n window.toolBinding = _extensionBinding;\n // SECURITY (audit H4): announce the resolved binding to the parent so the\n // host bridge can gate dangerous helpers based on viewer role. Sent\n // BEFORE the user-authored content has a chance to run, so a malicious\n // extension body cannot suppress or rewrite the announcement. The parent\n // ignores subsequent announcements for the same iframe; see\n // ExtensionViewer.tsx / EmbeddedExtension.tsx.\n try {\n window.parent.postMessage(\n {\n type: 'agent-native-extension-binding',\n extensionId: _extensionId,\n binding: _extensionBinding,\n },\n '*',\n );\n } catch (_) {}\n // SECURITY: when the viewer is not the author of this extension, emit a\n // clear console warning. The bridge currently runs every helper with the\n // viewer's session — a malicious shared extension can call any action,\n // read any owned table row in scope, and resolve any user-scope secret.\n // A full consent step is tracked as TODO C1 in audit 05-tools-sandbox.md.\n if (_extensionBinding && !_extensionBinding.isAuthor) {\n try {\n console.warn(\n '[agent-native] Shared extension — running with viewer\\\\'s session. ' +\n 'Author: ' + (_extensionBinding.authorEmail || '<unknown>') + '. ' +\n 'Bridge calls (appAction, dbExec, extensionFetch) execute under ' +\n 'your account; they are gated by your permissions, not the ' +\n 'author\\\\'s. Do not run untrusted shared extensions.',\n );\n } catch (_) {}\n }\n\n var extensionData = {\n\t async list(collection, opts) {\n\t var limit = (opts && opts.limit) || 100;\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '?limit=' + limit + '&scope=' + scope);\n\t if (!res.ok) throw new Error('Failed to list extension data');\n\t return res.body;\n\t },\n async get(collection, id, opts) {\n var scope = (opts && opts.scope) || 'user';\n var items = await this.list(collection, { scope: scope });\n return (items || []).find(function(item) { return item.id === id; }) || null;\n },\n async set(collection, id, data, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection), {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({ id: id, data: data, scope: scope }),\n\t });\n\t if (!res.ok) throw new Error('Failed to save extension data');\n\t return res.body;\n\t },\n\t async remove(collection, id, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '/' + encodeURIComponent(id) + '?scope=' + scope, {\n\t method: 'DELETE',\n\t });\n\t if (!res.ok) throw new Error('Failed to delete extension data');\n\t return res.body;\n\t },\n\t };\n\n\t // Legacy aliases — extension bodies authored before the rename use\n\t // toolFetch, toolData, toolId. Keep these working forever.\n\t var toolFetch = extensionFetch;\n\t var toolData = extensionData;\n\t var _toolId = _extensionId;\n\t window.agentNative = Object.assign(window.agentNative || {}, {\n\t extensionId: _extensionId,\n\t extensionBinding: _extensionBinding,\n\t appAction: appAction,\n\t appFetch: appFetch,\n\t dbQuery: dbQuery,\n\t dbExec: dbExec,\n\t extensionFetch: extensionFetch,\n\t extensionData: extensionData,\n\t data: extensionData,\n\t sendToChat: sendToChat,\n\t chat: Object.assign({}, (window.agentNative && window.agentNative.chat) || {}, {\n\t send: sendToChat,\n\t }),\n\t ui: Object.assign({}, (window.agentNative && window.agentNative.ui) || {}, {\n\t output: outputToUi,\n\t }),\n\t });\n\t window.sendToAgentChat = sendToChat;\n\t </script>\n\t <style>\n\t #__extension-error-toast {\n\t display: none;\n\t position: fixed;\n\t bottom: 16px;\n\t right: 16px;\n\t max-width: 420px;\n\t background: hsl(var(--destructive));\n\t color: hsl(var(--destructive-foreground));\n\t border: 1px solid hsl(var(--destructive) / .6);\n\t border-radius: calc(var(--radius, .5rem) + 2px);\n\t padding: 12px 16px;\n\t font-size: 13px;\n\t line-height: 1.4;\n\t font-family: 'Inter', sans-serif;\n\t z-index: 9999;\n\t box-shadow: 0 4px 12px rgba(0,0,0,.15), 0 1px 3px rgba(0,0,0,.1);\n\t animation: __toast-in 0.2s ease-out;\n\t }\n\t @keyframes __toast-in {\n\t from { opacity: 0; transform: translateY(8px); }\n\t to { opacity: 1; transform: translateY(0); }\n\t }\n\t </style>\n\t <script>\n\t // Extension-point slot context: when an extension is rendered embedded\n\t // inside an ExtensionSlot, the host pushes a context object via\n\t // postMessage. Extensions read it synchronously via window.slotContext\n\t // or subscribe to changes via window.onSlotContext(fn). When rendered\n\t // full-page (no ?slot= param), slotContext stays null and extensions\n\t // branch on that.\n\t window.slotContext = null;\n\t var _slotContextSubscribers = [];\n\t window.onSlotContext = function(fn) {\n\t _slotContextSubscribers.push(fn);\n\t if (window.slotContext !== null) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t }\n\t return function() {\n\t _slotContextSubscribers = _slotContextSubscribers.filter(function(f) { return f !== fn; });\n\t };\n\t };\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-slot-context') return;\n\t window.slotContext = msg.context || {};\n\t _slotContextSubscribers.forEach(function(fn) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t });\n\t });\n\n\t // Auto-resize iframe renders. Persisted extension slots include ?slot=;\n\t // transient inline chat UI uses srcdoc, so detect that by parent frame.\n\t // The host listens for agent-native-extension-resize and adjusts height.\n\t if (new URLSearchParams(location.search).get('slot') || window.parent !== window) {\n\t var _lastH = 0;\n\t var _reportHeight = function() {\n\t var h = Math.max(\n\t document.documentElement.scrollHeight,\n\t document.body ? document.body.scrollHeight : 0,\n\t );\n\t if (h !== _lastH) {\n\t _lastH = h;\n\t window.parent.postMessage({ type: 'agent-native-extension-resize', height: h }, '*');\n\t }\n\t };\n\t if (typeof ResizeObserver !== 'undefined') {\n\t var _ro = new ResizeObserver(_reportHeight);\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _ro.observe(document.documentElement);\n\t if (document.body) _ro.observe(document.body);\n\t });\n\t }\n\t // Initial reports — Alpine takes a tick to render after DOMContentLoaded.\n\t setTimeout(_reportHeight, 50);\n\t setTimeout(_reportHeight, 250);\n\t }\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-theme-update') return;\n\t var root = document.documentElement;\n\t if (msg.isDark !== undefined) {\n\t if (msg.isDark) root.classList.add('dark');\n\t else root.classList.remove('dark');\n\t }\n\t var vars = msg.vars || {};\n\t for (var key in vars) {\n\t if (vars.hasOwnProperty(key)) {\n\t root.style.setProperty(key, vars[key]);\n\t }\n\t }\n\t });\n\n\t document.addEventListener('keydown', function(e) {\n\t if ((e.metaKey || e.ctrlKey) && !e.altKey) {\n\t var key = (e.key || '').toLowerCase();\n\t if (key === 'c' || key === 'v' || key === 'x' || key === 'a' || key === 'z' || key === 'y') return;\n\t e.preventDefault();\n\t e.stopPropagation();\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: e.metaKey, ctrlKey: e.ctrlKey,\n\t shiftKey: e.shiftKey, altKey: e.altKey,\n\t }, '*');\n\t return;\n\t }\n\t if (e.key === 'Escape') {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: false, ctrlKey: false,\n\t shiftKey: false, altKey: false,\n\t }, '*');\n\t }\n\t });\n\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _renderErrorToast();\n\t var fixBtn = document.getElementById('__extension-error-fix');\n\t if (fixBtn) {\n\t fixBtn.addEventListener('click', function() {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-error-fix',\n\t errors: _extensionErrors,\n\t errorDetails: _extensionErrorDetails,\n\t consoleLogs: _consoleLogs.slice(-30),\n\t networkLogs: _networkLogs.slice(-15)\n\t }, '*');\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t var dismissBtn = document.getElementById('__extension-error-dismiss');\n\t if (dismissBtn) {\n\t dismissBtn.addEventListener('click', function() {\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t });\n\t </script>\n\t${buildSessionReplayIframeBootstrap()}\n\t</head>\n\t<body${extensionId ? ` data-extension-id=\"${extensionIdAttr}\" data-tool-id=\"${extensionIdAttr}\"` : \"\"} class=\"text-foreground\">\n\t${content}\n\t<div id=\"__extension-error-toast\">\n\t <div style=\"display:flex;align-items:flex-start;gap:8px;\">\n\t <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0;margin-top:1px;\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/></svg>\n\t <span id=\"__extension-error-msg\" style=\"flex:1;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;\"></span>\n\t <button id=\"__extension-error-fix\" style=\"cursor:pointer;border:none;background:rgba(255,255,255,.9);color:hsl(0 84.2% 40%);font-size:12px;font-weight:500;padding:4px 12px;border-radius:4px;flex-shrink:0;\">Fix</button>\n\t <button id=\"__extension-error-dismiss\" style=\"cursor:pointer;border:none;background:transparent;color:inherit;font-size:16px;padding:2px 6px;opacity:0.7;flex-shrink:0;\">×</button>\n\t </div>\n\t</div>\n\t</body>\n\t</html>`;\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"html-shell.js","sourceRoot":"","sources":["../../src/extensions/html-shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAC;AAE/E,MAAM,yBAAyB,GAC7B,mXAAmX,CAAC;AAEtX,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,QAAQ;IACR,0BAA0B;IAC1B,4BAA4B;IAC5B,oBAAoB;IACpB,oBAAoB;IACpB,gCAAgC;IAChC,0CAA0C;CAC3C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,yBAAyB,oBAAoB,yBAAyB,GAAG,CAAC;AAEjH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAqEnE,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,SAAiB,EACjB,MAAe,EACf,WAAoB,EACpB,OAAgC;IAEhC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,mBAAmB,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAChC,OAAO,IAAI;QACT,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,OAAO;KACd,CACF,CAAC;IAEF,OAAO;iBACQ,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;;;;wDAIU,yBAAyB;IAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,uDAAuD,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmFlI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAsVK,eAAe;8BACV,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoPtC,iCAAiC,EAAE;;QAE9B,WAAW,CAAC,CAAC,CAAC,uBAAuB,eAAe,mBAAmB,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE;GACnG,OAAO;;;;;;;;;;SAUD,CAAC;AACV,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["import { buildSessionReplayIframeBootstrap } from \"./session-replay-iframe.js\";\n\nconst EXTENSION_IFRAME_CSP_BASE =\n \"default-src 'none'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; font-src https://fonts.gstatic.com; connect-src 'self'; img-src 'self' data: blob:; media-src 'self' data: blob:; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none';\";\n\nexport const EXTENSION_FRAME_ANCESTORS = [\n \"'self'\",\n \"https://agent-native.com\",\n \"https://*.agent-native.com\",\n \"http://localhost:*\",\n \"http://127.0.0.1:*\",\n \"https://*.claudemcpcontent.com\",\n \"https://*.web-sandbox.oaiusercontent.com\",\n].join(\" \");\n\nexport const EXTENSION_IFRAME_CSP = `${EXTENSION_IFRAME_CSP_BASE} frame-ancestors ${EXTENSION_FRAME_ANCESTORS};`;\n\nexport const EXTENSION_IFRAME_META_CSP = EXTENSION_IFRAME_CSP_BASE;\n\n/**\n * SECURITY — EXTENSION CONTENT IS UNTRUSTED.\n *\n * `${content}` (line ~Body) interpolates raw HTML/JS authored by a user. This\n * file is the boundary between framework-controlled HTML and user-controlled\n * HTML. Two non-negotiable invariants for every change here:\n *\n * 1. The iframe MUST be rendered with a `sandbox` attribute that does NOT\n * include `allow-same-origin`. The viewer (`ExtensionViewer.tsx`,\n * `EmbeddedExtension.tsx`) normalizes the sandbox through\n * `normalizeAgentNativeExtensionSandbox()`, which permits scripts, forms,\n * popups, and downloads but strips `allow-same-origin`. Adding\n * `allow-same-origin` would give the extension full DOM access to the\n * parent window via cross-frame script.\n *\n * 2. Every reachable parent action must treat the postMessage payload as\n * hostile. The bridge in `iframe-bridge.ts` enforces a path allowlist,\n * header sanitization, and method allowlist; do not relax those gates\n * for \"convenience\" in this file or any caller.\n *\n * For the trust model rationale, see audit 05-tools-sandbox.md (C1) and the\n * `extensions` skill. When in doubt, fail closed.\n *\n * BACKWARDS COMPAT — the iframe injects helpers under both their canonical\n * `extension*` names (`extensionFetch`, `extensionData`, `extensionId`,\n * `extensionBinding`) AND legacy `tool*` aliases (`toolFetch`, `toolData`,\n * `toolId`, `toolBinding`) so existing user-authored extension bodies that\n * pre-date the rename keep working. Same for layout opt-ins:\n * `data-extension-layout=\"full-bleed\"` / `data-extension-padding=\"none\"` /\n * class `agent-native-extension-bleed` / CSS var\n * `--agent-native-extension-padding` are canonical; the `data-tool-*`,\n * `agent-native-tool-bleed`, and `--agent-native-tool-padding` variants are\n * accepted as aliases.\n */\n\nexport interface ExtensionRenderBinding {\n /** Email of the user who authored / owns the extension. */\n authorEmail: string;\n /** Email of the user currently viewing/running the extension. */\n viewerEmail: string;\n /** True when viewer === author. */\n isAuthor: boolean;\n /**\n * Resolved role for the viewer (\"owner\" | \"admin\" | \"editor\" | \"viewer\").\n *\n * TODO(security, audit H4): the host-side bridge does not yet gate any\n * helper based on this value — every viewer gets the same powers as the\n * author. The role is plumbed through so a follow-up PR can constrain\n * `appAction` / `dbExec` / `extensionFetch` for non-author viewers (and\n * eventually require an explicit consent step before running a shared\n * extension, audit C1). For now this is metadata only.\n */\n role: \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n /** Where the extension definition came from. Database extensions are the default. */\n source?: \"database\" | \"local-files\";\n /**\n * Fine-grained helper permissions for local file extensions. Database-backed\n * extensions keep using the role table in the parent bridge.\n */\n permissions?: {\n appActions?: string[];\n extensionData?: boolean;\n sql?: boolean;\n externalFetch?: boolean;\n };\n}\n\nexport function buildExtensionHtml(\n content: string,\n themeVars: string,\n isDark: boolean,\n extensionId?: string,\n binding?: ExtensionRenderBinding,\n): string {\n const extensionIdJson = JSON.stringify(extensionId ?? \"\");\n const extensionIdAttr = escapeHtmlAttribute(extensionId ?? \"\");\n const bindingJson = JSON.stringify(\n binding ?? {\n authorEmail: \"\",\n viewerEmail: \"\",\n isAuthor: true,\n role: \"owner\",\n },\n );\n\n return `<!DOCTYPE html>\n<html lang=\"en\"${isDark ? ' class=\"dark\"' : \"\"}>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Security-Policy\" content=\"${EXTENSION_IFRAME_META_CSP}\" />\n ${binding && !binding.isAuthor ? `<meta name=\"agent-native-extension-author\" content=\"${escapeHtmlAttribute(binding.authorEmail)}\" />` : \"\"}\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300..700&display=swap\" rel=\"stylesheet\" />\n <script>\n var _extensionErrors = [];\n var _extensionErrorDetails = [];\n var _consoleLogs = [];\n var _networkLogs = [];\n\n var _origConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info };\n function _wrapConsole(level, orig) {\n return function() {\n var args = Array.prototype.slice.call(arguments);\n var msg = args.map(function(a) {\n try { return typeof a === 'object' ? JSON.stringify(a) : String(a); }\n catch(e) { return String(a); }\n }).join(' ');\n if (_consoleLogs.length >= 50) _consoleLogs.shift();\n _consoleLogs.push({ level: level, message: msg });\n orig.apply(console, arguments);\n };\n }\n console.log = _wrapConsole('log', _origConsole.log);\n console.warn = _wrapConsole('warn', _origConsole.warn);\n console.error = _wrapConsole('error', _origConsole.error);\n console.info = _wrapConsole('info', _origConsole.info);\n\n function _collectError(message, stack) {\n if (!message) return;\n if (message === 'Script error.' || message === 'Script error') message = 'Runtime error';\n if (_extensionErrors.indexOf(message) !== -1) return;\n _extensionErrors.push(message);\n _extensionErrorDetails.push({ message: message, stack: stack || '' });\n _renderErrorToast();\n }\n\n function _renderErrorToast() {\n var toast = document.getElementById('__extension-error-toast');\n if (!toast) return;\n var msg = document.getElementById('__extension-error-msg');\n if (!msg || _extensionErrors.length === 0) return;\n if (_extensionErrors.length === 1) {\n msg.textContent = _extensionErrors[0];\n } else {\n msg.textContent = _extensionErrors.length + ' errors — ' + _extensionErrors[_extensionErrors.length - 1];\n }\n toast.style.display = 'block';\n }\n\n window.addEventListener('error', function(event) {\n var msg = event.message || '';\n if (msg.indexOf('Alpine Expression Error') === 0) return;\n var stack = event.error && event.error.stack ? event.error.stack : '';\n _collectError(msg, stack);\n });\n\n window.addEventListener('unhandledrejection', function(event) {\n var msg = event.reason && event.reason.message ? event.reason.message : String(event.reason);\n var stack = event.reason && event.reason.stack ? event.reason.stack : '';\n _collectError(msg, stack);\n });\n </script>\n <!--\n SECURITY: pinned to exact patch versions + SRI integrity hashes. A\n malicious republish of @tailwindcss/browser@4.x or alpinejs@3.x would\n otherwise inject code into every extension. To bump these versions:\n 1. npm view @tailwindcss/browser version (or alpinejs)\n 2. curl -sL https://cdn.jsdelivr.net/npm/@tailwindcss/browser@<v> \\\\\n | openssl dgst -sha384 -binary | openssl base64 -A\n 3. Update the URL + integrity hash below in lockstep.\n -->\n <script\n src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.2.4\"\n integrity=\"sha384-yNSZBFvuOWcmww494a9+1zNuvgUGEXoWkein7cxP8wHUTi3iXCU4vJ7hr3tzBCml\"\n crossorigin=\"anonymous\"\n ></script>\n <script\n defer\n src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.15.11/dist/cdn.min.js\"\n integrity=\"sha384-WPtu0YHhJ3arcykfnv1JgUffWDSKRnqnDeTpJUbOc2os2moEmLkIdaeR0trPN4be\"\n crossorigin=\"anonymous\"\n ></script>\n <style>${themeVars}</style>\n <style type=\"text/tailwindcss\">\n @custom-variant dark (&:where(.dark, .dark *));\n @theme {\n --color-border: hsl(var(--border));\n --color-input: hsl(var(--input));\n --color-ring: hsl(var(--ring));\n --color-background: hsl(var(--background));\n --color-foreground: hsl(var(--foreground));\n --color-primary: hsl(var(--primary));\n --color-primary-foreground: hsl(var(--primary-foreground));\n --color-secondary: hsl(var(--secondary));\n --color-secondary-foreground: hsl(var(--secondary-foreground));\n --color-destructive: hsl(var(--destructive));\n --color-destructive-foreground: hsl(var(--destructive-foreground));\n --color-muted: hsl(var(--muted));\n --color-muted-foreground: hsl(var(--muted-foreground));\n --color-accent: hsl(var(--accent));\n --color-accent-foreground: hsl(var(--accent-foreground));\n --color-popover: hsl(var(--popover));\n --color-popover-foreground: hsl(var(--popover-foreground));\n --color-card: hsl(var(--card));\n --color-card-foreground: hsl(var(--card-foreground));\n --color-sidebar: hsl(var(--sidebar-background));\n --color-sidebar-foreground: hsl(var(--sidebar-foreground));\n --color-sidebar-primary: hsl(var(--sidebar-primary));\n --color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));\n --color-sidebar-accent: hsl(var(--sidebar-accent));\n --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));\n --color-sidebar-border: hsl(var(--sidebar-border));\n --color-sidebar-ring: hsl(var(--sidebar-ring));\n --radius-lg: var(--radius);\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n }\n </style>\n\t <style>\n\t *, *::before, *::after { border-color: hsl(var(--border)); }\n\t html, body {\n\t /* Transparent so the iframe inherits the host surface (dashboard panel,\n\t sidebar, chat) instead of painting the browser's default white canvas.\n\t The dark class still flips the theme vars; content paints its own\n\t bg-background / bg-card surfaces. */\n\t background: transparent;\n\t }\n\t body {\n\t --agent-native-extension-padding: clamp(16px, 2vw, 24px);\n\t /* Legacy alias for pre-rename extension content (do not remove). */\n\t --agent-native-tool-padding: var(--agent-native-extension-padding);\n\t box-sizing: border-box;\n\t color: hsl(var(--foreground));\n\t font-family: 'Inter', sans-serif;\n\t margin: 0;\n\t min-height: 100vh;\n\t padding: var(--agent-native-extension-padding);\n\t }\n\t body:has(> [data-extension-layout=\"full-bleed\"]),\n\t body:has(> [data-extension-padding=\"none\"]),\n\t body:has(> .agent-native-extension-bleed),\n\t /* Legacy aliases (do not remove). */\n\t body:has(> [data-tool-layout=\"full-bleed\"]),\n\t body:has(> [data-tool-padding=\"none\"]),\n\t body:has(> .agent-native-tool-bleed) {\n\t padding: 0;\n\t }\n\t </style>\n\t <script>\n\t var _extensionRequestSeq = 0;\n\t var _extensionPendingRequests = {};\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var message = event.data || {};\n\t if (\n\t message.type !== 'agent-native-extension-response' &&\n\t message.type !== 'agent-native-tool-response'\n\t ) return;\n\t var pending = _extensionPendingRequests[message.requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[message.requestId];\n\t if (message.error) {\n\t pending.reject(new Error(message.error));\n\t } else {\n\t pending.resolve(message.response);\n\t }\n\t });\n\n\t function hostRequest(path, options) {\n\t options = options || {};\n\t return new Promise(function(resolve, reject) {\n\t var requestId = 'extension-req-' + (++_extensionRequestSeq);\n\t _extensionPendingRequests[requestId] = { resolve: resolve, reject: reject };\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-request',\n\t requestId: requestId,\n\t path: path,\n\t options: {\n\t method: options.method || 'GET',\n\t headers: options.headers || {},\n\t body: options.body,\n\t },\n\t }, '*');\n\t setTimeout(function() {\n\t var pending = _extensionPendingRequests[requestId];\n\t if (!pending) return;\n\t delete _extensionPendingRequests[requestId];\n\t pending.reject(new Error('Extension host request timed out'));\n\t }, 30000);\n\t });\n\t }\n\n\t var _origHostRequest = hostRequest;\n\t hostRequest = function(path, options) {\n\t var entry = { path: path, method: (options && options.method) || 'GET' };\n\t return _origHostRequest(path, options).then(function(res) {\n\t entry.ok = res.ok;\n\t entry.status = res.status;\n\t if (!res.ok && res.body) {\n\t try { entry.error = typeof res.body === 'string' ? res.body.slice(0, 200) : JSON.stringify(res.body).slice(0, 200); } catch(e) {}\n\t }\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t return res;\n\t }, function(err) {\n\t entry.ok = false;\n\t entry.error = err.message;\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t throw err;\n\t });\n\t };\n\n\t function extensionFetch(url, options) {\n\t var opts = options || {};\n\t return hostRequest('/_agent-native/extensions/proxy', {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({\n\t url: url,\n method: opts.method || 'GET',\n headers: opts.headers,\n body: opts.body,\n }),\n\t }).then(function(res) {\n\t var data = res.body;\n\t if (data.error && data.status === undefined) {\n\t throw new Error(data.error);\n\t }\n return {\n ok: data.status >= 200 && data.status < 300,\n status: data.status,\n\t json: function() { return Promise.resolve(data.body); },\n\t text: function() { return Promise.resolve(typeof data.body === 'string' ? data.body : JSON.stringify(data.body)); },\n\t };\n\t });\n\t }\n\n\t function _appendActionQuery(path, params) {\n\t var search = new URLSearchParams();\n\t params = params || {};\n\t Object.keys(params).forEach(function(key) {\n\t var value = params[key];\n\t if (value === undefined || value === null) return;\n\t if (Array.isArray(value)) {\n\t value.forEach(function(item) {\n\t if (item !== undefined && item !== null) {\n\t search.append(key, String(item));\n\t }\n\t });\n\t return;\n\t }\n\t search.set(key, String(value));\n\t });\n\t var qs = search.toString();\n\t return qs ? path + '?' + qs : path;\n\t }\n\n\t function _methodHintFromActionResponse(res) {\n\t if (!res || res.status !== 405) return null;\n\t var body = res.body || {};\n\t var message = typeof body === 'string' ? body : body.error;\n\t if (!message) return null;\n\t var match = String(message).match(/Use (GET|POST|PUT|PATCH|DELETE|HEAD)\\\\.?/i);\n\t return match ? match[1].toUpperCase() : null;\n\t }\n\n\t async function appAction(name, params) {\n\t params = params || {};\n\t if (name === 'navigate') {\n\t var navRes = await hostRequest('/_agent-native/application-state/navigate', {\n\t method: 'PUT',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\t if (!navRes.ok) {\n\t var navErr = navRes.body || { error: navRes.statusText };\n\t throw new Error(navErr.error || 'Navigation failed: ' + navRes.status);\n\t }\n\t return navRes.body;\n\t }\n\t var path = '/_agent-native/actions/' + encodeURIComponent(name);\n\t var res = await hostRequest(path, {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\n\t var retryMethod = _methodHintFromActionResponse(res);\n\t if (!res.ok && retryMethod && retryMethod !== 'POST') {\n\t var retryPath = path;\n\t var retryOptions = {\n\t method: retryMethod,\n\t headers: { 'Content-Type': 'application/json' },\n\t };\n\t if (retryMethod === 'GET' || retryMethod === 'HEAD') {\n\t retryPath = _appendActionQuery(path, params);\n\t } else {\n\t retryOptions.body = JSON.stringify(params);\n\t }\n\t res = await hostRequest(retryPath, retryOptions);\n\t }\n\n\t if (!res.ok) {\n\t var err = res.body || {};\n\t var rawError = typeof err === 'string' ? err : err.error;\n\t var message = (typeof rawError === 'string' && rawError.trim())\n\t ? rawError\n\t : (res.status === 404\n\t ? \"Action '\" + name + \"' is not available over HTTP (404). It may be agent-only (http: false); expose it with an HTTP-mounted action to call it from an extension.\"\n\t : \"Action '\" + name + \"' failed (\" + (res.status || 'network error') + \")\");\n\t throw new Error(message);\n\t }\n\t return res.body;\n\t }\n\n var mcp = {\n listTools: function(serverId) {\n var params = serverId ? { serverId: String(serverId) } : {};\n return appAction('list-mcp-tools', params);\n },\n callTool: function(serverId, toolName, args) {\n if (!serverId || !toolName) {\n return Promise.reject(new Error('MCP serverId and toolName are required'));\n }\n return appAction('call-mcp-tool', {\n serverId: String(serverId),\n toolName: String(toolName),\n arguments: args || {},\n });\n },\n };\n\n var providerApi = {\n catalog: function(params) {\n return appAction('provider-api-catalog', params || {});\n },\n docs: function(params) {\n return appAction('provider-api-docs', params || {});\n },\n };\n\n async function appFetch(path, options) {\n\t options = options || {};\n\t var res = await hostRequest(path, {\n\t ...options,\n\t headers: {\n\t 'Content-Type': 'application/json',\n\t ...(options.headers || {}),\n\t },\n\t });\n\t if (!res.ok) {\n\t var err = typeof res.body === 'object' && res.body ? res.body : { error: res.statusText };\n\t throw new Error(err.error || 'Request failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n\t function sendToChat(message, options) {\n\t options = options || {};\n\t var text = typeof message === 'string' ? message : JSON.stringify(message);\n\t window.parent.postMessage({\n\t type: 'agent-native-send-to-chat',\n\t message: text,\n\t context: options.context,\n\t submit: options.submit !== false,\n\t openSidebar: options.openSidebar !== false,\n\t }, '*');\n\t return { ok: true };\n\t }\n\n\t function inlineUiOutputKey() {\n\t var safeId = String(_extensionId || 'unknown').replace(/[^A-Za-z0-9_:-]/g, '') || 'unknown';\n\t return 'inline-ui:' + safeId + ':output';\n\t }\n\n\t async function outputToUi(value, options) {\n\t options = options || {};\n\t var key = inlineUiOutputKey();\n\t var payload = {\n\t value: value,\n\t updatedAt: new Date().toISOString(),\n\t extensionId: _extensionId,\n\t source: 'inline-ui',\n\t };\n\t if (options.label !== undefined) payload.label = options.label;\n\t if (options.context !== undefined) payload.context = options.context;\n\t if (options.meta !== undefined) payload.meta = options.meta;\n\t var output = await appFetch('/_agent-native/application-state/' + key, {\n\t method: 'PUT',\n\t headers: { 'X-Request-Source': 'inline-ui' },\n\t body: JSON.stringify(payload),\n\t });\n\t try {\n\t window.parent.postMessage({\n\t type: 'agent-native-ui-output',\n\t extensionId: _extensionId,\n\t key: key,\n\t value: value,\n\t output: output,\n\t }, '*');\n\t } catch (_) {}\n\t return { ok: true, key: key, output: output };\n\t }\n\n async function dbQuery(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/query', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n async function dbExec(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/extensions/sql/exec', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n var _extensionId = ${extensionIdJson};\n var _extensionBinding = ${bindingJson};\n window.extensionBinding = _extensionBinding;\n // Legacy alias for extension bodies authored before the rename.\n window.toolBinding = _extensionBinding;\n // SECURITY (audit H4): announce the resolved binding to the parent so the\n // host bridge can gate dangerous helpers based on viewer role. Sent\n // BEFORE the user-authored content has a chance to run, so a malicious\n // extension body cannot suppress or rewrite the announcement. The parent\n // ignores subsequent announcements for the same iframe; see\n // ExtensionViewer.tsx / EmbeddedExtension.tsx.\n try {\n window.parent.postMessage(\n {\n type: 'agent-native-extension-binding',\n extensionId: _extensionId,\n binding: _extensionBinding,\n },\n '*',\n );\n } catch (_) {}\n // SECURITY: when the viewer is not the author of this extension, emit a\n // clear console warning. The bridge currently runs every helper with the\n // viewer's session — a malicious shared extension can call any action,\n // read any owned table row in scope, and resolve any user-scope secret.\n // A full consent step is tracked as TODO C1 in audit 05-tools-sandbox.md.\n if (_extensionBinding && !_extensionBinding.isAuthor) {\n try {\n console.warn(\n '[agent-native] Shared extension — running with viewer\\\\'s session. ' +\n 'Author: ' + (_extensionBinding.authorEmail || '<unknown>') + '. ' +\n 'Bridge calls (appAction, dbExec, extensionFetch) execute under ' +\n 'your account; they are gated by your permissions, not the ' +\n 'author\\\\'s. Do not run untrusted shared extensions.',\n );\n } catch (_) {}\n }\n\n var extensionData = {\n\t async list(collection, opts) {\n\t var limit = (opts && opts.limit) || 100;\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '?limit=' + limit + '&scope=' + scope);\n\t if (!res.ok) throw new Error('Failed to list extension data');\n\t return res.body;\n\t },\n async get(collection, id, opts) {\n var scope = (opts && opts.scope) || 'user';\n var items = await this.list(collection, { scope: scope });\n return (items || []).find(function(item) { return item.id === id; }) || null;\n },\n async set(collection, id, data, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection), {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({ id: id, data: data, scope: scope }),\n\t });\n\t if (!res.ok) throw new Error('Failed to save extension data');\n\t return res.body;\n\t },\n\t async remove(collection, id, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/extensions/data/' + _extensionId + '/' + encodeURIComponent(collection) + '/' + encodeURIComponent(id) + '?scope=' + scope, {\n\t method: 'DELETE',\n\t });\n\t if (!res.ok) throw new Error('Failed to delete extension data');\n\t return res.body;\n\t },\n\t };\n\n\t // Legacy aliases — extension bodies authored before the rename use\n\t // toolFetch, toolData, toolId. Keep these working forever.\n\t var toolFetch = extensionFetch;\n\t var toolData = extensionData;\n\t var _toolId = _extensionId;\n\t window.agentNative = Object.assign(window.agentNative || {}, {\n\t extensionId: _extensionId,\n\t extensionBinding: _extensionBinding,\n\t appAction: appAction,\n\t appFetch: appFetch,\n\t dbQuery: dbQuery,\n\t dbExec: dbExec,\n\t extensionFetch: extensionFetch,\n\t extensionData: extensionData,\n\t data: extensionData,\n\t mcp: mcp,\n\t providerApi: providerApi,\n\t connectors: Object.assign({}, (window.agentNative && window.agentNative.connectors) || {}, {\n\t mcp: mcp,\n\t providerApi: providerApi,\n\t }),\n\t sendToChat: sendToChat,\n\t chat: Object.assign({}, (window.agentNative && window.agentNative.chat) || {}, {\n\t send: sendToChat,\n\t }),\n\t ui: Object.assign({}, (window.agentNative && window.agentNative.ui) || {}, {\n\t output: outputToUi,\n\t }),\n\t });\n\t window.sendToAgentChat = sendToChat;\n\t </script>\n\t <style>\n\t #__extension-error-toast {\n\t display: none;\n\t position: fixed;\n\t bottom: 16px;\n\t right: 16px;\n\t max-width: 420px;\n\t background: hsl(var(--destructive));\n\t color: hsl(var(--destructive-foreground));\n\t border: 1px solid hsl(var(--destructive) / .6);\n\t border-radius: calc(var(--radius, .5rem) + 2px);\n\t padding: 12px 16px;\n\t font-size: 13px;\n\t line-height: 1.4;\n\t font-family: 'Inter', sans-serif;\n\t z-index: 9999;\n\t box-shadow: 0 4px 12px rgba(0,0,0,.15), 0 1px 3px rgba(0,0,0,.1);\n\t animation: __toast-in 0.2s ease-out;\n\t }\n\t @keyframes __toast-in {\n\t from { opacity: 0; transform: translateY(8px); }\n\t to { opacity: 1; transform: translateY(0); }\n\t }\n\t </style>\n\t <script>\n\t // Extension-point slot context: when an extension is rendered embedded\n\t // inside an ExtensionSlot, the host pushes a context object via\n\t // postMessage. Extensions read it synchronously via window.slotContext\n\t // or subscribe to changes via window.onSlotContext(fn). When rendered\n\t // full-page (no ?slot= param), slotContext stays null and extensions\n\t // branch on that.\n\t window.slotContext = null;\n\t var _slotContextSubscribers = [];\n\t window.onSlotContext = function(fn) {\n\t _slotContextSubscribers.push(fn);\n\t if (window.slotContext !== null) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t }\n\t return function() {\n\t _slotContextSubscribers = _slotContextSubscribers.filter(function(f) { return f !== fn; });\n\t };\n\t };\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-slot-context') return;\n\t window.slotContext = msg.context || {};\n\t _slotContextSubscribers.forEach(function(fn) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t });\n\t });\n\n\t // Auto-resize iframe renders. Persisted extension slots include ?slot=;\n\t // transient inline chat UI uses srcdoc, so detect that by parent frame.\n\t // The host listens for agent-native-extension-resize and adjusts height.\n\t if (new URLSearchParams(location.search).get('slot') || window.parent !== window) {\n\t var _lastH = 0;\n\t var _reportHeight = function() {\n\t var h = Math.max(\n\t document.documentElement.scrollHeight,\n\t document.body ? document.body.scrollHeight : 0,\n\t );\n\t if (h !== _lastH) {\n\t _lastH = h;\n\t window.parent.postMessage({ type: 'agent-native-extension-resize', height: h }, '*');\n\t }\n\t };\n\t if (typeof ResizeObserver !== 'undefined') {\n\t var _ro = new ResizeObserver(_reportHeight);\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _ro.observe(document.documentElement);\n\t if (document.body) _ro.observe(document.body);\n\t });\n\t }\n\t // Initial reports — Alpine takes a tick to render after DOMContentLoaded.\n\t setTimeout(_reportHeight, 50);\n\t setTimeout(_reportHeight, 250);\n\t }\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-theme-update') return;\n\t var root = document.documentElement;\n\t if (msg.isDark !== undefined) {\n\t if (msg.isDark) root.classList.add('dark');\n\t else root.classList.remove('dark');\n\t }\n\t var vars = msg.vars || {};\n\t for (var key in vars) {\n\t if (vars.hasOwnProperty(key)) {\n\t root.style.setProperty(key, vars[key]);\n\t }\n\t }\n\t });\n\n\t document.addEventListener('keydown', function(e) {\n\t if ((e.metaKey || e.ctrlKey) && !e.altKey) {\n\t var key = (e.key || '').toLowerCase();\n\t if (key === 'c' || key === 'v' || key === 'x' || key === 'a' || key === 'z' || key === 'y') return;\n\t e.preventDefault();\n\t e.stopPropagation();\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: e.metaKey, ctrlKey: e.ctrlKey,\n\t shiftKey: e.shiftKey, altKey: e.altKey,\n\t }, '*');\n\t return;\n\t }\n\t if (e.key === 'Escape') {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: false, ctrlKey: false,\n\t shiftKey: false, altKey: false,\n\t }, '*');\n\t }\n\t });\n\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _renderErrorToast();\n\t var fixBtn = document.getElementById('__extension-error-fix');\n\t if (fixBtn) {\n\t fixBtn.addEventListener('click', function() {\n\t window.parent.postMessage({\n\t type: 'agent-native-extension-error-fix',\n\t errors: _extensionErrors,\n\t errorDetails: _extensionErrorDetails,\n\t consoleLogs: _consoleLogs.slice(-30),\n\t networkLogs: _networkLogs.slice(-15)\n\t }, '*');\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t var dismissBtn = document.getElementById('__extension-error-dismiss');\n\t if (dismissBtn) {\n\t dismissBtn.addEventListener('click', function() {\n\t document.getElementById('__extension-error-toast').style.display = 'none';\n\t });\n\t }\n\t });\n\t </script>\n\t${buildSessionReplayIframeBootstrap()}\n\t</head>\n\t<body${extensionId ? ` data-extension-id=\"${extensionIdAttr}\" data-tool-id=\"${extensionIdAttr}\"` : \"\"} class=\"text-foreground\">\n\t${content}\n\t<div id=\"__extension-error-toast\">\n\t <div style=\"display:flex;align-items:flex-start;gap:8px;\">\n\t <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0;margin-top:1px;\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/></svg>\n\t <span id=\"__extension-error-msg\" style=\"flex:1;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;\"></span>\n\t <button id=\"__extension-error-fix\" style=\"cursor:pointer;border:none;background:rgba(255,255,255,.9);color:hsl(0 84.2% 40%);font-size:12px;font-weight:500;padding:4px 12px;border-radius:4px;flex-shrink:0;\">Fix</button>\n\t <button id=\"__extension-error-dismiss\" style=\"cursor:pointer;border:none;background:transparent;color:inherit;font-size:16px;padding:2px 6px;opacity:0.7;flex-shrink:0;\">×</button>\n\t </div>\n\t</div>\n\t</body>\n\t</html>`;\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"office.d.ts","sourceRoot":"","sources":["../../src/ingestion/office.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;AAEhF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EACF,iBAAiB,GACjB,cAAc,GACd,kBAAkB,GAClB,YAAY,CAAC;IACjB,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,MAAM,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CACT,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE;QACP,QAAQ,EAAE,kBAAkB,CAAC;QAC7B,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,kBAAkB,EAAE,OAAO,CAAC;QAC5B,WAAW,EAAE,OAAO,CAAC;KACtB,GACA,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/B;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,EAC/B,MAAM,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CAyG/B;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,kBAAkB,CAapB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO3D;
|
|
1
|
+
{"version":3,"file":"office.d.ts","sourceRoot":"","sources":["../../src/ingestion/office.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;AAEhF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EACF,iBAAiB,GACjB,cAAc,GACd,kBAAkB,GAClB,YAAY,CAAC;IACjB,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,MAAM,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CACT,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE;QACP,QAAQ,EAAE,kBAAkB,CAAC;QAC7B,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,kBAAkB,EAAE,OAAO,CAAC;QAC5B,WAAW,EAAE,OAAO,CAAC;KACtB,GACA,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/B;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,EAC/B,MAAM,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CAyG/B;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,kBAAkB,CAapB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO3D;AAoBD,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACvB,MAAM,WAAW,CAAC"}
|
package/dist/ingestion/office.js
CHANGED
|
@@ -123,9 +123,8 @@ export function normalizeDocumentText(value) {
|
|
|
123
123
|
.trim();
|
|
124
124
|
}
|
|
125
125
|
async function loadOfficeParser() {
|
|
126
|
-
const specifier = "officeparser";
|
|
127
126
|
try {
|
|
128
|
-
const module = (await import(
|
|
127
|
+
const module = (await import("officeparser"));
|
|
129
128
|
return module.OfficeParser ?? null;
|
|
130
129
|
}
|
|
131
130
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"office.js","sourceRoot":"","sources":["../../src/ingestion/office.ts"],"names":[],"mappings":"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","sourcesContent":["export type OfficeDocumentType = \"pptx\" | \"docx\" | \"pdf\" | \"txt\" | \"md\" | \"csv\";\n\nexport interface ParseOfficeDocumentInput {\n data: Uint8Array;\n fileName: string;\n mimeType?: string;\n signal?: AbortSignal;\n}\n\nexport interface ParsedOfficeDocument {\n text: string;\n fileType: OfficeDocumentType;\n title: string;\n parser:\n | \"structured-pptx\"\n | \"mammoth-docx\"\n | \"officeparser-pdf\"\n | \"plain-text\";\n parts: OfficeDocumentPart[];\n metadata: Record<string, unknown>;\n warnings: string[];\n}\n\nexport interface OfficeDocumentPart {\n kind: \"slide\" | \"section\" | \"page\" | \"document\";\n index: number;\n title: string;\n text: string;\n notes?: string;\n textRuns?: ParsedPptxTextRun[];\n images?: ParsedPptxImage[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface OfficeDocumentAst {\n type?: string;\n metadata?: Record<string, unknown>;\n warnings?: unknown[];\n toText(): string | Promise<string>;\n}\n\nexport interface OfficeDocumentParser {\n parseOffice(\n data: Uint8Array,\n options: {\n fileType: OfficeDocumentType;\n abortSignal?: AbortSignal;\n extractAttachments: boolean;\n ignoreNotes: boolean;\n },\n ): Promise<OfficeDocumentAst>;\n}\n\nexport async function parseOfficeDocument(\n input: ParseOfficeDocumentInput,\n parser?: OfficeDocumentParser,\n): Promise<ParsedOfficeDocument> {\n const fileType = detectOfficeDocumentType(input.fileName, input.mimeType);\n if (fileType === \"txt\" || fileType === \"md\" || fileType === \"csv\") {\n const text = normalizeDocumentText(new TextDecoder().decode(input.data));\n return {\n text,\n fileType,\n title: input.fileName,\n parser: \"plain-text\",\n parts: [{ kind: \"document\", index: 0, title: input.fileName, text }],\n metadata: {},\n warnings: [],\n };\n }\n if (fileType === \"pptx\") {\n const presentation = await parsePptxPresentation(input.data);\n const parts = presentation.slides.map((slide, index) => {\n const body = normalizeDocumentText(\n slide.texts.map((run) => run.content).join(\"\\n\"),\n );\n return {\n kind: \"slide\" as const,\n index,\n title:\n slide.texts\n .find((run) => run.content.trim())\n ?.content.trim()\n .slice(0, 160) ?? `Slide ${index + 1}`,\n text: normalizeDocumentText(\n [body, slide.notes ? `Speaker notes\\n${slide.notes}` : \"\"]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n ),\n notes: slide.notes,\n textRuns: slide.texts,\n images: slide.images,\n metadata: {\n layoutHint: slide.layoutHint,\n theme: presentation.theme,\n },\n };\n });\n return {\n text: parts.map((part) => part.text).join(\"\\n\\n\"),\n fileType,\n title: presentation.title,\n parser: \"structured-pptx\",\n parts,\n metadata: { theme: presentation.theme, slideCount: parts.length },\n warnings: [],\n };\n }\n if (fileType === \"docx\") {\n const document = await parseDocxDocument(input.data);\n const parts = document.sections.map((section, index) => {\n const html = sanitizeInertDocumentHtml(section.html);\n return {\n kind: \"section\" as const,\n index,\n title: section.heading || `Section ${index + 1}`,\n text: normalizeDocumentText(\n [section.heading, section.text].filter(Boolean).join(\"\\n\\n\"),\n ),\n metadata: { html },\n };\n });\n return {\n text: normalizeDocumentText(document.text),\n fileType,\n title: document.title,\n parser: \"mammoth-docx\",\n parts,\n metadata: { sectionCount: parts.length },\n warnings: [],\n };\n }\n const resolvedParser = parser ?? (await loadOfficeParser());\n if (!resolvedParser) {\n throw new Error(\n `Parsing ${fileType.toUpperCase()} uploads requires the optional officeparser dependency.`,\n );\n }\n const ast = await resolvedParser.parseOffice(input.data, {\n fileType,\n abortSignal: input.signal,\n extractAttachments: false,\n ignoreNotes: false,\n });\n const text = normalizeDocumentText(await ast.toText());\n const pages = text.split(/\\f+/).map(normalizeDocumentText).filter(Boolean);\n const parts = (pages.length > 0 ? pages : [text]).map((page, index) => ({\n kind: \"page\" as const,\n index,\n title: `Page ${index + 1}`,\n text: page,\n }));\n return {\n text,\n fileType: isOfficeDocumentType(ast.type) ? ast.type : fileType,\n title: input.fileName,\n parser: \"officeparser-pdf\",\n parts,\n metadata: ast.metadata ?? {},\n warnings: (ast.warnings ?? []).map(String),\n };\n}\n\nexport function detectOfficeDocumentType(\n fileName: string,\n mimeType?: string,\n): OfficeDocumentType {\n const mime = mimeType?.toLowerCase() ?? \"\";\n if (mime.includes(\"presentationml\")) return \"pptx\";\n if (mime.includes(\"wordprocessingml\")) return \"docx\";\n if (mime.includes(\"pdf\")) return \"pdf\";\n if (mime.includes(\"markdown\")) return \"md\";\n if (mime.includes(\"csv\")) return \"csv\";\n if (mime.startsWith(\"text/\")) return \"txt\";\n const extension = fileName.toLowerCase().match(/\\.([a-z0-9]+)$/)?.[1];\n if (isOfficeDocumentType(extension)) return extension;\n throw new Error(\n `Unsupported upload type ${mimeType ?? extension ?? \"unknown\"}; supported formats are PPTX, DOCX, PDF, and text.`,\n );\n}\n\nexport function normalizeDocumentText(value: string): string {\n return value\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(/[\\t\\f\\v ]+/g, \" \")\n .replace(/ *\\n */g, \"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n}\n\nasync function loadOfficeParser(): Promise<OfficeDocumentParser | null> {\n const specifier = \"officeparser\";\n try {\n const module = (await import(specifier)) as {\n OfficeParser?: OfficeDocumentParser;\n };\n return module.OfficeParser ?? null;\n } catch {\n return null;\n }\n}\n\nfunction isOfficeDocumentType(value: unknown): value is OfficeDocumentType {\n return (\n typeof value === \"string\" &&\n ([\"pptx\", \"docx\", \"pdf\", \"txt\", \"md\", \"csv\"] as string[]).includes(value)\n );\n}\nimport { parseDocxDocument, sanitizeInertDocumentHtml } from \"./docx.js\";\nimport {\n parsePptxPresentation,\n type ParsedPptxImage,\n type ParsedPptxTextRun,\n} from \"./pptx.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"office.js","sourceRoot":"","sources":["../../src/ingestion/office.ts"],"names":[],"mappings":"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","sourcesContent":["export type OfficeDocumentType = \"pptx\" | \"docx\" | \"pdf\" | \"txt\" | \"md\" | \"csv\";\n\nexport interface ParseOfficeDocumentInput {\n data: Uint8Array;\n fileName: string;\n mimeType?: string;\n signal?: AbortSignal;\n}\n\nexport interface ParsedOfficeDocument {\n text: string;\n fileType: OfficeDocumentType;\n title: string;\n parser:\n | \"structured-pptx\"\n | \"mammoth-docx\"\n | \"officeparser-pdf\"\n | \"plain-text\";\n parts: OfficeDocumentPart[];\n metadata: Record<string, unknown>;\n warnings: string[];\n}\n\nexport interface OfficeDocumentPart {\n kind: \"slide\" | \"section\" | \"page\" | \"document\";\n index: number;\n title: string;\n text: string;\n notes?: string;\n textRuns?: ParsedPptxTextRun[];\n images?: ParsedPptxImage[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface OfficeDocumentAst {\n type?: string;\n metadata?: Record<string, unknown>;\n warnings?: unknown[];\n toText(): string | Promise<string>;\n}\n\nexport interface OfficeDocumentParser {\n parseOffice(\n data: Uint8Array,\n options: {\n fileType: OfficeDocumentType;\n abortSignal?: AbortSignal;\n extractAttachments: boolean;\n ignoreNotes: boolean;\n },\n ): Promise<OfficeDocumentAst>;\n}\n\nexport async function parseOfficeDocument(\n input: ParseOfficeDocumentInput,\n parser?: OfficeDocumentParser,\n): Promise<ParsedOfficeDocument> {\n const fileType = detectOfficeDocumentType(input.fileName, input.mimeType);\n if (fileType === \"txt\" || fileType === \"md\" || fileType === \"csv\") {\n const text = normalizeDocumentText(new TextDecoder().decode(input.data));\n return {\n text,\n fileType,\n title: input.fileName,\n parser: \"plain-text\",\n parts: [{ kind: \"document\", index: 0, title: input.fileName, text }],\n metadata: {},\n warnings: [],\n };\n }\n if (fileType === \"pptx\") {\n const presentation = await parsePptxPresentation(input.data);\n const parts = presentation.slides.map((slide, index) => {\n const body = normalizeDocumentText(\n slide.texts.map((run) => run.content).join(\"\\n\"),\n );\n return {\n kind: \"slide\" as const,\n index,\n title:\n slide.texts\n .find((run) => run.content.trim())\n ?.content.trim()\n .slice(0, 160) ?? `Slide ${index + 1}`,\n text: normalizeDocumentText(\n [body, slide.notes ? `Speaker notes\\n${slide.notes}` : \"\"]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n ),\n notes: slide.notes,\n textRuns: slide.texts,\n images: slide.images,\n metadata: {\n layoutHint: slide.layoutHint,\n theme: presentation.theme,\n },\n };\n });\n return {\n text: parts.map((part) => part.text).join(\"\\n\\n\"),\n fileType,\n title: presentation.title,\n parser: \"structured-pptx\",\n parts,\n metadata: { theme: presentation.theme, slideCount: parts.length },\n warnings: [],\n };\n }\n if (fileType === \"docx\") {\n const document = await parseDocxDocument(input.data);\n const parts = document.sections.map((section, index) => {\n const html = sanitizeInertDocumentHtml(section.html);\n return {\n kind: \"section\" as const,\n index,\n title: section.heading || `Section ${index + 1}`,\n text: normalizeDocumentText(\n [section.heading, section.text].filter(Boolean).join(\"\\n\\n\"),\n ),\n metadata: { html },\n };\n });\n return {\n text: normalizeDocumentText(document.text),\n fileType,\n title: document.title,\n parser: \"mammoth-docx\",\n parts,\n metadata: { sectionCount: parts.length },\n warnings: [],\n };\n }\n const resolvedParser = parser ?? (await loadOfficeParser());\n if (!resolvedParser) {\n throw new Error(\n `Parsing ${fileType.toUpperCase()} uploads requires the optional officeparser dependency.`,\n );\n }\n const ast = await resolvedParser.parseOffice(input.data, {\n fileType,\n abortSignal: input.signal,\n extractAttachments: false,\n ignoreNotes: false,\n });\n const text = normalizeDocumentText(await ast.toText());\n const pages = text.split(/\\f+/).map(normalizeDocumentText).filter(Boolean);\n const parts = (pages.length > 0 ? pages : [text]).map((page, index) => ({\n kind: \"page\" as const,\n index,\n title: `Page ${index + 1}`,\n text: page,\n }));\n return {\n text,\n fileType: isOfficeDocumentType(ast.type) ? ast.type : fileType,\n title: input.fileName,\n parser: \"officeparser-pdf\",\n parts,\n metadata: ast.metadata ?? {},\n warnings: (ast.warnings ?? []).map(String),\n };\n}\n\nexport function detectOfficeDocumentType(\n fileName: string,\n mimeType?: string,\n): OfficeDocumentType {\n const mime = mimeType?.toLowerCase() ?? \"\";\n if (mime.includes(\"presentationml\")) return \"pptx\";\n if (mime.includes(\"wordprocessingml\")) return \"docx\";\n if (mime.includes(\"pdf\")) return \"pdf\";\n if (mime.includes(\"markdown\")) return \"md\";\n if (mime.includes(\"csv\")) return \"csv\";\n if (mime.startsWith(\"text/\")) return \"txt\";\n const extension = fileName.toLowerCase().match(/\\.([a-z0-9]+)$/)?.[1];\n if (isOfficeDocumentType(extension)) return extension;\n throw new Error(\n `Unsupported upload type ${mimeType ?? extension ?? \"unknown\"}; supported formats are PPTX, DOCX, PDF, and text.`,\n );\n}\n\nexport function normalizeDocumentText(value: string): string {\n return value\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(/[\\t\\f\\v ]+/g, \" \")\n .replace(/ *\\n */g, \"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n}\n\nasync function loadOfficeParser(): Promise<OfficeDocumentParser | null> {\n try {\n const module = (await import(\"officeparser\")) as unknown as {\n OfficeParser?: OfficeDocumentParser;\n };\n return module.OfficeParser ?? null;\n } catch {\n return null;\n }\n}\n\nfunction isOfficeDocumentType(value: unknown): value is OfficeDocumentType {\n return (\n typeof value === \"string\" &&\n ([\"pptx\", \"docx\", \"pdf\", \"txt\", \"md\", \"csv\"] as string[]).includes(value)\n );\n}\nimport { parseDocxDocument, sanitizeInertDocumentHtml } from \"./docx.js\";\nimport {\n parsePptxPresentation,\n type ParsedPptxImage,\n type ParsedPptxTextRun,\n} from \"./pptx.js\";\n"]}
|
package/dist/ingestion/pptx.js
CHANGED
|
@@ -209,12 +209,10 @@ function imageMimeType(name) {
|
|
|
209
209
|
}[extension ?? ""] ?? "application/octet-stream");
|
|
210
210
|
}
|
|
211
211
|
async function loadPptxDependencies() {
|
|
212
|
-
const zipModuleName = "jszip";
|
|
213
|
-
const xmlModuleName = "fast-xml-parser";
|
|
214
212
|
try {
|
|
215
213
|
const [zipModule, xmlModule] = await Promise.all([
|
|
216
|
-
import(
|
|
217
|
-
import(
|
|
214
|
+
import("jszip"),
|
|
215
|
+
import("fast-xml-parser"),
|
|
218
216
|
]);
|
|
219
217
|
const parser = new xmlModule.XMLParser({
|
|
220
218
|
ignoreAttributes: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pptx.js","sourceRoot":"","sources":["../../src/ingestion/pptx.ts"],"names":[],"mappings":"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","sourcesContent":["export interface ParsedPptxTextRun {\n content: string;\n bold?: boolean;\n italic?: boolean;\n fontSize?: number;\n color?: string;\n}\n\nexport interface ParsedPptxImage {\n data: Uint8Array;\n mimeType: string;\n name: string;\n}\n\nexport interface ParsedPptxSlide {\n texts: ParsedPptxTextRun[];\n images: ParsedPptxImage[];\n notes?: string;\n layoutHint?: string;\n}\n\nexport interface ParsedPptxPresentation {\n title: string;\n slides: ParsedPptxSlide[];\n theme?: { colors: string[]; fonts: string[] };\n}\n\ninterface ZipFile {\n async(type: \"string\"): Promise<string>;\n async(type: \"nodebuffer\"): Promise<Buffer>;\n}\n\ninterface ZipArchive {\n files: Record<string, unknown>;\n file(path: string): ZipFile | null;\n}\n\nexport async function parsePptxPresentation(\n fileBuffer: Uint8Array,\n): Promise<ParsedPptxPresentation> {\n const { loadZip, parseXml } = await loadPptxDependencies();\n const zip = await loadZip(fileBuffer);\n const presentationXml = await zip\n .file(\"ppt/presentation.xml\")\n ?.async(\"string\");\n if (!presentationXml)\n throw new Error(\"Invalid PPTX: missing ppt/presentation.xml\");\n const presentation = parseXml(presentationXml);\n const slideIds = asArray(\n record(record(record(presentation)?.[\"p:presentation\"])?.[\"p:sldIdLst\"])?.[\n \"p:sldId\"\n ],\n ).map((entry) => stringValue(record(entry)?.[\"@_r:id\"]) ?? \"\");\n const relationshipsXml = await zip\n .file(\"ppt/_rels/presentation.xml.rels\")\n ?.async(\"string\");\n const relationships = relationshipsXml\n ? parseRelationships(parseXml(relationshipsXml))\n : new Map<string, { target: string; type: string }>();\n const slidePaths = slideIds.flatMap((id) => {\n const relationship = relationships.get(id);\n if (!relationship) return [];\n return [\n relationship.target.startsWith(\"/\")\n ? relationship.target.slice(1)\n : `ppt/${relationship.target}`,\n ];\n });\n if (slidePaths.length === 0) {\n slidePaths.push(\n ...Object.keys(zip.files)\n .filter((path) => /^ppt\\/slides\\/slide\\d+\\.xml$/.test(path))\n .sort((a, b) => slideNumber(a) - slideNumber(b)),\n );\n }\n const theme = await parseTheme(zip, parseXml);\n const slides: ParsedPptxSlide[] = [];\n for (const slidePath of slidePaths) {\n const xml = await zip.file(slidePath)?.async(\"string\");\n if (!xml) continue;\n let slide: unknown;\n try {\n slide = parseXml(xml);\n } catch {\n continue;\n }\n const texts: ParsedPptxTextRun[] = [];\n collectTextRuns(slide, texts);\n const images: ParsedPptxImage[] = [];\n const relationshipPath = slidePath.replace(\n /slides\\/(slide\\d+\\.xml)/,\n \"slides/_rels/$1.rels\",\n );\n const slideRelationshipsXml = await zip\n .file(relationshipPath)\n ?.async(\"string\");\n if (slideRelationshipsXml) {\n for (const relationship of parseRelationships(\n parseXml(slideRelationshipsXml),\n ).values()) {\n if (\n !relationship.type.includes(\"/image\") &&\n !/\\.(png|jpe?g|gif|svg|webp|bmp|tiff?|emf|wmf)$/i.test(\n relationship.target,\n )\n ) {\n continue;\n }\n const imagePath = relationship.target.startsWith(\"/\")\n ? relationship.target.slice(1)\n : relationship.target.startsWith(\"../\")\n ? `ppt/${relationship.target.replace(/^\\.\\.\\//, \"\")}`\n : `ppt/slides/${relationship.target}`;\n const image = zip.file(imagePath);\n if (!image) continue;\n const name = imagePath.split(\"/\").at(-1) ?? \"image\";\n images.push({\n data: new Uint8Array(await image.async(\"nodebuffer\")),\n mimeType: imageMimeType(name),\n name,\n });\n }\n }\n const number = slideNumber(slidePath);\n const notesXml = await zip\n .file(`ppt/notesSlides/notesSlide${number}.xml`)\n ?.async(\"string\");\n let notes: string | undefined;\n if (notesXml) {\n const runs: ParsedPptxTextRun[] = [];\n collectTextRuns(parseXml(notesXml), runs);\n const value = runs\n .map((run) => run.content)\n .join(\" \")\n .trim();\n if (value.length > 1) notes = value;\n }\n slides.push({\n texts,\n images,\n notes,\n layoutHint: guessLayoutHint(texts, images.length > 0),\n });\n }\n const firstSlide = slides[0]?.texts ?? [];\n const title =\n [...firstSlide]\n .sort((a, b) => (b.fontSize ?? 0) - (a.fontSize ?? 0))[0]\n ?.content.trim()\n .slice(0, 200) || \"Imported Presentation\";\n return { title, slides, theme };\n}\n\nasync function parseTheme(\n zip: ZipArchive,\n parseXml: (xml: string) => unknown,\n): Promise<ParsedPptxPresentation[\"theme\"]> {\n const xml = await zip.file(\"ppt/theme/theme1.xml\")?.async(\"string\");\n if (!xml) return undefined;\n const root = record(parseXml(xml));\n const elements = record(record(root?.[\"a:theme\"])?.[\"a:themeElements\"]);\n const scheme = record(elements?.[\"a:clrScheme\"]);\n const colors: string[] = [];\n for (const [key, value] of Object.entries(scheme ?? {})) {\n if (key.startsWith(\"@_\")) continue;\n const color = record(value);\n const rgb = stringValue(record(color?.[\"a:srgbClr\"])?.[\"@_val\"]);\n const system = stringValue(record(color?.[\"a:sysClr\"])?.[\"@_lastClr\"]);\n if (rgb || system) colors.push(`#${rgb ?? system}`);\n }\n const fontScheme = record(elements?.[\"a:fontScheme\"]);\n const fonts = [\"a:majorFont\", \"a:minorFont\"].flatMap((key) => {\n const value = stringValue(\n record(record(fontScheme?.[key])?.[\"a:latin\"])?.[\"@_typeface\"],\n );\n return value ? [value] : [];\n });\n return colors.length || fonts.length ? { colors, fonts } : undefined;\n}\n\nfunction collectTextRuns(\n value: unknown,\n runs: ParsedPptxTextRun[],\n inherited: Omit<ParsedPptxTextRun, \"content\"> = {},\n): void {\n const node = record(value);\n if (!node) return;\n for (const raw of asArray(node[\"a:r\"])) {\n const run = record(raw);\n const content = innerText(run?.[\"a:t\"]);\n if (content)\n runs.push({\n content,\n ...runProperties(record(run?.[\"a:rPr\"]), inherited),\n });\n }\n if (node[\"a:t\"] !== undefined && node[\"a:r\"] === undefined) {\n const content = innerText(node[\"a:t\"]);\n if (content) runs.push({ content, ...inherited });\n }\n for (const [key, child] of Object.entries(node)) {\n if (key.startsWith(\"@_\") || key === \"a:r\" || key === \"a:t\") continue;\n for (const item of asArray(child)) collectTextRuns(item, runs, inherited);\n }\n}\n\nfunction runProperties(\n value: Record<string, unknown> | null,\n inherited: Omit<ParsedPptxTextRun, \"content\">,\n): Omit<ParsedPptxTextRun, \"content\"> {\n if (!value) return inherited;\n const size = Number(value[\"@_sz\"]);\n const rgb = stringValue(\n record(record(value[\"a:solidFill\"])?.[\"a:srgbClr\"])?.[\"@_val\"],\n );\n return {\n ...inherited,\n ...(value[\"@_b\"] === \"1\" || value[\"@_b\"] === 1 || value[\"@_b\"] === true\n ? { bold: true }\n : {}),\n ...(value[\"@_i\"] === \"1\" || value[\"@_i\"] === 1 || value[\"@_i\"] === true\n ? { italic: true }\n : {}),\n ...(Number.isFinite(size) && size > 0 ? { fontSize: size / 100 } : {}),\n ...(rgb ? { color: `#${rgb}` } : {}),\n };\n}\n\nfunction parseRelationships(value: unknown) {\n const output = new Map<string, { target: string; type: string }>();\n for (const raw of asArray(\n record(record(value)?.Relationships)?.Relationship,\n )) {\n const relationship = record(raw);\n const id = stringValue(relationship?.[\"@_Id\"]);\n const target = stringValue(relationship?.[\"@_Target\"]);\n if (id && target) {\n output.set(id, {\n target,\n type: stringValue(relationship?.[\"@_Type\"]) ?? \"\",\n });\n }\n }\n return output;\n}\n\nfunction guessLayoutHint(texts: ParsedPptxTextRun[], hasImages: boolean) {\n if (hasImages) return \"image\";\n const maxSize = Math.max(...texts.map((text) => text.fontSize ?? 0), 0);\n const length = texts.reduce((total, text) => total + text.content.length, 0);\n if (texts.length <= 3 && length < 200 && maxSize >= 28) return \"title\";\n if (texts.length <= 2 && length < 100) return \"section\";\n return \"content\";\n}\n\nfunction imageMimeType(name: string): string {\n const extension = name.split(\".\").at(-1)?.toLowerCase();\n return (\n {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n svg: \"image/svg+xml\",\n webp: \"image/webp\",\n bmp: \"image/bmp\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n emf: \"image/emf\",\n wmf: \"image/wmf\",\n }[extension ?? \"\"] ?? \"application/octet-stream\"\n );\n}\n\nasync function loadPptxDependencies(): Promise<{\n loadZip(data: Uint8Array): Promise<ZipArchive>;\n parseXml(xml: string): unknown;\n}> {\n const zipModuleName = \"jszip\";\n const xmlModuleName = \"fast-xml-parser\";\n try {\n const [zipModule, xmlModule] = await Promise.all([\n import(zipModuleName) as Promise<{\n default: { loadAsync(data: Uint8Array): Promise<ZipArchive> };\n }>,\n import(xmlModuleName) as Promise<{\n XMLParser: new (options: Record<string, unknown>) => {\n parse(xml: string): unknown;\n };\n }>,\n ]);\n const parser = new xmlModule.XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n });\n return {\n loadZip: (data) => zipModule.default.loadAsync(data),\n parseXml: (xml) => parser.parse(xml),\n };\n } catch {\n throw new Error(\n \"Structured PPTX parsing requires the optional jszip and fast-xml-parser dependencies.\",\n );\n }\n}\n\nfunction slideNumber(value: string): number {\n return Number(value.match(/slide(\\d+)/)?.[1] ?? 0);\n}\n\nfunction innerText(value: unknown): string {\n if (typeof value === \"string\" || typeof value === \"number\")\n return String(value);\n return String(record(value)?.[\"#text\"] ?? \"\");\n}\n\nfunction asArray(value: unknown): unknown[] {\n return value === undefined || value === null\n ? []\n : Array.isArray(value)\n ? value\n : [value];\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pptx.js","sourceRoot":"","sources":["../../src/ingestion/pptx.ts"],"names":[],"mappings":"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","sourcesContent":["export interface ParsedPptxTextRun {\n content: string;\n bold?: boolean;\n italic?: boolean;\n fontSize?: number;\n color?: string;\n}\n\nexport interface ParsedPptxImage {\n data: Uint8Array;\n mimeType: string;\n name: string;\n}\n\nexport interface ParsedPptxSlide {\n texts: ParsedPptxTextRun[];\n images: ParsedPptxImage[];\n notes?: string;\n layoutHint?: string;\n}\n\nexport interface ParsedPptxPresentation {\n title: string;\n slides: ParsedPptxSlide[];\n theme?: { colors: string[]; fonts: string[] };\n}\n\ninterface ZipFile {\n async(type: \"string\"): Promise<string>;\n async(type: \"nodebuffer\"): Promise<Buffer>;\n}\n\ninterface ZipArchive {\n files: Record<string, unknown>;\n file(path: string): ZipFile | null;\n}\n\nexport async function parsePptxPresentation(\n fileBuffer: Uint8Array,\n): Promise<ParsedPptxPresentation> {\n const { loadZip, parseXml } = await loadPptxDependencies();\n const zip = await loadZip(fileBuffer);\n const presentationXml = await zip\n .file(\"ppt/presentation.xml\")\n ?.async(\"string\");\n if (!presentationXml)\n throw new Error(\"Invalid PPTX: missing ppt/presentation.xml\");\n const presentation = parseXml(presentationXml);\n const slideIds = asArray(\n record(record(record(presentation)?.[\"p:presentation\"])?.[\"p:sldIdLst\"])?.[\n \"p:sldId\"\n ],\n ).map((entry) => stringValue(record(entry)?.[\"@_r:id\"]) ?? \"\");\n const relationshipsXml = await zip\n .file(\"ppt/_rels/presentation.xml.rels\")\n ?.async(\"string\");\n const relationships = relationshipsXml\n ? parseRelationships(parseXml(relationshipsXml))\n : new Map<string, { target: string; type: string }>();\n const slidePaths = slideIds.flatMap((id) => {\n const relationship = relationships.get(id);\n if (!relationship) return [];\n return [\n relationship.target.startsWith(\"/\")\n ? relationship.target.slice(1)\n : `ppt/${relationship.target}`,\n ];\n });\n if (slidePaths.length === 0) {\n slidePaths.push(\n ...Object.keys(zip.files)\n .filter((path) => /^ppt\\/slides\\/slide\\d+\\.xml$/.test(path))\n .sort((a, b) => slideNumber(a) - slideNumber(b)),\n );\n }\n const theme = await parseTheme(zip, parseXml);\n const slides: ParsedPptxSlide[] = [];\n for (const slidePath of slidePaths) {\n const xml = await zip.file(slidePath)?.async(\"string\");\n if (!xml) continue;\n let slide: unknown;\n try {\n slide = parseXml(xml);\n } catch {\n continue;\n }\n const texts: ParsedPptxTextRun[] = [];\n collectTextRuns(slide, texts);\n const images: ParsedPptxImage[] = [];\n const relationshipPath = slidePath.replace(\n /slides\\/(slide\\d+\\.xml)/,\n \"slides/_rels/$1.rels\",\n );\n const slideRelationshipsXml = await zip\n .file(relationshipPath)\n ?.async(\"string\");\n if (slideRelationshipsXml) {\n for (const relationship of parseRelationships(\n parseXml(slideRelationshipsXml),\n ).values()) {\n if (\n !relationship.type.includes(\"/image\") &&\n !/\\.(png|jpe?g|gif|svg|webp|bmp|tiff?|emf|wmf)$/i.test(\n relationship.target,\n )\n ) {\n continue;\n }\n const imagePath = relationship.target.startsWith(\"/\")\n ? relationship.target.slice(1)\n : relationship.target.startsWith(\"../\")\n ? `ppt/${relationship.target.replace(/^\\.\\.\\//, \"\")}`\n : `ppt/slides/${relationship.target}`;\n const image = zip.file(imagePath);\n if (!image) continue;\n const name = imagePath.split(\"/\").at(-1) ?? \"image\";\n images.push({\n data: new Uint8Array(await image.async(\"nodebuffer\")),\n mimeType: imageMimeType(name),\n name,\n });\n }\n }\n const number = slideNumber(slidePath);\n const notesXml = await zip\n .file(`ppt/notesSlides/notesSlide${number}.xml`)\n ?.async(\"string\");\n let notes: string | undefined;\n if (notesXml) {\n const runs: ParsedPptxTextRun[] = [];\n collectTextRuns(parseXml(notesXml), runs);\n const value = runs\n .map((run) => run.content)\n .join(\" \")\n .trim();\n if (value.length > 1) notes = value;\n }\n slides.push({\n texts,\n images,\n notes,\n layoutHint: guessLayoutHint(texts, images.length > 0),\n });\n }\n const firstSlide = slides[0]?.texts ?? [];\n const title =\n [...firstSlide]\n .sort((a, b) => (b.fontSize ?? 0) - (a.fontSize ?? 0))[0]\n ?.content.trim()\n .slice(0, 200) || \"Imported Presentation\";\n return { title, slides, theme };\n}\n\nasync function parseTheme(\n zip: ZipArchive,\n parseXml: (xml: string) => unknown,\n): Promise<ParsedPptxPresentation[\"theme\"]> {\n const xml = await zip.file(\"ppt/theme/theme1.xml\")?.async(\"string\");\n if (!xml) return undefined;\n const root = record(parseXml(xml));\n const elements = record(record(root?.[\"a:theme\"])?.[\"a:themeElements\"]);\n const scheme = record(elements?.[\"a:clrScheme\"]);\n const colors: string[] = [];\n for (const [key, value] of Object.entries(scheme ?? {})) {\n if (key.startsWith(\"@_\")) continue;\n const color = record(value);\n const rgb = stringValue(record(color?.[\"a:srgbClr\"])?.[\"@_val\"]);\n const system = stringValue(record(color?.[\"a:sysClr\"])?.[\"@_lastClr\"]);\n if (rgb || system) colors.push(`#${rgb ?? system}`);\n }\n const fontScheme = record(elements?.[\"a:fontScheme\"]);\n const fonts = [\"a:majorFont\", \"a:minorFont\"].flatMap((key) => {\n const value = stringValue(\n record(record(fontScheme?.[key])?.[\"a:latin\"])?.[\"@_typeface\"],\n );\n return value ? [value] : [];\n });\n return colors.length || fonts.length ? { colors, fonts } : undefined;\n}\n\nfunction collectTextRuns(\n value: unknown,\n runs: ParsedPptxTextRun[],\n inherited: Omit<ParsedPptxTextRun, \"content\"> = {},\n): void {\n const node = record(value);\n if (!node) return;\n for (const raw of asArray(node[\"a:r\"])) {\n const run = record(raw);\n const content = innerText(run?.[\"a:t\"]);\n if (content)\n runs.push({\n content,\n ...runProperties(record(run?.[\"a:rPr\"]), inherited),\n });\n }\n if (node[\"a:t\"] !== undefined && node[\"a:r\"] === undefined) {\n const content = innerText(node[\"a:t\"]);\n if (content) runs.push({ content, ...inherited });\n }\n for (const [key, child] of Object.entries(node)) {\n if (key.startsWith(\"@_\") || key === \"a:r\" || key === \"a:t\") continue;\n for (const item of asArray(child)) collectTextRuns(item, runs, inherited);\n }\n}\n\nfunction runProperties(\n value: Record<string, unknown> | null,\n inherited: Omit<ParsedPptxTextRun, \"content\">,\n): Omit<ParsedPptxTextRun, \"content\"> {\n if (!value) return inherited;\n const size = Number(value[\"@_sz\"]);\n const rgb = stringValue(\n record(record(value[\"a:solidFill\"])?.[\"a:srgbClr\"])?.[\"@_val\"],\n );\n return {\n ...inherited,\n ...(value[\"@_b\"] === \"1\" || value[\"@_b\"] === 1 || value[\"@_b\"] === true\n ? { bold: true }\n : {}),\n ...(value[\"@_i\"] === \"1\" || value[\"@_i\"] === 1 || value[\"@_i\"] === true\n ? { italic: true }\n : {}),\n ...(Number.isFinite(size) && size > 0 ? { fontSize: size / 100 } : {}),\n ...(rgb ? { color: `#${rgb}` } : {}),\n };\n}\n\nfunction parseRelationships(value: unknown) {\n const output = new Map<string, { target: string; type: string }>();\n for (const raw of asArray(\n record(record(value)?.Relationships)?.Relationship,\n )) {\n const relationship = record(raw);\n const id = stringValue(relationship?.[\"@_Id\"]);\n const target = stringValue(relationship?.[\"@_Target\"]);\n if (id && target) {\n output.set(id, {\n target,\n type: stringValue(relationship?.[\"@_Type\"]) ?? \"\",\n });\n }\n }\n return output;\n}\n\nfunction guessLayoutHint(texts: ParsedPptxTextRun[], hasImages: boolean) {\n if (hasImages) return \"image\";\n const maxSize = Math.max(...texts.map((text) => text.fontSize ?? 0), 0);\n const length = texts.reduce((total, text) => total + text.content.length, 0);\n if (texts.length <= 3 && length < 200 && maxSize >= 28) return \"title\";\n if (texts.length <= 2 && length < 100) return \"section\";\n return \"content\";\n}\n\nfunction imageMimeType(name: string): string {\n const extension = name.split(\".\").at(-1)?.toLowerCase();\n return (\n {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n svg: \"image/svg+xml\",\n webp: \"image/webp\",\n bmp: \"image/bmp\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n emf: \"image/emf\",\n wmf: \"image/wmf\",\n }[extension ?? \"\"] ?? \"application/octet-stream\"\n );\n}\n\nasync function loadPptxDependencies(): Promise<{\n loadZip(data: Uint8Array): Promise<ZipArchive>;\n parseXml(xml: string): unknown;\n}> {\n try {\n const [zipModule, xmlModule] = await Promise.all([\n import(\"jszip\") as Promise<{\n default: { loadAsync(data: Uint8Array): Promise<ZipArchive> };\n }>,\n import(\"fast-xml-parser\") as Promise<{\n XMLParser: new (options: Record<string, unknown>) => {\n parse(xml: string): unknown;\n };\n }>,\n ]);\n const parser = new xmlModule.XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n });\n return {\n loadZip: (data) => zipModule.default.loadAsync(data),\n parseXml: (xml) => parser.parse(xml),\n };\n } catch {\n throw new Error(\n \"Structured PPTX parsing requires the optional jszip and fast-xml-parser dependencies.\",\n );\n }\n}\n\nfunction slideNumber(value: string): number {\n return Number(value.match(/slide(\\d+)/)?.[1] ?? 0);\n}\n\nfunction innerText(value: unknown): string {\n if (typeof value === \"string\" || typeof value === \"number\")\n return String(value);\n return String(record(value)?.[\"#text\"] ?? \"\");\n}\n\nfunction asArray(value: unknown): unknown[] {\n return value === undefined || value === null\n ? []\n : Array.isArray(value)\n ? value\n : [value];\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n"]}
|
|
@@ -604,6 +604,9 @@ declare const messages: {
|
|
|
604
604
|
chatIntegrations: string;
|
|
605
605
|
chatIntegrationsDescription: string;
|
|
606
606
|
addIntegration: string;
|
|
607
|
+
addSomething: string;
|
|
608
|
+
addSomethingTitle: string;
|
|
609
|
+
addSomethingPlaceholder: string;
|
|
607
610
|
dispatchEntrypoint: string;
|
|
608
611
|
sharedMessaging: string;
|
|
609
612
|
};
|
|
@@ -614,11 +617,16 @@ declare const messages: {
|
|
|
614
617
|
description: string;
|
|
615
618
|
searchPlaceholder: string;
|
|
616
619
|
addYourOwn: string;
|
|
620
|
+
addSomething: string;
|
|
621
|
+
addSomethingTitle: string;
|
|
622
|
+
addSomethingPlaceholder: string;
|
|
617
623
|
noMatches: string;
|
|
618
624
|
connected: string;
|
|
619
625
|
configure: string;
|
|
620
626
|
connect: string;
|
|
621
627
|
connectWithOAuth: string;
|
|
628
|
+
connectSuggestion: string;
|
|
629
|
+
dismissSuggestion: string;
|
|
622
630
|
backToIntegrations: string;
|
|
623
631
|
customTitle: string;
|
|
624
632
|
configureTitle: string;
|
|
@@ -640,6 +648,7 @@ declare const messages: {
|
|
|
640
648
|
descriptionPlaceholder: string;
|
|
641
649
|
headersPlaceholder: string;
|
|
642
650
|
openSetupDocs: string;
|
|
651
|
+
viewSetup: string;
|
|
643
652
|
test: string;
|
|
644
653
|
toolsAvailable_one: string;
|
|
645
654
|
toolsAvailable_other: string;
|
|
@@ -657,6 +666,7 @@ declare const messages: {
|
|
|
657
666
|
notion: {
|
|
658
667
|
description: string;
|
|
659
668
|
useCase: string;
|
|
669
|
+
setupNote: string;
|
|
660
670
|
};
|
|
661
671
|
semgrep: {
|
|
662
672
|
description: string;
|
|
@@ -683,12 +693,100 @@ declare const messages: {
|
|
|
683
693
|
useCase: string;
|
|
684
694
|
setupNote: string;
|
|
685
695
|
};
|
|
696
|
+
cloudflare: {
|
|
697
|
+
description: string;
|
|
698
|
+
useCase: string;
|
|
699
|
+
setupNote: string;
|
|
700
|
+
};
|
|
701
|
+
gitlab: {
|
|
702
|
+
description: string;
|
|
703
|
+
useCase: string;
|
|
704
|
+
setupNote: string;
|
|
705
|
+
};
|
|
706
|
+
figma: {
|
|
707
|
+
description: string;
|
|
708
|
+
useCase: string;
|
|
709
|
+
setupNote: string;
|
|
710
|
+
};
|
|
711
|
+
canva: {
|
|
712
|
+
description: string;
|
|
713
|
+
useCase: string;
|
|
714
|
+
setupNote: string;
|
|
715
|
+
};
|
|
716
|
+
vercel: {
|
|
717
|
+
description: string;
|
|
718
|
+
useCase: string;
|
|
719
|
+
setupNote: string;
|
|
720
|
+
};
|
|
721
|
+
github: {
|
|
722
|
+
description: string;
|
|
723
|
+
useCase: string;
|
|
724
|
+
setupNote: string;
|
|
725
|
+
};
|
|
726
|
+
slack: {
|
|
727
|
+
description: string;
|
|
728
|
+
useCase: string;
|
|
729
|
+
setupNote: string;
|
|
730
|
+
};
|
|
731
|
+
asana: {
|
|
732
|
+
description: string;
|
|
733
|
+
useCase: string;
|
|
734
|
+
setupNote: string;
|
|
735
|
+
};
|
|
736
|
+
hubspot: {
|
|
737
|
+
description: string;
|
|
738
|
+
useCase: string;
|
|
739
|
+
setupNote: string;
|
|
740
|
+
};
|
|
741
|
+
intercom: {
|
|
742
|
+
description: string;
|
|
743
|
+
useCase: string;
|
|
744
|
+
setupNote: string;
|
|
745
|
+
};
|
|
746
|
+
monday: {
|
|
747
|
+
description: string;
|
|
748
|
+
useCase: string;
|
|
749
|
+
setupNote: string;
|
|
750
|
+
};
|
|
751
|
+
webflow: {
|
|
752
|
+
description: string;
|
|
753
|
+
useCase: string;
|
|
754
|
+
setupNote: string;
|
|
755
|
+
};
|
|
756
|
+
paypal: {
|
|
757
|
+
description: string;
|
|
758
|
+
useCase: string;
|
|
759
|
+
setupNote: string;
|
|
760
|
+
};
|
|
761
|
+
box: {
|
|
762
|
+
description: string;
|
|
763
|
+
useCase: string;
|
|
764
|
+
setupNote: string;
|
|
765
|
+
};
|
|
766
|
+
netlify: {
|
|
767
|
+
description: string;
|
|
768
|
+
useCase: string;
|
|
769
|
+
setupNote: string;
|
|
770
|
+
};
|
|
771
|
+
zapier: {
|
|
772
|
+
description: string;
|
|
773
|
+
useCase: string;
|
|
774
|
+
setupNote: string;
|
|
775
|
+
};
|
|
686
776
|
};
|
|
687
777
|
auth: {
|
|
688
778
|
none: string;
|
|
689
779
|
headers: string;
|
|
690
780
|
oauth: string;
|
|
691
781
|
};
|
|
782
|
+
status: {
|
|
783
|
+
beta: string;
|
|
784
|
+
setupRequired: string;
|
|
785
|
+
clientRestricted: string;
|
|
786
|
+
verified: string;
|
|
787
|
+
preflightOnly: string;
|
|
788
|
+
restricted: string;
|
|
789
|
+
};
|
|
692
790
|
};
|
|
693
791
|
observability: {
|
|
694
792
|
noData: string;
|