@wowyuarm/dsh-agent-team 0.1.1 → 0.1.3

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 (92) hide show
  1. package/README.md +1 -0
  2. package/README.zh.md +2 -0
  3. package/package.json +42 -25
  4. package/packages/agent-team/README.md +1 -1
  5. package/packages/agent-team/README.zh.md +1 -1
  6. package/packages/agent-team/lib/attachments.js +11 -12
  7. package/packages/agent-team/lib/auto-compaction.js +163 -0
  8. package/packages/agent-team/lib/index.js +262 -189
  9. package/packages/agent-team/lib/ledger.js +140 -109
  10. package/packages/agent-team/lib/recovery.js +30 -35
  11. package/packages/agent-team/lib/spec.js +10 -4
  12. package/packages/agent-team/lib/typert.host.js +68 -71
  13. package/packages/agent-team/lib/typert.remote-client.d.ts +3 -3
  14. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  15. package/packages/agent-team/lib/typert.remote-client.js +41 -56
  16. package/packages/agent-team/lib/types/attachments.d.ts +2 -2
  17. package/packages/agent-team/lib/types/attachments.d.ts.map +1 -1
  18. package/packages/agent-team/lib/types/auto-compaction.d.ts +38 -0
  19. package/packages/agent-team/lib/types/auto-compaction.d.ts.map +1 -0
  20. package/packages/agent-team/lib/types/index.d.ts +49 -24
  21. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  22. package/packages/agent-team/lib/types/ledger.d.ts +24 -11
  23. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  24. package/packages/agent-team/lib/types/recovery.d.ts +15 -16
  25. package/packages/agent-team/lib/types/recovery.d.ts.map +1 -1
  26. package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
  27. package/packages/agent-team/lib/types/types.d.ts +20 -12
  28. package/packages/agent-team/lib/types/types.d.ts.map +1 -1
  29. package/packages/agent-team/preset/team-member/agent.cordis.yml +8 -3
  30. package/packages/client-agent-team/README.md +3 -2
  31. package/packages/client-agent-team/README.zh.md +3 -2
  32. package/packages/client-agent-team/lib/client.js +1507 -525
  33. package/packages/client-agent-team/lib/client.js.map +1 -1
  34. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts +1 -2
  35. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
  36. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +24 -182
  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 +27 -5
  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 +19 -4
  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 +22 -2
  44. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
  45. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
  46. package/packages/client-agent-team/lib/types/client/TeamConversation.js +3 -3
  47. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts +34 -0
  48. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -0
  49. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +169 -0
  50. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts +17 -0
  51. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts.map +1 -0
  52. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.js +120 -0
  53. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +7 -2
  54. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
  55. package/packages/client-agent-team/lib/types/client/TeamMessage.js +170 -18
  56. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +4 -0
  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 +70 -13
  59. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts +1 -1
  60. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
  61. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +2 -2
  62. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  63. package/packages/client-agent-team/lib/types/client/index.js +72 -2
  64. package/packages/client-agent-team/lib/types/client/locales.d.ts +8 -2
  65. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
  66. package/packages/client-agent-team/lib/types/client/locales.js +8 -2
  67. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts +22 -0
  68. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts.map +1 -0
  69. package/packages/client-agent-team/lib/types/client/member-session-input.js +98 -0
  70. package/packages/client-agent-team/lib/types/client/requests.d.ts +16 -0
  71. package/packages/client-agent-team/lib/types/client/requests.d.ts.map +1 -0
  72. package/packages/client-agent-team/lib/types/client/requests.js +22 -0
  73. package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts +35 -0
  74. package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts.map +1 -0
  75. package/packages/client-agent-team/lib/types/client/sidebar-drag.js +70 -0
  76. package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts +27 -0
  77. package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts.map +1 -0
  78. package/packages/client-agent-team/lib/types/client/sidebar-order.js +170 -0
  79. package/packages/client-agent-team/lib/types/client/slots.d.ts +2 -2
  80. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
  81. package/packages/client-agent-team/lib/types/client/task-refs.d.ts +25 -0
  82. package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +1 -0
  83. package/packages/client-agent-team/lib/types/client/task-refs.js +77 -0
  84. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +54 -1
  85. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
  86. package/packages/client-agent-team/lib/types/client/team-formatters.js +83 -2
  87. package/packages/client-agent-team/lib/types/client/team-membership.d.ts.map +1 -1
  88. package/packages/client-agent-team/lib/types/client/team-membership.js +2 -1
  89. package/packages/tool-agent-team/lib/index.js +4 -4
  90. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts +0 -13
  91. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts.map +0 -1
  92. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.js +0 -90
@@ -1007,7 +1007,7 @@ window.__ModuleLoader__.load({
1007
1007
  };
1008
1008
  //#endregion
1009
1009
  //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js
1010
- const version = {
1010
+ const version$1 = {
1011
1011
  major: 4,
1012
1012
  minor: 4,
1013
1013
  patch: 3
@@ -1019,7 +1019,7 @@ window.__ModuleLoader__.load({
1019
1019
  inst ?? (inst = {});
1020
1020
  inst._zod.def = def;
1021
1021
  inst._zod.bag = inst._zod.bag || {};
1022
- inst._zod.version = version;
1022
+ inst._zod.version = version$1;
1023
1023
  const checks = [...inst._zod.def.checks ?? []];
1024
1024
  if (inst._zod.traits.has("$ZodCheck")) checks.unshift(inst);
1025
1025
  for (const ch of checks) for (const fn of ch._zod.onattach) fn(inst);
@@ -4220,6 +4220,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4220
4220
  literal("reopen")
4221
4221
  ]).readonly(),
4222
4222
  "releasedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
4223
+ "completedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
4223
4224
  "activityRef": intersection(string(), unknown()).readonly(),
4224
4225
  "taskRef": intersection(string(), unknown()).readonly(),
4225
4226
  "threadRef": intersection(string(), unknown()).readonly(),
@@ -4509,6 +4510,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4509
4510
  literal("reopen")
4510
4511
  ]).readonly(),
4511
4512
  "releasedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
4513
+ "completedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
4512
4514
  "activityRef": intersection(string(), unknown()).readonly(),
4513
4515
  "taskRef": intersection(string(), unknown()).readonly(),
4514
4516
  "threadRef": intersection(string(), unknown()).readonly(),
@@ -4636,6 +4638,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4636
4638
  "baseRevision": number().readonly(),
4637
4639
  "recipients": array(intersection(string(), unknown())).readonly().optional(),
4638
4640
  "attachmentPaths": union([_undefined(), array(string())]).readonly().optional(),
4641
+ "attachments": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
4639
4642
  "confirmationToken": intersection(string(), unknown()).readonly().optional()
4640
4643
  });
4641
4644
  const _wowyuarm_dsh_agent_team_agentTeam_reply_result$schema = union([
@@ -4733,52 +4736,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4733
4736
  })).readonly()
4734
4737
  })
4735
4738
  ]);
4736
- const _wowyuarm_dsh_agent_team_agentTeam_restartMember_parameter_0$schema = object({
4737
- "requestId": intersection(string(), unknown()).readonly(),
4739
+ const _wowyuarm_dsh_agent_team_agentTeam_resolveTaskRefs_parameter_0$schema = object({
4738
4740
  "workspaceId": intersection(string(), unknown()).readonly(),
4739
- "memberId": intersection(string(), unknown()).readonly()
4740
- });
4741
- const _wowyuarm_dsh_agent_team_agentTeam_restartMember_result$schema = object({
4742
- "receipt": object({
4743
- "operationId": intersection(string(), unknown()).readonly(),
4744
- "requestId": intersection(string(), unknown()).readonly(),
4745
- "sequence": number().readonly()
4746
- }).readonly(),
4747
- "status": object({
4748
- "member": object({
4749
- "memberId": intersection(string(), unknown()).readonly(),
4750
- "sessionId": intersection(string(), unknown()).readonly(),
4751
- "workspaceId": intersection(string(), unknown()).readonly(),
4752
- "handle": string().readonly(),
4753
- "description": string().readonly(),
4754
- "presetId": string().readonly(),
4755
- "model": union([_undefined(), object({
4756
- "provider": string().readonly(),
4757
- "model": string().readonly(),
4758
- "reasoningEffort": intersection(string(), unknown()).readonly().optional()
4759
- })]).readonly().optional(),
4760
- "privateMemoryPath": string().readonly(),
4761
- "state": union([
4762
- literal("enabled"),
4763
- literal("suspended"),
4764
- literal("inactive")
4765
- ]).readonly()
4766
- }).readonly(),
4767
- "availability": union([
4768
- literal("suspended"),
4769
- literal("inactive"),
4770
- literal("active"),
4771
- literal("unavailable")
4772
- ]).readonly(),
4773
- "presence": union([
4774
- literal("unavailable"),
4775
- literal("available"),
4776
- literal("working"),
4777
- literal("error")
4778
- ]).readonly(),
4779
- "diagnostic": string().readonly().optional()
4780
- }).readonly()
4741
+ "taskRefs": array(intersection(string(), unknown())).readonly()
4781
4742
  });
4743
+ const _wowyuarm_dsh_agent_team_agentTeam_resolveTaskRefs_result$schema = object({ "resolved": array(object({
4744
+ "taskRef": intersection(string(), unknown()).readonly(),
4745
+ "channelRef": intersection(string(), unknown()).readonly(),
4746
+ "threadRef": intersection(string(), unknown()).readonly(),
4747
+ "taskNumber": number().readonly()
4748
+ })).readonly() });
4782
4749
  const _wowyuarm_dsh_agent_team_agentTeam_sendMessage_parameter_0$schema = object({
4783
4750
  "requestId": intersection(string(), unknown()).readonly(),
4784
4751
  "workspaceId": intersection(string(), unknown()).readonly(),
@@ -4961,6 +4928,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4961
4928
  literal("reopen")
4962
4929
  ]).readonly(),
4963
4930
  "releasedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
4931
+ "completedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
4964
4932
  "activityRef": intersection(string(), unknown()).readonly(),
4965
4933
  "taskRef": intersection(string(), unknown()).readonly(),
4966
4934
  "threadRef": intersection(string(), unknown()).readonly(),
@@ -5193,6 +5161,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5193
5161
  literal("reopen")
5194
5162
  ]).readonly(),
5195
5163
  "releasedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
5164
+ "completedClaimRefs": union([_undefined(), array(intersection(string(), unknown()))]).readonly().optional(),
5196
5165
  "activityRef": intersection(string(), unknown()).readonly(),
5197
5166
  "taskRef": intersection(string(), unknown()).readonly(),
5198
5167
  "threadRef": intersection(string(), unknown()).readonly(),
@@ -5251,7 +5220,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5251
5220
  },
5252
5221
  sourceLocation: {
5253
5222
  "file": "packages/agent-team/src/index.ts",
5254
- "line": 325,
5223
+ "line": 378,
5255
5224
  "column": 9
5256
5225
  }
5257
5226
  },
@@ -5278,7 +5247,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5278
5247
  },
5279
5248
  sourceLocation: {
5280
5249
  "file": "packages/agent-team/src/index.ts",
5281
- "line": 663,
5250
+ "line": 641,
5282
5251
  "column": 9
5283
5252
  }
5284
5253
  },
@@ -5306,7 +5275,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5306
5275
  },
5307
5276
  sourceLocation: {
5308
5277
  "file": "packages/agent-team/src/index.ts",
5309
- "line": 262,
5278
+ "line": 315,
5310
5279
  "column": 9
5311
5280
  }
5312
5281
  },
@@ -5333,7 +5302,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5333
5302
  },
5334
5303
  sourceLocation: {
5335
5304
  "file": "packages/agent-team/src/index.ts",
5336
- "line": 543,
5305
+ "line": 541,
5337
5306
  "column": 9
5338
5307
  }
5339
5308
  },
@@ -5360,7 +5329,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5360
5329
  },
5361
5330
  sourceLocation: {
5362
5331
  "file": "packages/agent-team/src/index.ts",
5363
- "line": 303,
5332
+ "line": 356,
5364
5333
  "column": 9
5365
5334
  }
5366
5335
  },
@@ -5387,7 +5356,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5387
5356
  },
5388
5357
  sourceLocation: {
5389
5358
  "file": "packages/agent-team/src/index.ts",
5390
- "line": 640,
5359
+ "line": 627,
5391
5360
  "column": 9
5392
5361
  }
5393
5362
  },
@@ -5414,7 +5383,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5414
5383
  },
5415
5384
  sourceLocation: {
5416
5385
  "file": "packages/agent-team/src/index.ts",
5417
- "line": 673,
5386
+ "line": 650,
5418
5387
  "column": 3
5419
5388
  }
5420
5389
  },
@@ -5441,7 +5410,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5441
5410
  },
5442
5411
  sourceLocation: {
5443
5412
  "file": "packages/agent-team/src/index.ts",
5444
- "line": 553,
5413
+ "line": 551,
5445
5414
  "column": 9
5446
5415
  }
5447
5416
  },
@@ -5469,7 +5438,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5469
5438
  },
5470
5439
  sourceLocation: {
5471
5440
  "file": "packages/agent-team/src/index.ts",
5472
- "line": 253,
5441
+ "line": 306,
5473
5442
  "column": 3
5474
5443
  }
5475
5444
  },
@@ -5496,7 +5465,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5496
5465
  },
5497
5466
  sourceLocation: {
5498
5467
  "file": "packages/agent-team/src/index.ts",
5499
- "line": 627,
5468
+ "line": 614,
5500
5469
  "column": 9
5501
5470
  }
5502
5471
  },
@@ -5523,7 +5492,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5523
5492
  },
5524
5493
  sourceLocation: {
5525
5494
  "file": "packages/agent-team/src/index.ts",
5526
- "line": 680,
5495
+ "line": 657,
5527
5496
  "column": 9
5528
5497
  }
5529
5498
  },
@@ -5550,7 +5519,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5550
5519
  },
5551
5520
  sourceLocation: {
5552
5521
  "file": "packages/agent-team/src/index.ts",
5553
- "line": 382,
5522
+ "line": 429,
5554
5523
  "column": 9
5555
5524
  }
5556
5525
  },
@@ -5577,7 +5546,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5577
5546
  },
5578
5547
  sourceLocation: {
5579
5548
  "file": "packages/agent-team/src/index.ts",
5580
- "line": 565,
5549
+ "line": 562,
5581
5550
  "column": 9
5582
5551
  }
5583
5552
  },
@@ -5604,15 +5573,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5604
5573
  },
5605
5574
  sourceLocation: {
5606
5575
  "file": "packages/agent-team/src/index.ts",
5607
- "line": 648,
5576
+ "line": 635,
5608
5577
  "column": 9
5609
5578
  }
5610
5579
  },
5611
5580
  {
5612
- id: "@wowyuarm/dsh-agent-team#agentTeam/restartMember",
5581
+ id: "@wowyuarm/dsh-agent-team#agentTeam/resolveTaskRefs",
5613
5582
  service: "agentTeam",
5614
5583
  namespace: "agentTeam",
5615
- method: "restartMember",
5584
+ method: "resolveTaskRefs",
5616
5585
  invocation: { kind: "direct" },
5617
5586
  parameters: [{
5618
5587
  name: "request",
@@ -5620,19 +5589,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5620
5589
  source: "json",
5621
5590
  codec: {
5622
5591
  mode: "strict",
5623
- typeSymbol: "@wowyuarm/dsh-agent-team/types#AgentTeamRestartMemberRequest",
5624
- schema: _wowyuarm_dsh_agent_team_agentTeam_restartMember_parameter_0$schema
5592
+ typeSymbol: "@wowyuarm/dsh-agent-team/types#AgentTeamResolveTaskRefsRequest",
5593
+ schema: _wowyuarm_dsh_agent_team_agentTeam_resolveTaskRefs_parameter_0$schema
5625
5594
  }
5626
5595
  }],
5627
5596
  result: {
5628
5597
  mode: "strict",
5629
- typeSymbol: "@wowyuarm/dsh-agent-team/types#AgentTeamRestartMemberResult",
5630
- schema: _wowyuarm_dsh_agent_team_agentTeam_restartMember_result$schema
5598
+ typeSymbol: "@wowyuarm/dsh-agent-team/types#AgentTeamResolveTaskRefsResult",
5599
+ schema: _wowyuarm_dsh_agent_team_agentTeam_resolveTaskRefs_result$schema
5631
5600
  },
5632
5601
  sourceLocation: {
5633
5602
  "file": "packages/agent-team/src/index.ts",
5634
- "line": 401,
5635
- "column": 9
5603
+ "line": 293,
5604
+ "column": 3
5636
5605
  }
5637
5606
  },
5638
5607
  {
@@ -5658,7 +5627,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5658
5627
  },
5659
5628
  sourceLocation: {
5660
5629
  "file": "packages/agent-team/src/index.ts",
5661
- "line": 575,
5630
+ "line": 571,
5662
5631
  "column": 9
5663
5632
  }
5664
5633
  },
@@ -5685,7 +5654,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5685
5654
  },
5686
5655
  sourceLocation: {
5687
5656
  "file": "packages/agent-team/src/index.ts",
5688
- "line": 697,
5657
+ "line": 673,
5689
5658
  "column": 3
5690
5659
  }
