crewly 1.20.334 → 1.20.336

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 (115) hide show
  1. package/config/skills/marketplace-registry.ts +19 -4
  2. package/config/skills/registry.json +8 -8
  3. package/dist/backend/backend/src/constants.d.ts +28 -0
  4. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  5. package/dist/backend/backend/src/constants.js +28 -0
  6. package/dist/backend/backend/src/constants.js.map +1 -1
  7. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
  8. package/dist/backend/backend/src/controllers/chat/chat.controller.js +35 -0
  9. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
  10. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -1
  11. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +22 -1
  12. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -1
  13. package/dist/backend/backend/src/index.d.ts +8 -0
  14. package/dist/backend/backend/src/index.d.ts.map +1 -1
  15. package/dist/backend/backend/src/index.js +67 -0
  16. package/dist/backend/backend/src/index.js.map +1 -1
  17. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +8 -0
  18. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  19. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +10 -0
  20. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  21. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +9 -0
  22. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  23. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +18 -0
  24. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  25. package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts +22 -0
  26. package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
  27. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +43 -0
  28. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
  29. package/dist/backend/backend/src/services/decisions/decision.service.d.ts +12 -1
  30. package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  31. package/dist/backend/backend/src/services/decisions/decision.service.js +31 -5
  32. package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
  33. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
  34. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +25 -19
  35. package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
  36. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts +23 -1
  37. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  38. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +64 -17
  39. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  40. package/dist/backend/backend/src/services/slack/slack-history-reader.d.ts +26 -0
  41. package/dist/backend/backend/src/services/slack/slack-history-reader.d.ts.map +1 -0
  42. package/dist/backend/backend/src/services/slack/slack-history-reader.js +43 -0
  43. package/dist/backend/backend/src/services/slack/slack-history-reader.js.map +1 -0
  44. package/dist/backend/backend/src/services/slack/slack-inbound-backfill.service.d.ts +98 -0
  45. package/dist/backend/backend/src/services/slack/slack-inbound-backfill.service.d.ts.map +1 -0
  46. package/dist/backend/backend/src/services/slack/slack-inbound-backfill.service.js +116 -0
  47. package/dist/backend/backend/src/services/slack/slack-inbound-backfill.service.js.map +1 -0
  48. package/dist/backend/backend/src/services/slack/slack-outbound-delivery.d.ts +48 -0
  49. package/dist/backend/backend/src/services/slack/slack-outbound-delivery.d.ts.map +1 -0
  50. package/dist/backend/backend/src/services/slack/slack-outbound-delivery.js +73 -0
  51. package/dist/backend/backend/src/services/slack/slack-outbound-delivery.js.map +1 -0
  52. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +25 -2
  53. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  54. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +72 -11
  55. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  56. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts +2 -0
  57. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
  58. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js +1 -0
  59. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
  60. package/dist/backend/backend/src/services/slack/slack.service.d.ts +2 -0
  61. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  62. package/dist/backend/backend/src/services/slack/slack.service.js +12 -2
  63. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  64. package/dist/backend/backend/src/types/slack.types.d.ts +2 -0
  65. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  66. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  67. package/dist/backend/build-info.json +2 -2
  68. package/dist/cli/backend/src/constants.d.ts +28 -0
  69. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  70. package/dist/cli/backend/src/constants.js +28 -0
  71. package/dist/cli/backend/src/constants.js.map +1 -1
  72. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +8 -0
  73. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  74. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +10 -0
  75. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  76. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +9 -0
  77. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  78. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +18 -0
  79. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  80. package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts +22 -0
  81. package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
  82. package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +43 -0
  83. package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
  84. package/dist/cli/backend/src/services/decisions/decision.service.d.ts +12 -1
  85. package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  86. package/dist/cli/backend/src/services/decisions/decision.service.js +31 -5
  87. package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
  88. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts +23 -1
  89. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  90. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +64 -17
  91. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  92. package/dist/cli/backend/src/services/slack/slack-outbound-delivery.d.ts +48 -0
  93. package/dist/cli/backend/src/services/slack/slack-outbound-delivery.d.ts.map +1 -0
  94. package/dist/cli/backend/src/services/slack/slack-outbound-delivery.js +73 -0
  95. package/dist/cli/backend/src/services/slack/slack-outbound-delivery.js.map +1 -0
  96. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +25 -2
  97. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  98. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +72 -11
  99. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  100. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts +2 -0
  101. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
  102. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js +1 -0
  103. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
  104. package/dist/cli/backend/src/services/slack/slack.service.d.ts +2 -0
  105. package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
  106. package/dist/cli/backend/src/services/slack/slack.service.js +12 -2
  107. package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
  108. package/dist/cli/backend/src/types/slack.types.d.ts +2 -0
  109. package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
  110. package/dist/cli/backend/src/types/slack.types.js.map +1 -1
  111. package/dist/cli/config/skills/marketplace-registry.d.ts +10 -2
  112. package/dist/cli/config/skills/marketplace-registry.d.ts.map +1 -1
  113. package/dist/cli/config/skills/marketplace-registry.js +18 -4
  114. package/dist/cli/config/skills/marketplace-registry.js.map +1 -1
  115. package/package.json +1 -1
