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,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatV2DispatcherService — deliver user-origin chat messages to the
|
|
3
|
+
* bound agent session.
|
|
4
|
+
*
|
|
5
|
+
* Flow:
|
|
6
|
+
* HTTP POST /api/chat/channels/:id/messages
|
|
7
|
+
* → ChatV2Service.sendMessage (persist + dedupe)
|
|
8
|
+
* → controller broadcasts WS message frame (user bubble)
|
|
9
|
+
* → controller calls ChatV2Dispatcher.dispatchToAgent(channel, messageDTO)
|
|
10
|
+
* → sendMessageToAgent(agent_session, "[CHAT:<id>] <content>\n<hint>")
|
|
11
|
+
* → agent processes + calls `reply-channel` skill
|
|
12
|
+
* → skill POSTs back to /api/chat/channels/:id/messages as the agent
|
|
13
|
+
* → same controller path → WS message frame (agent bubble)
|
|
14
|
+
*
|
|
15
|
+
* This service is intentionally thin — a couple of dozen lines of glue
|
|
16
|
+
* around the AgentRegistrationService's `sendMessageToAgent` primitive.
|
|
17
|
+
* The dispatch prompt is extracted so tests can assert the format, which
|
|
18
|
+
* is the contract the `reply-channel` skill relies on.
|
|
19
|
+
*
|
|
20
|
+
* @module services/chat-v2/chat-v2.dispatcher.service
|
|
21
|
+
*/
|
|
22
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Prompt formatter
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Default prompt formatter the agent sees when a user sends in their
|
|
28
|
+
* chat channel.
|
|
29
|
+
*
|
|
30
|
+
* Format is intentionally stable and tag-prefixed so the `reply-channel`
|
|
31
|
+
* skill (and future tooling) can reliably extract the channelId without
|
|
32
|
+
* regex ambiguity. The `回复:` hint line gives the agent a one-step
|
|
33
|
+
* instruction on how to reply.
|
|
34
|
+
*/
|
|
35
|
+
export function defaultFormatPrompt(args) {
|
|
36
|
+
const { channelId, channelName, senderId, content, clientMessageId } = args;
|
|
37
|
+
const trimmed = content.trim();
|
|
38
|
+
const idHint = clientMessageId ? ` [cmid:${clientMessageId}]` : '';
|
|
39
|
+
return [
|
|
40
|
+
`[CHAT:${channelId}]${idHint} <${senderId}@${channelName}>`,
|
|
41
|
+
``,
|
|
42
|
+
trimmed,
|
|
43
|
+
``,
|
|
44
|
+
`---`,
|
|
45
|
+
`回复本频道: 用 \`reply-channel\` skill, 参数 channelId="${channelId}"、content="<your reply>"。`,
|
|
46
|
+
].join('\n');
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Service
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
/**
|
|
52
|
+
* Dispatches user-origin chat messages to the agent session bound to the
|
|
53
|
+
* channel. Invoked from the chat controller after `ChatV2Service.sendMessage`
|
|
54
|
+
* returns.
|
|
55
|
+
*/
|
|
56
|
+
export class ChatV2DispatcherService {
|
|
57
|
+
agentSink;
|
|
58
|
+
formatPrompt;
|
|
59
|
+
mentionResolver;
|
|
60
|
+
logger;
|
|
61
|
+
constructor(options) {
|
|
62
|
+
this.agentSink = options.agentSink;
|
|
63
|
+
this.formatPrompt = options.formatPrompt ?? defaultFormatPrompt;
|
|
64
|
+
this.mentionResolver = options.mentionResolver;
|
|
65
|
+
this.logger = LoggerService.getInstance().createComponentLogger('ChatV2Dispatcher');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Phase C BE.3 entry point — choose the routing strategy from
|
|
69
|
+
* `channel.type` and the message's mentions, then fan out.
|
|
70
|
+
*
|
|
71
|
+
* Routing rules (SEALED §2.1):
|
|
72
|
+
* - `type='dm'` → existing 1:1 path via `dispatchToAgent`. Mentions
|
|
73
|
+
* in DMs are advisory only (the channel already binds to one
|
|
74
|
+
* agent); the dispatcher does not currently re-route them.
|
|
75
|
+
* - `type='channel'` → resolve `message.mentions` via the injected
|
|
76
|
+
* `mentionResolver`, then dispatch the formatted prompt to each
|
|
77
|
+
* resolved sessionName. No mentions → no dispatch (the message
|
|
78
|
+
* still persists; nobody is paged).
|
|
79
|
+
* - Agent-origin messages always skip dispatch (no self-loopback).
|
|
80
|
+
*
|
|
81
|
+
* Always resolves; per-recipient errors are captured in
|
|
82
|
+
* {@link DispatchMessageResult.mentionOutcomes} and never thrown.
|
|
83
|
+
*
|
|
84
|
+
* @param channel - The channel DTO (provides `type`, name, agentSession).
|
|
85
|
+
* @param message - The persisted message DTO (provides senderType, mentions).
|
|
86
|
+
* @returns Aggregate result describing the strategy + outcomes.
|
|
87
|
+
*/
|
|
88
|
+
async dispatchMessage(channel, message) {
|
|
89
|
+
if (message.senderType !== 'user') {
|
|
90
|
+
return {
|
|
91
|
+
strategy: 'skip',
|
|
92
|
+
dispatched: false,
|
|
93
|
+
reason: 'not a user-origin message',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (channel.type === 'channel') {
|
|
97
|
+
return this.dispatchChannelMentions(channel, message);
|
|
98
|
+
}
|
|
99
|
+
// Default to the DM path for any other type (including legacy /
|
|
100
|
+
// missing — `type` is non-null after Phase A migration but defensive
|
|
101
|
+
// here keeps the dispatcher robust).
|
|
102
|
+
const dmResult = await this.dispatchToAgent(channel, message);
|
|
103
|
+
return {
|
|
104
|
+
strategy: 'dm',
|
|
105
|
+
dispatched: dmResult.dispatched,
|
|
106
|
+
dmResult,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Dispatch a `type='channel'` message to its resolved mentions.
|
|
111
|
+
*
|
|
112
|
+
* Skips entirely when:
|
|
113
|
+
* - No mention resolver is wired (return strategy=skip).
|
|
114
|
+
* - `mentions` is empty (return strategy=skip).
|
|
115
|
+
* - The resolver returns no targets (return strategy=channel-mentions
|
|
116
|
+
* with empty `mentionOutcomes`; `dispatched=false`).
|
|
117
|
+
*
|
|
118
|
+
* @param channel - The team channel.
|
|
119
|
+
* @param message - The persisted user message.
|
|
120
|
+
* @returns Aggregate result with one outcome per resolved recipient.
|
|
121
|
+
*/
|
|
122
|
+
async dispatchChannelMentions(channel, message) {
|
|
123
|
+
if (!this.mentionResolver) {
|
|
124
|
+
this.logger.debug('chat-v2 dispatch skipped — no mention resolver wired', {
|
|
125
|
+
channelId: channel.id,
|
|
126
|
+
messageId: message.id,
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
strategy: 'skip',
|
|
130
|
+
dispatched: false,
|
|
131
|
+
reason: 'no mention resolver wired for type=channel',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const mentions = Array.isArray(message.mentions) ? message.mentions : [];
|
|
135
|
+
if (mentions.length === 0) {
|
|
136
|
+
return {
|
|
137
|
+
strategy: 'skip',
|
|
138
|
+
dispatched: false,
|
|
139
|
+
reason: 'no mentions on type=channel message',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const ctx = { teamId: channel.teamId };
|
|
143
|
+
const targets = await this.mentionResolver.resolve(mentions, ctx);
|
|
144
|
+
const outcomes = [];
|
|
145
|
+
let anyDispatched = false;
|
|
146
|
+
for (const target of targets) {
|
|
147
|
+
const prompt = this.formatPrompt({
|
|
148
|
+
channelId: channel.id,
|
|
149
|
+
channelName: channel.name,
|
|
150
|
+
agentSession: target.sessionName,
|
|
151
|
+
senderId: message.senderId,
|
|
152
|
+
content: message.content,
|
|
153
|
+
clientMessageId: typeof message.metadata?.clientMessageId === 'string'
|
|
154
|
+
? message.metadata.clientMessageId
|
|
155
|
+
: undefined,
|
|
156
|
+
});
|
|
157
|
+
try {
|
|
158
|
+
const result = await this.agentSink.sendMessageToAgent(target.sessionName, prompt);
|
|
159
|
+
if (result.success) {
|
|
160
|
+
outcomes.push({ target, dispatched: true });
|
|
161
|
+
anyDispatched = true;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
this.logger.warn('chat-v2 mention dispatch reported failure', {
|
|
165
|
+
channelId: channel.id,
|
|
166
|
+
sessionName: target.sessionName,
|
|
167
|
+
err: result.error,
|
|
168
|
+
});
|
|
169
|
+
outcomes.push({
|
|
170
|
+
target,
|
|
171
|
+
dispatched: false,
|
|
172
|
+
error: result.error ?? 'unknown sink failure',
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
178
|
+
this.logger.error('chat-v2 mention dispatch threw', {
|
|
179
|
+
channelId: channel.id,
|
|
180
|
+
sessionName: target.sessionName,
|
|
181
|
+
err: errMsg,
|
|
182
|
+
});
|
|
183
|
+
outcomes.push({ target, dispatched: false, error: errMsg });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
strategy: 'channel-mentions',
|
|
188
|
+
dispatched: anyDispatched,
|
|
189
|
+
mentionOutcomes: outcomes,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Push a newly-persisted user message to the agent.
|
|
194
|
+
*
|
|
195
|
+
* Dispatch is fire-and-forget at the API-response level (the HTTP 201 has
|
|
196
|
+
* already been serialized), but we still await the write so tests can
|
|
197
|
+
* observe the outcome and the logger can record failures.
|
|
198
|
+
*
|
|
199
|
+
* Messages where `senderType !== "user"` are a no-op — we never loop an
|
|
200
|
+
* agent's own reply back into its own PTY.
|
|
201
|
+
*
|
|
202
|
+
* @param channel - Channel DTO (provides `agentSession` + display name)
|
|
203
|
+
* @param message - Persisted message DTO
|
|
204
|
+
*/
|
|
205
|
+
async dispatchToAgent(channel, message) {
|
|
206
|
+
if (message.senderType !== 'user') {
|
|
207
|
+
return { dispatched: false, error: 'not a user-origin message' };
|
|
208
|
+
}
|
|
209
|
+
if (!channel.agentSession) {
|
|
210
|
+
this.logger.warn('chat-v2 dispatch skipped — no agentSession', {
|
|
211
|
+
channelId: channel.id,
|
|
212
|
+
});
|
|
213
|
+
return { dispatched: false, error: 'channel has no bound agent' };
|
|
214
|
+
}
|
|
215
|
+
const prompt = this.formatPrompt({
|
|
216
|
+
channelId: channel.id,
|
|
217
|
+
channelName: channel.name,
|
|
218
|
+
agentSession: channel.agentSession,
|
|
219
|
+
senderId: message.senderId,
|
|
220
|
+
content: message.content,
|
|
221
|
+
clientMessageId: typeof message.metadata?.clientMessageId === 'string'
|
|
222
|
+
? message.metadata.clientMessageId
|
|
223
|
+
: undefined,
|
|
224
|
+
});
|
|
225
|
+
let result;
|
|
226
|
+
try {
|
|
227
|
+
result = await this.agentSink.sendMessageToAgent(channel.agentSession, prompt);
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
231
|
+
this.logger.error('chat-v2 dispatch threw', {
|
|
232
|
+
channelId: channel.id,
|
|
233
|
+
agentSession: channel.agentSession,
|
|
234
|
+
err: errMsg,
|
|
235
|
+
});
|
|
236
|
+
return { dispatched: false, error: errMsg };
|
|
237
|
+
}
|
|
238
|
+
if (!result.success) {
|
|
239
|
+
this.logger.warn('chat-v2 dispatch reported failure', {
|
|
240
|
+
channelId: channel.id,
|
|
241
|
+
agentSession: channel.agentSession,
|
|
242
|
+
err: result.error,
|
|
243
|
+
});
|
|
244
|
+
return { dispatched: false, error: result.error ?? 'unknown sink failure' };
|
|
245
|
+
}
|
|
246
|
+
this.logger.debug('chat-v2 dispatched', {
|
|
247
|
+
channelId: channel.id,
|
|
248
|
+
agentSession: channel.agentSession,
|
|
249
|
+
queued: result.queued ?? false,
|
|
250
|
+
});
|
|
251
|
+
return { dispatched: true };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=chat-v2.dispatcher.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.dispatcher.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.dispatcher.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatV2MentionResolver — turn `mentions[]` from a chat message into a
|
|
3
|
+
* deduplicated list of agent-session dispatch targets.
|
|
4
|
+
*
|
|
5
|
+
* Phase C BE.2 scaffolding for Slack-like team-chat mention dispatch
|
|
6
|
+
* (SEALED §2.1 routing rules):
|
|
7
|
+
*
|
|
8
|
+
* - **`@agent` mention** (mention id matches a `TeamMember.id`):
|
|
9
|
+
* resolves to that member's tmux/agent `sessionName`. The dispatcher
|
|
10
|
+
* will deliver the message directly into that agent's session.
|
|
11
|
+
*
|
|
12
|
+
* - **`@team` mention** (mention id matches a `Team.id`): resolves to
|
|
13
|
+
* that team's TL — the canonical primary responder per the spec
|
|
14
|
+
* ("the Team Lead is the primary responder; if busy, queue in the
|
|
15
|
+
* Team's Task Pool"). TL is selected as: first member with both
|
|
16
|
+
* `hierarchyLevel === 1` and `canDelegate === true`, falling back
|
|
17
|
+
* to any `canDelegate` member, then `members[0]` so the rule is
|
|
18
|
+
* deterministic even on legacy teams without hierarchy fields.
|
|
19
|
+
*
|
|
20
|
+
* - **Unknown mention id** (not a team or a known member): skipped
|
|
21
|
+
* with a debug log. The dispatcher must always succeed even when
|
|
22
|
+
* the FE includes a stale/typo mention; the chat HTTP ack has
|
|
23
|
+
* already been sent by the time we resolve.
|
|
24
|
+
*
|
|
25
|
+
* Phase C F2a (issue #333) — cross-tenant scope enforcement: when the
|
|
26
|
+
* caller passes `context.teamId`, the resolver enforces the channel's
|
|
27
|
+
* tenant boundary. `@agent` mentions to members of any other team are
|
|
28
|
+
* dropped (cross-tenant leak vector pinned by Arch on PR #331); `@team`
|
|
29
|
+
* mentions to any team still resolve (cross-team pings are a useful
|
|
30
|
+
* coordination affordance), but a mismatch emits a warn for audit.
|
|
31
|
+
*
|
|
32
|
+
* The resolver is the boundary between the chat-v2 wire (id strings)
|
|
33
|
+
* and the agent runtime (session names). It deliberately does NOT
|
|
34
|
+
* touch the agent registry — it only produces the addresses that the
|
|
35
|
+
* dispatcher will hand to `AgentMessageSink.sendMessageToAgent`.
|
|
36
|
+
*
|
|
37
|
+
* The team list is loaded via an injected `loadTeams()` callback so
|
|
38
|
+
* tests can drive it without a real `StorageService`. Production wiring
|
|
39
|
+
* passes `() => storageService.getTeams()`.
|
|
40
|
+
*
|
|
41
|
+
* @module services/chat-v2/chat-v2.mention-resolver
|
|
42
|
+
*/
|
|
43
|
+
import type { Team } from '../../types/index.js';
|
|
44
|
+
/** Kind of mention that resolved to a target. */
|
|
45
|
+
export type MentionTargetKind = 'agent' | 'team';
|
|
46
|
+
/**
|
|
47
|
+
* One resolved dispatch target. The dispatcher will call
|
|
48
|
+
* `sendMessageToAgent(sessionName, prompt)` for each unique entry.
|
|
49
|
+
*/
|
|
50
|
+
export interface MentionTarget {
|
|
51
|
+
/** Whether this target came from an `@agent` (member) or `@team` mention. */
|
|
52
|
+
kind: MentionTargetKind;
|
|
53
|
+
/** The original mention id as it appeared in the wire `mentions[]`. */
|
|
54
|
+
mentionId: string;
|
|
55
|
+
/** Resolved member id. For `kind='team'`, this is the TL's member id. */
|
|
56
|
+
memberId: string;
|
|
57
|
+
/** Resolved agent session name — the address `sendMessageToAgent` expects. */
|
|
58
|
+
sessionName: string;
|
|
59
|
+
/** For `kind='team'`, the matched team's id. Undefined for `kind='agent'`. */
|
|
60
|
+
teamId?: string;
|
|
61
|
+
}
|
|
62
|
+
/** Optional context the resolver may use to disambiguate. */
|
|
63
|
+
export interface MentionResolverContext {
|
|
64
|
+
/**
|
|
65
|
+
* The channel's `teamId` (when the channel is `type='channel'`). When set,
|
|
66
|
+
* the resolver enforces cross-tenant scope (Phase C F2a, issue #333):
|
|
67
|
+
*
|
|
68
|
+
* - `@agent` mentions are restricted to members whose owning team's
|
|
69
|
+
* id equals `teamId`. Mentions to agents of any other team are
|
|
70
|
+
* dropped with a debug log so a foreign-team agent never receives
|
|
71
|
+
* a dispatch frame from a channel they are not a member of.
|
|
72
|
+
*
|
|
73
|
+
* - `@team` mentions to any team id still resolve to that team's TL
|
|
74
|
+
* (they remain useful for cross-team coordination), but a mismatch
|
|
75
|
+
* between the channel's `teamId` and the mentioned team's id emits
|
|
76
|
+
* a warn so the cross-team ping is observable in audit/log.
|
|
77
|
+
*
|
|
78
|
+
* Leave undefined (or empty string) to disable scoping — used by the
|
|
79
|
+
* legacy DM dispatch path and by tests that need the global resolver.
|
|
80
|
+
*/
|
|
81
|
+
teamId?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Dependencies. The team-list source is callable so tests don't need a
|
|
85
|
+
* StorageService; the production path injects `() => storage.getTeams()`.
|
|
86
|
+
*/
|
|
87
|
+
export interface MentionResolverDeps {
|
|
88
|
+
/**
|
|
89
|
+
* Returns the current team list. May be sync or async — the resolver
|
|
90
|
+
* awaits the result either way. Errors propagate; the resolver
|
|
91
|
+
* surfaces an empty-target list on caller error so a transient
|
|
92
|
+
* storage hiccup never crashes the chat dispatch path.
|
|
93
|
+
*/
|
|
94
|
+
loadTeams: () => Promise<Team[]> | Team[];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Stateless resolver — instances are cheap to construct. Each `resolve()`
|
|
98
|
+
* call loads the team list fresh so dispatch always sees the latest
|
|
99
|
+
* member/session bindings (a new agent comes online → next mention
|
|
100
|
+
* resolves correctly without a restart).
|
|
101
|
+
*/
|
|
102
|
+
export declare class ChatV2MentionResolver {
|
|
103
|
+
private readonly loadTeams;
|
|
104
|
+
private readonly logger;
|
|
105
|
+
constructor(deps: MentionResolverDeps);
|
|
106
|
+
/**
|
|
107
|
+
* Resolve `mentions` to dispatch targets.
|
|
108
|
+
*
|
|
109
|
+
* Behavior:
|
|
110
|
+
* - Empty / whitespace mention ids are skipped silently.
|
|
111
|
+
* - Each id is classified as team-first, then agent-first; ties go to
|
|
112
|
+
* the team interpretation since team ids and member ids share the
|
|
113
|
+
* same UUID-shape namespace and team mentions are higher-impact.
|
|
114
|
+
* - Unknown ids are logged at debug level and skipped.
|
|
115
|
+
* - Duplicate `sessionName`s are collapsed (first-seen wins, keeping
|
|
116
|
+
* `kind` ordering stable for tests).
|
|
117
|
+
* - Targets with empty `sessionName` are skipped — there is no agent
|
|
118
|
+
* to dispatch to.
|
|
119
|
+
*
|
|
120
|
+
* Phase C F2a (#333) — when `context.teamId` is set:
|
|
121
|
+
* - `@agent` mentions whose owning team !== `context.teamId` are
|
|
122
|
+
* dropped at debug level (cross-tenant leak guard).
|
|
123
|
+
* - `@team` mentions to a different team still resolve to that
|
|
124
|
+
* team's TL but emit a warn so cross-team pings are auditable.
|
|
125
|
+
* - A blank/whitespace `context.teamId` is treated as "no scope"
|
|
126
|
+
* so DM dispatch and back-compat tests keep current behavior.
|
|
127
|
+
*
|
|
128
|
+
* @param mentions - The raw mention id list from `ChatMessageDTO.mentions`.
|
|
129
|
+
* @param context - Optional resolver context (teamId etc.).
|
|
130
|
+
* @returns Deduplicated dispatch targets, in input order with team-first ties.
|
|
131
|
+
*/
|
|
132
|
+
resolve(mentions: string[], context?: MentionResolverContext): Promise<MentionTarget[]>;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=chat-v2.mention-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.mention-resolver.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.mention-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,sBAAsB,CAAC;AAQ7D,iDAAiD;AACjD,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,IAAI,EAAE,iBAAiB,CAAC;IACxB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,6DAA6D;AAC7D,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC;CAC3C;AAMD;;;;;GAKG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAE7B,IAAI,EAAE,mBAAmB;IAKrC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAgJ9F"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatV2MentionResolver — turn `mentions[]` from a chat message into a
|
|
3
|
+
* deduplicated list of agent-session dispatch targets.
|
|
4
|
+
*
|
|
5
|
+
* Phase C BE.2 scaffolding for Slack-like team-chat mention dispatch
|
|
6
|
+
* (SEALED §2.1 routing rules):
|
|
7
|
+
*
|
|
8
|
+
* - **`@agent` mention** (mention id matches a `TeamMember.id`):
|
|
9
|
+
* resolves to that member's tmux/agent `sessionName`. The dispatcher
|
|
10
|
+
* will deliver the message directly into that agent's session.
|
|
11
|
+
*
|
|
12
|
+
* - **`@team` mention** (mention id matches a `Team.id`): resolves to
|
|
13
|
+
* that team's TL — the canonical primary responder per the spec
|
|
14
|
+
* ("the Team Lead is the primary responder; if busy, queue in the
|
|
15
|
+
* Team's Task Pool"). TL is selected as: first member with both
|
|
16
|
+
* `hierarchyLevel === 1` and `canDelegate === true`, falling back
|
|
17
|
+
* to any `canDelegate` member, then `members[0]` so the rule is
|
|
18
|
+
* deterministic even on legacy teams without hierarchy fields.
|
|
19
|
+
*
|
|
20
|
+
* - **Unknown mention id** (not a team or a known member): skipped
|
|
21
|
+
* with a debug log. The dispatcher must always succeed even when
|
|
22
|
+
* the FE includes a stale/typo mention; the chat HTTP ack has
|
|
23
|
+
* already been sent by the time we resolve.
|
|
24
|
+
*
|
|
25
|
+
* Phase C F2a (issue #333) — cross-tenant scope enforcement: when the
|
|
26
|
+
* caller passes `context.teamId`, the resolver enforces the channel's
|
|
27
|
+
* tenant boundary. `@agent` mentions to members of any other team are
|
|
28
|
+
* dropped (cross-tenant leak vector pinned by Arch on PR #331); `@team`
|
|
29
|
+
* mentions to any team still resolve (cross-team pings are a useful
|
|
30
|
+
* coordination affordance), but a mismatch emits a warn for audit.
|
|
31
|
+
*
|
|
32
|
+
* The resolver is the boundary between the chat-v2 wire (id strings)
|
|
33
|
+
* and the agent runtime (session names). It deliberately does NOT
|
|
34
|
+
* touch the agent registry — it only produces the addresses that the
|
|
35
|
+
* dispatcher will hand to `AgentMessageSink.sendMessageToAgent`.
|
|
36
|
+
*
|
|
37
|
+
* The team list is loaded via an injected `loadTeams()` callback so
|
|
38
|
+
* tests can drive it without a real `StorageService`. Production wiring
|
|
39
|
+
* passes `() => storageService.getTeams()`.
|
|
40
|
+
*
|
|
41
|
+
* @module services/chat-v2/chat-v2.mention-resolver
|
|
42
|
+
*/
|
|
43
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
44
|
+
import { pickTeamLead } from '../../utils/team.utils.js';
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Service
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
/**
|
|
49
|
+
* Stateless resolver — instances are cheap to construct. Each `resolve()`
|
|
50
|
+
* call loads the team list fresh so dispatch always sees the latest
|
|
51
|
+
* member/session bindings (a new agent comes online → next mention
|
|
52
|
+
* resolves correctly without a restart).
|
|
53
|
+
*/
|
|
54
|
+
export class ChatV2MentionResolver {
|
|
55
|
+
loadTeams;
|
|
56
|
+
logger;
|
|
57
|
+
constructor(deps) {
|
|
58
|
+
this.loadTeams = deps.loadTeams;
|
|
59
|
+
this.logger = LoggerService.getInstance().createComponentLogger('ChatV2MentionResolver');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolve `mentions` to dispatch targets.
|
|
63
|
+
*
|
|
64
|
+
* Behavior:
|
|
65
|
+
* - Empty / whitespace mention ids are skipped silently.
|
|
66
|
+
* - Each id is classified as team-first, then agent-first; ties go to
|
|
67
|
+
* the team interpretation since team ids and member ids share the
|
|
68
|
+
* same UUID-shape namespace and team mentions are higher-impact.
|
|
69
|
+
* - Unknown ids are logged at debug level and skipped.
|
|
70
|
+
* - Duplicate `sessionName`s are collapsed (first-seen wins, keeping
|
|
71
|
+
* `kind` ordering stable for tests).
|
|
72
|
+
* - Targets with empty `sessionName` are skipped — there is no agent
|
|
73
|
+
* to dispatch to.
|
|
74
|
+
*
|
|
75
|
+
* Phase C F2a (#333) — when `context.teamId` is set:
|
|
76
|
+
* - `@agent` mentions whose owning team !== `context.teamId` are
|
|
77
|
+
* dropped at debug level (cross-tenant leak guard).
|
|
78
|
+
* - `@team` mentions to a different team still resolve to that
|
|
79
|
+
* team's TL but emit a warn so cross-team pings are auditable.
|
|
80
|
+
* - A blank/whitespace `context.teamId` is treated as "no scope"
|
|
81
|
+
* so DM dispatch and back-compat tests keep current behavior.
|
|
82
|
+
*
|
|
83
|
+
* @param mentions - The raw mention id list from `ChatMessageDTO.mentions`.
|
|
84
|
+
* @param context - Optional resolver context (teamId etc.).
|
|
85
|
+
* @returns Deduplicated dispatch targets, in input order with team-first ties.
|
|
86
|
+
*/
|
|
87
|
+
async resolve(mentions, context) {
|
|
88
|
+
if (!Array.isArray(mentions) || mentions.length === 0) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
let teams;
|
|
92
|
+
try {
|
|
93
|
+
teams = await this.loadTeams();
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
this.logger.warn('chat-v2 mention-resolver loadTeams failed; returning no targets', {
|
|
97
|
+
err: err instanceof Error ? err.message : String(err),
|
|
98
|
+
});
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
// Build O(1) lookup maps once per call so even a wide mention array
|
|
102
|
+
// (capped at 50 by the service-layer validator) doesn't cause an
|
|
103
|
+
// O(N*M) team×member scan.
|
|
104
|
+
const teamById = new Map();
|
|
105
|
+
const memberById = new Map();
|
|
106
|
+
for (const team of teams) {
|
|
107
|
+
teamById.set(team.id, team);
|
|
108
|
+
for (const member of team.members ?? []) {
|
|
109
|
+
// First-seen wins on member-id collisions across teams. The
|
|
110
|
+
// legacy data model allows distinct teams to coexist with the
|
|
111
|
+
// same memberId only if both were imported from the same
|
|
112
|
+
// hierarchy backup — which is rare and never a chat path. We
|
|
113
|
+
// log the collision so it surfaces in observability.
|
|
114
|
+
if (memberById.has(member.id)) {
|
|
115
|
+
this.logger.warn('chat-v2 mention-resolver member-id collision across teams', {
|
|
116
|
+
memberId: member.id,
|
|
117
|
+
firstTeamId: memberById.get(member.id).team.id,
|
|
118
|
+
secondTeamId: team.id,
|
|
119
|
+
});
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
memberById.set(member.id, { team, member });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const results = [];
|
|
126
|
+
const seenSessions = new Set();
|
|
127
|
+
// Treat blank/whitespace teamId as "no scope" so callers don't have to
|
|
128
|
+
// pre-normalize. This matches the channel-rail listing endpoint's
|
|
129
|
+
// teamId filter normalization (see ChatV2Service.listChannels).
|
|
130
|
+
const scopeTeamId = typeof context?.teamId === 'string' && context.teamId.trim().length > 0
|
|
131
|
+
? context.teamId
|
|
132
|
+
: undefined;
|
|
133
|
+
for (const rawId of mentions) {
|
|
134
|
+
if (typeof rawId !== 'string')
|
|
135
|
+
continue;
|
|
136
|
+
const id = rawId.trim();
|
|
137
|
+
if (id.length === 0)
|
|
138
|
+
continue;
|
|
139
|
+
// 1) Team-mention takes precedence (higher routing impact).
|
|
140
|
+
const team = teamById.get(id);
|
|
141
|
+
if (team) {
|
|
142
|
+
// F2a (#333): when the channel scopes to a team, a `@team` mention
|
|
143
|
+
// to ANY OTHER team still resolves (deliberate — cross-team pings
|
|
144
|
+
// are a useful coordination affordance), but we emit a warn so
|
|
145
|
+
// operators can audit cross-tenant traffic. No warn on same-team
|
|
146
|
+
// mentions; that's the common case.
|
|
147
|
+
if (scopeTeamId !== undefined && team.id !== scopeTeamId) {
|
|
148
|
+
this.logger.warn('chat-v2 mention-resolver cross-team @team mention', {
|
|
149
|
+
mentionId: id,
|
|
150
|
+
mentionedTeamId: team.id,
|
|
151
|
+
contextTeamId: scopeTeamId,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
const tl = pickTeamLead(team);
|
|
155
|
+
if (!tl) {
|
|
156
|
+
this.logger.debug('chat-v2 mention-resolver team has no dispatchable TL', {
|
|
157
|
+
mentionId: id,
|
|
158
|
+
teamId: team.id,
|
|
159
|
+
});
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!tl.sessionName) {
|
|
163
|
+
this.logger.debug('chat-v2 mention-resolver TL has empty sessionName', {
|
|
164
|
+
mentionId: id,
|
|
165
|
+
teamId: team.id,
|
|
166
|
+
memberId: tl.id,
|
|
167
|
+
});
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (seenSessions.has(tl.sessionName))
|
|
171
|
+
continue;
|
|
172
|
+
seenSessions.add(tl.sessionName);
|
|
173
|
+
results.push({
|
|
174
|
+
kind: 'team',
|
|
175
|
+
mentionId: id,
|
|
176
|
+
memberId: tl.id,
|
|
177
|
+
sessionName: tl.sessionName,
|
|
178
|
+
teamId: team.id,
|
|
179
|
+
});
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
// 2) Agent (member) mention.
|
|
183
|
+
const hit = memberById.get(id);
|
|
184
|
+
if (hit) {
|
|
185
|
+
// F2a (#333): when the channel scopes to a team, drop @agent
|
|
186
|
+
// mentions whose owning team differs — without this, a
|
|
187
|
+
// type='channel' message in team-A could fan-out to an agent in
|
|
188
|
+
// team-B, the cross-tenant leak vector pinned by Arch on PR #331.
|
|
189
|
+
// The mention silently no-ops at debug level (the chat HTTP ack
|
|
190
|
+
// already returned 200; we don't fail the post for a dropped
|
|
191
|
+
// mention).
|
|
192
|
+
if (scopeTeamId !== undefined && hit.team.id !== scopeTeamId) {
|
|
193
|
+
this.logger.debug('chat-v2 mention-resolver dropping foreign-team @agent', {
|
|
194
|
+
mentionId: id,
|
|
195
|
+
mentionedMemberId: hit.member.id,
|
|
196
|
+
mentionedTeamId: hit.team.id,
|
|
197
|
+
contextTeamId: scopeTeamId,
|
|
198
|
+
});
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (!hit.member.sessionName) {
|
|
202
|
+
this.logger.debug('chat-v2 mention-resolver member has empty sessionName', {
|
|
203
|
+
mentionId: id,
|
|
204
|
+
memberId: hit.member.id,
|
|
205
|
+
teamId: hit.team.id,
|
|
206
|
+
});
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (seenSessions.has(hit.member.sessionName))
|
|
210
|
+
continue;
|
|
211
|
+
seenSessions.add(hit.member.sessionName);
|
|
212
|
+
results.push({
|
|
213
|
+
kind: 'agent',
|
|
214
|
+
mentionId: id,
|
|
215
|
+
memberId: hit.member.id,
|
|
216
|
+
sessionName: hit.member.sessionName,
|
|
217
|
+
});
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
this.logger.debug('chat-v2 mention-resolver unknown mention id', {
|
|
221
|
+
mentionId: id,
|
|
222
|
+
contextTeamId: scopeTeamId,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return results;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
// Helpers — `pickTeamLead` lives in `utils/team.utils.ts` so chat-v2 and
|
|
230
|
+
// mission-reminder share the canonical 4-rule cascade. Imported above.
|
|
231
|
+
// ---------------------------------------------------------------------------
|
|
232
|
+
//# sourceMappingURL=chat-v2.mention-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.mention-resolver.js","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.mention-resolver.ts"],"names":[],"mappings":"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"}
|