@wowyuarm/dsh-agent-team 0.1.2 → 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 (67) hide show
  1. package/README.md +1 -0
  2. package/README.zh.md +2 -0
  3. package/package.json +12 -3
  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 +214 -130
  9. package/packages/agent-team/lib/ledger.js +77 -70
  10. package/packages/agent-team/lib/recovery.js +30 -35
  11. package/packages/agent-team/lib/typert.host.js +33 -23
  12. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  13. package/packages/agent-team/lib/typert.remote-client.js +21 -21
  14. package/packages/agent-team/lib/types/attachments.d.ts +2 -2
  15. package/packages/agent-team/lib/types/attachments.d.ts.map +1 -1
  16. package/packages/agent-team/lib/types/auto-compaction.d.ts +38 -0
  17. package/packages/agent-team/lib/types/auto-compaction.d.ts.map +1 -0
  18. package/packages/agent-team/lib/types/index.d.ts +40 -12
  19. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  20. package/packages/agent-team/lib/types/ledger.d.ts +13 -0
  21. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  22. package/packages/agent-team/lib/types/recovery.d.ts +15 -16
  23. package/packages/agent-team/lib/types/recovery.d.ts.map +1 -1
  24. package/packages/agent-team/preset/team-member/agent.cordis.yml +6 -1
  25. package/packages/client-agent-team/README.md +1 -1
  26. package/packages/client-agent-team/README.zh.md +1 -1
  27. package/packages/client-agent-team/lib/client.js +942 -534
  28. package/packages/client-agent-team/lib/client.js.map +1 -1
  29. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
  30. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +5 -166
  31. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
  32. package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +6 -20
  33. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
  34. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +3 -2
  35. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
  36. package/packages/client-agent-team/lib/types/client/TeamComposer.js +0 -1
  37. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts +34 -0
  38. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -0
  39. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +169 -0
  40. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts +17 -0
  41. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts.map +1 -0
  42. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.js +120 -0
  43. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
  44. package/packages/client-agent-team/lib/types/client/TeamMessage.js +83 -43
  45. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
  46. package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +10 -23
  47. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  48. package/packages/client-agent-team/lib/types/client/index.js +71 -1
  49. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts +22 -0
  50. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts.map +1 -0
  51. package/packages/client-agent-team/lib/types/client/member-session-input.js +98 -0
  52. package/packages/client-agent-team/lib/types/client/requests.d.ts +16 -0
  53. package/packages/client-agent-team/lib/types/client/requests.d.ts.map +1 -0
  54. package/packages/client-agent-team/lib/types/client/requests.js +22 -0
  55. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
  56. package/packages/client-agent-team/lib/types/client/task-refs.d.ts +6 -1
  57. package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +1 -1
  58. package/packages/client-agent-team/lib/types/client/task-refs.js +19 -0
  59. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +43 -3
  60. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
  61. package/packages/client-agent-team/lib/types/client/team-formatters.js +61 -4
  62. package/packages/client-agent-team/lib/types/client/team-membership.d.ts.map +1 -1
  63. package/packages/client-agent-team/lib/types/client/team-membership.js +2 -1
  64. package/packages/tool-agent-team/lib/index.js +1 -1
  65. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts +0 -13
  66. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts.map +0 -1
  67. package/packages/client-agent-team/lib/types/client/TeamInboxPanel.js +0 -90
@@ -5220,7 +5220,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5220
5220
  },
5221
5221
  sourceLocation: {
5222
5222
  "file": "packages/agent-team/src/index.ts",
5223
- "line": 342,
5223
+ "line": 378,
5224
5224
  "column": 9
5225
5225
  }
5226
5226
  },
@@ -5247,7 +5247,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5247
5247
  },
5248
5248
  sourceLocation: {
5249
5249
  "file": "packages/agent-team/src/index.ts",
5250
- "line": 644,
5250
+ "line": 641,
5251
5251
  "column": 9
5252
5252
  }
5253
5253
  },
@@ -5275,7 +5275,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5275
5275
  },
5276
5276
  sourceLocation: {
5277
5277
  "file": "packages/agent-team/src/index.ts",
5278
- "line": 279,
5278
+ "line": 315,
5279
5279
  "column": 9
5280
5280
  }
5281
5281
  },
@@ -5302,7 +5302,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5302
5302
  },
5303
5303
  sourceLocation: {
5304
5304
  "file": "packages/agent-team/src/index.ts",
5305
- "line": 524,
5305
+ "line": 541,
5306
5306
  "column": 9
5307
5307
  }
5308
5308
  },
@@ -5329,7 +5329,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5329
5329
  },
5330
5330
  sourceLocation: {
5331
5331
  "file": "packages/agent-team/src/index.ts",
5332
- "line": 320,
5332
+ "line": 356,
5333
5333
  "column": 9
5334
5334
  }
5335
5335
  },
@@ -5356,7 +5356,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5356
5356
  },
5357
5357
  sourceLocation: {
5358
5358
  "file": "packages/agent-team/src/index.ts",
5359
- "line": 621,
5359
+ "line": 627,
5360
5360
  "column": 9
5361
5361
  }
5362
5362
  },
@@ -5383,7 +5383,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5383
5383
  },
5384
5384
  sourceLocation: {
5385
5385
  "file": "packages/agent-team/src/index.ts",
5386
- "line": 654,
5386
+ "line": 650,
5387
5387
  "column": 3
5388
5388
  }
5389
5389
  },
@@ -5410,7 +5410,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5410
5410
  },
5411
5411
  sourceLocation: {
5412
5412
  "file": "packages/agent-team/src/index.ts",
5413
- "line": 534,
5413
+ "line": 551,
5414
5414
  "column": 9
5415
5415
  }
5416
5416
  },
@@ -5438,7 +5438,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5438
5438
  },
5439
5439
  sourceLocation: {
5440
5440
  "file": "packages/agent-team/src/index.ts",
5441
- "line": 270,
5441
+ "line": 306,
5442
5442
  "column": 3
5443
5443
  }
5444
5444
  },
@@ -5465,7 +5465,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5465
5465
  },
5466
5466
  sourceLocation: {
5467
5467
  "file": "packages/agent-team/src/index.ts",
5468
- "line": 608,
5468
+ "line": 614,
5469
5469
  "column": 9
5470
5470
  }
5471
5471
  },
@@ -5492,7 +5492,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5492
5492
  },