5691
5660
  },
@@ -5712,7 +5681,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5712
5681
  },
5713
5682
  sourceLocation: {
5714
5683
  "file": "packages/agent-team/src/index.ts",
5715
- "line": 690,
5684
+ "line": 666,
5716
5685
  "column": 3
5717
5686
  }
5718
5687
  },
@@ -5739,7 +5708,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5739
5708
  },
5740
5709
  sourceLocation: {
5741
5710
  "file": "packages/agent-team/src/index.ts",
5742
- "line": 315,
5711
+ "line": 368,
5743
5712
  "column": 9
5744
5713
  }
5745
5714
  },
@@ -5766,7 +5735,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5766
5735
  },
5767
5736
  sourceLocation: {
5768
5737
  "file": "packages/agent-team/src/index.ts",
5769
- "line": 507,
5738
+ "line": 511,
5770
5739
  "column": 9
5771
5740
  }
5772
5741
  },
@@ -5793,7 +5762,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5793
5762
  },
5794
5763
  sourceLocation: {
5795
5764
  "file": "packages/agent-team/src/index.ts",
5796
- "line": 704,
5765
+ "line": 680,
5797
5766
  "column": 3
5798
5767
  }
5799
5768
  }
@@ -5801,7 +5770,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5801
5770
  };
5802
5771
  //#endregion
5803
5772
  //#region src/client/navigation.ts
5804
- const STORAGE_KEY$1 = "dsh.agent-team.navigation";
5773
+ const STORAGE_KEY$2 = "dsh.agent-team.navigation";
5805
5774
  function readSnapshot() {
5806
5775
  if (typeof localStorage === "undefined") return { mode: "conversation" };
5807
5776
  try {
@@ -5825,7 +5794,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5825
5794
  if (typeof localStorage === "undefined") return;
5826
5795
  try {
5827
5796
  const { mode, workspaceId, channelRef, taskRef, threadRef, taskNumber } = snapshot;
5828
- localStorage.setItem(STORAGE_KEY$1, JSON.stringify({
5797
+ localStorage.setItem(STORAGE_KEY$2, JSON.stringify({
5829
5798
  mode,
5830
5799
  ...workspaceId === void 0 ? {} : { workspaceId },
5831
5800
  ...channelRef === void 0 ? {} : { channelRef },
@@ -6036,7 +6005,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6036
6005
  };
6037
6006
  //#endregion
6038
6007
  //#region src/client/drafts.ts
6039
- const STORAGE_KEY = "dsh.agent-team.drafts.v1";
6008
+ const STORAGE_KEY$1 = "dsh.agent-team.drafts.v1";
6040
6009
  /** Retention ceiling; the oldest savedAt entries fall out first. */
6041
6010
  const LIMIT = 50;
6042
6011
  const EMPTY = Object.freeze({
@@ -6071,7 +6040,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6071
6040
  if (typeof localStorage === "undefined") return;
6072
6041
  try {
6073
6042
  const payload = Object.fromEntries([...entries].map(([key, entry]) => [key, entry]));
6074
- localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
6043
+ localStorage.setItem(STORAGE_KEY$1, JSON.stringify(payload));
6075
6044
  } catch {}
6076
6045
  }
6077
6046
  /**
@@ -6123,7 +6092,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6123
6092
  reset() {
6124
6093
  this.entries = /* @__PURE__ */ new Map();
6125
6094
  this.snapshots.clear();
6126
- if (typeof localStorage !== "undefined") localStorage.removeItem(STORAGE_KEY);
6095
+ if (typeof localStorage !== "undefined") localStorage.removeItem(STORAGE_KEY$1);
6127
6096
  for (const listener of this.listeners) listener();
6128
6097
  }
6129
6098
  /** Re-read persisted content — what a fresh page load starts from. */
@@ -6408,8 +6377,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6408
6377
  return `${(byteSize / (1024 * 1024)).toFixed(1)} MB`;
6409
6378
  }
6410
6379
  //#endregion
6380
+ //#region src/client/requests.ts
6381
+ /** Fresh idempotency identity for one Client-initiated durable request. */
6382
+ const mintRequestId = () => crypto.randomUUID();
6383
+ //#endregion
6411
6384
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/composer.module.css.mjs
6412
- const css$5 = ".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_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:6px;min-height:34px;padding:2px 8px 6px;display:flex}.x9jGQq_attachButton{background:var(--dsw-specific-selector);color:var(--dsw-alias-label-primary);cursor:pointer;border:0;border-radius:999px;flex:none;place-items:center;width:28px;height:28px;margin-right:auto;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_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);outline:none}.x9jGQq_sendButton{background:var(--dsw-alias-button-info-fill,var(--dsw-alias-button-primary-fill));color:#fff;cursor:pointer;border:0;border-radius:50%;justify-content:center;align-items:center;width:34px;height:34px;padding:0;transition:background-color .1s,opacity .1s;display:inline-flex}.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:not-allowed;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}}";
6385
+ const css$5 = ".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_memberSessionRoot{padding:0 var(--dsh-composer-side-clearance) 8px}.x9jGQq_memberSessionCard{font-family:var(--dsw-font-family);gap:6px;padding-top:10px;font-size:16px;line-height:24px}.x9jGQq_memberSessionInputArea textarea{min-height:28px;color:var(--dsw-alias-label-primary);caret-color:var(--dsw-alias-state-business-primary);font-family:var(--dsw-font-family);font-size:inherit;line-height:inherit;padding:4px 12px 0 16px}.x9jGQq_memberSessionStatus{width:100%;max-width:var(--dsh-composer-card-max-width);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-state-error-primary);border-radius:8px;margin:0 0 6px;padding:4px 8px;font-size:12px;line-height:18px}.x9jGQq_memberSessionToolbar{min-width:0;padding:2px 8px 6px}.x9jGQq_memberSessionPrimary{background:var(--dsw-alias-button-info-fill);border-radius:999px;place-items:center;display:grid;transform:translateY(-2px)}.x9jGQq_memberSessionPrimary:hover:not(:disabled){background:var(--dsw-alias-button-info-hover)}.x9jGQq_memberSessionPrimary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.x9jGQq_memberSessionPrimary:disabled{cursor:default;opacity:.4}.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_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:6px;min-height:34px;padding:2px 8px 6px;display:flex}.x9jGQq_attachButton{background:var(--dsw-specific-selector);color:var(--dsw-alias-label-primary);cursor:pointer;border:0;border-radius:999px;flex:none;place-items:center;width:28px;height:28px;margin-right:auto;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);outline:none}.x9jGQq_sendButton{background:var(--dsw-alias-button-info-fill,var(--dsw-alias-button-primary-fill));color:#fff;cursor:pointer;border:0;border-radius:50%;justify-content:center;align-items:center;width:34px;height:34px;padding:0;transition:background-color .1s,opacity .1s;display:inline-flex}.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:not-allowed;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}}";
6413
6386
  const tagId$5 = "@wowyuarm/dsh-agent-team/composer.module.css";
6414
6387
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
6415
6388
  const tag = document.createElement("style");
@@ -6426,9 +6399,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6426
6399
  "fileChip": "x9jGQq_fileChip",
6427
6400
  "fileChipName": "x9jGQq_fileChipName",
6428
6401
  "fileChipRemove": "x9jGQq_fileChipRemove",
6402
+ "fileChipSize": "x9jGQq_fileChipSize",
6429
6403
  "fileChips": "x9jGQq_fileChips",
6430
6404
  "fileInput": "x9jGQq_fileInput",
6405
+ "imageChip": "x9jGQq_imageChip",
6406
+ "imageChipPreview": "x9jGQq_imageChipPreview",
6431
6407
  "inputArea": "x9jGQq_inputArea",
6408
+ "memberSessionCard": "x9jGQq_memberSessionCard",
6409
+ "memberSessionInputArea": "x9jGQq_memberSessionInputArea",
6410
+ "memberSessionPrimary": "x9jGQq_memberSessionPrimary",
6411
+ "memberSessionRoot": "x9jGQq_memberSessionRoot",
6412
+ "memberSessionStatus": "x9jGQq_memberSessionStatus",
6413
+ "memberSessionToolbar": "x9jGQq_memberSessionToolbar",
6432
6414
  "mentionDescription": "x9jGQq_mentionDescription",
6433
6415
  "mentionMenu": "x9jGQq_mentionMenu",
6434
6416
  "mentionName": "x9jGQq_mentionName",
@@ -6464,6 +6446,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6464
6446
  const normalized = query.toLocaleLowerCase();
6465
6447
  return members.filter((status) => status.presence !== "unavailable" && status.member.state !== "inactive" && status.member.handle.toLocaleLowerCase().startsWith(normalized));
6466
6448
  }
6449
+ /** One object URL per draft file; revoked when the draft is removed. */
6450
+ const draftPreviewUrls = /* @__PURE__ */ new WeakMap();
6451
+ function draftPreviewUrl(file) {
6452
+ if (!file.type.startsWith("image/")) return void 0;
6453
+ let url = draftPreviewUrls.get(file);
6454
+ if (url === void 0) {
6455
+ url = URL.createObjectURL(file);
6456
+ draftPreviewUrls.set(file, url);
6457
+ }
6458
+ return url;
6459
+ }
6467
6460
  function TeamComposer({ members, recipients, draft, pending, confirmation, error, onDraftChange, onRecipientsChange, onSubmit, pendingFiles, onFilesChange, t }) {
6468
6461
  const inputRef = (0, react.useRef)(null);
6469
6462
  const fileInputRef = (0, react.useRef)(null);
@@ -6581,7 +6574,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6581
6574
  ref: rootRef,
6582
6575
  className: composer_module_css_default.root,
6583
6576
  onSubmit: (event) => {
6584
- console.log("DBG composer submit pending=%s draft=%j", pending, draft);
6585
6577
  event.preventDefault();
6586
6578
  if (!pending && draft.trim() !== "") onSubmit();
6587
6579
  },
@@ -6666,23 +6658,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6666
6658
  onFilesChange !== void 0 && pendingFiles !== void 0 && pendingFiles.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6667
6659
  className: composer_module_css_default.fileChips,
6668
6660
  "aria-label": t("attachFiles"),
6669
- children: pendingFiles.map((file, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
6670
- className: composer_module_css_default.fileChip,
6671
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6672
- className: composer_module_css_default.fileChipName,
6673
- title: file.name,
6674
- children: file.name
6675
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6676
- type: "button",
6677
- className: composer_module_css_default.fileChipRemove,
6678
- "aria-label": t("removeFile", { name: file.name }),
6679
- disabled: pending,
6680
- onClick: () => {
6681
- onFilesChange(pendingFiles.filter((_, candidate) => candidate !== index));
6682
- },
6683
- children: "×"
6684
- })]
6685
- }, `${file.name}-${index}`))
6661
+ children: pendingFiles.map((file, index) => {
6662
+ const previewUrl = draftPreviewUrl(file);
6663
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
6664
+ className: `${composer_module_css_default.fileChip} ${previewUrl !== void 0 ? composer_module_css_default.imageChip : ""}`,
6665
+ children: [
6666
+ previewUrl !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
6667
+ src: previewUrl,
6668
+ alt: "",
6669
+ className: composer_module_css_default.imageChipPreview
6670
+ }),
6671
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6672
+ className: composer_module_css_default.fileChipName,
6673
+ title: file.name,
6674
+ children: [file.name, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6675
+ className: composer_module_css_default.fileChipSize,
6676
+ children: formatByteSize(file.size)
6677
+ })]
6678
+ }),
6679
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6680
+ type: "button",
6681
+ className: composer_module_css_default.fileChipRemove,
6682
+ "aria-label": t("removeFile", { name: file.name }),
6683
+ disabled: pending,
6684
+ onClick: () => {
6685
+ const url = draftPreviewUrls.get(file);
6686
+ if (url !== void 0) URL.revokeObjectURL(url);
6687
+ onFilesChange(pendingFiles.filter((_, candidate) => candidate !== index));
6688
+ },
6689
+ children: "×"
6690
+ })
6691
+ ]
6692
+ }, `${file.name}-${index}`);
6693
+ })
6686
6694
  }),
6687
6695
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6688
6696
  className: composer_module_css_default.toolbar,
@@ -6729,6 +6737,77 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6729
6737
  });
6730
6738
  }
6731
6739
  //#endregion
