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,467 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatV2Service — orchestrator for the Agent-First Chat MVP.
|
|
3
|
+
*
|
|
4
|
+
* Wires ChannelStore + MessageStore, enforces the authorization rules
|
|
5
|
+
* laid out in the tech spec §7.2, and maps DB rows to wire-format DTOs.
|
|
6
|
+
*
|
|
7
|
+
* WebSocket push, offline queuing, and attachment durability land in
|
|
8
|
+
* later passes of Phase 1 — see §18 rollout plan.
|
|
9
|
+
*
|
|
10
|
+
* @module services/chat-v2/chat-v2.service
|
|
11
|
+
*/
|
|
12
|
+
import { ChannelStore } from './sqlite/channel.store.js';
|
|
13
|
+
import { MessageStore } from './sqlite/message.store.js';
|
|
14
|
+
import { openChatDatabase } from './sqlite/chat-db.js';
|
|
15
|
+
import { CHAT_CHANNEL_TYPES, CHAT_CONTENT_TYPES, CHAT_ERROR_CODES, ChatError, } from './types.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Service
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/** Default presence provider used until AgentRegistrationService is wired. */
|
|
20
|
+
const DEFAULT_PRESENCE = () => ({
|
|
21
|
+
status: 'offline',
|
|
22
|
+
lastSeenAt: null,
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Orchestrator for chat domain operations.
|
|
26
|
+
*
|
|
27
|
+
* Responsibilities:
|
|
28
|
+
* - Owns the DB handle + stores.
|
|
29
|
+
* - Enforces authorization per §7.2.
|
|
30
|
+
* - Maps rows → DTOs.
|
|
31
|
+
* - Fans out to WebSocket / adapters in later phases.
|
|
32
|
+
*/
|
|
33
|
+
export class ChatV2Service {
|
|
34
|
+
/** Phase A spec §3.2: max mention count per message. */
|
|
35
|
+
static MAX_MENTIONS_PER_MESSAGE = 50;
|
|
36
|
+
/** Phase A spec §3.2: max JSON-encoded byte size of the mentions array. */
|
|
37
|
+
static MAX_MENTIONS_JSON_BYTES = 1024;
|
|
38
|
+
config;
|
|
39
|
+
db;
|
|
40
|
+
channels;
|
|
41
|
+
messages;
|
|
42
|
+
presence;
|
|
43
|
+
validateTeamMembership;
|
|
44
|
+
now;
|
|
45
|
+
constructor(options) {
|
|
46
|
+
this.config = options.config;
|
|
47
|
+
this.db = options.db ?? openChatDatabase({ dbPath: options.config.storage.dbPath });
|
|
48
|
+
this.channels = new ChannelStore(this.db);
|
|
49
|
+
this.messages = new MessageStore(this.db);
|
|
50
|
+
this.presence = options.getPresence ?? DEFAULT_PRESENCE;
|
|
51
|
+
this.validateTeamMembership = options.validateTeamMembership;
|
|
52
|
+
this.now = options.now ?? Date.now;
|
|
53
|
+
}
|
|
54
|
+
/** Release the DB handle. Safe to call during graceful shutdown / in tests. */
|
|
55
|
+
close() {
|
|
56
|
+
try {
|
|
57
|
+
this.db.close();
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// swallow — nothing to do if already closed
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// -------------------------------------------------------------------------
|
|
64
|
+
// Channel operations
|
|
65
|
+
// -------------------------------------------------------------------------
|
|
66
|
+
/**
|
|
67
|
+
* Create a channel bound 1:1 to an agent session. Server always assigns
|
|
68
|
+
* `owner_user_id = principal.userId` — the body's owner fields are ignored.
|
|
69
|
+
*
|
|
70
|
+
* F2b (#333): when `type='channel'` and a `validateTeamMembership` provider
|
|
71
|
+
* is wired into the service, the principal must be authorized for the
|
|
72
|
+
* requested `teamId`. Failures throw `forbidden_team` (403) — distinct
|
|
73
|
+
* from generic `forbidden` so the FE can surface a tenant-specific
|
|
74
|
+
* message.
|
|
75
|
+
*
|
|
76
|
+
* @param args - Channel creation args
|
|
77
|
+
* @returns The created channel as a DTO
|
|
78
|
+
* @throws {ChatError} `validation_error` (400) / `forbidden_team` (403) /
|
|
79
|
+
* `agent_already_bound` (409)
|
|
80
|
+
*/
|
|
81
|
+
createChannel(args) {
|
|
82
|
+
const name = (args.name ?? '').trim();
|
|
83
|
+
if (name.length === 0) {
|
|
84
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, 'name is required');
|
|
85
|
+
}
|
|
86
|
+
if (name.length > this.config.maxChannelNameChars) {
|
|
87
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `name exceeds ${this.config.maxChannelNameChars} characters`);
|
|
88
|
+
}
|
|
89
|
+
// Phase A: validate channel type (defaults to 'dm' for backwards compat).
|
|
90
|
+
const channelType = args.type ?? 'dm';
|
|
91
|
+
if (!CHAT_CHANNEL_TYPES.includes(channelType)) {
|
|
92
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `unknown channel type: ${channelType}`);
|
|
93
|
+
}
|
|
94
|
+
// agentSession requirement is type-dependent:
|
|
95
|
+
// - 'dm' → required (existing Phase 1 contract).
|
|
96
|
+
// - 'channel' → not 1:1-bound; server stores '' even if caller passed
|
|
97
|
+
// something. Keep this strict so the wire shape matches
|
|
98
|
+
// the design and we don't accidentally bind a team
|
|
99
|
+
// channel to a single agent.
|
|
100
|
+
const rawAgentSession = (args.agentSession ?? '').trim();
|
|
101
|
+
let agentSession;
|
|
102
|
+
if (channelType === 'dm') {
|
|
103
|
+
if (rawAgentSession.length === 0) {
|
|
104
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, "agentSession is required when type='dm'");
|
|
105
|
+
}
|
|
106
|
+
agentSession = rawAgentSession;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// channel: discard any caller-supplied agentSession.
|
|
110
|
+
agentSession = '';
|
|
111
|
+
}
|
|
112
|
+
// Phase A: type='channel' must specify a teamId; type='dm' may
|
|
113
|
+
// optionally carry a targetMemberId. Reject the contradicting cases.
|
|
114
|
+
const teamId = args.teamId?.trim() || undefined;
|
|
115
|
+
const projectId = args.projectId?.trim() || undefined;
|
|
116
|
+
const targetMemberId = args.targetMemberId?.trim() || undefined;
|
|
117
|
+
if (channelType === 'channel' && !teamId) {
|
|
118
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, "teamId is required when type='channel'");
|
|
119
|
+
}
|
|
120
|
+
if (channelType === 'dm' && teamId) {
|
|
121
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, "teamId must be omitted when type='dm'");
|
|
122
|
+
}
|
|
123
|
+
if (channelType === 'channel' && targetMemberId) {
|
|
124
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, "targetMemberId must be omitted when type='channel'");
|
|
125
|
+
}
|
|
126
|
+
// F2b (#333) — outer-ring tenant defense. type='channel' bindings
|
|
127
|
+
// must pass the membership check when one is wired. Pre-checks
|
|
128
|
+
// already confirmed `teamId` is present and non-empty by here.
|
|
129
|
+
if (channelType === 'channel' && teamId && this.validateTeamMembership) {
|
|
130
|
+
const isMember = this.validateTeamMembership(args.principal, teamId);
|
|
131
|
+
if (!isMember) {
|
|
132
|
+
throw new ChatError(CHAT_ERROR_CODES.FORBIDDEN_TEAM, 403, 'caller is not a member of the requested team', { teamId, userId: args.principal.userId });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const purpose = args.purpose?.trim();
|
|
136
|
+
if (purpose && purpose.length > this.config.maxPurposeChars) {
|
|
137
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `purpose exceeds ${this.config.maxPurposeChars} characters`);
|
|
138
|
+
}
|
|
139
|
+
const row = this.channels.create({
|
|
140
|
+
agentSession,
|
|
141
|
+
ownerUserId: args.principal.userId,
|
|
142
|
+
name,
|
|
143
|
+
purpose: purpose || null,
|
|
144
|
+
type: channelType,
|
|
145
|
+
teamId: teamId ?? null,
|
|
146
|
+
projectId: projectId ?? null,
|
|
147
|
+
targetMemberId: targetMemberId ?? null,
|
|
148
|
+
nowMs: this.now(),
|
|
149
|
+
});
|
|
150
|
+
return this.toChannelDTO(row);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* List channels owned by the caller.
|
|
154
|
+
*
|
|
155
|
+
* Phase C: extended with optional `type` + `teamId` filters so the
|
|
156
|
+
* channel-rail can request a focused slice (e.g. "channels in this
|
|
157
|
+
* workspace only") without paging the full owner-scoped list. An
|
|
158
|
+
* unknown `type` value is rejected as `validation_error`. Blank
|
|
159
|
+
* `teamId` is normalized to "no filter" so callers don't need to
|
|
160
|
+
* sanitize empty query strings.
|
|
161
|
+
*
|
|
162
|
+
* @param args - List args (principal + optional filters)
|
|
163
|
+
* @returns DTO-mapped channels
|
|
164
|
+
* @throws {ChatError} `validation_error` (400) when `type` is set
|
|
165
|
+
* to a value outside {@link CHAT_CHANNEL_TYPES}.
|
|
166
|
+
*/
|
|
167
|
+
listChannels(args) {
|
|
168
|
+
if (args.type !== undefined && !CHAT_CHANNEL_TYPES.includes(args.type)) {
|
|
169
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `unknown channel type: ${args.type}`);
|
|
170
|
+
}
|
|
171
|
+
// Treat blank teamId the same as omitted — saves the channel-rail FE
|
|
172
|
+
// from having to strip empty query strings before issuing the GET.
|
|
173
|
+
const teamIdFilter = args.teamId !== undefined && args.teamId.trim().length > 0
|
|
174
|
+
? args.teamId
|
|
175
|
+
: undefined;
|
|
176
|
+
const rows = this.channels.listByOwner(args.principal.userId, {
|
|
177
|
+
includeArchived: args.includeArchived,
|
|
178
|
+
limit: args.limit,
|
|
179
|
+
type: args.type,
|
|
180
|
+
teamId: teamIdFilter,
|
|
181
|
+
});
|
|
182
|
+
return rows.map((r) => this.toChannelDTO(r));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Look up a single channel the caller owns.
|
|
186
|
+
*
|
|
187
|
+
* @param channelId - Channel id
|
|
188
|
+
* @param principal - Auth principal
|
|
189
|
+
* @returns DTO shape
|
|
190
|
+
* @throws {ChatError} `channel_not_found` (404) if the caller doesn't own it
|
|
191
|
+
*/
|
|
192
|
+
getChannel(channelId, principal) {
|
|
193
|
+
const row = this.requireOwnedChannel(channelId, principal);
|
|
194
|
+
return this.toChannelDTO(row);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Archive a channel. Returns true if a row was modified.
|
|
198
|
+
*
|
|
199
|
+
* @param channelId - Channel id
|
|
200
|
+
* @param principal - Auth principal
|
|
201
|
+
* @returns True if newly archived, false if already archived
|
|
202
|
+
* @throws {ChatError} `channel_not_found` (404)
|
|
203
|
+
*/
|
|
204
|
+
archiveChannel(channelId, principal) {
|
|
205
|
+
this.requireOwnedChannel(channelId, principal);
|
|
206
|
+
return this.channels.archive(channelId, this.now());
|
|
207
|
+
}
|
|
208
|
+
// -------------------------------------------------------------------------
|
|
209
|
+
// Message operations
|
|
210
|
+
// -------------------------------------------------------------------------
|
|
211
|
+
/**
|
|
212
|
+
* Persist a message sent by the caller. The server decides `sender_type`
|
|
213
|
+
* and `sender_id` from the auth principal; client fields are ignored.
|
|
214
|
+
*
|
|
215
|
+
* @param args - Send args
|
|
216
|
+
* @returns The persisted message as a DTO (fresh or deduped)
|
|
217
|
+
* @throws {ChatError} on validation, authorization, or size limit
|
|
218
|
+
*/
|
|
219
|
+
sendMessage(args) {
|
|
220
|
+
const row = this.requireReadableChannel(args.channelId, args.principal);
|
|
221
|
+
const content = args.content ?? '';
|
|
222
|
+
if (content.length === 0) {
|
|
223
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, 'content is required');
|
|
224
|
+
}
|
|
225
|
+
const byteLen = Buffer.byteLength(content, 'utf-8');
|
|
226
|
+
if (byteLen > this.config.maxMessageBytes) {
|
|
227
|
+
throw new ChatError(CHAT_ERROR_CODES.PAYLOAD_TOO_LARGE, 413, `content exceeds max bytes (${this.config.maxMessageBytes})`, { maxBytes: this.config.maxMessageBytes, yourBytes: byteLen });
|
|
228
|
+
}
|
|
229
|
+
const contentType = args.contentType ?? 'markdown';
|
|
230
|
+
if (!CHAT_CONTENT_TYPES.includes(contentType)) {
|
|
231
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `unknown contentType: ${contentType}`);
|
|
232
|
+
}
|
|
233
|
+
// Agents/users cannot self-tag as system.
|
|
234
|
+
if (contentType === 'system_note' && this.resolveSender(row, args.principal).type !== 'system') {
|
|
235
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, 'system_note can only be emitted server-side');
|
|
236
|
+
}
|
|
237
|
+
const { type: senderType, id: senderId } = this.resolveSender(row, args.principal);
|
|
238
|
+
// Phase A: validate mentions array. Bounded count + JSON-byte cap so
|
|
239
|
+
// a misbehaving client cannot blow past the spec §3.2 1KB ceiling.
|
|
240
|
+
const mentions = this.validateMentions(args.mentions);
|
|
241
|
+
// Phase A: validate threadId — must reference an existing message in
|
|
242
|
+
// this channel; refusing dangling thread refs prevents orphan replies
|
|
243
|
+
// and contains UX confusion if the FE composes against a stale id.
|
|
244
|
+
const threadId = this.validateThreadId(args.threadId, args.channelId);
|
|
245
|
+
const { row: persisted } = this.messages.insert({
|
|
246
|
+
channelId: args.channelId,
|
|
247
|
+
senderType,
|
|
248
|
+
senderId,
|
|
249
|
+
content,
|
|
250
|
+
contentType,
|
|
251
|
+
clientMessageId: args.clientMessageId,
|
|
252
|
+
mentions,
|
|
253
|
+
threadId,
|
|
254
|
+
nowMs: this.now(),
|
|
255
|
+
});
|
|
256
|
+
return this.toMessageDTO(persisted, args.attachments ?? []);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Phase A — validate the mentions array passed to sendMessage.
|
|
260
|
+
* Returns the cleaned array (or undefined when input is empty/missing).
|
|
261
|
+
*
|
|
262
|
+
* @param raw - The raw `mentions` field from the request body
|
|
263
|
+
* @returns Validated mention IDs (caller passes to messageStore)
|
|
264
|
+
* @throws {ChatError} `validation_error` (400) on type / size / count violation
|
|
265
|
+
*/
|
|
266
|
+
validateMentions(raw) {
|
|
267
|
+
if (raw === undefined || raw === null)
|
|
268
|
+
return undefined;
|
|
269
|
+
if (!Array.isArray(raw)) {
|
|
270
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, 'mentions must be an array');
|
|
271
|
+
}
|
|
272
|
+
if (raw.length === 0)
|
|
273
|
+
return undefined;
|
|
274
|
+
if (raw.length > ChatV2Service.MAX_MENTIONS_PER_MESSAGE) {
|
|
275
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `mentions exceeds max count (${ChatV2Service.MAX_MENTIONS_PER_MESSAGE})`);
|
|
276
|
+
}
|
|
277
|
+
const cleaned = [];
|
|
278
|
+
for (const item of raw) {
|
|
279
|
+
if (typeof item !== 'string') {
|
|
280
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, 'mentions entries must be strings');
|
|
281
|
+
}
|
|
282
|
+
const trimmed = item.trim();
|
|
283
|
+
if (trimmed.length === 0) {
|
|
284
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, 'mentions entries must be non-empty');
|
|
285
|
+
}
|
|
286
|
+
cleaned.push(trimmed);
|
|
287
|
+
}
|
|
288
|
+
// Bound the JSON size — spec §3.2 caps mentions JSON at 1KB.
|
|
289
|
+
const jsonByteLen = Buffer.byteLength(JSON.stringify(cleaned), 'utf-8');
|
|
290
|
+
if (jsonByteLen > ChatV2Service.MAX_MENTIONS_JSON_BYTES) {
|
|
291
|
+
throw new ChatError(CHAT_ERROR_CODES.PAYLOAD_TOO_LARGE, 413, `mentions JSON exceeds max bytes (${ChatV2Service.MAX_MENTIONS_JSON_BYTES})`);
|
|
292
|
+
}
|
|
293
|
+
return cleaned;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Phase A — validate the threadId passed to sendMessage.
|
|
297
|
+
*
|
|
298
|
+
* Returns the original threadId if it's a valid reference to a message
|
|
299
|
+
* in the same channel, or undefined when input is empty/missing.
|
|
300
|
+
* Refuses dangling references and cross-channel thread roots.
|
|
301
|
+
*
|
|
302
|
+
* @param raw - The raw `threadId` field from the request body
|
|
303
|
+
* @param channelId - The channel this message will be inserted into
|
|
304
|
+
* @returns Validated thread root id (caller passes to messageStore)
|
|
305
|
+
* @throws {ChatError} `validation_error` (400) when invalid
|
|
306
|
+
*/
|
|
307
|
+
validateThreadId(raw, channelId) {
|
|
308
|
+
if (raw === undefined || raw === null)
|
|
309
|
+
return undefined;
|
|
310
|
+
if (typeof raw !== 'string') {
|
|
311
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, 'threadId must be a string');
|
|
312
|
+
}
|
|
313
|
+
const trimmed = raw.trim();
|
|
314
|
+
if (trimmed.length === 0)
|
|
315
|
+
return undefined;
|
|
316
|
+
const root = this.messages.getById(trimmed);
|
|
317
|
+
if (!root) {
|
|
318
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `threadId references a non-existent message`, { threadId: trimmed });
|
|
319
|
+
}
|
|
320
|
+
if (root.channel_id !== channelId) {
|
|
321
|
+
// Returning validation_error (not channel_not_found) because the
|
|
322
|
+
// caller's intent IS valid — they're just pointing at the wrong
|
|
323
|
+
// channel's thread root. Distinct error helps debugging.
|
|
324
|
+
throw new ChatError(CHAT_ERROR_CODES.VALIDATION, 400, `threadId belongs to a different channel`, { threadId: trimmed, expectedChannelId: channelId });
|
|
325
|
+
}
|
|
326
|
+
return trimmed;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Page messages for a channel the caller may read.
|
|
330
|
+
*
|
|
331
|
+
* @param args - List args
|
|
332
|
+
* @returns A pagination envelope
|
|
333
|
+
* @throws {ChatError} on auth or invalid cursor
|
|
334
|
+
*/
|
|
335
|
+
listMessages(args) {
|
|
336
|
+
this.requireReadableChannel(args.channelId, args.principal);
|
|
337
|
+
const page = this.messages.listByChannel(args.channelId, {
|
|
338
|
+
cursor: args.cursor ?? null,
|
|
339
|
+
limit: args.limit,
|
|
340
|
+
direction: args.direction,
|
|
341
|
+
});
|
|
342
|
+
return {
|
|
343
|
+
channelId: args.channelId,
|
|
344
|
+
messages: page.rows.map((r) => this.toMessageDTO(r, [])),
|
|
345
|
+
nextCursor: page.nextCursor,
|
|
346
|
+
prevCursor: page.prevCursor,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
// -------------------------------------------------------------------------
|
|
350
|
+
// Authorization helpers (§7.2)
|
|
351
|
+
// -------------------------------------------------------------------------
|
|
352
|
+
/** Fetch the channel and enforce caller = owner. */
|
|
353
|
+
requireOwnedChannel(channelId, principal) {
|
|
354
|
+
const row = this.channels.getById(channelId);
|
|
355
|
+
if (!row) {
|
|
356
|
+
throw new ChatError(CHAT_ERROR_CODES.CHANNEL_NOT_FOUND, 404, 'Channel not found');
|
|
357
|
+
}
|
|
358
|
+
if (row.owner_user_id !== principal.userId) {
|
|
359
|
+
throw new ChatError(CHAT_ERROR_CODES.CHANNEL_NOT_FOUND, 404, 'Channel not found');
|
|
360
|
+
}
|
|
361
|
+
return row;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Fetch the channel and allow if the caller is the owner OR the bound agent.
|
|
365
|
+
* Used for read + send; agents must always be acting from their own session.
|
|
366
|
+
*/
|
|
367
|
+
requireReadableChannel(channelId, principal) {
|
|
368
|
+
const row = this.channels.getById(channelId);
|
|
369
|
+
if (!row) {
|
|
370
|
+
throw new ChatError(CHAT_ERROR_CODES.CHANNEL_NOT_FOUND, 404, 'Channel not found');
|
|
371
|
+
}
|
|
372
|
+
const isOwner = row.owner_user_id === principal.userId;
|
|
373
|
+
const isBoundAgent = !!principal.agentSession && principal.agentSession === row.agent_session;
|
|
374
|
+
if (!isOwner && !isBoundAgent) {
|
|
375
|
+
throw new ChatError(CHAT_ERROR_CODES.CHANNEL_NOT_FOUND, 404, 'Channel not found');
|
|
376
|
+
}
|
|
377
|
+
if (row.archived_at) {
|
|
378
|
+
throw new ChatError(CHAT_ERROR_CODES.CHANNEL_ARCHIVED, 404, 'Channel is archived');
|
|
379
|
+
}
|
|
380
|
+
return row;
|
|
381
|
+
}
|
|
382
|
+
/** Decide sender_type + sender_id for a message based on principal + channel. */
|
|
383
|
+
resolveSender(channel, principal) {
|
|
384
|
+
if (principal.agentSession && principal.agentSession === channel.agent_session) {
|
|
385
|
+
return { type: 'agent', id: principal.agentSession };
|
|
386
|
+
}
|
|
387
|
+
if (principal.userId === channel.owner_user_id) {
|
|
388
|
+
return { type: 'user', id: principal.userId };
|
|
389
|
+
}
|
|
390
|
+
// Server-minted system messages go through an internal path, not this one.
|
|
391
|
+
throw new ChatError(CHAT_ERROR_CODES.FORBIDDEN, 403, 'Principal cannot send in this channel');
|
|
392
|
+
}
|
|
393
|
+
// -------------------------------------------------------------------------
|
|
394
|
+
// DTO mappers
|
|
395
|
+
// -------------------------------------------------------------------------
|
|
396
|
+
/** Map a channel row + live presence into the wire DTO. */
|
|
397
|
+
toChannelDTO(row) {
|
|
398
|
+
// Phase B backwards-compat: legacy rows (pre-migration) lack `type` /
|
|
399
|
+
// team scope fields. The migration backfills `type='dm'` for existing
|
|
400
|
+
// rows; here we defend the in-memory path against rows that may not
|
|
401
|
+
// yet have the column populated (e.g. mid-migration test runs).
|
|
402
|
+
const channelType = row.type ?? 'dm';
|
|
403
|
+
const presenceSource = channelType === 'dm' ? row.agent_session : '';
|
|
404
|
+
const presence = (this.presence ?? DEFAULT_PRESENCE)(presenceSource);
|
|
405
|
+
return {
|
|
406
|
+
id: row.id,
|
|
407
|
+
agentSession: row.agent_session,
|
|
408
|
+
name: row.name,
|
|
409
|
+
purpose: row.purpose ?? undefined,
|
|
410
|
+
createdAt: row.created_at,
|
|
411
|
+
archivedAt: row.archived_at ?? null,
|
|
412
|
+
lastMessageAt: row.last_message_at ?? null,
|
|
413
|
+
agentPresence: {
|
|
414
|
+
status: presence.status,
|
|
415
|
+
lastSeenAt: presence.lastSeenAt,
|
|
416
|
+
},
|
|
417
|
+
type: channelType,
|
|
418
|
+
teamId: row.team_id ?? undefined,
|
|
419
|
+
projectId: row.project_id ?? undefined,
|
|
420
|
+
targetMemberId: row.target_member_id ?? undefined,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
/** Map a message row to the wire DTO. Attachments passed in by the caller. */
|
|
424
|
+
toMessageDTO(row, attachments) {
|
|
425
|
+
let metadata;
|
|
426
|
+
if (row.metadata) {
|
|
427
|
+
try {
|
|
428
|
+
metadata = JSON.parse(row.metadata);
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
metadata = undefined;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// Phase B backwards-compat: parse mentions from JSON-encoded array
|
|
435
|
+
// column. Legacy rows (pre-migration) have null; we surface as
|
|
436
|
+
// empty array so the wire contract `mentions: string[]` is never
|
|
437
|
+
// violated. A malformed JSON column also falls back to `[]` rather
|
|
438
|
+
// than throwing — the wire contract is the priority.
|
|
439
|
+
let mentions = [];
|
|
440
|
+
if (row.mentions) {
|
|
441
|
+
try {
|
|
442
|
+
const parsed = JSON.parse(row.mentions);
|
|
443
|
+
if (Array.isArray(parsed) && parsed.every((x) => typeof x === 'string')) {
|
|
444
|
+
mentions = parsed;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
catch {
|
|
448
|
+
mentions = [];
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
id: row.id,
|
|
453
|
+
channelId: row.channel_id,
|
|
454
|
+
seq: row.seq,
|
|
455
|
+
senderType: row.sender_type,
|
|
456
|
+
senderId: row.sender_id,
|
|
457
|
+
content: row.content,
|
|
458
|
+
contentType: row.content_type,
|
|
459
|
+
createdAt: row.created_at,
|
|
460
|
+
attachments,
|
|
461
|
+
metadata,
|
|
462
|
+
mentions,
|
|
463
|
+
threadId: row.thread_id ?? undefined,
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
//# sourceMappingURL=chat-v2.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide singleton accessor for `ChatV2Service`.
|
|
3
|
+
*
|
|
4
|
+
* The server wiring layer calls `getChatV2Service()` once and holds the
|
|
5
|
+
* reference; tests can `resetChatV2Service()` to start fresh.
|
|
6
|
+
*
|
|
7
|
+
* @module services/chat-v2/chat-v2.singleton
|
|
8
|
+
*/
|
|
9
|
+
import { ChatV2Service, type ChatV2ServiceOptions } from './chat-v2.service.js';
|
|
10
|
+
/**
|
|
11
|
+
* Return the process-wide `ChatV2Service`, constructing it on first call.
|
|
12
|
+
*
|
|
13
|
+
* @param overrides - Optional overrides passed when first constructed.
|
|
14
|
+
* Ignored on subsequent calls.
|
|
15
|
+
* @returns The shared service instance
|
|
16
|
+
*/
|
|
17
|
+
export declare function getChatV2Service(overrides?: Partial<ChatV2ServiceOptions>): ChatV2Service;
|
|
18
|
+
/**
|
|
19
|
+
* Replace the process-wide instance. Intended for tests and graceful
|
|
20
|
+
* shutdown paths; do not call from request handlers.
|
|
21
|
+
*
|
|
22
|
+
* @param next - Optional replacement; when omitted, the singleton is cleared
|
|
23
|
+
*/
|
|
24
|
+
export declare function setChatV2ServiceForTesting(next: ChatV2Service | null): void;
|
|
25
|
+
/** Close the current instance (if any) and clear the singleton. */
|
|
26
|
+
export declare function resetChatV2Service(): void;
|
|
27
|
+
//# sourceMappingURL=chat-v2.singleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.singleton.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.singleton.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAKhF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,aAAa,CAgBzF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAS3E;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide singleton accessor for `ChatV2Service`.
|
|
3
|
+
*
|
|
4
|
+
* The server wiring layer calls `getChatV2Service()` once and holds the
|
|
5
|
+
* reference; tests can `resetChatV2Service()` to start fresh.
|
|
6
|
+
*
|
|
7
|
+
* @module services/chat-v2/chat-v2.singleton
|
|
8
|
+
*/
|
|
9
|
+
import { ChatV2Service } from './chat-v2.service.js';
|
|
10
|
+
import { loadChatV2Config } from './config.js';
|
|
11
|
+
let _instance = null;
|
|
12
|
+
/**
|
|
13
|
+
* Return the process-wide `ChatV2Service`, constructing it on first call.
|
|
14
|
+
*
|
|
15
|
+
* @param overrides - Optional overrides passed when first constructed.
|
|
16
|
+
* Ignored on subsequent calls.
|
|
17
|
+
* @returns The shared service instance
|
|
18
|
+
*/
|
|
19
|
+
export function getChatV2Service(overrides) {
|
|
20
|
+
if (!_instance) {
|
|
21
|
+
const config = overrides?.config ?? loadChatV2Config();
|
|
22
|
+
_instance = new ChatV2Service({
|
|
23
|
+
config,
|
|
24
|
+
db: overrides?.db,
|
|
25
|
+
getPresence: overrides?.getPresence,
|
|
26
|
+
// F2b (#333) — forward the validator so the production composition
|
|
27
|
+
// root in backend/src/index.ts can wire a teamId-existence /
|
|
28
|
+
// tenant-membership check on the singleton on first construction.
|
|
29
|
+
// Subsequent calls ignore overrides (existing contract).
|
|
30
|
+
validateTeamMembership: overrides?.validateTeamMembership,
|
|
31
|
+
now: overrides?.now,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return _instance;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Replace the process-wide instance. Intended for tests and graceful
|
|
38
|
+
* shutdown paths; do not call from request handlers.
|
|
39
|
+
*
|
|
40
|
+
* @param next - Optional replacement; when omitted, the singleton is cleared
|
|
41
|
+
*/
|
|
42
|
+
export function setChatV2ServiceForTesting(next) {
|
|
43
|
+
if (_instance && _instance !== next) {
|
|
44
|
+
try {
|
|
45
|
+
_instance.close();
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// ignore — already closed
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
_instance = next;
|
|
52
|
+
}
|
|
53
|
+
/** Close the current instance (if any) and clear the singleton. */
|
|
54
|
+
export function resetChatV2Service() {
|
|
55
|
+
setChatV2ServiceForTesting(null);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=chat-v2.singleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.singleton.js","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.singleton.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAA6B,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,IAAI,SAAS,GAAyB,IAAI,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAyC;IACxE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,SAAS,EAAE,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACvD,SAAS,GAAG,IAAI,aAAa,CAAC;YAC5B,MAAM;YACN,EAAE,EAAE,SAAS,EAAE,EAAE;YACjB,WAAW,EAAE,SAAS,EAAE,WAAW;YACnC,mEAAmE;YACnE,6DAA6D;YAC7D,kEAAkE;YAClE,yDAAyD;YACzD,sBAAsB,EAAE,SAAS,EAAE,sBAAsB;YACzD,GAAG,EAAE,SAAS,EAAE,GAAG;SACpB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAA0B;IACnE,IAAI,SAAS,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,0BAA0B;QAC5B,CAAC;IACH,CAAC;IACD,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,kBAAkB;IAChC,0BAA0B,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OSS team-membership validator for `ChatV2Service.validateTeamMembership`.
|
|
3
|
+
*
|
|
4
|
+
* Phase C F2b (issue #333) — outer-ring tenant defense for type='channel'
|
|
5
|
+
* channel creation. The chat service's optional `validateTeamMembership`
|
|
6
|
+
* dependency is invoked when a caller binds a channel to a `teamId`; if
|
|
7
|
+
* the principal is not authorized for that team, the service throws
|
|
8
|
+
* `forbidden_team` (HTTP 403) before persisting the row.
|
|
9
|
+
*
|
|
10
|
+
* In OSS single-user mode there is no per-user tenant binding — the
|
|
11
|
+
* single user owns every team in their workspace. The right semantic is
|
|
12
|
+
* therefore "the team must exist" (you cannot bind a channel to a team
|
|
13
|
+
* id you fabricated). Cloud Portal Phase E swaps in a tenant-aware
|
|
14
|
+
* validator that checks the user's tenant membership against the team's
|
|
15
|
+
* tenant.
|
|
16
|
+
*
|
|
17
|
+
* Implementation: `existsSync` of `<teamsDir>/<teamId>/config.json`. Sync
|
|
18
|
+
* by design — `ChatV2Service.createChannel` runs inside the synchronous
|
|
19
|
+
* `runHandler` controller wrapper. Async refactors are a Phase E concern.
|
|
20
|
+
*
|
|
21
|
+
* @module services/chat-v2/chat-v2.team-membership
|
|
22
|
+
*/
|
|
23
|
+
import type { ChatPrincipal } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Build the OSS validator. Captures the StorageService instance lazily so
|
|
26
|
+
* the singleton resolves correctly even when `getInstance()` lands later
|
|
27
|
+
* in module-init order (matches the existing `loadTeams` injection
|
|
28
|
+
* pattern in chat-v2 wiring).
|
|
29
|
+
*
|
|
30
|
+
* @param deps - Optional dependency overrides for tests.
|
|
31
|
+
* @returns A sync validator suitable for `ChatV2ServiceOptions.validateTeamMembership`.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const validator = createOssTeamMembershipValidator();
|
|
35
|
+
* const service = getChatV2Service({ validateTeamMembership: validator });
|
|
36
|
+
*/
|
|
37
|
+
export declare function createOssTeamMembershipValidator(deps?: {
|
|
38
|
+
/** Resolves the per-team config dir. Defaults to StorageService singleton. */
|
|
39
|
+
getTeamDir?: (teamId: string) => string;
|
|
40
|
+
/** Existence check. Override in tests to avoid touching the real FS. */
|
|
41
|
+
fileExists?: (filePath: string) => boolean;
|
|
42
|
+
}): (principal: ChatPrincipal, teamId: string) => boolean;
|
|
43
|
+
//# sourceMappingURL=chat-v2.team-membership.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-v2.team-membership.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.team-membership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,GAAE;IACJ,8EAA8E;IAC9E,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,wEAAwE;IACxE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC,GACL,CAAC,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAgBvD"}
|