@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
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.92.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1ecce26: Surface missing LLM credentials and earlier stream errors as failed agent runs instead of successful completions.
|
|
8
|
+
|
|
9
|
+
## 0.92.11
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 4552931: Keep local React visual-edit previews hydrated by preserving Vite request metadata and response lengths through the bridge, and recover exact development source locations from React jsxDEV Fiber stacks.
|
|
14
|
+
- 4552931: Expose strict active-collaboration awareness reads so safety-critical sync flows can distinguish no open editor from presence-storage failures.
|
|
15
|
+
- 4552931: Add cancellation-safe `sendToAgentChatAndConfirm` delivery confirmation and its submit-result event contract so callers can preserve user work when a local chat message is rejected or times out, without allowing that timed-out message to arrive later.
|
|
16
|
+
- 4552931: Fix `.fig` and other binary files silently corrupting when uploaded through `index-design-system-with-builder`: `buildBuilderDesignSystemIndexFiles` always UTF-8-encoded file content even though `mimeTypeForBuilderDesignSystemFilename` already recognized `.fig` as binary (`application/octet-stream`). Add an optional per-file `encoding: "utf8" | "base64"` (defaults to `utf8`, unchanged for existing text-file callers) so binary files can be base64-encoded by the caller and decoded byte-exact here.
|
|
17
|
+
- 4552931: Prevent pre-seed collaborative editor updates from reaching autosave, and allow newer authoritative restores to reapply content previously emitted during mount while retaining stale-echo protection during active typing.
|
|
18
|
+
- 4552931: Prevent PR recap workflows from publishing screenshots of failed recap pages, and report SSR render failures through configured error monitoring.
|
|
19
|
+
- 4552931: Fix long agent-chat turns dying with a Netlify "508 Loop Detected" error after several server-driven continuation chunks: nested self-dispatch chains now break proactively before the platform's undocumented loop-protection limit, and a 508 that does occur is classified distinctly and deferred to the existing unclaimed-run sweep for recovery instead of failing the turn outright.
|
|
20
|
+
- 4552931: Recover background chat turns whose continuation handoff dispatch failed instead of failing them immediately: the pre-inserted successor run is left claimable so the unclaimed-run sweep can redispatch it (and the client poll defers to that sweep within a bound), backed by a backstop that still fails loud if the handoff never lands.
|
|
21
|
+
|
|
22
|
+
Operational note — terminal-reason change: when a continuation handoff exhausts its dispatch retry budget but the successor row exists, the run's `terminal_reason` is now `background_continuation_dispatch_deferred` (recoverable, awaiting sweep redispatch) instead of `background_continuation_dispatch_failed`. The old `background_continuation_dispatch_failed` reason is still emitted, but now only in the narrower case where the successor row itself could not be pre-inserted. Any dashboards, alerts, or audit queries matching `background_continuation_dispatch_failed` should add `background_continuation_dispatch_deferred` to keep covering this failure class.
|
|
23
|
+
|
|
24
|
+
- 4552931: Fix an awareness "storm" in `useCollaborativeDoc`: the shared collab connection's fast awareness-push path re-broadcast a client's own (unchanged) presence state whenever ANY remote participant's awareness changed, not just when the local user actually moved their cursor or updated their presence. With several people collaborating on the same document, every peer's cursor move caused every other connected client to also re-POST its own state, multiplying awareness traffic roughly quadratically with participant count. The fast-push listener now only fires on locally-originated awareness changes (`origin === "local"`), matching the equivalent guard already present in `usePresence`.
|
|
25
|
+
|
|
26
|
+
Also add a defensive size cap to the collab `recentEdits` ring (`appendRecentEdit`): descriptor strings (`quote`, `selector`, path entries) and the edit `label` are now truncated to 500 characters. The ring was already bounded in length, but an app forgetting to trim its own excerpt before publishing (e.g. passing a whole paragraph or document as `quote`) could otherwise push an oversized payload through the awareness fast-path broadcast and into the `_collab_awareness` SQL mirror.
|
|
27
|
+
|
|
28
|
+
- 4552931: Give the Design localhost bridge a per-boot `bridgeInstanceId`, exposed on `/health`, the `/live-edit-bridge` registration response, and the `/live-edit` "unknown bridge key" 409 (now carrying a machine-readable `code: "unknown-bridge-key"` and the echoed `bridgeKey`). This lets a client distinguish a bridge process restart — which silently empties the in-memory live-edit bridge script registry — from a genuine registration bug, instead of guessing from free-text error strings.
|
|
29
|
+
- 4552931: Fix a recurring `DataCloneError` console error when any embedded extension (Design's Tools/Extensions panel, or any other app using `EmbeddedExtension`) loads or its slot context updates. Slot contexts commonly carry live callback functions the host uses internally; `postMessage`'s structured clone algorithm throws on function-valued properties, so the context update silently never reached the extension iframe. Sanitize the context through a JSON round-trip (dropping functions) before posting it.
|
|
30
|
+
- 4552931: Harden local Design source writes with SHA-256 version checks, per-file serialization, atomic replacement, and repeated symlink containment validation.
|
|
31
|
+
|
|
3
32
|
## 0.92.10
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.12",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -136,6 +136,7 @@ import {
|
|
|
136
136
|
insertRun,
|
|
137
137
|
updateRunHeartbeat,
|
|
138
138
|
updateRunStatusIfRunning,
|
|
139
|
+
setRunError,
|
|
139
140
|
setRunTerminalReason,
|
|
140
141
|
claimBackgroundRun,
|
|
141
142
|
readBackgroundRunClaim,
|
|
@@ -4881,18 +4882,47 @@ export function shouldChainBackgroundContinuation(opts: {
|
|
|
4881
4882
|
export async function markBackgroundContinuationChunkTerminal(opts: {
|
|
4882
4883
|
runId: string;
|
|
4883
4884
|
continuationReason: AgentLoopContinuationReason;
|
|
4885
|
+
terminalEvent?: AgentChatEvent;
|
|
4884
4886
|
deps?: {
|
|
4885
4887
|
updateRunStatusIfRunning?: typeof updateRunStatusIfRunning;
|
|
4888
|
+
setRunError?: typeof setRunError;
|
|
4886
4889
|
setRunTerminalReason?: typeof setRunTerminalReason;
|
|
4887
4890
|
};
|
|
4888
4891
|
}): Promise<boolean> {
|
|
4889
4892
|
const updateStatus =
|
|
4890
4893
|
opts.deps?.updateRunStatusIfRunning ?? updateRunStatusIfRunning;
|
|
4894
|
+
const persistError = opts.deps?.setRunError ?? setRunError;
|
|
4891
4895
|
const setTerminalReason =
|
|
4892
4896
|
opts.deps?.setRunTerminalReason ?? setRunTerminalReason;
|
|
4893
|
-
const
|
|
4897
|
+
const terminalEvent = opts.terminalEvent;
|
|
4898
|
+
const isTerminalFailure =
|
|
4899
|
+
terminalEvent?.type === "error" ||
|
|
4900
|
+
terminalEvent?.type === "missing_api_key";
|
|
4901
|
+
const terminalReason =
|
|
4902
|
+
terminalEvent?.type === "error"
|
|
4903
|
+
? `error:${terminalEvent.errorCode || "unknown"}`
|
|
4904
|
+
: terminalEvent?.type === "missing_api_key"
|
|
4905
|
+
? "missing_api_key"
|
|
4906
|
+
: opts.continuationReason;
|
|
4907
|
+
const updated = await updateStatus(
|
|
4908
|
+
opts.runId,
|
|
4909
|
+
isTerminalFailure ? "errored" : "completed",
|
|
4910
|
+
);
|
|
4894
4911
|
if (updated) {
|
|
4895
|
-
await setTerminalReason(opts.runId,
|
|
4912
|
+
await setTerminalReason(opts.runId, terminalReason);
|
|
4913
|
+
if (terminalEvent?.type === "error") {
|
|
4914
|
+
await persistError(
|
|
4915
|
+
opts.runId,
|
|
4916
|
+
terminalEvent.errorCode,
|
|
4917
|
+
terminalEvent.details || terminalEvent.error,
|
|
4918
|
+
);
|
|
4919
|
+
} else if (terminalEvent?.type === "missing_api_key") {
|
|
4920
|
+
await persistError(
|
|
4921
|
+
opts.runId,
|
|
4922
|
+
LLM_MISSING_CREDENTIALS_ERROR_CODE,
|
|
4923
|
+
LLM_MISSING_CREDENTIALS_MESSAGE,
|
|
4924
|
+
);
|
|
4925
|
+
}
|
|
4896
4926
|
}
|
|
4897
4927
|
return updated;
|
|
4898
4928
|
}
|
|
@@ -5038,6 +5068,70 @@ export function resolveContinuationDispatchBudget(opts: {
|
|
|
5038
5068
|
};
|
|
5039
5069
|
}
|
|
5040
5070
|
|
|
5071
|
+
/**
|
|
5072
|
+
* True when a `fireInternalDispatch` failure is Netlify's Functions platform
|
|
5073
|
+
* loop-protection response (`HTTP 508 Loop Detected`), matched against the
|
|
5074
|
+
* exact message `self-dispatch.ts`'s `dispatchResponseError` constructs
|
|
5075
|
+
* (`Self-dispatch to ${path} returned HTTP ${res.status} ${res.statusText}...`).
|
|
5076
|
+
* Matches on the status code alone (not the reason phrase text) so it is
|
|
5077
|
+
* robust to any wording Netlify's edge puts in `statusText`.
|
|
5078
|
+
*
|
|
5079
|
+
* VERIFIED: production `agent_runs` diagnostics show exactly this failure mode
|
|
5080
|
+
* — 8 successful `chain_dispatch_sent` self-dispatches followed by a 9th/10th
|
|
5081
|
+
* that dies with `HTTP 508 Loop Detected`, terminal reason
|
|
5082
|
+
* `background_continuation_dispatch_failed`. UNVERIFIED (Netlify does not
|
|
5083
|
+
* document the mechanism — checked the Functions overview, Functions API
|
|
5084
|
+
* reference, Background Functions overview, Status Codes reference, and
|
|
5085
|
+
* Request Chain troubleshooting docs, none mention it): the ONLY public
|
|
5086
|
+
* confirmation is a Netlify staff forum reply — "we prevent multiple
|
|
5087
|
+
* executions after one-another as that's a 'loop' ... I believe we enforce
|
|
5088
|
+
* this after 9 or 10 self-invocations"
|
|
5089
|
+
* (https://answers.netlify.com/t/self-invoke-background-function-via-post-requests/146012)
|
|
5090
|
+
* — which also confirms Background Functions do NOT escape the limit (the
|
|
5091
|
+
* reporter's case was already a `-background` function self-invoking). See
|
|
5092
|
+
* `MAX_NESTED_SELF_DISPATCH_DEPTH` for how this classification is used.
|
|
5093
|
+
*/
|
|
5094
|
+
export function isLoopProtectionDispatchError(err: unknown): boolean {
|
|
5095
|
+
if (!(err instanceof Error)) return false;
|
|
5096
|
+
return /\bHTTP\s*508\b/i.test(err.message);
|
|
5097
|
+
}
|
|
5098
|
+
|
|
5099
|
+
/**
|
|
5100
|
+
* Conservative safety margin on NESTED self-dispatch chaining — a
|
|
5101
|
+
* continuation dispatched directly from within the live invocation that is
|
|
5102
|
+
* about to finish, as opposed to being picked up later by the
|
|
5103
|
+
* unclaimed-background-run sweep (`agent-chat-plugin.ts`), which fires its
|
|
5104
|
+
* redispatch from an unrelated, timer-driven invocation rather than from
|
|
5105
|
+
* inside the chain's own execution.
|
|
5106
|
+
*
|
|
5107
|
+
* Netlify's loop-protection ceiling is undocumented and platform-reported
|
|
5108
|
+
* only approximately ("I believe... 9 or 10" — see
|
|
5109
|
+
* `isLoopProtectionDispatchError`), so hard-coding that exact number here
|
|
5110
|
+
* would be pinning behavior to a number Netlify itself won't commit to, and
|
|
5111
|
+
* production evidence shows it can trigger by the 9th self-dispatch. Rather
|
|
5112
|
+
* than only reacting after triggering that undocumented limit,
|
|
5113
|
+
* `chainServerDrivenContinuation` proactively hands a chunk to the sweep once
|
|
5114
|
+
* `backgroundContinuationCount` (nested hops since the last chain break)
|
|
5115
|
+
* reaches this value — comfortably below the observed ~9-10 failure point —
|
|
5116
|
+
* instead of attempting another nested dispatch. This is the SAME deferred-
|
|
5117
|
+
* recovery path already used when a dispatch fails outright: the row is left
|
|
5118
|
+
* `status='running', dispatch_mode='background'` for the sweep to redispatch,
|
|
5119
|
+
* never silently dropped.
|
|
5120
|
+
*
|
|
5121
|
+
* The sweep's redispatch marker intentionally omits `continuationCount` (see
|
|
5122
|
+
* the "Unclaimed background-run sweep" in `agent-chat-plugin.ts`), so a
|
|
5123
|
+
* sweep-recovered chunk's own `backgroundContinuationCount` resets to 0 —
|
|
5124
|
+
* this constant therefore bounds each NESTED segment between chain breaks,
|
|
5125
|
+
* not the whole turn. The TRUE ceiling on total turn length is unaffected by
|
|
5126
|
+
* that reset: it is the durable per-turn SQL ledger (`countRunsForTurn`,
|
|
5127
|
+
* checked above in this function) plus `MAX_BACKGROUND_RUN_CONTINUATIONS` —
|
|
5128
|
+
* both counted independently of this in-marker value — so a legitimately
|
|
5129
|
+
* long turn keeps making progress in bounded nested segments, each recovered
|
|
5130
|
+
* by the sweep, until it genuinely exhausts the intentional overall budget
|
|
5131
|
+
* and fails loud with `turn_continuation_budget_exhausted`.
|
|
5132
|
+
*/
|
|
5133
|
+
export const MAX_NESTED_SELF_DISPATCH_DEPTH = 6;
|
|
5134
|
+
|
|
5041
5135
|
/**
|
|
5042
5136
|
* Server-driven continuation handoff for a chunk that hit its soft-timeout
|
|
5043
5137
|
* boundary still unfinished: mint the next chunk's runId, PRE-INSERT its run
|
|
@@ -5046,12 +5140,26 @@ export function resolveContinuationDispatchBudget(opts: {
|
|
|
5046
5140
|
* `_process-run` self-dispatch carrying ids only (the body is persisted on
|
|
5047
5141
|
* the row as `dispatch_payload`), fully AWAIT the dispatch acknowledgment
|
|
5048
5142
|
* with retries, and mark this chunk terminal only after the handoff landed.
|
|
5049
|
-
* On failure
|
|
5050
|
-
*
|
|
5051
|
-
*
|
|
5052
|
-
* the
|
|
5053
|
-
*
|
|
5054
|
-
*
|
|
5143
|
+
* On failure this chunk always goes terminal loudly (diag stage + terminal
|
|
5144
|
+
* reason recorded — never a silent loss), but the successor row's fate
|
|
5145
|
+
* depends on WHY the dispatch failed:
|
|
5146
|
+
* - the pre-insert itself failed (no successor row exists) — nothing for a
|
|
5147
|
+
* sweep to find, so this is unrecoverable: fail loud immediately with
|
|
5148
|
+
* `background_continuation_dispatch_failed`.
|
|
5149
|
+
* - every dispatch attempt failed but the successor row DOES exist with its
|
|
5150
|
+
* `dispatch_payload` intact — this is RECOVERABLE: the row is left alone
|
|
5151
|
+
* (`status='running', dispatch_mode='background'`) instead of being
|
|
5152
|
+
* errored, so the unclaimed-background-run sweep in `agent-chat-plugin.ts`
|
|
5153
|
+
* can redispatch it once `UNCLAIMED_BACKGROUND_RUN_GRACE_MS` has passed.
|
|
5154
|
+
* This chunk is flipped to errored with the distinct, honest
|
|
5155
|
+
* `background_continuation_dispatch_deferred` reason — the TURN is
|
|
5156
|
+
* deferred, not dead. The sweep still bounds this by
|
|
5157
|
+
* `UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS`: past that it falls back
|
|
5158
|
+
* to the existing loud reap, so a genuinely dead handoff never hangs
|
|
5159
|
+
* silently forever. (For a FOREGROUND self-chain the client additionally
|
|
5160
|
+
* still receives the terminal `auto_continue` event — run-manager emits
|
|
5161
|
+
* it after this callback — so the existing client re-POST path is a
|
|
5162
|
+
* second, faster fallback alongside the sweep.)
|
|
5055
5163
|
*
|
|
5056
5164
|
* `chainViaDurableBackground` selects the dispatch target:
|
|
5057
5165
|
* - true → the durable-background worker chain (unchanged behavior): the
|
|
@@ -5244,9 +5352,23 @@ export async function chainServerDrivenContinuation(opts: {
|
|
|
5244
5352
|
};
|
|
5245
5353
|
let dispatched = false;
|
|
5246
5354
|
let lastDispatchErr: unknown;
|
|
5355
|
+
// Proactive nested-chain safety margin — see `MAX_NESTED_SELF_DISPATCH_DEPTH`.
|
|
5356
|
+
// Skip the nested dispatch attempt entirely once this segment's hop count
|
|
5357
|
+
// reaches the cap; a nested attempt at this depth is expected to trip
|
|
5358
|
+
// Netlify's loop protection, so there is nothing to gain by trying it and
|
|
5359
|
+
// burning this worker's remaining wall clock on a doomed call. Falls
|
|
5360
|
+
// straight into the same deferred-recovery path below as an exhausted
|
|
5361
|
+
// retry budget.
|
|
5362
|
+
const nestedDepthExceeded =
|
|
5363
|
+
opts.backgroundContinuationCount >= MAX_NESTED_SELF_DISPATCH_DEPTH;
|
|
5364
|
+
if (nestedDepthExceeded) {
|
|
5365
|
+
lastDispatchErr = new Error(
|
|
5366
|
+
`proactive nested-dispatch depth cap reached (backgroundContinuationCount=${opts.backgroundContinuationCount} >= MAX_NESTED_SELF_DISPATCH_DEPTH=${MAX_NESTED_SELF_DISPATCH_DEPTH}) — deferring to the unclaimed-background-run sweep instead of risking Netlify loop protection`,
|
|
5367
|
+
);
|
|
5368
|
+
}
|
|
5247
5369
|
for (
|
|
5248
5370
|
let attempt = 0;
|
|
5249
|
-
attempt < maxDispatchAttempts && !dispatched;
|
|
5371
|
+
!nestedDepthExceeded && attempt < maxDispatchAttempts && !dispatched;
|
|
5250
5372
|
attempt++
|
|
5251
5373
|
) {
|
|
5252
5374
|
try {
|
|
@@ -5313,25 +5435,99 @@ export async function chainServerDrivenContinuation(opts: {
|
|
|
5313
5435
|
`[agent-chat] background continuation dispatch attempt ${attempt + 1} failed:`,
|
|
5314
5436
|
dispatchErr instanceof Error ? dispatchErr.message : dispatchErr,
|
|
5315
5437
|
);
|
|
5438
|
+
// Netlify loop protection (see `isLoopProtectionDispatchError`) is a
|
|
5439
|
+
// property of this same live, nested call chain — retrying the exact
|
|
5440
|
+
// same nested self-dispatch within the next few seconds will not
|
|
5441
|
+
// change that, so further attempts are a guaranteed-doomed use of
|
|
5442
|
+
// this worker's remaining wall clock. Stop immediately (instead of
|
|
5443
|
+
// burning the full `maxDispatchAttempts` budget) and fall into the
|
|
5444
|
+
// same deferred-recovery path below, which hands the successor to the
|
|
5445
|
+
// sweep — a genuinely different, non-nested invocation.
|
|
5446
|
+
if (isLoopProtectionDispatchError(dispatchErr)) {
|
|
5447
|
+
break;
|
|
5448
|
+
}
|
|
5316
5449
|
}
|
|
5317
5450
|
}
|
|
5318
5451
|
if (!dispatched) {
|
|
5319
|
-
// The pre-inserted successor row would otherwise sit unclaimed until
|
|
5320
|
-
// the sweep reaps it — error it now so the failure is immediate and
|
|
5321
|
-
// truthful.
|
|
5322
5452
|
if (nextRowInserted) {
|
|
5323
|
-
|
|
5324
|
-
|
|
5453
|
+
// Classify WHY this handoff is being deferred — distinct, greppable
|
|
5454
|
+
// tags so production diagnostics (which is all that is readable from
|
|
5455
|
+
// a background worker) can tell "we proactively avoided Netlify loop
|
|
5456
|
+
// protection", "we hit loop protection and stopped retrying", and "a
|
|
5457
|
+
// generic transient dispatch failure exhausted its retry budget"
|
|
5458
|
+
// apart, instead of lumping every deferred handoff into one bucket.
|
|
5459
|
+
const deferralClassification = nestedDepthExceeded
|
|
5460
|
+
? "proactive_depth_cap"
|
|
5461
|
+
: isLoopProtectionDispatchError(lastDispatchErr)
|
|
5462
|
+
? "netlify_loop_protection"
|
|
5463
|
+
: "dispatch_budget_exhausted";
|
|
5464
|
+
// RECOVERABLE: the successor row already exists in SQL with its
|
|
5465
|
+
// rehydration payload (`dispatch_payload`) intact and is still
|
|
5466
|
+
// `status='running', dispatch_mode='background'` — exactly the state
|
|
5467
|
+
// the unclaimed-background-run sweep (`agent-chat-plugin.ts`) already
|
|
5468
|
+
// scans for. Do NOT error it here: leave it alone so the sweep can
|
|
5469
|
+
// redispatch it once `UNCLAIMED_BACKGROUND_RUN_GRACE_MS` has passed,
|
|
5470
|
+
// bounded by `UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS` before it
|
|
5471
|
+
// falls back to the existing loud reap
|
|
5472
|
+
// (`background_worker_never_started`) — so this is deferred, never a
|
|
5473
|
+
// silent hang. This chunk still goes terminal (its own soft-timeout
|
|
5474
|
+
// budget is genuinely spent), but with an honest reason: the TURN is
|
|
5475
|
+
// not dead, only this handoff attempt was.
|
|
5476
|
+
//
|
|
5477
|
+
// THREE-SITE INVARIANT (keep in lockstep — a future reader must not
|
|
5478
|
+
// "fix" one without the others): this deferral only survives because
|
|
5479
|
+
// the ~1s client poll in `getActiveRunForThreadAsync`
|
|
5480
|
+
// (run-manager.ts) ALSO skips `reapUnclaimedBackgroundRun` while the
|
|
5481
|
+
// successor is within `UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS`
|
|
5482
|
+
// (via `shouldRedispatchUnclaimedBackgroundRun`). Without that guard a
|
|
5483
|
+
// connected client would reap this row at the 25s grace, before the
|
|
5484
|
+
// ~2-min sweep, defeating the deferral. The sweep in agent-chat-plugin
|
|
5485
|
+
// is the recovery actor; run-manager is the guard; this is the
|
|
5486
|
+
// producer.
|
|
5487
|
+
await d
|
|
5488
|
+
.recordRunDiagnostic(
|
|
5489
|
+
nextRunId,
|
|
5490
|
+
RUN_DIAG_STAGE.workerThrew,
|
|
5491
|
+
`chain_dispatch_deferred[${deferralClassification}]: dispatch budget exhausted (${maxDispatchAttempts} attempts) awaiting unclaimed-run sweep redispatch; ${
|
|
5492
|
+
lastDispatchErr instanceof Error
|
|
5493
|
+
? lastDispatchErr.message
|
|
5494
|
+
: String(lastDispatchErr)
|
|
5495
|
+
}`,
|
|
5496
|
+
)
|
|
5497
|
+
.catch(() => {});
|
|
5498
|
+
await d
|
|
5499
|
+
.recordRunDiagnostic(
|
|
5500
|
+
runId,
|
|
5501
|
+
RUN_DIAG_STAGE.workerThrew,
|
|
5502
|
+
`chain_dispatch_deferred[${deferralClassification}] nextRunId=${nextRunId} ${
|
|
5503
|
+
lastDispatchErr instanceof Error
|
|
5504
|
+
? lastDispatchErr.message
|
|
5505
|
+
: String(lastDispatchErr)
|
|
5506
|
+
}`,
|
|
5507
|
+
)
|
|
5508
|
+
.catch(() => {});
|
|
5509
|
+
console.error(
|
|
5510
|
+
`[agent-chat] background continuation dispatch deferred (${deferralClassification}); leaving the pre-inserted successor for the unclaimed-run sweep to redispatch:`,
|
|
5511
|
+
lastDispatchErr instanceof Error
|
|
5512
|
+
? lastDispatchErr.message
|
|
5513
|
+
: lastDispatchErr,
|
|
5514
|
+
);
|
|
5515
|
+
const statusUpdated = await d
|
|
5516
|
+
.updateRunStatusIfRunning(runId, "errored")
|
|
5325
5517
|
.catch(() => false);
|
|
5326
|
-
if (
|
|
5518
|
+
if (statusUpdated) {
|
|
5327
5519
|
await d
|
|
5328
5520
|
.setRunTerminalReason(
|
|
5329
|
-
|
|
5330
|
-
"
|
|
5521
|
+
runId,
|
|
5522
|
+
"background_continuation_dispatch_deferred",
|
|
5331
5523
|
)
|
|
5332
5524
|
.catch(() => {});
|
|
5333
5525
|
}
|
|
5526
|
+
return;
|
|
5334
5527
|
}
|
|
5528
|
+
// No successor row exists at all (the pre-insert itself failed) — there
|
|
5529
|
+
// is nothing for the sweep to find and recover, so this really is
|
|
5530
|
+
// fatal. Fail loud immediately via the shared catch block below.
|
|
5335
5531
|
throw lastDispatchErr instanceof Error
|
|
5336
5532
|
? lastDispatchErr
|
|
5337
5533
|
: new Error(String(lastDispatchErr));
|
|
@@ -5347,6 +5543,7 @@ export async function chainServerDrivenContinuation(opts: {
|
|
|
5347
5543
|
.markBackgroundContinuationChunkTerminal({
|
|
5348
5544
|
runId,
|
|
5349
5545
|
continuationReason,
|
|
5546
|
+
terminalEvent: run.events.at(-1)?.event,
|
|
5350
5547
|
})
|
|
5351
5548
|
.catch(() => {});
|
|
5352
5549
|
} catch (chainErr) {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { captureError } from "../server/capture-error.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
isLlmCredentialError,
|
|
4
|
+
LLM_MISSING_CREDENTIALS_ERROR_CODE,
|
|
5
|
+
LLM_MISSING_CREDENTIALS_MESSAGE,
|
|
6
|
+
} from "./engine/credential-errors.js";
|
|
3
7
|
import { EngineError } from "./engine/types.js";
|
|
4
8
|
import {
|
|
5
9
|
insertRun,
|
|
@@ -16,6 +20,7 @@ import {
|
|
|
16
20
|
bumpRunProgress,
|
|
17
21
|
reapIfStale,
|
|
18
22
|
reapUnclaimedBackgroundRun,
|
|
23
|
+
shouldRedispatchUnclaimedBackgroundRun,
|
|
19
24
|
reconcileTerminalRunFromEvents,
|
|
20
25
|
ensureTerminalRunEvent,
|
|
21
26
|
getLastTerminalRunEvent,
|
|
@@ -376,6 +381,10 @@ function isTerminalRunEvent(event: AgentChatEvent): boolean {
|
|
|
376
381
|
);
|
|
377
382
|
}
|
|
378
383
|
|
|
384
|
+
function terminalEventForcesErroredStatus(event: AgentChatEvent | null) {
|
|
385
|
+
return event?.type === "error" || event?.type === "missing_api_key";
|
|
386
|
+
}
|
|
387
|
+
|
|
379
388
|
function terminalReasonForRun(
|
|
380
389
|
finalStatus: "completed" | "errored" | "aborted",
|
|
381
390
|
terminalEvent: AgentChatEvent | null,
|
|
@@ -898,14 +907,27 @@ export function startRun(
|
|
|
898
907
|
// /runs/active check while we wait for SQL writes to land.
|
|
899
908
|
let completionError: unknown = null;
|
|
900
909
|
let terminalPersistenceError: unknown = null;
|
|
910
|
+
const terminalEvent = pendingTerminalEvent?.event ?? null;
|
|
901
911
|
if (
|
|
902
912
|
onComplete &&
|
|
903
913
|
!(run.status === "aborted" && run.abortReason === "no_progress")
|
|
904
914
|
) {
|
|
905
915
|
try {
|
|
906
|
-
const
|
|
907
|
-
|
|
908
|
-
|
|
916
|
+
const completionStatus =
|
|
917
|
+
run.status !== "aborted" &&
|
|
918
|
+
terminalEventForcesErroredStatus(terminalEvent)
|
|
919
|
+
? "errored"
|
|
920
|
+
: run.status;
|
|
921
|
+
const completionRun: ActiveRun =
|
|
922
|
+
pendingTerminalEvent || completionStatus !== run.status
|
|
923
|
+
? {
|
|
924
|
+
...run,
|
|
925
|
+
status: completionStatus,
|
|
926
|
+
events: pendingTerminalEvent
|
|
927
|
+
? [...run.events, pendingTerminalEvent]
|
|
928
|
+
: run.events,
|
|
929
|
+
}
|
|
930
|
+
: run;
|
|
909
931
|
await onComplete(completionRun);
|
|
910
932
|
} catch (err) {
|
|
911
933
|
completionError = err;
|
|
@@ -923,12 +945,14 @@ export function startRun(
|
|
|
923
945
|
const finalStatus =
|
|
924
946
|
run.status === "aborted"
|
|
925
947
|
? "aborted"
|
|
926
|
-
: run.status === "errored" ||
|
|
948
|
+
: run.status === "errored" ||
|
|
949
|
+
completionError ||
|
|
950
|
+
terminalEventForcesErroredStatus(terminalEvent)
|
|
927
951
|
? "errored"
|
|
928
952
|
: "completed";
|
|
929
953
|
const terminalReason = terminalReasonForRun(
|
|
930
954
|
finalStatus,
|
|
931
|
-
|
|
955
|
+
terminalEvent,
|
|
932
956
|
run.abortReason,
|
|
933
957
|
completionError,
|
|
934
958
|
);
|
|
@@ -952,7 +976,8 @@ export function startRun(
|
|
|
952
976
|
const terminalEvent: AgentChatEvent =
|
|
953
977
|
finalStatus === "completed"
|
|
954
978
|
? (pendingTerminalEvent?.event ?? { type: "done" })
|
|
955
|
-
: pendingTerminalEvent?.event.type === "error"
|
|
979
|
+
: pendingTerminalEvent?.event.type === "error" ||
|
|
980
|
+
pendingTerminalEvent?.event.type === "missing_api_key"
|
|
956
981
|
? pendingTerminalEvent.event
|
|
957
982
|
: pendingTerminalEvent?.event.type === "auto_continue"
|
|
958
983
|
? // The run was checkpointed at a soft-timeout/loop boundary and
|
|
@@ -1029,14 +1054,21 @@ export function startRun(
|
|
|
1029
1054
|
if (finalStatus === "errored") {
|
|
1030
1055
|
let errorCode: string | undefined;
|
|
1031
1056
|
let errorDetail: string | undefined;
|
|
1032
|
-
|
|
1033
|
-
|
|
1057
|
+
const diagnosticEvents = pendingTerminalEvent
|
|
1058
|
+
? [...run.events, pendingTerminalEvent]
|
|
1059
|
+
: run.events;
|
|
1060
|
+
for (let i = diagnosticEvents.length - 1; i >= 0; i--) {
|
|
1061
|
+
const ev = diagnosticEvents[i].event as {
|
|
1034
1062
|
type: string;
|
|
1035
1063
|
error?: string;
|
|
1036
1064
|
errorCode?: string;
|
|
1037
1065
|
details?: string;
|
|
1038
1066
|
};
|
|
1039
|
-
if (ev.type === "
|
|
1067
|
+
if (ev.type === "missing_api_key") {
|
|
1068
|
+
errorCode = LLM_MISSING_CREDENTIALS_ERROR_CODE;
|
|
1069
|
+
errorDetail = LLM_MISSING_CREDENTIALS_MESSAGE;
|
|
1070
|
+
break;
|
|
1071
|
+
} else if (ev.type === "error") {
|
|
1040
1072
|
errorCode = ev.errorCode;
|
|
1041
1073
|
errorDetail = ev.error ?? ev.details;
|
|
1042
1074
|
break;
|
|
@@ -1469,10 +1501,36 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
|
|
|
1469
1501
|
// past the tight grace means the bg-fn worker never started — a silent
|
|
1470
1502
|
// async-worker death that the 202-ack inline fallback can't catch. Reap it
|
|
1471
1503
|
// early and recoverably (background_worker_never_started) so the run no
|
|
1472
|
-
// longer hangs for the full 90s window
|
|
1473
|
-
//
|
|
1474
|
-
//
|
|
1475
|
-
|
|
1504
|
+
// longer hangs for the full 90s window. Only fires when there is provably
|
|
1505
|
+
// no live worker; a claimed/heartbeating run is left alone by the
|
|
1506
|
+
// conditional SQL.
|
|
1507
|
+
//
|
|
1508
|
+
// REDISPATCH-BOUND GUARD (must be kept in lockstep with the "Unclaimed
|
|
1509
|
+
// background-run sweep" in agent-chat-plugin.ts and with
|
|
1510
|
+
// chainServerDrivenContinuation's deferral in production-agent.ts — do NOT
|
|
1511
|
+
// remove this guard without reading those two sites):
|
|
1512
|
+
// `chainServerDrivenContinuation` now DEFERS a dispatch-failed successor
|
|
1513
|
+
// instead of erroring it — it leaves the row status='running',
|
|
1514
|
+
// dispatch_mode='background' with its dispatch_payload intact so the sweep
|
|
1515
|
+
// can silently redispatch it. This client poll runs every ~1s while a
|
|
1516
|
+
// client is connected, so without this guard it would reap that deferred
|
|
1517
|
+
// successor at the 25s unclaimed grace — long before the ~2-min sweep —
|
|
1518
|
+
// converting the intended SILENT server-side recovery into a user-visible
|
|
1519
|
+
// `background_worker_never_started` manual-retry error (that terminal
|
|
1520
|
+
// reason does NOT auto-continue in the client follow loop; only `stale_run`
|
|
1521
|
+
// does). While the successor is still inside its redispatch bound we skip
|
|
1522
|
+
// this reap and leave it for the sweep. The outer backstops still bound it:
|
|
1523
|
+
// `reapIfStale` below reaps a heartbeat-stale background row at 90s
|
|
1524
|
+
// (BACKGROUND_RUN_STALE_MS) to the recoverable `stale_run` — which the
|
|
1525
|
+
// follow loop AUTO-continues — and once the redispatch bound is exceeded
|
|
1526
|
+
// this reap fires loudly as before. So recovery stays automatic in the
|
|
1527
|
+
// common case and loud failure is only moved later, never removed.
|
|
1528
|
+
if (
|
|
1529
|
+
sqlRun.dispatchMode === "background" &&
|
|
1530
|
+
!shouldRedispatchUnclaimedBackgroundRun({
|
|
1531
|
+
startedAt: sqlRun.startedAt,
|
|
1532
|
+
})
|
|
1533
|
+
) {
|
|
1476
1534
|
const recovered = await reapUnclaimedBackgroundRun(sqlRun.id).catch(
|
|
1477
1535
|
() => false,
|
|
1478
1536
|
);
|