crewly 1.20.208 → 1.20.209

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 (74) hide show
  1. package/dist/backend/backend/src/constants.d.ts +2 -0
  2. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  3. package/dist/backend/backend/src/constants.js +2 -0
  4. package/dist/backend/backend/src/constants.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
  6. package/dist/backend/backend/src/controllers/slack/slack.controller.js +29 -0
  7. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
  8. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +9 -0
  9. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  10. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +11 -0
  11. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  12. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +10 -0
  13. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  14. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +19 -0
  15. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  16. package/dist/backend/backend/src/services/session/session-command-helper.d.ts.map +1 -1
  17. package/dist/backend/backend/src/services/session/session-command-helper.js +18 -6
  18. package/dist/backend/backend/src/services/session/session-command-helper.js.map +1 -1
  19. package/dist/backend/backend/src/services/session/tui-input-guard.d.ts +25 -0
  20. package/dist/backend/backend/src/services/session/tui-input-guard.d.ts.map +1 -1
  21. package/dist/backend/backend/src/services/session/tui-input-guard.js +24 -1
  22. package/dist/backend/backend/src/services/session/tui-input-guard.js.map +1 -1
  23. package/dist/backend/backend/src/services/slack/slack-delivery-audit.service.d.ts +156 -0
  24. package/dist/backend/backend/src/services/slack/slack-delivery-audit.service.d.ts.map +1 -0
  25. package/dist/backend/backend/src/services/slack/slack-delivery-audit.service.js +259 -0
  26. package/dist/backend/backend/src/services/slack/slack-delivery-audit.service.js.map +1 -0
  27. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  28. package/dist/backend/backend/src/services/slack/slack-initializer.js +19 -0
  29. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  30. package/dist/backend/backend/src/services/slack/slack-instance-registry.service.d.ts +14 -1
  31. package/dist/backend/backend/src/services/slack/slack-instance-registry.service.d.ts.map +1 -1
  32. package/dist/backend/backend/src/services/slack/slack-instance-registry.service.js +13 -0
  33. package/dist/backend/backend/src/services/slack/slack-instance-registry.service.js.map +1 -1
  34. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  35. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +7 -1
  36. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  37. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +22 -1
  38. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  39. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +41 -4
  40. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  41. package/dist/backend/backend/src/types/slack.types.d.ts +48 -0
  42. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  43. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  44. package/dist/backend/build-info.json +2 -2
  45. package/dist/cli/backend/src/constants.d.ts +2 -0
  46. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  47. package/dist/cli/backend/src/constants.js +2 -0
  48. package/dist/cli/backend/src/constants.js.map +1 -1
  49. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +9 -0
  50. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  51. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +11 -0
  52. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  53. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +10 -0
  54. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  55. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +19 -0
  56. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  57. package/dist/cli/backend/src/services/session/session-command-helper.d.ts.map +1 -1
  58. package/dist/cli/backend/src/services/session/session-command-helper.js +18 -6
  59. package/dist/cli/backend/src/services/session/session-command-helper.js.map +1 -1
  60. package/dist/cli/backend/src/services/session/tui-input-guard.d.ts +25 -0
  61. package/dist/cli/backend/src/services/session/tui-input-guard.d.ts.map +1 -1
  62. package/dist/cli/backend/src/services/session/tui-input-guard.js +24 -1
  63. package/dist/cli/backend/src/services/session/tui-input-guard.js.map +1 -1
  64. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  65. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +7 -1
  66. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  67. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +22 -1
  68. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  69. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +41 -4
  70. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  71. package/dist/cli/backend/src/types/slack.types.d.ts +48 -0
  72. package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
  73. package/dist/cli/backend/src/types/slack.types.js.map +1 -1
  74. package/package.json +1 -1
