@agent-native/core 0.80.11 → 0.81.1
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 +1 -1
- package/corpus/core/CHANGELOG.md +53 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/design-connect.ts +419 -19
- package/corpus/core/src/client/AgentPanel.tsx +33 -1
- package/corpus/core/src/client/ConnectBuilderCard.tsx +1 -0
- package/corpus/core/src/client/chat/index.ts +1 -0
- package/corpus/core/src/client/chat/run-recovery.tsx +9 -7
- package/corpus/core/src/client/chat-view-transition.ts +33 -2
- package/corpus/core/src/client/composer/PromptComposer.tsx +21 -2
- package/corpus/core/src/client/index.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -4
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -3
- package/corpus/core/src/client/use-agent-chat-home-handoff.ts +31 -3
- package/corpus/core/src/db/client.ts +29 -2
- package/corpus/core/src/provider-api/index.ts +29 -0
- package/corpus/core/src/server/core-routes-plugin.ts +58 -20
- package/corpus/core/src/styles/agent-native.css +54 -0
- package/corpus/core/src/usage/store.ts +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +118 -10
- package/corpus/templates/analytics/app/components/layout/layout-route-policy.ts +7 -0
- package/corpus/templates/analytics/app/global.css +8 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -1
- package/corpus/templates/analytics/app/lib/chat-handoff.ts +34 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +9 -18
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +109 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
- package/corpus/templates/analytics/changelog/2026-06-30-ask-opens-a-fresh-chat-unless-you-were-just-chatting-and-das.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-email-reports-are-more-reliable-and-use-cleaner.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-toolbar-controls-use-a-quieter-share-button-and-ve.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replay-rows-show-whole-minute-durations-in-the-playl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replays-now-render-captured-styling-and-keep-the-eve.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +16 -3
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +31 -14
- package/corpus/templates/assets/actions/open-asset-picker.ts +9 -0
- package/corpus/templates/assets/app/global.css +15 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +4 -0
- package/corpus/templates/assets/app/routes/library.tsx +90 -16
- package/corpus/templates/assets/changelog/2026-06-30-the-assets-picker-now-supports-a-vertical-embedded-layout-fo.md +6 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +1 -12
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -5
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -8
- package/corpus/templates/clips/changelog/2026-06-30-extension-save-recovery-avoids-false-upload-failures.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-30-longer-chrome-extension-recordings-now-keep-saving-reliably-.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +19 -10
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +38 -12
- package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +224 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +119 -16
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +16 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +48 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +9 -1
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +63 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +74 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +32 -0
- package/corpus/templates/design/AGENTS.md +27 -0
- package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1 -1
- package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +5 -5
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +63 -20
- package/corpus/templates/design/actions/apply-motion-edit.ts +67 -69
- package/corpus/templates/design/actions/apply-shader-fill.ts +148 -56
- package/corpus/templates/design/actions/capture-design-state.ts +27 -4
- package/corpus/templates/design/actions/connect-localhost.ts +59 -22
- package/corpus/templates/design/actions/export-zip.ts +23 -8
- package/corpus/templates/design/actions/generate-design.ts +53 -1
- package/corpus/templates/design/actions/get-component-details.ts +5 -19
- package/corpus/templates/design/actions/get-motion-timeline.ts +135 -10
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +116 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +521 -0
- package/corpus/templates/design/actions/index-design-tokens.ts +10 -1
- package/corpus/templates/design/actions/insert-design-native-asset.ts +268 -0
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +233 -0
- package/corpus/templates/design/actions/list-design-extensions.ts +32 -10
- package/corpus/templates/design/actions/list-design-native-assets.ts +105 -0
- package/corpus/templates/design/actions/list-figma-library-assets.ts +292 -0
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +238 -0
- package/corpus/templates/design/actions/navigate.ts +18 -3
- package/corpus/templates/design/actions/provider-api-catalog.ts +2 -2
- package/corpus/templates/design/actions/provider-api-docs.ts +1 -1
- package/corpus/templates/design/actions/provider-api-request.ts +3 -3
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +48 -0
- package/corpus/templates/design/actions/run-design-audit.ts +53 -4
- package/corpus/templates/design/actions/run-design-extension-action.ts +1 -1
- package/corpus/templates/design/actions/view-screen.ts +1 -1
- package/corpus/templates/design/actions/write-local-file.ts +213 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +230 -3308
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +30 -20
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +776 -287
- package/corpus/templates/design/app/components/design/EditPanel.tsx +212 -208
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +14 -2
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/MotionDock.tsx +235 -266
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +490 -55
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +43 -62
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +34 -61
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +251 -0
- package/corpus/templates/design/app/components/design/bridge/codegen.ts +125 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4037 -0
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +62 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +272 -0
- package/corpus/templates/design/app/components/design/bridge/nav.bridge.ts +116 -0
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +24 -0
- package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +78 -0
- package/corpus/templates/design/app/components/design/bridge/tsconfig.json +17 -0
- package/corpus/templates/design/app/components/design/bridge/tweak.bridge.ts +28 -0
- package/corpus/templates/design/app/components/design/bridge/zoom.bridge.ts +43 -0
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +45 -16
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +88 -9
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +94 -9
- package/corpus/templates/design/app/components/layout/Layout.tsx +19 -3
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/global.css +7 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +23 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +21 -0
- package/corpus/templates/design/app/i18n-data.ts +358 -0
- package/corpus/templates/design/app/lib/pending-generation.ts +1 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +2402 -499
- package/corpus/templates/design/app/pages/Index.tsx +5 -1
- package/corpus/templates/design/changelog/2026-06-30-applying-the-one-click-fix-for-a-small-tap-target-accessibil.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-canvas-creation-screen-dragging-undo-redo-and-image-fill-edi.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-component-prop-edits-and-shader-fills-now-preserve-rapid-sam.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-can-browse-figma-library-components-and-insert-them-i.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-native-components-embedded-media-and-figma-im.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-preview-now-includes-a-publish-app-waitlist-option-fr.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-left-rail-now-matches-the-sidebar-chrome-and-uses-t.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-tools-create-menu-now-stays-compact-instead-of-rend.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-starter-prompts-now-begin-generating-immediately-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-drawing-rectangles-on-the-all-screens-canvas-no-longer-flash.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-code-native-design-studio-edits-so-component-props-mot.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-visual-editing-hover-overlays-and-spacing-handles-so-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-edits-now-save-automatically-without-a-separate-css-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-timelines-now-reopen-as-editable-tracks-after-writing.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-new-design-prompts-with-uploaded-screenshots-work-reliably-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-screen-previews-in-all-screens-view-now-keep-rounded-outline.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-selection-outlines-now-sit-flush-on-rectangles-drawn-directl.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-share-options-use-a-tighter-design-editor-popover-with-compa.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-collapsed-motion-panel-now-stays-tucked-under-the-left-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-now-shows-states-and-review-in-a-tighte.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-sidebar-keeps-the-organization-picker-space-stable-while.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-tokens-can-now-be-imported-from-pasted-notes-code-files-fold.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +168 -65
- package/corpus/templates/design/package.json +3 -1
- package/corpus/templates/design/server/db/schema.ts +23 -0
- package/corpus/templates/design/server/handlers/uploads.ts +22 -1
- package/corpus/templates/design/server/lib/provider-api.ts +7 -4
- package/corpus/templates/design/server/lib/verify-write-grant.ts +108 -0
- package/corpus/templates/design/server/plugins/db.ts +39 -0
- package/corpus/templates/design/server/register-secrets.ts +38 -0
- package/corpus/templates/design/shared/board-file.ts +228 -0
- package/corpus/templates/design/shared/board-objects.ts +288 -0
- package/corpus/templates/design/shared/code-layer.ts +52 -0
- package/corpus/templates/design/shared/motion-compiler.ts +58 -7
- package/corpus/templates/design/shared/motion-timeline.ts +2 -2
- package/corpus/templates/design/tsconfig.json +2 -1
- package/corpus/templates/slides/AGENTS.md +9 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +4 -24
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +29 -20
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +365 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -9
- package/corpus/templates/slides/app/vite-env.d.ts +18 -0
- package/corpus/templates/slides/changelog/2026-06-30-powerpoint-downloads-now-preserve-the-rendered-slide-layout-.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-30-unavailable-decks-open-in-a-cleaner-full-height-centered-sta.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/vite.config.ts +1 -0
- package/dist/cli/design-connect.d.ts +25 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +357 -18
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +18 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +1 -0
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +5 -5
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat-view-transition.d.ts +6 -0
- package/dist/client/chat-view-transition.d.ts.map +1 -1
- package/dist/client/chat-view-transition.js +23 -2
- package/dist/client/chat-view-transition.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +3 -2
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -4
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -3
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +8 -2
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.js +20 -6
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/client.d.ts +1 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +28 -2
- package/dist/db/client.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +8 -8
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +5 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +28 -0
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts +25 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +43 -18
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +54 -0
- package/dist/usage/store.js +2 -2
- package/dist/usage/store.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { type AspectRatio, getAspectRatioDims } from "./aspect-ratios";
|
|
2
|
+
import {
|
|
3
|
+
findSlideExportSource,
|
|
4
|
+
preloadImagesWithCors,
|
|
5
|
+
} from "./export-pdf-client";
|
|
6
|
+
|
|
7
|
+
interface PptxExportSlide {
|
|
8
|
+
id: string;
|
|
9
|
+
notes?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function safePptxName(title: string) {
|
|
13
|
+
const safeName = title.replace(/[^a-zA-Z0-9]/g, "-") || "deck";
|
|
14
|
+
return `${safeName}.pptx`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function triggerBlobDownload(blob: Blob, filename: string) {
|
|
18
|
+
const url = URL.createObjectURL(blob);
|
|
19
|
+
const a = document.createElement("a");
|
|
20
|
+
a.href = url;
|
|
21
|
+
a.download = filename;
|
|
22
|
+
a.rel = "noopener";
|
|
23
|
+
document.body.appendChild(a);
|
|
24
|
+
a.click();
|
|
25
|
+
a.remove();
|
|
26
|
+
window.setTimeout(() => URL.revokeObjectURL(url), 60_000);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function escapeXml(value: string) {
|
|
30
|
+
return value
|
|
31
|
+
.replace(/&/g, "&")
|
|
32
|
+
.replace(/</g, "<")
|
|
33
|
+
.replace(/>/g, ">")
|
|
34
|
+
.replace(/"/g, """)
|
|
35
|
+
.replace(/'/g, "'");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function addRelationship(xml: string, relationship: string) {
|
|
39
|
+
if (xml.includes(relationship)) return xml;
|
|
40
|
+
return xml.replace("</Relationships>", `${relationship}</Relationships>`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function addContentTypeOverride(xml: string, partName: string, type: string) {
|
|
44
|
+
if (xml.includes(`PartName="${partName}"`)) return xml;
|
|
45
|
+
return xml.replace(
|
|
46
|
+
"</Types>",
|
|
47
|
+
`<Override PartName="${partName}" ContentType="${type}"/></Types>`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function nextRelationshipId(xml: string) {
|
|
52
|
+
const ids = Array.from(xml.matchAll(/\bId="rId(\d+)"/g)).map((match) =>
|
|
53
|
+
Number(match[1]),
|
|
54
|
+
);
|
|
55
|
+
return `rId${Math.max(0, ...ids) + 1}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function notesTextBody(notes: string) {
|
|
59
|
+
const lines = notes.split(/\r?\n/);
|
|
60
|
+
return lines
|
|
61
|
+
.map(
|
|
62
|
+
(line) =>
|
|
63
|
+
`<a:p><a:r><a:rPr lang="en-US" dirty="0"/><a:t>${escapeXml(line)}</a:t></a:r><a:endParaRPr lang="en-US" dirty="0"/></a:p>`,
|
|
64
|
+
)
|
|
65
|
+
.join("");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function notesSlideXml(notes: string, slideNumber: number) {
|
|
69
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
70
|
+
<p:notes xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"><p:cSld><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr><p:sp><p:nvSpPr><p:cNvPr id="2" name="Slide Image Placeholder 1"/><p:cNvSpPr><a:spLocks noGrp="1" noRot="1" noChangeAspect="1"/></p:cNvSpPr><p:nvPr><p:ph type="sldImg"/></p:nvPr></p:nvSpPr><p:spPr/></p:sp><p:sp><p:nvSpPr><p:cNvPr id="3" name="Notes Placeholder 2"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="body" idx="1"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/>${notesTextBody(notes)}</p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="4" name="Slide Number Placeholder 3"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="sldNum" sz="quarter" idx="10"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:fld id="{F7021451-1387-4CA6-816F-3879F97B5CBC}" type="slidenum"><a:rPr lang="en-US"/><a:t>${slideNumber}</a:t></a:fld><a:endParaRPr lang="en-US"/></a:p></p:txBody></p:sp></p:spTree></p:cSld><p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr></p:notes>`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const NOTES_MASTER_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
74
|
+
<p:notesMaster xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"><p:cSld><p:bg><p:bgRef idx="1001"><a:schemeClr val="bg1"/></p:bgRef></p:bg><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr></p:spTree></p:cSld><p:clrMap bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/><p:notesStyle><a:lvl1pPr marL="0" algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1200" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl1pPr></p:notesStyle></p:notesMaster>`;
|
|
75
|
+
|
|
76
|
+
const NOTES_MASTER_RELS_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
77
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="../theme/theme1.xml"/></Relationships>`;
|
|
78
|
+
|
|
79
|
+
export async function addSpeakerNotesToPptxBlob(
|
|
80
|
+
blob: Blob,
|
|
81
|
+
slides: PptxExportSlide[],
|
|
82
|
+
): Promise<Blob> {
|
|
83
|
+
const hasNotes = slides.some((slide) => slide.notes?.trim());
|
|
84
|
+
if (!hasNotes) return blob;
|
|
85
|
+
|
|
86
|
+
const { default: JSZip } = await import("jszip");
|
|
87
|
+
const zip = await JSZip.loadAsync(blob);
|
|
88
|
+
|
|
89
|
+
const contentTypesFile = zip.file("[Content_Types].xml");
|
|
90
|
+
const presentationFile = zip.file("ppt/presentation.xml");
|
|
91
|
+
const presentationRelsFile = zip.file("ppt/_rels/presentation.xml.rels");
|
|
92
|
+
|
|
93
|
+
if (!contentTypesFile || !presentationFile || !presentationRelsFile) {
|
|
94
|
+
return blob;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let contentTypes = await contentTypesFile.async("string");
|
|
98
|
+
let presentationXml = await presentationFile.async("string");
|
|
99
|
+
let presentationRels = await presentationRelsFile.async("string");
|
|
100
|
+
|
|
101
|
+
if (!zip.file("ppt/notesMasters/notesMaster1.xml")) {
|
|
102
|
+
zip.file("ppt/notesMasters/notesMaster1.xml", NOTES_MASTER_XML);
|
|
103
|
+
}
|
|
104
|
+
if (!zip.file("ppt/notesMasters/_rels/notesMaster1.xml.rels")) {
|
|
105
|
+
zip.file(
|
|
106
|
+
"ppt/notesMasters/_rels/notesMaster1.xml.rels",
|
|
107
|
+
NOTES_MASTER_RELS_XML,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
contentTypes = addContentTypeOverride(
|
|
112
|
+
contentTypes,
|
|
113
|
+
"/ppt/notesMasters/notesMaster1.xml",
|
|
114
|
+
"application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml",
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
if (!presentationRels.includes("relationships/notesMaster")) {
|
|
118
|
+
const relId = nextRelationshipId(presentationRels);
|
|
119
|
+
presentationRels = addRelationship(
|
|
120
|
+
presentationRels,
|
|
121
|
+
`<Relationship Id="${relId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster" Target="notesMasters/notesMaster1.xml"/>`,
|
|
122
|
+
);
|
|
123
|
+
if (!presentationXml.includes("<p:notesMasterIdLst>")) {
|
|
124
|
+
presentationXml = presentationXml.replace(
|
|
125
|
+
"</p:sldIdLst>",
|
|
126
|
+
`</p:sldIdLst><p:notesMasterIdLst><p:notesMasterId r:id="${relId}"/></p:notesMasterIdLst>`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!presentationXml.includes("<p:notesSz")) {
|
|
132
|
+
presentationXml = presentationXml.replace(
|
|
133
|
+
"<p:defaultTextStyle>",
|
|
134
|
+
'<p:notesSz cx="6858000" cy="12192000"/><p:defaultTextStyle>',
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (let i = 0; i < slides.length; i++) {
|
|
139
|
+
const notes = slides[i].notes?.trim();
|
|
140
|
+
if (!notes) continue;
|
|
141
|
+
|
|
142
|
+
const slideNumber = i + 1;
|
|
143
|
+
const slideRelsPath = `ppt/slides/_rels/slide${slideNumber}.xml.rels`;
|
|
144
|
+
const slideRelsFile = zip.file(slideRelsPath);
|
|
145
|
+
if (!slideRelsFile) continue;
|
|
146
|
+
|
|
147
|
+
let slideRels = await slideRelsFile.async("string");
|
|
148
|
+
if (!slideRels.includes("relationships/notesSlide")) {
|
|
149
|
+
const relId = nextRelationshipId(slideRels);
|
|
150
|
+
slideRels = addRelationship(
|
|
151
|
+
slideRels,
|
|
152
|
+
`<Relationship Id="${relId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide" Target="../notesSlides/notesSlide${slideNumber}.xml"/>`,
|
|
153
|
+
);
|
|
154
|
+
zip.file(slideRelsPath, slideRels);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
zip.file(
|
|
158
|
+
`ppt/notesSlides/notesSlide${slideNumber}.xml`,
|
|
159
|
+
notesSlideXml(notes, slideNumber),
|
|
160
|
+
);
|
|
161
|
+
zip.file(
|
|
162
|
+
`ppt/notesSlides/_rels/notesSlide${slideNumber}.xml.rels`,
|
|
163
|
+
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
164
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster" Target="../notesMasters/notesMaster1.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="../slides/slide${slideNumber}.xml"/></Relationships>`,
|
|
165
|
+
);
|
|
166
|
+
contentTypes = addContentTypeOverride(
|
|
167
|
+
contentTypes,
|
|
168
|
+
`/ppt/notesSlides/notesSlide${slideNumber}.xml`,
|
|
169
|
+
"application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml",
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
zip.file("[Content_Types].xml", contentTypes);
|
|
174
|
+
zip.file("ppt/presentation.xml", presentationXml);
|
|
175
|
+
zip.file("ppt/_rels/presentation.xml.rels", presentationRels);
|
|
176
|
+
|
|
177
|
+
return zip.generateAsync({
|
|
178
|
+
type: "blob",
|
|
179
|
+
compression: "DEFLATE",
|
|
180
|
+
compressionOptions: { level: 6 },
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function createUnscaledExportClone(
|
|
185
|
+
source: HTMLElement,
|
|
186
|
+
dims: { width: number; height: number },
|
|
187
|
+
) {
|
|
188
|
+
const stage = document.createElement("div");
|
|
189
|
+
stage.setAttribute("aria-hidden", "true");
|
|
190
|
+
Object.assign(stage.style, {
|
|
191
|
+
height: `${dims.height}px`,
|
|
192
|
+
left: "-100000px",
|
|
193
|
+
overflow: "hidden",
|
|
194
|
+
pointerEvents: "none",
|
|
195
|
+
position: "fixed",
|
|
196
|
+
top: "0",
|
|
197
|
+
width: `${dims.width}px`,
|
|
198
|
+
zIndex: "-1",
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const clone = source.cloneNode(true) as HTMLElement;
|
|
202
|
+
Object.assign(clone.style, {
|
|
203
|
+
height: `${dims.height}px`,
|
|
204
|
+
maxHeight: `${dims.height}px`,
|
|
205
|
+
maxWidth: `${dims.width}px`,
|
|
206
|
+
position: "relative",
|
|
207
|
+
transform: "none",
|
|
208
|
+
width: `${dims.width}px`,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
stage.appendChild(clone);
|
|
212
|
+
document.body.appendChild(stage);
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
element: clone,
|
|
216
|
+
cleanup: () => stage.remove(),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function svgDataUrl(svg: SVGSVGElement) {
|
|
221
|
+
const copy = svg.cloneNode(true) as SVGSVGElement;
|
|
222
|
+
if (!copy.getAttribute("xmlns")) {
|
|
223
|
+
copy.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
|
224
|
+
}
|
|
225
|
+
const serialized = new XMLSerializer().serializeToString(copy);
|
|
226
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(serialized)}`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function rasterizeSvgElement(
|
|
230
|
+
svg: SVGSVGElement,
|
|
231
|
+
width: number,
|
|
232
|
+
height: number,
|
|
233
|
+
) {
|
|
234
|
+
const fallback = svgDataUrl(svg);
|
|
235
|
+
const canvas = document.createElement("canvas");
|
|
236
|
+
const ctx = canvas.getContext("2d");
|
|
237
|
+
if (!ctx || typeof Image === "undefined") return fallback;
|
|
238
|
+
|
|
239
|
+
const scale = Math.max(2, window.devicePixelRatio || 1);
|
|
240
|
+
canvas.width = Math.max(1, Math.ceil(width * scale));
|
|
241
|
+
canvas.height = Math.max(1, Math.ceil(height * scale));
|
|
242
|
+
|
|
243
|
+
const image = new Image();
|
|
244
|
+
const loaded = new Promise<void>((resolve, reject) => {
|
|
245
|
+
image.onload = () => resolve();
|
|
246
|
+
image.onerror = () => reject(new Error("Could not rasterize SVG"));
|
|
247
|
+
});
|
|
248
|
+
image.src = fallback;
|
|
249
|
+
|
|
250
|
+
try {
|
|
251
|
+
await loaded;
|
|
252
|
+
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
253
|
+
return canvas.toDataURL("image/png");
|
|
254
|
+
} catch {
|
|
255
|
+
return fallback;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function replaceInlineSvgsWithImages(root: HTMLElement) {
|
|
260
|
+
const svgs = Array.from(root.querySelectorAll<SVGSVGElement>("svg"));
|
|
261
|
+
for (const svg of svgs) {
|
|
262
|
+
const rect = svg.getBoundingClientRect();
|
|
263
|
+
const viewBox = svg.viewBox?.baseVal;
|
|
264
|
+
const width =
|
|
265
|
+
rect.width || Number(svg.getAttribute("width")) || viewBox?.width || 1;
|
|
266
|
+
const height =
|
|
267
|
+
rect.height || Number(svg.getAttribute("height")) || viewBox?.height || 1;
|
|
268
|
+
const dataUrl = await rasterizeSvgElement(svg, width, height);
|
|
269
|
+
const img = document.createElement("img");
|
|
270
|
+
const style = window.getComputedStyle(svg);
|
|
271
|
+
img.src = dataUrl;
|
|
272
|
+
img.alt = svg.getAttribute("aria-label") ?? "";
|
|
273
|
+
Object.assign(img.style, {
|
|
274
|
+
alignSelf: style.alignSelf,
|
|
275
|
+
display: style.display === "inline" ? "inline-block" : style.display,
|
|
276
|
+
flex: style.flex,
|
|
277
|
+
height: `${height}px`,
|
|
278
|
+
justifySelf: style.justifySelf,
|
|
279
|
+
left: style.left,
|
|
280
|
+
marginBottom: style.marginBottom,
|
|
281
|
+
marginLeft: style.marginLeft,
|
|
282
|
+
marginRight: style.marginRight,
|
|
283
|
+
marginTop: style.marginTop,
|
|
284
|
+
objectFit: "contain",
|
|
285
|
+
opacity: style.opacity,
|
|
286
|
+
position: style.position,
|
|
287
|
+
right: style.right,
|
|
288
|
+
top: style.top,
|
|
289
|
+
transform: style.transform === "none" ? "" : style.transform,
|
|
290
|
+
width: `${width}px`,
|
|
291
|
+
zIndex: style.zIndex,
|
|
292
|
+
});
|
|
293
|
+
svg.replaceWith(img);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function widenNoWrapTextElements(root: HTMLElement) {
|
|
298
|
+
const elements = Array.from(root.querySelectorAll<HTMLElement>("*"));
|
|
299
|
+
for (const element of elements) {
|
|
300
|
+
if (!element.textContent?.trim()) continue;
|
|
301
|
+
if (element.querySelector("img,svg,video,canvas")) continue;
|
|
302
|
+
const style = window.getComputedStyle(element);
|
|
303
|
+
if (style.whiteSpace !== "nowrap" && style.whiteSpace !== "pre") continue;
|
|
304
|
+
const rect = element.getBoundingClientRect();
|
|
305
|
+
if (!rect.width || !rect.height) continue;
|
|
306
|
+
const buffer = Math.max(24, rect.width * 0.25);
|
|
307
|
+
element.style.boxSizing = "border-box";
|
|
308
|
+
if (style.display === "inline") {
|
|
309
|
+
element.style.display = "inline-block";
|
|
310
|
+
}
|
|
311
|
+
element.style.width = `${Math.ceil(rect.width + buffer)}px`;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export async function exportDeckAsPptx(
|
|
316
|
+
deckTitle: string,
|
|
317
|
+
slides: PptxExportSlide[],
|
|
318
|
+
aspectRatio?: AspectRatio,
|
|
319
|
+
): Promise<void> {
|
|
320
|
+
const { exportToPptx } = await import("dom-to-pptx");
|
|
321
|
+
|
|
322
|
+
if (typeof document !== "undefined" && document.fonts?.ready) {
|
|
323
|
+
await document.fonts.ready;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const dims = getAspectRatioDims(aspectRatio);
|
|
327
|
+
const exportClones: Array<{
|
|
328
|
+
element: HTMLElement;
|
|
329
|
+
cleanup: () => void;
|
|
330
|
+
}> = [];
|
|
331
|
+
|
|
332
|
+
try {
|
|
333
|
+
for (let i = 0; i < slides.length; i++) {
|
|
334
|
+
const exportSlide = slides[i];
|
|
335
|
+
const source = findSlideExportSource(exportSlide.id, i, slides.length);
|
|
336
|
+
const clone = createUnscaledExportClone(source, {
|
|
337
|
+
width: dims.width,
|
|
338
|
+
height: dims.height,
|
|
339
|
+
});
|
|
340
|
+
exportClones.push(clone);
|
|
341
|
+
widenNoWrapTextElements(clone.element);
|
|
342
|
+
await replaceInlineSvgsWithImages(clone.element);
|
|
343
|
+
await preloadImagesWithCors(clone.element);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const initialBlob = await exportToPptx(
|
|
347
|
+
exportClones.map((clone) => clone.element),
|
|
348
|
+
{
|
|
349
|
+
autoEmbedFonts: true,
|
|
350
|
+
fileName: safePptxName(deckTitle),
|
|
351
|
+
height: dims.pptxInches.h,
|
|
352
|
+
skipDownload: true,
|
|
353
|
+
svgAsVector: false,
|
|
354
|
+
width: dims.pptxInches.w,
|
|
355
|
+
},
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
const blob = await addSpeakerNotesToPptxBlob(initialBlob, slides);
|
|
359
|
+
triggerBlobDownload(blob, safePptxName(deckTitle));
|
|
360
|
+
} finally {
|
|
361
|
+
for (const clone of exportClones) {
|
|
362
|
+
clone.cleanup();
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
@@ -65,6 +65,7 @@ import { toast } from "@/hooks/use-toast";
|
|
|
65
65
|
import type { AspectRatio } from "@/lib/aspect-ratios";
|
|
66
66
|
import { getPreset } from "@/lib/design-systems";
|
|
67
67
|
import { exportDeckAsPdf } from "@/lib/export-pdf-client";
|
|
68
|
+
import { exportDeckAsPptx } from "@/lib/export-pptx-client";
|
|
68
69
|
import {
|
|
69
70
|
shouldClearNewDeckGeneratingState,
|
|
70
71
|
shouldShowNewDeckGeneratingOverlay,
|
|
@@ -81,7 +82,6 @@ const Pinpoint = lazy<ComponentType<PinpointProps>>(() =>
|
|
|
81
82
|
);
|
|
82
83
|
|
|
83
84
|
function MissingDeckAccessPane({
|
|
84
|
-
deckId,
|
|
85
85
|
hasTeamJoinOption,
|
|
86
86
|
orgLoading,
|
|
87
87
|
orgError,
|
|
@@ -89,7 +89,6 @@ function MissingDeckAccessPane({
|
|
|
89
89
|
onRetry,
|
|
90
90
|
onBack,
|
|
91
91
|
}: {
|
|
92
|
-
deckId: string | undefined;
|
|
93
92
|
hasTeamJoinOption: boolean;
|
|
94
93
|
orgLoading: boolean;
|
|
95
94
|
orgError: boolean;
|
|
@@ -116,7 +115,7 @@ function MissingDeckAccessPane({
|
|
|
116
115
|
: t("deckEditor.deckUnavailableDescription");
|
|
117
116
|
|
|
118
117
|
return (
|
|
119
|
-
<div className="flex
|
|
118
|
+
<div className="flex min-h-screen items-center justify-center bg-background px-4 py-10">
|
|
120
119
|
<div className="w-full max-w-md rounded-lg border border-border bg-card p-6 shadow-sm">
|
|
121
120
|
<div className="mb-4 flex items-center gap-3">
|
|
122
121
|
<div className="flex size-10 items-center justify-center rounded-md border border-border bg-background text-muted-foreground">
|
|
@@ -124,11 +123,6 @@ function MissingDeckAccessPane({
|
|
|
124
123
|
</div>
|
|
125
124
|
<div className="min-w-0">
|
|
126
125
|
<h1 className="text-base font-semibold text-foreground">{title}</h1>
|
|
127
|
-
{deckId && (
|
|
128
|
-
<p className="truncate text-xs text-muted-foreground">
|
|
129
|
-
Deck ID: {deckId}
|
|
130
|
-
</p>
|
|
131
|
-
)}
|
|
132
126
|
</div>
|
|
133
127
|
</div>
|
|
134
128
|
<p className="text-sm leading-6 text-muted-foreground">{description}</p>
|
|
@@ -723,7 +717,6 @@ export default function DeckEditor() {
|
|
|
723
717
|
if (!deck || !id) {
|
|
724
718
|
return (
|
|
725
719
|
<MissingDeckAccessPane
|
|
726
|
-
deckId={id}
|
|
727
720
|
hasTeamJoinOption={hasTeamJoinOption}
|
|
728
721
|
orgLoading={orgLoading}
|
|
729
722
|
orgError={orgError}
|
|
@@ -846,6 +839,16 @@ export default function DeckEditor() {
|
|
|
846
839
|
});
|
|
847
840
|
}
|
|
848
841
|
}}
|
|
842
|
+
onExportPptx={async () => {
|
|
843
|
+
const slides = deck.slides.map((s) => ({
|
|
844
|
+
id: s.id,
|
|
845
|
+
notes: s.notes,
|
|
846
|
+
}));
|
|
847
|
+
if (slides.length === 0) {
|
|
848
|
+
throw new Error(t("deckEditor.deckHasNoSlides"));
|
|
849
|
+
}
|
|
850
|
+
await exportDeckAsPptx(deck.title, slides, deck.aspectRatio);
|
|
851
|
+
}}
|
|
849
852
|
aspectRatio={deck.aspectRatio}
|
|
850
853
|
designSystemTitle={designSystemTitle}
|
|
851
854
|
onSetAspectRatio={(ratio: AspectRatio) => {
|
|
@@ -4,3 +4,21 @@ declare module "react-dom/server.browser" {
|
|
|
4
4
|
export * from "react-dom/server";
|
|
5
5
|
export { default } from "react-dom/server";
|
|
6
6
|
}
|
|
7
|
+
|
|
8
|
+
declare module "dom-to-pptx" {
|
|
9
|
+
export interface DomToPptxOptions {
|
|
10
|
+
autoEmbedFonts?: boolean;
|
|
11
|
+
fileName?: string;
|
|
12
|
+
fonts?: Array<{ name: string; url?: string; urls?: string[] }>;
|
|
13
|
+
height?: number;
|
|
14
|
+
layout?: string;
|
|
15
|
+
skipDownload?: boolean;
|
|
16
|
+
svgAsVector?: boolean;
|
|
17
|
+
width?: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function exportToPptx(
|
|
21
|
+
target: HTMLElement | string | Array<HTMLElement | string>,
|
|
22
|
+
options?: DomToPptxOptions,
|
|
23
|
+
): Promise<Blob>;
|
|
24
|
+
}
|
|
@@ -6,6 +6,11 @@ export interface DesignConnectArgs {
|
|
|
6
6
|
port: number;
|
|
7
7
|
root: string;
|
|
8
8
|
routeManifest?: string;
|
|
9
|
+
/** Optional deployed design app URL used to self-register the bridge on
|
|
10
|
+
* startup. When set (or when AGENT_NATIVE_URL / DESIGN_APP_URL env vars
|
|
11
|
+
* are present) the CLI POSTs to `/_agent-native/actions/connect-localhost`
|
|
12
|
+
* with the real bridge token so the server can store it for grant minting. */
|
|
13
|
+
appUrl?: string;
|
|
9
14
|
json: boolean;
|
|
10
15
|
once: boolean;
|
|
11
16
|
dryRun: boolean;
|
|
@@ -40,6 +45,10 @@ export interface DesignConnectManifest {
|
|
|
40
45
|
export interface DesignConnectBridge {
|
|
41
46
|
server: Server;
|
|
42
47
|
manifest: DesignConnectManifest;
|
|
48
|
+
/** Per-rootPath bridge token. Kept in-process only; never serialised into
|
|
49
|
+
* the manifest JSON so it is not exposed over the network via GET /manifest.
|
|
50
|
+
* The server-side grant action reads it from the running bridge instance. */
|
|
51
|
+
bridgeToken: string;
|
|
43
52
|
}
|
|
44
53
|
export declare function parseDesignConnectArgs(argv: string[]): DesignConnectArgs;
|
|
45
54
|
export declare function discoverDesignRoutes(root: string): DesignConnectRoute[];
|
|
@@ -47,6 +56,22 @@ export declare function prepareDesignConnectManifest(options?: Partial<DesignCon
|
|
|
47
56
|
root?: string;
|
|
48
57
|
}): Promise<DesignConnectManifest>;
|
|
49
58
|
export declare function startDesignConnectBridge(manifest: DesignConnectManifest): Promise<DesignConnectBridge>;
|
|
59
|
+
/**
|
|
60
|
+
* Resolve the design app URL from an explicit value or environment variables.
|
|
61
|
+
* Returns undefined when no URL is configured (registration is optional).
|
|
62
|
+
*/
|
|
63
|
+
export declare function resolveAppUrl(explicit?: string): string | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* POST to the design app's `connect-localhost` action endpoint to register
|
|
66
|
+
* (or refresh) the bridge connection and persist the real bridge token on the
|
|
67
|
+
* server row. This is a best-effort call: failures are logged but do not
|
|
68
|
+
* abort the bridge process.
|
|
69
|
+
*
|
|
70
|
+
* @param appUrl - Deployed design app base URL (e.g. https://design.agent-native.com)
|
|
71
|
+
* @param bridge - The running bridge returned by startDesignConnectBridge
|
|
72
|
+
* @param authToken - Optional bearer token for the authenticated action route
|
|
73
|
+
*/
|
|
74
|
+
export declare function registerConnectionWithServer(appUrl: string, bridge: DesignConnectBridge, authToken?: string): Promise<void>;
|
|
50
75
|
export declare function runDesign(argv: string[]): Promise<number>;
|
|
51
76
|
export {};
|
|
52
77
|
//# sourceMappingURL=design-connect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-connect.d.ts","sourceRoot":"","sources":["../../src/cli/design-connect.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"design-connect.d.ts","sourceRoot":"","sources":["../../src/cli/design-connect.ts"],"names":[],"mappings":"AAGA,OAAa,EAEX,KAAK,MAAM,EAEZ,MAAM,WAAW,CAAC;AAcnB,QAAA,MAAM,iBAAiB,YACrB,QAAQ,EACR,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,cAAc,CACN,CAAC;AAEX,KAAK,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;mFAG+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,cAAc,GAAG,MAAM,GAAG,QAAQ,CAAC;CAChD;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,6BAA6B,CAAC;IACtC,UAAU,EAAE,WAAW,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,KAAK,CAAC;QAClB,SAAS,EAAE,eAAe,CAAC;QAC3B,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;QAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,qBAAqB,CAAC;IAChC;;kFAE8E;IAC9E,WAAW,EAAE,MAAM,CAAC;CACrB;AAyBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,iBAAiB,CA6DxE;AAiED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE,CA+CvE;AA6DD,wBAAsB,4BAA4B,CAChD,OAAO,GAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3D,OAAO,CAAC,qBAAqB,CAAC,CA0ChC;AA0FD,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,mBAAmB,CAAC,CA4O9B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmBnE;AAiBD;;;;;;;;;GASG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,mBAAmB,EAC3B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAsDf;AAqCD,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,mBAqD7C"}
|