@wowyuarm/dsh-agent-team 0.1.11 → 0.1.12

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 (83) hide show
  1. package/README.md +4 -4
  2. package/README.zh.md +4 -4
  3. package/package.json +3 -2
  4. package/packages/agent-team/README.md +2 -2
  5. package/packages/agent-team/README.zh.md +2 -2
  6. package/packages/agent-team/lib/context-projection.js +5 -1
  7. package/packages/agent-team/lib/index.js +11 -44
  8. package/packages/agent-team/lib/ledger.js +251 -142
  9. package/packages/agent-team/lib/member-runtime.js +47 -9
  10. package/packages/agent-team/lib/mentions.js +56 -0
  11. package/packages/agent-team/lib/spec.js +1 -0
  12. package/packages/agent-team/lib/typert.host.js +80 -31
  13. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  14. package/packages/agent-team/lib/typert.remote-client.js +71 -26
  15. package/packages/agent-team/lib/types/context-projection.d.ts.map +1 -1
  16. package/packages/agent-team/lib/types/index.d.ts +1 -7
  17. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  18. package/packages/agent-team/lib/types/ledger.d.ts +75 -17
  19. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  20. package/packages/agent-team/lib/types/member-runtime.d.ts +2 -1
  21. package/packages/agent-team/lib/types/member-runtime.d.ts.map +1 -1
  22. package/packages/agent-team/lib/types/mentions.d.ts +34 -0
  23. package/packages/agent-team/lib/types/mentions.d.ts.map +1 -0
  24. package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
  25. package/packages/agent-team/lib/types/types/entities.d.ts +0 -18
  26. package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -1
  27. package/packages/agent-team/lib/types/types/requests-results.d.ts +57 -15
  28. package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
  29. package/packages/agent-team/preset/team-member/agent.cordis.yml +48 -8
  30. package/packages/client-agent-team/lib/client.js +1366 -909
  31. package/packages/client-agent-team/lib/client.js.map +1 -1
  32. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
  33. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +3 -3
  34. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts +18 -0
  35. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts.map +1 -0
  36. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.js +22 -0
  37. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +3 -1
  38. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
  39. package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +125 -13
  40. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
  41. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +10 -3
  42. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
  43. package/packages/client-agent-team/lib/types/client/TeamComposer.js +11 -17
  44. package/packages/client-agent-team/lib/types/client/TeamConversation.js +1 -1
  45. package/packages/client-agent-team/lib/types/client/TeamCountBadge.d.ts +20 -0
  46. package/packages/client-agent-team/lib/types/client/TeamCountBadge.d.ts.map +1 -0
  47. package/packages/client-agent-team/lib/types/client/TeamCountBadge.js +25 -0
  48. package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts +9 -5
  49. package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts.map +1 -1
  50. package/packages/client-agent-team/lib/types/client/TeamInboxPage.js +82 -14
  51. package/packages/client-agent-team/lib/types/client/TeamMemberRow.d.ts +43 -0
  52. package/packages/client-agent-team/lib/types/client/TeamMemberRow.d.ts.map +1 -0
  53. package/packages/client-agent-team/lib/types/client/TeamMemberRow.js +27 -0
  54. package/packages/client-agent-team/lib/types/client/TeamMembersAction.d.ts +2 -2
  55. package/packages/client-agent-team/lib/types/client/TeamMembersAction.d.ts.map +1 -1
  56. package/packages/client-agent-team/lib/types/client/TeamMembersAction.js +2 -2
  57. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
  58. package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +6 -2
  59. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
  60. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +28 -10
  61. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  62. package/packages/client-agent-team/lib/types/client/index.js +3 -4
  63. package/packages/client-agent-team/lib/types/client/locales.d.ts +36 -16
  64. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
  65. package/packages/client-agent-team/lib/types/client/locales.js +36 -16
  66. package/packages/client-agent-team/lib/types/client/slots.d.ts +0 -1
  67. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
  68. package/packages/client-agent-team/lib/types/client/team-changes.d.ts +7 -1
  69. package/packages/client-agent-team/lib/types/client/team-changes.d.ts.map +1 -1
  70. package/packages/client-agent-team/lib/types/client/team-changes.js +62 -31
  71. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +38 -5
  72. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
  73. package/packages/client-agent-team/lib/types/client/team-formatters.js +54 -7
  74. package/packages/tool-agent-team/README.md +2 -2
  75. package/packages/tool-agent-team/README.zh.md +2 -2
  76. package/packages/tool-agent-team/lib/index.js +29 -16
  77. package/packages/tool-agent-team/lib/types/index.d.ts.map +1 -1
  78. package/packages/agent-team/lib/progress-nudge.js +0 -328
  79. package/packages/agent-team/lib/types/progress-nudge.d.ts +0 -136
  80. package/packages/agent-team/lib/types/progress-nudge.d.ts.map +0 -1
  81. package/packages/client-agent-team/lib/types/client/TeamSettings.d.ts +0 -3
  82. package/packages/client-agent-team/lib/types/client/TeamSettings.d.ts.map +0 -1
  83. package/packages/client-agent-team/lib/types/client/TeamSettings.js +0 -5
@@ -4512,8 +4512,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4512
4512
  });
4513
4513
  const _wowyuarm_dsh_agent_team_agentTeam_inbox_parameter_0$schema = object({
4514
4514
  "workspaceId": intersection(string(), unknown()).readonly(),
4515
- "limit": number().readonly().optional(),
4516
- "directOnly": boolean().readonly().optional()
4515
+ "limit": number().readonly().optional()
4517
4516
  });
4518
4517
  const _wowyuarm_dsh_agent_team_agentTeam_inbox_result$schema = object({
4519
4518
  "items": array(object({
@@ -4547,6 +4546,60 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4547
4546
  "previewText": string().readonly().optional(),
4548
4547
  "newestSequence": number().readonly(),
4549
4548
  "newestOccurredAt": string().readonly(),
4549
+ "newestActor": object({
4550
+ "memberId": intersection(string(), unknown()).readonly(),
4551
+ "name": string().readonly()
4552
+ }).readonly(),
4553
+ "claimOwners": array(object({
4554
+ "memberId": intersection(string(), unknown()).readonly(),
4555
+ "name": string().readonly()
4556
+ })).readonly(),
4557
+ "attention": object({
4558
+ "memberId": intersection(string(), unknown()).readonly(),
4559
+ "threadRef": intersection(string(), unknown()).readonly(),
4560
+ "startSequence": number().readonly(),
4561
+ "readThroughSequence": number().readonly()
4562
+ }).readonly().optional()
4563
+ })).readonly(),
4564
+ "recent": array(object({
4565
+ "channelRef": intersection(string(), unknown()).readonly(),
4566
+ "channelName": string().readonly().optional(),
4567
+ "task": object({
4568
+ "taskRef": intersection(string(), unknown()).readonly(),
4569
+ "channelRef": intersection(string(), unknown()).readonly(),
4570
+ "threadRef": intersection(string(), unknown()).readonly(),
4571
+ "status": union([
4572
+ literal("done"),
4573
+ literal("todo"),
4574
+ literal("in_progress"),
4575
+ literal("in_review"),
4576
+ literal("closed")
4577
+ ]).readonly(),
4578
+ "resolution": union([
4579
+ literal("closed"),
4580
+ literal("open"),
4581
+ literal("accepted")
4582
+ ]).readonly()
4583
+ }).readonly().optional(),
4584
+ "taskNumber": number().readonly().optional(),
4585
+ "thread": object({
4586
+ "threadRef": intersection(string(), unknown()).readonly(),
4587
+ "taskRef": intersection(string(), unknown()).readonly().optional(),
4588
+ "revision": number().readonly()
4589
+ }).readonly(),
4590
+ "unreadCount": number().readonly(),
4591
+ "directCount": number().readonly(),
4592
+ "previewText": string().readonly().optional(),
4593
+ "newestSequence": number().readonly(),
4594
+ "newestOccurredAt": string().readonly(),
4595
+ "newestActor": object({
4596
+ "memberId": intersection(string(), unknown()).readonly(),
4597
+ "name": string().readonly()
4598
+ }).readonly(),
4599
+ "claimOwners": array(object({
4600
+ "memberId": intersection(string(), unknown()).readonly(),
4601
+ "name": string().readonly()
4602
+ })).readonly(),
4550
4603
  "attention": object({
4551
4604
  "memberId": intersection(string(), unknown()).readonly(),
4552
4605
  "threadRef": intersection(string(), unknown()).readonly(),
@@ -4856,6 +4909,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4856
4909
  })).readonly(),
4857
4910
  "readThroughSequence": number().readonly(),
4858
4911
  "remainingUnreadCount": number().readonly(),
4912
+ "earlierFactCount": number().readonly().optional(),
4859
4913
  "attention": object({
4860
4914
  "memberId": intersection(string(), unknown()).readonly(),
4861
4915
  "threadRef": intersection(string(), unknown()).readonly(),
@@ -5085,7 +5139,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5085
5139
  "threadRef": intersection(string(), unknown()).readonly(),
5086
5140
  "messageRef": intersection(string(), unknown()).readonly(),
5087
5141
  "sequence": number().readonly()
5088
- })).readonly()
5142
+ })).readonly(),
5143
+ "undeliveredMentions": array(intersection(string(), unknown())).readonly().optional()
5089
5144
  })
5090
5145
  ]);
5091
5146
  const _wowyuarm_dsh_agent_team_agentTeam_resolveTaskRefs_parameter_0$schema = object({
@@ -5620,7 +5675,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5620
5675
  },
5621
5676
  sourceLocation: {
5622
5677
  "file": "packages/agent-team/src/index.ts",
5623
- "line": 718,
5678
+ "line": 699,
5624
5679
  "column": 9
5625
5680
  }
5626
5681
  },
@@ -5647,7 +5702,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5647
5702
  },
5648
5703
  sourceLocation: {
5649
5704
  "file": "packages/agent-team/src/index.ts",
5650
- "line": 708,
5705
+ "line": 689,
5651
5706
  "column": 9
5652
5707
  }
5653
5708
  },
@@ -5674,7 +5729,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5674
5729
  },
5675
5730
  sourceLocation: {
5676
5731
  "file": "packages/agent-team/src/index.ts",
5677
- "line": 1105,
5732
+ "line": 1080,
5678
5733
  "column": 9
5679
5734
  }
5680
5735
  },
@@ -5701,7 +5756,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5701
5756
  },
5702
5757
  sourceLocation: {
5703
5758
  "file": "packages/agent-team/src/index.ts",
5704
- "line": 1227,
5759
+ "line": 1202,
5705
5760
  "column": 9
5706
5761
  }
5707
5762
  },
@@ -5729,7 +5784,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5729
5784
  },
5730
5785
  sourceLocation: {
5731
5786
  "file": "packages/agent-team/src/index.ts",
5732
- "line": 639,
5787
+ "line": 620,
5733
5788
  "column": 9
5734
5789
  }
5735
5790
  },
@@ -5756,7 +5811,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5756
5811
  },
5757
5812
  sourceLocation: {
5758
5813
  "file": "packages/agent-team/src/index.ts",
5759
- "line": 1117,
5814
+ "line": 1092,
5760
5815
  "column": 9
5761
5816
  }
5762
5817
  },
@@ -5783,7 +5838,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5783
5838
  },
5784
5839
  sourceLocation: {
5785
5840
  "file": "packages/agent-team/src/index.ts",
5786
- "line": 833,
5841
+ "line": 814,
5787
5842
  "column": 9
5788
5843
  }
5789
5844
  },
@@ -5810,7 +5865,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5810
5865
  },
5811
5866
  sourceLocation: {
5812
5867
  "file": "packages/agent-team/src/index.ts",
5813
- "line": 681,
5868
+ "line": 662,
5814
5869
  "column": 9
5815
5870
  }
5816
5871
  },
@@ -5837,7 +5892,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5837
5892
  },
5838
5893
  sourceLocation: {
5839
5894
  "file": "packages/agent-team/src/index.ts",
5840
- "line": 1213,
5895
+ "line": 1188,
5841
5896
  "column": 9
5842
5897
  }
5843
5898
  },
@@ -5864,7 +5919,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5864
5919
  },
5865
5920
  sourceLocation: {
5866
5921
  "file": "packages/agent-team/src/index.ts",
5867
- "line": 1236,
5922
+ "line": 1211,
5868
5923
  "column": 3
5869
5924
  }
5870
5925
  },
@@ -5891,7 +5946,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5891
5946
  },
5892
5947
  sourceLocation: {
5893
5948
  "file": "packages/agent-team/src/index.ts",
5894
- "line": 1137,
5949
+ "line": 1112,
5895
5950
  "column": 9
5896
5951
  }
5897
5952
  },
@@ -5919,7 +5974,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5919
5974
  },
5920
5975
  sourceLocation: {
5921
5976
  "file": "packages/agent-team/src/index.ts",
5922
- "line": 630,
5977
+ "line": 611,
5923
5978
  "column": 3
5924
5979
  }
5925
5980
  },
@@ -5946,7 +6001,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5946
6001
  },
5947
6002
  sourceLocation: {
5948
6003
  "file": "packages/agent-team/src/index.ts",
5949
- "line": 1127,
6004
+ "line": 1102,
5950
6005
  "column": 9
5951
6006
  }
5952
6007
  },
@@ -5973,7 +6028,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5973
6028
  },
5974
6029
  sourceLocation: {
5975
6030
  "file": "packages/agent-team/src/index.ts",
5976
- "line": 1200,
6031
+ "line": 1175,
5977
6032
  "column": 9
5978
6033
  }
5979
6034
  },
@@ -6000,7 +6055,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6000
6055
  },
6001
6056
  sourceLocation: {
6002
6057
  "file": "packages/agent-team/src/index.ts",
6003
- "line": 1243,
6058
+ "line": 1218,
6004
6059
  "column": 9
6005
6060
  }
6006
6061
  },
@@ -6027,7 +6082,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6027
6082
  },
6028
6083
  sourceLocation: {
6029
6084
  "file": "packages/agent-team/src/index.ts",
6030
- "line": 778,
6085
+ "line": 759,
6031
6086
  "column": 9
6032
6087
  }
6033
6088
  },
@@ -6054,7 +6109,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6054
6109
  },
6055
6110
  sourceLocation: {
6056
6111
  "file": "packages/agent-team/src/index.ts",
6057
- "line": 1148,
6112
+ "line": 1123,
6058
6113
  "column": 9
6059
6114
  }
6060
6115
  },
@@ -6081,7 +6136,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6081
6136
  },
6082
6137
  sourceLocation: {
6083
6138
  "file": "packages/agent-team/src/index.ts",
6084
- "line": 1221,
6139
+ "line": 1196,
6085
6140
  "column": 9
6086
6141
  }
6087
6142
  },
@@ -6108,7 +6163,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6108
6163
  },
6109
6164
  sourceLocation: {
6110
6165
  "file": "packages/agent-team/src/index.ts",
6111
- "line": 617,
6166
+ "line": 598,
6112
6167
  "column": 3
6113
6168
  }
6114
6169
  },
@@ -6135,7 +6190,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6135
6190
  },
6136
6191
  sourceLocation: {
6137
6192
  "file": "packages/agent-team/src/index.ts",
6138
- "line": 1157,
6193
+ "line": 1132,
6139
6194
  "column": 9
6140
6195
  }
6141
6196
  },
@@ -6162,7 +6217,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6162
6217
  },
6163
6218
  sourceLocation: {
6164
6219
  "file": "packages/agent-team/src/index.ts",
6165
- "line": 1261,
6220
+ "line": 1236,
6166
6221
  "column": 3
6167
6222
  }
6168
6223
  },
@@ -6189,7 +6244,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6189
6244
  },
6190
6245
  sourceLocation: {
6191
6246
  "file": "packages/agent-team/src/index.ts",
6192
- "line": 1254,
6247
+ "line": 1229,
6193
6248
  "column": 3
6194
6249
  }
6195
6250
  },
@@ -6216,7 +6271,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6216
6271
  },
6217
6272
  sourceLocation: {
6218
6273
  "file": "packages/agent-team/src/index.ts",
6219
- "line": 693,
6274
+ "line": 674,
6220
6275
  "column": 9
6221
6276
  }
6222
6277
  },
@@ -6243,7 +6298,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6243
6298
  },
6244
6299
  sourceLocation: {
6245
6300
  "file": "packages/agent-team/src/index.ts",
6246
- "line": 1045,
6301
+ "line": 1020,
6247
6302
  "column": 9
6248
6303
  }
6249
6304
  },
@@ -6270,7 +6325,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6270
6325
  },
6271
6326
  sourceLocation: {
6272
6327
  "file": "packages/agent-team/src/index.ts",
6273
- "line": 1268,
6328
+ "line": 1243,
6274
6329
  "column": 3
6275
6330
  }
6276
6331
  }
@@ -6453,6 +6508,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6453
6508
  };
6454
6509
  //#endregion
6455
6510
  //#region src/client/team-changes.ts
6511
+ /** First retry delay after a failed call, doubling up to the cap. */
6512
+ const RETRY_BASE_MS = 1e3;
6513
+ const RETRY_MAX_MS = 3e4;
6514
+ /** Abortable delay: the poll's subscription ending must not wait out a backoff. */
6515
+ function sleep(ms, signal) {
6516
+ return new Promise((resolve) => {
6517
+ const done = () => {
6518
+ clearTimeout(timer);
6519
+ signal.removeEventListener("abort", done);
6520
+ resolve();
6521
+ };
6522
+ const timer = setTimeout(done, ms);
6523
+ signal.addEventListener("abort", done, { once: true });
6524
+ });
6525
+ }
6456
6526
  function scopeKey(scope) {
6457
6527
  return scope === void 0 ? "all" : scope.kind === "workspace" ? `workspace:${scope.workspaceId}` : scope.kind === "channel" ? `channel:${scope.channelRef}` : scope.kind === "presence" ? `presence:${scope.workspaceId}` : `thread:${scope.threadRef}`;
6458
6528
  }
@@ -6461,6 +6531,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6461
6531
  * and pages never open parallel `changes` requests for the same scope, and
6462
6532
  * the poll is aborted as soon as the last subscriber leaves.
6463
6533
  *
6534
+ * A failed call reports the outage to every listener once and then keeps
6535
+ * retrying with backoff. The transport recovers on its own terms — a Host
6536
+ * restart, a sleep/wake, a dropped proxy — and a surface that stayed mounted
6537
+ * has to resume from that recovery rather than stay silent until it remounts,
6538
+ * so the first answered call after an outage wakes every listener once even
6539
+ * when the cursor did not move.
6540
+ *
6464
6541
  * Each poll keeps its own cursor, and a cursor only means something inside the
6465
6542
  * scope it was issued for: the Host answers a presence scope from a
6466
6543
  * process-local wake epoch and every other scope from a durable ledger
@@ -6507,22 +6584,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6507
6584
  ...scope === void 0 ? {} : { scope }
6508
6585
  });
6509
6586
  let version = poll.resumeFrom;
6510
- if (version === void 0) {
6511
- const probe = await this.changes(request(0), signal);
6512
- if (signal.aborted) return;
6513
- if (!probe.ok) {
6514
- this.fail(key, poll, probe.error.message);
6515
- return;
6516
- }
6517
- version = probe.value.version;
6518
- this.observed.set(key, version);
6519
- }
6587
+ let retryDelay = RETRY_BASE_MS;
6588
+ let reported = false;
6520
6589
  while (!signal.aborted) {
6521
- const result = await this.changes(request(version), signal);
6522
- if (signal.aborted) return;
6590
+ const result = await this.changes(request(version ?? 0), signal);
6591
+ if (signal.aborted || this.polls.get(key) !== poll) return;
6523
6592
  if (!result.ok) {
6524
- this.fail(key, poll, result.error.message);
6525
- return;
6593
+ if (!reported) {
6594
+ reported = true;
6595
+ for (const listener of poll.listeners) listener({
6596
+ type: "failed",
6597
+ message: result.error.message
6598
+ });
6599
+ }
6600
+ await sleep(retryDelay, signal);
6601
+ retryDelay = Math.min(retryDelay * 2, RETRY_MAX_MS);
6602
+ continue;
6603
+ }
6604
+ retryDelay = RETRY_BASE_MS;
6605
+ if (reported) {
6606
+ reported = false;
6607
+ version = result.value.version;
6608
+ this.observed.set(key, version);
6609
+ for (const listener of poll.listeners) listener({
6610
+ type: "changed",
6611
+ version
6612
+ });
6613
+ continue;
6614
+ }
6615
+ if (version === void 0) {
6616
+ version = result.value.version;
6617
+ this.observed.set(key, version);
6618
+ continue;
6526
6619
  }
6527
6620
  this.observed.set(key, result.value.version);
6528
6621
  if (result.value.version !== version) {
@@ -6534,13 +6627,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6534
6627
  }
6535
6628
  }
6536
6629
  }
6537
- fail(key, poll, message) {
6538
- if (this.polls.get(key) === poll) this.polls.delete(key);
6539
- for (const listener of poll.listeners) listener({
6540
- type: "failed",
6541
- message
6542
- });
6543
- }
6544
6630
  };
6545
6631
  /**
6546
6632
  * The Host's `changes` stream never wakes on a Thread read — a read advances
@@ -6695,13 +6781,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6695
6781
  };
6696
6782
  //#endregion
6697
6783
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/team.module.css.mjs
6698
- const css$10 = ".YvAbSa_footerStack{flex:none;width:100%;height:42px;margin:8px 0 0;display:flex}.YvAbSa_footerAction,.YvAbSa_settingsAction{box-sizing:border-box;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:8px;width:calc(100% + 4px);height:42px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.YvAbSa_footerAction{margin:0 -2px}.YvAbSa_settingsAction{margin:4px -2px}.YvAbSa_footerAction:hover,.YvAbSa_footerAction:focus-visible,.YvAbSa_settingsAction:hover,.YvAbSa_settingsAction:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}.YvAbSa_footerAction:focus-visible,.YvAbSa_settingsAction:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.YvAbSa_footerAction.YvAbSa_rail,.YvAbSa_settingsAction.YvAbSa_rail{corner-shape:round;border-radius:50%;justify-content:center;width:36px;height:36px;padding:0}.YvAbSa_footerAction.YvAbSa_rail{margin:0}.YvAbSa_settingsAction.YvAbSa_rail{margin:8px 0 10px}.YvAbSa_railStack{align-items:center;width:36px;height:36px;margin:0}";
6699
- const tagId$10 = "@wowyuarm/dsh-agent-team/team.module.css";
6700
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$10) + "]") === null) {
6784
+ const css$13 = ".YvAbSa_footerStack{flex:none;width:100%;height:42px;margin:8px 0 0;display:flex}.YvAbSa_footerAction,.YvAbSa_settingsAction{box-sizing:border-box;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:8px;width:calc(100% + 4px);height:42px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.YvAbSa_footerAction{margin:0 -2px}.YvAbSa_settingsAction{margin:4px -2px}.YvAbSa_footerAction:hover,.YvAbSa_footerAction:focus-visible,.YvAbSa_settingsAction:hover,.YvAbSa_settingsAction:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}.YvAbSa_footerAction:focus-visible,.YvAbSa_settingsAction:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.YvAbSa_footerAction.YvAbSa_rail,.YvAbSa_settingsAction.YvAbSa_rail{corner-shape:round;border-radius:50%;justify-content:center;width:36px;height:36px;padding:0}.YvAbSa_footerAction.YvAbSa_rail{margin:0}.YvAbSa_settingsAction.YvAbSa_rail{margin:8px 0 10px}.YvAbSa_railStack{align-items:center;width:36px;height:36px;margin:0}";
6785
+ const tagId$13 = "@wowyuarm/dsh-agent-team/team.module.css";
6786
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$13) + "]") === null) {
6701
6787
  const tag = document.createElement("style");
6702
6788
  tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
6703
- tag.dataset.pluginCss = tagId$10;
6704
- tag.textContent = css$10;
6789
+ tag.dataset.pluginCss = tagId$13;
6790
+ tag.textContent = css$13;
6705
6791
  document.head.appendChild(tag);
6706
6792
  }
6707
6793
  var team_module_css_default = {
@@ -6744,125 +6830,574 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6744
6830
  }) });
6745
6831
  }
6746
6832
  //#endregion
6747
- //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/state-dot.module.css.mjs
6748
- const css$9 = ".DalNWW_quiet{corner-shape:round;border-radius:50%;flex:none;display:inline-block;position:relative}.DalNWW_quiet[data-variant=todo]{border:1px solid var(--dsw-alias-label-tertiary)}.DalNWW_quiet[data-variant=quiet]{color:var(--dsw-alias-label-tertiary)}.DalNWW_quiet[data-variant=quiet]:before{corner-shape:round;content:\"\";opacity:.1;background:currentColor;border-radius:50%;position:absolute;inset:0}.DalNWW_quiet[data-variant=quiet]:after{corner-shape:round;content:\"\";background:currentColor;border-radius:50%;position:absolute;inset:20%}";
6749
- const tagId$9 = "@wowyuarm/dsh-agent-team/state-dot.module.css";
6750
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$9) + "]") === null) {
6751
- const tag = document.createElement("style");
6752
- tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
6753
- tag.dataset.pluginCss = tagId$9;
6754
- tag.textContent = css$9;
6755
- document.head.appendChild(tag);
6833
+ //#region src/client/team-formatters.ts
6834
+ function formatTaskStatus(status, t) {
6835
+ return t({
6836
+ todo: "taskStatusTodo",
6837
+ in_progress: "taskStatusInProgress",
6838
+ in_review: "taskStatusInReview",
6839
+ done: "taskStatusDone",
6840
+ closed: "taskStatusClosed"
6841
+ }[status]);
6842
+ }
6843
+ function formatClaimState(state, t) {
6844
+ return t({
6845
+ active: "claimStateActive",
6846
+ done: "claimStateDone",
6847
+ released: "claimStateReleased"
6848
+ }[state]);
6756
6849
  }
6757
- var state_dot_module_css_default = { "quiet": "DalNWW_quiet" };
6758
- //#endregion
6759
- //#region src/client/TeamStateDot.tsx
6760
6850
  /**
6761
- * Render the one shared Team status indicator. Native StateDot states pass
6762
- * through; the quiet statuses mirror StateDot geometry locally so every
6763
- * surface renders the same shape — todo a hollow ring (not started), quiet a
6764
- * solid tertiary dot with the same 10% halo (closed, unavailable).
6851
+ * Status indicator for a Task status, the dot every Task surface renders.
6852
+ * Active states map to StateDot variants; every status renders a dot so they
6853
+ * share one shape language — todo is a hollow ring (not started), closed a
6854
+ * quiet gray dot (archived).
6765
6855
  */