5493
5493
  sourceLocation: {
5494
5494
  "file": "packages/agent-team/src/index.ts",
5495
- "line": 661,
5495
+ "line": 657,
5496
5496
  "column": 9
5497
5497
  }
5498
5498
  },
@@ -5519,7 +5519,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5519
5519
  },
5520
5520
  sourceLocation: {
5521
5521
  "file": "packages/agent-team/src/index.ts",
5522
- "line": 400,
5522
+ "line": 429,
5523
5523
  "column": 9
5524
5524
  }
5525
5525
  },
@@ -5546,7 +5546,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5546
5546
  },
5547
5547
  sourceLocation: {
5548
5548
  "file": "packages/agent-team/src/index.ts",
5549
- "line": 546,
5549
+ "line": 562,
5550
5550
  "column": 9
5551
5551
  }
5552
5552
  },
@@ -5573,7 +5573,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5573
5573
  },
5574
5574
  sourceLocation: {
5575
5575
  "file": "packages/agent-team/src/index.ts",
5576
- "line": 629,
5576
+ "line": 635,
5577
5577
  "column": 9
5578
5578
  }
5579
5579
  },
@@ -5600,7 +5600,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5600
5600
  },
5601
5601
  sourceLocation: {
5602
5602
  "file": "packages/agent-team/src/index.ts",
5603
- "line": 258,
5603
+ "line": 293,
5604
5604
  "column": 3
5605
5605
  }
5606
5606
  },
@@ -5627,7 +5627,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5627
5627
  },
5628
5628
  sourceLocation: {
5629
5629
  "file": "packages/agent-team/src/index.ts",
5630
- "line": 556,
5630
+ "line": 571,
5631
5631
  "column": 9
5632
5632
  }
5633
5633
  },
@@ -5654,7 +5654,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5654
5654
  },
5655
5655
  sourceLocation: {
5656
5656
  "file": "packages/agent-team/src/index.ts",
5657
- "line": 678,
5657
+ "line": 673,
5658
5658
  "column": 3
5659
5659
  }
5660
5660
  },
@@ -5681,7 +5681,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5681
5681
  },
5682
5682
  sourceLocation: {
5683
5683
  "file": "packages/agent-team/src/index.ts",
5684
- "line": 671,
5684
+ "line": 666,
5685
5685
  "column": 3
5686
5686
  }
5687
5687
  },
@@ -5708,7 +5708,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5708
5708
  },
5709
5709
  sourceLocation: {
5710
5710
  "file": "packages/agent-team/src/index.ts",
5711
- "line": 332,
5711
+ "line": 368,
5712
5712
  "column": 9
5713
5713
  }
5714
5714
  },
@@ -5735,7 +5735,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5735
5735
  },
5736
5736
  sourceLocation: {
5737
5737
  "file": "packages/agent-team/src/index.ts",
5738
- "line": 487,
5738
+ "line": 511,
5739
5739
  "column": 9
5740
5740
  }
5741
5741
  },
@@ -5762,7 +5762,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5762
5762
  },
5763
5763
  sourceLocation: {
5764
5764
  "file": "packages/agent-team/src/index.ts",
5765
- "line": 685,
5765
+ "line": 680,
5766
5766
  "column": 3
5767
5767
  }
5768
5768
  }
@@ -6377,8 +6377,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6377
6377
  return `${(byteSize / (1024 * 1024)).toFixed(1)} MB`;
6378
6378
  }
6379
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
6380
6384
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/composer.module.css.mjs
6381
- 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_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}}";
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}}";
6382
6386
  const tagId$5 = "@wowyuarm/dsh-agent-team/composer.module.css";
6383
6387
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
6384
6388
  const tag = document.createElement("style");
@@ -6401,6 +6405,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6401
6405
  "imageChip": "x9jGQq_imageChip",
6402
6406
  "imageChipPreview": "x9jGQq_imageChipPreview",
6403
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",
6404
6414
  "mentionDescription": "x9jGQq_mentionDescription",
6405
6415
  "mentionMenu": "x9jGQq_mentionMenu",
6406
6416
  "mentionName": "x9jGQq_mentionName",
@@ -6564,7 +6574,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6564
6574
  ref: rootRef,
6565
6575
  className: composer_module_css_default.root,
6566
6576
  onSubmit: (event) => {
6567
- console.log("DBG composer submit pending=%s draft=%j", pending, draft);
6568
6577
  event.preventDefault();
6569
6578
  if (!pending && draft.trim() !== "") onSubmit();
6570
6579
  },
@@ -6756,6 +6765,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6756
6765
  pending.delete(entry.taskRef);
6757
6766
  emit();
6758
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
+ };
6759
6789
  /**
6760
6790
  * Batch-resolve unknown refs through the Host lookup. Concurrent callers
6761
6791
  * deduplicate through the pending set; failures just clear the pending mark
@@ -6821,12 +6851,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6821
6851
  for (let index = 0; index < memberId.length; index += 1) hash = (hash * 31 + memberId.charCodeAt(index)) % 360;
6822
6852
  return hash;
6823
6853
  }
6824
- const BRANDED_REF_PATTERN = /\b(task|channel|thread):[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
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
+ }
6825
6863
  /**
6826
6864
  * Split a literal text run into plain and branded-ref segments. The pattern
6827
6865
  * anchors on the fixed ref prefixes plus the UUID shape, so ordinary prose
6828
- * containing a colon never linkifies. Refs render as navigation links; text
6829
- * without any ref comes back as one untouched segment.
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.
6830
6870
  */
6831
6871
  function splitBrandedRefs(text) {
6832
6872
  const segments = [];
@@ -6836,13 +6876,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6836
6876
  if (start > cursor) segments.push({ text: text.slice(cursor, start) });
6837
6877
  segments.push({
6838
6878
  text: match[0],
6839
- ref: match[0]
6879
+ ref: canonicalBrandedRef(match[0])
6840
6880
  });
6841
6881
  cursor = start + match[0].length;
6842
6882
  }
6843
6883
  if (cursor < text.length) segments.push({ text: text.slice(cursor) });
6844
6884
  return segments;
6845
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
+ }
6846
6897
  function escapeRegExp(value) {
6847
6898
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6848
6899
  }
@@ -6952,6 +7003,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6952
7003
  function stripAttachmentLines(body) {
6953
7004
  return body.replaceAll(/^\[attachment\] .*$(\n)?/gm, "").replace(/\n+$/, "");
6954
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
+ }
6955
7031
  //#endregion
