@agent-native/core 0.149.1 → 0.149.3
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/templates/analytics/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/analytics/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/analytics/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/analytics/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/analytics/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +2 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/analytics/AGENTS.md +25 -32
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +150 -46
- package/corpus/templates/analytics/app/global.css +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +37 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +32 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +2 -0
- package/corpus/templates/analytics/changelog/2026-08-10-dashboard-tables-can-be-copied-and-sorted-by-multiple-column.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/assets/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/assets/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/assets/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/assets/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/assets/AGENTS.md +6 -9
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/assets/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/assets/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/brain/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/brain/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/brain/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/brain/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/brain/AGENTS.md +5 -12
- package/corpus/templates/brain/app/global.css +1 -1
- package/corpus/templates/brain/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/brain/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/calendar/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/calendar/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/calendar/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/calendar/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/calendar/AGENTS.md +8 -9
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/chat/AGENTS.md +32 -80
- package/corpus/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/clips/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/clips/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/clips/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/clips/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/clips/AGENTS.md +25 -31
- package/corpus/templates/clips/changelog/2026-08-10-clips-desktop-sign-in-now-starts-with-magic-links-and-google.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.css +1 -0
- package/corpus/templates/clips/desktop/src/app.tsx +274 -137
- package/corpus/templates/clips/desktop/src/styles.css +35 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/content/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/content/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/content/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/content/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/content/AGENTS.md +5 -9
- package/corpus/templates/content/app/global.css +1 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/crm/AGENTS.md +7 -11
- package/corpus/templates/crm/app/global.css +1 -1
- package/corpus/templates/crm/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/crm/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/design/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/design/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/design/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/design/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +70 -3
- package/corpus/templates/design/AGENTS.md +13 -21
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +19 -2
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +115 -7
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +82 -7
- package/corpus/templates/design/app/components/design/design-trace.ts +120 -0
- package/corpus/templates/design/app/components/design/dnd-debug.ts +2 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +40 -26
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -1
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +12 -3
- package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +4 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +7 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -5
- package/corpus/templates/design/app/pages/DesignSystems.tsx +3 -2
- package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +100 -13
- package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/data-operations.ts +14 -0
- package/corpus/templates/design/changelog/2026-08-10-marquee-selecting-layers-far-down-a-tall-screen-now-selects-.md +6 -0
- package/corpus/templates/design/changelog/2026-08-10-the-frame-tool-draws-a-plain-frame-by-default-with-screen-av.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +27 -32
- package/corpus/templates/design/playwright.config.ts +3 -5
- package/corpus/templates/design/shared/breakpoint-media.ts +9 -2
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/dispatch/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/dispatch/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/dispatch/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/dispatch/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/dispatch/AGENTS.md +9 -16
- package/corpus/templates/dispatch/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/factory/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/factory/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/factory/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/factory/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/factory/AGENTS.md +10 -24
- package/corpus/templates/factory/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/forms/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/forms/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/forms/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/forms/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/forms/AGENTS.md +11 -17
- package/corpus/templates/forms/app/global.css +1 -0
- package/corpus/templates/forms/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/forms/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/macros/AGENTS.md +8 -8
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/mail/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/mail/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/mail/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/mail/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/mail/AGENTS.md +5 -6
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/plan/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/plan/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/plan/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/plan/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/plan/AGENTS.md +5 -14
- package/corpus/templates/plan/app/global.css +1 -0
- package/corpus/templates/plan/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/plan/changelog/2026-08-11-plan-no-longer-reloads-when-runtime-state-changes.md +6 -0
- package/corpus/templates/plan/server/ui-plan-html.ts +4 -1
- package/corpus/templates/plan/vite.config.ts +5 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/slides/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/slides/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/slides/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +2 -2
- package/corpus/templates/slides/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +6 -3
- package/corpus/templates/slides/.agents/skills/deck-management/SKILL.md +6 -1
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +3 -2
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +3 -0
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +3 -3
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/slides/AGENTS.md +33 -35
- package/corpus/templates/slides/actions/add-deck.ts +2 -0
- package/corpus/templates/slides/actions/add-slide.ts +15 -1
- package/corpus/templates/slides/actions/create-deck.ts +18 -6
- package/corpus/templates/slides/actions/get-deck-reference-context.ts +2 -2
- package/corpus/templates/slides/actions/get-deck.ts +83 -7
- package/corpus/templates/slides/actions/import-file.ts +2 -1
- package/corpus/templates/slides/actions/patch-deck.ts +165 -9
- package/corpus/templates/slides/actions/save-deck.ts +24 -1
- package/corpus/templates/slides/actions/update-slide.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +2 -2
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -23
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +2 -2
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +6 -6
- package/corpus/templates/slides/app/components/editor/AnimationsPanel.tsx +3 -3
- package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +4 -4
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +432 -668
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +296 -259
- package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +13 -1
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +56 -174
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +241 -116
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +42 -14
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +6 -12
- package/corpus/templates/slides/app/components/editor/editor-command-model.ts +35 -0
- package/corpus/templates/slides/app/components/layout/AgentWorkIndicator.tsx +1 -1
- package/corpus/templates/slides/app/components/layout/Layout.tsx +34 -35
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +8 -10
- package/corpus/templates/slides/app/components/layout/layout-route-policy.ts +2 -5
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +45 -40
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +63 -16
- package/corpus/templates/slides/app/context/DeckContext.tsx +2 -1
- package/corpus/templates/slides/app/global.css +76 -1
- package/corpus/templates/slides/app/hooks/use-generating-slide-preview.ts +25 -3
- package/corpus/templates/slides/app/i18n/en-US.ts +2 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +52 -23
- package/corpus/templates/slides/app/lib/recent-references.ts +23 -1
- package/corpus/templates/slides/app/lib/slide-animation-elements.ts +104 -3
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -33
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +2 -2
- package/corpus/templates/slides/app/pages/Index.tsx +315 -151
- package/corpus/templates/slides/app/root.tsx +43 -0
- package/corpus/templates/slides/changelog/2026-08-10-ai-editing-avatar-badge.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-generated-decks-keep-a-clear-human-readable-title.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-new-deck-creation-now-shows-progress-opens-the-editor-direct.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-presentation-reveals-now-follow-valid-targets.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-editing-controls-are-consolidated-into-one-focused-me.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-now-verify-and-restyle-every-imported-slide-in-one-pa.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-only-suggests-a-google-connection-for-relevant-reques.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-the-google-slides-import-option-is-now-labeled-slides.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-faster-slides-chat-deck-reads.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-chat-can-read-one-slide-without-loading-the-full-deck.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-clearly-indicate-when-an-ai-agent-is-editing-alongsid.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
- package/corpus/templates/slides/server/lib/validate-slide-animations.ts +163 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +8 -5
- package/corpus/templates/slides/shared/api.ts +47 -15
- package/corpus/templates/slides/shared/deck-title.ts +135 -0
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/tasks/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/tasks/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/tasks/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/tasks/.agents/skills/agent-watchdog/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/tasks/.agents/skills/efficient-fable/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/efficient-frontier/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/tasks/.agents/skills/plan-arbiter/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/plow-ahead/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/quick-recap/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/stay-within-limits/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/tasks/AGENTS.md +5 -20
- package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +4 -1
- package/dist/agent/engine/ai-sdk-engine.js +1 -1
- package/dist/agent/production-agent.d.ts +21 -1
- package/dist/agent/production-agent.js +505 -355
- package/dist/agent/run-manager.js +156 -14
- package/dist/agent/run-store.d.ts +11 -10
- package/dist/agent/run-store.js +17 -13
- package/dist/agent/tool-approval-store.d.ts +18 -0
- package/dist/agent/tool-approval-store.js +122 -0
- package/dist/agent/types.d.ts +1 -1
- package/dist/cli/code-agent-executor.js +11 -2
- package/dist/client/AgentPanel.js +31 -6
- package/dist/client/AssistantChat.d.ts +9 -4
- package/dist/client/AssistantChat.js +221 -149
- package/dist/client/active-run-state.d.ts +9 -1
- package/dist/client/active-run-state.js +34 -3
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat-adapter.d.ts +8 -0
- package/dist/client/agent-chat-adapter.js +125 -28
- package/dist/client/agent-chat.d.ts +1 -1
- package/dist/client/chat/markdown-renderer.js +14 -2
- package/dist/client/chat/message-components.d.ts +13 -3
- package/dist/client/chat/message-components.js +57 -52
- package/dist/client/chat/run-recovery.d.ts +1 -0
- package/dist/client/chat/run-recovery.js +8 -0
- package/dist/client/chat/tool-call-display.d.ts +5 -5
- package/dist/client/chat/tool-call-display.js +9 -212
- package/dist/client/chat-first/apps-rail.js +3 -3
- package/dist/client/chat-first/browser-pane.js +4 -1
- package/dist/client/chat-first/chat-history.d.ts +3 -1
- package/dist/client/chat-first/chat-history.js +7 -4
- package/dist/client/chat-first/surface-tabs.d.ts +1 -1
- package/dist/client/chat-first/surface-tabs.js +52 -41
- package/dist/client/chat-first/types.d.ts +3 -0
- package/dist/client/chat-first.d.ts +10 -0
- package/dist/client/chat-first.js +37 -2
- package/dist/client/components/ui/message-scroller.js +4 -1
- package/dist/client/i18n.js +3 -1
- package/dist/client/resources/McpConnectionSuggestion.js +9 -1
- package/dist/client/sse-event-processor.d.ts +4 -2
- package/dist/client/sse-event-processor.js +46 -6
- package/dist/client/use-chat-models.js +156 -80
- package/dist/client/use-run-stuck-detection.d.ts +2 -0
- package/dist/client/use-run-stuck-detection.js +85 -9
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/integrations/adapters/slack.d.ts +0 -4
- package/dist/integrations/adapters/slack.js +6 -30
- package/dist/integrations/catalog.js +1 -1
- package/dist/integrations/pending-tasks-store.d.ts +0 -8
- package/dist/integrations/pending-tasks-store.js +0 -21
- package/dist/integrations/slack-manifest.d.ts +2 -2
- package/dist/integrations/slack-manifest.js +0 -3
- package/dist/integrations/webhook-handler.js +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/scripts/docs/source-search.js +2 -2
- package/dist/server/agent-chat/framework-prompts.js +7 -2
- package/dist/server/agent-chat/prompt-resources.js +2 -2
- package/dist/server/agent-chat/skill-frontmatter.d.ts +31 -2
- package/dist/server/agent-chat/skill-frontmatter.js +41 -15
- package/dist/server/agent-chat-plugin.js +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agents-bundle.d.ts +16 -19
- package/dist/server/agents-bundle.js +19 -35
- package/dist/server/auth.js +262 -31
- package/dist/server/better-auth-instance.d.ts +1 -0
- package/dist/server/better-auth-instance.js +17 -2
- package/dist/server/onboarding-html.js +56 -9
- package/dist/server/prompts/framework-core-compact.d.ts +6 -1
- package/dist/server/prompts/framework-core-compact.js +12 -9
- package/dist/server/prompts/framework-core.d.ts +6 -1
- package/dist/server/prompts/framework-core.js +11 -9
- package/dist/server/prompts/index.d.ts +1 -1
- package/dist/server/prompts/index.js +1 -1
- package/dist/server/prompts/shared-rules.d.ts +15 -11
- package/dist/server/prompts/shared-rules.js +17 -13
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/reasoning-effort.d.ts +8 -8
- package/dist/shared/reasoning-effort.js +10 -10
- package/dist/shared/streaming-text-smoothing.js +41 -11
- package/dist/styles/agent-native.css +19 -32
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/chat/AGENTS.md +32 -80
- package/dist/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/default/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/headless/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
- package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
- package/dist/templates/workspace-core/AGENTS.md +7 -16
- package/docs/content/messaging.mdx +6 -7
- package/docs/content/template-chat.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/chat/AGENTS.md +32 -80
- package/src/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/default/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/headless/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/headless/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
- package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
- package/src/templates/workspace-core/AGENTS.md +7 -16
|
@@ -6,6 +6,22 @@ import { fetchBuilderStatus, fetchEnvironmentStatus, } from "./client-status-req
|
|
|
6
6
|
import { callAction } from "./use-action.js";
|
|
7
7
|
const DEFAULT_STORAGE_KEY = "agent-native:chat-models:selection";
|
|
8
8
|
export const CHAT_MODEL_SELECTION_CHANGED_EVENT = "agent-native:chat-model-selection-changed";
|
|
9
|
+
const MODEL_DISCOVERY_RETRY_DELAYS_MS = [250, 1_000];
|
|
10
|
+
async function fetchEngineCatalog() {
|
|
11
|
+
try {
|
|
12
|
+
const result = (await callAction("manage-agent-engine", { action: "list" }));
|
|
13
|
+
if (!result ||
|
|
14
|
+
typeof result !== "object" ||
|
|
15
|
+
!("engines" in result) ||
|
|
16
|
+
!Array.isArray(result.engines)) {
|
|
17
|
+
return { state: "unavailable" };
|
|
18
|
+
}
|
|
19
|
+
return { state: "available", value: result };
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return { state: "unavailable" };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
9
25
|
function readPersisted(key) {
|
|
10
26
|
if (!key || typeof window === "undefined")
|
|
11
27
|
return {};
|
|
@@ -50,6 +66,9 @@ export function useChatModels({ storageKey = DEFAULT_STORAGE_KEY, enabled = true
|
|
|
50
66
|
selectedEngine,
|
|
51
67
|
selectedEffort,
|
|
52
68
|
});
|
|
69
|
+
const mountedRef = useRef(true);
|
|
70
|
+
const refreshGenerationRef = useRef(0);
|
|
71
|
+
const retryTimerRef = useRef(null);
|
|
53
72
|
useEffect(() => {
|
|
54
73
|
selectionRef.current = {
|
|
55
74
|
selectedModel,
|
|
@@ -109,98 +128,155 @@ export function useChatModels({ storageKey = DEFAULT_STORAGE_KEY, enabled = true
|
|
|
109
128
|
const refreshEngines = useCallback(() => {
|
|
110
129
|
if (!enabled)
|
|
111
130
|
return;
|
|
131
|
+
refreshGenerationRef.current += 1;
|
|
132
|
+
const refreshGeneration = refreshGenerationRef.current;
|
|
133
|
+
if (retryTimerRef.current !== null) {
|
|
134
|
+
clearTimeout(retryTimerRef.current);
|
|
135
|
+
retryTimerRef.current = null;
|
|
136
|
+
}
|
|
112
137
|
setIsLoading(true);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
138
|
+
const isCurrentRefresh = () => mountedRef.current && refreshGenerationRef.current === refreshGeneration;
|
|
139
|
+
const finish = () => {
|
|
140
|
+
if (isCurrentRefresh())
|
|
141
|
+
setIsLoading(false);
|
|
142
|
+
};
|
|
143
|
+
function scheduleRetry(attempt) {
|
|
144
|
+
const delay = MODEL_DISCOVERY_RETRY_DELAYS_MS[attempt];
|
|
145
|
+
if (delay === undefined || !isCurrentRefresh())
|
|
146
|
+
return false;
|
|
147
|
+
retryTimerRef.current = setTimeout(() => {
|
|
148
|
+
retryTimerRef.current = null;
|
|
149
|
+
load(attempt + 1);
|
|
150
|
+
}, delay);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
function load(attempt) {
|
|
154
|
+
if (!isCurrentRefresh())
|
|
127
155
|
return;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
156
|
+
Promise.all([
|
|
157
|
+
fetchEngineCatalog(),
|
|
158
|
+
fetchEnvironmentStatus(),
|
|
159
|
+
fetchBuilderStatus(),
|
|
160
|
+
])
|
|
161
|
+
.then(([engineResult, envResult, builderResult]) => {
|
|
162
|
+
if (!isCurrentRefresh())
|
|
163
|
+
return;
|
|
164
|
+
if (engineResult.state !== "available" ||
|
|
165
|
+
envResult.state !== "available" ||
|
|
166
|
+
builderResult.state !== "available") {
|
|
167
|
+
if (scheduleRetry(attempt))
|
|
168
|
+
return;
|
|
169
|
+
if (engineResult.state !== "available") {
|
|
170
|
+
// Without a catalog the picker keeps an unvalidated DEFAULT_MODEL,
|
|
171
|
+
// which is indistinguishable from a real selection unless we say so.
|
|
172
|
+
console.warn("[agent-chat] engine list unavailable; model picker is showing an unvalidated default");
|
|
173
|
+
}
|
|
174
|
+
finish();
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const enginesData = engineResult.value;
|
|
178
|
+
const envKeys = envResult.value;
|
|
179
|
+
const builderStatus = builderResult.value;
|
|
180
|
+
const configuredKeys = new Set(envKeys.filter((k) => k.configured).map((k) => k.key));
|
|
181
|
+
const builderConnected = builderStatus?.configured === true;
|
|
182
|
+
const currentEngineName = enginesData.current?.engine;
|
|
183
|
+
const currentModel = enginesData.current?.model;
|
|
184
|
+
const groups = buildChatModelGroups({
|
|
185
|
+
engines: enginesData.engines,
|
|
186
|
+
configuredKeys,
|
|
187
|
+
builderConnected,
|
|
188
|
+
currentEngineName,
|
|
189
|
+
currentModel,
|
|
190
|
+
});
|
|
191
|
+
const nextDefaultModel = currentModel ?? DEFAULT_MODEL;
|
|
192
|
+
setAvailableModels(groups);
|
|
193
|
+
setDefaultModel(nextDefaultModel);
|
|
194
|
+
const selection = selectionRef.current;
|
|
195
|
+
// Default only to a CONFIGURED group, and to nothing when there is
|
|
196
|
+
// none. `DEFAULT_MODEL` is a builder-gateway id that no group carries
|
|
197
|
+
// unless Builder is connected, and unconfigured groups are kept in the
|
|
198
|
+
// list for their connect affordance — so both `?? DEFAULT_MODEL` and
|
|
199
|
+
// `?? groups[0]` yield a selection the app cannot route, which the
|
|
200
|
+
// server silently replaces with its own default. An empty selection
|
|
201
|
+
// hides the picker instead of showing a model that will not be used.
|
|
202
|
+
const configuredGroups = groups.filter((g) => g.configured);
|
|
203
|
+
const resolveRoutableSelection = () => {
|
|
204
|
+
const group = configuredGroups.find((g) => g.models.includes(nextDefaultModel)) ?? configuredGroups[0];
|
|
205
|
+
if (!group)
|
|
206
|
+
return null;
|
|
207
|
+
const model = group.models.find((m) => m === nextDefaultModel) ??
|
|
208
|
+
group.models[0];
|
|
209
|
+
if (!model)
|
|
210
|
+
return null;
|
|
211
|
+
return {
|
|
212
|
+
model,
|
|
213
|
+
engine: group.engine,
|
|
214
|
+
effort: resolveReasoningEffortSelection(model, selection.selectedEffort),
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
const applyFallback = (persist) => {
|
|
218
|
+
const next = resolveRoutableSelection();
|
|
219
|
+
setSelectedModel(next?.model ?? "");
|
|
220
|
+
setSelectedEngine(next?.engine ?? "");
|
|
221
|
+
if (next) {
|
|
222
|
+
setSelectedEffort(next.effort);
|
|
223
|
+
if (persist)
|
|
224
|
+
writePersisted(storageKey, next);
|
|
225
|
+
}
|
|
166
226
|
};
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
setSelectedEngine(next?.engine ?? "");
|
|
172
|
-
if (next) {
|
|
173
|
-
setSelectedEffort(next.effort);
|
|
174
|
-
if (persist)
|
|
175
|
-
writePersisted(storageKey, next);
|
|
227
|
+
if (!hasExplicitSelectionRef.current) {
|
|
228
|
+
applyFallback(false);
|
|
229
|
+
finish();
|
|
230
|
+
return;
|
|
176
231
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (selection.selectedEngine !== selectedGroup.engine) {
|
|
189
|
-
setSelectedEngine(selectedGroup.engine);
|
|
232
|
+
const selectedGroup = groups.find((group) => group.models.includes(selection.selectedModel) &&
|
|
233
|
+
(!selection.selectedEngine ||
|
|
234
|
+
group.engine === selection.selectedEngine));
|
|
235
|
+
if (selectedGroup) {
|
|
236
|
+
// Heal a selection stored without an engine (or with a stale one) so
|
|
237
|
+
// later submits carry the pair the catalog resolved.
|
|
238
|
+
if (selection.selectedEngine !== selectedGroup.engine) {
|
|
239
|
+
setSelectedEngine(selectedGroup.engine);
|
|
240
|
+
}
|
|
241
|
+
finish();
|
|
242
|
+
return;
|
|
190
243
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
244
|
+
applyFallback(true);
|
|
245
|
+
finish();
|
|
246
|
+
})
|
|
247
|
+
.catch(() => {
|
|
248
|
+
if (!isCurrentRefresh())
|
|
249
|
+
return;
|
|
250
|
+
if (!scheduleRetry(attempt))
|
|
251
|
+
finish();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
load(0);
|
|
197
255
|
}, [enabled, storageKey]);
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
mountedRef.current = true;
|
|
258
|
+
return () => {
|
|
259
|
+
mountedRef.current = false;
|
|
260
|
+
refreshGenerationRef.current += 1;
|
|
261
|
+
if (retryTimerRef.current !== null) {
|
|
262
|
+
clearTimeout(retryTimerRef.current);
|
|
263
|
+
retryTimerRef.current = null;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
}, []);
|
|
198
267
|
useEffect(() => {
|
|
199
268
|
if (!enabled) {
|
|
269
|
+
refreshGenerationRef.current += 1;
|
|
270
|
+
if (retryTimerRef.current !== null) {
|
|
271
|
+
clearTimeout(retryTimerRef.current);
|
|
272
|
+
retryTimerRef.current = null;
|
|
273
|
+
}
|
|
200
274
|
setIsLoading(false);
|
|
201
275
|
return;
|
|
202
276
|
}
|
|
203
277
|
refreshEngines();
|
|
278
|
+
window.addEventListener("agent-engine:configured-changed", refreshEngines);
|
|
279
|
+
return () => window.removeEventListener("agent-engine:configured-changed", refreshEngines);
|
|
204
280
|
}, [enabled, refreshEngines]);
|
|
205
281
|
return {
|
|
206
282
|
availableModels,
|
|
@@ -18,6 +18,8 @@ export interface RunStuckState {
|
|
|
18
18
|
lastProgressAt: number | null;
|
|
19
19
|
/** Milliseconds since `lastProgressAt`, or null. */
|
|
20
20
|
stuckSinceMs: number | null;
|
|
21
|
+
/** Last browser SSE sequence classified as real work progress, or null. */
|
|
22
|
+
lastProgressSeq: number | null;
|
|
21
23
|
/** Server timestamp (ms) of the last process-alive heartbeat. */
|
|
22
24
|
heartbeatAt: number | null;
|
|
23
25
|
/** Milliseconds since `heartbeatAt`, computed against the server clock. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useState, useCallback } from "react";
|
|
2
2
|
import { createPollEngine } from "../shared/poll-engine.js";
|
|
3
|
+
import { ACTIVE_RUN_STATE_EVENT, getActiveRun, } from "./active-run-state.js";
|
|
3
4
|
import { agentNativePath } from "./api-path.js";
|
|
4
5
|
const DEFAULT_STUCK_THRESHOLD_MS = 90_000;
|
|
5
6
|
export const DEFAULT_BACKGROUND_STUCK_THRESHOLD_MS = 180_000;
|
|
@@ -20,6 +21,7 @@ const EMPTY_STATE = {
|
|
|
20
21
|
status: null,
|
|
21
22
|
lastProgressAt: null,
|
|
22
23
|
stuckSinceMs: null,
|
|
24
|
+
lastProgressSeq: null,
|
|
23
25
|
heartbeatAt: null,
|
|
24
26
|
heartbeatSinceMs: null,
|
|
25
27
|
dispatchMode: null,
|
|
@@ -37,6 +39,8 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
|
|
|
37
39
|
let cancelled = false;
|
|
38
40
|
let snapshotTransitionTimer = null;
|
|
39
41
|
let snapshotVersion = 0;
|
|
42
|
+
let lastObservedLocalProgressAt = null;
|
|
43
|
+
let lastObservedLocalProgressSeq = null;
|
|
40
44
|
let consecutivePollFailures = 0;
|
|
41
45
|
// The engine's own cadence varies per tick (idle backoff, error backoff),
|
|
42
46
|
// which is why intervalMs below reads from this ref instead of a fixed
|
|
@@ -86,8 +90,14 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
|
|
|
86
90
|
const currentStuckSinceMs = snapshot.stuckSinceMs == null
|
|
87
91
|
? null
|
|
88
92
|
: snapshot.stuckSinceMs + currentElapsedMs;
|
|
93
|
+
const currentLocalProgressSinceMs = snapshot.localProgressObservedAt == null
|
|
94
|
+
? null
|
|
95
|
+
: Math.max(0, Date.now() - snapshot.localProgressObservedAt);
|
|
89
96
|
const effectiveThresholdMs = effectiveThresholdFor(snapshot.dispatchMode, currentHeartbeatSinceMs);
|
|
90
|
-
const
|
|
97
|
+
const localProgressFresh = Boolean(currentLocalProgressSinceMs != null &&
|
|
98
|
+
currentLocalProgressSinceMs <= effectiveThresholdMs);
|
|
99
|
+
const currentlyStuck = Boolean(!localProgressFresh &&
|
|
100
|
+
currentStuckSinceMs != null &&
|
|
91
101
|
currentStuckSinceMs > effectiveThresholdMs);
|
|
92
102
|
const transitionDelaysMs = [];
|
|
93
103
|
if (currentHeartbeatSinceMs != null &&
|
|
@@ -95,9 +105,14 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
|
|
|
95
105
|
currentHeartbeatSinceMs < FRESH_BACKGROUND_HEARTBEAT_MS) {
|
|
96
106
|
transitionDelaysMs.push(FRESH_BACKGROUND_HEARTBEAT_MS - currentHeartbeatSinceMs + 1);
|
|
97
107
|
}
|
|
98
|
-
if (
|
|
108
|
+
if (!localProgressFresh &&
|
|
109
|
+
currentStuckSinceMs != null &&
|
|
110
|
+
!currentlyStuck) {
|
|
99
111
|
transitionDelaysMs.push(Math.max(1, effectiveThresholdMs - currentStuckSinceMs + 1));
|
|
100
112
|
}
|
|
113
|
+
if (localProgressFresh && currentLocalProgressSinceMs != null) {
|
|
114
|
+
transitionDelaysMs.push(Math.max(1, effectiveThresholdMs - currentLocalProgressSinceMs + 1));
|
|
115
|
+
}
|
|
101
116
|
if (transitionDelaysMs.length === 0)
|
|
102
117
|
return;
|
|
103
118
|
// Both ages originate from the server clock. Advance those snapshots by
|
|
@@ -116,26 +131,66 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
|
|
|
116
131
|
const nextStuckSinceMs = snapshot.stuckSinceMs == null
|
|
117
132
|
? null
|
|
118
133
|
: snapshot.stuckSinceMs + elapsedSinceObservationMs;
|
|
134
|
+
const nextLocalProgressSinceMs = snapshot.localProgressObservedAt == null
|
|
135
|
+
? null
|
|
136
|
+
: Math.max(0, Date.now() - snapshot.localProgressObservedAt);
|
|
119
137
|
const nextEffectiveThresholdMs = effectiveThresholdFor(snapshot.dispatchMode, nextHeartbeatSinceMs);
|
|
120
|
-
const
|
|
138
|
+
const nextLocalProgressFresh = Boolean(nextLocalProgressSinceMs != null &&
|
|
139
|
+
nextLocalProgressSinceMs <= nextEffectiveThresholdMs);
|
|
140
|
+
const nextIsStuck = Boolean(!nextLocalProgressFresh &&
|
|
141
|
+
nextStuckSinceMs != null &&
|
|
121
142
|
nextStuckSinceMs > nextEffectiveThresholdMs);
|
|
122
143
|
setState((current) => {
|
|
123
144
|
if (version !== snapshotVersion ||
|
|
124
145
|
current.runId !== snapshot.runId ||
|
|
125
146
|
current.lastProgressAt !== snapshot.lastProgressAt ||
|
|
126
|
-
current.heartbeatAt !== snapshot.heartbeatAt
|
|
147
|
+
current.heartbeatAt !== snapshot.heartbeatAt ||
|
|
148
|
+
current.lastProgressSeq !== snapshot.lastProgressSeq) {
|
|
127
149
|
return current;
|
|
128
150
|
}
|
|
129
151
|
return {
|
|
130
152
|
...current,
|
|
131
153
|
isStuck: nextIsStuck,
|
|
132
|
-
stuckSinceMs: nextStuckSinceMs,
|
|
154
|
+
stuckSinceMs: nextLocalProgressFresh ? null : nextStuckSinceMs,
|
|
133
155
|
heartbeatSinceMs: nextHeartbeatSinceMs,
|
|
134
156
|
};
|
|
135
157
|
});
|
|
136
158
|
scheduleSnapshotTransition(snapshot, observedAtMs, version);
|
|
137
159
|
}, delayMs);
|
|
138
160
|
};
|
|
161
|
+
// A healthy SSE stream is a stronger local proof of progress than a
|
|
162
|
+
// delayed SQL timestamp. Listen only to the real-progress cursor - raw
|
|
163
|
+
// keepalives still advance the reconnect cursor but must not suppress the
|
|
164
|
+
// stuck detector forever.
|
|
165
|
+
const onActiveRunStateChange = (event) => {
|
|
166
|
+
const activeRun = (event.detail?.state ?? getActiveRun());
|
|
167
|
+
const progressSeq = activeRun?.lastProgressSeq ?? null;
|
|
168
|
+
const hasNewerProgress = typeof activeRun?.lastProgressObservedAt === "number" &&
|
|
169
|
+
(activeRun.lastProgressObservedAt >
|
|
170
|
+
(lastObservedLocalProgressAt ?? -1) ||
|
|
171
|
+
(activeRun.lastProgressObservedAt === lastObservedLocalProgressAt &&
|
|
172
|
+
progressSeq != null &&
|
|
173
|
+
progressSeq > (lastObservedLocalProgressSeq ?? -1)));
|
|
174
|
+
if (!activeRun ||
|
|
175
|
+
activeRun.threadId !== threadId ||
|
|
176
|
+
typeof activeRun.lastProgressObservedAt !== "number" ||
|
|
177
|
+
!hasNewerProgress) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
lastObservedLocalProgressAt = activeRun.lastProgressObservedAt;
|
|
181
|
+
lastObservedLocalProgressSeq = progressSeq;
|
|
182
|
+
snapshotVersion += 1;
|
|
183
|
+
if (snapshotTransitionTimer)
|
|
184
|
+
clearTimeout(snapshotTransitionTimer);
|
|
185
|
+
snapshotTransitionTimer = null;
|
|
186
|
+
setState((current) => {
|
|
187
|
+
if (current.runId !== activeRun.runId || !current.isStuck) {
|
|
188
|
+
return current;
|
|
189
|
+
}
|
|
190
|
+
return { ...current, isStuck: false, stuckSinceMs: null };
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
window.addEventListener(ACTIVE_RUN_STATE_EVENT, onActiveRunStateChange);
|
|
139
194
|
const attempt = async (signal) => {
|
|
140
195
|
let nextDelay = pollIntervalMs;
|
|
141
196
|
try {
|
|
@@ -156,6 +211,14 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
|
|
|
156
211
|
const heartbeatAt = data.heartbeatAt ?? null;
|
|
157
212
|
const heartbeatSinceMs = heartbeatAt != null ? nowMs - heartbeatAt : null;
|
|
158
213
|
const dispatchMode = typeof data.dispatchMode === "string" ? data.dispatchMode : null;
|
|
214
|
+
const runId = data.runId ?? null;
|
|
215
|
+
const activeRun = getActiveRun();
|
|
216
|
+
const localProgressObservedAt = activeRun?.threadId === threadId && activeRun.runId === runId
|
|
217
|
+
? (activeRun.lastProgressObservedAt ?? null)
|
|
218
|
+
: null;
|
|
219
|
+
const localProgressSinceMs = localProgressObservedAt == null
|
|
220
|
+
? null
|
|
221
|
+
: Math.max(0, Date.now() - localProgressObservedAt);
|
|
159
222
|
// A claimed durable worker with a fresh heartbeat can legitimately
|
|
160
223
|
// be waiting on a bounded long-running tool/sub-agent call. Still
|
|
161
224
|
// surface informational status at the normal background threshold;
|
|
@@ -166,25 +229,37 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
|
|
|
166
229
|
const isStuck = Boolean(data.active &&
|
|
167
230
|
data.status === "running" &&
|
|
168
231
|
stuckSinceMs != null &&
|
|
169
|
-
stuckSinceMs > effectiveThresholdMs
|
|
232
|
+
stuckSinceMs > effectiveThresholdMs &&
|
|
233
|
+
(localProgressSinceMs == null ||
|
|
234
|
+
localProgressSinceMs > effectiveThresholdMs));
|
|
170
235
|
const observedAtMs = Date.now();
|
|
171
236
|
const version = ++snapshotVersion;
|
|
172
237
|
scheduleSnapshotTransition({
|
|
173
238
|
active: data.active,
|
|
174
|
-
runId
|
|
239
|
+
runId,
|
|
175
240
|
status: data.status ?? null,
|
|
176
241
|
lastProgressAt,
|
|
177
242
|
stuckSinceMs,
|
|
243
|
+
localProgressObservedAt,
|
|
244
|
+
lastProgressSeq: activeRun?.threadId === threadId && activeRun.runId === runId
|
|
245
|
+
? (activeRun.lastProgressSeq ?? null)
|
|
246
|
+
: null,
|
|
178
247
|
heartbeatAt,
|
|
179
248
|
heartbeatSinceMs,
|
|
180
249
|
dispatchMode,
|
|
181
250
|
}, observedAtMs, version);
|
|
182
251
|
setState({
|
|
183
252
|
isStuck,
|
|
184
|
-
runId
|
|
253
|
+
runId,
|
|
185
254
|
status: data.status ?? null,
|
|
186
255
|
lastProgressAt,
|
|
187
|
-
stuckSinceMs
|
|
256
|
+
stuckSinceMs: localProgressSinceMs != null &&
|
|
257
|
+
localProgressSinceMs <= effectiveThresholdMs
|
|
258
|
+
? null
|
|
259
|
+
: stuckSinceMs,
|
|
260
|
+
lastProgressSeq: activeRun?.threadId === threadId && activeRun.runId === runId
|
|
261
|
+
? (activeRun.lastProgressSeq ?? null)
|
|
262
|
+
: null,
|
|
188
263
|
heartbeatAt,
|
|
189
264
|
heartbeatSinceMs,
|
|
190
265
|
dispatchMode,
|
|
@@ -245,6 +320,7 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
|
|
|
245
320
|
engine.stop();
|
|
246
321
|
if (snapshotTransitionTimer)
|
|
247
322
|
clearTimeout(snapshotTransitionTimer);
|
|
323
|
+
window.removeEventListener(ACTIVE_RUN_STATE_EVENT, onActiveRunStateChange);
|
|
248
324
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
249
325
|
};
|
|
250
326
|
}, [
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
states: {
|
|
66
67
|
clientId: number;
|
|
67
68
|
state: string;
|
|
68
69
|
}[];
|
|
69
|
-
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
+
error?: undefined;
|
|
80
81
|
users: {
|
|
81
82
|
clientId: number;
|
|
82
83
|
lastSeen: number;
|
|
83
84
|
}[];
|
|
84
|
-
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
ok?: undefined;
|
|
30
29
|
error: string;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -2,10 +2,6 @@ import type { PlatformAdapter, IncomingMessage } from "../types.js";
|
|
|
2
2
|
export interface SlackAdapterOptions {
|
|
3
3
|
/** Resolve the bot token for the exact Slack installation. */
|
|
4
4
|
resolveBotToken?: (incoming: IncomingMessage) => Promise<string | undefined>;
|
|
5
|
-
/** Override active-thread detection for hosted adapters/tests. */
|
|
6
|
-
isThreadActive?: (incoming: IncomingMessage) => Promise<boolean>;
|
|
7
|
-
/** Override one-shot clarification-window consumption for tests. */
|
|
8
|
-
consumeAwaitingInput?: (incoming: IncomingMessage) => Promise<boolean>;
|
|
9
5
|
}
|
|
10
6
|
/**
|
|
11
7
|
* Create a Slack platform adapter.
|
|
@@ -3,10 +3,8 @@ import { createError, getHeader, readRawBody } from "h3";
|
|
|
3
3
|
import { resolveSecret } from "../../server/credential-provider.js";
|
|
4
4
|
import { getRequestContext } from "../../server/request-context.js";
|
|
5
5
|
import { getIntegrationRequestContext } from "../../server/request-context.js";
|
|
6
|
-
import { consumeIntegrationAwaitingInput } from "../awaiting-input-store.js";
|
|
7
6
|
import { createIntegrationControl } from "../controls-store.js";
|
|
8
7
|
import { getActiveIntegrationInstallationByKey, listActiveIntegrationInstallationsForTenant, listIntegrationInstallations, resolveIntegrationTokenBundle, } from "../installations-store.js";
|
|
9
|
-
import { hasActivePendingTask } from "../pending-tasks-store.js";
|
|
10
8
|
import { slackInstallationKey } from "../slack-oauth.js";
|
|
11
9
|
/** Slack's max message length */
|
|
12
10
|
const SLACK_MAX_LENGTH = 4000;
|
|
@@ -195,10 +193,10 @@ export function slackAdapter(options = {}) {
|
|
|
195
193
|
// Ignore message edits and deletes
|
|
196
194
|
if (e.subtype === "message_changed" || e.subtype === "message_deleted")
|
|
197
195
|
return null;
|
|
198
|
-
// Handle DMs and explicit mentions.
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
//
|
|
196
|
+
// Handle DMs and explicit mentions only. A channel thread can contain
|
|
197
|
+
// many human replies after an agent mention; each new agent turn must
|
|
198
|
+
// opt in with another explicit mention instead of inheriting the
|
|
199
|
+
// parent message's invocation.
|
|
202
200
|
const text = e.text?.trim();
|
|
203
201
|
if (!text)
|
|
204
202
|
return null;
|
|
@@ -211,8 +209,7 @@ export function slackAdapter(options = {}) {
|
|
|
211
209
|
? e.channel_type === "im"
|
|
212
210
|
: typeof e.channel === "string" && e.channel.startsWith("D");
|
|
213
211
|
const isMention = e.type === "app_mention";
|
|
214
|
-
|
|
215
|
-
if (!isDm && !isMention && !isThreadReply)
|
|
212
|
+
if (!isDm && !isMention)
|
|
216
213
|
return null;
|
|
217
214
|
// Remove bot mention from text (e.g., "<@U123> do something" → "do something")
|
|
218
215
|
const cleanText = text.replace(/<@[A-Z0-9]+>/g, "").trim();
|
|
@@ -227,7 +224,7 @@ export function slackAdapter(options = {}) {
|
|
|
227
224
|
text: cleanText,
|
|
228
225
|
senderName: e.user,
|
|
229
226
|
senderId: e.user,
|
|
230
|
-
triggerKind: isDm ? "dm" :
|
|
227
|
+
triggerKind: isDm ? "dm" : "mention",
|
|
231
228
|
conversationType: isDm ? "dm" : "unknown",
|
|
232
229
|
tenantId: teamId,
|
|
233
230
|
// The signed Slack envelope authenticates the workspace, not the
|
|
@@ -256,27 +253,6 @@ export function slackAdapter(options = {}) {
|
|
|
256
253
|
replyRef: e.ts,
|
|
257
254
|
timestamp: Math.floor(parseFloat(e.ts) * 1000),
|
|
258
255
|
};
|
|
259
|
-
if (isThreadReply) {
|
|
260
|
-
// An ordinary thread reply is narrowly admitted when either work is
|
|
261
|
-
// still queued or the same Slack user is answering a fresh
|
|
262
|
-
// integration-originated clarification. Consuming the latter is a
|
|
263
|
-
// conditional SQL delete, so concurrent replies cannot both reopen
|
|
264
|
-
// the agent and unrelated channel messages remain ignored.
|
|
265
|
-
const answeredClarification = options.consumeAwaitingInput
|
|
266
|
-
? await options.consumeAwaitingInput(partialIncoming)
|
|
267
|
-
: options.isThreadActive
|
|
268
|
-
? false
|
|
269
|
-
: await consumeIntegrationAwaitingInput({
|
|
270
|
-
platform: "slack",
|
|
271
|
-
externalThreadId,
|
|
272
|
-
requesterId: e.user,
|
|
273
|
-
});
|
|
274
|
-
const active = options.isThreadActive
|
|
275
|
-
? await options.isThreadActive(partialIncoming)
|
|
276
|
-
: await hasActivePendingTask("slack", externalThreadId);
|
|
277
|
-
if (!active && !answeredClarification)
|
|
278
|
-
return null;
|
|
279
|
-
}
|
|
280
256
|
const token = await resolveBotToken(partialIncoming);
|
|
281
257
|
const threadPermalink = await resolveSlackThreadPermalink(e.channel, threadTs, token);
|
|
282
258
|
return {
|
|
@@ -36,7 +36,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
|
|
|
36
36
|
"Apply the Agent Native Slack manifest to enable Agent View and writable direct messages.",
|
|
37
37
|
"Configure the OAuth client id, client secret, and signing secret.",
|
|
38
38
|
"Enable Event Subscriptions and Interactivity with the documented URLs.",
|
|
39
|
-
"Subscribe to app_home_opened, app_context_changed, app_mention, and message.im
|
|
39
|
+
"Subscribe to app_home_opened, app_context_changed, app_mention, and message.im, then use Add to Slack.",
|
|
40
40
|
],
|
|
41
41
|
},
|
|
42
42
|
credentialRequirements: [
|
|
@@ -20,14 +20,6 @@ export interface PendingTask {
|
|
|
20
20
|
updatedAt: number;
|
|
21
21
|
completedAt: number | null;
|
|
22
22
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Whether a provider thread currently has queued or executing work.
|
|
25
|
-
*
|
|
26
|
-
* Messaging adapters use this to accept unmentioned replies only while an
|
|
27
|
-
* agent task is active. This prevents broad message subscriptions from turning
|
|
28
|
-
* every channel message into an agent invocation.
|
|
29
|
-
*/
|
|
30
|
-
export declare function hasActivePendingTask(platform: string, externalThreadId: string): Promise<boolean>;
|
|
31
23
|
/**
|
|
32
24
|
* Insert a new pending task. Returns the generated task id.
|
|
33
25
|
*
|