@@ -87,16 +87,34 @@ export function slackChannelNameFor(teamName, prefix = '') {
87
87
  * there is awake; otherwise the lowest instance id among machines with an
88
88
  * awake room member. Null when nobody is awake (Cloud's fallback decides).
89
89
  *
90
+ * Cloud's delivery facts come first (specs/2026-10-04-room-delivery-audit.md):
91
+ * the responder Cloud names (`delivery.owner`) is the owner — Cloud pushes it
92
+ * first and names another if it cannot be reached. Without one, the owner is
93
+ * computed among the machines Cloud delivered to (`delivery.targets`) only,
94
+ * a machine with an awake team leader first: exactly one machine takes the
95
+ * message, and never one that does not have it (2026-10-03, #content-team:
96
+ * nobody; review of crewly-services#32: "uncertain" must not mean everyone).
97
+ *
90
98
  * @param room - Cloud's room presence
91
99
  * @returns Owning instance id, or null
92
100
  */
93
101
  export function roomOwnerInstance(room) {
94
- const awake = [...new Set(room.members.filter((m) => m.awake).map((m) => m.instanceId))];
102
+ const delivery = room.delivery;
103
+ if (delivery?.owner)
104
+ return delivery.owner;
105
+ const targets = delivery && Array.isArray(delivery.targets) && delivery.targets.length > 0 ? delivery.targets : null;
106
+ const awakeMembers = room.members.filter((m) => m.awake && (!targets || targets.includes(m.instanceId)));
107
+ const awake = [...new Set(awakeMembers.map((m) => m.instanceId))].sort();
95
108
  if (awake.length === 0)
96
109
  return null;
97
110
  if (room.home && awake.includes(room.home.instanceId))
98
111
  return room.home.instanceId;
99
- return awake.sort()[0];
112
+ if (delivery) {
113
+ const withLeader = [...new Set(awakeMembers.filter((m) => m.leader).map((m) => m.instanceId))].sort();
114
+ if (withLeader.length > 0)
115
+ return withLeader[0];
116
+ }
117
+ return awake[0];
100
118
  }
101
119
  /**
102
120
  * The one machine that watches a shared-room message nobody on it answers:
@@ -116,8 +134,12 @@ export function roomWatcherInstance(room) {
116
134
  if (owner)
117
135
  return owner;
118
136
  const live = (m) => m.live;
119
- const pool = room.members.some((m) => live(m) === true) ? room.members.filter((m) => live(m) === true) : room.members.filter((m) => live(m) !== false);
120
- return [...new Set(pool.map((m) => m.instanceId))].sort()[0] ?? null;
137
+ // Only a machine Cloud delivered this message to can watch it.
138
+ const targets = room.delivery?.targets;
139
+ const members = Array.isArray(targets) && targets.length > 0 ? room.members.filter((m) => targets.includes(m.instanceId)) : room.members;
140
+ const pool = members.some((m) => live(m) === true) ? members.filter((m) => live(m) === true) : members.filter((m) => live(m) !== false);
141
+ const fromMembers = [...new Set(pool.map((m) => m.instanceId))].sort()[0];
142
+ return fromMembers ?? (Array.isArray(targets) ? [...targets].sort()[0] ?? null : null);
121
143
  }
122
144
  /**
123
145
  * Whether a mapping is an ad-hoc channel (no Crewly team behind it).
@@ -2444,6 +2466,21 @@ export class SlackTeamChannelService {
2444
2466
  this.logger.info('Room message handed to an agent on another machine', { agentSession: hit.session, slackChannel: mapping.slackChannelName });
2445
2467
  return { ok: true, agentSession: hit.session, displayName: hit.name, via: 'cloud' };
2446
2468
  }
2469
+ /**
2470
+ * Every Slack channel this machine maps — team channels and ad-hoc rooms —
2471
+ * with the local agents in it. What the delivery audit reads Slack for.
2472
+ *
2473
+ * @returns Channel id, name and local member sessions
2474
+ */
2475
+ async listMappedRooms() {
2476
+ await this.load();
2477
+ const teams = await this.deps.storage.getTeams();
2478
+ return (this.store?.mappings ?? []).map((m) => {
2479
+ const team = isAdhocMapping(m) ? undefined : teams.find((t) => t.id === m.teamId);
2480
+ const members = team ? teamChannelMembers(team).map((x) => x.sessionName) : [...(m.members ?? [])];
2481
+ return { slackChannelId: m.slackChannelId, slackChannelName: m.slackChannelName, members };
2482
+ });
2483
+ }
2447
2484
  /**
2448
2485
  * The ad-hoc rooms this machine's agents are in, for the Cloud heartbeat —
2449
2486
  * Cloud builds each room's cross-machine roster from these.