6956
7032
  //#region \0dsh-css:/home/yu/projects/dsh-agent-team/packages/client-agent-team/src/client/conversation.module.css.mjs
6957
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}";
@@ -7010,13 +7086,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7010
7086
  /** One chat message row with identity chrome and sender-appropriate rendering. */
7011
7087
  function TeamMessage({ senderName, memberId, human, body, occurredAt, mentionNames, senderTitle, grouped, attachments, loadAttachment, t, onOpenRef, onResolveTaskRefs, children }) {
7012
7088
  const avatarStyle = human ? void 0 : { "--team-avatar-hue": memberHue(memberId) };
7013
- const displayBody = stripAttachmentLines(body) === "" ? body : stripAttachmentLines(body);
7014
- const inline = (human || isPlainTextBody(displayBody)) && mentionNames !== void 0 && mentionNames.length > 0 ? splitMentionNames(displayBody, mentionNames) : void 0;
7015
- const fallbackNames = inline === void 0 ? mentionNames ?? [] : inline.unmatched;
7016
- const richAgentBody = !human && !isPlainTextBody(displayBody);
7017
- const fallbackRefs = richAgentBody && onOpenRef !== void 0 ? splitBrandedRefs(displayBody).filter((segment) => segment.ref !== void 0 && !segment.ref.startsWith("task:")).map((segment) => segment.ref) : [];
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;
7018
7096
  const refVersion = useResolvedTaskRefVersion();
7019
- const bodyTaskRefs = onOpenRef === void 0 || richAgentBody ? [] : splitBrandedRefs(displayBody).filter((segment) => segment.ref !== void 0 && segment.ref.startsWith("task:")).map((segment) => segment.ref);
7097
+ const bodyTaskRefs = plan.taskRefs;
7020
7098
  const bodyTaskRefKey = bodyTaskRefs.join(",");
7021
7099
  (0, react.useEffect)(() => {
7022
7100
  if (onResolveTaskRefs === void 0 || bodyTaskRefKey === "") return;
@@ -7032,9 +7110,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7032
7110
  const root = markdownRef.current;
7033
7111
  if (!richAgentBody || root === null || onOpenRef === void 0) return;
7034
7112
  const textNodes = markdownProseTextNodes(root);
7035
- const taskRefs = [...new Set(textNodes.flatMap((node) => splitBrandedRefs(node.data).filter((segment) => segment.ref?.startsWith("task:") === true).map((segment) => segment.ref)))];
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)))];
7036
7115
  if (onResolveTaskRefs !== void 0 && taskRefs.length > 0) resolveUnknownTaskRefs(taskRefs, onResolveTaskRefs);
7037
- for (const node of textNodes) renderResolvedMarkdownTaskRefs(node, taskLabel);
7116
+ for (const code of styledRefCodes) renderResolvedMarkdownCodeRef(code, taskLabel);
7117
+ for (const node of textNodes) renderResolvedMarkdownText(node, mentionNames ?? [], taskLabel);
7038
7118
  for (const button of root.querySelectorAll("button[data-task-ref]")) {
7039
7119
  const taskRef = button.dataset.taskRef;
7040
7120
  const hit = taskRef === void 0 ? void 0 : cachedResolvedTaskRef(taskRef);
@@ -7045,7 +7125,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7045
7125
  onOpenRef,
7046
7126
  onResolveTaskRefs,
7047
7127
  refVersion,
7048
- taskLabel
7128
+ taskLabel,
7129
+ mentionNames
7049
7130
  ]);
7050
7131
  (0, react.useEffect)(() => {
7051
7132
  const root = markdownRef.current;
@@ -7085,13 +7166,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7085
7166
  children: formatMessageTime(occurredAt)
7086
7167
  })]
7087
7168
  }),
7088
- 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", {
7089
7170
  className: conversation_module_css_default.messageText,
7090
- 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", {
7091
7172
  className: conversation_module_css_default.mention,
7092
7173
  children: segment.text
7093
7174
  }, index) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderRefs(segment.text, onOpenRef, taskLabel) }, index))
7094
- }) : human || onOpenRef !== void 0 && isPlainTextBody(displayBody) && splitBrandedRefs(displayBody).some((segment) => segment.ref !== void 0) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7175
+ }) : plan.render === "literal" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7095
7176
  className: conversation_module_css_default.messageText,
7096
7177
  children: onOpenRef === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MessageText, { text: displayBody }) : renderRefs(displayBody, onOpenRef, taskLabel)
7097
7178
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -7099,12 +7180,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7099
7180
  className: conversation_module_css_default.messageMarkdown,
7100
7181
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: displayBody }, `${displayBody}:${onOpenRef === void 0 ? "literal" : "refs"}`)
7101
7182
  }),
7102
- (fallbackNames.length > 0 || fallbackRefs.length > 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7183
+ (plan.fallbackNames.length > 0 || plan.fallbackRefs.length > 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7103
7184
  className: conversation_module_css_default.mentionsRow,
7104
- children: [fallbackNames.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7185
+ children: [plan.fallbackNames.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7105
7186
  className: conversation_module_css_default.mention,
7106
7187
  children: ["@", name]
7107
- }, name)), fallbackRefs.map((ref) => {
7188
+ }, name)), plan.fallbackRefs.map((ref) => {
7108
7189
  const resolved = cachedResolvedTaskRef(ref);
7109
7190
  const label = resolved !== void 0 && ref.startsWith("task:") ? taskLabel(resolved.taskNumber) : ref;
7110
7191
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -7134,35 +7215,71 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7134
7215
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
7135
7216
  for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
7136
7217
  const parent = node.parentElement;
7137
- if (parent !== null && parent.closest("code, pre, a, button") === null) nodes.push(node);
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);
7138
7222
  }
7139
7223
  return nodes;
7140
7224
  }
