crewly 1.20.302 → 1.20.304
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/developer/prompt.md +7 -0
- package/config/roles/fullstack-dev/prompt.md +7 -0
- package/config/roles/product-manager/prompt.md +7 -0
- package/config/skills/orchestrator/move-team/SKILL.md +53 -0
- package/config/skills/orchestrator/move-team/execute.sh +42 -0
- package/config/skills/orchestrator/usage-categories/SKILL.md +59 -0
- package/config/skills/orchestrator/usage-categories/execute.sh +81 -0
- package/config/skills/orchestrator/usage-categories/execute.test.sh +45 -0
- package/config/skills/orchestrator/usage-report/SKILL.md +71 -0
- package/config/skills/orchestrator/usage-report/execute.sh +84 -0
- package/config/skills/orchestrator/usage-report/execute.test.sh +39 -0
- package/config/skills/team-leader/usage-report/SKILL.md +71 -0
- package/config/skills/team-leader/usage-report/execute.sh +84 -0
- package/config/skills/team-leader/usage-report/execute.test.sh +39 -0
- package/dist/backend/backend/src/constants.d.ts +80 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +80 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/team-move/team-move.controller.d.ts +45 -0
- package/dist/backend/backend/src/controllers/team-move/team-move.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/team-move/team-move.controller.js +214 -0
- package/dist/backend/backend/src/controllers/team-move/team-move.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.controller.d.ts +36 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.controller.js +158 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.routes.d.ts +15 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.routes.js +26 -0
- package/dist/backend/backend/src/controllers/usage-ledger/usage-ledger.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +10 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +97 -20
- 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 +6 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/follow-through.wiring.d.ts +32 -0
- package/dist/backend/backend/src/services/agent/follow-through.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/follow-through.wiring.js +42 -1
- package/dist/backend/backend/src/services/agent/follow-through.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/agent/resource-mode.service.d.ts +26 -6
- package/dist/backend/backend/src/services/agent/resource-mode.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/resource-mode.service.js +59 -5
- package/dist/backend/backend/src/services/agent/resource-mode.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +1 -1
- 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 +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.d.ts +18 -0
- package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js +16 -0
- package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts +19 -0
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.js +46 -0
- package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.d.ts +35 -0
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.js +101 -0
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/background-work-watchdog.d.ts +58 -0
- package/dist/backend/backend/src/services/monitoring/background-work-watchdog.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/background-work-watchdog.js +100 -0
- package/dist/backend/backend/src/services/monitoring/background-work-watchdog.js.map +1 -0
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js +3 -0
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts +7 -0
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +15 -0
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.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 +2 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.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 +25 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts +24 -0
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js +63 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +19 -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 +41 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/team-move/team-move-archive.d.ts +122 -0
- package/dist/backend/backend/src/services/team-move/team-move-archive.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-archive.js +202 -0
- package/dist/backend/backend/src/services/team-move/team-move-archive.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-chat.d.ts +59 -0
- package/dist/backend/backend/src/services/team-move/team-move-chat.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-chat.js +133 -0
- package/dist/backend/backend/src/services/team-move/team-move-chat.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.d.ts +102 -0
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.js +217 -0
- package/dist/backend/backend/src/services/team-move/team-move-cloud.client.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-crypto.d.ts +102 -0
- package/dist/backend/backend/src/services/team-move/team-move-crypto.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-crypto.js +348 -0
- package/dist/backend/backend/src/services/team-move/team-move-crypto.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-driver.service.d.ts +209 -0
- package/dist/backend/backend/src/services/team-move/team-move-driver.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-driver.service.js +504 -0
- package/dist/backend/backend/src/services/team-move/team-move-driver.service.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-exporter.d.ts +156 -0
- package/dist/backend/backend/src/services/team-move/team-move-exporter.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-exporter.js +462 -0
- package/dist/backend/backend/src/services/team-move/team-move-exporter.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-fs.d.ts +157 -0
- package/dist/backend/backend/src/services/team-move/team-move-fs.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-fs.js +298 -0
- package/dist/backend/backend/src/services/team-move/team-move-fs.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-git.d.ts +69 -0
- package/dist/backend/backend/src/services/team-move/team-move-git.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-git.js +198 -0
- package/dist/backend/backend/src/services/team-move/team-move-git.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts +121 -0
- package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-importer.js +462 -0
- package/dist/backend/backend/src/services/team-move/team-move-importer.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-journal.d.ts +110 -0
- package/dist/backend/backend/src/services/team-move/team-move-journal.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-journal.js +198 -0
- package/dist/backend/backend/src/services/team-move/team-move-journal.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-preflight.d.ts +71 -0
- package/dist/backend/backend/src/services/team-move/team-move-preflight.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-preflight.js +102 -0
- package/dist/backend/backend/src/services/team-move/team-move-preflight.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-runtime.d.ts +29 -0
- package/dist/backend/backend/src/services/team-move/team-move-runtime.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-runtime.js +173 -0
- package/dist/backend/backend/src/services/team-move/team-move-runtime.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-secret-scan.d.ts +50 -0
- package/dist/backend/backend/src/services/team-move/team-move-secret-scan.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-secret-scan.js +96 -0
- package/dist/backend/backend/src/services/team-move/team-move-secret-scan.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-select.d.ts +94 -0
- package/dist/backend/backend/src/services/team-move/team-move-select.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move-select.js +124 -0
- package/dist/backend/backend/src/services/team-move/team-move-select.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move.fixture.d.ts +46 -0
- package/dist/backend/backend/src/services/team-move/team-move.fixture.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move.fixture.js +202 -0
- package/dist/backend/backend/src/services/team-move/team-move.fixture.js.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move.types.d.ts +269 -0
- package/dist/backend/backend/src/services/team-move/team-move.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/team-move/team-move.types.js +44 -0
- package/dist/backend/backend/src/services/team-move/team-move.types.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-context.service.d.ts +42 -2
- package/dist/backend/backend/src/services/trace/trace-context.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-context.service.js +66 -5
- package/dist/backend/backend/src/services/trace/trace-context.service.js.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-recorder.d.ts.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-recorder.js +11 -0
- package/dist/backend/backend/src/services/trace/trace-recorder.js.map +1 -1
- package/dist/backend/backend/src/services/usage-ledger/categories-param.d.ts +28 -0
- package/dist/backend/backend/src/services/usage-ledger/categories-param.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/categories-param.js +67 -0
- package/dist/backend/backend/src/services/usage-ledger/categories-param.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/excerpt.d.ts +37 -0
- package/dist/backend/backend/src/services/usage-ledger/excerpt.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/excerpt.js +49 -0
- package/dist/backend/backend/src/services/usage-ledger/excerpt.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/index.d.ts +14 -0
- package/dist/backend/backend/src/services/usage-ledger/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/index.js +14 -0
- package/dist/backend/backend/src/services/usage-ledger/index.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-hooks.d.ts +44 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-hooks.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-hooks.js +52 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-hooks.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-rollup.d.ts +100 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-rollup.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-rollup.js +189 -0
- package/dist/backend/backend/src/services/usage-ledger/ledger-rollup.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/owner-spans.d.ts +41 -0
- package/dist/backend/backend/src/services/usage-ledger/owner-spans.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/owner-spans.js +71 -0
- package/dist/backend/backend/src/services/usage-ledger/owner-spans.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/team-directory.d.ts +47 -0
- package/dist/backend/backend/src/services/usage-ledger/team-directory.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/team-directory.js +106 -0
- package/dist/backend/backend/src/services/usage-ledger/team-directory.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/unit-classifier.d.ts +101 -0
- package/dist/backend/backend/src/services/usage-ledger/unit-classifier.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/unit-classifier.js +263 -0
- package/dist/backend/backend/src/services/usage-ledger/unit-classifier.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-categories.store.d.ts +96 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-categories.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-categories.store.js +166 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-categories.store.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.backfill.d.ts +90 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.backfill.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.backfill.js +294 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.backfill.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.recorder.d.ts +102 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.recorder.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.recorder.js +314 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.recorder.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.runtime.d.ts +62 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.runtime.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.runtime.js +106 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.runtime.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.store.d.ts +52 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.store.js +95 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.store.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.types.d.ts +127 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.types.js +19 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-ledger.types.js.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-report.service.d.ts +124 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-report.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-report.service.js +372 -0
- package/dist/backend/backend/src/services/usage-ledger/usage-report.service.js.map +1 -0
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +80 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +80 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/resource-mode.service.d.ts +26 -6
- package/dist/cli/backend/src/services/agent/resource-mode.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/resource-mode.service.js +59 -5
- package/dist/cli/backend/src/services/agent/resource-mode.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +1 -1
- 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 +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/cli/backend/src/services/core/storage.service.d.ts +18 -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 +16 -0
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts +19 -0
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision.service.js +46 -0
- package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.d.ts +35 -0
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.js +101 -0
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js +3 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.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 +25 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts +24 -0
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js +63 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +19 -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 +41 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-context.service.d.ts +42 -2
- package/dist/cli/backend/src/services/trace/trace-context.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-context.service.js +66 -5
- package/dist/cli/backend/src/services/trace/trace-context.service.js.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-recorder.d.ts.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-recorder.js +11 -0
- package/dist/cli/backend/src/services/trace/trace-recorder.js.map +1 -1
- package/dist/cli/backend/src/services/usage-ledger/ledger-hooks.d.ts +44 -0
- package/dist/cli/backend/src/services/usage-ledger/ledger-hooks.d.ts.map +1 -0
- package/dist/cli/backend/src/services/usage-ledger/ledger-hooks.js +52 -0
- package/dist/cli/backend/src/services/usage-ledger/ledger-hooks.js.map +1 -0
- package/dist/cli/cli/src/commands/team-move.d.ts +68 -0
- package/dist/cli/cli/src/commands/team-move.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/team-move.js +155 -0
- package/dist/cli/cli/src/commands/team-move.js.map +1 -0
- package/dist/cli/cli/src/index.js +33 -0
- package/dist/cli/cli/src/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source-side stop, archive and rollback of a moved team.
|
|
3
|
+
*
|
|
4
|
+
* `archive` stops the team and hides it: its folder, open work items, open
|
|
5
|
+
* decisions, chat channels and Slack mapping are saved under
|
|
6
|
+
* `~/.crewly/team-moves/<moveId>/archive/` and taken out of the live stores, so
|
|
7
|
+
* nothing on this machine wakes agents that now live elsewhere. The archive is
|
|
8
|
+
* kept 7 days. `restore` puts everything back and starts the team (rollback).
|
|
9
|
+
* The same `archive` is what the target runs when a move is rolled back.
|
|
10
|
+
*
|
|
11
|
+
* The team's folder is removed with `detachTeamForMove`, never `deleteTeam`:
|
|
12
|
+
* a delete would archive the Slack channel and remove the agents' Slack apps,
|
|
13
|
+
* which now belong to the other machine.
|
|
14
|
+
*
|
|
15
|
+
* @module services/team-move/team-move-archive
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'node:fs/promises';
|
|
18
|
+
import * as path from 'node:path';
|
|
19
|
+
import { TEAM_MOVE_CONSTANTS } from '../../constants.js';
|
|
20
|
+
import { safeReadJson } from '../../utils/file-io.utils.js';
|
|
21
|
+
import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
|
|
22
|
+
import { readTeamChat, setChannelsArchived } from './team-move-chat.js';
|
|
23
|
+
import { StagingArea, pathExists, walkFiles } from './team-move-fs.js';
|
|
24
|
+
import { MoveJournal, listLocalMoveIds, moveDirFor } from './team-move-journal.js';
|
|
25
|
+
import { identityOf, selectDecisions, selectPoolItems, selectScheduledMessages } from './team-move-select.js';
|
|
26
|
+
const C = TEAM_MOVE_CONSTANTS;
|
|
27
|
+
/** The archiver. */
|
|
28
|
+
export class TeamMoveArchiver {
|
|
29
|
+
deps;
|
|
30
|
+
home;
|
|
31
|
+
now;
|
|
32
|
+
constructor(deps) {
|
|
33
|
+
this.deps = deps;
|
|
34
|
+
this.home = deps.home ?? getCrewlyHomePath();
|
|
35
|
+
this.now = deps.now ?? (() => new Date().toISOString());
|
|
36
|
+
}
|
|
37
|
+
archiveDir(moveId) {
|
|
38
|
+
return path.join(moveDirFor(moveId, this.home), 'archive');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read a move's archive record.
|
|
42
|
+
*
|
|
43
|
+
* @param moveId - Move id
|
|
44
|
+
* @returns The metadata, or null when nothing was archived
|
|
45
|
+
*/
|
|
46
|
+
async readMeta(moveId) {
|
|
47
|
+
return safeReadJson(path.join(this.archiveDir(moveId), 'meta.json'), null);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Stop the team and archive it (hidden, kept 7 days). Idempotent.
|
|
51
|
+
*
|
|
52
|
+
* @param moveId - Move id
|
|
53
|
+
* @param teamId - Team to archive
|
|
54
|
+
* @returns The archive metadata, or null when the team is not on this machine
|
|
55
|
+
*/
|
|
56
|
+
async archive(moveId, teamId) {
|
|
57
|
+
const journal = new MoveJournal(moveId, this.home, this.now);
|
|
58
|
+
const existing = await this.readMeta(moveId);
|
|
59
|
+
if (existing && existing.state === 'archived')
|
|
60
|
+
return existing;
|
|
61
|
+
const team = (await this.deps.storage.getTeams()).find((t) => t.id === teamId);
|
|
62
|
+
if (!team)
|
|
63
|
+
return null;
|
|
64
|
+
const id = identityOf(team);
|
|
65
|
+
const dir = this.archiveDir(moveId);
|
|
66
|
+
await journal.run('archive:stop', async () => {
|
|
67
|
+
await this.deps.runtime.stopTeam(teamId);
|
|
68
|
+
return { stopped: true };
|
|
69
|
+
});
|
|
70
|
+
const records = await journal.run('archive:snapshot', async () => {
|
|
71
|
+
const staging = new StagingArea(path.join(dir, 'team'));
|
|
72
|
+
await staging.init();
|
|
73
|
+
const teamDir = path.join(this.home, 'teams', teamId);
|
|
74
|
+
for await (const f of walkFiles(teamDir))
|
|
75
|
+
await staging.copyIn(f.abs, f.rel);
|
|
76
|
+
// The config as stored, with its runtime state (the live file is about to go).
|
|
77
|
+
const config = await safeReadJson(path.join(teamDir, 'config.json'), null);
|
|
78
|
+
await staging.writeJson('config.json', config ?? team);
|
|
79
|
+
const pool = await this.deps.pool.read();
|
|
80
|
+
const slice = selectPoolItems(pool, id);
|
|
81
|
+
const decisions = selectDecisions(await this.deps.decisions.list(), id);
|
|
82
|
+
const scheduled = selectScheduledMessages(await this.deps.storage.getScheduledMessages(), id);
|
|
83
|
+
const chat = readTeamChat(this.home, id);
|
|
84
|
+
const out = {
|
|
85
|
+
workItems: slice.workItems,
|
|
86
|
+
decisionIds: decisions.map((d) => d.id),
|
|
87
|
+
channelIds: chat.channels.map((c) => String(c['id'])),
|
|
88
|
+
mapping: null,
|
|
89
|
+
scheduledMessages: scheduled,
|
|
90
|
+
};
|
|
91
|
+
return out;
|
|
92
|
+
});
|
|
93
|
+
// Take the team out of the live stores. Each piece is safe to repeat.
|
|
94
|
+
await journal.run('archive:release', async () => {
|
|
95
|
+
const removed = await this.deps.pool.removeWorkItems(records.workItems.map((w) => w.id));
|
|
96
|
+
for (const decisionId of records.decisionIds)
|
|
97
|
+
await this.deps.decisions.setStatus(decisionId, 'cancelled');
|
|
98
|
+
for (const m of records.scheduledMessages)
|
|
99
|
+
await this.deps.storage.deleteScheduledMessage(m.id);
|
|
100
|
+
setChannelsArchived(this.home, records.channelIds, true);
|
|
101
|
+
const mapping = await this.deps.slack.unlink(teamId);
|
|
102
|
+
return { removed, mapping };
|
|
103
|
+
});
|
|
104
|
+
const released = (await journal.detailOf('archive:release')) ?? { mapping: null };
|
|
105
|
+
await journal.run('archive:detach', async () => {
|
|
106
|
+
await this.deps.storage.detachTeamForMove(teamId);
|
|
107
|
+
return { detached: true };
|
|
108
|
+
});
|
|
109
|
+
const at = this.now();
|
|
110
|
+
const meta = {
|
|
111
|
+
moveId,
|
|
112
|
+
teamId,
|
|
113
|
+
teamName: team.name,
|
|
114
|
+
archivedAt: at,
|
|
115
|
+
expiresAt: new Date(Date.parse(at) + C.ARCHIVE_RETENTION_MS).toISOString(),
|
|
116
|
+
state: 'archived',
|
|
117
|
+
records: { ...records, mapping: released.mapping },
|
|
118
|
+
};
|
|
119
|
+
await fs.mkdir(dir, { recursive: true });
|
|
120
|
+
await fs.writeFile(path.join(dir, 'meta.json'), JSON.stringify(meta, null, 2));
|
|
121
|
+
return meta;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Put an archived team back and start it (rollback on the source).
|
|
125
|
+
*
|
|
126
|
+
* @param moveId - Move id
|
|
127
|
+
* @param options - `start` false restores without starting
|
|
128
|
+
* @returns What happened; `restored` is false when there is nothing to restore
|
|
129
|
+
*/
|
|
130
|
+
async restore(moveId, options = {}) {
|
|
131
|
+
const meta = await this.readMeta(moveId);
|
|
132
|
+
if (!meta || meta.state !== 'archived')
|
|
133
|
+
return { restored: false, started: false };
|
|
134
|
+
if (Date.parse(meta.expiresAt) < Date.parse(this.now()))
|
|
135
|
+
return { restored: false, started: false, error: 'the archive has expired' };
|
|
136
|
+
const dir = this.archiveDir(moveId);
|
|
137
|
+
const teamDir = path.join(this.home, 'teams', meta.teamId);
|
|
138
|
+
const journal = new MoveJournal(moveId, this.home, this.now);
|
|
139
|
+
await journal.run('restore:records', async () => {
|
|
140
|
+
// The Slack mapping first, so the returning team keeps its channel.
|
|
141
|
+
if (meta.records.mapping)
|
|
142
|
+
await this.deps.slack.adopt(meta.records.mapping);
|
|
143
|
+
setChannelsArchived(this.home, meta.records.channelIds, false);
|
|
144
|
+
await this.deps.pool.addWorkItems(meta.records.workItems);
|
|
145
|
+
for (const decisionId of meta.records.decisionIds)
|
|
146
|
+
await this.deps.decisions.setStatus(decisionId, 'open');
|
|
147
|
+
const have = new Set((await this.deps.storage.getScheduledMessages()).map((m) => m.id));
|
|
148
|
+
for (const m of meta.records.scheduledMessages)
|
|
149
|
+
if (!have.has(m.id))
|
|
150
|
+
await this.deps.storage.saveScheduledMessage(m);
|
|
151
|
+
return { restored: true };
|
|
152
|
+
});
|
|
153
|
+
await journal.run('restore:team', async () => {
|
|
154
|
+
for await (const f of walkFiles(path.join(dir, 'team'))) {
|
|
155
|
+
if (f.rel === 'config.json')
|
|
156
|
+
continue;
|
|
157
|
+
const dest = path.join(teamDir, ...f.rel.split('/'));
|
|
158
|
+
await fs.mkdir(path.dirname(dest), { recursive: true });
|
|
159
|
+
await fs.copyFile(f.abs, dest);
|
|
160
|
+
}
|
|
161
|
+
const config = await safeReadJson(path.join(dir, 'team', 'config.json'), null);
|
|
162
|
+
if (!config)
|
|
163
|
+
throw new Error('the archive has no team config');
|
|
164
|
+
await this.deps.storage.saveTeam({ ...config, updatedAt: this.now() });
|
|
165
|
+
return { restored: true };
|
|
166
|
+
});
|
|
167
|
+
let started = false;
|
|
168
|
+
let error;
|
|
169
|
+
if (options.start !== false) {
|
|
170
|
+
const result = await journal.run('restore:start', async () => this.deps.runtime.startTeam(meta.teamId));
|
|
171
|
+
started = result.ok;
|
|
172
|
+
error = result.error;
|
|
173
|
+
}
|
|
174
|
+
await fs.writeFile(path.join(dir, 'meta.json'), JSON.stringify({ ...meta, state: 'restored' }, null, 2));
|
|
175
|
+
return { restored: true, started, ...(error ? { error } : {}) };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Delete archives past their retention. Run at boot and daily.
|
|
179
|
+
*
|
|
180
|
+
* @returns Move ids that were purged
|
|
181
|
+
*/
|
|
182
|
+
async purgeExpired() {
|
|
183
|
+
const purged = [];
|
|
184
|
+
const nowMs = Date.parse(this.now());
|
|
185
|
+
for (const moveId of await listLocalMoveIds(this.home)) {
|
|
186
|
+
const meta = await this.readMeta(moveId);
|
|
187
|
+
if (!meta || meta.state === 'purged')
|
|
188
|
+
continue;
|
|
189
|
+
if (meta.state === 'archived' && Date.parse(meta.expiresAt) > nowMs)
|
|
190
|
+
continue;
|
|
191
|
+
// A restored archive and an expired one are both done with.
|
|
192
|
+
const dir = this.archiveDir(moveId);
|
|
193
|
+
if (await pathExists(dir)) {
|
|
194
|
+
await fs.rm(path.join(dir, 'team'), { recursive: true, force: true });
|
|
195
|
+
await fs.writeFile(path.join(dir, 'meta.json'), JSON.stringify({ ...meta, state: 'purged', records: { ...meta.records, workItems: [] } }, null, 2));
|
|
196
|
+
}
|
|
197
|
+
purged.push(moveId);
|
|
198
|
+
}
|
|
199
|
+
return purged;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=team-move-archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-move-archive.js","sourceRoot":"","sources":["../../../../../../backend/src/services/team-move/team-move-archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat channels and rooms of a team (chat-v2 SQLite): which exist, who is a
|
|
3
|
+
* member, and putting them on another machine. Messages stay where they were
|
|
4
|
+
* said: only the channels and their membership move, so the team's rooms (and
|
|
5
|
+
* the Slack mapping that points at them) exist on the target from the start.
|
|
6
|
+
*
|
|
7
|
+
* @module services/team-move/team-move-chat
|
|
8
|
+
*/
|
|
9
|
+
import type { TeamIdentity } from './team-move-select.js';
|
|
10
|
+
/** A `chat_channels` row (columns vary by schema version). */
|
|
11
|
+
export type ChannelRecord = Record<string, string | number | null>;
|
|
12
|
+
/** A `chat_channel_members` row. */
|
|
13
|
+
export interface ChannelMemberRecord {
|
|
14
|
+
channel_id: string;
|
|
15
|
+
member_session: string;
|
|
16
|
+
joined_at: number;
|
|
17
|
+
}
|
|
18
|
+
/** What a package carries of the chat store. */
|
|
19
|
+
export interface ChatRecords {
|
|
20
|
+
channels: ChannelRecord[];
|
|
21
|
+
members: ChannelMemberRecord[];
|
|
22
|
+
}
|
|
23
|
+
/** File name of the chat-v2 store under the Crewly home (the default chat database path). */
|
|
24
|
+
export declare const CHAT_V2_DB_FILE = "chat.db";
|
|
25
|
+
/**
|
|
26
|
+
* The team's channels, rooms and DMs with their members.
|
|
27
|
+
*
|
|
28
|
+
* @param home - Crewly home of the source
|
|
29
|
+
* @param id - Team identity
|
|
30
|
+
* @returns Records (empty when the machine has no chat store)
|
|
31
|
+
*/
|
|
32
|
+
export declare function readTeamChat(home: string, id: TeamIdentity): ChatRecords;
|
|
33
|
+
/** Outcome of {@link applyTeamChat}. */
|
|
34
|
+
export interface ApplyChatResult {
|
|
35
|
+
channelsAdded: number;
|
|
36
|
+
channelsExisting: number;
|
|
37
|
+
membersAdded: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Add channels and members that are not there yet (idempotent). A channel that
|
|
41
|
+
* exists already (same id, or the same unique name) is kept as it is.
|
|
42
|
+
*
|
|
43
|
+
* @param home - Crewly home of the target
|
|
44
|
+
* @param records - Records from the package
|
|
45
|
+
* @returns Counts
|
|
46
|
+
*/
|
|
47
|
+
export declare function applyTeamChat(home: string, records: ChatRecords): ApplyChatResult;
|
|
48
|
+
/**
|
|
49
|
+
* Archive (hide) or unarchive channels. Used on the source while the moved
|
|
50
|
+
* team is away.
|
|
51
|
+
*
|
|
52
|
+
* @param home - Crewly home
|
|
53
|
+
* @param channelIds - Channel ids
|
|
54
|
+
* @param archived - True to archive, false to bring them back
|
|
55
|
+
* @param nowMs - Archive time
|
|
56
|
+
* @returns Number of rows changed
|
|
57
|
+
*/
|
|
58
|
+
export declare function setChannelsArchived(home: string, channelIds: readonly string[], archived: boolean, nowMs?: number): number;
|
|
59
|
+
//# sourceMappingURL=team-move-chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-move-chat.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/team-move/team-move-chat.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,8DAA8D;AAC9D,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;AACnE,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED,6FAA6F;AAC7F,eAAO,MAAM,eAAe,YAAY,CAAC;AAYzC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,WAAW,CA2BxE;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,eAAe,CA0BjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,GAAE,MAAmB,GAAG,MAAM,CAgBtI"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat channels and rooms of a team (chat-v2 SQLite): which exist, who is a
|
|
3
|
+
* member, and putting them on another machine. Messages stay where they were
|
|
4
|
+
* said: only the channels and their membership move, so the team's rooms (and
|
|
5
|
+
* the Slack mapping that points at them) exist on the target from the start.
|
|
6
|
+
*
|
|
7
|
+
* @module services/team-move/team-move-chat
|
|
8
|
+
*/
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { openChatDatabase } from '../chat-v2/sqlite/chat-db.js';
|
|
12
|
+
/** File name of the chat-v2 store under the Crewly home (the default chat database path). */
|
|
13
|
+
export const CHAT_V2_DB_FILE = 'chat.db';
|
|
14
|
+
/**
|
|
15
|
+
* Open the chat store of a home.
|
|
16
|
+
*
|
|
17
|
+
* @param home - Crewly home
|
|
18
|
+
* @returns Database handle (caller closes)
|
|
19
|
+
*/
|
|
20
|
+
function open(home) {
|
|
21
|
+
return openChatDatabase({ dbPath: path.join(home, CHAT_V2_DB_FILE), skipIntegrityCheck: true });
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The team's channels, rooms and DMs with their members.
|
|
25
|
+
*
|
|
26
|
+
* @param home - Crewly home of the source
|
|
27
|
+
* @param id - Team identity
|
|
28
|
+
* @returns Records (empty when the machine has no chat store)
|
|
29
|
+
*/
|
|
30
|
+
export function readTeamChat(home, id) {
|
|
31
|
+
if (!existsSync(path.join(home, CHAT_V2_DB_FILE)))
|
|
32
|
+
return { channels: [], members: [] };
|
|
33
|
+
const db = open(home);
|
|
34
|
+
try {
|
|
35
|
+
const sessions = [...id.sessions];
|
|
36
|
+
const channels = db.prepare('SELECT * FROM chat_channels WHERE archived_at IS NULL').all();
|
|
37
|
+
const members = db.prepare('SELECT channel_id, member_session, joined_at FROM chat_channel_members').all();
|
|
38
|
+
const membersByChannel = new Map();
|
|
39
|
+
for (const m of members) {
|
|
40
|
+
const list = membersByChannel.get(m.channel_id) ?? [];
|
|
41
|
+
list.push(m.member_session);
|
|
42
|
+
membersByChannel.set(m.channel_id, list);
|
|
43
|
+
}
|
|
44
|
+
const selected = channels.filter((c) => {
|
|
45
|
+
if (c['team_id'] === id.teamId)
|
|
46
|
+
return true;
|
|
47
|
+
if (c['type'] === 'dm')
|
|
48
|
+
return typeof c['agent_session'] === 'string' && id.sessions.has(c['agent_session']);
|
|
49
|
+
if (c['type'] === 'huddle') {
|
|
50
|
+
const roster = membersByChannel.get(String(c['id'])) ?? [];
|
|
51
|
+
return roster.length > 0 && roster.every((s) => sessions.includes(s));
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
});
|
|
55
|
+
const ids = new Set(selected.map((c) => String(c['id'])));
|
|
56
|
+
return { channels: selected, members: members.filter((m) => ids.has(m.channel_id)) };
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
db.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Add channels and members that are not there yet (idempotent). A channel that
|
|
64
|
+
* exists already (same id, or the same unique name) is kept as it is.
|
|
65
|
+
*
|
|
66
|
+
* @param home - Crewly home of the target
|
|
67
|
+
* @param records - Records from the package
|
|
68
|
+
* @returns Counts
|
|
69
|
+
*/
|
|
70
|
+
export function applyTeamChat(home, records) {
|
|
71
|
+
const result = { channelsAdded: 0, channelsExisting: 0, membersAdded: 0 };
|
|
72
|
+
if (records.channels.length === 0)
|
|
73
|
+
return result;
|
|
74
|
+
const db = open(home);
|
|
75
|
+
try {
|
|
76
|
+
const columns = new Set(db.prepare('PRAGMA table_info(chat_channels)').all().map((c) => c.name));
|
|
77
|
+
const tx = db.transaction(() => {
|
|
78
|
+
for (const row of records.channels) {
|
|
79
|
+
const keys = Object.keys(row).filter((k) => columns.has(k));
|
|
80
|
+
const sql = `INSERT OR IGNORE INTO chat_channels (${keys.join(',')}) VALUES (${keys.map(() => '?').join(',')})`;
|
|
81
|
+
const info = db.prepare(sql).run(...keys.map((k) => row[k] ?? null));
|
|
82
|
+
if (info.changes > 0)
|
|
83
|
+
result.channelsAdded += 1;
|
|
84
|
+
else
|
|
85
|
+
result.channelsExisting += 1;
|
|
86
|
+
}
|
|
87
|
+
const insertMember = db.prepare('INSERT OR IGNORE INTO chat_channel_members (channel_id, member_session, joined_at) VALUES (?, ?, ?)');
|
|
88
|
+
for (const m of records.members) {
|
|
89
|
+
const exists = db.prepare('SELECT 1 FROM chat_channels WHERE id = ?').get(m.channel_id);
|
|
90
|
+
if (!exists)
|
|
91
|
+
continue;
|
|
92
|
+
if (insertMember.run(m.channel_id, m.member_session, m.joined_at).changes > 0)
|
|
93
|
+
result.membersAdded += 1;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
tx();
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
db.close();
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Archive (hide) or unarchive channels. Used on the source while the moved
|
|
105
|
+
* team is away.
|
|
106
|
+
*
|
|
107
|
+
* @param home - Crewly home
|
|
108
|
+
* @param channelIds - Channel ids
|
|
109
|
+
* @param archived - True to archive, false to bring them back
|
|
110
|
+
* @param nowMs - Archive time
|
|
111
|
+
* @returns Number of rows changed
|
|
112
|
+
*/
|
|
113
|
+
export function setChannelsArchived(home, channelIds, archived, nowMs = Date.now()) {
|
|
114
|
+
if (channelIds.length === 0 || !existsSync(path.join(home, CHAT_V2_DB_FILE)))
|
|
115
|
+
return 0;
|
|
116
|
+
const db = open(home);
|
|
117
|
+
try {
|
|
118
|
+
const stmt = archived
|
|
119
|
+
? db.prepare('UPDATE chat_channels SET archived_at = ? WHERE id = ? AND archived_at IS NULL')
|
|
120
|
+
: db.prepare('UPDATE chat_channels SET archived_at = NULL WHERE id = ? AND archived_at IS NOT NULL');
|
|
121
|
+
let changed = 0;
|
|
122
|
+
const tx = db.transaction(() => {
|
|
123
|
+
for (const id of channelIds)
|
|
124
|
+
changed += (archived ? stmt.run(nowMs, id) : stmt.run(id)).changes;
|
|
125
|
+
});
|
|
126
|
+
tx();
|
|
127
|
+
return changed;
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
db.close();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=team-move-chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-move-chat.js","sourceRoot":"","sources":["../../../../../../backend/src/services/team-move/team-move-chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud client of the team move: the REST calls of the shared contract
|
|
3
|
+
* (`<cloud>/api/cloud/team-moves`). The machine authenticates with the same
|
|
4
|
+
* account token it uses for every other Cloud call; Cloud answers an instance
|
|
5
|
+
* only about moves of its own account and machine.
|
|
6
|
+
*
|
|
7
|
+
* @module services/team-move/team-move-cloud.client
|
|
8
|
+
*/
|
|
9
|
+
import type { CloudManifestSummary, TeamMovePreflight, TeamMoveReportStatus, TeamMoveView } from './team-move.types.js';
|
|
10
|
+
/** The Cloud session (CloudClientService). */
|
|
11
|
+
export interface TeamMoveCloudSession {
|
|
12
|
+
getToken(): string | null;
|
|
13
|
+
getCloudUrl(): string | null;
|
|
14
|
+
/** Refresh an expired access token; true when a new one is in place. */
|
|
15
|
+
tryRefreshToken?(): Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
/** An error answer from Cloud (or no answer at all). */
|
|
18
|
+
export declare class TeamMoveCloudError extends Error {
|
|
19
|
+
readonly status: number;
|
|
20
|
+
readonly code?: string | undefined;
|
|
21
|
+
constructor(message: string, status: number, code?: string | undefined);
|
|
22
|
+
/** Worth trying again: the network, a server error, rate limiting. */
|
|
23
|
+
get retryable(): boolean;
|
|
24
|
+
}
|
|
25
|
+
/** Constructor options. */
|
|
26
|
+
export interface TeamMoveCloudClientOptions {
|
|
27
|
+
session: TeamMoveCloudSession;
|
|
28
|
+
/** This machine's Cloud instance id; sent on every call (owner and instance share one token). */
|
|
29
|
+
getInstanceId: () => Promise<string>;
|
|
30
|
+
fetchImpl?: typeof fetch;
|
|
31
|
+
sleep?: (ms: number) => Promise<void>;
|
|
32
|
+
/** Retry backoff base (ms); tests pass 0. */
|
|
33
|
+
retryBaseMs?: number;
|
|
34
|
+
}
|
|
35
|
+
/** Client for the team-move endpoints. */
|
|
36
|
+
export declare class TeamMoveCloudClient {
|
|
37
|
+
private readonly options;
|
|
38
|
+
private readonly fetchImpl;
|
|
39
|
+
private readonly sleep;
|
|
40
|
+
private readonly retryBaseMs;
|
|
41
|
+
constructor(options: TeamMoveCloudClientOptions);
|
|
42
|
+
/** Whether the machine is signed in to Cloud. */
|
|
43
|
+
isConnected(): boolean;
|
|
44
|
+
private url;
|
|
45
|
+
/**
|
|
46
|
+
* One authenticated request with a token refresh on 401 and retries on
|
|
47
|
+
* network and 5xx errors.
|
|
48
|
+
*/
|
|
49
|
+
private request;
|
|
50
|
+
private errorFrom;
|
|
51
|
+
/** Cloud wraps answers in `{success, data}`; accept both shapes. */
|
|
52
|
+
private data;
|
|
53
|
+
/** The caller's moves, newest first. An instance sees what it has to do (`role`/`action`). */
|
|
54
|
+
list(): Promise<TeamMoveView[]>;
|
|
55
|
+
/** One move. */
|
|
56
|
+
get(moveId: string): Promise<TeamMoveView>;
|
|
57
|
+
/** Ask Cloud to start a move (the owner path, or an instance acting for the owner). */
|
|
58
|
+
create(body: {
|
|
59
|
+
teamId: string;
|
|
60
|
+
sourceInstanceId: string;
|
|
61
|
+
targetInstanceId: string;
|
|
62
|
+
}): Promise<{
|
|
63
|
+
moveId: string;
|
|
64
|
+
}>;
|
|
65
|
+
/** Target: publish the per-move public key and preflight. */
|
|
66
|
+
postTargetKey(moveId: string, body: {
|
|
67
|
+
publicKey: string;
|
|
68
|
+
preflight: TeamMovePreflight;
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
/** Source: announce the ciphertext. */
|
|
71
|
+
packageInit(moveId: string, body: {
|
|
72
|
+
size: number;
|
|
73
|
+
sha256: string;
|
|
74
|
+
chunks: number;
|
|
75
|
+
manifest: CloudManifestSummary;
|
|
76
|
+
}): Promise<{
|
|
77
|
+
uploadId: string;
|
|
78
|
+
received: number[];
|
|
79
|
+
}>;
|
|
80
|
+
/** Source: upload one ciphertext chunk (0-based). */
|
|
81
|
+
putChunk(moveId: string, n: number, chunk: Buffer): Promise<void>;
|
|
82
|
+
/** Source: all chunks are up. */
|
|
83
|
+
packageComplete(moveId: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Target: download the ciphertext, resuming a partial file with `Range`.
|
|
86
|
+
*
|
|
87
|
+
* @param moveId - Move id
|
|
88
|
+
* @param dest - File to write (kept between attempts)
|
|
89
|
+
* @param totalSize - Expected size from the package metadata
|
|
90
|
+
* @returns Final size
|
|
91
|
+
*/
|
|
92
|
+
downloadPackage(moveId: string, dest: string, totalSize: number): Promise<number>;
|
|
93
|
+
/** Report a status. */
|
|
94
|
+
postStatus(moveId: string, body: {
|
|
95
|
+
status: TeamMoveReportStatus;
|
|
96
|
+
report?: unknown;
|
|
97
|
+
error?: string;
|
|
98
|
+
}): Promise<void>;
|
|
99
|
+
/** Owner: roll the move back. */
|
|
100
|
+
rollback(moveId: string): Promise<void>;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=team-move-cloud.client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-move-cloud.client.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/team-move/team-move-cloud.client.ts"],"names":[],"mappings":"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"}
|