6740
+ //#region src/client/task-refs.ts
6741
+ const resolved = /* @__PURE__ */ new Map();
6742
+ const pending = /* @__PURE__ */ new Set();
6743
+ /** Refs the Host did not recognize; never re-queried (no retry loops). */
6744
+ const unresolvable = /* @__PURE__ */ new Set();
6745
+ const listeners$1 = /* @__PURE__ */ new Set();
6746
+ let version = 0;
6747
+ const emit = () => {
6748
+ version += 1;
6749
+ for (const listener of listeners$1) listener();
6750
+ };
6751
+ const subscribe = (listener) => {
6752
+ listeners$1.add(listener);
6753
+ return () => {
6754
+ listeners$1.delete(listener);
6755
+ };
6756
+ };
6757
+ /** Stable snapshot token; the map is read directly after this changes. */
6758
+ const getSnapshot = () => version;
6759
+ /** React binding: re-renders the caller when any ref resolution lands. */
6760
+ const useResolvedTaskRefVersion = () => (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6761
+ const cachedResolvedTaskRef = (taskRef) => resolved.get(taskRef);
6762
+ /** Store one resolution (click path) and wake every rendered link. */
6763
+ const rememberResolvedTaskRef = (entry) => {
6764
+ resolved.set(entry.taskRef, entry);
6765
+ pending.delete(entry.taskRef);
6766
+ emit();
6767
+ };
6768
+ /** Click-path Host lookup: remember every resolved entry and hand them back for immediate navigation. */
6769
+ const hostTaskRefLookup = (resolveTaskRefs, workspaceId) => async (taskRefs) => {
6770
+ const result = await resolveTaskRefs({
6771
+ workspaceId,
6772
+ taskRefs
6773
+ });
6774
+ if (!result.ok) return [];
6775
+ for (const entry of result.value.resolved) rememberResolvedTaskRef(entry);
6776
+ return result.value.resolved;
6777
+ };
6778
+ /** Resolve one Task ref through the Host and jump to its home Channel Thread. */
6779
+ const jumpToTaskThread = (resolveTaskRefs, workspaceId, taskRef, selectThread) => {
6780
+ resolveTaskRefs({
6781
+ workspaceId,
6782
+ taskRefs: [taskRef]
6783
+ }).then((result) => {
6784
+ if (!result.ok) return;
6785
+ const hit = result.value.resolved[0];
6786
+ if (hit !== void 0) selectThread(hit.taskRef, hit.threadRef, hit.channelRef, hit.taskNumber);
6787
+ });
6788
+ };
6789
+ /**
6790
+ * Batch-resolve unknown refs through the Host lookup. Concurrent callers
6791
+ * deduplicate through the pending set; failures just clear the pending mark
6792
+ * so a later interaction can retry.
6793
+ */
6794
+ const resolveUnknownTaskRefs = async (refs, lookup) => {
6795
+ const missing = refs.filter((taskRef) => !resolved.has(taskRef) && !pending.has(taskRef) && !unresolvable.has(taskRef));
6796
+ if (missing.length === 0) return;
6797
+ for (const taskRef of missing) pending.add(taskRef);
6798
+ try {
6799
+ const entries = await lookup(missing);
6800
+ for (const entry of entries) {
6801
+ resolved.set(entry.taskRef, entry);
6802
+ pending.delete(entry.taskRef);
6803
+ }
6804
+ for (const taskRef of missing) if (!resolved.has(taskRef)) unresolvable.add(taskRef);
6805
+ if (entries.length > 0) emit();
6806
+ } finally {
6807
+ for (const taskRef of missing) pending.delete(taskRef);
6808
+ }
6809
+ };
6810
+ //#endregion
6732
6811
  //#region src/client/team-formatters.ts
6733
6812
  function formatTaskStatus(status, t) {
6734
6813
  return t({
@@ -6772,6 +6851,49 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6772
6851
  for (let index = 0; index < memberId.length; index += 1) hash = (hash * 31 + memberId.charCodeAt(index)) % 360;
6773
6852
  return hash;
6774
6853
  }
6854
+ const BRANDED_REF_PATTERN = /\b(task|channel|thread):{1,2}[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
6855
+ /**
6856
+ * Canonical form of one matched ref: models occasionally double the colon or
6857
+ * uppercase the UUID when citing a ref in prose, while Host lookups and
6858
+ * navigation only accept the lowercase single-colon ref the ledger mints.
6859
+ */
6860
+ function canonicalBrandedRef(match) {
6861
+ return match.replace("::", ":").toLowerCase();
6862
+ }
6863
+ /**
6864
+ * Split a literal text run into plain and branded-ref segments. The pattern
6865
+ * anchors on the fixed ref prefixes plus the UUID shape, so ordinary prose
6866
+ * containing a colon never linkifies; a doubled colon from model output is
6867
+ * tolerated. Segment refs are always canonical, so resolution and navigation
6868
+ * work regardless of how the ref was spelled; text without any ref comes
6869
+ * back as one untouched segment.
6870
+ */
6871
+ function splitBrandedRefs(text) {
6872
+ const segments = [];
6873
+ let cursor = 0;
6874
+ for (const match of text.matchAll(BRANDED_REF_PATTERN)) {
6875
+ const start = match.index ?? 0;
6876
+ if (start > cursor) segments.push({ text: text.slice(cursor, start) });
6877
+ segments.push({
6878
+ text: match[0],
6879
+ ref: canonicalBrandedRef(match[0])
6880
+ });
6881
+ cursor = start + match[0].length;
6882
+ }
6883
+ if (cursor < text.length) segments.push({ text: text.slice(cursor) });
6884
+ return segments;
6885
+ }
6886
+ /**
6887
+ * Whether one string's whole content is exactly one branded ref. A code span
6888
+ * like this is the model styling a ref as an identifier, not publishing code,
6889
+ * so the Markdown pass may linkify it; anything larger stays literal.
6890
+ */
6891
+ function isSingleBrandedRef(text) {
6892
+ const trimmed = text.trim();
6893
+ if (trimmed === "") return false;
6894
+ const matches = [...trimmed.matchAll(BRANDED_REF_PATTERN)];
6895
+ return matches.length === 1 && matches[0][0] === trimmed;
6896
+ }
6775
6897
  function escapeRegExp(value) {
6776
6898
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6777
6899
  }
@@ -6852,7 +6974,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6852
6974
  }
6853
6975
  function formatActivity(activity, options) {
6854
6976
  const actor = options.actorName(activity.actor);
6855
- if (activity.kind === "accept") return options.t("activityAccepted", { actor });
6977
+ if (activity.kind === "accept") return activity.completedClaimRefs !== void 0 && activity.completedClaimRefs.length > 0 ? options.t("activityAcceptedWithClaims", {
6978
+ actor,
6979
+ count: activity.completedClaimRefs.length
6980
+ }) : options.t("activityAccepted", { actor });
6856
6981
  if (activity.kind === "close") return options.t("activityClosed", { actor });
6857
6982
  if (activity.kind === "reopen") return options.t("activityReopened", { actor });
6858
6983
  const direction = "claimRef" in activity ? options.claims.find((claim) => claim.claimRef === activity.claimRef)?.direction ?? options.t("claims") : options.t("claims");
@@ -6878,9 +7003,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6878
7003
  function stripAttachmentLines(body) {
6879
7004
  return body.replaceAll(/^\[attachment\] .*$(\n)?/gm, "").replace(/\n+$/, "");
6880
7005
  }
7006
+ /**
7007
+ * Decide how one Message body renders. Human input and plain-prose Agent
7008
+ * bodies stay literal, with structured mention chips inline where possible;
7009
+ * rich Agent Markdown keeps unmatched mentions and non-Task refs in the
7010
+ * trailing fallback row while the post-render pass handles Task refs at their
7011
+ * authored position. Surfaces without ref navigation render everything
7012
+ * literally and keep the full fallback row.
7013
+ */
7014
+ function planMessageBody(body, options) {
7015
+ const stripped = stripAttachmentLines(body);
7016
+ const displayBody = stripped === "" ? body : stripped;
7017
+ const richAgentBody = !options.human && !isPlainTextBody(displayBody);
7018
+ const inline = (options.human || isPlainTextBody(displayBody)) && options.mentionNames !== void 0 && options.mentionNames.length > 0 ? splitMentionNames(displayBody, options.mentionNames) : void 0;
7019
+ const fallbackNames = inline !== void 0 ? inline.unmatched : richAgentBody && options.canOpenRefs && options.mentionNames !== void 0 ? splitMentionNames(displayBody, options.mentionNames).unmatched : options.mentionNames ?? [];
7020
+ const refs = splitBrandedRefs(displayBody).flatMap((segment) => segment.ref === void 0 ? [] : [segment.ref]);
7021
+ return {
7022
+ displayBody,
7023
+ richAgentBody,
7024
+ render: inline !== void 0 ? "inline" : options.human || options.canOpenRefs && !richAgentBody && refs.length > 0 ? "literal" : "markdown",
7025
+ ...inline === void 0 ? {} : { inline },
7026
+ fallbackNames,
7027
+ fallbackRefs: richAgentBody && options.canOpenRefs ? refs.filter((ref) => !ref.startsWith("task:")) : [],
7028
+ taskRefs: options.canOpenRefs && !richAgentBody ? refs.filter((ref) => ref.startsWith("task:")).map((ref) => ref) : []
7029
+ };
7030
+ }
6881
7031
  //#endregion
6882
7032
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/conversation.module.css.mjs
6883
- const css$4 = ".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{margin-top:0}.omcBaG_messageIdentity{background:hsl(var(--team-avatar-hue,212) 42% 46%);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_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);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){border-top:1px solid var(--dsw-alias-border-l2);margin-top:3px;padding-top:7px}.omcBaG_runDivider{border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);margin:2px 0 0;padding:5px 0 0 38px;font-size:11px;line-height:16px}.omcBaG_runDivider+.omcBaG_messageRow[data-grouped]:has(.omcBaG_messageBody>button){border-top:0;margin-top:0}.omcBaG_mention{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);color:var(--dsw-alias-state-business-primary);border-radius:5px;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_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}";
7033
+ const css$4 = ".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{margin-top:0}.omcBaG_messageIdentity{background:hsl(var(--team-avatar-hue,212) 42% 46%);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_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);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){border-top:1px solid var(--dsw-alias-border-l2);margin-top:3px;padding-top:7px}.omcBaG_runDivider{border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);margin:2px 0 0;padding:5px 0 0 38px;font-size:11px;line-height:16px}.omcBaG_runDivider+.omcBaG_messageRow[data-grouped]:has(.omcBaG_messageBody>button){border-top:0;margin-top:0}.omcBaG_mention{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);color:var(--dsw-alias-state-business-primary);border-radius:5px;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}";
6884
7034
  const tagId$4 = "@wowyuarm/dsh-agent-team/conversation.module.css";
6885
7035
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
6886
7036
  const tag = document.createElement("style");
@@ -6898,6 +7048,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6898
7048
  "attachmentThumb": "omcBaG_attachmentThumb",
6899
7049
  "attachmentZoom": "omcBaG_attachmentZoom",
6900
7050
  "backRow": "omcBaG_backRow",
7051
+ "confirmBody": "omcBaG_confirmBody",
7052
+ "confirmList": "omcBaG_confirmList",
6901
7053
  "emptyState": "omcBaG_emptyState",
6902
7054
  "emptySurface": "omcBaG_emptySurface",
6903
7055
  "error": "omcBaG_error",
@@ -6918,6 +7070,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6918
7070
  "messageTime": "omcBaG_messageTime",
6919
7071
  "nameRow": "omcBaG_nameRow",
6920
7072
  "pulse": "omcBaG_pulse",
7073
+ "refLink": "omcBaG_refLink",
6921
7074
  "runDivider": "omcBaG_runDivider",
6922
7075
  "surface": "omcBaG_surface",
6923
7076
  "surfaceHeader": "omcBaG_surfaceHeader",
@@ -6931,11 +7084,66 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6931
7084
  //#endregion
6932
7085
  //#region src/client/TeamMessage.tsx
6933
7086
  /** One chat message row with identity chrome and sender-appropriate rendering. */
6934
- function TeamMessage({ senderName, memberId, human, body, occurredAt, mentionNames, senderTitle, grouped, attachments, loadAttachment, t, children }) {
7087
+ function TeamMessage({ senderName, memberId, human, body, occurredAt, mentionNames, senderTitle, grouped, attachments, loadAttachment, t, onOpenRef, onResolveTaskRefs, children }) {
6935
7088
  const avatarStyle = human ? void 0 : { "--team-avatar-hue": memberHue(memberId) };
6936
- const displayBody = stripAttachmentLines(body) === "" ? body : stripAttachmentLines(body);
6937
- const inline = (human || isPlainTextBody(displayBody)) && mentionNames !== void 0 && mentionNames.length > 0 ? splitMentionNames(displayBody, mentionNames) : void 0;
6938
- const fallbackNames = inline === void 0 ? mentionNames ?? [] : inline.unmatched;
7089
+ const plan = planMessageBody(body, {
7090
+ human,
7091
+ ...mentionNames === void 0 ? {} : { mentionNames },
7092
+ canOpenRefs: onOpenRef !== void 0
7093
+ });
7094
+ const displayBody = plan.displayBody;
7095
+ const { richAgentBody } = plan;
7096
+ const refVersion = useResolvedTaskRefVersion();
7097
+ const bodyTaskRefs = plan.taskRefs;
7098
+ const bodyTaskRefKey = bodyTaskRefs.join(",");
7099
+ (0, react.useEffect)(() => {
7100
+ if (onResolveTaskRefs === void 0 || bodyTaskRefKey === "") return;
7101
+ resolveUnknownTaskRefs(bodyTaskRefs, onResolveTaskRefs);
7102
+ }, [
7103
+ onResolveTaskRefs,
7104
+ bodyTaskRefKey,
7105
+ refVersion
7106
+ ]);
7107
+ const taskLabel = (0, react.useCallback)((taskNumber) => t?.("taskLabel", { number: taskNumber }) ?? `Task #${taskNumber}`, [t]);
7108
+ const markdownRef = (0, react.useRef)(null);
7109
+ (0, react.useLayoutEffect)(() => {
7110
+ const root = markdownRef.current;
7111
+ if (!richAgentBody || root === null || onOpenRef === void 0) return;
7112
+ const textNodes = markdownProseTextNodes(root);
7113
+ const styledRefCodes = markdownStyledRefCodeElements(root);
7114
+ const taskRefs = [...new Set([...textNodes.map((node) => node.data), ...styledRefCodes.map((code) => code.textContent ?? "")].flatMap((text) => splitBrandedRefs(text).filter((segment) => segment.ref?.startsWith("task:") === true).map((segment) => segment.ref)))];
7115
+ if (onResolveTaskRefs !== void 0 && taskRefs.length > 0) resolveUnknownTaskRefs(taskRefs, onResolveTaskRefs);
7116
+ for (const code of styledRefCodes) renderResolvedMarkdownCodeRef(code, taskLabel);
7117
+ for (const node of textNodes) renderResolvedMarkdownText(node, mentionNames ?? [], taskLabel);
7118
+ for (const button of root.querySelectorAll("button[data-task-ref]")) {
7119
+ const taskRef = button.dataset.taskRef;
7120
+ const hit = taskRef === void 0 ? void 0 : cachedResolvedTaskRef(taskRef);
7121
+ if (taskRef !== void 0 && hit !== void 0) button.textContent = taskLabel(hit.taskNumber);
7122
+ }
7123
+ }, [
7124
+ richAgentBody,
7125
+ onOpenRef,
7126
+ onResolveTaskRefs,
7127
+ refVersion,
7128
+ taskLabel,
7129
+ mentionNames
7130
+ ]);
7131
+ (0, react.useEffect)(() => {
7132
+ const root = markdownRef.current;
7133
+ if (!richAgentBody || root === null || onOpenRef === void 0) return;
7134
+ const openTask = (event) => {
7135
+ const target = event.target;
7136
+ if (!(target instanceof Element)) return;
7137
+ const button = target.closest("button[data-task-ref]");
7138
+ if (button === null || !root.contains(button)) return;
7139
+ const taskRef = button instanceof HTMLElement ? button.dataset.taskRef : void 0;
7140
+ if (taskRef !== void 0) onOpenRef(taskRef);
7141
+ };
7142
+ root.addEventListener("click", openTask);
7143
+ return () => {
7144
+ root.removeEventListener("click", openTask);
7145
+ };
7146
+ }, [richAgentBody, onOpenRef]);
6939
7147
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
6940
7148
  className: conversation_module_css_default.messageRow,
6941
7149
  "data-human": human || void 0,
@@ -6958,25 +7166,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6958
7166
  children: formatMessageTime(occurredAt)
6959
7167
  })]
6960
7168
  }),
6961
- inline !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7169
+ plan.render === "inline" && plan.inline !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6962
7170
  className: conversation_module_css_default.messageText,
6963
- children: inline.segments.map((segment, index) => segment.mention ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7171
+ children: plan.inline.segments.map((segment, index) => segment.mention ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6964
7172
  className: conversation_module_css_default.mention,
6965
7173
  children: segment.text
6966
- }, index) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: segment.text }, index))
6967
- }) : human ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7174
+ }, index) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderRefs(segment.text, onOpenRef, taskLabel) }, index))
7175
+ }) : plan.render === "literal" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6968
7176
  className: conversation_module_css_default.messageText,
6969
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MessageText, { text: displayBody })
7177
+ children: onOpenRef === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MessageText, { text: displayBody }) : renderRefs(displayBody, onOpenRef, taskLabel)
6970
7178
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7179
+ ref: markdownRef,
6971
7180
  className: conversation_module_css_default.messageMarkdown,
6972
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: displayBody })
7181
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: displayBody }, `${displayBody}:${onOpenRef === void 0 ? "literal" : "refs"}`)
6973
7182
  }),
6974
- fallbackNames.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7183
+ (plan.fallbackNames.length > 0 || plan.fallbackRefs.length > 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6975
7184
  className: conversation_module_css_default.mentionsRow,
6976
- children: fallbackNames.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7185
+ children: [plan.fallbackNames.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6977
7186
  className: conversation_module_css_default.mention,
6978
7187
  children: ["@", name]
6979
- }, name))
7188
+ }, name)), plan.fallbackRefs.map((ref) => {
7189
+ const resolved = cachedResolvedTaskRef(ref);
7190
+ const label = resolved !== void 0 && ref.startsWith("task:") ? taskLabel(resolved.taskNumber) : ref;
7191
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7192
+ type: "button",
7193
+ className: conversation_module_css_default.refLink,
7194
+ title: ref,
7195
+ onClick: () => {
7196
+ onOpenRef(ref);
7197
+ },
7198
+ children: label
7199
+ }, ref);
7200
+ })]
6980
7201
  }),
6981
7202
  attachments !== void 0 && attachments.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamAttachmentStrip, {
6982
7203
  attachments,
@@ -6988,6 +7209,96 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6988
7209
  })]
6989
7210
  });
6990
7211
  }
7212
+ /** Text nodes that Markdown rendered as prose rather than code or a link. */
7213
+ function markdownProseTextNodes(root) {
7214
+ const nodes = [];
7215
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
7216
+ for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
7217
+ const parent = node.parentElement;
7218
+ if (parent === null) continue;
7219
+ if (parent.closest("code, pre, a, button") !== null) continue;
7220
+ if (conversation_module_css_default.mention !== void 0 && parent.closest(`[class~="${conversation_module_css_default.mention}"]`) !== null) continue;
7221
+ nodes.push(node);
7222
+ }
7223
+ return nodes;
7224
+ }
7225
+ /** Code spans whose entire content is one branded ref: model styling around a ref, not code. */
7226
+ function markdownStyledRefCodeElements(root) {
7227
+ const elements = [];
7228
+ for (const code of root.querySelectorAll("code")) {
7229
+ if (code.closest("pre, a, button") !== null) continue;
7230
+ if (!isSingleBrandedRef(code.textContent ?? "")) continue;
7231
+ elements.push(code);
7232
+ }
7233
+ return elements;
7234
+ }
7235
+ /** One resolved Task-ref chip built outside React, matching the styled ref link. */
7236
+ function resolvedTaskRefButton(taskRef, label) {
7237
+ const button = document.createElement("button");
7238
+ button.type = "button";
7239
+ if (conversation_module_css_default.refLink !== void 0) button.className = conversation_module_css_default.refLink;
7240
+ button.dataset.taskRef = taskRef;
7241
+ button.title = taskRef;
7242
+ button.textContent = label;
7243
+ return button;
7244
+ }
7245
+ /** Replace a whole-ref code span with its resolved Task chip once known. */
7246
+ function renderResolvedMarkdownCodeRef(code, taskLabel) {
7247
+ const segments = splitBrandedRefs((code.textContent ?? "").trim());
7248
+ const segment = segments.length === 1 ? segments[0] : void 0;
7249
+ const taskRef = segment?.ref?.startsWith("task:") === true ? segment.ref : void 0;
7250
+ const resolved = taskRef === void 0 ? void 0 : cachedResolvedTaskRef(taskRef);
7251
+ if (taskRef === void 0 || resolved === void 0) return;
7252
+ code.replaceWith(resolvedTaskRefButton(taskRef, taskLabel(resolved.taskNumber)));
7253
+ }
7254
+ /** Replace resolved Task refs and structured mention handles in one prose text node without changing Markdown structure. */
7255
+ function renderResolvedMarkdownText(node, mentionNames, taskLabel) {
7256
+ let changed = false;
7257
+ const fragment = document.createDocumentFragment();
7258
+ for (const refSegment of splitBrandedRefs(node.data)) {
7259
+ if (refSegment.ref === void 0) {
7260
+ for (const mentionSegment of splitMentionNames(refSegment.text, mentionNames).segments) {
7261
+ if (!mentionSegment.mention) {
7262
+ fragment.append(mentionSegment.text);
7263
+ continue;
7264
+ }
7265
+ changed = true;
7266
+ const chip = document.createElement("span");
7267
+ if (conversation_module_css_default.mention !== void 0) chip.className = conversation_module_css_default.mention;
7268
+ chip.textContent = mentionSegment.text;
7269
+ fragment.append(chip);
7270
+ }
7271
+ continue;
7272
+ }
7273
+ const taskRef = refSegment.ref.startsWith("task:") === true ? refSegment.ref : void 0;
7274
+ const resolved = taskRef === void 0 ? void 0 : cachedResolvedTaskRef(taskRef);
7275
+ if (resolved === void 0) {
7276
+ fragment.append(refSegment.text);
7277
+ continue;
7278
+ }
7279
+ changed = true;
7280
+ fragment.append(resolvedTaskRefButton(taskRef, taskLabel(resolved.taskNumber)));
7281
+ }
7282
+ if (changed) node.replaceWith(fragment);
7283
+ }
7284
+ /** Render one literal text run, linkifying branded refs when navigation is available. */
7285
+ function renderRefs(text, onOpenRef, taskLabel) {
7286
+ if (onOpenRef === void 0) return text;
7287
+ return splitBrandedRefs(text).map((segment, index) => {
7288
+ if (segment.ref === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: segment.text }, index);
7289
+ const resolved = cachedResolvedTaskRef(segment.ref);
7290
+ const label = resolved !== void 0 && segment.ref.startsWith("task:") ? taskLabel(resolved.taskNumber) : segment.ref;
7291
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7292
+ type: "button",
7293
+ className: conversation_module_css_default.refLink,
7294
+ title: segment.ref,
7295
+ onClick: () => {
7296
+ onOpenRef(segment.ref);
7297
+ },
7298
+ children: label
7299
+ }, index);
7300
+ });
7301
+ }
6991
7302
  /** One message's attachment strip: image thumbnails with a large view, or name chips when bytes are gone. */