7141
- /** Replace resolved refs in one prose text node without changing Markdown structure. */
7142
- function renderResolvedMarkdownTaskRefs(node, taskLabel) {
7143
- const segments = splitBrandedRefs(node.data);
7144
- if (!segments.some((segment) => segment.ref?.startsWith("task:") === true && cachedResolvedTaskRef(segment.ref) !== void 0)) return;
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;
7145
7257
  const fragment = document.createDocumentFragment();
7146
- for (const segment of segments) {
7147
- const taskRef = segment.ref?.startsWith("task:") === true ? segment.ref : void 0;
7148
- if (taskRef === void 0) {
7149
- fragment.append(segment.text);
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
+ }
7150
7271
  continue;
7151
7272
  }
7152
- const resolved = cachedResolvedTaskRef(taskRef);
7273
+ const taskRef = refSegment.ref.startsWith("task:") === true ? refSegment.ref : void 0;
7274
+ const resolved = taskRef === void 0 ? void 0 : cachedResolvedTaskRef(taskRef);
7153
7275
  if (resolved === void 0) {
7154
- fragment.append(segment.text);
7276
+ fragment.append(refSegment.text);
7155
7277
  continue;
7156
7278
  }
7157
- const button = document.createElement("button");
7158
- button.type = "button";
7159
- if (conversation_module_css_default.refLink !== void 0) button.className = conversation_module_css_default.refLink;
7160
- button.dataset.taskRef = taskRef;
7161
- button.title = taskRef;
7162
- button.textContent = taskLabel(resolved.taskNumber);
7163
- fragment.append(button);
7279
+ changed = true;
7280
+ fragment.append(resolvedTaskRefButton(taskRef, taskLabel(resolved.taskNumber)));
7164
7281
  }
7165
- node.replaceWith(fragment);
7282
+ if (changed) node.replaceWith(fragment);
7166
7283
  }
7167
7284
  /** Render one literal text run, linkifying branded refs when navigation is available. */
7168
7285
  function renderRefs(text, onOpenRef, taskLabel) {
@@ -7290,7 +7407,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7290
7407
  return next;
7291
7408
  });
7292
7409
  const key = `${membership.joined ? "remove" : "join"}:${membership.memberId}:${membership.channelRef}`;
7293
- const requestId = requestIds.current.get(key) ?? crypto.randomUUID();
7410
+ const requestId = requestIds.current.get(key) ?? mintRequestId();
7294
7411
  requestIds.current.set(key, requestId);
7295
7412
  const request = {
7296
7413
  requestId,
@@ -7549,24 +7666,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7549
7666
  selectThread(match.task.taskRef, match.thread.threadRef, channelRef, match.taskNumber);
7550
7667
  return;
7551
7668
  }
7552
- resolveTaskRefs({
7553
- workspaceId,
7554
- taskRefs: [ref]
7555
- }).then((result) => {
7556
- if (!result.ok) return;
7557
- const hit = result.value.resolved[0];
7558
- if (hit !== void 0) selectThread(hit.taskRef, hit.threadRef, hit.channelRef, hit.taskNumber);
7559
- });
7669
+ jumpToTaskThread(resolveTaskRefs, workspaceId, ref, selectThread);
7560
7670
  }
7561
7671
  };
7562
- const lookupTaskRefs = (taskRefs) => resolveTaskRefs({
7563
- workspaceId,
7564
- taskRefs
7565
- }).then((result) => {
7566
- if (!result.ok) return [];
7567
- for (const entry of result.value.resolved) rememberResolvedTaskRef(entry);
7568
- return result.value.resolved;
7569
- });
7672
+ const lookupTaskRefs = hostTaskRefLookup(resolveTaskRefs, workspaceId);
7570
7673
  const timeline = useTimelineScroll(`${view?.items.length ?? 0}:${channelLastItem?.message.messageRef ?? ""}`);
7571
7674
  const channel = view?.channels.find((item) => item.channelRef === channelRef);
7572
7675
  const channelMemberIds = new Set(view?.members.filter((item) => item.channelRef === channelRef).map((item) => item.memberId) ?? []);
@@ -7695,10 +7798,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7695
7798
  });
7696
7799
  const pendingSendId = (0, react.useRef)();
