@agent-native/core 0.92.9 → 0.92.11
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 +29 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +181 -15
- package/corpus/core/src/agent/run-manager.ts +31 -4
- package/corpus/core/src/agent/run-store.ts +80 -0
- package/corpus/core/src/cli/design-connect.ts +433 -151
- package/corpus/core/src/cli/skills.ts +14 -0
- package/corpus/core/src/client/AssistantChat.tsx +25 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +40 -6
- package/corpus/core/src/client/agent-chat.ts +165 -1
- package/corpus/core/src/client/chat/index.ts +9 -1
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +38 -2
- package/corpus/core/src/client/index.ts +5 -0
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +18 -7
- package/corpus/core/src/collab/awareness-store.ts +23 -12
- package/corpus/core/src/collab/client.ts +16 -5
- package/corpus/core/src/collab/index.ts +4 -0
- package/corpus/core/src/collab/recent-edits.ts +65 -2
- package/corpus/core/src/deploy/build.ts +133 -5
- package/corpus/core/src/index.browser.ts +1 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +98 -11
- package/corpus/core/src/server/builder-design-systems.ts +30 -4
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +12 -6
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/create-recording.ts +2 -0
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +5 -3
- package/corpus/templates/clips/actions/request-transcript.ts +102 -33
- package/corpus/templates/clips/app/components/library/library-grid.tsx +1 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +59 -19
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +48 -4
- package/corpus/templates/clips/app/components/player/video-player.tsx +17 -12
- package/corpus/templates/clips/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -37
- package/corpus/templates/clips/app/routes/record.tsx +17 -4
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-popover-sits-closer-to-the-menu-bar.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-recording-optimization-progress-stays-visible-until-the-clip-opens.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-large-video-file-uploads-failing-before-their-resumabl.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-new-video-uploads-defaulting-to-private.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-long-recordings-now-get-enough-time-to-download-their-media-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-meeting-notes-no-longer-lowers-your-microphone-volume-for-ot.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-on-mobile-tapping-a-playing-clip-reveals-playback-controls-w.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-regenerate-any-clip-transcript-from-its-saved-recording-or-r.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-slack-previews-now-show-the-clip-length-alongside-its-descri.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +12 -2
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +8 -1
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -5
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +5 -5
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +3 -0
- package/corpus/templates/clips/desktop/src/styles.css +6 -3
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +29 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +103 -21
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +117 -39
- package/corpus/templates/clips/server/lib/slack-unfurls.ts +20 -1
- package/corpus/templates/clips/server/lib/streaming-upload-mode.ts +10 -4
- package/corpus/templates/clips/shared/recording-core.ts +12 -0
- package/corpus/templates/content/AGENTS.md +7 -6
- package/corpus/templates/content/actions/_document-flush.ts +132 -17
- package/corpus/templates/content/actions/_notion-action-utils.ts +15 -0
- package/corpus/templates/content/actions/create-and-link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/pull-document.ts +5 -7
- package/corpus/templates/content/actions/pull-notion-page.ts +2 -0
- package/corpus/templates/content/actions/push-notion-page.ts +10 -0
- package/corpus/templates/content/actions/resolve-notion-sync-conflict.ts +2 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +88 -23
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +32 -2
- package/corpus/templates/content/app/hooks/use-notion.ts +6 -6
- package/corpus/templates/content/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/content/app/i18n-data.ts +18 -0
- package/corpus/templates/content/changelog/2026-07-09-notion-conflict-choices-and-version-restores-preserve-docume.md +6 -0
- package/corpus/templates/content/server/lib/notion-sync.ts +80 -64
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +29 -2
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +86 -0
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +57 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +11 -0
- package/corpus/templates/design/AGENTS.md +45 -10
- package/corpus/templates/design/actions/add-localhost-screens.ts +66 -13
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +45 -36
- package/corpus/templates/design/actions/apply-motion-edit.ts +25 -31
- package/corpus/templates/design/actions/apply-shader-fill.ts +29 -42
- package/corpus/templates/design/actions/detach-component-instance.ts +337 -0
- package/corpus/templates/design/actions/export-design-as-figma-svg.ts +219 -0
- package/corpus/templates/design/actions/generate-design.ts +79 -12
- package/corpus/templates/design/actions/generate-screens.ts +57 -12
- package/corpus/templates/design/actions/get-figma-styles.ts +115 -0
- package/corpus/templates/design/actions/go-to-main-component.ts +254 -0
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +4 -3
- package/corpus/templates/design/actions/import-design-source.ts +4 -31
- package/corpus/templates/design/actions/import-figma-clipboard.ts +134 -0
- package/corpus/templates/design/actions/import-figma-frame.ts +95 -0
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/design/actions/list-design-components.ts +104 -0
- package/corpus/templates/design/actions/list-figma-library-assets.ts +1 -24
- package/corpus/templates/design/actions/open-component-source.ts +2 -4
- package/corpus/templates/design/actions/present-design-variants.ts +412 -16
- package/corpus/templates/design/actions/preview-source-edit.ts +14 -1
- package/corpus/templates/design/actions/run-design-audit.ts +25 -3
- package/corpus/templates/design/actions/show-design-questions.ts +10 -0
- package/corpus/templates/design/actions/swap-component-instance.ts +544 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +45 -60
- package/corpus/templates/design/actions/write-local-file.ts +25 -1
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +152 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1077 -58
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +5 -5
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +73 -21
- package/corpus/templates/design/app/components/design/EditPanel.tsx +16 -11
- package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +364 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +180 -53
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +0 -2
- package/corpus/templates/design/app/components/design/MotionDock.tsx +144 -21
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1152 -167
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +27 -5
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +23 -2
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +63 -49
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +1293 -54
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +6 -1
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +23 -6
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +5 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +14 -2
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +37 -2
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open-guard.ts +25 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +19 -1
- package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +43 -5
- package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +27 -2
- package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +10 -1
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +19 -2
- package/corpus/templates/design/app/components/design/design-canvas/annotation-snapshot.ts +265 -0
- package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +16 -5
- package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +16 -2
- package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +7 -2
- package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +3 -1
- package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +78 -8
- package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +451 -73
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +12 -4
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +398 -272
- package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +41 -7
- package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +16 -3
- package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +24 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +222 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +171 -78
- package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +45 -5
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +299 -28
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +120 -150
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +53 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +284 -117
- package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +81 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +19 -14
- package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +7 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +155 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +268 -46
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +350 -31
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +233 -23
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +72 -2
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +51 -11
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +84 -11
- package/corpus/templates/design/app/components/design/inspector/index.ts +3 -0
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +552 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +157 -0
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +53 -0
- package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +184 -0
- package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +403 -26
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +20 -1
- package/corpus/templates/design/app/components/design/types.ts +33 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +59 -7
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +119 -17
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +275 -63
- package/corpus/templates/design/app/hooks/use-question-flow.ts +14 -3
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +67 -10
- package/corpus/templates/design/app/i18n/zh-TW.ts +91 -1
- package/corpus/templates/design/app/i18n-data.ts +1217 -10
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +577 -0
- package/corpus/templates/design/app/lib/agent-chat.ts +23 -0
- package/corpus/templates/design/app/lib/design-import.ts +24 -0
- package/corpus/templates/design/app/lib/figma-clipboard.ts +157 -0
- package/corpus/templates/design/app/lib/figma-svg-copy.ts +221 -0
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +143 -30
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +15 -0
- package/corpus/templates/design/app/pages/design-editor/editor-session.ts +33 -0
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +38 -0
- package/corpus/templates/design/app/pages/design-editor/overview-annotation-context.ts +157 -0
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +62 -6
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +245 -0
- package/corpus/templates/design/app/pages/design-editor/react-semantic-handoff.ts +586 -0
- package/corpus/templates/design/app/pages/design-editor/screen-auto-layout.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +201 -1
- package/corpus/templates/design/changelog/2026-07-09-added-underline-strikethrough-and-text-case-uppercase-lowerc.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-annotate-now-draws-across-the-all-screens-canvas-without-swi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-auto-layout-children-can-now-be-dragged-into-freeform-screen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-board-shapes-now-stay-visible-and-nest-correctly-across-the-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-component-source-navigation-now-opens-reliably-from-the-insp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-local-react-layer-moves-now-hand-off-exact-sour.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-moves-undo-and-redo-now-keep-both-screens-stabl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-detach-a-component-instance-into-plain-editable-eleme.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-dragging-layers-into-auto-layout-now-respects-ignore-auto-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-drawing-annotations-sent-to-the-agent-now-include-a-rendered.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-editor-sidebars-now-use-figma-matched-default-widths-for-a-r.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-empty-frames-and-rectangles-now-expose-full-auto-layout-cont.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-export-any-design-screen-as-a-real-vector-svg-for-figma-with.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-grid-auto-layout-now-uses-true-responsive-rows-and-columns-w.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-hidden-and-locked-screens-now-behave-consistently-between-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-image-fills-now-preserve-valid-urls-and-layered-fit-settings.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-import-figma-frames-as-pixel-accurate-design-screens-via-a-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspect-code-now-hides-internal-styling-metadata-and-wraps-l.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspector-blur-and-shadow-effects-now-preserve-other-effects.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-jump-to-a-components-other-instances-from-the-inspecto.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-keyboard-shortcuts-are-now-discoverable-in-a-figma-style-bot.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layer-selection-now-keeps-cmd-or-ctrl-toggles-and-shift-rang.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layers-dropped-into-auto-layout-now-participate-correctly-in.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-live-edit-screens-now-enter-and-leave-full-view-withou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-preview-urls-now-live-in-the-inspector-instead-of-taki.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-can-now-be-hidden-and-locked-from-layers-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-now-keep-exact-source-provenance-and-supp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-visual-editing-now-loads-reliably-and-shows-live.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-paste-from-figma-cmd-v-now-imports-exact-editable-nodes-when.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-pressing-escape-after-selecting-a-screen-now-reveals-page-pr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-right-click-overlapping-or-nested-objects-to-choose-the-exac.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-scale-edge-stretch-and-center-constraints-now-preserve-layer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-rows-can-now-be-reordered-in-layers-with-matching-can.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-selection-stays-responsive-in-designs-with-hundreds-o.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-shift-a-now-enables-auto-layout-on-a-selected-screen-with-fl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-swap-a-component-instance-for-another-from-the-libra.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-drawing-annotations-now-stay-available-to-retry-when-the.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +3 -6
- package/corpus/templates/design/e2e/helpers.ts +27 -6
- package/corpus/templates/design/server/lib/design-to-figma-svg.ts +1412 -0
- package/corpus/templates/design/server/lib/figma-clipboard-match.ts +196 -0
- package/corpus/templates/design/server/lib/figma-node-import.ts +311 -0
- package/corpus/templates/design/server/lib/figma-node-to-html.ts +1334 -0
- package/corpus/templates/design/server/lib/figma-paste-fallback.ts +64 -0
- package/corpus/templates/design/server/lib/playwright-runtime.ts +78 -0
- package/corpus/templates/design/server/plugins/db.ts +41 -0
- package/corpus/templates/design/server/source-workspace.ts +64 -0
- package/corpus/templates/design/shared/board-file.ts +13 -2
- package/corpus/templates/design/shared/canvas-math.ts +231 -33
- package/corpus/templates/design/shared/code-layer.ts +122 -8
- package/corpus/templates/design/shared/component-library.ts +161 -0
- package/corpus/templates/design/shared/db-conflict.ts +27 -0
- package/corpus/templates/design/shared/design-source-capabilities.ts +2 -1
- package/corpus/templates/design/shared/figma-url.ts +149 -0
- package/corpus/templates/design/shared/pen-path.ts +16 -7
- package/corpus/templates/design/shared/source-mode.ts +1 -0
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +7 -19
- package/corpus/templates/plan/changelog/2026-07-09-canvas-panning-now-keeps-zoom-fixed-even-at-the-edges.md +6 -0
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +311 -70
- package/corpus/templates/slides/changelog/2026-07-09-fixed-the-slide-rail-going-permanently-stale-during-a-long-a.md +6 -0
- package/dist/agent/production-agent.d.ts +79 -6
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +161 -14
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +29 -5
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +46 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +61 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/cli/design-connect.d.ts +6 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +336 -139
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +14 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +19 -3
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +38 -18
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +60 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +122 -1
- package/dist/client/agent-chat.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/extensions/EmbeddedExtension.d.ts +12 -0
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +36 -2
- package/dist/client/extensions/EmbeddedExtension.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/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +18 -6
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/collab/awareness-store.d.ts +5 -0
- package/dist/collab/awareness-store.d.ts.map +1 -1
- package/dist/collab/awareness-store.js +19 -12
- package/dist/collab/awareness-store.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +13 -5
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +1 -0
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +1 -0
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/recent-edits.d.ts +3 -1
- package/dist/collab/recent-edits.d.ts.map +1 -1
- package/dist/collab/recent-edits.js +57 -2
- package/dist/collab/recent-edits.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.d.ts +24 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +102 -5
- package/dist/deploy/build.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +87 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/builder-design-systems.d.ts +15 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +9 -4
- package/dist/server/builder-design-systems.js.map +1 -1
- package/package.json +1 -1
|
@@ -2463,6 +2463,8 @@ const enUS = {
|
|
|
2463
2463
|
couldNotSaveLocalFile: "Could not save local file",
|
|
2464
2464
|
collabConnectingReadOnly:
|
|
2465
2465
|
"Connecting live editor. Showing a read-only snapshot.",
|
|
2466
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
2467
|
+
"The live document could not be saved before syncing.",
|
|
2466
2468
|
documentTitle: "Document title",
|
|
2467
2469
|
builderBodySyncing: "Content is still syncing from Builder",
|
|
2468
2470
|
builderBodySyncingDescription:
|
|
@@ -4843,6 +4845,7 @@ const editorMessagesByLocale = {
|
|
|
4843
4845
|
"zh-CN": {
|
|
4844
4846
|
noDocumentSelected: "未选择文档",
|
|
4845
4847
|
collabConnectingReadOnly: "正在连接实时编辑器。显示只读快照。",
|
|
4848
|
+
liveDocumentSaveBeforeSyncFailed: "实时文档无法在同步前保存。",
|
|
4846
4849
|
builderBodySyncing: "内容仍在从 Builder 同步",
|
|
4847
4850
|
builderBodySyncingDescription:
|
|
4848
4851
|
"同步 Builder 正文完成前会暂停编辑,避免覆盖现有文章内容。",
|
|
@@ -5169,6 +5172,8 @@ const editorMessagesByLocale = {
|
|
|
5169
5172
|
noDocumentSelected: "Ningún documento seleccionado",
|
|
5170
5173
|
collabConnectingReadOnly:
|
|
5171
5174
|
"Conectando el editor en vivo. Mostrando una instantánea de solo lectura.",
|
|
5175
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
5176
|
+
"No se pudo guardar el documento activo antes de sincronizarlo.",
|
|
5172
5177
|
builderBodySyncing: "El contenido aún se está sincronizando desde Builder",
|
|
5173
5178
|
builderBodySyncingDescription:
|
|
5174
5179
|
"La edición está en pausa hasta que el cuerpo de Builder termine de sincronizarse, para no sobrescribir el contenido existente del artículo.",
|
|
@@ -5506,6 +5511,8 @@ const editorMessagesByLocale = {
|
|
|
5506
5511
|
noDocumentSelected: "Aucun document sélectionné",
|
|
5507
5512
|
collabConnectingReadOnly:
|
|
5508
5513
|
"Connexion de l'éditeur en direct. Affichage d'un instantané en lecture seule.",
|
|
5514
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
5515
|
+
"Le document actif n’a pas pu être enregistré avant la synchronisation.",
|
|
5509
5516
|
builderBodySyncing:
|
|
5510
5517
|
"Le contenu est encore en cours de synchronisation depuis Builder",
|
|
5511
5518
|
builderBodySyncingDescription:
|
|
@@ -5846,6 +5853,8 @@ const editorMessagesByLocale = {
|
|
|
5846
5853
|
noDocumentSelected: "Kein Dokument ausgewählt",
|
|
5847
5854
|
collabConnectingReadOnly:
|
|
5848
5855
|
"Live-Editor wird verbunden. Schreibgeschützte Momentaufnahme wird angezeigt.",
|
|
5856
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
5857
|
+
"Das aktive Dokument konnte vor der Synchronisierung nicht gespeichert werden.",
|
|
5849
5858
|
builderBodySyncing: "Inhalte werden noch von Builder synchronisiert",
|
|
5850
5859
|
builderBodySyncingDescription:
|
|
5851
5860
|
"Die Bearbeitung ist pausiert, bis der Builder-Textkörper fertig synchronisiert ist, damit der bestehende Artikelinhalt nicht überschrieben wird.",
|
|
@@ -6190,6 +6199,8 @@ const editorMessagesByLocale = {
|
|
|
6190
6199
|
noDocumentSelected: "ドキュメントが選択されていません",
|
|
6191
6200
|
collabConnectingReadOnly:
|
|
6192
6201
|
"ライブエディターに接続中。読み取り専用のスナップショットを表示しています。",
|
|
6202
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
6203
|
+
"同期前にライブドキュメントを保存できませんでした。",
|
|
6193
6204
|
builderBodySyncing: "コンテンツはまだ Builder から同期中です",
|
|
6194
6205
|
builderBodySyncingDescription:
|
|
6195
6206
|
"既存の記事内容を上書きしないよう、Builder 本文の同期が完了するまで編集は一時停止されます。",
|
|
@@ -6524,6 +6535,8 @@ const editorMessagesByLocale = {
|
|
|
6524
6535
|
noDocumentSelected: "선택한 문서가 없습니다.",
|
|
6525
6536
|
collabConnectingReadOnly:
|
|
6526
6537
|
"라이브 편집기에 연결하는 중입니다. 읽기 전용 스냅샷을 표시합니다.",
|
|
6538
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
6539
|
+
"동기화하기 전에 실시간 문서를 저장하지 못했습니다.",
|
|
6527
6540
|
builderBodySyncing: "콘텐츠가 아직 Builder에서 동기화되는 중입니다",
|
|
6528
6541
|
builderBodySyncingDescription:
|
|
6529
6542
|
"기존 문서 내용을 덮어쓰지 않도록 Builder 본문 동기화가 완료될 때까지 편집이 일시 중지됩니다.",
|
|
@@ -6857,6 +6870,8 @@ const editorMessagesByLocale = {
|
|
|
6857
6870
|
noDocumentSelected: "Nenhum documento selecionado",
|
|
6858
6871
|
collabConnectingReadOnly:
|
|
6859
6872
|
"Conectando o editor ao vivo. Exibindo um instantâneo somente leitura.",
|
|
6873
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
6874
|
+
"Não foi possível salvar o documento ativo antes da sincronização.",
|
|
6860
6875
|
builderBodySyncing: "O conteúdo ainda está sincronizando do Builder",
|
|
6861
6876
|
builderBodySyncingDescription:
|
|
6862
6877
|
"A edição fica pausada até o corpo do Builder terminar de sincronizar, para não sobrescrever o conteúdo existente do artigo.",
|
|
@@ -7196,6 +7211,8 @@ const editorMessagesByLocale = {
|
|
|
7196
7211
|
noDocumentSelected: "कोई दस्तावेज़ चयनित नहीं",
|
|
7197
7212
|
collabConnectingReadOnly:
|
|
7198
7213
|
"लाइव संपादक कनेक्ट हो रहा है। केवल-पठन स्नैपशॉट दिखाया जा रहा है।",
|
|
7214
|
+
liveDocumentSaveBeforeSyncFailed:
|
|
7215
|
+
"सिंक करने से पहले लाइव दस्तावेज़ सहेजा नहीं जा सका।",
|
|
7199
7216
|
builderBodySyncing: "सामग्री अभी भी Builder से सिंक हो रही है",
|
|
7200
7217
|
builderBodySyncingDescription:
|
|
7201
7218
|
"Builder का मुख्य भाग सिंक पूरा होने तक संपादन रोका गया है, ताकि मौजूदा लेख सामग्री अधिलेखित न हो।",
|
|
@@ -7525,6 +7542,7 @@ const editorMessagesByLocale = {
|
|
|
7525
7542
|
noDocumentSelected: "لم يتم تحديد أي مستند",
|
|
7526
7543
|
collabConnectingReadOnly:
|
|
7527
7544
|
"جارٍ الاتصال بالمحرر المباشر. يتم عرض لقطة للقراءة فقط.",
|
|
7545
|
+
liveDocumentSaveBeforeSyncFailed: "تعذّر حفظ المستند المباشر قبل المزامنة.",
|
|
7528
7546
|
builderBodySyncing: "لا يزال المحتوى قيد المزامنة من Builder",
|
|
7529
7547
|
builderBodySyncingDescription:
|
|
7530
7548
|
"يتم إيقاف التحرير مؤقتًا حتى تكتمل مزامنة نص Builder، حتى لا يتم استبدال محتوى المقالة الحالي.",
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// in pnpm's node_modules. Logic is correct; types just don't unify across instances.
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
4
|
|
|
5
|
-
import { deleteCollabState, releaseDoc } from "@agent-native/core/collab";
|
|
6
5
|
import { and, eq, inArray, isNull, lt, or } from "drizzle-orm";
|
|
7
6
|
import type { InferSelectModel } from "drizzle-orm";
|
|
8
7
|
|
|
@@ -37,6 +36,56 @@ function nanoid(size = 12): string {
|
|
|
37
36
|
return Array.from(bytes, (byte) => chars[byte % chars.length]).join("");
|
|
38
37
|
}
|
|
39
38
|
|
|
39
|
+
async function replaceDocumentFromExternal(args: {
|
|
40
|
+
document: DocumentRow;
|
|
41
|
+
expectedUpdatedAt: string;
|
|
42
|
+
title: string;
|
|
43
|
+
content: string;
|
|
44
|
+
icon: string | null;
|
|
45
|
+
updatedAt: string;
|
|
46
|
+
}): Promise<boolean> {
|
|
47
|
+
const db = getDb();
|
|
48
|
+
return db.transaction(async (tx) => {
|
|
49
|
+
const applied = await tx
|
|
50
|
+
.update(schema.documents)
|
|
51
|
+
.set({
|
|
52
|
+
title: args.title,
|
|
53
|
+
content: args.content,
|
|
54
|
+
icon: args.icon,
|
|
55
|
+
updatedAt: args.updatedAt,
|
|
56
|
+
})
|
|
57
|
+
.where(
|
|
58
|
+
and(
|
|
59
|
+
eq(schema.documents.id, args.document.id),
|
|
60
|
+
eq(schema.documents.ownerEmail, args.document.ownerEmail),
|
|
61
|
+
eq(schema.documents.updatedAt, args.expectedUpdatedAt),
|
|
62
|
+
),
|
|
63
|
+
)
|
|
64
|
+
.returning({ id: schema.documents.id });
|
|
65
|
+
|
|
66
|
+
if (!applied || applied.length === 0) return false;
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
args.title !== args.document.title ||
|
|
70
|
+
args.content !== args.document.content
|
|
71
|
+
) {
|
|
72
|
+
// Keep the recovery snapshot in the same transaction as the replacement:
|
|
73
|
+
// a lost CAS creates no phantom version, and a snapshot failure rolls the
|
|
74
|
+
// destructive replacement back instead of leaving it unrecoverable.
|
|
75
|
+
await tx.insert(schema.documentVersions).values({
|
|
76
|
+
id: nanoid(),
|
|
77
|
+
ownerEmail: args.document.ownerEmail,
|
|
78
|
+
documentId: args.document.id,
|
|
79
|
+
title: args.document.title,
|
|
80
|
+
content: args.document.content,
|
|
81
|
+
createdAt: nowIso(),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return true;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
40
89
|
/**
|
|
41
90
|
* Hash of the canonical content. Two documents with the same hash are
|
|
42
91
|
* byte-identical once canonicalized, so this is the authoritative "did the
|
|
@@ -827,8 +876,6 @@ async function pullDocumentFromNotionInner(
|
|
|
827
876
|
remotePageDocumentIdByPageId?: RemotePageDocumentLookup;
|
|
828
877
|
},
|
|
829
878
|
): Promise<DocumentSyncStatus> {
|
|
830
|
-
const db = getDb();
|
|
831
|
-
const document = await getDocument(documentId, owner);
|
|
832
879
|
const link = await getSyncLink(documentId, owner);
|
|
833
880
|
if (!link) throw new Error("Document is not linked to a Notion page.");
|
|
834
881
|
const connection = await getNotionConnectionForOwner(owner);
|
|
@@ -935,28 +982,18 @@ async function pullDocumentFromNotionInner(
|
|
|
935
982
|
// check will mistake the unchanged document for a fresh local edit.
|
|
936
983
|
const updatedAt = contentChanged ? nowIso() : freshDocument.updatedAt;
|
|
937
984
|
if (contentChanged) {
|
|
938
|
-
//
|
|
939
|
-
//
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
updatedAt,
|
|
949
|
-
})
|
|
950
|
-
.where(
|
|
951
|
-
and(
|
|
952
|
-
eq(schema.documents.id, documentId),
|
|
953
|
-
eq(schema.documents.ownerEmail, owner),
|
|
954
|
-
eq(schema.documents.updatedAt, freshDocument.updatedAt),
|
|
955
|
-
),
|
|
956
|
-
)
|
|
957
|
-
.returning({ id: schema.documents.id });
|
|
985
|
+
// Snapshot + compare-and-swap are one transaction: only the winning
|
|
986
|
+
// replacement gets a recovery version, and snapshot failure rolls it back.
|
|
987
|
+
const applied = await replaceDocumentFromExternal({
|
|
988
|
+
document: freshDocument,
|
|
989
|
+
expectedUpdatedAt: freshDocument.updatedAt,
|
|
990
|
+
title: newTitle,
|
|
991
|
+
content: newContent,
|
|
992
|
+
icon: newIcon,
|
|
993
|
+
updatedAt,
|
|
994
|
+
});
|
|
958
995
|
|
|
959
|
-
if (!applied
|
|
996
|
+
if (!applied) {
|
|
960
997
|
// A newer local save raced in after our re-read. Do not adopt the
|
|
961
998
|
// pulled content or advance the hash baseline — surface a conflict so
|
|
962
999
|
// the user resolves it explicitly instead of silently losing the edit.
|
|
@@ -986,16 +1023,10 @@ async function pullDocumentFromNotionInner(
|
|
|
986
1023
|
});
|
|
987
1024
|
}
|
|
988
1025
|
|
|
989
|
-
//
|
|
990
|
-
//
|
|
991
|
-
//
|
|
992
|
-
//
|
|
993
|
-
try {
|
|
994
|
-
await deleteCollabState(documentId);
|
|
995
|
-
releaseDoc(documentId);
|
|
996
|
-
} catch {
|
|
997
|
-
// Non-fatal — the client-side sync will still reconcile via setContent.
|
|
998
|
-
}
|
|
1026
|
+
// Keep the Y.Doc intact. The live editor's updatedAt-gated reconcile applies
|
|
1027
|
+
// this authoritative SQL snapshot as a minimal Yjs transaction. Deleting
|
|
1028
|
+
// collab state here races connected clients (which can re-persist the stale
|
|
1029
|
+
// pre-pull state) and briefly makes later flush handshakes miss the editor.
|
|
999
1030
|
}
|
|
1000
1031
|
|
|
1001
1032
|
await upsertSyncLink({
|
|
@@ -1193,7 +1224,6 @@ async function pushDocumentToNotionInner(
|
|
|
1193
1224
|
// the rare case Notion normalizes a construct differently, immediately
|
|
1194
1225
|
// converging instead of ping-ponging. Re-read the row first so a local save
|
|
1195
1226
|
// that landed during the multi-round-trip push isn't clobbered below.
|
|
1196
|
-
const db = getDb();
|
|
1197
1227
|
const freshDocument = await getDocument(documentId, owner);
|
|
1198
1228
|
const newContent = remote.content ?? document.content;
|
|
1199
1229
|
const newTitle = remote.title || document.title;
|
|
@@ -1211,39 +1241,25 @@ async function pushDocumentToNotionInner(
|
|
|
1211
1241
|
// exactly what we pushed, since contentChanged is false).
|
|
1212
1242
|
let baselineContent = document.content;
|
|
1213
1243
|
if (contentChanged) {
|
|
1214
|
-
//
|
|
1215
|
-
//
|
|
1216
|
-
//
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
icon: newIcon,
|
|
1226
|
-
updatedAt: pushedAt,
|
|
1227
|
-
})
|
|
1228
|
-
.where(
|
|
1229
|
-
and(
|
|
1230
|
-
eq(schema.documents.id, documentId),
|
|
1231
|
-
eq(schema.documents.ownerEmail, owner),
|
|
1232
|
-
eq(schema.documents.updatedAt, document.updatedAt),
|
|
1233
|
-
),
|
|
1234
|
-
)
|
|
1235
|
-
.returning({ id: schema.documents.id });
|
|
1244
|
+
// Snapshot + compare-and-swap are atomic. If a concurrent save changed the
|
|
1245
|
+
// row since `document` was read, skip both the provider readback adoption
|
|
1246
|
+
// and its recovery version; the newer local edit remains localChanged.
|
|
1247
|
+
const applied = await replaceDocumentFromExternal({
|
|
1248
|
+
document: freshDocument,
|
|
1249
|
+
expectedUpdatedAt: document.updatedAt,
|
|
1250
|
+
title: newTitle,
|
|
1251
|
+
content: newContent,
|
|
1252
|
+
icon: newIcon,
|
|
1253
|
+
updatedAt: pushedAt,
|
|
1254
|
+
});
|
|
1236
1255
|
|
|
1237
|
-
if (applied
|
|
1256
|
+
if (applied) {
|
|
1238
1257
|
// The CAS landed — the row now holds Notion's normalized readback, so
|
|
1239
1258
|
// the baseline must match that, not the pre-push content we sent.
|
|
1240
1259
|
baselineContent = newContent;
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
} catch {
|
|
1245
|
-
// Non-fatal — the client reconciles via setContent.
|
|
1246
|
-
}
|
|
1260
|
+
// Preserve the live Y.Doc and let the updatedAt-gated editor reconcile
|
|
1261
|
+
// apply this provider-normalized snapshot. Clearing collab persistence
|
|
1262
|
+
// here can race a connected client's stale update and resurrect it.
|
|
1247
1263
|
}
|
|
1248
1264
|
// else: CAS raced and lost — the row holds the concurrent edit's content,
|
|
1249
1265
|
// not `newContent` and not `document.content`. Keep baselineContent as
|
|
@@ -173,7 +173,7 @@ defaults. The banned-defaults list above still applies, plus:
|
|
|
173
173
|
|
|
174
174
|
## Generation Workflow — the canonical 5-phase flow
|
|
175
175
|
|
|
176
|
-
This flow mirrors Claude Design's UX:
|
|
176
|
+
This flow mirrors Claude Design's UX: clarify only what's unclear → show variants → user picks → refine. Don't collapse phases into one shot for new, open-ended designs.
|
|
177
177
|
|
|
178
178
|
### Phase 1 — Create the project + ask before generating
|
|
179
179
|
|
|
@@ -187,7 +187,28 @@ application state. External MCP hosts should surface the `create-design`
|
|
|
187
187
|
returned "Open design" link, then use `present-design-variants` to open the
|
|
188
188
|
visual picker.
|
|
189
189
|
|
|
190
|
-
Then, for
|
|
190
|
+
Then, for a brief or ambiguous first prompt to a **new** design, call
|
|
191
|
+
`show-design-questions` BEFORE generating. The editor renders a full-canvas
|
|
192
|
+
overlay; answers come back as a chat message. Size the question count to how
|
|
193
|
+
much is actually unresolved — most prompts warrant 2-4 questions, not the full
|
|
194
|
+
1-8 range — and never ask about something the prompt already specified (a
|
|
195
|
+
stated color, audience, or layout is settled; don't re-ask it as a choice).
|
|
196
|
+
|
|
197
|
+
Skip the questions entirely when:
|
|
198
|
+
- the prompt is already specific enough to generate from (names the audience,
|
|
199
|
+
purpose, and a visual direction, e.g. "a dark, data-dense analytics
|
|
200
|
+
dashboard for ops engineers" or "re-skin this with my brand colors");
|
|
201
|
+
- it's a tweak/edit/refinement to an existing design rather than a new one —
|
|
202
|
+
go straight to `edit-design` (see Phase 3 and "Making edits" below);
|
|
203
|
+
- the user already answered a question set for this design and is now
|
|
204
|
+
iterating — don't re-ask settled ground on follow-up prompts for the same
|
|
205
|
+
design; or
|
|
206
|
+
- the user says "decide for me," "surprise me," "just build it," or similar.
|
|
207
|
+
|
|
208
|
+
Asking on every prompt is as much a failure mode as never asking: a detailed
|
|
209
|
+
prompt that already answers the obvious questions should generate
|
|
210
|
+
immediately, and a design already in flight should not be interrupted with a
|
|
211
|
+
second questionnaire.
|
|
191
212
|
|
|
192
213
|
```bash
|
|
193
214
|
pnpm action show-design-questions \
|
|
@@ -196,6 +217,12 @@ pnpm action show-design-questions \
|
|
|
196
217
|
--questions '[{"id":"form_factor","type":"text-options","question":"What form factor?","options":[{"label":"Desktop web app","value":"desktop"},{"label":"Mobile app","value":"mobile"},{"label":"Both / responsive","value":"responsive"},{"label":"Decide for me","value":"decide"}],"allowOther":true}]'
|
|
197
218
|
```
|
|
198
219
|
|
|
220
|
+
Favor choice-first questions (2-5 concrete options, `allowOther: true`, and a
|
|
221
|
+
"Decide for me" option when any answer is acceptable) over open-ended
|
|
222
|
+
`freeform` text, and avoid `multiSelect` unless the question genuinely allows
|
|
223
|
+
combining multiple answers — stacking multi-select questions multiplies
|
|
224
|
+
follow-up ambiguity instead of resolving it.
|
|
225
|
+
|
|
199
226
|
**Carry the form-factor answer through to generation — do not just ask and discard it.** A "Desktop web app" answer means the generated screen's canvas frame must be desktop-sized (~1440×1024), not left at whatever a screen with no placement falls back to. Map the answer to real frame geometry: pass `deviceType` (`"mobile"` / `"tablet"` / `"desktop"`) per screen to `generate-screens`, explicit `width`/`height` per variant to `present-design-variants`, or an explicit `canvasFrames` entry to `generate-design` — see Phase 2 and Phase 3 below. For "Both / responsive," generate at desktop width and rely on the responsive breakpoint system (see `responsive-breakpoints` skill) rather than guessing a size.
|
|
200
227
|
|
|
201
228
|
### Phase 2 — Generate side-by-side variations (2-5, three by default)
|
|
@@ -248,6 +248,92 @@ design-system indexing just to insert a component. Use
|
|
|
248
248
|
component/component set with provenance. Styles and variables still belong in
|
|
249
249
|
the Builder-backed design-system path above.
|
|
250
250
|
|
|
251
|
+
### Import from Figma (pixel-accurate frame import)
|
|
252
|
+
|
|
253
|
+
**When the user pastes a Figma frame/screen link and wants a real, editable
|
|
254
|
+
Design screen** (not a rendered image, not a component insert), use
|
|
255
|
+
`import-figma-frame` instead of `list-figma-library-assets` +
|
|
256
|
+
`insert-figma-library-asset`:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
pnpm action import-figma-frame --figmaUrl "https://www.figma.com/design/<fileKey>/<name>?node-id=<id>"
|
|
260
|
+
# or
|
|
261
|
+
pnpm action import-figma-frame --fileKey "<fileKey>" --nodeId "12:34" --designId "<designId>"
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
- Accepts a full Figma URL (design/file/proto share links, including
|
|
265
|
+
`/branch/<key>/` branch URLs — the branch's own key is used automatically) or
|
|
266
|
+
an explicit `fileKey` + `nodeId`. If `nodeId` is omitted, the file's first
|
|
267
|
+
top-level frame is imported.
|
|
268
|
+
- Maps the node tree to real HTML/CSS: exact position/size, auto-layout as
|
|
269
|
+
flexbox, text (font, line-height, letter-spacing, case, decoration, align),
|
|
270
|
+
fills (solid/gradient/image, correctly layered and gradient-angle-derived,
|
|
271
|
+
not a default angle), strokes (including the CENTER/INSIDE/OUTSIDE
|
|
272
|
+
distinction), per-corner radii, shadows/blur, opacity, and blend modes.
|
|
273
|
+
Vector networks, boolean operations, and other structurally unsupported node
|
|
274
|
+
types are rendered as an exact PNG at 2x scale instead of an approximated
|
|
275
|
+
shape guess.
|
|
276
|
+
- Saves the result as a new screen via the same import path as other Design
|
|
277
|
+
imports (`saveImportedDesignFiles`), placed on the overview canvas.
|
|
278
|
+
- Returns a `fidelityReport` — `exactCount`, `approximated` (properties CSS
|
|
279
|
+
can only approximate: rotation, per-side stroke weights, radial/angular/
|
|
280
|
+
diamond gradients, blur radius scale), and `imageFallbacks` (subtrees
|
|
281
|
+
rendered as PNG instead of structural HTML). Read this back to the user when
|
|
282
|
+
a design has non-trivial fallbacks so they know what to expect if they later
|
|
283
|
+
edit that subtree.
|
|
284
|
+
- After import, treat the screen like any other: `view-screen`,
|
|
285
|
+
`get-design-snapshot`, `apply-visual-edit` / `edit-design` all work normally
|
|
286
|
+
on it.
|
|
287
|
+
- For a file's published FILL/TEXT/EFFECT/GRID styles (name, description, node
|
|
288
|
+
id — not full token values), use `get-figma-styles` with `fileUrl`/`fileKey`.
|
|
289
|
+
This is the file's Styles panel, not the Enterprise Variables API; full
|
|
290
|
+
design-token extraction still routes through the Builder-backed
|
|
291
|
+
`index-design-system-with-builder` path above.
|
|
292
|
+
|
|
293
|
+
#### Paste from Figma (Cmd+C/Cmd+V) vs. a copied frame link
|
|
294
|
+
|
|
295
|
+
A plain clipboard paste (Cmd+C in Figma, Cmd+V on the Design canvas) is
|
|
296
|
+
handled separately from `import-figma-frame`, because a clipboard paste and a
|
|
297
|
+
copied frame **link** carry fundamentally different information:
|
|
298
|
+
|
|
299
|
+
- **A copied frame link** (`?node-id=...`) names an exact node. Always exact —
|
|
300
|
+
use `import-figma-frame`.
|
|
301
|
+
- **A plain clipboard paste** only carries Figma's `figmeta` marker, which is
|
|
302
|
+
`{fileKey, pasteID, dataType}` — **no node id at all**, and `pasteID` is an
|
|
303
|
+
ephemeral, server-side identifier that the public REST API can't resolve
|
|
304
|
+
back to a node. So a clipboard paste can only ever get an exact node import
|
|
305
|
+
on a **best-effort match**, never a guarantee.
|
|
306
|
+
|
|
307
|
+
The canvas paste listener (`app/lib/figma-clipboard.ts` +
|
|
308
|
+
`import-figma-clipboard`) handles this automatically:
|
|
309
|
+
|
|
310
|
+
1. Decodes `figmeta` from the pasted HTML client-side
|
|
311
|
+
(`extractFigmeta`/`resolveFigmaPasteImportCall`) to decide whether to call
|
|
312
|
+
`import-figma-clipboard` (figmeta present) or the legacy
|
|
313
|
+
`import-design-source` HTML path (no figmeta — not a Figma paste, or an
|
|
314
|
+
older Figma client that doesn't emit the marker).
|
|
315
|
+
2. `import-figma-clipboard` fetches the file's shallow structure (top-level
|
|
316
|
+
frames + their direct children, `server/lib/figma-node-import.ts`'s
|
|
317
|
+
`fetchFileStructure(fileKey, 3)`) and heuristically matches it against the
|
|
318
|
+
pasted content's visible text (`server/lib/figma-clipboard-match.ts`):
|
|
319
|
+
a frame is only imported when its **name** or at least **two distinct
|
|
320
|
+
text-layer contents** appear verbatim in the paste. Anything ambiguous or
|
|
321
|
+
unmatched imports **nothing structural** — it never guesses and never
|
|
322
|
+
imports the whole file uninvited.
|
|
323
|
+
3. On a confident match, the matched node(s) are fetched and mapped through
|
|
324
|
+
the same `buildScreenFilesFromFigmaNodes` core `import-figma-frame` uses
|
|
325
|
+
(`strategy: "restNodes"` in the result, with a `fidelityReport`).
|
|
326
|
+
4. Otherwise it falls back to the legacy visible-HTML paste
|
|
327
|
+
(`strategy: "htmlFallback"`), and reports why via `matchStatus`
|
|
328
|
+
(`"ambiguous"`, `"none"`, or `"error"`) and `figmaApiKeyMissing` (no
|
|
329
|
+
`FIGMA_ACCESS_TOKEN` configured). The canvas paste toast surfaces a hint in
|
|
330
|
+
both cases: connect the Figma access token, or paste a frame **link**
|
|
331
|
+
instead for a guaranteed-exact import.
|
|
332
|
+
|
|
333
|
+
Tell users who want guaranteed pixel-exact imports to copy a frame **link**
|
|
334
|
+
("Copy link to selection" in Figma), not just Cmd+C — a plain paste is
|
|
335
|
+
convenient but only best-effort.
|
|
336
|
+
|
|
251
337
|
### Source: Brand Analysis (combines website + notes)
|
|
252
338
|
|
|
253
339
|
```bash
|
|
@@ -17,6 +17,9 @@ How to export designs and generate handoff documentation for developers converti
|
|
|
17
17
|
with the editor's Download SVG command. The editor's own Download SVG
|
|
18
18
|
command captures the live browser DOM for the most faithful snapshot; use
|
|
19
19
|
the action when you need agent-side SVG export without a live browser.
|
|
20
|
+
**This is not importable into Figma as editable vectors** — Figma cannot
|
|
21
|
+
parse `foreignObject` content, so it stays an opaque embedded HTML blob.
|
|
22
|
+
Use `export-design-as-figma-svg` (below) when the destination is Figma.
|
|
20
23
|
- **PNG**: there is no PNG export action. Point the user to the editor's
|
|
21
24
|
download menu (Download PNG) — PNG export is a client-side rasterization of
|
|
22
25
|
the live canvas and is not exposed as an agent action.
|
|
@@ -88,6 +91,60 @@ pnpm action export-pdf --id <designId>
|
|
|
88
91
|
|
|
89
92
|
Returns all design data and files needed for the client to render a PDF.
|
|
90
93
|
|
|
94
|
+
## Export to Figma (SVG)
|
|
95
|
+
|
|
96
|
+
`export-design-as-figma-svg` exports a design screen (or a selected
|
|
97
|
+
element's subtree) as a genuinely VECTOR SVG document — real
|
|
98
|
+
`<rect>`/`<path>`/`<text>`/`<image>` markup with
|
|
99
|
+
`<linearGradient>`/`<radialGradient>`/`<filter>` defs. Figma's SVG importer
|
|
100
|
+
parses this into normal, editable layers (rect/path/gradients/filters stay
|
|
101
|
+
editable). This is a different artifact from `export-svg` above, whose
|
|
102
|
+
`foreignObject` wrapper Figma cannot import as vectors at all.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pnpm action export-design-as-figma-svg --designId <designId>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Optional args:
|
|
109
|
+
|
|
110
|
+
- `fileId` / `filename` — pick a specific screen (defaults to `index.html`).
|
|
111
|
+
- `nodeId` — scope the export to one selected element's subtree via its
|
|
112
|
+
`data-agent-native-node-id`, instead of the whole screen.
|
|
113
|
+
- `embedImages` (default `true`) — fetch and inline `http(s)` image sources
|
|
114
|
+
and background-images as `data:` URIs, so the SVG is self-contained for
|
|
115
|
+
clipboard paste. Set `false` to keep absolute URLs instead.
|
|
116
|
+
|
|
117
|
+
Returns `{ svg, filename, report, filePath? }`. `report` classifies every
|
|
118
|
+
element as `vectorized`, `approximated` (mapped with a documented caveat —
|
|
119
|
+
e.g. a non-square gradient angle, a non-uniform border, a radial gradient's
|
|
120
|
+
shape/position), `rasterized` (video/canvas/iframe content, and any element
|
|
121
|
+
with `backdrop-filter`, which SVG cannot express — embedded as a cropped
|
|
122
|
+
screenshot instead), or `omitted`. If no headless Chromium binary is
|
|
123
|
+
available in the current environment (expected in hosted/serverless
|
|
124
|
+
deploys), the action returns `{ ok: false, reason }` instead of throwing —
|
|
125
|
+
fall back to `export-svg` or `export-html`.
|
|
126
|
+
|
|
127
|
+
**Vectorized-text caveat**: Figma converts every imported SVG `<text>`
|
|
128
|
+
element to outlined vector paths on paste/drag-import. The exported
|
|
129
|
+
geometry is pixel-exact, but text pasted from this export is no longer
|
|
130
|
+
live, editable type in Figma — it's outlines, the same way any other
|
|
131
|
+
SVG-authoring tool's text becomes outlines on import. This is a Figma
|
|
132
|
+
import limitation, not a defect in the export; the report's
|
|
133
|
+
`vectorizedTextCaveat` field carries this note for the agent/user.
|
|
134
|
+
|
|
135
|
+
**Getting it into Figma**: two supported paths —
|
|
136
|
+
|
|
137
|
+
1. **Copy, then paste into Figma.** In the editor, right-click a selected
|
|
138
|
+
element or the canvas and choose **Copy as SVG** (Copy/Paste as ▸ Copy as
|
|
139
|
+
SVG). This writes the SVG markup to the system clipboard as `text/plain`
|
|
140
|
+
(the MIME Figma's own paste handler reads for "paste as vector shapes")
|
|
141
|
+
plus `image/svg+xml` as a secondary representation. Paste directly into a
|
|
142
|
+
Figma canvas.
|
|
143
|
+
2. **Download, then drag-import.** Figma's file browser also accepts a
|
|
144
|
+
plain `.svg` file dropped/imported directly — save the `svg` string
|
|
145
|
+
returned by the action to a `.svg` file and drag it into a Figma page the
|
|
146
|
+
same way you'd import any other SVG asset.
|
|
147
|
+
|
|
91
148
|
## Coding Handoff
|
|
92
149
|
|
|
93
150
|
When a user wants to convert an Alpine.js + Tailwind prototype into production
|
|
@@ -208,6 +208,17 @@ the connected app's text/code files through the bridge
|
|
|
208
208
|
- Saves are conflict-checked against the file's on-disk version — a file that
|
|
209
209
|
changed since it was read fails with a version conflict instead of being
|
|
210
210
|
overwritten.
|
|
211
|
+
- React/TSX canvas edits use build/debug provenance to locate the responsible
|
|
212
|
+
source, but structural meaning belongs to the coding agent. Do not apply a
|
|
213
|
+
generic AST reparent/group/ungroup transform. Hand off the exact subject and
|
|
214
|
+
target source anchors plus their runtime relationship; repeated `.map()`
|
|
215
|
+
instances, shared components, dynamic expressions, and cross-file edits
|
|
216
|
+
always require semantic inspection.
|
|
217
|
+
- For every semantic React write, read the file first, pass that exact
|
|
218
|
+
`versionHash` to `write-local-file` with `requireExpectedVersionHash: true`,
|
|
219
|
+
re-read and re-plan if it conflicts, and
|
|
220
|
+
verify the resulting HMR/runtime state before treating the preview as saved.
|
|
221
|
+
Human write consent remains mandatory and cannot be granted by an agent.
|
|
211
222
|
|
|
212
223
|
## Verification
|
|
213
224
|
|
|
@@ -67,6 +67,17 @@ patterns live in `.agents/skills/`.
|
|
|
67
67
|
or pass it as an action parameter. Figma styles and variables are design-system
|
|
68
68
|
inputs, not draggable media assets; route full file/design-system extraction
|
|
69
69
|
through Builder-backed indexing.
|
|
70
|
+
- To import a Figma frame/screen as a real, editable Design screen (not a
|
|
71
|
+
rendered image), use `import-figma-frame` with a `figmaUrl` (or
|
|
72
|
+
`fileKey`/`nodeId`) — it maps position, auto-layout, text, fills/gradients,
|
|
73
|
+
strokes, corner radii, effects, opacity, and blend modes pixel-accurately,
|
|
74
|
+
falling back to an exact PNG only for vector networks/boolean ops/unsupported
|
|
75
|
+
node types, and saves the result as a new screen. Read the returned
|
|
76
|
+
`fidelityReport` (`approximated`, `imageFallbacks`) back to the user when
|
|
77
|
+
non-trivial. Use `get-figma-styles` for a file's published style names (not
|
|
78
|
+
the Enterprise Variables API; full token extraction still routes through
|
|
79
|
+
Builder-backed indexing). See the `design-systems` skill's "Import from
|
|
80
|
+
Figma" section.
|
|
70
81
|
- Use Alpine.js and Tailwind CDN for interactive prototypes. Prefer Alpine
|
|
71
82
|
directives over raw inline event handlers.
|
|
72
83
|
- Navigate between prototype screens with Alpine state (`x-show`), a
|
|
@@ -112,9 +123,14 @@ patterns live in `.agents/skills/`.
|
|
|
112
123
|
workflow.
|
|
113
124
|
- Persist useful work early: create/update the design and files as soon as a
|
|
114
125
|
coherent candidate exists, then iterate.
|
|
115
|
-
- For
|
|
116
|
-
design shell, call `show-design-questions
|
|
117
|
-
|
|
126
|
+
- For a brief or ambiguous _new_ design prompt, ask before generating:
|
|
127
|
+
create/open the design shell, call `show-design-questions` with a small
|
|
128
|
+
tailored set, stop while the main canvas shows the questions, then continue
|
|
129
|
+
from the user's answers. Skip asking when the prompt is already specific,
|
|
130
|
+
it's a tweak/edit to an existing design, the user already answered a
|
|
131
|
+
question set for this design and is now iterating, or they say "decide for
|
|
132
|
+
me"/"surprise me"/"just build it" — see the `design-generation` skill for
|
|
133
|
+
how to size and word the questions.
|
|
118
134
|
- For multiple screens/states, call `generate-screens` first. It opens the
|
|
119
135
|
infinite screen overview and returns target filenames plus `canvasFrame`
|
|
120
136
|
placements. Then call `generate-design` with those files and pass the matching
|
|
@@ -202,12 +218,27 @@ patterns live in `.agents/skills/`.
|
|
|
202
218
|
layers: text, classes, styles, attributes, source order, and small structural
|
|
203
219
|
changes. Use it for selected-element edits before falling back to full
|
|
204
220
|
`update-design` / `generate-design` rewrites.
|
|
221
|
+
- For localhost React/TSX screens, treat compiler/debug metadata (project-relative
|
|
222
|
+
source file, line, column, component, and runtime multiplicity) as evidence
|
|
223
|
+
for locating source, not as permission to run a generic AST transform.
|
|
224
|
+
Compiler tooling may verify an anchor, classify a literal edit, and validate
|
|
225
|
+
syntax. Reparenting, grouping/ungrouping, wrappers, dynamic expressions,
|
|
226
|
+
repeated `.map()` instances, shared components, and cross-file changes must
|
|
227
|
+
be handed to the coding agent with both runtime relationships and exact
|
|
228
|
+
source anchors so it can inspect the surrounding program semantics.
|
|
229
|
+
- A localhost React handoff must read each source file first, write with the
|
|
230
|
+
exact returned `versionHash` as `expectedVersionHash` with
|
|
231
|
+
`requireExpectedVersionHash: true`, re-read and re-plan on conflict, and leave the
|
|
232
|
+
optimistic canvas preview in place until the dev server/HMR confirms the
|
|
233
|
+
runtime result. Never report a semantic canvas change as persisted merely
|
|
234
|
+
because it was submitted to the coding agent.
|
|
205
235
|
- Prefer `data-agent-native-layer-name="Readable name"` on meaningful elements.
|
|
206
236
|
The projection uses it before semantic/text fallbacks, and layer renames should
|
|
207
237
|
persist by updating that attribute.
|
|
208
|
-
-
|
|
209
|
-
|
|
210
|
-
|
|
238
|
+
- Inline/Alpine screens continue to use deterministic HTML code-layer edits.
|
|
239
|
+
Localhost React/TSX screens use the semantic coding-agent handoff above;
|
|
240
|
+
deterministic direct React writes remain intentionally limited to narrowly
|
|
241
|
+
proven literal edits and never include generic structural transforms.
|
|
211
242
|
|
|
212
243
|
## Code Workspace
|
|
213
244
|
|
|
@@ -282,12 +313,16 @@ patterns live in `.agents/skills/`.
|
|
|
282
313
|
and live app captures. See the same skill section.
|
|
283
314
|
- **Components**: `create-component` promotes a selected element into a
|
|
284
315
|
recognised reusable component; `index-components` scans a design's HTML for
|
|
285
|
-
existing component annotations; `
|
|
316
|
+
existing component annotations; `list-design-components` scans all HTML
|
|
317
|
+
screens for swap targets; `get-component-details`,
|
|
286
318
|
`preview-component-prop-edit`, `apply-component-prop-edit`, and
|
|
287
319
|
`open-component-source` inspect, preview, persist, and navigate to a
|
|
288
|
-
component instance.
|
|
289
|
-
|
|
290
|
-
|
|
320
|
+
component instance. Use `go-to-main-component` to select the earliest known
|
|
321
|
+
instance, `swap-component-instance` to replace an inline/Alpine instance
|
|
322
|
+
while preserving same-named prop overrides, and
|
|
323
|
+
`detach-component-instance` to turn an instance into plain editable markup.
|
|
324
|
+
See the `design-generation` skill's "Component reuse" section — promote a
|
|
325
|
+
3+ times repeated pattern instead of inventing another near-duplicate.
|
|
291
326
|
|
|
292
327
|
## Full App Building
|
|
293
328
|
|