6992
7303
  function TeamAttachmentStrip({ attachments, loadAttachment, t }) {
6993
7304
  const [zoomed, setZoomed] = (0, react.useState)();
@@ -7096,7 +7407,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7096
7407
  return next;
7097
7408
  });
7098
7409
  const key = `${membership.joined ? "remove" : "join"}:${membership.memberId}:${membership.channelRef}`;
7099
- const requestId = requestIds.current.get(key) ?? crypto.randomUUID();
7410
+ const requestId = requestIds.current.get(key) ?? mintRequestId();
7100
7411
  requestIds.current.set(key, requestId);
7101
7412
  const request = {
7102
7413
  requestId,
@@ -7327,7 +7638,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7327
7638
  hasMore: fresh.hasMore || current.cursor < fresh.cursor
7328
7639
  };
7329
7640
  }
7330
- function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, backToChannels, t }) {
7641
+ function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, selectChannel, backToChannels, resolveTaskRefs, t }) {
7331
7642
  const [view, setView] = (0, react.useState)();
7332
7643
  const [members, setMembers] = (0, react.useState)([]);
7333
7644
  const [error, setError] = (0, react.useState)();
@@ -7344,6 +7655,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7344
7655
  const mountedRef = (0, react.useRef)(false);
7345
7656
  const refreshSequenceRef = (0, react.useRef)(0);
7346
7657
  const channelLastItem = view?.items[view.items.length - 1];
7658
+ const openRef = (ref) => {
7659
+ if (ref.startsWith("channel:")) {
7660
+ if (ref !== channelRef) selectChannel(ref);
7661
+ return;
7662
+ }
7663
+ if (ref.startsWith("task:")) {
7664
+ const match = view?.items.find((item) => item.task.taskRef === ref);
7665
+ if (match !== void 0) {
7666
+ selectThread(match.task.taskRef, match.thread.threadRef, channelRef, match.taskNumber);
7667
+ return;
7668
+ }
7669
+ jumpToTaskThread(resolveTaskRefs, workspaceId, ref, selectThread);
7670
+ }
7671
+ };
7672
+ const lookupTaskRefs = hostTaskRefLookup(resolveTaskRefs, workspaceId);
7347
7673
  const timeline = useTimelineScroll(`${view?.items.length ?? 0}:${channelLastItem?.message.messageRef ?? ""}`);
7348
7674
  const channel = view?.channels.find((item) => item.channelRef === channelRef);
7349
7675
  const channelMemberIds = new Set(view?.members.filter((item) => item.channelRef === channelRef).map((item) => item.memberId) ?? []);
@@ -7472,10 +7798,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7472
7798
  });
7473
7799
  const pendingSendId = (0, react.useRef)();
7474
7800
  const send = async () => {
7475
- console.log("DBG send entry pending=%s draft=%j files=%d", pending, draft, pendingFiles.length);
7476
7801
  if (pending || draft.trim() === "") return;
7477
7802
  const recipientIds = [...recipients].sort();
7478
- const requestId = pendingSendId.current ?? crypto.randomUUID();
7803
+ const requestId = pendingSendId.current ?? mintRequestId();
7479
7804
  pendingSendId.current = requestId;
7480
7805
  setPending(true);
7481
7806
  setError(void 0);
@@ -7484,7 +7809,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7484
7809
  const attachmentIds = [];
7485
7810
  for (const file of pendingFiles) {
7486
7811
  const uploaded = await putAttachment({
7487
- requestId: crypto.randomUUID(),
7812
+ requestId: mintRequestId(),
7488
7813
  workspaceId,
7489
7814
  name: file.name,
7490
7815
  mediaType: file.type === "" ? void 0 : file.type,
@@ -7689,6 +8014,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7689
8014
  t,
7690
8015
  occurredAt: item.message.occurredAt,
7691
8016
  mentionNames: mentionNamesOf(item.mentions, mentionHandlesMap),
8017
+ onOpenRef: openRef,
8018
+ onResolveTaskRefs: lookupTaskRefs,
7692
8019
  grouped: index > 0,
7693
8020
  ...senderStatus === void 0 ? {} : { senderTitle: senderStatus.member.description },
7694
8021
  children: item.message.topLevel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
@@ -7787,7 +8114,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7787
8114
  return new Map(facts.map((fact) => [factKey(fact.fact), fact]));
7788
8115
  }
7789
8116
  function TeamThreadPage(props) {
7790
- const { workspaceId, channelRef, taskRef, threadRef, taskNumber, backToWorkspace, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, drafts, getAttachment, reply, changeTask, t } = props;
8117
+ const { workspaceId, channelRef, taskRef, threadRef, taskNumber, backToWorkspace, selectChannel, selectThread, resolveTaskRefs, putAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, drafts, getAttachment, reply, changeTask, t } = props;
7791
8118
  const [projection, setProjection] = (0, react.useState)();
7792
8119
  const [channelView, setChannelView] = (0, react.useState)();
7793
8120
  const [members, setMembers] = (0, react.useState)([]);
@@ -7801,6 +8128,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7801
8128
  const draftKey = `thread:${threadRef}`;
7802
8129
  const { draft, recipients } = (0, react.useSyncExternalStore)(drafts.subscribe, () => drafts.getSnapshot(draftKey));
7803
8130
  const [claimsOpen, setClaimsOpen] = (0, react.useState)(false);
8131
+ const [confirmingAccept, setConfirmingAccept] = (0, react.useState)(false);
8132
+ (0, react.useEffect)(() => {
8133
+ if (confirmingAccept && projection?.task.resolution === "accepted") setConfirmingAccept(false);
8134
+ }, [confirmingAccept, projection?.task.resolution]);
7804
8135
  const [replyRequestId, setReplyRequestId] = (0, react.useState)();
7805
8136
  const [confirmation, setConfirmation] = (0, react.useState)();
7806
8137
  const [statusMessage, setStatusMessage] = (0, react.useState)();
@@ -7810,7 +8141,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7810
8141
  const mountedRef = (0, react.useRef)(false);
7811
8142
  const currentFactsRef = (0, react.useRef)([]);
7812
8143
  const sequenceRef = (0, react.useRef)(0);
7813
- const readRequestIdRef = (0, react.useRef)(crypto.randomUUID());
8144
+ const readRequestIdRef = (0, react.useRef)(mintRequestId());
7814
8145
  const mutationRequests = (0, react.useRef)(/* @__PURE__ */ new Map());
7815
8146
  const threadLastFact = currentFacts[currentFacts.length - 1];
7816
8147
  const timeline = useTimelineScroll(`${currentFacts.length}:${olderFacts.length}:${threadLastFact === void 0 ? "" : factKey(threadLastFact)}`);
@@ -7828,7 +8159,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7828
8159
  };
7829
8160
  const readCurrent = async (newRequest = false) => {
7830
8161
  if (!mountedRef.current) return false;
7831
- if (newRequest) readRequestIdRef.current = crypto.randomUUID();
8162
+ if (newRequest) readRequestIdRef.current = mintRequestId();
7832
8163
  const sequence = sequenceRef.current + 1;
7833
8164
  sequenceRef.current = sequence;
7834
8165
  setLoading(true);
@@ -8025,14 +8356,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8025
8356
  const mentionHandlesMap = (0, react.useMemo)(() => new Map(members.map((status) => [status.member.memberId, status.member.handle.replace(/^@/, "")])), [members]);
8026
8357
  const metadata = (0, react.useMemo)(() => readMeta(readFacts), [readFacts]);
8027
8358
  const unreadIndex = (0, react.useMemo)(() => {
8028
- return mergeFacts([
8029
- messageFact(activeProjection?.anchor ?? {
8030
- messageRef: "missing",
8031
- sequence: 0
8032
- }, activeProjection?.anchorMentions),
8033
- ...readFacts.map((fact) => fact.fact),
8034
- ...currentFacts
8035
- ]).findIndex((fact) => metadata.get(factKey(fact))?.unread === true);
8359
+ return mergeFacts(...activeProjection === void 0 ? [] : [[messageFact(activeProjection.anchor, activeProjection.anchorMentions)]], readFacts.map((fact) => fact.fact), currentFacts).findIndex((fact) => metadata.get(factKey(fact))?.unread === true);
8036
8360
  }, [
8037
8361
  activeProjection?.anchor,
8038
8362
  readFacts,
@@ -8045,6 +8369,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8045
8369
  return status === void 0 ? t("memberUnknown") : `@${status.member.handle}`;
8046
8370
  };
8047
8371
  const messageSender = (fact) => fact.kind === "message" ? fact.message.sender : void 0;
8372
+ const [pendingFiles, setPendingFiles] = (0, react.useState)([]);
8373
+ const openRef = (ref) => {
8374
+ if (ref.startsWith("channel:") && ref !== channelRef) selectChannel(ref);
8375
+ if (ref.startsWith("task:") && ref !== taskRef) jumpToTaskThread(resolveTaskRefs, workspaceId, ref, selectThread);
8376
+ };
8377
+ const lookupTaskRefs = hostTaskRefLookup(resolveTaskRefs, workspaceId);
8048
8378
  const renderFact = (fact, grouped = false) => {
8049
8379
  if (fact.kind === "message") {
8050
8380
  const sender = memberName(fact.message.sender);
@@ -8059,6 +8389,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8059
8389
  t,
8060
8390
  occurredAt: fact.message.occurredAt,
8061
8391
  mentionNames: mentionNamesOf(fact.mentions, mentionHandlesMap),
8392
+ onOpenRef: openRef,
8393
+ onResolveTaskRefs: lookupTaskRefs,
8062
8394
  grouped,
8063
8395
  ...senderStatus === void 0 ? {} : { senderTitle: senderStatus.member.description }
8064
8396
  }, factKey(fact));
@@ -8134,7 +8466,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8134
8466
  setPending(true);
8135
8467
  setError(void 0);
8136
8468
  const key = `task:${action}`;
8137
- const requestId = mutationRequests.current.get(key) ?? crypto.randomUUID();
8469
+ const requestId = mutationRequests.current.get(key) ?? mintRequestId();
8138
8470
  mutationRequests.current.set(key, requestId);
8139
8471
  try {
8140
8472
  const result = await changeTask({
@@ -8185,11 +8517,26 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8185
8517
  };
8186
8518
  const sendReply = async () => {
8187
8519
  if (pending || task === void 0 || thread === void 0 || draft.trim() === "") return;
8188
- const id = replyRequestId ?? crypto.randomUUID();
8520
+ const id = replyRequestId ?? mintRequestId();
8189
8521
  setReplyRequestId(id);
8190
8522
  setPending(true);
8191
8523
  setError(void 0);
8192
8524
  try {
8525
+ const attachmentIds = [];
8526
+ for (const file of pendingFiles) {
8527
+ const uploaded = await putAttachment({
8528
+ requestId: mintRequestId(),
8529
+ workspaceId,
8530
+ name: file.name,
8531
+ mediaType: file.type === "" ? void 0 : file.type,
8532
+ bytesBase64: bytesToBase64(new Uint8Array(await file.arrayBuffer()))
8533
+ });
8534
+ if (!uploaded.ok) {
8535
+ setError(uploaded.error.message);
8536
+ return;
8537
+ }
8538
+ attachmentIds.push(uploaded.value.attachmentId);
8539
+ }
8193
8540
  const result = await reply({
8194
8541
  requestId: id,
8195
8542
  workspaceId,
@@ -8197,6 +8544,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8197
8544
  body: draft.trim(),
8198
8545
  baseRevision: thread.revision,
8199
8546
  recipients: [...recipients].sort(),
8547
+ ...attachmentIds.length === 0 ? {} : { attachments: attachmentIds },
8200
8548
  ...confirmation === void 0 ? {} : { confirmationToken: confirmation }
8201
8549
  });
8202
8550
  if (!result.ok) {
@@ -8221,6 +8569,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8221
8569
  thread: committed.thread
8222
8570
  });
8223
8571
  drafts.clear(draftKey);
8572
+ setPendingFiles([]);
8224
8573
  setReplyRequestId(void 0);
8225
8574
  setConfirmation(void 0);
8226
8575
  setStatusMessage(void 0);
@@ -8291,15 +8640,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8291
8640
  })]
8292
8641
  }), task !== void 0 && thread !== void 0 && task.resolution !== "closed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8293
8642
  className: conversation_module_css_default.headerActions,
8294
- children: [task.status === "in_review" && task.resolution === "open" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8295
- size: "sm",
8296
- variant: "primary",
8297
- disabled: pending,
8298
- onClick: () => {
8299
- mutateTask("accept");
8300
- },
8301
- children: t("acceptTask")
8302
- }), task.resolution === "open" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8643
+ children: [(() => {
8644
+ const activeClaims = projection?.claims.filter((claim) => claim.taskRef === task.taskRef && claim.state === "active") ?? [];
8645
+ const earlyAccept = task.resolution === "open" && task.status === "in_progress" && activeClaims.length > 0;
8646
+ if (!(task.status === "in_review" || earlyAccept) || task.resolution !== "open") return null;
8647
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8648
+ size: "sm",
8649
+ variant: "primary",
8650
+ disabled: pending,
8651
+ onClick: () => {
8652
+ if (earlyAccept) setConfirmingAccept(true);
8653
+ else mutateTask("accept");
8654
+ },
8655
+ children: t("acceptTask")
8656
+ });
8657
+ })(), task.resolution === "open" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8303
8658
  size: "sm",
8304
8659
  variant: "outline",
8305
8660
  disabled: pending,
@@ -8336,6 +8691,43 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8336
8691
  ] })]
8337
8692
  }, claim.claimRef))]
8338
8693
  }),
8694
+ task !== void 0 && thread !== void 0 && (() => {
8695
+ const activeClaims = projection?.claims.filter((claim) => claim.taskRef === task.taskRef && claim.state === "active") ?? [];
8696
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
8697
+ open: confirmingAccept,
8698
+ onClose: () => {
8699
+ if (!pending) setConfirmingAccept(false);
8700
+ },
8701
+ title: t("acceptEarlyTitle"),
8702
+ closeLabel: t("cancel"),
8703
+ footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8704
+ variant: "outline",
8705
+ disabled: pending,
8706
+ onClick: () => {
8707
+ setConfirmingAccept(false);
8708
+ },
8709
+ children: t("cancel")
8710
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8711
+ variant: "primary",
8712
+ disabled: pending,
8713
+ onClick: () => {
8714
+ mutateTask("accept");
8715
+ },
8716
+ children: pending ? t("acceptingTask") : t("acceptTask")
8717
+ })] }),
8718
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8719
+ className: conversation_module_css_default.confirmBody,
8720
+ children: t("acceptEarlyBody", { count: activeClaims.length })
8721
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
8722
+ className: conversation_module_css_default.confirmList,
8723
+ children: activeClaims.map((claim) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
8724
+ memberName(claim.owner),
8725
+ " · ",
8726
+ claim.direction
8727
+ ] }, claim.claimRef))
8728
+ })]
8729
+ });
8730
+ })(),
8339
8731
  task !== void 0 && thread !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
8340
8732
  className: thread_module_css_default.workSection,
8341
8733
  "aria-label": t("claims"),
@@ -8502,6 +8894,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8502
8894
  onSubmit: () => {
8503
8895
  sendReply();
8504
8896
  },
8897
+ pendingFiles,
8898
+ onFilesChange: setPendingFiles,
8505
8899
  t
8506
8900
  }, draftKey) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {})
8507
8901
  ]
@@ -8509,14 +8903,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8509
8903
  }
8510
8904
  //#endregion
8511
8905
  //#region src/client/TeamConversation.tsx