7697
7800
  const send = async () => {
7698
- console.log("DBG send entry pending=%s draft=%j files=%d", pending, draft, pendingFiles.length);
7699
7801
  if (pending || draft.trim() === "") return;
7700
7802
  const recipientIds = [...recipients].sort();
7701
- const requestId = pendingSendId.current ?? crypto.randomUUID();
7803
+ const requestId = pendingSendId.current ?? mintRequestId();
7702
7804
  pendingSendId.current = requestId;
7703
7805
  setPending(true);
7704
7806
  setError(void 0);
@@ -7707,7 +7809,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7707
7809
  const attachmentIds = [];
7708
7810
  for (const file of pendingFiles) {
7709
7811
  const uploaded = await putAttachment({
7710
- requestId: crypto.randomUUID(),
7812
+ requestId: mintRequestId(),
7711
7813
  workspaceId,
7712
7814
  name: file.name,
7713
7815
  mediaType: file.type === "" ? void 0 : file.type,
@@ -8039,7 +8141,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8039
8141
  const mountedRef = (0, react.useRef)(false);
8040
8142
  const currentFactsRef = (0, react.useRef)([]);
8041
8143
  const sequenceRef = (0, react.useRef)(0);
8042
- const readRequestIdRef = (0, react.useRef)(crypto.randomUUID());
8144
+ const readRequestIdRef = (0, react.useRef)(mintRequestId());
8043
8145
  const mutationRequests = (0, react.useRef)(/* @__PURE__ */ new Map());
8044
8146
  const threadLastFact = currentFacts[currentFacts.length - 1];
8045
8147
  const timeline = useTimelineScroll(`${currentFacts.length}:${olderFacts.length}:${threadLastFact === void 0 ? "" : factKey(threadLastFact)}`);
@@ -8057,7 +8159,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8057
8159
  };
8058
8160
  const readCurrent = async (newRequest = false) => {
8059
8161
  if (!mountedRef.current) return false;
8060
- if (newRequest) readRequestIdRef.current = crypto.randomUUID();
8162
+ if (newRequest) readRequestIdRef.current = mintRequestId();
8061
8163
  const sequence = sequenceRef.current + 1;
8062
8164
  sequenceRef.current = sequence;
8063
8165
  setLoading(true);
@@ -8254,14 +8356,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8254
8356
  const mentionHandlesMap = (0, react.useMemo)(() => new Map(members.map((status) => [status.member.memberId, status.member.handle.replace(/^@/, "")])), [members]);
8255
8357
  const metadata = (0, react.useMemo)(() => readMeta(readFacts), [readFacts]);
8256
8358
  const unreadIndex = (0, react.useMemo)(() => {
8257
- return mergeFacts([
8258
- messageFact(activeProjection?.anchor ?? {
8259
- messageRef: "missing",
8260
- sequence: 0
8261
- }, activeProjection?.anchorMentions),
8262
- ...readFacts.map((fact) => fact.fact),
8263
- ...currentFacts
8264
- ]).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);
8265
8360
  }, [
8266
8361
  activeProjection?.anchor,
8267
8362
  readFacts,
@@ -8277,23 +8372,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8277
8372
  const [pendingFiles, setPendingFiles] = (0, react.useState)([]);
8278
8373
  const openRef = (ref) => {
8279
8374
  if (ref.startsWith("channel:") && ref !== channelRef) selectChannel(ref);
8280
- if (ref.startsWith("task:") && ref !== taskRef) resolveTaskRefs({
8281
- workspaceId,
8282
- taskRefs: [ref]
8283
- }).then((result) => {
8284
- if (!result.ok) return;
8285
- const hit = result.value.resolved[0];
8286
- if (hit !== void 0) selectThread(hit.taskRef, hit.threadRef, hit.channelRef, hit.taskNumber);
8287
- });
8375
+ if (ref.startsWith("task:") && ref !== taskRef) jumpToTaskThread(resolveTaskRefs, workspaceId, ref, selectThread);
8288
8376
  };
8289
- const lookupTaskRefs = (refs) => resolveTaskRefs({
8290
- workspaceId,
8291
- taskRefs: refs
8292
- }).then((result) => {
8293
- if (!result.ok) return [];
8294
- for (const entry of result.value.resolved) rememberResolvedTaskRef(entry);
8295
- return result.value.resolved;
8296
- });
8377
+ const lookupTaskRefs = hostTaskRefLookup(resolveTaskRefs, workspaceId);
8297
8378
  const renderFact = (fact, grouped = false) => {
8298
8379
  if (fact.kind === "message") {
8299
8380
  const sender = memberName(fact.message.sender);
@@ -8385,7 +8466,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8385
8466
  setPending(true);
8386
8467
  setError(void 0);
8387
8468
  const key = `task:${action}`;
8388
- const requestId = mutationRequests.current.get(key) ?? crypto.randomUUID();
8469
+ const requestId = mutationRequests.current.get(key) ?? mintRequestId();
8389
8470
  mutationRequests.current.set(key, requestId);
8390
8471
  try {
8391
8472
  const result = await changeTask({
@@ -8436,7 +8517,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8436
8517
  };
8437
8518
  const sendReply = async () => {
8438
8519
  if (pending || task === void 0 || thread === void 0 || draft.trim() === "") return;
8439
- const id = replyRequestId ?? crypto.randomUUID();
8520
+ const id = replyRequestId ?? mintRequestId();
8440
8521
  setReplyRequestId(id);
8441
8522
  setPending(true);
8442
8523
  setError(void 0);
@@ -8444,7 +8525,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8444
8525
  const attachmentIds = [];
8445
8526
  for (const file of pendingFiles) {
8446
8527
  const uploaded = await putAttachment({
8447
- requestId: crypto.randomUUID(),
8528
+ requestId: mintRequestId(),
8448
8529
  workspaceId,
8449
8530
  name: file.name,
8450
8531
  mediaType: file.type === "" ? void 0 : file.type,
@@ -9390,416 +9471,74 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9390
9471
  });
9391
9472
  }
9392
9473
  //#endregion
9393
- //#region src/client/TeamAgentsPanel.tsx
9394
- function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }) {
9395
- const [members, setMembers] = (0, react.useState)([]);
9396
- const [channels, setChannels] = (0, react.useState)([]);
9397
- const [channelRefs, setChannelRefs] = (0, react.useState)([]);
9398
- const [loading, setLoading] = (0, react.useState)(true);
9399
- const [error, setError] = (0, react.useState)();
9400
- const [formOpen, setFormOpen] = (0, react.useState)(false);
9401
- const [handle, setHandle] = (0, react.useState)("");
9402
- const [description, setDescription] = (0, react.useState)("");
9403
- const [model, setModel] = (0, react.useState)(void 0);
9404
- const [creating, setCreating] = (0, react.useState)(false);
9405
- const [retryRequest, setRetryRequest] = (0, react.useState)();
9406
- const triggerRef = (0, react.useRef)(null);
9407
- const orderedAgentRefs = useSidebarOrder(workspaceId, "agents", (0, react.useMemo)(() => members.map((status) => status.member.memberId), [members]));
9408
- const orderedMembers = (0, react.useMemo)(() => {
9409
- const byId = new Map(members.map((status) => [status.member.memberId, status]));
9410
- return orderedAgentRefs.map((memberId) => byId.get(memberId)).filter((status) => status !== void 0);
9411
- }, [orderedAgentRefs, members]);
9412
- const applyMove = (movedRef, targetRef, marker) => {
9413
- moveSidebarItem(workspaceId, "agents", orderedAgentRefs, movedRef, targetRef, marker);
9414
- };
9415
- const drag = useSidebarRowDrag({
9416
- refs: orderedAgentRefs,
9417
- onCommit: applyMove
9418
- });
9419
- const refresh = (0, react.useCallback)(async () => {
9420
- setLoading(true);
9421
- const result = await loadMembers({ workspaceId });
9422
- if (result.ok) {
9423
- setMembers(result.value);
9424
- setError(void 0);
9425
- } else setError(result.error.message);
9426
- setLoading(false);
9427
- }, [loadMembers, workspaceId]);
9474
+ //#region src/client/TeamMemberEditor.tsx
9475
+ /** Model option key inside one editor; opaque and resolved against the loaded groups. */
9476
+ function modelKey(provider, model) {
9477
+ return `${provider}\u0000${model}`;
9478
+ }
9479
+ /**
9480
+ * Shared provider/model dropdown for the create and edit forms. The option
9481
+ * list rides the shared Menu primitive (one leading "follow Host default"
9482
+ * row, then non-selectable provider headings) with a capped, internally
9483
+ * scrolling card so growing model catalogs cannot stretch the dialog.
9484
+ */
9485
+ function ModelPickerField({ model, onModelChange, loadModels, disabled, t }) {
9486
+ const [groups, setGroups] = (0, react.useState)();
9487
+ const [modelsError, setModelsError] = (0, react.useState)();
9488
+ const [open, setModelOpen] = (0, react.useState)(false);
9489
+ const [effortOpen, setEffortOpen] = (0, react.useState)(false);
9428
9490
  (0, react.useEffect)(() => {
9429
- refresh();
9430
- }, [refresh]);
9431
- const loadWorkspaceChannels = (0, react.useCallback)(async () => {
9432
- const result = await loadChannels({
9433
- workspaceId,
9434
- topLevelOnly: true,
9435
- includeActivities: false,
9436
- limit: 1
9491
+ let mounted = true;
9492
+ loadModels().then((result) => {
9493
+ if (!mounted) return;
9494
+ if (result.ok) {
9495
+ setGroups(result.value.groups);
9496
+ setModelsError(void 0);
9497
+ } else setModelsError(result.error.message);
9437
9498
  });
9438
- if (result.ok) setChannels(result.value.channels);
9439
- }, [loadChannels, workspaceId]);
9440
- (0, react.useEffect)(() => {
9441
- loadWorkspaceChannels();
9442
- }, [loadWorkspaceChannels]);
9443
- (0, react.useEffect)(() => subscribeChanges({
9444
- kind: "workspace",
9445
- workspaceId
9446
- }, (update) => {
9447
- if (update.type === "failed") {
9448
- setError(update.message);
9449
- return;
9450
- }
9451
- refresh();
9452
- loadWorkspaceChannels();
9453
- }), [
9454
- subscribeChanges,
9455
- refresh,
9456
- loadWorkspaceChannels,
9457
- workspaceId
9458
- ]);
9459
- const closeForm = () => {
9460
- if (creating) return;
9461
- setFormOpen(false);
9462
- queueMicrotask(() => {
9463
- triggerRef.current?.focus();
9499
+ return () => {
9500
+ mounted = false;
9501
+ };
9502
+ }, [loadModels]);
9503
+ const items = [{
9504
+ id: "",
9505
+ label: t("modelFollowDefault")
9506
+ }];
9507
+ const byKey = /* @__PURE__ */ new Map();
9508
+ for (const group of groups ?? []) {
9509
+ items.push({
9510
+ type: "label",
9511
+ id: `model-group:${group.id}`,
9512
+ text: group.name
9464
9513
  });
9465
- };
9466
- const provision = async (request) => {
9467
- setCreating(true);
9468
- onCreatingChange(request, true);
9469
- setError(void 0);
9470
- setRetryRequest(request);
9471
- try {
9472
- const result = await addMember(request);
9473
- if (result.ok) {
9474
- setMembers((current) => {
9475
- return [...current.filter((status) => status.member.memberId !== result.value.status.member.memberId), result.value.status];
9476
- });
9477
- setHandle("");
9478
- setDescription("");
9479
- setModel(void 0);
9480
- setChannelRefs([]);
9481
- setFormOpen(false);
9482
- if (result.value.status.presence === "unavailable") setError(result.value.status.diagnostic ?? t("statusUnavailable"));
9483
- else setRetryRequest(void 0);
9484
- queueMicrotask(() => {
9485
- triggerRef.current?.focus();
9486
- });
9487
- } else {
9488
- await refresh();
9489
- setError(result.error.message);
9490
- }
9491
- } catch (cause) {
9492
- setError(cause instanceof Error ? cause.message : String(cause));
9493
- } finally {
9494
- setCreating(false);
9495
- onCreatingChange(request, false);
9514
+ for (const entry of group.models) {
9515
+ const key = modelKey(group.id, entry.id);
9516
+ byKey.set(key, {
9517
+ provider: group.id,
9518
+ id: entry.id,
9519
+ name: entry.name,
9520
+ efforts: entry.reasoning?.efforts ?? []
9521
+ });
9522
+ items.push({
9523
+ id: key,
9524
+ label: entry.name
9525
+ });
9496
9526
  }
9497
- };
9498
- const submit = (event) => {
9499
- event.preventDefault();
9500
- const normalizedHandle = handle.trim();
9501
- const normalizedDescription = description.trim();
9502
- if (normalizedHandle.length === 0 || creating) return;
9503
- 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 : {
9504
- requestId: crypto.randomUUID(),
9505
- workspaceId,
9506
- handle: normalizedHandle,
9507
- description: normalizedDescription,
9508
- presetId: "team-member",
9509
- channelRefs,
9510
- ...model === void 0 ? {} : { model }
9511
- });
9512
- };
9527
+ }
9528
+ const selectedModelKey = model === void 0 ? "" : modelKey(model.provider, model.model);
9529
+ const triggerLabel = model === void 0 ? t("modelFollowDefault") : byKey.get(selectedModelKey)?.name ?? `${model.provider} / ${model.model}`;
9530
+ const efforts = model === void 0 ? [] : byKey.get(selectedModelKey)?.efforts ?? [];
9531
+ const effortItems = [{
9532
+ id: "",
9533
+ label: t("effortFollowDefault")
9534
+ }, ...efforts.map((effort) => ({
9535
+ id: effort.id,
9536
+ label: effort.name
9537
+ }))];
9538
+ const selectedEffort = model?.reasoningEffort ?? "";
9539
+ const effortTriggerLabel = model === void 0 || selectedEffort === "" ? t("effortFollowDefault") : efforts.find((effort) => effort.id === selectedEffort)?.name ?? selectedEffort;
9513
9540
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9514
- className: sidebar_module_css_default.panel,
9515
- children: [
9516
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
9517
- open: formOpen,
9518
- onClose: closeForm,
9519
- title: t("addAgent"),
9520
- closeLabel: t("close"),
9521
- contentClassName: create_module_css_default.dialogContent,
9522
- 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, {
9523
- variant: "outline",
9524
- disabled: creating,
9525
- onClick: closeForm,
9526
- children: t("cancel")
9527
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
9528
- type: "submit",
9529
- form: "team-agent-create-form",
9530
- variant: "primary",
9531
- disabled: creating || handle.trim().length === 0,
9532
- children: creating ? t("creatingAgent") : t("createAgent")
9533
- })] }),
9534
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
9535
- id: "team-agent-create-form",
9536
- className: create_module_css_default.form,
9537
- onSubmit: submit,
9538
- children: [
9539
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
9540
- className: create_module_css_default.field,
9541
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("agentName") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
9542
- className: create_module_css_default.input,
9543
- value: handle,
9544
- onChange: (event) => {
9545
- setHandle(event.target.value);
9546
- setRetryRequest(void 0);
9547
- },
9548
- disabled: creating,
9549
- autoFocus: true
9550
- })]
9551
- }),
9552
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
9553
- className: create_module_css_default.field,
9554
- 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, {
9555
- className: create_module_css_default.input,
9556
- value: description,
9557
- placeholder: t("agentDescriptionPlaceholder"),
9558
- onChange: (event) => {
9559
- setDescription(event.target.value);
9560
- setRetryRequest(void 0);
9561
- },
9562
- disabled: creating
9563
- })]
9564
- }),
9565
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPickerField, {
9566
- model,
9567
- onModelChange: (choice) => {
9568
- setModel(choice);
9569
- setRetryRequest(void 0);
9570
- },
9571
- loadModels,
9572
- disabled: creating,
9573
- t
9574
- }),
9575
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiMenuField, {
9576
- label: `${t("initialChannels")}${t("optionalSuffix")}`,
9577
- disabled: creating,
9578
- options: channels.map((channel) => ({
9579
- id: channel.channelRef,
9580
- label: channel.name
9581
- })),
9582
- selected: channelRefs,
9583
- onToggle: (ref) => {
9584
- setChannelRefs((current) => current.includes(ref) ? current.filter((item) => item !== ref) : [...current, ref]);
9585
- setRetryRequest(void 0);
9586
- },
9587
- emptyText: t("noChannelsForAgent"),
9588
- triggerEmptyLabel: t("channelsPickerEmpty"),
9589
- formatCount: (count) => t("channelsPickerCount", { count })
9590
- }),
9591
- formOpen && error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9592
- className: create_module_css_default.error,
9593
- role: "alert",
9594
- children: error
9595
- })
9596
- ]
9597
- })
9598
- }),
9599
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TeamSidebarSection, {
9600
- title: t("agents"),
9601
- actions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
9602
- label: t("addAgent"),
9603
- delayMs: 500,
9604
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
9605
- ref: triggerRef,
9606
- type: "button",
9607
- className: sidebar_module_css_default.iconButton,
9608
- "aria-label": t("addAgent"),
9609
- onClick: () => {
9610
- setError(void 0);
9611
- setFormOpen(true);
9612
- },
9613
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 })
9614
- })
9615
- }),
9616
- children: [
9617
- loading && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9618
- className: sidebar_module_css_default.emptyState,
9619
- children: t("loadingAgents")
9620
- }),
9621
- !loading && members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9622
- className: sidebar_module_css_default.emptyState,
9623
- children: t("emptyAgents")
9624
- }),
9625
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9626
- className: sidebar_module_css_default.agentList,
9627
- children: orderedMembers.map((status) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SortableRow, {
9628
- drag,
9629
- orderKey: status.member.memberId,
9630
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentRow, {
9631
- status,
9632
- ...memberSessionId === void 0 ? {} : { current: status.member.sessionId === memberSessionId },
9633
- channels,
9634
- loadChannels,
9635
- updateMember,
9636
- recoverMember,
9637
- joinChannel,
9638
- removeChannelMember,
9639
- loadModels,
9640
- openMemberSession,
9641
- onUpdated: () => {
9642
- refresh();
9643
- },
9644
- t
9645
- })
9646
- }, status.member.memberId))
9647
- })
9648
- ]
9649
- }),
9650
- !formOpen && error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9651
- className: sidebar_module_css_default.retryError,
9652
- role: "alert",
9653
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: error }), retryRequest !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
9654
- type: "button",
9655
- className: sidebar_module_css_default.textButton,
9656
- disabled: creating,
9657
- onClick: () => {
9658
- setFormOpen(true);
9659
- },
9660
- children: t("retry")
9661
- })]
9662
- })
9663
- ]
9664
- });
9665
- }
9666
- /**
9667
- * One sidebar Agent row: the select button opens the Member's own Session
9668
- * conversation page, the avatar carries identity plus the presence badge, and
9669
- * the row menu opens the editor.
9670
- */
9671
- function AgentRow({ status, current, channels, loadChannels, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, openMemberSession, onUpdated, t }) {
9672
- const [menuOpen, setMenuOpen] = (0, react.useState)(false);
9673
- const [editing, setEditing] = (0, react.useState)(false);
9674
- const resume = async () => {
9675
- await recoverMember({
9676
- requestId: crypto.randomUUID(),
9677
- workspaceId: status.member.workspaceId,
9678
- memberId: status.member.memberId
9679
- });
9680
- await onUpdated();
9681
- };
9682
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9683
- className: sidebar_module_css_default.agentRow,
9684
- "data-menu-open": menuOpen || void 0,
9685
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
9686
- type: "button",
9687
- className: sidebar_module_css_default.agentSelect,
9688
- "aria-label": t("openAgentSession", { name: status.member.handle }),
9689
- "aria-current": current ? "page" : void 0,
9690
- disabled: status.availability !== "active",
9691
- onClick: () => {
9692
- openMemberSession(status.member.sessionId);
9693
- },
9694
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamMemberAvatar, {
9695
- status,
9696
- t
9697
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9698
- className: sidebar_module_css_default.agentCopy,
9699
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status.member.handle }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: status.member.description })]
9700
- })]
9701
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9702
- className: sidebar_module_css_default.rowMenu,
9703
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TeamRowMenu, {
9704
- label: t("actionsAgent", { name: status.member.handle }),
9705
- items: [{
9706
- id: "edit",
9707
- label: t("editAgent"),
9708
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {})
9709
- }, ...status.presence === "error" ? [{
9710
- id: "resume",
9711
- label: t("resumeAgent"),
9712
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlayOutline16, {})
9713
- }] : []],
9714
- onSelect: (id) => {
9715
- if (id === "resume") resume();
9716
- else setEditing(true);
9717
- },
9718
- onOpenChange: setMenuOpen
9719
- })
9720
- })]
9721
- }), editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentEditorDialog, {
9722
- status,
9723
- channels,
9724
- loadChannels,
9725
- updateMember,
9726
- joinChannel,
9727
- removeChannelMember,
9728
- loadModels,
9729
- onCommitted: onUpdated,
9730
- onClose: () => {
9731
- setEditing(false);
9732
- },
9733
- t
9734
- })] });
9735
- }
9736
- /** Model option key inside one editor; opaque and resolved against the loaded groups. */
9737
- function modelKey(provider, model) {
9738
- return `${provider}\u0000${model}`;
9739
- }
9740
- /**
9741
- * Shared provider/model dropdown for the create and edit forms. The option
9742
- * list rides the shared Menu primitive (one leading "follow Host default"
9743
- * row, then non-selectable provider headings) with a capped, internally
9744
- * scrolling card so growing model catalogs cannot stretch the dialog.
9745
- */
9746
- function ModelPickerField({ model, onModelChange, loadModels, disabled, t }) {
9747
- const [groups, setGroups] = (0, react.useState)();
9748
- const [modelsError, setModelsError] = (0, react.useState)();
9749
- const [open, setModelOpen] = (0, react.useState)(false);
9750
- const [effortOpen, setEffortOpen] = (0, react.useState)(false);
9751
- (0, react.useEffect)(() => {
9752
- let mounted = true;
9753
- loadModels().then((result) => {
9754
- if (!mounted) return;
9755
- if (result.ok) {
9756
- setGroups(result.value.groups);
9757
- setModelsError(void 0);
9758
- } else setModelsError(result.error.message);
9759
- });
9760
- return () => {
9761
- mounted = false;
9762
- };
9763
- }, [loadModels]);
9764
- const items = [{
9765
- id: "",
9766
- label: t("modelFollowDefault")
9767
- }];
9768
- const byKey = /* @__PURE__ */ new Map();
9769
- for (const group of groups ?? []) {
9770
- items.push({
9771
- type: "label",
9772
- id: `model-group:${group.id}`,
9773
- text: group.name
9774
- });
9775
- for (const entry of group.models) {
9776
- const key = modelKey(group.id, entry.id);
9777
- byKey.set(key, {
9778
- provider: group.id,
9779
- id: entry.id,
9780
- name: entry.name,
9781
- efforts: entry.reasoning?.efforts ?? []
9782
- });
9783
- items.push({
9784
- id: key,
9785
- label: entry.name
9786
- });
9787
- }
9788
- }
9789
- const selectedModelKey = model === void 0 ? "" : modelKey(model.provider, model.model);
9790
- const triggerLabel = model === void 0 ? t("modelFollowDefault") : byKey.get(selectedModelKey)?.name ?? `${model.provider} / ${model.model}`;
9791
- const efforts = model === void 0 ? [] : byKey.get(selectedModelKey)?.efforts ?? [];
9792
- const effortItems = [{
9793
- id: "",
9794
- label: t("effortFollowDefault")
9795
- }, ...efforts.map((effort) => ({
9796
- id: effort.id,
9797
- label: effort.name
9798
- }))];
9799
- const selectedEffort = model?.reasoningEffort ?? "";
9800
- const effortTriggerLabel = model === void 0 || selectedEffort === "" ? t("effortFollowDefault") : efforts.find((effort) => effort.id === selectedEffort)?.name ?? selectedEffort;
9801
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9802
- className: create_module_css_default.field,
9541
+ className: create_module_css_default.field,
9803
9542
  children: [
9804
9543
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("memberModel") }),
9805
9544
  groups === void 0 && modelsError === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
