@agent-native/core 0.92.10 → 0.92.12
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 +214 -17
- package/corpus/core/src/agent/run-manager.ts +72 -14
- package/corpus/core/src/agent/run-store.ts +152 -27
- 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-adapter.ts +56 -12
- 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/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 +75 -9
- package/corpus/templates/clips/app/components/player/video-player.tsx +17 -12
- package/corpus/templates/clips/app/hooks/use-player-shortcuts.ts +1 -0
- 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/changelog/2026-07-10-fixed-copying-agent-responses-and-transcript-text-from-recor.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/_builder-cms-read-client.ts +82 -7
- package/corpus/templates/content/actions/_database-source-utils.ts +149 -30
- 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/add-content-database-source-field-property.ts +4 -7
- package/corpus/templates/content/actions/attach-content-database-source.ts +41 -17
- package/corpus/templates/content/actions/change-content-database-source-role.ts +46 -8
- 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/actions/suggest-source-join-key.ts +8 -1
- 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-builder-source-refreshes-now-keep-mapped-fields-such-as-topi.md +6 -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/content/shared/api.ts +1 -0
- 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 +82 -7
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +180 -17
- 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 +63 -14
- 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 +129 -22
- 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-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +48 -12
- package/dist/client/agent-chat-adapter.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/struct-routes.d.ts +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/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- 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
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe context handoff for React changes that require semantic source edits.
|
|
3
|
+
*
|
|
4
|
+
* This module deliberately does not transform JSX. Compiler/AST tooling may
|
|
5
|
+
* verify an anchor or validate syntax elsewhere, but reparenting, grouping,
|
|
6
|
+
* wrappers, conditional renders, and shared component changes belong to the
|
|
7
|
+
* coding agent, which can inspect the surrounding program before editing it.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type ReactSourceScope =
|
|
11
|
+
| "single-instance"
|
|
12
|
+
| "repeated-render"
|
|
13
|
+
| "shared-component-definition"
|
|
14
|
+
| "unknown";
|
|
15
|
+
|
|
16
|
+
/** Optional while an edit is only a live canvas preview. */
|
|
17
|
+
export interface ReactSourceAnchor {
|
|
18
|
+
id?: string;
|
|
19
|
+
relPath?: string;
|
|
20
|
+
sourceFile?: string;
|
|
21
|
+
line?: number;
|
|
22
|
+
column?: number;
|
|
23
|
+
component?: string;
|
|
24
|
+
runtimeMultiplicity?: number;
|
|
25
|
+
reason?: string;
|
|
26
|
+
scope?: ReactSourceScope;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ExactReactSourceAnchor {
|
|
30
|
+
id: string;
|
|
31
|
+
relPath: string;
|
|
32
|
+
sourceFile: string;
|
|
33
|
+
line: number;
|
|
34
|
+
column: number;
|
|
35
|
+
component?: string;
|
|
36
|
+
runtimeMultiplicity: number;
|
|
37
|
+
reason?: string;
|
|
38
|
+
scope: ReactSourceScope;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type ReactSemanticOperation =
|
|
42
|
+
| "move"
|
|
43
|
+
| "reparent"
|
|
44
|
+
| "group"
|
|
45
|
+
| "ungroup"
|
|
46
|
+
| "wrap"
|
|
47
|
+
| "unwrap"
|
|
48
|
+
| "insert"
|
|
49
|
+
| "remove"
|
|
50
|
+
| "auto-layout"
|
|
51
|
+
| "set-layer-state"
|
|
52
|
+
| "component-change";
|
|
53
|
+
|
|
54
|
+
export type ReactRuntimeRelationshipKind =
|
|
55
|
+
| "before"
|
|
56
|
+
| "after"
|
|
57
|
+
| "inside"
|
|
58
|
+
| "wrap"
|
|
59
|
+
| "unwrap"
|
|
60
|
+
| "remove"
|
|
61
|
+
| "style"
|
|
62
|
+
| "metadata";
|
|
63
|
+
|
|
64
|
+
export interface ReactRuntimeRelationship {
|
|
65
|
+
kind: ReactRuntimeRelationshipKind;
|
|
66
|
+
subjectAnchorIds: readonly string[];
|
|
67
|
+
targetAnchorId?: string;
|
|
68
|
+
screenId?: string;
|
|
69
|
+
sourceScreenId?: string;
|
|
70
|
+
targetScreenId?: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ReactSourceVersionHash {
|
|
75
|
+
relPath: string;
|
|
76
|
+
versionHash: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type DeterministicWritebackRejectionCode =
|
|
80
|
+
| "semantic-source-change"
|
|
81
|
+
| "repeated-runtime-render"
|
|
82
|
+
| "shared-component-scope"
|
|
83
|
+
| "dynamic-source-expression"
|
|
84
|
+
| "ambiguous-source-anchor";
|
|
85
|
+
|
|
86
|
+
export interface DeterministicWritebackRejection {
|
|
87
|
+
code: DeterministicWritebackRejectionCode;
|
|
88
|
+
reason: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface BuildReactSemanticHandoffInput {
|
|
92
|
+
operation: ReactSemanticOperation;
|
|
93
|
+
desiredChange: string;
|
|
94
|
+
sourceAnchors: readonly ReactSourceAnchor[];
|
|
95
|
+
runtimeRelationship: ReactRuntimeRelationship;
|
|
96
|
+
versionHashes?: readonly ReactSourceVersionHash[];
|
|
97
|
+
deterministicRejection?: DeterministicWritebackRejection;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ReactSemanticExecutionContract {
|
|
101
|
+
requiresHumanWriteConsent: true;
|
|
102
|
+
requiresReadBeforeWrite: true;
|
|
103
|
+
requiresExpectedVersionHash: true;
|
|
104
|
+
allowsBlindOverwrite: false;
|
|
105
|
+
allowsGenericAstStructureTransform: false;
|
|
106
|
+
preservePreviewUntilHmrConfirmation: true;
|
|
107
|
+
onVersionConflict: "re-read-and-replan";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface ReactSemanticHandoff {
|
|
111
|
+
version: 1;
|
|
112
|
+
executionMode: "coding-agent";
|
|
113
|
+
operation: ReactSemanticOperation;
|
|
114
|
+
desiredChange: string;
|
|
115
|
+
sourceAnchors: ExactReactSourceAnchor[];
|
|
116
|
+
runtimeRelationship: {
|
|
117
|
+
kind: ReactRuntimeRelationshipKind;
|
|
118
|
+
subjectAnchorIds: string[];
|
|
119
|
+
targetAnchorId?: string;
|
|
120
|
+
screenId?: string;
|
|
121
|
+
sourceScreenId?: string;
|
|
122
|
+
targetScreenId?: string;
|
|
123
|
+
description?: string;
|
|
124
|
+
};
|
|
125
|
+
versionHashes: ReactSourceVersionHash[];
|
|
126
|
+
deterministicWritebackRejection: DeterministicWritebackRejection;
|
|
127
|
+
executionContract: ReactSemanticExecutionContract;
|
|
128
|
+
instructions: string[];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export type ReactSemanticHandoffBuildFailureCode =
|
|
132
|
+
| "missing-source-provenance"
|
|
133
|
+
| "unsafe-source-path"
|
|
134
|
+
| "invalid-source-location"
|
|
135
|
+
| "duplicate-anchor-id"
|
|
136
|
+
| "invalid-runtime-relationship"
|
|
137
|
+
| "context-limit-exceeded";
|
|
138
|
+
|
|
139
|
+
export type ReactSemanticHandoffBuildResult =
|
|
140
|
+
| { ok: true; handoff: ReactSemanticHandoff }
|
|
141
|
+
| {
|
|
142
|
+
ok: false;
|
|
143
|
+
rejection: {
|
|
144
|
+
code: ReactSemanticHandoffBuildFailureCode;
|
|
145
|
+
reason: string;
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const MAX_SOURCE_ANCHORS = 8;
|
|
150
|
+
const MAX_VERSION_HASHES = 12;
|
|
151
|
+
const MAX_DESIRED_CHANGE_LENGTH = 2_000;
|
|
152
|
+
const MAX_REASON_LENGTH = 800;
|
|
153
|
+
const MAX_DESCRIPTION_LENGTH = 800;
|
|
154
|
+
const MAX_COMPONENT_LENGTH = 160;
|
|
155
|
+
const MAX_ID_LENGTH = 120;
|
|
156
|
+
const MAX_SCREEN_ID_LENGTH = 160;
|
|
157
|
+
|
|
158
|
+
export interface BuildRuntimeReactStructureMoveHandoffInput {
|
|
159
|
+
subjectAnchor: ReactSourceAnchor;
|
|
160
|
+
targetAnchor: ReactSourceAnchor;
|
|
161
|
+
placement: "before" | "after" | "inside";
|
|
162
|
+
sourceScreenId: string;
|
|
163
|
+
targetScreenId: string;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export type RuntimeReactLayerState = "locked" | "hidden";
|
|
167
|
+
|
|
168
|
+
export interface BuildRuntimeReactLayerStateHandoffInput {
|
|
169
|
+
subjectAnchor: ReactSourceAnchor;
|
|
170
|
+
screenId: string;
|
|
171
|
+
state: RuntimeReactLayerState;
|
|
172
|
+
enabled: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export type RuntimeStructureMoveExecutionMode =
|
|
176
|
+
| "source-edit"
|
|
177
|
+
| "screen-bridge"
|
|
178
|
+
| "semantic-handoff";
|
|
179
|
+
|
|
180
|
+
export function resolveRuntimeStructureMoveExecutionMode(input: {
|
|
181
|
+
subjectRuntimeOnly: boolean;
|
|
182
|
+
targetRuntimeOnly: boolean;
|
|
183
|
+
sourceScreenId: string;
|
|
184
|
+
targetScreenId: string;
|
|
185
|
+
}): RuntimeStructureMoveExecutionMode {
|
|
186
|
+
if (!input.subjectRuntimeOnly && !input.targetRuntimeOnly)
|
|
187
|
+
return "source-edit";
|
|
188
|
+
if (
|
|
189
|
+
input.subjectRuntimeOnly &&
|
|
190
|
+
input.targetRuntimeOnly &&
|
|
191
|
+
input.sourceScreenId === input.targetScreenId
|
|
192
|
+
) {
|
|
193
|
+
return "screen-bridge";
|
|
194
|
+
}
|
|
195
|
+
return "semantic-handoff";
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function bounded(
|
|
199
|
+
value: string | undefined,
|
|
200
|
+
maxLength: number,
|
|
201
|
+
): string | undefined {
|
|
202
|
+
const trimmed = value?.trim();
|
|
203
|
+
if (!trimmed) return undefined;
|
|
204
|
+
return trimmed.slice(0, maxLength);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function safeRelativePath(value: string | undefined): string | null {
|
|
208
|
+
const trimmed = value?.trim();
|
|
209
|
+
if (!trimmed || trimmed.includes("\0")) return null;
|
|
210
|
+
if (/^(?:[a-z]+:|\\\\|\/)/i.test(trimmed)) return null;
|
|
211
|
+
const normalized = trimmed.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
212
|
+
const parts = normalized.split("/");
|
|
213
|
+
if (
|
|
214
|
+
!normalized ||
|
|
215
|
+
parts.some((part) => part === "" || part === "." || part === "..")
|
|
216
|
+
) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
return normalized;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Bound an optional live-preview anchor for prompt serialization. Absolute
|
|
224
|
+
* Fiber paths are replaced by the bridge-safe relPath when available, or
|
|
225
|
+
* omitted when no safe project-relative path has been resolved yet.
|
|
226
|
+
*/
|
|
227
|
+
export function redactReactSourceAnchor(
|
|
228
|
+
anchor: ReactSourceAnchor | undefined,
|
|
229
|
+
): ReactSourceAnchor | undefined {
|
|
230
|
+
if (!anchor) return undefined;
|
|
231
|
+
const relPath = safeRelativePath(anchor.relPath);
|
|
232
|
+
const sourceFile = safeRelativePath(anchor.sourceFile);
|
|
233
|
+
const canonicalPath = relPath ?? sourceFile;
|
|
234
|
+
return {
|
|
235
|
+
...(bounded(anchor.id, MAX_ID_LENGTH)
|
|
236
|
+
? { id: bounded(anchor.id, MAX_ID_LENGTH) }
|
|
237
|
+
: {}),
|
|
238
|
+
...(canonicalPath
|
|
239
|
+
? {
|
|
240
|
+
relPath: canonicalPath,
|
|
241
|
+
sourceFile: sourceFile ?? canonicalPath,
|
|
242
|
+
}
|
|
243
|
+
: {}),
|
|
244
|
+
...(Number.isInteger(anchor.line) && (anchor.line ?? 0) > 0
|
|
245
|
+
? { line: anchor.line }
|
|
246
|
+
: {}),
|
|
247
|
+
...(Number.isInteger(anchor.column) && (anchor.column ?? 0) > 0
|
|
248
|
+
? { column: anchor.column }
|
|
249
|
+
: {}),
|
|
250
|
+
...(bounded(anchor.component, MAX_COMPONENT_LENGTH)
|
|
251
|
+
? { component: bounded(anchor.component, MAX_COMPONENT_LENGTH) }
|
|
252
|
+
: {}),
|
|
253
|
+
...(Number.isInteger(anchor.runtimeMultiplicity) &&
|
|
254
|
+
(anchor.runtimeMultiplicity ?? 0) > 0
|
|
255
|
+
? { runtimeMultiplicity: anchor.runtimeMultiplicity }
|
|
256
|
+
: {}),
|
|
257
|
+
...(bounded(anchor.reason, MAX_REASON_LENGTH)
|
|
258
|
+
? { reason: bounded(anchor.reason, MAX_REASON_LENGTH) }
|
|
259
|
+
: {}),
|
|
260
|
+
...(anchor.scope ? { scope: anchor.scope } : {}),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function anchorFailure(
|
|
265
|
+
code: ReactSemanticHandoffBuildFailureCode,
|
|
266
|
+
reason: string,
|
|
267
|
+
): ReactSemanticHandoffBuildResult {
|
|
268
|
+
return { ok: false, rejection: { code, reason } };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function exactAnchor(
|
|
272
|
+
anchor: ReactSourceAnchor,
|
|
273
|
+
index: number,
|
|
274
|
+
): ExactReactSourceAnchor | ReactSemanticHandoffBuildResult {
|
|
275
|
+
const relPath = safeRelativePath(anchor.relPath);
|
|
276
|
+
const sourceFile = safeRelativePath(anchor.sourceFile);
|
|
277
|
+
const canonicalPath = relPath ?? sourceFile;
|
|
278
|
+
if (!canonicalPath) {
|
|
279
|
+
if (anchor.relPath || anchor.sourceFile) {
|
|
280
|
+
return anchorFailure(
|
|
281
|
+
"unsafe-source-path",
|
|
282
|
+
`Source anchor ${index + 1} does not include a safe project-relative path.`,
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
return anchorFailure(
|
|
286
|
+
"missing-source-provenance",
|
|
287
|
+
`Source anchor ${index + 1} is missing file provenance.`,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
if (
|
|
291
|
+
!Number.isInteger(anchor.line) ||
|
|
292
|
+
!Number.isInteger(anchor.column) ||
|
|
293
|
+
(anchor.line ?? 0) < 1 ||
|
|
294
|
+
(anchor.column ?? 0) < 1
|
|
295
|
+
) {
|
|
296
|
+
return anchorFailure(
|
|
297
|
+
"invalid-source-location",
|
|
298
|
+
`Source anchor ${index + 1} requires positive line and column coordinates.`,
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
const id = bounded(anchor.id, MAX_ID_LENGTH) ?? `source-${index + 1}`;
|
|
302
|
+
return {
|
|
303
|
+
id,
|
|
304
|
+
relPath: canonicalPath,
|
|
305
|
+
// Never forward an absolute jsxDEV/Fiber path. The verified root-relative
|
|
306
|
+
// path is exact for the bridge and safe to include in an agent prompt.
|
|
307
|
+
sourceFile: sourceFile ?? canonicalPath,
|
|
308
|
+
line: anchor.line!,
|
|
309
|
+
column: anchor.column!,
|
|
310
|
+
...(bounded(anchor.component, MAX_COMPONENT_LENGTH)
|
|
311
|
+
? { component: bounded(anchor.component, MAX_COMPONENT_LENGTH) }
|
|
312
|
+
: {}),
|
|
313
|
+
runtimeMultiplicity:
|
|
314
|
+
Number.isInteger(anchor.runtimeMultiplicity) &&
|
|
315
|
+
(anchor.runtimeMultiplicity ?? 0) > 0
|
|
316
|
+
? anchor.runtimeMultiplicity!
|
|
317
|
+
: 1,
|
|
318
|
+
...(bounded(anchor.reason, MAX_REASON_LENGTH)
|
|
319
|
+
? { reason: bounded(anchor.reason, MAX_REASON_LENGTH) }
|
|
320
|
+
: {}),
|
|
321
|
+
scope: anchor.scope ?? "unknown",
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function inferredDeterministicRejection(
|
|
326
|
+
anchors: readonly ExactReactSourceAnchor[],
|
|
327
|
+
): DeterministicWritebackRejection {
|
|
328
|
+
if (
|
|
329
|
+
anchors.some((anchor) => anchor.scope === "shared-component-definition")
|
|
330
|
+
) {
|
|
331
|
+
return {
|
|
332
|
+
code: "shared-component-scope",
|
|
333
|
+
reason:
|
|
334
|
+
"The runtime node resolves to a shared component definition, so the coding agent must inspect call sites and confirm the intended instance scope.",
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
if (
|
|
338
|
+
anchors.some(
|
|
339
|
+
(anchor) =>
|
|
340
|
+
anchor.scope === "repeated-render" || anchor.runtimeMultiplicity > 1,
|
|
341
|
+
)
|
|
342
|
+
) {
|
|
343
|
+
return {
|
|
344
|
+
code: "repeated-runtime-render",
|
|
345
|
+
reason:
|
|
346
|
+
"More than one runtime node resolves to the same source anchor, so a deterministic per-instance source edit would be unsafe.",
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
code: "semantic-source-change",
|
|
351
|
+
reason:
|
|
352
|
+
"This operation changes React program structure and requires the coding agent to inspect component and control-flow semantics.",
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Build a bounded, path-redacted context packet for the coding agent.
|
|
358
|
+
* Validation failures never echo an unsafe path back to the caller.
|
|
359
|
+
*/
|
|
360
|
+
export function buildReactSemanticHandoff(
|
|
361
|
+
input: BuildReactSemanticHandoffInput,
|
|
362
|
+
): ReactSemanticHandoffBuildResult {
|
|
363
|
+
if (
|
|
364
|
+
input.sourceAnchors.length === 0 ||
|
|
365
|
+
input.sourceAnchors.length > MAX_SOURCE_ANCHORS ||
|
|
366
|
+
(input.versionHashes?.length ?? 0) > MAX_VERSION_HASHES
|
|
367
|
+
) {
|
|
368
|
+
return anchorFailure(
|
|
369
|
+
"context-limit-exceeded",
|
|
370
|
+
`Semantic handoff requires 1-${MAX_SOURCE_ANCHORS} anchors and at most ${MAX_VERSION_HASHES} version hashes.`,
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const sourceAnchors: ExactReactSourceAnchor[] = [];
|
|
375
|
+
for (const [index, inputAnchor] of input.sourceAnchors.entries()) {
|
|
376
|
+
const anchor = exactAnchor(inputAnchor, index);
|
|
377
|
+
if ("ok" in anchor) return anchor;
|
|
378
|
+
sourceAnchors.push(anchor);
|
|
379
|
+
}
|
|
380
|
+
const anchorIds = new Set(sourceAnchors.map((anchor) => anchor.id));
|
|
381
|
+
if (anchorIds.size !== sourceAnchors.length) {
|
|
382
|
+
return anchorFailure(
|
|
383
|
+
"duplicate-anchor-id",
|
|
384
|
+
"Every source anchor in a semantic handoff must have a unique id.",
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const subjectAnchorIds = input.runtimeRelationship.subjectAnchorIds.map(
|
|
389
|
+
(id) => bounded(id, MAX_ID_LENGTH) ?? "",
|
|
390
|
+
);
|
|
391
|
+
const targetAnchorId = bounded(
|
|
392
|
+
input.runtimeRelationship.targetAnchorId,
|
|
393
|
+
MAX_ID_LENGTH,
|
|
394
|
+
);
|
|
395
|
+
if (
|
|
396
|
+
subjectAnchorIds.length === 0 ||
|
|
397
|
+
subjectAnchorIds.some((id) => !id || !anchorIds.has(id)) ||
|
|
398
|
+
(targetAnchorId !== undefined && !anchorIds.has(targetAnchorId))
|
|
399
|
+
) {
|
|
400
|
+
return anchorFailure(
|
|
401
|
+
"invalid-runtime-relationship",
|
|
402
|
+
"Runtime relationships must reference ids present in the bounded source anchor list.",
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const versionHashes: ReactSourceVersionHash[] = [];
|
|
407
|
+
for (const entry of input.versionHashes ?? []) {
|
|
408
|
+
const relPath = safeRelativePath(entry.relPath);
|
|
409
|
+
if (!relPath) {
|
|
410
|
+
return anchorFailure(
|
|
411
|
+
"unsafe-source-path",
|
|
412
|
+
"A version hash entry does not include a safe project-relative path.",
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
versionHashes.push({
|
|
416
|
+
relPath,
|
|
417
|
+
versionHash: entry.versionHash.trim().slice(0, 256),
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const inferredRejection = inferredDeterministicRejection(sourceAnchors);
|
|
422
|
+
const requestedRejection = input.deterministicRejection;
|
|
423
|
+
const deterministicWritebackRejection = requestedRejection
|
|
424
|
+
? {
|
|
425
|
+
code: requestedRejection.code,
|
|
426
|
+
reason:
|
|
427
|
+
bounded(requestedRejection.reason, MAX_REASON_LENGTH) ??
|
|
428
|
+
inferredRejection.reason,
|
|
429
|
+
}
|
|
430
|
+
: inferredRejection;
|
|
431
|
+
|
|
432
|
+
return {
|
|
433
|
+
ok: true,
|
|
434
|
+
handoff: {
|
|
435
|
+
version: 1,
|
|
436
|
+
executionMode: "coding-agent",
|
|
437
|
+
operation: input.operation,
|
|
438
|
+
desiredChange:
|
|
439
|
+
bounded(input.desiredChange, MAX_DESIRED_CHANGE_LENGTH) ??
|
|
440
|
+
"Apply the described live canvas change to the React source.",
|
|
441
|
+
sourceAnchors,
|
|
442
|
+
runtimeRelationship: {
|
|
443
|
+
kind: input.runtimeRelationship.kind,
|
|
444
|
+
subjectAnchorIds,
|
|
445
|
+
...(targetAnchorId ? { targetAnchorId } : {}),
|
|
446
|
+
...(bounded(input.runtimeRelationship.screenId, MAX_SCREEN_ID_LENGTH)
|
|
447
|
+
? {
|
|
448
|
+
screenId: bounded(
|
|
449
|
+
input.runtimeRelationship.screenId,
|
|
450
|
+
MAX_SCREEN_ID_LENGTH,
|
|
451
|
+
),
|
|
452
|
+
}
|
|
453
|
+
: {}),
|
|
454
|
+
...(bounded(
|
|
455
|
+
input.runtimeRelationship.sourceScreenId,
|
|
456
|
+
MAX_SCREEN_ID_LENGTH,
|
|
457
|
+
)
|
|
458
|
+
? {
|
|
459
|
+
sourceScreenId: bounded(
|
|
460
|
+
input.runtimeRelationship.sourceScreenId,
|
|
461
|
+
MAX_SCREEN_ID_LENGTH,
|
|
462
|
+
),
|
|
463
|
+
}
|
|
464
|
+
: {}),
|
|
465
|
+
...(bounded(
|
|
466
|
+
input.runtimeRelationship.targetScreenId,
|
|
467
|
+
MAX_SCREEN_ID_LENGTH,
|
|
468
|
+
)
|
|
469
|
+
? {
|
|
470
|
+
targetScreenId: bounded(
|
|
471
|
+
input.runtimeRelationship.targetScreenId,
|
|
472
|
+
MAX_SCREEN_ID_LENGTH,
|
|
473
|
+
),
|
|
474
|
+
}
|
|
475
|
+
: {}),
|
|
476
|
+
...(bounded(
|
|
477
|
+
input.runtimeRelationship.description,
|
|
478
|
+
MAX_DESCRIPTION_LENGTH,
|
|
479
|
+
)
|
|
480
|
+
? {
|
|
481
|
+
description: bounded(
|
|
482
|
+
input.runtimeRelationship.description,
|
|
483
|
+
MAX_DESCRIPTION_LENGTH,
|
|
484
|
+
),
|
|
485
|
+
}
|
|
486
|
+
: {}),
|
|
487
|
+
},
|
|
488
|
+
versionHashes,
|
|
489
|
+
deterministicWritebackRejection,
|
|
490
|
+
executionContract: {
|
|
491
|
+
requiresHumanWriteConsent: true,
|
|
492
|
+
requiresReadBeforeWrite: true,
|
|
493
|
+
requiresExpectedVersionHash: true,
|
|
494
|
+
allowsBlindOverwrite: false,
|
|
495
|
+
allowsGenericAstStructureTransform: false,
|
|
496
|
+
preservePreviewUntilHmrConfirmation: true,
|
|
497
|
+
onVersionConflict: "re-read-and-replan",
|
|
498
|
+
},
|
|
499
|
+
instructions: [
|
|
500
|
+
"Read every target file and verify each source anchor against the surrounding React control flow before editing.",
|
|
501
|
+
"Use semantic source edits; do not apply a generic AST reparent, group, or wrapper transform.",
|
|
502
|
+
"Obtain human write consent and write through the local bridge with expectedVersionHash from the corresponding read and requireExpectedVersionHash: true.",
|
|
503
|
+
"If a version hash conflicts, re-read the source and re-plan instead of overwriting it.",
|
|
504
|
+
"Keep the live preview pending until HMR renders and confirms the intended runtime relationship.",
|
|
505
|
+
],
|
|
506
|
+
},
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/** Build the safe coding-agent packet for a runtime Layers-panel move that a
|
|
511
|
+
* screen-scoped StructureMove bridge cannot execute. Both runtime endpoints
|
|
512
|
+
* must already have exact compiler provenance; the generic builder rejects
|
|
513
|
+
* either missing/unsafe anchor rather than guessing from a selector. */
|
|
514
|
+
export function buildRuntimeReactStructureMoveHandoff(
|
|
515
|
+
input: BuildRuntimeReactStructureMoveHandoffInput,
|
|
516
|
+
): ReactSemanticHandoffBuildResult {
|
|
517
|
+
const sourceScreenId = bounded(input.sourceScreenId, MAX_SCREEN_ID_LENGTH);
|
|
518
|
+
const targetScreenId = bounded(input.targetScreenId, MAX_SCREEN_ID_LENGTH);
|
|
519
|
+
if (!sourceScreenId || !targetScreenId) {
|
|
520
|
+
return anchorFailure(
|
|
521
|
+
"invalid-runtime-relationship",
|
|
522
|
+
"Cross-screen runtime structure moves require exact source and target screen ids.",
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
const subjectAnchor = { ...input.subjectAnchor, id: "subject" };
|
|
526
|
+
const targetAnchor = { ...input.targetAnchor, id: "target" };
|
|
527
|
+
const operation = input.placement === "inside" ? "reparent" : "move";
|
|
528
|
+
return buildReactSemanticHandoff({
|
|
529
|
+
operation,
|
|
530
|
+
desiredChange:
|
|
531
|
+
input.placement === "inside"
|
|
532
|
+
? `Move the runtime React subject from screen "${sourceScreenId}" inside the exact target anchor in screen "${targetScreenId}" while preserving the intended visual order and behavior.`
|
|
533
|
+
: `Move the runtime React subject from screen "${sourceScreenId}" ${input.placement} the exact target anchor in screen "${targetScreenId}" while preserving the intended visual order and behavior.`,
|
|
534
|
+
sourceAnchors: [subjectAnchor, targetAnchor],
|
|
535
|
+
runtimeRelationship: {
|
|
536
|
+
kind: input.placement,
|
|
537
|
+
subjectAnchorIds: ["subject"],
|
|
538
|
+
targetAnchorId: "target",
|
|
539
|
+
// Keep the legacy singular field pointed at the destination while also
|
|
540
|
+
// carrying both endpoints explicitly for cross-screen execution.
|
|
541
|
+
screenId: targetScreenId,
|
|
542
|
+
sourceScreenId,
|
|
543
|
+
targetScreenId,
|
|
544
|
+
description: `Runtime React ${operation} from screen "${sourceScreenId}" to screen "${targetScreenId}" with placement "${input.placement}". Verify both exact source anchors and their surrounding control flow before editing either file.`,
|
|
545
|
+
},
|
|
546
|
+
versionHashes: [],
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** Build the safe coding-agent packet for a runtime-only layer state toggle.
|
|
551
|
+
* The exact JSX host element receives durable source metadata which survives
|
|
552
|
+
* HMR and is preserved by the runtime Layers snapshot. This is deliberately a
|
|
553
|
+
* semantic handoff: compiler provenance identifies the opening element, but no
|
|
554
|
+
* generic AST transform is authorized to mutate the source. */
|
|
555
|
+
export function buildRuntimeReactLayerStateHandoff(
|
|
556
|
+
input: BuildRuntimeReactLayerStateHandoffInput,
|
|
557
|
+
): ReactSemanticHandoffBuildResult {
|
|
558
|
+
const screenId = bounded(input.screenId, MAX_SCREEN_ID_LENGTH);
|
|
559
|
+
if (!screenId) {
|
|
560
|
+
return anchorFailure(
|
|
561
|
+
"invalid-runtime-relationship",
|
|
562
|
+
"Runtime layer state changes require an exact owning screen id.",
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const attributeName = `data-agent-native-${input.state}`;
|
|
567
|
+
const subjectAnchor = { ...input.subjectAnchor, id: "subject" };
|
|
568
|
+
const desiredChange = input.enabled
|
|
569
|
+
? `Set ${attributeName}="true" on the exact JSX host element for this runtime layer. Keep it as durable source metadata; do not replace it with a transient DOM mutation, CSS-only workaround, or wrapper.`
|
|
570
|
+
: `Remove the ${attributeName} attribute from the exact JSX host element for this runtime layer. Do not replace it with a transient DOM mutation, CSS-only workaround, or wrapper.`;
|
|
571
|
+
|
|
572
|
+
return buildReactSemanticHandoff({
|
|
573
|
+
operation: "set-layer-state",
|
|
574
|
+
desiredChange,
|
|
575
|
+
sourceAnchors: [subjectAnchor],
|
|
576
|
+
runtimeRelationship: {
|
|
577
|
+
kind: "metadata",
|
|
578
|
+
subjectAnchorIds: ["subject"],
|
|
579
|
+
screenId,
|
|
580
|
+
sourceScreenId: screenId,
|
|
581
|
+
targetScreenId: screenId,
|
|
582
|
+
description: `${input.enabled ? "Set" : "Clear"} runtime React layer state "${input.state}" using the durable ${attributeName} JSX attribute in screen "${screenId}".`,
|
|
583
|
+
},
|
|
584
|
+
versionHashes: [],
|
|
585
|
+
});
|
|
586
|
+
}
|