@agent-native/core 0.129.2 → 0.130.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +78 -0
- package/corpus/core/docs/content/cloneable-saas.mdx +114 -0
- package/corpus/core/docs/content/creating-templates.mdx +28 -2
- package/corpus/core/docs/content/syncing-template-changes.mdx +7 -0
- package/corpus/core/docs/content/template-clips-developers.mdx +12 -5
- package/corpus/core/docs/content/template-dispatch-developers.mdx +1 -1
- package/corpus/core/docs/content/template-dispatch.mdx +1 -1
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/action-ui.ts +1 -0
- package/corpus/core/src/action.ts +5 -1
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +15 -5
- package/corpus/core/src/agent/harness/runner.ts +5 -0
- package/corpus/core/src/agent/production-agent.ts +33 -0
- package/corpus/core/src/agent/run-loop-with-resume.ts +5 -0
- package/corpus/core/src/agent/run-manager.ts +126 -1
- package/corpus/core/src/agent/thread-data-builder.ts +47 -2
- package/corpus/core/src/agent/types.ts +2 -0
- package/corpus/core/src/chat-threads/store.ts +4 -5
- package/corpus/core/src/cli/create.ts +1139 -65
- package/corpus/core/src/cli/design-connect.ts +3 -7
- package/corpus/core/src/cli/index.ts +5 -3
- package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +83 -47
- package/corpus/core/src/client/AssistantChat.tsx +27 -16
- package/corpus/core/src/client/agent-chat-adapter.ts +24 -0
- package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +17 -2
- package/corpus/core/src/client/chat/index.ts +1 -0
- package/corpus/core/src/client/chat/message-components.tsx +104 -1
- package/corpus/core/src/client/chat/run-recovery.tsx +15 -3
- package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +10 -29
- package/corpus/core/src/client/chat/widgets/WorkspaceFileWidget.tsx +71 -0
- package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +22 -0
- package/corpus/core/src/client/chat/widgets/workspace-file-result.ts +49 -0
- package/corpus/core/src/client/embed-auth.ts +2 -0
- package/corpus/core/src/client/org/InvitationBanner.tsx +14 -1
- package/corpus/core/src/client/org/OrgSwitcher.tsx +23 -0
- package/corpus/core/src/client/org/TeamPage.tsx +130 -0
- package/corpus/core/src/client/org/WorkspaceNotice.tsx +85 -0
- package/corpus/core/src/client/org/hooks.ts +14 -0
- package/corpus/core/src/client/org/index.ts +2 -0
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +27 -40
- package/corpus/core/src/client/resources/ResourcesPanel.tsx +134 -51
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +7 -0
- package/corpus/core/src/client/resources/use-resources.ts +6 -0
- package/corpus/core/src/client/use-action.ts +3 -1
- package/corpus/core/src/client/widgets/index.ts +1 -0
- package/corpus/core/src/coding-tools/run-code.ts +2 -1
- package/corpus/core/src/db/client.ts +28 -4
- package/corpus/core/src/deploy/build.ts +31 -3
- package/corpus/core/src/eject/remote-mcp-presets.ts +1 -1
- package/corpus/core/src/index.browser.ts +1 -0
- package/corpus/core/src/index.ts +1 -0
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +481 -122
- package/corpus/core/src/integrations/a2a-continuations-store.ts +345 -14
- package/corpus/core/src/integrations/adapters/slack.ts +243 -53
- package/corpus/core/src/integrations/google-docs-poller.ts +3 -0
- package/corpus/core/src/integrations/integration-campaign-recovery.ts +4 -1
- package/corpus/core/src/integrations/plugin.ts +39 -21
- package/corpus/core/src/integrations/task-queue-stats.ts +146 -0
- package/corpus/core/src/integrations/types.ts +25 -4
- package/corpus/core/src/integrations/webhook-handler.ts +46 -16
- package/corpus/core/src/jobs/scheduler.ts +4 -0
- package/corpus/core/src/localization/default-messages.ts +3 -2
- package/corpus/core/src/observability/traces.ts +48 -12
- package/corpus/core/src/org/handlers.ts +52 -1
- package/corpus/core/src/org/migrations.ts +4 -0
- package/corpus/core/src/org/plugin.ts +14 -0
- package/corpus/core/src/org/schema.ts +1 -0
- package/corpus/core/src/org/types.ts +8 -0
- package/corpus/core/src/org/workspace-url.ts +74 -0
- package/corpus/core/src/resources/handlers.ts +35 -5
- package/corpus/core/src/scripts/runner.ts +183 -5
- package/corpus/core/src/server/action-routes.ts +32 -2
- package/corpus/core/src/server/agent-chat-plugin.ts +29 -0
- package/corpus/core/src/server/agent-teams.ts +10 -1
- package/corpus/core/src/server/auth.ts +33 -7
- package/corpus/core/src/server/embed-route.ts +9 -0
- package/corpus/core/src/server/embed-session.ts +62 -3
- package/corpus/core/src/server/open-route.ts +20 -6
- package/corpus/core/src/server/prompts/framework-core-compact.ts +1 -1
- package/corpus/core/src/server/prompts/framework-core.ts +1 -0
- package/corpus/core/src/server/request-context.ts +36 -1
- package/corpus/core/src/shared/embed-auth.ts +1 -0
- package/corpus/core/src/shared/html-document.ts +115 -0
- package/corpus/core/src/shared/index.ts +1 -0
- package/corpus/core/src/sharing/access.ts +8 -1
- package/corpus/core/src/sharing/registry.ts +11 -2
- package/corpus/core/src/workspace-files/actions.ts +100 -0
- package/corpus/core/src/workspace-files/tool.ts +4 -0
- package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +4 -0
- package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +9 -1
- package/corpus/templates/analytics/AGENTS.md +17 -24
- package/corpus/templates/analytics/actions/data-source-status.ts +11 -1
- package/corpus/templates/analytics/app/i18n-data.ts +34 -0
- package/corpus/templates/analytics/app/lib/data-source-status.ts +86 -0
- package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +9 -0
- package/corpus/templates/analytics/app/pages/DataSources.tsx +184 -20
- package/corpus/templates/analytics/changelog/2026-07-28-native-analytics-data-sources-no-longer-show-duplicate-mc.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-29-exports-now-appear-in-chat-with-a-direct-download-instead-of.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-29-queued-chat-prompts-no-longer-resend-after-analytics-navigat.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-29-scheduled-dashboard-emails-load-every-panel-reliably-without.md +6 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +6 -3
- package/corpus/templates/analytics/server/lib/credential-keys.ts +1 -1
- package/corpus/templates/analytics/server/lib/hubspot.ts +1 -1
- package/corpus/templates/analytics/server/lib/provider-credentials.ts +55 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +123 -27
- package/corpus/templates/analytics/server/routes/[...page].get.ts +2 -7
- package/corpus/templates/analytics/vite.config.ts +7 -0
- package/corpus/templates/brain/actions/list-connection-providers.ts +100 -2
- package/corpus/templates/brain/app/lib/brain.ts +10 -0
- package/corpus/templates/brain/app/routes/sources.tsx +15 -4
- package/corpus/templates/brain/changelog/2026-07-29-brain-automatically-retries-failed-source-syncs-and-guides-y.md +6 -0
- package/corpus/templates/brain/jobs/process-ingest-queue.ts +13 -0
- package/corpus/templates/brain/server/jobs/sync-sources.ts +27 -22
- package/corpus/templates/brain/server/plugins/agent-chat.ts +2 -1
- package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +7 -1
- package/corpus/templates/clips/AGENTS.md +1 -1
- package/corpus/templates/clips/actions/create-recording-agent-link.ts +11 -1
- package/corpus/templates/clips/actions/update-comment.ts +68 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +0 -1
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +221 -65
- package/corpus/templates/clips/app/components/player/video-player.tsx +101 -27
- package/corpus/templates/clips/app/i18n/en-US.ts +2 -1
- package/corpus/templates/clips/app/routes/bug-report.done.tsx +48 -27
- package/corpus/templates/clips/app/routes/bug-report.tsx +43 -4
- package/corpus/templates/clips/app/routes/record.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-07-29-clip-playback-now-recovers-instead-of-getting-stuck-when-a-b.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-29-comments-can-now-be-edited-after-posting.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-29-download-actions-now-use-a-shorter-clearer-label.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-29-embedded-bug-reports-now-return-a-temporary-agent-readable.md +6 -0
- package/corpus/templates/clips/shared/bug-report.ts +99 -0
- package/corpus/templates/content/actions/_content-database-personal-view.ts +7 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +5 -2
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +20 -8
- package/corpus/templates/content/changelog/2026-07-29-missing-databases-no-longer-trigger-repeated-personal-view-e.md +6 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +83 -47
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +474 -55
- package/corpus/templates/design/.generated/bridge/embedded-wheel.generated.ts +3 -0
- package/corpus/templates/design/.generated/bridge/hit-test.generated.ts +18 -1
- package/corpus/templates/design/.generated/bridge/source-location.generated.ts +348 -0
- package/corpus/templates/design/actions/add-localhost-screens.ts +2 -7
- package/corpus/templates/design/actions/apply-visual-edit.ts +7 -1
- package/corpus/templates/design/actions/connect-localhost.ts +5 -9
- package/corpus/templates/design/actions/create-component.ts +16 -13
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +2 -7
- package/corpus/templates/design/actions/list-design-source-capabilities.ts +4 -7
- package/corpus/templates/design/actions/list-local-files.ts +26 -50
- package/corpus/templates/design/actions/list-localhost-connections.ts +2 -7
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +2 -2
- package/corpus/templates/design/actions/open-visual-edit.ts +234 -135
- package/corpus/templates/design/actions/read-local-file.ts +26 -50
- package/corpus/templates/design/actions/request-localhost-write-consent.ts +2 -7
- package/corpus/templates/design/actions/write-local-file.ts +31 -73
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +307 -133
- package/corpus/templates/design/app/components/design/EditPanel.tsx +94 -22
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +137 -60
- package/corpus/templates/design/app/components/design/ResponsiveInteractBar.tsx +75 -14
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +755 -97
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +8 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +24 -1
- package/corpus/templates/design/app/components/design/bridge/source-location.bridge.ts +530 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbenchLoader.tsx +278 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +32 -12
- package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +14 -3
- package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +87 -24
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +36 -0
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +2 -1
- package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +48 -8
- package/corpus/templates/design/app/components/design/design-canvas/content-size-report.ts +3 -13
- package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +4 -2
- package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +3 -13
- package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +3 -1
- package/corpus/templates/design/app/components/design/edit-panel/inspect-code-source.ts +93 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -2
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +35 -0
- package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +24 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -0
- package/corpus/templates/design/app/components/design/types.ts +29 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -4
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +153 -46
- package/corpus/templates/design/app/i18n-responsive-interact.ts +12 -12
- package/corpus/templates/design/app/lib/design-editor-route.ts +23 -0
- package/corpus/templates/design/app/pages/VisualEdit.tsx +19 -6
- package/corpus/templates/design/app/pages/design-editor/action-error.ts +19 -0
- package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +29 -0
- package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +6 -0
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +277 -15
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +75 -9
- package/corpus/templates/design/app/pages/design-editor/layer-state-scope.ts +28 -0
- package/corpus/templates/design/app/pages/design-editor/live-screen-layer-drop.ts +41 -0
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +496 -41
- package/corpus/templates/design/app/pages/design-editor/pending-live-edit-unload-guard.ts +27 -0
- package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +10 -0
- package/corpus/templates/design/app/pages/design-editor/react-semantic-handoff.ts +168 -9
- package/corpus/templates/design/app/pages/design-editor/responsive-interact.ts +41 -3
- package/corpus/templates/design/app/pages/design-editor/screen-command-utils.ts +5 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +42 -13
- package/corpus/templates/design/app/pages/design-editor/source-location.ts +180 -0
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +17 -0
- package/corpus/templates/design/app/public-routes.ts +1 -0
- package/corpus/templates/design/app/routes/visual-edit.$id.tsx +15 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +1 -1
- package/corpus/templates/design/changelog/2026-07-28-deleting-a-selected-element-now-removes-it-from-the-live-pre.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-deleting-an-element-on-a-connected-localhost-screen-now-queu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-shows-a-responsive-device-preview-with-pre.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-layer-hide-and-lock-now-apply-to-the-live-preview-instead-of.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-layers-panel-selections-on-a-connected-localhost-screen-can-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-locked-layers-now-show-a-subtle-dashed-outline-in-the-live-p.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-the-apply-design-updates-button-now-counts-pending-live-text.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-the-design-canvas-no-longer-stalls-on-a-render-loop-while-a-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-visual-edit-on-a-local-dev-server-no-longer-requires-signing.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-visual-edits-on-a-react-19-app-no-longer-report-a-source-lin.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-an-edit-that-cannot-be-written-to-source-now-names-the-reaso.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-applying-a-primitive-dropped-onto-a-connected-localhost-scre.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-changing-a-style-in-the-inspector-now-updates-a-connected-lo.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-choosing-edit-or-annotate-from-a-focused-screen-now-returns-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-concurrent-source-edits-now-return-a-clear-conflict-response.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-creating-a-component-from-an-element-that-repeats-in-the-sou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-deleting-an-element-you-just-dropped-onto-a-live-screen-no-l.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-dragging-a-layer-across-screens-no-longer-dies-when-the-poin.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-dragging-an-element-from-a-stored-screen-into-a-live-localho.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-drawing-a-box-on-the-canvas-and-dragging-it-into-a-connected.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-fixed-a-loading-screen-flicker-when-reopening-designs-with-a.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-interact-mode-has-edit-and-annotate-buttons-again-so-you-can.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-layer-groups-can-be-dropped-onto-live-localhost-screens.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-localhost-source-errors-now-say-what-actually-went-wrong-whi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-opening-or-refreshing-a-live-localhost-screen-in-single-scre.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-redo-after-undoing-a-drop-onto-a-live-screen-puts-the-elemen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-shapes-can-be-drawn-directly-onto-live-localhost-screens.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-shapes-drawn-on-the-canvas-board-now-appear-immediately-inst.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-style-edits-on-a-running-localhost-screen-now-preview-live-a.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-the-apply-design-updates-control-now-appears-as-a-clean-conn.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-visual-edits-on-a-mapped-component-instance-now-tell-the-age.md +6 -0
- package/corpus/templates/design/server/lib/design-data-access.ts +21 -7
- package/corpus/templates/design/server/lib/localhost-connection.ts +240 -0
- package/corpus/templates/design/server/routes/[...page].get.ts +2 -5
- package/corpus/templates/design/server/source-workspace.ts +2 -0
- package/corpus/templates/design/shared/code-layer.ts +43 -0
- package/corpus/templates/design/shared/html-content.ts +26 -0
- package/corpus/templates/design/shared/html-integrity.ts +21 -1
- package/corpus/templates/design/shared/local-jsx-visual-edit.ts +15 -0
- package/corpus/templates/design/shared/source-mode.ts +76 -0
- package/corpus/templates/dispatch/changelog/2026-07-26-slack-replies-recover-after-connected-app-updates.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-29-workspace-members-without-admin-access-now-see-a-clear-permi.md +6 -0
- package/corpus/templates/dispatch/server/lib/usage-metrics.ts +2 -1
- package/corpus/templates/plan/app/lib/plan-annotation-runtime.ts +3 -4
- package/corpus/templates/plan/server/routes/[...page].get.ts +2 -5
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +15 -0
- package/corpus/templates/slides/actions/delete-design-system.ts +145 -0
- package/corpus/templates/slides/actions/list-design-systems.ts +94 -2
- package/corpus/templates/slides/actions/patch-deck.ts +29 -17
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +43 -1
- package/corpus/templates/slides/app/hooks/use-design-systems.ts +2 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +7 -0
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +56 -1
- package/corpus/templates/slides/changelog/2026-07-28-delete-a-design-system-you-own-from-the-design-systems-page-.md +6 -0
- package/corpus/toolkit/CHANGELOG.md +6 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/composer/ComposerPlusMenu.tsx +3 -2
- package/dist/action-ui.d.ts +1 -0
- package/dist/action-ui.d.ts.map +1 -1
- package/dist/action-ui.js +1 -0
- package/dist/action-ui.js.map +1 -1
- package/dist/action.d.ts +5 -1
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +13 -5
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/harness/runner.d.ts.map +1 -1
- package/dist/agent/harness/runner.js +5 -0
- package/dist/agent/harness/runner.js.map +1 -1
- package/dist/agent/production-agent.d.ts +16 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +18 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +6 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-manager.d.ts +14 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +91 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +3 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +35 -3
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/agent/types.d.ts +2 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +4 -6
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/create.d.ts +66 -6
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +765 -66
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +2 -7
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/index.js +5 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.js +83 -47
- package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +16 -9
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +21 -0
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +2 -0
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.js +8 -2
- package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +17 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +24 -2
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts +6 -0
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +13 -3
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.js +2 -3
- package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
- package/dist/client/chat/widgets/WorkspaceFileWidget.d.ts +5 -0
- package/dist/client/chat/widgets/WorkspaceFileWidget.d.ts.map +1 -0
- package/dist/client/chat/widgets/WorkspaceFileWidget.js +34 -0
- package/dist/client/chat/widgets/WorkspaceFileWidget.js.map +1 -0
- package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.js +13 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
- package/dist/client/chat/widgets/workspace-file-result.d.ts +12 -0
- package/dist/client/chat/widgets/workspace-file-result.d.ts.map +1 -0
- package/dist/client/chat/widgets/workspace-file-result.js +34 -0
- package/dist/client/chat/widgets/workspace-file-result.js.map +1 -0
- package/dist/client/embed-auth.d.ts.map +1 -1
- package/dist/client/embed-auth.js +2 -1
- package/dist/client/embed-auth.js.map +1 -1
- package/dist/client/org/InvitationBanner.d.ts +5 -2
- package/dist/client/org/InvitationBanner.d.ts.map +1 -1
- package/dist/client/org/InvitationBanner.js +9 -2
- package/dist/client/org/InvitationBanner.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +3 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +27 -3
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/org/WorkspaceNotice.d.ts +18 -0
- package/dist/client/org/WorkspaceNotice.d.ts.map +1 -0
- package/dist/client/org/WorkspaceNotice.js +56 -0
- package/dist/client/org/WorkspaceNotice.js.map +1 -0
- package/dist/client/org/hooks.d.ts +1 -0
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +12 -0
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +2 -1
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +2 -1
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +8 -12
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts +3 -0
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +49 -20
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +3 -0
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/resources/use-resources.d.ts +1 -0
- package/dist/client/resources/use-resources.d.ts.map +1 -1
- package/dist/client/resources/use-resources.js +3 -0
- package/dist/client/resources/use-resources.js.map +1 -1
- package/dist/client/use-action.d.ts +3 -1
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +3 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/widgets/index.d.ts +1 -1
- package/dist/client/widgets/index.d.ts.map +1 -1
- package/dist/client/widgets/index.js +1 -1
- package/dist/client/widgets/index.js.map +1 -1
- package/dist/coding-tools/run-code.js +2 -1
- package/dist/coding-tools/run-code.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.d.ts +1 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +24 -3
- package/dist/db/client.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +25 -3
- package/dist/deploy/build.js.map +1 -1
- package/dist/eject/remote-mcp-presets.js +1 -1
- package/dist/eject/remote-mcp-presets.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts +5 -0
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +293 -79
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts +23 -1
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +249 -15
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +155 -31
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/google-docs-poller.d.ts.map +1 -1
- package/dist/integrations/google-docs-poller.js +4 -1
- package/dist/integrations/google-docs-poller.js.map +1 -1
- package/dist/integrations/integration-campaign-recovery.d.ts.map +1 -1
- package/dist/integrations/integration-campaign-recovery.js +3 -1
- package/dist/integrations/integration-campaign-recovery.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +29 -12
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/task-queue-stats.d.ts +12 -0
- package/dist/integrations/task-queue-stats.d.ts.map +1 -1
- package/dist/integrations/task-queue-stats.js +106 -0
- package/dist/integrations/task-queue-stats.js.map +1 -1
- package/dist/integrations/types.d.ts +24 -6
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +35 -14
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/scheduler.js +4 -0
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +3 -2
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +3 -2
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +27 -7
- package/dist/observability/traces.js.map +1 -1
- package/dist/org/handlers.d.ts +15 -0
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +45 -1
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +4 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/org/plugin.d.ts +1 -0
- package/dist/org/plugin.d.ts.map +1 -1
- package/dist/org/plugin.js +10 -1
- package/dist/org/plugin.js.map +1 -1
- package/dist/org/schema.d.ts +19 -0
- package/dist/org/schema.d.ts.map +1 -1
- package/dist/org/schema.js +1 -0
- package/dist/org/schema.js.map +1 -1
- package/dist/org/types.d.ts +8 -0
- package/dist/org/types.d.ts.map +1 -1
- package/dist/org/types.js.map +1 -1
- package/dist/org/workspace-url.d.ts +32 -0
- package/dist/org/workspace-url.d.ts.map +1 -0
- package/dist/org/workspace-url.js +63 -0
- package/dist/org/workspace-url.js.map +1 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/resources/handlers.d.ts +3 -4
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +25 -5
- package/dist/resources/handlers.js.map +1 -1
- package/dist/scripts/runner.d.ts +17 -0
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +130 -5
- package/dist/scripts/runner.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +24 -2
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +26 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +10 -1
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/auth.d.ts +22 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +33 -7
- package/dist/server/auth.js.map +1 -1
- package/dist/server/embed-route.d.ts.map +1 -1
- package/dist/server/embed-route.js +6 -1
- package/dist/server/embed-route.js.map +1 -1
- package/dist/server/embed-session.d.ts +7 -0
- package/dist/server/embed-session.d.ts.map +1 -1
- package/dist/server/embed-session.js +46 -4
- package/dist/server/embed-session.js.map +1 -1
- package/dist/server/open-route.d.ts.map +1 -1
- package/dist/server/open-route.js +17 -7
- package/dist/server/open-route.js.map +1 -1
- package/dist/server/prompts/framework-core-compact.js +1 -1
- package/dist/server/prompts/framework-core-compact.js.map +1 -1
- package/dist/server/prompts/framework-core.d.ts.map +1 -1
- package/dist/server/prompts/framework-core.js +1 -0
- package/dist/server/prompts/framework-core.js.map +1 -1
- package/dist/server/request-context.d.ts +26 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +18 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/shared/embed-auth.d.ts +1 -0
- package/dist/shared/embed-auth.d.ts.map +1 -1
- package/dist/shared/embed-auth.js +1 -0
- package/dist/shared/embed-auth.js.map +1 -1
- package/dist/shared/html-document.d.ts +12 -0
- package/dist/shared/html-document.d.ts.map +1 -0
- package/dist/shared/html-document.js +92 -0
- package/dist/shared/html-document.js.map +1 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/sharing/access.d.ts +1 -0
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +8 -2
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/registry.d.ts +3 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/workspace-files/actions.d.ts +28 -0
- package/dist/workspace-files/actions.d.ts.map +1 -0
- package/dist/workspace-files/actions.js +75 -0
- package/dist/workspace-files/actions.js.map +1 -0
- package/dist/workspace-files/tool.d.ts.map +1 -1
- package/dist/workspace-files/tool.js +4 -0
- package/dist/workspace-files/tool.js.map +1 -1
- package/docs/content/cloneable-saas.mdx +114 -0
- package/docs/content/creating-templates.mdx +28 -2
- package/docs/content/syncing-template-changes.mdx +7 -0
- package/docs/content/template-clips-developers.mdx +12 -5
- package/docs/content/template-dispatch-developers.mdx +1 -1
- package/docs/content/template-dispatch.mdx +1 -1
- package/package.json +2 -2
- package/src/action-ui.ts +1 -0
- package/src/action.ts +5 -1
- package/src/agent/engine/ai-sdk-engine.ts +15 -5
- package/src/agent/harness/runner.ts +5 -0
- package/src/agent/production-agent.ts +33 -0
- package/src/agent/run-loop-with-resume.ts +5 -0
- package/src/agent/run-manager.ts +126 -1
- package/src/agent/thread-data-builder.ts +47 -2
- package/src/agent/types.ts +2 -0
- package/src/chat-threads/store.ts +4 -5
- package/src/cli/create.ts +1139 -65
- package/src/cli/design-connect.ts +3 -7
- package/src/cli/index.ts +5 -3
- package/src/cli/skills-content/design-visual-edit-skill.ts +83 -47
- package/src/client/AssistantChat.tsx +27 -16
- package/src/client/agent-chat-adapter.ts +24 -0
- package/src/client/blocks/library/wireframe-kit.tsx +17 -2
- package/src/client/chat/index.ts +1 -0
- package/src/client/chat/message-components.tsx +104 -1
- package/src/client/chat/run-recovery.tsx +15 -3
- package/src/client/chat/widgets/DataTableWidget.tsx +10 -29
- package/src/client/chat/widgets/WorkspaceFileWidget.tsx +71 -0
- package/src/client/chat/widgets/builtin-tool-renderers.tsx +22 -0
- package/src/client/chat/widgets/workspace-file-result.ts +49 -0
- package/src/client/embed-auth.ts +2 -0
- package/src/client/org/InvitationBanner.tsx +14 -1
- package/src/client/org/OrgSwitcher.tsx +23 -0
- package/src/client/org/TeamPage.tsx +130 -0
- package/src/client/org/WorkspaceNotice.tsx +85 -0
- package/src/client/org/hooks.ts +14 -0
- package/src/client/org/index.ts +2 -0
- package/src/client/resources/McpIntegrationDialog.tsx +27 -40
- package/src/client/resources/ResourcesPanel.tsx +134 -51
- package/src/client/resources/mcp-integration-catalog.ts +7 -0
- package/src/client/resources/use-resources.ts +6 -0
- package/src/client/use-action.ts +3 -1
- package/src/client/widgets/index.ts +1 -0
- package/src/coding-tools/run-code.ts +2 -1
- package/src/db/client.ts +28 -4
- package/src/deploy/build.ts +31 -3
- package/src/eject/remote-mcp-presets.ts +1 -1
- package/src/index.browser.ts +1 -0
- package/src/index.ts +1 -0
- package/src/integrations/a2a-continuation-processor.ts +481 -122
- package/src/integrations/a2a-continuations-store.ts +345 -14
- package/src/integrations/adapters/slack.ts +243 -53
- package/src/integrations/google-docs-poller.ts +3 -0
- package/src/integrations/integration-campaign-recovery.ts +4 -1
- package/src/integrations/plugin.ts +39 -21
- package/src/integrations/task-queue-stats.ts +146 -0
- package/src/integrations/types.ts +25 -4
- package/src/integrations/webhook-handler.ts +46 -16
- package/src/jobs/scheduler.ts +4 -0
- package/src/localization/default-messages.ts +3 -2
- package/src/observability/traces.ts +48 -12
- package/src/org/handlers.ts +52 -1
- package/src/org/migrations.ts +4 -0
- package/src/org/plugin.ts +14 -0
- package/src/org/schema.ts +1 -0
- package/src/org/types.ts +8 -0
- package/src/org/workspace-url.ts +74 -0
- package/src/resources/handlers.ts +35 -5
- package/src/scripts/runner.ts +183 -5
- package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +2 -1
- package/src/server/action-routes.ts +32 -2
- package/src/server/agent-chat-plugin.ts +29 -0
- package/src/server/agent-teams.ts +10 -1
- package/src/server/auth.ts +33 -7
- package/src/server/embed-route.ts +9 -0
- package/src/server/embed-session.ts +62 -3
- package/src/server/open-route.ts +20 -6
- package/src/server/prompts/framework-core-compact.ts +1 -1
- package/src/server/prompts/framework-core.ts +1 -0
- package/src/server/request-context.ts +36 -1
- package/src/shared/embed-auth.ts +1 -0
- package/src/shared/html-document.ts +115 -0
- package/src/shared/index.ts +1 -0
- package/src/sharing/access.ts +8 -1
- package/src/sharing/registry.ts +11 -2
- package/src/workspace-files/actions.ts +100 -0
- package/src/workspace-files/tool.ts +4 -0
- package/corpus/templates/design/changelog/2026-07-28-interact-mode-can-preview-designs-in-responsive-device-sizes.md +0 -6
- package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-opens-a-full-screen-responsive-preview-wit.md +0 -6
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* columns before the SELECTs execute.
|
|
9
9
|
*/
|
|
10
10
|
import { getDbExec } from "../db/client.js";
|
|
11
|
+
import { ensureA2AContinuationsTable } from "./a2a-continuations-store.js";
|
|
11
12
|
import { ensurePendingTasksTable } from "./pending-tasks-store.js";
|
|
12
13
|
|
|
13
14
|
export interface RecentFailure {
|
|
@@ -23,6 +24,18 @@ export interface TaskQueueStats {
|
|
|
23
24
|
completed_last_hour: number;
|
|
24
25
|
failed_last_hour: number;
|
|
25
26
|
oldest_pending_age_seconds: number;
|
|
27
|
+
waiting_campaigns: number;
|
|
28
|
+
active_a2a_continuations: number;
|
|
29
|
+
oldest_active_a2a_age_seconds: number;
|
|
30
|
+
terminal_a2a_without_delivery: number;
|
|
31
|
+
recent_a2a_orphans: Array<{
|
|
32
|
+
continuation_id: string;
|
|
33
|
+
integration_task_id: string;
|
|
34
|
+
status: string;
|
|
35
|
+
attempts: number;
|
|
36
|
+
age_seconds: number;
|
|
37
|
+
reason_class: string;
|
|
38
|
+
}>;
|
|
26
39
|
recent_failures: RecentFailure[];
|
|
27
40
|
recent_tasks: Array<{
|
|
28
41
|
id: string;
|
|
@@ -46,6 +59,11 @@ const ZERO_STATS: TaskQueueStats = {
|
|
|
46
59
|
completed_last_hour: 0,
|
|
47
60
|
failed_last_hour: 0,
|
|
48
61
|
oldest_pending_age_seconds: 0,
|
|
62
|
+
waiting_campaigns: 0,
|
|
63
|
+
active_a2a_continuations: 0,
|
|
64
|
+
oldest_active_a2a_age_seconds: 0,
|
|
65
|
+
terminal_a2a_without_delivery: 0,
|
|
66
|
+
recent_a2a_orphans: [],
|
|
49
67
|
recent_failures: [],
|
|
50
68
|
recent_tasks: [],
|
|
51
69
|
};
|
|
@@ -66,11 +84,14 @@ export async function getTaskQueueStats(
|
|
|
66
84
|
scope: TaskQueueStatsScope,
|
|
67
85
|
): Promise<TaskQueueStats> {
|
|
68
86
|
await ensurePendingTasksTable();
|
|
87
|
+
await ensureA2AContinuationsTable();
|
|
69
88
|
const client = getDbExec();
|
|
70
89
|
const now = Date.now();
|
|
71
90
|
const oneHourAgo = now - 60 * 60 * 1000;
|
|
72
91
|
const scopeSql = `owner_email = ?
|
|
73
92
|
AND ((org_id IS NULL AND CAST(? AS TEXT) IS NULL) OR org_id = ?)`;
|
|
93
|
+
const joinedScopeSql = `t.owner_email = ?
|
|
94
|
+
AND ((t.org_id IS NULL AND CAST(? AS TEXT) IS NULL) OR t.org_id = ?)`;
|
|
74
95
|
const scopeArgs = [scope.ownerEmail, scope.orgId, scope.orgId];
|
|
75
96
|
|
|
76
97
|
try {
|
|
@@ -178,6 +199,17 @@ export async function getTaskQueueStats(
|
|
|
178
199
|
),
|
|
179
200
|
}),
|
|
180
201
|
);
|
|
202
|
+
const waitingCampaigns = await readWaitingCampaignCount(
|
|
203
|
+
client,
|
|
204
|
+
joinedScopeSql,
|
|
205
|
+
scopeArgs,
|
|
206
|
+
);
|
|
207
|
+
const a2aStats = await readA2AContinuationStats(
|
|
208
|
+
client,
|
|
209
|
+
joinedScopeSql,
|
|
210
|
+
scopeArgs,
|
|
211
|
+
now,
|
|
212
|
+
);
|
|
181
213
|
|
|
182
214
|
return {
|
|
183
215
|
pending,
|
|
@@ -185,6 +217,8 @@ export async function getTaskQueueStats(
|
|
|
185
217
|
completed_last_hour: completedLastHour,
|
|
186
218
|
failed_last_hour: failedLastHour,
|
|
187
219
|
oldest_pending_age_seconds: oldestPendingAgeSeconds,
|
|
220
|
+
waiting_campaigns: waitingCampaigns,
|
|
221
|
+
...a2aStats,
|
|
188
222
|
recent_failures: recentFailures,
|
|
189
223
|
recent_tasks: recentTasks,
|
|
190
224
|
};
|
|
@@ -195,3 +229,115 @@ export async function getTaskQueueStats(
|
|
|
195
229
|
throw err;
|
|
196
230
|
}
|
|
197
231
|
}
|
|
232
|
+
|
|
233
|
+
async function readWaitingCampaignCount(
|
|
234
|
+
client: ReturnType<typeof getDbExec>,
|
|
235
|
+
scopeSql: string,
|
|
236
|
+
scopeArgs: Array<string | null>,
|
|
237
|
+
): Promise<number> {
|
|
238
|
+
try {
|
|
239
|
+
const result = await client.execute({
|
|
240
|
+
sql: `SELECT COUNT(*) AS c
|
|
241
|
+
FROM integration_campaigns c
|
|
242
|
+
INNER JOIN integration_pending_tasks t
|
|
243
|
+
ON t.id = c.integration_task_id
|
|
244
|
+
WHERE ${scopeSql}
|
|
245
|
+
AND c.status = 'waiting'`,
|
|
246
|
+
args: scopeArgs,
|
|
247
|
+
});
|
|
248
|
+
return Number(result.rows[0]?.c ?? 0);
|
|
249
|
+
} catch (err) {
|
|
250
|
+
if (isMissingTableError(err)) return 0;
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function readA2AContinuationStats(
|
|
256
|
+
client: ReturnType<typeof getDbExec>,
|
|
257
|
+
scopeSql: string,
|
|
258
|
+
scopeArgs: Array<string | null>,
|
|
259
|
+
now: number,
|
|
260
|
+
): Promise<
|
|
261
|
+
Pick<
|
|
262
|
+
TaskQueueStats,
|
|
263
|
+
| "active_a2a_continuations"
|
|
264
|
+
| "oldest_active_a2a_age_seconds"
|
|
265
|
+
| "terminal_a2a_without_delivery"
|
|
266
|
+
| "recent_a2a_orphans"
|
|
267
|
+
>
|
|
268
|
+
> {
|
|
269
|
+
try {
|
|
270
|
+
const live = await client.execute({
|
|
271
|
+
sql: `SELECT
|
|
272
|
+
COUNT(CASE WHEN c.status IN ('pending', 'processing', 'delivering') THEN 1 END) AS active_count,
|
|
273
|
+
MIN(CASE WHEN c.status IN ('pending', 'processing', 'delivering') THEN c.created_at END) AS oldest_created_at,
|
|
274
|
+
COUNT(CASE WHEN c.status IN ('completed', 'failed')
|
|
275
|
+
AND c.terminal_delivery_confirmed_at IS NULL THEN 1 END) AS orphan_count
|
|
276
|
+
FROM integration_a2a_continuations c
|
|
277
|
+
INNER JOIN integration_pending_tasks t
|
|
278
|
+
ON t.id = c.integration_task_id
|
|
279
|
+
WHERE ${scopeSql}`,
|
|
280
|
+
args: scopeArgs,
|
|
281
|
+
});
|
|
282
|
+
const orphaned = await client.execute({
|
|
283
|
+
sql: `SELECT c.id, c.integration_task_id, c.status, c.attempts,
|
|
284
|
+
c.created_at, c.error_message
|
|
285
|
+
FROM integration_a2a_continuations c
|
|
286
|
+
INNER JOIN integration_pending_tasks t
|
|
287
|
+
ON t.id = c.integration_task_id
|
|
288
|
+
WHERE ${scopeSql}
|
|
289
|
+
AND c.status IN ('completed', 'failed')
|
|
290
|
+
AND c.terminal_delivery_confirmed_at IS NULL
|
|
291
|
+
ORDER BY c.updated_at DESC
|
|
292
|
+
LIMIT 5`,
|
|
293
|
+
args: scopeArgs,
|
|
294
|
+
});
|
|
295
|
+
const activeCount = Number(live.rows[0]?.active_count ?? 0);
|
|
296
|
+
const orphanCount = Number(live.rows[0]?.orphan_count ?? 0);
|
|
297
|
+
const oldestCreatedAt = Number(live.rows[0]?.oldest_created_at ?? now);
|
|
298
|
+
const recentOrphans = (orphaned.rows as Array<Record<string, unknown>>).map(
|
|
299
|
+
(row) => ({
|
|
300
|
+
continuation_id: String(row.id ?? ""),
|
|
301
|
+
integration_task_id: String(row.integration_task_id ?? ""),
|
|
302
|
+
status: String(row.status ?? ""),
|
|
303
|
+
attempts: Number(row.attempts ?? 0),
|
|
304
|
+
age_seconds: Math.max(
|
|
305
|
+
0,
|
|
306
|
+
Math.floor((now - Number(row.created_at ?? now)) / 1000),
|
|
307
|
+
),
|
|
308
|
+
reason_class: classifyA2AOrphanReason(row.error_message),
|
|
309
|
+
}),
|
|
310
|
+
);
|
|
311
|
+
return {
|
|
312
|
+
active_a2a_continuations: activeCount,
|
|
313
|
+
oldest_active_a2a_age_seconds:
|
|
314
|
+
activeCount > 0
|
|
315
|
+
? Math.max(0, Math.floor((now - oldestCreatedAt) / 1000))
|
|
316
|
+
: 0,
|
|
317
|
+
terminal_a2a_without_delivery: orphanCount,
|
|
318
|
+
recent_a2a_orphans: recentOrphans,
|
|
319
|
+
};
|
|
320
|
+
} catch (err) {
|
|
321
|
+
if (isMissingTableError(err)) {
|
|
322
|
+
return {
|
|
323
|
+
active_a2a_continuations: 0,
|
|
324
|
+
oldest_active_a2a_age_seconds: 0,
|
|
325
|
+
terminal_a2a_without_delivery: 0,
|
|
326
|
+
recent_a2a_orphans: [],
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
throw err;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function classifyA2AOrphanReason(value: unknown): string {
|
|
334
|
+
const message = String(value ?? "");
|
|
335
|
+
if (!message) return "missing_terminal_delivery";
|
|
336
|
+
if (/timeout|timed out|abort/i.test(message)) return "timeout";
|
|
337
|
+
if (/token|secret|auth|credential/i.test(message)) return "authentication";
|
|
338
|
+
if (/database|sql|store|persist/i.test(message)) return "persistence";
|
|
339
|
+
if (/slack|provider|deliver|stream|response/i.test(message)) {
|
|
340
|
+
return "provider_delivery";
|
|
341
|
+
}
|
|
342
|
+
return "processor_failure";
|
|
343
|
+
}
|
|
@@ -134,6 +134,19 @@ export interface PlatformDeliveryReceipt {
|
|
|
134
134
|
messageRefs?: string[];
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
export interface PlatformDeliveryOptions {
|
|
138
|
+
/** Provider-owned message reference that should be updated in place. */
|
|
139
|
+
placeholderRef?: string;
|
|
140
|
+
/** Stable logical delivery key for provider-side retry reconciliation. */
|
|
141
|
+
idempotencyKey?: string;
|
|
142
|
+
/** Earliest provider timestamp (epoch ms) that can contain this delivery. */
|
|
143
|
+
reconcileAfter?: number;
|
|
144
|
+
/** Abort provider I/O before the caller releases its durable delivery claim. */
|
|
145
|
+
signal?: AbortSignal;
|
|
146
|
+
/** Do not fall back to a fresh post if the stable target cannot be updated. */
|
|
147
|
+
strictTargetRef?: boolean;
|
|
148
|
+
}
|
|
149
|
+
|
|
137
150
|
/**
|
|
138
151
|
* Proactive outbound message target for a platform.
|
|
139
152
|
* Used when the agent needs to send to a saved destination instead of replying
|
|
@@ -201,12 +214,20 @@ export interface PlatformRunProgress {
|
|
|
201
214
|
* credentials, or provider payload.
|
|
202
215
|
*/
|
|
203
216
|
ref?: PlatformRunProgressRef;
|
|
217
|
+
/** Stable provider message target that can receive the terminal answer. */
|
|
218
|
+
responseTargetRef?: string;
|
|
204
219
|
/** Receive normalized agent events. Implementations should throttle writes. */
|
|
205
|
-
onEvent(
|
|
220
|
+
onEvent(
|
|
221
|
+
event: AgentChatEvent,
|
|
222
|
+
opts?: { signal?: AbortSignal },
|
|
223
|
+
): Promise<void> | void;
|
|
206
224
|
/** Finalize the provider-native progress surface with the answer. */
|
|
207
|
-
complete(
|
|
225
|
+
complete(
|
|
226
|
+
message: OutgoingMessage,
|
|
227
|
+
opts?: { signal?: AbortSignal },
|
|
228
|
+
): Promise<void | PlatformDeliveryReceipt>;
|
|
208
229
|
/** Mark the provider-native surface failed and leave a retryable explanation. */
|
|
209
|
-
fail?(message: string): Promise<void>;
|
|
230
|
+
fail?(message: string, opts?: { signal?: AbortSignal }): Promise<void>;
|
|
210
231
|
}
|
|
211
232
|
|
|
212
233
|
/**
|
|
@@ -322,7 +343,7 @@ export interface PlatformAdapter {
|
|
|
322
343
|
sendResponse(
|
|
323
344
|
message: OutgoingMessage,
|
|
324
345
|
context: IncomingMessage,
|
|
325
|
-
opts?:
|
|
346
|
+
opts?: PlatformDeliveryOptions,
|
|
326
347
|
): Promise<void | PlatformDeliveryReceipt>;
|
|
327
348
|
|
|
328
349
|
/**
|
|
@@ -35,7 +35,11 @@ import {
|
|
|
35
35
|
appendDurableContinuationContext,
|
|
36
36
|
runAgentLoopDirectWithSoftTimeout,
|
|
37
37
|
} from "../agent/run-loop-with-resume.js";
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
startRun,
|
|
40
|
+
type ActiveRun,
|
|
41
|
+
type StartRunOptions,
|
|
42
|
+
} from "../agent/run-manager.js";
|
|
39
43
|
import {
|
|
40
44
|
buildCurrentTimeUserContext,
|
|
41
45
|
buildRuntimeContextPrompt,
|
|
@@ -63,7 +67,8 @@ import {
|
|
|
63
67
|
import { runWithRequestContext } from "../server/request-context.js";
|
|
64
68
|
import { normalizeReasoningEffortForRequest } from "../shared/reasoning-effort.js";
|
|
65
69
|
import { A2A_CONTINUATION_QUEUED_MARKER } from "./a2a-continuation-marker.js";
|
|
66
|
-
import {
|
|
70
|
+
import { reconcileTerminalA2AParentIfDisabled } from "./a2a-continuation-processor.js";
|
|
71
|
+
import { getA2AContinuationTaskOutcome } from "./a2a-continuations-store.js";
|
|
67
72
|
import {
|
|
68
73
|
clearIntegrationAwaitingInput,
|
|
69
74
|
setIntegrationAwaitingInput,
|
|
@@ -1082,10 +1087,22 @@ async function processIncomingMessage(
|
|
|
1082
1087
|
JSON.parse(campaign.row.checkpoint).waitingForA2A === true;
|
|
1083
1088
|
} catch {}
|
|
1084
1089
|
if (waitingForA2A) {
|
|
1085
|
-
const
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1090
|
+
const a2aOutcome = await getA2AContinuationTaskOutcome(opts.taskId);
|
|
1091
|
+
if (a2aOutcome !== "terminal-delivered") {
|
|
1092
|
+
if (
|
|
1093
|
+
a2aOutcome === "terminal-without-delivery" &&
|
|
1094
|
+
(await reconcileTerminalA2AParentIfDisabled(opts.taskId))
|
|
1095
|
+
) {
|
|
1096
|
+
await releaseApplicableIntegrationBudgets(
|
|
1097
|
+
budgetReservations.reservations,
|
|
1098
|
+
);
|
|
1099
|
+
return { status: "campaign-failed" };
|
|
1100
|
+
}
|
|
1101
|
+
if (a2aOutcome !== "active") {
|
|
1102
|
+
console.warn(
|
|
1103
|
+
`[integrations] Waiting campaign ${campaign.row.id} has A2A outcome ${a2aOutcome} without terminal delivery proof`,
|
|
1104
|
+
);
|
|
1105
|
+
}
|
|
1089
1106
|
const waiting = await waitForA2AIntegrationCampaign(campaign.row.id, {
|
|
1090
1107
|
runId: campaign.runId,
|
|
1091
1108
|
leaseToken: campaign.leaseToken,
|
|
@@ -1211,6 +1228,26 @@ async function processIncomingMessage(
|
|
|
1211
1228
|
let usage: Awaited<ReturnType<typeof runAgentLoop>> | null = null;
|
|
1212
1229
|
let budgetsSettled = false;
|
|
1213
1230
|
|
|
1231
|
+
// Populated once `resolvedModel`/`engine` are known inside the run
|
|
1232
|
+
// callback below (stored-model + platform-default resolution can't happen
|
|
1233
|
+
// until then) and read back by run-manager's terminal tracking event via
|
|
1234
|
+
// this same object reference — `startRun` reads `options.model` only in
|
|
1235
|
+
// its `.finally()`, after this callback has settled, so the mutation is
|
|
1236
|
+
// guaranteed to land before it's read.
|
|
1237
|
+
const runOptions: StartRunOptions = {
|
|
1238
|
+
useHostedSoftTimeoutDefault: true,
|
|
1239
|
+
backgroundFunction: isInBackgroundFunctionRuntime(),
|
|
1240
|
+
...(campaign
|
|
1241
|
+
? {
|
|
1242
|
+
turnId: campaign.row.turnId,
|
|
1243
|
+
noProgressTimeoutMs: INTEGRATION_CAMPAIGN_NO_PROGRESS_TIMEOUT_MS,
|
|
1244
|
+
}
|
|
1245
|
+
: {}),
|
|
1246
|
+
// No userId here: `ownerEmail` is PII (email), which the terminal event
|
|
1247
|
+
// must not carry.
|
|
1248
|
+
attemptCount: opts.attempts,
|
|
1249
|
+
};
|
|
1250
|
+
|
|
1214
1251
|
// Wait for the run to complete inside this fresh function execution.
|
|
1215
1252
|
// We use a Promise so the processor endpoint can await the full lifecycle.
|
|
1216
1253
|
return new Promise<ProcessIntegrationTaskResult>((resolve) => {
|
|
@@ -1283,6 +1320,8 @@ async function processIncomingMessage(
|
|
|
1283
1320
|
engine,
|
|
1284
1321
|
modelCandidate,
|
|
1285
1322
|
);
|
|
1323
|
+
runOptions.model = resolvedModel;
|
|
1324
|
+
runOptions.engineName = engine.name;
|
|
1286
1325
|
|
|
1287
1326
|
// Wrapper, not raw `runAgentLoop`: an integration turn has no
|
|
1288
1327
|
// browser to re-POST a continuation, so a transport-level cut
|
|
@@ -1847,16 +1886,7 @@ async function processIncomingMessage(
|
|
|
1847
1886
|
// chains) with no visible answer. `isInBackgroundFunctionRuntime()` is
|
|
1848
1887
|
// the runtime proof — never a config guess — so the wider ceiling is
|
|
1849
1888
|
// taken only where the ~60s synchronous wall genuinely does not apply.
|
|
1850
|
-
|
|
1851
|
-
useHostedSoftTimeoutDefault: true,
|
|
1852
|
-
backgroundFunction: isInBackgroundFunctionRuntime(),
|
|
1853
|
-
...(campaign
|
|
1854
|
-
? {
|
|
1855
|
-
turnId: campaign.row.turnId,
|
|
1856
|
-
noProgressTimeoutMs: INTEGRATION_CAMPAIGN_NO_PROGRESS_TIMEOUT_MS,
|
|
1857
|
-
}
|
|
1858
|
-
: {}),
|
|
1859
|
-
},
|
|
1889
|
+
runOptions,
|
|
1860
1890
|
);
|
|
1861
1891
|
});
|
|
1862
1892
|
}
|
|
@@ -692,6 +692,10 @@ async function executeJob(
|
|
|
692
692
|
// streams a job, so it gets reaped mid-flight.
|
|
693
693
|
dispatchMode: "background",
|
|
694
694
|
// turnId defaults to runId — fine for single-turn jobs
|
|
695
|
+
// No userId here: `jobUserEmail` is PII (email), which the
|
|
696
|
+
// terminal event must not carry.
|
|
697
|
+
model,
|
|
698
|
+
engineName: engine.name,
|
|
695
699
|
},
|
|
696
700
|
);
|
|
697
701
|
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
// templates ship as verbatim copy-only scaffolding (.ts), so their compiled
|
|
5
5
|
// .js never exists in dist.
|
|
6
6
|
const messages = {
|
|
7
|
+
workspaceFile: {
|
|
8
|
+
download: "Download",
|
|
9
|
+
},
|
|
7
10
|
home: {
|
|
8
11
|
settingsTitle: "Settings",
|
|
9
12
|
settingsDescription: "Language and agent preferences",
|
|
@@ -867,8 +870,6 @@ const messages = {
|
|
|
867
870
|
"This provider usually requires an OAuth setup. Follow the provider docs, or add an Authorization header if your endpoint supports token-based access.",
|
|
868
871
|
personal: "Personal",
|
|
869
872
|
organization: "Organization",
|
|
870
|
-
orgNoOrg: "Join an organization to share MCP servers",
|
|
871
|
-
orgAdminOnly: "Only owners and admins can add org-scope servers",
|
|
872
873
|
serverNameRequired: "Enter a server name before connecting with OAuth.",
|
|
873
874
|
serverName: "Server name",
|
|
874
875
|
url: "URL",
|
|
@@ -74,12 +74,25 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
74
74
|
llmSpanId: string;
|
|
75
75
|
engineName: string | undefined;
|
|
76
76
|
model: string;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Undefined means the engine never reported a usage figure for this run
|
|
79
|
+
* (e.g. killed for silence before any provider response arrived) — not
|
|
80
|
+
* that the count was zero. Callers must omit these from the emitted event
|
|
81
|
+
* rather than coerce to 0; a coerced 0 is indistinguishable from a real
|
|
82
|
+
* empty-input run and defeats analysis of failing runs by input size.
|
|
83
|
+
*/
|
|
84
|
+
inputTokens: number | undefined;
|
|
85
|
+
outputTokens: number | undefined;
|
|
86
|
+
cacheReadTokens: number | undefined;
|
|
87
|
+
cacheWriteTokens: number | undefined;
|
|
88
|
+
/** Same "unknown vs zero" rule as the token fields — cost is derived from
|
|
89
|
+
* them and is equally unmeasurable when they were never reported. */
|
|
90
|
+
costCentsX100: number | undefined;
|
|
82
91
|
durationMs: number;
|
|
92
|
+
/** Elapsed ms from run start to the first non-heartbeat engine event.
|
|
93
|
+
* Undefined when no such event ever arrived (the run never produced a
|
|
94
|
+
* token before being aborted) — never coerced to 0. */
|
|
95
|
+
firstTokenMs: number | undefined;
|
|
83
96
|
status: "success" | "error";
|
|
84
97
|
errorMessage: string | null;
|
|
85
98
|
toolCalls: number;
|
|
@@ -102,7 +115,14 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
102
115
|
modelSelectionSource?: string;
|
|
103
116
|
}): void {
|
|
104
117
|
const provider = llmProviderFromEngine(args.engineName, args.model);
|
|
105
|
-
const costUsd =
|
|
118
|
+
const costUsd =
|
|
119
|
+
args.costCentsX100 !== undefined
|
|
120
|
+
? costUsdFromCenticents(args.costCentsX100)
|
|
121
|
+
: undefined;
|
|
122
|
+
const totalTokens =
|
|
123
|
+
args.inputTokens !== undefined && args.outputTokens !== undefined
|
|
124
|
+
? args.inputTokens + args.outputTokens
|
|
125
|
+
: undefined;
|
|
106
126
|
const error = args.errorMessage ?? undefined;
|
|
107
127
|
const properties: Record<string, unknown> = {
|
|
108
128
|
...trackingIdentityProperties(),
|
|
@@ -116,12 +136,13 @@ function emitLlmGenerationTrackingEvent(args: {
|
|
|
116
136
|
provider,
|
|
117
137
|
input_tokens: args.inputTokens,
|
|
118
138
|
output_tokens: args.outputTokens,
|
|
119
|
-
total_tokens:
|
|
139
|
+
total_tokens: totalTokens,
|
|
120
140
|
cache_read_tokens: args.cacheReadTokens,
|
|
121
141
|
cache_write_tokens: args.cacheWriteTokens,
|
|
122
142
|
cost_cents_x100: args.costCentsX100,
|
|
123
143
|
cost_usd: costUsd,
|
|
124
144
|
duration_ms: args.durationMs,
|
|
145
|
+
time_to_first_token_ms: args.firstTokenMs,
|
|
125
146
|
status: args.status,
|
|
126
147
|
tool_calls: args.toolCalls,
|
|
127
148
|
successful_tools: args.successfulTools,
|
|
@@ -643,6 +664,16 @@ export async function instrumentAgentLoop(opts: {
|
|
|
643
664
|
cacheWriteTokens: 0,
|
|
644
665
|
model: loopOpts.model,
|
|
645
666
|
};
|
|
667
|
+
// The engine never reported a `usage` event for this run (killed for
|
|
668
|
+
// silence before any provider response, or the loop threw before
|
|
669
|
+
// returning). `generationUsage`'s token fields are placeholder zeros in
|
|
670
|
+
// that case, not measured values — the tracking event below must omit
|
|
671
|
+
// them rather than report a fabricated 0.
|
|
672
|
+
const usageReported = usage?.usageReported === true;
|
|
673
|
+
const firstTokenMs =
|
|
674
|
+
usage?.firstEngineEventAtMs !== undefined
|
|
675
|
+
? Math.max(0, usage.firstEngineEventAtMs - runStart)
|
|
676
|
+
: undefined;
|
|
646
677
|
const llmSpanId = spanId();
|
|
647
678
|
const llmSpan: TraceSpan = {
|
|
648
679
|
id: llmSpanId,
|
|
@@ -675,12 +706,17 @@ export async function instrumentAgentLoop(opts: {
|
|
|
675
706
|
? loopOpts.engine.name
|
|
676
707
|
: undefined,
|
|
677
708
|
model: generationUsage.model,
|
|
678
|
-
inputTokens: generationUsage.inputTokens,
|
|
679
|
-
outputTokens: generationUsage.outputTokens,
|
|
680
|
-
cacheReadTokens:
|
|
681
|
-
|
|
682
|
-
|
|
709
|
+
inputTokens: usageReported ? generationUsage.inputTokens : undefined,
|
|
710
|
+
outputTokens: usageReported ? generationUsage.outputTokens : undefined,
|
|
711
|
+
cacheReadTokens: usageReported
|
|
712
|
+
? generationUsage.cacheReadTokens
|
|
713
|
+
: undefined,
|
|
714
|
+
cacheWriteTokens: usageReported
|
|
715
|
+
? generationUsage.cacheWriteTokens
|
|
716
|
+
: undefined,
|
|
717
|
+
costCentsX100: usageReported ? costCentsX100 : undefined,
|
|
683
718
|
durationMs: totalDurationMs,
|
|
719
|
+
firstTokenMs,
|
|
684
720
|
status: runStatus,
|
|
685
721
|
errorMessage,
|
|
686
722
|
toolCalls: toolCallCount,
|
|
@@ -47,6 +47,7 @@ import { setActiveOrgId } from "./active-org.js";
|
|
|
47
47
|
import { getOrgContext, createOrganization } from "./context.js";
|
|
48
48
|
import { isFreeEmailProvider } from "./free-email-providers.js";
|
|
49
49
|
import type { OrgRole } from "./types.js";
|
|
50
|
+
import { parseWorkspaceUrl } from "./workspace-url.js";
|
|
50
51
|
|
|
51
52
|
function getInviteAppUrl(event: H3Event): string {
|
|
52
53
|
return getAppProductionUrl(event);
|
|
@@ -108,16 +109,19 @@ export const getMyOrgHandler = defineEventHandler(async (event: H3Event) => {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
let allowedDomain: string | null = null;
|
|
112
|
+
let workspaceUrl: string | null = null;
|
|
111
113
|
let a2aSecretSet = false;
|
|
112
114
|
if (ctx.orgId) {
|
|
113
115
|
try {
|
|
114
116
|
const adRes = await e.execute({
|
|
115
|
-
sql: `SELECT allowed_domain, a2a_secret FROM organizations WHERE id = ? LIMIT 1`,
|
|
117
|
+
sql: `SELECT allowed_domain, a2a_secret, workspace_url FROM organizations WHERE id = ? LIMIT 1`,
|
|
116
118
|
args: [ctx.orgId],
|
|
117
119
|
});
|
|
118
120
|
if (adRes.rows[0]) {
|
|
119
121
|
allowedDomain =
|
|
120
122
|
String((adRes.rows[0] as any).allowed_domain ?? "") || null;
|
|
123
|
+
workspaceUrl =
|
|
124
|
+
String((adRes.rows[0] as any).workspace_url ?? "") || null;
|
|
121
125
|
a2aSecretSet = Boolean(
|
|
122
126
|
String((adRes.rows[0] as any).a2a_secret ?? "").trim(),
|
|
123
127
|
);
|
|
@@ -156,6 +160,7 @@ export const getMyOrgHandler = defineEventHandler(async (event: H3Event) => {
|
|
|
156
160
|
pendingInvitations,
|
|
157
161
|
domainMatches,
|
|
158
162
|
allowedDomain,
|
|
163
|
+
workspaceUrl,
|
|
159
164
|
// Never serialize the A2A secret here. This route runs on every page load,
|
|
160
165
|
// so the value would sit in JSON any script on the page can read, and it
|
|
161
166
|
// signs the JWTs peers accept as first-party callers. Reveal is an explicit
|
|
@@ -954,6 +959,52 @@ export const setDomainHandler = defineEventHandler(async (event: H3Event) => {
|
|
|
954
959
|
return { domain: raw };
|
|
955
960
|
});
|
|
956
961
|
|
|
962
|
+
/**
|
|
963
|
+
* PUT /_agent-native/org/workspace-url — set or clear the org's own workspace
|
|
964
|
+
* origin (owner/admin only).
|
|
965
|
+
*
|
|
966
|
+
* Members who reach a shared hosted app from the template catalog land in a
|
|
967
|
+
* different deployment than their team's workspace, with the same org name in
|
|
968
|
+
* the switcher, and read the empty app as broken rather than as somewhere
|
|
969
|
+
* else. Setting this points them home from wherever they land.
|
|
970
|
+
*
|
|
971
|
+
* Body: { url: string | null } — a full URL or bare host; stored as an origin.
|
|
972
|
+
*/
|
|
973
|
+
export const setWorkspaceUrlHandler = defineEventHandler(
|
|
974
|
+
async (event: H3Event) => {
|
|
975
|
+
const ctx = await getOrgContext(event);
|
|
976
|
+
if (!ctx.orgId) {
|
|
977
|
+
throw createError({ statusCode: 400, message: "No active organization" });
|
|
978
|
+
}
|
|
979
|
+
if (ctx.role !== "owner" && ctx.role !== "admin") {
|
|
980
|
+
throw createError({
|
|
981
|
+
statusCode: 403,
|
|
982
|
+
message: "Only owners and admins can set the workspace URL",
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
const body = await readBody(event);
|
|
987
|
+
const raw = typeof body?.url === "string" ? body.url.trim() : "";
|
|
988
|
+
|
|
989
|
+
let workspaceUrl: string | null = null;
|
|
990
|
+
if (raw) {
|
|
991
|
+
const parsed = parseWorkspaceUrl(raw);
|
|
992
|
+
if (!parsed.ok) {
|
|
993
|
+
throw createError({ statusCode: 400, message: parsed.reason });
|
|
994
|
+
}
|
|
995
|
+
workspaceUrl = parsed.url;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
const e = await exec();
|
|
999
|
+
await e.execute({
|
|
1000
|
+
sql: `UPDATE organizations SET workspace_url = ? WHERE id = ?`,
|
|
1001
|
+
args: [workspaceUrl, ctx.orgId],
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
return { url: workspaceUrl };
|
|
1005
|
+
},
|
|
1006
|
+
);
|
|
1007
|
+
|
|
957
1008
|
/**
|
|
958
1009
|
* GET /_agent-native/org/a2a-secret — reveal the org's A2A secret
|
|
959
1010
|
* (owner/admin only). Separate from `/org/me` so the secret is only ever sent
|
|
@@ -124,4 +124,8 @@ export const ORG_MIGRATIONS = [
|
|
|
124
124
|
sql: `CREATE UNIQUE INDEX IF NOT EXISTS app_member_roles_org_app_lower_email_uidx
|
|
125
125
|
ON app_member_roles (org_id, app_id, LOWER(email))`,
|
|
126
126
|
},
|
|
127
|
+
{
|
|
128
|
+
version: 1013,
|
|
129
|
+
sql: `ALTER TABLE organizations ADD COLUMN IF NOT EXISTS workspace_url TEXT`,
|
|
130
|
+
},
|
|
127
131
|
];
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
acceptInvitationHandler,
|
|
32
32
|
joinByDomainHandler,
|
|
33
33
|
setDomainHandler,
|
|
34
|
+
setWorkspaceUrlHandler,
|
|
34
35
|
revealA2ASecretHandler,
|
|
35
36
|
setA2ASecretHandler,
|
|
36
37
|
syncA2ASecretHandler,
|
|
@@ -61,6 +62,7 @@ const ORG_PREFIX = `${FRAMEWORK_PREFIX}/org`;
|
|
|
61
62
|
* POST /_agent-native/org/invitations/:id/accept — accept an invitation
|
|
62
63
|
* POST /_agent-native/org/join-by-domain — join org via email domain match
|
|
63
64
|
* PUT /_agent-native/org/domain — set/clear allowed email domain (owner/admin)
|
|
65
|
+
* PUT /_agent-native/org/workspace-url — set/clear the org's workspace origin (owner/admin)
|
|
64
66
|
* GET /_agent-native/org/a2a-secret — reveal A2A secret on demand (owner/admin)
|
|
65
67
|
* PUT /_agent-native/org/a2a-secret — regenerate or set A2A secret (owner/admin)
|
|
66
68
|
* POST /_agent-native/org/a2a-secret/sync — push secret to all connected apps (owner/admin)
|
|
@@ -251,6 +253,18 @@ export function createOrgPlugin(): NitroPluginDef {
|
|
|
251
253
|
}),
|
|
252
254
|
);
|
|
253
255
|
|
|
256
|
+
// PUT /workspace-url
|
|
257
|
+
app.use(
|
|
258
|
+
`${ORG_PREFIX}/workspace-url`,
|
|
259
|
+
defineEventHandler(async (event: H3Event) => {
|
|
260
|
+
if (getMethod(event) !== "PUT") {
|
|
261
|
+
setResponseStatus(event, 405);
|
|
262
|
+
return { error: "Method not allowed" };
|
|
263
|
+
}
|
|
264
|
+
return setWorkspaceUrlHandler(event);
|
|
265
|
+
}),
|
|
266
|
+
);
|
|
267
|
+
|
|
254
268
|
// PUT /switch
|
|
255
269
|
app.use(
|
|
256
270
|
`${ORG_PREFIX}/switch`,
|
|
@@ -7,6 +7,7 @@ export const organizations = table("organizations", {
|
|
|
7
7
|
createdAt: integer("created_at").notNull(),
|
|
8
8
|
allowedDomain: text("allowed_domain"),
|
|
9
9
|
a2aSecret: text("a2a_secret"),
|
|
10
|
+
workspaceUrl: text("workspace_url"),
|
|
10
11
|
});
|
|
11
12
|
|
|
12
13
|
export const orgMembers = table("org_members", {
|
|
@@ -38,6 +38,14 @@ export interface OrgInfo {
|
|
|
38
38
|
pendingInvitations: OrgInvitationSummary[];
|
|
39
39
|
domainMatches: DomainMatchOrg[];
|
|
40
40
|
allowedDomain: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Origin of the org's own workspace deployment, when it runs one. Members
|
|
43
|
+
* who land on a different host (a shared hosted app reached from the
|
|
44
|
+
* template catalog) get pointed here instead of concluding their team's
|
|
45
|
+
* apps are missing. Null for the common case of an org with no separate
|
|
46
|
+
* workspace.
|
|
47
|
+
*/
|
|
48
|
+
workspaceUrl: string | null;
|
|
41
49
|
/**
|
|
42
50
|
* Whether the active org has an A2A secret. The value itself is never part
|
|
43
51
|
* of this payload — owners/admins fetch it on demand from
|