crewly 1.20.147 → 1.20.149

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.
Files changed (126) hide show
  1. package/config/constants.ts +43 -0
  2. package/config/roles/developer/prompt.md +2 -1
  3. package/config/roles/orchestrator/prompt.md +3 -2
  4. package/config/roles/product-manager/prompt.md +2 -1
  5. package/config/roles/team-leader/tl-addon.md +11 -2
  6. package/config/skills/team-leader/set-member-model/SKILL.md +60 -0
  7. package/config/skills/team-leader/set-member-model/execute.sh +55 -0
  8. package/config/skills/team-leader/set-member-model/execute.test.sh +76 -0
  9. package/dist/backend/backend/src/constants.d.ts +75 -0
  10. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  11. package/dist/backend/backend/src/constants.js +58 -1
  12. package/dist/backend/backend/src/constants.js.map +1 -1
  13. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  14. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +21 -0
  15. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  16. package/dist/backend/backend/src/index.d.ts +11 -0
  17. package/dist/backend/backend/src/index.d.ts.map +1 -1
  18. package/dist/backend/backend/src/index.js +86 -11
  19. package/dist/backend/backend/src/index.js.map +1 -1
  20. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +9 -6
  21. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  22. package/dist/backend/backend/src/services/agent/agent-registration.service.js +22 -16
  23. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  24. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts +248 -0
  25. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -0
  26. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js +572 -0
  27. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -0
  28. package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts +8 -0
  29. package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/agent/runtime-session-recovery.js +12 -1
  31. package/dist/backend/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
  32. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts +200 -0
  33. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.d.ts.map +1 -0
  34. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js +485 -0
  35. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.service.js.map +1 -0
  36. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts +163 -0
  37. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.d.ts.map +1 -0
  38. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js +176 -0
  39. package/dist/backend/backend/src/services/cloud/cloud-disconnect-notice.utils.js.map +1 -0
  40. package/dist/backend/backend/src/services/cloud/cloud-login-runner.d.ts +106 -0
  41. package/dist/backend/backend/src/services/cloud/cloud-login-runner.d.ts.map +1 -0
  42. package/dist/backend/backend/src/services/cloud/cloud-login-runner.js +238 -0
  43. package/dist/backend/backend/src/services/cloud/cloud-login-runner.js.map +1 -0
  44. package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts +16 -1
  45. package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
  46. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +38 -0
  47. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
  48. package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +14 -0
  49. package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
  50. package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
  51. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts +10 -0
  52. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
  53. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +41 -3
  54. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
  55. package/dist/backend/backend/src/services/session/session-state-persistence.d.ts +9 -0
  56. package/dist/backend/backend/src/services/session/session-state-persistence.d.ts.map +1 -1
  57. package/dist/backend/backend/src/services/session/session-state-persistence.js +20 -0
  58. package/dist/backend/backend/src/services/session/session-state-persistence.js.map +1 -1
  59. package/dist/backend/backend/src/services/skill/skill-permission.service.d.ts.map +1 -1
  60. package/dist/backend/backend/src/services/skill/skill-permission.service.js +1 -0
  61. package/dist/backend/backend/src/services/skill/skill-permission.service.js.map +1 -1
  62. package/dist/backend/backend/src/services/slack/slack-owner-direct-dm.d.ts +55 -0
  63. package/dist/backend/backend/src/services/slack/slack-owner-direct-dm.d.ts.map +1 -0
  64. package/dist/backend/backend/src/services/slack/slack-owner-direct-dm.js +114 -0
  65. package/dist/backend/backend/src/services/slack/slack-owner-direct-dm.js.map +1 -0
  66. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.d.ts +25 -1
  67. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.d.ts.map +1 -1
  68. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js +82 -2
  69. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js.map +1 -1
  70. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +27 -0
  71. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
  72. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +48 -2
  73. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
  74. package/dist/backend/backend/src/types/settings.types.d.ts +8 -0
  75. package/dist/backend/backend/src/types/settings.types.d.ts.map +1 -1
  76. package/dist/backend/backend/src/types/settings.types.js +4 -0
  77. package/dist/backend/backend/src/types/settings.types.js.map +1 -1
  78. package/dist/backend/backend/src/utils/member-default-model.utils.d.ts +66 -0
  79. package/dist/backend/backend/src/utils/member-default-model.utils.d.ts.map +1 -0
  80. package/dist/backend/backend/src/utils/member-default-model.utils.js +95 -0
  81. package/dist/backend/backend/src/utils/member-default-model.utils.js.map +1 -0
  82. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.d.ts +53 -0
  83. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.d.ts.map +1 -0
  84. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.js +75 -0
  85. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.js.map +1 -0
  86. package/dist/backend/build-info.json +2 -2
  87. package/dist/backend/config/constants.d.ts +42 -0
  88. package/dist/backend/config/constants.d.ts.map +1 -1
  89. package/dist/backend/config/constants.js +42 -0
  90. package/dist/backend/config/constants.js.map +1 -1
  91. package/dist/cli/backend/src/constants.d.ts +75 -0
  92. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  93. package/dist/cli/backend/src/constants.js +58 -1
  94. package/dist/cli/backend/src/constants.js.map +1 -1
  95. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +9 -6
  96. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  97. package/dist/cli/backend/src/services/agent/agent-registration.service.js +22 -16
  98. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  99. package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts +8 -0
  100. package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
  101. package/dist/cli/backend/src/services/agent/runtime-session-recovery.js +12 -1
  102. package/dist/cli/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
  103. package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts +16 -1
  104. package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
  105. package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +38 -0
  106. package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
  107. package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +14 -0
  108. package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
  109. package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
  110. package/dist/cli/backend/src/services/session/session-state-persistence.d.ts +9 -0
  111. package/dist/cli/backend/src/services/session/session-state-persistence.d.ts.map +1 -1
  112. package/dist/cli/backend/src/services/session/session-state-persistence.js +20 -0
  113. package/dist/cli/backend/src/services/session/session-state-persistence.js.map +1 -1
  114. package/dist/cli/backend/src/types/settings.types.d.ts +8 -0
  115. package/dist/cli/backend/src/types/settings.types.d.ts.map +1 -1
  116. package/dist/cli/backend/src/types/settings.types.js +4 -0
  117. package/dist/cli/backend/src/types/settings.types.js.map +1 -1
  118. package/dist/cli/backend/src/utils/member-default-model.utils.d.ts +66 -0
  119. package/dist/cli/backend/src/utils/member-default-model.utils.d.ts.map +1 -0
  120. package/dist/cli/backend/src/utils/member-default-model.utils.js +95 -0
  121. package/dist/cli/backend/src/utils/member-default-model.utils.js.map +1 -0
  122. package/dist/cli/config/constants.d.ts +42 -0
  123. package/dist/cli/config/constants.d.ts.map +1 -1
  124. package/dist/cli/config/constants.js +42 -0
  125. package/dist/cli/config/constants.js.map +1 -1
  126. package/package.json +1 -1