6766
- function TeamStateDot({ state, size = 10 }) {
6767
- if (state === "todo" || state === "quiet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6768
- className: state_dot_module_css_default.quiet,
6769
- "data-variant": state,
6770
- style: {
6771
- width: size,
6772
- height: size
6773
- },
6774
- "aria-hidden": "true"
6775
- });
6776
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
6777
- state,
6778
- size
6779
- });
6780
- }
6781
- //#endregion
6782
- //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/presence.module.css.mjs
6783
- const css$8 = ".-\\36 lQ-q_target{flex:0 0 14px;justify-content:center;align-items:center;display:inline-flex}";
6784
- const tagId$8 = "@wowyuarm/dsh-agent-team/presence.module.css";
6785
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$8) + "]") === null) {
6786
- const tag = document.createElement("style");
6787
- tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
6788
- tag.dataset.pluginCss = tagId$8;
6789
- tag.textContent = css$8;
6790
- document.head.appendChild(tag);
6856
+ function taskStatusDot(status) {
6857
+ return {
6858
+ todo: "todo",
6859
+ in_progress: "ongoing",
6860
+ in_review: "warning",
6861
+ done: "done",
6862
+ closed: "quiet"
6863
+ }[status];
6791
6864
  }
6792
- var presence_module_css_default = { "target": "-6lQ-q_target" };
6793
- //#endregion
6794
- //#region src/client/TeamPresenceDot.tsx
6795
- function presenceLabel(status, t) {
6796
- const label = status.presence === "available" ? t("statusAvailable") : status.presence === "working" ? t("statusWorking") : status.presence === "error" ? t("statusError") : t("statusUnavailable");
6797
- return status.diagnostic === void 0 ? label : `${label}: ${diagnosticText(status)}`;
6865
+ /** One-line title snippet derived from the Task's root Message body. */
6866
+ function formatTaskTitle(body) {
6867
+ const firstLine = body.split("\n", 1)[0]?.trim() ?? "";
6868
+ return firstLine.length > 120 ? `${firstLine.slice(0, 119)}…` : firstLine;
6798
6869
  }
6799
- /** One line of human-readable diagnostic text: the reason, plus the refused artifact path when one was reported. */
6800
- function diagnosticText(status) {
6801
- const diagnostic = status.diagnostic;
6802
- if (diagnostic === void 0) return "";
6803
- return diagnostic.location === void 0 ? diagnostic.detail : `${diagnostic.detail} (${diagnostic.location.path})`;
6870
+ /** Deterministic avatar hue for one Member identity; stable across sessions and themes. */
6871
+ function memberHue(memberId) {
6872
+ let hash = 0;
6873
+ for (let index = 0; index < memberId.length; index += 1) hash = (hash * 31 + memberId.charCodeAt(index)) % 360;
6874
+ return hash;
6804
6875
  }
6876
+ const BRANDED_REF_PATTERN = /\b(task|channel|thread):{1,2}[0-9a-f]{6,}(?:-[0-9a-f]{1,})*\b/gi;
6805
6877
  /**
6806
- * Whether the restart action can help an unavailable Member: it heals
6807
- * transient and repairable failures, but not a transient rollover window
6808
- * (which resolves on its own) or a refusal already proven non-remediable.
6878
+ * Canonical form of one matched ref: models occasionally double the colon or
6879
+ * uppercase the UUID when citing a ref in prose, while Host lookups and
6880
+ * navigation only accept the lowercase single-colon ref the ledger mints.
6809
6881
  */
6810
- function restartOffered(status) {
6811
- const diagnostic = status.diagnostic;
6812
- if (diagnostic === void 0) return true;
6813
- if (diagnostic.class === "rollover") return false;
6814
- return !(diagnostic.class === "session-refused" && diagnostic.remediable === false);
6882
+ function canonicalBrandedRef(match) {
6883
+ return match.replace("::", ":").toLowerCase();
6815
6884
  }
6816
- /** Shared presence → indicator mapping for dots and avatar badges. */
6817
- function presenceDotState(presence) {
6818
- return presence === "available" ? "done" : presence === "working" ? "ongoing" : presence === "error" ? "error" : "quiet";
6885
+ /**
6886
+ * Split a literal text run into plain and branded-ref segments. The pattern
6887
+ * anchors on the fixed ref prefixes plus a UUID shape (full or abbreviated),
6888
+ * so ordinary prose containing a colon never linkifies; a doubled colon from
6889
+ * model output is tolerated. Segment refs are always canonical, so resolution
6890
+ * and navigation work regardless of how the ref was spelled; text without any
6891
+ * ref comes back as one untouched segment.
6892
+ */
6893
+ function splitBrandedRefs(text) {
6894
+ const segments = [];
6895
+ let cursor = 0;
6896
+ for (const match of text.matchAll(BRANDED_REF_PATTERN)) {
6897
+ const start = match.index ?? 0;
6898
+ if (start > cursor) segments.push({ text: text.slice(cursor, start) });
6899
+ segments.push({
6900
+ text: match[0],
6901
+ ref: canonicalBrandedRef(match[0])
6902
+ });
6903
+ cursor = start + match[0].length;
6904
+ }
6905
+ if (cursor < text.length) segments.push({ text: text.slice(cursor) });
6906
+ return segments;
6819
6907
  }
6820
- function TeamPresenceDot({ status, t }) {
6821
- const label = presenceLabel(status, t);
6822
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
6823
- label,
6824
- delayMs: 300,
6825
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6826
- className: presence_module_css_default.target,
6827
- role: "img",
6828
- "aria-label": label,
6829
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamStateDot, { state: presenceDotState(status.presence) })
6830
- })
6831
- });
6908
+ /**
6909
+ * Whether one string's whole content is exactly one branded ref. A code span
6910
+ * like this is the model styling a ref as an identifier, not publishing code,
6911
+ * so the Markdown pass may linkify it; anything larger stays literal.
6912
+ */
6913
+ function isSingleBrandedRef(text) {
6914
+ const trimmed = text.trim();
6915
+ if (trimmed === "") return false;
6916
+ const matches = [...trimmed.matchAll(BRANDED_REF_PATTERN)];
6917
+ return matches.length === 1 && matches[0][0] === trimmed;
6832
6918
  }
6833
- //#endregion
6834
- //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/members.module.css.mjs
6835
- const css$7 = ".UkovOW_body{max-height:min(65vh,560px);overflow-y:auto}.UkovOW_content{outline:none;gap:12px;display:grid}.UkovOW_group{gap:3px;display:grid}.UkovOW_group+.UkovOW_group{border-top:1px solid var(--dsw-alias-border-l2);padding-top:10px}.UkovOW_group h3{color:var(--dsw-alias-label-secondary);margin:0 0 3px;font-size:12px;font-weight:600;line-height:18px}.UkovOW_member{border-radius:6px;grid-template-columns:14px minmax(0,1fr);align-items:center;gap:0 8px;min-height:36px;padding:4px 6px;display:grid}.UkovOW_member:hover{background:var(--dsw-alias-interactive-bg-hover)}.UkovOW_copy{min-width:0;display:grid}.UkovOW_copy strong{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;line-height:18px;overflow:hidden}.UkovOW_copy small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:14px;overflow:hidden}.UkovOW_state,.UkovOW_error{margin:0;padding:6px 0;font-size:12px;line-height:18px}.UkovOW_state{color:var(--dsw-alias-label-tertiary)}.UkovOW_error{color:var(--dsw-alias-state-error-primary)}@media (width<=600px){.UkovOW_body{max-height:calc(100vh - 160px)}}";
6836
- const tagId$7 = "@wowyuarm/dsh-agent-team/members.module.css";
6837
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$7) + "]") === null) {
6838
- const tag = document.createElement("style");
6839
- tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
6840
- tag.dataset.pluginCss = tagId$7;
6841
- tag.textContent = css$7;
6842
- document.head.appendChild(tag);
6919
+ function escapeRegExp(value) {
6920
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6843
6921
  }
6844
- var members_module_css_default = {
6845
- "body": "UkovOW_body",
6846
- "content": "UkovOW_content",
6847
- "copy": "UkovOW_copy",
6848
- "error": "UkovOW_error",
6849
- "group": "UkovOW_group",
6850
- "member": "UkovOW_member",
6851
- "state": "UkovOW_state"
6852
- };
6853
- //#endregion
6854
- //#region src/client/TeamMembersAction.tsx
6855
- function TeamMembersAction({ wide, loadMemberGroups, t }) {
6856
- const [panelOpen, setPanelOpen] = (0, react.useState)(false);
6857
- const [groups, setGroups] = (0, react.useState)([]);
6858
- const [loading, setLoading] = (0, react.useState)(false);
6859
- const [error, setError] = (0, react.useState)();
6860
- const triggerRef = (0, react.useRef)(null);
6861
- const contentRef = (0, react.useRef)(null);
6862
- (0, react.useEffect)(() => {
6863
- if (!panelOpen) return;
6864
- queueMicrotask(() => {
6865
- contentRef.current?.focus();
6922
+ /**
6923
+ * Locate one Message's structured mention names inside its literal body. A
6924
+ * name matches case-insensitively with an optional leading '@' on Unicode word
6925
+ * boundaries, and longer names win at the same position. Mention segments
6926
+ * render the canonical `@Handle`; names absent from the body come back
6927
+ * unmatched so the consumer can append them as a fallback chip row.
6928
+ */
6929
+ function splitMentionNames(text, names) {
6930
+ if (names.length === 0) return {
6931
+ segments: [{
6932
+ text,
6933
+ mention: false
6934
+ }],
6935
+ unmatched: []
6936
+ };
6937
+ const ordered = [...names].sort((left, right) => right.length - left.length);
6938
+ const pattern = new RegExp(`(?<![\\p{L}\\p{N}_@])@?(?:${ordered.map((name) => `(${escapeRegExp(name)})`).join("|")})(?=$|[^\\p{L}\\p{N}_])`, "giu");
6939
+ const segments = [];
6940
+ const matched = /* @__PURE__ */ new Set();
6941
+ let cursor = 0;
6942
+ for (const match of text.matchAll(pattern)) {
6943
+ const groupIndex = match.findIndex((group, index) => index >= 1 && group !== void 0);
6944
+ if (groupIndex < 1) continue;
6945
+ if (match.index > cursor) segments.push({
6946
+ text: text.slice(cursor, match.index),
6947
+ mention: false
6948
+ });
6949
+ const name = ordered[groupIndex - 1];
6950
+ segments.push({
6951
+ text: `@${name}`,
6952
+ mention: true,
6953
+ name
6954
+ });
6955
+ matched.add(name.toLowerCase());
6956
+ cursor = match.index + match[0].length;
6957
+ }
6958
+ if (cursor < text.length) segments.push({
6959
+ text: text.slice(cursor),
6960
+ mention: false
6961
+ });
6962
+ return {
6963
+ segments,
6964
+ unmatched: names.filter((name) => !matched.has(name.toLowerCase()))
6965
+ };
6966
+ }
6967
+ /**
6968
+ * Whether one draft spells a handle as an authored `@mention`: a literal `@`
6969
+ * before the handle, case-insensitively, on Unicode word boundaries. The Host
6970
+ * resolves delivery from the same text with its own scanner, so this is the
6971
+ * Client's single answer to "did the author call this name" — the composer
6972
+ * prunes picked recipients with it and previews the draft's notifications with
6973
+ * it.
6974
+ */
6975
+ function containsMention(body, handle) {
6976
+ return new RegExp(`(?:^|[^\\p{L}\\p{N}_])@${escapeRegExp(handle)}(?=$|[^\\p{L}\\p{N}_])`, "iu").test(body);
6977
+ }
6978
+ /** Whether one draft carries the `@all` marker the mention menu expands. */
6979
+ function containsAllMention(body) {
6980
+ return /(?<![\p{L}\p{N}_@])@all(?=$|[^\p{L}\p{N}_])/u.test(body);
6981
+ }
6982
+ /**
6983
+ * Every Member the mention menu's `@all` row stands for: the roster this
6984
+ * composer was handed minus Members who cannot take a Message right now — the
6985
+ * same filter the per-handle rows apply, so the expansion and the menu agree.
6986
+ */
6987
+ function allMentionMembers(members) {
6988
+ return members.filter((status) => status.presence !== "unavailable" && status.member.state !== "inactive" && status.member.state !== "archived");
6989
+ }
6990
+ /**
6991
+ * Member ids one draft asks to notify by text alone: the Client's preview of
6992
+ * the Host's own body mention resolution, so a hand-typed `@Handle` reports
6993
+ * exactly like a pick from the mention menu. `@all` stands for the menu's
6994
+ * expansion; a written handle counts whenever its Member can still take a
6995
+ * Message — state decides, not presence, because an offline Member is notified
6996
+ * and reads it later.
6997
+ *
6998
+ * The result is preview-only. Only picked recipients travel as explicit
6999
+ * recipients, where a name the Channel cannot reach would be a rejected target
7000
+ * rather than the prose the Host reads.
7001
+ */
7002
+ function mentionedMemberIds(body, members) {
7003
+ if (containsAllMention(body)) return allMentionMembers(members).map((status) => status.member.memberId);
7004
+ return members.filter((status) => status.member.state !== "inactive" && status.member.state !== "archived").filter((status) => containsMention(body, status.member.handle)).map((status) => status.member.memberId);
7005
+ }
7006
+ /** Canonical chip handles for one Message's structured mention refs. */
7007
+ function mentionNamesOf(mentions, handles) {
7008
+ return mentions.map((memberId) => memberId === "member:human" ? "human" : handles.get(memberId)).filter((name) => name !== void 0);
7009
+ }
7010
+ const MARKDOWN_BLOCK_CONSTRUCT = /(^|\n)[ \t]{0,3}(?:#{1,6}[ \t]|>[ \t]|[-*+][ \t]|\d+[.)][ \t])|^[ \t]*\|.+\|/m;
7011
+ const MARKDOWN_INLINE_CONSTRUCT = /[`*_[\]!]|~~~|```/;
7012
+ /**
7013
+ * Whether an Agent body survives literal rendering unchanged: no fences,
7014
+ * inline code, emphasis markers, links, images, tables, or block constructs.
7015
+ * Only such plain-prose bodies may reuse the Human inline mention flow —
7016
+ * anything richer keeps the trailing chip row because the Markdown primitive
7017
+ * renders block-level documents that cannot interleave inline chips.
7018
+ */
7019
+ function isPlainTextBody(text) {
7020
+ return !(MARKDOWN_BLOCK_CONSTRUCT.test(text) || MARKDOWN_INLINE_CONSTRUCT.test(text));
7021
+ }
7022
+ const pad$1 = (value) => String(value).padStart(2, "0");
7023
+ /** Absolute local `YYYY-MM-DD HH:mm` label: the precise instant behind every shorter form. */
7024
+ function formatAbsoluteTime(occurredAt) {
7025
+ const at = new Date(occurredAt);
7026
+ if (Number.isNaN(at.getTime())) return "";
7027
+ return `${at.getFullYear()}-${pad$1(at.getMonth() + 1)}-${pad$1(at.getDate())} ${pad$1(at.getHours())}:${pad$1(at.getMinutes())}`;
7028
+ }
7029
+ /**
7030
+ * Wall-clock label for one Message instant: time within the current day,
7031
+ * month-day time within the year, full date otherwise.
7032
+ */
7033
+ function formatMessageTime(occurredAt, now = /* @__PURE__ */ new Date()) {
7034
+ const at = new Date(occurredAt);
7035
+ if (Number.isNaN(at.getTime())) return "";
7036
+ if (at.getFullYear() === now.getFullYear() && at.getMonth() === now.getMonth() && at.getDate() === now.getDate()) return `${pad$1(at.getHours())}:${pad$1(at.getMinutes())}`;
7037
+ const absolute = formatAbsoluteTime(occurredAt);
7038
+ return at.getFullYear() === now.getFullYear() ? absolute.slice(5) : absolute;
7039
+ }
7040
+ /**
7041
+ * Calendar days between two instants in the viewer's own zone, so "yesterday"
7042
+ * means yesterday locally rather than 24 hours earlier.
7043
+ */
7044
+ function calendarDayDelta(at, now) {
7045
+ const midnight = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
7046
+ return Math.round((midnight(now) - midnight(at)) / 864e5);
7047
+ }
7048
+ /**
7049
+ * Recency label for one Inbox row's newest fact, shared with the Channel feed's
7050
+ * entry line so the two agree about the same instant. Today is a bare clock time
7051
+ * — the reader is in today, and 「今天」 printed down every row spends the label's
7052
+ * first word on the one segment that never varies, while `HH:mm` alone still
7053
+ * reads as a clock because it is exactly one. The first day that is not today is
7054
+ * the fact the reader has to be told, so it keeps its word; everything older
7055
+ * keeps the Message date form, so the row and the Thread it opens agree.
7056
+ */
7057
+ function formatInboxTime(occurredAt, t, now = /* @__PURE__ */ new Date()) {
7058
+ const at = new Date(occurredAt);
7059
+ if (Number.isNaN(at.getTime())) return "";
7060
+ const days = calendarDayDelta(at, now);
7061
+ if (days === 0) return `${pad$1(at.getHours())}:${pad$1(at.getMinutes())}`;
7062
+ if (days === 1) return `${t("inboxTimeYesterday")} ${pad$1(at.getHours())}:${pad$1(at.getMinutes())}`;
7063
+ return formatMessageTime(occurredAt, now);
7064
+ }
7065
+ function formatActivity(activity, options) {
7066
+ const actor = options.actorName(activity.actor);
7067
+ if (activity.kind === "accept") return activity.completedClaimRefs !== void 0 && activity.completedClaimRefs.length > 0 ? options.t("activityAcceptedWithClaims", {
7068
+ actor,
7069
+ count: activity.completedClaimRefs.length
7070
+ }) : options.t("activityAccepted", { actor });
7071
+ if (activity.kind === "promote") return options.t("activityPromoted", { actor });
7072
+ if (activity.kind === "close") return options.t("activityClosed", { actor });
7073
+ if (activity.kind === "reopen") return options.t("activityReopened", { actor });
7074
+ const direction = "claimRef" in activity ? options.claims.find((claim) => claim.claimRef === activity.claimRef)?.direction ?? options.t("claims") : options.t("claims");
7075
+ if (activity.kind === "claim") return options.t("activityClaimed", {
7076
+ actor,
7077
+ direction
7078
+ });
7079
+ if (activity.kind === "done") return options.t("activityClaimDone", {
7080
+ actor,
7081
+ direction
7082
+ });
7083
+ if (activity.kind === "release") return options.t("activityClaimReleased", {
7084
+ actor,
7085
+ direction
7086
+ });
7087
+ if (activity.kind === "claims_released") return options.t("activityClaimsReleased", {
7088
+ actor,
7089
+ count: activity.claimRefs.length
7090
+ });
7091
+ throw new Error(`unknown Team Activity kind: ${activity.kind}`);
7092
+ }
7093
+ /** Remove the machine-facing `[attachment] <path>` prompt lines from a body before display. */
7094
+ function stripAttachmentLines(body) {
7095
+ return body.replaceAll(/^\[attachment\] .*$(\n)?/gm, "").replace(/\n+$/, "");
7096
+ }
7097
+ /** Whether one displayed Message body starts clamped behind the expand control. */
7098
+ function shouldClampMessage(displayBody) {
7099
+ return displayBody.length > 600;
7100
+ }
7101
+ /**
7102
+ * Decide how one Message body renders. Human input and plain-prose Agent
7103
+ * bodies stay literal, with structured mention chips inline where possible;
7104
+ * rich Agent Markdown keeps unmatched mentions and non-Task refs in the
7105
+ * trailing fallback row while the post-render pass handles Task refs at their
7106
+ * authored position. Surfaces without ref navigation render everything
7107
+ * literally and keep the full fallback row.
7108
+ */
7109
+ function planMessageBody(body, options) {
7110
+ const stripped = stripAttachmentLines(body);
7111
+ const displayBody = stripped === "" ? body : stripped;
7112
+ const richAgentBody = !options.human && !isPlainTextBody(displayBody);
7113
+ const inline = (options.human || isPlainTextBody(displayBody)) && options.mentionNames !== void 0 && options.mentionNames.length > 0 ? splitMentionNames(displayBody, options.mentionNames) : void 0;
7114
+ const fallbackNames = inline !== void 0 ? inline.unmatched : richAgentBody && options.canOpenRefs && options.mentionNames !== void 0 ? splitMentionNames(displayBody, options.mentionNames).unmatched : options.mentionNames ?? [];
7115
+ const refs = splitBrandedRefs(displayBody).flatMap((segment) => segment.ref === void 0 ? [] : [segment.ref]);
7116
+ return {
7117
+ displayBody,
7118
+ richAgentBody,
7119
+ render: inline !== void 0 ? "inline" : options.human || options.canOpenRefs && !richAgentBody && refs.length > 0 ? "literal" : "markdown",
7120
+ ...inline === void 0 ? {} : { inline },
7121
+ fallbackNames,
7122
+ fallbackRefs: richAgentBody && !options.canOpenRefs ? refs : [],
7123
+ taskRefs: options.canOpenRefs && !richAgentBody ? refs.filter((ref) => ref.startsWith("task:")).map((ref) => ref) : []
7124
+ };
7125
+ }
7126
+ //#endregion
7127
+ //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/state-dot.module.css.mjs
7128
+ const css$12 = ".DalNWW_quiet{corner-shape:round;border-radius:50%;flex:none;display:inline-block;position:relative}.DalNWW_quiet[data-variant=todo]{border:1px solid var(--dsw-alias-label-tertiary)}.DalNWW_quiet[data-variant=quiet]{color:var(--dsw-alias-label-tertiary)}.DalNWW_quiet[data-variant=quiet]:before{corner-shape:round;content:\"\";opacity:.1;background:currentColor;border-radius:50%;position:absolute;inset:0}.DalNWW_quiet[data-variant=quiet]:after{corner-shape:round;content:\"\";background:currentColor;border-radius:50%;position:absolute;inset:20%}";
7129
+ const tagId$12 = "@wowyuarm/dsh-agent-team/state-dot.module.css";
7130
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$12) + "]") === null) {
7131
+ const tag = document.createElement("style");
7132
+ tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
7133
+ tag.dataset.pluginCss = tagId$12;
7134
+ tag.textContent = css$12;
7135
+ document.head.appendChild(tag);
7136
+ }
7137
+ var state_dot_module_css_default = { "quiet": "DalNWW_quiet" };
7138
+ //#endregion
7139
+ //#region src/client/TeamStateDot.tsx
7140
+ /**
7141
+ * Render the one shared Team status indicator. Native StateDot states pass
7142
+ * through; the quiet statuses mirror StateDot geometry locally so every
7143
+ * surface renders the same shape — todo a hollow ring (not started), quiet a
7144
+ * solid tertiary dot with the same 10% halo (closed, unavailable).
7145
+ */
7146
+ function TeamStateDot({ state, size = 10 }) {
7147
+ if (state === "todo" || state === "quiet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7148
+ className: state_dot_module_css_default.quiet,
7149
+ "data-variant": state,
7150
+ style: {
7151
+ width: size,
7152
+ height: size
7153
+ },
7154
+ "aria-hidden": "true"
7155
+ });
7156
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
7157
+ state,
7158
+ size
7159
+ });
7160
+ }
7161
+ //#endregion
7162
+ //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/presence.module.css.mjs
7163
+ const css$11 = ".-\\36 lQ-q_target{flex:0 0 14px;justify-content:center;align-items:center;display:inline-flex}";
7164
+ const tagId$11 = "@wowyuarm/dsh-agent-team/presence.module.css";
7165
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$11) + "]") === null) {
7166
+ const tag = document.createElement("style");
7167
+ tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
7168
+ tag.dataset.pluginCss = tagId$11;
7169
+ tag.textContent = css$11;
7170
+ document.head.appendChild(tag);
7171
+ }
7172
+ var presence_module_css_default = { "target": "-6lQ-q_target" };
7173
+ //#endregion
7174
+ //#region src/client/TeamPresenceDot.tsx
7175
+ function presenceLabel(status, t) {
7176
+ const label = status.presence === "available" ? t("statusAvailable") : status.presence === "working" ? t("statusWorking") : status.presence === "error" ? t("statusError") : t("statusUnavailable");
7177
+ return status.diagnostic === void 0 ? label : `${label}: ${diagnosticText(status)}`;
7178
+ }
7179
+ /** One line of human-readable diagnostic text: the reason, plus the refused artifact path when one was reported. */
7180
+ function diagnosticText(status) {
7181
+ const diagnostic = status.diagnostic;
7182
+ if (diagnostic === void 0) return "";
7183
+ return diagnostic.location === void 0 ? diagnostic.detail : `${diagnostic.detail} (${diagnostic.location.path})`;
7184
+ }
7185
+ /**
7186
+ * Whether the restart action can help an unavailable Member: it heals
7187
+ * transient and repairable failures, but not a transient rollover window
7188
+ * (which resolves on its own) or a refusal already proven non-remediable.
7189
+ */
7190
+ function restartOffered(status) {
7191
+ const diagnostic = status.diagnostic;
7192
+ if (diagnostic === void 0) return true;
7193
+ if (diagnostic.class === "rollover") return false;
7194
+ return !(diagnostic.class === "session-refused" && diagnostic.remediable === false);
7195
+ }
7196
+ /** Shared presence → indicator mapping for dots and avatar badges. */
7197
+ function presenceDotState(presence) {
7198
+ return presence === "available" ? "done" : presence === "working" ? "ongoing" : presence === "error" ? "error" : "quiet";
7199
+ }
7200
+ function TeamPresenceDot({ status, t }) {
7201
+ const label = presenceLabel(status, t);
7202
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
7203
+ label,
7204
+ delayMs: 300,
7205
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7206
+ className: presence_module_css_default.target,
7207
+ role: "img",
7208
+ "aria-label": label,
7209
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamStateDot, { state: presenceDotState(status.presence) })
7210
+ })
7211
+ });
7212
+ }
7213
+ //#endregion
7214
+ //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/sidebar.module.css.mjs
7215
+ const css$10 = "html[data-agent-team-mode=team] button[class*=newSession]{display:none}.d0xfxa_workspaceBrowser{flex-direction:column;height:100%;min-height:0;padding:0 8px 8px;display:flex}.d0xfxa_railButton{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:0;display:inline-flex}.d0xfxa_railButton:hover,.d0xfxa_railButton:focus-visible{--team-mark-ring:var(--dsw-alias-interactive-bg-hover);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_railButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_workspaceList{flex-direction:column;gap:2px;padding-bottom:2px;display:flex}.d0xfxa_workspaceRow{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;align-items:center;gap:6px;width:100%;height:34px;padding:0 8px;display:flex}.d0xfxa_workspaceRow:hover,.d0xfxa_workspaceRow:focus-visible,.d0xfxa_workspaceRow[aria-current=page]{background:var(--dsw-alias-interactive-bg-hover)}.d0xfxa_workspaceRow:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_workspaceIcon{color:var(--dsw-alias-label-tertiary);flex:0 0 16px;justify-content:center;align-items:center;height:20px;display:inline-flex}.d0xfxa_workspaceRow[data-selected] .d0xfxa_workspaceIcon{color:var(--dsw-alias-state-business-primary)}.d0xfxa_workspaceCopy{min-width:0;display:flex}.d0xfxa_workspaceCopy strong{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:400;line-height:20px;overflow:hidden}.d0xfxa_emptyState{color:var(--dsw-alias-label-tertiary);margin:8px;font-size:12px;line-height:18px}.d0xfxa_inboxCard{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;flex:none;align-items:center;gap:6px;width:100%;height:34px;margin:4px 0 2px;padding:0 8px;display:flex}.d0xfxa_inboxCard:hover,.d0xfxa_inboxCard:focus-visible,.d0xfxa_inboxCard[aria-current=page]{--team-mark-ring:var(--dsw-alias-interactive-bg-hover);background:var(--dsw-alias-interactive-bg-hover)}.d0xfxa_inboxCard:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_inboxCard .d0xfxa_inboxMark{color:var(--dsw-alias-label-tertiary)}.d0xfxa_inboxCardLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:14px;line-height:20px;overflow:hidden}.d0xfxa_inboxMark{flex:0 0 16px;display:inline-flex;position:relative}.d0xfxa_inboxDot{background:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 2px var(--team-mark-ring,var(--dsw-alias-bg-base));corner-shape:round;border-radius:50%;width:8px;height:8px;position:absolute;top:-2px;left:-2px}.d0xfxa_railWorkspace{flex-direction:column;align-items:center;gap:8px;padding-top:8px;display:flex}.d0xfxa_railButton{corner-shape:round;border-radius:50%;width:36px;height:36px;position:relative}.d0xfxa_railButton[aria-current=page]{--team-mark-ring:var(--dsw-alias-interactive-bg-hover);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_workspaceSection{flex-direction:column;flex:1;gap:4px;min-height:0;margin-top:2px;display:flex;overflow-y:auto}.d0xfxa_section{flex-direction:column;display:flex}.d0xfxa_sectionHeader{align-items:center;min-height:26px;padding-right:2px;display:flex}.d0xfxa_sectionToggle{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;align-items:center;gap:4px;min-width:0;min-height:24px;padding:0 6px;font-size:12px;line-height:18px;display:inline-flex}.d0xfxa_sectionToggle:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_sectionToggle:hover .d0xfxa_sectionChevron,.d0xfxa_sectionToggle:focus-visible .d0xfxa_sectionChevron{color:var(--dsw-alias-label-primary)}.d0xfxa_sectionChevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .12s,color .12s}.d0xfxa_sectionToggle[aria-expanded=false] .d0xfxa_sectionChevron{transform:rotate(-90deg)}.d0xfxa_sectionTitle{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.d0xfxa_sectionActions{align-items:center;margin-left:auto;display:inline-flex}.d0xfxa_panel{flex-direction:column;display:flex}.d0xfxa_iconButton{corner-shape:round;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;display:inline-flex}.d0xfxa_iconButton:hover,.d0xfxa_iconButton:focus-visible{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_iconButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_textButton{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:5px;padding:2px 5px;font-size:11px;line-height:18px}.d0xfxa_textButton:hover,.d0xfxa_textButton:focus-visible{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_textButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_textButton:disabled{cursor:not-allowed;opacity:.4}.d0xfxa_channelList,.d0xfxa_agentList{flex-direction:column;gap:1px;padding:0 4px 4px;display:flex}.d0xfxa_sidebarRowDragging{opacity:.5}.d0xfxa_sidebarRowDropBefore,.d0xfxa_sidebarRowDropAfter{position:relative}.d0xfxa_sidebarRowDropBefore:before,.d0xfxa_sidebarRowDropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:4px}.d0xfxa_sidebarRowDropBefore:before{top:-7px}.d0xfxa_sidebarRowDropAfter:after{bottom:-7px}.d0xfxa_channelRow{color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;min-height:30px;display:flex;position:relative}.d0xfxa_channelSelect{box-sizing:border-box;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;flex:1;align-items:center;min-width:0;min-height:30px;padding:3px 4px 3px 8px;display:flex}.d0xfxa_channelSelect:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_channelName{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:400;line-height:18px;overflow:hidden}.d0xfxa_agentRow{color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;min-height:38px;display:flex;position:relative}.d0xfxa_agentSelect{box-sizing:border-box;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;flex:1;grid-template-columns:24px minmax(0,1fr);align-items:center;gap:0 8px;min-width:0;min-height:38px;padding:3px 4px 3px 8px;display:grid}.d0xfxa_agentSelect:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_agentSelect[aria-current=page]{background:var(--dsw-alias-interactive-bg-hover);border-radius:8px}.d0xfxa_agentRow:hover .d0xfxa_agentSelect[aria-current=page],.d0xfxa_agentRow:focus-within .d0xfxa_agentSelect[aria-current=page],.d0xfxa_agentRow[data-menu-open] .d0xfxa_agentSelect[aria-current=page]{background:0 0}.d0xfxa_agentAvatar{background:hsl(var(--team-avatar-hue,212) 42% 46%);corner-shape:round;color:#fff;cursor:default;border-radius:50%;flex:0 0 24px;justify-content:center;align-items:center;width:24px;height:24px;font-size:11px;font-weight:600;display:inline-flex;position:relative}.d0xfxa_agentAvatarBadge{background:var(--dsw-specific-sidebar-fill);corner-shape:round;box-shadow:0 0 0 1px var(--dsw-specific-sidebar-fill);border-radius:50%;justify-content:center;align-items:center;width:12px;height:12px;padding:1px;line-height:0;display:inline-flex;position:absolute;bottom:-3px;right:-3px}.d0xfxa_agentCopy{flex-direction:column;justify-content:flex-start;min-width:0;display:flex}.d0xfxa_agentCopy strong{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:17px;overflow:hidden}.d0xfxa_agentCopy small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:13px;overflow:hidden}.d0xfxa_unavailableDot{background:var(--dsw-alias-label-tertiary);corner-shape:round;border-radius:50%;width:7px;height:7px;display:inline-block}.d0xfxa_rowMenu{flex:none;align-items:center;padding-right:4px;display:none}.d0xfxa_channelRow:hover .d0xfxa_rowMenu,.d0xfxa_channelRow:focus-within .d0xfxa_rowMenu,.d0xfxa_channelRow[data-menu-open] .d0xfxa_rowMenu,.d0xfxa_agentRow:hover .d0xfxa_rowMenu,.d0xfxa_agentRow:focus-within .d0xfxa_rowMenu,.d0xfxa_agentRow[data-menu-open] .d0xfxa_rowMenu{display:inline-flex}.d0xfxa_channelRow[data-menu-open],.d0xfxa_agentRow[data-menu-open],.d0xfxa_channelRow:hover,.d0xfxa_agentRow:hover,.d0xfxa_channelRow:focus-within,.d0xfxa_agentRow:focus-within,.d0xfxa_channelRow[aria-current=page]{background:var(--dsw-alias-interactive-bg-hover)}.d0xfxa_rowMenuButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;justify-content:center;align-items:center;width:20px;height:20px;padding:0;display:inline-flex}.d0xfxa_rowMenuButton:hover,.d0xfxa_rowMenuButton:focus-visible{color:var(--dsw-alias-label-primary)}.d0xfxa_rowMenuButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_retryError{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:8px;padding:8px 12px;font-size:11px;display:flex}.d0xfxa_rowAlert{color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;padding:2px 8px 6px;font-size:11px}.d0xfxa_error{color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;margin:0;padding:4px 12px 6px;font-size:11px;line-height:16px}.d0xfxa_editDescription{color:var(--dsw-alias-label-secondary);margin:0 0 10px;font-size:12px;line-height:18px}.d0xfxa_editMemberList{gap:2px;display:grid}.d0xfxa_editChannelName{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:400;line-height:18px;overflow:hidden}.d0xfxa_editHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:16px}.d0xfxa_menuHint{color:var(--dsw-alias-label-tertiary);margin-left:4px;font-size:10px;line-height:14px}.d0xfxa_rowError{color:var(--dsw-alias-state-error-primary);grid-column:1/-1;margin:2px 0;font-size:11px;line-height:16px}";
7216
+ const tagId$10 = "@wowyuarm/dsh-agent-team/sidebar.module.css";
7217
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$10) + "]") === null) {
7218
+ const tag = document.createElement("style");
7219
+ tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
7220
+ tag.dataset.pluginCss = tagId$10;
7221
+ tag.textContent = css$10;
7222
+ document.head.appendChild(tag);
7223
+ }
7224
+ var sidebar_module_css_default = {
7225
+ "agentAvatar": "d0xfxa_agentAvatar",
7226
+ "agentAvatarBadge": "d0xfxa_agentAvatarBadge",
7227
+ "agentCopy": "d0xfxa_agentCopy",
7228
+ "agentList": "d0xfxa_agentList",
7229
+ "agentRow": "d0xfxa_agentRow",
7230
+ "agentSelect": "d0xfxa_agentSelect",
7231
+ "channelList": "d0xfxa_channelList",
7232
+ "channelName": "d0xfxa_channelName",
7233
+ "channelRow": "d0xfxa_channelRow",
7234
+ "channelSelect": "d0xfxa_channelSelect",
7235
+ "editChannelName": "d0xfxa_editChannelName",
7236
+ "editDescription": "d0xfxa_editDescription",
7237
+ "editHint": "d0xfxa_editHint",
7238
+ "editMemberList": "d0xfxa_editMemberList",
7239
+ "emptyState": "d0xfxa_emptyState",
7240
+ "error": "d0xfxa_error",
7241
+ "iconButton": "d0xfxa_iconButton",
7242
+ "inboxCard": "d0xfxa_inboxCard",
7243
+ "inboxCardLabel": "d0xfxa_inboxCardLabel",
7244
+ "inboxDot": "d0xfxa_inboxDot",
7245
+ "inboxMark": "d0xfxa_inboxMark",
7246
+ "menuHint": "d0xfxa_menuHint",
7247
+ "panel": "d0xfxa_panel",
7248
+ "railButton": "d0xfxa_railButton",
7249
+ "railWorkspace": "d0xfxa_railWorkspace",
7250
+ "retryError": "d0xfxa_retryError",
7251
+ "rowAlert": "d0xfxa_rowAlert",
7252
+ "rowError": "d0xfxa_rowError",
7253
+ "rowMenu": "d0xfxa_rowMenu",
7254
+ "rowMenuButton": "d0xfxa_rowMenuButton",
7255
+ "section": "d0xfxa_section",
7256
+ "sectionActions": "d0xfxa_sectionActions",
7257
+ "sectionChevron": "d0xfxa_sectionChevron",
7258
+ "sectionHeader": "d0xfxa_sectionHeader",
7259
+ "sectionTitle": "d0xfxa_sectionTitle",
7260
+ "sectionToggle": "d0xfxa_sectionToggle",
7261
+ "sidebarRowDragging": "d0xfxa_sidebarRowDragging",
7262
+ "sidebarRowDropAfter": "d0xfxa_sidebarRowDropAfter",
7263
+ "sidebarRowDropBefore": "d0xfxa_sidebarRowDropBefore",
7264
+ "textButton": "d0xfxa_textButton",
7265
+ "unavailableDot": "d0xfxa_unavailableDot",
7266
+ "workspaceBrowser": "d0xfxa_workspaceBrowser",
7267
+ "workspaceCopy": "d0xfxa_workspaceCopy",
7268
+ "workspaceIcon": "d0xfxa_workspaceIcon",
7269
+ "workspaceList": "d0xfxa_workspaceList",
7270
+ "workspaceRow": "d0xfxa_workspaceRow",
7271
+ "workspaceSection": "d0xfxa_workspaceSection"
7272
+ };
7273
+ //#endregion
7274
+ //#region src/client/TeamMemberAvatar.tsx
7275
+ /**
7276
+ * Sidebar Member avatar reusing the conversation identity language: the
7277
+ * deterministic member hue and handle initial, with the presence indicator
7278
+ * overlaid at the bottom-right so one glyph carries identity and state.
7279
+ */
7280
+ function TeamMemberAvatar({ status, t }) {
7281
+ const label = presenceLabel(status, t);
7282
+ const state = presenceDotState(status.presence);
7283
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
7284
+ label,
7285
+ delayMs: 300,
7286
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7287
+ className: sidebar_module_css_default.agentAvatar,
7288
+ style: { "--team-avatar-hue": memberHue(status.member.memberId) },
7289
+ role: "img",
7290
+ "aria-label": label,
7291
+ children: [status.member.handle.replace("@", "").slice(0, 1).toUpperCase(), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7292
+ className: sidebar_module_css_default.agentAvatarBadge,
7293
+ "aria-hidden": "true",
7294
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamStateDot, { state })
7295
+ })]
7296
+ })
7297
+ });
7298
+ }
7299
+ //#endregion
7300
+ //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/member-row.module.css.mjs
7301
+ const css$9 = ".xnbzeW_row{border-radius:8px;grid-template-columns:24px minmax(0,1fr);align-items:center;gap:0 10px;min-height:40px;padding:8px 10px;display:grid}.xnbzeW_row:has(button){grid-template-columns:24px minmax(0,1fr) auto}.xnbzeW_row:hover{background:var(--dsw-alias-interactive-bg-hover)}.xnbzeW_copy{min-width:0;display:grid}.xnbzeW_copy strong{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;line-height:18px;overflow:hidden}.xnbzeW_copy small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.xnbzeW_action{justify-self:end;min-width:64px}.xnbzeW_error{color:var(--dsw-alias-state-error-primary);grid-column:2/-1;margin:2px 0 0;font-size:11px;line-height:16px}@media (width<=600px){.xnbzeW_row,.xnbzeW_row:has(button){grid-template-columns:24px minmax(0,1fr);align-items:start}.xnbzeW_action{grid-column:2;justify-self:start;margin-top:6px}}";
7302
+ const tagId$9 = "@wowyuarm/dsh-agent-team/member-row.module.css";
7303
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$9) + "]") === null) {
7304
+ const tag = document.createElement("style");
7305
+ tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
7306
+ tag.dataset.pluginCss = tagId$9;
7307
+ tag.textContent = css$9;
7308
+ document.head.appendChild(tag);
7309
+ }
7310
+ var member_row_module_css_default = {
7311
+ "action": "xnbzeW_action",
7312
+ "copy": "xnbzeW_copy",
7313
+ "error": "xnbzeW_error",
7314
+ "row": "xnbzeW_row"
7315
+ };
7316
+ //#endregion
7317
+ //#region src/client/TeamMemberRow.tsx
7318
+ /**
7319
+ * The one place a Member's identity is drawn: the presence-bearing avatar plus
7320
+ * the handle over its description. Read-only rosters, the rosters with a
7321
+ * membership action, and the sidebar Agent list all render this, so identity,
7322
+ * tone and truncation cannot drift between surfaces that show the same person.
7323
+ *
7324
+ * A fragment, not a row: each surface owns its own row element, hit target and
7325
+ * grid, and places this identity in that grid's first two tracks. The handle
7326
+ * spelling is the surface's call — rosters address Members the way the
7327
+ * composer does (`@handle`), the sidebar names them as the directory does.
7328
+ */
7329
+ function TeamMemberIdentity({ status, name, className, t }) {
7330
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberAvatar, {
7331
+ status,
7332
+ t
7333
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7334
+ className: className === void 0 ? member_row_module_css_default.copy : `${member_row_module_css_default.copy} ${className}`,
7335
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: name ?? `@${status.member.handle.replace(/^@/, "")}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
7336
+ })] });
7337
+ }
7338
+ /**
7339
+ * The one roster row: identity, an optional membership action, and the row's
7340
+ * own failure line. The action is the row's only chrome, so the eye lands on
7341
+ * the handle first and on the action second. A read-only roster omits it and
7342
+ * the trailing track collapses, handing its width back to the description.
7343
+ */
7344
+ function TeamMemberRow({ status, action, error, className, t }) {
7345
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7346
+ className: className === void 0 ? member_row_module_css_default.row : `${member_row_module_css_default.row} ${className}`,
7347
+ "data-team-member-row": true,
7348
+ children: [
7349
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberIdentity, {
7350
+ status,
7351
+ t
7352
+ }),
7353
+ action !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7354
+ size: "sm",
7355
+ variant: "outline",
7356
+ className: member_row_module_css_default.action,
7357
+ disabled: action.disabled === true,
7358
+ onClick: action.onSelect,
7359
+ children: action.label
7360
+ }),
7361
+ error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7362
+ className: member_row_module_css_default.error,
7363
+ role: "alert",
7364
+ children: error
7365
+ })
7366
+ ]
7367
+ });
7368
+ }
7369
+ //#endregion
7370
+ //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/members.module.css.mjs
7371
+ const css$8 = ".UkovOW_body{max-height:min(65vh,560px);overflow-y:auto}.UkovOW_content{outline:none;gap:12px;display:grid}.UkovOW_group{gap:2px;display:grid}.UkovOW_group+.UkovOW_group{border-top:1px solid var(--dsw-alias-border-l2);padding-top:10px}.UkovOW_group h3{color:var(--dsw-alias-label-secondary);margin:0 0 3px;font-size:12px;font-weight:600;line-height:18px}.UkovOW_member{margin:0 -6px}.UkovOW_state,.UkovOW_error{margin:0;padding:6px 0;font-size:12px;line-height:18px}.UkovOW_state{color:var(--dsw-alias-label-tertiary)}.UkovOW_error{color:var(--dsw-alias-state-error-primary)}@media (width<=600px){.UkovOW_body{max-height:calc(100vh - 160px)}}";
7372
+ const tagId$8 = "@wowyuarm/dsh-agent-team/members.module.css";
7373
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$8) + "]") === null) {
7374
+ const tag = document.createElement("style");
7375
+ tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
7376
+ tag.dataset.pluginCss = tagId$8;
7377
+ tag.textContent = css$8;
7378
+ document.head.appendChild(tag);
7379
+ }
7380
+ var members_module_css_default = {
7381
+ "body": "UkovOW_body",
7382
+ "content": "UkovOW_content",
7383
+ "error": "UkovOW_error",
7384
+ "group": "UkovOW_group",
7385
+ "member": "UkovOW_member",
7386
+ "state": "UkovOW_state"
7387
+ };
7388
+ //#endregion
7389
+ //#region src/client/TeamMembersAction.tsx
7390
+ function TeamMembersAction({ wide, loadMemberGroups, t }) {
7391
+ const [panelOpen, setPanelOpen] = (0, react.useState)(false);
7392
+ const [groups, setGroups] = (0, react.useState)([]);
7393
+ const [loading, setLoading] = (0, react.useState)(false);
7394
+ const [error, setError] = (0, react.useState)();
7395
+ const triggerRef = (0, react.useRef)(null);
7396
+ const contentRef = (0, react.useRef)(null);
7397
+ (0, react.useEffect)(() => {
7398
+ if (!panelOpen) return;
7399
+ queueMicrotask(() => {
7400
+ contentRef.current?.focus();
6866
7401
  });
6867
7402
  }, [panelOpen]);
6868
7403
  const openMembers = () => {
@@ -6920,15 +7455,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6920
7455
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
6921
7456
  id: `team-members-${group.workspaceId}`,
6922
7457
  children: group.workspaceTitle
6923
- }), group.members.map((status) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7458
+ }), group.members.map((status) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberRow, {
7459
+ status,
6924
7460
  className: members_module_css_default.member,
6925
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamPresenceDot, {
6926
- status,
6927
- t
6928
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6929
- className: members_module_css_default.copy,
6930
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: ["@", status.member.handle] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
6931
- })]
7461
+ t
6932
7462
  }, status.member.memberId))]
6933
7463
  }, group.workspaceId)),
6934
7464
  error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -6941,15 +7471,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6941
7471
  })] });
6942
7472
  }
6943
7473
  //#endregion
6944
- //#region src/client/TeamSettings.tsx
6945
- function TeamSettings({ wide, loadMemberGroups, t }) {
6946
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMembersAction, {
6947
- wide,
6948
- loadMemberGroups,
6949
- t
6950
- });
6951
- }
6952
- //#endregion
6953
7474
  //#region src/client/attachment-preview.ts
6954
7475
  /** Base64 one file payload in chunks so large uploads stay off the call-stack limit. */
6955
7476
  function bytesToBase64(bytes) {
@@ -7012,13 +7533,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7012
7533
  };
7013
7534
  //#endregion
7014
7535
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/composer.module.css.mjs
7015
- const css$6 = ".x9jGQq_root{padding:0 var(--dsh-composer-side-clearance,16px) 8px;flex-direction:column;align-items:center;display:flex}.x9jGQq_card{box-sizing:border-box;width:100%;max-width:var(--dsh-composer-card-max-width,780px);border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));box-shadow:var(--dsw-shadow-lv2);border-radius:22px;flex-direction:column;gap:6px;padding:10px 0 0;display:flex;position:relative}.x9jGQq_inputArea{min-height:28px;position:relative}.x9jGQq_inputArea textarea{box-sizing:border-box;resize:none;width:100%;min-height:28px;max-height:336px;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-primary));font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;background:0 0;border:0;outline:0;padding:4px 12px 0 16px;font-size:15px;line-height:24px;display:block;overflow-y:auto}.x9jGQq_inputArea textarea::placeholder{color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary))}.x9jGQq_inputArea textarea:disabled{cursor:not-allowed;opacity:.55}.x9jGQq_mentionMenu{z-index:10;border:1px solid var(--dsw-alias-border-inverted);background:var(--dsw-specific-menu);max-height:min(320px,40vh);box-shadow:var(--dsw-shadow-lv3);border-radius:12px;padding:4px;position:absolute;bottom:calc(100% + 12px);left:0;right:0;overflow-y:auto}.x9jGQq_mentionOption{width:100%;min-height:40px;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-primary));cursor:pointer;text-align:left;background:0 0;border:0;border-radius:10px;grid-template-columns:16px minmax(0,auto) minmax(0,1fr);align-items:center;gap:8px;padding:8px 10px;font-size:14px;line-height:22px;display:grid}.x9jGQq_mentionOption:hover,.x9jGQq_mentionOption[aria-selected=true]{background:var(--dsw-alias-interactive-bg-hover)}.x9jGQq_mentionName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.x9jGQq_mentionAllDot{corner-shape:round;background:var(--dsw-alias-label-primary);border-radius:50%;justify-self:center;width:8px;height:8px}.x9jGQq_mentionDescription{min-width:0;color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-tertiary));text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.x9jGQq_toolbar{justify-content:flex-end;align-items:center;gap:12px;min-height:34px;padding:2px 8px 6px;display:flex;container-type:inline-size}.x9jGQq_asTaskPill{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:24px;flex:none;align-items:center;gap:4px;height:28px;padding:0 10px 0 8px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}.x9jGQq_asTaskPill:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.x9jGQq_asTaskPill:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.x9jGQq_asTaskPill:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.x9jGQq_asTaskPillOn,.x9jGQq_asTaskPillOn:hover:not(:disabled){background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.x9jGQq_asTaskLabel{white-space:nowrap}@container (width<=460px){.x9jGQq_asTaskPill .x9jGQq_asTaskLabel{display:none}}.x9jGQq_attachButton{background:var(--dsw-specific-selector);corner-shape:round;color:var(--dsw-alias-label-primary);cursor:pointer;border:0;border-radius:999px;flex:none;place-items:center;width:28px;height:28px;display:grid}.x9jGQq_attachButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.x9jGQq_attachButton:disabled{cursor:default;opacity:.5}.x9jGQq_attachButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,var(--dsw-specific-selector));outline-offset:1px}.x9jGQq_fileInput{display:none}.x9jGQq_fileChips{flex-wrap:wrap;gap:4px;margin:0;padding:4px 8px 0;list-style:none;display:flex}.x9jGQq_fileChip{background:var(--dsw-alias-interactive-bg-hover);border-radius:6px;align-items:center;gap:4px;max-width:100%;padding:2px 4px 2px 8px;display:inline-flex}.x9jGQq_fileChipSize{color:var(--dsw-alias-label-tertiary);margin-left:6px}.x9jGQq_imageChip{align-items:center;display:flex}.x9jGQq_imageChipPreview{border:1px solid var(--dsw-alias-border-l2);object-fit:cover;border-radius:4px;width:56px;height:40px}.x9jGQq_fileChipName{text-overflow:ellipsis;white-space:nowrap;max-width:220px;font-size:11px;line-height:16px;overflow:hidden}.x9jGQq_fileChipRemove{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:12px;display:inline-flex}.x9jGQq_fileChipRemove:hover,.x9jGQq_fileChipRemove:focus-visible{color:var(--dsw-alias-label-primary)}.x9jGQq_fileChipRemove:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.x9jGQq_sendButton{background:var(--dsw-alias-button-info-fill,var(--dsw-alias-button-primary-fill));corner-shape:round;color:#fff;cursor:pointer;border:0;border-radius:999px;justify-content:center;align-items:center;width:34px;height:34px;margin-left:auto;padding:0;transition:background-color .1s,opacity .1s;display:inline-flex;transform:translateY(-2px)}.x9jGQq_sendButton:hover:not(:disabled){background:var(--dsw-alias-button-info-hover,var(--dsw-alias-button-primary-hover))}.x9jGQq_sendButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.x9jGQq_sendButton:disabled{cursor:default;opacity:.4}.x9jGQq_confirmation{color:var(--dsw-alias-label-tertiary);align-self:stretch;margin:0;padding:0 16px;font-size:12px;line-height:18px}.x9jGQq_notifyRow{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-tertiary));overflow-wrap:anywhere;margin:0;padding:0 16px;font-size:12px;line-height:18px}.x9jGQq_error{color:var(--dsw-alias-state-error-primary);align-self:stretch;margin:0;padding:0 4px 2px;font-size:12px;line-height:18px}@media (width<=600px){.x9jGQq_mentionOption{grid-template-columns:16px minmax(0,1fr);min-height:36px;padding-block:6px}.x9jGQq_mentionDescription{display:none}}@media (prefers-reduced-motion:reduce){.x9jGQq_sendButton{transition:none}}";
7016
- const tagId$6 = "@wowyuarm/dsh-agent-team/composer.module.css";
7017
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
7536
+ const css$7 = ".x9jGQq_root{padding:0 var(--dsh-composer-side-clearance,16px) 8px;flex-direction:column;align-items:center;display:flex}.x9jGQq_card{box-sizing:border-box;width:100%;max-width:var(--dsh-composer-card-max-width,780px);border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));box-shadow:var(--dsw-shadow-lv2);border-radius:22px;flex-direction:column;gap:6px;padding:10px 0 0;display:flex;position:relative}.x9jGQq_inputArea{min-height:28px;position:relative}.x9jGQq_inputArea textarea{box-sizing:border-box;resize:none;width:100%;min-height:28px;max-height:336px;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-primary));font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;background:0 0;border:0;outline:0;padding:4px 12px 0 16px;font-size:15px;line-height:24px;display:block;overflow-y:auto}.x9jGQq_inputArea textarea::placeholder{color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary))}.x9jGQq_inputArea textarea:disabled{cursor:not-allowed;opacity:.55}.x9jGQq_mentionMenu{z-index:10;border:1px solid var(--dsw-alias-border-inverted);background:var(--dsw-specific-menu);max-height:min(320px,40vh);box-shadow:var(--dsw-shadow-lv3);border-radius:12px;padding:4px;position:absolute;bottom:calc(100% + 12px);left:0;right:0;overflow-y:auto}.x9jGQq_mentionOption{width:100%;min-height:40px;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-primary));cursor:pointer;text-align:left;background:0 0;border:0;border-radius:10px;grid-template-columns:16px minmax(0,auto) minmax(0,1fr);align-items:center;gap:8px;padding:8px 10px;font-size:14px;line-height:22px;display:grid}.x9jGQq_mentionOption:hover,.x9jGQq_mentionOption[aria-selected=true]{background:var(--dsw-alias-interactive-bg-hover)}.x9jGQq_mentionName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.x9jGQq_mentionAllDot{corner-shape:round;background:var(--dsw-alias-label-primary);border-radius:50%;justify-self:center;width:8px;height:8px}.x9jGQq_mentionDescription{min-width:0;color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-tertiary));text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.x9jGQq_toolbar{justify-content:flex-end;align-items:center;gap:12px;min-height:34px;padding:2px 8px 6px;display:flex;container-type:inline-size}.x9jGQq_asTaskPill{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:24px;flex:none;align-items:center;gap:4px;height:28px;padding:0 10px 0 8px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}.x9jGQq_asTaskPill:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.x9jGQq_asTaskPill:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.x9jGQq_asTaskPill:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.x9jGQq_asTaskPillOn,.x9jGQq_asTaskPillOn:hover:not(:disabled){background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.x9jGQq_asTaskLabel{white-space:nowrap}@container (width<=460px){.x9jGQq_asTaskPill .x9jGQq_asTaskLabel{display:none}}.x9jGQq_attachButton{background:var(--dsw-specific-selector);corner-shape:round;color:var(--dsw-alias-label-primary);cursor:pointer;border:0;border-radius:999px;flex:none;place-items:center;width:28px;height:28px;display:grid}.x9jGQq_attachButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.x9jGQq_attachButton:disabled{cursor:default;opacity:.5}.x9jGQq_attachButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,var(--dsw-specific-selector));outline-offset:1px}.x9jGQq_fileInput{display:none}.x9jGQq_fileChips{flex-wrap:wrap;gap:4px;margin:0;padding:4px 8px 0;list-style:none;display:flex}.x9jGQq_fileChip{background:var(--dsw-alias-interactive-bg-hover);border-radius:6px;align-items:center;gap:4px;max-width:100%;padding:2px 4px 2px 8px;display:inline-flex}.x9jGQq_fileChipSize{color:var(--dsw-alias-label-tertiary);margin-left:6px}.x9jGQq_imageChip{align-items:center;display:flex}.x9jGQq_imageChipPreview{border:1px solid var(--dsw-alias-border-l2);object-fit:cover;border-radius:4px;width:56px;height:40px}.x9jGQq_fileChipName{text-overflow:ellipsis;white-space:nowrap;max-width:220px;font-size:11px;line-height:16px;overflow:hidden}.x9jGQq_fileChipRemove{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:12px;display:inline-flex}.x9jGQq_fileChipRemove:hover,.x9jGQq_fileChipRemove:focus-visible{color:var(--dsw-alias-label-primary)}.x9jGQq_fileChipRemove:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.x9jGQq_sendButton{background:var(--dsw-alias-button-info-fill,var(--dsw-alias-button-primary-fill));corner-shape:round;color:#fff;cursor:pointer;border:0;border-radius:999px;justify-content:center;align-items:center;width:34px;height:34px;margin-left:auto;padding:0;transition:background-color .1s,opacity .1s;display:inline-flex;transform:translateY(-2px)}.x9jGQq_sendButton:hover:not(:disabled){background:var(--dsw-alias-button-info-hover,var(--dsw-alias-button-primary-hover))}.x9jGQq_sendButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.x9jGQq_sendButton:disabled{cursor:default;opacity:.4}.x9jGQq_confirmation{color:var(--dsw-alias-label-tertiary);align-self:stretch;margin:0;padding:0 16px;font-size:12px;line-height:18px}.x9jGQq_notifyRow{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-tertiary));overflow-wrap:anywhere;margin:0;padding:0 16px;font-size:12px;line-height:18px}.x9jGQq_error{color:var(--dsw-alias-state-error-primary);align-self:stretch;margin:0;padding:0 4px 2px;font-size:12px;line-height:18px}@media (width<=600px){.x9jGQq_mentionOption{grid-template-columns:16px minmax(0,1fr);min-height:36px;padding-block:6px}.x9jGQq_mentionDescription{display:none}}@media (prefers-reduced-motion:reduce){.x9jGQq_sendButton{transition:none}}";
7537
+ const tagId$7 = "@wowyuarm/dsh-agent-team/composer.module.css";
7538
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$7) + "]") === null) {
7018
7539
  const tag = document.createElement("style");
7019
7540
  tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
7020
- tag.dataset.pluginCss = tagId$6;
7021
- tag.textContent = css$6;
7541
+ tag.dataset.pluginCss = tagId$7;
7542
+ tag.textContent = css$7;
7022
7543
  document.head.appendChild(tag);
7023
7544
  }
7024
7545
  var composer_module_css_default = {
@@ -7064,12 +7585,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7064
7585
  query: beforeCaret.slice(at + 1)
7065
7586
  };
7066
7587
  }
7067
- function escapeRegExp$1(value) {
7068
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7069
- }
7070
- function containsMention(draft, handle) {
7071
- return new RegExp(`(?:^|[^\\p{L}\\p{N}_])@${escapeRegExp$1(handle)}(?=$|[^\\p{L}\\p{N}_])`, "u").test(draft);
7072
- }
7073
7588
  function mentionCandidates(members, query) {
7074
7589
  const normalized = query.toLocaleLowerCase();
7075
7590
  return members.filter((status) => status.presence !== "unavailable" && status.member.state !== "inactive" && status.member.state !== "archived" && status.member.handle.toLocaleLowerCase().startsWith(normalized));
@@ -7079,13 +7594,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7079
7594
  if (followers === void 0 || followers.size === 0) return candidates;
7080
7595
  return [...candidates].sort((left, right) => Number(followers.has(right.member.memberId)) - Number(followers.has(left.member.memberId)));
7081
7596
  }
7082
- /** Every member a manual handle pick could reach: the @all expansion snapshot. */
7083
- function allMentionMembers(members) {
7084
- return members.filter((status) => status.presence !== "unavailable" && status.member.state !== "inactive" && status.member.state !== "archived");
7085
- }
7086
- function containsAllMention(draft) {
7087
- return /(?:^|[^\p{L}\p{N}_])@all(?=$|[^\p{L}\p{N}_])/u.test(draft);
7088
- }
7089
7597
  /** One object URL per draft file; revoked when the draft is removed. */
7090
7598
  const draftPreviewUrls = /* @__PURE__ */ new WeakMap();
7091
7599
  function draftPreviewUrl(file) {
@@ -7154,12 +7662,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7154
7662
  if (confirmation === void 0 || pending) return;
7155
7663
  inputRef.current?.focus({ preventScroll: true });
7156
7664
  }, [confirmation, pending]);
7665
+ const memberHandles = new Map(members.map((status) => [status.member.memberId, status.member.handle]));
7157
7666
  const pruneRecipients = (nextDraft) => {
7158
7667
  if (containsAllMention(nextDraft)) return;
7159
- const knownMembers = new Map(members.map((status) => [status.member.memberId, status.member]));
7160
7668
  const next = new Set([...recipients].filter((memberId) => {
7161
- const member = knownMembers.get(memberId);
7162
- return member !== void 0 && containsMention(nextDraft, member.handle);
7669
+ const handle = memberHandles.get(memberId);
7670
+ return handle !== void 0 && containsMention(nextDraft, handle);
7163
7671
  }));
7164
7672
  if (next.size !== recipients.size) drafts.writeRecipients(draftKey, next);
7165
7673
  };
@@ -7171,6 +7679,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7171
7679
  recipients,
7172
7680
  members
7173
7681
  ]);
7682
+ const notifiedIds = [...new Set([...recipients, ...mentionedMemberIds(draft, members)])].sort();
7174
7683
  const updateMention = (nextDraft, caret) => {
7175
7684
  const match = findMention(nextDraft, caret);
7176
7685
  setMention(match);
@@ -7359,10 +7868,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7359
7868
  }
7360
7869
  })]
7361
7870
  }),
7362
- recipients.size > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7871
+ notifiedIds.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7363
7872
  className: composer_module_css_default.notifyRow,
7364
7873
  "data-team-notify": true,
7365
- children: t("composerNotify", { ids: [...recipients].sort().map((memberId) => `@${members.find((candidate) => candidate.member.memberId === memberId)?.member.handle ?? memberId}`).join(", ") })
7874
+ children: t("composerNotify", { ids: notifiedIds.map((memberId) => `@${memberHandles.get(memberId) ?? memberId}`).join(", ") })
7366
7875
  }),
7367
7876
  onFilesChange !== void 0 && pendingFiles !== void 0 && pendingFiles.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
7368
7877
  className: composer_module_css_default.fileChips,
@@ -7455,370 +7964,119 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7455
7964
  event.preventDefault();
7456
7965
  inputRef.current?.focus({ preventScroll: true });
7457
7966
  },
7458
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSendOutline16, { size: 16 })
7459
- })
7460
- ]
7461
- })
7462
- ]
7463
- }), error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7464
- className: composer_module_css_default.error,
7465
- role: "alert",
7466
- children: error
7467
- })]
7468
- });
7469
- }
7470
- //#endregion
7471
- //#region src/client/task-refs.ts
7472
- const resolved = /* @__PURE__ */ new Map();
7473
- const pending = /* @__PURE__ */ new Set();
7474
- /** Refs the Host did not recognize; never re-queried (no retry loops). */
7475
- const unresolvable = /* @__PURE__ */ new Set();
7476
- const listeners$2 = /* @__PURE__ */ new Set();
7477
- let version = 0;
7478
- const emit = () => {
7479
- version += 1;
7480
- for (const listener of listeners$2) listener();
7481
- };
7482
- const subscribe = (listener) => {
7483
- listeners$2.add(listener);
7484
- return () => {
7485
- listeners$2.delete(listener);
7486
- };
7487
- };
7488
- /** Stable snapshot token; the map is read directly after this changes. */
7489
- const getSnapshot = () => version;
7490
- /** React binding: re-renders the caller when any ref resolution lands. */
7491
- const useResolvedTaskRefVersion = () => (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7492
- const cachedResolvedTaskRef = (taskRef) => resolved.get(taskRef);
7493
- /** Store one resolution (click path) and wake every rendered link. */
7494
- const rememberResolvedTaskRef = (entry) => {
7495
- resolved.set(entry.taskRef, entry);
7496
- pending.delete(entry.taskRef);
7497
- emit();
7498
- };
7499
- /** Compare refs by branded prefix plus hyphen-stripped UUID, so abbreviated spellings line up with their full form. */
7500
- function refKeyOf(ref) {
7501
- return ref.toLowerCase().replaceAll("-", "");
7502
- }
7503
- /**
7504
- * Click-path Host lookup: remember every resolved entry and hand them back
7505
- * for immediate navigation. The Host keeps `resolved` in the same order as
7506
- * the input `taskRefs` (one entry per resolvable input, unknowns omitted);
7507
- * the pairing walk below relies on that contract, so it must be preserved
7508
- * together with this implementation.
7509
- */
7510
- const hostTaskRefLookup = (resolveTaskRefs, workspaceId) => async (taskRefs) => {
7511
- const result = await resolveTaskRefs({
7512
- workspaceId,
7513
- taskRefs
7514
- });
7515
- if (!result.ok) return [];
7516
- const entries = result.value.resolved;
7517
- let entryIndex = 0;
7518
- for (const requested of taskRefs) {
7519
- const entry = entries[entryIndex];
7520
- if (entry === void 0 || !refKeyOf(entry.taskRef).startsWith(refKeyOf(requested))) continue;
7521
- if (entry.taskRef !== requested) rememberResolvedTaskRef({
7522
- ...entry,
7523
- taskRef: requested
7524
- });
7525
- rememberResolvedTaskRef(entry);
7526
- entryIndex += 1;
7527
- }
7528
- return entries;
7529
- };
7530
- /** Resolve one Task ref through the Host and jump to its home Channel Thread. */
7531
- const jumpToTaskThread = (resolveTaskRefs, workspaceId, taskRef, selectThread) => {
7532
- resolveTaskRefs({
7533
- workspaceId,
7534
- taskRefs: [taskRef]
7535
- }).then((result) => {
7536
- if (!result.ok) return;
7537
- const hit = result.value.resolved[0];
7538
- if (hit !== void 0) selectThread(hit.threadRef, hit.channelRef, hit.taskRef, hit.taskNumber);
7539
- });
7540
- };
7541
- /**
7542
- * Batch-resolve unknown refs through the Host lookup. Concurrent callers
7543
- * deduplicate through the pending set; failures just clear the pending mark
7544
- * so a later interaction can retry.
7545
- */
7546
- const resolveUnknownTaskRefs = async (refs, lookup) => {
7547
- const missing = refs.filter((taskRef) => !resolved.has(taskRef) && !pending.has(taskRef) && !unresolvable.has(taskRef));
7548
- if (missing.length === 0) return;
7549
- for (const taskRef of missing) pending.add(taskRef);
7550
- try {
7551
- const entries = await lookup(missing);
7552
- for (const entry of entries) {
7553
- resolved.set(entry.taskRef, entry);
7554
- pending.delete(entry.taskRef);
7555
- }
7556
- for (const taskRef of missing) if (!resolved.has(taskRef)) unresolvable.add(taskRef);
7557
- if (entries.length > 0) emit();
7558
- } finally {
7559
- for (const taskRef of missing) pending.delete(taskRef);
7560
- }
7561
- };
7562
- //#endregion
7563
- //#region src/client/team-formatters.ts
7564
- function formatTaskStatus(status, t) {
7565
- return t({
7566
- todo: "taskStatusTodo",
7567
- in_progress: "taskStatusInProgress",
7568
- in_review: "taskStatusInReview",
7569
- done: "taskStatusDone",
7570
- closed: "taskStatusClosed"
7571
- }[status]);
7572
- }
7573
- function formatClaimState(state, t) {
7574
- return t({
7575
- active: "claimStateActive",
7576
- done: "claimStateDone",
7577
- released: "claimStateReleased"
7578
- }[state]);
7579
- }
7580
- /**
7581
- * Status indicator for a Task status, the dot every Task surface renders.
7582
- * Active states map to StateDot variants; every status renders a dot so they
7583
- * share one shape language — todo is a hollow ring (not started), closed a
7584
- * quiet gray dot (archived).
7585
- */
7586
- function taskStatusDot(status) {
7587
- return {
7588
- todo: "todo",
7589
- in_progress: "ongoing",
7590
- in_review: "warning",
7591
- done: "done",
7592
- closed: "quiet"
7593
- }[status];
7594
- }
7595
- /** One-line title snippet derived from the Task's root Message body. */
7596
- function formatTaskTitle(body) {
7597
- const firstLine = body.split("\n", 1)[0]?.trim() ?? "";
7598
- return firstLine.length > 120 ? `${firstLine.slice(0, 119)}…` : firstLine;
7599
- }
7600
- /** Deterministic avatar hue for one Member identity; stable across sessions and themes. */
7601
- function memberHue(memberId) {
7602
- let hash = 0;
7603
- for (let index = 0; index < memberId.length; index += 1) hash = (hash * 31 + memberId.charCodeAt(index)) % 360;
7604
- return hash;
7605
- }
7606
- const BRANDED_REF_PATTERN = /\b(task|channel|thread):{1,2}[0-9a-f]{6,}(?:-[0-9a-f]{1,})*\b/gi;
7607
- /**
7608
- * Canonical form of one matched ref: models occasionally double the colon or
7609
- * uppercase the UUID when citing a ref in prose, while Host lookups and
7610
- * navigation only accept the lowercase single-colon ref the ledger mints.
7611
- */
7612
- function canonicalBrandedRef(match) {
7613
- return match.replace("::", ":").toLowerCase();
7614
- }
7615
- /**
7616
- * Split a literal text run into plain and branded-ref segments. The pattern
7617
- * anchors on the fixed ref prefixes plus a UUID shape (full or abbreviated),
7618
- * so ordinary prose containing a colon never linkifies; a doubled colon from
7619
- * model output is tolerated. Segment refs are always canonical, so resolution
7620
- * and navigation work regardless of how the ref was spelled; text without any
7621
- * ref comes back as one untouched segment.
7622
- */
7623
- function splitBrandedRefs(text) {
7624
- const segments = [];
7625
- let cursor = 0;
7626
- for (const match of text.matchAll(BRANDED_REF_PATTERN)) {
7627
- const start = match.index ?? 0;
7628
- if (start > cursor) segments.push({ text: text.slice(cursor, start) });
7629
- segments.push({
7630
- text: match[0],
7631
- ref: canonicalBrandedRef(match[0])
7632
- });
7633
- cursor = start + match[0].length;
7634
- }
7635
- if (cursor < text.length) segments.push({ text: text.slice(cursor) });
7636
- return segments;
7637
- }
7638
- /**
7639
- * Whether one string's whole content is exactly one branded ref. A code span
7640
- * like this is the model styling a ref as an identifier, not publishing code,
7641
- * so the Markdown pass may linkify it; anything larger stays literal.
7642
- */
7643
- function isSingleBrandedRef(text) {
7644
- const trimmed = text.trim();
7645
- if (trimmed === "") return false;
7646
- const matches = [...trimmed.matchAll(BRANDED_REF_PATTERN)];
7647
- return matches.length === 1 && matches[0][0] === trimmed;
7648
- }
7649
- function escapeRegExp(value) {
7650
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7651
- }
7652
- /**
7653
- * Locate one Message's structured mention names inside its literal body. A
7654
- * name matches case-insensitively with an optional leading '@' on Unicode word
7655
- * boundaries, and longer names win at the same position. Mention segments
7656
- * render the canonical `@Handle`; names absent from the body come back
7657
- * unmatched so the consumer can append them as a fallback chip row.
7658
- */
7659
- function splitMentionNames(text, names) {
7660
- if (names.length === 0) return {
7661
- segments: [{
7662
- text,
7663
- mention: false
7664
- }],
7665
- unmatched: []
7666
- };
7667
- const ordered = [...names].sort((left, right) => right.length - left.length);
7668
- const pattern = new RegExp(`(?<![\\p{L}\\p{N}_@])@?(?:${ordered.map((name) => `(${escapeRegExp(name)})`).join("|")})(?=$|[^\\p{L}\\p{N}_])`, "giu");
7669
- const segments = [];
7670
- const matched = /* @__PURE__ */ new Set();
7671
- let cursor = 0;
7672
- for (const match of text.matchAll(pattern)) {
7673
- const groupIndex = match.findIndex((group, index) => index >= 1 && group !== void 0);
7674
- if (groupIndex < 1) continue;
7675
- if (match.index > cursor) segments.push({
7676
- text: text.slice(cursor, match.index),
7677
- mention: false
7678
- });
7679
- const name = ordered[groupIndex - 1];
7680
- segments.push({
7681
- text: `@${name}`,
7682
- mention: true,
7683
- name
7684
- });
7685
- matched.add(name.toLowerCase());
7686
- cursor = match.index + match[0].length;
7687
- }
7688
- if (cursor < text.length) segments.push({
7689
- text: text.slice(cursor),
7690
- mention: false
7967
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSendOutline16, { size: 16 })
7968
+ })
7969
+ ]
7970
+ })
7971
+ ]
7972
+ }), error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7973
+ className: composer_module_css_default.error,
7974
+ role: "alert",
7975
+ children: error
7976
+ })]
7691
7977
  });
7692
- return {
7693
- segments,
7694
- unmatched: names.filter((name) => !matched.has(name.toLowerCase()))
7695
- };
7696
- }
7697
- /** Canonical chip handles for one Message's structured mention refs. */
7698
- function mentionNamesOf(mentions, handles) {
7699
- return mentions.map((memberId) => memberId === "member:human" ? "human" : handles.get(memberId)).filter((name) => name !== void 0);
7700
- }
7701
- const MARKDOWN_BLOCK_CONSTRUCT = /(^|\n)[ \t]{0,3}(?:#{1,6}[ \t]|>[ \t]|[-*+][ \t]|\d+[.)][ \t])|^[ \t]*\|.+\|/m;
7702
- const MARKDOWN_INLINE_CONSTRUCT = /[`*_[\]!]|~~~|```/;
7703
- /**
7704
- * Whether an Agent body survives literal rendering unchanged: no fences,
7705
- * inline code, emphasis markers, links, images, tables, or block constructs.
7706
- * Only such plain-prose bodies may reuse the Human inline mention flow —
7707
- * anything richer keeps the trailing chip row because the Markdown primitive
7708
- * renders block-level documents that cannot interleave inline chips.
7709
- */
7710
- function isPlainTextBody(text) {
7711
- return !(MARKDOWN_BLOCK_CONSTRUCT.test(text) || MARKDOWN_INLINE_CONSTRUCT.test(text));
7712
- }
7713
- const pad$1 = (value) => String(value).padStart(2, "0");
7714
- /** Absolute local `YYYY-MM-DD HH:mm` label: the precise instant behind every shorter form. */
7715
- function formatAbsoluteTime(occurredAt) {
7716
- const at = new Date(occurredAt);
7717
- if (Number.isNaN(at.getTime())) return "";
7718
- return `${at.getFullYear()}-${pad$1(at.getMonth() + 1)}-${pad$1(at.getDate())} ${pad$1(at.getHours())}:${pad$1(at.getMinutes())}`;
7719
- }
7720
- /**
7721
- * Wall-clock label for one Message instant: time within the current day,
7722
- * month-day time within the year, full date otherwise.
7723
- */
7724
- function formatMessageTime(occurredAt, now = /* @__PURE__ */ new Date()) {
7725
- const at = new Date(occurredAt);
7726
- if (Number.isNaN(at.getTime())) return "";
7727
- if (at.getFullYear() === now.getFullYear() && at.getMonth() === now.getMonth() && at.getDate() === now.getDate()) return `${pad$1(at.getHours())}:${pad$1(at.getMinutes())}`;
7728
- const absolute = formatAbsoluteTime(occurredAt);
7729
- return at.getFullYear() === now.getFullYear() ? absolute.slice(5) : absolute;
7730
7978
  }
7731
- /**
7732
- * Calendar days between two instants in the viewer's own zone, so "yesterday"
7733
- * means yesterday locally rather than 24 hours earlier.
7734
- */
7735
- function calendarDayDelta(at, now) {
7736
- const midnight = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
7737
- return Math.round((midnight(now) - midnight(at)) / 864e5);
7979
+ //#endregion
7980
+ //#region src/client/task-refs.ts
7981
+ const resolved = /* @__PURE__ */ new Map();
7982
+ const pending = /* @__PURE__ */ new Set();
7983
+ /** Refs the Host did not recognize; never re-queried (no retry loops). */
7984
+ const unresolvable = /* @__PURE__ */ new Set();
7985
+ const listeners$2 = /* @__PURE__ */ new Set();
7986
+ let version = 0;
7987
+ const emit = () => {
7988
+ version += 1;
7989
+ for (const listener of listeners$2) listener();
7990
+ };
7991
+ const subscribe = (listener) => {
7992
+ listeners$2.add(listener);
7993
+ return () => {
7994
+ listeners$2.delete(listener);
7995
+ };
7996
+ };
7997
+ /** Stable snapshot token; the map is read directly after this changes. */
7998
+ const getSnapshot = () => version;
7999
+ /** React binding: re-renders the caller when any ref resolution lands. */
8000
+ const useResolvedTaskRefVersion = () => (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8001
+ const cachedResolvedTaskRef = (taskRef) => resolved.get(taskRef);
8002
+ /** Store one resolution (click path) and wake every rendered link. */
8003
+ const rememberResolvedTaskRef = (entry) => {
8004
+ resolved.set(entry.taskRef, entry);
8005
+ pending.delete(entry.taskRef);
8006
+ emit();
8007
+ };
8008
+ /** Compare refs by branded prefix plus hyphen-stripped UUID, so abbreviated spellings line up with their full form. */
8009
+ function refKeyOf(ref) {
8010
+ return ref.toLowerCase().replaceAll("-", "");
7738
8011
  }
7739
8012
  /**
7740
- * Queue label for one Inbox row's newest mention. The mention queue scans by
7741
- * recency, so the two days a reader reasons about by name are named ("今天" /
7742
- * "昨天") while everything older keeps the Message date form, so the row and
7743
- * the Thread it opens agree about the same instant.
8013
+ * Click-path Host lookup: remember every resolved entry and hand them back
8014
+ * for immediate navigation. The Host keeps `resolved` in the same order as
8015
+ * the input `taskRefs` (one entry per resolvable input, unknowns omitted);
8016
+ * the pairing walk below relies on that contract, so it must be preserved
8017
+ * together with this implementation.
7744
8018
  */
7745
- function formatInboxTime(occurredAt, t, now = /* @__PURE__ */ new Date()) {
7746
- const at = new Date(occurredAt);
7747
- if (Number.isNaN(at.getTime())) return "";
7748
- const days = calendarDayDelta(at, now);
7749
- if (days === 0 || days === 1) return `${t(days === 0 ? "inboxTimeToday" : "inboxTimeYesterday")} ${pad$1(at.getHours())}:${pad$1(at.getMinutes())}`;
7750
- return formatMessageTime(occurredAt, now);
7751
- }
7752
- function formatActivity(activity, options) {
7753
- const actor = options.actorName(activity.actor);
7754
- if (activity.kind === "accept") return activity.completedClaimRefs !== void 0 && activity.completedClaimRefs.length > 0 ? options.t("activityAcceptedWithClaims", {
7755
- actor,
7756
- count: activity.completedClaimRefs.length
7757
- }) : options.t("activityAccepted", { actor });
7758
- if (activity.kind === "promote") return options.t("activityPromoted", { actor });
7759
- if (activity.kind === "close") return options.t("activityClosed", { actor });
7760
- if (activity.kind === "reopen") return options.t("activityReopened", { actor });
7761
- const direction = "claimRef" in activity ? options.claims.find((claim) => claim.claimRef === activity.claimRef)?.direction ?? options.t("claims") : options.t("claims");
7762
- if (activity.kind === "claim") return options.t("activityClaimed", {
7763
- actor,
7764
- direction
7765
- });
7766
- if (activity.kind === "done") return options.t("activityClaimDone", {
7767
- actor,
7768
- direction
7769
- });
7770
- if (activity.kind === "release") return options.t("activityClaimReleased", {
7771
- actor,
7772
- direction
8019
+ const hostTaskRefLookup = (resolveTaskRefs, workspaceId) => async (taskRefs) => {
8020
+ const result = await resolveTaskRefs({
8021
+ workspaceId,
8022
+ taskRefs
7773
8023
  });
7774
- if (activity.kind === "claims_released") return options.t("activityClaimsReleased", {
7775
- actor,
7776
- count: activity.claimRefs.length
8024
+ if (!result.ok) return [];
8025
+ const entries = result.value.resolved;
8026
+ let entryIndex = 0;
8027
+ for (const requested of taskRefs) {
8028
+ const entry = entries[entryIndex];
8029
+ if (entry === void 0 || !refKeyOf(entry.taskRef).startsWith(refKeyOf(requested))) continue;
8030
+ if (entry.taskRef !== requested) rememberResolvedTaskRef({
8031
+ ...entry,
8032
+ taskRef: requested
8033
+ });
8034
+ rememberResolvedTaskRef(entry);
8035
+ entryIndex += 1;
8036
+ }
8037
+ return entries;
8038
+ };
8039
+ /** Resolve one Task ref through the Host and jump to its home Channel Thread. */
8040
+ const jumpToTaskThread = (resolveTaskRefs, workspaceId, taskRef, selectThread) => {
8041
+ resolveTaskRefs({
8042
+ workspaceId,
8043
+ taskRefs: [taskRef]
8044
+ }).then((result) => {
8045
+ if (!result.ok) return;
8046
+ const hit = result.value.resolved[0];
8047
+ if (hit !== void 0) selectThread(hit.threadRef, hit.channelRef, hit.taskRef, hit.taskNumber);
7777
8048
  });
7778
- throw new Error(`unknown Team Activity kind: ${activity.kind}`);
7779
- }
7780
- /** Remove the machine-facing `[attachment] <path>` prompt lines from a body before display. */
7781
- function stripAttachmentLines(body) {
7782
- return body.replaceAll(/^\[attachment\] .*$(\n)?/gm, "").replace(/\n+$/, "");
7783
- }
7784
- /** Whether one displayed Message body starts clamped behind the expand control. */
7785
- function shouldClampMessage(displayBody) {
7786
- return displayBody.length > 600;
7787
- }
8049
+ };
7788
8050
  /**
7789
- * Decide how one Message body renders. Human input and plain-prose Agent
7790
- * bodies stay literal, with structured mention chips inline where possible;
7791
- * rich Agent Markdown keeps unmatched mentions and non-Task refs in the
7792
- * trailing fallback row while the post-render pass handles Task refs at their
7793
- * authored position. Surfaces without ref navigation render everything
7794
- * literally and keep the full fallback row.
8051
+ * Batch-resolve unknown refs through the Host lookup. Concurrent callers
8052
+ * deduplicate through the pending set; failures just clear the pending mark
8053
+ * so a later interaction can retry.
7795
8054
  */
7796
- function planMessageBody(body, options) {
7797
- const stripped = stripAttachmentLines(body);
7798
- const displayBody = stripped === "" ? body : stripped;
7799
- const richAgentBody = !options.human && !isPlainTextBody(displayBody);
7800
- const inline = (options.human || isPlainTextBody(displayBody)) && options.mentionNames !== void 0 && options.mentionNames.length > 0 ? splitMentionNames(displayBody, options.mentionNames) : void 0;
7801
- const fallbackNames = inline !== void 0 ? inline.unmatched : richAgentBody && options.canOpenRefs && options.mentionNames !== void 0 ? splitMentionNames(displayBody, options.mentionNames).unmatched : options.mentionNames ?? [];
7802
- const refs = splitBrandedRefs(displayBody).flatMap((segment) => segment.ref === void 0 ? [] : [segment.ref]);
7803
- return {
7804
- displayBody,
7805
- richAgentBody,
7806
- render: inline !== void 0 ? "inline" : options.human || options.canOpenRefs && !richAgentBody && refs.length > 0 ? "literal" : "markdown",
7807
- ...inline === void 0 ? {} : { inline },
7808
- fallbackNames,
7809
- fallbackRefs: richAgentBody && !options.canOpenRefs ? refs : [],
7810
- taskRefs: options.canOpenRefs && !richAgentBody ? refs.filter((ref) => ref.startsWith("task:")).map((ref) => ref) : []
7811
- };
7812
- }
8055
+ const resolveUnknownTaskRefs = async (refs, lookup) => {
8056
+ const missing = refs.filter((taskRef) => !resolved.has(taskRef) && !pending.has(taskRef) && !unresolvable.has(taskRef));
8057
+ if (missing.length === 0) return;
8058
+ for (const taskRef of missing) pending.add(taskRef);
8059
+ try {
8060
+ const entries = await lookup(missing);
8061
+ for (const entry of entries) {
8062
+ resolved.set(entry.taskRef, entry);
8063
+ pending.delete(entry.taskRef);
8064
+ }
8065
+ for (const taskRef of missing) if (!resolved.has(taskRef)) unresolvable.add(taskRef);
8066
+ if (entries.length > 0) emit();
8067
+ } finally {
8068
+ for (const taskRef of missing) pending.delete(taskRef);
8069
+ }
8070
+ };
7813
8071
  //#endregion
7814
8072
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/conversation.module.css.mjs
7815
- const css$5 = ".omcBaG_surface{grid-template-rows:auto minmax(0,1fr) auto;min-width:0;height:100%;min-height:0;display:grid;overflow:hidden}.omcBaG_surfaceHeader{border-bottom:1px solid var(--dsw-alias-border-l2);min-width:0;padding:14px clamp(18px,3vw,36px) 12px}.omcBaG_headerRow{justify-content:space-between;align-items:flex-start;gap:16px;min-width:0;max-width:880px;margin:0 auto;display:flex}.omcBaG_headerCopy{min-width:0}.omcBaG_headerCopy h1{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;font-size:20px;font-weight:600;line-height:28px}.omcBaG_headerCopy p{color:var(--dsw-alias-label-secondary);margin:3px 0 0;font-size:13px;line-height:20px}.omcBaG_headerActions{flex:none;align-items:center;gap:6px;display:flex}.omcBaG_backRow{max-width:880px;margin:0 auto 8px}.omcBaG_timeline{overscroll-behavior:contain;scrollbar-gutter:stable;min-height:0;padding:12px clamp(18px,3vw,36px) 24px;overflow:hidden auto}.omcBaG_timelineContent{flex-direction:column;min-width:0;max-width:880px;min-height:100%;margin:0 auto;display:flex}.omcBaG_emptySurface{margin:auto;padding:32px 0}.omcBaG_emptySurface .omcBaG_emptyState{text-align:center;justify-items:center}.omcBaG_timelineAction{justify-content:center;padding:2px 0 8px;display:flex}.omcBaG_messageRow{gap:10px;padding:10px 0;display:flex}.omcBaG_messageRow[data-grouped]{padding-top:2px}.omcBaG_messageRow[data-grouped] .omcBaG_messageBody>:first-child,.omcBaG_messageRow[data-grouped] .omcBaG_messageBody>:first-child>:first-child{margin-top:0}.omcBaG_messageIdentity{background:hsl(var(--team-avatar-hue,212) 42% 46%);corner-shape:round;color:#fff;border-radius:50%;flex:0 0 28px;justify-content:center;align-items:center;height:28px;font-size:12px;font-weight:600;display:flex}.omcBaG_messageRow[data-human] .omcBaG_messageIdentity{background:var(--dsw-alias-state-business-primary)}.omcBaG_messageRow[data-grouped] .omcBaG_messageIdentity{visibility:hidden}.omcBaG_messageBody{min-width:0}.omcBaG_nameRow{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.omcBaG_nameRow strong{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:20px}.omcBaG_messageTime{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:20px}.omcBaG_messageText{white-space:pre-wrap;word-break:break-word;margin:6px 0;font-size:14px;line-height:22px}.omcBaG_messageClamp{max-height:176px;overflow:hidden;-webkit-mask-image:linear-gradient(#000 72%,#0000 100%);mask-image:linear-gradient(#000 72%,#0000 100%)}.omcBaG_messageExpand{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;width:fit-content;margin-top:4px;padding:0;font-size:12px;line-height:20px;display:block}.omcBaG_messageExpand:hover,.omcBaG_messageExpand:focus-visible{color:var(--dsw-alias-label-primary);text-underline-offset:2px;outline:none;text-decoration:underline}.omcBaG_messageBody .omcBaG_messageMarkdown{font-size:14px;line-height:22px}.omcBaG_messageBody .omcBaG_messageMarkdown>div:first-child{color:var(--dsw-alias-label-primary);font:inherit}.omcBaG_messageBody .omcBaG_messageMarkdown p{margin:6px 0}.omcBaG_messageBody .omcBaG_messageMarkdown :where(ul,ol){margin:6px 0;padding-left:22px}.omcBaG_messageBody .omcBaG_messageMarkdown li+li{margin-top:2px}.omcBaG_messageBody .omcBaG_messageMarkdown strong{font-weight:600}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h1,h2,h3,h4,h5,h6){margin:12px 0 4px}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h1){font-size:17px;line-height:26px}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h2){font-size:16px;line-height:24px}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h3,h4,h5,h6){font-size:15px;line-height:22px}.omcBaG_messageBody .omcBaG_messageMarkdown pre{margin:8px 0;padding:10px 12px;font-size:13px}.omcBaG_messageBody .omcBaG_messageMarkdown blockquote{margin:6px 0}.omcBaG_messageBody .omcBaG_messageMarkdown :where(th,td){padding-block:5px}.omcBaG_emptyState,.omcBaG_loadingState{color:var(--dsw-alias-label-tertiary);margin:0;padding:14px 0;font-size:13px;line-height:20px}.omcBaG_emptyState{gap:3px;display:grid}.omcBaG_emptyState strong{color:var(--dsw-alias-label-secondary);font-weight:500}.omcBaG_emptyState span{font-size:12px}.omcBaG_loadingState{align-items:center;gap:8px;display:flex}.omcBaG_loadingMark{background:var(--dsw-alias-bg-skeleton);corner-shape:round;border-radius:50%;width:8px;height:8px;animation:1.2s ease-in-out infinite omcBaG_pulse}.omcBaG_error,.omcBaG_errorState{color:var(--dsw-alias-state-error-primary);max-width:880px;margin:0 auto;padding-top:6px;font-size:12px;line-height:18px}.omcBaG_errorState{justify-content:space-between;align-items:center;gap:8px;display:flex}.omcBaG_welcomeSurface{justify-content:center;align-items:center;min-width:0;height:100%;padding:32px;display:flex}.omcBaG_welcome{text-align:center;max-width:420px}.omcBaG_welcomeEyebrow{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;font-size:12px;line-height:18px}.omcBaG_welcome h1{color:var(--dsw-alias-label-primary);margin:8px 0;font-size:24px;font-weight:600;line-height:32px}.omcBaG_welcome p{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:20px}@keyframes omcBaG_pulse{0%,to{opacity:.35}50%{opacity:1}}@media (width<=600px){.omcBaG_surfaceHeader{padding:12px 12px 10px}.omcBaG_headerRow{flex-direction:column;align-items:stretch;gap:8px}.omcBaG_headerActions{flex-wrap:wrap}.omcBaG_backRow{margin-bottom:6px}.omcBaG_timeline{scrollbar-gutter:auto;padding:8px 12px 16px}.omcBaG_messageRow{padding:8px 0}}@media (prefers-reduced-motion:reduce){.omcBaG_loadingMark{animation:none}}.omcBaG_messageRun{margin:2px 0;padding:3px 0}.omcBaG_messageRow[data-grouped]:has(.omcBaG_messageBody>button:not([data-message-expand])){margin-top:3px;padding-top:7px;position:relative}.omcBaG_messageRow[data-grouped]:has(.omcBaG_messageBody>button:not([data-message-expand])):before{background:var(--dsw-alias-border-l2);content:\"\";height:1px;position:absolute;inset:0 0 auto 38px}.omcBaG_runDivider{border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);margin:2px 0 0 38px;padding:5px 0 0;font-size:11px;line-height:16px}.omcBaG_runDivider+.omcBaG_messageRow[data-grouped]:has(.omcBaG_messageBody>button:not([data-message-expand])){margin-top:0}.omcBaG_runDivider+.omcBaG_messageRow[data-grouped]:has(.omcBaG_messageBody>button:not([data-message-expand])):before{content:none}.omcBaG_mention{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);color:var(--dsw-alias-state-business-primary);border-radius:6px;padding:0 4px;font-weight:500;box-shadow:0 1px 2px #00000014}.omcBaG_mentionsRow{gap:4px;width:fit-content;margin-top:3px;font-size:.85em;display:flex}.omcBaG_attachmentStrip{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}.omcBaG_attachmentThumb{cursor:zoom-in;border:0;border-radius:8px;padding:0}.omcBaG_attachmentThumb img{object-fit:cover;border-radius:8px;width:128px;height:96px;display:block}.omcBaG_attachmentThumb:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,currentColor);outline-offset:1px}.omcBaG_confirmBody{margin:0 0 8px}.omcBaG_confirmList{gap:6px;margin:0;padding-left:18px;display:grid}.omcBaG_refLink{color:var(--dsw-alias-state-business-primary);cursor:pointer;font:inherit;text-align:left;text-underline-offset:3px;background:0 0;border:none;border-radius:4px;padding:0;text-decoration:underline}.omcBaG_refLink:hover{text-decoration-thickness:2px}.omcBaG_refLink:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}.omcBaG_attachmentModal{width:min(1100px,92vw)}.omcBaG_attachmentZoom{object-fit:contain;border-radius:12px;max-width:100%;max-height:78vh;margin:0 auto;display:block}.omcBaG_attachmentChip{background:var(--dsw-alias-interactive-bg-hover);border-radius:6px;align-items:baseline;gap:6px;max-width:100%;padding:3px 8px;display:inline-flex}.omcBaG_attachmentChipName{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:17px;overflow:hidden}.omcBaG_attachmentChipSize{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11px;line-height:17px}";
7816
- const tagId$5 = "@wowyuarm/dsh-agent-team/conversation.module.css";
7817
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
8073
+ const css$6 = ".omcBaG_surface{grid-template-rows:auto minmax(0,1fr) auto;min-width:0;height:100%;min-height:0;display:grid;overflow:hidden}.omcBaG_surfaceHeader{border-bottom:1px solid var(--dsw-alias-border-l2);min-width:0;padding:14px clamp(18px,3vw,36px) 12px}.omcBaG_headerRow{justify-content:space-between;align-items:flex-start;gap:16px;min-width:0;max-width:880px;margin:0 auto;display:flex}.omcBaG_headerCopy{min-width:0}.omcBaG_headerCopy h1{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;font-size:20px;font-weight:600;line-height:28px}.omcBaG_headerCopy p{color:var(--dsw-alias-label-secondary);margin:3px 0 0;font-size:13px;line-height:20px}.omcBaG_headerActions{flex:none;align-items:center;gap:6px;display:flex}.omcBaG_backRow{max-width:880px;margin:0 auto 8px}.omcBaG_timeline{overscroll-behavior:contain;scrollbar-gutter:stable;min-height:0;padding:12px clamp(18px,3vw,36px) 24px;overflow:hidden auto}.omcBaG_timelineContent{flex-direction:column;min-width:0;max-width:880px;min-height:100%;margin:0 auto;display:flex}.omcBaG_emptySurface{margin:auto;padding:32px 0}.omcBaG_emptySurface .omcBaG_emptyState{text-align:center;justify-items:center}.omcBaG_timelineAction{justify-content:center;padding:2px 0 8px;display:flex}.omcBaG_messageRow{gap:10px;padding:10px 0;display:flex}.omcBaG_messageRow[data-grouped]{padding-top:2px}.omcBaG_messageRow[data-grouped] .omcBaG_messageBody>:first-child,.omcBaG_messageRow[data-grouped] .omcBaG_messageBody>:first-child>:first-child{margin-top:0}.omcBaG_messageIdentity{background:hsl(var(--team-avatar-hue,212) 42% 46%);corner-shape:round;color:#fff;border-radius:50%;flex:0 0 28px;justify-content:center;align-items:center;height:28px;font-size:12px;font-weight:600;display:flex}.omcBaG_messageRow[data-human] .omcBaG_messageIdentity{background:var(--dsw-alias-state-business-primary)}.omcBaG_messageRow[data-grouped] .omcBaG_messageIdentity{visibility:hidden}.omcBaG_messageBody{min-width:0}.omcBaG_nameRow{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.omcBaG_nameRow strong{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:20px}.omcBaG_messageTime{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:20px}.omcBaG_stateCluster{flex:none;align-items:center;gap:6px;display:inline-flex}.omcBaG_statusWord{color:var(--dsw-alias-label-secondary);font-size:11px;line-height:18px}.omcBaG_entryLine{flex-wrap:wrap;align-items:center;gap:8px;max-width:100%;margin:4px 0 0;display:flex}.omcBaG_entryRow{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:2px 0;font-size:12px;line-height:18px;display:inline-flex}.omcBaG_entryRow:hover,.omcBaG_entryRow:focus-visible{color:var(--dsw-alias-label-primary)}.omcBaG_entryRow:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.omcBaG_entryArrow{align-items:center;transition:transform .12s;display:inline-flex}.omcBaG_entryRow:hover .omcBaG_entryArrow,.omcBaG_entryRow:focus-visible .omcBaG_entryArrow{transform:translate(2px)}.omcBaG_messageText{white-space:pre-wrap;word-break:break-word;margin:6px 0;font-size:14px;line-height:22px}.omcBaG_messageClamp{max-height:176px;overflow:hidden;-webkit-mask-image:linear-gradient(#000 72%,#0000 100%);mask-image:linear-gradient(#000 72%,#0000 100%)}.omcBaG_messageExpand{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;width:fit-content;margin-top:4px;padding:0;font-size:12px;line-height:20px;display:block}.omcBaG_messageExpand:hover,.omcBaG_messageExpand:focus-visible{color:var(--dsw-alias-label-primary);text-underline-offset:2px;outline:none;text-decoration:underline}.omcBaG_messageBody .omcBaG_messageMarkdown{font-size:14px;line-height:22px}.omcBaG_messageBody .omcBaG_messageMarkdown>div:first-child{color:var(--dsw-alias-label-primary);font:inherit}.omcBaG_messageBody .omcBaG_messageMarkdown p{margin:6px 0}.omcBaG_messageBody .omcBaG_messageMarkdown :where(ul,ol){margin:6px 0;padding-left:22px}.omcBaG_messageBody .omcBaG_messageMarkdown li+li{margin-top:2px}.omcBaG_messageBody .omcBaG_messageMarkdown strong{font-weight:600}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h1,h2,h3,h4,h5,h6){margin:12px 0 4px}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h1){font-size:17px;line-height:26px}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h2){font-size:16px;line-height:24px}.omcBaG_messageBody .omcBaG_messageMarkdown :where(h3,h4,h5,h6){font-size:15px;line-height:22px}.omcBaG_messageBody .omcBaG_messageMarkdown pre{margin:8px 0;padding:10px 12px;font-size:13px}.omcBaG_messageBody .omcBaG_messageMarkdown blockquote{margin:6px 0}.omcBaG_messageBody .omcBaG_messageMarkdown :where(th,td){padding-block:5px}.omcBaG_emptyState,.omcBaG_loadingState{color:var(--dsw-alias-label-tertiary);margin:0;padding:14px 0;font-size:13px;line-height:20px}.omcBaG_emptyState{gap:3px;display:grid}.omcBaG_emptyState strong{color:var(--dsw-alias-label-secondary);font-weight:500}.omcBaG_emptyState span{font-size:12px}.omcBaG_loadingState{align-items:center;gap:8px;display:flex}.omcBaG_loadingMark{background:var(--dsw-alias-bg-skeleton);corner-shape:round;border-radius:50%;width:8px;height:8px;animation:1.2s ease-in-out infinite omcBaG_pulse}.omcBaG_error{color:var(--dsw-alias-state-error-primary);max-width:880px;margin:0;padding-top:6px;font-size:12px;line-height:18px}.omcBaG_errorState{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:8px;max-width:880px;margin:auto;padding:32px 0;font-size:12px;line-height:18px;display:flex}.omcBaG_welcomeSurface{justify-content:center;align-items:center;min-width:0;height:100%;padding:32px;display:flex}.omcBaG_welcome{text-align:center;max-width:420px}.omcBaG_welcomeEyebrow{color:var(--dsw-alias-label-tertiary);text-transform:uppercase;font-size:12px;line-height:18px}.omcBaG_welcome h1{color:var(--dsw-alias-label-primary);margin:8px 0;font-size:24px;font-weight:600;line-height:32px}.omcBaG_welcome p{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:20px}@keyframes omcBaG_pulse{0%,to{opacity:.35}50%{opacity:1}}@media (width<=600px){.omcBaG_surfaceHeader{padding:12px 12px 10px}.omcBaG_headerRow{flex-direction:column;align-items:stretch;gap:8px}.omcBaG_headerActions{flex-wrap:wrap}.omcBaG_backRow{margin-bottom:6px}.omcBaG_timeline{scrollbar-gutter:auto;padding:8px 12px 16px}.omcBaG_messageRow{padding:8px 0}}@media (prefers-reduced-motion:reduce){.omcBaG_loadingMark{animation:none}.omcBaG_entryArrow{transition:none}.omcBaG_entryRow:hover .omcBaG_entryArrow,.omcBaG_entryRow:focus-visible .omcBaG_entryArrow{transform:none}}.omcBaG_messageRun{margin:2px 0;padding:3px 0}.omcBaG_messageRow[data-grouped]:has([data-thread-entry]){margin-top:3px;padding-top:7px;position:relative}.omcBaG_messageRow[data-grouped]:has([data-thread-entry]):before{background:var(--dsw-alias-border-l2);content:\"\";height:1px;position:absolute;inset:0 0 auto 38px}.omcBaG_runDivider{border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);margin:2px 0 0 38px;padding:5px 0 0;font-size:11px;line-height:16px}.omcBaG_runDivider+.omcBaG_messageRow[data-grouped]:has([data-thread-entry]){margin-top:0}.omcBaG_runDivider+.omcBaG_messageRow[data-grouped]:has([data-thread-entry]):before{content:none}.omcBaG_mention{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);color:var(--dsw-alias-state-business-primary);border-radius:6px;padding:0 4px;font-weight:500;box-shadow:0 1px 2px #00000014}.omcBaG_mentionsRow{gap:4px;width:fit-content;margin-top:3px;font-size:.85em;display:flex}.omcBaG_attachmentStrip{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}.omcBaG_attachmentThumb{cursor:zoom-in;border:0;border-radius:8px;padding:0}.omcBaG_attachmentThumb img{object-fit:cover;border-radius:8px;width:128px;height:96px;display:block}.omcBaG_attachmentThumb:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,currentColor);outline-offset:1px}.omcBaG_confirmBody{margin:0 0 8px}.omcBaG_confirmList{gap:6px;margin:0;padding-left:18px;display:grid}.omcBaG_refLink{color:var(--dsw-alias-state-business-primary);cursor:pointer;font:inherit;text-align:left;text-underline-offset:3px;background:0 0;border:none;border-radius:4px;padding:0;text-decoration:underline}.omcBaG_refLink:hover{text-decoration-thickness:2px}.omcBaG_refLink:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}.omcBaG_attachmentModal{width:min(1100px,92vw)}.omcBaG_attachmentZoom{object-fit:contain;border-radius:12px;max-width:100%;max-height:78vh;margin:0 auto;display:block}.omcBaG_attachmentChip{background:var(--dsw-alias-interactive-bg-hover);border-radius:6px;align-items:baseline;gap:6px;max-width:100%;padding:3px 8px;display:inline-flex}.omcBaG_attachmentChipName{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:17px;overflow:hidden}.omcBaG_attachmentChipSize{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11px;line-height:17px}";
8074
+ const tagId$6 = "@wowyuarm/dsh-agent-team/conversation.module.css";
8075
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
7818
8076
  const tag = document.createElement("style");
7819
8077
  tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
7820
- tag.dataset.pluginCss = tagId$5;
7821
- tag.textContent = css$5;
8078
+ tag.dataset.pluginCss = tagId$6;
8079
+ tag.textContent = css$6;
7822
8080
  document.head.appendChild(tag);
7823
8081
  }
7824
8082
  var conversation_module_css_default = {
@@ -7834,6 +8092,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7834
8092
  "confirmList": "omcBaG_confirmList",
7835
8093
  "emptyState": "omcBaG_emptyState",
7836
8094
  "emptySurface": "omcBaG_emptySurface",
8095
+ "entryArrow": "omcBaG_entryArrow",
8096
+ "entryLine": "omcBaG_entryLine",
8097
+ "entryRow": "omcBaG_entryRow",
7837
8098
  "error": "omcBaG_error",
7838
8099
  "errorState": "omcBaG_errorState",
7839
8100
  "headerActions": "omcBaG_headerActions",
@@ -7856,6 +8117,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7856
8117
  "pulse": "omcBaG_pulse",
7857
8118
  "refLink": "omcBaG_refLink",
7858
8119
  "runDivider": "omcBaG_runDivider",
8120
+ "stateCluster": "omcBaG_stateCluster",
8121
+ "statusWord": "omcBaG_statusWord",
7859
8122
  "surface": "omcBaG_surface",
7860
8123
  "surfaceHeader": "omcBaG_surfaceHeader",
7861
8124
  "timeline": "omcBaG_timeline",
@@ -8211,6 +8474,101 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8211
8474
  });
8212
8475
  }
8213
8476
  //#endregion
8477
+ //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/avatar-stack.module.css.mjs
8478
+ const css$5 = ".aACNsW_stack{flex:none;align-items:center;display:inline-flex}.aACNsW_avatar,.aACNsW_overflow{box-shadow:0 0 0 2px var(--team-mark-ring,var(--dsw-alias-bg-base));corner-shape:round;border-radius:50%;justify-content:center;align-items:center;width:18px;height:18px;font-size:9px;font-weight:600;display:inline-flex}.aACNsW_avatar{background:hsl(var(--team-avatar-hue,212) 42% 46%);color:#fff}.aACNsW_overflow{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.aACNsW_avatar+.aACNsW_avatar,.aACNsW_avatar+.aACNsW_overflow{margin-left:-6px}";
8479
+ const tagId$5 = "@wowyuarm/dsh-agent-team/avatar-stack.module.css";
8480
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
8481
+ const tag = document.createElement("style");
8482
+ tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
8483
+ tag.dataset.pluginCss = tagId$5;
8484
+ tag.textContent = css$5;
8485
+ document.head.appendChild(tag);
8486
+ }
8487
+ var avatar_stack_module_css_default = {
8488
+ "avatar": "aACNsW_avatar",
8489
+ "overflow": "aACNsW_overflow",
8490
+ "stack": "aACNsW_stack"
8491
+ };
8492
+ //#endregion
8493
+ //#region src/client/TeamAvatarStack.tsx
8494
+ /** Distinct owners past this count collapse into one `+N` chip. */
8495
+ const MAX_VISIBLE = 3;
8496
+ /**
8497
+ * The compact "who is on this work" stack: overlapping 18px Member circles in
8498
+ * the shared identity language, capped at three plus a `+N` chip. The circles
8499
+ * are presentational, so the stack is one `role="img"` whose label carries the
8500
+ * whole roster — three anonymous initials would read as noise.
8501
+ */
8502
+ function TeamAvatarStack({ owners, label }) {
8503
+ if (owners.length === 0) return null;
8504
+ const shown = owners.slice(0, MAX_VISIBLE);
8505
+ const overflow = owners.length - shown.length;
8506
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8507
+ className: avatar_stack_module_css_default.stack,
8508
+ role: "img",
8509
+ "aria-label": label,
8510
+ children: [shown.map((owner) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8511
+ className: avatar_stack_module_css_default.avatar,
8512
+ style: { "--team-avatar-hue": memberHue(owner.memberId) },
8513
+ children: initial(owner.name)
8514
+ }, owner.memberId)), overflow > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8515
+ className: avatar_stack_module_css_default.overflow,
8516
+ children: `+${overflow}`
8517
+ })]
8518
+ });
8519
+ }
8520
+ /** First visible character of a handle — and of a raw Member id when that is all there is. */
8521
+ function initial(name) {
8522
+ return name.replace(/^@/, "").replace(/^member:/, "").slice(0, 1).toUpperCase();
8523
+ }
8524
+ //#endregion
8525
+ //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/countBadge.module.css.mjs
8526
+ const css$4 = ".LBWXOW_badge{background:var(--dsw-alias-state-business-primary);box-sizing:border-box;color:var(--dsw-alias-label-primary-foreground);corner-shape:round;font-variant-numeric:tabular-nums;border-radius:999px;flex:none;justify-content:center;align-items:center;min-width:18px;height:18px;padding:0 5px;font-size:11px;font-weight:600;line-height:18px;display:inline-flex}.LBWXOW_hairline{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0;padding:0 4px}";
8527
+ const tagId$4 = "@wowyuarm/dsh-agent-team/countBadge.module.css";
8528
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
8529
+ const tag = document.createElement("style");
8530
+ tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
8531
+ tag.dataset.pluginCss = tagId$4;
8532
+ tag.textContent = css$4;
8533
+ document.head.appendChild(tag);
8534
+ }
8535
+ var countBadge_module_css_default = {
8536
+ "badge": "LBWXOW_badge",
8537
+ "hairline": "LBWXOW_hairline"
8538
+ };
8539
+ //#endregion
8540
+ //#region src/client/TeamCountBadge.tsx
8541
+ /** Every count the Human reads is capped at this, so one wide number never widens the capsule. */
8542
+ const COUNT_CAP = 99;
8543
+ /**
8544
+ * The one count capsule. The Human Inbox entry, the Channel feed's Thread
8545
+ * entry, and the Inbox queue row all answer the same question — how much is
8546
+ * waiting here — so they wear the same box rather than one hand-written copy
8547
+ * of the same declarations per surface. Three copies is how the feed's digit
8548
+ * ended up on a different line box from the other two.
8549
+ *
8550
+ * Zero is the absence of a count rather than a capsule reading zero, which is
8551
+ * the rule every caller wants and therefore the component's own.
8552
+ */
8553
+ function TeamCountBadge({ count, tone = "solid", label, className }) {
8554
+ if (count <= 0) return null;
8555
+ const text = count > COUNT_CAP ? `${COUNT_CAP}+` : String(count);
8556
+ const classes = `${countBadge_module_css_default.badge}${tone === "hairline" ? ` ${countBadge_module_css_default.hairline}` : ""}${className === void 0 ? "" : ` ${className}`}`;
8557
+ return label === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8558
+ className: classes,
8559
+ "data-team-count-badge": tone,
8560
+ "aria-hidden": "true",
8561
+ children: text
8562
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8563
+ className: classes,
8564
+ "data-team-count-badge": tone,
8565
+ role: "img",
8566
+ "aria-label": label,
8567
+ title: label,
8568
+ children: text
8569
+ });
8570
+ }
8571
+ //#endregion
8214
8572
  //#region src/client/TeamRunDivider.tsx
8215
8573
  /**
8216
8574
  * Explicit boundary between two same-sender Messages of one run separated by
@@ -8390,39 +8748,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8390
8748
  }
8391
8749
  //#endregion
8392
8750
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/channel.module.css.mjs
8393
- const css$4 = ".MYaRJa_headerMeta{color:var(--dsw-alias-label-tertiary);flex-wrap:wrap;align-items:center;gap:6px;margin-top:7px;font-size:12px;line-height:18px;display:flex}.MYaRJa_headerMeta span+span:before{content:\"·\";margin-right:6px}.MYaRJa_taskFooter{border:1px solid var(--dsw-alias-border-l2);corner-shape:round;color:var(--dsw-alias-label-secondary);cursor:pointer;text-align:left;background:0 0;border-radius:999px;align-items:center;gap:6px;max-width:100%;margin:6px 0 0;padding:2px 10px;transition:background-color .12s,border-color .12s,color .12s;display:inline-flex}.MYaRJa_taskFooter:hover,.MYaRJa_taskFooter:focus-visible{background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary)}.MYaRJa_taskFooter:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.MYaRJa_taskNumber{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600;line-height:18px}.MYaRJa_taskStatus,.MYaRJa_taskCount{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px}.MYaRJa_taskDot{flex:none;align-items:center;width:8px;display:inline-flex}.MYaRJa_taskArrow{color:var(--dsw-alias-label-tertiary);align-items:center;transition:transform .12s;display:inline-flex}.MYaRJa_taskFooter:hover .MYaRJa_taskArrow,.MYaRJa_taskFooter:focus-visible .MYaRJa_taskArrow{transform:translate(2px)}.MYaRJa_memberList{gap:3px;display:grid}.MYaRJa_memberRow{border-radius:6px;grid-template-columns:14px minmax(0,1fr) auto;align-items:center;gap:0 8px;min-height:40px;padding:4px 6px;display:grid}.MYaRJa_memberRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.MYaRJa_memberCopy{min-width:0;display:grid}.MYaRJa_memberCopy strong{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;line-height:18px;overflow:hidden}.MYaRJa_memberCopy small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:14px;overflow:hidden}.MYaRJa_memberAction{min-width:60px}.MYaRJa_memberError{color:var(--dsw-alias-state-error-primary);grid-column:2/-1;margin:2px 0;font-size:11px;line-height:16px}.MYaRJa_modalBody{max-height:min(65vh,520px);overflow-y:auto}@media (width<=600px){.MYaRJa_memberRow{grid-template-columns:14px minmax(0,1fr)}.MYaRJa_memberAction{grid-column:2;justify-self:start;margin-top:3px}}@media (prefers-reduced-motion:reduce){.MYaRJa_taskFooter,.MYaRJa_taskArrow{transition:none}.MYaRJa_taskFooter:hover .MYaRJa_taskArrow,.MYaRJa_taskFooter:focus-visible .MYaRJa_taskArrow{transform:none}}";
8394
- const tagId$4 = "@wowyuarm/dsh-agent-team/channel.module.css";
8395
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
8751
+ const css$3 = ".MYaRJa_headerMeta{color:var(--dsw-alias-label-tertiary);flex-wrap:wrap;align-items:center;gap:6px;margin-top:7px;font-size:12px;line-height:18px;display:flex}.MYaRJa_headerMeta span+span:before{content:\"·\";margin-right:6px}.MYaRJa_memberList{gap:2px;margin:0 -6px;display:grid}.MYaRJa_modalBody{max-height:min(65vh,520px);overflow-y:auto}";
8752
+ const tagId$3 = "@wowyuarm/dsh-agent-team/channel.module.css";
8753
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
8396
8754
  const tag = document.createElement("style");
8397
8755
  tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
8398
- tag.dataset.pluginCss = tagId$4;
8399
- tag.textContent = css$4;
8756
+ tag.dataset.pluginCss = tagId$3;
8757
+ tag.textContent = css$3;
8400
8758
  document.head.appendChild(tag);
8401
8759
  }
8402
8760
  var channel_module_css_default = {
8403
8761
  "headerMeta": "MYaRJa_headerMeta",
8404
- "memberAction": "MYaRJa_memberAction",
8405
- "memberCopy": "MYaRJa_memberCopy",
8406
- "memberError": "MYaRJa_memberError",
8407
8762
  "memberList": "MYaRJa_memberList",
8408
- "memberRow": "MYaRJa_memberRow",
8409
- "modalBody": "MYaRJa_modalBody",
8410
- "taskArrow": "MYaRJa_taskArrow",
8411
- "taskCount": "MYaRJa_taskCount",
8412
- "taskDot": "MYaRJa_taskDot",
8413
- "taskFooter": "MYaRJa_taskFooter",
8414
- "taskNumber": "MYaRJa_taskNumber",
8415
- "taskStatus": "MYaRJa_taskStatus"
8763
+ "modalBody": "MYaRJa_modalBody"
8416
8764
  };
8417
8765
  //#endregion
8418
8766
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/thread.module.css.mjs
8419
- const css$3 = ".-Qiwua_titleLine{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.-Qiwua_titleLine h1{margin:0}.-Qiwua_workSection{border-top:1px solid var(--dsw-alias-border-l2);max-width:880px;margin:12px auto 0;padding-top:8px}.-Qiwua_riskSection{border-top:1px solid var(--dsw-alias-border-l2);max-width:880px;margin:12px auto 0;padding-top:10px}.-Qiwua_riskSection h2{color:var(--dsw-alias-state-error-primary);margin:0 0 5px;font-size:12px;font-weight:600;line-height:18px}.-Qiwua_riskRow{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;margin:3px 0;font-size:12px;line-height:18px;display:flex}.-Qiwua_claimList{gap:4px;padding:4px 0 2px 22px;display:grid}.-Qiwua_claimRow{border-radius:6px;grid-template-columns:14px minmax(96px,auto) minmax(0,1fr) auto auto;align-items:center;gap:4px 8px;min-height:36px;padding:4px 6px;display:grid}.-Qiwua_claimRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.-Qiwua_claimOwner{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:500;line-height:18px;overflow:hidden}.-Qiwua_claimDirection{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;min-width:0;font-size:12px;line-height:18px}.-Qiwua_claimState{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11px;line-height:18px}.-Qiwua_emptyClaims{color:var(--dsw-alias-label-tertiary);margin:0;padding:5px 6px;font-size:11px;line-height:18px}.-Qiwua_activityRow{color:var(--dsw-alias-label-tertiary);text-align:center;justify-content:center;align-items:center;gap:8px;max-width:100%;margin:4px auto;padding:5px 12px;font-size:11px;line-height:18px;display:flex}.-Qiwua_activityText{overflow-wrap:anywhere;min-width:0}.-Qiwua_activityMark{background:var(--dsw-alias-border-l3);corner-shape:round;border-radius:50%;flex:0 0 5px;width:5px;height:5px}.-Qiwua_activityRow:has(+.-Qiwua_activityRow),.-Qiwua_activityRow+.-Qiwua_activityRow{text-align:left;justify-content:flex-start;padding-left:38px}.-Qiwua_historySection{border-bottom:1px solid var(--dsw-alias-border-l2);max-width:100%;margin:0 auto 12px;padding-bottom:10px}.-Qiwua_historySection h2{color:var(--dsw-alias-label-tertiary);letter-spacing:.02em;text-transform:uppercase;margin:0 0 4px;font-size:11px;font-weight:600;line-height:16px}.-Qiwua_publicSection{min-width:0}.-Qiwua_unreadBoundary{color:var(--dsw-alias-label-tertiary);align-items:center;gap:10px;margin:10px 0 6px;font-size:11px;line-height:16px;display:flex}.-Qiwua_unreadBoundary:before,.-Qiwua_unreadBoundary:after{background:var(--dsw-alias-border-l3);content:\"\";flex:1;height:1px}.-Qiwua_unreadBoundary span{flex:none}.-Qiwua_daySeparator{color:var(--dsw-alias-label-tertiary);letter-spacing:.02em;align-items:center;gap:10px;margin:12px 0 4px;font-size:11px;line-height:16px;display:flex}.-Qiwua_daySeparator:before,.-Qiwua_daySeparator:after{background:var(--dsw-alias-border-l2);content:\"\";flex:1;height:1px}.-Qiwua_daySeparator span{flex:none}.-Qiwua_newUpdates{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2-darkmode-thin);corner-shape:round;box-shadow:var(--dsw-shadow-lv2);z-index:2;border-radius:999px;justify-content:center;align-items:center;width:fit-content;margin:8px auto;padding:4px 12px;font-size:12px;line-height:18px;display:flex;position:sticky;bottom:8px}.-Qiwua_newUpdatesJump{color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;line-height:inherit;background:0 0;border:0;padding:0}.-Qiwua_newUpdatesJump:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px;border-radius:6px}.-Qiwua_taskTitle{color:var(--dsw-alias-label-secondary);-webkit-line-clamp:2;overflow-wrap:anywhere;-webkit-box-orient:vertical;margin:2px 0 0;font-size:13px;line-height:20px;display:-webkit-box;overflow:hidden}.-Qiwua_closedBar{flex-direction:column;align-items:center;display:flex}.-Qiwua_closedNotice{color:var(--dsw-alias-label-tertiary);flex-wrap:wrap;justify-content:center;align-items:center;gap:12px;padding:10px 16px 14px;font-size:13px;line-height:20px;display:flex}@media (width<=600px){.-Qiwua_claimRow{grid-template-columns:14px minmax(0,1fr) auto;align-items:start}.-Qiwua_claimState{grid-area:1/3;justify-self:end}.-Qiwua_claimDirection{grid-column:2/-1}.-Qiwua_activityRow{padding-inline:0}.-Qiwua_newUpdates{max-width:calc(100% - 16px)}}";
8420
- const tagId$3 = "@wowyuarm/dsh-agent-team/thread.module.css";
8421
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
8767
+ const css$2 = ".-Qiwua_titleLine{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.-Qiwua_titleLine h1{margin:0}.-Qiwua_workSection{border-top:1px solid var(--dsw-alias-border-l2);max-width:880px;margin:12px auto 0;padding-top:8px}.-Qiwua_riskSection{border-top:1px solid var(--dsw-alias-border-l2);max-width:880px;margin:12px auto 0;padding-top:10px}.-Qiwua_riskSection h2{color:var(--dsw-alias-state-error-primary);margin:0 0 5px;font-size:12px;font-weight:600;line-height:18px}.-Qiwua_riskRow{color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;margin:3px 0;font-size:12px;line-height:18px;display:flex}.-Qiwua_claimList{gap:4px;padding:4px 0 2px 22px;display:grid}.-Qiwua_claimRow{border-radius:6px;grid-template-columns:14px minmax(96px,auto) minmax(0,1fr) auto auto;align-items:center;gap:4px 8px;min-height:36px;padding:4px 6px;display:grid}.-Qiwua_claimRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.-Qiwua_claimOwner{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:500;line-height:18px;overflow:hidden}.-Qiwua_claimDirection{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;min-width:0;font-size:12px;line-height:18px}.-Qiwua_claimState{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:11px;line-height:18px}.-Qiwua_emptyClaims{color:var(--dsw-alias-label-tertiary);margin:0;padding:5px 6px;font-size:11px;line-height:18px}.-Qiwua_activityRow{color:var(--dsw-alias-label-tertiary);text-align:center;justify-content:center;align-items:center;gap:8px;max-width:100%;margin:4px auto;padding:5px 12px;font-size:11px;line-height:18px;display:flex}.-Qiwua_activityText{overflow-wrap:anywhere;min-width:0}.-Qiwua_activityMark{background:var(--dsw-alias-border-l3);corner-shape:round;border-radius:50%;flex:0 0 5px;width:5px;height:5px}.-Qiwua_activityRow:has(+.-Qiwua_activityRow),.-Qiwua_activityRow+.-Qiwua_activityRow{text-align:left;justify-content:flex-start;padding-left:38px}.-Qiwua_historySection{border-bottom:1px solid var(--dsw-alias-border-l2);max-width:100%;margin:0 auto 12px;padding-bottom:10px}.-Qiwua_historySection h2{color:var(--dsw-alias-label-tertiary);letter-spacing:.02em;text-transform:uppercase;margin:0 0 4px;font-size:11px;font-weight:600;line-height:16px}.-Qiwua_publicSection{min-width:0}.-Qiwua_unreadBoundary{color:var(--dsw-alias-label-tertiary);align-items:center;gap:10px;margin:10px 0 6px;font-size:11px;line-height:16px;display:flex}.-Qiwua_unreadBoundary:before,.-Qiwua_unreadBoundary:after{background:var(--dsw-alias-border-l3);content:\"\";flex:1;height:1px}.-Qiwua_unreadBoundary span{flex:none}.-Qiwua_daySeparator{color:var(--dsw-alias-label-tertiary);letter-spacing:.02em;align-items:center;gap:10px;margin:12px 0 4px;font-size:11px;line-height:16px;display:flex}.-Qiwua_daySeparator:before,.-Qiwua_daySeparator:after{background:var(--dsw-alias-border-l2);content:\"\";flex:1;height:1px}.-Qiwua_daySeparator span{flex:none}.-Qiwua_newUpdates{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2-darkmode-thin);corner-shape:round;box-shadow:var(--dsw-shadow-lv2);z-index:2;border-radius:999px;justify-content:center;align-items:center;width:fit-content;margin:8px auto;padding:4px 12px;font-size:12px;line-height:18px;display:flex;position:sticky;bottom:8px}.-Qiwua_newUpdatesJump{color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;line-height:inherit;background:0 0;border:0;padding:0}.-Qiwua_newUpdatesJump:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px;border-radius:6px}.-Qiwua_taskTitle{color:var(--dsw-alias-label-secondary);-webkit-line-clamp:2;overflow-wrap:anywhere;-webkit-box-orient:vertical;margin:2px 0 0;font-size:13px;line-height:20px;display:-webkit-box;overflow:hidden}.-Qiwua_closedBar{flex-direction:column;align-items:center;display:flex}.-Qiwua_closedNotice{color:var(--dsw-alias-label-tertiary);flex-wrap:wrap;justify-content:center;align-items:center;gap:12px;padding:10px 16px 14px;font-size:13px;line-height:20px;display:flex}@media (width<=600px){.-Qiwua_claimRow{grid-template-columns:14px minmax(0,1fr) auto;align-items:start}.-Qiwua_claimState{grid-area:1/3;justify-self:end}.-Qiwua_claimDirection{grid-column:2/-1}.-Qiwua_activityRow{padding-inline:0}.-Qiwua_newUpdates{max-width:calc(100% - 16px)}}";
8768
+ const tagId$2 = "@wowyuarm/dsh-agent-team/thread.module.css";
8769
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
8422
8770
  const tag = document.createElement("style");
8423
8771
  tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
8424
- tag.dataset.pluginCss = tagId$3;
8425
- tag.textContent = css$3;
8772
+ tag.dataset.pluginCss = tagId$2;
8773
+ tag.textContent = css$2;
8426
8774
  document.head.appendChild(tag);
8427
8775
  }
8428
8776
  var thread_module_css_default = {
@@ -8452,12 +8800,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8452
8800
  //#endregion
8453
8801
  //#region src/client/TeamChannelPage.tsx
8454
8802
  /**
8455
- * Merge the freshest top-level window over what the reader already has:
8456
- * a change-driven refresh must not discard older messages loaded earlier.
8803
+ * Merge the freshest top-level window over what the reader already has. The
8804
+ * fresh window is authoritative for every Message it covers — a change wake
8805
+ * must move that row's live Task state, newest instant, and unread with it —
8806
+ * while older Messages loaded earlier are retained instead of discarded.
8457
8807
  */
8458
8808
  function mergeChannelView(current, fresh) {
8459
- const known = new Set(current.items.map((item) => item.message.messageRef));
8460
- const items = [...fresh.items.filter((item) => !known.has(item.message.messageRef)), ...current.items].sort((left, right) => left.message.sequence - right.message.sequence);
8809
+ const freshRefs = new Set(fresh.items.map((item) => item.message.messageRef));
8810
+ const items = [...current.items.filter((item) => !freshRefs.has(item.message.messageRef)), ...fresh.items].sort((left, right) => left.message.sequence - right.message.sequence);
8461
8811
  return {
8462
8812
  ...fresh,
8463
8813
  items,
@@ -8465,9 +8815,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8465
8815
  hasMore: fresh.hasMore || current.cursor < fresh.cursor
8466
8816
  };
8467
8817
  }
8468
- function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, selectChannel, backToChannels, resolveTaskRefs, t }) {
8818
+ /**
8819
+ * The people the Channel feed shows on one Task: owners of its live Claims, in
8820
+ * claim order, deduped. Claim state is a Host fact, not decoration — a released
8821
+ * Claim is no longer work — and only a Task still in progress or review has
8822
+ * any, because a done or closed Task keeps its Claims as history that the state
8823
+ * word already tells the reader.
8824
+ */
8825
+ function liveOwnersByTask(items, claims) {
8826
+ const live = new Set(items.flatMap((item) => item.task === void 0 ? [] : [item.task]).filter((task) => task.status === "in_progress" || task.status === "in_review").map((task) => task.taskRef));
8827
+ const owners = /* @__PURE__ */ new Map();
8828
+ for (const claim of claims) {
8829
+ if (!live.has(claim.taskRef) || claim.state === "released") continue;
8830
+ const known = owners.get(claim.taskRef);
8831
+ if (known === void 0) owners.set(claim.taskRef, [claim.owner]);
8832
+ else if (!known.includes(claim.owner)) known.push(claim.owner);
8833
+ }
8834
+ return owners;
8835
+ }
8836
+ /**
8837
+ * The newest fact instant, or nothing when the entry's own Message is still the
8838
+ * newest fact on its Thread. That difference is exactly what "has follow-up
8839
+ * activity" means, and the Host projects both instants from the ledger.
8840
+ */
8841
+ function followUpAt(item) {
8842
+ const lastActivityAt = item.lastActivityAt;
8843
+ return lastActivityAt === void 0 || lastActivityAt === item.message.occurredAt ? void 0 : lastActivityAt;
8844
+ }
8845
+ /** Host unread per Thread, keyed for the feed's rows: zero unread is the absence of a badge, not a row. */
8846
+ function unreadCounts(inbox) {
8847
+ return new Map(inbox.items.filter((item) => item.unreadCount > 0).map((item) => [item.thread.threadRef, item.unreadCount]));
8848
+ }
8849
+ function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, loadInbox, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, selectChannel, backToChannels, resolveTaskRefs, t }) {
8469
8850
  const [view, setView] = (0, react.useState)();
8470
8851
  const [members, setMembers] = (0, react.useState)([]);
8852
+ const [unreadByThread, setUnreadByThread] = (0, react.useState)(/* @__PURE__ */ new Map());
8471
8853
  const [error, setError] = (0, react.useState)();
8472
8854
  const [pendingFiles, setPendingFiles] = (0, react.useState)([]);
8473
8855
  const [statusMessage, setStatusMessage] = (0, react.useState)();
@@ -8525,7 +8907,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8525
8907
  const channelMembers = members.filter((status) => channelMemberIds.has(status.member.memberId) && status.member.state !== "inactive" && status.member.state !== "archived");
8526
8908
  const onlineCount = channelMembers.filter((status) => status.presence === "available" || status.presence === "working").length;
8527
8909
  const messageSender = (item) => item.message.sender;
8528
- const mentionHandlesMap = new Map(members.map((status) => [status.member.memberId, status.member.handle.replace(/^@/, "")]));
8910
+ const handleByMember = new Map(members.map((status) => [status.member.memberId, status.member.handle.replace(/^@/, "")]));
8911
+ const ownersByTask = liveOwnersByTask(view?.items ?? [], view?.claims ?? []);
8529
8912
  const refresh = async (clearError = false) => {
8530
8913
  if (!mountedRef.current) return false;
8531
8914
  const sequence = refreshSequenceRef.current + 1;
@@ -8536,14 +8919,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8536
8919
  setStatusMessage(void 0);
8537
8920
  }
8538
8921
  try {
8539
- const [loaded, loadedMembers] = await Promise.all([loadChannels({
8540
- workspaceId,
8541
- channelRef,
8542
- direction: "before",
8543
- topLevelOnly: true,
8544
- includeActivities: false,
8545
- limit: 20
8546
- }), loadMembers({ workspaceId })]);
8922
+ const [loaded, loadedMembers, loadedInbox] = await Promise.all([
8923
+ loadChannels({
8924
+ workspaceId,
8925
+ channelRef,
8926
+ direction: "before",
8927
+ topLevelOnly: true,
8928
+ includeActivities: false,
8929
+ limit: 20
8930
+ }),
8931
+ loadMembers({ workspaceId }),
8932
+ loadInbox({
8933
+ workspaceId,
8934
+ limit: 100
8935
+ })
8936
+ ]);
8547
8937
  if (!mountedRef.current || sequence !== refreshSequenceRef.current) return false;
8548
8938
  if (loaded.ok) {
8549
8939
  setView((current) => current === void 0 ? loaded.value : mergeChannelView(current, loaded.value));
@@ -8551,7 +8941,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8551
8941
  } else setError(loaded.error.message);
8552
8942
  if (loadedMembers.ok) setMembers(loadedMembers.value);
8553
8943
  else setError(loadedMembers.error.message);
8554
- return loaded.ok && loadedMembers.ok;
8944
+ if (loadedInbox.ok) setUnreadByThread(unreadCounts(loadedInbox.value));
8945
+ else {
8946
+ setUnreadByThread(/* @__PURE__ */ new Map());
8947
+ setError(loadedInbox.error.message);
8948
+ }
8949
+ return loaded.ok && loadedMembers.ok && loadedInbox.ok;
8555
8950
  } catch (cause) {
8556
8951
  if (mountedRef.current && sequence === refreshSequenceRef.current) setError(cause instanceof Error ? cause.message : String(cause));
8557
8952
  return false;
@@ -8766,39 +9161,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8766
9161
  children: members.filter((status) => status.member.state !== "inactive" && status.member.state !== "archived").map((status) => {
8767
9162
  const joined = channelMemberIds.has(status.member.memberId);
8768
9163
  const rowPending = membership.pending.has(status.member.memberId);
8769
- const disabled = rowPending || !joined && status.presence === "unavailable";
9164
+ const disabled = rowPending || !joined && status.availability !== "active";
8770
9165
  const rowError = membership.errors.get(status.member.memberId);
8771
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8772
- className: channel_module_css_default.memberRow,
8773
- children: [
8774
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamPresenceDot, {
8775
- status,
8776
- t
8777
- }),
8778
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8779
- className: channel_module_css_default.memberCopy,
8780
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: ["@", status.member.handle] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
8781
- }),
8782
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8783
- className: channel_module_css_default.memberAction,
8784
- size: "sm",
8785
- disabled,
8786
- onClick: () => {
8787
- membership.change({
8788
- workspaceId,
8789
- channelRef,
8790
- memberId: status.member.memberId,
8791
- joined
8792
- });
8793
- },
8794
- children: rowPending ? t("membershipUpdating") : joined ? t("removeFromChannel") : t("addToChannel")
8795
- }),
8796
- rowError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8797
- className: channel_module_css_default.memberError,
8798
- role: "alert",
8799
- children: rowError
8800
- })
8801
- ]
9166
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberRow, {
9167
+ status,
9168
+ action: {
9169
+ label: rowPending ? t("membershipUpdating") : joined ? t("removeFromChannel") : t("addToChannel"),
9170
+ disabled,
9171
+ onSelect: () => {
9172
+ membership.change({
9173
+ workspaceId,
9174
+ channelRef,
9175
+ memberId: status.member.memberId,
9176
+ joined
9177
+ });
9178
+ }
9179
+ },
9180
+ ...rowError === void 0 ? {} : { error: rowError },
9181
+ t
8802
9182
  }, status.member.memberId);
8803
9183
  })
8804
9184
  })
@@ -8868,7 +9248,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8868
9248
  const human = item.message.sender === view.humanMemberId;
8869
9249
  const sender = human ? t("human") : senderStatus?.member.handle ?? item.message.sender;
8870
9250
  const turnGap = isRunGap(index > 0 ? block.items[index - 1].message.occurredAt : void 0, item.message.occurredAt);
8871
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [turnGap && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamRunDivider, { occurredAt: item.message.occurredAt }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TeamMessage, {
9251
+ const task = item.task;
9252
+ const owners = task === void 0 ? [] : ownersByTask.get(task.taskRef) ?? [];
9253
+ const unread = unreadByThread.get(item.thread.threadRef) ?? 0;
9254
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [turnGap && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamRunDivider, { occurredAt: item.message.occurredAt }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMessage, {
8872
9255
  senderName: sender,
8873
9256
  memberId: item.message.sender,
8874
9257
  human,
@@ -8877,68 +9260,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8877
9260
  loadAttachment: getAttachment,
8878
9261
  t,
8879
9262
  occurredAt: item.message.occurredAt,
8880
- mentionNames: mentionNamesOf(item.mentions, mentionHandlesMap),
9263
+ mentionNames: mentionNamesOf(item.mentions, handleByMember),
8881
9264
  onOpenRef: openRef,
8882
9265
  onResolveTaskRefs: lookupTaskRefs,
8883
9266
  grouped: index > 0,
8884
9267
  showGroupedTime: item.message.topLevel === true && !turnGap,
8885
9268
  ...senderStatus === void 0 ? {} : { senderTitle: senderStatus.member.description },
8886
- children: [item.message.topLevel && item.task !== void 0 && item.taskNumber !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8887
- type: "button",
8888
- className: channel_module_css_default.taskFooter,
8889
- "aria-label": t("openTask", { number: item.taskNumber }),
8890
- onClick: () => {
8891
- selectThread(item.thread.threadRef, channelRef, item.task?.taskRef, item.taskNumber);
8892
- },
8893
- children: [
8894
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8895
- className: channel_module_css_default.taskDot,
8896
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamStateDot, {
8897
- size: 8,
8898
- state: taskStatusDot(item.task.status)
8899
- })
8900
- }),
8901
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8902
- className: channel_module_css_default.taskNumber,
8903
- children: t("taskLabel", { number: item.taskNumber })
8904
- }),
8905
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8906
- className: channel_module_css_default.taskStatus,
8907
- children: formatTaskStatus(item.task.status, t)
8908
- }),
8909
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8910
- className: channel_module_css_default.taskCount,
8911
- children: t("taskMessageCount", { count: item.messageCount })
8912
- }),
8913
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8914
- className: channel_module_css_default.taskArrow,
8915
- "aria-hidden": "true",
8916
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, { size: 12 })
8917
- })
8918
- ]
8919
- }), item.message.topLevel && item.task === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8920
- type: "button",
8921
- className: channel_module_css_default.taskFooter,
8922
- "aria-label": t("openThread"),
8923
- onClick: () => {
8924
- selectThread(item.thread.threadRef, channelRef);
8925
- },
8926
- children: [
8927
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8928
- className: channel_module_css_default.taskNumber,
8929
- children: t("threadLabel")
8930
- }),
8931
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8932
- className: channel_module_css_default.taskCount,
8933
- children: t("taskMessageCount", { count: item.messageCount })
8934
- }),
8935
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8936
- className: channel_module_css_default.taskArrow,
8937
- "aria-hidden": "true",
8938
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, { size: 12 })
8939
- })
8940
- ]
8941
- })]
9269
+ children: item.message.topLevel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadEntryRow, {
9270
+ item,
9271
+ owners: owners.map((memberId) => ({
9272
+ memberId,
9273
+ name: handleByMember.get(memberId) ?? memberId
9274
+ })),
9275
+ unread,
9276
+ t,
9277
+ onOpen: () => {
9278
+ selectThread(item.thread.threadRef, channelRef, task?.taskRef, item.taskNumber);
9279
+ }
9280
+ })
8942
9281
  })] }, item.message.messageRef);
8943
9282
  })
8944
9283
  }, `run-${block.items[0].message.messageRef}`))
@@ -8965,31 +9304,116 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8965
9304
  ]
8966
9305
  });
8967
9306
  }
9307
+ /**
9308
+ * One entry's state: who is on the work, where it stands, and how much of it
9309
+ * needs the reader. It leads the entry's own line rather than trailing the
9310
+ * identity line, so a reader meets it where they are already reading instead of
9311
+ * crossing the column for it — and the same placement holds whether this
9312
+ * Message opened its run or continued one, where an identity line would have
9313
+ * carried nothing else. The unread capsule is the only member a taskless
9314
+ * discussion can carry: it needs no Task.
9315
+ */
9316
+ function ThreadStateCluster({ task, owners, unread, t }) {
9317
+ if (task === void 0 && unread === 0) return null;
9318
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9319
+ className: conversation_module_css_default.stateCluster,
9320
+ children: [
9321
+ task !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamAvatarStack, {
9322
+ owners,
9323
+ label: t("claimers", { names: owners.map((owner) => `@${owner.name}`).join(", ") })
9324
+ }),
9325
+ task !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamStateDot, {
9326
+ size: 8,
9327
+ state: taskStatusDot(task.status)
9328
+ }),
9329
+ task !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9330
+ className: conversation_module_css_default.statusWord,
9331
+ children: formatTaskStatus(task.status, t)
9332
+ }),
9333
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamCountBadge, { count: unread })
9334
+ ]
9335
+ });
9336
+ }
9337
+ /**
9338
+ * The gate under one top-level Message: the single row that opens its Thread,
9339
+ * and the one line that says what stands there. State leads it, then what the
9340
+ * entry is: a Task entry keeps its number so the status word never floats free
9341
+ * of the Task it describes, follow-up activity adds when the work last moved,
9342
+ * and an unanswered Thread says only 回复. The instant uses the Inbox's own
9343
+ * 今天/昨天 form with the precise local time on the control's title, and an
9344
+ * unread Thread says so in the control's label rather than only in pixels.
9345
+ */
9346
+ function ThreadEntryRow({ item, owners, unread, t, onOpen }) {
9347
+ const taskNumber = item.taskNumber;
9348
+ const followUp = followUpAt(item);
9349
+ const label = taskNumber !== void 0 ? t("taskLabel", { number: taskNumber }) : followUp === void 0 ? t("replyAction") : t("threadLabel");
9350
+ const text = followUp === void 0 ? label : `${label} · ${t("recentActivity", { time: formatInboxTime(followUp, t) })}`;
9351
+ const openLabel = taskNumber === void 0 ? unread > 0 ? t("openThreadUnread", { count: unread }) : t("openThread") : unread > 0 ? t("openTaskUnread", {
9352
+ number: taskNumber,
9353
+ count: unread
9354
+ }) : t("openTask", { number: taskNumber });
9355
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9356
+ className: conversation_module_css_default.entryLine,
9357
+ "data-thread-entry": "",
9358
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadStateCluster, {
9359
+ task: item.task,
9360
+ owners,
9361
+ unread,
9362
+ t
9363
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
9364
+ type: "button",
9365
+ className: conversation_module_css_default.entryRow,
9366
+ "aria-label": openLabel,
9367
+ ...followUp === void 0 ? {} : { title: formatAbsoluteTime(followUp) },
9368
+ onClick: onOpen,
9369
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9370
+ className: conversation_module_css_default.entryArrow,
9371
+ "aria-hidden": "true",
9372
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, { size: 12 })
9373
+ })]
9374
+ })]
9375
+ });
9376
+ }
8968
9377
  //#endregion
8969
9378
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/inbox.module.css.mjs
8970
- const css$2 = ".s2ibaa_list{flex-direction:column;gap:2px;display:flex}.s2ibaa_headerMeta{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.s2ibaa_row{color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:8px;grid-template-columns:minmax(0,1fr) auto;align-items:baseline;gap:2px 12px;width:100%;padding:9px 8px;display:grid}.s2ibaa_row:hover,.s2ibaa_row:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}.s2ibaa_row:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.s2ibaa_rowCrumb{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;grid-column:1;min-width:0;font-size:12px;line-height:18px;overflow:hidden}.s2ibaa_rowChannel{color:var(--dsw-alias-label-secondary);font-weight:600}.s2ibaa_rowTask{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);white-space:nowrap;border-radius:6px;margin-left:8px;padding:0 5px;font-size:11px;font-weight:600;line-height:15px}.s2ibaa_rowPreview{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;grid-column:1/-1;min-width:0;font-size:14px;line-height:22px;overflow:hidden}.s2ibaa_rowTime{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;grid-area:1/2;font-size:11px;line-height:18px}";
8971
- const tagId$2 = "@wowyuarm/dsh-agent-team/inbox.module.css";
8972
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
9379
+ const css$1 = ".s2ibaa_list{flex-direction:column;gap:2px;display:flex}.s2ibaa_headerMeta{font-variant-numeric:tabular-nums;flex-wrap:wrap;align-items:baseline;gap:0 10px;display:flex;overflow:hidden}.s2ibaa_headerUnread{color:var(--dsw-alias-label-primary);font-weight:600}.s2ibaa_row{color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:8px;grid-template-columns:max-content minmax(0,1fr);align-items:baseline;gap:1px 8px;width:100%;padding:8px;display:grid}.s2ibaa_row:hover,.s2ibaa_row:focus-visible{--team-mark-ring:var(--dsw-alias-interactive-bg-hover);background:var(--dsw-alias-interactive-bg-hover)}.s2ibaa_row:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.s2ibaa_rowActor{grid-area:1/1;display:flex}.s2ibaa_rowLine{grid-area:1/2;align-items:baseline;gap:2px 8px;min-width:0;display:flex}.s2ibaa_rowCrumb{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;font-size:13px;line-height:20px;overflow:hidden}.s2ibaa_rowWorkspace{color:var(--dsw-alias-label-tertiary);font-size:12px}.s2ibaa_rowChannel{color:var(--dsw-alias-label-primary);font-weight:600}.s2ibaa_rowTask{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);white-space:nowrap;border-radius:6px;flex:none;margin-left:3px;padding:0 5px;font-size:11px;font-weight:600;line-height:15px}.s2ibaa_rowTime{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;font-size:11px;line-height:18px}.s2ibaa_rowPreview{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;grid-area:2/2;min-width:0;font-size:13px;line-height:20px;overflow:hidden}.s2ibaa_section{flex-direction:column;display:flex}.s2ibaa_section+.s2ibaa_section{margin-top:20px}.s2ibaa_sectionTitle{color:var(--dsw-alias-label-tertiary);margin:0 0 4px;padding:0 8px 0 34px;font-size:12px;font-weight:600;line-height:18px}.s2ibaa_sectionCount{font-variant-numeric:tabular-nums;margin-left:6px}";
9380
+ const tagId$1 = "@wowyuarm/dsh-agent-team/inbox.module.css";
9381
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
8973
9382
  const tag = document.createElement("style");
8974
9383
  tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
8975
- tag.dataset.pluginCss = tagId$2;
8976
- tag.textContent = css$2;
9384
+ tag.dataset.pluginCss = tagId$1;
9385
+ tag.textContent = css$1;
8977
9386
  document.head.appendChild(tag);
8978
9387
  }
8979
9388
  var inbox_module_css_default = {
8980
9389
  "headerMeta": "s2ibaa_headerMeta",
9390
+ "headerUnread": "s2ibaa_headerUnread",
8981
9391
  "list": "s2ibaa_list",
8982
9392
  "row": "s2ibaa_row",
9393
+ "rowActor": "s2ibaa_rowActor",
8983
9394
  "rowChannel": "s2ibaa_rowChannel",
8984
9395
  "rowCrumb": "s2ibaa_rowCrumb",
9396
+ "rowLine": "s2ibaa_rowLine",
8985
9397
  "rowPreview": "s2ibaa_rowPreview",
8986
9398
  "rowTask": "s2ibaa_rowTask",
8987
- "rowTime": "s2ibaa_rowTime"
9399
+ "rowTime": "s2ibaa_rowTime",
9400
+ "rowWorkspace": "s2ibaa_rowWorkspace",
9401
+ "section": "s2ibaa_section",
9402
+ "sectionCount": "s2ibaa_sectionCount",
9403
+ "sectionTitle": "s2ibaa_sectionTitle"
8988
9404
  };
8989
9405
  //#endregion
8990
9406
  //#region src/client/TeamInboxPage.tsx
8991
9407
  /**
8992
- * Queue order: newest mention first, one total order across Workspaces. Each
9408
+ * How many 「最近活跃」 rows the merged page may show. The Host bounds each
9409
+ * Workspace's own slice; this is the single bound across every Workspace on
9410
+ * screen, so the section stays the same size no matter how many are open — and
9411
+ * it stays a way back into work rather than a second queue, which is why it is
9412
+ * shorter than the queue the reader is actually being asked to work through.
9413
+ */
9414
+ const RECENT_ROWS_LIMIT = 5;
9415
+ /**
9416
+ * Queue order: newest unread first, one total order across Workspaces. Each
8993
9417
  * Workspace slice arrives in the Host's own order (that order is the Host's
8994
9418
  * truncation policy); the merged display order is decided here, where the
8995
9419
  * merge happens, and the ledger sequence breaks ties so the queue never
@@ -9002,16 +9426,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9002
9426
  return byTime !== 0 ? byTime : right.item.newestSequence - left.item.newestSequence;
9003
9427
  }
9004
9428
  /**
9005
- * The Human 「提到我」 queue: one direct-only Inbox call per visible Workspace,
9006
- * merged into a single recency-ordered list newest mention first across every
9007
- * Workspace, since a queue is read by recency rather than by Workspace.
9429
+ * The Human Inbox: one Inbox call per visible Workspace, rendering the Host's
9430
+ * two slices the unread queue (「需要我」, mentions counted inside it rather
9431
+ * than alone) and the 「最近活跃」 tail of Threads the reader took part in.
9432
+ * Both merge across every Workspace into one recency-ordered list, newest
9433
+ * first, since a queue is read by recency rather than by Workspace.
9008
9434
  * Opening the page never acknowledges anything — only a durable Thread read
9009
- * consumes a mention marker, so rows and the badge drop after the Thread is
9010
- * opened through the existing auto-ack path.
9435
+ * advances the watermark and consumes a mention marker, so rows and the badge
9436
+ * drop after the Thread is opened through the existing auto-ack path. A Thread
9437
+ * holding unread is only ever in the queue: the Host already excludes it from
9438
+ * the tail, and this page never re-derives that judgement.
9011
9439
  */
9012
9440
  function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, selectWorkspace, selectThread, t }) {
9013
9441
  const workspaces = useWorkspaces((state) => state.items);
9014
9442
  const [rows, setRows] = (0, react.useState)();
9443
+ const [recentRows, setRecentRows] = (0, react.useState)([]);
9015
9444
  const [loading, setLoading] = (0, react.useState)(true);
9016
9445
  const [error, setError] = (0, react.useState)();
9017
9446
  const loadedRef = (0, react.useRef)(false);
@@ -9020,25 +9449,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9020
9449
  const results = await Promise.all(workspaces.map(async (workspace) => {
9021
9450
  const result = await loadInbox({
9022
9451
  workspaceId: workspace.workspaceId,
9023
- directOnly: true,
9024
9452
  limit: 100
9025
9453
  });
9026
9454
  return result.ok ? {
9027
9455
  ok: true,
9028
9456
  workspaceId: workspace.workspaceId,
9029
9457
  workspaceTitle: workspace.title,
9030
- items: result.value.items
9458
+ items: result.value.items,
9459
+ recent: result.value.recent
9031
9460
  } : {
9032
9461
  ok: false,
9033
9462
  message: result.error.message
9034
9463
  };
9035
9464
  }));
9036
9465
  const failure = results.find((result) => !result.ok);
9037
- setRows(results.flatMap((result) => result.ok ? result.items.map((item) => ({
9038
- workspaceId: result.workspaceId,
9039
- workspaceTitle: result.workspaceTitle,
9466
+ const asRows = (items, workspaceId, workspaceTitle) => items.map((item) => ({
9467
+ workspaceId,
9468
+ workspaceTitle,
9040
9469
  item
9041
- })) : []).sort(compareInboxRows));
9470
+ }));
9471
+ setRows(results.flatMap((result) => result.ok ? asRows(result.items, result.workspaceId, result.workspaceTitle) : []).sort(compareInboxRows));
9472
+ setRecentRows(results.flatMap((result) => result.ok ? asRows(result.recent, result.workspaceId, result.workspaceTitle) : []).sort(compareInboxRows).slice(0, RECENT_ROWS_LIMIT));
9042
9473
  setError(failure?.ok === false ? failure.message : void 0);
9043
9474
  loadedRef.current = true;
9044
9475
  setLoading(false);
@@ -9057,6 +9488,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9057
9488
  selectWorkspace(row.workspaceId);
9058
9489
  selectThread(row.item.thread.threadRef, row.item.channelRef, row.item.task?.taskRef, row.item.taskNumber);
9059
9490
  };
9491
+ const totalUnread = rows?.reduce((sum, row) => sum + row.item.unreadCount, 0) ?? 0;
9492
+ const totalMentions = rows?.reduce((sum, row) => sum + row.item.directCount, 0) ?? 0;
9493
+ const shownWorkspaces = /* @__PURE__ */ new Set();
9494
+ for (const row of rows ?? []) shownWorkspaces.add(row.workspaceTitle);
9495
+ for (const row of recentRows) shownWorkspaces.add(row.workspaceTitle);
9496
+ const showWorkspace = shownWorkspaces.size > 1;
9060
9497
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
9061
9498
  className: conversation_module_css_default.surface,
9062
9499
  "data-team-inbox": true,
@@ -9066,12 +9503,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9066
9503
  className: conversation_module_css_default.headerRow,
9067
9504
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9068
9505
  className: conversation_module_css_default.headerCopy,
9069
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: t("mentionsOfMe") }), rows !== void 0 && rows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9506
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: t("inboxTitle") }), rows !== void 0 && rows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
9070
9507
  className: inbox_module_css_default.headerMeta,
9071
- children: t("inboxHeaderMeta", {
9072
- threads: rows.length,
9073
- mentions: rows.reduce((sum, row) => sum + row.item.directCount, 0)
9074
- })
9508
+ children: [
9509
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("inboxHeaderThreads", { count: rows.length }) }),
9510
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9511
+ className: inbox_module_css_default.headerUnread,
9512
+ children: t("inboxHeaderUnread", { count: totalUnread })
9513
+ }),
9514
+ totalMentions > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("inboxHeaderMentions", { count: totalMentions }) })
9515
+ ]
9075
9516
  })]
9076
9517
  })
9077
9518
  })
@@ -9102,49 +9543,51 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9102
9543
  children: t("retry")
9103
9544
  })]
9104
9545
  }),
9105
- rows !== void 0 && (rows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9546
+ rows !== void 0 && (rows.length === 0 && recentRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9106
9547
  className: conversation_module_css_default.emptySurface,
9107
9548
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9108
9549
  className: conversation_module_css_default.emptyState,
9109
9550
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("inboxEmptyTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("inboxEmptyHint") })]
9110
9551
  })
9111
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9112
- className: inbox_module_css_default.list,
9113
- children: rows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
9114
- type: "button",
9115
- className: inbox_module_css_default.row,
9116
- onClick: () => {
9117
- open(row);
9118
- },
9119
- children: [
9120
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9121
- className: inbox_module_css_default.rowCrumb,
9122
- children: [
9123
- row.workspaceTitle,
9124
- " / ",
9125
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9126
- className: inbox_module_css_default.rowChannel,
9127
- children: ["#", row.item.channelName]
9128
- }),
9129
- row.item.taskNumber !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9130
- className: inbox_module_css_default.rowTask,
9131
- children: t("taskLabel", { number: row.item.taskNumber })
9132
- })
9133
- ]
9134
- }),
9135
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9136
- className: inbox_module_css_default.rowPreview,
9137
- children: row.item.previewText
9138
- }),
9139
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
9140
- className: inbox_module_css_default.rowTime,
9141
- dateTime: row.item.newestOccurredAt,
9142
- title: formatAbsoluteTime(row.item.newestOccurredAt),
9143
- children: formatInboxTime(row.item.newestOccurredAt, t)
9144
- })
9145
- ]
9146
- }, `${row.workspaceId} ${row.item.thread.threadRef}`))
9147
- })),
9552
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [rows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
9553
+ className: inbox_module_css_default.section,
9554
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
9555
+ className: inbox_module_css_default.sectionTitle,
9556
+ children: [t("inboxSectionNeedsMe"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9557
+ className: inbox_module_css_default.sectionCount,
9558
+ children: rows.length
9559
+ })]
9560
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9561
+ className: inbox_module_css_default.list,
9562
+ children: rows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InboxQueueRow, {
9563
+ row,
9564
+ t,
9565
+ showWorkspace,
9566
+ onOpen: () => {
9567
+ open(row);
9568
+ }
9569
+ }, `${row.workspaceId} ${row.item.thread.threadRef}`))
9570
+ })]
9571
+ }), recentRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
9572
+ className: inbox_module_css_default.section,
9573
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
9574
+ className: inbox_module_css_default.sectionTitle,
9575
+ children: [t("inboxSectionRecent"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9576
+ className: inbox_module_css_default.sectionCount,
9577
+ children: recentRows.length
9578
+ })]
9579
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9580
+ className: inbox_module_css_default.list,
9581
+ children: recentRows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InboxQueueRow, {
9582
+ row,
9583
+ t,
9584
+ showWorkspace,
9585
+ onOpen: () => {
9586
+ open(row);
9587
+ }
9588
+ }, `${row.workspaceId} ${row.item.thread.threadRef}`))
9589
+ })]
9590
+ })] })),
9148
9591
  rows !== void 0 && error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9149
9592
  className: conversation_module_css_default.error,
9150
9593
  role: "alert",
@@ -9155,6 +9598,95 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9155
9598
  })]
9156
9599
  });
9157
9600
  }
9601
+ /**
9602
+ * One queue row, shaped like the shipped two-line result row: who is on this
9603
+ * Thread leads in the gutter, the identity line answers which Thread this is,
9604
+ * how much is waiting, and when it last moved, and the gist sits under it on the
9605
+ * same column as evidence for that identity rather than as the row's subject.
9606
+ *
9607
+ * The gutter carries the one thing every row has — who is on the work, or who
9608
+ * moved a Thread nobody has claimed — so a Thread that merely arrived and one
9609
+ * that named the reader open on the same edge instead of the quieter one opening
9610
+ * on a slot reserved for a count it does not hold. It is the grammar the Channel
9611
+ * feed's Thread entry row already speaks, where the people on the work lead the
9612
+ * row.
9613
+ *
9614
+ * Before the queue admitted every unread Thread, each row was a mention and the
9615
+ * rows were interchangeable; now that named and ambient unread share one list,
9616
+ * the row has to carry that difference itself. The count closes the identity
9617
+ * line and only its ink changes — the shared capsule fill for a row that names
9618
+ * the reader, a hairline for one that merely moved. The two numbers behind that
9619
+ * ink (unread, mentions) reach assistive tech through the capsule's own name,
9620
+ * because a second visible count beside the first would cost the row the one
9621
+ * thing it needs to stay scannable.
9622
+ */
9623
+ function InboxQueueRow({ row, t, showWorkspace, onOpen }) {
9624
+ const { item } = row;
9625
+ const actor = item.newestActor;
9626
+ const owners = item.claimOwners;
9627
+ const named = item.directCount > 0;
9628
+ const countLabel = named ? t("inboxRowUnreadMentions", {
9629
+ count: item.unreadCount,
9630
+ mentions: item.directCount
9631
+ }) : t("inboxRowUnread", { count: item.unreadCount });
9632
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
9633
+ type: "button",
9634
+ className: inbox_module_css_default.row,
9635
+ "data-named": named || void 0,
9636
+ onClick: onOpen,
9637
+ children: [
9638
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9639
+ className: inbox_module_css_default.rowActor,
9640
+ children: owners.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamAvatarStack, {
9641
+ owners,
9642
+ label: t("claimers", { names: owners.map((owner) => `@${owner.name}`).join(", ") })
9643
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamAvatarStack, {
9644
+ owners: [actor],
9645
+ label: t("inboxRowActor", { name: `@${actor.name}` })
9646
+ })
9647
+ }),
9648
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9649
+ className: inbox_module_css_default.rowLine,
9650
+ children: [
9651
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9652
+ className: inbox_module_css_default.rowCrumb,
9653
+ children: [
9654
+ showWorkspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9655
+ className: inbox_module_css_default.rowWorkspace,
9656
+ children: row.workspaceTitle
9657
+ }),
9658
+ showWorkspace && " / ",
9659
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9660
+ className: inbox_module_css_default.rowChannel,
9661
+ children: ["#", item.channelName]
9662
+ }),
9663
+ " ",
9664
+ item.taskNumber !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9665
+ className: inbox_module_css_default.rowTask,
9666
+ children: t("taskLabel", { number: item.taskNumber })
9667
+ })
9668
+ ]
9669
+ }),
9670
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamCountBadge, {
9671
+ count: item.unreadCount,
9672
+ tone: named ? "solid" : "hairline",
9673
+ label: countLabel
9674
+ }),
9675
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
9676
+ className: inbox_module_css_default.rowTime,
9677
+ dateTime: item.newestOccurredAt,
9678
+ title: formatAbsoluteTime(item.newestOccurredAt),
9679
+ children: formatInboxTime(item.newestOccurredAt, t)
9680
+ })
9681
+ ]
9682
+ }),
9683
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9684
+ className: inbox_module_css_default.rowPreview,
9685
+ children: item.previewText
9686
+ })
9687
+ ]
9688
+ });
9689
+ }
9158
9690
  //#endregion
9159
9691
  //#region src/client/scope-coverage.ts
9160
9692
  /**
@@ -9876,12 +10408,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9876
10408
  }
9877
10409
  if (result.value.kind === "committed") {
9878
10410
  const committed = result.value;
10411
+ const optimisticMentions = [...new Set([...recipients, ...mentionedMemberIds(draft, channelMembers)])].sort();
9879
10412
  setCurrentFacts((current) => {
9880
10413
  const merged = mergeFacts(current, [{
9881
10414
  kind: "message",
9882
10415
  sequence: committed.message.sequence,
9883
10416
  message: committed.message,
9884
- mentions: [...recipients].sort(),
10417
+ mentions: optimisticMentions,
9885
10418
  occurredAt: committed.receipt.occurredAt
9886
10419
  }]);
9887
10420
  currentFactsRef.current = merged;
@@ -10280,6 +10813,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10280
10813
  loadChannels,
10281
10814
  subscribeChanges,
10282
10815
  loadMembers,
10816
+ loadInbox,
10283
10817
  sendMessage,
10284
10818
  joinChannel,
10285
10819
  removeChannelMember,
@@ -10315,67 +10849,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10315
10849
  });
10316
10850
  }
10317
10851
  //#endregion
10318
- //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/sidebar.module.css.mjs
10319
- const css$1 = "html[data-agent-team-mode=team] button[class*=newSession]{display:none}.d0xfxa_workspaceBrowser{flex-direction:column;height:100%;min-height:0;padding:0 8px 8px;display:flex}.d0xfxa_railButton{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:0;display:inline-flex}.d0xfxa_railButton:hover,.d0xfxa_railButton:focus-visible{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_railButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_workspaceList{flex-direction:column;gap:2px;padding-bottom:2px;display:flex}.d0xfxa_workspaceRow{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;align-items:center;gap:6px;width:100%;height:34px;padding:0 8px;display:flex}.d0xfxa_workspaceRow:hover,.d0xfxa_workspaceRow:focus-visible,.d0xfxa_workspaceRow[aria-current=page]{background:var(--dsw-alias-interactive-bg-hover)}.d0xfxa_workspaceRow:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_workspaceIcon{color:var(--dsw-alias-label-tertiary);flex:0 0 16px;justify-content:center;align-items:center;height:20px;display:inline-flex}.d0xfxa_workspaceRow[data-selected] .d0xfxa_workspaceIcon{color:var(--dsw-alias-state-business-primary)}.d0xfxa_workspaceCopy{min-width:0;display:flex}.d0xfxa_workspaceCopy strong{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:400;line-height:20px;overflow:hidden}.d0xfxa_emptyState{color:var(--dsw-alias-label-tertiary);margin:8px;font-size:12px;line-height:18px}.d0xfxa_inboxCard{color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;flex:none;align-items:center;gap:6px;width:100%;height:34px;margin:4px 0 2px;padding:0 8px;display:flex}.d0xfxa_inboxCard:hover,.d0xfxa_inboxCard:focus-visible,.d0xfxa_inboxCard[aria-current=page]{background:var(--dsw-alias-interactive-bg-hover)}.d0xfxa_inboxCard:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_inboxCard>svg{color:var(--dsw-alias-label-tertiary);flex:0 0 16px}.d0xfxa_inboxCardLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:14px;line-height:20px;overflow:hidden}.d0xfxa_inboxBadge{background:var(--dsw-alias-state-business-primary);box-sizing:border-box;color:var(--dsw-alias-label-primary-foreground);corner-shape:round;border-radius:999px;flex:none;justify-content:center;align-items:center;min-width:18px;height:18px;margin-left:auto;padding:0 5px;font-size:11px;font-weight:600;line-height:18px;display:inline-flex}.d0xfxa_railButton .d0xfxa_inboxBadge{margin-left:0;position:absolute;top:0;right:0}.d0xfxa_railWorkspace{flex-direction:column;align-items:center;gap:8px;padding-top:8px;display:flex}.d0xfxa_railButton{corner-shape:round;border-radius:50%;width:36px;height:36px;position:relative}.d0xfxa_railButton[data-active]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_workspaceSection{flex-direction:column;flex:1;gap:4px;min-height:0;margin-top:2px;display:flex;overflow-y:auto}.d0xfxa_section{flex-direction:column;display:flex}.d0xfxa_sectionHeader{align-items:center;min-height:26px;padding-right:2px;display:flex}.d0xfxa_sectionToggle{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;align-items:center;gap:4px;min-width:0;min-height:24px;padding:0 6px;font-size:12px;line-height:18px;display:inline-flex}.d0xfxa_sectionToggle:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_sectionToggle:hover .d0xfxa_sectionChevron,.d0xfxa_sectionToggle:focus-visible .d0xfxa_sectionChevron{color:var(--dsw-alias-label-primary)}.d0xfxa_sectionChevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .12s,color .12s}.d0xfxa_sectionToggle[aria-expanded=false] .d0xfxa_sectionChevron{transform:rotate(-90deg)}.d0xfxa_sectionTitle{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.d0xfxa_sectionActions{align-items:center;margin-left:auto;display:inline-flex}.d0xfxa_panel{flex-direction:column;display:flex}.d0xfxa_iconButton{corner-shape:round;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;display:inline-flex}.d0xfxa_iconButton:hover,.d0xfxa_iconButton:focus-visible{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_iconButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_textButton{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:5px;padding:2px 5px;font-size:11px;line-height:18px}.d0xfxa_textButton:hover,.d0xfxa_textButton:focus-visible{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.d0xfxa_textButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_textButton:disabled{cursor:not-allowed;opacity:.4}.d0xfxa_channelList,.d0xfxa_agentList{flex-direction:column;gap:1px;padding:0 4px 4px;display:flex}.d0xfxa_sidebarRowDragging{opacity:.5}.d0xfxa_sidebarRowDropBefore,.d0xfxa_sidebarRowDropAfter{position:relative}.d0xfxa_sidebarRowDropBefore:before,.d0xfxa_sidebarRowDropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:4px}.d0xfxa_sidebarRowDropBefore:before{top:-7px}.d0xfxa_sidebarRowDropAfter:after{bottom:-7px}.d0xfxa_channelRow{color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;min-height:30px;display:flex;position:relative}.d0xfxa_channelSelect{box-sizing:border-box;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;flex:1;align-items:center;min-width:0;min-height:30px;padding:3px 4px 3px 8px;display:flex}.d0xfxa_channelSelect:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_channelName{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:400;line-height:18px;overflow:hidden}.d0xfxa_agentRow{color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;min-height:38px;display:flex;position:relative}.d0xfxa_agentSelect{box-sizing:border-box;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:8px;flex:1;grid-template-columns:24px minmax(0,1fr);align-items:center;gap:0 8px;min-width:0;min-height:38px;padding:3px 4px 3px 8px;display:grid}.d0xfxa_agentSelect:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.d0xfxa_agentSelect[aria-current=page]{background:var(--dsw-alias-interactive-bg-hover);border-radius:8px}.d0xfxa_agentRow:hover .d0xfxa_agentSelect[aria-current=page],.d0xfxa_agentRow:focus-within .d0xfxa_agentSelect[aria-current=page],.d0xfxa_agentRow[data-menu-open] .d0xfxa_agentSelect[aria-current=page]{background:0 0}.d0xfxa_agentAvatar{background:hsl(var(--team-avatar-hue,212) 42% 46%);corner-shape:round;color:#fff;cursor:default;border-radius:50%;flex:0 0 24px;justify-content:center;align-items:center;width:24px;height:24px;font-size:11px;font-weight:600;display:inline-flex;position:relative}.d0xfxa_agentAvatarBadge{background:var(--dsw-specific-sidebar-fill);corner-shape:round;box-shadow:0 0 0 1px var(--dsw-specific-sidebar-fill);border-radius:50%;justify-content:center;align-items:center;width:12px;height:12px;padding:1px;line-height:0;display:inline-flex;position:absolute;bottom:-3px;right:-3px}.d0xfxa_agentCopy{flex-direction:column;min-width:0;display:flex}.d0xfxa_agentCopy strong{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:400;line-height:17px;overflow:hidden}.d0xfxa_agentCopy small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:13px;overflow:hidden}.d0xfxa_unavailableDot{background:var(--dsw-alias-label-tertiary);corner-shape:round;border-radius:50%;width:7px;height:7px;display:inline-block}.d0xfxa_rowMenu{flex:none;align-items:center;padding-right:4px;display:none}.d0xfxa_channelRow:hover .d0xfxa_rowMenu,.d0xfxa_channelRow:focus-within .d0xfxa_rowMenu,.d0xfxa_channelRow[data-menu-open] .d0xfxa_rowMenu,.d0xfxa_agentRow:hover .d0xfxa_rowMenu,.d0xfxa_agentRow:focus-within .d0xfxa_rowMenu,.d0xfxa_agentRow[data-menu-open] .d0xfxa_rowMenu{display:inline-flex}.d0xfxa_channelRow[data-menu-open],.d0xfxa_agentRow[data-menu-open],.d0xfxa_channelRow:hover,.d0xfxa_agentRow:hover,.d0xfxa_channelRow:focus-within,.d0xfxa_agentRow:focus-within,.d0xfxa_channelRow[aria-current=page]{background:var(--dsw-alias-interactive-bg-hover)}.d0xfxa_rowMenuButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;justify-content:center;align-items:center;width:20px;height:20px;padding:0;display:inline-flex}.d0xfxa_rowMenuButton:hover,.d0xfxa_rowMenuButton:focus-visible{color:var(--dsw-alias-label-primary)}.d0xfxa_rowMenuButton:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.d0xfxa_retryError{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:8px;padding:8px;font-size:11px;display:flex}.d0xfxa_rowAlert{color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;padding:2px 8px 6px;font-size:11px}.d0xfxa_editDescription{color:var(--dsw-alias-label-secondary);margin:0 0 10px;font-size:12px;line-height:18px}.d0xfxa_editMemberList{gap:3px;display:grid}.d0xfxa_editMemberRow{border-radius:6px;grid-template-columns:14px minmax(0,1fr) auto;align-items:center;gap:0 8px;min-height:40px;padding:3px 6px;display:grid}.d0xfxa_editMemberRowChannels{grid-template-columns:minmax(0,1fr) auto}.d0xfxa_editMemberRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.d0xfxa_editMemberCopy{min-width:0;display:grid}.d0xfxa_editMemberCopy strong{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;line-height:18px;overflow:hidden}.d0xfxa_editMemberCopy small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:14px;overflow:hidden}.d0xfxa_editChannelName{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:400;line-height:18px;overflow:hidden}.d0xfxa_editMemberRow button{min-width:60px}.d0xfxa_editHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:16px}.d0xfxa_menuHint{color:var(--dsw-alias-label-tertiary);margin-left:4px;font-size:10px;line-height:14px}.d0xfxa_rowError{color:var(--dsw-alias-state-error-primary);grid-column:1/-1;margin:2px 0;font-size:11px;line-height:16px}";
10320
- const tagId$1 = "@wowyuarm/dsh-agent-team/sidebar.module.css";
10321
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
10322
- const tag = document.createElement("style");
10323
- tag.dataset.plugin = "@wowyuarm/dsh-agent-team";
10324
- tag.dataset.pluginCss = tagId$1;
10325
- tag.textContent = css$1;
10326
- document.head.appendChild(tag);
10327
- }
10328
- var sidebar_module_css_default = {
10329
- "agentAvatar": "d0xfxa_agentAvatar",
10330
- "agentAvatarBadge": "d0xfxa_agentAvatarBadge",
10331
- "agentCopy": "d0xfxa_agentCopy",
10332
- "agentList": "d0xfxa_agentList",
10333
- "agentRow": "d0xfxa_agentRow",
10334
- "agentSelect": "d0xfxa_agentSelect",
10335
- "channelList": "d0xfxa_channelList",
10336
- "channelName": "d0xfxa_channelName",
10337
- "channelRow": "d0xfxa_channelRow",
10338
- "channelSelect": "d0xfxa_channelSelect",
10339
- "editChannelName": "d0xfxa_editChannelName",
10340
- "editDescription": "d0xfxa_editDescription",
10341
- "editHint": "d0xfxa_editHint",
10342
- "editMemberCopy": "d0xfxa_editMemberCopy",
10343
- "editMemberList": "d0xfxa_editMemberList",
10344
- "editMemberRow": "d0xfxa_editMemberRow",
10345
- "editMemberRowChannels": "d0xfxa_editMemberRowChannels",
10346
- "emptyState": "d0xfxa_emptyState",
10347
- "iconButton": "d0xfxa_iconButton",
10348
- "inboxBadge": "d0xfxa_inboxBadge",
10349
- "inboxCard": "d0xfxa_inboxCard",
10350
- "inboxCardLabel": "d0xfxa_inboxCardLabel",
10351
- "menuHint": "d0xfxa_menuHint",
10352
- "panel": "d0xfxa_panel",
10353
- "railButton": "d0xfxa_railButton",
10354
- "railWorkspace": "d0xfxa_railWorkspace",
10355
- "retryError": "d0xfxa_retryError",
10356
- "rowAlert": "d0xfxa_rowAlert",
10357
- "rowError": "d0xfxa_rowError",
10358
- "rowMenu": "d0xfxa_rowMenu",
10359
- "rowMenuButton": "d0xfxa_rowMenuButton",
10360
- "section": "d0xfxa_section",
10361
- "sectionActions": "d0xfxa_sectionActions",
10362
- "sectionChevron": "d0xfxa_sectionChevron",
10363
- "sectionHeader": "d0xfxa_sectionHeader",
10364
- "sectionTitle": "d0xfxa_sectionTitle",
10365
- "sectionToggle": "d0xfxa_sectionToggle",
10366
- "sidebarRowDragging": "d0xfxa_sidebarRowDragging",
10367
- "sidebarRowDropAfter": "d0xfxa_sidebarRowDropAfter",
10368
- "sidebarRowDropBefore": "d0xfxa_sidebarRowDropBefore",
10369
- "textButton": "d0xfxa_textButton",
10370
- "unavailableDot": "d0xfxa_unavailableDot",
10371
- "workspaceBrowser": "d0xfxa_workspaceBrowser",
10372
- "workspaceCopy": "d0xfxa_workspaceCopy",
10373
- "workspaceIcon": "d0xfxa_workspaceIcon",
10374
- "workspaceList": "d0xfxa_workspaceList",
10375
- "workspaceRow": "d0xfxa_workspaceRow",
10376
- "workspaceSection": "d0xfxa_workspaceSection"
10377
- };
10378
- //#endregion
10379
10852
  //#region src/client/TeamWorkspaceRow.tsx
10380
10853
  function TeamWorkspaceRow({ workspaceId, title, path, selected, current, onSelect }) {
10381
10854
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
@@ -10510,32 +10983,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10510
10983
  for (const listener of listeners$1) listener();
10511
10984
  }
10512
10985
  //#endregion
10513
- //#region src/client/TeamMemberAvatar.tsx
10514
- /**
10515
- * Sidebar Member avatar reusing the conversation identity language: the
10516
- * deterministic member hue and handle initial, with the presence indicator
10517
- * overlaid at the bottom-right so one glyph carries identity and state.
10518
- */
10519
- function TeamMemberAvatar({ status, t }) {
10520
- const label = presenceLabel(status, t);
10521
- const state = presenceDotState(status.presence);
10522
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
10523
- label,
10524
- delayMs: 300,
10525
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
10526
- className: sidebar_module_css_default.agentAvatar,
10527
- style: { "--team-avatar-hue": memberHue(status.member.memberId) },
10528
- role: "img",
10529
- "aria-label": label,
10530
- children: [status.member.handle.replace("@", "").slice(0, 1).toUpperCase(), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
10531
- className: sidebar_module_css_default.agentAvatarBadge,
10532
- "aria-hidden": "true",
10533
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamStateDot, { state })
10534
- })]
10535
- })
10536
- });
10537
- }
10538
- //#endregion
10539
10986
  //#region src/client/sidebar-drag.tsx
10540
10987
  /**
10541
10988
  * Native whole-row drag for the Team sidebar lists. Unlike the Harness
@@ -11395,7 +11842,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11395
11842
  className: sidebar_module_css_default.emptyState,
11396
11843
  children: t("loadingAgents")
11397
11844
  }),
11398
- !loading && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
11845
+ !loading && error === void 0 && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
11399
11846
  className: sidebar_module_css_default.emptyState,
11400
11847
  children: t("emptyAgents")
11401
11848
  }),
@@ -11489,8 +11936,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11489
11936
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
11490
11937
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
11491
11938
  className: sidebar_module_css_default.agentRow,
11939
+ "data-agent-row": true,
11492
11940
  "data-menu-open": menuOpen || void 0,
11493
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
11941
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
11494
11942
  type: "button",
11495
11943
  className: sidebar_module_css_default.agentSelect,
11496
11944
  "aria-label": t("openAgentSession", { name: status.member.handle }),
@@ -11499,13 +11947,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11499
11947
  onClick: () => {
11500
11948
  openMemberSession(status.member.sessionId);
11501
11949
  },
11502
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberAvatar, {
11950
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberIdentity, {
11503
11951
  status,
11504
- t
11505
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
11952
+ name: status.member.handle.replace(/^@/, ""),
11506
11953
  className: sidebar_module_css_default.agentCopy,
11507
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status.member.handle }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
11508
- })]
11954
+ t
11955
+ })
11509
11956
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
11510
11957
  className: sidebar_module_css_default.rowMenu,
11511
11958
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamRowMenu, {
@@ -11896,7 +12343,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11896
12343
  className: sidebar_module_css_default.emptyState,
11897
12344
  children: t("loadingChannels")
11898
12345
  }),
11899
- !loading && (view?.channels.length ?? 0) === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
12346
+ !loading && error === void 0 && view !== void 0 && view.channels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
11900
12347
  className: sidebar_module_css_default.emptyState,
11901
12348
  children: t("emptyChannels")
11902
12349
  }),
@@ -12132,39 +12579,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12132
12579
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("legend", { children: t("channelMembersSection") }), members.map((status) => {
12133
12580
  const joined = joinedIds.has(status.member.memberId);
12134
12581
  const rowPending = membership.pending.has(status.member.memberId);
12135
- const disabled = rowPending || !joined && status.presence === "unavailable";
12582
+ const disabled = rowPending || !joined && status.availability !== "active";
12136
12583
  const rowError = membership.errors.get(status.member.memberId);
12137
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
12138
- className: sidebar_module_css_default.editMemberRow,
12139
- children: [
12140
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamPresenceDot, {
12141
- status,
12142
- t
12143
- }),
12144
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
12145
- className: sidebar_module_css_default.editMemberCopy,
12146
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: ["@", status.member.handle] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
12147
- }),
12148
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
12149
- size: "sm",
12150
- variant: "outline",
12151
- disabled,
12152
- onClick: () => {
12153
- membership.change({
12154
- workspaceId: channel.workspaceId,
12155
- channelRef: channel.channelRef,
12156
- memberId: status.member.memberId,
12157
- joined
12158
- });
12159
- },
12160
- children: rowPending ? t("membershipUpdating") : joined ? t("removeFromChannel") : t("addToChannel")
12161
- }),
12162
- rowError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
12163
- className: sidebar_module_css_default.rowError,
12164
- role: "alert",
12165
- children: rowError
12166
- })
12167
- ]
12584
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberRow, {
12585
+ status,
12586
+ action: {
12587
+ label: rowPending ? t("membershipUpdating") : joined ? t("removeFromChannel") : t("addToChannel"),
12588
+ disabled,
12589
+ onSelect: () => {
12590
+ membership.change({
12591
+ workspaceId: channel.workspaceId,
12592
+ channelRef: channel.channelRef,
12593
+ memberId: status.member.memberId,
12594
+ joined
12595
+ });
12596
+ }
12597
+ },
12598
+ ...rowError === void 0 ? {} : { error: rowError },
12599
+ t
12168
12600
  }, status.member.memberId);
12169
12601
  })]
12170
12602
  }),
@@ -12179,26 +12611,44 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12179
12611
  }
12180
12612
  //#endregion
12181
12613
  //#region src/client/TeamWorkspaceBrowser.tsx
12614
+ /**
12615
+ * The Inbox entry's icon with its unread mark. The quantity left this surface
12616
+ * and lives in the control's accessible name: the sidebar answers whether
12617
+ * anything is waiting at a glance, and the number — which moves on every fact —
12618
+ * is what a reader asks for on purpose. The mark hangs off the icon rather than
12619
+ * off the control, so the wide card and the 36px rail button put the same dot
12620
+ * on the same corner of the same glyph.
12621
+ */
12622
+ function InboxMark({ unread }) {
12623
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
12624
+ className: sidebar_module_css_default.inboxMark,
12625
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutline14, { size: 16 }), unread > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
12626
+ className: sidebar_module_css_default.inboxDot,
12627
+ "data-team-inbox-dot": true,
12628
+ "aria-hidden": "true"
12629
+ })]
12630
+ });
12631
+ }
12182
12632
  function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, selectInbox, t, useWorkspaces, loadMembers, loadInbox, subscribeChanges, subscribeReads, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember, archiveMember, joinChannel, removeChannelMember, loadModels, openMemberSession }) {
12183
12633
  const navigationState = (0, react.useSyncExternalStore)(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
12184
12634
  const workspaces = useWorkspaces((state) => state.items);
12185
12635
  const selected = navigationState.workspaceId;
12186
12636
  const selectedId = selected !== void 0 && workspaces.some((workspace) => workspace.workspaceId === selected) ? selected : workspaces[0]?.workspaceId;
12187
12637
  const overviewIsCurrent = navigationState.channelRef === void 0 && navigationState.memberSessionId === void 0 && navigationState.inbox !== true;
12188
- const inboxIsCurrent = navigationState.inbox === true;
12638
+ const inboxIsCurrent = navigationState.inbox === true && navigationState.memberSessionId === void 0;
12189
12639
  const [creatingAgents, setCreatingAgents] = (0, react.useState)([]);
12190
12640
  const [pendingSection, setPendingSection] = (0, react.useState)();
12191
12641
  const channelsRef = (0, react.useRef)(null);
12192
12642
  const agentsRef = (0, react.useRef)(null);
12193
12643
  const workspacesOpen = useSidebarSectionOpen(void 0, "workspaces");
12194
12644
  const [inboxTotal, setInboxTotal] = (0, react.useState)(0);
12645
+ const inboxLabel = inboxTotal > 0 ? t("inboxTitleWithCount", { count: inboxTotal }) : t("inboxTitle");
12195
12646
  (0, react.useEffect)(() => {
12196
12647
  let disposed = false;
12197
12648
  let scheduled;
12198
12649
  const refresh = async () => {
12199
12650
  const results = await Promise.all(workspaces.map((workspace) => loadInbox({
12200
12651
  workspaceId: workspace.workspaceId,
12201
- directOnly: true,
12202
12652
  limit: 1
12203
12653
  })));
12204
12654
  if (disposed) return;
@@ -12251,22 +12701,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12251
12701
  "aria-label": t("workspaceSections"),
12252
12702
  children: [
12253
12703
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
12254
- label: t("mentionsOfMe"),
12704
+ label: inboxLabel,
12255
12705
  side: "right",
12256
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
12706
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
12257
12707
  type: "button",
12258
12708
  className: sidebar_module_css_default.railButton,
12259
- "aria-label": inboxTotal > 0 ? t("mentionsOfMeWithCount", { count: inboxTotal }) : t("mentionsOfMe"),
12709
+ "aria-label": inboxLabel,
12260
12710
  "aria-current": inboxIsCurrent ? "page" : void 0,
12261
12711
  onClick: () => {
12262
12712
  selectInbox();
12263
12713
  expandSidebar();
12264
12714
  },
12265
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutline14, { size: 16 }), inboxTotal > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
12266
- className: sidebar_module_css_default.inboxBadge,
12267
- "aria-hidden": "true",
12268
- children: inboxTotal > 99 ? "99+" : inboxTotal
12269
- })]
12715
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InboxMark, { unread: inboxTotal })
12270
12716
  })
12271
12717
  }),
12272
12718
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
@@ -12306,21 +12752,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12306
12752
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
12307
12753
  type: "button",
12308
12754
  className: sidebar_module_css_default.inboxCard,
12309
- "aria-label": inboxTotal > 0 ? t("mentionsOfMeWithCount", { count: inboxTotal }) : t("mentionsOfMe"),
12755
+ "aria-label": inboxLabel,
12310
12756
  "aria-current": inboxIsCurrent ? "page" : void 0,
12311
12757
  onClick: selectInbox,
12312
- children: [
12313
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutline14, { size: 16 }),
12314
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
12315
- className: sidebar_module_css_default.inboxCardLabel,
12316
- children: t("mentionsOfMe")
12317
- }),
12318
- inboxTotal > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
12319
- className: sidebar_module_css_default.inboxBadge,
12320
- "aria-hidden": "true",
12321
- children: inboxTotal > 99 ? "99+" : inboxTotal
12322
- })
12323
- ]
12758
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InboxMark, { unread: inboxTotal }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
12759
+ className: sidebar_module_css_default.inboxCardLabel,
12760
+ children: t("inboxTitle")
12761
+ })]
12324
12762
  }),
12325
12763
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamSidebarSection, {
12326
12764
  title: t("workspaces"),
@@ -12416,14 +12854,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12416
12854
  statusError: "错误",
12417
12855
  statusUnavailable: "不可用",
12418
12856
  addChannel: "新建频道",
12419
- mentionsOfMe: "提到我",
12420
- mentionsOfMeWithCount: "提到我,{count} 条未读提及",
12421
- loadingInbox: "正在加载提到我…",
12422
- inboxEmptyTitle: "还没有人提到你",
12423
- inboxEmptyHint: "需要你知道或做决定时,成员会提到你",
12424
- inboxTimeToday: "今天",
12857
+ inboxTitle: "收件箱",
12858
+ inboxTitleWithCount: "收件箱,{count} 条未读",
12859
+ loadingInbox: "正在加载收件箱…",
12860
+ inboxEmptyTitle: "收件箱是空的",
12861
+ inboxEmptyHint: "你参与的 Thread 有新活动、或有人提到你时,会出现在这里",
12425
12862
  inboxTimeYesterday: "昨天",
12426
- inboxHeaderMeta: "{threads} 个 Thread · {mentions} 条提及,按最新提及排序",
12863
+ inboxHeaderThreads: "{count} 个 Thread",
12864
+ inboxHeaderUnread: "{count} 条未读",
12865
+ inboxHeaderMentions: "{count} 条提及",
12866
+ inboxRowUnread: "{count} 条未读",
12867
+ inboxRowUnreadMentions: "{count} 条未读,其中 {mentions} 条提及",
12868
+ inboxRowActor: "最新来自 {name}",
12869
+ inboxSectionNeedsMe: "需要我",
12870
+ inboxSectionRecent: "最近活跃",
12427
12871
  channelName: "名称",
12428
12872
  channelDescription: "说明",
12429
12873
  initialMembers: "初始成员",
@@ -12489,12 +12933,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12489
12933
  taskStatusInReview: "待验收",
12490
12934
  taskStatusDone: "已完成",
12491
12935
  taskStatusClosed: "已关闭",
12492
- taskMessageCount: "{count} 条消息",
12493
12936
  taskLabel: "Task #{number}",
12494
12937
  taskPending: "Task …",
12495
12938
  openTask: "打开 Task #{number}",
12496
12939
  openThread: "打开讨论",
12940
+ openTaskUnread: "打开 Task #{number}({count} 条新动态)",
12941
+ openThreadUnread: "打开讨论({count} 条新动态)",
12497
12942
  threadLabel: "讨论",
12943
+ recentActivity: "最近活动 {time}",
12944
+ replyAction: "回复",
12945
+ claimers: "由 {names} 处理",
12498
12946
  asTask: "作为任务",
12499
12947
  promoteToTask: "转为 Task",
12500
12948
  promotingTask: "正在转为 Task…",
@@ -12573,14 +13021,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12573
13021
  statusError: "Error",
12574
13022
  statusUnavailable: "Unavailable",
12575
13023
  addChannel: "New Channel",
12576
- mentionsOfMe: "Mentions of me",
12577
- mentionsOfMeWithCount: "Mentions of me, {count} unread mention(s)",
12578
- loadingInbox: "Loading mentions…",
12579
- inboxEmptyTitle: "Nobody has mentioned you yet",
12580
- inboxEmptyHint: "Members will mention you when you must know or decide",
12581
- inboxTimeToday: "Today",
13024
+ inboxTitle: "Inbox",
13025
+ inboxTitleWithCount: "Inbox, {count} unread",
13026
+ loadingInbox: "Loading Inbox…",
13027
+ inboxEmptyTitle: "Your Inbox is empty",
13028
+ inboxEmptyHint: "Threads you take part in appear here when they have new activity or mention you",
12582
13029
  inboxTimeYesterday: "Yesterday",
12583
- inboxHeaderMeta: "{threads} Thread(s) · {mentions} mention(s), newest first",
13030
+ inboxHeaderThreads: "{count} Thread(s)",
13031
+ inboxHeaderUnread: "{count} unread",
13032
+ inboxHeaderMentions: "{count} mention(s)",
13033
+ inboxRowUnread: "{count} unread",
13034
+ inboxRowUnreadMentions: "{count} unread, {mentions} mention(s)",
13035
+ inboxRowActor: "Latest from {name}",
13036
+ inboxSectionNeedsMe: "Needs me",
13037
+ inboxSectionRecent: "Recently active",
12584
13038
  channelName: "Name",
12585
13039
  channelDescription: "Description",
12586
13040
  initialMembers: "Initial members",
@@ -12646,12 +13100,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12646
13100
  taskStatusInReview: "In review",
12647
13101
  taskStatusDone: "Done",
12648
13102
  taskStatusClosed: "Closed",
12649
- taskMessageCount: "{count} messages",
12650
13103
  taskLabel: "Task #{number}",
12651
13104
  taskPending: "Task …",
12652
13105
  openTask: "Open Task #{number}",
12653
13106
  openThread: "Open thread",
13107
+ openTaskUnread: "Open Task #{number} ({count} new updates)",
13108
+ openThreadUnread: "Open thread ({count} new updates)",
12654
13109
  threadLabel: "Thread",
13110
+ recentActivity: "Last activity {time}",
13111
+ replyAction: "Reply",
13112
+ claimers: "Handled by {names}",
12655
13113
  asTask: "As task",
12656
13114
  promoteToTask: "Convert to Task",
12657
13115
  promotingTask: "Converting to Task…",
@@ -12852,13 +13310,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12852
13310
  leaveTeam: () => {
12853
13311
  navigation.actions().exitMemberSession();
12854
13312
  navigation.actions().leaveTeam();
12855
- },
12856
- loadMemberGroups
13313
+ }
12857
13314
  })
12858
13315
  }, TeamFooterAction));
12859
13316
  registerModeShadow(ctx, navigation, changes, reads, drafts, "sidebar.workspaces", TeamWorkspaceBrowser);
12860
13317
  registerModeShadow(ctx, navigation, changes, reads, drafts, "main", TeamConversation, void 0, "conversation");
12861
- registerModeShadow(ctx, navigation, changes, reads, drafts, "sidebar.settings", TeamSettings, () => ({ loadMemberGroups }));
13318
+ registerModeShadow(ctx, navigation, changes, reads, drafts, "sidebar.settings", TeamMembersAction, () => ({ loadMemberGroups }));
12862
13319
  }
12863
13320
  async function apply(ctx) {
12864
13321
  const disposeRemote = await ctx.remote.$mount(TYPERT_REMOTE);