@agent-native/core 0.128.3 → 0.129.0
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 +91 -0
- package/corpus/core/docs/content/template-design-collaboration-and-full-apps.mdx +3 -1
- package/corpus/core/package.json +6 -3
- package/corpus/core/src/a2a/client.ts +18 -4
- package/corpus/core/src/a2a/server.ts +19 -3
- package/corpus/core/src/a2a/types.ts +7 -0
- package/corpus/core/src/action.ts +43 -16
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +14 -10
- package/corpus/core/src/agent/production-agent.ts +41 -3
- package/corpus/core/src/agent/thread-data-builder.ts +5 -0
- package/corpus/core/src/chat-threads/migrations.ts +53 -0
- package/corpus/core/src/cli/create.ts +4 -0
- package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +36 -16
- package/corpus/core/src/cli/skills.ts +16 -0
- package/corpus/core/src/client/AgentPanel.tsx +9 -5
- package/corpus/core/src/client/AssistantChat.tsx +138 -46
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +16 -10
- package/corpus/core/src/client/agent-chat-adapter.ts +21 -3
- package/corpus/core/src/client/analytics.ts +159 -102
- package/corpus/core/src/client/chat/legacy-chart-shorthand.tsx +479 -0
- package/corpus/core/src/client/chat/markdown-renderer.tsx +23 -3
- package/corpus/core/src/client/chat/message-components.tsx +12 -5
- package/corpus/core/src/client/chat/runtime.ts +2 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +25 -2
- package/corpus/core/src/client/chat-model-groups.ts +3 -0
- package/corpus/core/src/client/client-status-requests.ts +161 -0
- package/corpus/core/src/client/settings/VoiceTranscriptionSection.tsx +2 -2
- package/corpus/core/src/client/sse-event-processor.ts +15 -3
- package/corpus/core/src/client/use-agent-engine-configured.ts +54 -50
- package/corpus/core/src/client/use-chat-models.ts +16 -11
- package/corpus/core/src/client/use-chat-threads.ts +32 -9
- package/corpus/core/src/client/use-session.ts +4 -5
- package/corpus/core/src/db/client.ts +83 -8
- package/corpus/core/src/db/ensure-additive-columns.ts +31 -20
- package/corpus/core/src/db/migrations.ts +22 -2
- package/corpus/core/src/extensions/actions.ts +1 -1
- package/corpus/core/src/mcp/approval-store.ts +99 -0
- package/corpus/core/src/mcp/build-server.ts +579 -303
- package/corpus/core/src/mcp/embed-app.ts +1 -1
- package/corpus/core/src/mcp/oauth-client-metadata.ts +380 -0
- package/corpus/core/src/mcp/oauth-route.ts +57 -52
- package/corpus/core/src/mcp/screen-memory-stdio.ts +400 -378
- package/corpus/core/src/mcp/server.ts +29 -145
- package/corpus/core/src/mcp/stdio.ts +72 -80
- package/corpus/core/src/mcp-client/manager.ts +6 -10
- package/corpus/core/src/mcp-client/oauth-client.ts +127 -36
- package/corpus/core/src/mcp-client/oauth-routes.ts +16 -6
- package/corpus/core/src/mcp-client/routes.ts +6 -5
- package/corpus/core/src/server/agent-capabilities.ts +20 -0
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +27 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +18 -0
- package/corpus/core/src/server/transcribe-voice.ts +14 -5
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +13 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +12 -0
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/analytics/actions/generate-chart.ts +2 -2
- package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +1 -10
- package/corpus/templates/analytics/app/global.css +0 -31
- package/corpus/templates/analytics/app/lib/sql-query.ts +46 -20
- package/corpus/templates/analytics/changelog/2026-07-28-analytics-dashboard-loading-states-now-use-a-simpler-standar.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-28-analytics-dashboards-now-load-first-party-charts-reliably-in.md +6 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-cache.ts +42 -16
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +4 -2
- package/corpus/templates/analytics/shared/sql-query-limits.ts +1 -0
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/clips/app/components/player/player-controls.tsx +3 -6
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +6 -2
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -1
- package/corpus/templates/clips/changelog/2026-07-28-copied-share-links-no-longer-leave-an-unnecessary-confirmati.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-playback-skip-controls-no-longer-show-overlapping-numbers.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-public-clips-share-buttons-now-use-a-clean-text-only-label.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +14 -17
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +3 -1
- package/corpus/templates/clips/desktop/src/styles.css +13 -10
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +2 -2
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +36 -0
- package/corpus/templates/content/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +155 -34
- package/corpus/templates/content/actions/_builder-docs-client.ts +151 -30
- package/corpus/templates/content/actions/stage-builder-source-bulk-update.ts +5 -2
- package/corpus/templates/content/app/root.tsx +35 -14
- package/corpus/templates/content/changelog/2026-07-28-builder-backed-files-media-fields-now-accept-direct-file-url.md +6 -0
- package/corpus/templates/content/changelog/2026-07-28-builder-content-reads-now-negotiate-the-newest-mcp-protocol-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-28-public-content-pages-load-faster-before-the-optional-ask-sid.md +6 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +36 -16
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +42 -3
- package/corpus/templates/design/actions/open-visual-edit.ts +2 -1
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +14 -15
- package/corpus/templates/design/app/components/design/ResponsiveInteractBar.tsx +314 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +88 -3
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +7 -6
- package/corpus/templates/design/app/i18n-data.ts +56 -11
- package/corpus/templates/design/app/i18n-responsive-interact.ts +183 -0
- package/corpus/templates/design/app/lib/agent-chat.ts +60 -0
- package/corpus/templates/design/app/pages/design-editor/responsive-interact.ts +89 -0
- package/corpus/templates/design/changelog/2026-07-28-design-edits-can-be-applied-through-the-host-coding-agent-fr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-interact-mode-can-preview-designs-in-responsive-device-sizes.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-opens-a-full-screen-responsive-preview-wit.md +6 -0
- package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +2 -2
- package/corpus/templates/design/changelog/2026-07-28-visual-edit-now-always-shows-the-live-running-app-in-the-can.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +13 -2
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +13 -2
- package/corpus/toolkit/CHANGELOG.md +13 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/chat-history.css +1 -2
- package/corpus/toolkit/src/composer/TiptapComposer.tsx +45 -0
- package/dist/a2a/client.d.ts +7 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +8 -3
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +18 -3
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/types.d.ts +7 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/action.d.ts +15 -1
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +39 -16
- 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 +14 -10
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +35 -7
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +2 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +3 -0
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/chat-threads/migrations.d.ts +21 -0
- package/dist/chat-threads/migrations.d.ts.map +1 -0
- package/dist/chat-threads/migrations.js +45 -0
- package/dist/chat-threads/migrations.js.map +1 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +4 -0
- package/dist/cli/create.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 +36 -16
- package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +15 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -5
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +37 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +41 -8
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +11 -10
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +19 -3
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +150 -101
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/legacy-chart-shorthand.d.ts +29 -0
- package/dist/client/chat/legacy-chart-shorthand.d.ts.map +1 -0
- package/dist/client/chat/legacy-chart-shorthand.js +330 -0
- package/dist/client/chat/legacy-chart-shorthand.js.map +1 -0
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/client/chat/markdown-renderer.js +8 -2
- package/dist/client/chat/markdown-renderer.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +2 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +11 -4
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/runtime.d.ts.map +1 -1
- package/dist/client/chat/runtime.js +2 -1
- package/dist/client/chat/runtime.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +4 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +14 -8
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat-model-groups.d.ts.map +1 -1
- package/dist/client/chat-model-groups.js +3 -0
- package/dist/client/chat-model-groups.js.map +1 -1
- package/dist/client/client-status-requests.d.ts +14 -0
- package/dist/client/client-status-requests.d.ts.map +1 -0
- package/dist/client/client-status-requests.js +126 -0
- package/dist/client/client-status-requests.js.map +1 -0
- package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +7 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +8 -3
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +29 -43
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-chat-models.d.ts.map +1 -1
- package/dist/client/use-chat-models.js +11 -11
- package/dist/client/use-chat-models.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +23 -7
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-session.d.ts.map +1 -1
- package/dist/client/use-session.js +4 -4
- package/dist/client/use-session.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +48 -4
- package/dist/db/client.js.map +1 -1
- package/dist/db/ensure-additive-columns.d.ts.map +1 -1
- package/dist/db/ensure-additive-columns.js +32 -21
- package/dist/db/ensure-additive-columns.js.map +1 -1
- package/dist/db/migrations.d.ts +9 -0
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +14 -3
- package/dist/db/migrations.js.map +1 -1
- package/dist/extensions/actions.js +1 -1
- package/dist/extensions/actions.js.map +1 -1
- package/dist/mcp/approval-store.d.ts +16 -0
- package/dist/mcp/approval-store.d.ts.map +1 -0
- package/dist/mcp/approval-store.js +85 -0
- package/dist/mcp/approval-store.js.map +1 -0
- package/dist/mcp/build-server.d.ts +1 -34
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +220 -23
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/embed-app.js +1 -1
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/mcp/oauth-client-metadata.d.ts +15 -0
- package/dist/mcp/oauth-client-metadata.d.ts.map +1 -0
- package/dist/mcp/oauth-client-metadata.js +297 -0
- package/dist/mcp/oauth-client-metadata.js.map +1 -0
- package/dist/mcp/oauth-route.d.ts.map +1 -1
- package/dist/mcp/oauth-route.js +39 -53
- package/dist/mcp/oauth-route.js.map +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts.map +1 -1
- package/dist/mcp/screen-memory-stdio.js +304 -296
- package/dist/mcp/screen-memory-stdio.js.map +1 -1
- package/dist/mcp/server.d.ts +12 -25
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +24 -133
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts.map +1 -1
- package/dist/mcp/stdio.js +36 -35
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/mcp-client/manager.d.ts.map +1 -1
- package/dist/mcp-client/manager.js +6 -6
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/oauth-client.d.ts +13 -17
- package/dist/mcp-client/oauth-client.d.ts.map +1 -1
- package/dist/mcp-client/oauth-client.js +74 -16
- package/dist/mcp-client/oauth-client.js.map +1 -1
- package/dist/mcp-client/oauth-routes.d.ts +2 -2
- package/dist/mcp-client/oauth-routes.d.ts.map +1 -1
- package/dist/mcp-client/oauth-routes.js +16 -6
- package/dist/mcp-client/oauth-routes.js.map +1 -1
- package/dist/mcp-client/routes.js +5 -5
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-capabilities.d.ts.map +1 -1
- package/dist/server/agent-capabilities.js +21 -0
- package/dist/server/agent-capabilities.js.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.d.ts +14 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +16 -0
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +11 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/transcribe-voice.js +12 -6
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/templates/chat/.agents/skills/security/SKILL.md +13 -2
- package/dist/templates/default/.agents/skills/security/SKILL.md +13 -2
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
- package/docs/content/template-design-collaboration-and-full-apps.mdx +3 -1
- package/package.json +7 -4
- package/src/a2a/client.ts +18 -4
- package/src/a2a/server.ts +19 -3
- package/src/a2a/types.ts +7 -0
- package/src/action.ts +43 -16
- package/src/agent/engine/ai-sdk-engine.ts +14 -10
- package/src/agent/production-agent.ts +41 -3
- package/src/agent/thread-data-builder.ts +5 -0
- package/src/chat-threads/migrations.ts +53 -0
- package/src/cli/create.ts +4 -0
- package/src/cli/skills-content/design-visual-edit-skill.ts +36 -16
- package/src/cli/skills.ts +16 -0
- package/src/client/AgentPanel.tsx +9 -5
- package/src/client/AssistantChat.tsx +138 -46
- package/src/client/MultiTabAssistantChat.tsx +16 -10
- package/src/client/agent-chat-adapter.ts +21 -3
- package/src/client/analytics.ts +159 -102
- package/src/client/chat/legacy-chart-shorthand.tsx +479 -0
- package/src/client/chat/markdown-renderer.tsx +23 -3
- package/src/client/chat/message-components.tsx +12 -5
- package/src/client/chat/runtime.ts +2 -1
- package/src/client/chat/tool-call-display.tsx +25 -2
- package/src/client/chat-model-groups.ts +3 -0
- package/src/client/client-status-requests.ts +161 -0
- package/src/client/settings/VoiceTranscriptionSection.tsx +2 -2
- package/src/client/sse-event-processor.ts +15 -3
- package/src/client/use-agent-engine-configured.ts +54 -50
- package/src/client/use-chat-models.ts +16 -11
- package/src/client/use-chat-threads.ts +32 -9
- package/src/client/use-session.ts +4 -5
- package/src/db/client.ts +83 -8
- package/src/db/ensure-additive-columns.ts +31 -20
- package/src/db/migrations.ts +22 -2
- package/src/extensions/actions.ts +1 -1
- package/src/mcp/approval-store.ts +99 -0
- package/src/mcp/build-server.ts +579 -303
- package/src/mcp/embed-app.ts +1 -1
- package/src/mcp/oauth-client-metadata.ts +380 -0
- package/src/mcp/oauth-route.ts +57 -52
- package/src/mcp/screen-memory-stdio.ts +400 -378
- package/src/mcp/server.ts +29 -145
- package/src/mcp/stdio.ts +72 -80
- package/src/mcp-client/manager.ts +6 -10
- package/src/mcp-client/oauth-client.ts +127 -36
- package/src/mcp-client/oauth-routes.ts +16 -6
- package/src/mcp-client/routes.ts +6 -5
- package/src/server/agent-capabilities.ts +20 -0
- package/src/server/agent-chat/action-filters-a2a.ts +27 -0
- package/src/server/agent-chat-plugin.ts +18 -0
- package/src/server/transcribe-voice.ts +14 -5
- package/src/templates/chat/.agents/skills/security/SKILL.md +13 -2
- package/src/templates/default/.agents/skills/security/SKILL.md +13 -2
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { ToolCallMessagePartProps } from "@assistant-ui/react";
|
|
5
5
|
import {
|
|
6
6
|
IconLoader2,
|
|
7
|
+
IconAlertTriangle,
|
|
7
8
|
IconCircleX,
|
|
8
9
|
IconCheck,
|
|
9
10
|
IconChevronRight,
|
|
@@ -583,6 +584,7 @@ export function ToolCallDisplay({
|
|
|
583
584
|
mcpApp,
|
|
584
585
|
chatUI,
|
|
585
586
|
isRunning,
|
|
587
|
+
outcome,
|
|
586
588
|
structuredMeta,
|
|
587
589
|
approval,
|
|
588
590
|
repeatCount,
|
|
@@ -596,6 +598,8 @@ export function ToolCallDisplay({
|
|
|
596
598
|
mcpApp?: AgentMcpAppPayload;
|
|
597
599
|
chatUI?: ActionChatUIConfig;
|
|
598
600
|
isRunning: boolean;
|
|
601
|
+
/** "unknown": the stream ended mid-flight, so the side effect may have landed. */
|
|
602
|
+
outcome?: "unknown";
|
|
599
603
|
structuredMeta?: Record<string, unknown>;
|
|
600
604
|
approval?: { approvalKey: string; dismissed?: boolean };
|
|
601
605
|
repeatCount?: number;
|
|
@@ -661,6 +665,7 @@ export function ToolCallDisplay({
|
|
|
661
665
|
mcpApp={mcpApp}
|
|
662
666
|
chatUI={chatUI}
|
|
663
667
|
isRunning={isRunning}
|
|
668
|
+
outcome={outcome}
|
|
664
669
|
isActiveTail={showActiveTail}
|
|
665
670
|
structuredMeta={structuredMeta}
|
|
666
671
|
approval={approval}
|
|
@@ -677,6 +682,7 @@ function ToolCallDisplayGeneric({
|
|
|
677
682
|
mcpApp,
|
|
678
683
|
chatUI,
|
|
679
684
|
isRunning,
|
|
685
|
+
outcome,
|
|
680
686
|
isActiveTail,
|
|
681
687
|
structuredMeta,
|
|
682
688
|
approval,
|
|
@@ -689,6 +695,7 @@ function ToolCallDisplayGeneric({
|
|
|
689
695
|
mcpApp?: AgentMcpAppPayload;
|
|
690
696
|
chatUI?: ActionChatUIConfig;
|
|
691
697
|
isRunning: boolean;
|
|
698
|
+
outcome?: "unknown";
|
|
692
699
|
isActiveTail: boolean;
|
|
693
700
|
structuredMeta?: Record<string, unknown>;
|
|
694
701
|
approval?: { approvalKey: string; dismissed?: boolean };
|
|
@@ -704,6 +711,7 @@ function ToolCallDisplayGeneric({
|
|
|
704
711
|
? args.agent
|
|
705
712
|
: null;
|
|
706
713
|
const isAgentError = isAgentCall && result === "Error calling agent";
|
|
714
|
+
const isUnknownOutcome = !isRunning && outcome === "unknown";
|
|
707
715
|
const agentStreamText = isRawCallAgent
|
|
708
716
|
? (result ?? "")
|
|
709
717
|
: isAgentCall
|
|
@@ -865,6 +873,8 @@ function ToolCallDisplayGeneric({
|
|
|
865
873
|
<IconLoader2 className="size-3.5 animate-spin" />
|
|
866
874
|
) : isAgentError ? (
|
|
867
875
|
<IconCircleX className="size-3.5 text-destructive" />
|
|
876
|
+
) : isUnknownOutcome ? (
|
|
877
|
+
<IconAlertTriangle className="size-3.5 text-muted-foreground" />
|
|
868
878
|
) : (
|
|
869
879
|
<>
|
|
870
880
|
<ToolIcon
|
|
@@ -929,6 +939,12 @@ function ToolCallDisplayGeneric({
|
|
|
929
939
|
)}
|
|
930
940
|
</div>
|
|
931
941
|
</AnimatedCollapse>
|
|
942
|
+
{isUnknownOutcome && (
|
|
943
|
+
<p role="status" className="ps-5 text-xs text-muted-foreground">
|
|
944
|
+
Interrupted before this finished reporting — it may or may not have
|
|
945
|
+
completed. Check before retrying.
|
|
946
|
+
</p>
|
|
947
|
+
)}
|
|
932
948
|
{approval && (
|
|
933
949
|
<ApprovalAffordance toolName={toolName} approval={approval} />
|
|
934
950
|
)}
|
|
@@ -1149,14 +1165,19 @@ export function ToolCallFallback({
|
|
|
1149
1165
|
chatUI?: ActionChatUIConfig;
|
|
1150
1166
|
structuredMeta?: Record<string, unknown>;
|
|
1151
1167
|
activity?: boolean;
|
|
1168
|
+
outcome?: "unknown";
|
|
1152
1169
|
approval?: { approvalKey: string; dismissed?: boolean };
|
|
1153
1170
|
repeatCount?: number;
|
|
1154
1171
|
isLatestRunning?: boolean;
|
|
1155
1172
|
isActiveTail?: boolean;
|
|
1156
1173
|
}) {
|
|
1157
1174
|
const chatRunning = React.useContext(ChatRunningContext);
|
|
1158
|
-
|
|
1159
|
-
|
|
1175
|
+
// A spinner is a claim that something is running right now, so it needs an
|
|
1176
|
+
// actually-running chat. `chatRunning` already stays true across
|
|
1177
|
+
// auto-continuation gaps and server-active runs (resolveAssistantChatRunningState),
|
|
1178
|
+
// so an activity placeholder alone must never resurrect one on rehydrated
|
|
1179
|
+
// history.
|
|
1180
|
+
const isRunning = result === undefined && chatRunning;
|
|
1160
1181
|
return (
|
|
1161
1182
|
<ToolCallDisplay
|
|
1162
1183
|
toolName={toolName}
|
|
@@ -1173,6 +1194,7 @@ export function ToolCallFallback({
|
|
|
1173
1194
|
chatUI={rest.chatUI}
|
|
1174
1195
|
structuredMeta={rest.structuredMeta}
|
|
1175
1196
|
isRunning={isRunning}
|
|
1197
|
+
outcome={rest.outcome}
|
|
1176
1198
|
isActiveTail={rest.isActiveTail}
|
|
1177
1199
|
isLatestRunning={rest.isLatestRunning}
|
|
1178
1200
|
approval={rest.approval}
|
|
@@ -1247,6 +1269,7 @@ export function ReconnectStreamMessage({
|
|
|
1247
1269
|
mcpApp={part.mcpApp}
|
|
1248
1270
|
chatUI={part.chatUI}
|
|
1249
1271
|
structuredMeta={part.structuredMeta}
|
|
1272
|
+
outcome={part.outcome}
|
|
1250
1273
|
isRunning={
|
|
1251
1274
|
part.result === undefined && (chatRunning || part.activity === true)
|
|
1252
1275
|
}
|
|
@@ -40,6 +40,9 @@ function addCurrentModel(
|
|
|
40
40
|
return next;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// Cheapest → most expensive. The composer mirrors these tokens for the `$`
|
|
44
|
+
// cost labels on picker rows (packages/toolkit/src/composer/TiptapComposer.tsx);
|
|
45
|
+
// the toolkit cannot import core, so a new family must be added in both lists.
|
|
43
46
|
const MODEL_COST_ORDER = [
|
|
44
47
|
"luna",
|
|
45
48
|
"terra",
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { agentNativePath } from "./api-path.js";
|
|
2
|
+
|
|
3
|
+
export type ClientStatusResult<T> =
|
|
4
|
+
| { state: "available"; value: T }
|
|
5
|
+
| { state: "unavailable"; status?: number };
|
|
6
|
+
|
|
7
|
+
type CacheEntry = {
|
|
8
|
+
expiresAt: number;
|
|
9
|
+
result: ClientStatusResult<unknown>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const RESULT_TTL_MS = 500;
|
|
13
|
+
const REQUEST_TIMEOUT_MS = 15_000;
|
|
14
|
+
const cache = new Map<string, CacheEntry>();
|
|
15
|
+
const requests = new Map<string, Promise<ClientStatusResult<unknown>>>();
|
|
16
|
+
const requestControllers = new Map<string, AbortController>();
|
|
17
|
+
const requestGenerations = new Map<string, number>();
|
|
18
|
+
let invalidationListenersInstalled = false;
|
|
19
|
+
let generation = 0;
|
|
20
|
+
|
|
21
|
+
function expireClientStatusCache(): void {
|
|
22
|
+
generation += 1;
|
|
23
|
+
cache.clear();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function installInvalidationListeners(): void {
|
|
27
|
+
if (
|
|
28
|
+
invalidationListenersInstalled ||
|
|
29
|
+
typeof window === "undefined" ||
|
|
30
|
+
typeof document === "undefined"
|
|
31
|
+
) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
invalidationListenersInstalled = true;
|
|
35
|
+
|
|
36
|
+
if (typeof window.addEventListener === "function") {
|
|
37
|
+
window.addEventListener("focus", expireClientStatusCache);
|
|
38
|
+
window.addEventListener(
|
|
39
|
+
"agent-engine:configured-changed",
|
|
40
|
+
invalidateClientStatusRequests,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (typeof document.addEventListener === "function") {
|
|
44
|
+
document.addEventListener("visibilitychange", () => {
|
|
45
|
+
if (document.visibilityState === "visible") {
|
|
46
|
+
expireClientStatusCache();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function fetchClientStatus<T>(
|
|
53
|
+
path: string,
|
|
54
|
+
): Promise<ClientStatusResult<T>> {
|
|
55
|
+
installInvalidationListeners();
|
|
56
|
+
const url = agentNativePath(path);
|
|
57
|
+
const cached = cache.get(url);
|
|
58
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
59
|
+
return cached.result as ClientStatusResult<T>;
|
|
60
|
+
}
|
|
61
|
+
cache.delete(url);
|
|
62
|
+
|
|
63
|
+
const pending = requests.get(url);
|
|
64
|
+
if (pending) return pending as Promise<ClientStatusResult<T>>;
|
|
65
|
+
|
|
66
|
+
const requestGeneration = generation;
|
|
67
|
+
const requestUrlGeneration = requestGenerations.get(url) ?? 0;
|
|
68
|
+
const controller =
|
|
69
|
+
typeof AbortController === "undefined" ? null : new AbortController();
|
|
70
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
71
|
+
const timeout = new Promise<ClientStatusResult<unknown>>((resolve) => {
|
|
72
|
+
timeoutId = setTimeout(() => {
|
|
73
|
+
controller?.abort();
|
|
74
|
+
resolve({ state: "unavailable" });
|
|
75
|
+
}, REQUEST_TIMEOUT_MS);
|
|
76
|
+
});
|
|
77
|
+
const transport = fetch(url, {
|
|
78
|
+
cache: "no-store",
|
|
79
|
+
credentials: "same-origin",
|
|
80
|
+
...(controller ? { signal: controller.signal } : {}),
|
|
81
|
+
})
|
|
82
|
+
.then(async (response): Promise<ClientStatusResult<unknown>> => {
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
return { state: "unavailable", status: response.status };
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
return { state: "available", value: await response.json() };
|
|
88
|
+
} catch {
|
|
89
|
+
return { state: "unavailable", status: response.status };
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
.catch((): ClientStatusResult<unknown> => ({ state: "unavailable" }));
|
|
93
|
+
const request = Promise.race([transport, timeout])
|
|
94
|
+
.then((result) => {
|
|
95
|
+
if (
|
|
96
|
+
generation === requestGeneration &&
|
|
97
|
+
(requestGenerations.get(url) ?? 0) === requestUrlGeneration &&
|
|
98
|
+
result.state === "available"
|
|
99
|
+
) {
|
|
100
|
+
cache.set(url, {
|
|
101
|
+
expiresAt: Date.now() + RESULT_TTL_MS,
|
|
102
|
+
result,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
})
|
|
107
|
+
.finally(() => {
|
|
108
|
+
if (timeoutId !== undefined) clearTimeout(timeoutId);
|
|
109
|
+
if (requests.get(url) === request) requests.delete(url);
|
|
110
|
+
if (requestControllers.get(url) === controller) {
|
|
111
|
+
requestControllers.delete(url);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
requests.set(url, request);
|
|
116
|
+
if (controller) requestControllers.set(url, controller);
|
|
117
|
+
return request as Promise<ClientStatusResult<T>>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function invalidateClientStatusRequest(path: string): void {
|
|
121
|
+
const url = agentNativePath(path);
|
|
122
|
+
requestGenerations.set(url, (requestGenerations.get(url) ?? 0) + 1);
|
|
123
|
+
cache.delete(url);
|
|
124
|
+
requestControllers.get(url)?.abort();
|
|
125
|
+
requestControllers.delete(url);
|
|
126
|
+
requests.delete(url);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function invalidateClientStatusRequests(): void {
|
|
130
|
+
generation += 1;
|
|
131
|
+
cache.clear();
|
|
132
|
+
for (const controller of requestControllers.values()) {
|
|
133
|
+
controller.abort();
|
|
134
|
+
}
|
|
135
|
+
requestControllers.clear();
|
|
136
|
+
requests.clear();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function fetchAgentEngineStatus<T = unknown>(): Promise<
|
|
140
|
+
ClientStatusResult<T>
|
|
141
|
+
> {
|
|
142
|
+
return fetchClientStatus<T>("/_agent-native/agent-engine/status");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function fetchEnvironmentStatus<T = unknown>(): Promise<
|
|
146
|
+
ClientStatusResult<T>
|
|
147
|
+
> {
|
|
148
|
+
return fetchClientStatus<T>("/_agent-native/env-status");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function fetchBuilderStatus<T = unknown>(): Promise<
|
|
152
|
+
ClientStatusResult<T>
|
|
153
|
+
> {
|
|
154
|
+
return fetchClientStatus<T>("/_agent-native/builder/status");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function fetchAuthSessionStatus<T = unknown>(): Promise<
|
|
158
|
+
ClientStatusResult<T>
|
|
159
|
+
> {
|
|
160
|
+
return fetchClientStatus<T>("/_agent-native/auth/session");
|
|
161
|
+
}
|
|
@@ -627,8 +627,8 @@ export function VoiceTranscriptionSection() {
|
|
|
627
627
|
id="openai"
|
|
628
628
|
selected={transcriptionMode === "batch" && provider === "openai"}
|
|
629
629
|
onSelect={() => chooseBatchProvider("openai")}
|
|
630
|
-
title="OpenAI
|
|
631
|
-
subtitle="Batch
|
|
630
|
+
title="OpenAI Transcribe"
|
|
631
|
+
subtitle="Batch transcription provider. Requires an OpenAI API key."
|
|
632
632
|
rightSlot={
|
|
633
633
|
openAiConfigured === null ? null : openAiConfigured ? (
|
|
634
634
|
<span className="flex items-center gap-1 text-[10px] text-green-500">
|
|
@@ -34,6 +34,13 @@ export type ContentPart =
|
|
|
34
34
|
args: Record<string, string>;
|
|
35
35
|
result?: string;
|
|
36
36
|
isError?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Set when the stream ended while this tool was still in flight. We know
|
|
39
|
+
* it started and NOT whether its side effect landed, so it is deliberately
|
|
40
|
+
* separate from `isError` — an email that WAS delivered must never render
|
|
41
|
+
* as a failure just because the transport dropped before `tool_done`.
|
|
42
|
+
*/
|
|
43
|
+
outcome?: "unknown";
|
|
37
44
|
completedSideEffect?: boolean;
|
|
38
45
|
mcpApp?: AgentMcpAppPayload;
|
|
39
46
|
chatUI?: ActionChatUIConfig;
|
|
@@ -155,7 +162,10 @@ export function settleInterruptedToolCalls(
|
|
|
155
162
|
part.activity === true
|
|
156
163
|
? (options?.activityResult ?? INTERRUPTED_ACTIVITY_RESULT)
|
|
157
164
|
: result;
|
|
158
|
-
|
|
165
|
+
// Interrupted is not failed: the side effect may well have landed. Never
|
|
166
|
+
// set `isError` here — that is reserved for a result the server told us
|
|
167
|
+
// failed.
|
|
168
|
+
part.outcome = "unknown";
|
|
159
169
|
changed = true;
|
|
160
170
|
}
|
|
161
171
|
}
|
|
@@ -1029,7 +1039,8 @@ function completedToolNamesAfterLastAssistantText(
|
|
|
1029
1039
|
part.type === "tool-call" &&
|
|
1030
1040
|
part.activity !== true &&
|
|
1031
1041
|
part.result !== undefined &&
|
|
1032
|
-
part.isError !== true
|
|
1042
|
+
part.isError !== true &&
|
|
1043
|
+
part.outcome !== "unknown"
|
|
1033
1044
|
) {
|
|
1034
1045
|
names.add(part.toolName);
|
|
1035
1046
|
}
|
|
@@ -1053,7 +1064,8 @@ function hasCompletedCustomUi(content: ContentPart[]): boolean {
|
|
|
1053
1064
|
part?.type !== "tool-call" ||
|
|
1054
1065
|
part.activity === true ||
|
|
1055
1066
|
part.result === undefined ||
|
|
1056
|
-
part.isError === true
|
|
1067
|
+
part.isError === true ||
|
|
1068
|
+
part.outcome === "unknown"
|
|
1057
1069
|
) {
|
|
1058
1070
|
continue;
|
|
1059
1071
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { PROVIDER_ENV_VARS } from "../agent/engine/provider-env-vars.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
fetchAgentEngineStatus,
|
|
6
|
+
fetchBuilderStatus,
|
|
7
|
+
fetchEnvironmentStatus,
|
|
8
|
+
invalidateClientStatusRequest,
|
|
9
|
+
type ClientStatusResult,
|
|
10
|
+
} from "./client-status-requests.js";
|
|
5
11
|
|
|
6
12
|
const PROVIDER_ENV_VAR_SET = new Set(PROVIDER_ENV_VARS);
|
|
7
13
|
|
|
@@ -39,43 +45,32 @@ export interface UseAgentEngineConfiguredOptions {
|
|
|
39
45
|
threadId?: string | null;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
// Abort ceiling for a hung request, NOT a deadline the probes race against.
|
|
43
|
-
// `/agent-engine/status` resolves session, org context, a scoped secret and a
|
|
44
|
-
// settings row — several DB round-trips that measured ~4.7s on a warm local
|
|
45
|
-
// dev server, so any budget short enough to "feel fast" just manufactures a
|
|
46
|
-
// fake answer. Losing this ceiling is treated as "don't know", never "missing".
|
|
47
|
-
const DEFAULT_STATUS_CHECK_TIMEOUT_MS = 15000;
|
|
48
48
|
const RETRY_BASE_MS = 2000;
|
|
49
49
|
const RETRY_MAX_MS = 30000;
|
|
50
50
|
|
|
51
|
-
async function
|
|
51
|
+
async function waitForStatus<T>(
|
|
52
|
+
request: Promise<ClientStatusResult<T>>,
|
|
52
53
|
path: string,
|
|
53
|
-
timeoutMs: number,
|
|
54
|
-
): Promise<
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
timeoutMs: number | undefined,
|
|
55
|
+
): Promise<ClientStatusResult<T>> {
|
|
56
|
+
if (timeoutMs === undefined) return request;
|
|
57
|
+
|
|
57
58
|
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
58
|
-
const timeout = new Promise<
|
|
59
|
+
const timeout = new Promise<ClientStatusResult<T>>((resolve) => {
|
|
59
60
|
timeoutId = setTimeout(() => {
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
// A request that loses this race may never settle. Evict and abort the
|
|
62
|
+
// shared probe so the scheduled retry starts a genuinely new request.
|
|
63
|
+
invalidateClientStatusRequest(path);
|
|
64
|
+
resolve({ state: "unavailable" });
|
|
62
65
|
}, timeoutMs);
|
|
63
66
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
})
|
|
72
|
-
.then((r) => (r.ok ? r.json() : null))
|
|
73
|
-
.catch(() => null)
|
|
74
|
-
.finally(() => {
|
|
75
|
-
if (timeoutId !== undefined) clearTimeout(timeoutId);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
return Promise.race([request, timeout]);
|
|
67
|
+
try {
|
|
68
|
+
return await Promise.race([request, timeout]);
|
|
69
|
+
} finally {
|
|
70
|
+
if (timeoutId !== undefined) {
|
|
71
|
+
clearTimeout(timeoutId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
79
74
|
}
|
|
80
75
|
|
|
81
76
|
function hasConfiguredFlag(value: unknown): value is { configured: boolean } {
|
|
@@ -117,22 +112,38 @@ export async function fetchAgentEngineConfiguredState(
|
|
|
117
112
|
const timeoutMs =
|
|
118
113
|
typeof options?.timeoutMs === "number" && options.timeoutMs > 0
|
|
119
114
|
? options.timeoutMs
|
|
120
|
-
:
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return "
|
|
115
|
+
: undefined;
|
|
116
|
+
const engineResult = await waitForStatus(
|
|
117
|
+
fetchAgentEngineStatus(),
|
|
118
|
+
"/_agent-native/agent-engine/status",
|
|
119
|
+
timeoutMs,
|
|
120
|
+
);
|
|
121
|
+
if (
|
|
122
|
+
engineResult.state === "available" &&
|
|
123
|
+
hasConfiguredFlag(engineResult.value)
|
|
124
|
+
) {
|
|
125
|
+
return engineResult.value.configured ? "configured" : "missing";
|
|
131
126
|
}
|
|
132
127
|
|
|
128
|
+
// Older hosts may not expose the canonical route. Only then pay for the two
|
|
129
|
+
// legacy probes; current hosts answer readiness with one request.
|
|
130
|
+
const [envResult, builderResult] = await Promise.all([
|
|
131
|
+
waitForStatus(
|
|
132
|
+
fetchEnvironmentStatus(),
|
|
133
|
+
"/_agent-native/env-status",
|
|
134
|
+
timeoutMs,
|
|
135
|
+
),
|
|
136
|
+
waitForStatus(
|
|
137
|
+
fetchBuilderStatus(),
|
|
138
|
+
"/_agent-native/builder/status",
|
|
139
|
+
timeoutMs,
|
|
140
|
+
),
|
|
141
|
+
]);
|
|
142
|
+
const envKeys = envResult.state === "available" ? envResult.value : undefined;
|
|
143
|
+
const builderStatus =
|
|
144
|
+
builderResult.state === "available" ? builderResult.value : undefined;
|
|
133
145
|
const envKeysKnown = Array.isArray(envKeys);
|
|
134
146
|
const builderStatusKnown = hasConfiguredFlag(builderStatus);
|
|
135
|
-
const engineStatusKnown = hasConfiguredFlag(engineStatus);
|
|
136
147
|
const keys = envKeysKnown
|
|
137
148
|
? (envKeys as Array<{
|
|
138
149
|
key: string;
|
|
@@ -142,16 +153,9 @@ export async function fetchAgentEngineConfiguredState(
|
|
|
142
153
|
const llmKeys = keys.filter((k) => PROVIDER_ENV_VAR_SET.has(k.key));
|
|
143
154
|
const anyConfigured =
|
|
144
155
|
llmKeys.some((k) => k.configured) ||
|
|
145
|
-
(builderStatusKnown && builderStatus.configured)
|
|
146
|
-
(engineStatusKnown && engineStatus.configured);
|
|
156
|
+
(builderStatusKnown && builderStatus.configured);
|
|
147
157
|
if (anyConfigured) return "configured";
|
|
148
158
|
|
|
149
|
-
// The engine status route is the canonical readiness check: it resolves
|
|
150
|
-
// Builder, scoped BYOK secrets, deployment credentials, and custom engines.
|
|
151
|
-
// Once it has answered `configured: false`, a slow legacy env/Builder status
|
|
152
|
-
// request must not leave the composer permissively stuck in `unknown`.
|
|
153
|
-
if (engineStatusKnown) return "missing";
|
|
154
|
-
|
|
155
159
|
// Compatibility fallback for older hosts without the canonical route.
|
|
156
160
|
return envKeysKnown && builderStatusKnown ? "missing" : "unavailable";
|
|
157
161
|
}
|
|
@@ -7,11 +7,14 @@ import {
|
|
|
7
7
|
resolveReasoningEffortSelection,
|
|
8
8
|
type ReasoningEffort,
|
|
9
9
|
} from "../shared/reasoning-effort.js";
|
|
10
|
-
import { agentNativePath } from "./api-path.js";
|
|
11
10
|
import {
|
|
12
11
|
buildChatModelGroups,
|
|
13
12
|
type EngineModelGroup,
|
|
14
13
|
} from "./chat-model-groups.js";
|
|
14
|
+
import {
|
|
15
|
+
fetchBuilderStatus,
|
|
16
|
+
fetchEnvironmentStatus,
|
|
17
|
+
} from "./client-status-requests.js";
|
|
15
18
|
import { callAction } from "./use-action.js";
|
|
16
19
|
|
|
17
20
|
export type { EngineModelGroup } from "./chat-model-groups.js";
|
|
@@ -192,14 +195,10 @@ export function useChatModels({
|
|
|
192
195
|
callAction("manage-agent-engine" as any, { action: "list" } as any).catch(
|
|
193
196
|
() => null,
|
|
194
197
|
),
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
.catch(() => []),
|
|
198
|
-
fetch(agentNativePath("/_agent-native/builder/status"))
|
|
199
|
-
.then((r) => (r.ok ? r.json() : null))
|
|
200
|
-
.catch(() => null),
|
|
198
|
+
fetchEnvironmentStatus<Array<{ key: string; configured: boolean }>>(),
|
|
199
|
+
fetchBuilderStatus<{ configured?: boolean }>(),
|
|
201
200
|
])
|
|
202
|
-
.then(([enginesData,
|
|
201
|
+
.then(([enginesData, envResult, builderResult]) => {
|
|
203
202
|
if (!enginesData?.engines) {
|
|
204
203
|
// Without a catalog the picker keeps an unvalidated DEFAULT_MODEL,
|
|
205
204
|
// which is indistinguishable from a real selection unless we say so.
|
|
@@ -208,10 +207,16 @@ export function useChatModels({
|
|
|
208
207
|
);
|
|
209
208
|
return;
|
|
210
209
|
}
|
|
210
|
+
if (
|
|
211
|
+
envResult.state !== "available" ||
|
|
212
|
+
builderResult.state !== "available"
|
|
213
|
+
) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const envKeys = envResult.value;
|
|
217
|
+
const builderStatus = builderResult.value;
|
|
211
218
|
const configuredKeys = new Set(
|
|
212
|
-
(
|
|
213
|
-
.filter((k) => k.configured)
|
|
214
|
-
.map((k) => k.key),
|
|
219
|
+
envKeys.filter((k) => k.configured).map((k) => k.key),
|
|
215
220
|
);
|
|
216
221
|
const builderConnected = builderStatus?.configured === true;
|
|
217
222
|
const currentEngineName: string | undefined =
|
|
@@ -78,6 +78,35 @@ const ACTIVE_THREAD_KEY = "agent-chat-active-thread";
|
|
|
78
78
|
const THREADS_UPDATED_EVENT = "agent-chat:threads-updated";
|
|
79
79
|
const THREADS_PAGE_SIZE = 50;
|
|
80
80
|
|
|
81
|
+
const sharedThreadListRequests = new Map<
|
|
82
|
+
string,
|
|
83
|
+
Promise<ChatThreadSummary[] | undefined>
|
|
84
|
+
>();
|
|
85
|
+
|
|
86
|
+
async function fetchSharedThreadListPage(
|
|
87
|
+
apiUrl: string,
|
|
88
|
+
offset: number,
|
|
89
|
+
): Promise<ChatThreadSummary[] | undefined> {
|
|
90
|
+
const requestKey = `${apiUrl}\n${offset}`;
|
|
91
|
+
const pending = sharedThreadListRequests.get(requestKey);
|
|
92
|
+
if (pending) return pending;
|
|
93
|
+
|
|
94
|
+
const request = fetch(
|
|
95
|
+
offset > 0 ? `${apiUrl}/threads?offset=${offset}` : `${apiUrl}/threads`,
|
|
96
|
+
)
|
|
97
|
+
.then(async (res) => {
|
|
98
|
+
if (!res.ok) return undefined;
|
|
99
|
+
const data = await res.json();
|
|
100
|
+
const threads = (data.threads ?? []) as ChatThreadSummary[];
|
|
101
|
+
return threads;
|
|
102
|
+
})
|
|
103
|
+
.finally(() => {
|
|
104
|
+
sharedThreadListRequests.delete(requestKey);
|
|
105
|
+
});
|
|
106
|
+
sharedThreadListRequests.set(requestKey, request);
|
|
107
|
+
return request;
|
|
108
|
+
}
|
|
109
|
+
|
|
81
110
|
function emitThreadsUpdated() {
|
|
82
111
|
if (typeof window === "undefined") return;
|
|
83
112
|
window.dispatchEvent(new CustomEvent(THREADS_UPDATED_EVENT));
|
|
@@ -441,20 +470,14 @@ export function useChatThreads(
|
|
|
441
470
|
async (options?: { append?: boolean }) => {
|
|
442
471
|
try {
|
|
443
472
|
const offset = options?.append ? nextThreadsOffsetRef.current : 0;
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
? `${apiUrl}/threads?offset=${offset}`
|
|
447
|
-
: `${apiUrl}/threads`,
|
|
448
|
-
);
|
|
449
|
-
if (!res.ok) {
|
|
473
|
+
const loaded = await fetchSharedThreadListPage(apiUrl, offset);
|
|
474
|
+
if (!loaded) {
|
|
450
475
|
if (!options?.append) {
|
|
451
476
|
setThreadsLoadError("Could not load chat history.");
|
|
452
477
|
}
|
|
453
478
|
return;
|
|
454
479
|
}
|
|
455
|
-
const data = await res.json();
|
|
456
480
|
setThreadsLoadError(null);
|
|
457
|
-
const loaded = (data.threads ?? []) as ChatThreadSummary[];
|
|
458
481
|
if (!options?.append) {
|
|
459
482
|
nextThreadsOffsetRef.current = loaded.length;
|
|
460
483
|
} else {
|
|
@@ -526,7 +549,7 @@ export function useChatThreads(
|
|
|
526
549
|
}
|
|
527
550
|
return [...optimisticOnly, ...merged];
|
|
528
551
|
});
|
|
529
|
-
return
|
|
552
|
+
return loaded;
|
|
530
553
|
} catch {
|
|
531
554
|
if (!options?.append) {
|
|
532
555
|
setThreadsLoadError("Could not load chat history.");
|
|
@@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
|
|
|
2
2
|
|
|
3
3
|
import type { AuthSession } from "../server/auth.js";
|
|
4
4
|
import { setSentryUser, trackSessionStatus } from "./analytics.js";
|
|
5
|
-
import {
|
|
5
|
+
import { fetchAuthSessionStatus } from "./client-status-requests.js";
|
|
6
6
|
|
|
7
7
|
export type { AuthSession };
|
|
8
8
|
|
|
@@ -51,10 +51,9 @@ function fetchSharedSession(): Promise<AuthSession | null | undefined> {
|
|
|
51
51
|
|
|
52
52
|
sessionRequest = (async () => {
|
|
53
53
|
try {
|
|
54
|
-
const
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
const data = await res.json();
|
|
54
|
+
const result = await fetchAuthSessionStatus();
|
|
55
|
+
if (result.state === "unavailable") return undefined;
|
|
56
|
+
const data = result.value as AuthSession & { error?: unknown };
|
|
58
57
|
const session = data.error ? null : (data as AuthSession);
|
|
59
58
|
cachedSession = session;
|
|
60
59
|
cachedSessionAt = Date.now();
|