@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
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
/**
|
|
6
|
+
* Integrated channel + DM routes (separate from proxy-mode routes/channels.ts).
|
|
7
|
+
*/
|
|
8
|
+
export function registerChannelsIntegratedRoutes(app, deps) {
|
|
9
|
+
const { storage, teamDir, attachmentRegistry, onlineUsers, userBridge, spawnReader, resolveWorkspaceId, loadChannelRecords, persistChannelMembershipEvent, getRelayClient, buildThreadSummaryMap, isInternalAgent, getAllData, } = deps;
|
|
10
|
+
app.get('/api/data', (req, res) => {
|
|
11
|
+
getAllData().then((data) => {
|
|
12
|
+
const safeData = data ?? { agents: [], users: [], messages: [], activity: [], sessions: [], summaries: [] };
|
|
13
|
+
res.json(safeData);
|
|
14
|
+
}).catch((err) => {
|
|
15
|
+
console.error('Failed to fetch dashboard data', err);
|
|
16
|
+
res.status(500).json({ error: 'Failed to load data' });
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
app.get('/api/channels', async (req, res) => {
|
|
20
|
+
const username = req.query.username;
|
|
21
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
22
|
+
if (!storage) {
|
|
23
|
+
if (!username) {
|
|
24
|
+
return res.status(400).json({ error: 'username query param required' });
|
|
25
|
+
}
|
|
26
|
+
const channels = userBridge?.getUserChannels(username) ?? [];
|
|
27
|
+
return res.json({
|
|
28
|
+
channels: channels.map((id) => ({
|
|
29
|
+
id,
|
|
30
|
+
name: id.startsWith('#') ? id.slice(1) : id,
|
|
31
|
+
visibility: 'public',
|
|
32
|
+
status: 'active',
|
|
33
|
+
createdAt: new Date().toISOString(),
|
|
34
|
+
createdBy: username,
|
|
35
|
+
memberCount: 0,
|
|
36
|
+
unreadCount: 0,
|
|
37
|
+
hasMentions: false,
|
|
38
|
+
isDm: id.startsWith('dm:'),
|
|
39
|
+
})),
|
|
40
|
+
archivedChannels: [],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const channelMap = await loadChannelRecords(workspaceId);
|
|
45
|
+
const activeChannels = [];
|
|
46
|
+
const archivedChannels = [];
|
|
47
|
+
for (const record of channelMap.values()) {
|
|
48
|
+
const isMember = !username || record.members.has(username) || record.id === '#general';
|
|
49
|
+
if (!isMember) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const channel = {
|
|
53
|
+
id: record.id,
|
|
54
|
+
name: record.id.startsWith('#') ? record.id.slice(1) : record.id,
|
|
55
|
+
description: record.description,
|
|
56
|
+
visibility: record.visibility,
|
|
57
|
+
status: record.status,
|
|
58
|
+
createdAt: record.createdAt ? new Date(record.createdAt).toISOString() : new Date(record.lastActivityAt || Date.now()).toISOString(),
|
|
59
|
+
createdBy: record.createdBy || '__system__',
|
|
60
|
+
lastActivityAt: record.lastActivityAt ? new Date(record.lastActivityAt).toISOString() : undefined,
|
|
61
|
+
memberCount: record.members.size,
|
|
62
|
+
unreadCount: 0,
|
|
63
|
+
hasMentions: false,
|
|
64
|
+
lastMessage: record.lastMessage,
|
|
65
|
+
isDm: record.id.startsWith('dm:'),
|
|
66
|
+
dmParticipants: record.dmParticipants,
|
|
67
|
+
};
|
|
68
|
+
if (record.status === 'archived') {
|
|
69
|
+
archivedChannels.push(channel);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
activeChannels.push(channel);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return res.json({
|
|
76
|
+
channels: activeChannels,
|
|
77
|
+
archivedChannels,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
console.error('[channels] Failed to load channels', err);
|
|
82
|
+
return res.status(500).json({ error: 'Failed to load channels' });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
app.get('/api/channels/available-members', async (_req, res) => {
|
|
86
|
+
try {
|
|
87
|
+
const availableAgents = [];
|
|
88
|
+
if (spawnReader) {
|
|
89
|
+
const activeWorkers = spawnReader.getActiveWorkers();
|
|
90
|
+
for (const worker of activeWorkers) {
|
|
91
|
+
availableAgents.push({
|
|
92
|
+
id: worker.name,
|
|
93
|
+
displayName: worker.name,
|
|
94
|
+
entityType: 'agent',
|
|
95
|
+
status: 'online',
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (userBridge) {
|
|
100
|
+
const registeredUsers = userBridge.getRegisteredUsers();
|
|
101
|
+
for (const username of registeredUsers) {
|
|
102
|
+
if (!availableAgents.some((a) => a.id === username) && username !== 'Dashboard') {
|
|
103
|
+
availableAgents.push({
|
|
104
|
+
id: username,
|
|
105
|
+
displayName: username,
|
|
106
|
+
entityType: 'agent',
|
|
107
|
+
status: 'online',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return res.json({
|
|
113
|
+
success: true,
|
|
114
|
+
members: [],
|
|
115
|
+
agents: availableAgents,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
console.error('[channels] Failed to get available members:', err);
|
|
120
|
+
return res.status(500).json({ error: 'Failed to get available members' });
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
app.post('/api/channels', express.json(), async (req, res) => {
|
|
124
|
+
const { name, description, isPrivate, invites } = req.body;
|
|
125
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
126
|
+
const username = req.query.username || req.body.username || 'Dashboard';
|
|
127
|
+
if (!name) {
|
|
128
|
+
return res.status(400).json({ error: 'name is required' });
|
|
129
|
+
}
|
|
130
|
+
const channelId = name.startsWith('#') ? name : `#${name}`;
|
|
131
|
+
try {
|
|
132
|
+
await userBridge?.joinChannel(username, channelId);
|
|
133
|
+
await persistChannelMembershipEvent(channelId, username, 'join', { workspaceId });
|
|
134
|
+
if (invites) {
|
|
135
|
+
const inviteList = invites.split(',').map((s) => s.trim()).filter(Boolean);
|
|
136
|
+
for (const invitee of inviteList) {
|
|
137
|
+
await userBridge?.joinChannel(invitee, channelId);
|
|
138
|
+
await persistChannelMembershipEvent(channelId, invitee, 'invite', { invitedBy: username, workspaceId });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (storage) {
|
|
142
|
+
await storage.saveMessage({
|
|
143
|
+
id: `channel-create-${crypto.randomUUID()}`,
|
|
144
|
+
ts: Date.now(),
|
|
145
|
+
from: '__system__',
|
|
146
|
+
to: channelId,
|
|
147
|
+
topic: undefined,
|
|
148
|
+
kind: 'state',
|
|
149
|
+
body: `Channel created by ${username}`,
|
|
150
|
+
data: {
|
|
151
|
+
_channelCreate: {
|
|
152
|
+
createdBy: username,
|
|
153
|
+
description,
|
|
154
|
+
isPrivate: isPrivate ?? false,
|
|
155
|
+
},
|
|
156
|
+
...(workspaceId ? { _workspaceId: workspaceId } : {}),
|
|
157
|
+
},
|
|
158
|
+
status: 'read',
|
|
159
|
+
is_urgent: false,
|
|
160
|
+
is_broadcast: true,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return res.json({
|
|
164
|
+
success: true,
|
|
165
|
+
channel: {
|
|
166
|
+
id: channelId,
|
|
167
|
+
name: name.startsWith('#') ? name.slice(1) : name,
|
|
168
|
+
description,
|
|
169
|
+
visibility: isPrivate ? 'private' : 'public',
|
|
170
|
+
status: 'active',
|
|
171
|
+
createdAt: new Date().toISOString(),
|
|
172
|
+
createdBy: username,
|
|
173
|
+
memberCount: 1,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
const message = err instanceof Error ? err.message : 'Failed to create channel';
|
|
179
|
+
console.error('[channels] Failed to create channel:', err);
|
|
180
|
+
return res.status(500).json({ error: message });
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
app.post('/api/channels/invite', express.json(), async (req, res) => {
|
|
184
|
+
const { channel, invites, invitedBy } = req.body;
|
|
185
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
186
|
+
if (!channel || !invites) {
|
|
187
|
+
return res.status(400).json({ error: 'channel and invites are required' });
|
|
188
|
+
}
|
|
189
|
+
const channelId = channel.startsWith('dm:')
|
|
190
|
+
? channel
|
|
191
|
+
: (channel.startsWith('#') ? channel : `#${channel}`);
|
|
192
|
+
let inviteList;
|
|
193
|
+
if (typeof invites === 'string') {
|
|
194
|
+
inviteList = invites.split(',').map((s) => s.trim()).filter(Boolean)
|
|
195
|
+
.map((id) => ({ id, type: 'agent' }));
|
|
196
|
+
}
|
|
197
|
+
else if (Array.isArray(invites)) {
|
|
198
|
+
inviteList = invites.map((item) => {
|
|
199
|
+
if (typeof item === 'string') {
|
|
200
|
+
return { id: item, type: 'agent' };
|
|
201
|
+
}
|
|
202
|
+
return { id: item.id, type: item.type || 'agent' };
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
return res.status(400).json({ error: 'invites must be a string or array' });
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
const results = [];
|
|
210
|
+
for (const invitee of inviteList) {
|
|
211
|
+
let success = false;
|
|
212
|
+
let reason;
|
|
213
|
+
if (userBridge?.isUserRegistered(invitee.id)) {
|
|
214
|
+
success = await userBridge.joinChannel(invitee.id, channelId);
|
|
215
|
+
if (!success) {
|
|
216
|
+
reason = 'join_failed';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
success = true;
|
|
221
|
+
reason = 'pending';
|
|
222
|
+
}
|
|
223
|
+
await persistChannelMembershipEvent(channelId, invitee.id, 'invite', {
|
|
224
|
+
invitedBy,
|
|
225
|
+
workspaceId,
|
|
226
|
+
});
|
|
227
|
+
results.push({ id: invitee.id, type: invitee.type, success, reason });
|
|
228
|
+
}
|
|
229
|
+
return res.json({ channel: channelId, invited: results });
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
const message = err instanceof Error ? err.message : 'Failed to invite members';
|
|
233
|
+
console.error('[channels] Failed to invite to channel:', err);
|
|
234
|
+
return res.status(500).json({ error: message });
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
app.get('/api/channels/users', (_req, res) => {
|
|
238
|
+
const users = userBridge?.getRegisteredUsers() ?? [];
|
|
239
|
+
res.json({ users });
|
|
240
|
+
});
|
|
241
|
+
app.post('/api/channels/join', express.json(), async (req, res) => {
|
|
242
|
+
const { username, channel } = req.body;
|
|
243
|
+
if (!username || !channel) {
|
|
244
|
+
return res.status(400).json({ error: 'username and channel required' });
|
|
245
|
+
}
|
|
246
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
247
|
+
const channelId = channel.startsWith('dm:')
|
|
248
|
+
? channel
|
|
249
|
+
: (channel.startsWith('#') ? channel : `#${channel}`);
|
|
250
|
+
let success = false;
|
|
251
|
+
const isLocalUser = userBridge?.isUserRegistered(username);
|
|
252
|
+
if (isLocalUser) {
|
|
253
|
+
success = await userBridge?.joinChannel(username, channelId) ?? false;
|
|
254
|
+
}
|
|
255
|
+
if (!success) {
|
|
256
|
+
try {
|
|
257
|
+
const client = await getRelayClient(username);
|
|
258
|
+
if (client && client.state === 'READY') {
|
|
259
|
+
success = client.joinChannel(channelId, username);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Ignore fallback errors.
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (success) {
|
|
267
|
+
await persistChannelMembershipEvent(channelId, username, 'join', { workspaceId });
|
|
268
|
+
}
|
|
269
|
+
return res.json({ success, channel: channelId });
|
|
270
|
+
});
|
|
271
|
+
app.post('/api/channels/leave', express.json(), async (req, res) => {
|
|
272
|
+
const { username, channel } = req.body;
|
|
273
|
+
if (!username || !channel) {
|
|
274
|
+
return res.status(400).json({ error: 'username and channel required' });
|
|
275
|
+
}
|
|
276
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
277
|
+
try {
|
|
278
|
+
const success = await userBridge?.leaveChannel(username, channel);
|
|
279
|
+
if (success) {
|
|
280
|
+
await persistChannelMembershipEvent(channel, username, 'leave', { workspaceId });
|
|
281
|
+
}
|
|
282
|
+
return res.json({ success, channel });
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
const message = err instanceof Error ? err.message : 'Leave failed';
|
|
286
|
+
return res.status(500).json({ error: message });
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
app.post('/api/channels/admin-join', express.json(), async (req, res) => {
|
|
290
|
+
const { channel, member } = req.body;
|
|
291
|
+
if (!channel || !member) {
|
|
292
|
+
return res.status(400).json({ error: 'channel and member required' });
|
|
293
|
+
}
|
|
294
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
295
|
+
try {
|
|
296
|
+
const success = await userBridge?.adminJoinChannel(channel, member);
|
|
297
|
+
if (success) {
|
|
298
|
+
await persistChannelMembershipEvent(channel, member, 'join', { workspaceId });
|
|
299
|
+
}
|
|
300
|
+
let warning;
|
|
301
|
+
const connectedAgentsPath = path.join(teamDir, 'connected-agents.json');
|
|
302
|
+
try {
|
|
303
|
+
if (fs.existsSync(connectedAgentsPath)) {
|
|
304
|
+
const data = JSON.parse(fs.readFileSync(connectedAgentsPath, 'utf-8'));
|
|
305
|
+
const connectedAgents = data.agents || [];
|
|
306
|
+
const connectedUsers = data.users || [];
|
|
307
|
+
const allConnected = [...connectedAgents, ...connectedUsers];
|
|
308
|
+
const isConnected = allConnected.some((name) => name.toLowerCase() === member.toLowerCase());
|
|
309
|
+
if (!isConnected) {
|
|
310
|
+
warning = `Member "${member}" is not currently connected to the daemon. Messages sent to this channel will not be delivered until the agent connects.`;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
// Ignore parse errors.
|
|
316
|
+
}
|
|
317
|
+
return res.json({ success, channel, member, warning });
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
const message = err instanceof Error ? err.message : 'Admin join failed';
|
|
321
|
+
return res.status(500).json({ error: message });
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
app.post('/api/channels/admin-remove', express.json(), async (req, res) => {
|
|
325
|
+
const { channel, member } = req.body;
|
|
326
|
+
if (!channel || !member) {
|
|
327
|
+
return res.status(400).json({ error: 'channel and member required' });
|
|
328
|
+
}
|
|
329
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
330
|
+
try {
|
|
331
|
+
const success = await userBridge?.adminRemoveMember(channel, member);
|
|
332
|
+
if (success) {
|
|
333
|
+
await persistChannelMembershipEvent(channel, member, 'leave', { workspaceId });
|
|
334
|
+
}
|
|
335
|
+
return res.json({ success, channel, member });
|
|
336
|
+
}
|
|
337
|
+
catch (err) {
|
|
338
|
+
const message = err instanceof Error ? err.message : 'Admin remove failed';
|
|
339
|
+
return res.status(500).json({ error: message });
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
app.get('/api/channels/:channel/members', async (req, res) => {
|
|
343
|
+
const channelId = req.params.channel.startsWith('#') ? req.params.channel : `#${req.params.channel}`;
|
|
344
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
345
|
+
try {
|
|
346
|
+
const channelMap = await loadChannelRecords(workspaceId);
|
|
347
|
+
const record = channelMap.get(channelId);
|
|
348
|
+
const agentsPath = path.join(teamDir, 'agents.json');
|
|
349
|
+
const onlineAgents = [];
|
|
350
|
+
const thirtySecondsAgo = Date.now() - 30 * 1000;
|
|
351
|
+
if (fs.existsSync(agentsPath)) {
|
|
352
|
+
try {
|
|
353
|
+
const data = JSON.parse(fs.readFileSync(agentsPath, 'utf-8'));
|
|
354
|
+
for (const agent of (data.agents || [])) {
|
|
355
|
+
if (agent.lastSeen && new Date(agent.lastSeen).getTime() > thirtySecondsAgo) {
|
|
356
|
+
onlineAgents.push(agent.name);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
// Ignore parse errors.
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const connectedUsers = userBridge?.getRegisteredUsers() ?? [];
|
|
365
|
+
const memberSet = new Set();
|
|
366
|
+
if (record?.members) {
|
|
367
|
+
for (const member of record.members) {
|
|
368
|
+
memberSet.add(member);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (channelId === '#general') {
|
|
372
|
+
for (const agent of onlineAgents) {
|
|
373
|
+
memberSet.add(agent);
|
|
374
|
+
}
|
|
375
|
+
for (const user of connectedUsers) {
|
|
376
|
+
memberSet.add(user);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
const members = Array.from(memberSet).map((name) => {
|
|
380
|
+
const isOnlineAgent = onlineAgents.includes(name);
|
|
381
|
+
const isOnlineUser = connectedUsers.includes(name);
|
|
382
|
+
return {
|
|
383
|
+
id: name,
|
|
384
|
+
displayName: name,
|
|
385
|
+
entityType: isOnlineUser ? 'user' : 'agent',
|
|
386
|
+
role: 'member',
|
|
387
|
+
status: isOnlineAgent || isOnlineUser ? 'online' : 'offline',
|
|
388
|
+
joinedAt: new Date().toISOString(),
|
|
389
|
+
};
|
|
390
|
+
});
|
|
391
|
+
return res.json({ members });
|
|
392
|
+
}
|
|
393
|
+
catch (err) {
|
|
394
|
+
const message = err instanceof Error ? err.message : 'Failed to get channel members';
|
|
395
|
+
console.error('[channels] Failed to get channel members:', err);
|
|
396
|
+
return res.status(500).json({ error: message });
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
app.get('/api/channels/:channel/messages', async (req, res) => {
|
|
400
|
+
if (!storage) {
|
|
401
|
+
return res.status(503).json({ error: 'Storage not configured' });
|
|
402
|
+
}
|
|
403
|
+
const channelId = req.params.channel;
|
|
404
|
+
const limit = req.query.limit ? parseInt(req.query.limit, 10) : 200;
|
|
405
|
+
const beforeTs = req.query.before ? parseInt(req.query.before, 10) : undefined;
|
|
406
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
407
|
+
try {
|
|
408
|
+
const query = {
|
|
409
|
+
to: channelId,
|
|
410
|
+
limit,
|
|
411
|
+
order: 'desc',
|
|
412
|
+
};
|
|
413
|
+
if (beforeTs) {
|
|
414
|
+
query.sinceTs = beforeTs;
|
|
415
|
+
}
|
|
416
|
+
let messages = await storage.getMessages(query);
|
|
417
|
+
messages = messages.filter((m) => {
|
|
418
|
+
const data = m.data;
|
|
419
|
+
if (workspaceId && data?._workspaceId && data._workspaceId !== workspaceId) {
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
if (isInternalAgent(m.from))
|
|
423
|
+
return false;
|
|
424
|
+
return Boolean(data?._isChannelMessage) || (m.to && m.to.startsWith('#'));
|
|
425
|
+
});
|
|
426
|
+
messages.sort((a, b) => a.ts - b.ts);
|
|
427
|
+
const threadSummaries = buildThreadSummaryMap(messages);
|
|
428
|
+
return res.json({
|
|
429
|
+
messages: messages.map((m) => {
|
|
430
|
+
const senderPresence = onlineUsers.get(m.from);
|
|
431
|
+
const fromAvatarUrl = senderPresence?.info.avatarUrl;
|
|
432
|
+
const fromEntityType = senderPresence ? 'user' : 'agent';
|
|
433
|
+
const summaryFromReplies = threadSummaries.get(m.id);
|
|
434
|
+
const threadSummary = summaryFromReplies ?? (m.replyCount && m.replyCount > 0
|
|
435
|
+
? {
|
|
436
|
+
threadId: m.id,
|
|
437
|
+
replyCount: m.replyCount,
|
|
438
|
+
participants: [],
|
|
439
|
+
lastReplyAt: m.ts,
|
|
440
|
+
}
|
|
441
|
+
: undefined);
|
|
442
|
+
return {
|
|
443
|
+
id: m.id,
|
|
444
|
+
channelId,
|
|
445
|
+
from: m.from,
|
|
446
|
+
fromEntityType,
|
|
447
|
+
fromAvatarUrl,
|
|
448
|
+
content: m.body,
|
|
449
|
+
timestamp: new Date(m.ts).toISOString(),
|
|
450
|
+
threadId: m.thread || undefined,
|
|
451
|
+
threadSummary,
|
|
452
|
+
isRead: true,
|
|
453
|
+
};
|
|
454
|
+
}),
|
|
455
|
+
hasMore: messages.length === limit,
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
catch (err) {
|
|
459
|
+
console.error('[channels] Failed to fetch channel messages', err);
|
|
460
|
+
return res.status(500).json({ error: 'Failed to fetch channel messages' });
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
app.post('/api/channels/subscribe', express.json(), async (req, res) => {
|
|
464
|
+
const { username, channels } = req.body;
|
|
465
|
+
if (!username) {
|
|
466
|
+
return res.status(400).json({ error: 'username required' });
|
|
467
|
+
}
|
|
468
|
+
try {
|
|
469
|
+
const joinedChannels = [];
|
|
470
|
+
const channelList = channels || ['#general'];
|
|
471
|
+
let regAttempts = 0;
|
|
472
|
+
const maxRegAttempts = 20;
|
|
473
|
+
while (!userBridge?.isUserRegistered(username) && regAttempts < maxRegAttempts) {
|
|
474
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
475
|
+
regAttempts++;
|
|
476
|
+
}
|
|
477
|
+
if (userBridge?.isUserRegistered(username)) {
|
|
478
|
+
for (const channel of channelList) {
|
|
479
|
+
const channelId = channel.startsWith('dm:')
|
|
480
|
+
? channel
|
|
481
|
+
: (channel.startsWith('#') ? channel : `#${channel}`);
|
|
482
|
+
const joined = await userBridge.joinChannel(username, channelId);
|
|
483
|
+
if (joined) {
|
|
484
|
+
joinedChannels.push(channelId);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return res.json({ success: true, channels: joinedChannels });
|
|
488
|
+
}
|
|
489
|
+
const client = await getRelayClient(username);
|
|
490
|
+
if (!client) {
|
|
491
|
+
return res.status(503).json({ error: 'Could not acquire relay adapter client' });
|
|
492
|
+
}
|
|
493
|
+
let attempts = 0;
|
|
494
|
+
while (client.state !== 'READY' && attempts < 50) {
|
|
495
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
496
|
+
attempts++;
|
|
497
|
+
}
|
|
498
|
+
if (client.state !== 'READY') {
|
|
499
|
+
return res.status(503).json({ error: 'Relay client not ready' });
|
|
500
|
+
}
|
|
501
|
+
for (const channel of channelList) {
|
|
502
|
+
const channelId = channel.startsWith('dm:')
|
|
503
|
+
? channel
|
|
504
|
+
: (channel.startsWith('#') ? channel : `#${channel}`);
|
|
505
|
+
const joined = client.joinChannel(channelId, username);
|
|
506
|
+
if (joined) {
|
|
507
|
+
joinedChannels.push(channelId);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return res.json({ success: true, channels: joinedChannels });
|
|
511
|
+
}
|
|
512
|
+
catch (err) {
|
|
513
|
+
const message = err instanceof Error ? err.message : 'Subscribe failed';
|
|
514
|
+
return res.status(500).json({ error: message });
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
app.post('/api/channels/message', express.json(), async (req, res) => {
|
|
518
|
+
const { username, channel, body, thread, attachmentIds } = req.body;
|
|
519
|
+
if (!username || !channel || !body) {
|
|
520
|
+
return res.status(400).json({ error: 'username, channel, and body required' });
|
|
521
|
+
}
|
|
522
|
+
let attachments;
|
|
523
|
+
if (attachmentIds && Array.isArray(attachmentIds) && attachmentIds.length > 0) {
|
|
524
|
+
attachments = [];
|
|
525
|
+
for (const id of attachmentIds) {
|
|
526
|
+
const attachment = attachmentRegistry.get(id);
|
|
527
|
+
if (attachment) {
|
|
528
|
+
attachments.push(attachment);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
533
|
+
const channelId = channel.startsWith('dm:')
|
|
534
|
+
? channel
|
|
535
|
+
: (channel.startsWith('#') ? channel : `#${channel}`);
|
|
536
|
+
let success = false;
|
|
537
|
+
const isLocalUser = userBridge?.isUserRegistered(username);
|
|
538
|
+
if (isLocalUser) {
|
|
539
|
+
success = await userBridge?.sendChannelMessage(username, channelId, body, {
|
|
540
|
+
thread,
|
|
541
|
+
data: workspaceId ? { _workspaceId: workspaceId } : undefined,
|
|
542
|
+
attachments,
|
|
543
|
+
}) ?? false;
|
|
544
|
+
}
|
|
545
|
+
if (!success) {
|
|
546
|
+
try {
|
|
547
|
+
const client = await getRelayClient(username);
|
|
548
|
+
if (client && client.state === 'READY') {
|
|
549
|
+
client.joinChannel(channelId, username);
|
|
550
|
+
success = client.sendChannelMessage(channelId, body, {
|
|
551
|
+
thread,
|
|
552
|
+
data: workspaceId ? { _workspaceId: workspaceId } : undefined,
|
|
553
|
+
attachments,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
catch {
|
|
558
|
+
// Ignore fallback errors.
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return res.json({ success });
|
|
562
|
+
});
|
|
563
|
+
app.post('/api/channels/archive', express.json(), async (req, res) => {
|
|
564
|
+
if (!storage) {
|
|
565
|
+
return res.status(503).json({ error: 'Storage not configured' });
|
|
566
|
+
}
|
|
567
|
+
const { channel } = req.body;
|
|
568
|
+
if (!channel) {
|
|
569
|
+
return res.status(400).json({ error: 'channel required' });
|
|
570
|
+
}
|
|
571
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
572
|
+
try {
|
|
573
|
+
await storage.saveMessage({
|
|
574
|
+
id: `state-${Date.now()}`,
|
|
575
|
+
ts: Date.now(),
|
|
576
|
+
from: '__system__',
|
|
577
|
+
to: channel,
|
|
578
|
+
topic: undefined,
|
|
579
|
+
kind: 'message',
|
|
580
|
+
body: 'STATE:archived',
|
|
581
|
+
data: {
|
|
582
|
+
_channelState: 'archived',
|
|
583
|
+
...(workspaceId ? { _workspaceId: workspaceId } : {}),
|
|
584
|
+
},
|
|
585
|
+
status: 'read',
|
|
586
|
+
is_urgent: false,
|
|
587
|
+
is_broadcast: true,
|
|
588
|
+
});
|
|
589
|
+
return res.json({ success: true });
|
|
590
|
+
}
|
|
591
|
+
catch (err) {
|
|
592
|
+
console.error('[channels] Failed to archive channel', err);
|
|
593
|
+
return res.status(500).json({ error: 'Failed to archive channel' });
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
app.post('/api/channels/unarchive', express.json(), async (req, res) => {
|
|
597
|
+
if (!storage) {
|
|
598
|
+
return res.status(503).json({ error: 'Storage not configured' });
|
|
599
|
+
}
|
|
600
|
+
const { channel } = req.body;
|
|
601
|
+
if (!channel) {
|
|
602
|
+
return res.status(400).json({ error: 'channel required' });
|
|
603
|
+
}
|
|
604
|
+
const workspaceId = resolveWorkspaceId(req);
|
|
605
|
+
try {
|
|
606
|
+
await storage.saveMessage({
|
|
607
|
+
id: `state-${Date.now()}`,
|
|
608
|
+
ts: Date.now(),
|
|
609
|
+
from: '__system__',
|
|
610
|
+
to: channel,
|
|
611
|
+
topic: undefined,
|
|
612
|
+
kind: 'message',
|
|
613
|
+
body: 'STATE:active',
|
|
614
|
+
data: {
|
|
615
|
+
_channelState: 'active',
|
|
616
|
+
...(workspaceId ? { _workspaceId: workspaceId } : {}),
|
|
617
|
+
},
|
|
618
|
+
status: 'read',
|
|
619
|
+
is_urgent: false,
|
|
620
|
+
is_broadcast: true,
|
|
621
|
+
});
|
|
622
|
+
return res.json({ success: true });
|
|
623
|
+
}
|
|
624
|
+
catch (err) {
|
|
625
|
+
console.error('[channels] Failed to unarchive channel', err);
|
|
626
|
+
return res.status(500).json({ error: 'Failed to unarchive channel' });
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
app.post('/api/dm', express.json(), async (req, res) => {
|
|
630
|
+
const { from, to, body, thread } = req.body;
|
|
631
|
+
if (!from || !to || !body) {
|
|
632
|
+
return res.status(400).json({ error: 'from, to, and body required' });
|
|
633
|
+
}
|
|
634
|
+
try {
|
|
635
|
+
const success = await userBridge?.sendDirectMessage(from, to, body, { thread });
|
|
636
|
+
return res.json({ success });
|
|
637
|
+
}
|
|
638
|
+
catch (err) {
|
|
639
|
+
const message = err instanceof Error ? err.message : 'DM failed';
|
|
640
|
+
return res.status(500).json({ error: message });
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
//# sourceMappingURL=channels-integrated.js.map
|