agent-relay 2.0.21 → 2.0.23
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/bin/relay-pty-linux-arm64 +0 -0
- package/dist/src/cli/index.d.ts +3 -3
- package/dist/src/cli/index.js +31 -100
- package/package.json +22 -29
- package/packages/api-types/package.json +1 -1
- package/packages/bridge/package.json +8 -8
- package/packages/cli-tester/package.json +1 -1
- package/packages/cloud/dist/server.js +25 -4
- package/packages/cloud/package.json +6 -6
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +1 -1
- package/packages/daemon/dist/orchestrator.js +21 -1
- package/packages/daemon/dist/router.d.ts +5 -0
- package/packages/daemon/dist/router.js +31 -0
- package/packages/daemon/dist/server.d.ts +5 -0
- package/packages/daemon/dist/server.js +131 -1
- package/packages/daemon/package.json +12 -12
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/dist/client.d.ts +15 -0
- package/packages/mcp/dist/client.js +9 -0
- package/packages/mcp/dist/server.js +13 -1
- package/packages/mcp/dist/tools/index.d.ts +2 -0
- package/packages/mcp/dist/tools/index.js +2 -0
- package/packages/mcp/dist/tools/relay-connected.d.ts +17 -0
- package/packages/mcp/dist/tools/relay-connected.js +40 -0
- package/packages/mcp/dist/tools/relay-remove-agent.d.ts +20 -0
- package/packages/mcp/dist/tools/relay-remove-agent.js +50 -0
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/dist/types.d.ts +46 -1
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/dist/client.d.ts +22 -1
- package/packages/sdk/dist/client.js +31 -0
- package/packages/sdk/dist/protocol/index.d.ts +1 -1
- package/packages/sdk/dist/protocol/types.d.ts +35 -1
- package/packages/sdk/package.json +2 -2
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/dist/adapter.d.ts +4 -0
- package/packages/storage/dist/sqlite-adapter.d.ts +10 -0
- package/packages/storage/dist/sqlite-adapter.js +26 -0
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/dist/update-checker.js +4 -0
- package/packages/utils/package.json +1 -1
- package/packages/wrapper/package.json +6 -6
- package/deploy/workspace/codex.config.toml +0 -20
- package/deploy/workspace/entrypoint-browser.sh +0 -118
- package/deploy/workspace/entrypoint.sh +0 -612
- package/deploy/workspace/gh-credential-relay +0 -90
- package/deploy/workspace/gh-relay +0 -156
- package/deploy/workspace/git-credential-relay +0 -330
- package/deploy/workspace/git-credential-relay.test.sh +0 -230
- package/dist/dashboard/out/404.html +0 -1
- package/dist/dashboard/out/_next/static/7MZPqYkVGw3EGzVBkVmY9/_buildManifest.js +0 -1
- package/dist/dashboard/out/_next/static/7MZPqYkVGw3EGzVBkVmY9/_ssgManifest.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/116-a883fca163f3a5bc.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/117-c8afed19e821a35d.js +0 -2
- package/dist/dashboard/out/_next/static/chunks/282-980c2eb8fff20123.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/320-a6304232cd0ee2ce.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/532-bace199897eeab37.js +0 -9
- package/dist/dashboard/out/_next/static/chunks/631-16b905e5920f9b59.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/648-acb2ff9f77cbfbd3.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/766-2aea80818f7eb0d8.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/83-26d2bde54616ee90.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/847-f1f467060f32afff.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/891-5cb1513eeb97a891.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/_not-found/page-60501fddbafba9dc.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/page-9914652442f7e4fb.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/app/page-366fb7c078d4e9e0.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/cloud/link/page-fa1d5842aa90e8a6.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/complete-profile/page-dd64bbdf66b639cd.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/connect-repos/page-113060009ef35bc2.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/history/page-9965d2483011b846.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/layout-6b91e33784c20610.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/login/page-435eceb0073be027.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/metrics/page-1e37ef8e73940b40.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/page-8119d4246743574e.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/pricing/page-9db3ebdfa567a7c9.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-ecb16ffd3b36262b.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-4dbe33f0f7691b7c.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/signup/page-c7a0a28341365ae0.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/e868780c-48e5f147c90a3a41.js +0 -18
- package/dist/dashboard/out/_next/static/chunks/fd9d1056-609918ca7b6280bb.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/framework-f66176bb897dc684.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/main-311c3db74dcfadb7.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/main-app-fdbeb09028f57c9f.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/pages/_app-72b849fbd24ac258.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/pages/_error-7ba65e1336b92748.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +0 -1
- package/dist/dashboard/out/_next/static/css/4034f236dd1a3178.css +0 -1
- package/dist/dashboard/out/_next/static/css/6892f8422896ef7a.css +0 -1
- package/dist/dashboard/out/alt-logos/agent-relay-logo-128.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-256.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-32.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-512.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-64.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo.svg +0 -45
- package/dist/dashboard/out/alt-logos/logo.svg +0 -38
- package/dist/dashboard/out/alt-logos/monogram-logo-128.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-256.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-32.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-512.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-64.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo.svg +0 -38
- package/dist/dashboard/out/app/onboarding.html +0 -1
- package/dist/dashboard/out/app/onboarding.txt +0 -7
- package/dist/dashboard/out/app.html +0 -1
- package/dist/dashboard/out/app.txt +0 -7
- package/dist/dashboard/out/apple-icon.png +0 -0
- package/dist/dashboard/out/cloud/link.html +0 -1
- package/dist/dashboard/out/cloud/link.txt +0 -7
- package/dist/dashboard/out/complete-profile.html +0 -5
- package/dist/dashboard/out/complete-profile.txt +0 -7
- package/dist/dashboard/out/connect-repos.html +0 -1
- package/dist/dashboard/out/connect-repos.txt +0 -7
- package/dist/dashboard/out/history.html +0 -1
- package/dist/dashboard/out/history.txt +0 -7
- package/dist/dashboard/out/index.html +0 -1
- package/dist/dashboard/out/index.txt +0 -7
- package/dist/dashboard/out/login.html +0 -5
- package/dist/dashboard/out/login.txt +0 -7
- package/dist/dashboard/out/metrics.html +0 -1
- package/dist/dashboard/out/metrics.txt +0 -7
- package/dist/dashboard/out/pricing.html +0 -13
- package/dist/dashboard/out/pricing.txt +0 -7
- package/dist/dashboard/out/providers/setup/claude.html +0 -1
- package/dist/dashboard/out/providers/setup/claude.txt +0 -8
- package/dist/dashboard/out/providers/setup/codex.html +0 -1
- package/dist/dashboard/out/providers/setup/codex.txt +0 -8
- package/dist/dashboard/out/providers/setup/cursor.html +0 -1
- package/dist/dashboard/out/providers/setup/cursor.txt +0 -8
- package/dist/dashboard/out/providers.html +0 -1
- package/dist/dashboard/out/providers.txt +0 -7
- package/dist/dashboard/out/signup.html +0 -6
- package/dist/dashboard/out/signup.txt +0 -7
- package/dist/src/dashboard-server/index.d.ts +0 -8
- package/dist/src/dashboard-server/index.js +0 -8
- package/packages/dashboard/README.md +0 -48
- package/packages/dashboard/dist/health-worker-manager.d.ts +0 -62
- package/packages/dashboard/dist/health-worker-manager.js +0 -144
- package/packages/dashboard/dist/health-worker.d.ts +0 -9
- package/packages/dashboard/dist/health-worker.js +0 -79
- package/packages/dashboard/dist/index.d.ts +0 -20
- package/packages/dashboard/dist/index.js +0 -19
- package/packages/dashboard/dist/metrics.d.ts +0 -105
- package/packages/dashboard/dist/metrics.js +0 -193
- package/packages/dashboard/dist/needs-attention.d.ts +0 -24
- package/packages/dashboard/dist/needs-attention.js +0 -78
- package/packages/dashboard/dist/server.d.ts +0 -25
- package/packages/dashboard/dist/server.js +0 -5270
- package/packages/dashboard/dist/start.d.ts +0 -6
- package/packages/dashboard/dist/start.js +0 -13
- package/packages/dashboard/dist/types/threading.d.ts +0 -8
- package/packages/dashboard/dist/types/threading.js +0 -2
- package/packages/dashboard/dist/user-bridge.d.ts +0 -154
- package/packages/dashboard/dist/user-bridge.js +0 -372
- package/packages/dashboard/package.json +0 -65
- package/packages/dashboard/ui/app/app/onboarding/page.tsx +0 -394
- package/packages/dashboard/ui/app/app/page.tsx +0 -667
- package/packages/dashboard/ui/app/apple-icon.png +0 -0
- package/packages/dashboard/ui/app/cloud/link/page.tsx +0 -464
- package/packages/dashboard/ui/app/complete-profile/page.tsx +0 -204
- package/packages/dashboard/ui/app/connect-repos/page.tsx +0 -410
- package/packages/dashboard/ui/app/favicon.png +0 -0
- package/packages/dashboard/ui/app/globals.css +0 -59
- package/packages/dashboard/ui/app/history/page.tsx +0 -658
- package/packages/dashboard/ui/app/layout.tsx +0 -25
- package/packages/dashboard/ui/app/login/page.tsx +0 -424
- package/packages/dashboard/ui/app/metrics/page.tsx +0 -751
- package/packages/dashboard/ui/app/page.tsx +0 -59
- package/packages/dashboard/ui/app/pricing/page.tsx +0 -7
- package/packages/dashboard/ui/app/providers/page.tsx +0 -193
- package/packages/dashboard/ui/app/providers/setup/[provider]/ProviderSetupClient.tsx +0 -148
- package/packages/dashboard/ui/app/providers/setup/[provider]/constants.ts +0 -35
- package/packages/dashboard/ui/app/providers/setup/[provider]/page.tsx +0 -42
- package/packages/dashboard/ui/app/signup/page.tsx +0 -533
- package/packages/dashboard/ui/index.ts +0 -49
- package/packages/dashboard/ui/landing/LandingPage.tsx +0 -713
- package/packages/dashboard/ui/landing/PricingPage.tsx +0 -559
- package/packages/dashboard/ui/landing/index.ts +0 -6
- package/packages/dashboard/ui/landing/styles.css +0 -2850
- package/packages/dashboard/ui/lib/agent-merge.ts +0 -35
- package/packages/dashboard/ui/lib/api.ts +0 -1155
- package/packages/dashboard/ui/lib/cloudApi.ts +0 -877
- package/packages/dashboard/ui/lib/colors.ts +0 -218
- package/packages/dashboard/ui/lib/hierarchy.ts +0 -242
- package/packages/dashboard/ui/lib/stuckDetection.ts +0 -142
- package/packages/dashboard/ui/next-env.d.ts +0 -5
- package/packages/dashboard/ui/next.config.js +0 -41
- package/packages/dashboard/ui/package-lock.json +0 -2882
- package/packages/dashboard/ui/package.json +0 -33
- package/packages/dashboard/ui/postcss.config.js +0 -5
- package/packages/dashboard/ui/react-components/ActivityFeed.tsx +0 -216
- package/packages/dashboard/ui/react-components/AddWorkspaceModal.tsx +0 -170
- package/packages/dashboard/ui/react-components/AgentCard.tsx +0 -587
- package/packages/dashboard/ui/react-components/AgentList.tsx +0 -411
- package/packages/dashboard/ui/react-components/AgentProfilePanel.tsx +0 -564
- package/packages/dashboard/ui/react-components/App.tsx +0 -3033
- package/packages/dashboard/ui/react-components/BillingPanel.tsx +0 -922
- package/packages/dashboard/ui/react-components/BillingResult.tsx +0 -447
- package/packages/dashboard/ui/react-components/BroadcastComposer.tsx +0 -690
- package/packages/dashboard/ui/react-components/ChannelAdminPanel.tsx +0 -773
- package/packages/dashboard/ui/react-components/ChannelBrowser.tsx +0 -385
- package/packages/dashboard/ui/react-components/ChannelChat.tsx +0 -261
- package/packages/dashboard/ui/react-components/ChannelSidebar.tsx +0 -399
- package/packages/dashboard/ui/react-components/CloudSessionProvider.tsx +0 -130
- package/packages/dashboard/ui/react-components/CommandPalette.tsx +0 -815
- package/packages/dashboard/ui/react-components/ConfirmationDialog.tsx +0 -133
- package/packages/dashboard/ui/react-components/ConversationHistory.tsx +0 -518
- package/packages/dashboard/ui/react-components/CoordinatorPanel.tsx +0 -944
- package/packages/dashboard/ui/react-components/DecisionQueue.tsx +0 -717
- package/packages/dashboard/ui/react-components/DirectMessageView.tsx +0 -164
- package/packages/dashboard/ui/react-components/FileAutocomplete.tsx +0 -368
- package/packages/dashboard/ui/react-components/FleetOverview.tsx +0 -278
- package/packages/dashboard/ui/react-components/LogViewer.tsx +0 -310
- package/packages/dashboard/ui/react-components/LogViewerPanel.tsx +0 -482
- package/packages/dashboard/ui/react-components/Logo.tsx +0 -284
- package/packages/dashboard/ui/react-components/MentionAutocomplete.tsx +0 -384
- package/packages/dashboard/ui/react-components/MessageComposer.tsx +0 -457
- package/packages/dashboard/ui/react-components/MessageList.tsx +0 -649
- package/packages/dashboard/ui/react-components/MessageSenderName.tsx +0 -91
- package/packages/dashboard/ui/react-components/MessageStatusIndicator.tsx +0 -142
- package/packages/dashboard/ui/react-components/NewConversationModal.tsx +0 -400
- package/packages/dashboard/ui/react-components/NotificationToast.tsx +0 -488
- package/packages/dashboard/ui/react-components/OnlineUsersIndicator.tsx +0 -164
- package/packages/dashboard/ui/react-components/Pagination.tsx +0 -124
- package/packages/dashboard/ui/react-components/PricingPlans.tsx +0 -386
- package/packages/dashboard/ui/react-components/ProjectList.tsx +0 -625
- package/packages/dashboard/ui/react-components/ProviderAuthFlow.tsx +0 -853
- package/packages/dashboard/ui/react-components/ProviderConnectionList.tsx +0 -378
- package/packages/dashboard/ui/react-components/ProvisioningProgress.tsx +0 -730
- package/packages/dashboard/ui/react-components/RepoAccessPanel.tsx +0 -549
- package/packages/dashboard/ui/react-components/ServerCard.tsx +0 -202
- package/packages/dashboard/ui/react-components/SessionExpiredModal.tsx +0 -128
- package/packages/dashboard/ui/react-components/SpawnModal.tsx +0 -804
- package/packages/dashboard/ui/react-components/TaskAssignmentUI.tsx +0 -375
- package/packages/dashboard/ui/react-components/TerminalProviderSetup.tsx +0 -608
- package/packages/dashboard/ui/react-components/ThemeProvider.tsx +0 -325
- package/packages/dashboard/ui/react-components/ThinkingIndicator.tsx +0 -231
- package/packages/dashboard/ui/react-components/ThreadList.tsx +0 -198
- package/packages/dashboard/ui/react-components/ThreadPanel.tsx +0 -346
- package/packages/dashboard/ui/react-components/TrajectoryViewer.tsx +0 -698
- package/packages/dashboard/ui/react-components/TypingIndicator.tsx +0 -69
- package/packages/dashboard/ui/react-components/UsageBanner.tsx +0 -231
- package/packages/dashboard/ui/react-components/UserProfilePanel.tsx +0 -233
- package/packages/dashboard/ui/react-components/WorkspaceContext.tsx +0 -107
- package/packages/dashboard/ui/react-components/WorkspaceSelector.tsx +0 -234
- package/packages/dashboard/ui/react-components/WorkspaceStatusIndicator.tsx +0 -370
- package/packages/dashboard/ui/react-components/XTermInteractive.tsx +0 -510
- package/packages/dashboard/ui/react-components/XTermLogViewer.tsx +0 -719
- package/packages/dashboard/ui/react-components/channels/ChannelDialogs.tsx +0 -1411
- package/packages/dashboard/ui/react-components/channels/ChannelHeader.tsx +0 -317
- package/packages/dashboard/ui/react-components/channels/ChannelMessageList.tsx +0 -463
- package/packages/dashboard/ui/react-components/channels/ChannelViewV1.tsx +0 -146
- package/packages/dashboard/ui/react-components/channels/MessageInput.tsx +0 -288
- package/packages/dashboard/ui/react-components/channels/SearchInput.tsx +0 -172
- package/packages/dashboard/ui/react-components/channels/SearchResults.tsx +0 -336
- package/packages/dashboard/ui/react-components/channels/api.ts +0 -697
- package/packages/dashboard/ui/react-components/channels/index.ts +0 -76
- package/packages/dashboard/ui/react-components/channels/mockApi.ts +0 -344
- package/packages/dashboard/ui/react-components/channels/types.ts +0 -566
- package/packages/dashboard/ui/react-components/hooks/index.ts +0 -57
- package/packages/dashboard/ui/react-components/hooks/useAgentLogs.ts +0 -394
- package/packages/dashboard/ui/react-components/hooks/useAgents.ts +0 -127
- package/packages/dashboard/ui/react-components/hooks/useBroadcastDedup.ts +0 -86
- package/packages/dashboard/ui/react-components/hooks/useChannelAdmin.ts +0 -329
- package/packages/dashboard/ui/react-components/hooks/useChannelBrowser.ts +0 -239
- package/packages/dashboard/ui/react-components/hooks/useChannelCommands.ts +0 -138
- package/packages/dashboard/ui/react-components/hooks/useChannels.ts +0 -328
- package/packages/dashboard/ui/react-components/hooks/useDebounce.ts +0 -29
- package/packages/dashboard/ui/react-components/hooks/useDirectMessage.ts +0 -141
- package/packages/dashboard/ui/react-components/hooks/useMessages.ts +0 -309
- package/packages/dashboard/ui/react-components/hooks/useOrchestrator.ts +0 -364
- package/packages/dashboard/ui/react-components/hooks/usePinnedAgents.ts +0 -140
- package/packages/dashboard/ui/react-components/hooks/usePresence.ts +0 -340
- package/packages/dashboard/ui/react-components/hooks/useRecentRepos.ts +0 -130
- package/packages/dashboard/ui/react-components/hooks/useSession.ts +0 -209
- package/packages/dashboard/ui/react-components/hooks/useTrajectory.ts +0 -265
- package/packages/dashboard/ui/react-components/hooks/useWebSocket.ts +0 -169
- package/packages/dashboard/ui/react-components/hooks/useWorkspaceMembers.ts +0 -120
- package/packages/dashboard/ui/react-components/hooks/useWorkspaceRepos.ts +0 -73
- package/packages/dashboard/ui/react-components/hooks/useWorkspaceStatus.ts +0 -237
- package/packages/dashboard/ui/react-components/index.ts +0 -81
- package/packages/dashboard/ui/react-components/layout/Header.tsx +0 -355
- package/packages/dashboard/ui/react-components/layout/RepoContextHeader.tsx +0 -361
- package/packages/dashboard/ui/react-components/layout/Sidebar.archive.test.tsx +0 -126
- package/packages/dashboard/ui/react-components/layout/Sidebar.test.tsx +0 -691
- package/packages/dashboard/ui/react-components/layout/Sidebar.tsx +0 -930
- package/packages/dashboard/ui/react-components/layout/index.ts +0 -7
- package/packages/dashboard/ui/react-components/settings/BillingSettingsPanel.tsx +0 -564
- package/packages/dashboard/ui/react-components/settings/SettingsPage.tsx +0 -544
- package/packages/dashboard/ui/react-components/settings/TeamSettingsPanel.tsx +0 -560
- package/packages/dashboard/ui/react-components/settings/WorkspaceSettingsPanel.tsx +0 -1386
- package/packages/dashboard/ui/react-components/settings/index.ts +0 -11
- package/packages/dashboard/ui/react-components/settings/types.ts +0 -53
- package/packages/dashboard/ui/react-components/utils/messageFormatting.tsx +0 -370
- package/packages/dashboard/ui/tailwind.config.js +0 -148
- package/packages/dashboard/ui/types/index.ts +0 -304
- package/packages/dashboard/ui/types/threading.ts +0 -7
- package/packages/dashboard/ui-dist/404.html +0 -1
- package/packages/dashboard/ui-dist/_next/static/7MZPqYkVGw3EGzVBkVmY9/_buildManifest.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/7MZPqYkVGw3EGzVBkVmY9/_ssgManifest.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/116-a883fca163f3a5bc.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/117-c8afed19e821a35d.js +0 -2
- package/packages/dashboard/ui-dist/_next/static/chunks/282-980c2eb8fff20123.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/320-a6304232cd0ee2ce.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/532-bace199897eeab37.js +0 -9
- package/packages/dashboard/ui-dist/_next/static/chunks/631-16b905e5920f9b59.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/648-acb2ff9f77cbfbd3.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/766-2aea80818f7eb0d8.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/83-26d2bde54616ee90.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/847-f1f467060f32afff.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/891-5cb1513eeb97a891.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/_not-found/page-60501fddbafba9dc.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/app/onboarding/page-9914652442f7e4fb.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/app/page-366fb7c078d4e9e0.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/cloud/link/page-fa1d5842aa90e8a6.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/complete-profile/page-dd64bbdf66b639cd.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/connect-repos/page-113060009ef35bc2.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/history/page-9965d2483011b846.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/layout-6b91e33784c20610.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/login/page-435eceb0073be027.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/metrics/page-1e37ef8e73940b40.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/page-8119d4246743574e.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/pricing/page-9db3ebdfa567a7c9.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/page-ecb16ffd3b36262b.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/setup/[provider]/page-4dbe33f0f7691b7c.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/signup/page-c7a0a28341365ae0.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/e868780c-48e5f147c90a3a41.js +0 -18
- package/packages/dashboard/ui-dist/_next/static/chunks/fd9d1056-609918ca7b6280bb.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/framework-f66176bb897dc684.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/main-311c3db74dcfadb7.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/main-app-fdbeb09028f57c9f.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/pages/_app-72b849fbd24ac258.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/pages/_error-7ba65e1336b92748.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/css/4034f236dd1a3178.css +0 -1
- package/packages/dashboard/ui-dist/_next/static/css/6892f8422896ef7a.css +0 -1
- package/packages/dashboard/ui-dist/_next/static/iJ3Uiz3IrqUJL7IxKZHiV/_buildManifest.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/iJ3Uiz3IrqUJL7IxKZHiV/_ssgManifest.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/l-jd878zUJ_IlraqEWMZc/_buildManifest.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/l-jd878zUJ_IlraqEWMZc/_ssgManifest.js +0 -1
- package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-128.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-256.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-32.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-512.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-64.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo.svg +0 -45
- package/packages/dashboard/ui-dist/alt-logos/logo.svg +0 -38
- package/packages/dashboard/ui-dist/alt-logos/monogram-logo-128.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/monogram-logo-256.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/monogram-logo-32.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/monogram-logo-512.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/monogram-logo-64.png +0 -0
- package/packages/dashboard/ui-dist/alt-logos/monogram-logo.svg +0 -38
- package/packages/dashboard/ui-dist/app/onboarding.html +0 -1
- package/packages/dashboard/ui-dist/app/onboarding.txt +0 -7
- package/packages/dashboard/ui-dist/app.html +0 -1
- package/packages/dashboard/ui-dist/app.txt +0 -7
- package/packages/dashboard/ui-dist/apple-icon.png +0 -0
- package/packages/dashboard/ui-dist/cloud/link.html +0 -1
- package/packages/dashboard/ui-dist/cloud/link.txt +0 -7
- package/packages/dashboard/ui-dist/complete-profile.html +0 -5
- package/packages/dashboard/ui-dist/complete-profile.txt +0 -7
- package/packages/dashboard/ui-dist/connect-repos.html +0 -1
- package/packages/dashboard/ui-dist/connect-repos.txt +0 -7
- package/packages/dashboard/ui-dist/history.html +0 -1
- package/packages/dashboard/ui-dist/history.txt +0 -7
- package/packages/dashboard/ui-dist/index.html +0 -1
- package/packages/dashboard/ui-dist/index.txt +0 -7
- package/packages/dashboard/ui-dist/login.html +0 -5
- package/packages/dashboard/ui-dist/login.txt +0 -7
- package/packages/dashboard/ui-dist/metrics.html +0 -1
- package/packages/dashboard/ui-dist/metrics.txt +0 -7
- package/packages/dashboard/ui-dist/pricing.html +0 -13
- package/packages/dashboard/ui-dist/pricing.txt +0 -7
- package/packages/dashboard/ui-dist/providers/setup/claude.html +0 -1
- package/packages/dashboard/ui-dist/providers/setup/claude.txt +0 -8
- package/packages/dashboard/ui-dist/providers/setup/codex.html +0 -1
- package/packages/dashboard/ui-dist/providers/setup/codex.txt +0 -8
- package/packages/dashboard/ui-dist/providers/setup/cursor.html +0 -1
- package/packages/dashboard/ui-dist/providers/setup/cursor.txt +0 -8
- package/packages/dashboard/ui-dist/providers.html +0 -1
- package/packages/dashboard/ui-dist/providers.txt +0 -7
- package/packages/dashboard/ui-dist/signup.html +0 -6
- package/packages/dashboard/ui-dist/signup.txt +0 -7
- package/packages/dashboard-server/dist/health-worker-manager.d.ts +0 -62
- package/packages/dashboard-server/dist/health-worker-manager.js +0 -144
- package/packages/dashboard-server/dist/health-worker.d.ts +0 -9
- package/packages/dashboard-server/dist/health-worker.js +0 -79
- package/packages/dashboard-server/dist/index.d.ts +0 -18
- package/packages/dashboard-server/dist/index.js +0 -17
- package/packages/dashboard-server/dist/metrics.d.ts +0 -105
- package/packages/dashboard-server/dist/metrics.js +0 -193
- package/packages/dashboard-server/dist/needs-attention.d.ts +0 -24
- package/packages/dashboard-server/dist/needs-attention.js +0 -78
- package/packages/dashboard-server/dist/server.d.ts +0 -25
- package/packages/dashboard-server/dist/server.js +0 -5158
- package/packages/dashboard-server/dist/start.d.ts +0 -6
- package/packages/dashboard-server/dist/start.js +0 -13
- package/packages/dashboard-server/dist/types/threading.d.ts +0 -8
- package/packages/dashboard-server/dist/types/threading.js +0 -2
- package/packages/dashboard-server/dist/user-bridge.d.ts +0 -158
- package/packages/dashboard-server/dist/user-bridge.js +0 -390
- package/packages/dashboard-server/package.json +0 -55
|
@@ -1,1155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dashboard API Client
|
|
3
|
-
*
|
|
4
|
-
* Provides a clean interface to the dashboard REST and WebSocket APIs.
|
|
5
|
-
* Can be used by both the current dashboard and the v2 React dashboard.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
Agent,
|
|
10
|
-
Message,
|
|
11
|
-
Session,
|
|
12
|
-
AgentSummary,
|
|
13
|
-
FleetData,
|
|
14
|
-
SendMessageRequest,
|
|
15
|
-
SpawnAgentRequest,
|
|
16
|
-
SpawnAgentResponse,
|
|
17
|
-
ApiResponse,
|
|
18
|
-
Attachment,
|
|
19
|
-
} from '../types';
|
|
20
|
-
|
|
21
|
-
// API base URL - relative in browser, can be configured for SSR
|
|
22
|
-
const API_BASE = '';
|
|
23
|
-
|
|
24
|
-
// Storage key for workspace ID persistence
|
|
25
|
-
const WORKSPACE_ID_KEY = 'agentrelay_workspace_id';
|
|
26
|
-
|
|
27
|
-
// Workspace ID for cloud mode proxying
|
|
28
|
-
let activeWorkspaceId: string | null = null;
|
|
29
|
-
|
|
30
|
-
// CSRF token for cloud mode requests
|
|
31
|
-
let csrfToken: string | null = null;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Set the CSRF token for API requests
|
|
35
|
-
*/
|
|
36
|
-
export function setCsrfToken(token: string | null): void {
|
|
37
|
-
csrfToken = token;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Get the current CSRF token
|
|
42
|
-
*/
|
|
43
|
-
export function getCsrfToken(): string | null {
|
|
44
|
-
return csrfToken;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Capture CSRF token from response headers
|
|
49
|
-
*/
|
|
50
|
-
function captureCsrfToken(response: Response): void {
|
|
51
|
-
const token = response.headers.get('X-CSRF-Token');
|
|
52
|
-
if (token) {
|
|
53
|
-
csrfToken = token;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Set the active workspace ID for API proxying in cloud mode.
|
|
59
|
-
* Also persists to localStorage so other pages can access it.
|
|
60
|
-
*/
|
|
61
|
-
export function setActiveWorkspaceId(workspaceId: string | null): void {
|
|
62
|
-
activeWorkspaceId = workspaceId;
|
|
63
|
-
// Persist to localStorage for cross-page access
|
|
64
|
-
if (typeof window !== 'undefined') {
|
|
65
|
-
if (workspaceId) {
|
|
66
|
-
localStorage.setItem(WORKSPACE_ID_KEY, workspaceId);
|
|
67
|
-
} else {
|
|
68
|
-
localStorage.removeItem(WORKSPACE_ID_KEY);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Get the active workspace ID
|
|
75
|
-
*/
|
|
76
|
-
export function getActiveWorkspaceId(): string | null {
|
|
77
|
-
return activeWorkspaceId;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Initialize workspace ID from localStorage if not already set.
|
|
82
|
-
* Call this on pages that need workspace context but aren't in the main app flow.
|
|
83
|
-
*/
|
|
84
|
-
export function initializeWorkspaceId(): string | null {
|
|
85
|
-
if (activeWorkspaceId) {
|
|
86
|
-
return activeWorkspaceId;
|
|
87
|
-
}
|
|
88
|
-
if (typeof window !== 'undefined') {
|
|
89
|
-
const stored = localStorage.getItem(WORKSPACE_ID_KEY);
|
|
90
|
-
if (stored) {
|
|
91
|
-
activeWorkspaceId = stored;
|
|
92
|
-
return stored;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Cloud-native API paths that should NOT be proxied through workspace.
|
|
100
|
-
* These are routes handled by the cloud server itself, not workspace daemons.
|
|
101
|
-
*/
|
|
102
|
-
const CLOUD_NATIVE_PATHS = [
|
|
103
|
-
'/api/daemons/', // Linked daemons API
|
|
104
|
-
'/api/workspaces/', // Workspace management
|
|
105
|
-
'/api/providers/', // OAuth providers
|
|
106
|
-
'/api/auth/', // Authentication
|
|
107
|
-
'/api/billing/', // Billing
|
|
108
|
-
'/api/usage/', // Usage metrics
|
|
109
|
-
'/api/admin/', // Admin endpoints
|
|
110
|
-
'/api/onboarding/', // Onboarding
|
|
111
|
-
'/api/repos/', // Repository management
|
|
112
|
-
'/api/project-groups/', // Coordinators
|
|
113
|
-
'/api/github-app/', // GitHub App
|
|
114
|
-
'/api/channels', // Channel proxy handled by dashboard server
|
|
115
|
-
];
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Get the API URL, accounting for cloud mode proxying
|
|
119
|
-
* @param path - API path like '/api/spawn' or '/api/send'
|
|
120
|
-
*/
|
|
121
|
-
export function getApiUrl(path: string): string {
|
|
122
|
-
if (activeWorkspaceId) {
|
|
123
|
-
// Check if this is a cloud-native path that shouldn't be proxied
|
|
124
|
-
const isCloudNative = CLOUD_NATIVE_PATHS.some(prefix => path.startsWith(prefix));
|
|
125
|
-
if (isCloudNative) {
|
|
126
|
-
return `${API_BASE}${path}`;
|
|
127
|
-
}
|
|
128
|
-
// In cloud mode, proxy through the cloud server
|
|
129
|
-
// Strip /api/ prefix since the proxy endpoint adds it back
|
|
130
|
-
const proxyPath = path.startsWith('/api/') ? path.substring(5) : path.replace(/^\//, '');
|
|
131
|
-
return `/api/workspaces/${activeWorkspaceId}/proxy/${proxyPath}`;
|
|
132
|
-
}
|
|
133
|
-
return `${API_BASE}${path}`;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Wrapper for fetch that handles CSRF tokens and credentials
|
|
138
|
-
* All requests include credentials and capture CSRF tokens from responses.
|
|
139
|
-
* Non-GET requests include the CSRF token in headers.
|
|
140
|
-
*/
|
|
141
|
-
async function apiFetch(
|
|
142
|
-
url: string,
|
|
143
|
-
options: RequestInit = {}
|
|
144
|
-
): Promise<Response> {
|
|
145
|
-
const method = options.method?.toUpperCase() || 'GET';
|
|
146
|
-
const headers: Record<string, string> = {
|
|
147
|
-
...(options.headers as Record<string, string>),
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
// Add CSRF token for state-changing requests
|
|
151
|
-
if (method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS') {
|
|
152
|
-
if (csrfToken) {
|
|
153
|
-
headers['X-CSRF-Token'] = csrfToken;
|
|
154
|
-
}
|
|
155
|
-
// Ensure Content-Type is set for requests with body
|
|
156
|
-
if (options.body && !headers['Content-Type']) {
|
|
157
|
-
headers['Content-Type'] = 'application/json';
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const response = await fetch(url, {
|
|
162
|
-
...options,
|
|
163
|
-
headers,
|
|
164
|
-
credentials: 'include',
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// Always capture CSRF token from response
|
|
168
|
-
captureCsrfToken(response);
|
|
169
|
-
|
|
170
|
-
return response;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Dashboard data received from WebSocket
|
|
175
|
-
*/
|
|
176
|
-
export interface DashboardData {
|
|
177
|
-
agents: Agent[];
|
|
178
|
-
messages: Message[];
|
|
179
|
-
sessions?: Session[];
|
|
180
|
-
summaries?: AgentSummary[];
|
|
181
|
-
fleet?: FleetData;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* WebSocket connection manager
|
|
186
|
-
*/
|
|
187
|
-
export class DashboardWebSocket {
|
|
188
|
-
private ws: WebSocket | null = null;
|
|
189
|
-
private reconnectAttempts = 0;
|
|
190
|
-
private maxReconnectAttempts = 10;
|
|
191
|
-
private reconnectDelay = 1000;
|
|
192
|
-
private listeners: Set<(data: DashboardData) => void> = new Set();
|
|
193
|
-
private statusListeners: Set<(connected: boolean) => void> = new Set();
|
|
194
|
-
|
|
195
|
-
constructor(private url?: string) {}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Connect to the WebSocket server
|
|
199
|
-
*/
|
|
200
|
-
connect(): void {
|
|
201
|
-
if (this.ws?.readyState === WebSocket.OPEN) return;
|
|
202
|
-
|
|
203
|
-
const wsUrl = this.url || this.getDefaultUrl();
|
|
204
|
-
this.ws = new WebSocket(wsUrl);
|
|
205
|
-
|
|
206
|
-
this.ws.onopen = () => {
|
|
207
|
-
this.reconnectAttempts = 0;
|
|
208
|
-
this.reconnectDelay = 1000;
|
|
209
|
-
this.notifyStatus(true);
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
this.ws.onclose = () => {
|
|
213
|
-
this.notifyStatus(false);
|
|
214
|
-
this.scheduleReconnect();
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
this.ws.onerror = (error) => {
|
|
218
|
-
console.error('[ws] WebSocket error:', error);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
this.ws.onmessage = (event) => {
|
|
222
|
-
try {
|
|
223
|
-
const data = JSON.parse(event.data) as DashboardData;
|
|
224
|
-
this.notifyListeners(data);
|
|
225
|
-
} catch (e) {
|
|
226
|
-
console.error('[ws] Failed to parse message:', e);
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Disconnect from the WebSocket server
|
|
233
|
-
*/
|
|
234
|
-
disconnect(): void {
|
|
235
|
-
if (this.ws) {
|
|
236
|
-
this.ws.close();
|
|
237
|
-
this.ws = null;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Subscribe to data updates
|
|
243
|
-
*/
|
|
244
|
-
onData(callback: (data: DashboardData) => void): () => void {
|
|
245
|
-
this.listeners.add(callback);
|
|
246
|
-
return () => this.listeners.delete(callback);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Subscribe to connection status changes
|
|
251
|
-
*/
|
|
252
|
-
onStatusChange(callback: (connected: boolean) => void): () => void {
|
|
253
|
-
this.statusListeners.add(callback);
|
|
254
|
-
return () => this.statusListeners.delete(callback);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Check if connected
|
|
259
|
-
*/
|
|
260
|
-
get isConnected(): boolean {
|
|
261
|
-
return this.ws?.readyState === WebSocket.OPEN;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
private getDefaultUrl(): string {
|
|
265
|
-
// This utility is designed for browser use. In Node.js, always pass a URL to constructor.
|
|
266
|
-
// The browser check uses globalThis to avoid TypeScript errors in Node.js compilation.
|
|
267
|
-
try {
|
|
268
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
269
|
-
const g = globalThis as any;
|
|
270
|
-
if (g.window?.location) {
|
|
271
|
-
const loc = g.window.location;
|
|
272
|
-
const protocol = loc.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
273
|
-
return `${protocol}//${loc.host}/ws`;
|
|
274
|
-
}
|
|
275
|
-
} catch {
|
|
276
|
-
// Ignore - not in browser
|
|
277
|
-
}
|
|
278
|
-
return 'ws://localhost:3888/ws';
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
private notifyListeners(data: DashboardData): void {
|
|
282
|
-
for (const listener of this.listeners) {
|
|
283
|
-
try {
|
|
284
|
-
listener(data);
|
|
285
|
-
} catch (e) {
|
|
286
|
-
console.error('[ws] Listener error:', e);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
private notifyStatus(connected: boolean): void {
|
|
292
|
-
for (const listener of this.statusListeners) {
|
|
293
|
-
try {
|
|
294
|
-
listener(connected);
|
|
295
|
-
} catch (e) {
|
|
296
|
-
console.error('[ws] Status listener error:', e);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
private scheduleReconnect(): void {
|
|
302
|
-
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
303
|
-
console.error('[ws] Max reconnect attempts reached');
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
this.reconnectAttempts++;
|
|
308
|
-
const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000);
|
|
309
|
-
|
|
310
|
-
setTimeout(() => {
|
|
311
|
-
console.log(`[ws] Reconnecting (attempt ${this.reconnectAttempts})...`);
|
|
312
|
-
this.connect();
|
|
313
|
-
}, delay);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* REST API methods
|
|
319
|
-
*/
|
|
320
|
-
export const api = {
|
|
321
|
-
/**
|
|
322
|
-
* Generic GET request
|
|
323
|
-
*/
|
|
324
|
-
async get<T = unknown>(path: string): Promise<T> {
|
|
325
|
-
const response = await apiFetch(getApiUrl(path), {
|
|
326
|
-
method: 'GET',
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
if (!response.ok) {
|
|
330
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
return await response.json() as T;
|
|
334
|
-
},
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Generic POST request
|
|
338
|
-
*/
|
|
339
|
-
async post<T = unknown>(path: string, body?: unknown): Promise<T> {
|
|
340
|
-
const response = await apiFetch(getApiUrl(path), {
|
|
341
|
-
method: 'POST',
|
|
342
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
if (!response.ok) {
|
|
346
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return await response.json() as T;
|
|
350
|
-
},
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Generic PATCH request
|
|
354
|
-
*/
|
|
355
|
-
async patch<T = unknown>(path: string, body?: unknown): Promise<T> {
|
|
356
|
-
const response = await apiFetch(getApiUrl(path), {
|
|
357
|
-
method: 'PATCH',
|
|
358
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
if (!response.ok) {
|
|
362
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
return await response.json() as T;
|
|
366
|
-
},
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Generic DELETE request
|
|
370
|
-
*/
|
|
371
|
-
async delete<T = unknown>(path: string): Promise<T> {
|
|
372
|
-
const response = await apiFetch(getApiUrl(path), {
|
|
373
|
-
method: 'DELETE',
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
if (!response.ok) {
|
|
377
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
return await response.json() as T;
|
|
381
|
-
},
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Send a message via the relay
|
|
385
|
-
*/
|
|
386
|
-
async sendMessage(request: SendMessageRequest): Promise<ApiResponse<void>> {
|
|
387
|
-
try {
|
|
388
|
-
const response = await apiFetch(getApiUrl('/api/send'), {
|
|
389
|
-
method: 'POST',
|
|
390
|
-
body: JSON.stringify(request),
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
const result = await response.json() as { success?: boolean; error?: string };
|
|
394
|
-
|
|
395
|
-
if (response.ok && result.success) {
|
|
396
|
-
return { success: true };
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return { success: false, error: result.error || 'Failed to send message' };
|
|
400
|
-
} catch (_error) {
|
|
401
|
-
return { success: false, error: 'Network error' };
|
|
402
|
-
}
|
|
403
|
-
},
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Upload an attachment (image/screenshot)
|
|
407
|
-
* @param file - File object or { filename, mimeType, data } for base64 uploads
|
|
408
|
-
*/
|
|
409
|
-
async uploadAttachment(
|
|
410
|
-
file: File | { filename: string; mimeType: string; data: string }
|
|
411
|
-
): Promise<ApiResponse<{ attachment: Omit<Attachment, 'data'> }>> {
|
|
412
|
-
try {
|
|
413
|
-
let filename: string;
|
|
414
|
-
let mimeType: string;
|
|
415
|
-
let data: string;
|
|
416
|
-
|
|
417
|
-
if (file instanceof File) {
|
|
418
|
-
// Convert File to base64
|
|
419
|
-
filename = file.name;
|
|
420
|
-
mimeType = file.type;
|
|
421
|
-
data = await new Promise<string>((resolve, reject) => {
|
|
422
|
-
const reader = new FileReader();
|
|
423
|
-
reader.onload = () => resolve(reader.result as string);
|
|
424
|
-
reader.onerror = reject;
|
|
425
|
-
reader.readAsDataURL(file);
|
|
426
|
-
});
|
|
427
|
-
} else {
|
|
428
|
-
filename = file.filename;
|
|
429
|
-
mimeType = file.mimeType;
|
|
430
|
-
data = file.data;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const response = await apiFetch(getApiUrl('/api/upload'), {
|
|
434
|
-
method: 'POST',
|
|
435
|
-
body: JSON.stringify({ filename, mimeType, data }),
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
const result = await response.json() as {
|
|
439
|
-
success?: boolean;
|
|
440
|
-
attachment?: Omit<Attachment, 'data'>;
|
|
441
|
-
error?: string;
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
if (response.ok && result.success && result.attachment) {
|
|
445
|
-
return { success: true, data: { attachment: result.attachment } };
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
return { success: false, error: result.error || 'Failed to upload attachment' };
|
|
449
|
-
} catch (_error) {
|
|
450
|
-
return { success: false, error: 'Network error' };
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* Spawn a new agent
|
|
456
|
-
*/
|
|
457
|
-
async spawnAgent(request: SpawnAgentRequest): Promise<SpawnAgentResponse> {
|
|
458
|
-
try {
|
|
459
|
-
const response = await apiFetch(getApiUrl('/api/spawn'), {
|
|
460
|
-
method: 'POST',
|
|
461
|
-
body: JSON.stringify(request),
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
return await response.json() as SpawnAgentResponse;
|
|
465
|
-
} catch (_error) {
|
|
466
|
-
return { success: false, name: request.name, error: 'Network error' };
|
|
467
|
-
}
|
|
468
|
-
},
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* Get list of spawned agents
|
|
472
|
-
*/
|
|
473
|
-
async getSpawnedAgents(): Promise<ApiResponse<{ agents: Array<{ name: string; cli: string; startedAt: string }> }>> {
|
|
474
|
-
try {
|
|
475
|
-
const response = await apiFetch(getApiUrl('/api/spawned'));
|
|
476
|
-
const result = await response.json() as { success?: boolean; agents?: Array<{ name: string; cli: string; startedAt: string }>; error?: string };
|
|
477
|
-
|
|
478
|
-
if (response.ok && result.success) {
|
|
479
|
-
return { success: true, data: { agents: result.agents || [] } };
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
return { success: false, error: result.error };
|
|
483
|
-
} catch (_error) {
|
|
484
|
-
return { success: false, error: 'Network error' };
|
|
485
|
-
}
|
|
486
|
-
},
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Release a spawned agent
|
|
490
|
-
*/
|
|
491
|
-
async releaseAgent(name: string): Promise<ApiResponse<void>> {
|
|
492
|
-
try {
|
|
493
|
-
const response = await apiFetch(getApiUrl(`/api/spawned/${encodeURIComponent(name)}`), {
|
|
494
|
-
method: 'DELETE',
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
const result = await response.json() as { success?: boolean; error?: string };
|
|
498
|
-
|
|
499
|
-
if (response.ok && result.success) {
|
|
500
|
-
return { success: true };
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
return { success: false, error: result.error };
|
|
504
|
-
} catch (_error) {
|
|
505
|
-
return { success: false, error: 'Network error' };
|
|
506
|
-
}
|
|
507
|
-
},
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Interrupt an agent by sending Ctrl+C (SIGINT equivalent).
|
|
511
|
-
* Use this to break an agent out of a stuck loop for refocusing.
|
|
512
|
-
* @param agentName - The agent's name
|
|
513
|
-
*/
|
|
514
|
-
async interruptAgent(agentName: string): Promise<ApiResponse<void>> {
|
|
515
|
-
try {
|
|
516
|
-
const response = await apiFetch(getApiUrl(`/api/agents/by-name/${encodeURIComponent(agentName)}/interrupt`), {
|
|
517
|
-
method: 'POST',
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
const result = await response.json() as { success?: boolean; error?: string };
|
|
521
|
-
|
|
522
|
-
if (response.ok && result.success) {
|
|
523
|
-
return { success: true };
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
return { success: false, error: result.error || 'Failed to interrupt agent' };
|
|
527
|
-
} catch (_error) {
|
|
528
|
-
return { success: false, error: 'Network error' };
|
|
529
|
-
}
|
|
530
|
-
},
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Get dashboard data (fallback for REST polling)
|
|
534
|
-
*/
|
|
535
|
-
async getData(): Promise<ApiResponse<DashboardData>> {
|
|
536
|
-
try {
|
|
537
|
-
const response = await apiFetch(getApiUrl('/api/data'));
|
|
538
|
-
const data = await response.json() as DashboardData;
|
|
539
|
-
|
|
540
|
-
if (response.ok) {
|
|
541
|
-
return { success: true, data };
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
return { success: false, error: 'Failed to fetch data' };
|
|
545
|
-
} catch (_error) {
|
|
546
|
-
return { success: false, error: 'Network error' };
|
|
547
|
-
}
|
|
548
|
-
},
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* Get bridge data for multi-project view
|
|
552
|
-
*/
|
|
553
|
-
async getBridgeData(): Promise<ApiResponse<FleetData>> {
|
|
554
|
-
try {
|
|
555
|
-
const response = await apiFetch(getApiUrl('/api/bridge'));
|
|
556
|
-
const data = await response.json() as FleetData;
|
|
557
|
-
|
|
558
|
-
if (response.ok) {
|
|
559
|
-
return { success: true, data };
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
return { success: false, error: 'Failed to fetch bridge data' };
|
|
563
|
-
} catch (_error) {
|
|
564
|
-
return { success: false, error: 'Network error' };
|
|
565
|
-
}
|
|
566
|
-
},
|
|
567
|
-
|
|
568
|
-
/**
|
|
569
|
-
* Get system metrics
|
|
570
|
-
*/
|
|
571
|
-
async getMetrics(): Promise<ApiResponse<unknown>> {
|
|
572
|
-
try {
|
|
573
|
-
const response = await apiFetch(getApiUrl('/api/metrics'));
|
|
574
|
-
const data = await response.json();
|
|
575
|
-
|
|
576
|
-
if (response.ok) {
|
|
577
|
-
return { success: true, data };
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
return { success: false, error: 'Failed to fetch metrics' };
|
|
581
|
-
} catch (_error) {
|
|
582
|
-
return { success: false, error: 'Network error' };
|
|
583
|
-
}
|
|
584
|
-
},
|
|
585
|
-
|
|
586
|
-
// ===== Conversation History API =====
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* Get historical sessions
|
|
590
|
-
*/
|
|
591
|
-
async getHistorySessions(params?: {
|
|
592
|
-
agent?: string;
|
|
593
|
-
since?: number;
|
|
594
|
-
limit?: number;
|
|
595
|
-
}): Promise<ApiResponse<{ sessions: HistorySession[] }>> {
|
|
596
|
-
try {
|
|
597
|
-
const query = new URLSearchParams();
|
|
598
|
-
if (params?.agent) query.set('agent', params.agent);
|
|
599
|
-
if (params?.since) query.set('since', String(params.since));
|
|
600
|
-
if (params?.limit) query.set('limit', String(params.limit));
|
|
601
|
-
|
|
602
|
-
const response = await apiFetch(getApiUrl(`/api/history/sessions?${query}`));
|
|
603
|
-
const data = await response.json();
|
|
604
|
-
|
|
605
|
-
if (response.ok) {
|
|
606
|
-
return { success: true, data };
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
return { success: false, error: 'Failed to fetch sessions' };
|
|
610
|
-
} catch (_error) {
|
|
611
|
-
return { success: false, error: 'Network error' };
|
|
612
|
-
}
|
|
613
|
-
},
|
|
614
|
-
|
|
615
|
-
/**
|
|
616
|
-
* Get historical messages
|
|
617
|
-
*/
|
|
618
|
-
async getHistoryMessages(params?: {
|
|
619
|
-
from?: string;
|
|
620
|
-
to?: string;
|
|
621
|
-
thread?: string;
|
|
622
|
-
since?: number;
|
|
623
|
-
limit?: number;
|
|
624
|
-
order?: 'asc' | 'desc';
|
|
625
|
-
search?: string;
|
|
626
|
-
}): Promise<ApiResponse<{ messages: HistoryMessage[] }>> {
|
|
627
|
-
try {
|
|
628
|
-
const query = new URLSearchParams();
|
|
629
|
-
if (params?.from) query.set('from', params.from);
|
|
630
|
-
if (params?.to) query.set('to', params.to);
|
|
631
|
-
if (params?.thread) query.set('thread', params.thread);
|
|
632
|
-
if (params?.since) query.set('since', String(params.since));
|
|
633
|
-
if (params?.limit) query.set('limit', String(params.limit));
|
|
634
|
-
if (params?.order) query.set('order', params.order);
|
|
635
|
-
if (params?.search) query.set('search', params.search);
|
|
636
|
-
|
|
637
|
-
const response = await apiFetch(getApiUrl(`/api/history/messages?${query}`));
|
|
638
|
-
const data = await response.json();
|
|
639
|
-
|
|
640
|
-
if (response.ok) {
|
|
641
|
-
return { success: true, data };
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
return { success: false, error: 'Failed to fetch messages' };
|
|
645
|
-
} catch (_error) {
|
|
646
|
-
return { success: false, error: 'Network error' };
|
|
647
|
-
}
|
|
648
|
-
},
|
|
649
|
-
|
|
650
|
-
/**
|
|
651
|
-
* Get unique conversations (agent pairs)
|
|
652
|
-
*/
|
|
653
|
-
async getHistoryConversations(): Promise<ApiResponse<{ conversations: Conversation[] }>> {
|
|
654
|
-
try {
|
|
655
|
-
const response = await apiFetch(getApiUrl('/api/history/conversations'));
|
|
656
|
-
const data = await response.json();
|
|
657
|
-
|
|
658
|
-
if (response.ok) {
|
|
659
|
-
return { success: true, data };
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
return { success: false, error: 'Failed to fetch conversations' };
|
|
663
|
-
} catch (_error) {
|
|
664
|
-
return { success: false, error: 'Network error' };
|
|
665
|
-
}
|
|
666
|
-
},
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* Get a single message by ID
|
|
670
|
-
*/
|
|
671
|
-
async getHistoryMessage(id: string): Promise<ApiResponse<HistoryMessage>> {
|
|
672
|
-
try {
|
|
673
|
-
const response = await apiFetch(getApiUrl(`/api/history/message/${encodeURIComponent(id)}`));
|
|
674
|
-
const data = await response.json();
|
|
675
|
-
|
|
676
|
-
if (response.ok) {
|
|
677
|
-
return { success: true, data };
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
return { success: false, error: data.error || 'Failed to fetch message' };
|
|
681
|
-
} catch (_error) {
|
|
682
|
-
return { success: false, error: 'Network error' };
|
|
683
|
-
}
|
|
684
|
-
},
|
|
685
|
-
|
|
686
|
-
/**
|
|
687
|
-
* Get storage statistics
|
|
688
|
-
*/
|
|
689
|
-
async getHistoryStats(): Promise<ApiResponse<HistoryStats>> {
|
|
690
|
-
try {
|
|
691
|
-
const response = await apiFetch(getApiUrl('/api/history/stats'));
|
|
692
|
-
const data = await response.json();
|
|
693
|
-
|
|
694
|
-
if (response.ok) {
|
|
695
|
-
return { success: true, data };
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
return { success: false, error: 'Failed to fetch stats' };
|
|
699
|
-
} catch (_error) {
|
|
700
|
-
return { success: false, error: 'Network error' };
|
|
701
|
-
}
|
|
702
|
-
},
|
|
703
|
-
|
|
704
|
-
// ===== File Search API =====
|
|
705
|
-
|
|
706
|
-
/**
|
|
707
|
-
* Search for files in the repository
|
|
708
|
-
*/
|
|
709
|
-
async searchFiles(params?: {
|
|
710
|
-
query?: string;
|
|
711
|
-
limit?: number;
|
|
712
|
-
}): Promise<ApiResponse<FileSearchResponse>> {
|
|
713
|
-
try {
|
|
714
|
-
const queryParams = new URLSearchParams();
|
|
715
|
-
if (params?.query) queryParams.set('q', params.query);
|
|
716
|
-
if (params?.limit) queryParams.set('limit', String(params.limit));
|
|
717
|
-
|
|
718
|
-
const response = await apiFetch(getApiUrl(`/api/files?${queryParams}`));
|
|
719
|
-
const data = await response.json();
|
|
720
|
-
|
|
721
|
-
if (response.ok) {
|
|
722
|
-
return { success: true, data };
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
return { success: false, error: 'Failed to search files' };
|
|
726
|
-
} catch (_error) {
|
|
727
|
-
return { success: false, error: 'Network error' };
|
|
728
|
-
}
|
|
729
|
-
},
|
|
730
|
-
|
|
731
|
-
// ===== Decision Queue API =====
|
|
732
|
-
|
|
733
|
-
/**
|
|
734
|
-
* Get all pending decisions
|
|
735
|
-
*/
|
|
736
|
-
async getDecisions(): Promise<ApiResponse<{ decisions: ApiDecision[] }>> {
|
|
737
|
-
try {
|
|
738
|
-
const response = await apiFetch(getApiUrl('/api/decisions'));
|
|
739
|
-
const data = await response.json();
|
|
740
|
-
|
|
741
|
-
if (response.ok && data.success) {
|
|
742
|
-
return { success: true, data: { decisions: data.decisions || [] } };
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
return { success: false, error: data.error || 'Failed to fetch decisions' };
|
|
746
|
-
} catch (_error) {
|
|
747
|
-
return { success: false, error: 'Network error' };
|
|
748
|
-
}
|
|
749
|
-
},
|
|
750
|
-
|
|
751
|
-
/**
|
|
752
|
-
* Approve a decision
|
|
753
|
-
*/
|
|
754
|
-
async approveDecision(id: string, optionId?: string, response?: string): Promise<ApiResponse<void>> {
|
|
755
|
-
try {
|
|
756
|
-
const res = await apiFetch(getApiUrl(`/api/decisions/${encodeURIComponent(id)}/approve`), {
|
|
757
|
-
method: 'POST',
|
|
758
|
-
body: JSON.stringify({ optionId, response }),
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
const data = await res.json();
|
|
762
|
-
|
|
763
|
-
if (res.ok && data.success) {
|
|
764
|
-
return { success: true };
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
return { success: false, error: data.error || 'Failed to approve decision' };
|
|
768
|
-
} catch (_error) {
|
|
769
|
-
return { success: false, error: 'Network error' };
|
|
770
|
-
}
|
|
771
|
-
},
|
|
772
|
-
|
|
773
|
-
/**
|
|
774
|
-
* Reject a decision
|
|
775
|
-
*/
|
|
776
|
-
async rejectDecision(id: string, reason?: string): Promise<ApiResponse<void>> {
|
|
777
|
-
try {
|
|
778
|
-
const res = await apiFetch(getApiUrl(`/api/decisions/${encodeURIComponent(id)}/reject`), {
|
|
779
|
-
method: 'POST',
|
|
780
|
-
body: JSON.stringify({ reason }),
|
|
781
|
-
});
|
|
782
|
-
|
|
783
|
-
const data = await res.json();
|
|
784
|
-
|
|
785
|
-
if (res.ok && data.success) {
|
|
786
|
-
return { success: true };
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
return { success: false, error: data.error || 'Failed to reject decision' };
|
|
790
|
-
} catch (_error) {
|
|
791
|
-
return { success: false, error: 'Network error' };
|
|
792
|
-
}
|
|
793
|
-
},
|
|
794
|
-
|
|
795
|
-
/**
|
|
796
|
-
* Dismiss a decision
|
|
797
|
-
*/
|
|
798
|
-
async dismissDecision(id: string): Promise<ApiResponse<void>> {
|
|
799
|
-
try {
|
|
800
|
-
const res = await apiFetch(getApiUrl(`/api/decisions/${encodeURIComponent(id)}`), {
|
|
801
|
-
method: 'DELETE',
|
|
802
|
-
});
|
|
803
|
-
|
|
804
|
-
const data = await res.json();
|
|
805
|
-
|
|
806
|
-
if (res.ok && data.success) {
|
|
807
|
-
return { success: true };
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
return { success: false, error: data.error || 'Failed to dismiss decision' };
|
|
811
|
-
} catch (_error) {
|
|
812
|
-
return { success: false, error: 'Network error' };
|
|
813
|
-
}
|
|
814
|
-
},
|
|
815
|
-
|
|
816
|
-
// ===== Fleet Overview API =====
|
|
817
|
-
|
|
818
|
-
/**
|
|
819
|
-
* Get fleet servers
|
|
820
|
-
*/
|
|
821
|
-
async getFleetServers(): Promise<ApiResponse<{ servers: FleetServer[] }>> {
|
|
822
|
-
try {
|
|
823
|
-
const response = await apiFetch(getApiUrl('/api/fleet/servers'));
|
|
824
|
-
const data = await response.json();
|
|
825
|
-
|
|
826
|
-
if (response.ok && data.success) {
|
|
827
|
-
return { success: true, data: { servers: data.servers || [] } };
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
return { success: false, error: data.error || 'Failed to fetch fleet servers' };
|
|
831
|
-
} catch (_error) {
|
|
832
|
-
return { success: false, error: 'Network error' };
|
|
833
|
-
}
|
|
834
|
-
},
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Get fleet statistics
|
|
838
|
-
*/
|
|
839
|
-
async getFleetStats(): Promise<ApiResponse<{ stats: FleetStats }>> {
|
|
840
|
-
try {
|
|
841
|
-
const response = await apiFetch(getApiUrl('/api/fleet/stats'));
|
|
842
|
-
const data = await response.json();
|
|
843
|
-
|
|
844
|
-
if (response.ok && data.success) {
|
|
845
|
-
return { success: true, data: { stats: data.stats } };
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
return { success: false, error: data.error || 'Failed to fetch fleet stats' };
|
|
849
|
-
} catch (_error) {
|
|
850
|
-
return { success: false, error: 'Network error' };
|
|
851
|
-
}
|
|
852
|
-
},
|
|
853
|
-
|
|
854
|
-
// ===== Task Assignment API =====
|
|
855
|
-
|
|
856
|
-
/**
|
|
857
|
-
* Get all tasks
|
|
858
|
-
*/
|
|
859
|
-
async getTasks(params?: {
|
|
860
|
-
status?: string;
|
|
861
|
-
agent?: string;
|
|
862
|
-
}): Promise<ApiResponse<{ tasks: TaskAssignment[] }>> {
|
|
863
|
-
try {
|
|
864
|
-
const queryParams = new URLSearchParams();
|
|
865
|
-
if (params?.status) queryParams.set('status', params.status);
|
|
866
|
-
if (params?.agent) queryParams.set('agent', params.agent);
|
|
867
|
-
|
|
868
|
-
const response = await apiFetch(getApiUrl(`/api/tasks?${queryParams}`));
|
|
869
|
-
const data = await response.json();
|
|
870
|
-
|
|
871
|
-
if (response.ok && data.success) {
|
|
872
|
-
return { success: true, data: { tasks: data.tasks || [] } };
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
return { success: false, error: data.error || 'Failed to fetch tasks' };
|
|
876
|
-
} catch (_error) {
|
|
877
|
-
return { success: false, error: 'Network error' };
|
|
878
|
-
}
|
|
879
|
-
},
|
|
880
|
-
|
|
881
|
-
/**
|
|
882
|
-
* Create and assign a task
|
|
883
|
-
*/
|
|
884
|
-
async createTask(request: {
|
|
885
|
-
agentName: string;
|
|
886
|
-
title: string;
|
|
887
|
-
description?: string;
|
|
888
|
-
priority: 'low' | 'medium' | 'high' | 'critical';
|
|
889
|
-
}): Promise<ApiResponse<{ task: TaskAssignment }>> {
|
|
890
|
-
try {
|
|
891
|
-
const response = await apiFetch(getApiUrl('/api/tasks'), {
|
|
892
|
-
method: 'POST',
|
|
893
|
-
body: JSON.stringify(request),
|
|
894
|
-
});
|
|
895
|
-
|
|
896
|
-
const data = await response.json();
|
|
897
|
-
|
|
898
|
-
if (response.ok && data.success) {
|
|
899
|
-
return { success: true, data: { task: data.task } };
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
return { success: false, error: data.error || 'Failed to create task' };
|
|
903
|
-
} catch (_error) {
|
|
904
|
-
return { success: false, error: 'Network error' };
|
|
905
|
-
}
|
|
906
|
-
},
|
|
907
|
-
|
|
908
|
-
/**
|
|
909
|
-
* Update task status
|
|
910
|
-
*/
|
|
911
|
-
async updateTask(id: string, updates: {
|
|
912
|
-
status?: TaskAssignment['status'];
|
|
913
|
-
result?: string;
|
|
914
|
-
}): Promise<ApiResponse<{ task: TaskAssignment }>> {
|
|
915
|
-
try {
|
|
916
|
-
const response = await apiFetch(getApiUrl(`/api/tasks/${encodeURIComponent(id)}`), {
|
|
917
|
-
method: 'PATCH',
|
|
918
|
-
body: JSON.stringify(updates),
|
|
919
|
-
});
|
|
920
|
-
|
|
921
|
-
const data = await response.json();
|
|
922
|
-
|
|
923
|
-
if (response.ok && data.success) {
|
|
924
|
-
return { success: true, data: { task: data.task } };
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
return { success: false, error: data.error || 'Failed to update task' };
|
|
928
|
-
} catch (_error) {
|
|
929
|
-
return { success: false, error: 'Network error' };
|
|
930
|
-
}
|
|
931
|
-
},
|
|
932
|
-
|
|
933
|
-
/**
|
|
934
|
-
* Cancel a task
|
|
935
|
-
*/
|
|
936
|
-
async cancelTask(id: string): Promise<ApiResponse<void>> {
|
|
937
|
-
try {
|
|
938
|
-
const response = await apiFetch(getApiUrl(`/api/tasks/${encodeURIComponent(id)}`), {
|
|
939
|
-
method: 'DELETE',
|
|
940
|
-
});
|
|
941
|
-
|
|
942
|
-
const data = await response.json();
|
|
943
|
-
|
|
944
|
-
if (response.ok && data.success) {
|
|
945
|
-
return { success: true };
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
return { success: false, error: data.error || 'Failed to cancel task' };
|
|
949
|
-
} catch (_error) {
|
|
950
|
-
return { success: false, error: 'Network error' };
|
|
951
|
-
}
|
|
952
|
-
},
|
|
953
|
-
|
|
954
|
-
// ===== Beads Integration API =====
|
|
955
|
-
|
|
956
|
-
/**
|
|
957
|
-
* Create a bead (task/issue) via the beads CLI
|
|
958
|
-
*/
|
|
959
|
-
async createBead(request: {
|
|
960
|
-
title: string;
|
|
961
|
-
assignee?: string;
|
|
962
|
-
priority?: number;
|
|
963
|
-
type?: 'task' | 'bug' | 'feature';
|
|
964
|
-
description?: string;
|
|
965
|
-
}): Promise<ApiResponse<{ bead: { id: string; title: string } }>> {
|
|
966
|
-
try {
|
|
967
|
-
const response = await apiFetch(getApiUrl('/api/beads'), {
|
|
968
|
-
method: 'POST',
|
|
969
|
-
body: JSON.stringify(request),
|
|
970
|
-
});
|
|
971
|
-
|
|
972
|
-
const data = await response.json();
|
|
973
|
-
|
|
974
|
-
if (response.ok && data.success) {
|
|
975
|
-
return { success: true, data: { bead: data.bead } };
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
return { success: false, error: data.error || 'Failed to create bead' };
|
|
979
|
-
} catch (_error) {
|
|
980
|
-
return { success: false, error: 'Network error' };
|
|
981
|
-
}
|
|
982
|
-
},
|
|
983
|
-
|
|
984
|
-
/**
|
|
985
|
-
* Send a relay message to an agent (non-interrupting notification)
|
|
986
|
-
*/
|
|
987
|
-
async sendRelayMessage(request: {
|
|
988
|
-
to: string;
|
|
989
|
-
content: string;
|
|
990
|
-
thread?: string;
|
|
991
|
-
}): Promise<ApiResponse<{ messageId: string }>> {
|
|
992
|
-
try {
|
|
993
|
-
const response = await apiFetch(getApiUrl('/api/relay/send'), {
|
|
994
|
-
method: 'POST',
|
|
995
|
-
body: JSON.stringify(request),
|
|
996
|
-
});
|
|
997
|
-
|
|
998
|
-
const data = await response.json();
|
|
999
|
-
|
|
1000
|
-
if (response.ok && data.success) {
|
|
1001
|
-
return { success: true, data: { messageId: data.messageId } };
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
return { success: false, error: data.error || 'Failed to send message' };
|
|
1005
|
-
} catch (_error) {
|
|
1006
|
-
return { success: false, error: 'Network error' };
|
|
1007
|
-
}
|
|
1008
|
-
},
|
|
1009
|
-
};
|
|
1010
|
-
|
|
1011
|
-
// History API types
|
|
1012
|
-
export interface HistorySession {
|
|
1013
|
-
id: string;
|
|
1014
|
-
agentName: string;
|
|
1015
|
-
cli?: string;
|
|
1016
|
-
startedAt: string;
|
|
1017
|
-
endedAt?: string;
|
|
1018
|
-
duration: string;
|
|
1019
|
-
messageCount: number;
|
|
1020
|
-
summary?: string;
|
|
1021
|
-
isActive: boolean;
|
|
1022
|
-
closedBy?: 'agent' | 'disconnect' | 'error';
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
export interface HistoryMessage {
|
|
1026
|
-
id: string;
|
|
1027
|
-
from: string;
|
|
1028
|
-
to: string;
|
|
1029
|
-
content: string;
|
|
1030
|
-
timestamp: string;
|
|
1031
|
-
thread?: string;
|
|
1032
|
-
isBroadcast?: boolean;
|
|
1033
|
-
isUrgent?: boolean;
|
|
1034
|
-
status?: string;
|
|
1035
|
-
data?: Record<string, unknown>;
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
export interface Conversation {
|
|
1039
|
-
participants: string[];
|
|
1040
|
-
lastMessage: string;
|
|
1041
|
-
lastTimestamp: string;
|
|
1042
|
-
messageCount: number;
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
export interface HistoryStats {
|
|
1046
|
-
messageCount: number | string;
|
|
1047
|
-
sessionCount: number | string;
|
|
1048
|
-
activeSessions: number | string;
|
|
1049
|
-
uniqueAgents: number | string;
|
|
1050
|
-
oldestMessageDate?: string | null;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
// File search types
|
|
1054
|
-
export interface FileSearchResult {
|
|
1055
|
-
path: string;
|
|
1056
|
-
name: string;
|
|
1057
|
-
isDirectory: boolean;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
export interface FileSearchResponse {
|
|
1061
|
-
files: FileSearchResult[];
|
|
1062
|
-
query: string;
|
|
1063
|
-
searchRoot: string;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
// Decision Queue types (API response format)
|
|
1067
|
-
export interface ApiDecision {
|
|
1068
|
-
id: string;
|
|
1069
|
-
agentName: string;
|
|
1070
|
-
title: string;
|
|
1071
|
-
description: string;
|
|
1072
|
-
options?: { id: string; label: string; description?: string }[];
|
|
1073
|
-
urgency: 'low' | 'medium' | 'high' | 'critical';
|
|
1074
|
-
category: 'approval' | 'choice' | 'input' | 'confirmation';
|
|
1075
|
-
createdAt: string;
|
|
1076
|
-
expiresAt?: string;
|
|
1077
|
-
context?: Record<string, unknown>;
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
// Decision type (component format)
|
|
1081
|
-
export interface Decision {
|
|
1082
|
-
id: string;
|
|
1083
|
-
agentName: string;
|
|
1084
|
-
timestamp: string | number;
|
|
1085
|
-
type: 'approval' | 'choice' | 'confirmation' | 'input';
|
|
1086
|
-
title: string;
|
|
1087
|
-
description: string;
|
|
1088
|
-
options?: { id: string; label: string; description?: string }[];
|
|
1089
|
-
priority: 'low' | 'medium' | 'high' | 'critical';
|
|
1090
|
-
context?: Record<string, unknown>;
|
|
1091
|
-
expiresAt?: string | number;
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
// Convert API decision to component format
|
|
1095
|
-
export function convertApiDecision(apiDecision: ApiDecision): Decision {
|
|
1096
|
-
return {
|
|
1097
|
-
id: apiDecision.id,
|
|
1098
|
-
agentName: apiDecision.agentName,
|
|
1099
|
-
timestamp: apiDecision.createdAt,
|
|
1100
|
-
type: apiDecision.category,
|
|
1101
|
-
title: apiDecision.title,
|
|
1102
|
-
description: apiDecision.description,
|
|
1103
|
-
options: apiDecision.options,
|
|
1104
|
-
priority: apiDecision.urgency,
|
|
1105
|
-
context: apiDecision.context,
|
|
1106
|
-
expiresAt: apiDecision.expiresAt,
|
|
1107
|
-
};
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
// Fleet types
|
|
1111
|
-
export interface FleetServer {
|
|
1112
|
-
id: string;
|
|
1113
|
-
name: string;
|
|
1114
|
-
status: 'healthy' | 'degraded' | 'offline';
|
|
1115
|
-
agents: { name: string; status: string }[];
|
|
1116
|
-
cpuUsage: number;
|
|
1117
|
-
memoryUsage: number;
|
|
1118
|
-
activeConnections: number;
|
|
1119
|
-
uptime: number;
|
|
1120
|
-
lastHeartbeat: string;
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
export interface FleetStats {
|
|
1124
|
-
totalAgents: number;
|
|
1125
|
-
onlineAgents: number;
|
|
1126
|
-
busyAgents: number;
|
|
1127
|
-
pendingDecisions: number;
|
|
1128
|
-
activeTasks: number;
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
// Task Assignment types
|
|
1132
|
-
export interface TaskAssignment {
|
|
1133
|
-
id: string;
|
|
1134
|
-
agentName: string;
|
|
1135
|
-
title: string;
|
|
1136
|
-
description: string;
|
|
1137
|
-
priority: 'low' | 'medium' | 'high' | 'critical';
|
|
1138
|
-
status: 'pending' | 'assigned' | 'in_progress' | 'completed' | 'failed';
|
|
1139
|
-
createdAt: string;
|
|
1140
|
-
assignedAt?: string;
|
|
1141
|
-
completedAt?: string;
|
|
1142
|
-
result?: string;
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
/**
|
|
1146
|
-
* Create a singleton WebSocket connection
|
|
1147
|
-
*/
|
|
1148
|
-
let wsInstance: DashboardWebSocket | null = null;
|
|
1149
|
-
|
|
1150
|
-
export function getWebSocket(): DashboardWebSocket {
|
|
1151
|
-
if (!wsInstance) {
|
|
1152
|
-
wsInstance = new DashboardWebSocket();
|
|
1153
|
-
}
|
|
1154
|
-
return wsInstance;
|
|
1155
|
-
}
|