@@ -23,7 +23,7 @@ import { TerminalGateway, setTerminalGateway } from './websocket/terminal.gatewa
23
23
  import { initializeChatGateway } from './websocket/chat.gateway.js';
24
24
  import { LoggerService } from './services/core/logger.service.js';
25
25
  import { retryWithBackoff } from './services/core/retry.util.js';
26
- import { CREWLY_CONSTANTS, ORCHESTRATOR_SESSION_NAME, ORCHESTRATOR_ROLE, ORCHESTRATOR_WINDOW_NAME, MESSAGE_QUEUE_CONSTANTS, RUNTIME_TYPES, AUDITOR_CONSTANTS, AUDITOR_SCHEDULER_CONSTANTS, API_SECURITY_CONSTANTS, } from './constants.js';
26
+ import { CREWLY_CONSTANTS, ORCHESTRATOR_SESSION_NAME, CLOUD_DISCONNECT_NOTICE_CONSTANTS, ORCHESTRATOR_ROLE, ORCHESTRATOR_WINDOW_NAME, MESSAGE_QUEUE_CONSTANTS, RUNTIME_TYPES, AUDITOR_CONSTANTS, AUDITOR_SCHEDULER_CONSTANTS, API_SECURITY_CONSTANTS, } from './constants.js';
27
27
  import { getSettingsService } from './services/settings/index.js';
28
28
  import { MemoryService } from './services/memory/memory.service.js';
29
29
  import { getImprovementStartupService } from './services/orchestrator/improvement-startup.service.js';
