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,759 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Active Work Briefing Service
|
|
3
|
+
*
|
|
4
|
+
* Generates an authoritative-state briefing for an agent at session startup
|
|
5
|
+
* (and on-demand mid-session via the `core/get-my-active-work` skill).
|
|
6
|
+
*
|
|
7
|
+
* Today the agent recovery prompt is memory-only — `SessionMemoryService`
|
|
8
|
+
* dumps the last session summary, agent/project knowledge, daily logs, and
|
|
9
|
+
* recent learning files. That is supplementary; it does NOT capture
|
|
10
|
+
* authoritative runtime state. Symptom: an agent restarts amnesiac about
|
|
11
|
+
* Requests it owes a reply on, queued WorkItems that survived the restart,
|
|
12
|
+
* and in-flight delegations.
|
|
13
|
+
*
|
|
14
|
+
* This service mirrors `SessionMemoryService` (`generate*` + `format*`
|
|
15
|
+
* methods, singleton, soft-fail wrapping at the call site) and produces a
|
|
16
|
+
* per-agent slice of the live Request + WorkItem state. The briefing is
|
|
17
|
+
* prepended ABOVE the memory briefing in the agent's startup prompt so the
|
|
18
|
+
* first thing the agent reads is "what am I on the hook for RIGHT NOW".
|
|
19
|
+
*
|
|
20
|
+
* Sources:
|
|
21
|
+
* - {@link RequestService.listAll} — all Requests on disk
|
|
22
|
+
* - {@link TaskPoolService.getAllItems} — all WorkItems in the pool
|
|
23
|
+
*
|
|
24
|
+
* Design doc: `/tmp/agent-state-recovery-design.md` (architect output)
|
|
25
|
+
* GitHub issue: stevehuang0115/crewly#395
|
|
26
|
+
*
|
|
27
|
+
* @module services/agent/active-work-briefing.service
|
|
28
|
+
*/
|
|
29
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
30
|
+
import { ORCHESTRATOR_ROLE, ORCHESTRATOR_SESSION_NAME } from '../../constants.js';
|
|
31
|
+
/**
|
|
32
|
+
* Default per-section item caps for non-orchestrator agents.
|
|
33
|
+
* Total cap = 45 items, ~6,300 chars (~1,500 tokens).
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_CAPS = {
|
|
36
|
+
openRequests: 10,
|
|
37
|
+
activeWorkItems: 15,
|
|
38
|
+
pendingReviews: 5,
|
|
39
|
+
outboundDelegations: 10,
|
|
40
|
+
recentlyAutoResolved: 5,
|
|
41
|
+
};
|
|
42
|
+
/** Orchestrator gets system-wide visibility — caps × 3. */
|
|
43
|
+
const ORCHESTRATOR_CAP_MULTIPLIER = 3;
|
|
44
|
+
/**
|
|
45
|
+
* Hard ceiling on the orchestrator's formatted briefing (chars). If the
|
|
46
|
+
* formatted markdown crosses this threshold, the formatter drops description
|
|
47
|
+
* fields to keep the prompt tractable. Bounded — does not truncate items.
|
|
48
|
+
*/
|
|
49
|
+
const ORCHESTRATOR_OVERFLOW_CHARS = 25_000;
|
|
50
|
+
/** Default recently-resolved window: 30 minutes. */
|
|
51
|
+
const DEFAULT_RECENTLY_RESOLVED_WINDOW_MS = 30 * 60 * 1000;
|
|
52
|
+
/** Per-item title cap to prevent unbounded growth. */
|
|
53
|
+
const MAX_TITLE_CHARS = 80;
|
|
54
|
+
/** Per-item description cap. */
|
|
55
|
+
const MAX_DESCRIPTION_CHARS = 120;
|
|
56
|
+
/**
|
|
57
|
+
* Request statuses that count as "open / on the hook" for briefing
|
|
58
|
+
* inclusion. Terminal statuses (`done`, `cancelled`) are excluded —
|
|
59
|
+
* memory recall handles "what did I close last week".
|
|
60
|
+
*/
|
|
61
|
+
const ACTIVE_REQUEST_STATUSES = new Set([
|
|
62
|
+
'open',
|
|
63
|
+
'ready',
|
|
64
|
+
'running',
|
|
65
|
+
'blocked',
|
|
66
|
+
'waiting_confirmation',
|
|
67
|
+
]);
|
|
68
|
+
/**
|
|
69
|
+
* WorkItem statuses that are still "in-flight" for the agent (target of a
|
|
70
|
+
* claim or work). Terminal statuses (`done`, `verified`, `cancelled`,
|
|
71
|
+
* `failed`, `rejected`) are excluded — they are recovered via memory.
|
|
72
|
+
*/
|
|
73
|
+
const ACTIVE_WORK_ITEM_STATUSES = new Set([
|
|
74
|
+
'queued',
|
|
75
|
+
'scheduled',
|
|
76
|
+
'proposed',
|
|
77
|
+
'accepted',
|
|
78
|
+
'running',
|
|
79
|
+
'blocked',
|
|
80
|
+
'escalated',
|
|
81
|
+
]);
|
|
82
|
+
/** Status indicating a WorkItem is awaiting verifier review. */
|
|
83
|
+
const PENDING_REVIEW_STATUS = 'done_by_worker';
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Service
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
/**
|
|
88
|
+
* Singleton service producing per-agent active-work briefings.
|
|
89
|
+
*
|
|
90
|
+
* Mirrors the `SessionMemoryService.generate* + format*` shape so the
|
|
91
|
+
* `agent-registration.service.ts` glue can call them in parallel and
|
|
92
|
+
* concatenate the markdown.
|
|
93
|
+
*
|
|
94
|
+
* Stateless beyond singleton bookkeeping — every call hits the live
|
|
95
|
+
* `RequestService` + `TaskPoolService` instances.
|
|
96
|
+
*/
|
|
97
|
+
export class ActiveWorkBriefingService {
|
|
98
|
+
requestServiceFactory;
|
|
99
|
+
taskPoolFactory;
|
|
100
|
+
static instance = null;
|
|
101
|
+
logger;
|
|
102
|
+
/**
|
|
103
|
+
* Private constructor — use {@link getInstance}. The `requestServiceFactory`
|
|
104
|
+
* and `taskPoolFactory` are dependency seams for tests; production code
|
|
105
|
+
* lets {@link getInstance} provide the live singletons.
|
|
106
|
+
*/
|
|
107
|
+
constructor(requestServiceFactory, taskPoolFactory) {
|
|
108
|
+
this.requestServiceFactory = requestServiceFactory;
|
|
109
|
+
this.taskPoolFactory = taskPoolFactory;
|
|
110
|
+
this.logger = LoggerService.getInstance().createComponentLogger('ActiveWorkBriefingService');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Returns the singleton instance.
|
|
114
|
+
*
|
|
115
|
+
* The `RequestService` and `TaskPoolService` modules are loaded LAZILY here
|
|
116
|
+
* (CommonJS `require` rather than top-of-file `import`) so that consumers
|
|
117
|
+
* of this module do not pay the import cost — and more importantly, do not
|
|
118
|
+
* transitively load `chokidar` via `v3-data.service.ts` — until they
|
|
119
|
+
* actually call `getInstance()`. This keeps the agent-registration test
|
|
120
|
+
* suite mockable without forcing every caller to mock the v3 pipeline.
|
|
121
|
+
*/
|
|
122
|
+
static getInstance() {
|
|
123
|
+
if (!ActiveWorkBriefingService.instance) {
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
|
125
|
+
const { RequestService } = require('../v3/request.service.js');
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
|
127
|
+
const { TaskPoolService } = require('../task-pool/task-pool.service.js');
|
|
128
|
+
ActiveWorkBriefingService.instance = new ActiveWorkBriefingService(() => RequestService.getInstance(), () => TaskPoolService.getInstance());
|
|
129
|
+
}
|
|
130
|
+
return ActiveWorkBriefingService.instance;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Resets the singleton — for tests only.
|
|
134
|
+
*/
|
|
135
|
+
static resetInstance() {
|
|
136
|
+
ActiveWorkBriefingService.instance = null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Test-only escape hatch to swap the underlying service factories.
|
|
140
|
+
* Production code never calls this; the public surface is the singleton.
|
|
141
|
+
*
|
|
142
|
+
* @param requestServiceFactory - Returns a `listAll` provider
|
|
143
|
+
* @param taskPoolFactory - Returns a `getAllItems` provider
|
|
144
|
+
*/
|
|
145
|
+
static createForTest(requestServiceFactory, taskPoolFactory) {
|
|
146
|
+
return new ActiveWorkBriefingService(requestServiceFactory, taskPoolFactory);
|
|
147
|
+
}
|
|
148
|
+
// -------------------------------------------------------------------------
|
|
149
|
+
// Internal helpers
|
|
150
|
+
// -------------------------------------------------------------------------
|
|
151
|
+
/**
|
|
152
|
+
* Compute the effective per-section caps for the requested role. Orchestrator
|
|
153
|
+
* gets caps × 3 for system-wide visibility; everyone else uses the defaults
|
|
154
|
+
* (with optional overrides from {@link GenerateOptions.caps}).
|
|
155
|
+
*
|
|
156
|
+
* @param role - Agent role (orchestrator gets the multiplier)
|
|
157
|
+
* @param overrides - Optional explicit caps that win over both defaults and
|
|
158
|
+
* the role multiplier.
|
|
159
|
+
* @returns Effective caps for each section
|
|
160
|
+
*/
|
|
161
|
+
resolveCaps(role, overrides) {
|
|
162
|
+
const isOrchestrator = role === ORCHESTRATOR_ROLE;
|
|
163
|
+
const multiplier = isOrchestrator ? ORCHESTRATOR_CAP_MULTIPLIER : 1;
|
|
164
|
+
return {
|
|
165
|
+
openRequests: overrides?.openRequests ?? DEFAULT_CAPS.openRequests * multiplier,
|
|
166
|
+
activeWorkItems: overrides?.activeWorkItems ?? DEFAULT_CAPS.activeWorkItems * multiplier,
|
|
167
|
+
pendingReviews: overrides?.pendingReviews ?? DEFAULT_CAPS.pendingReviews * multiplier,
|
|
168
|
+
outboundDelegations: overrides?.outboundDelegations ?? DEFAULT_CAPS.outboundDelegations * multiplier,
|
|
169
|
+
recentlyAutoResolved: overrides?.recentlyAutoResolved ?? DEFAULT_CAPS.recentlyAutoResolved * multiplier,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Convert a 'low' | 'normal' | 'high' priority to a sort key.
|
|
174
|
+
* Higher number = higher priority (sorted DESC).
|
|
175
|
+
*
|
|
176
|
+
* @param p - Priority value
|
|
177
|
+
* @returns Numeric sort key
|
|
178
|
+
*/
|
|
179
|
+
priorityRank(p) {
|
|
180
|
+
switch (p) {
|
|
181
|
+
case 'high':
|
|
182
|
+
return 3;
|
|
183
|
+
case 'normal':
|
|
184
|
+
return 2;
|
|
185
|
+
case 'low':
|
|
186
|
+
return 1;
|
|
187
|
+
default:
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Compute age in hours since `createdAt`. Negative or NaN inputs are
|
|
193
|
+
* coerced to 0 — defensive against malformed timestamps.
|
|
194
|
+
*
|
|
195
|
+
* @param createdAt - ISO8601 timestamp
|
|
196
|
+
* @param nowMs - Current time in milliseconds
|
|
197
|
+
* @returns Age in hours (>= 0)
|
|
198
|
+
*/
|
|
199
|
+
ageHours(createdAt, nowMs) {
|
|
200
|
+
const created = new Date(createdAt).getTime();
|
|
201
|
+
if (!Number.isFinite(created))
|
|
202
|
+
return 0;
|
|
203
|
+
const diff = nowMs - created;
|
|
204
|
+
return diff > 0 ? diff / (60 * 60 * 1000) : 0;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Read a string-typed field from a `metadata` blob, or null if missing /
|
|
208
|
+
* not a string. WorkItem.metadata is typed as `Record<string, unknown>` so
|
|
209
|
+
* every read needs this guard.
|
|
210
|
+
*
|
|
211
|
+
* @param metadata - WorkItem.metadata or undefined
|
|
212
|
+
* @param key - Field name to read
|
|
213
|
+
* @returns Trimmed string value or null
|
|
214
|
+
*/
|
|
215
|
+
readMetadataString(metadata, key) {
|
|
216
|
+
if (!metadata)
|
|
217
|
+
return null;
|
|
218
|
+
const value = metadata[key];
|
|
219
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
220
|
+
return null;
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Apply the per-section cap. Returns the slice + a {@link SectionTruncation}
|
|
225
|
+
* object that the formatter renders as a "... and X more" marker.
|
|
226
|
+
*
|
|
227
|
+
* @param items - Sorted candidate rows
|
|
228
|
+
* @param cap - Per-section cap
|
|
229
|
+
* @returns Truncation metadata + the kept rows
|
|
230
|
+
*/
|
|
231
|
+
applyCap(items, cap) {
|
|
232
|
+
const rows = items.slice(0, cap);
|
|
233
|
+
return {
|
|
234
|
+
rows,
|
|
235
|
+
truncation: {
|
|
236
|
+
totalCandidates: items.length,
|
|
237
|
+
cap,
|
|
238
|
+
truncated: items.length > cap,
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
// -------------------------------------------------------------------------
|
|
243
|
+
// Filter / project — Request rows
|
|
244
|
+
// -------------------------------------------------------------------------
|
|
245
|
+
/**
|
|
246
|
+
* Project Requests visible to this agent. Non-orchestrator agents only see
|
|
247
|
+
* Requests where they are the `ownerAgent`; the orchestrator sees all open
|
|
248
|
+
* Requests system-wide.
|
|
249
|
+
*
|
|
250
|
+
* @param requests - All Requests from {@link RequestService.listAll}
|
|
251
|
+
* @param sessionName - Agent session name
|
|
252
|
+
* @param role - Agent role
|
|
253
|
+
* @param nowMs - "Now" for age computation
|
|
254
|
+
* @returns Sorted candidate rows (priority DESC, then age DESC — older first)
|
|
255
|
+
*/
|
|
256
|
+
projectRequests(requests, sessionName, role, nowMs) {
|
|
257
|
+
const isOrchestrator = role === ORCHESTRATOR_ROLE || sessionName === ORCHESTRATOR_SESSION_NAME;
|
|
258
|
+
const filtered = requests.filter((r) => {
|
|
259
|
+
if (!ACTIVE_REQUEST_STATUSES.has(r.status))
|
|
260
|
+
return false;
|
|
261
|
+
if (isOrchestrator)
|
|
262
|
+
return true;
|
|
263
|
+
// Non-orchestrator agents: must be on the hook (ownerAgent === sessionName).
|
|
264
|
+
return r.ownerAgent === sessionName;
|
|
265
|
+
});
|
|
266
|
+
const rows = filtered.map((r) => ({
|
|
267
|
+
id: r.id,
|
|
268
|
+
title: this.truncateTitle(r.title),
|
|
269
|
+
status: r.status,
|
|
270
|
+
priority: r.priority,
|
|
271
|
+
ageHours: this.ageHours(r.createdAt, nowMs),
|
|
272
|
+
source: r.sourceConversationItemId,
|
|
273
|
+
}));
|
|
274
|
+
rows.sort((a, b) => this.priorityRank(b.priority) - this.priorityRank(a.priority) ||
|
|
275
|
+
b.ageHours - a.ageHours);
|
|
276
|
+
return rows;
|
|
277
|
+
}
|
|
278
|
+
// -------------------------------------------------------------------------
|
|
279
|
+
// Filter / project — WorkItem rows
|
|
280
|
+
// -------------------------------------------------------------------------
|
|
281
|
+
/**
|
|
282
|
+
* Project active WorkItems for this agent: items the agent is on the hook
|
|
283
|
+
* to execute (target=me) OR items the agent has actively claimed
|
|
284
|
+
* (claimedBy=me, surfaced via `metadata.claimedBy`). Items targeted at this
|
|
285
|
+
* agent but already claimed by *another* agent are excluded — they are
|
|
286
|
+
* not actionable for the current session.
|
|
287
|
+
*
|
|
288
|
+
* Orchestrator override: include ALL active work items.
|
|
289
|
+
*
|
|
290
|
+
* @param items - All WorkItems from {@link TaskPoolService.getAllItems}
|
|
291
|
+
* @param sessionName - Agent session name
|
|
292
|
+
* @param role - Agent role
|
|
293
|
+
* @param nowMs - "Now" for age computation
|
|
294
|
+
* @returns Sorted candidate rows
|
|
295
|
+
*/
|
|
296
|
+
projectActiveWorkItems(items, sessionName, role, nowMs) {
|
|
297
|
+
const isOrchestrator = role === ORCHESTRATOR_ROLE || sessionName === ORCHESTRATOR_SESSION_NAME;
|
|
298
|
+
const filtered = items.filter((wi) => {
|
|
299
|
+
if (!ACTIVE_WORK_ITEM_STATUSES.has(wi.status))
|
|
300
|
+
return false;
|
|
301
|
+
if (isOrchestrator)
|
|
302
|
+
return true;
|
|
303
|
+
const claimedBy = this.readMetadataString(wi.metadata, 'claimedBy');
|
|
304
|
+
const isTargetMe = wi.target === sessionName;
|
|
305
|
+
const isClaimedByMe = claimedBy === sessionName;
|
|
306
|
+
if (!isTargetMe && !isClaimedByMe)
|
|
307
|
+
return false;
|
|
308
|
+
// Excluded: target is me but another agent already claimed it.
|
|
309
|
+
if (isTargetMe && claimedBy && claimedBy !== sessionName)
|
|
310
|
+
return false;
|
|
311
|
+
return true;
|
|
312
|
+
});
|
|
313
|
+
const rows = filtered.map((wi) => ({
|
|
314
|
+
id: wi.id,
|
|
315
|
+
title: this.truncateTitle(wi.title),
|
|
316
|
+
status: wi.status,
|
|
317
|
+
ageHours: this.ageHours(wi.createdAt, nowMs),
|
|
318
|
+
priority: this.readPriorityFromMetadata(wi.metadata),
|
|
319
|
+
requestId: wi.requestId,
|
|
320
|
+
description: wi.description ? this.truncateDescription(wi.description) : undefined,
|
|
321
|
+
}));
|
|
322
|
+
rows.sort((a, b) => this.priorityRank(b.priority) - this.priorityRank(a.priority) ||
|
|
323
|
+
b.ageHours - a.ageHours);
|
|
324
|
+
return rows;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Pending review rows — WorkItems in `done_by_worker` where this agent
|
|
328
|
+
* is the verifier. Verifier signal = `metadata.verifier === sessionName`
|
|
329
|
+
* (TL/orchestrator pattern). For the orchestrator role we surface ALL
|
|
330
|
+
* `done_by_worker` items system-wide.
|
|
331
|
+
*
|
|
332
|
+
* @param items - All WorkItems from the pool
|
|
333
|
+
* @param sessionName - Agent session name
|
|
334
|
+
* @param role - Agent role
|
|
335
|
+
* @param nowMs - "Now" for age computation
|
|
336
|
+
* @returns Sorted candidate rows (oldest first — review backlog)
|
|
337
|
+
*/
|
|
338
|
+
projectPendingReviews(items, sessionName, role, nowMs) {
|
|
339
|
+
const isOrchestrator = role === ORCHESTRATOR_ROLE || sessionName === ORCHESTRATOR_SESSION_NAME;
|
|
340
|
+
const filtered = items.filter((wi) => {
|
|
341
|
+
if (wi.status !== PENDING_REVIEW_STATUS)
|
|
342
|
+
return false;
|
|
343
|
+
if (isOrchestrator)
|
|
344
|
+
return true;
|
|
345
|
+
const verifier = this.readMetadataString(wi.metadata, 'verifier');
|
|
346
|
+
return verifier === sessionName;
|
|
347
|
+
});
|
|
348
|
+
const rows = filtered.map((wi) => ({
|
|
349
|
+
id: wi.id,
|
|
350
|
+
title: this.truncateTitle(wi.title),
|
|
351
|
+
ageHours: this.ageHours(wi.createdAt, nowMs),
|
|
352
|
+
claimedBy: this.readMetadataString(wi.metadata, 'claimedBy') ?? undefined,
|
|
353
|
+
}));
|
|
354
|
+
// Oldest first — review backlog should be drained FIFO.
|
|
355
|
+
rows.sort((a, b) => b.ageHours - a.ageHours);
|
|
356
|
+
return rows;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Outbound delegations — WorkItems this agent delegated and that haven't
|
|
360
|
+
* resolved yet. Identified by `metadata.delegatedBy === sessionName`.
|
|
361
|
+
* Forward-compatible: if upstream code does not yet populate
|
|
362
|
+
* `metadata.delegatedBy`, this section is empty.
|
|
363
|
+
*
|
|
364
|
+
* @param items - All WorkItems from the pool
|
|
365
|
+
* @param sessionName - Agent session name
|
|
366
|
+
* @param nowMs - "Now" for age computation
|
|
367
|
+
* @returns Sorted candidate rows
|
|
368
|
+
*/
|
|
369
|
+
projectOutboundDelegations(items, sessionName, nowMs) {
|
|
370
|
+
const filtered = items.filter((wi) => {
|
|
371
|
+
if (!ACTIVE_WORK_ITEM_STATUSES.has(wi.status))
|
|
372
|
+
return false;
|
|
373
|
+
const delegatedBy = this.readMetadataString(wi.metadata, 'delegatedBy');
|
|
374
|
+
return delegatedBy === sessionName;
|
|
375
|
+
});
|
|
376
|
+
const rows = filtered.map((wi) => ({
|
|
377
|
+
id: wi.id,
|
|
378
|
+
title: this.truncateTitle(wi.title),
|
|
379
|
+
status: wi.status,
|
|
380
|
+
ageHours: this.ageHours(wi.createdAt, nowMs),
|
|
381
|
+
target: wi.target,
|
|
382
|
+
}));
|
|
383
|
+
rows.sort((a, b) => b.ageHours - a.ageHours);
|
|
384
|
+
return rows;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Recently auto-resolved WorkItems within the configured window
|
|
388
|
+
* (default 30 minutes). Surfaced so the agent knows what closed
|
|
389
|
+
* automatically while it was down. Identified by
|
|
390
|
+
* `metadata.slaResolvedAt` falling inside the window.
|
|
391
|
+
*
|
|
392
|
+
* @param items - All WorkItems from the pool
|
|
393
|
+
* @param sessionName - Agent session name (filters to items relevant to this agent)
|
|
394
|
+
* @param role - Agent role
|
|
395
|
+
* @param nowMs - "Now" for age computation
|
|
396
|
+
* @param windowMs - Window size in milliseconds
|
|
397
|
+
* @returns Sorted candidate rows (most recent first)
|
|
398
|
+
*/
|
|
399
|
+
projectRecentlyResolved(items, sessionName, role, nowMs, windowMs) {
|
|
400
|
+
const isOrchestrator = role === ORCHESTRATOR_ROLE || sessionName === ORCHESTRATOR_SESSION_NAME;
|
|
401
|
+
const cutoff = nowMs - windowMs;
|
|
402
|
+
const filtered = items.filter((wi) => {
|
|
403
|
+
const resolvedAt = this.readMetadataString(wi.metadata, 'slaResolvedAt');
|
|
404
|
+
if (!resolvedAt)
|
|
405
|
+
return false;
|
|
406
|
+
const ts = new Date(resolvedAt).getTime();
|
|
407
|
+
if (!Number.isFinite(ts))
|
|
408
|
+
return false;
|
|
409
|
+
if (ts < cutoff)
|
|
410
|
+
return false;
|
|
411
|
+
if (isOrchestrator)
|
|
412
|
+
return true;
|
|
413
|
+
const claimedBy = this.readMetadataString(wi.metadata, 'claimedBy');
|
|
414
|
+
const delegatedBy = this.readMetadataString(wi.metadata, 'delegatedBy');
|
|
415
|
+
return (wi.target === sessionName ||
|
|
416
|
+
claimedBy === sessionName ||
|
|
417
|
+
delegatedBy === sessionName);
|
|
418
|
+
});
|
|
419
|
+
const rows = filtered.map((wi) => ({
|
|
420
|
+
id: wi.id,
|
|
421
|
+
title: this.truncateTitle(wi.title),
|
|
422
|
+
resolvedAt: this.readMetadataString(wi.metadata, 'slaResolvedAt') ?? '',
|
|
423
|
+
resolvedReason: this.readMetadataString(wi.metadata, 'slaResolvedReason') ?? undefined,
|
|
424
|
+
}));
|
|
425
|
+
rows.sort((a, b) => new Date(b.resolvedAt).getTime() - new Date(a.resolvedAt).getTime());
|
|
426
|
+
return rows;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Read a priority hint from WorkItem.metadata. Falls back to `'normal'`.
|
|
430
|
+
*
|
|
431
|
+
* @param metadata - WorkItem metadata blob
|
|
432
|
+
* @returns Briefing priority
|
|
433
|
+
*/
|
|
434
|
+
readPriorityFromMetadata(metadata) {
|
|
435
|
+
const raw = this.readMetadataString(metadata, 'priority');
|
|
436
|
+
if (raw === 'high' || raw === 'normal' || raw === 'low')
|
|
437
|
+
return raw;
|
|
438
|
+
return 'normal';
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Truncate a row title to {@link MAX_TITLE_CHARS}.
|
|
442
|
+
*
|
|
443
|
+
* @param title - Raw title
|
|
444
|
+
* @returns Truncated title (with ellipsis suffix if cut)
|
|
445
|
+
*/
|
|
446
|
+
truncateTitle(title) {
|
|
447
|
+
if (title.length <= MAX_TITLE_CHARS)
|
|
448
|
+
return title;
|
|
449
|
+
return title.slice(0, MAX_TITLE_CHARS - 1) + '…';
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Truncate a row description to {@link MAX_DESCRIPTION_CHARS}. Replaces
|
|
453
|
+
* newlines with spaces so a description never wraps the briefing layout.
|
|
454
|
+
*
|
|
455
|
+
* @param desc - Raw description
|
|
456
|
+
* @returns Truncated description
|
|
457
|
+
*/
|
|
458
|
+
truncateDescription(desc) {
|
|
459
|
+
const oneLine = desc.replace(/\s+/g, ' ').trim();
|
|
460
|
+
if (oneLine.length <= MAX_DESCRIPTION_CHARS)
|
|
461
|
+
return oneLine;
|
|
462
|
+
return oneLine.slice(0, MAX_DESCRIPTION_CHARS - 1) + '…';
|
|
463
|
+
}
|
|
464
|
+
// -------------------------------------------------------------------------
|
|
465
|
+
// Public API — generate
|
|
466
|
+
// -------------------------------------------------------------------------
|
|
467
|
+
/**
|
|
468
|
+
* Generates an active-work briefing for the given agent.
|
|
469
|
+
*
|
|
470
|
+
* Pulls from {@link RequestService} + {@link TaskPoolService}, filters
|
|
471
|
+
* to the agent's slice (orchestrator gets system-wide), applies per-section
|
|
472
|
+
* caps, and returns the structured payload. The caller renders it via
|
|
473
|
+
* {@link formatBriefingAsMarkdown}.
|
|
474
|
+
*
|
|
475
|
+
* Soft-fail policy: any error from the underlying services bubbles up.
|
|
476
|
+
* The CALL SITE in `agent-registration.service.ts` wraps this in a try/catch
|
|
477
|
+
* with WARN-level logging — we deliberately do NOT swallow errors here so
|
|
478
|
+
* test scenarios can assert that the rejection occurs, and so the optional
|
|
479
|
+
* skill endpoint can return a structured 500 response.
|
|
480
|
+
*
|
|
481
|
+
* @param sessionName - Agent session name (e.g. `crewly-product-sam-dd2b46f7`)
|
|
482
|
+
* @param role - Agent role (`developer`, `orchestrator`, etc.)
|
|
483
|
+
* @param options - Optional caps + window overrides for testing
|
|
484
|
+
* @returns The structured briefing
|
|
485
|
+
*
|
|
486
|
+
* @throws Rethrows any error from {@link RequestService.listAll} or
|
|
487
|
+
* {@link TaskPoolService.getAllItems}.
|
|
488
|
+
*
|
|
489
|
+
* @example
|
|
490
|
+
* ```typescript
|
|
491
|
+
* const briefing = await ActiveWorkBriefingService.getInstance()
|
|
492
|
+
* .generateActiveWorkBriefing('dev-001', 'developer');
|
|
493
|
+
* const md = ActiveWorkBriefingService.getInstance()
|
|
494
|
+
* .formatBriefingAsMarkdown(briefing);
|
|
495
|
+
* ```
|
|
496
|
+
*/
|
|
497
|
+
async generateActiveWorkBriefing(sessionName, role, options = {}) {
|
|
498
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
499
|
+
const windowMs = options.recentlyResolvedWindowMs ?? DEFAULT_RECENTLY_RESOLVED_WINDOW_MS;
|
|
500
|
+
const caps = this.resolveCaps(role, options.caps);
|
|
501
|
+
// Fetch in parallel — both services are independent.
|
|
502
|
+
const [requests, workItems] = await Promise.all([
|
|
503
|
+
this.requestServiceFactory().listAll(),
|
|
504
|
+
this.taskPoolFactory().getAllItems(),
|
|
505
|
+
]);
|
|
506
|
+
const openRequestsAll = this.projectRequests(requests, sessionName, role, nowMs);
|
|
507
|
+
const activeWorkItemsAll = this.projectActiveWorkItems(workItems, sessionName, role, nowMs);
|
|
508
|
+
const pendingReviewsAll = this.projectPendingReviews(workItems, sessionName, role, nowMs);
|
|
509
|
+
const outboundDelegationsAll = this.projectOutboundDelegations(workItems, sessionName, nowMs);
|
|
510
|
+
const recentlyAutoResolvedAll = this.projectRecentlyResolved(workItems, sessionName, role, nowMs, windowMs);
|
|
511
|
+
const openRequests = this.applyCap(openRequestsAll, caps.openRequests);
|
|
512
|
+
const activeWorkItems = this.applyCap(activeWorkItemsAll, caps.activeWorkItems);
|
|
513
|
+
const pendingReviews = this.applyCap(pendingReviewsAll, caps.pendingReviews);
|
|
514
|
+
const outboundDelegations = this.applyCap(outboundDelegationsAll, caps.outboundDelegations);
|
|
515
|
+
const recentlyAutoResolved = this.applyCap(recentlyAutoResolvedAll, caps.recentlyAutoResolved);
|
|
516
|
+
const truncated = openRequests.truncation.truncated ||
|
|
517
|
+
activeWorkItems.truncation.truncated ||
|
|
518
|
+
pendingReviews.truncation.truncated ||
|
|
519
|
+
outboundDelegations.truncation.truncated ||
|
|
520
|
+
recentlyAutoResolved.truncation.truncated;
|
|
521
|
+
return {
|
|
522
|
+
openRequests: openRequests.rows,
|
|
523
|
+
activeWorkItems: activeWorkItems.rows,
|
|
524
|
+
pendingReviews: pendingReviews.rows,
|
|
525
|
+
outboundDelegations: outboundDelegations.rows,
|
|
526
|
+
recentlyAutoResolved: recentlyAutoResolved.rows,
|
|
527
|
+
truncation: {
|
|
528
|
+
openRequests: openRequests.truncation,
|
|
529
|
+
activeWorkItems: activeWorkItems.truncation,
|
|
530
|
+
pendingReviews: pendingReviews.truncation,
|
|
531
|
+
outboundDelegations: outboundDelegations.truncation,
|
|
532
|
+
recentlyAutoResolved: recentlyAutoResolved.truncation,
|
|
533
|
+
},
|
|
534
|
+
truncated,
|
|
535
|
+
generatedAt: new Date(nowMs).toISOString(),
|
|
536
|
+
totalCounts: {
|
|
537
|
+
requests: requests.length,
|
|
538
|
+
workItems: workItems.length,
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
// -------------------------------------------------------------------------
|
|
543
|
+
// Public API — format
|
|
544
|
+
// -------------------------------------------------------------------------
|
|
545
|
+
/**
|
|
546
|
+
* Format a briefing as markdown suitable for prompt injection.
|
|
547
|
+
*
|
|
548
|
+
* Output structure:
|
|
549
|
+
*
|
|
550
|
+
* ```
|
|
551
|
+
* ## Your Active Work
|
|
552
|
+
*
|
|
553
|
+
* ### Open Requests
|
|
554
|
+
* - **request-abc** — Slack inbound — _open · 2h_ *(memory: marked done — verify)*
|
|
555
|
+
* ...
|
|
556
|
+
* ### Active WorkItems
|
|
557
|
+
* - **wi-123** — Implement feature X — _running · 1h_
|
|
558
|
+
* - desc here
|
|
559
|
+
* ...
|
|
560
|
+
* ```
|
|
561
|
+
*
|
|
562
|
+
* If a {@link MemoryHints} map is provided, contradicting memory notes are
|
|
563
|
+
* appended INLINE on each row, per design Q5/decision #2.
|
|
564
|
+
*
|
|
565
|
+
* Soft-formatting policy: empty briefing collapses to "(No active work —
|
|
566
|
+
* fresh start)". Sections with zero rows are omitted (no empty headings).
|
|
567
|
+
*
|
|
568
|
+
* @param briefing - Structured briefing payload
|
|
569
|
+
* @param memoryHints - Optional namespaced map of `req:<id>` / `wi:<id>` →
|
|
570
|
+
* short note string
|
|
571
|
+
* @returns Markdown string
|
|
572
|
+
*/
|
|
573
|
+
formatBriefingAsMarkdown(briefing, memoryHints) {
|
|
574
|
+
const totalRows = briefing.openRequests.length +
|
|
575
|
+
briefing.activeWorkItems.length +
|
|
576
|
+
briefing.pendingReviews.length +
|
|
577
|
+
briefing.outboundDelegations.length +
|
|
578
|
+
briefing.recentlyAutoResolved.length;
|
|
579
|
+
if (totalRows === 0) {
|
|
580
|
+
return '## Your Active Work\n\n(No active work — fresh start)';
|
|
581
|
+
}
|
|
582
|
+
const sections = ['## Your Active Work'];
|
|
583
|
+
// First pass — full description rendering. We may re-render in compact
|
|
584
|
+
// mode below if the orchestrator's briefing crosses the overflow ceiling.
|
|
585
|
+
sections.push(...this.renderSections(briefing, memoryHints, /* compact */ false));
|
|
586
|
+
let md = sections.join('\n\n').trim();
|
|
587
|
+
if (md.length > ORCHESTRATOR_OVERFLOW_CHARS) {
|
|
588
|
+
this.logger.debug('Active-work briefing exceeded overflow ceiling — re-rendering compact', {
|
|
589
|
+
chars: md.length,
|
|
590
|
+
ceiling: ORCHESTRATOR_OVERFLOW_CHARS,
|
|
591
|
+
});
|
|
592
|
+
const compact = ['## Your Active Work'];
|
|
593
|
+
compact.push(...this.renderSections(briefing, memoryHints, /* compact */ true));
|
|
594
|
+
md = compact.join('\n\n').trim();
|
|
595
|
+
}
|
|
596
|
+
return md;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Render the five briefing sub-sections to markdown lines. Pulled out of
|
|
600
|
+
* {@link formatBriefingAsMarkdown} so the overflow-recover path can reuse
|
|
601
|
+
* the same renderer with `compact=true` (drops descriptions to bound
|
|
602
|
+
* the orchestrator briefing).
|
|
603
|
+
*
|
|
604
|
+
* @param briefing - Briefing payload
|
|
605
|
+
* @param memoryHints - Optional contradiction notes
|
|
606
|
+
* @param compact - If true, drop description lines under WorkItem rows
|
|
607
|
+
* @returns Array of markdown blocks (joined by blank lines by caller)
|
|
608
|
+
*/
|
|
609
|
+
renderSections(briefing, memoryHints, compact) {
|
|
610
|
+
const out = [];
|
|
611
|
+
if (briefing.openRequests.length > 0) {
|
|
612
|
+
out.push(this.renderOpenRequests(briefing.openRequests, briefing.truncation.openRequests, memoryHints));
|
|
613
|
+
}
|
|
614
|
+
if (briefing.activeWorkItems.length > 0) {
|
|
615
|
+
out.push(this.renderActiveWorkItems(briefing.activeWorkItems, briefing.truncation.activeWorkItems, memoryHints, compact));
|
|
616
|
+
}
|
|
617
|
+
if (briefing.pendingReviews.length > 0) {
|
|
618
|
+
out.push(this.renderPendingReviews(briefing.pendingReviews, briefing.truncation.pendingReviews, memoryHints));
|
|
619
|
+
}
|
|
620
|
+
if (briefing.outboundDelegations.length > 0) {
|
|
621
|
+
out.push(this.renderOutboundDelegations(briefing.outboundDelegations, briefing.truncation.outboundDelegations, memoryHints));
|
|
622
|
+
}
|
|
623
|
+
if (briefing.recentlyAutoResolved.length > 0) {
|
|
624
|
+
out.push(this.renderRecentlyResolved(briefing.recentlyAutoResolved, briefing.truncation.recentlyAutoResolved, memoryHints));
|
|
625
|
+
}
|
|
626
|
+
return out;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Render the truncation marker line for a section. No-op when the section
|
|
630
|
+
* was not truncated.
|
|
631
|
+
*
|
|
632
|
+
* @param truncation - Section truncation metadata
|
|
633
|
+
* @returns Marker line (empty string if not truncated)
|
|
634
|
+
*/
|
|
635
|
+
renderTruncationMarker(truncation) {
|
|
636
|
+
if (!truncation.truncated)
|
|
637
|
+
return '';
|
|
638
|
+
const more = truncation.totalCandidates - truncation.cap;
|
|
639
|
+
return `\n_… and ${more} more (call \`get-my-active-work\` for full list)_`;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Append a memory-hint annotation to a row line, if a hint exists for the
|
|
643
|
+
* given key. Renders the annotation italicized so it visually subordinates
|
|
644
|
+
* to the actionable state row.
|
|
645
|
+
*
|
|
646
|
+
* @param line - Row line so far
|
|
647
|
+
* @param key - Hint lookup key (e.g. `req:abc-123`)
|
|
648
|
+
* @param hints - Memory hints map (optional)
|
|
649
|
+
* @returns The line with annotation appended, or unchanged
|
|
650
|
+
*/
|
|
651
|
+
appendMemoryHint(line, key, hints) {
|
|
652
|
+
if (!hints)
|
|
653
|
+
return line;
|
|
654
|
+
const note = hints.get(key);
|
|
655
|
+
if (!note)
|
|
656
|
+
return line;
|
|
657
|
+
return `${line} *(memory: ${note})*`;
|
|
658
|
+
}
|
|
659
|
+
/** Format hours into a compact "Nh" / "Nm" string for row metadata. */
|
|
660
|
+
formatAge(ageHours) {
|
|
661
|
+
if (ageHours < 1)
|
|
662
|
+
return `${Math.max(1, Math.round(ageHours * 60))}m`;
|
|
663
|
+
return `${Math.round(ageHours)}h`;
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Render the Open Requests section.
|
|
667
|
+
*
|
|
668
|
+
* @param rows - Capped rows
|
|
669
|
+
* @param truncation - Section truncation metadata
|
|
670
|
+
* @param hints - Memory hints
|
|
671
|
+
* @returns Markdown block
|
|
672
|
+
*/
|
|
673
|
+
renderOpenRequests(rows, truncation, hints) {
|
|
674
|
+
const lines = ['### Open Requests'];
|
|
675
|
+
for (const row of rows) {
|
|
676
|
+
const base = `- **${row.id}** — ${row.title} — _${row.status} · ${row.priority} · ${this.formatAge(row.ageHours)}_`;
|
|
677
|
+
lines.push(this.appendMemoryHint(base, `req:${row.id}`, hints));
|
|
678
|
+
}
|
|
679
|
+
const marker = this.renderTruncationMarker(truncation);
|
|
680
|
+
return lines.join('\n') + marker;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Render the Active WorkItems section.
|
|
684
|
+
*
|
|
685
|
+
* @param rows - Capped rows
|
|
686
|
+
* @param truncation - Section truncation metadata
|
|
687
|
+
* @param hints - Memory hints
|
|
688
|
+
* @param compact - If true, drop description lines (orchestrator overflow)
|
|
689
|
+
* @returns Markdown block
|
|
690
|
+
*/
|
|
691
|
+
renderActiveWorkItems(rows, truncation, hints, compact) {
|
|
692
|
+
const lines = ['### Active WorkItems'];
|
|
693
|
+
for (const row of rows) {
|
|
694
|
+
const reqRef = row.requestId ? ` · req=${row.requestId}` : '';
|
|
695
|
+
const base = `- **${row.id}** — ${row.title} — _${row.status} · ${row.priority} · ${this.formatAge(row.ageHours)}${reqRef}_`;
|
|
696
|
+
lines.push(this.appendMemoryHint(base, `wi:${row.id}`, hints));
|
|
697
|
+
if (!compact && row.description) {
|
|
698
|
+
lines.push(` - ${row.description}`);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
const marker = this.renderTruncationMarker(truncation);
|
|
702
|
+
return lines.join('\n') + marker;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Render the Pending Reviews section.
|
|
706
|
+
*
|
|
707
|
+
* @param rows - Capped rows
|
|
708
|
+
* @param truncation - Section truncation metadata
|
|
709
|
+
* @param hints - Memory hints
|
|
710
|
+
* @returns Markdown block
|
|
711
|
+
*/
|
|
712
|
+
renderPendingReviews(rows, truncation, hints) {
|
|
713
|
+
const lines = ['### Pending Reviews'];
|
|
714
|
+
for (const row of rows) {
|
|
715
|
+
const claimedBy = row.claimedBy ? ` · by ${row.claimedBy}` : '';
|
|
716
|
+
const base = `- **${row.id}** — ${row.title} — _${this.formatAge(row.ageHours)}${claimedBy}_`;
|
|
717
|
+
lines.push(this.appendMemoryHint(base, `wi:${row.id}`, hints));
|
|
718
|
+
}
|
|
719
|
+
const marker = this.renderTruncationMarker(truncation);
|
|
720
|
+
return lines.join('\n') + marker;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Render the Outbound Delegations section.
|
|
724
|
+
*
|
|
725
|
+
* @param rows - Capped rows
|
|
726
|
+
* @param truncation - Section truncation metadata
|
|
727
|
+
* @param hints - Memory hints
|
|
728
|
+
* @returns Markdown block
|
|
729
|
+
*/
|
|
730
|
+
renderOutboundDelegations(rows, truncation, hints) {
|
|
731
|
+
const lines = ['### Outbound Delegations'];
|
|
732
|
+
for (const row of rows) {
|
|
733
|
+
const target = row.target ? ` → ${row.target}` : '';
|
|
734
|
+
const base = `- **${row.id}** — ${row.title} — _${row.status} · ${this.formatAge(row.ageHours)}${target}_`;
|
|
735
|
+
lines.push(this.appendMemoryHint(base, `wi:${row.id}`, hints));
|
|
736
|
+
}
|
|
737
|
+
const marker = this.renderTruncationMarker(truncation);
|
|
738
|
+
return lines.join('\n') + marker;
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Render the Recently Auto-Resolved section.
|
|
742
|
+
*
|
|
743
|
+
* @param rows - Capped rows
|
|
744
|
+
* @param truncation - Section truncation metadata
|
|
745
|
+
* @param hints - Memory hints
|
|
746
|
+
* @returns Markdown block
|
|
747
|
+
*/
|
|
748
|
+
renderRecentlyResolved(rows, truncation, hints) {
|
|
749
|
+
const lines = ['### Recently Auto-Resolved (last 30min)'];
|
|
750
|
+
for (const row of rows) {
|
|
751
|
+
const reason = row.resolvedReason ? ` — ${row.resolvedReason}` : '';
|
|
752
|
+
const base = `- **${row.id}** — ${row.title}${reason}`;
|
|
753
|
+
lines.push(this.appendMemoryHint(base, `wi:${row.id}`, hints));
|
|
754
|
+
}
|
|
755
|
+
const marker = this.renderTruncationMarker(truncation);
|
|
756
|
+
return lines.join('\n') + marker;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
//# sourceMappingURL=active-work-briefing.service.js.map
|