8512
- function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, sendMessage, joinChannel, removeChannelMember, reply, changeTask, selectThread, backToWorkspace, backToChannels }) {
8906
+ function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, sendMessage, joinChannel, removeChannelMember, reply, changeTask, selectThread, selectChannel, backToWorkspace, backToChannels, resolveTaskRefs }) {
8513
8907
  const navigationState = (0, react.useSyncExternalStore)(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
8514
8908
  const current = useWorkspaces((state) => state.items).find((workspace) => workspace.workspaceId === navigationState.workspaceId);
8515
8909
  if (current !== void 0 && navigationState.taskRef !== void 0 && navigationState.threadRef !== void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamThreadPage, {
8516
8910
  workspaceId: current.workspaceId,
8911
+ putAttachment,
8517
8912
  taskRef: navigationState.taskRef,
8518
8913
  threadRef: navigationState.threadRef,
8519
8914
  backToWorkspace,
8915
+ selectChannel,
8916
+ selectThread,
8917
+ resolveTaskRefs,
8520
8918
  ...navigationState.channelRef === void 0 ? {} : { channelRef: navigationState.channelRef },
8521
8919
  ...navigationState.taskNumber === void 0 ? {} : { taskNumber: navigationState.taskNumber },
8522
8920
  drafts,
@@ -8543,7 +8941,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8543
8941
  joinChannel,
8544
8942
  removeChannelMember,
8545
8943
  selectThread,
8944
+ selectChannel,
8546
8945
  backToChannels,
8946
+ resolveTaskRefs,
8547
8947
  t
8548
8948
  }, navigationState.channelRef);
8549
8949
  const welcome = current === void 0 ? {
@@ -8573,7 +8973,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8573
8973
  }
8574
8974
  //#endregion
8575
8975
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/sidebar.module.css.mjs
8576
- 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_workspaceHeader{color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;min-height:28px;padding:0 4px 0 8px;font-size:13px;font-weight:600;line-height:20px;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);outline:none}.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);outline:none}.d0xfxa_workspaceRow:focus-visible{box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l3)}.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_railWorkspace{flex-direction:column;align-items:center;gap:8px;padding-top:8px;display:flex}.d0xfxa_railButton{border-radius:50%;width:36px;height:36px}.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;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:none}.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{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);outline:none}.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);outline:none}.d0xfxa_textButton:disabled{cursor:not-allowed;opacity:.4}.d0xfxa_channelList,.d0xfxa_agentList{flex-direction:column;gap:1px;padding:0 4px 4px;display:flex}.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;flex:1;align-items:center;min-width:0;min-height:30px;padding:3px 4px 3px 8px;display:flex}.d0xfxa_channelSelect:focus-visible{outline:none}.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;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:none}.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%);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);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);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);outline:none}.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_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}";
8976
+ 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_workspaceHeader{color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;min-height:28px;padding:0 4px 0 8px;font-size:13px;font-weight:600;line-height:20px;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);outline:none}.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);outline:none}.d0xfxa_workspaceRow:focus-visible{box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l3)}.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_railWorkspace{flex-direction:column;align-items:center;gap:8px;padding-top:8px;display:flex}.d0xfxa_railButton{border-radius:50%;width:36px;height:36px}.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;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:none}.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{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);outline:none}.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);outline:none}.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;flex:1;align-items:center;min-width:0;min-height:30px;padding:3px 4px 3px 8px;display:flex}.d0xfxa_channelSelect:focus-visible{outline:none}.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;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:none}.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%);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);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);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);outline:none}.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_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}";
8577
8977
  const tagId$1 = "@wowyuarm/dsh-agent-team/sidebar.module.css";
8578
8978
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
8579
8979
  const tag = document.createElement("style");
@@ -8616,6 +9016,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8616
9016
  "sectionHeader": "d0xfxa_sectionHeader",
8617
9017
  "sectionTitle": "d0xfxa_sectionTitle",
8618
9018
  "sectionToggle": "d0xfxa_sectionToggle",
9019
+ "sidebarRowDragging": "d0xfxa_sidebarRowDragging",
9020
+ "sidebarRowDropAfter": "d0xfxa_sidebarRowDropAfter",
9021
+ "sidebarRowDropBefore": "d0xfxa_sidebarRowDropBefore",
8619
9022
  "textButton": "d0xfxa_textButton",
8620
9023
  "unavailableDot": "d0xfxa_unavailableDot",
8621
9024
  "workspaceBrowser": "d0xfxa_workspaceBrowser",
@@ -8678,6 +9081,237 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8678
9081
  });
8679
9082
  }
8680
9083
  //#endregion
9084
+ //#region src/client/sidebar-drag.tsx
9085
+ /**
9086
+ * Native whole-row drag for the Team sidebar lists. Unlike the Harness
9087
+ * workspace list there is no document-level acceptance here: hovering another
9088
+ * row shows the before/after insertion marker and releasing on a row commits
9089
+ * exactly once per gesture, while a release outside any row — including over
9090
+ * the other sidebar list, whose panel never responds — just cancels without
9091
+ * committing.
9092
+ */
9093
+ /**
9094
+ * One drag gesture per panel instance. `onCommit` receives the moved ref,
9095
+ * the drop target and the insertion side exactly once per completed gesture;
9096
+ * releases outside the list never reach it.
9097
+ */
9098
+ function useSidebarRowDrag({ refs, onCommit }) {
9099
+ const [state, setState] = (0, react.useState)(null);
9100
+ const committed = (0, react.useRef)(false);
9101
+ const half = (event) => {
9102
+ const rect = event.currentTarget.getBoundingClientRect();
9103
+ return event.clientY - rect.top < rect.height / 2 ? "before" : "after";
9104
+ };
9105
+ return { rowProps: (orderKey) => ({
9106
+ draggable: true,
9107
+ className: state === null ? void 0 : state.active === orderKey ? sidebar_module_css_default.sidebarRowDragging : state.over === orderKey ? state.marker === "before" ? sidebar_module_css_default.sidebarRowDropBefore : sidebar_module_css_default.sidebarRowDropAfter : void 0,
9108
+ onDragStart: (event) => {
9109
+ if (event.dataTransfer === null) return;
9110
+ event.dataTransfer.effectAllowed = "move";
9111
+ event.dataTransfer.setData("text/plain", orderKey);
9112
+ committed.current = false;
9113
+ setState({
9114
+ active: orderKey,
9115
+ over: orderKey,
9116
+ marker: "after"
9117
+ });
9118
+ },
9119
+ onDragEnd: () => {
9120
+ setState(null);
9121
+ },
9122
+ onDragOver: (event) => {
9123
+ if (state === null || !refs.includes(orderKey)) return;
9124
+ event.preventDefault();
9125
+ if (event.dataTransfer !== null) event.dataTransfer.dropEffect = "move";
9126
+ const marker = half(event);
9127
+ if (state.over !== orderKey || state.marker !== marker) setState({
9128
+ ...state,
9129
+ over: orderKey,
9130
+ marker
9131
+ });
9132
+ },
9133
+ onDrop: (event) => {
9134
+ if (state === null || !refs.includes(orderKey)) return;
9135
+ event.preventDefault();
9136
+ if (committed.current) return;
9137
+ committed.current = true;
9138
+ onCommit(state.active, orderKey, half(event));
9139
+ }
9140
+ }) };
9141
+ }
9142
+ /**
9143
+ * Transparent wrapper that owns the drop-marker styling for one draggable
9144
+ * sidebar row. It adds no layout of its own; the styled row stays inside so
9145
+ * hover/focus descendant selectors keep working.
9146
+ */
9147
+ function SortableRow({ drag, orderKey, children }) {
9148
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9149
+ ...drag.rowProps(orderKey),
9150
+ children
9151
+ });
9152
+ }
9153
+ //#endregion
9154
+ //#region src/client/sidebar-order.ts
9155
+ /**
9156
+ * Human presentation preference for the Team sidebar: the row order of the
9157
+ * Channels and Agents lists. The order lives in this browser only — it is UI
9158
+ * taste, never a shared Team fact, so nothing here touches the ledger.
9159
+ *
9160
+ * One deep module owns the whole concern: storage, reconcile against the
9161
+ * current Remote order (drop removed refs, keep the user's relative order,
9162
+ * append newcomers in default order), the single `moveSidebarItem` mutation
9163
+ * behind whole-row drag, and a small subscription hook with snapshot-stable
9164
+ * results for `useSyncExternalStore`.
9165
+ */
9166
+ const STORAGE_KEY = "dsh.agent-team.sidebar-order";
9167
+ function listKey(workspaceId, kind) {
9168
+ return workspaceId === void 0 ? void 0 : `${workspaceId}|${kind}`;
9169
+ }
9170
+ const MEMORY_ONLY = Symbol("sidebar-order.memory");
9171
+ /**
9172
+ * Read-through parse cache over the raw persisted payload: repeated snapshots
9173
+ * skip re-validating an unchanged payload, while anything written outside this
9174
+ * module — another tab, devtools, a cleared store — is picked up because the
9175
+ * raw comparison misses.
9176
+ */
9177
+ let cachedRaw;
9178
+ let cachedOrders = {};
9179
+ /**
9180
+ * Parse persisted orders defensively: private mode, quota errors, and stale
9181
+ * or corrupted payloads all degrade to "no preference" instead of breaking
9182
+ * the sidebar.
9183
+ */
9184
+ function storedOrders() {
9185
+ let raw = null;
9186
+ try {
9187
+ raw = typeof localStorage === "undefined" ? null : localStorage.getItem(STORAGE_KEY);
9188
+ } catch {
9189
+ raw = null;
9190
+ }
9191
+ if (cachedRaw !== void 0 && raw !== null && raw === cachedRaw) return cachedOrders;
9192
+ if (raw === null) {
9193
+ if (cachedRaw === MEMORY_ONLY) return cachedOrders;
9194
+ cachedRaw = raw;
9195
+ cachedOrders = {};
9196
+ return cachedOrders;
9197
+ }
9198
+ try {
9199
+ const parsed = JSON.parse(raw);
9200
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("not an object");
9201
+ const clean = {};
9202
+ for (const [key, value] of Object.entries(parsed)) {
9203
+ if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) continue;
9204
+ clean[key] = value;
9205
+ }
9206
+ cachedRaw = raw;
9207
+ cachedOrders = clean;
9208
+ return cachedOrders;
9209
+ } catch {
9210
+ return {};
9211
+ }
9212
+ }
9213
+ function saveOrder(key, refs) {
9214
+ const next = {
9215
+ ...structuredClone(storedOrders()),
9216
+ [key]: refs
9217
+ };
9218
+ cachedOrders = next;
9219
+ try {
9220
+ if (typeof localStorage !== "undefined") {
9221
+ const raw = JSON.stringify(next);
9222
+ localStorage.setItem(STORAGE_KEY, raw);
9223
+ cachedRaw = raw;
9224
+ return;
9225
+ }
9226
+ } catch {}
9227
+ cachedRaw = MEMORY_ONLY;
9228
+ }
9229
+ /**
9230
+ * Merge the saved personal order into the current Remote order: kept refs
9231
+ * stay in the user's relative order with duplicates collapsed, removed refs
9232
+ * disappear, and new refs join in their Remote default positions after the
9233
+ * known ones.
9234
+ */
9235
+ function reconcileSidebarOrder(saved, current) {
9236
+ const present = new Set(current);
9237
+ const seen = /* @__PURE__ */ new Set();
9238
+ const merged = [];
9239
+ for (const ref of saved) {
9240
+ if (seen.has(ref) || !present.has(ref)) continue;
9241
+ seen.add(ref);
9242
+ merged.push(ref);
9243
+ }
9244
+ for (const ref of current) {
9245
+ if (seen.has(ref)) continue;
9246
+ seen.add(ref);
9247
+ merged.push(ref);
9248
+ }
9249
+ return merged;
9250
+ }
9251
+ let revision = 0;
9252
+ const listeners = /* @__PURE__ */ new Set();
9253
+ const snapshots = /* @__PURE__ */ new Map();
9254
+ function savedFingerprint(key) {
9255
+ const saved = storedOrders()[key];
9256
+ return saved === void 0 ? "" : `f${saved.length}:${saved.join(",")}`;
9257
+ }
9258
+ function emitChange() {
9259
+ revision += 1;
9260
+ for (const listener of listeners) listener();
9261
+ }
9262
+ function orderedSnapshot(workspaceId, kind, refs) {
9263
+ const key = listKey(workspaceId, kind);
9264
+ if (key === void 0) return refs;
9265
+ const signature = refs.join("\0");
9266
+ const fingerprint = savedFingerprint(key);
9267
+ const hit = snapshots.get(key);
9268
+ if (hit !== void 0 && hit.atRevision === revision && hit.signature === signature && hit.savedFingerprint === fingerprint) return hit.result;
9269
+ const result = reconcileSidebarOrder(storedOrders()[key] ?? [], refs);
9270
+ snapshots.set(key, {
9271
+ atRevision: revision,
9272
+ signature,
9273
+ savedFingerprint: fingerprint,
9274
+ result
9275
+ });
9276
+ return result;
9277
+ }
9278
+ /**
9279
+ * Effective row order for one sidebar list: the user's saved order folded
9280
+ * into the given Remote default order. Identity-stable across renders while
9281
+ * neither the data nor this browser's preference changes.
9282
+ */
9283
+ function useSidebarOrder(workspaceId, kind, refs) {
9284
+ return (0, react.useSyncExternalStore)((0, react.useCallback)((listener) => {
9285
+ listeners.add(listener);
9286
+ return () => {
9287
+ listeners.delete(listener);
9288
+ };
9289
+ }, []), () => orderedSnapshot(workspaceId, kind, refs), () => orderedSnapshot(workspaceId, kind, refs));
9290
+ }
9291
+ /**
9292
+ * The only mutation path: move `movedRef` to the given side of `targetRef`
9293
+ * inside the list's current effective order. Returns the new order, or
9294
+ * `undefined` when the request cannot change anything (unknown refs, dropping
9295
+ * a row onto itself, or an adjacent marker that would put it right back).
9296
+ * Persistence and subscriber notification happen here.
9297
+ */
9298
+ function moveSidebarItem(workspaceId, kind, refs, movedRef, targetRef, marker) {
9299
+ const key = listKey(workspaceId, kind);
9300
+ const from = refs.indexOf(movedRef);
9301
+ const nextFromTarget = refs.indexOf(targetRef);
9302
+ if (key === void 0 || from < 0 || nextFromTarget < 0 || movedRef === targetRef) return void 0;
9303
+ const next = [...refs];
9304
+ const [item] = next.splice(from, 1);
9305
+ if (item === void 0) return void 0;
9306
+ const insertAt = next.indexOf(targetRef) + (marker === "after" ? 1 : 0);
9307
+ if (insertAt === from) return void 0;
9308
+ next.splice(insertAt, 0, item);
9309
+ saveOrder(key, next);
9310
+ snapshots.delete(key);
9311
+ emitChange();
9312
+ return next;
9313
+ }
9314
+ //#endregion
8681
9315
  //#region src/client/TeamRowMenu.tsx