@@ -9949,7 +9688,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9949
9688
  ...model === void 0 ? {} : { model }
9950
9689
  };
9951
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 : {
9952
- requestId: crypto.randomUUID(),
9691
+ requestId: mintRequestId(),
9953
9692
  ...payload
9954
9693
  };
9955
9694
  pendingRequest.current = request;
@@ -10069,27 +9808,371 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10069
9808
  ]
10070
9809
  }, channel.channelRef);
10071
9810
  }),
10072
- channels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("noChannelsForAgent") }),
10073
- loadError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
10074
- 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,
10075
10034
  role: "alert",
10076
- children: loadError
10035
+ children: error
10077
10036
  })
10078
10037
  ]
10079
- }),
10080
- error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
10081
- className: create_module_css_default.error,
10082
- role: "alert",
10083
- children: error
10084
10038
  })
10085
- ]
10086
- })
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
+ ]
10087
10105
  });
10088
10106
  }
10089
- function sameModel(left, right) {
10090
- if (left === void 0 && right === void 0) return true;
10091
- if (left === void 0 || right === void 0) return false;
10092
- 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
+ })] });
10093
10176
  }
10094
10177
  //#endregion
10095
10178
  //#region src/client/TeamChannelsPanel.tsx
@@ -10189,7 +10272,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10189
10272
  memberIds: [...selected]