@@ -109,6 +109,9 @@ import { assertBuildProvenance } from './utils/build-provenance.js';
109
109
  import { isNativeBindingFatalError } from './utils/native-binding.utils.js';
110
110
  import { VersionCheckService } from './services/system/version-check.service.js';
111
111
  import { AutoUpdateService, createAutoUpdateService } from './services/system/auto-update.service.js';
112
+ import { createCloudDisconnectNoticeService, } from './services/cloud/cloud-disconnect-notice.service.js';
113
+ import { isNoticeEnabled } from './services/cloud/cloud-disconnect-notice.utils.js';
114
+ import { createOwnerDirectDm } from './services/slack/slack-owner-direct-dm.js';
112
115
  import { LogRotationService } from './services/session/log-rotation.service.js';
113
116
  import { AuditorSchedulerService } from './services/agent/auditor-scheduler.service.js';
114
117
  import { setAuditorSchedulerService } from './controllers/auditor/auditor.controller.js';
@@ -212,6 +215,8 @@ export class CrewlyServer {
212
215
  chatV2Dispatcher = null;
213
216
  // Shutdown state
214
217
  isShuttingDown = false;
218
+ /** Tells the owner on Slack when this machine loses Crewly Cloud */
219
+ cloudDisconnectNotice = null;
215
220
  /** Epoch ms of the last shutdown signal acted on (dedups process-group delivery) */
216
221
  lastShutdownSignalAt = 0;
217
222
  /** Interrupted turns loaded at boot, resumed once their agents are back */
@@ -2300,16 +2305,35 @@ export class CrewlyServer {
2300
2305
  triggerId,
2301
2306
  requestId: template.requestId,
2302
2307
  });
2303
- await TaskPoolService.getInstance().addToPool(workItem);
2304
- // Project as a trigger_action TaskRecord
2305
- await taskProjection.createRecord({
2306
- title: workItem.title,
2307
- type: 'trigger_action',
2308
- ownerAgent: 'system',
2309
- triggerId,
2310
- workItemId: workItem.id,
2311
- });
2312
- logger.info('TriggerEngine: WorkItem enqueued', { triggerId, workItemId: workItem.id });
2308
+ // Each fire is a full wake-up for the target. Skip it when the same
2309
+ // work is still open: an identical item from an earlier fire, or —
2310
+ // for an idle-verify watcher — the bridge's Verify item for that
2311
+ // worker (agent:idle_after_task fires on every busy→idle).
2312
+ const { findOpenDuplicateWorkItem, findCoveringVerifyItem } = await import('./utils/trigger-workitem-dedupe.utils.js');
2313
+ const poolItems = await TaskPoolService.getInstance().getAllItems().catch(() => []);
2314
+ const draft = { target: workItem.target, owner: workItem.owner, title: workItem.title };
2315
+ const duplicate = findOpenDuplicateWorkItem(poolItems, draft)
2316
+ ?? findCoveringVerifyItem(poolItems, trigger, draft);
2317
+ if (duplicate) {
2318
+ logger.debug('TriggerEngine: WorkItem skipped — same work already open', {
2319
+ triggerId,
2320
+ target: workItem.target,
2321
+ title: workItem.title,
2322
+ existingWorkItemId: duplicate.id,
2323
+ });
2324
+ }
2325
+ else {
2326
+ await TaskPoolService.getInstance().addToPool(workItem);
2327
+ // Project as a trigger_action TaskRecord
2328
+ await taskProjection.createRecord({
2329
+ title: workItem.title,
2330
+ type: 'trigger_action',
2331
+ ownerAgent: 'system',
2332
+ triggerId,
2333
+ workItemId: workItem.id,
2334
+ });
2335
+ logger.info('TriggerEngine: WorkItem enqueued', { triggerId, workItemId: workItem.id });
2336
+ }
2313
2337
  }
