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,309 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useMessages Hook
|
|
3
|
-
*
|
|
4
|
-
* React hook for managing message state with filtering,
|
|
5
|
-
* threading, and send functionality.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useState, useMemo, useCallback, useEffect } from 'react';
|
|
9
|
-
import type { Message, SendMessageRequest } from '../../types';
|
|
10
|
-
import { api } from '../../lib/api';
|
|
11
|
-
|
|
12
|
-
export interface UseMessagesOptions {
|
|
13
|
-
messages: Message[];
|
|
14
|
-
currentChannel?: string;
|
|
15
|
-
/** Optional sender name for cloud mode (GitHub username). Falls back to 'Dashboard' if not provided. */
|
|
16
|
-
senderName?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface ThreadInfo {
|
|
20
|
-
id: string;
|
|
21
|
-
name: string;
|
|
22
|
-
lastMessage: Message;
|
|
23
|
-
messageCount: number;
|
|
24
|
-
unreadCount: number;
|
|
25
|
-
participants: string[];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface UseMessagesReturn {
|
|
29
|
-
// Filtered messages
|
|
30
|
-
messages: Message[];
|
|
31
|
-
threadMessages: (threadId: string) => Message[];
|
|
32
|
-
|
|
33
|
-
// Channel/thread state
|
|
34
|
-
currentChannel: string;
|
|
35
|
-
setCurrentChannel: (channel: string) => void;
|
|
36
|
-
currentThread: string | null;
|
|
37
|
-
setCurrentThread: (threadId: string | null) => void;
|
|
38
|
-
|
|
39
|
-
// Thread info
|
|
40
|
-
activeThreads: ThreadInfo[];
|
|
41
|
-
totalUnreadThreadCount: number;
|
|
42
|
-
|
|
43
|
-
// Message actions
|
|
44
|
-
sendMessage: (to: string, content: string, thread?: string, attachmentIds?: string[]) => Promise<boolean>;
|
|
45
|
-
isSending: boolean;
|
|
46
|
-
sendError: string | null;
|
|
47
|
-
|
|
48
|
-
// Stats
|
|
49
|
-
totalCount: number;
|
|
50
|
-
unreadCount: number;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function useMessages({
|
|
54
|
-
messages,
|
|
55
|
-
currentChannel: initialChannel = 'general',
|
|
56
|
-
senderName,
|
|
57
|
-
}: UseMessagesOptions): UseMessagesReturn {
|
|
58
|
-
const [currentChannel, setCurrentChannel] = useState(initialChannel);
|
|
59
|
-
const [currentThreadInternal, setCurrentThreadInternal] = useState<string | null>(null);
|
|
60
|
-
const [isSending, setIsSending] = useState(false);
|
|
61
|
-
const [sendError, setSendError] = useState<string | null>(null);
|
|
62
|
-
|
|
63
|
-
// Track seen threads with timestamp of when they were last viewed
|
|
64
|
-
// This allows us to show new messages that arrive after viewing
|
|
65
|
-
const [seenThreads, setSeenThreads] = useState<Map<string, number>>(new Map());
|
|
66
|
-
|
|
67
|
-
// Effective sender name for the current user (used for filtering own messages)
|
|
68
|
-
const effectiveSenderName = senderName || 'Dashboard';
|
|
69
|
-
|
|
70
|
-
// Optimistic messages: shown immediately before server confirms
|
|
71
|
-
// These have status='sending' and a temp ID prefixed with 'optimistic-'
|
|
72
|
-
const [optimisticMessages, setOptimisticMessages] = useState<Message[]>([]);
|
|
73
|
-
|
|
74
|
-
// Clean up optimistic messages when they appear in the real messages list
|
|
75
|
-
// Match by to + content only (not from, since server may use different sender like '_DashboardUI')
|
|
76
|
-
useEffect(() => {
|
|
77
|
-
if (optimisticMessages.length === 0) return;
|
|
78
|
-
|
|
79
|
-
// Create a set of "fingerprints" for real messages (recent ones only)
|
|
80
|
-
// Use to + content only - the 'from' field may differ between optimistic (user's name)
|
|
81
|
-
// and real message (server may use '_DashboardUI' as relay client name)
|
|
82
|
-
const recentMessages = messages.slice(-50); // Only check recent messages for performance
|
|
83
|
-
const realFingerprints = new Set(
|
|
84
|
-
recentMessages.map((m) => `${m.to}:${m.content.slice(0, 100)}`)
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
// Remove optimistic messages that now exist in real messages
|
|
88
|
-
setOptimisticMessages((prev) =>
|
|
89
|
-
prev.filter((opt) => {
|
|
90
|
-
const fingerprint = `${opt.to}:${opt.content.slice(0, 100)}`;
|
|
91
|
-
return !realFingerprints.has(fingerprint);
|
|
92
|
-
})
|
|
93
|
-
);
|
|
94
|
-
}, [messages, optimisticMessages.length]);
|
|
95
|
-
|
|
96
|
-
// Combine real messages with optimistic messages
|
|
97
|
-
const allMessages = useMemo(() => {
|
|
98
|
-
if (optimisticMessages.length === 0) return messages;
|
|
99
|
-
// Append optimistic messages at the end (they're the most recent)
|
|
100
|
-
return [...messages, ...optimisticMessages];
|
|
101
|
-
}, [messages, optimisticMessages]);
|
|
102
|
-
|
|
103
|
-
// Filter messages by current channel
|
|
104
|
-
// Only exclude reply-chain replies (where thread is another message's ID)
|
|
105
|
-
// Keep topic thread messages (where thread is a topic name, not a message ID)
|
|
106
|
-
const filteredMessages = useMemo(() => {
|
|
107
|
-
// Build set of message IDs for efficient lookup
|
|
108
|
-
const messageIds = new Set(allMessages.map((m) => m.id));
|
|
109
|
-
|
|
110
|
-
// Filter out reply-chain replies (thread points to existing message ID)
|
|
111
|
-
// Keep topic thread messages (thread is a name, not a message ID)
|
|
112
|
-
const mainViewMessages = allMessages.filter((m) => {
|
|
113
|
-
if (!m.thread) return true; // No thread - show it
|
|
114
|
-
// If thread is a message ID, it's a reply - hide it from main view
|
|
115
|
-
// If thread is a topic name, show it
|
|
116
|
-
return !messageIds.has(m.thread);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
if (currentChannel === 'general') {
|
|
120
|
-
return mainViewMessages;
|
|
121
|
-
}
|
|
122
|
-
return mainViewMessages.filter(
|
|
123
|
-
(m) => m.from === currentChannel || m.to === currentChannel
|
|
124
|
-
);
|
|
125
|
-
}, [allMessages, currentChannel]);
|
|
126
|
-
|
|
127
|
-
// Get messages for a specific thread
|
|
128
|
-
const threadMessages = useCallback(
|
|
129
|
-
(threadId: string) => allMessages.filter((m) => m.thread === threadId),
|
|
130
|
-
[allMessages]
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
// Calculate active threads with unread counts
|
|
134
|
-
const activeThreads = useMemo((): ThreadInfo[] => {
|
|
135
|
-
const threadMap = new Map<string, Message[]>();
|
|
136
|
-
const messageIds = new Set(allMessages.map((m) => m.id));
|
|
137
|
-
|
|
138
|
-
// Group messages by thread
|
|
139
|
-
for (const msg of allMessages) {
|
|
140
|
-
if (msg.thread) {
|
|
141
|
-
const existing = threadMap.get(msg.thread) || [];
|
|
142
|
-
existing.push(msg);
|
|
143
|
-
threadMap.set(msg.thread, existing);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Convert to ThreadInfo array
|
|
148
|
-
const threads: ThreadInfo[] = [];
|
|
149
|
-
for (const [threadId, threadMsgs] of threadMap.entries()) {
|
|
150
|
-
// Sort by timestamp to get the last message
|
|
151
|
-
const sorted = [...threadMsgs].sort(
|
|
152
|
-
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
// Get unique participants
|
|
156
|
-
const participants = [...new Set(threadMsgs.flatMap((m) => [m.from, m.to]))].filter(
|
|
157
|
-
(p) => p !== '*'
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
// Count unread messages in thread
|
|
161
|
-
// Consider messages as "read" if they arrived before we last viewed this thread
|
|
162
|
-
// Exclude messages from current user - users shouldn't get notifications for their own messages
|
|
163
|
-
const seenTimestamp = seenThreads.get(threadId);
|
|
164
|
-
const unreadCount = threadMsgs.filter((m) => {
|
|
165
|
-
if (m.from === effectiveSenderName) return false; // Don't count own messages as unread
|
|
166
|
-
if (m.isRead) return false; // Already marked as read
|
|
167
|
-
if (seenTimestamp) {
|
|
168
|
-
// If we've seen this thread, only count messages after that time
|
|
169
|
-
return new Date(m.timestamp).getTime() > seenTimestamp;
|
|
170
|
-
}
|
|
171
|
-
return true; // Not seen yet, count as unread
|
|
172
|
-
}).length;
|
|
173
|
-
|
|
174
|
-
// Determine thread name: if threadId is a message ID, use first message content as name
|
|
175
|
-
let name = threadId;
|
|
176
|
-
if (messageIds.has(threadId)) {
|
|
177
|
-
// Find the original message that started the thread
|
|
178
|
-
const originalMsg = allMessages.find((m) => m.id === threadId);
|
|
179
|
-
if (originalMsg) {
|
|
180
|
-
// Use first line of content, truncated
|
|
181
|
-
const firstLine = originalMsg.content.split('\n')[0];
|
|
182
|
-
name = firstLine.length > 30 ? firstLine.substring(0, 30) + '...' : firstLine;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
threads.push({
|
|
187
|
-
id: threadId,
|
|
188
|
-
name,
|
|
189
|
-
lastMessage: sorted[0],
|
|
190
|
-
messageCount: threadMsgs.length,
|
|
191
|
-
unreadCount,
|
|
192
|
-
participants,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Sort by last activity (most recent first)
|
|
197
|
-
return threads.sort(
|
|
198
|
-
(a, b) =>
|
|
199
|
-
new Date(b.lastMessage.timestamp).getTime() - new Date(a.lastMessage.timestamp).getTime()
|
|
200
|
-
);
|
|
201
|
-
}, [allMessages, seenThreads]);
|
|
202
|
-
|
|
203
|
-
// Wrapper for setCurrentThread that also marks the thread as seen
|
|
204
|
-
const setCurrentThread = useCallback((threadId: string | null) => {
|
|
205
|
-
setCurrentThreadInternal(threadId);
|
|
206
|
-
if (threadId) {
|
|
207
|
-
// Mark thread as seen with current timestamp
|
|
208
|
-
setSeenThreads((prev) => {
|
|
209
|
-
const next = new Map(prev);
|
|
210
|
-
next.set(threadId, Date.now());
|
|
211
|
-
return next;
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
}, []);
|
|
215
|
-
|
|
216
|
-
// Calculate total unread threads
|
|
217
|
-
const totalUnreadThreadCount = useMemo(
|
|
218
|
-
() => activeThreads.filter((t) => t.unreadCount > 0).length,
|
|
219
|
-
[activeThreads]
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
// Calculate stats
|
|
223
|
-
const stats = useMemo(() => {
|
|
224
|
-
const unread = allMessages.filter((m) => !m.isRead).length;
|
|
225
|
-
return {
|
|
226
|
-
totalCount: allMessages.length,
|
|
227
|
-
unreadCount: unread,
|
|
228
|
-
};
|
|
229
|
-
}, [allMessages]);
|
|
230
|
-
|
|
231
|
-
// Send message function with optimistic updates
|
|
232
|
-
const sendMessage = useCallback(
|
|
233
|
-
async (to: string, content: string, thread?: string, attachmentIds?: string[]): Promise<boolean> => {
|
|
234
|
-
setIsSending(true);
|
|
235
|
-
setSendError(null);
|
|
236
|
-
|
|
237
|
-
// Create optimistic message and add it immediately for snappy UX
|
|
238
|
-
const from = effectiveSenderName;
|
|
239
|
-
const optimisticId = `optimistic-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
240
|
-
const optimisticMsg: Message = {
|
|
241
|
-
id: optimisticId,
|
|
242
|
-
from,
|
|
243
|
-
to,
|
|
244
|
-
content,
|
|
245
|
-
timestamp: new Date().toISOString(),
|
|
246
|
-
status: 'sending',
|
|
247
|
-
thread,
|
|
248
|
-
isRead: true, // User's own messages are always "read"
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
// Add optimistic message immediately - UI updates instantly
|
|
252
|
-
setOptimisticMessages((prev) => [...prev, optimisticMsg]);
|
|
253
|
-
|
|
254
|
-
try {
|
|
255
|
-
const request: SendMessageRequest & { from?: string } = {
|
|
256
|
-
to,
|
|
257
|
-
message: content,
|
|
258
|
-
thread,
|
|
259
|
-
attachments: attachmentIds,
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// Include sender name for cloud mode (GitHub username)
|
|
263
|
-
if (senderName) {
|
|
264
|
-
request.from = senderName;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Use api.sendMessage which handles:
|
|
268
|
-
// - Workspace proxy routing (in cloud mode)
|
|
269
|
-
// - CSRF token headers
|
|
270
|
-
// - Credentials
|
|
271
|
-
const result = await api.sendMessage(request);
|
|
272
|
-
|
|
273
|
-
if (result.success) {
|
|
274
|
-
// Success! The optimistic message will be cleaned up when
|
|
275
|
-
// the real message arrives via WebSocket
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Failed - remove the optimistic message and show error
|
|
280
|
-
setOptimisticMessages((prev) => prev.filter((m) => m.id !== optimisticId));
|
|
281
|
-
setSendError(result.error || 'Failed to send message');
|
|
282
|
-
return false;
|
|
283
|
-
} catch (_error) {
|
|
284
|
-
// Network error - remove optimistic message
|
|
285
|
-
setOptimisticMessages((prev) => prev.filter((m) => m.id !== optimisticId));
|
|
286
|
-
setSendError('Network error');
|
|
287
|
-
return false;
|
|
288
|
-
} finally {
|
|
289
|
-
setIsSending(false);
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
[effectiveSenderName, senderName]
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
return {
|
|
296
|
-
messages: filteredMessages,
|
|
297
|
-
threadMessages,
|
|
298
|
-
currentChannel,
|
|
299
|
-
setCurrentChannel,
|
|
300
|
-
currentThread: currentThreadInternal,
|
|
301
|
-
setCurrentThread,
|
|
302
|
-
activeThreads,
|
|
303
|
-
totalUnreadThreadCount,
|
|
304
|
-
sendMessage,
|
|
305
|
-
isSending,
|
|
306
|
-
sendError,
|
|
307
|
-
...stats,
|
|
308
|
-
};
|
|
309
|
-
}
|
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useOrchestrator Hook
|
|
3
|
-
*
|
|
4
|
-
* Connects to the daemon orchestrator for workspace and agent management.
|
|
5
|
-
* Provides real-time updates via WebSocket.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
9
|
-
import type { Workspace } from '../WorkspaceSelector';
|
|
10
|
-
|
|
11
|
-
export interface OrchestratorAgent {
|
|
12
|
-
id: string;
|
|
13
|
-
name: string;
|
|
14
|
-
workspaceId: string;
|
|
15
|
-
provider: string;
|
|
16
|
-
status: 'running' | 'idle' | 'crashed' | 'restarting' | 'stopped';
|
|
17
|
-
pid?: number;
|
|
18
|
-
task?: string;
|
|
19
|
-
spawnedAt: Date;
|
|
20
|
-
restartCount: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface OrchestratorEvent {
|
|
24
|
-
type: string;
|
|
25
|
-
workspaceId?: string;
|
|
26
|
-
agentId?: string;
|
|
27
|
-
data: unknown;
|
|
28
|
-
timestamp: Date;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface UseOrchestratorOptions {
|
|
32
|
-
/** Orchestrator API URL (default: http://localhost:3456) */
|
|
33
|
-
apiUrl?: string;
|
|
34
|
-
/** Enable orchestrator connection (default: false - orchestrator is optional) */
|
|
35
|
-
enabled?: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface UseOrchestratorResult {
|
|
39
|
-
/** All workspaces */
|
|
40
|
-
workspaces: Workspace[];
|
|
41
|
-
/** Currently active workspace ID */
|
|
42
|
-
activeWorkspaceId?: string;
|
|
43
|
-
/** Active workspace agents */
|
|
44
|
-
agents: OrchestratorAgent[];
|
|
45
|
-
/** Connection status */
|
|
46
|
-
isConnected: boolean;
|
|
47
|
-
/** Loading state */
|
|
48
|
-
isLoading: boolean;
|
|
49
|
-
/** Error state */
|
|
50
|
-
error: Error | null;
|
|
51
|
-
/** Switch to a workspace */
|
|
52
|
-
switchWorkspace: (workspaceId: string) => Promise<void>;
|
|
53
|
-
/** Add a new workspace */
|
|
54
|
-
addWorkspace: (path: string, name?: string) => Promise<Workspace>;
|
|
55
|
-
/** Remove a workspace */
|
|
56
|
-
removeWorkspace: (workspaceId: string) => Promise<void>;
|
|
57
|
-
/** Spawn an agent */
|
|
58
|
-
spawnAgent: (name: string, task?: string, provider?: string) => Promise<OrchestratorAgent>;
|
|
59
|
-
/** Stop an agent */
|
|
60
|
-
stopAgent: (agentName: string) => Promise<void>;
|
|
61
|
-
/** Refresh data */
|
|
62
|
-
refresh: () => Promise<void>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function useOrchestrator(options: UseOrchestratorOptions = {}): UseOrchestratorResult {
|
|
66
|
-
const { apiUrl = 'http://localhost:3456', enabled = false } = options;
|
|
67
|
-
|
|
68
|
-
const [workspaces, setWorkspaces] = useState<Workspace[]>([]);
|
|
69
|
-
const [activeWorkspaceId, setActiveWorkspaceId] = useState<string>();
|
|
70
|
-
const [agents, setAgents] = useState<OrchestratorAgent[]>([]);
|
|
71
|
-
const [isConnected, setIsConnected] = useState(false);
|
|
72
|
-
const [isLoading, setIsLoading] = useState(enabled);
|
|
73
|
-
const [error, setError] = useState<Error | null>(null);
|
|
74
|
-
|
|
75
|
-
const wsRef = useRef<WebSocket | null>(null);
|
|
76
|
-
const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
77
|
-
|
|
78
|
-
// Convert API URL to WebSocket URL
|
|
79
|
-
const wsUrl = apiUrl.replace(/^http/, 'ws');
|
|
80
|
-
|
|
81
|
-
// Fetch initial data - only if enabled
|
|
82
|
-
const fetchData = useCallback(async () => {
|
|
83
|
-
if (!enabled) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
setIsLoading(true);
|
|
89
|
-
setError(null);
|
|
90
|
-
|
|
91
|
-
const response = await fetch(`${apiUrl}/workspaces`);
|
|
92
|
-
if (!response.ok) {
|
|
93
|
-
throw new Error(`Failed to fetch workspaces: ${response.statusText}`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const data = await response.json();
|
|
97
|
-
setWorkspaces(
|
|
98
|
-
data.workspaces.map((w: Workspace) => ({
|
|
99
|
-
...w,
|
|
100
|
-
lastActiveAt: new Date(w.lastActiveAt),
|
|
101
|
-
}))
|
|
102
|
-
);
|
|
103
|
-
setActiveWorkspaceId(data.activeWorkspaceId);
|
|
104
|
-
|
|
105
|
-
// Fetch agents for active workspace
|
|
106
|
-
if (data.activeWorkspaceId) {
|
|
107
|
-
const agentsResponse = await fetch(`${apiUrl}/workspaces/${data.activeWorkspaceId}/agents`);
|
|
108
|
-
if (agentsResponse.ok) {
|
|
109
|
-
const agentsData = await agentsResponse.json();
|
|
110
|
-
setAgents(
|
|
111
|
-
agentsData.agents.map((a: OrchestratorAgent) => ({
|
|
112
|
-
...a,
|
|
113
|
-
spawnedAt: new Date(a.spawnedAt),
|
|
114
|
-
}))
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
} catch (err) {
|
|
119
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
120
|
-
} finally {
|
|
121
|
-
setIsLoading(false);
|
|
122
|
-
}
|
|
123
|
-
}, [apiUrl, enabled]);
|
|
124
|
-
|
|
125
|
-
// WebSocket connection - only connect if enabled
|
|
126
|
-
useEffect(() => {
|
|
127
|
-
// Skip connection if orchestrator is not enabled
|
|
128
|
-
if (!enabled) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const connect = () => {
|
|
133
|
-
try {
|
|
134
|
-
const ws = new WebSocket(wsUrl);
|
|
135
|
-
|
|
136
|
-
ws.onopen = () => {
|
|
137
|
-
setIsConnected(true);
|
|
138
|
-
setError(null);
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
ws.onmessage = (event) => {
|
|
142
|
-
try {
|
|
143
|
-
const message = JSON.parse(event.data);
|
|
144
|
-
|
|
145
|
-
if (message.type === 'init') {
|
|
146
|
-
// Initial state from server
|
|
147
|
-
setWorkspaces(
|
|
148
|
-
message.data.workspaces.map((w: Workspace) => ({
|
|
149
|
-
...w,
|
|
150
|
-
lastActiveAt: new Date(w.lastActiveAt),
|
|
151
|
-
}))
|
|
152
|
-
);
|
|
153
|
-
setActiveWorkspaceId(message.data.activeWorkspaceId);
|
|
154
|
-
setAgents(
|
|
155
|
-
message.data.agents?.map((a: OrchestratorAgent) => ({
|
|
156
|
-
...a,
|
|
157
|
-
spawnedAt: new Date(a.spawnedAt),
|
|
158
|
-
})) || []
|
|
159
|
-
);
|
|
160
|
-
setIsLoading(false);
|
|
161
|
-
} else if (message.type === 'event') {
|
|
162
|
-
handleEvent(message.data as OrchestratorEvent);
|
|
163
|
-
}
|
|
164
|
-
} catch (err) {
|
|
165
|
-
console.error('Failed to parse WebSocket message:', err);
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
ws.onclose = () => {
|
|
170
|
-
setIsConnected(false);
|
|
171
|
-
wsRef.current = null;
|
|
172
|
-
|
|
173
|
-
// Reconnect after delay
|
|
174
|
-
reconnectTimeoutRef.current = setTimeout(connect, 3000);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
ws.onerror = (err) => {
|
|
178
|
-
console.error('WebSocket error:', err);
|
|
179
|
-
ws.close();
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
wsRef.current = ws;
|
|
183
|
-
} catch (err) {
|
|
184
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
185
|
-
// Retry connection
|
|
186
|
-
reconnectTimeoutRef.current = setTimeout(connect, 3000);
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
// Start with HTTP fetch, then upgrade to WebSocket
|
|
191
|
-
fetchData().then(connect);
|
|
192
|
-
|
|
193
|
-
return () => {
|
|
194
|
-
if (reconnectTimeoutRef.current) {
|
|
195
|
-
clearTimeout(reconnectTimeoutRef.current);
|
|
196
|
-
}
|
|
197
|
-
if (wsRef.current) {
|
|
198
|
-
wsRef.current.close();
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
}, [wsUrl, fetchData, enabled]);
|
|
202
|
-
|
|
203
|
-
// Handle real-time events
|
|
204
|
-
const handleEvent = useCallback((event: OrchestratorEvent) => {
|
|
205
|
-
switch (event.type) {
|
|
206
|
-
case 'workspace:added':
|
|
207
|
-
setWorkspaces((prev) => [...prev, event.data as Workspace]);
|
|
208
|
-
break;
|
|
209
|
-
|
|
210
|
-
case 'workspace:removed':
|
|
211
|
-
setWorkspaces((prev) => prev.filter((w) => w.id !== event.workspaceId));
|
|
212
|
-
break;
|
|
213
|
-
|
|
214
|
-
case 'workspace:updated':
|
|
215
|
-
setWorkspaces((prev) =>
|
|
216
|
-
prev.map((w) =>
|
|
217
|
-
w.id === event.workspaceId ? { ...w, ...(event.data as Partial<Workspace>) } : w
|
|
218
|
-
)
|
|
219
|
-
);
|
|
220
|
-
break;
|
|
221
|
-
|
|
222
|
-
case 'workspace:switched':
|
|
223
|
-
setActiveWorkspaceId((event.data as { currentId: string }).currentId);
|
|
224
|
-
break;
|
|
225
|
-
|
|
226
|
-
case 'agent:spawned':
|
|
227
|
-
setAgents((prev) => [...prev, event.data as OrchestratorAgent]);
|
|
228
|
-
break;
|
|
229
|
-
|
|
230
|
-
case 'agent:stopped':
|
|
231
|
-
case 'agent:crashed':
|
|
232
|
-
setAgents((prev) => prev.filter((a) => a.name !== (event.data as { name: string }).name));
|
|
233
|
-
break;
|
|
234
|
-
|
|
235
|
-
case 'agent:restarted':
|
|
236
|
-
setAgents((prev) =>
|
|
237
|
-
prev.map((a) =>
|
|
238
|
-
a.name === (event.data as { name: string }).name
|
|
239
|
-
? { ...a, status: 'running' as const, restartCount: a.restartCount + 1 }
|
|
240
|
-
: a
|
|
241
|
-
)
|
|
242
|
-
);
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
|
-
}, []);
|
|
246
|
-
|
|
247
|
-
// Switch workspace
|
|
248
|
-
const switchWorkspace = useCallback(
|
|
249
|
-
async (workspaceId: string) => {
|
|
250
|
-
const response = await fetch(`${apiUrl}/workspaces/${workspaceId}/switch`, {
|
|
251
|
-
method: 'POST',
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
if (!response.ok) {
|
|
255
|
-
throw new Error(`Failed to switch workspace: ${response.statusText}`);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Fetch agents for new workspace
|
|
259
|
-
const agentsResponse = await fetch(`${apiUrl}/workspaces/${workspaceId}/agents`);
|
|
260
|
-
if (agentsResponse.ok) {
|
|
261
|
-
const agentsData = await agentsResponse.json();
|
|
262
|
-
setAgents(
|
|
263
|
-
agentsData.agents.map((a: OrchestratorAgent) => ({
|
|
264
|
-
...a,
|
|
265
|
-
spawnedAt: new Date(a.spawnedAt),
|
|
266
|
-
}))
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
[apiUrl]
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
// Add workspace
|
|
274
|
-
const addWorkspace = useCallback(
|
|
275
|
-
async (path: string, name?: string): Promise<Workspace> => {
|
|
276
|
-
const response = await fetch(`${apiUrl}/workspaces`, {
|
|
277
|
-
method: 'POST',
|
|
278
|
-
headers: { 'Content-Type': 'application/json' },
|
|
279
|
-
body: JSON.stringify({ path, name }),
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
if (!response.ok) {
|
|
283
|
-
const error = await response.json();
|
|
284
|
-
throw new Error(error.error || 'Failed to add workspace');
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return response.json();
|
|
288
|
-
},
|
|
289
|
-
[apiUrl]
|
|
290
|
-
);
|
|
291
|
-
|
|
292
|
-
// Remove workspace
|
|
293
|
-
const removeWorkspace = useCallback(
|
|
294
|
-
async (workspaceId: string) => {
|
|
295
|
-
const response = await fetch(`${apiUrl}/workspaces/${workspaceId}`, {
|
|
296
|
-
method: 'DELETE',
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
if (!response.ok) {
|
|
300
|
-
throw new Error(`Failed to remove workspace: ${response.statusText}`);
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
[apiUrl]
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
// Spawn agent
|
|
307
|
-
const spawnAgent = useCallback(
|
|
308
|
-
async (name: string, task?: string, provider?: string): Promise<OrchestratorAgent> => {
|
|
309
|
-
if (!activeWorkspaceId) {
|
|
310
|
-
throw new Error('No active workspace');
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const response = await fetch(`${apiUrl}/workspaces/${activeWorkspaceId}/agents`, {
|
|
314
|
-
method: 'POST',
|
|
315
|
-
headers: { 'Content-Type': 'application/json' },
|
|
316
|
-
body: JSON.stringify({ name, task, provider }),
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
if (!response.ok) {
|
|
320
|
-
const error = await response.json();
|
|
321
|
-
throw new Error(error.error || 'Failed to spawn agent');
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
return response.json();
|
|
325
|
-
},
|
|
326
|
-
[apiUrl, activeWorkspaceId]
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
// Stop agent
|
|
330
|
-
const stopAgent = useCallback(
|
|
331
|
-
async (agentName: string) => {
|
|
332
|
-
if (!activeWorkspaceId) {
|
|
333
|
-
throw new Error('No active workspace');
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
const response = await fetch(
|
|
337
|
-
`${apiUrl}/workspaces/${activeWorkspaceId}/agents/${agentName}`,
|
|
338
|
-
{
|
|
339
|
-
method: 'DELETE',
|
|
340
|
-
}
|
|
341
|
-
);
|
|
342
|
-
|
|
343
|
-
if (!response.ok) {
|
|
344
|
-
throw new Error(`Failed to stop agent: ${response.statusText}`);
|
|
345
|
-
}
|
|
346
|
-
},
|
|
347
|
-
[apiUrl, activeWorkspaceId]
|
|
348
|
-
);
|
|
349
|
-
|
|
350
|
-
return {
|
|
351
|
-
workspaces,
|
|
352
|
-
activeWorkspaceId,
|
|
353
|
-
agents,
|
|
354
|
-
isConnected,
|
|
355
|
-
isLoading,
|
|
356
|
-
error,
|
|
357
|
-
switchWorkspace,
|
|
358
|
-
addWorkspace,
|
|
359
|
-
removeWorkspace,
|
|
360
|
-
spawnAgent,
|
|
361
|
-
stopAgent,
|
|
362
|
-
refresh: fetchData,
|
|
363
|
-
};
|
|
364
|
-
}
|