8682
9316
  /**
8683
9317
  * Row-level overflow menu shared by sidebar Channel and Agent rows, mirroring
@@ -8837,350 +9471,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8837
9471
  });
8838
9472
  }
8839
9473
  //#endregion
8840
- //#region src/client/TeamAgentsPanel.tsx
8841
- function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, restartMember, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }) {
8842
- const [members, setMembers] = (0, react.useState)([]);
8843
- const [channels, setChannels] = (0, react.useState)([]);
8844
- const [channelRefs, setChannelRefs] = (0, react.useState)([]);
8845
- const [loading, setLoading] = (0, react.useState)(true);
8846
- const [error, setError] = (0, react.useState)();
8847
- const [formOpen, setFormOpen] = (0, react.useState)(false);
8848
- const [handle, setHandle] = (0, react.useState)("");
8849
- const [description, setDescription] = (0, react.useState)("");
8850
- const [model, setModel] = (0, react.useState)(void 0);
8851
- const [creating, setCreating] = (0, react.useState)(false);
8852
- const [retryRequest, setRetryRequest] = (0, react.useState)();
8853
- const triggerRef = (0, react.useRef)(null);
8854
- const refresh = (0, react.useCallback)(async () => {
8855
- setLoading(true);
8856
- const result = await loadMembers({ workspaceId });
8857
- if (result.ok) {
8858
- setMembers(result.value);
8859
- setError(void 0);
8860
- } else setError(result.error.message);
8861
- setLoading(false);
8862
- }, [loadMembers, workspaceId]);
8863
- (0, react.useEffect)(() => {
8864
- refresh();
8865
- }, [refresh]);
8866
- const loadWorkspaceChannels = (0, react.useCallback)(async () => {
8867
- const result = await loadChannels({
8868
- workspaceId,
8869
- topLevelOnly: true,
8870
- includeActivities: false,
8871
- limit: 1
8872
- });
8873
- if (result.ok) setChannels(result.value.channels);
8874
- }, [loadChannels, workspaceId]);
8875
- (0, react.useEffect)(() => {
8876
- loadWorkspaceChannels();
8877
- }, [loadWorkspaceChannels]);
8878
- (0, react.useEffect)(() => subscribeChanges({
8879
- kind: "workspace",
8880
- workspaceId
8881
- }, (update) => {
8882
- if (update.type === "failed") {
8883
- setError(update.message);
8884
- return;
8885
- }
8886
- refresh();
8887
- loadWorkspaceChannels();
8888
- }), [
8889
- subscribeChanges,
8890
- refresh,
8891
- loadWorkspaceChannels,
8892
- workspaceId
8893
- ]);
8894
- const closeForm = () => {
8895
- if (creating) return;
8896
- setFormOpen(false);
8897
- queueMicrotask(() => {
8898
- triggerRef.current?.focus();
8899
- });
8900
- };
8901
- const provision = async (request) => {
8902
- setCreating(true);
8903
- onCreatingChange(request, true);
8904
- setError(void 0);
8905
- setRetryRequest(request);
8906
- try {
8907
- const result = await addMember(request);
8908
- if (result.ok) {
8909
- setMembers((current) => {
8910
- return [...current.filter((status) => status.member.memberId !== result.value.status.member.memberId), result.value.status];
8911
- });
8912
- setHandle("");
8913
- setDescription("");
8914
- setModel(void 0);
8915
- setChannelRefs([]);
8916
- setFormOpen(false);
8917
- if (result.value.status.presence === "unavailable") setError(result.value.status.diagnostic ?? t("statusUnavailable"));
8918
- else setRetryRequest(void 0);
8919
- queueMicrotask(() => {
8920
- triggerRef.current?.focus();
8921
- });
8922
- } else {
8923
- await refresh();
8924
- setError(result.error.message);
8925
- }
8926
- } catch (cause) {
8927
- setError(cause instanceof Error ? cause.message : String(cause));
8928
- } finally {
8929
- setCreating(false);
8930
- onCreatingChange(request, false);
8931
- }
8932
- };
8933
- const submit = (event) => {
8934
- event.preventDefault();
8935
- const normalizedHandle = handle.trim();
8936
- const normalizedDescription = description.trim();
8937
- if (normalizedHandle.length === 0 || creating) return;
8938
- provision(retryRequest !== void 0 && retryRequest.workspaceId === workspaceId && retryRequest.handle === normalizedHandle && retryRequest.description === normalizedDescription && sameModel(retryRequest.model, model) && retryRequest.channelRefs.length === channelRefs.length && retryRequest.channelRefs.every((ref) => channelRefs.includes(ref)) ? retryRequest : {
8939
- requestId: crypto.randomUUID(),
8940
- workspaceId,
8941
- handle: normalizedHandle,
8942
- description: normalizedDescription,
8943
- presetId: "team-member",
8944
- channelRefs,
8945
- ...model === void 0 ? {} : { model }
8946
- });
8947
- };
8948
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8949
- className: sidebar_module_css_default.panel,
8950
- children: [
8951
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
8952
- open: formOpen,
8953
- onClose: closeForm,
8954
- title: t("addAgent"),
8955
- closeLabel: t("close"),
8956
- contentClassName: create_module_css_default.dialogContent,
8957
- footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8958
- variant: "outline",
8959
- disabled: creating,
8960
- onClick: closeForm,
8961
- children: t("cancel")
8962
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8963
- type: "submit",
8964
- form: "team-agent-create-form",
8965
- variant: "primary",
8966
- disabled: creating || handle.trim().length === 0,
8967
- children: creating ? t("creatingAgent") : t("createAgent")
8968
- })] }),
8969
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
8970
- id: "team-agent-create-form",
8971
- className: create_module_css_default.form,
8972
- onSubmit: submit,
8973
- children: [
8974
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
8975
- className: create_module_css_default.field,
8976
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("agentName") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
8977
- className: create_module_css_default.input,
8978
- value: handle,
8979
- onChange: (event) => {
8980
- setHandle(event.target.value);
8981
- setRetryRequest(void 0);
8982
- },
8983
- disabled: creating,
8984
- autoFocus: true
8985
- })]
8986
- }),
8987
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
8988
- className: create_module_css_default.field,
8989
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [t("agentDescription"), t("optionalSuffix")] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
8990
- className: create_module_css_default.input,
8991
- value: description,
8992
- placeholder: t("agentDescriptionPlaceholder"),
8993
- onChange: (event) => {
8994
- setDescription(event.target.value);
8995
- setRetryRequest(void 0);
8996
- },
8997
- disabled: creating
8998
- })]
8999
- }),
9000
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPickerField, {
9001
- model,
9002
- onModelChange: (choice) => {
9003
- setModel(choice);
9004
- setRetryRequest(void 0);
9005
- },
9006
- loadModels,
9007
- disabled: creating,
9008
- t
9009
- }),
9010
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiMenuField, {
9011
- label: `${t("initialChannels")}${t("optionalSuffix")}`,
9012
- disabled: creating,
9013
- options: channels.map((channel) => ({
9014
- id: channel.channelRef,
9015
- label: channel.name
9016
- })),
9017
- selected: channelRefs,
9018
- onToggle: (ref) => {
9019
- setChannelRefs((current) => current.includes(ref) ? current.filter((item) => item !== ref) : [...current, ref]);
9020
- setRetryRequest(void 0);
9021
- },
9022
- emptyText: t("noChannelsForAgent"),
9023
- triggerEmptyLabel: t("channelsPickerEmpty"),
9024
- formatCount: (count) => t("channelsPickerCount", { count })
9025
- }),
9026
- formOpen && error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9027
- className: create_module_css_default.error,
9028
- role: "alert",
9029
- children: error
9030
- })
9031
- ]
9032
- })
9033
- }),
9034
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TeamSidebarSection, {
9035
- title: t("agents"),
9036
- actions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
9037
- label: t("addAgent"),
9038
- delayMs: 500,
9039
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
9040
- ref: triggerRef,
9041
- type: "button",
9042
- className: sidebar_module_css_default.iconButton,
9043
- "aria-label": t("addAgent"),
9044
- onClick: () => {
9045
- setError(void 0);
9046
- setFormOpen(true);
9047
- },
9048
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 })
9049
- })
9050
- }),
9051
- children: [
9052
- loading && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9053
- className: sidebar_module_css_default.emptyState,
9054
- children: t("loadingAgents")
9055
- }),
9056
- !loading && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9057
- className: sidebar_module_css_default.emptyState,
9058
- children: t("emptyAgents")
9059
- }),
9060
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9061
- className: sidebar_module_css_default.agentList,
9062
- children: members.map((status) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentRow, {
9063
- status,
9064
- ...memberSessionId === void 0 ? {} : { current: status.member.sessionId === memberSessionId },
9065
- channels,
9066
- loadChannels,
9067
- updateMember,
9068
- recoverMember,
9069
- restartMember,
9070
- joinChannel,
9071
- removeChannelMember,
9072
- loadModels,
9073
- openMemberSession,
9074
- onUpdated: () => {
9075
- refresh();
9076
- },
9077
- t
9078
- }, status.member.memberId))
9079
- })
9080
- ]
9081
- }),
9082
- !formOpen && error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9083
- className: sidebar_module_css_default.retryError,
9084
- role: "alert",
9085
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: error }), retryRequest !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
9086
- type: "button",
9087
- className: sidebar_module_css_default.textButton,
9088
- disabled: creating,
9089
- onClick: () => {
9090
- setFormOpen(true);
9091
- },
9092
- children: t("retry")
9093
- })]
9094
- })
9095
- ]
9096
- });
9097
- }
9098
- /**
9099
- * One sidebar Agent row: the select button opens the Member's own Session
9100
- * conversation page, the avatar carries identity plus the presence badge, and
9101
- * the row menu opens the editor.
9102
- */
9103
- function AgentRow({ status, current, channels, loadChannels, updateMember, recoverMember, restartMember, joinChannel, removeChannelMember, loadModels, openMemberSession, onUpdated, t }) {
9104
- const [menuOpen, setMenuOpen] = (0, react.useState)(false);
9105
- const [editing, setEditing] = (0, react.useState)(false);
9106
- const resume = async () => {
9107
- await recoverMember({
9108
- requestId: crypto.randomUUID(),
9109
- workspaceId: status.member.workspaceId,
9110
- memberId: status.member.memberId
9111
- });
9112
- await onUpdated();
9113
- };
9114
- const restart = async () => {
9115
- await restartMember({
9116
- requestId: crypto.randomUUID(),
9117
- workspaceId: status.member.workspaceId,
9118
- memberId: status.member.memberId
9119
- });
9120
- await onUpdated();
9121
- };
9122
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9123
- className: sidebar_module_css_default.agentRow,
9124
- "data-menu-open": menuOpen || void 0,
9125
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
9126
- type: "button",
9127
- className: sidebar_module_css_default.agentSelect,
9128
- "aria-label": t("openAgentSession", { name: status.member.handle }),
9129
- "aria-current": current ? "page" : void 0,
9130
- onClick: () => {
9131
- openMemberSession(status.member.sessionId);
9132
- },
9133
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberAvatar, {
9134
- status,
9135
- t
9136
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9137
- className: sidebar_module_css_default.agentCopy,
9138
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status.member.handle }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
9139
- })]
9140
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9141
- className: sidebar_module_css_default.rowMenu,
9142
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamRowMenu, {
9143
- label: t("actionsAgent", { name: status.member.handle }),
9144
- items: [
9145
- {
9146
- id: "edit",
9147
- label: t("editAgent"),
9148
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {})
9149
- },
9150
- ...status.presence === "error" ? [{
9151
- id: "resume",
9152
- label: t("resumeAgent"),
9153
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlayOutline16, {})
9154
- }] : [],
9155
- {
9156
- id: "restart",
9157
- label: t("restartAgent"),
9158
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, {})
9159
- }
9160
- ],
9161
- onSelect: (id) => {
9162
- if (id === "resume") resume();
9163
- else if (id === "restart") restart();
9164
- else setEditing(true);
9165
- },
9166
- onOpenChange: setMenuOpen
9167
- })
9168
- })]
9169
- }), editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentEditorDialog, {
9170
- status,
9171
- channels,
9172
- loadChannels,
9173
- updateMember,
9174
- joinChannel,
9175
- removeChannelMember,
9176
- loadModels,
9177
- onCommitted: onUpdated,
9178
- onClose: () => {
9179
- setEditing(false);
9180
- },
9181
- t
9182
- })] });
9183
- }
9474
+ //#region src/client/TeamMemberEditor.tsx
9184
9475
  /** Model option key inside one editor; opaque and resolved against the loaded groups. */
9185
9476
  function modelKey(provider, model) {
9186
9477
  return `${provider}\u0000${model}`;
@@ -9397,7 +9688,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9397
9688
  ...model === void 0 ? {} : { model }
9398
9689
  };
9399
9690
  const request = pendingRequest.current !== void 0 && pendingRequest.current.memberId === payload.memberId && pendingRequest.current.handle === payload.handle && pendingRequest.current.description === payload.description && sameModel(pendingRequest.current.model, model) ? pendingRequest.current : {
9400
- requestId: crypto.randomUUID(),
9691
+ requestId: mintRequestId(),
9401
9692
  ...payload
9402
9693
  };
9403
9694
  pendingRequest.current = request;
@@ -9517,27 +9808,371 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9517
9808
  ]
9518
9809
  }, channel.channelRef);
9519
9810
  }),
9520
- channels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("noChannelsForAgent") }),
9521
- loadError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9522
- className: sidebar_module_css_default.rowError,
9811
+ channels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("noChannelsForAgent") }),
9812
+ loadError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9813
+ className: sidebar_module_css_default.rowError,
9814
+ role: "alert",
9815
+ children: loadError
9816
+ })
9817
+ ]
9818
+ }),
9819
+ error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9820
+ className: create_module_css_default.error,
9821
+ role: "alert",
9822
+ children: error
9823
+ })
9824
+ ]
9825
+ })
9826
+ });
9827
+ }
9828
+ function sameModel(left, right) {
9829
+ if (left === void 0 && right === void 0) return true;
9830
+ if (left === void 0 || right === void 0) return false;
9831
+ return left.provider === right.provider && left.model === right.model && left.reasoningEffort === right.reasoningEffort;
9832
+ }
9833
+ //#endregion
9834
+ //#region src/client/TeamAgentsPanel.tsx
9835
+ function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }) {
9836
+ const [members, setMembers] = (0, react.useState)([]);
9837
+ const [channels, setChannels] = (0, react.useState)([]);
9838
+ const [channelRefs, setChannelRefs] = (0, react.useState)([]);
9839
+ const [loading, setLoading] = (0, react.useState)(true);
9840
+ const [error, setError] = (0, react.useState)();
9841
+ const [formOpen, setFormOpen] = (0, react.useState)(false);
9842
+ const [handle, setHandle] = (0, react.useState)("");
9843
+ const [description, setDescription] = (0, react.useState)("");
9844
+ const [model, setModel] = (0, react.useState)(void 0);
9845
+ const [creating, setCreating] = (0, react.useState)(false);
9846
+ const [retryRequest, setRetryRequest] = (0, react.useState)();
9847
+ const triggerRef = (0, react.useRef)(null);
9848
+ const orderedAgentRefs = useSidebarOrder(workspaceId, "agents", (0, react.useMemo)(() => members.map((status) => status.member.memberId), [members]));
9849
+ const orderedMembers = (0, react.useMemo)(() => {
9850
+ const byId = new Map(members.map((status) => [status.member.memberId, status]));
9851
+ return orderedAgentRefs.map((memberId) => byId.get(memberId)).filter((status) => status !== void 0);
9852
+ }, [orderedAgentRefs, members]);
9853
+ const applyMove = (movedRef, targetRef, marker) => {
9854
+ moveSidebarItem(workspaceId, "agents", orderedAgentRefs, movedRef, targetRef, marker);
9855
+ };
9856
+ const drag = useSidebarRowDrag({
9857
+ refs: orderedAgentRefs,
9858
+ onCommit: applyMove
9859
+ });
9860
+ const refresh = (0, react.useCallback)(async () => {
9861
+ setLoading(true);
9862
+ const result = await loadMembers({ workspaceId });
9863
+ if (result.ok) {
9864
+ setMembers(result.value);
9865
+ setError(void 0);
9866
+ } else setError(result.error.message);
9867
+ setLoading(false);
9868
+ }, [loadMembers, workspaceId]);
9869
+ (0, react.useEffect)(() => {
9870
+ refresh();
9871
+ }, [refresh]);
9872
+ const loadWorkspaceChannels = (0, react.useCallback)(async () => {
9873
+ const result = await loadChannels({
9874
+ workspaceId,
9875
+ topLevelOnly: true,
9876
+ includeActivities: false,
9877
+ limit: 1
9878
+ });
9879
+ if (result.ok) setChannels(result.value.channels);
9880
+ }, [loadChannels, workspaceId]);
9881
+ (0, react.useEffect)(() => {
9882
+ loadWorkspaceChannels();
9883
+ }, [loadWorkspaceChannels]);
9884
+ (0, react.useEffect)(() => subscribeChanges({
9885
+ kind: "workspace",
9886
+ workspaceId
9887
+ }, (update) => {
9888
+ if (update.type === "failed") {
9889
+ setError(update.message);
9890
+ return;
9891
+ }
9892
+ refresh();
9893
+ loadWorkspaceChannels();
9894
+ }), [
9895
+ subscribeChanges,
9896
+ refresh,
9897
+ loadWorkspaceChannels,
9898
+ workspaceId
9899
+ ]);
9900
+ const closeForm = () => {
9901
+ if (creating) return;
9902
+ setFormOpen(false);
9903
+ queueMicrotask(() => {
9904
+ triggerRef.current?.focus();
9905
+ });
9906
+ };
9907
+ const provision = async (request) => {
9908
+ setCreating(true);
9909
+ onCreatingChange(request, true);
9910
+ setError(void 0);
9911
+ setRetryRequest(request);
9912
+ try {
9913
+ const result = await addMember(request);
9914
+ if (result.ok) {
9915
+ setMembers((current) => {
9916
+ return [...current.filter((status) => status.member.memberId !== result.value.status.member.memberId), result.value.status];
9917
+ });
9918
+ setHandle("");
9919
+ setDescription("");
9920
+ setModel(void 0);
9921
+ setChannelRefs([]);
9922
+ setFormOpen(false);
9923
+ if (result.value.status.presence === "unavailable") setError(result.value.status.diagnostic ?? t("statusUnavailable"));
9924
+ else setRetryRequest(void 0);
9925
+ queueMicrotask(() => {
9926
+ triggerRef.current?.focus();
9927
+ });
9928
+ } else {
9929
+ await refresh();
9930
+ setError(result.error.message);
9931
+ }
9932
+ } catch (cause) {
9933
+ setError(cause instanceof Error ? cause.message : String(cause));
9934
+ } finally {
9935
+ setCreating(false);
9936
+ onCreatingChange(request, false);
9937
+ }
9938
+ };
9939
+ const submit = (event) => {
9940
+ event.preventDefault();
9941
+ const normalizedHandle = handle.trim();
9942
+ const normalizedDescription = description.trim();
9943
+ if (normalizedHandle.length === 0 || creating) return;
9944
+ provision(retryRequest !== void 0 && retryRequest.workspaceId === workspaceId && retryRequest.handle === normalizedHandle && retryRequest.description === normalizedDescription && sameModel(retryRequest.model, model) && retryRequest.channelRefs.length === channelRefs.length && retryRequest.channelRefs.every((ref) => channelRefs.includes(ref)) ? retryRequest : {
9945
+ requestId: mintRequestId(),
9946
+ workspaceId,
9947
+ handle: normalizedHandle,
9948
+ description: normalizedDescription,
9949
+ presetId: "team-member",
9950
+ channelRefs,
9951
+ ...model === void 0 ? {} : { model }
9952
+ });
9953
+ };
9954
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9955
+ className: sidebar_module_css_default.panel,
9956
+ children: [
9957
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
9958
+ open: formOpen,
9959
+ onClose: closeForm,
9960
+ title: t("addAgent"),
9961
+ closeLabel: t("close"),
9962
+ contentClassName: create_module_css_default.dialogContent,
9963
+ footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
9964
+ variant: "outline",
9965
+ disabled: creating,
9966
+ onClick: closeForm,
9967
+ children: t("cancel")
9968
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
9969
+ type: "submit",
9970
+ form: "team-agent-create-form",
9971
+ variant: "primary",
9972
+ disabled: creating || handle.trim().length === 0,
9973
+ children: creating ? t("creatingAgent") : t("createAgent")
9974
+ })] }),
9975
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
9976
+ id: "team-agent-create-form",
9977
+ className: create_module_css_default.form,
9978
+ onSubmit: submit,
9979
+ children: [
9980
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
9981
+ className: create_module_css_default.field,
9982
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("agentName") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
9983
+ className: create_module_css_default.input,
9984
+ value: handle,
9985
+ onChange: (event) => {
9986
+ setHandle(event.target.value);
9987
+ setRetryRequest(void 0);
9988
+ },
9989
+ disabled: creating,
9990
+ autoFocus: true
9991
+ })]
9992
+ }),
9993
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
9994
+ className: create_module_css_default.field,
9995
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [t("agentDescription"), t("optionalSuffix")] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
9996
+ className: create_module_css_default.input,
9997
+ value: description,
9998
+ placeholder: t("agentDescriptionPlaceholder"),
9999
+ onChange: (event) => {
10000
+ setDescription(event.target.value);
10001
+ setRetryRequest(void 0);
10002
+ },
10003
+ disabled: creating
10004
+ })]
10005
+ }),
10006
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPickerField, {
10007
+ model,
10008
+ onModelChange: (choice) => {
10009
+ setModel(choice);
10010
+ setRetryRequest(void 0);
10011
+ },
10012
+ loadModels,
10013
+ disabled: creating,
10014
+ t
10015
+ }),
10016
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiMenuField, {
10017
+ label: `${t("initialChannels")}${t("optionalSuffix")}`,
10018
+ disabled: creating,
10019
+ options: channels.map((channel) => ({
10020
+ id: channel.channelRef,
10021
+ label: channel.name
10022
+ })),
10023
+ selected: channelRefs,
10024
+ onToggle: (ref) => {
10025
+ setChannelRefs((current) => current.includes(ref) ? current.filter((item) => item !== ref) : [...current, ref]);
10026
+ setRetryRequest(void 0);
10027
+ },
10028
+ emptyText: t("noChannelsForAgent"),
10029
+ triggerEmptyLabel: t("channelsPickerEmpty"),
10030
+ formatCount: (count) => t("channelsPickerCount", { count })
10031
+ }),
10032
+ formOpen && error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
10033
+ className: create_module_css_default.error,
9523
10034
  role: "alert",