2314
2338
  catch (err) {
2315
2339
  logger.warn('TriggerEngine: createWorkItem failed', {
@@ -2554,6 +2578,9 @@ export class CrewlyServer {
2554
2578
  // orchestrator auto-start so an upgrade boot is known when the
2555
2579
  // "back online" announcement is composed.
2556
2580
  this.startAutoUpdate();
2581
+ // Tell the owner (Slack DM, phone re-login link) when this machine
2582
+ // loses Crewly Cloud — inbound Slack then queues in Cloud unseen.
2583
+ this.startCloudDisconnectNotice();
2557
2584
  // V3-only as of spec 2026-05-06-task-management-v1-deprecation.md.
2558
2585
  // The legacy `TaskTrackingService.startAutoSync()` is gone — V3
2559
2586
  // task-pool reconciler owns lifecycle cleanup now.
@@ -3640,6 +3667,53 @@ export class CrewlyServer {
3640
3667
  });
3641
3668
  }
3642
3669
  }
3670
+ /**
3671
+ * Start the Cloud disconnect notice: DM the owner on Slack when this
3672
+ * machine has lost Crewly Cloud (sign-in expired, Cloud unreachable), with
3673
+ * a re-login link from `crewly cloud login` run by Crewly itself. The DM
3674
+ * goes straight through the Slack Web API with the orchestrator's own bot
3675
+ * (falling back to the workspace bot) — outbound Slack needs no Cloud.
3676
+ * Off with `CREWLY_CLOUD_DISCONNECT_NOTICE=0`. Never throws.
3677
+ */
3678
+ startCloudDisconnectNotice() {
3679
+ if (!isNoticeEnabled(process.env[CLOUD_DISCONNECT_NOTICE_CONSTANTS.ENV_SWITCH])) {
3680
+ this.logger.info('Cloud disconnect notice off (CREWLY_CLOUD_DISCONNECT_NOTICE=0)');
3681
+ return;
3682
+ }
3683
+ try {
3684
+ const service = createCloudDisconnectNoticeService({
3685
+ crewlyHome: this.config.crewlyHome,
3686
+ getDm: () => {
3687
+ const slack = getSlackService();
3688
+ const ownerUserId = slack.getOwnerUserId?.() ?? null;
3689
+ const botToken = getSlackAgentIdentityService()?.getInstalled(ORCHESTRATOR_SESSION_NAME)?.botToken ?? slack.getBotToken();
3690
+ return ownerUserId && botToken ? createOwnerDirectDm({ botToken, ownerUserId }) : null;
3691
+ },
3692
+ reconnect: async () => {
3693
+ // The CLI already POSTed /api/cloud/connect; connect again from
3694
+ // the saved config so CloudSync surely runs on the new token
3695
+ // (the CLI may target another port, or sync was mid-error).
3696
+ const { CloudClientService } = await import('./services/cloud/cloud-client.service.js');
3697
+ const { CloudSyncService } = await import('./services/cloud/cloud-sync.service.js');
3698
+ const { performCloudConnect } = await import('./controllers/cloud/cloud.controller.js');
3699
+ const config = await CloudClientService.getInstance().loadPersistedConfig();
3700
+ if (!config)
3701
+ return false;
3702
+ CloudSyncService.getInstance().stop();
3703
+ await performCloudConnect({ cloudUrl: config.cloudUrl, token: config.token, refreshToken: config.refreshToken });
3704
+ return CloudSyncService.getInstance().getState() === 'syncing';
3705
+ },
3706
+ getDeviceName: async () => (await DeviceIdentityService.getInstance().getOrCreateIdentity()).deviceName,
3707
+ });
3708
+ service.start();
3709
+ this.cloudDisconnectNotice = service;
3710
+ }
3711
+ catch (error) {
3712
+ this.logger.warn('Cloud disconnect notice not started (non-fatal)', {
3713
+ error: error instanceof Error ? error.message : String(error),
3714
+ });
3715
+ }
3716
+ }
3643
3717
  /**
3644
3718
  * Load interrupted turns left by the previous shutdown (fresh ones only).
3645
3719
  */
@@ -4065,6 +4139,7 @@ export class CrewlyServer {
4065
4139
  const exitCode = options.exitCode ?? PROCESS_EXIT_CODES.SUCCESS;
4066
4140
  this.logger.info('Shutting down Crewly server...', { reason: options.reason ?? 'unspecified' });
4067
4141
  AutoUpdateService.getInstance()?.stop();
4142
+ this.cloudDisconnectNotice?.stop();
4068
4143
  // Safe restart: stop delivering, wait for agents mid-turn, persist the rest.
4069
4144
  // Runs before the force-exit timer below, which only bounds the teardown.
4070
4145
  await this.drainInFlightTurns(options.reason ?? 'shutdown', options.drain !== false);