crewly 1.20.211 → 1.20.213
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/prompt.md +1 -0
- package/config/skills/agent/core/send-message/SKILL.md +9 -0
- package/config/skills/orchestrator/delegate-task/SKILL.md +9 -0
- package/config/skills/orchestrator/get-team-status/SKILL.md +9 -0
- package/config/skills/orchestrator/get-team-status/execute.sh +5 -1
- package/config/skills/orchestrator/send-message/SKILL.md +9 -0
- package/config/skills/orchestrator/start-agent/SKILL.md +9 -0
- package/config/skills/orchestrator/start-team/SKILL.md +9 -0
- package/config/skills/team-leader/assign-ticket/SKILL.md +9 -0
- package/config/skills/team-leader/delegate-task/SKILL.md +9 -0
- package/dist/backend/backend/src/constants.d.ts +25 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +25 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +36 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/request-types.d.ts +10 -1
- package/dist/backend/backend/src/controllers/request-types.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +0 -36
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +41 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team-pause.controller.d.ts +59 -0
- package/dist/backend/backend/src/controllers/team/team-pause.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/team/team-pause.controller.js +161 -0
- package/dist/backend/backend/src/controllers/team/team-pause.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts +14 -0
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +78 -5
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.js +7 -1
- package/dist/backend/backend/src/controllers/team/team.routes.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +18 -1
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/models/Team.d.ts +5 -1
- package/dist/backend/backend/src/models/Team.d.ts.map +1 -1
- package/dist/backend/backend/src/models/Team.js +8 -0
- package/dist/backend/backend/src/models/Team.js.map +1 -1
- package/dist/backend/backend/src/services/agent/owner-stopped.registry.d.ts +7 -2
- package/dist/backend/backend/src/services/agent/owner-stopped.registry.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/owner-stopped.registry.js +9 -3
- package/dist/backend/backend/src/services/agent/owner-stopped.registry.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +14 -4
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +3 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/ticket-line.utils.d.ts +29 -0
- package/dist/backend/backend/src/services/chat-v2/ticket-line.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/ticket-line.utils.js +48 -0
- package/dist/backend/backend/src/services/chat-v2/ticket-line.utils.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/conversation-cloud-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/conversation-cloud-sync.service.js +3 -1
- package/dist/backend/backend/src/services/cloud/conversation-cloud-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js +6 -0
- package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js +6 -0
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts +12 -0
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js +59 -0
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +12 -6
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +5 -0
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js +4 -0
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +22 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-channel-members.d.ts +27 -0
- package/dist/backend/backend/src/services/slack/slack-channel-members.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-channel-members.js +54 -0
- package/dist/backend/backend/src/services/slack/slack-channel-members.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-directory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-directory.service.js +7 -2
- package/dist/backend/backend/src/services/slack/slack-directory.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js +3 -0
- package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +12 -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 +57 -16
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +48 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +155 -4
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +11 -0
- 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 +36 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/untargeted-router.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/untargeted-router.js +14 -6
- package/dist/backend/backend/src/services/task-pool/untargeted-router.js.map +1 -1
- package/dist/backend/backend/src/services/team/team-pause-command.d.ts +97 -0
- package/dist/backend/backend/src/services/team/team-pause-command.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause-command.js +177 -0
- package/dist/backend/backend/src/services/team/team-pause-command.js.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause-notice.d.ts +43 -0
- package/dist/backend/backend/src/services/team/team-pause-notice.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause-notice.js +61 -0
- package/dist/backend/backend/src/services/team/team-pause-notice.js.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause.registry.d.ts +167 -0
- package/dist/backend/backend/src/services/team/team-pause.registry.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause.registry.js +263 -0
- package/dist/backend/backend/src/services/team/team-pause.registry.js.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause.service.d.ts +172 -0
- package/dist/backend/backend/src/services/team/team-pause.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause.service.js +254 -0
- package/dist/backend/backend/src/services/team/team-pause.service.js.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause.wiring.d.ts +30 -0
- package/dist/backend/backend/src/services/team/team-pause.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team/team-pause.wiring.js +48 -0
- package/dist/backend/backend/src/services/team/team-pause.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js +11 -0
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts +9 -0
- package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/trigger-engine.service.js +27 -2
- package/dist/backend/backend/src/services/v3/trigger-engine.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +7 -0
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.js +14 -0
- package/dist/backend/backend/src/services/workflow/cron-task.service.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.js +5 -0
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.js +6 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +22 -0
- 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/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +25 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +25 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/models/Team.d.ts +5 -1
- package/dist/cli/backend/src/models/Team.d.ts.map +1 -1
- package/dist/cli/backend/src/models/Team.js +8 -0
- package/dist/cli/backend/src/models/Team.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +14 -4
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +3 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/ticket-line.utils.d.ts +29 -0
- package/dist/cli/backend/src/services/chat-v2/ticket-line.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/ticket-line.utils.js +48 -0
- package/dist/cli/backend/src/services/chat-v2/ticket-line.utils.js.map +1 -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 +6 -0
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +22 -0
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-directory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-directory.service.js +7 -2
- package/dist/cli/backend/src/services/slack/slack-directory.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +12 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +57 -16
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +48 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +155 -4
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +11 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +36 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/services/team/team-pause-notice.d.ts +43 -0
- package/dist/cli/backend/src/services/team/team-pause-notice.d.ts.map +1 -0
- package/dist/cli/backend/src/services/team/team-pause-notice.js +61 -0
- package/dist/cli/backend/src/services/team/team-pause-notice.js.map +1 -0
- package/dist/cli/backend/src/services/team/team-pause.registry.d.ts +167 -0
- package/dist/cli/backend/src/services/team/team-pause.registry.d.ts.map +1 -0
- package/dist/cli/backend/src/services/team/team-pause.registry.js +263 -0
- package/dist/cli/backend/src/services/team/team-pause.registry.js.map +1 -0
- package/dist/cli/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/workflow/cron-task.service.js +14 -0
- package/dist/cli/backend/src/services/workflow/cron-task.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +22 -0
- package/dist/cli/backend/src/types/index.d.ts.map +1 -1
- package/dist/cli/backend/src/types/index.js.map +1 -1
- package/frontend/dist/assets/{index-f64b333a.js → index-917db1b8.js} +279 -279
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-pause-command.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/team/team-pause-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGjD,uDAAuD;AACvD,MAAM,MAAM,gBAAgB,GACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACzG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC;AAqC7D;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,gBAAgB,GAAG,IAAI,CAsCvF;AAED,kCAAkC;AAClC,MAAM,WAAW,oBAAoB;IACpC,oHAAoH;IACpH,YAAY,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC;IACxE,mCAAmC;IACnC,aAAa,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC;IAC1D,gCAAgC;IAChC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,8DAA8D;IAC9D,UAAU,EAAE,MAAM,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,aAAa,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,KAAK,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACxP,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB5H;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,oBAAoB,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CA0BjH"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pause / resume a team from the owner's DM with the orc
|
|
3
|
+
* (specs/2026-10-04-team-pause.md). The owner is usually away from the
|
|
4
|
+
* machine, so the Slack DM is the main control. Handled by the backend as
|
|
5
|
+
* an owner command — never by the orc's LLM — and only for the owner's own
|
|
6
|
+
* messages in their DM with the orc:
|
|
7
|
+
*
|
|
8
|
+
* - `pause <team>` / `pause team <team>`
|
|
9
|
+
* - `pause <team> for 3d` (`m`, `h`, `d`, `w`; also `3 days`, `2 hours`)
|
|
10
|
+
* - `pause <team> until 2026-10-10` (anything `Date.parse` reads)
|
|
11
|
+
* - `pause <team> because <reason>` / `pause <team>: <reason>`
|
|
12
|
+
* - `resume <team>` / `unpause <team>`
|
|
13
|
+
* - Chinese aliases: `暂停 <team>`, `恢复 <team>`, `取消暂停 <team>`
|
|
14
|
+
*
|
|
15
|
+
* A message is consumed only when its target names a team (or it says
|
|
16
|
+
* `pause team <x>` explicitly); anything else goes on to the orc. Replies are
|
|
17
|
+
* English (harness text rule).
|
|
18
|
+
*
|
|
19
|
+
* @module services/team/team-pause-command
|
|
20
|
+
*/
|
|
21
|
+
import { findTeamByRef } from './team-pause.service.js';
|
|
22
|
+
const UNIT_MS = {
|
|
23
|
+
m: 60_000,
|
|
24
|
+
min: 60_000,
|
|
25
|
+
mins: 60_000,
|
|
26
|
+
minute: 60_000,
|
|
27
|
+
minutes: 60_000,
|
|
28
|
+
h: 3_600_000,
|
|
29
|
+
hr: 3_600_000,
|
|
30
|
+
hrs: 3_600_000,
|
|
31
|
+
hour: 3_600_000,
|
|
32
|
+
hours: 3_600_000,
|
|
33
|
+
d: 86_400_000,
|
|
34
|
+
day: 86_400_000,
|
|
35
|
+
days: 86_400_000,
|
|
36
|
+
w: 604_800_000,
|
|
37
|
+
week: 604_800_000,
|
|
38
|
+
weeks: 604_800_000,
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Normalise a message for matching.
|
|
42
|
+
*
|
|
43
|
+
* @param text - Raw text
|
|
44
|
+
* @returns Mentions, emphasis and trailing punctuation removed; whitespace collapsed
|
|
45
|
+
*/
|
|
46
|
+
function norm(text) {
|
|
47
|
+
return text
|
|
48
|
+
.replace(/<@[A-Z0-9]+>/g, '')
|
|
49
|
+
.replace(/[`*_]/g, '')
|
|
50
|
+
.replace(/[\s.。!!~~]+$/u, '')
|
|
51
|
+
.replace(/^(?:please|pls|请)\s*/iu, '')
|
|
52
|
+
.replace(/\s+/g, ' ')
|
|
53
|
+
.trim();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parse a pause / resume command.
|
|
57
|
+
*
|
|
58
|
+
* @param text - Message text
|
|
59
|
+
* @returns The command, or null when the message is not one
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* parseTeamPauseCommand('pause Crewly for 3d because harness work moved') // { kind: 'pause', target: 'Crewly', forMs: 259200000, reason: 'harness work moved', explicitTeam: false }
|
|
63
|
+
* parseTeamPauseCommand('resume team Crewly') // { kind: 'resume', target: 'Crewly', explicitTeam: true }
|
|
64
|
+
*/
|
|
65
|
+
export function parseTeamPauseCommand(text) {
|
|
66
|
+
if (!text)
|
|
67
|
+
return null;
|
|
68
|
+
const t = norm(text);
|
|
69
|
+
if (!t || t.includes('\n'))
|
|
70
|
+
return null;
|
|
71
|
+
let m = /^(?:resume|unpause|un-pause)\s+(team\s+)?(.+)$/i.exec(t) ?? /^(?:恢复|取消暂停)\s*(团队)?\s*(.+)$/u.exec(t);
|
|
72
|
+
if (m) {
|
|
73
|
+
const target = m[2].trim().replace(/^the\s+/i, '').replace(/\s+team$/i, '');
|
|
74
|
+
return target ? { kind: 'resume', target, explicitTeam: !!m[1] } : null;
|
|
75
|
+
}
|
|
76
|
+
m = /^pause\s+(team\s+)?(.+)$/i.exec(t) ?? /^暂停\s*(团队)?\s*(.+)$/u.exec(t);
|
|
77
|
+
if (!m)
|
|
78
|
+
return null;
|
|
79
|
+
let rest = m[2].trim();
|
|
80
|
+
const explicitTeam = !!m[1];
|
|
81
|
+
let reason;
|
|
82
|
+
// A colon starts a reason only when no "until <time>" could contain it.
|
|
83
|
+
const why = /^(.+?)(?:\s+because\s+|\s+reason:?\s+|\s+因为\s*)(.+)$/i.exec(rest) ??
|
|
84
|
+
(/\b(?:until|till|til)\b/i.test(rest) ? null : /^(.+?)\s*[::]\s*(.+)$/.exec(rest));
|
|
85
|
+
if (why) {
|
|
86
|
+
rest = why[1].trim();
|
|
87
|
+
reason = why[2].trim();
|
|
88
|
+
}
|
|
89
|
+
let until;
|
|
90
|
+
let forMs;
|
|
91
|
+
const dur = /^(.+?)\s+for\s+(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(rest);
|
|
92
|
+
const till = /^(.+?)\s+(?:until|till|til)\s+(.+)$/i.exec(rest);
|
|
93
|
+
if (dur && UNIT_MS[dur[3].toLowerCase()]) {
|
|
94
|
+
rest = dur[1].trim();
|
|
95
|
+
forMs = Number(dur[2]) * UNIT_MS[dur[3].toLowerCase()];
|
|
96
|
+
}
|
|
97
|
+
else if (till) {
|
|
98
|
+
rest = till[1].trim();
|
|
99
|
+
until = till[2].trim();
|
|
100
|
+
}
|
|
101
|
+
const target = rest.replace(/^the\s+/i, '').replace(/\s+team$/i, '').trim();
|
|
102
|
+
if (!target)
|
|
103
|
+
return null;
|
|
104
|
+
return { kind: 'pause', target, explicitTeam, ...(reason ? { reason } : {}), ...(until ? { until } : {}), ...(forMs ? { forMs } : {}) };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Run a parsed command and build the owner's reply.
|
|
108
|
+
*
|
|
109
|
+
* @param cmd - Command
|
|
110
|
+
* @param teamId - Resolved team
|
|
111
|
+
* @param deps - Collaborators
|
|
112
|
+
* @returns Reply text
|
|
113
|
+
*/
|
|
114
|
+
export async function runTeamPauseCommand(cmd, teamId, deps) {
|
|
115
|
+
if (cmd.kind === 'resume') {
|
|
116
|
+
const out = await deps.resume(teamId);
|
|
117
|
+
return out.wasPaused
|
|
118
|
+
? `${out.team.name} is resumed. Its members start again when there is work for them, or when you start them.`
|
|
119
|
+
: `${out.team.name} was not paused.`;
|
|
120
|
+
}
|
|
121
|
+
const now = deps.now?.() ?? Date.now();
|
|
122
|
+
const until = cmd.forMs ? new Date(now + cmd.forMs).toISOString() : cmd.until;
|
|
123
|
+
const out = await deps.pause(teamId, { ...(cmd.reason ? { reason: cmd.reason } : {}), ...(until ? { until } : {}) });
|
|
124
|
+
const parts = [
|
|
125
|
+
`${out.team.name} is ${out.alreadyPaused ? 'still ' : ''}paused${out.team.paused?.until ? ` until ${out.team.paused.until}` : ''}.`,
|
|
126
|
+
'No automation will wake it, and other agents are told to file a GitHub issue' +
|
|
127
|
+
(out.team.issueRepo ? ` in ${out.team.issueRepo}` : ' (no issue repo set: they tell the orc)') +
|
|
128
|
+
' instead of handing it work.',
|
|
129
|
+
];
|
|
130
|
+
if (out.stopped.length > 0)
|
|
131
|
+
parts.push(`Stopped: ${out.stopped.join(', ')}.`);
|
|
132
|
+
if (out.stopFailed.length > 0)
|
|
133
|
+
parts.push(`Could not stop: ${out.stopFailed.map((f) => `${f.member} (${f.error})`).join(', ')}.`);
|
|
134
|
+
const released = out.releasedWorkItems.length + out.releasedTickets.length;
|
|
135
|
+
if (released > 0)
|
|
136
|
+
parts.push(`Unassigned ${released} item(s) that had not started.`);
|
|
137
|
+
parts.push(`Say "resume ${out.team.name}" to undo.`);
|
|
138
|
+
return parts.join(' ');
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The Slack bridge interceptor for the owner's orc DM.
|
|
142
|
+
*
|
|
143
|
+
* @param deps - Collaborators
|
|
144
|
+
* @returns Interceptor: true when the message was a pause / resume command (consumed)
|
|
145
|
+
*/
|
|
146
|
+
export function createTeamPauseInterceptor(deps) {
|
|
147
|
+
return (message) => {
|
|
148
|
+
if (message.hasFiles)
|
|
149
|
+
return false;
|
|
150
|
+
if (deps.ownerDmScope(message) !== 'orc')
|
|
151
|
+
return false;
|
|
152
|
+
const cmd = parseTeamPauseCommand(message.text);
|
|
153
|
+
if (!cmd)
|
|
154
|
+
return false;
|
|
155
|
+
const teams = deps.knownTeams();
|
|
156
|
+
const team = findTeamByRef(teams.map((t) => ({ id: t.id, name: t.name, members: [], projectIds: [], createdAt: '', updatedAt: '' })), cmd.target);
|
|
157
|
+
const target = deps.replyTargetOf(message);
|
|
158
|
+
if (!team) {
|
|
159
|
+
// "pause team X" is unmistakably a command: answer it. Anything else
|
|
160
|
+
// ("pause the deploy") is the orc's.
|
|
161
|
+
if (!cmd.explicitTeam)
|
|
162
|
+
return false;
|
|
163
|
+
void deps
|
|
164
|
+
.reply(`No team named "${cmd.target}". Teams: ${teams.map((t) => t.name).join(', ') || 'none'}.`, target)
|
|
165
|
+
.catch((err) => deps.onError?.(err));
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
void runTeamPauseCommand(cmd, team.id, deps)
|
|
169
|
+
.then((text) => deps.reply(text, target))
|
|
170
|
+
.catch((err) => {
|
|
171
|
+
deps.onError?.(err);
|
|
172
|
+
return deps.reply(`Couldn't ${cmd.kind} ${team.name}: ${err instanceof Error ? err.message : String(err)}`, target).catch(() => undefined);
|
|
173
|
+
});
|
|
174
|
+
return true;
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=team-pause-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-pause-command.js","sourceRoot":"","sources":["../../../../../../backend/src/services/team/team-pause-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Slack auto-reply for a paused agent (specs/2026-10-04-team-pause.md):
|
|
3
|
+
* an @mention or DM of a paused team's agent does not wake it; a short
|
|
4
|
+
* English line in the thread says why — at most once per thread.
|
|
5
|
+
*
|
|
6
|
+
* @module services/team/team-pause-notice
|
|
7
|
+
*/
|
|
8
|
+
import { type PausedTeamInfo } from './team-pause.registry.js';
|
|
9
|
+
/**
|
|
10
|
+
* The auto-reply text.
|
|
11
|
+
*
|
|
12
|
+
* @param info - The paused team
|
|
13
|
+
* @param agentName - Display name of the agent that was addressed
|
|
14
|
+
* @param options - `toAgent`: the author is another agent (it gets the refusal: file an issue / tell the orc)
|
|
15
|
+
* @returns Text
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* pausedSlackNotice(info, 'Leo') // 'Leo is on Crewly, which the owner has paused, so Leo won't pick this up. …'
|
|
19
|
+
*/
|
|
20
|
+
export declare function pausedSlackNotice(info: PausedTeamInfo, agentName: string, options?: {
|
|
21
|
+
toAgent?: boolean;
|
|
22
|
+
}): string;
|
|
23
|
+
/** Remembers which threads were already told (one notice per thread per team). */
|
|
24
|
+
export declare class PausedThreadNotices {
|
|
25
|
+
private readonly max;
|
|
26
|
+
private readonly told;
|
|
27
|
+
/**
|
|
28
|
+
* @param max - Threads remembered before the oldest are forgotten
|
|
29
|
+
*/
|
|
30
|
+
constructor(max?: number);
|
|
31
|
+
/**
|
|
32
|
+
* Claim the notice for a thread: true the first time, false after.
|
|
33
|
+
*
|
|
34
|
+
* @param channelId - Slack channel
|
|
35
|
+
* @param threadTs - Thread (root ts)
|
|
36
|
+
* @param teamId - Paused team
|
|
37
|
+
* @returns True when the notice should be posted now
|
|
38
|
+
*/
|
|
39
|
+
claim(channelId: string, threadTs: string | undefined, teamId: string): boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Shared by the Slack paths so a thread is told once whichever path saw it. */
|
|
42
|
+
export declare const pausedThreadNotices: PausedThreadNotices;
|
|
43
|
+
//# sourceMappingURL=team-pause-notice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-pause-notice.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/team/team-pause-notice.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAErF;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAOtH;AAED,kFAAkF;AAClF,qBAAa,mBAAmB;IAMnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAE1C;;OAEG;gBAC0B,GAAG,GAAE,MAAiD;IAEnF;;;;;;;OAOG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;CAU/E;AAED,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Slack auto-reply for a paused agent (specs/2026-10-04-team-pause.md):
|
|
3
|
+
* an @mention or DM of a paused team's agent does not wake it; a short
|
|
4
|
+
* English line in the thread says why — at most once per thread.
|
|
5
|
+
*
|
|
6
|
+
* @module services/team/team-pause-notice
|
|
7
|
+
*/
|
|
8
|
+
import { TEAM_PAUSE_CONSTANTS } from '../../constants.js';
|
|
9
|
+
import { pausedRefusalMessage } from './team-pause.registry.js';
|
|
10
|
+
/**
|
|
11
|
+
* The auto-reply text.
|
|
12
|
+
*
|
|
13
|
+
* @param info - The paused team
|
|
14
|
+
* @param agentName - Display name of the agent that was addressed
|
|
15
|
+
* @param options - `toAgent`: the author is another agent (it gets the refusal: file an issue / tell the orc)
|
|
16
|
+
* @returns Text
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* pausedSlackNotice(info, 'Leo') // 'Leo is on Crewly, which the owner has paused, so Leo won't pick this up. …'
|
|
20
|
+
*/
|
|
21
|
+
export function pausedSlackNotice(info, agentName, options = {}) {
|
|
22
|
+
if (options.toAgent)
|
|
23
|
+
return pausedRefusalMessage(info);
|
|
24
|
+
const until = info.pause.until ? ` (until ${info.pause.until})` : '';
|
|
25
|
+
return (`${agentName} is on ${info.teamName}, which the owner has paused${until}, so ${agentName} won't pick this up. ` +
|
|
26
|
+
`To bring the team back, DM the orc "resume ${info.teamName}".`);
|
|
27
|
+
}
|
|
28
|
+
/** Remembers which threads were already told (one notice per thread per team). */
|
|
29
|
+
export class PausedThreadNotices {
|
|
30
|
+
max;
|
|
31
|
+
told = new Set();
|
|
32
|
+
/**
|
|
33
|
+
* @param max - Threads remembered before the oldest are forgotten
|
|
34
|
+
*/
|
|
35
|
+
constructor(max = TEAM_PAUSE_CONSTANTS.SLACK_NOTICE_MEMORY) {
|
|
36
|
+
this.max = max;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Claim the notice for a thread: true the first time, false after.
|
|
40
|
+
*
|
|
41
|
+
* @param channelId - Slack channel
|
|
42
|
+
* @param threadTs - Thread (root ts)
|
|
43
|
+
* @param teamId - Paused team
|
|
44
|
+
* @returns True when the notice should be posted now
|
|
45
|
+
*/
|
|
46
|
+
claim(channelId, threadTs, teamId) {
|
|
47
|
+
const key = `${channelId}:${threadTs ?? ''}:${teamId}`;
|
|
48
|
+
if (this.told.has(key))
|
|
49
|
+
return false;
|
|
50
|
+
this.told.add(key);
|
|
51
|
+
if (this.told.size > this.max) {
|
|
52
|
+
const oldest = this.told.values().next().value;
|
|
53
|
+
if (oldest !== undefined)
|
|
54
|
+
this.told.delete(oldest);
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Shared by the Slack paths so a thread is told once whichever path saw it. */
|
|
60
|
+
export const pausedThreadNotices = new PausedThreadNotices();
|
|
61
|
+
//# sourceMappingURL=team-pause-notice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-pause-notice.js","sourceRoot":"","sources":["../../../../../../backend/src/services/team/team-pause-notice.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAuB,MAAM,0BAA0B,CAAC;AAErF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAoB,EAAE,SAAiB,EAAE,UAAiC,EAAE;IAC7G,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,OAAO,CACN,GAAG,SAAS,UAAU,IAAI,CAAC,QAAQ,+BAA+B,KAAK,QAAQ,SAAS,uBAAuB;QAC/G,8CAA8C,IAAI,CAAC,QAAQ,IAAI,CAC/D,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,OAAO,mBAAmB;IAMF;IALZ,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C;;OAEG;IACH,YAA6B,MAAc,oBAAoB,CAAC,mBAAmB;QAAtD,QAAG,GAAH,GAAG,CAAmD;IAAG,CAAC;IAEvF;;;;;;;OAOG;IACH,KAAK,CAAC,SAAiB,EAAE,QAA4B,EAAE,MAAc;QACpE,MAAM,GAAG,GAAG,GAAG,SAAS,IAAI,QAAQ,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;QACvD,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC/C,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;CACD;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paused teams — the in-memory index every automation path consults
|
|
3
|
+
* (specs/2026-10-04-team-pause.md).
|
|
4
|
+
*
|
|
5
|
+
* The pause itself is stored on the team (`Team.paused`, persisted in the
|
|
6
|
+
* team's config.json), so it survives restarts. This module keeps a
|
|
7
|
+
* synchronous index of it — team id → pause, and every session name a
|
|
8
|
+
* member of a paused team may run under → team — because most of the gates
|
|
9
|
+
* (the reconciler's wake rule, the queued-message wake, the dispatcher's
|
|
10
|
+
* target planning) only have a session name and must not await storage.
|
|
11
|
+
*
|
|
12
|
+
* The index is rebuilt from storage: {@link syncPausedTeams} runs on every
|
|
13
|
+
* `StorageService.getTeams()` read and at boot, and {@link notePausedTeam}
|
|
14
|
+
* on every save. A pause whose `until` has passed counts as resumed at once,
|
|
15
|
+
* before the auto-resume sweep clears it from storage.
|
|
16
|
+
*
|
|
17
|
+
* Module-level and dependency-free (types and two utils only), so the team
|
|
18
|
+
* controller, the storage service and the services can share it without
|
|
19
|
+
* import cycles.
|
|
20
|
+
*
|
|
21
|
+
* @module services/team/team-pause.registry
|
|
22
|
+
*/
|
|
23
|
+
import type { Team, TeamMember, TeamPauseState } from '../../types/index.js';
|
|
24
|
+
/** What the gates need to know about a paused team. */
|
|
25
|
+
export interface PausedTeamInfo {
|
|
26
|
+
teamId: string;
|
|
27
|
+
teamName: string;
|
|
28
|
+
/** GitHub repository for issues while paused (`owner/name`), when configured */
|
|
29
|
+
issueRepo?: string;
|
|
30
|
+
pause: TeamPauseState;
|
|
31
|
+
/** Every session name a member may run under (session, agent id, derived name) */
|
|
32
|
+
sessions: string[];
|
|
33
|
+
/** Member display names */
|
|
34
|
+
memberNames: string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether a pause is in force at `now` (set, and its `until` not reached).
|
|
38
|
+
*
|
|
39
|
+
* @param pause - The team's pause, if any
|
|
40
|
+
* @param now - Clock (ms)
|
|
41
|
+
* @returns True while paused
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* isPauseActive({ pausedAt: '…', by: 'owner', until: '2099-01-01T00:00:00Z' }) // true
|
|
45
|
+
*/
|
|
46
|
+
export declare function isPauseActive(pause: TeamPauseState | null | undefined, now?: number): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether a team object is paused now. Prefer this where the team is at
|
|
49
|
+
* hand: it reads the team itself, not the index.
|
|
50
|
+
*
|
|
51
|
+
* @param team - Team (only `paused` is read)
|
|
52
|
+
* @param now - Clock (ms)
|
|
53
|
+
* @returns True while paused
|
|
54
|
+
*/
|
|
55
|
+
export declare function isTeamPausedNow(team: Pick<Team, 'paused'> | null | undefined, now?: number): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Every session name a member may run under: its live session, its
|
|
58
|
+
* permanent agent id, and the name the controller derives on start.
|
|
59
|
+
*
|
|
60
|
+
* @param teamName - Team display name
|
|
61
|
+
* @param member - Member
|
|
62
|
+
* @returns Distinct, non-empty session names
|
|
63
|
+
*/
|
|
64
|
+
export declare function memberSessionKeys(teamName: string, member: Pick<TeamMember, 'sessionName' | 'agentId' | 'name' | 'id'>): string[];
|
|
65
|
+
/**
|
|
66
|
+
* Update the index for one team (after a save). A team that is not paused
|
|
67
|
+
* is removed from it.
|
|
68
|
+
*
|
|
69
|
+
* @param team - The saved team
|
|
70
|
+
*/
|
|
71
|
+
export declare function notePausedTeam(team: Team | null | undefined): void;
|
|
72
|
+
/**
|
|
73
|
+
* Forget a deleted team.
|
|
74
|
+
*
|
|
75
|
+
* @param teamId - Deleted team
|
|
76
|
+
*/
|
|
77
|
+
export declare function noteTeamDeleted(teamId: string): void;
|
|
78
|
+
/**
|
|
79
|
+
* Every team the index has seen (id and name), archived ones excluded.
|
|
80
|
+
*
|
|
81
|
+
* @returns Teams
|
|
82
|
+
*/
|
|
83
|
+
export declare function listKnownTeams(): Array<{
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Rebuild the index from a full team list (a storage read, boot).
|
|
89
|
+
*
|
|
90
|
+
* @param teams - Every stored team
|
|
91
|
+
*/
|
|
92
|
+
export declare function syncPausedTeams(teams: readonly Team[]): void;
|
|
93
|
+
/**
|
|
94
|
+
* The paused team with this id, if its pause is in force.
|
|
95
|
+
*
|
|
96
|
+
* @param teamId - Team id
|
|
97
|
+
* @param now - Clock (ms)
|
|
98
|
+
* @returns Info, or null
|
|
99
|
+
*/
|
|
100
|
+
export declare function pausedTeamById(teamId: string | null | undefined, now?: number): PausedTeamInfo | null;
|
|
101
|
+
/**
|
|
102
|
+
* Whether the team with this id is paused now.
|
|
103
|
+
*
|
|
104
|
+
* @param teamId - Team id
|
|
105
|
+
* @returns True while paused
|
|
106
|
+
*/
|
|
107
|
+
export declare function isTeamIdPaused(teamId: string | null | undefined): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* The paused team a session belongs to, if its pause is in force.
|
|
110
|
+
*
|
|
111
|
+
* @param session - Agent session (or agent id)
|
|
112
|
+
* @param now - Clock (ms)
|
|
113
|
+
* @returns Info, or null
|
|
114
|
+
*/
|
|
115
|
+
export declare function pausedTeamOfSession(session: string | null | undefined, now?: number): PausedTeamInfo | null;
|
|
116
|
+
/**
|
|
117
|
+
* Whether a session belongs to a paused team.
|
|
118
|
+
*
|
|
119
|
+
* @param session - Agent session (or agent id)
|
|
120
|
+
* @returns True while its team is paused
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* if (isSessionPaused(wi.target)) return false; // do not dispatch
|
|
124
|
+
*/
|
|
125
|
+
export declare function isSessionPaused(session: string | null | undefined): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* The paused team named by an id, a name (case-insensitive) or a member
|
|
128
|
+
* session — whatever an agent typed.
|
|
129
|
+
*
|
|
130
|
+
* @param ref - Team id, team name, or member session
|
|
131
|
+
* @returns Info, or null
|
|
132
|
+
*/
|
|
133
|
+
export declare function pausedTeamByRef(ref: string | null | undefined): PausedTeamInfo | null;
|
|
134
|
+
/**
|
|
135
|
+
* Every team paused now.
|
|
136
|
+
*
|
|
137
|
+
* @param now - Clock (ms)
|
|
138
|
+
* @returns Infos
|
|
139
|
+
*/
|
|
140
|
+
export declare function listPausedTeams(now?: number): PausedTeamInfo[];
|
|
141
|
+
/**
|
|
142
|
+
* Teams whose pause has an `until` that has passed (still stored as paused).
|
|
143
|
+
*
|
|
144
|
+
* @param now - Clock (ms)
|
|
145
|
+
* @returns Infos due for auto-resume
|
|
146
|
+
*/
|
|
147
|
+
export declare function listExpiredPauses(now?: number): PausedTeamInfo[];
|
|
148
|
+
/**
|
|
149
|
+
* The refusal an agent gets when it targets a paused team (English: harness
|
|
150
|
+
* text rule).
|
|
151
|
+
*
|
|
152
|
+
* @param info - The paused team
|
|
153
|
+
* @param options - `callerIsOrc`: the orchestrator asked (it tells the owner, not itself)
|
|
154
|
+
* @returns Message
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* pausedRefusalMessage({ teamName: 'Crewly', issueRepo: 'stevehuang0115/crewly' })
|
|
158
|
+
* // 'Crewly is paused by the owner. File a GitHub issue instead: `gh issue create -R stevehuang0115/crewly --title "…" --body "…"`'
|
|
159
|
+
*/
|
|
160
|
+
export declare function pausedRefusalMessage(info: Pick<PausedTeamInfo, 'teamName' | 'issueRepo'> & {
|
|
161
|
+
pause?: TeamPauseState;
|
|
162
|
+
}, options?: {
|
|
163
|
+
callerIsOrc?: boolean;
|
|
164
|
+
}): string;
|
|
165
|
+
/** Clear the index (tests only). */
|
|
166
|
+
export declare function resetTeamPauseRegistryForTesting(): void;
|
|
167
|
+
//# sourceMappingURL=team-pause.registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-pause.registry.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/team/team-pause.registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG7E,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,CAAC;IACtB,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAOD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAKzG;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAEhH;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,EAAE,CAGjI;AAiCD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAQlE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGpD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,IAAI,CAK5D;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,GAAE,MAAmB,GAAG,cAAc,GAAG,IAAI,CAIjH;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEzE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,GAAE,MAAmB,GAAG,cAAc,GAAG,IAAI,CAIvH;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CASrF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAmB,GAAG,cAAc,EAAE,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAmB,GAAG,cAAc,EAAE,CAE5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CACnC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,WAAW,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,cAAc,CAAA;CAAE,EACjF,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,MAAM,CASR;AAED,oCAAoC;AACpC,wBAAgB,gCAAgC,IAAI,IAAI,CAIvD"}
|