9524
- children: loadError
10035
+ children: error
9525
10036
  })
9526
10037
  ]
9527
- }),
9528
- error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9529
- className: create_module_css_default.error,
9530
- role: "alert",
9531
- children: error
9532
10038
  })
9533
- ]
9534
- })
10039
+ }),
10040
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TeamSidebarSection, {
10041
+ title: t("agents"),
10042
+ actions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
10043
+ label: t("addAgent"),
10044
+ delayMs: 500,
10045
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
10046
+ ref: triggerRef,
10047
+ type: "button",
10048
+ className: sidebar_module_css_default.iconButton,
10049
+ "aria-label": t("addAgent"),
10050
+ onClick: () => {
10051
+ setError(void 0);
10052
+ setFormOpen(true);
10053
+ },
10054
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 })
10055
+ })
10056
+ }),
10057
+ children: [
10058
+ loading && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
10059
+ className: sidebar_module_css_default.emptyState,
10060
+ children: t("loadingAgents")
10061
+ }),
10062
+ !loading && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
10063
+ className: sidebar_module_css_default.emptyState,
10064
+ children: t("emptyAgents")
10065
+ }),
10066
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
10067
+ className: sidebar_module_css_default.agentList,
10068
+ children: orderedMembers.map((status) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SortableRow, {
10069
+ drag,
10070
+ orderKey: status.member.memberId,
10071
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentRow, {
10072
+ status,
10073
+ ...memberSessionId === void 0 ? {} : { current: status.member.sessionId === memberSessionId },
10074
+ channels,
10075
+ loadChannels,
10076
+ updateMember,
10077
+ recoverMember,
10078
+ joinChannel,
10079
+ removeChannelMember,
10080
+ loadModels,
10081
+ openMemberSession,
10082
+ onUpdated: () => {
10083
+ refresh();
10084
+ },
10085
+ t
10086
+ })
10087
+ }, status.member.memberId))
10088
+ })
10089
+ ]
10090
+ }),
10091
+ !formOpen && error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
10092
+ className: sidebar_module_css_default.retryError,
10093
+ role: "alert",
10094
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: error }), retryRequest !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
10095
+ type: "button",
10096
+ className: sidebar_module_css_default.textButton,
10097
+ disabled: creating,
10098
+ onClick: () => {
10099
+ setFormOpen(true);
10100
+ },
10101
+ children: t("retry")
10102
+ })]
10103
+ })
10104
+ ]
9535
10105
  });
9536
10106
  }
9537
- function sameModel(left, right) {
9538
- if (left === void 0 && right === void 0) return true;
9539
- if (left === void 0 || right === void 0) return false;
9540
- return left.provider === right.provider && left.model === right.model && left.reasoningEffort === right.reasoningEffort;
10107
+ /**
10108
+ * One sidebar Agent row: the select button opens the Member's own Session
10109
+ * conversation page, the avatar carries identity plus the presence badge, and
10110
+ * the row menu opens the editor.
10111
+ */
10112
+ function AgentRow({ status, current, channels, loadChannels, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, openMemberSession, onUpdated, t }) {
10113
+ const [menuOpen, setMenuOpen] = (0, react.useState)(false);
10114
+ const [editing, setEditing] = (0, react.useState)(false);
10115
+ const resume = async () => {
10116
+ await recoverMember({
10117
+ requestId: mintRequestId(),
10118
+ workspaceId: status.member.workspaceId,
10119
+ memberId: status.member.memberId
10120
+ });
10121
+ await onUpdated();
10122
+ };
10123
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
10124
+ className: sidebar_module_css_default.agentRow,
10125
+ "data-menu-open": menuOpen || void 0,
10126
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
10127
+ type: "button",
10128
+ className: sidebar_module_css_default.agentSelect,
10129
+ "aria-label": t("openAgentSession", { name: status.member.handle }),
10130
+ "aria-current": current ? "page" : void 0,
10131
+ disabled: status.availability !== "active",
10132
+ onClick: () => {
10133
+ openMemberSession(status.member.sessionId);
10134
+ },
10135
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberAvatar, {
10136
+ status,
10137
+ t
10138
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
10139
+ className: sidebar_module_css_default.agentCopy,
10140
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status.member.handle }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
10141
+ })]
10142
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
10143
+ className: sidebar_module_css_default.rowMenu,
10144
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamRowMenu, {
10145
+ label: t("actionsAgent", { name: status.member.handle }),
10146
+ items: [{
10147
+ id: "edit",
10148
+ label: t("editAgent"),
10149
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {})
10150
+ }, ...status.presence === "error" ? [{
10151
+ id: "resume",
10152
+ label: t("resumeAgent"),
10153
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlayOutline16, {})
10154
+ }] : []],
10155
+ onSelect: (id) => {
10156
+ if (id === "resume") resume();
10157
+ else setEditing(true);
10158
+ },
10159
+ onOpenChange: setMenuOpen
10160
+ })
10161
+ })]
10162
+ }), editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentEditorDialog, {
10163
+ status,
10164
+ channels,
10165
+ loadChannels,
10166
+ updateMember,
10167
+ joinChannel,
10168
+ removeChannelMember,
10169
+ loadModels,
10170
+ onCommitted: onUpdated,
10171
+ onClose: () => {
10172
+ setEditing(false);
10173
+ },
10174
+ t
10175
+ })] });
9541
10176
  }
9542
10177
  //#endregion
9543
10178
  //#region src/client/TeamChannelsPanel.tsx
@@ -9555,6 +10190,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9555
10190
  const [pendingCreate, setPendingCreate] = (0, react.useState)();
9556
10191
  const previousCreatingKey = (0, react.useRef)(creatingAgents.map((request) => request.requestId).join(","));
9557
10192
  const triggerRef = (0, react.useRef)(null);
10193
+ const orderedChannelRefs = useSidebarOrder(workspaceId, "channels", (0, react.useMemo)(() => view?.channels.map((channel) => channel.channelRef) ?? [], [view]));
10194
+ const orderedChannels = (0, react.useMemo)(() => {
10195
+ const byRef = new Map((view?.channels ?? []).map((channel) => [channel.channelRef, channel]));
10196
+ return orderedChannelRefs.map((channelRef) => byRef.get(channelRef)).filter((channel) => channel !== void 0);
10197
+ }, [orderedChannelRefs, view]);
10198
+ const applyMove = (movedRef, targetRef, marker) => {
10199
+ moveSidebarItem(workspaceId, "channels", orderedChannelRefs, movedRef, targetRef, marker);
10200
+ };
10201
+ const drag = useSidebarRowDrag({
10202
+ refs: orderedChannelRefs,
10203
+ onCommit: applyMove
10204
+ });
9558
10205
  const refresh = (0, react.useCallback)(async () => {
9559
10206
  setLoading(true);
9560
10207
  const [channelResult, memberResult] = await Promise.all([loadChannels({
@@ -9625,7 +10272,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9625
10272
  memberIds: [...selected]
9626
10273
  };
9627
10274
  const request = pendingCreate !== void 0 && pendingCreate.workspaceId === payload.workspaceId && pendingCreate.name === payload.name && pendingCreate.description === payload.description && JSON.stringify(pendingCreate.memberIds) === JSON.stringify(payload.memberIds) ? pendingCreate : {
9628
- requestId: crypto.randomUUID(),
10275
+ requestId: mintRequestId(),
9629
10276
  ...payload
9630
10277
  };
9631
10278
  setPendingCreate(request);
@@ -9773,20 +10420,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9773
10420
  }),
9774
10421
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9775
10422
  className: sidebar_module_css_default.channelList,
9776
- children: view?.channels.map((channel) => {
9777
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChannelRow, {
9778
- channel,
9779
- members,
9780
- joinedIds: membership.get(channel.channelRef) ?? /* @__PURE__ */ new Set(),
9781
- selected: selectedChannelRef === channel.channelRef,
9782
- updateChannel,
9783
- joinChannel: props.joinChannel,
9784
- removeChannelMember: props.removeChannelMember,
9785
- onCommitted: () => {
9786
- refresh();
9787
- },
9788
- selectChannel,
9789
- t
10423
+ children: orderedChannels.map((channel) => {
10424
+ const joined = membership.get(channel.channelRef) ?? /* @__PURE__ */ new Set();
10425
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SortableRow, {
10426
+ drag,
10427
+ orderKey: channel.channelRef,
10428
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChannelRow, {
10429
+ channel,
10430
+ members,
10431
+ joinedIds: joined,
10432
+ selected: selectedChannelRef === channel.channelRef,
10433
+ updateChannel,
10434
+ joinChannel: props.joinChannel,
10435
+ removeChannelMember: props.removeChannelMember,
10436
+ onCommitted: () => {
10437
+ refresh();
10438
+ },
10439
+ selectChannel,
10440
+ t
10441
+ })
9790
10442
  }, channel.channelRef);
9791
10443
  })
9792
10444
  })
@@ -9874,7 +10526,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9874
10526
  const normalizedDescription = description.trim();
9875
10527
  if (saving || !dirty || normalizedName === "") return;
9876
10528
  const request = pendingRequest.current !== void 0 && pendingRequest.current.channelRef === channel.channelRef && pendingRequest.current.name === normalizedName && pendingRequest.current.description === normalizedDescription ? pendingRequest.current : {
9877
- requestId: crypto.randomUUID(),
10529
+ requestId: mintRequestId(),
9878
10530
  workspaceId: channel.workspaceId,
9879
10531
  channelRef: channel.channelRef,
9880
10532
  name: normalizedName,
@@ -10001,7 +10653,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10001
10653
  }
10002
10654
  //#endregion
10003
10655
  //#region src/client/TeamWorkspaceBrowser.tsx
10004
- function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, updateMember, recoverMember, restartMember, joinChannel, removeChannelMember, loadModels, openMemberSession }) {
10656
+ function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, openMemberSession }) {
10005
10657
  const navigationState = (0, react.useSyncExternalStore)(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
10006
10658
  const workspaces = useWorkspaces((state) => state.items);
10007
10659
  const selected = navigationState.workspaceId;
@@ -10108,7 +10760,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10108
10760
  addMember,
10109
10761
  updateMember,
10110
10762
  recoverMember,
10111
- restartMember,
10112
10763
  joinChannel,
10113
10764
  removeChannelMember,
10114
10765
  loadModels,
@@ -10125,6 +10776,260 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10125
10776
  });
10126
10777
  }
10127
10778
  //#endregion
