@agent-relay/dashboard-server 2.0.82 → 2.0.84
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/dist/index.d.ts +3 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -23
- package/dist/index.js.map +1 -1
- package/dist/lib/attachment-storage.d.ts +10 -0
- package/dist/lib/attachment-storage.d.ts.map +1 -0
- package/dist/lib/attachment-storage.js +53 -0
- package/dist/lib/attachment-storage.js.map +1 -0
- package/dist/lib/broadcast.d.ts +18 -0
- package/dist/lib/broadcast.d.ts.map +1 -0
- package/dist/lib/broadcast.js +118 -0
- package/dist/lib/broadcast.js.map +1 -0
- package/dist/lib/channel-state.d.ts +32 -0
- package/dist/lib/channel-state.d.ts.map +1 -0
- package/dist/lib/channel-state.js +146 -0
- package/dist/lib/channel-state.js.map +1 -0
- package/dist/lib/cli-auth.d.ts +40 -0
- package/dist/lib/cli-auth.d.ts.map +1 -0
- package/dist/lib/cli-auth.js +144 -0
- package/dist/lib/cli-auth.js.map +1 -0
- package/dist/lib/cloud-persistence.d.ts +6 -0
- package/dist/lib/cloud-persistence.d.ts.map +1 -0
- package/dist/lib/cloud-persistence.js +130 -0
- package/dist/lib/cloud-persistence.js.map +1 -0
- package/dist/lib/data-assembly.d.ts +136 -0
- package/dist/lib/data-assembly.d.ts.map +1 -0
- package/dist/lib/data-assembly.js +550 -0
- package/dist/lib/data-assembly.js.map +1 -0
- package/dist/lib/file-search.d.ts +8 -0
- package/dist/lib/file-search.d.ts.map +1 -0
- package/dist/lib/file-search.js +90 -0
- package/dist/lib/file-search.js.map +1 -0
- package/dist/lib/identity.d.ts +54 -0
- package/dist/lib/identity.d.ts.map +1 -0
- package/dist/lib/identity.js +124 -0
- package/dist/lib/identity.js.map +1 -0
- package/dist/lib/log-line-cleaner.d.ts +20 -0
- package/dist/lib/log-line-cleaner.d.ts.map +1 -0
- package/dist/lib/log-line-cleaner.js +117 -0
- package/dist/lib/log-line-cleaner.js.map +1 -0
- package/dist/lib/log-reader.d.ts +14 -0
- package/dist/lib/log-reader.d.ts.map +1 -0
- package/dist/lib/log-reader.js +80 -0
- package/dist/lib/log-reader.js.map +1 -0
- package/dist/lib/message-id.d.ts +30 -0
- package/dist/lib/message-id.d.ts.map +1 -0
- package/dist/lib/message-id.js +50 -0
- package/dist/lib/message-id.js.map +1 -0
- package/dist/lib/process-metrics.d.ts +11 -0
- package/dist/lib/process-metrics.d.ts.map +1 -0
- package/dist/lib/process-metrics.js +252 -0
- package/dist/lib/process-metrics.js.map +1 -0
- package/dist/lib/proxy-route-table.d.ts +16 -0
- package/dist/lib/proxy-route-table.d.ts.map +1 -0
- package/dist/lib/proxy-route-table.js +73 -0
- package/dist/lib/proxy-route-table.js.map +1 -0
- package/dist/lib/send-strategy.d.ts +61 -0
- package/dist/lib/send-strategy.d.ts.map +1 -0
- package/dist/lib/send-strategy.js +134 -0
- package/dist/lib/send-strategy.js.map +1 -0
- package/dist/lib/server-state.d.ts +115 -0
- package/dist/lib/server-state.d.ts.map +1 -0
- package/dist/lib/server-state.js +138 -0
- package/dist/lib/server-state.js.map +1 -0
- package/dist/lib/spawned-agents.d.ts +35 -0
- package/dist/lib/spawned-agents.d.ts.map +1 -0
- package/dist/lib/spawned-agents.js +323 -0
- package/dist/lib/spawned-agents.js.map +1 -0
- package/dist/lib/types.d.ts +117 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +12 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utils.d.ts +71 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +332 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/websocket-runtime.d.ts +17 -0
- package/dist/lib/websocket-runtime.d.ts.map +1 -0
- package/dist/lib/websocket-runtime.js +76 -0
- package/dist/lib/websocket-runtime.js.map +1 -0
- package/dist/mocks/fixtures.d.ts +2 -2
- package/dist/mocks/fixtures.js +1 -1
- package/dist/mocks/routes.d.ts.map +1 -1
- package/dist/mocks/routes.js +30 -3
- package/dist/mocks/routes.js.map +1 -1
- package/dist/mocks/types.d.ts +1 -1
- package/dist/mocks/types.js +1 -1
- package/dist/proxy-server.d.ts +7 -33
- package/dist/proxy-server.d.ts.map +1 -1
- package/dist/proxy-server.js +292 -200
- package/dist/proxy-server.js.map +1 -1
- package/dist/relaycast-provider-helpers.d.ts +40 -0
- package/dist/relaycast-provider-helpers.d.ts.map +1 -0
- package/dist/relaycast-provider-helpers.js +284 -0
- package/dist/relaycast-provider-helpers.js.map +1 -0
- package/dist/relaycast-provider-types.d.ts +116 -0
- package/dist/relaycast-provider-types.d.ts.map +1 -0
- package/dist/relaycast-provider-types.js +6 -0
- package/dist/relaycast-provider-types.js.map +1 -0
- package/dist/relaycast-provider.d.ts +42 -0
- package/dist/relaycast-provider.d.ts.map +1 -0
- package/dist/relaycast-provider.js +277 -0
- package/dist/relaycast-provider.js.map +1 -0
- package/dist/routes/agents.d.ts +7 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +180 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/auth.d.ts +45 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +261 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/broker-proxy.d.ts +7 -0
- package/dist/routes/broker-proxy.d.ts.map +1 -0
- package/dist/routes/broker-proxy.js +114 -0
- package/dist/routes/broker-proxy.js.map +1 -0
- package/dist/routes/channels-integrated.d.ts +84 -0
- package/dist/routes/channels-integrated.d.ts.map +1 -0
- package/dist/routes/channels-integrated.js +644 -0
- package/dist/routes/channels-integrated.js.map +1 -0
- package/dist/routes/channels.d.ts +7 -0
- package/dist/routes/channels.d.ts.map +1 -0
- package/dist/routes/channels.js +453 -0
- package/dist/routes/channels.js.map +1 -0
- package/dist/routes/data.d.ts +7 -0
- package/dist/routes/data.d.ts.map +1 -0
- package/dist/routes/data.js +108 -0
- package/dist/routes/data.js.map +1 -0
- package/dist/routes/decisions.d.ts +31 -0
- package/dist/routes/decisions.d.ts.map +1 -0
- package/dist/routes/decisions.js +109 -0
- package/dist/routes/decisions.js.map +1 -0
- package/dist/routes/fleet.d.ts +24 -0
- package/dist/routes/fleet.d.ts.map +1 -0
- package/dist/routes/fleet.js +131 -0
- package/dist/routes/fleet.js.map +1 -0
- package/dist/routes/health.d.ts +7 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +55 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/history-relaycast.d.ts +8 -0
- package/dist/routes/history-relaycast.d.ts.map +1 -0
- package/dist/routes/history-relaycast.js +165 -0
- package/dist/routes/history-relaycast.js.map +1 -0
- package/dist/routes/history.d.ts +13 -0
- package/dist/routes/history.d.ts.map +1 -0
- package/dist/routes/history.js +205 -0
- package/dist/routes/history.js.map +1 -0
- package/dist/routes/messaging.d.ts +31 -0
- package/dist/routes/messaging.d.ts.map +1 -0
- package/dist/routes/messaging.js +182 -0
- package/dist/routes/messaging.js.map +1 -0
- package/dist/routes/metrics.d.ts +26 -0
- package/dist/routes/metrics.d.ts.map +1 -0
- package/dist/routes/metrics.js +276 -0
- package/dist/routes/metrics.js.map +1 -0
- package/dist/routes/reactions.d.ts +9 -0
- package/dist/routes/reactions.d.ts.map +1 -0
- package/dist/routes/reactions.js +76 -0
- package/dist/routes/reactions.js.map +1 -0
- package/dist/routes/relay-config.d.ts +4 -0
- package/dist/routes/relay-config.d.ts.map +1 -0
- package/dist/routes/relay-config.js +50 -0
- package/dist/routes/relay-config.js.map +1 -0
- package/dist/routes/settings.d.ts +6 -0
- package/dist/routes/settings.d.ts.map +1 -0
- package/dist/routes/settings.js +119 -0
- package/dist/routes/settings.js.map +1 -0
- package/dist/routes/spawn.d.ts +74 -0
- package/dist/routes/spawn.d.ts.map +1 -0
- package/dist/routes/spawn.js +520 -0
- package/dist/routes/spawn.js.map +1 -0
- package/dist/routes/system.d.ts +21 -0
- package/dist/routes/system.d.ts.map +1 -0
- package/dist/routes/system.js +186 -0
- package/dist/routes/system.js.map +1 -0
- package/dist/routes/tasks.d.ts +27 -0
- package/dist/routes/tasks.d.ts.map +1 -0
- package/dist/routes/tasks.js +103 -0
- package/dist/routes/tasks.js.map +1 -0
- package/dist/routes/ui.d.ts +6 -0
- package/dist/routes/ui.d.ts.map +1 -0
- package/dist/routes/ui.js +114 -0
- package/dist/routes/ui.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +337 -6072
- package/dist/server.js.map +1 -1
- package/dist/services/broker-spawn-reader.d.ts +40 -0
- package/dist/services/broker-spawn-reader.d.ts.map +1 -0
- package/dist/services/broker-spawn-reader.js +155 -0
- package/dist/services/broker-spawn-reader.js.map +1 -0
- package/dist/services/health-worker-manager.d.ts +9 -60
- package/dist/services/health-worker-manager.d.ts.map +1 -1
- package/dist/services/health-worker-manager.js +18 -148
- package/dist/services/health-worker-manager.js.map +1 -1
- package/dist/services/index.d.ts +3 -3
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +3 -3
- package/dist/services/index.js.map +1 -1
- package/dist/services/metrics.d.ts +11 -104
- package/dist/services/metrics.d.ts.map +1 -1
- package/dist/services/metrics.js +21 -190
- package/dist/services/metrics.js.map +1 -1
- package/dist/services/needs-attention.d.ts +21 -22
- package/dist/services/needs-attention.d.ts.map +1 -1
- package/dist/services/needs-attention.js +46 -71
- package/dist/services/needs-attention.js.map +1 -1
- package/dist/services/user-bridge.d.ts +0 -3
- package/dist/services/user-bridge.d.ts.map +1 -1
- package/dist/services/user-bridge.js +0 -5
- package/dist/services/user-bridge.js.map +1 -1
- package/dist/start.d.ts +4 -4
- package/dist/start.js +96 -89
- package/dist/start.js.map +1 -1
- package/dist/types/index.d.ts +13 -16
- package/dist/types/index.d.ts.map +1 -1
- package/dist/websocket/bridge.d.ts +12 -0
- package/dist/websocket/bridge.d.ts.map +1 -0
- package/dist/websocket/bridge.js +33 -0
- package/dist/websocket/bridge.js.map +1 -0
- package/dist/websocket/logs.d.ts +30 -0
- package/dist/websocket/logs.d.ts.map +1 -0
- package/dist/websocket/logs.js +577 -0
- package/dist/websocket/logs.js.map +1 -0
- package/dist/websocket/main.d.ts +15 -0
- package/dist/websocket/main.d.ts.map +1 -0
- package/dist/websocket/main.js +84 -0
- package/dist/websocket/main.js.map +1 -0
- package/dist/websocket/mock.d.ts +6 -0
- package/dist/websocket/mock.d.ts.map +1 -0
- package/dist/websocket/mock.js +49 -0
- package/dist/websocket/mock.js.map +1 -0
- package/dist/websocket/presence.d.ts +74 -0
- package/dist/websocket/presence.d.ts.map +1 -0
- package/dist/websocket/presence.js +330 -0
- package/dist/websocket/presence.js.map +1 -0
- package/dist/websocket/proxy.d.ts +6 -0
- package/dist/websocket/proxy.d.ts.map +1 -0
- package/dist/websocket/proxy.js +39 -0
- package/dist/websocket/proxy.js.map +1 -0
- package/dist/websocket/standalone.d.ts +17 -0
- package/dist/websocket/standalone.d.ts.map +1 -0
- package/dist/websocket/standalone.js +268 -0
- package/dist/websocket/standalone.js.map +1 -0
- package/out/404.html +1 -1
- package/out/_next/static/chunks/1028-da5d75e35d1420f1.js +1 -0
- package/out/_next/static/chunks/1528-78b17000a7e10bc6.js +2 -0
- package/out/_next/static/chunks/1695-4a5d33ba715e09b4.js +1 -0
- package/out/_next/static/chunks/1705-36c2180d00a4a569.js +1 -0
- package/out/_next/static/chunks/1dd3208c-e1f87c7b3dc1a820.js +1 -0
- package/out/_next/static/chunks/3663-47290254b8f6f5dd.js +1 -0
- package/out/_next/static/chunks/3677-4b225baf4801d9b9.js +73 -0
- package/out/_next/static/chunks/5118-7e8ada2df38eef07.js +1 -0
- package/out/_next/static/chunks/5888-15cbe97c90ed5fae.js +1 -0
- package/out/_next/static/chunks/6773-a45343a98df3abb5.js +1 -0
- package/out/_next/static/chunks/6940-b824612b605e79b3.js +9 -0
- package/out/_next/static/chunks/7894-f4a15249082a680d.js +1 -0
- package/out/_next/static/chunks/9175-b3617c1e5cbfed0e.js +1 -0
- package/out/_next/static/chunks/9372-1a804b8d08c7a236.js +1 -0
- package/out/_next/static/chunks/{ab6c8a12-0a58072fbb505134.js → ab6c8a12-91438a812d94ecf0.js} +1 -1
- package/out/_next/static/chunks/app/_not-found/page-8e8842f82d204726.js +1 -0
- package/out/_next/static/chunks/app/about/page-b78577a7da8fa459.js +1 -0
- package/out/_next/static/chunks/app/app/[[...slug]]/page-3dffd65b6344f53e.js +1 -0
- package/out/_next/static/chunks/app/app/onboarding/page-b89be9aa6264a5e1.js +1 -0
- package/out/_next/static/chunks/app/blog/go-to-bed-wake-up-to-a-finished-product/page-fbd00893ef69e499.js +1 -0
- package/out/_next/static/chunks/app/blog/let-them-cook-multi-agent-orchestration/page-de2ea13649d0b6d3.js +1 -0
- package/out/_next/static/chunks/app/blog/page-a08e263c57a156fa.js +1 -0
- package/out/_next/static/chunks/app/careers/page-02228e1d6969b232.js +1 -0
- package/out/_next/static/chunks/app/changelog/page-1b5c1d79efc6e53a.js +1 -0
- package/out/_next/static/chunks/app/cloud/link/page-99654edffffb3af2.js +1 -0
- package/out/_next/static/chunks/app/complete-profile/page-59d146e5ddeafc5c.js +1 -0
- package/out/_next/static/chunks/app/connect-repos/page-995e16a976a6632c.js +1 -0
- package/out/_next/static/chunks/app/contact/page-273396a5ad57bcee.js +1 -0
- package/out/_next/static/chunks/app/dev/cli-tools/page-a71b80dcb2d5fc8d.js +1 -0
- package/out/_next/static/chunks/app/dev/log-viewer/page-46a6151ae1be0796.js +1 -0
- package/out/_next/static/chunks/app/docs/page-7c7cb603b24b7c40.js +1 -0
- package/out/_next/static/chunks/app/history/page-0c5cab1dab4e8886.js +1 -0
- package/out/_next/static/chunks/app/layout-96d72ba8ef8a43a0.js +1 -0
- package/out/_next/static/chunks/app/login/page-0ccbab34213df842.js +1 -0
- package/out/_next/static/chunks/app/metrics/page-8616272aeab9c8b0.js +1 -0
- package/out/_next/static/chunks/app/page-09ce10603ad9a251.js +1 -0
- package/out/_next/static/chunks/app/pricing/page-91c975079120c941.js +1 -0
- package/out/_next/static/chunks/app/privacy/{page-c21d51ac2dee3a88.js → page-a49ab271cc686644.js} +1 -1
- package/out/_next/static/chunks/app/providers/{page-59114505f4353512.js → page-d775d6eb5bc29e96.js} +1 -1
- package/out/_next/static/chunks/app/providers/setup/[provider]/page-ec4ef3cd80de807e.js +1 -0
- package/out/_next/static/chunks/app/security/page-d9da9bd9191e8f95.js +1 -0
- package/out/_next/static/chunks/app/signup/page-930eca0bf5fd299d.js +1 -0
- package/out/_next/static/chunks/app/terms/page-3e4827620b98613c.js +1 -0
- package/out/_next/static/chunks/framework-648e1ae7da590300.js +1 -0
- package/out/_next/static/chunks/{main-acb1b24265295d6a.js → main-2b1990080c292d92.js} +1 -1
- package/out/_next/static/chunks/main-app-9f6b7ff9e754a8f5.js +1 -0
- package/out/_next/static/chunks/pages/_app-a077b72e02273ab1.js +1 -0
- package/out/_next/static/chunks/pages/_error-84001666436a04e4.js +1 -0
- package/out/_next/static/chunks/{webpack-dd93b81e2659669c.js → webpack-7586035f1585f2db.js} +1 -1
- package/out/_next/static/css/eb9fc69d1e3d2bed.css +1 -0
- package/out/_next/static/{IxfA6RZu4trcsEMYlkQra → g3G0LMdB7lxcrU5mdM54m}/_buildManifest.js +1 -1
- package/out/about.html +2 -2
- package/out/about.txt +2 -2
- package/out/app/onboarding.html +1 -1
- package/out/app/onboarding.txt +2 -2
- package/out/app.html +1 -1
- package/out/app.txt +2 -2
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.html +3 -3
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.txt +1 -1
- package/out/blog/let-them-cook-multi-agent-orchestration.html +2 -2
- package/out/blog/let-them-cook-multi-agent-orchestration.txt +2 -2
- package/out/blog.html +2 -2
- package/out/blog.txt +1 -1
- package/out/careers.html +2 -2
- package/out/careers.txt +2 -2
- package/out/changelog.html +2 -2
- package/out/changelog.txt +2 -2
- package/out/cloud/link.html +1 -1
- package/out/cloud/link.txt +2 -2
- package/out/complete-profile.html +2 -2
- package/out/complete-profile.txt +2 -2
- package/out/connect-repos.html +1 -1
- package/out/connect-repos.txt +2 -2
- package/out/contact.html +2 -2
- package/out/contact.txt +2 -2
- package/out/dev/cli-tools.html +1 -0
- package/out/dev/cli-tools.txt +7 -0
- package/out/dev/log-viewer.html +23 -0
- package/out/dev/log-viewer.txt +7 -0
- package/out/docs.html +2 -2
- package/out/docs.txt +2 -2
- package/out/history.html +1 -1
- package/out/history.txt +2 -2
- package/out/index.html +1 -1
- package/out/index.txt +2 -2
- package/out/login.html +2 -2
- package/out/login.txt +2 -2
- package/out/metrics.html +1 -1
- package/out/metrics.txt +2 -2
- package/out/pricing.html +2 -2
- package/out/pricing.txt +2 -2
- package/out/privacy.html +2 -2
- package/out/privacy.txt +2 -2
- package/out/providers/setup/claude.html +1 -1
- package/out/providers/setup/claude.txt +2 -2
- package/out/providers/setup/codex.html +1 -1
- package/out/providers/setup/codex.txt +2 -2
- package/out/providers/setup/cursor.html +1 -1
- package/out/providers/setup/cursor.txt +2 -2
- package/out/providers.html +1 -1
- package/out/providers.txt +2 -2
- package/out/security.html +2 -2
- package/out/security.txt +2 -2
- package/out/signup.html +2 -2
- package/out/signup.txt +2 -2
- package/out/terms.html +2 -2
- package/out/terms.txt +2 -2
- package/package.json +10 -11
- package/out/_next/static/chunks/11-9a2993a37266dcb3.js +0 -9
- package/out/_next/static/chunks/118-ae2b650136a5a5fc.js +0 -1
- package/out/_next/static/chunks/1dd3208c-40ab0fc0f60392b8.js +0 -1
- package/out/_next/static/chunks/202-fc0763dd7488e58f.js +0 -1
- package/out/_next/static/chunks/259-83b77fa1b91ba5aa.js +0 -1
- package/out/_next/static/chunks/407-0c82986cf79c8ecb.js +0 -1
- package/out/_next/static/chunks/528-f5f676996d613c25.js +0 -2
- package/out/_next/static/chunks/663-ddb04081febc3678.js +0 -1
- package/out/_next/static/chunks/687-88b6b139a6bb0e2e.js +0 -1
- package/out/_next/static/chunks/695-51d25b1988644374.js +0 -1
- package/out/_next/static/chunks/773-54a2641043c81e55.js +0 -1
- package/out/_next/static/chunks/app/_not-found/page-6da9b72091e5b511.js +0 -1
- package/out/_next/static/chunks/app/about/page-fff7c6457683f243.js +0 -1
- package/out/_next/static/chunks/app/app/[[...slug]]/page-f7eca1b66fb4249b.js +0 -1
- package/out/_next/static/chunks/app/app/onboarding/page-129abc5da2e67971.js +0 -1
- package/out/_next/static/chunks/app/blog/go-to-bed-wake-up-to-a-finished-product/page-5d5f28fd126b692f.js +0 -1
- package/out/_next/static/chunks/app/blog/let-them-cook-multi-agent-orchestration/page-b194f207fbd91862.js +0 -1
- package/out/_next/static/chunks/app/blog/page-b9bd9d8703fca76a.js +0 -1
- package/out/_next/static/chunks/app/careers/page-a4bd8d5f4de8f4eb.js +0 -1
- package/out/_next/static/chunks/app/changelog/page-9a1f6ad1743d63c5.js +0 -1
- package/out/_next/static/chunks/app/cloud/link/page-0844c5699b027c3b.js +0 -1
- package/out/_next/static/chunks/app/complete-profile/page-39ed5a67916beb87.js +0 -1
- package/out/_next/static/chunks/app/connect-repos/page-297eddee0c39f2a3.js +0 -1
- package/out/_next/static/chunks/app/contact/page-3c1dd8690217fade.js +0 -1
- package/out/_next/static/chunks/app/docs/page-1875e981f2c3fd13.js +0 -1
- package/out/_next/static/chunks/app/history/page-2d5c5695c9e8b40c.js +0 -1
- package/out/_next/static/chunks/app/layout-0a4b99656da25511.js +0 -1
- package/out/_next/static/chunks/app/login/page-f69c076f5a6fc520.js +0 -1
- package/out/_next/static/chunks/app/metrics/page-bebbee055669a17e.js +0 -1
- package/out/_next/static/chunks/app/page-0ee604f7070d14c0.js +0 -1
- package/out/_next/static/chunks/app/pricing/page-eeae7d594af333b6.js +0 -1
- package/out/_next/static/chunks/app/providers/setup/[provider]/page-daf9b3e05e77ae19.js +0 -1
- package/out/_next/static/chunks/app/security/page-cd562730fe84a0a2.js +0 -1
- package/out/_next/static/chunks/app/signup/page-c242ca08101a84ff.js +0 -1
- package/out/_next/static/chunks/app/terms/page-c7001720e7941dc6.js +0 -1
- package/out/_next/static/chunks/framework-3664cab31236a9fa.js +0 -1
- package/out/_next/static/chunks/main-app-7f73a939a312a228.js +0 -1
- package/out/_next/static/chunks/pages/_app-10a93ab5b7c32eb3.js +0 -1
- package/out/_next/static/chunks/pages/_error-2d792b2a41857be4.js +0 -1
- package/out/_next/static/css/8968d98ed4c4d33f.css +0 -1
- /package/out/_next/static/{IxfA6RZu4trcsEMYlkQra → g3G0LMdB7lxcrU5mdM54m}/_ssgManifest.js +0 -0
package/dist/proxy-server.js
CHANGED
|
@@ -1,63 +1,108 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Relay Dashboard Server
|
|
3
3
|
*
|
|
4
|
-
* A flexible server that can operate in
|
|
5
|
-
* 1. Proxy mode (default):
|
|
6
|
-
* 2.
|
|
7
|
-
*
|
|
8
|
-
* This allows the dashboard to run independently without any external dependencies.
|
|
4
|
+
* A flexible server that can operate in three modes:
|
|
5
|
+
* 1. Proxy mode (default): static files + Relaycast data + broker proxy
|
|
6
|
+
* 2. Standalone mode: static files + Relaycast data (no broker proxy)
|
|
7
|
+
* 3. Mock mode: fixture-backed standalone mode for demos/tests
|
|
9
8
|
*/
|
|
10
9
|
import express from 'express';
|
|
11
10
|
import { createServer as createHttpServer } from 'http';
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
11
|
+
import { WebSocketServer } from 'ws';
|
|
12
|
+
import fs from 'fs';
|
|
14
13
|
import path from 'path';
|
|
15
14
|
import { fileURLToPath } from 'url';
|
|
16
15
|
import { registerMockRoutes } from './mocks/routes.js';
|
|
17
|
-
import {
|
|
16
|
+
import { fetchAgents, fetchChannels, loadRelaycastConfig, } from './relaycast-provider.js';
|
|
17
|
+
import { createSendStrategy } from './lib/send-strategy.js';
|
|
18
|
+
import { DASHBOARD_DISPLAY_NAME } from './relaycast-provider-types.js';
|
|
19
|
+
import { resolveIdentity } from './lib/identity.js';
|
|
20
|
+
import { EMPTY_DASHBOARD_SNAPSHOT } from './lib/types.js';
|
|
21
|
+
import { normalizeRelayUrl, normalizeName, isDirectRecipient, sendHtmlFileOrFallback, getBindHost, mapChannelForDashboard, } from './lib/utils.js';
|
|
22
|
+
import { filterPhantomAgents, mergeBrokerSpawnedAgents, createSpawnedAgentsCaches, } from './lib/spawned-agents.js';
|
|
23
|
+
import { handleMockWebSocket } from './websocket/mock.js';
|
|
24
|
+
import { handleStandaloneWebSocket, handleHybridWebSocket } from './websocket/standalone.js';
|
|
25
|
+
import { handleStandaloneLogWebSocket } from './websocket/logs.js';
|
|
26
|
+
import { registerHealthRoutes } from './routes/health.js';
|
|
27
|
+
import { registerDataRoutes } from './routes/data.js';
|
|
28
|
+
import { registerAgentRoutes } from './routes/agents.js';
|
|
29
|
+
import { registerChannelRoutes } from './routes/channels.js';
|
|
30
|
+
import { registerBrokerProxyRoutes } from './routes/broker-proxy.js';
|
|
31
|
+
import { registerMetricsRoutes } from './routes/metrics.js';
|
|
32
|
+
import { registerReactionRoutes } from './routes/reactions.js';
|
|
33
|
+
import { registerRelayConfigRoutes } from './routes/relay-config.js';
|
|
34
|
+
import { registerRelaycastHistoryRoutes } from './routes/history-relaycast.js';
|
|
18
35
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
36
|
const __dirname = path.dirname(__filename);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
function resolveMetricsPagePath(staticDir) {
|
|
38
|
+
const candidates = [
|
|
39
|
+
path.join(staticDir, 'metrics.html'),
|
|
40
|
+
path.join(staticDir, 'metrics', 'index.html'),
|
|
41
|
+
path.join(staticDir, 'app.html'),
|
|
42
|
+
path.join(staticDir, 'index.html'),
|
|
43
|
+
];
|
|
44
|
+
for (const candidate of candidates) {
|
|
45
|
+
if (fs.existsSync(candidate)) {
|
|
46
|
+
return candidate;
|
|
47
|
+
}
|
|
30
48
|
}
|
|
31
|
-
|
|
32
|
-
// Fly.io internal network uses IPv6 (fdaa:...), so 0.0.0.0 won't work
|
|
33
|
-
const isCloudEnvironment = process.env.FLY_APP_NAME || // Fly.io
|
|
34
|
-
process.env.WORKSPACE_ID || // Agent Relay workspace
|
|
35
|
-
process.env.RELAY_WORKSPACE_ID || // Alternative workspace ID
|
|
36
|
-
process.env.RUNNING_IN_DOCKER === 'true'; // Docker container
|
|
37
|
-
return isCloudEnvironment ? '::' : undefined;
|
|
49
|
+
return candidates[0];
|
|
38
50
|
}
|
|
51
|
+
const asString = (value) => {
|
|
52
|
+
if (typeof value === 'string' && value.length > 0)
|
|
53
|
+
return value;
|
|
54
|
+
if (Array.isArray(value)) {
|
|
55
|
+
for (const item of value) {
|
|
56
|
+
if (typeof item === 'string' && item.length > 0)
|
|
57
|
+
return item;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
};
|
|
62
|
+
const getWorkspaceHeader = (headers) => {
|
|
63
|
+
if (!headers)
|
|
64
|
+
return undefined;
|
|
65
|
+
const direct = headers['x-workspace-id'];
|
|
66
|
+
if (typeof direct === 'string' && direct.length > 0)
|
|
67
|
+
return direct;
|
|
68
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
69
|
+
if (key.toLowerCase() === 'x-workspace-id' && typeof value === 'string' && value.length > 0) {
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
};
|
|
39
75
|
/**
|
|
40
76
|
* Create the dashboard server without starting it
|
|
41
77
|
*/
|
|
42
78
|
export function createServer(options = {}) {
|
|
43
|
-
const {
|
|
79
|
+
const { relayUrl: relayUrlOption, staticDir = process.env.STATIC_DIR || path.join(__dirname, '..', 'out'), dataDir = process.env.DATA_DIR || path.join(process.cwd(), '.agent-relay'), verbose = process.env.VERBOSE === 'true', mock = process.env.MOCK === 'true', corsOrigins = process.env.CORS_ORIGINS || '', requestTimeout = parseInt(process.env.REQUEST_TIMEOUT || '60000', 10), } = options;
|
|
80
|
+
const resolvedDataDir = path.resolve(dataDir);
|
|
81
|
+
if (!process.env.AGENT_RELAY_PROJECT) {
|
|
82
|
+
process.env.AGENT_RELAY_PROJECT = path.dirname(resolvedDataDir);
|
|
83
|
+
}
|
|
84
|
+
const relayUrl = normalizeRelayUrl(relayUrlOption ?? process.env.RELAY_URL);
|
|
85
|
+
const mode = mock ? 'mock' : (relayUrl ? 'proxy' : 'standalone');
|
|
86
|
+
const brokerProxyEnabled = mode === 'proxy' && Boolean(relayUrl);
|
|
87
|
+
const defaultWorkspaceId = process.env.RELAY_WORKSPACE_ID ?? process.env.AGENT_RELAY_WORKSPACE_ID;
|
|
88
|
+
const resolveWorkspaceId = (req) => {
|
|
89
|
+
const fromQuery = asString(req.query?.workspaceId);
|
|
90
|
+
const fromBody = asString(req.body?.workspaceId);
|
|
91
|
+
const fromHeader = getWorkspaceHeader(req.headers);
|
|
92
|
+
return fromQuery || fromBody || fromHeader || defaultWorkspaceId;
|
|
93
|
+
};
|
|
44
94
|
const app = express();
|
|
45
95
|
const server = createHttpServer(app);
|
|
46
|
-
const mode = mock ? 'mock' : 'proxy';
|
|
47
|
-
// Set request timeout
|
|
48
96
|
server.timeout = requestTimeout;
|
|
49
|
-
// Parse JSON bodies
|
|
50
97
|
app.use(express.json({ limit: '10mb' }));
|
|
51
|
-
// CORS middleware - configurable for cross-origin deployments
|
|
52
98
|
if (corsOrigins) {
|
|
53
99
|
app.use((req, res, next) => {
|
|
54
100
|
const origin = req.headers.origin;
|
|
55
|
-
// Check if origin is allowed
|
|
56
101
|
if (corsOrigins === '*') {
|
|
57
102
|
res.header('Access-Control-Allow-Origin', '*');
|
|
58
103
|
}
|
|
59
104
|
else if (origin) {
|
|
60
|
-
const allowedOrigins = corsOrigins.split(',').map(
|
|
105
|
+
const allowedOrigins = corsOrigins.split(',').map((value) => value.trim());
|
|
61
106
|
if (allowedOrigins.includes(origin)) {
|
|
62
107
|
res.header('Access-Control-Allow-Origin', origin);
|
|
63
108
|
}
|
|
@@ -66,7 +111,6 @@ export function createServer(options = {}) {
|
|
|
66
111
|
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-CSRF-Token');
|
|
67
112
|
res.header('Access-Control-Allow-Credentials', 'true');
|
|
68
113
|
res.header('Access-Control-Expose-Headers', 'X-CSRF-Token');
|
|
69
|
-
// Handle preflight requests
|
|
70
114
|
if (req.method === 'OPTIONS') {
|
|
71
115
|
res.sendStatus(204);
|
|
72
116
|
return;
|
|
@@ -74,99 +118,250 @@ export function createServer(options = {}) {
|
|
|
74
118
|
next();
|
|
75
119
|
});
|
|
76
120
|
}
|
|
77
|
-
// Logging middleware
|
|
78
121
|
if (verbose) {
|
|
79
122
|
app.use((req, _res, next) => {
|
|
80
123
|
console.log(`[dashboard] ${req.method} ${req.url}`);
|
|
81
124
|
next();
|
|
82
125
|
});
|
|
83
126
|
}
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
// Keep-alive endpoint
|
|
94
|
-
app.get('/keep-alive', (_req, res) => {
|
|
95
|
-
res.json({ ok: true });
|
|
127
|
+
// --- Build shared context ---
|
|
128
|
+
const resolveRelaycastConfig = () => loadRelaycastConfig(dataDir);
|
|
129
|
+
const { getSpawnedAgents, getLocalAgentNames } = createSpawnedAgentsCaches({
|
|
130
|
+
brokerProxyEnabled,
|
|
131
|
+
relayUrl,
|
|
132
|
+
dataDir,
|
|
133
|
+
verbose,
|
|
96
134
|
});
|
|
135
|
+
const getRelaycastSnapshot = async () => {
|
|
136
|
+
const config = resolveRelaycastConfig();
|
|
137
|
+
if (!config) {
|
|
138
|
+
return { ...EMPTY_DASHBOARD_SNAPSHOT };
|
|
139
|
+
}
|
|
140
|
+
const [agents, spawnedAgents, localAgentNames] = await Promise.all([
|
|
141
|
+
fetchAgents(config),
|
|
142
|
+
brokerProxyEnabled ? getSpawnedAgents() : Promise.resolve({ names: null, agents: null }),
|
|
143
|
+
brokerProxyEnabled ? Promise.resolve(null) : Promise.resolve(getLocalAgentNames()),
|
|
144
|
+
]);
|
|
145
|
+
const filteredAgents = filterPhantomAgents(agents, spawnedAgents.names, localAgentNames);
|
|
146
|
+
const mergedAgents = mergeBrokerSpawnedAgents(filteredAgents, spawnedAgents.agents);
|
|
147
|
+
return {
|
|
148
|
+
agents: mergedAgents,
|
|
149
|
+
users: [],
|
|
150
|
+
messages: [],
|
|
151
|
+
activity: [],
|
|
152
|
+
sessions: [],
|
|
153
|
+
summaries: [],
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
const getRelaycastChannels = async () => {
|
|
157
|
+
const config = resolveRelaycastConfig();
|
|
158
|
+
if (!config) {
|
|
159
|
+
return { channels: [], archivedChannels: [] };
|
|
160
|
+
}
|
|
161
|
+
const channels = await fetchChannels(config);
|
|
162
|
+
const activeChannels = [];
|
|
163
|
+
const archivedChannels = [];
|
|
164
|
+
for (const channel of channels) {
|
|
165
|
+
const mapped = mapChannelForDashboard({ ...channel, is_archived: channel.is_archived ?? false });
|
|
166
|
+
if (mapped.status === 'archived') {
|
|
167
|
+
archivedChannels.push(mapped);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
activeChannels.push(mapped);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
activeChannels.sort((a, b) => a.name.localeCompare(b.name));
|
|
174
|
+
archivedChannels.sort((a, b) => a.name.localeCompare(b.name));
|
|
175
|
+
return { channels: activeChannels, archivedChannels };
|
|
176
|
+
};
|
|
177
|
+
const sendRelaycastMessage = async (params) => {
|
|
178
|
+
const sendTimeout = Math.max(requestTimeout - 5000, 10000);
|
|
179
|
+
const sendStart = Date.now();
|
|
180
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Send timed out')), sendTimeout));
|
|
181
|
+
try {
|
|
182
|
+
return await Promise.race([
|
|
183
|
+
(async () => {
|
|
184
|
+
const config = resolveRelaycastConfig();
|
|
185
|
+
const rawTarget = params.to.trim();
|
|
186
|
+
const message = params.message.trim();
|
|
187
|
+
let resolvedTarget = rawTarget;
|
|
188
|
+
if (isDirectRecipient(rawTarget) && config) {
|
|
189
|
+
const relayAgents = await fetchAgents(config);
|
|
190
|
+
const relayMatch = relayAgents.find((agent) => normalizeName(agent.name) === normalizeName(rawTarget));
|
|
191
|
+
if (relayMatch) {
|
|
192
|
+
resolvedTarget = relayMatch.name;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const projectIdentity = config?.agentName?.trim()
|
|
196
|
+
|| path.basename(path.resolve(dataDir, '..'))
|
|
197
|
+
|| DASHBOARD_DISPLAY_NAME;
|
|
198
|
+
const senderInput = params.from?.trim() ?? '';
|
|
199
|
+
const senderName = mode === 'proxy'
|
|
200
|
+
? resolveIdentity(senderInput || projectIdentity, {
|
|
201
|
+
projectIdentity: projectIdentity.trim(),
|
|
202
|
+
relayAgentName: config?.agentName?.trim(),
|
|
203
|
+
})
|
|
204
|
+
: (senderInput || projectIdentity);
|
|
205
|
+
const strategy = createSendStrategy({
|
|
206
|
+
brokerProxyEnabled,
|
|
207
|
+
brokerUrl: relayUrl,
|
|
208
|
+
relaycastConfig: config,
|
|
209
|
+
dataDir,
|
|
210
|
+
});
|
|
211
|
+
if (!strategy) {
|
|
212
|
+
return {
|
|
213
|
+
success: false,
|
|
214
|
+
status: 503,
|
|
215
|
+
error: `Relaycast credentials not found in ${path.join(dataDir, 'relaycast.json')}`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
console.log(`[dashboard] /api/send request: to=${resolvedTarget}, from=${senderName}, relayUrl=${relayUrl}, timeoutMs=${sendTimeout}`);
|
|
219
|
+
const outcome = await strategy.send({ to: resolvedTarget, message, from: senderName });
|
|
220
|
+
console.log(`[dashboard] /api/send completed in ${Date.now() - sendStart}ms with status=${outcome.success ? 200 : outcome.status}`);
|
|
221
|
+
// Enrich "agent not found" errors with available agent names
|
|
222
|
+
if (!outcome.success && isDirectRecipient(params.to) && config) {
|
|
223
|
+
if (/agent\s+\".+\"\s+not\s+found/i.test(outcome.error)) {
|
|
224
|
+
const relayAgents = await fetchAgents(config);
|
|
225
|
+
const available = relayAgents.map((agent) => agent.name).sort();
|
|
226
|
+
const suffix = available.length > 0
|
|
227
|
+
? ` Available relay agents: ${available.join(', ')}.`
|
|
228
|
+
: ' No relay agents are currently online.';
|
|
229
|
+
return {
|
|
230
|
+
success: false,
|
|
231
|
+
status: 404,
|
|
232
|
+
error: `${outcome.error}.${suffix}`,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return outcome;
|
|
237
|
+
})(),
|
|
238
|
+
timeoutPromise,
|
|
239
|
+
]);
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
console.error(`[dashboard] /api/send failed after ${Date.now() - sendStart}ms: ${err.message}`);
|
|
243
|
+
return {
|
|
244
|
+
success: false,
|
|
245
|
+
status: 504,
|
|
246
|
+
error: err.message || 'Send request timed out',
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const ctx = {
|
|
251
|
+
mode,
|
|
252
|
+
dataDir,
|
|
253
|
+
staticDir,
|
|
254
|
+
verbose,
|
|
255
|
+
relayUrl,
|
|
256
|
+
brokerProxyEnabled,
|
|
257
|
+
resolveRelaycastConfig,
|
|
258
|
+
getRelaycastSnapshot,
|
|
259
|
+
getRelaycastChannels,
|
|
260
|
+
sendRelaycastMessage,
|
|
261
|
+
getSpawnedAgents,
|
|
262
|
+
getLocalAgentNames,
|
|
263
|
+
filterPhantomAgents,
|
|
264
|
+
};
|
|
265
|
+
// --- Register routes ---
|
|
266
|
+
registerHealthRoutes(app, ctx);
|
|
97
267
|
if (mock) {
|
|
98
|
-
|
|
99
|
-
// Register mock API routes for standalone operation
|
|
100
|
-
console.log('[dashboard] Running in MOCK mode - no relay daemon required');
|
|
268
|
+
console.log('[dashboard] Running in MOCK mode - no relay broker required');
|
|
101
269
|
registerMockRoutes(app, verbose);
|
|
102
270
|
}
|
|
103
271
|
else {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
app.use('/api', createProxyMiddleware(apiProxyOptions));
|
|
126
|
-
app.use('/auth', createProxyMiddleware(apiProxyOptions));
|
|
127
|
-
app.use('/metrics', createProxyMiddleware(apiProxyOptions));
|
|
272
|
+
if (mode === 'proxy' && relayUrl) {
|
|
273
|
+
console.log(`[dashboard] Running in PROXY mode - relaycast + broker proxy (${relayUrl})`);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
console.log('[dashboard] Running in STANDALONE mode - relaycast only (read-only broker surface)');
|
|
277
|
+
}
|
|
278
|
+
registerAgentRoutes(app, ctx);
|
|
279
|
+
registerDataRoutes(app, ctx);
|
|
280
|
+
registerRelayConfigRoutes(app, ctx);
|
|
281
|
+
registerChannelRoutes(app, ctx);
|
|
282
|
+
registerReactionRoutes(app, ctx);
|
|
283
|
+
registerMetricsRoutes(app, {
|
|
284
|
+
teamDir: path.join(dataDir, 'team'),
|
|
285
|
+
resolveWorkspaceId,
|
|
286
|
+
});
|
|
287
|
+
registerRelaycastHistoryRoutes(app, ctx);
|
|
288
|
+
registerBrokerProxyRoutes(app, ctx);
|
|
128
289
|
}
|
|
129
|
-
//
|
|
290
|
+
// --- Static files and SPA fallback ---
|
|
291
|
+
const fallbackHtml = `<!doctype html>
|
|
292
|
+
<html lang="en">
|
|
293
|
+
<head>
|
|
294
|
+
<meta charset="utf-8" />
|
|
295
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
296
|
+
<title>Relay Dashboard</title>
|
|
297
|
+
</head>
|
|
298
|
+
<body>
|
|
299
|
+
<h1>Relay Dashboard</h1>
|
|
300
|
+
<p>Dashboard static build not found.</p>
|
|
301
|
+
</body>
|
|
302
|
+
</html>`;
|
|
303
|
+
app.get('/metrics', (_req, res) => {
|
|
304
|
+
const metricsPath = resolveMetricsPagePath(staticDir);
|
|
305
|
+
sendHtmlFileOrFallback(res, metricsPath, fallbackHtml, 200);
|
|
306
|
+
});
|
|
307
|
+
app.get('/app', (_req, res) => {
|
|
308
|
+
const appHtmlPath = path.join(staticDir, 'app.html');
|
|
309
|
+
sendHtmlFileOrFallback(res, appHtmlPath, fallbackHtml, 200);
|
|
310
|
+
});
|
|
311
|
+
app.get('/app/{*path}', (_req, res) => {
|
|
312
|
+
const appHtmlPath = path.join(staticDir, 'app.html');
|
|
313
|
+
sendHtmlFileOrFallback(res, appHtmlPath, fallbackHtml, 200);
|
|
314
|
+
});
|
|
130
315
|
app.use(express.static(staticDir, {
|
|
131
316
|
extensions: ['html'],
|
|
132
317
|
}));
|
|
133
|
-
|
|
134
|
-
|
|
318
|
+
app.get('/', (_req, res) => {
|
|
319
|
+
const indexPath = path.join(staticDir, 'index.html');
|
|
320
|
+
sendHtmlFileOrFallback(res, indexPath, fallbackHtml, 200);
|
|
321
|
+
});
|
|
135
322
|
app.get('/{*path}', (req, res) => {
|
|
136
|
-
//
|
|
323
|
+
// WebSocket endpoints require upgrade - return 426 for regular HTTP requests
|
|
324
|
+
if (req.path === '/ws' || req.path.startsWith('/ws/')) {
|
|
325
|
+
res.status(426).json({ error: 'Upgrade Required', message: 'WebSocket upgrade required' });
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
137
328
|
if (req.path.startsWith('/api') || req.path.startsWith('/auth') || req.path.includes('.')) {
|
|
138
329
|
res.status(404).json({ error: 'Not found' });
|
|
139
330
|
return;
|
|
140
331
|
}
|
|
141
|
-
// For /app/* routes (including /app/channel/*, /app/agent/*, /app/dm/*, /app/settings/*),
|
|
142
|
-
// serve the app.html which handles client-side routing
|
|
143
332
|
if (req.path.startsWith('/app')) {
|
|
144
|
-
|
|
333
|
+
const appHtmlPath = path.join(staticDir, 'app.html');
|
|
334
|
+
sendHtmlFileOrFallback(res, appHtmlPath, fallbackHtml, 200);
|
|
145
335
|
return;
|
|
146
336
|
}
|
|
147
|
-
|
|
148
|
-
res
|
|
337
|
+
const indexPath = path.join(staticDir, 'index.html');
|
|
338
|
+
sendHtmlFileOrFallback(res, indexPath, fallbackHtml, 200);
|
|
149
339
|
});
|
|
150
|
-
// WebSocket
|
|
340
|
+
// --- WebSocket ---
|
|
151
341
|
const wss = new WebSocketServer({ noServer: true });
|
|
152
|
-
// Handle WebSocket upgrade
|
|
153
342
|
server.on('upgrade', (request, socket, head) => {
|
|
154
343
|
const pathname = request.url ? new URL(request.url, `http://${request.headers.host}`).pathname : '';
|
|
155
344
|
if (pathname === '/ws') {
|
|
156
345
|
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
157
|
-
if (mock) {
|
|
158
|
-
// Mock WebSocket - send periodic updates with fixture data
|
|
346
|
+
if (mode === 'mock') {
|
|
159
347
|
handleMockWebSocket(ws, verbose);
|
|
160
348
|
}
|
|
349
|
+
else if (mode === 'proxy' && relayUrl) {
|
|
350
|
+
handleHybridWebSocket(ws, getRelaycastSnapshot, relayUrl, verbose);
|
|
351
|
+
}
|
|
161
352
|
else {
|
|
162
|
-
|
|
163
|
-
handleProxyWebSocket(ws, relayUrl, verbose);
|
|
353
|
+
handleStandaloneWebSocket(ws, getRelaycastSnapshot, verbose);
|
|
164
354
|
}
|
|
165
355
|
});
|
|
356
|
+
return;
|
|
166
357
|
}
|
|
167
|
-
|
|
168
|
-
|
|
358
|
+
if (mode !== 'mock' && (pathname === '/ws/logs' || pathname.startsWith('/ws/logs/'))) {
|
|
359
|
+
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
360
|
+
handleStandaloneLogWebSocket(ws, pathname, dataDir, getLocalAgentNames, verbose);
|
|
361
|
+
});
|
|
362
|
+
return;
|
|
169
363
|
}
|
|
364
|
+
socket.destroy();
|
|
170
365
|
});
|
|
171
366
|
const close = () => {
|
|
172
367
|
return new Promise((resolve) => {
|
|
@@ -180,110 +375,7 @@ export function createServer(options = {}) {
|
|
|
180
375
|
return { app, server, wss, close, mode };
|
|
181
376
|
}
|
|
182
377
|
/**
|
|
183
|
-
*
|
|
184
|
-
* Sends periodic updates with fixture data
|
|
185
|
-
*/
|
|
186
|
-
function handleMockWebSocket(ws, verbose) {
|
|
187
|
-
if (verbose) {
|
|
188
|
-
console.log('[dashboard] Mock WebSocket client connected');
|
|
189
|
-
}
|
|
190
|
-
// Send initial data
|
|
191
|
-
const sendData = () => {
|
|
192
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
193
|
-
ws.send(JSON.stringify({
|
|
194
|
-
agents: mockAgents,
|
|
195
|
-
messages: mockMessages,
|
|
196
|
-
sessions: mockSessions,
|
|
197
|
-
}));
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
// Send initial data immediately
|
|
201
|
-
sendData();
|
|
202
|
-
// Send updates every 5 seconds
|
|
203
|
-
const interval = setInterval(sendData, 5000);
|
|
204
|
-
// Handle messages from client
|
|
205
|
-
ws.on('message', (data) => {
|
|
206
|
-
try {
|
|
207
|
-
const msg = JSON.parse(data.toString());
|
|
208
|
-
if (verbose) {
|
|
209
|
-
console.log('[dashboard] Mock WS received:', msg);
|
|
210
|
-
}
|
|
211
|
-
// Echo back acknowledgment for certain message types
|
|
212
|
-
if (msg.type === 'ping') {
|
|
213
|
-
ws.send(JSON.stringify({ type: 'pong' }));
|
|
214
|
-
}
|
|
215
|
-
else if (msg.type === 'subscribe') {
|
|
216
|
-
// Send current data when client subscribes
|
|
217
|
-
sendData();
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
catch {
|
|
221
|
-
// Ignore parse errors
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
ws.on('close', () => {
|
|
225
|
-
if (verbose) {
|
|
226
|
-
console.log('[dashboard] Mock WebSocket client disconnected');
|
|
227
|
-
}
|
|
228
|
-
clearInterval(interval);
|
|
229
|
-
});
|
|
230
|
-
ws.on('error', (err) => {
|
|
231
|
-
console.error('[dashboard] Mock WebSocket error:', err.message);
|
|
232
|
-
clearInterval(interval);
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Handle proxy WebSocket connections
|
|
237
|
-
* Forwards messages bidirectionally to relay daemon
|
|
238
|
-
*/
|
|
239
|
-
function handleProxyWebSocket(ws, relayUrl, verbose) {
|
|
240
|
-
const relayUrlObj = new URL(relayUrl);
|
|
241
|
-
const wsRelayUrl = `ws://${relayUrlObj.host}`;
|
|
242
|
-
// Create connection to relay daemon
|
|
243
|
-
const relayWs = new WebSocket(`${wsRelayUrl}/ws`);
|
|
244
|
-
relayWs.on('open', () => {
|
|
245
|
-
if (verbose) {
|
|
246
|
-
console.log('[dashboard] WebSocket connected to relay daemon');
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
// Forward messages from client to relay
|
|
250
|
-
ws.on('message', (data) => {
|
|
251
|
-
if (relayWs.readyState === WebSocket.OPEN) {
|
|
252
|
-
relayWs.send(data);
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
// Forward messages from relay to client
|
|
256
|
-
relayWs.on('message', (data) => {
|
|
257
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
258
|
-
ws.send(data);
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
// Handle client disconnect
|
|
262
|
-
ws.on('close', () => {
|
|
263
|
-
if (verbose) {
|
|
264
|
-
console.log('[dashboard] Client WebSocket closed');
|
|
265
|
-
}
|
|
266
|
-
relayWs.close();
|
|
267
|
-
});
|
|
268
|
-
// Handle relay disconnect
|
|
269
|
-
relayWs.on('close', () => {
|
|
270
|
-
if (verbose) {
|
|
271
|
-
console.log('[dashboard] Relay WebSocket closed');
|
|
272
|
-
}
|
|
273
|
-
ws.close();
|
|
274
|
-
});
|
|
275
|
-
// Handle errors
|
|
276
|
-
ws.on('error', (err) => {
|
|
277
|
-
console.error('[dashboard] Client WebSocket error:', err.message);
|
|
278
|
-
relayWs.close();
|
|
279
|
-
});
|
|
280
|
-
relayWs.on('error', (err) => {
|
|
281
|
-
console.error('[dashboard] Relay WebSocket error:', err.message);
|
|
282
|
-
ws.close();
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Try to listen on a port, returns the port if successful or null if in use
|
|
378
|
+
* Try to listen on a port, returns the port if successful or null if in use.
|
|
287
379
|
*/
|
|
288
380
|
function tryListen(server, port) {
|
|
289
381
|
return new Promise((resolve) => {
|
|
@@ -310,7 +402,7 @@ function tryListen(server, port) {
|
|
|
310
402
|
});
|
|
311
403
|
}
|
|
312
404
|
/**
|
|
313
|
-
* Find an available port starting from the preferred port
|
|
405
|
+
* Find an available port starting from the preferred port.
|
|
314
406
|
*/
|
|
315
407
|
async function findAvailablePort(server, preferredPort, maxAttempts = 10) {
|
|
316
408
|
for (let i = 0; i < maxAttempts; i++) {
|
|
@@ -319,19 +411,16 @@ async function findAvailablePort(server, preferredPort, maxAttempts = 10) {
|
|
|
319
411
|
if (result !== null) {
|
|
320
412
|
return result;
|
|
321
413
|
}
|
|
322
|
-
// Close and recreate listener for next attempt
|
|
323
414
|
server.close();
|
|
324
415
|
}
|
|
325
416
|
throw new Error(`Could not find available port after ${maxAttempts} attempts starting from ${preferredPort}`);
|
|
326
417
|
}
|
|
327
418
|
/**
|
|
328
|
-
* Start the dashboard server
|
|
329
|
-
* Automatically finds an available port if the preferred port is in use
|
|
419
|
+
* Start the dashboard server.
|
|
330
420
|
*/
|
|
331
421
|
export async function startServer(options = {}) {
|
|
332
422
|
const preferredPort = options.port || parseInt(process.env.PORT || '3888', 10);
|
|
333
423
|
const dashboard = createServer(options);
|
|
334
|
-
// Try preferred port first, then search for available port
|
|
335
424
|
const actualPort = await findAvailablePort(dashboard.server, preferredPort);
|
|
336
425
|
if (actualPort !== preferredPort) {
|
|
337
426
|
console.log(`[dashboard] Port ${preferredPort} in use, using port ${actualPort}`);
|
|
@@ -340,8 +429,11 @@ export async function startServer(options = {}) {
|
|
|
340
429
|
if (dashboard.mode === 'mock') {
|
|
341
430
|
console.log('[dashboard] Using mock data - ready for standalone testing');
|
|
342
431
|
}
|
|
432
|
+
else if (dashboard.mode === 'proxy') {
|
|
433
|
+
console.log(`[dashboard] Proxy mode enabled - broker URL ${normalizeRelayUrl(options.relayUrl ?? process.env.RELAY_URL)}`);
|
|
434
|
+
}
|
|
343
435
|
else {
|
|
344
|
-
console.log(
|
|
436
|
+
console.log('[dashboard] Standalone mode enabled - relaycast data only');
|
|
345
437
|
}
|
|
346
438
|
return dashboard;
|
|
347
439
|
}
|