@@ -54,6 +54,7 @@ import { withTopicLine } from '../orc/work-item-destination.js';
54
54
  import { resolveSlackMentions, extractNativeMentionIds, leadingNameMention } from './slack-mention-resolver.js';
55
55
  import { toSlackMrkdwn } from './slack-mrkdwn.js';
56
56
  import { renderSlackThreadContext } from './slack-thread-context.service.js';
57
+ import { trackSlackDelivery, SLACK_DELIVERY_METADATA_KEY } from './slack-outbound-delivery.js';
57
58
  const EMPTY_STORE = {
58
59
  version: 1,
59
60
  autoCreate: true,
@@ -426,7 +427,10 @@ export class SlackTeamChannelService {
426
427
  onChatMessage = (dto) => {
427
428
  if (dto.senderType === 'agent')
428
429
  this.noteAgentActivity(dto.channelId, dto.threadId ?? null, 'here');
429
- void this.mirrorOutbound(dto);
430
+ if (dto.senderType === 'agent')
431
+ trackSlackDelivery(dto.id, this.mirrorOutboundDetailed(dto).then((r) => r.delivery));
432
+ else
433
+ void this.mirrorOutbound(dto);
430
434
  };
431
435
  started = false;
432
436
  /** Per-team serialisation so two team-saved events cannot create two channels. */
@@ -3320,6 +3324,17 @@ export class SlackTeamChannelService {
3320
3324
  * @returns True when a Slack post was attempted
3321
3325
  */
3322
3326
  async mirrorOutbound(dto) {
3327
+ return (await this.mirrorOutboundDetailed(dto)).attempted;
3328
+ }
3329
+ /**
3330
+ * {@link mirrorOutbound} with the outcome: the Slack channel + ts the reply
3331
+ * landed at (also stored on the chat message), or Slack's error.
3332
+ *
3333
+ * @param dto - The chat-v2 message
3334
+ * @returns Whether a post was attempted, and its delivery (null when not meant for Slack)
3335
+ */
3336
+ async mirrorOutboundDetailed(dto) {
3337
+ const skipped = { attempted: false, delivery: null };
3323
3338
  try {
3324
3339
  // Every reason a reply does not reach Slack is logged. Until now all
3325
3340
  // four were silent `return false`, so an agent could answer, be told
@@ -3331,13 +3346,13 @@ export class SlackTeamChannelService {
3331
3346
  channelId: dto.channelId,
3332
3347
  sender: dto.senderId,
3333
3348
  });
3334
- return false;
3349
+ return skipped;
3335
3350
  };
3336
3351
  if (dto.senderType === 'user' && isOwnerTypedInCrewly(dto) && !isDriveModeRow(dto)) {
3337
3352
  await this.load();
3338
3353
  const room = this.findByChatChannelId(dto.channelId);
3339
3354
  if (room && isAdhocMapping(room))
3340
- return await this.mirrorOwnerPost(room, dto);
3355
+ return { attempted: await this.mirrorOwnerPost(room, dto), delivery: null };
3341
3356
  }
3342
3357
  // A colleague agent on another machine: its post was made in Slack by
3343
3358
  // that machine and reached this one from Slack, stored as a user turn on
@@ -3393,40 +3408,84 @@ export class SlackTeamChannelService {
3393
3408
  // same step as the resolve: as two steps, a final answer landing in
3394
3409
  // between found nothing to replace and the re-opened placeholder then
3395
3410
  // stayed under it (2026-09-28).
3411
+ let postedTs = '';
3412
+ const onMessageTs = (ts) => { postedTs = ts; };
3396
3413
  if (isInterim(dto))
3397
- await this.deps.typing.resolve(typingKey, text, typingIdentity, { reopen: 'typing' });
3414
+ await this.deps.typing.resolve(typingKey, text, typingIdentity, { reopen: 'typing', onMessageTs });
3398
3415
  else
3399
- await this.deps.typing.resolve(typingKey, text, typingIdentity);
3416
+ await this.deps.typing.resolve(typingKey, text, typingIdentity, { onMessageTs });
3417
+ const delivery = this.recordDelivery(dto, mapping.slackChannelId, postedTs, threadTs);
3400
3418
  this.logger.info('Agent reply mirrored to Slack', {
3401
3419
  slackChannel: mapping.slackChannelName,
3402
3420
  sender: dto.senderId,
3403
3421
  threaded: Boolean(threadTs),
3404
3422
  via: 'typing-placeholder',
3423
+ ts: postedTs || undefined,
3405
3424
  });
3406
- return true;
3425
+ return { attempted: true, delivery };
3407
3426
  }
3408
- await this.deps.slack.sendMessage({
3427
+ const sentTs = await this.deps.slack.sendMessage({
3409
3428
  channelId: mapping.slackChannelId,
3410
3429
  text,
3411
3430
  threadTs,
3412
3431
  skipChatV2Mirror: true,
3432
+ senderSession: dto.senderId,
3413
3433
  ...identity,
3414
3434
  });
3435
+ const delivery = this.recordDelivery(dto, mapping.slackChannelId, sentTs, threadTs);
3415
3436
  this.logger.info('Agent reply mirrored to Slack', {
3416
3437
  slackChannel: mapping.slackChannelName,
3417
3438
  sender: dto.senderId,
3418
3439
  threaded: Boolean(threadTs),
3440
+ ts: sentTs || undefined,
3419
3441
  });
3420
- return true;
3442
+ return { attempted: true, delivery };
3421
3443
  }
3422
3444
  catch (err) {
3445
+ const error = err instanceof Error ? err.message : String(err);
3423
3446
  this.logger.warn('Outbound mirror to Slack failed', {
3424
3447
  channelId: dto.channelId,
3425
3448
  sender: dto.senderId,
3449
+ error,
3450
+ });
3451
+ // The post was attempted for a Slack-mapped room and failed: the
3452
+ // reply call tells the agent instead of reporting success.
3453
+ const mapped = this.findByChatChannelId(dto.channelId);
3454
+ return {
3455
+ attempted: true,
3456
+ delivery: mapped ? { delivered: false, slackChannelId: mapped.slackChannelId, error } : null,
3457
+ };
3458
+ }
3459
+ }
3460
+ /**
3461
+ * Store where a mirrored reply landed on its chat message, in the shape
3462
+ * inbound messages use, so the Slack side can be audited from our store.
3463
+ *
3464
+ * @param dto - The mirrored message
3465
+ * @param slackChannelId - Slack channel posted to
3466
+ * @param ts - Slack ts of the message that carries the reply ('' when unknown)
3467
+ * @param threadTs - Thread the reply is in
3468
+ * @returns The delivery
3469
+ */
3470
+ recordDelivery(dto, slackChannelId, ts, threadTs) {
3471
+ const delivery = {
3472
+ delivered: true,
3473
+ slackChannelId,
3474
+ ...(ts ? { ts } : {}),
3475
+ ...(threadTs ? { threadTs } : {}),
3476
+ };
3477
+ try {
3478
+ this.deps.chat.updateMessageMetadata?.(dto.id, {
3479
+ [SLACK_DELIVERY_METADATA_KEY]: { slackChannelId, ts: ts || null, threadTs: threadTs ?? null },
3480
+ });
3481
+ }
3482
+ catch (err) {
3483
+ this.logger.warn('Could not store the Slack ts on the mirrored message', {
3484
+ messageId: dto.id,
3426
3485
  error: err instanceof Error ? err.message : String(err),
3427
3486
  });
3428
- return false;
3429
3487
  }
3488
+ return delivery;
3430
3489
  }
3431
3490
  /**
3432
3491
  * Post a message the owner typed in Crewly into the room's Slack channel,
@@ -3530,7 +3589,7 @@ export class SlackTeamChannelService {
3530
3589
  *
3531
3590
  * @param mapping - Channel mapping
3532
3591
  * @param dto - The agent message (no thread)
3533
- * @returns True when the post was attempted
3592
+ * @returns The attempt and its delivery (Slack's ts is stored on the chat row)
3534
3593
  */
3535
3594
  async postTopLevel(mapping, dto) {
3536
3595
  let done = () => undefined;
@@ -3544,10 +3603,12 @@ export class SlackTeamChannelService {
3544
3603
  channelId: mapping.slackChannelId,
3545
3604
  text,
3546
3605
  skipChatV2Mirror: true,
3606
+ senderSession: dto.senderId,
3547
3607
  ...identity,
3548
3608
  });
3549
3609
  if (ts)
3550
3610
  this.recordSlackRoot(dto, mapping, ts);
3611
+ const delivery = this.recordDelivery(dto, mapping.slackChannelId, ts);
3551
3612
  this.logger.info('Agent reply mirrored to Slack', {
3552
3613
  slackChannel: mapping.slackChannelName,
3553
3614
  sender: dto.senderId,
@@ -3555,7 +3616,7 @@ export class SlackTeamChannelService {
3555
3616
  via: 'top-level',
3556
3617
  messageId: dto.id,
3557
3618
  });
3558
- return true;
3619
+ return { attempted: true, delivery };
3559
3620
  }
3560
3621
  finally {
3561
3622
  done();