crewly 1.20.192 → 1.20.193
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/constants.ts +11 -0
- package/config/hooks/subagent-guard/subagent.sh +113 -0
- package/config/roles/architect/prompt.md +1 -1
- package/config/roles/auditor/prompt.md +1 -1
- package/config/roles/backend-developer/prompt.md +1 -1
- package/config/roles/content-strategist/prompt.md +2 -2
- package/config/roles/designer/prompt.md +1 -1
- package/config/roles/developer/prompt.md +2 -2
- package/config/roles/frontend-developer/prompt.md +1 -1
- package/config/roles/fullstack-dev/prompt.md +1 -1
- package/config/roles/generalist/prompt.md +1 -1
- package/config/roles/ops/prompt.md +1 -1
- package/config/roles/orchestrator/prompt.md +2 -2
- package/config/roles/product-manager/prompt.md +1 -1
- package/config/roles/qa/prompt.md +1 -1
- package/config/roles/qa-engineer/prompt.md +1 -1
- package/config/roles/researcher/prompt.md +1 -1
- package/config/roles/sales/prompt.md +1 -1
- package/config/roles/support/prompt.md +1 -1
- package/config/roles/team-leader/prompt.md +1 -1
- package/config/roles/tpm/prompt.md +1 -1
- package/config/roles/ux-designer/prompt.md +1 -1
- package/config/skills/_common/complete-body-shape.test.sh +17 -0
- package/config/skills/agent/core/complete-task/SKILL.md +27 -4
- package/config/skills/agent/core/complete-task/execute.sh +23 -3
- package/config/skills/agent/core/complete-task/execute.test.sh +34 -0
- package/config/skills/agent/core/handoff-task/execute.sh +1 -1
- package/config/skills/agent/core/report-status/SKILL.md +27 -4
- package/config/skills/agent/core/report-status/execute.sh +104 -4
- package/config/skills/agent/core/todo-add/SKILL.md +16 -2
- package/config/skills/agent/core/todo-add/execute.sh +21 -5
- package/config/skills/agent/core/todo-add/execute.test.sh +14 -0
- package/config/skills/agent/core/todo-tasks/SKILL.md +4 -3
- package/config/skills/agent/core/todo-update/SKILL.md +13 -2
- package/config/skills/agent/core/todo-update/execute.sh +41 -3
- package/config/skills/agent/core/todo-update/execute.test.sh +7 -0
- package/config/skills/marketplace-registry.ts +4 -4
- package/config/skills/orchestrator/complete-task/SKILL.md +13 -6
- package/config/skills/orchestrator/complete-task/execute.sh +22 -3
- package/config/skills/orchestrator/delegate-task/execute.sh +2 -2
- package/config/skills/orchestrator/harness-login/SKILL.md +9 -1
- package/config/skills/orchestrator/harness-login/execute.sh +12 -4
- package/config/skills/orchestrator/harness-login/execute.test.sh +7 -0
- package/config/skills/team-leader/delegate-task/execute.sh +1 -1
- package/config/skills/team-leader/verify-output/SKILL.md +18 -1
- package/config/skills/team-leader/verify-output/execute.sh +28 -0
- package/config/skills/team-leader/verify-output/execute.test.sh +27 -0
- package/dist/backend/backend/src/constants.d.ts +135 -2
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +136 -1
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts +6 -0
- package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.controller.js +13 -2
- package/dist/backend/backend/src/controllers/canva/canva.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.js +3 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +4 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts +4 -0
- package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/connector/connector.controller.js +32 -3
- package/dist/backend/backend/src/controllers/connector/connector.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.d.ts +41 -0
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.js +75 -0
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.js.map +1 -0
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts +6 -0
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.js +19 -0
- package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.js +3 -1
- package/dist/backend/backend/src/controllers/google/google.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.js +22 -3
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.d.ts +19 -2
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.js +37 -4
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.js +3 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts +9 -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 +26 -0
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/people/people.routes.d.ts +25 -0
- package/dist/backend/backend/src/controllers/people/people.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/people/people.routes.js +90 -0
- package/dist/backend/backend/src/controllers/people/people.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/request-types.d.ts +2 -0
- package/dist/backend/backend/src/controllers/request-types.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.d.ts +22 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js +143 -3
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +25 -3
- 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 +125 -19
- package/dist/backend/backend/src/controllers/task-pool/task-pool.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 +14 -0
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +44 -1
- 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 +3 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +13 -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 +28 -3
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts +3 -2
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js +14 -3
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts +28 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js +48 -4
- package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +2 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.js +17 -4
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts +14 -0
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js +38 -0
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts +34 -0
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js +49 -5
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js +8 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js.map +1 -1
- package/dist/backend/backend/src/services/canva/canva-token.service.d.ts +17 -4
- package/dist/backend/backend/src/services/canva/canva-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/canva/canva-token.service.js +49 -17
- package/dist/backend/backend/src/services/canva/canva-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +24 -0
- 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 +52 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts +17 -2
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js +30 -6
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts +38 -2
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js +63 -1
- package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts +74 -4
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +204 -56
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +19 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +3 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts +25 -2
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js +48 -7
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/claude-accounts.d.ts +207 -0
- package/dist/backend/backend/src/services/harness/claude-accounts.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/claude-accounts.js +306 -0
- package/dist/backend/backend/src/services/harness/claude-accounts.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts +35 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-credentials.store.js +48 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.js.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.d.ts +70 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.js +156 -19
- package/dist/backend/backend/src/services/harness/harness-relogin.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/harness.types.d.ts +2 -0
- package/dist/backend/backend/src/services/harness/harness.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/harness.types.js.map +1 -1
- package/dist/backend/backend/src/services/harness/login-broker.service.d.ts +19 -4
- package/dist/backend/backend/src/services/harness/login-broker.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/login-broker.service.js +46 -7
- package/dist/backend/backend/src/services/harness/login-broker.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/owner-login-request.d.ts +18 -2
- package/dist/backend/backend/src/services/harness/owner-login-request.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/owner-login-request.js +31 -7
- package/dist/backend/backend/src/services/harness/owner-login-request.js.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts +21 -0
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js +39 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +11 -0
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js +29 -0
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +5 -0
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +13 -0
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.d.ts +87 -5
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.js +151 -12
- package/dist/backend/backend/src/services/microsoft/microsoft-todo.service.js.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.d.ts +17 -4
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.js +45 -17
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.d.ts +53 -7
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.js +77 -14
- package/dist/backend/backend/src/services/monitoring/claude-session-tokens.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts +53 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js +130 -29
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/people/acting-for.service.d.ts +151 -0
- package/dist/backend/backend/src/services/people/acting-for.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/acting-for.service.js +224 -0
- package/dist/backend/backend/src/services/people/acting-for.service.js.map +1 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.d.ts +89 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.js +113 -0
- package/dist/backend/backend/src/services/people/dedicated-agent.js.map +1 -0
- package/dist/backend/backend/src/services/people/grant-sharing.d.ts +79 -0
- package/dist/backend/backend/src/services/people/grant-sharing.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/grant-sharing.js +135 -0
- package/dist/backend/backend/src/services/people/grant-sharing.js.map +1 -0
- package/dist/backend/backend/src/services/people/people-directory.service.d.ts +181 -0
- package/dist/backend/backend/src/services/people/people-directory.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/people/people-directory.service.js +317 -0
- package/dist/backend/backend/src/services/people/people-directory.service.js.map +1 -0
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.d.ts +29 -1
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.js +40 -0
- package/dist/backend/backend/src/services/runtime-fallback/effective-runtime.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.d.ts +8 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js +16 -2
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts +60 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js +140 -8
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.store.js +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.store.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +20 -7
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.js +24 -7
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js +12 -2
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.d.ts +7 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.js +18 -3
- package/dist/backend/backend/src/services/runtime-fallback/runtime-usage-probe.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 +3 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +10 -0
- 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 +51 -0
- 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 +9 -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 +46 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts +105 -0
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js +238 -0
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js.map +1 -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 +4 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts +39 -12
- package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/usage/usage-stats.service.js +61 -20
- package/dist/backend/backend/src/services/usage/usage-stats.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.d.ts +2 -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 +9 -0
- package/dist/backend/backend/src/services/v3/agent-auto-claim.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +10 -0
- 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 +45 -2
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +12 -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/messaging.types.d.ts +5 -0
- package/dist/backend/backend/src/types/messaging.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/messaging.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts +77 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.js +119 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.js.map +1 -0
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts +13 -0
- 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.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/backend/config/constants.d.ts +11 -0
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +11 -0
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +135 -2
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +136 -1
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +13 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +28 -3
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts +3 -2
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js +14 -3
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts +28 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js +48 -4
- package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +2 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js +17 -4
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts +14 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +38 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts +34 -0
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js +49 -5
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js +8 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/lazy-anti-patterns.module.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +24 -0
- 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 +52 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts +74 -4
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +204 -56
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +19 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/cli/backend/src/services/harness/claude-accounts.d.ts +207 -0
- package/dist/cli/backend/src/services/harness/claude-accounts.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/claude-accounts.js +306 -0
- package/dist/cli/backend/src/services/harness/claude-accounts.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts +35 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-credentials.store.js +48 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.js.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.d.ts +70 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.js +156 -19
- package/dist/cli/backend/src/services/harness/harness-relogin.service.js.map +1 -1
- package/dist/cli/backend/src/services/harness/harness.types.d.ts +2 -0
- package/dist/cli/backend/src/services/harness/harness.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/harness.types.js.map +1 -1
- package/dist/cli/backend/src/services/harness/login-broker.service.d.ts +19 -4
- package/dist/cli/backend/src/services/harness/login-broker.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/login-broker.service.js +46 -7
- package/dist/cli/backend/src/services/harness/login-broker.service.js.map +1 -1
- package/dist/cli/backend/src/services/harness/owner-login-request.d.ts +18 -2
- package/dist/cli/backend/src/services/harness/owner-login-request.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/owner-login-request.js +31 -7
- package/dist/cli/backend/src/services/harness/owner-login-request.js.map +1 -1
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.d.ts +21 -0
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.js +39 -1
- package/dist/cli/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts +11 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js +29 -0
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +5 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +13 -0
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.d.ts +197 -0
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.js +455 -0
- package/dist/cli/backend/src/services/monitoring/claude-session-tokens.service.js.map +1 -0
- package/dist/cli/backend/src/services/people/acting-for.service.d.ts +151 -0
- package/dist/cli/backend/src/services/people/acting-for.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/people/acting-for.service.js +224 -0
- package/dist/cli/backend/src/services/people/acting-for.service.js.map +1 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.d.ts +89 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.d.ts.map +1 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.js +113 -0
- package/dist/cli/backend/src/services/people/dedicated-agent.js.map +1 -0
- package/dist/cli/backend/src/services/people/people-directory.service.d.ts +181 -0
- package/dist/cli/backend/src/services/people/people-directory.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/people/people-directory.service.js +317 -0
- package/dist/cli/backend/src/services/people/people-directory.service.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.d.ts +29 -1
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.d.ts.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.js +40 -0
- package/dist/cli/backend/src/services/runtime-fallback/effective-runtime.js.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +20 -7
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.js +24 -7
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.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 +3 -0
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +10 -0
- 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 +51 -0
- 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 +9 -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 +46 -0
- 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.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +4 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +12 -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/messaging.types.d.ts +5 -0
- package/dist/cli/backend/src/types/messaging.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/messaging.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts +13 -0
- 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.map +1 -1
- package/dist/cli/cli/src/utils/marketplace.d.ts +21 -0
- package/dist/cli/cli/src/utils/marketplace.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/marketplace.js +35 -1
- package/dist/cli/cli/src/utils/marketplace.js.map +1 -1
- package/dist/cli/config/constants.d.ts +11 -0
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +11 -0
- package/dist/cli/config/constants.js.map +1 -1
- package/dist/cli/config/skills/marketplace-registry.d.ts +4 -4
- package/dist/cli/config/skills/marketplace-registry.js +4 -4
- package/frontend/dist/assets/{index-5b7af029.js → index-465d1f8f.js} +293 -293
- package/frontend/dist/assets/{index-fc715ec3.css → index-5e967795.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/packages/crewly-agent/src/runtime/tool-registry.test.ts +45 -0
- package/packages/crewly-agent/src/runtime/tool-registry.ts +40 -5
- package/packages/crewly-agent/src/test/isolated-home.test.ts +24 -0
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { EventEmitter } from 'events';
|
|
18
18
|
import type { CloudSyncConfig, CloudSyncHealth, CloudSyncState, SyncDevice, MessageType } from './cloud-sync.types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Gap before the next queue registration after `failures` consecutive
|
|
21
|
+
* failures: REGISTER_RETRY_BACKOFF_MS in order, then its last value forever.
|
|
22
|
+
*
|
|
23
|
+
* @param failures - Consecutive failures so far (>= 1)
|
|
24
|
+
* @returns Delay in ms
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerRetryDelay(failures: number): number;
|
|
19
27
|
export declare class CloudSyncService extends EventEmitter {
|
|
20
28
|
private static instance;
|
|
21
29
|
private readonly logger;
|
|
@@ -37,8 +45,31 @@ export declare class CloudSyncService extends EventEmitter {
|
|
|
37
45
|
private messagePollRunning;
|
|
38
46
|
/** When the last message-poll cycle finished (watchdog input). */
|
|
39
47
|
private lastMessagePollAt;
|
|
40
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* Next queue registration (self-scheduling): every REGISTER_INTERVAL_MS
|
|
50
|
+
* while registered (lets the relay evict stale Portal pairs), on the
|
|
51
|
+
* REGISTER_RETRY_BACKOFF_MS schedule while registration fails.
|
|
52
|
+
*/
|
|
41
53
|
private registerTimer;
|
|
54
|
+
/** Consecutive failed queue registrations */
|
|
55
|
+
private queueFailures;
|
|
56
|
+
/** Epoch ms of the first failure in the current registration failure streak */
|
|
57
|
+
private queueFailingSince;
|
|
58
|
+
/** Epoch ms of the next scheduled registration */
|
|
59
|
+
private nextQueueAttemptAt;
|
|
60
|
+
/**
|
|
61
|
+
* Bumped by start() and stop(). An attempt that started under an older
|
|
62
|
+
* generation must not touch state or files — a stop() (or a test's
|
|
63
|
+
* cleanup) can land while a registration is still in flight.
|
|
64
|
+
*/
|
|
65
|
+
private generation;
|
|
66
|
+
/**
|
|
67
|
+
* Crewly home, resolved once at start(). Resolving it at write time let a
|
|
68
|
+
* write that outlived its caller land in a different home (a test that
|
|
69
|
+
* had already restored CREWLY_HOME wrote a random id into the owner's
|
|
70
|
+
* real ~/.crewly — 2026-10-02).
|
|
71
|
+
*/
|
|
72
|
+
private crewlyHome;
|
|
42
73
|
/** Peer reported by the last registration, so a repeat is not logged at info. */
|
|
43
74
|
private lastLoggedPeer;
|
|
44
75
|
/** Consecutive heartbeat failure count */
|
|
@@ -173,6 +204,22 @@ export declare class CloudSyncService extends EventEmitter {
|
|
|
173
204
|
* @throws Error when not started or the HTTP send fails
|
|
174
205
|
*/
|
|
175
206
|
sendToPeerQueueId(peerQueueId: string, type: MessageType, payload: unknown): Promise<void>;
|
|
207
|
+
/**
|
|
208
|
+
* One registration attempt, then schedule the next: the keep-alive
|
|
209
|
+
* interval after a success, the backoff after a failure. Never gives up —
|
|
210
|
+
* a machine without a queue is deaf to Cloud and Slack, and on 2026-10-02
|
|
211
|
+
* one sat like that for half an hour after a single 429 at boot.
|
|
212
|
+
*
|
|
213
|
+
* @param gen - Generation this cycle belongs to (a stale cycle exits)
|
|
214
|
+
*/
|
|
215
|
+
private runRegisterCycle;
|
|
216
|
+
/**
|
|
217
|
+
* Schedule the next registration attempt.
|
|
218
|
+
*
|
|
219
|
+
* @param gen - Generation the attempt belongs to
|
|
220
|
+
* @param delayMs - Gap before it
|
|
221
|
+
*/
|
|
222
|
+
private scheduleRegister;
|
|
176
223
|
/**
|
|
177
224
|
* Register with the Cloud relay message queue.
|
|
178
225
|
*
|
|
@@ -180,16 +227,38 @@ export declare class CloudSyncService extends EventEmitter {
|
|
|
180
227
|
* derived from the JWT user ID. This allows both devices of the same user
|
|
181
228
|
* to auto-discover each other's queueId for message routing.
|
|
182
229
|
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
230
|
+
* Which id to claim, in order:
|
|
231
|
+
* 1. the queue this process already registered — a running machine never
|
|
232
|
+
* switches queues (each switch left the old queue behind and used up
|
|
233
|
+
* the relay's per-user quota: f68e1995 → a8eeab1d → d5c4ebc2 in one
|
|
234
|
+
* day, all on one MacBook, when something rewrote the id file);
|
|
235
|
+
* 2. the id remembered in `<crewlyHome>/cloud/relay-queue.json`;
|
|
236
|
+
* 3. the device id.
|
|
237
|
+
*
|
|
238
|
+
* @param gen - Generation of the calling cycle
|
|
239
|
+
* @throws Error when registration fails (the caller retries)
|
|
185
240
|
*/
|
|
186
241
|
private registerQueue;
|
|
242
|
+
/**
|
|
243
|
+
* Keep the id file in step with the queue we actually hold, so the next
|
|
244
|
+
* boot claims the same queue instead of creating another: rewrite it when
|
|
245
|
+
* it names a different queue, remove it when we hold the device-id queue
|
|
246
|
+
* (the file is only for the fallback case).
|
|
247
|
+
*
|
|
248
|
+
* @param registered - The id just registered
|
|
249
|
+
* @param remembered - What the file said before this attempt
|
|
250
|
+
* @param deviceId - This machine's device id
|
|
251
|
+
* @param gen - Generation of the calling cycle
|
|
252
|
+
*/
|
|
253
|
+
private syncFallbackFile;
|
|
187
254
|
/**
|
|
188
255
|
* One registration attempt against a specific queue id.
|
|
189
256
|
*
|
|
190
257
|
* @param queueId - The id to claim
|
|
191
258
|
* @param pairingCode - Deterministic code derived from the signed-in user
|
|
259
|
+
* @param gen - Generation of the calling cycle
|
|
192
260
|
* @throws {QueueForbiddenError} When the relay says the queue is someone else's
|
|
261
|
+
* @throws Error on any other failure, or when Cloud Sync stopped meanwhile
|
|
193
262
|
*/
|
|
194
263
|
private registerQueueAs;
|
|
195
264
|
/**
|
|
@@ -206,7 +275,7 @@ export declare class CloudSyncService extends EventEmitter {
|
|
|
206
275
|
* @returns The polled queue id, else the device id
|
|
207
276
|
*/
|
|
208
277
|
private relayDeviceId;
|
|
209
|
-
/** Where a queue id taken after a 403 is remembered. */
|
|
278
|
+
/** Where a queue id taken after a 403 is remembered (home resolved at start()). */
|
|
210
279
|
private fallbackQueueFile;
|
|
211
280
|
/**
|
|
212
281
|
* The queue id this machine fell back to previously, if any.
|
|
@@ -219,6 +288,7 @@ export declare class CloudSyncService extends EventEmitter {
|
|
|
219
288
|
* time — the relay caps queues per user.
|
|
220
289
|
*
|
|
221
290
|
* @param queueId - The id that was accepted
|
|
291
|
+
* @param gen - Generation of the calling cycle (a stale one writes nothing)
|
|
222
292
|
*/
|
|
223
293
|
private writeFallbackQueueId;
|
|
224
294
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-sync.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-sync.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAQtC,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,cAAc,EACd,UAAU,EAKV,WAAW,EACZ,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"cloud-sync.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-sync.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -75,6 +75,17 @@ async function gatherTeamSummaries() {
|
|
|
75
75
|
return [];
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Gap before the next queue registration after `failures` consecutive
|
|
80
|
+
* failures: REGISTER_RETRY_BACKOFF_MS in order, then its last value forever.
|
|
81
|
+
*
|
|
82
|
+
* @param failures - Consecutive failures so far (>= 1)
|
|
83
|
+
* @returns Delay in ms
|
|
84
|
+
*/
|
|
85
|
+
export function registerRetryDelay(failures) {
|
|
86
|
+
const steps = CLOUD_SYNC_CONSTANTS.REGISTER_RETRY_BACKOFF_MS;
|
|
87
|
+
return steps[Math.min(Math.max(failures, 1), steps.length) - 1];
|
|
88
|
+
}
|
|
78
89
|
// ---------------------------------------------------------------------------
|
|
79
90
|
// Service
|
|
80
91
|
// ---------------------------------------------------------------------------
|
|
@@ -123,8 +134,31 @@ export class CloudSyncService extends EventEmitter {
|
|
|
123
134
|
messagePollRunning = false;
|
|
124
135
|
/** When the last message-poll cycle finished (watchdog input). */
|
|
125
136
|
lastMessagePollAt = 0;
|
|
126
|
-
/**
|
|
137
|
+
/**
|
|
138
|
+
* Next queue registration (self-scheduling): every REGISTER_INTERVAL_MS
|
|
139
|
+
* while registered (lets the relay evict stale Portal pairs), on the
|
|
140
|
+
* REGISTER_RETRY_BACKOFF_MS schedule while registration fails.
|
|
141
|
+
*/
|
|
127
142
|
registerTimer = null;
|
|
143
|
+
/** Consecutive failed queue registrations */
|
|
144
|
+
queueFailures = 0;
|
|
145
|
+
/** Epoch ms of the first failure in the current registration failure streak */
|
|
146
|
+
queueFailingSince = null;
|
|
147
|
+
/** Epoch ms of the next scheduled registration */
|
|
148
|
+
nextQueueAttemptAt = null;
|
|
149
|
+
/**
|
|
150
|
+
* Bumped by start() and stop(). An attempt that started under an older
|
|
151
|
+
* generation must not touch state or files — a stop() (or a test's
|
|
152
|
+
* cleanup) can land while a registration is still in flight.
|
|
153
|
+
*/
|
|
154
|
+
generation = 0;
|
|
155
|
+
/**
|
|
156
|
+
* Crewly home, resolved once at start(). Resolving it at write time let a
|
|
157
|
+
* write that outlived its caller land in a different home (a test that
|
|
158
|
+
* had already restored CREWLY_HOME wrote a random id into the owner's
|
|
159
|
+
* real ~/.crewly — 2026-10-02).
|
|
160
|
+
*/
|
|
161
|
+
crewlyHome = null;
|
|
128
162
|
/** Peer reported by the last registration, so a repeat is not logged at info. */
|
|
129
163
|
lastLoggedPeer = null;
|
|
130
164
|
/** Consecutive heartbeat failure count */
|
|
@@ -203,6 +237,14 @@ export class CloudSyncService extends EventEmitter {
|
|
|
203
237
|
this.config = config;
|
|
204
238
|
this.state = 'syncing';
|
|
205
239
|
this.startedAt = Date.now();
|
|
240
|
+
this.generation += 1;
|
|
241
|
+
this.crewlyHome = process.env['CREWLY_HOME'] ?? join(homedir(), '.crewly');
|
|
242
|
+
// The queue is re-chosen per start (a re-login may be another account).
|
|
243
|
+
this.queueId = null;
|
|
244
|
+
this.queueError = null;
|
|
245
|
+
this.queueFailures = 0;
|
|
246
|
+
this.queueFailingSince = null;
|
|
247
|
+
this.lastLoggedPeer = null;
|
|
206
248
|
this.authRejected = false;
|
|
207
249
|
this.heartbeatFailures = 0;
|
|
208
250
|
this.devicePollFailures = 0;
|
|
@@ -216,16 +258,9 @@ export class CloudSyncService extends EventEmitter {
|
|
|
216
258
|
readVersion().then((v) => { this.version = v; }).catch(() => { });
|
|
217
259
|
// Register with Cloud message queue for inter-device messaging.
|
|
218
260
|
// This gets us a queueId used for message polling and makes us
|
|
219
|
-
// discoverable by peer devices with the same pairing code.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
// Not "may not work": without a queue id the Slack instance heartbeat
|
|
223
|
-
// is skipped, so Cloud marks this machine stale and every inbound
|
|
224
|
-
// Slack event is queued instead of delivered (2026-09-21).
|
|
225
|
-
this.logger.error('Queue registration failed — this machine will not receive Cloud or Slack messages', {
|
|
226
|
-
error: this.queueError,
|
|
227
|
-
});
|
|
228
|
-
});
|
|
261
|
+
// discoverable by peer devices with the same pairing code. Retries on
|
|
262
|
+
// its own schedule until it succeeds (see runRegisterCycle).
|
|
263
|
+
void this.runRegisterCycle(this.generation);
|
|
229
264
|
// Perform initial sync immediately
|
|
230
265
|
this.sendHeartbeat().catch(() => { });
|
|
231
266
|
this.pollDevices().catch(() => { });
|
|
@@ -239,18 +274,12 @@ export class CloudSyncService extends EventEmitter {
|
|
|
239
274
|
// held long-poll never overlaps the next request. Kicks off immediately;
|
|
240
275
|
// each cycle picks its own next gap (see runMessagePollCycle).
|
|
241
276
|
this.scheduleNextMessagePoll(0);
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
// OSS would stay wedged against a dead Portal session until restart.
|
|
245
|
-
this.registerTimer = setInterval(() => { this.registerQueue().catch(() => { }); }, CLOUD_SYNC_CONSTANTS.REGISTER_INTERVAL_MS);
|
|
246
|
-
// Unref timers so they don't keep the process alive (messagePollTimer is
|
|
247
|
-
// unref'd inside scheduleNextMessagePoll on each cycle).
|
|
277
|
+
// Unref timers so they don't keep the process alive (messagePollTimer and
|
|
278
|
+
// registerTimer are unref'd where they are scheduled).
|
|
248
279
|
if (this.heartbeatTimer.unref)
|
|
249
280
|
this.heartbeatTimer.unref();
|
|
250
281
|
if (this.devicePollTimer.unref)
|
|
251
282
|
this.devicePollTimer.unref();
|
|
252
|
-
if (this.registerTimer.unref)
|
|
253
|
-
this.registerTimer.unref();
|
|
254
283
|
}
|
|
255
284
|
/**
|
|
256
285
|
* Stop the Cloud Sync service.
|
|
@@ -274,9 +303,11 @@ export class CloudSyncService extends EventEmitter {
|
|
|
274
303
|
this.messagePollTimer = null;
|
|
275
304
|
}
|
|
276
305
|
if (this.registerTimer) {
|
|
277
|
-
|
|
306
|
+
clearTimeout(this.registerTimer);
|
|
278
307
|
this.registerTimer = null;
|
|
279
308
|
}
|
|
309
|
+
this.nextQueueAttemptAt = null;
|
|
310
|
+
this.generation += 1;
|
|
280
311
|
if (this.errorRecoveryTimer) {
|
|
281
312
|
clearInterval(this.errorRecoveryTimer);
|
|
282
313
|
this.errorRecoveryTimer = null;
|
|
@@ -318,6 +349,13 @@ export class CloudSyncService extends EventEmitter {
|
|
|
318
349
|
lastContactAt: this.lastContactAt || null,
|
|
319
350
|
startedAt: this.startedAt || null,
|
|
320
351
|
authRejected: this.authRejected,
|
|
352
|
+
relayQueue: {
|
|
353
|
+
queueId: this.queueId,
|
|
354
|
+
error: this.queueError,
|
|
355
|
+
failingSince: this.queueFailingSince,
|
|
356
|
+
failures: this.queueFailures,
|
|
357
|
+
nextAttemptAt: this.nextQueueAttemptAt,
|
|
358
|
+
},
|
|
321
359
|
};
|
|
322
360
|
}
|
|
323
361
|
/** Record a request Cloud answered successfully. */
|
|
@@ -455,6 +493,67 @@ export class CloudSyncService extends EventEmitter {
|
|
|
455
493
|
// -------------------------------------------------------------------------
|
|
456
494
|
// Internal: Queue Registration
|
|
457
495
|
// -------------------------------------------------------------------------
|
|
496
|
+
/**
|
|
497
|
+
* One registration attempt, then schedule the next: the keep-alive
|
|
498
|
+
* interval after a success, the backoff after a failure. Never gives up —
|
|
499
|
+
* a machine without a queue is deaf to Cloud and Slack, and on 2026-10-02
|
|
500
|
+
* one sat like that for half an hour after a single 429 at boot.
|
|
501
|
+
*
|
|
502
|
+
* @param gen - Generation this cycle belongs to (a stale cycle exits)
|
|
503
|
+
*/
|
|
504
|
+
async runRegisterCycle(gen) {
|
|
505
|
+
if (gen !== this.generation || !this.config)
|
|
506
|
+
return;
|
|
507
|
+
let delay = CLOUD_SYNC_CONSTANTS.REGISTER_INTERVAL_MS;
|
|
508
|
+
try {
|
|
509
|
+
await this.registerQueue(gen);
|
|
510
|
+
if (gen !== this.generation)
|
|
511
|
+
return;
|
|
512
|
+
if (this.queueFailures > 0) {
|
|
513
|
+
this.logger.info('Queue registration succeeded after failing', {
|
|
514
|
+
failures: this.queueFailures,
|
|
515
|
+
queueId: this.queueId,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
this.queueFailures = 0;
|
|
519
|
+
this.queueFailingSince = null;
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
if (gen !== this.generation)
|
|
523
|
+
return;
|
|
524
|
+
this.queueError = err instanceof Error ? err.message : String(err);
|
|
525
|
+
this.queueFailures += 1;
|
|
526
|
+
this.queueFailingSince ??= Date.now();
|
|
527
|
+
delay = registerRetryDelay(this.queueFailures);
|
|
528
|
+
// Not "may not work": without a queue id the Slack instance heartbeat
|
|
529
|
+
// is skipped, so Cloud marks this machine stale and every inbound
|
|
530
|
+
// Slack event is queued instead of delivered (2026-09-21).
|
|
531
|
+
const level = this.queueId === null ? 'error' : 'warn';
|
|
532
|
+
this.logger[level](this.queueId === null
|
|
533
|
+
? 'Queue registration failed — this machine will not receive Cloud or Slack messages until it succeeds'
|
|
534
|
+
: 'Queue re-registration failed — still polling the queue registered earlier', { error: this.queueError, attempt: this.queueFailures, retryInMs: delay });
|
|
535
|
+
}
|
|
536
|
+
this.scheduleRegister(gen, delay);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Schedule the next registration attempt.
|
|
540
|
+
*
|
|
541
|
+
* @param gen - Generation the attempt belongs to
|
|
542
|
+
* @param delayMs - Gap before it
|
|
543
|
+
*/
|
|
544
|
+
scheduleRegister(gen, delayMs) {
|
|
545
|
+
if (gen !== this.generation)
|
|
546
|
+
return;
|
|
547
|
+
if (this.registerTimer)
|
|
548
|
+
clearTimeout(this.registerTimer);
|
|
549
|
+
this.nextQueueAttemptAt = Date.now() + delayMs;
|
|
550
|
+
this.registerTimer = setTimeout(() => {
|
|
551
|
+
this.registerTimer = null;
|
|
552
|
+
this.nextQueueAttemptAt = null;
|
|
553
|
+
void this.runRegisterCycle(gen);
|
|
554
|
+
}, delayMs);
|
|
555
|
+
this.registerTimer.unref?.();
|
|
556
|
+
}
|
|
458
557
|
/**
|
|
459
558
|
* Register with the Cloud relay message queue.
|
|
460
559
|
*
|
|
@@ -462,52 +561,95 @@ export class CloudSyncService extends EventEmitter {
|
|
|
462
561
|
* derived from the JWT user ID. This allows both devices of the same user
|
|
463
562
|
* to auto-discover each other's queueId for message routing.
|
|
464
563
|
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
564
|
+
* Which id to claim, in order:
|
|
565
|
+
* 1. the queue this process already registered — a running machine never
|
|
566
|
+
* switches queues (each switch left the old queue behind and used up
|
|
567
|
+
* the relay's per-user quota: f68e1995 → a8eeab1d → d5c4ebc2 in one
|
|
568
|
+
* day, all on one MacBook, when something rewrote the id file);
|
|
569
|
+
* 2. the id remembered in `<crewlyHome>/cloud/relay-queue.json`;
|
|
570
|
+
* 3. the device id.
|
|
571
|
+
*
|
|
572
|
+
* @param gen - Generation of the calling cycle
|
|
573
|
+
* @throws Error when registration fails (the caller retries)
|
|
467
574
|
*/
|
|
468
|
-
async registerQueue() {
|
|
575
|
+
async registerQueue(gen) {
|
|
469
576
|
if (!this.config)
|
|
470
|
-
|
|
577
|
+
throw new Error('Cloud Sync is not running');
|
|
471
578
|
// Derive deterministic pairing code from JWT user ID
|
|
472
579
|
const pairingCode = await this.derivePairingCode();
|
|
473
580
|
if (!pairingCode) {
|
|
474
|
-
|
|
475
|
-
return;
|
|
581
|
+
throw new Error('Cannot register queue: unable to derive pairing code from token');
|
|
476
582
|
}
|
|
477
583
|
// The relay uses deviceId as the queue id, and refuses to hand a queue to
|
|
478
584
|
// a different account than the one that created it — correct, but it
|
|
479
585
|
// strands a machine whose owner signs in under another account: the
|
|
480
586
|
// queue id is the machine's, and the 403 repeats on every boot. One
|
|
481
|
-
// MacBook sat deaf to Slack for two hours this way (2026-09-21).
|
|
482
|
-
//
|
|
483
|
-
//
|
|
484
|
-
|
|
485
|
-
const
|
|
587
|
+
// MacBook sat deaf to Slack for two hours this way (2026-09-21). On a
|
|
588
|
+
// 403 take a fresh queue (persisted, so we do not mint one per restart
|
|
589
|
+
// and eat the quota). A 403 means the queue is not ours, so minting a
|
|
590
|
+
// replacement never orphans a queue of ours.
|
|
591
|
+
const deviceId = this.config.deviceId;
|
|
592
|
+
const remembered = await this.readFallbackQueueId();
|
|
593
|
+
const first = this.queueId ?? remembered ?? deviceId;
|
|
486
594
|
try {
|
|
487
|
-
await this.registerQueueAs(first, pairingCode);
|
|
595
|
+
await this.registerQueueAs(first, pairingCode, gen);
|
|
596
|
+
await this.syncFallbackFile(first, remembered, deviceId, gen);
|
|
488
597
|
return;
|
|
489
598
|
}
|
|
490
599
|
catch (err) {
|
|
491
|
-
if (!(err instanceof QueueForbiddenError)
|
|
600
|
+
if (!(err instanceof QueueForbiddenError))
|
|
492
601
|
throw err;
|
|
493
|
-
this.logger.warn('Relay refused our
|
|
494
|
-
|
|
602
|
+
this.logger.warn('Relay refused our queue (it belongs to another account) — taking a fresh one', {
|
|
603
|
+
queueId: first,
|
|
604
|
+
deviceId,
|
|
495
605
|
});
|
|
496
606
|
}
|
|
497
607
|
const fresh = randomUUID();
|
|
498
|
-
await this.registerQueueAs(fresh, pairingCode);
|
|
499
|
-
await this.writeFallbackQueueId(fresh);
|
|
608
|
+
await this.registerQueueAs(fresh, pairingCode, gen);
|
|
609
|
+
await this.writeFallbackQueueId(fresh, gen);
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Keep the id file in step with the queue we actually hold, so the next
|
|
613
|
+
* boot claims the same queue instead of creating another: rewrite it when
|
|
614
|
+
* it names a different queue, remove it when we hold the device-id queue
|
|
615
|
+
* (the file is only for the fallback case).
|
|
616
|
+
*
|
|
617
|
+
* @param registered - The id just registered
|
|
618
|
+
* @param remembered - What the file said before this attempt
|
|
619
|
+
* @param deviceId - This machine's device id
|
|
620
|
+
* @param gen - Generation of the calling cycle
|
|
621
|
+
*/
|
|
622
|
+
async syncFallbackFile(registered, remembered, deviceId, gen) {
|
|
623
|
+
if (remembered === registered || gen !== this.generation)
|
|
624
|
+
return;
|
|
625
|
+
if (registered !== deviceId) {
|
|
626
|
+
this.logger.warn('Relay queue id file did not match the queue in use — restoring it', {
|
|
627
|
+
inUse: registered,
|
|
628
|
+
inFile: remembered,
|
|
629
|
+
});
|
|
630
|
+
await this.writeFallbackQueueId(registered, gen);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (remembered !== null) {
|
|
634
|
+
this.logger.warn('Relay queue id file named a queue this machine does not use — removing it', {
|
|
635
|
+
inUse: registered,
|
|
636
|
+
inFile: remembered,
|
|
637
|
+
});
|
|
638
|
+
await fsp.rm(this.fallbackQueueFile(), { force: true }).catch(() => { });
|
|
639
|
+
}
|
|
500
640
|
}
|
|
501
641
|
/**
|
|
502
642
|
* One registration attempt against a specific queue id.
|
|
503
643
|
*
|
|
504
644
|
* @param queueId - The id to claim
|
|
505
645
|
* @param pairingCode - Deterministic code derived from the signed-in user
|
|
646
|
+
* @param gen - Generation of the calling cycle
|
|
506
647
|
* @throws {QueueForbiddenError} When the relay says the queue is someone else's
|
|
648
|
+
* @throws Error on any other failure, or when Cloud Sync stopped meanwhile
|
|
507
649
|
*/
|
|
508
|
-
async registerQueueAs(queueId, pairingCode) {
|
|
509
|
-
if (!this.config)
|
|
510
|
-
|
|
650
|
+
async registerQueueAs(queueId, pairingCode, gen) {
|
|
651
|
+
if (!this.config || gen !== this.generation)
|
|
652
|
+
throw new Error('Cloud Sync stopped during queue registration');
|
|
511
653
|
const url = `${this.config.cloudUrl}/api/v1/relay/queue/register`;
|
|
512
654
|
const response = await fetch(url, {
|
|
513
655
|
method: 'POST',
|
|
@@ -528,19 +670,21 @@ export class CloudSyncService extends EventEmitter {
|
|
|
528
670
|
throw new Error(message);
|
|
529
671
|
}
|
|
530
672
|
const data = await response.json();
|
|
531
|
-
if (
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
673
|
+
if (gen !== this.generation)
|
|
674
|
+
throw new Error('Cloud Sync stopped during queue registration');
|
|
675
|
+
if (!data.queueId)
|
|
676
|
+
throw new Error('Queue registration failed: the relay returned no queue id');
|
|
677
|
+
// Re-registered every minute to keep the queue alive; only a change is
|
|
678
|
+
// worth an info line (it was 1,442 identical lines a day).
|
|
679
|
+
const peer = data.peerQueueId ?? 'none (waiting for peer)';
|
|
680
|
+
const changed = data.queueId !== this.queueId || peer !== this.lastLoggedPeer || this.queueError !== null;
|
|
681
|
+
this.queueId = data.queueId;
|
|
682
|
+
this.queueError = null;
|
|
683
|
+
this.lastLoggedPeer = peer;
|
|
684
|
+
this.logger[changed ? 'info' : 'debug']('Registered with Cloud message queue', {
|
|
685
|
+
queueId: this.queueId,
|
|
686
|
+
peerQueueId: peer,
|
|
687
|
+
});
|
|
544
688
|
}
|
|
545
689
|
/**
|
|
546
690
|
* The id the relay knows this machine by: the queue we actually poll.
|
|
@@ -558,9 +702,10 @@ export class CloudSyncService extends EventEmitter {
|
|
|
558
702
|
relayDeviceId() {
|
|
559
703
|
return this.queueId ?? this.config?.deviceId ?? '';
|
|
560
704
|
}
|
|
561
|
-
/** Where a queue id taken after a 403 is remembered. */
|
|
705
|
+
/** Where a queue id taken after a 403 is remembered (home resolved at start()). */
|
|
562
706
|
fallbackQueueFile() {
|
|
563
|
-
|
|
707
|
+
const home = this.crewlyHome ?? process.env['CREWLY_HOME'] ?? join(homedir(), '.crewly');
|
|
708
|
+
return join(home, 'cloud', 'relay-queue.json');
|
|
564
709
|
}
|
|
565
710
|
/**
|
|
566
711
|
* The queue id this machine fell back to previously, if any.
|
|
@@ -582,8 +727,11 @@ export class CloudSyncService extends EventEmitter {
|
|
|
582
727
|
* time — the relay caps queues per user.
|
|
583
728
|
*
|
|
584
729
|
* @param queueId - The id that was accepted
|
|
730
|
+
* @param gen - Generation of the calling cycle (a stale one writes nothing)
|
|
585
731
|
*/
|
|
586
|
-
async writeFallbackQueueId(queueId) {
|
|
732
|
+
async writeFallbackQueueId(queueId, gen) {
|
|
733
|
+
if (gen !== this.generation)
|
|
734
|
+
return;
|
|
587
735
|
const file = this.fallbackQueueFile();
|
|
588
736
|
try {
|
|
589
737
|
await fsp.mkdir(dirname(file), { recursive: true });
|