crewly 1.6.0 → 1.6.2
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/config/roles/orchestrator/fragments/role-boundary.md +4 -1
- package/config/roles/orchestrator/prompt.md +53 -0
- package/config/roles/orchestrator/soul.md +47 -10
- package/config/skills/_common/lib.sh +28 -0
- package/config/skills/agent/core/cancel-followup/execute.sh +0 -19
- package/config/skills/agent/core/get-my-active-work/SKILL.md +101 -0
- package/config/skills/agent/core/get-my-active-work/execute.sh +122 -0
- package/config/skills/agent/core/list-my-followups/execute.sh +0 -19
- package/config/skills/agent/core/record-learning/SKILL.md +29 -0
- package/config/skills/agent/core/reply-channel/SKILL.md +41 -0
- package/config/skills/agent/core/reply-channel/execute.sh +165 -0
- package/config/skills/agent/core/reply-channel/execute.test.sh +148 -0
- package/config/skills/agent/core/schedule-followup/execute.sh +0 -19
- package/config/skills/agent/core/watch-for-event/execute.sh +0 -19
- package/config/skills/agent/remote-browser/execute.sh +296 -14
- package/config/skills/agent/remote-browser/execute.test.sh +482 -0
- package/config/skills/orchestrator/credential-manager/execute.test.sh +88 -0
- package/config/skills/orchestrator/send-message/SKILL.md +30 -7
- package/config/skills/orchestrator/team-health-scan/SKILL.md +98 -0
- package/config/skills/orchestrator/team-health-scan/execute.sh +44 -0
- package/config/skills/registry.json +62 -1
- package/config/sops/developer/git-workflow.md +38 -3
- package/dist/backend/backend/src/config/oauth.config.d.ts +33 -0
- package/dist/backend/backend/src/config/oauth.config.d.ts.map +1 -0
- package/dist/backend/backend/src/config/oauth.config.js +45 -0
- package/dist/backend/backend/src/config/oauth.config.js.map +1 -0
- package/dist/backend/backend/src/constants.d.ts +69 -1
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +69 -2
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.d.ts +53 -0
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.js +92 -0
- package/dist/backend/backend/src/controllers/active-work/active-work.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.js +18 -1
- package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts +68 -0
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js +233 -5
- package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.js +10 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +8 -3
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts +132 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +401 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.d.ts +29 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.js +39 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.d.ts +8 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.js +8 -0
- package/dist/backend/backend/src/controllers/chat-v2/index.js.map +1 -0
- package/dist/backend/backend/src/controllers/credentials/credentials.controller.d.ts +0 -26
- package/dist/backend/backend/src/controllers/credentials/credentials.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/credentials/credentials.controller.js +47 -184
- package/dist/backend/backend/src/controllers/credentials/credentials.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/credentials/credentials.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/credentials/credentials.routes.js +2 -1
- package/dist/backend/backend/src/controllers/credentials/credentials.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.d.ts +40 -0
- package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js +162 -0
- package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.d.ts +13 -13
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.js +74 -234
- package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.js +4 -6
- package/dist/backend/backend/src/controllers/request/request.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/skill/skill.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/skill/skill.controller.js +1 -0
- package/dist/backend/backend/src/controllers/skill/skill.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts +43 -0
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.js +200 -72
- package/dist/backend/backend/src/controllers/task-management/tasks.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +46 -0
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.d.ts +59 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.js +127 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.d.ts +13 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.js +20 -0
- package/dist/backend/backend/src/controllers/team-health/team-health.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +9 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +256 -4
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +43 -6
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts +498 -0
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.js +759 -0
- package/dist/backend/backend/src/services/agent/active-work-briefing.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +25 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +193 -57
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +9 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +35 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts +8 -2
- package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/types.js +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/types.js.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux-command.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux-command.service.js +2 -1
- package/dist/backend/backend/src/services/agent/tmux-command.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/tmux.service.js +2 -1
- package/dist/backend/backend/src/services/agent/tmux.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +148 -3
- package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js +241 -2
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js +13 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js +30 -2
- package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +17 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts +79 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts.map +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js +118 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +161 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js +382 -2
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +105 -0
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js +232 -13
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +178 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +254 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts +134 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.js +232 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.d.ts +25 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.js +23 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +254 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +467 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.d.ts +27 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.js +57 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.d.ts +43 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.js +54 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/config.d.ts +100 -0
- package/dist/backend/backend/src/services/chat-v2/config.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/config.js +174 -0
- package/dist/backend/backend/src/services/chat-v2/config.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/index.d.ts +11 -0
- package/dist/backend/backend/src/services/chat-v2/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/index.js +12 -0
- package/dist/backend/backend/src/services/chat-v2/index.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts +114 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js +194 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.d.ts +100 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.js +351 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +132 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +281 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/types.d.ts +295 -0
- package/dist/backend/backend/src/services/chat-v2/types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/types.js +61 -0
- package/dist/backend/backend/src/services/chat-v2/types.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.d.ts +113 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.js +179 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.d.ts +131 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.js +227 -0
- package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.js.map +1 -0
- package/dist/backend/backend/src/services/core/config.service.js +3 -3
- package/dist/backend/backend/src/services/core/config.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.d.ts +7 -0
- package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js +15 -0
- package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +4 -16
- package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -1
- package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +7 -28
- package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts +69 -1
- package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-bus.service.js +118 -0
- package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts +275 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +736 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -0
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.js +18 -2
- package/dist/backend/backend/src/services/knowledge/fts5-index.service.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts +49 -13
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +123 -29
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.d.ts +159 -0
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.js +304 -0
- package/dist/backend/backend/src/services/knowledge/learnings-index.service.js.map +1 -0
- package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/vector-store.service.js +24 -4
- package/dist/backend/backend/src/services/knowledge/vector-store.service.js.map +1 -1
- package/dist/backend/backend/src/services/mcp-server.d.ts +46 -2
- package/dist/backend/backend/src/services/mcp-server.d.ts.map +1 -1
- package/dist/backend/backend/src/services/mcp-server.js +216 -211
- package/dist/backend/backend/src/services/mcp-server.js.map +1 -1
- package/dist/backend/backend/src/services/mcp-tool-definitions.d.ts +254 -0
- package/dist/backend/backend/src/services/mcp-tool-definitions.d.ts.map +1 -0
- package/dist/backend/backend/src/services/mcp-tool-definitions.js +285 -0
- package/dist/backend/backend/src/services/mcp-tool-definitions.js.map +1 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts +174 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js +375 -0
- package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js.map +1 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts +97 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.js +209 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.js.map +1 -0
- package/dist/backend/backend/src/services/memory/vector-store.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/vector-store.service.js +19 -4
- package/dist/backend/backend/src/services/memory/vector-store.service.js.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.d.ts +16 -5
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.js +32 -5
- package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.js.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding.service.d.ts +157 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.service.js +229 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.service.js.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.d.ts +141 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.js +18 -0
- package/dist/backend/backend/src/services/onboarding/onboarding.types.js.map +1 -0
- package/dist/backend/backend/src/services/pr-review/pr-review.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/pr-review/pr-review.service.js +1 -1
- package/dist/backend/backend/src/services/pr-review/pr-review.service.js.map +1 -1
- package/dist/backend/backend/src/services/project/task.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project/task.service.js +5 -0
- package/dist/backend/backend/src/services/project/task.service.js.map +1 -1
- package/dist/backend/backend/src/services/skill/skill-executor.service.d.ts +41 -0
- package/dist/backend/backend/src/services/skill/skill-executor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/skill/skill-executor.service.js +136 -7
- package/dist/backend/backend/src/services/skill/skill-executor.service.js.map +1 -1
- package/dist/backend/backend/src/services/skill/skill.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/skill/skill.service.js +1 -0
- package/dist/backend/backend/src/services/skill/skill.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/cross-machine-message.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/cross-machine-message.service.js +17 -1
- package/dist/backend/backend/src/services/slack/cross-machine-message.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +39 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +158 -26
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +248 -6
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js +531 -51
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/team-health/index.d.ts +16 -0
- package/dist/backend/backend/src/services/team-health/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/index.js +16 -0
- package/dist/backend/backend/src/services/team-health/index.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.d.ts +52 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js +161 -0
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.d.ts +53 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.js +88 -0
- package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.d.ts +44 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.js +83 -0
- package/dist/backend/backend/src/services/team-health/stale-trigger-detector.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.d.ts +92 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.js +328 -0
- package/dist/backend/backend/src/services/team-health/team-health-alert-router.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.d.ts +41 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.js +213 -0
- package/dist/backend/backend/src/services/team-health/team-health-config.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.d.ts +46 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.js +347 -0
- package/dist/backend/backend/src/services/team-health/team-health-detector.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.d.ts +154 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.js +94 -0
- package/dist/backend/backend/src/services/team-health/team-health-types.js.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.d.ts +111 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.js +226 -0
- package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.js.map +1 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts +148 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.js +545 -0
- package/dist/backend/backend/src/services/v3/mission-reminder.service.js.map +1 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts +499 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +1105 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -0
- package/dist/backend/backend/src/services/v3/request.service.d.ts +22 -0
- package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/request.service.js +71 -0
- package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.d.ts +1 -0
- package/dist/backend/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.js +22 -6
- package/dist/backend/backend/src/services/v3/v3-data.service.js.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.d.ts +19 -1
- package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.js +43 -0
- package/dist/backend/backend/src/types/event-bus.types.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +22 -1
- package/dist/backend/backend/src/types/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/index.js.map +1 -1
- package/dist/backend/backend/src/types/review-reason.types.d.ts +63 -0
- package/dist/backend/backend/src/types/review-reason.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/review-reason.types.js +50 -0
- package/dist/backend/backend/src/types/review-reason.types.js.map +1 -0
- package/dist/backend/backend/src/types/skill.types.d.ts +9 -0
- package/dist/backend/backend/src/types/skill.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/skill.types.js.map +1 -1
- package/dist/backend/backend/src/types/slack.types.d.ts +4 -1
- package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/slack.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/mission.types.d.ts +18 -0
- package/dist/backend/backend/src/types/v2/mission.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/mission.types.js +1 -0
- package/dist/backend/backend/src/types/v2/mission.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.js +25 -1
- package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/backend/backend/src/utils/google-userinfo.utils.d.ts +41 -0
- package/dist/backend/backend/src/utils/google-userinfo.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/google-userinfo.utils.js +44 -0
- package/dist/backend/backend/src/utils/google-userinfo.utils.js.map +1 -0
- package/dist/backend/backend/src/utils/team.utils.d.ts +38 -0
- package/dist/backend/backend/src/utils/team.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/team.utils.js +45 -0
- package/dist/backend/backend/src/utils/team.utils.js.map +1 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.d.ts +195 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.d.ts.map +1 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.js +401 -0
- package/dist/backend/backend/src/websocket/chat-v2.gateway.js.map +1 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +37 -2
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +106 -5
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/cli/backend/src/config/oauth.config.d.ts +33 -0
- package/dist/cli/backend/src/config/oauth.config.d.ts.map +1 -0
- package/dist/cli/backend/src/config/oauth.config.js +45 -0
- package/dist/cli/backend/src/config/oauth.config.js.map +1 -0
- package/dist/cli/backend/src/constants.d.ts +69 -1
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +69 -2
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/core/config.service.js +3 -3
- package/dist/cli/backend/src/services/core/config.service.js.map +1 -1
- package/dist/cli/backend/src/services/core/storage.service.d.ts +7 -0
- package/dist/cli/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/core/storage.service.js +15 -0
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +4 -16
- package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -1
- package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +7 -28
- package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.js +18 -2
- package/dist/cli/backend/src/services/knowledge/fts5-index.service.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts +49 -13
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +123 -29
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js +24 -4
- package/dist/cli/backend/src/services/knowledge/vector-store.service.js.map +1 -1
- package/dist/cli/backend/src/services/mcp-server.d.ts +46 -2
- package/dist/cli/backend/src/services/mcp-server.d.ts.map +1 -1
- package/dist/cli/backend/src/services/mcp-server.js +216 -211
- package/dist/cli/backend/src/services/mcp-server.js.map +1 -1
- package/dist/cli/backend/src/services/mcp-tool-definitions.d.ts +254 -0
- package/dist/cli/backend/src/services/mcp-tool-definitions.d.ts.map +1 -0
- package/dist/cli/backend/src/services/mcp-tool-definitions.js +285 -0
- package/dist/cli/backend/src/services/mcp-tool-definitions.js.map +1 -0
- package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts +18 -0
- package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/skill/skill-executor.service.js +7 -9
- package/dist/cli/backend/src/services/skill/skill-executor.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +22 -1
- package/dist/cli/backend/src/types/index.d.ts.map +1 -1
- package/dist/cli/backend/src/types/index.js.map +1 -1
- package/dist/cli/backend/src/types/skill.types.d.ts +9 -0
- package/dist/cli/backend/src/types/skill.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/skill.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.js +25 -1
- package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/cli/backend/src/utils/google-userinfo.utils.d.ts +41 -0
- package/dist/cli/backend/src/utils/google-userinfo.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/google-userinfo.utils.js +44 -0
- package/dist/cli/backend/src/utils/google-userinfo.utils.js.map +1 -0
- package/frontend/dist/assets/{index-9e6d97d1.js → index-7a4e7df5.js} +328 -326
- package/frontend/dist/assets/index-b7e59b2b.css +33 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +2 -1
- package/config/skills/orchestrator/recall/SKILL.md +0 -47
- package/config/skills/orchestrator/recall/execute.sh +0 -13
- package/config/skills/orchestrator/record-learning/SKILL.md +0 -47
- package/config/skills/orchestrator/record-learning/execute.sh +0 -13
- package/config/skills/orchestrator/remember/SKILL.md +0 -55
- package/config/skills/orchestrator/remember/execute.sh +0 -15
- package/frontend/dist/assets/index-6aaa0630.css +0 -33
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatV2Gateway — native WebSocket gateway for the Phase 1 Chat MVP.
|
|
3
|
+
*
|
|
4
|
+
* Listens on `/ws/chat?channelId=X&token=Y&lastSeenSeq=N` and fans out
|
|
5
|
+
* wire-format frames to subscribers per Sam's tech spec §6 / the frontend
|
|
6
|
+
* contract implemented by Max in `packages/chat-ui/src/api/client.ts`.
|
|
7
|
+
*
|
|
8
|
+
* Wire contract this gateway must honor (enforced by co-located tests):
|
|
9
|
+
* - Client→server: `{type:"ping",ts}` every 25s
|
|
10
|
+
* - Server→client: `{type:"pong",ts}` echo within 10s
|
|
11
|
+
* - Server→client: `{type:"message",payload:{channelId,message:MessageDTO}}`
|
|
12
|
+
* - Server→client: `{type:"presence",payload:{agentSession,status,lastSeenAt?}}`
|
|
13
|
+
* - Server→client: `{type:"error",code,message}` followed by close() on fatal
|
|
14
|
+
*
|
|
15
|
+
* This module is intentionally thin: it does not persist, does not dispatch
|
|
16
|
+
* to agents, and does not manage presence state. The controller/dispatcher
|
|
17
|
+
* call `broadcast()` after the service layer writes to SQLite, so the
|
|
18
|
+
* gateway's only job is routing frames to the right sockets.
|
|
19
|
+
*
|
|
20
|
+
* Upgrade-handoff pattern copied from `BrowserBridgeService.attach()` —
|
|
21
|
+
* Socket.IO's Engine.IO upgrade handler would otherwise corrupt frames on
|
|
22
|
+
* non-`/socket.io/` paths, so we intercept the `upgrade` event on the
|
|
23
|
+
* HTTP server and handle `/ws/chat` exclusively.
|
|
24
|
+
*
|
|
25
|
+
* @module websocket/chat-v2.gateway
|
|
26
|
+
*/
|
|
27
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
28
|
+
import { ChatError, CHAT_ERROR_CODES } from '../services/chat-v2/types.js';
|
|
29
|
+
import { LoggerService } from '../services/core/logger.service.js';
|
|
30
|
+
/** Default WS mount path — matches the frontend `?${qs}` URL in client.ts. */
|
|
31
|
+
export const CHAT_V2_WS_PATH = '/ws/chat';
|
|
32
|
+
/**
|
|
33
|
+
* Always-accept token verifier used when `CREWLY_JWT_SECRET` is not
|
|
34
|
+
* configured. Returns the SAME `userId` that `requireAuth`'s dev
|
|
35
|
+
* fallback uses (`dev-user-001`) so that channels created via the
|
|
36
|
+
* REST API are owned by the same principal the WS client will verify
|
|
37
|
+
* as. Not for production — in production a JWT-verifying `verifyToken`
|
|
38
|
+
* function is passed to `ChatV2Gateway` instead.
|
|
39
|
+
*/
|
|
40
|
+
export const devAnonymousTokenVerifier = async () => ({
|
|
41
|
+
userId: 'dev-user-001',
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
* A WebSocket gateway that fans chat events out to subscribers.
|
|
45
|
+
*
|
|
46
|
+
* Lifecycle:
|
|
47
|
+
* 1. `attach(httpServer)` — hooks the upgrade interceptor
|
|
48
|
+
* 2. `broadcast(channelId, event)` — called by controller after persist
|
|
49
|
+
* 3. `close()` — shutdown hook (graceful close all sockets)
|
|
50
|
+
*
|
|
51
|
+
* The gateway owns the WebSocketServer and the subscribers map. It never
|
|
52
|
+
* reaches into the service layer on its own — all domain data arrives via
|
|
53
|
+
* `broadcast()` from callers who have already persisted.
|
|
54
|
+
*/
|
|
55
|
+
export class ChatV2Gateway {
|
|
56
|
+
service;
|
|
57
|
+
verifyToken;
|
|
58
|
+
path;
|
|
59
|
+
webSocketServerImpl;
|
|
60
|
+
now;
|
|
61
|
+
logger;
|
|
62
|
+
wss = null;
|
|
63
|
+
attached = false;
|
|
64
|
+
/** channelId → set of subscribers listening on that channel. */
|
|
65
|
+
subscribers = new Map();
|
|
66
|
+
constructor(options) {
|
|
67
|
+
this.service = options.service;
|
|
68
|
+
this.verifyToken = options.verifyToken;
|
|
69
|
+
this.path = options.path ?? CHAT_V2_WS_PATH;
|
|
70
|
+
this.webSocketServerImpl = options.webSocketServerImpl ?? WebSocketServer;
|
|
71
|
+
this.now = options.now ?? Date.now;
|
|
72
|
+
this.logger = LoggerService.getInstance().createComponentLogger('ChatV2Gateway');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Mount the gateway on an HTTP server.
|
|
76
|
+
*
|
|
77
|
+
* Uses `noServer:true` + an `httpServer.emit` override identical to
|
|
78
|
+
* `BrowserBridgeService.attach()` — the override exclusively handles
|
|
79
|
+
* upgrades whose pathname matches `this.path`, so Engine.IO never sees
|
|
80
|
+
* them and cannot corrupt the frames.
|
|
81
|
+
*
|
|
82
|
+
* @param httpServer - Shared Node HTTP server instance
|
|
83
|
+
*/
|
|
84
|
+
attach(httpServer) {
|
|
85
|
+
if (this.attached) {
|
|
86
|
+
this.logger.warn('chat-v2 WS gateway already attached');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this.attached = true;
|
|
90
|
+
this.wss = new this.webSocketServerImpl({
|
|
91
|
+
noServer: true,
|
|
92
|
+
perMessageDeflate: false,
|
|
93
|
+
});
|
|
94
|
+
// Two-part installation:
|
|
95
|
+
// 1. Register an explicit `upgrade` listener. This guarantees the
|
|
96
|
+
// event is wired even when we're the ONLY listener (tests, dev
|
|
97
|
+
// standalone — no Socket.IO). In production Socket.IO ALSO
|
|
98
|
+
// listens; both fire, but step 2 keeps them from colliding.
|
|
99
|
+
// 2. Override `httpServer.emit` so that a `/ws/chat` upgrade event
|
|
100
|
+
// is handled exclusively, with no other listeners (Engine.IO's
|
|
101
|
+
// in particular) seeing it. Without this, Engine.IO's 1s
|
|
102
|
+
// socket.end() timer and compression bits would corrupt our
|
|
103
|
+
// frames. Same pattern as `BrowserBridgeService.attach()`.
|
|
104
|
+
const pathMatches = (req) => {
|
|
105
|
+
const url = req.url || '';
|
|
106
|
+
const host = req.headers.host || 'localhost';
|
|
107
|
+
try {
|
|
108
|
+
return new URL(url, `http://${host}`).pathname === this.path;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const performUpgrade = (request, socket, head) => {
|
|
115
|
+
if (!pathMatches(request))
|
|
116
|
+
return;
|
|
117
|
+
this.wss.handleUpgrade(request, socket, head, (ws, req) => {
|
|
118
|
+
this.wss.emit('connection', ws, req);
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
// Register the listener so the 'upgrade' event fires at all (Node's
|
|
122
|
+
// HTTP server routes upgrade requests to the regular request handler
|
|
123
|
+
// when no 'upgrade' listener is registered).
|
|
124
|
+
httpServer.on('upgrade', performUpgrade);
|
|
125
|
+
const originalEmit = httpServer.emit.bind(httpServer);
|
|
126
|
+
httpServer.emit = (event, ...args) => {
|
|
127
|
+
if (event === 'upgrade') {
|
|
128
|
+
const request = args[0];
|
|
129
|
+
if (pathMatches(request)) {
|
|
130
|
+
// Run our upgrade handler exclusively — skip every other
|
|
131
|
+
// listener (Engine.IO's especially) so their post-hooks cannot
|
|
132
|
+
// corrupt our socket.
|
|
133
|
+
performUpgrade(args[0], args[1], args[2]);
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return originalEmit(event, ...args);
|
|
138
|
+
};
|
|
139
|
+
this.wss.on('connection', (ws, req) => {
|
|
140
|
+
// ts-jest in CI sometimes resolves req.url as undefined when the
|
|
141
|
+
// upgrade interceptor is exercised from a test — guard both.
|
|
142
|
+
void this.handleConnection(ws, req);
|
|
143
|
+
});
|
|
144
|
+
this.wss.on('error', (err) => {
|
|
145
|
+
this.logger.error('WS server error', { error: err.message });
|
|
146
|
+
});
|
|
147
|
+
this.logger.info('chat-v2 WS gateway attached', { path: this.path });
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Broadcast a wire event to every subscriber on `channelId`.
|
|
151
|
+
*
|
|
152
|
+
* Safe to call synchronously from inside a DB transaction — sends are
|
|
153
|
+
* queued on the underlying socket and do not block.
|
|
154
|
+
*
|
|
155
|
+
* @param channelId - Target channel
|
|
156
|
+
* @param event - Wire frame to push
|
|
157
|
+
*/
|
|
158
|
+
broadcast(channelId, event) {
|
|
159
|
+
const set = this.subscribers.get(channelId);
|
|
160
|
+
if (!set || set.size === 0)
|
|
161
|
+
return;
|
|
162
|
+
const frame = JSON.stringify(event);
|
|
163
|
+
for (const sub of set) {
|
|
164
|
+
if (sub.ws.readyState !== WebSocket.OPEN)
|
|
165
|
+
continue;
|
|
166
|
+
try {
|
|
167
|
+
sub.ws.send(frame);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
this.logger.warn('chat-v2 ws send failed', {
|
|
171
|
+
channelId,
|
|
172
|
+
err: err instanceof Error ? err.message : String(err),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Count of currently-open subscribers for a channel. Exposed for tests
|
|
179
|
+
* and future observability dashboards.
|
|
180
|
+
*/
|
|
181
|
+
subscriberCount(channelId) {
|
|
182
|
+
return this.subscribers.get(channelId)?.size ?? 0;
|
|
183
|
+
}
|
|
184
|
+
/** Total open sockets across all channels. Observability helper. */
|
|
185
|
+
totalSubscribers() {
|
|
186
|
+
let n = 0;
|
|
187
|
+
for (const set of this.subscribers.values())
|
|
188
|
+
n += set.size;
|
|
189
|
+
return n;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Gracefully close all sockets. Called during shutdown.
|
|
193
|
+
*/
|
|
194
|
+
async close() {
|
|
195
|
+
if (!this.wss)
|
|
196
|
+
return;
|
|
197
|
+
for (const set of this.subscribers.values()) {
|
|
198
|
+
for (const sub of set) {
|
|
199
|
+
try {
|
|
200
|
+
sub.ws.close(1001, 'server shutdown');
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// ignore
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
this.subscribers.clear();
|
|
208
|
+
await new Promise((resolve) => {
|
|
209
|
+
this.wss.close(() => resolve());
|
|
210
|
+
});
|
|
211
|
+
this.wss = null;
|
|
212
|
+
}
|
|
213
|
+
// -------------------------------------------------------------------------
|
|
214
|
+
// Connection lifecycle
|
|
215
|
+
// -------------------------------------------------------------------------
|
|
216
|
+
/**
|
|
217
|
+
* Handle a freshly-upgraded socket: parse query string, verify token,
|
|
218
|
+
* authorize against the channel, and register the subscriber.
|
|
219
|
+
*
|
|
220
|
+
* On any failure we send a single `{type:"error",...}` frame and close
|
|
221
|
+
* with a 1008 (policy violation) code — matching the frontend's
|
|
222
|
+
* "fatal, stop reconnecting" contract.
|
|
223
|
+
*/
|
|
224
|
+
async handleConnection(ws, req) {
|
|
225
|
+
const host = req.headers.host || 'localhost';
|
|
226
|
+
let parsed;
|
|
227
|
+
try {
|
|
228
|
+
parsed = new URL(req.url ?? '', `http://${host}`);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
this.sendErrorAndClose(ws, 'bad_request', 'malformed URL');
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const channelId = parsed.searchParams.get('channelId');
|
|
235
|
+
const token = parsed.searchParams.get('token');
|
|
236
|
+
// lastSeenSeq is accepted but not yet acted on (Phase 1.5 replay).
|
|
237
|
+
// Parsing validates that callers send a number if they send it at all.
|
|
238
|
+
const lastSeenSeqRaw = parsed.searchParams.get('lastSeenSeq');
|
|
239
|
+
if (lastSeenSeqRaw !== null && !/^\d+$/.test(lastSeenSeqRaw)) {
|
|
240
|
+
this.sendErrorAndClose(ws, 'bad_request', 'lastSeenSeq must be a non-negative integer');
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!channelId) {
|
|
244
|
+
this.sendErrorAndClose(ws, 'bad_request', 'channelId is required');
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
let identity;
|
|
248
|
+
try {
|
|
249
|
+
identity = await this.verifyToken(token);
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
this.logger.warn('chat-v2 ws token verify threw', {
|
|
253
|
+
err: err instanceof Error ? err.message : String(err),
|
|
254
|
+
});
|
|
255
|
+
this.sendErrorAndClose(ws, 'unauthorized', 'token verification failed');
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (!identity) {
|
|
259
|
+
this.sendErrorAndClose(ws, 'unauthorized', 'invalid token');
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
// Authorize: the channel must exist AND be owned by this user (or —
|
|
263
|
+
// in a later iteration — be readable by the agent identified here).
|
|
264
|
+
try {
|
|
265
|
+
this.service.getChannel(channelId, { userId: identity.userId, source: 'oss' });
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
if (err instanceof ChatError && err.code === CHAT_ERROR_CODES.CHANNEL_NOT_FOUND) {
|
|
269
|
+
// 404 leaks less than 403 for ownership checks (consistent with §7.2)
|
|
270
|
+
this.sendErrorAndClose(ws, 'channel_not_found', 'channel not found');
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
this.sendErrorAndClose(ws, 'internal_error', 'authorization failed');
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const subscriber = {
|
|
277
|
+
ws,
|
|
278
|
+
channelId,
|
|
279
|
+
userId: identity.userId,
|
|
280
|
+
connectedAt: this.now(),
|
|
281
|
+
};
|
|
282
|
+
this.registerSubscriber(subscriber);
|
|
283
|
+
ws.on('message', (data) => this.handleMessage(subscriber, data));
|
|
284
|
+
ws.on('close', () => this.unregisterSubscriber(subscriber));
|
|
285
|
+
ws.on('error', (err) => {
|
|
286
|
+
this.logger.warn('chat-v2 ws socket error', {
|
|
287
|
+
channelId: subscriber.channelId,
|
|
288
|
+
err: err.message,
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
this.logger.debug('chat-v2 ws connection established', {
|
|
292
|
+
channelId,
|
|
293
|
+
userId: identity.userId,
|
|
294
|
+
total: this.totalSubscribers(),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
// -------------------------------------------------------------------------
|
|
298
|
+
// Message routing
|
|
299
|
+
// -------------------------------------------------------------------------
|
|
300
|
+
/**
|
|
301
|
+
* Handle a frame from the client.
|
|
302
|
+
*
|
|
303
|
+
* Phase 1 only understands `{type:"ping",ts}`; any other shape is
|
|
304
|
+
* silently dropped (forward-compat with future client-origin frames).
|
|
305
|
+
*/
|
|
306
|
+
handleMessage(sub, raw) {
|
|
307
|
+
let parsed = null;
|
|
308
|
+
try {
|
|
309
|
+
const text = typeof raw === 'string' ? raw : Buffer.isBuffer(raw) ? raw.toString('utf-8') : String(raw);
|
|
310
|
+
const obj = JSON.parse(text);
|
|
311
|
+
if (obj && obj.type === 'ping') {
|
|
312
|
+
const ts = typeof obj.ts === 'number' ? obj.ts : this.now();
|
|
313
|
+
parsed = { type: 'ping', ts };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// malformed frame — drop
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (!parsed)
|
|
321
|
+
return;
|
|
322
|
+
// Echo pong with the client's own ts — the client uses the round-trip
|
|
323
|
+
// for its 10s timeout, not strict clock agreement.
|
|
324
|
+
const pong = { type: 'pong', ts: parsed.ts };
|
|
325
|
+
if (sub.ws.readyState === WebSocket.OPEN) {
|
|
326
|
+
try {
|
|
327
|
+
sub.ws.send(JSON.stringify(pong));
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
// ignore — the socket will close and the close handler cleans up
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// -------------------------------------------------------------------------
|
|
335
|
+
// Subscriber bookkeeping
|
|
336
|
+
// -------------------------------------------------------------------------
|
|
337
|
+
registerSubscriber(sub) {
|
|
338
|
+
let set = this.subscribers.get(sub.channelId);
|
|
339
|
+
if (!set) {
|
|
340
|
+
set = new Set();
|
|
341
|
+
this.subscribers.set(sub.channelId, set);
|
|
342
|
+
}
|
|
343
|
+
set.add(sub);
|
|
344
|
+
}
|
|
345
|
+
unregisterSubscriber(sub) {
|
|
346
|
+
const set = this.subscribers.get(sub.channelId);
|
|
347
|
+
if (!set)
|
|
348
|
+
return;
|
|
349
|
+
set.delete(sub);
|
|
350
|
+
if (set.size === 0)
|
|
351
|
+
this.subscribers.delete(sub.channelId);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Send an error frame then close with 1008. Used for all pre-subscribe
|
|
355
|
+
* rejections (auth, malformed URL, missing channelId, not-found).
|
|
356
|
+
*/
|
|
357
|
+
sendErrorAndClose(ws, code, message) {
|
|
358
|
+
try {
|
|
359
|
+
if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
|
|
360
|
+
ws.send(JSON.stringify({ type: 'error', code, message }));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
// ignore
|
|
365
|
+
}
|
|
366
|
+
try {
|
|
367
|
+
ws.close(1008, code);
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
// ignore
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
// Channel presence broadcast helper (future — not wired in Phase 1)
|
|
376
|
+
// ---------------------------------------------------------------------------
|
|
377
|
+
/**
|
|
378
|
+
* Build a presence wire frame. Placed here so both the gateway's tests and
|
|
379
|
+
* future presence emitters use the same shape.
|
|
380
|
+
*
|
|
381
|
+
* @param agentSession - The agent whose presence changed
|
|
382
|
+
* @param status - New status
|
|
383
|
+
* @param lastSeenAt - Optional last-seen timestamp (ms)
|
|
384
|
+
*/
|
|
385
|
+
export function buildPresenceEvent(agentSession, status, lastSeenAt) {
|
|
386
|
+
return {
|
|
387
|
+
type: 'presence',
|
|
388
|
+
payload: { agentSession, status, lastSeenAt: lastSeenAt ?? null },
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Build a message wire frame from a DTO. Used by both the controller (on
|
|
393
|
+
* HTTP persist) and the dispatcher (on agent reply).
|
|
394
|
+
*/
|
|
395
|
+
export function buildMessageEvent(channelId, message) {
|
|
396
|
+
return {
|
|
397
|
+
type: 'message',
|
|
398
|
+
payload: { channelId, message },
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=chat-v2.gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.gateway.js","sourceRoot":"","sources":["../../../../../backend/src/websocket/chat-v2.gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,14 @@ export declare class TerminalGateway {
|
|
|
28
28
|
private sessionSubscriptions;
|
|
29
29
|
/** Set of sessions with persistent monitoring (not stopped on client disconnect) */
|
|
30
30
|
private persistentMonitoringSessions;
|
|
31
|
+
/**
|
|
32
|
+
* Pending retry timers for eager monitoring attempts that fired before the
|
|
33
|
+
* PTY session was registered in the SessionBackend.
|
|
34
|
+
*
|
|
35
|
+
* Keyed by session name. Cleared on first successful attach, on stop, and
|
|
36
|
+
* on destroy so a backoff schedule never leaks a timer past the gateway.
|
|
37
|
+
*/
|
|
38
|
+
private pendingMonitoringRetries;
|
|
31
39
|
/** Current active chat conversation ID for orchestrator responses */
|
|
32
40
|
private activeConversationId;
|
|
33
41
|
/**
|
|
@@ -106,15 +114,42 @@ export declare class TerminalGateway {
|
|
|
106
114
|
private stopPtyStreaming;
|
|
107
115
|
/**
|
|
108
116
|
* Start persistent monitoring for the orchestrator session.
|
|
109
|
-
*
|
|
117
|
+
*
|
|
118
|
+
* Ensures chat responses are captured even when no WebSocket clients are
|
|
119
|
+
* viewing the terminal. If the PTY session is not yet registered in the
|
|
120
|
+
* SessionBackend (e.g. eager call from boot fires before
|
|
121
|
+
* createAgentSession's backend registration completes), schedules bounded
|
|
122
|
+
* retries on the {@link TERMINAL_GATEWAY_CONSTANTS.MONITORING_RETRY_BACKOFFS_MS}
|
|
123
|
+
* backoff schedule. Persistent flag stays set across retries so a parallel
|
|
124
|
+
* subscriber path doesn't bypass eventual attachment.
|
|
110
125
|
*
|
|
111
126
|
* @param sessionName - The orchestrator session name to monitor
|
|
112
|
-
* @returns True if monitoring started
|
|
127
|
+
* @returns True if monitoring started synchronously on first attempt; false
|
|
128
|
+
* if a retry was scheduled (caller-visible failure is reserved for
|
|
129
|
+
* terminal failure after all retries, surfaced via ERROR log only).
|
|
113
130
|
*/
|
|
114
131
|
startOrchestratorChatMonitoring(sessionName: string): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Schedule the next bounded retry attempt to attach orchestrator monitoring.
|
|
134
|
+
*
|
|
135
|
+
* @param sessionName - Session name being monitored
|
|
136
|
+
* @param attemptIndex - 0-based index into MONITORING_RETRY_BACKOFFS_MS
|
|
137
|
+
*/
|
|
138
|
+
private scheduleMonitoringRetry;
|
|
139
|
+
/**
|
|
140
|
+
* Clear any pending monitoring retry timer for a session.
|
|
141
|
+
*
|
|
142
|
+
* Idempotent — safe to call when no retry is queued.
|
|
143
|
+
*
|
|
144
|
+
* @param sessionName - Session name whose retry should be cleared
|
|
145
|
+
*/
|
|
146
|
+
private clearPendingMonitoringRetry;
|
|
115
147
|
/**
|
|
116
148
|
* Stop persistent monitoring for the orchestrator session.
|
|
117
149
|
*
|
|
150
|
+
* Cancels any in-flight retry schedule so a stop mid-backoff doesn't leak
|
|
151
|
+
* a timer that later attaches to a session the caller already gave up on.
|
|
152
|
+
*
|
|
118
153
|
* @param sessionName - The orchestrator session name
|
|
119
154
|
*/
|
|
120
155
|
stopOrchestratorChatMonitoring(sessionName: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.gateway.d.ts","sourceRoot":"","sources":["../../../../../backend/src/websocket/terminal.gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAY7D;;;;;;;;GAQG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,MAAM,CAAkB;IAEhC,0DAA0D;IAC1D,OAAO,CAAC,gBAAgB,CAAuC;IAE/D,iEAAiE;IACjE,OAAO,CAAC,oBAAoB,CAAsC;IAElE,oFAAoF;IACpF,OAAO,CAAC,4BAA4B,CAA0B;IAE9D,qEAAqE;IACrE,OAAO,CAAC,oBAAoB,CAAuB;IAEnD;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAqB;IAE7C;;;OAGG;IACH,OAAO,CAAC,0BAA0B,CAAqB;IAEvD;;;OAGG;IACH,OAAO,CAAC,oBAAoB,CAAuE;IAEnG;;;;OAIG;gBACS,EAAE,EAAE,cAAc;IAQ9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA+C1B;;;;;OAKG;IACH,OAAO,CAAC,0BAA0B;IA6BlC;;;;;OAKG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIhD;;;;;OAKG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAiD7D;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAiEzB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAgBxB
|
|
1
|
+
{"version":3,"file":"terminal.gateway.d.ts","sourceRoot":"","sources":["../../../../../backend/src/websocket/terminal.gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { LoggerService } from '../services/core/logger.service.js';
|
|
13
13
|
import { getSessionBackendSync, } from '../services/session/index.js';
|
|
14
|
+
import { TERMINAL_GATEWAY_CONSTANTS } from '../constants.js';
|
|
14
15
|
import { InProcessLogBuffer } from '../services/agent/crewly-agent/in-process-log-buffer.js';
|
|
15
16
|
/**
|
|
16
17
|
* Terminal Gateway class for WebSocket-based terminal streaming.
|
|
@@ -30,6 +31,14 @@ export class TerminalGateway {
|
|
|
30
31
|
sessionSubscriptions = new Map();
|
|
31
32
|
/** Set of sessions with persistent monitoring (not stopped on client disconnect) */
|
|
32
33
|
persistentMonitoringSessions = new Set();
|
|
34
|
+
/**
|
|
35
|
+
* Pending retry timers for eager monitoring attempts that fired before the
|
|
36
|
+
* PTY session was registered in the SessionBackend.
|
|
37
|
+
*
|
|
38
|
+
* Keyed by session name. Cleared on first successful attach, on stop, and
|
|
39
|
+
* on destroy so a backoff schedule never leaks a timer past the gateway.
|
|
40
|
+
*/
|
|
41
|
+
pendingMonitoringRetries = new Map();
|
|
33
42
|
/** Current active chat conversation ID for orchestrator responses */
|
|
34
43
|
activeConversationId = null;
|
|
35
44
|
/**
|
|
@@ -297,13 +306,25 @@ export class TerminalGateway {
|
|
|
297
306
|
}
|
|
298
307
|
/**
|
|
299
308
|
* Start persistent monitoring for the orchestrator session.
|
|
300
|
-
*
|
|
309
|
+
*
|
|
310
|
+
* Ensures chat responses are captured even when no WebSocket clients are
|
|
311
|
+
* viewing the terminal. If the PTY session is not yet registered in the
|
|
312
|
+
* SessionBackend (e.g. eager call from boot fires before
|
|
313
|
+
* createAgentSession's backend registration completes), schedules bounded
|
|
314
|
+
* retries on the {@link TERMINAL_GATEWAY_CONSTANTS.MONITORING_RETRY_BACKOFFS_MS}
|
|
315
|
+
* backoff schedule. Persistent flag stays set across retries so a parallel
|
|
316
|
+
* subscriber path doesn't bypass eventual attachment.
|
|
301
317
|
*
|
|
302
318
|
* @param sessionName - The orchestrator session name to monitor
|
|
303
|
-
* @returns True if monitoring started
|
|
319
|
+
* @returns True if monitoring started synchronously on first attempt; false
|
|
320
|
+
* if a retry was scheduled (caller-visible failure is reserved for
|
|
321
|
+
* terminal failure after all retries, surfaced via ERROR log only).
|
|
304
322
|
*/
|
|
305
323
|
startOrchestratorChatMonitoring(sessionName) {
|
|
306
324
|
this.logger.info('Starting persistent orchestrator chat monitoring', { sessionName });
|
|
325
|
+
// Cancel any in-flight retry from a previous start call so we don't
|
|
326
|
+
// stack two backoff schedules on the same session.
|
|
327
|
+
this.clearPendingMonitoringRetry(sessionName);
|
|
307
328
|
// Force cleanup any stale subscription from a previous session.
|
|
308
329
|
// When the orchestrator is restarted, the old PTY session is destroyed but
|
|
309
330
|
// the subscription entry may still exist pointing to the dead session.
|
|
@@ -317,19 +338,92 @@ export class TerminalGateway {
|
|
|
317
338
|
// Mark session as persistent so it won't be stopped when clients disconnect
|
|
318
339
|
this.persistentMonitoringSessions.add(sessionName);
|
|
319
340
|
const started = this.startPtyStreaming(sessionName);
|
|
320
|
-
if (
|
|
321
|
-
|
|
341
|
+
if (started) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
// Backend hasn't registered the session yet (race with createAgentSession).
|
|
345
|
+
// Keep persistentMonitoringSessions flagged and schedule bounded retries.
|
|
346
|
+
this.logger.warn('PTY not ready for orchestrator chat monitoring, scheduling retries', { sessionName, schedule: TERMINAL_GATEWAY_CONSTANTS.MONITORING_RETRY_BACKOFFS_MS });
|
|
347
|
+
this.scheduleMonitoringRetry(sessionName, 0);
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Schedule the next bounded retry attempt to attach orchestrator monitoring.
|
|
352
|
+
*
|
|
353
|
+
* @param sessionName - Session name being monitored
|
|
354
|
+
* @param attemptIndex - 0-based index into MONITORING_RETRY_BACKOFFS_MS
|
|
355
|
+
*/
|
|
356
|
+
scheduleMonitoringRetry(sessionName, attemptIndex) {
|
|
357
|
+
const schedule = TERMINAL_GATEWAY_CONSTANTS.MONITORING_RETRY_BACKOFFS_MS;
|
|
358
|
+
if (attemptIndex >= schedule.length) {
|
|
359
|
+
// Exhausted retries — log diagnostics and give up. Drop the
|
|
360
|
+
// persistent flag so a subsequent subscriber-driven attach can
|
|
361
|
+
// still proceed via the normal subscribeToSession path.
|
|
362
|
+
const backend = getSessionBackendSync();
|
|
363
|
+
this.logger.error('Orchestrator chat monitoring failed after all retries — orc output will not stream until a client subscribes', {
|
|
364
|
+
sessionName,
|
|
365
|
+
attempts: schedule.length,
|
|
366
|
+
availableSessions: backend?.listSessions() ?? [],
|
|
367
|
+
});
|
|
322
368
|
this.persistentMonitoringSessions.delete(sessionName);
|
|
369
|
+
this.pendingMonitoringRetries.delete(sessionName);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const delayMs = schedule[attemptIndex];
|
|
373
|
+
const timer = setTimeout(() => {
|
|
374
|
+
this.pendingMonitoringRetries.delete(sessionName);
|
|
375
|
+
// Stop guard: the persistent flag is cleared by
|
|
376
|
+
// stopOrchestratorChatMonitoring. If it's gone, abandon retry.
|
|
377
|
+
if (!this.persistentMonitoringSessions.has(sessionName)) {
|
|
378
|
+
this.logger.debug('Monitoring retry abandoned — persistent flag cleared', {
|
|
379
|
+
sessionName,
|
|
380
|
+
attemptIndex,
|
|
381
|
+
});
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const started = this.startPtyStreaming(sessionName);
|
|
385
|
+
if (started) {
|
|
386
|
+
this.logger.info('Orchestrator chat monitoring attached on retry', {
|
|
387
|
+
sessionName,
|
|
388
|
+
attemptIndex: attemptIndex + 1,
|
|
389
|
+
delayMs,
|
|
390
|
+
});
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
this.scheduleMonitoringRetry(sessionName, attemptIndex + 1);
|
|
394
|
+
}, delayMs);
|
|
395
|
+
// Allow the process to exit even if a retry is still pending.
|
|
396
|
+
// Without unref, lingering timers keep node alive past graceful shutdown.
|
|
397
|
+
if (typeof timer.unref === 'function') {
|
|
398
|
+
timer.unref();
|
|
399
|
+
}
|
|
400
|
+
this.pendingMonitoringRetries.set(sessionName, timer);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Clear any pending monitoring retry timer for a session.
|
|
404
|
+
*
|
|
405
|
+
* Idempotent — safe to call when no retry is queued.
|
|
406
|
+
*
|
|
407
|
+
* @param sessionName - Session name whose retry should be cleared
|
|
408
|
+
*/
|
|
409
|
+
clearPendingMonitoringRetry(sessionName) {
|
|
410
|
+
const timer = this.pendingMonitoringRetries.get(sessionName);
|
|
411
|
+
if (timer) {
|
|
412
|
+
clearTimeout(timer);
|
|
413
|
+
this.pendingMonitoringRetries.delete(sessionName);
|
|
323
414
|
}
|
|
324
|
-
return started;
|
|
325
415
|
}
|
|
326
416
|
/**
|
|
327
417
|
* Stop persistent monitoring for the orchestrator session.
|
|
328
418
|
*
|
|
419
|
+
* Cancels any in-flight retry schedule so a stop mid-backoff doesn't leak
|
|
420
|
+
* a timer that later attaches to a session the caller already gave up on.
|
|
421
|
+
*
|
|
329
422
|
* @param sessionName - The orchestrator session name
|
|
330
423
|
*/
|
|
331
424
|
stopOrchestratorChatMonitoring(sessionName) {
|
|
332
425
|
this.logger.info('Stopping persistent orchestrator chat monitoring', { sessionName });
|
|
426
|
+
this.clearPendingMonitoringRetry(sessionName);
|
|
333
427
|
this.stopPtyStreaming(sessionName, true);
|
|
334
428
|
}
|
|
335
429
|
/**
|
|
@@ -778,6 +872,13 @@ export class TerminalGateway {
|
|
|
778
872
|
* Destroy the gateway and clean up all subscriptions.
|
|
779
873
|
*/
|
|
780
874
|
destroy() {
|
|
875
|
+
// Cancel any pending monitoring retries before tearing down.
|
|
876
|
+
// Otherwise a queued retry could fire after destroy and attach
|
|
877
|
+
// a listener to a session whose owner has gone away.
|
|
878
|
+
for (const timer of this.pendingMonitoringRetries.values()) {
|
|
879
|
+
clearTimeout(timer);
|
|
880
|
+
}
|
|
881
|
+
this.pendingMonitoringRetries.clear();
|
|
781
882
|
// Unsubscribe from all PTY sessions
|
|
782
883
|
for (const unsubscribe of this.sessionSubscriptions.values()) {
|
|
783
884
|
unsubscribe();
|