10779
+ //#region src/client/member-session-input.ts
10780
+ const TEAM_COMMAND_SOURCE = "agent-team-command";
10781
+ const TEAM_MEMBER_SOURCE = "agent-team-member";
10782
+ /** Preserve the public Session command admission contract, not handler outcome. */
10783
+ async function admitTeamCompact(session) {
10784
+ const result = await session.command("/compact");
10785
+ if (!result.ok) throw new Error(`session.command failed: ${result.error.message}`);
10786
+ return result.value.matched ? { kind: "success" } : {
10787
+ kind: "error",
10788
+ text: "unknown command: /compact"
10789
+ };
10790
+ }
10791
+ /**
10792
+ * The two Team-only sources live in the shared public registry, but their
10793
+ * candidate plane is inert for every ordinary Session. The member source owns
10794
+ * its stable ref→label cache so serialization never falls back to guessing a
10795
+ * handle from plain text.
10796
+ */
10797
+ function createTeamMemberSessionSources(options) {
10798
+ const labels = /* @__PURE__ */ new Map();
10799
+ return [{
10800
+ trigger: "/",
10801
+ name: TEAM_COMMAND_SOURCE,
10802
+ showGroupTitle: false,
10803
+ async candidates(session, { query }) {
10804
+ if (!options.isEmbeddedMemberSession(session.sessionId) || !"compact".startsWith(query.toLocaleLowerCase())) return [];
10805
+ return [{
10806
+ name: "/compact",
10807
+ description: "压缩当前 Session 上下文",
10808
+ value: "compact"
10809
+ }];
10810
+ },
10811
+ onPick({ candidate, session }) {
10812
+ if (candidate.value !== "compact" || !options.isEmbeddedMemberSession(session.sessionId)) return void 0;
10813
+ return { claim: {
10814
+ token: "/compact",
10815
+ submit: async () => options.executeCompact(session.sessionId)
10816
+ } };
10817
+ }
10818
+ }, {
10819
+ trigger: "@",
10820
+ name: TEAM_MEMBER_SOURCE,
10821
+ showGroupTitle: false,
10822
+ async candidates(session, { query, signal }) {
10823
+ if (!options.isEmbeddedMemberSession(session.sessionId)) return [];
10824
+ const normalized = query.toLocaleLowerCase();
10825
+ const members = await options.members();
10826
+ if (signal.aborted) return [];
10827
+ return members.filter((status) => status.member.sessionId !== session.sessionId && status.member.state !== "inactive").filter((status) => status.member.handle.toLocaleLowerCase().startsWith(normalized)).map((status) => {
10828
+ labels.set(status.member.memberId, `@${status.member.handle}`);
10829
+ return {
10830
+ name: `@${status.member.handle}`,
10831
+ description: "引用成员 · 不会通知",
10832
+ value: String(status.member.memberId)
10833
+ };
10834
+ });
10835
+ },
10836
+ onPick({ candidate, session }) {
10837
+ if (!options.isEmbeddedMemberSession(session.sessionId) || candidate.value === void 0) return void 0;
10838
+ const ref = candidate.value;
10839
+ const label = labels.get(ref);
10840
+ if (label === void 0) return void 0;
10841
+ return { insert: {
10842
+ source: TEAM_MEMBER_SOURCE,
10843
+ label: label.slice(1),
10844
+ ref,
10845
+ clipboardText: label
10846
+ } };
10847
+ },
10848
+ codec: {
10849
+ clipboardText: (ref) => labels.get(ref) ?? `@${String(ref)}`,
10850
+ serialize: async (ref) => {
10851
+ const stable = String(ref);
10852
+ const label = labels.get(ref) ?? "";
10853
+ return `<team-member ref="${escapeAttribute(stable)}">${escapeText(label)}</team-member>`;
10854
+ }
10855
+ }
10856
+ }];
10857
+ }
10858
+ /** Unknown leading slash must never fall into the shipped global palette. */
10859
+ function allowsMemberSessionSubmit(draft, claimToken) {
10860
+ return !draft.trimStart().startsWith("/") || claimToken === "/compact";
10861
+ }
10862
+ function escapeText(value) {
10863
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
10864
+ }
10865
+ function escapeAttribute(value) {
10866
+ return escapeText(value).replaceAll("\"", "&quot;").replaceAll("'", "&#39;");
10867
+ }
10868
+ //#endregion
10869
+ //#region src/client/TeamMemberSessionComposer.tsx
10870
+ /**
10871
+ * Narrow, Team-owned member-session composer. It deliberately uses the public
10872
+ * input state/actions and trigger controller rather than the shipped InputBar;
10873
+ * owner-provided overlay remains inside the card so the shared menu renders.
10874
+ */
10875
+ function TeamMemberSessionComposer({ controller, inputActions, overlay, placeholder, disabled, blocked, stop, submitInput, useInput, useSession }) {
10876
+ const input = useInput((state) => state);
10877
+ const session = useSession((state) => state);
10878
+ const textarea = (0, react.useRef)(null);
10879
+ const editedByHuman = (0, react.useRef)(void 0);
10880
+ const compactWasSubmitting = (0, react.useRef)(false);
10881
+ const composing = (0, react.useRef)(false);
10882
+ const [submissionNotice, setSubmissionNotice] = (0, react.useState)();
10883
+ const draft = input?.draft ?? "";
10884
+ const isLocked = disabled === true || blocked !== void 0 || inputActions === void 0 || input === void 0;
10885
+ (0, react.useEffect)(() => {
10886
+ if (isLocked) return;
10887
+ const active = document.activeElement;
10888
+ if (active !== document.body && active?.closest("[aria-current=\"page\"]") === null) return;
10889
+ textarea.current?.focus({ preventScroll: true });
10890
+ }, [isLocked]);
10891
+ (0, react.useLayoutEffect)(() => {
10892
+ const element = textarea.current;
10893
+ if (element === null) return;
10894
+ element.style.height = "auto";
10895
+ element.style.height = `${Math.min(element.scrollHeight, 336)}px`;
10896
+ }, [draft]);
10897
+ (0, react.useEffect)(() => {
10898
+ if (input === void 0) return;
10899
+ if (input.phase === "submitting" && input.claim?.token === "/compact") {
10900
+ compactWasSubmitting.current = true;
10901
+ return;
10902
+ }
10903
+ if (input.phase === "claimed" && input.claim?.token === "/compact" && compactWasSubmitting.current) {
10904
+ compactWasSubmitting.current = false;
10905
+ setSubmissionNotice("Compact 未执行,请重试。");
10906
+ return;
10907
+ }
10908
+ if (input.phase === "plain") compactWasSubmitting.current = false;
10909
+ }, [input?.claim?.token, input?.phase]);
10910
+ (0, react.useEffect)(() => {
10911
+ if (input === void 0) return;
10912
+ const edit = editedByHuman.current;
10913
+ if (edit === void 0 || edit.draft !== input.draft) return;
10914
+ editedByHuman.current = void 0;
10915
+ const hit = triggerHit(input.draft, edit.caret, input.draftRev);
10916
+ controller.dismiss();
10917
+ if (hit !== void 0) controller.toggleSource(hit.trigger === "/" ? TEAM_COMMAND_SOURCE : TEAM_MEMBER_SOURCE, hit);
10918
+ }, [
10919
+ controller,
10920
+ input?.draft,
10921
+ input?.draftRev
10922
+ ]);
10923
+ const onChange = (event) => {
10924
+ const caret = event.currentTarget.selectionStart;
10925
+ editedByHuman.current = {
10926
+ draft: event.currentTarget.value,
10927
+ caret
10928
+ };
10929
+ setSubmissionNotice(void 0);
10930
+ inputActions?.setDraft(event.currentTarget.value);
10931
+ };
10932
+ const submit = () => {
10933
+ if (input === void 0 || inputActions === void 0) return;
10934
+ if (!allowsMemberSessionSubmit(input.draft, input.claim?.token)) {
10935
+ setSubmissionNotice("此 Member Session 仅支持 /compact 命令。");
10936
+ return;
10937
+ }
10938
+ setSubmissionNotice(void 0);
10939
+ submitInput(running ? "steer" : "queue");
10940
+ };
10941
+ const onKeyDown = (event) => {
10942
+ if (event.key === "Enter" && event.shiftKey) return;
10943
+ if (event.repeat || composing.current || event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;
10944
+ const key = event.key === "ArrowUp" ? "up" : event.key === "ArrowDown" ? "down" : event.key === "Escape" ? "escape" : event.key === "Enter" ? "enter" : void 0;
10945
+ if (key !== void 0) {
10946
+ if (controller.arbitrate(key, false) !== "pass") {
10947
+ event.preventDefault();
10948
+ return;
10949
+ }
10950
+ }
10951
+ if (event.key === "Enter") {
10952
+ event.preventDefault();
10953
+ submit();
10954
+ }
10955
+ };
10956
+ const running = session?.running ?? false;
10957
+ const promptError = session?.promptError;
10958
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
10959
+ className: `${composer_module_css_default.root} ${composer_module_css_default.memberSessionRoot}`,
10960
+ "data-team-member-composer": "true",
10961
+ children: [(submissionNotice !== void 0 || promptError !== null && promptError !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
10962
+ className: composer_module_css_default.memberSessionStatus,
10963
+ role: "alert",
10964
+ children: submissionNotice ?? promptError?.error.message
10965
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
10966
+ className: `${composer_module_css_default.card} ${composer_module_css_default.memberSessionCard}`,
10967
+ "data-composer-card": "true",
10968
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
10969
+ className: `${composer_module_css_default.inputArea} ${composer_module_css_default.memberSessionInputArea}`,
10970
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
10971
+ ref: textarea,
10972
+ value: draft,
10973
+ disabled: isLocked,
10974
+ placeholder: blocked?.reason ?? placeholder ?? "给成员发送直接消息",
10975
+ onChange,
10976
+ onKeyDown,
10977
+ onCompositionStart: () => {
10978
+ composing.current = true;
10979
+ },
10980
+ onCompositionEnd: () => {
10981
+ composing.current = false;
10982
+ }
10983
+ }), overlay]
10984
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
10985
+ className: `${composer_module_css_default.toolbar} ${composer_module_css_default.memberSessionToolbar}`,
10986
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
10987
+ className: `${composer_module_css_default.sendButton} ${composer_module_css_default.memberSessionPrimary}`,
10988
+ type: "button",
10989
+ "aria-label": running ? "停止生成" : "发送消息",
10990
+ disabled: isLocked || !running && draft.trim() === "",
10991
+ onClick: () => {
10992
+ if (running) stop?.();
10993
+ else submit();
10994
+ },
10995
+ children: running ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconStopFill16, { size: 16 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSendOutline16, { size: 16 })
10996
+ })
10997
+ })]
10998
+ })]
10999
+ });
11000
+ }
11001
+ function triggerHit(draft, caret, draftRev) {
11002
+ const before = draft.slice(0, caret);
11003
+ const leading = before.match(/^\s*\/([^\s]*)$/u);
11004
+ if (leading !== null) {
11005
+ const start = before.indexOf("/");
11006
+ return {
11007
+ trigger: "/",
11008
+ query: leading[1],
11009
+ quoted: false,
11010
+ position: "leading",
11011
+ span: {
11012
+ start,
11013
+ end: caret,
11014
+ draftRev
11015
+ }
11016
+ };
11017
+ }
11018
+ const at = before.lastIndexOf("@");
11019
+ if (at < 0 || /[\p{L}\p{N}_]/u.test(before[at - 1] ?? "") || /\s/u.test(before.slice(at + 1))) return void 0;
11020
+ return {
11021
+ trigger: "@",
11022
+ query: before.slice(at + 1),
11023
+ quoted: false,
11024
+ position: "inline",
11025
+ span: {
11026
+ start: at,
11027
+ end: caret,
11028
+ draftRev
11029
+ }
11030
+ };
11031
+ }
11032
+ //#endregion
10128
11033
  //#region src/client/locales.ts
10129
11034
  const zh = {
10130
11035
  team: "团队",
@@ -10165,7 +11070,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10165
11070
  editChannel: "编辑频道",
10166
11071
  editAgent: "编辑 Agent",
10167
11072
  resumeAgent: "恢复",
10168
- restartAgent: "重启会话",
10169
11073
  optionalSuffix: "(可选)",
10170
11074
  agentDescriptionPlaceholder: "留空则暂无描述",
10171
11075
  channelsPickerEmpty: "选择初始频道",
@@ -10243,6 +11147,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10243
11147
  activityClaimReleased: "{actor} 释放了「{direction}」",
10244
11148
  activityClaimsReleased: "{actor} 因成员权限变化释放了 {count} 个 Claim",
10245
11149
  activityAccepted: "{actor} 验收了此 Task",
11150
+ activityAcceptedWithClaims: "{actor} 验收了此 Task,并一并完成了 {count} 个未完成 Claim",
11151
+ acceptEarlyTitle: "提前验收任务",
11152
+ acceptEarlyBody: "将验收本 Task,并把以下 {count} 个未完成的 Claim 一并标记为完成:",
11153
+ acceptingTask: "验收中…",
10246
11154
  activityClosed: "{actor} 关闭了此 Task",
10247
11155
  activityReopened: "{actor} 重新打开了此 Task",
10248
11156
  mentionConfirmation: "提及未关注成员需要确认,再次发送以继续",
@@ -10290,7 +11198,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10290
11198
  editChannel: "Edit Channel",
10291
11199
  editAgent: "Edit Agent",
10292
11200
  resumeAgent: "Resume",
10293
- restartAgent: "Restart session",
10294
11201
  optionalSuffix: " (optional)",
10295
11202
  agentDescriptionPlaceholder: "Leave empty if not needed",
10296
11203
  channelsPickerEmpty: "Choose initial channels",
@@ -10368,6 +11275,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10368
11275
  activityClaimReleased: "{actor} released “{direction}”",
10369
11276
  activityClaimsReleased: "{actor} released {count} Claim(s) after a membership change",
10370
11277
  activityAccepted: "{actor} accepted this Task",
11278
+ activityAcceptedWithClaims: "{actor} accepted this Task and completed {count} unfinished Claims with it",
11279
+ acceptEarlyTitle: "Accept Task early",
11280
+ acceptEarlyBody: "This accepts the Task and marks the following {count} unfinished Claims as done:",
11281
+ acceptingTask: "Accepting…",
10371
11282
  activityClosed: "{actor} closed this Task",
10372
11283
  activityReopened: "{actor} reopened this Task",
10373
11284
  mentionConfirmation: "Mentioning an unfollowed member requires confirmation; send again to continue",
@@ -10385,7 +11296,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10385
11296
  "locale",
10386
11297
  "remote",
10387
11298
  "sessions",
10388
- "connection"
11299
+ "connection",
11300
+ "conversation",
11301
+ "inputTriggers"
10389
11302
  ];
10390
11303
  function registerModeShadow(ctx, navigation, changes, drafts, name, component, extraInject) {
10391
11304
  const sharedRemotes = {
@@ -10398,7 +11311,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10398
11311
  updateChannel: (request) => ctx.remote.agentTeam.updateChannel(request),
10399
11312
  updateMember: (request) => ctx.remote.agentTeam.updateMember(request),
10400
11313
  recoverMember: (request) => ctx.remote.agentTeam.recoverMember(request),
10401
- restartMember: (request) => ctx.remote.agentTeam.restartMember(request),
10402
11314
  loadModels: async () => {
10403
11315
  return (await ctx.get("connection").api.llm.models({})).result;
10404
11316
  },
@@ -10432,7 +11344,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10432
11344
  putAttachment: (request) => ctx.remote.agentTeam.putAttachment(request),
10433
11345
  getAttachment: (request) => ctx.remote.agentTeam.getAttachment(request),
10434
11346
  reply: (request) => ctx.remote.agentTeam.reply(request),
10435
- changeTask: (request) => ctx.remote.agentTeam.changeTask(request)
11347
+ changeTask: (request) => ctx.remote.agentTeam.changeTask(request),
11348
+ resolveTaskRefs: (request) => ctx.remote.agentTeam.resolveTaskRefs(request)
10436
11349
  } : {},
10437
11350
  ...name === "sidebar.workspaces" ? {
10438
11351
  addMember: (request) => ctx.remote.agentTeam.addMember(request),
@@ -10454,6 +11367,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10454
11367
  };
10455
11368
  });
10456
11369
  }
11370
+ function registerMemberSessionComposer(ctx, navigation) {
11371
+ ctx.slots.inject("conversation.composer.bar", () => {
11372
+ let dispose;
11373
+ let registeredSessionId;
11374
+ const reconcile = () => {
11375
+ const memberSessionId = navigation.getSnapshot().memberSessionId;
11376
+ const active = navigation.getSnapshot().mode === "team" && memberSessionId !== void 0;
11377
+ if (dispose !== void 0 && (!active || registeredSessionId !== memberSessionId)) {
11378
+ dispose();
11379
+ dispose = void 0;
11380
+ registeredSessionId = void 0;
11381
+ }
11382
+ if (active && dispose === void 0) {
11383
+ registeredSessionId = memberSessionId;
11384
+ dispose = ctx.slots.register({
11385
+ name: "conversation.composer.bar",
11386
+ priority: -100,
11387
+ select: () => ctx.sessions.list.getSnapshot().current === memberSessionId ? {} : null,
11388
+ inject: (sessionId) => {
11389
+ const actx = ctx.sessions.scope(sessionId);
11390
+ if (actx === void 0) throw new Error(`agent-team: Member session ${String(sessionId)} has no client scope`);
11391
+ const sessions = ctx.sessions;
11392
+ return {
11393
+ controller: ctx.get("inputTriggers").sessionOf(actx),
11394
+ stop: () => {
11395
+ sessions.sessionOf(actx)?.cancel();
11396
+ },
11397
+ submitInput: (mode) => ctx.conversation.input.for(actx).submit(mode)
11398
+ };
11399
+ }
11400
+ }, TeamMemberSessionComposer);
11401
+ }
11402
+ };
11403
+ const offNavigation = navigation.subscribe(reconcile);
11404
+ reconcile();
11405
+ return () => {
11406
+ offNavigation();
11407
+ dispose?.();
11408
+ };
11409
+ });
11410
+ }
10457
11411
  function applyUi(ctx) {
10458
11412
  ctx.effect(() => ctx.locale.register(NS, {
10459
11413
  zh,
@@ -10470,6 +11424,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10470
11424
  disposeDrafts();
10471
11425
  }, "agent-team: navigation service");
10472
11426
  const changes = new TeamChangeStream((request, signal) => ctx.remote.agentTeam.changes(request, signal));
11427
+ const triggerSources = createTeamMemberSessionSources({
11428
+ isEmbeddedMemberSession: (sessionId) => {
11429
+ const snapshot = navigation.getSnapshot();
11430
+ return snapshot.mode === "team" && snapshot.memberSessionId === sessionId && snapshot.workspaceId !== void 0;
11431
+ },
11432
+ members: async () => {
11433
+ const workspaceId = navigation.getSnapshot().workspaceId;
11434
+ if (workspaceId === void 0) return [];
11435
+ const result = await ctx.remote.agentTeam.members({ workspaceId });
11436
+ return result.ok ? result.value : [];
11437
+ },
11438
+ executeCompact: async (sessionId) => {
11439
+ const actx = ctx.sessions.scope(sessionId);
11440
+ const session = actx === void 0 ? void 0 : ctx.sessions.sessionOf(actx);
11441
+ return session === void 0 ? {
11442
+ kind: "error",
11443
+ text: "current Member Session is unavailable"
11444
+ } : admitTeamCompact(session);
11445
+ }
11446
+ });
11447
+ const inputTriggers = ctx.get("inputTriggers");
11448
+ ctx.effect(() => {
11449
+ const disposers = triggerSources.map((source) => inputTriggers.registerSource(source));
11450
+ return () => {
11451
+ for (const dispose of disposers) dispose();
11452
+ };
11453
+ }, "agent-team: Member session trigger sources");
10473
11454
  const loadMemberGroups = async () => {
10474
11455
  const workspaces = ctx.workspaces.list.getSnapshot().items;
10475
11456
  return (await Promise.all(workspaces.map(async (workspace) => {
@@ -10506,6 +11487,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10506
11487
  }, TeamFooterAction));
10507
11488
  registerModeShadow(ctx, navigation, changes, drafts, "sidebar.workspaces", TeamWorkspaceBrowser);
10508
11489
  registerModeShadow(ctx, navigation, changes, drafts, "conversation", TeamConversation);
11490
+ registerMemberSessionComposer(ctx, navigation);
10509
11491
  registerModeShadow(ctx, navigation, changes, drafts, "sidebar.settings", TeamSettings, () => ({ loadMemberGroups }));
10510
11492
  }
10511
11493
  async function apply(ctx) {