10190
10273
  };
10191
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 : {
10192
- requestId: crypto.randomUUID(),
10275
+ requestId: mintRequestId(),
10193
10276
  ...payload
10194
10277
  };
10195
10278
  setPendingCreate(request);
@@ -10443,7 +10526,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10443
10526
  const normalizedDescription = description.trim();
10444
10527
  if (saving || !dirty || normalizedName === "") return;
10445
10528
  const request = pendingRequest.current !== void 0 && pendingRequest.current.channelRef === channel.channelRef && pendingRequest.current.name === normalizedName && pendingRequest.current.description === normalizedDescription ? pendingRequest.current : {
10446
- requestId: crypto.randomUUID(),
10529
+ requestId: mintRequestId(),
10447
10530
  workspaceId: channel.workspaceId,
10448
10531
  channelRef: channel.channelRef,
10449
10532
  name: normalizedName,
@@ -10693,6 +10776,260 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10693
10776
  });
10694
10777
  }
10695
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
10696
11033
  //#region src/client/locales.ts
10697
11034
  const zh = {
10698
11035
  team: "团队",
@@ -10959,7 +11296,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10959
11296
  "locale",
10960
11297
  "remote",
10961
11298
  "sessions",
10962
- "connection"
11299
+ "connection",
11300
+ "conversation",
11301
+ "inputTriggers"
10963
11302
  ];
10964
11303
  function registerModeShadow(ctx, navigation, changes, drafts, name, component, extraInject) {
10965
11304
  const sharedRemotes = {
@@ -11028,6 +11367,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11028
11367
  };
11029
11368
  });
11030
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
+ }
11031
11411
  function applyUi(ctx) {
11032
11412
  ctx.effect(() => ctx.locale.register(NS, {
11033
11413
  zh,
@@ -11044,6 +11424,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11044
11424
  disposeDrafts();
11045
11425
  }, "agent-team: navigation service");
11046
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");
11047
11454
  const loadMemberGroups = async () => {
11048
11455
  const workspaces = ctx.workspaces.list.getSnapshot().items;
11049
11456
  return (await Promise.all(workspaces.map(async (workspace) => {
@@ -11080,6 +11487,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11080
11487
  }, TeamFooterAction));
11081
11488
  registerModeShadow(ctx, navigation, changes, drafts, "sidebar.workspaces", TeamWorkspaceBrowser);
11082
11489
  registerModeShadow(ctx, navigation, changes, drafts, "conversation", TeamConversation);
11490
+ registerMemberSessionComposer(ctx, navigation);
11083
11491
  registerModeShadow(ctx, navigation, changes, drafts, "sidebar.settings", TeamSettings, () => ({ loadMemberGroups }));
11084
11492
  }
11085
11493
  async function apply(ctx) {