@wowyuarm/dsh-agent-team 0.1.6 → 0.1.8

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 (108) hide show
  1. package/README.md +11 -5
  2. package/README.zh.md +11 -5
  3. package/package.json +44 -42
  4. package/packages/agent-team/README.md +2 -0
  5. package/packages/agent-team/README.zh.md +2 -0
  6. package/packages/agent-team/core-skills/member-skill-manager/SKILL.md +2 -0
  7. package/packages/agent-team/lib/index.js +140 -204
  8. package/packages/agent-team/lib/ledger.js +436 -25
  9. package/packages/agent-team/lib/member-context.js +6 -2
  10. package/packages/agent-team/lib/member-runtime.js +229 -0
  11. package/packages/agent-team/lib/preset-roster.js +1 -0
  12. package/packages/agent-team/lib/progress-nudge.js +320 -0
  13. package/packages/agent-team/lib/spec.js +30 -1
  14. package/packages/agent-team/lib/typert.host.js +250 -70
  15. package/packages/agent-team/lib/typert.remote-client.d.ts +5 -1
  16. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  17. package/packages/agent-team/lib/typert.remote-client.js +168 -38
  18. package/packages/agent-team/lib/types/entities.js +1 -0
  19. package/packages/agent-team/lib/types/index.d.ts +28 -44
  20. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  21. package/packages/agent-team/lib/types/ledger.d.ts +60 -2
  22. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  23. package/packages/agent-team/lib/types/member-context.d.ts.map +1 -1
  24. package/packages/agent-team/lib/types/member-runtime.d.ts +108 -0
  25. package/packages/agent-team/lib/types/member-runtime.d.ts.map +1 -0
  26. package/packages/agent-team/lib/types/operations.js +1 -0
  27. package/packages/agent-team/lib/types/preset-roster.d.ts.map +1 -1
  28. package/packages/agent-team/lib/types/progress-nudge.d.ts +136 -0
  29. package/packages/agent-team/lib/types/progress-nudge.d.ts.map +1 -0
  30. package/packages/agent-team/lib/types/requests-results.js +1 -0
  31. package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
  32. package/packages/agent-team/lib/types/types/entities.d.ts +357 -0
  33. package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -0
  34. package/packages/agent-team/lib/types/types/operations.d.ts +303 -0
  35. package/packages/agent-team/lib/types/types/operations.d.ts.map +1 -0
  36. package/packages/agent-team/lib/types/types/requests-results.d.ts +529 -0
  37. package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -0
  38. package/packages/agent-team/lib/types/types.d.ts +10 -1070
  39. package/packages/agent-team/lib/types/types.d.ts.map +1 -1
  40. package/packages/agent-team/preset/team-member/agent.cordis.yml +6 -4
  41. package/packages/client-agent-team/README.md +3 -1
  42. package/packages/client-agent-team/README.zh.md +3 -1
  43. package/packages/client-agent-team/lib/client.js +773 -733
  44. package/packages/client-agent-team/lib/client.js.map +1 -1
  45. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts +3 -2
  46. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
  47. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +30 -7
  48. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +1 -1
  49. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
  50. package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +5 -9
  51. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts +2 -1
  52. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
  53. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +31 -5
  54. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts +3 -1
  55. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
  56. package/packages/client-agent-team/lib/types/client/TeamComposer.js +39 -28
  57. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
  58. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
  59. package/packages/client-agent-team/lib/types/client/TeamConversation.js +2 -2
  60. package/packages/client-agent-team/lib/types/client/TeamMemberAvatar.d.ts.map +1 -1
  61. package/packages/client-agent-team/lib/types/client/TeamMemberAvatar.js +3 -2
  62. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
  63. package/packages/client-agent-team/lib/types/client/TeamMessage.js +15 -3
  64. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.d.ts +2 -2
  65. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.d.ts.map +1 -1
  66. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.js +4 -6
  67. package/packages/client-agent-team/lib/types/client/TeamStateDot.d.ts +14 -0
  68. package/packages/client-agent-team/lib/types/client/TeamStateDot.d.ts.map +1 -0
  69. package/packages/client-agent-team/lib/types/client/TeamStateDot.js +15 -0
  70. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +2 -1
  71. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
  72. package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +41 -16
  73. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts +1 -1
  74. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
  75. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +2 -2
  76. package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.d.ts +1 -1
  77. package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.d.ts.map +1 -1
  78. package/packages/client-agent-team/lib/types/client/index.d.ts +1 -1
  79. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  80. package/packages/client-agent-team/lib/types/client/index.js +9 -77
  81. package/packages/client-agent-team/lib/types/client/locales.d.ts +26 -0
  82. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
  83. package/packages/client-agent-team/lib/types/client/locales.js +26 -0
  84. package/packages/client-agent-team/lib/types/client/navigation.d.ts +2 -1
  85. package/packages/client-agent-team/lib/types/client/navigation.d.ts.map +1 -1
  86. package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts +1 -2
  87. package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts.map +1 -1
  88. package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts +1 -1
  89. package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts.map +1 -1
  90. package/packages/client-agent-team/lib/types/client/sidebar-sections.d.ts +1 -1
  91. package/packages/client-agent-team/lib/types/client/sidebar-sections.d.ts.map +1 -1
  92. package/packages/client-agent-team/lib/types/client/slots.d.ts +5 -1
  93. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
  94. package/packages/client-agent-team/lib/types/client/task-refs.d.ts +7 -1
  95. package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +1 -1
  96. package/packages/client-agent-team/lib/types/client/task-refs.js +25 -3
  97. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +11 -10
  98. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
  99. package/packages/client-agent-team/lib/types/client/team-formatters.js +14 -11
  100. package/packages/client-agent-team/lib/types/client/team-membership.d.ts +1 -1
  101. package/packages/client-agent-team/lib/types/client/team-membership.d.ts.map +1 -1
  102. package/packages/tool-agent-team/lib/index.js +9 -9
  103. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts +0 -17
  104. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts.map +0 -1
  105. package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.js +0 -135
  106. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts +0 -22
  107. package/packages/client-agent-team/lib/types/client/member-session-input.d.ts.map +0 -1
  108. package/packages/client-agent-team/lib/types/client/member-session-input.js +0 -98
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Fragment, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
3
3
  import { MarkdownText, MessageText, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import { cachedAttachmentDataUrl, formatByteSize, loadAttachmentDataUrl } from "./attachment-preview.js";
5
5
  import { cachedResolvedTaskRef, resolveUnknownTaskRefs, useResolvedTaskRefVersion } from "./task-refs.js";
@@ -30,6 +30,13 @@ export function TeamMessage({ senderName, memberId, human, body, occurredAt, men
30
30
  }, [onResolveTaskRefs, bodyTaskRefKey, refVersion]);
31
31
  const taskLabel = useCallback((taskNumber) => t?.('taskLabel', { number: taskNumber }) ?? `Task #${taskNumber}`, [t]);
32
32
  const refLabel = useCallback((ref) => ref.startsWith('thread:') ? (t?.('threadLabel') ?? 'Thread') : ref.startsWith('channel:') ? (t?.('channels') ?? 'Channels') : ref, [t]);
33
+ // Markdown chrome (code-copy buttons, footnotes heading) is locale copy the
34
+ // cordis-free primitive receives via props. Stable per locale revision — a
35
+ // fresh object per render would rebuild the component table every chunk.
36
+ const markdownLabels = useMemo(() => ({
37
+ code: { copyLabel: t?.('copyCode') ?? 'Copy', copiedLabel: t?.('copiedCode') ?? 'Copied' },
38
+ footnotes: t?.('markdownFootnotes') ?? 'Footnotes',
39
+ }), [t]);
33
40
  // Long bodies start clamped behind the expand control. The default derives
34
41
  // from the body alone; the toggle itself is per-mount view state nothing
35
42
  // persists.
@@ -84,7 +91,7 @@ export function TeamMessage({ senderName, memberId, human, body, occurredAt, men
84
91
  : _jsx(Fragment, { children: renderRefs(segment.text, onOpenRef, taskLabel, refLabel) }, index)) })
85
92
  : plan.render === 'literal'
86
93
  ? _jsx("div", { className: css.messageText, children: onOpenRef === undefined ? _jsx(MessageText, { text: displayBody }) : renderRefs(displayBody, onOpenRef, taskLabel, refLabel) })
87
- : _jsx("div", { ref: markdownRef, className: css.messageMarkdown, children: _jsx(MarkdownText, { text: displayBody }, `${displayBody}:${onOpenRef === undefined ? 'literal' : 'refs'}`) });
94
+ : _jsx("div", { ref: markdownRef, className: css.messageMarkdown, children: _jsx(MarkdownText, { text: displayBody, labels: markdownLabels }, `${displayBody}:${onOpenRef === undefined ? 'literal' : 'refs'}`) });
88
95
  return (_jsxs("article", { className: css.messageRow, "data-human": human || undefined, "data-grouped": grouped || undefined, children: [_jsx("div", { className: css.messageIdentity, style: avatarStyle, "aria-hidden": "true", children: senderName.replace('@', '').slice(0, 1).toUpperCase() }), _jsxs("div", { className: css.messageBody, children: [(!grouped || showGroupedTime === true) && (_jsxs("div", { className: css.nameRow, children: [!grouped && _jsx("strong", { ...(senderTitle === undefined ? {} : { title: senderTitle }), children: senderName }), occurredAt !== undefined && _jsx("span", { className: css.messageTime, children: formatMessageTime(occurredAt) })] })), clampable ? _jsx("div", { className: clamped ? css.messageClamp : undefined, children: bodyNode }) : bodyNode, clampable && (_jsx("button", { type: "button", className: css.messageExpand, "data-message-expand": "true", "aria-expanded": expanded, onClick: () => { setExpanded(value => !value); }, children: expanded ? (t?.('collapseMessage') ?? 'Show less') : (t?.('expandMessage') ?? 'Show more') })), (plan.fallbackNames.length > 0 || plan.fallbackRefs.length > 0) && (_jsxs("div", { className: css.mentionsRow, children: [plan.fallbackNames.map(name => _jsxs("span", { className: css.mention, children: ["@", name] }, name)), plan.fallbackRefs.map(ref => {
89
96
  const resolved = cachedResolvedTaskRef(ref);
90
97
  const label = resolved !== undefined && ref.startsWith('task:') ? taskLabel(resolved.taskNumber) : ref;
@@ -211,6 +218,11 @@ function renderRefs(text, onOpenRef, taskLabel, refLabel) {
211
218
  if (segment.ref === undefined)
212
219
  return _jsx(Fragment, { children: segment.text }, index);
213
220
  const resolved = cachedResolvedTaskRef(segment.ref);
221
+ // Task refs link only once the Host confirms them; abbreviated or unknown
222
+ // refs stay plain text so prose never misfires as a link. Channel and
223
+ // Thread refs have no resolver and link at the authored position.
224
+ if (segment.ref.startsWith('task:') && resolved === undefined)
225
+ return _jsx(Fragment, { children: segment.text }, index);
214
226
  const label = resolved !== undefined && segment.ref.startsWith('task:') ? taskLabel(resolved.taskNumber) : refLabel(segment.ref);
215
227
  return _jsx("button", { type: "button", className: css.refLink, title: segment.ref, onClick: () => { onOpenRef(segment.ref); }, children: label }, index);
216
228
  });
@@ -218,7 +230,7 @@ function renderRefs(text, onOpenRef, taskLabel, refLabel) {
218
230
  /** One message's attachment strip: image thumbnails with a large view, or name chips when bytes are gone. */
219
231
  function TeamAttachmentStrip({ attachments, loadAttachment, t }) {
220
232
  const [zoomed, setZoomed] = useState();
221
- return _jsxs("div", { className: css.attachmentStrip, children: [attachments.map(attachment => _jsx(TeamAttachment, { attachment: attachment, ...(loadAttachment === undefined ? {} : { loadAttachment }), ...(t === undefined ? {} : { t }), onZoom: setZoomed }, attachment.attachmentId)), zoomed !== undefined && _jsx(Modal, { open: true, ...(css.attachmentModal === undefined ? {} : { className: css.attachmentModal }), title: zoomed.name, onClose: () => { setZoomed(undefined); }, children: _jsx("img", { className: css.attachmentZoom, src: cachedAttachmentDataUrl(zoomed.attachmentId) ?? undefined, alt: zoomed.name }) })] });
233
+ return _jsxs("div", { className: css.attachmentStrip, children: [attachments.map(attachment => _jsx(TeamAttachment, { attachment: attachment, ...(loadAttachment === undefined ? {} : { loadAttachment }), ...(t === undefined ? {} : { t }), onZoom: setZoomed }, attachment.attachmentId)), zoomed !== undefined && _jsx(Modal, { open: true, ...(css.attachmentModal === undefined ? {} : { className: css.attachmentModal }), title: zoomed.name, closeLabel: t?.('close') ?? 'Close', onClose: () => { setZoomed(undefined); }, children: _jsx("img", { className: css.attachmentZoom, src: cachedAttachmentDataUrl(zoomed.attachmentId) ?? undefined, alt: zoomed.name }) })] });
222
234
  }
223
235
  function TeamAttachment({ attachment, loadAttachment, t, onZoom }) {
224
236
  const wantsPreview = loadAttachment !== undefined && attachment.mediaType.startsWith('image/');
@@ -1,9 +1,9 @@
1
- import type { StateDotState } from '@deepseek-ai/dsh-client-ui-primitives';
2
1
  import type { AgentTeamClientMemberStatus } from '@wowyuarm/dsh-agent-team/types';
3
2
  import type { TeamSidebarProps } from './slots.ts';
3
+ import type { TeamStateDotState } from './TeamStateDot.tsx';
4
4
  export declare function presenceLabel(status: AgentTeamClientMemberStatus, t: TeamSidebarProps['t']): string;
5
5
  /** Shared presence → indicator mapping for dots and avatar badges. */
6
- export declare function presenceDotState(presence: AgentTeamClientMemberStatus['presence']): StateDotState | 'gray';
6
+ export declare function presenceDotState(presence: AgentTeamClientMemberStatus['presence']): TeamStateDotState;
7
7
  export declare function TeamPresenceDot({ status, t }: {
8
8
  readonly status: AgentTeamClientMemberStatus;
9
9
  readonly t: TeamSidebarProps['t'];
@@ -1 +1 @@
1
- {"version":3,"file":"TeamPresenceDot.d.ts","sourceRoot":"","sources":["../../../src/client/TeamPresenceDot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAA;AAC1E,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAA;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAGlD,wBAAgB,aAAa,CAAC,MAAM,EAAE,2BAA2B,EAAE,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,GAAG,MAAM,CAKnG;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,GAAG,aAAa,GAAG,MAAM,CAE1G;AAED,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;IAC7C,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BAYA"}
1
+ {"version":3,"file":"TeamPresenceDot.d.ts","sourceRoot":"","sources":["../../../src/client/TeamPresenceDot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAA;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAG3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,2BAA2B,EAAE,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,GAAG,MAAM,CAKnG;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,GAAG,iBAAiB,CAErG;AAED,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;IAC7C,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BASA"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { StateDot, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
2
+ import { Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { TeamStateDot } from "./TeamStateDot.js";
3
4
  import css from './presence.module.css';
4
5
  export function presenceLabel(status, t) {
5
6
  const label = status.presence === 'available' ? t('statusAvailable')
@@ -9,12 +10,9 @@ export function presenceLabel(status, t) {
9
10
  }
10
11
  /** Shared presence → indicator mapping for dots and avatar badges. */
11
12
  export function presenceDotState(presence) {
12
- return presence === 'available' ? 'done' : presence === 'working' ? 'ongoing' : presence === 'error' ? 'error' : 'gray';
13
+ return presence === 'available' ? 'done' : presence === 'working' ? 'ongoing' : presence === 'error' ? 'error' : 'quiet';
13
14
  }
14
15
  export function TeamPresenceDot({ status, t }) {
15
16
  const label = presenceLabel(status, t);
16
- const state = presenceDotState(status.presence);
17
- return (_jsx(Tooltip, { label: label, delayMs: 300, children: _jsx("span", { className: css.target, role: "img", "aria-label": label, children: state === 'gray'
18
- ? _jsx("span", { className: css.unavailableDot, "aria-hidden": "true" })
19
- : _jsx(StateDot, { state: state }) }) }));
17
+ return (_jsx(Tooltip, { label: label, delayMs: 300, children: _jsx("span", { className: css.target, role: "img", "aria-label": label, children: _jsx(TeamStateDot, { state: presenceDotState(status.presence) }) }) }));
20
18
  }
@@ -0,0 +1,14 @@
1
+ import type { StateDotState } from '@deepseek-ai/dsh-client-ui-primitives';
2
+ /** The Team status dot language: the DSH four-color states plus the two quiet statuses StateDot has no slot for. */
3
+ export type TeamStateDotState = StateDotState | 'todo' | 'quiet';
4
+ /**
5
+ * Render the one shared Team status indicator. Native StateDot states pass
6
+ * through; the quiet statuses mirror StateDot geometry locally so every
7
+ * surface renders the same shape — todo a hollow ring (not started), quiet a
8
+ * solid tertiary dot with the same 10% halo (closed, unavailable).
9
+ */
10
+ export declare function TeamStateDot({ state, size }: {
11
+ readonly state: TeamStateDotState;
12
+ readonly size?: number | undefined;
13
+ }): import("react").JSX.Element;
14
+ //# sourceMappingURL=TeamStateDot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TeamStateDot.d.ts","sourceRoot":"","sources":["../../../src/client/TeamStateDot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAA;AAG1E,oHAAoH;AACpH,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,MAAM,GAAG,OAAO,CAAA;AAEhE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE;IACjD,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC,+BAKA"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { StateDot } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import css from './state-dot.module.css';
4
+ /**
5
+ * Render the one shared Team status indicator. Native StateDot states pass
6
+ * through; the quiet statuses mirror StateDot geometry locally so every
7
+ * surface renders the same shape — todo a hollow ring (not started), quiet a
8
+ * solid tertiary dot with the same 10% halo (closed, unavailable).
9
+ */
10
+ export function TeamStateDot({ state, size = 10 }) {
11
+ if (state === 'todo' || state === 'quiet') {
12
+ return _jsx("span", { className: css.quiet, "data-variant": state, style: { width: size, height: size }, "aria-hidden": "true" });
13
+ }
14
+ return _jsx(StateDot, { state: state, size: size });
15
+ }
@@ -1,5 +1,5 @@
1
1
  import type { AgentTeamChannelRef, AgentTeamTaskRef, AgentTeamThreadRef } from '@wowyuarm/dsh-agent-team/types';
2
- import type { WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client';
2
+ import type { WorkspaceId } from '@deepseek-ai/dsh-api-workspace-controller/client';
3
3
  import type { TeamConversationProps } from './slots.ts';
4
4
  import type { TeamDraftStore } from './drafts.ts';
5
5
  interface TeamThreadPageProps {
@@ -12,6 +12,7 @@ interface TeamThreadPageProps {
12
12
  readonly loadChannels: TeamConversationProps['loadChannels'];
13
13
  readonly readThread: TeamConversationProps['readThread'];
14
14
  readonly loadThreadHistory: TeamConversationProps['loadThreadHistory'];
15
+ readonly threadObservations: TeamConversationProps['threadObservations'];
15
16
  readonly subscribeChanges: TeamConversationProps['subscribeChanges'];
16
17
  readonly loadMembers: TeamConversationProps['loadMembers'];
17
18
  readonly drafts: TeamDraftStore;
@@ -1 +1 @@
1
- {"version":3,"file":"TeamThreadPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamThreadPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,mBAAmB,EAInB,gBAAgB,EAGhB,kBAAkB,EAEnB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,aAAa,CAAA;AAc/D,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAA;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAA;IACnC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACxD,QAAQ,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAA;IACtE,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;IACpE,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAA;IAC1D,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAA;IAC9C,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACxD,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC;AA8BD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,+BAuqBxD"}
1
+ {"version":3,"file":"TeamThreadPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamThreadPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,mBAAmB,EAInB,gBAAgB,EAGhB,kBAAkB,EAEnB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,aAAa,CAAA;AAe/D,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAA;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAA;IACnC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACxD,QAAQ,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAA;IACtE,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,oBAAoB,CAAC,CAAA;IACxE,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;IACpE,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAA;IAC1D,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAA;IAC9C,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACxD,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC;AA8BD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,+BAgsBxD"}
@@ -5,7 +5,8 @@ import { TeamComposer } from "./TeamComposer.js";
5
5
  import { TeamPresenceDot } from "./TeamPresenceDot.js";
6
6
  import { TeamMessage } from "./TeamMessage.js";
7
7
  import { TeamRunDivider } from "./TeamRunDivider.js";
8
- import { formatActivity, formatClaimState, formatTaskStatus, formatTaskTitle, mentionNamesOf } from "./team-formatters.js";
8
+ import { formatActivity, formatClaimState, formatTaskStatus, formatTaskTitle, mentionNamesOf, taskStatusDot } from "./team-formatters.js";
9
+ import { TeamStateDot } from "./TeamStateDot.js";
9
10
  import { mintRequestId } from "./requests.js";
10
11
  import { daySeparatorLabel, isRunGap, timelineDayKey } from "./team-separators.js";
11
12
  import { useTimelineScroll } from "./timeline-scroll.js";
@@ -33,11 +34,14 @@ function readMeta(facts) {
33
34
  return new Map(facts.map(fact => [factKey(fact.fact), fact]));
34
35
  }
35
36
  export function TeamThreadPage(props) {
36
- const { workspaceId, channelRef, taskRef, threadRef, taskNumber, backToWorkspace, selectChannel, selectThread, resolveTaskRefs, putAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, drafts, getAttachment, reply, changeTask, promoteThread, t, } = props;
37
+ const { workspaceId, channelRef, taskRef, threadRef, taskNumber, backToWorkspace, selectChannel, selectThread, resolveTaskRefs, putAttachment, loadChannels, readThread, loadThreadHistory, threadObservations, subscribeChanges, loadMembers, drafts, getAttachment, reply, changeTask, promoteThread, t, } = props;
37
38
  const threadRequest = { threadRef, ...(taskRef === undefined ? {} : { taskRef }) };
38
39
  const [projection, setProjection] = useState();
39
40
  const [channelView, setChannelView] = useState();
40
41
  const [members, setMembers] = useState([]);
42
+ // Current Thread followers; the composer ranks them first because a mention
43
+ // to a follower delivers directly instead of entering the invite detour.
44
+ const [followerIds, setFollowerIds] = useState(() => new Set());
41
45
  const [currentFacts, setCurrentFacts] = useState([]);
42
46
  const [olderFacts, setOlderFacts] = useState([]);
43
47
  const [readFacts, setReadFacts] = useState([]);
@@ -196,29 +200,37 @@ export function TeamThreadPage(props) {
196
200
  // Every arrival while the Thread is open is acknowledged durably: the
197
201
  // timeline renders it either way, and the Human has no manual read
198
202
  // action anymore. The count only feeds the pure jump hint for a reader
199
- // away from the bottom; returning to the bottom clears it.
203
+ // away from the tail; a bottom-pinned reader already sees the arrivals.
200
204
  if (!timeline.isPinned())
201
205
  setNewFactsCount(current => current + additions.length);
202
- const priorSequence = sequenceRef.current;
203
- if (await readCurrent(true))
204
- return;
205
- // The durable acknowledgment did not happen (it failed, a newer read
206
- // superseded it, or the page unmounted); the count keeps the jump hint
207
- // visible unless that newer read now owns the tail.
208
- if (!mountedRef.current || sequenceRef.current !== priorSequence + 1)
209
- return;
210
- setNewFactsCount(current => current + additions.length);
206
+ // The acknowledgment outcome does not change what is on screen: a
207
+ // failed read surfaces through the error surface, not through the count.
208
+ await readCurrent(true);
211
209
  }
212
210
  catch {
213
211
  // A passive refresh is an invalidation convenience; the next explicit action rereads Host state.
214
212
  }
215
213
  };
214
+ // Follower ranking is an enhancement, not a page fact: a failed observation
215
+ // read leaves the roster order in place instead of surfacing an error.
216
+ const refreshFollowers = async () => {
217
+ try {
218
+ const result = await threadObservations({ workspaceId, ...threadRequest });
219
+ if (!mountedRef.current || !result.ok)
220
+ return;
221
+ setFollowerIds(new Set(result.value.followers));
222
+ }
223
+ catch {
224
+ // The next thread-scope wake retries; ranking falls back to roster order.
225
+ }
226
+ };
216
227
  useEffect(() => {
217
228
  mountedRef.current = true;
218
229
  projectionRef.current = undefined;
219
230
  setProjection(undefined);
220
231
  setChannelView(undefined);
221
232
  setMembers([]);
233
+ setFollowerIds(new Set());
222
234
  setCurrentFacts([]);
223
235
  currentFactsRef.current = [];
224
236
  setOlderFacts([]);
@@ -235,9 +247,10 @@ export function TeamThreadPage(props) {
235
247
  void (async () => {
236
248
  // One parallel round covers the whole first paint. The durable read no
237
249
  // longer wakes any change scope, so no second wave follows it.
238
- const [read, history] = await Promise.all([
250
+ const [read, history, observations] = await Promise.all([
239
251
  readThread({ requestId: readRequestIdRef.current, workspaceId, ...threadRequest }),
240
252
  loadThreadHistory({ workspaceId, ...threadRequest, limit: 20 }).catch(() => undefined),
253
+ threadObservations({ workspaceId, ...threadRequest }).catch(() => undefined),
241
254
  ]);
242
255
  if (!mountedRef.current || sequence !== sequenceRef.current)
243
256
  return;
@@ -259,6 +272,8 @@ export function TeamThreadPage(props) {
259
272
  setHistoryCursor(history.value.cursor);
260
273
  setHistoryHasMore(history.value.hasMore);
261
274
  }
275
+ if (observations !== undefined && observations.ok)
276
+ setFollowerIds(new Set(observations.value.followers));
262
277
  setError(undefined);
263
278
  setLoading(false);
264
279
  await drainUnread();
@@ -273,6 +288,8 @@ export function TeamThreadPage(props) {
273
288
  return;
274
289
  }
275
290
  void refreshPassiveFacts();
291
+ // Attention changes wake this scope too; keep the mention ranking current.
292
+ void refreshFollowers();
276
293
  }),
277
294
  subscribeChanges({ kind: 'workspace', workspaceId }, update => {
278
295
  if (!mountedRef.current)
@@ -298,6 +315,14 @@ export function TeamThreadPage(props) {
298
315
  if (newFactsCount > 0 && timeline.isPinned())
299
316
  setNewFactsCount(0);
300
317
  }, [newFactsCount, currentFacts, olderFacts, timeline]);
318
+ // The hint answers "where is the tail?"; the moment the reader is back
319
+ // within the follow margin — by the jump click or their own scroll — it
320
+ // must go away even when no render follows that position change.
321
+ const handleTimelineScroll = () => {
322
+ timeline.onScroll();
323
+ if (timeline.isPinned())
324
+ setNewFactsCount(0);
325
+ };
301
326
  const loadOlder = async () => {
302
327
  if (historyHasMore === false && historyCursor === undefined)
303
328
  return;
@@ -614,7 +639,7 @@ export function TeamThreadPage(props) {
614
639
  // Threads are always entered through a Channel page, so a Channel origin
615
640
  // returns to its timeline; a Thread restored without one returns further.
616
641
  const backLabel = channelRef === undefined ? t('backToWorkspace') : t('backToChannel');
617
- return _jsxs("main", { className: css.surface, "data-team-thread": threadRef, children: [_jsxs("div", { className: css.surfaceHeader, children: [_jsx("div", { className: css.backRow, children: _jsx(Button, { size: "sm", icon: _jsx(IconChevronLeftOutline14, {}), onClick: backToWorkspace, children: backLabel }) }), _jsxs("header", { className: css.headerRow, children: [_jsxs("div", { className: css.headerCopy, children: [_jsxs("div", { className: threadCss.titleLine, children: [_jsx("h1", { children: task === undefined ? t('threadLabel') : t('taskLabel', { number: resolvedTaskNumber ?? '…' }) }), task !== undefined && _jsx(Pill, { children: formatTaskStatus(task.status, t) })] }), taskTitle !== undefined && taskTitle !== '' && _jsx("p", { className: threadCss.taskTitle, title: taskTitle, children: taskTitle })] }), task === undefined && thread !== undefined && _jsx("div", { className: css.headerActions, children: _jsx(Button, { size: "sm", variant: "primary", disabled: pending, onClick: () => { void convertToTask(); }, children: mutating === 'promote' ? t('promotingTask') : t('promoteToTask') }) }), task !== undefined && thread !== undefined && task.resolution !== 'closed' && _jsxs("div", { className: css.headerActions, children: [(() => {
642
+ return _jsxs("main", { className: css.surface, "data-team-thread": threadRef, children: [_jsxs("div", { className: css.surfaceHeader, children: [_jsx("div", { className: css.backRow, children: _jsx(Button, { size: "sm", icon: _jsx(IconChevronLeftOutline14, {}), onClick: backToWorkspace, children: backLabel }) }), _jsxs("header", { className: css.headerRow, children: [_jsxs("div", { className: css.headerCopy, children: [_jsxs("div", { className: threadCss.titleLine, children: [_jsx("h1", { children: task === undefined ? t('threadLabel') : t('taskLabel', { number: resolvedTaskNumber ?? '…' }) }), task !== undefined && _jsxs(Pill, { children: [_jsx(TeamStateDot, { size: 8, state: taskStatusDot(task.status) }), formatTaskStatus(task.status, t)] })] }), taskTitle !== undefined && taskTitle !== '' && _jsx("p", { className: threadCss.taskTitle, title: taskTitle, children: taskTitle })] }), task === undefined && thread !== undefined && _jsx("div", { className: css.headerActions, children: _jsx(Button, { size: "sm", variant: "primary", disabled: pending, onClick: () => { void convertToTask(); }, children: mutating === 'promote' ? t('promotingTask') : t('promoteToTask') }) }), task !== undefined && thread !== undefined && task.resolution !== 'closed' && _jsxs("div", { className: css.headerActions, children: [(() => {
618
643
  const activeClaims = projection?.claims.filter(claim => claim.taskRef === task.taskRef && claim.state === 'active') ?? [];
619
644
  const earlyAccept = task.resolution === 'open' && task.status === 'in_progress' && activeClaims.length > 0;
620
645
  // todo Tasks accept directly: the work finished outside the
@@ -637,7 +662,7 @@ export function TeamThreadPage(props) {
637
662
  })(), task !== undefined && thread !== undefined && _jsx("section", { className: threadCss.workSection, "aria-label": t('claims'), children: _jsx(DisclosureRow, { expandOnRowClick: true, expandable: true, open: claimsOpen, onToggle: () => { setClaimsOpen(current => !current); }, icon: _jsx(IconChecklistOutline14, { size: 14 }), title: `${t('claims')} · ${taskClaims.length}`, children: _jsxs("div", { className: threadCss.claimList, children: [taskClaims.length === 0 && _jsx("p", { className: threadCss.emptyClaims, children: t('noClaims') }), taskClaims.map(claim => {
638
663
  const ownerStatus = members.find(status => status.member.memberId === claim.owner);
639
664
  return _jsxs("article", { className: threadCss.claimRow, children: [ownerStatus === undefined ? _jsx("span", {}) : _jsx(TeamPresenceDot, { status: ownerStatus, t: t }), _jsx("strong", { className: threadCss.claimOwner, children: memberName(claim.owner) }), _jsx("span", { className: threadCss.claimDirection, children: claim.direction }), _jsx("small", { className: threadCss.claimState, children: formatClaimState(claim.state, t) })] }, claim.claimRef);
640
- })] }) }) })] }), _jsx("section", { ref: timeline.ref, onScroll: timeline.onScroll, className: css.timeline, "aria-label": t('timelineLabel'), children: _jsxs("div", { className: css.timelineContent, children: [loading && projection === undefined && error === undefined && _jsx("div", { className: css.emptySurface, children: _jsxs("p", { className: css.loadingState, children: [_jsx("span", { className: css.loadingMark, "aria-hidden": "true" }), t('loadingThread')] }) }), projection === undefined && error !== undefined && _jsxs("div", { className: css.errorState, role: "alert", children: [_jsx("span", { children: error }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => { void readCurrent(); }, children: t('retry') })] }), olderFacts.length > 0 && _jsxs("section", { className: threadCss.historySection, "aria-label": t('olderHistory'), children: [_jsx("h2", { children: t('olderHistory') }), renderFactBlocks(olderFacts, undefined)] }), historyHasMore && _jsx("div", { className: css.timelineAction, children: _jsx(Button, { size: "sm", onClick: () => { void loadOlder(); }, children: t('loadOlder') }) }), currentFactsWithAnchor.length > 0 && _jsx("section", { className: threadCss.publicSection, children: renderFactBlocks(currentFactsWithAnchor, unreadBoundary) }), autoReadExhausted && _jsxs("div", { className: css.timelineAction, role: "alert", children: [_jsx("span", { children: t('autoReadIncomplete') }), _jsx(Button, { size: "sm", onClick: () => { setAutoReadExhausted(false); void drainUnread(); }, disabled: loading, children: t('retry') })] }), newFactsCount > 0 && _jsx("div", { className: threadCss.newUpdates, role: "status", children: _jsx("button", { type: "button", className: threadCss.newUpdatesJump, onClick: timeline.scrollToBottom, children: t('newUpdatesJump', { count: newFactsCount }) }) })] }) }), projection !== undefined && thread !== undefined ? (task?.resolution === 'closed'
665
+ })] }) }) })] }), _jsx("section", { ref: timeline.ref, onScroll: handleTimelineScroll, className: css.timeline, "aria-label": t('timelineLabel'), children: _jsxs("div", { className: css.timelineContent, children: [loading && projection === undefined && error === undefined && _jsx("div", { className: css.emptySurface, children: _jsxs("p", { className: css.loadingState, children: [_jsx("span", { className: css.loadingMark, "aria-hidden": "true" }), t('loadingThread')] }) }), projection === undefined && error !== undefined && _jsxs("div", { className: css.errorState, role: "alert", children: [_jsx("span", { children: error }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => { void readCurrent(); }, children: t('retry') })] }), olderFacts.length > 0 && _jsxs("section", { className: threadCss.historySection, "aria-label": t('olderHistory'), children: [_jsx("h2", { children: t('olderHistory') }), renderFactBlocks(olderFacts, undefined)] }), historyHasMore && _jsx("div", { className: css.timelineAction, children: _jsx(Button, { size: "sm", onClick: () => { void loadOlder(); }, children: t('loadOlder') }) }), currentFactsWithAnchor.length > 0 && _jsx("section", { className: threadCss.publicSection, children: renderFactBlocks(currentFactsWithAnchor, unreadBoundary) }), autoReadExhausted && _jsxs("div", { className: css.timelineAction, role: "alert", children: [_jsx("span", { children: t('autoReadIncomplete') }), _jsx(Button, { size: "sm", onClick: () => { setAutoReadExhausted(false); void drainUnread(); }, disabled: loading, children: t('retry') })] }), newFactsCount > 0 && _jsx("div", { className: threadCss.newUpdates, role: "status", children: _jsx("button", { type: "button", className: threadCss.newUpdatesJump, onClick: () => { setNewFactsCount(0); timeline.scrollToBottom(); }, children: t('newUpdatesJump', { count: newFactsCount }) }) })] }) }), projection !== undefined && thread !== undefined ? (task?.resolution === 'closed'
641
666
  ? _jsxs("div", { className: threadCss.closedBar, "data-team-closed": true, children: [error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error }), _jsxs("div", { className: threadCss.closedNotice, children: [_jsx("span", { children: t('taskClosedNotice') }), _jsx(Button, { size: "sm", variant: "outline", disabled: pending, onClick: () => { void mutateTask('reopen'); }, children: t('reopenTask') })] })] })
642
- : _jsx(TeamComposer, { members: channelMembers, recipients: recipients, draft: draft, pending: pending, ...(statusMessage === undefined ? {} : { confirmation: statusMessage }), ...(error === undefined ? {} : { error }), onDraftChange: next => { drafts.writeDraft(draftKey, next); setConfirmation(undefined); setReplyRequestId(undefined); setStatusMessage(undefined); }, onRecipientsChange: next => { drafts.writeRecipients(draftKey, next); setConfirmation(undefined); setReplyRequestId(undefined); setStatusMessage(undefined); }, onSubmit: () => { void sendReply(); }, placeholder: t('replyPlaceholder'), pendingFiles: pendingFiles, onFilesChange: setPendingFiles, t: t }, draftKey)) : _jsx("div", {})] });
667
+ : _jsx(TeamComposer, { members: channelMembers, followerMemberIds: followerIds, recipients: recipients, draft: draft, pending: pending, ...(statusMessage === undefined ? {} : { confirmation: statusMessage }), ...(error === undefined ? {} : { error }), onDraftChange: next => { drafts.writeDraft(draftKey, next); setConfirmation(undefined); setReplyRequestId(undefined); setStatusMessage(undefined); }, onRecipientsChange: next => { drafts.writeRecipients(draftKey, next); setConfirmation(undefined); setReplyRequestId(undefined); setStatusMessage(undefined); }, onSubmit: () => { void sendReply(); }, placeholder: t('replyPlaceholder'), pendingFiles: pendingFiles, onFilesChange: setPendingFiles, t: t }, draftKey)) : _jsx("div", {})] });
643
668
  }
@@ -1,3 +1,3 @@
1
1
  import type { TeamSidebarProps } from './slots.ts';
2
- export declare function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, updateMember, recoverMember, clearMemberContext, joinChannel, removeChannelMember, loadModels, openMemberSession }: TeamSidebarProps): import("react").JSX.Element;
2
+ export declare function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember, clearMemberContext, archiveMember, joinChannel, removeChannelMember, loadModels, openMemberSession }: TeamSidebarProps): import("react").JSX.Element;
3
3
  //# sourceMappingURL=TeamWorkspaceBrowser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamWorkspaceBrowser.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceBrowser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAUlD,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,+BA8DnV"}
1
+ {"version":3,"file":"TeamWorkspaceBrowser.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceBrowser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAUlD,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,+BA8DlX"}
@@ -7,7 +7,7 @@ import { useSidebarSectionOpen, setSidebarSectionOpen } from "./sidebar-sections
7
7
  import { TeamAgentsPanel } from "./TeamAgentsPanel.js";
8
8
  import { TeamChannelsPanel } from "./TeamChannelsPanel.js";
9
9
  import css from './sidebar.module.css';
10
- export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, updateMember, recoverMember, clearMemberContext, joinChannel, removeChannelMember, loadModels, openMemberSession }) {
10
+ export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember, clearMemberContext, archiveMember, joinChannel, removeChannelMember, loadModels, openMemberSession }) {
11
11
  const navigationState = useSyncExternalStore(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
12
12
  const workspaces = useWorkspaces(state => state.items);
13
13
  const selected = navigationState.workspaceId;
@@ -39,5 +39,5 @@ export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWo
39
39
  if (!wide) {
40
40
  return _jsxs("nav", { className: css.railWorkspace, "aria-label": t('workspaceSections'), children: [_jsx(Tooltip, { label: t('channels'), side: "right", children: _jsx("button", { type: "button", className: css.railButton, "aria-label": t('channels'), onClick: () => { setPendingSection('channels'); expandSidebar(); }, children: _jsx(IconListPenOutline16, { size: 16 }) }) }), _jsx(Tooltip, { label: t('agents'), side: "right", children: _jsx("button", { type: "button", className: css.railButton, "aria-label": t('agents'), onClick: () => { setPendingSection('agents'); expandSidebar(); }, children: _jsx(IconAgentPresetOutline16, { size: 16 }) }) })] });
41
41
  }
42
- return _jsxs("section", { className: css.workspaceBrowser, "aria-label": t('workspaces'), children: [_jsx(TeamSidebarSection, { title: t('workspaces'), open: workspacesOpen, onToggle: open => { setSidebarSectionOpen(undefined, 'workspaces', open); }, children: _jsxs("div", { className: css.workspaceList, children: [workspaces.map(workspace => _jsx(TeamWorkspaceRow, { workspaceId: workspace.workspaceId, title: workspace.title, path: workspace.path, selected: workspace.workspaceId === selectedId, current: workspace.workspaceId === selectedId && overviewIsCurrent, onSelect: selectWorkspace }, workspace.workspaceId)), workspaces.length === 0 && _jsx("p", { className: css.emptyState, children: t('empty') })] }) }), selectedId !== undefined && _jsxs("div", { className: css.workspaceSection, children: [_jsx("div", { ref: channelsRef, children: _jsx(TeamChannelsPanel, { workspaceId: selectedId, loadMembers: loadMembers, loadChannels: loadChannels, subscribeChanges: subscribeChanges, createChannel: createChannel, updateChannel: updateChannel, joinChannel: joinChannel, removeChannelMember: removeChannelMember, creatingAgents: creatingAgents.filter(request => request.workspaceId === selectedId), ...(navigationState.memberSessionId !== undefined || navigationState.channelRef === undefined ? {} : { selectedChannelRef: navigationState.channelRef }), selectChannel: selectChannel, t: t }, selectedId) }), _jsx("div", { ref: agentsRef, children: _jsx(TeamAgentsPanel, { workspaceId: selectedId, loadMembers: loadMembers, subscribeChanges: subscribeChanges, addMember: addMember, updateMember: updateMember, recoverMember: recoverMember, clearMemberContext: clearMemberContext, loadModels: loadModels, ...(navigationState.memberSessionId === undefined ? {} : { memberSessionId: navigationState.memberSessionId }), openMemberSession: openMemberSession, onCreatingChange: (request, creating) => { setCreatingAgents(current => creating ? [...current.filter(item => item.requestId !== request.requestId), request] : current.filter(item => item.requestId !== request.requestId)); }, t: t }, selectedId) })] })] });
42
+ return _jsxs("section", { className: css.workspaceBrowser, "aria-label": t('workspaces'), children: [_jsx(TeamSidebarSection, { title: t('workspaces'), open: workspacesOpen, onToggle: open => { setSidebarSectionOpen(undefined, 'workspaces', open); }, children: _jsxs("div", { className: css.workspaceList, children: [workspaces.map(workspace => _jsx(TeamWorkspaceRow, { workspaceId: workspace.workspaceId, title: workspace.title, path: workspace.path, selected: workspace.workspaceId === selectedId, current: workspace.workspaceId === selectedId && overviewIsCurrent, onSelect: selectWorkspace }, workspace.workspaceId)), workspaces.length === 0 && _jsx("p", { className: css.emptyState, children: t('empty') })] }) }), selectedId !== undefined && _jsxs("div", { className: css.workspaceSection, children: [_jsx("div", { ref: channelsRef, children: _jsx(TeamChannelsPanel, { workspaceId: selectedId, loadMembers: loadMembers, loadChannels: loadChannels, subscribeChanges: subscribeChanges, createChannel: createChannel, updateChannel: updateChannel, archiveChannel: archiveChannel, joinChannel: joinChannel, removeChannelMember: removeChannelMember, creatingAgents: creatingAgents.filter(request => request.workspaceId === selectedId), ...(navigationState.memberSessionId !== undefined || navigationState.channelRef === undefined ? {} : { selectedChannelRef: navigationState.channelRef }), selectChannel: selectChannel, t: t }, selectedId) }), _jsx("div", { ref: agentsRef, children: _jsx(TeamAgentsPanel, { workspaceId: selectedId, loadMembers: loadMembers, subscribeChanges: subscribeChanges, addMember: addMember, updateMember: updateMember, recoverMember: recoverMember, clearMemberContext: clearMemberContext, archiveMember: archiveMember, loadModels: loadModels, ...(navigationState.memberSessionId === undefined ? {} : { memberSessionId: navigationState.memberSessionId }), openMemberSession: openMemberSession, onCreatingChange: (request, creating) => { setCreatingAgents(current => creating ? [...current.filter(item => item.requestId !== request.requestId), request] : current.filter(item => item.requestId !== request.requestId)); }, t: t }, selectedId) })] })] });
43
43
  }
@@ -1,4 +1,4 @@
1
- import type { WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client';
1
+ import type { WorkspaceId } from '@deepseek-ai/dsh-api-workspace-controller/client';
2
2
  export declare function TeamWorkspaceRow({ workspaceId, title, path, selected, current, onSelect }: {
3
3
  workspaceId: WorkspaceId;
4
4
  title: string;
@@ -1 +1 @@
1
- {"version":3,"file":"TeamWorkspaceRow.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceRow.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAGzE,wBAAgB,gBAAgB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAC1F,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAA;CAC7C,+BAgBA"}
1
+ {"version":3,"file":"TeamWorkspaceRow.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceRow.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAGnF,wBAAgB,gBAAgB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAC1F,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAA;CAC7C,+BAgBA"}
@@ -1,4 +1,4 @@
1
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
1
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
2
2
  import { TeamNavigation } from './navigation.ts';
3
3
  import { TeamDraftStore } from './drafts.ts';
4
4
  import { type TeamKey } from './locales.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,wCAAwC,CAAA;AAiCtF,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAO5C,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAEnD,YAAY,EAAE,QAAQ,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC9F,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAIhD,eAAO,MAAM,MAAM,UAElB,CAAA;AAED,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,IAAI,EAAE,OAAO,CAAA;KACd;CACF;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,cAAc,EAAE,cAAc,CAAA;QAC9B,UAAU,EAAE,cAAc,CAAA;KAC3B;CACF;AA0ND,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAoCnE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAK5C,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAEnD,YAAY,EAAE,QAAQ,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC9F,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAIhD,eAAO,MAAM,MAAM,UAElB,CAAA;AAED,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,IAAI,EAAE,OAAO,CAAA;KACd;CACF;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,cAAc,EAAE,cAAc,CAAA;QAC9B,UAAU,EAAE,cAAc,CAAA;KAC3B;CACF;AAyJD,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7D"}
@@ -6,13 +6,11 @@ import { TeamFooterAction } from "./TeamFooterAction.js";
6
6
  import { TeamSettings } from "./TeamSettings.js";
7
7
  import { TeamConversation } from "./TeamConversation.js";
8
8
  import { TeamWorkspaceBrowser } from "./TeamWorkspaceBrowser.js";
9
- import { TeamMemberSessionComposer } from "./TeamMemberSessionComposer.js";
10
- import { admitTeamCompact, createTeamMemberSessionSources } from "./member-session-input.js";
11
9
  import { en, zh } from "./locales.js";
12
10
  export { TeamNavigation } from "./navigation.js";
13
11
  const NS = 'team';
14
12
  export const inject = [
15
- 'slots', 'workspaces', 'locale', 'remote', 'sessions', 'connection', 'conversation', 'inputTriggers',
13
+ 'slots', 'workspaces', 'locale', 'remote', 'remote.session', 'sessions', 'connection', 'conversation',
16
14
  ];
17
15
  function registerModeShadow(ctx, navigation, changes, drafts, name, component, extraInject) {
18
16
  // Stay in Team mode: the conversation shadow stands down for Member Session
@@ -37,15 +35,13 @@ function registerModeShadow(ctx, navigation, changes, drafts, name, component, e
37
35
  joinChannel: (request) => ctx.remote.agentTeam.joinChannel(request),
38
36
  removeChannelMember: (request) => ctx.remote.agentTeam.removeChannelMember(request),
39
37
  updateChannel: (request) => ctx.remote.agentTeam.updateChannel(request),
38
+ archiveChannel: (request) => ctx.remote.agentTeam.archiveChannel(request),
40
39
  updateMember: (request) => ctx.remote.agentTeam.updateMember(request),
41
40
  recoverMember: (request) => ctx.remote.agentTeam.recoverMember(request),
42
41
  clearMemberContext: (request) => ctx.remote.agentTeam.clearMemberContext(request),
42
+ archiveMember: (request) => ctx.remote.agentTeam.archiveMember(request),
43
43
  // The Host-scoped catalog needs no live Member, so suspended ones stay editable too.
44
- loadModels: async () => {
45
- const connection = ctx.get('connection');
46
- const response = await connection.api.llm.models({});
47
- return response.result;
48
- },
44
+ loadModels: () => ctx.remote.session.modelCatalog(),
49
45
  openMemberSession: openMemberSessionImpl,
50
46
  };
51
47
  ctx.slots.inject(name, () => {
@@ -69,6 +65,7 @@ function registerModeShadow(ctx, navigation, changes, drafts, name, component, e
69
65
  ...(name === 'conversation' ? {
70
66
  readThread: (request) => ctx.remote.agentTeam.readThread(request),
71
67
  loadThreadHistory: (request) => ctx.remote.agentTeam.threadHistory(request),
68
+ threadObservations: (request) => ctx.remote.agentTeam.threadObservations(request),
72
69
  sendMessage: (request) => ctx.remote.agentTeam.sendMessage(request),
73
70
  putAttachment: (request) => ctx.remote.agentTeam.putAttachment(request),
74
71
  getAttachment: (request) => ctx.remote.agentTeam.getAttachment(request),
@@ -98,49 +95,6 @@ function registerModeShadow(ctx, navigation, changes, drafts, name, component, e
98
95
  };
99
96
  });
100
97
  }
101
- function registerMemberSessionComposer(ctx, navigation) {
102
- ctx.slots.inject('conversation.composer.bar', () => {
103
- let dispose;
104
- let registeredSessionId;
105
- const reconcile = () => {
106
- const memberSessionId = navigation.getSnapshot().memberSessionId;
107
- const active = navigation.getSnapshot().mode === 'team' && memberSessionId !== undefined;
108
- if (dispose !== undefined && (!active || registeredSessionId !== memberSessionId)) {
109
- dispose();
110
- dispose = undefined;
111
- registeredSessionId = undefined;
112
- }
113
- if (active && dispose === undefined) {
114
- registeredSessionId = memberSessionId;
115
- dispose = ctx.slots.register({
116
- name: 'conversation.composer.bar',
117
- priority: -100,
118
- // The registration may remain live during a session transition, but
119
- // it elects only when the shell's current Session is the embedded
120
- // Member. This avoids taking an ordinary Session if selection races.
121
- select: () => ctx.sessions.list.getSnapshot().current === memberSessionId ? {} : null,
122
- inject: (sessionId) => {
123
- const actx = ctx.sessions.scope(sessionId);
124
- if (actx === undefined)
125
- throw new Error(`agent-team: Member session ${String(sessionId)} has no client scope`);
126
- const sessions = ctx.sessions;
127
- return {
128
- controller: ctx.get('inputTriggers').sessionOf(actx),
129
- stop: () => { void sessions.sessionOf(actx)?.cancel(); },
130
- submitInput: (mode) => ctx.conversation.input.for(actx).submit(mode),
131
- };
132
- },
133
- }, TeamMemberSessionComposer);
134
- }
135
- };
136
- const offNavigation = navigation.subscribe(reconcile);
137
- reconcile();
138
- return () => {
139
- offNavigation();
140
- dispose?.();
141
- };
142
- });
143
- }
144
98
  function applyUi(ctx) {
145
99
  ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'agent-team: dictionaries');
146
100
  const navigation = new TeamNavigation();
@@ -154,37 +108,16 @@ function applyUi(ctx) {
154
108
  void disposeDrafts();
155
109
  }, 'agent-team: navigation service');
156
110
  const changes = new TeamChangeStream((request, signal) => ctx.remote.agentTeam.changes(request, signal));
157
- const triggerSources = createTeamMemberSessionSources({
158
- isEmbeddedMemberSession: sessionId => {
159
- const snapshot = navigation.getSnapshot();
160
- return snapshot.mode === 'team' && snapshot.memberSessionId === sessionId && snapshot.workspaceId !== undefined;
161
- },
162
- members: async () => {
163
- const workspaceId = navigation.getSnapshot().workspaceId;
164
- if (workspaceId === undefined)
165
- return [];
166
- const result = await ctx.remote.agentTeam.members({ workspaceId });
167
- return result.ok ? result.value : [];
168
- },
169
- executeCompact: async (sessionId) => {
170
- const actx = ctx.sessions.scope(sessionId);
171
- const session = actx === undefined ? undefined : ctx.sessions.sessionOf(actx);
172
- return session === undefined ? { kind: 'error', text: 'current Member Session is unavailable' } : admitTeamCompact(session);
173
- },
174
- });
175
- const inputTriggers = ctx.get('inputTriggers');
176
- ctx.effect(() => {
177
- const disposers = triggerSources.map(source => inputTriggers.registerSource(source));
178
- return () => { for (const dispose of disposers)
179
- dispose(); };
180
- }, 'agent-team: Member session trigger sources');
181
111
  const loadMemberGroups = async () => {
182
112
  const workspaces = ctx.workspaces.list.getSnapshot().items;
183
113
  const groups = await Promise.all(workspaces.map(async (workspace) => {
184
114
  const result = await ctx.remote.agentTeam.members({ workspaceId: workspace.workspaceId });
185
115
  if (!result.ok)
186
116
  throw new Error(result.error.message);
187
- return { workspaceId: workspace.workspaceId, workspaceTitle: workspace.title, members: result.value };
117
+ // The members modal is a listing surface: archived Members are hidden
118
+ // everywhere, and removed (inactive) ones never belong in a roster.
119
+ const members = result.value.filter(status => status.member.state !== 'inactive' && status.member.state !== 'archived');
120
+ return { workspaceId: workspace.workspaceId, workspaceTitle: workspace.title, members };
188
121
  }));
189
122
  return groups.filter(group => group.members.length > 0);
190
123
  };
@@ -216,7 +149,6 @@ function applyUi(ctx) {
216
149
  }, TeamFooterAction));
217
150
  registerModeShadow(ctx, navigation, changes, drafts, 'sidebar.workspaces', TeamWorkspaceBrowser);
218
151
  registerModeShadow(ctx, navigation, changes, drafts, 'conversation', TeamConversation);
219
- registerMemberSessionComposer(ctx, navigation);
220
152
  registerModeShadow(ctx, navigation, changes, drafts, 'sidebar.settings', TeamSettings, () => ({ loadMemberGroups }));
221
153
  }
222
154
  export async function apply(ctx) {
@@ -12,6 +12,9 @@ export declare const zh: {
12
12
  readonly addAgent: "添加 Agent";
13
13
  readonly cancel: "取消";
14
14
  readonly close: "关闭";
15
+ readonly copyCode: "复制";
16
+ readonly copiedCode: "已复制";
17
+ readonly markdownFootnotes: "脚注";
15
18
  readonly retry: "重试";
16
19
  readonly agentName: "名称";
17
20
  readonly agentDescription: "说明";
@@ -45,6 +48,16 @@ export declare const zh: {
45
48
  readonly clearContextNotice: "将结束 {name} 当前的会话上下文并从空白开始:旧对话会归档保留在会话记录中。{name} 的身份、私有记忆与 notes、频道和会话绑定都保持不变,后续协作从新上下文继续累积。";
46
49
  readonly clearContextConfirm: "开始全新上下文";
47
50
  readonly clearContextFailed: "清空上下文失败:{message}";
51
+ readonly archiveAgent: "归档";
52
+ readonly archiveAgentTitle: "归档 Agent:{name}";
53
+ readonly archiveAgentNotice: "将把 {name} 从所有列表收起:会话与私有记忆保留在磁盘上、活跃 Claim 会释放,但暂无恢复入口。";
54
+ readonly archiveAgentConfirm: "归档";
55
+ readonly archiveAgentFailed: "归档失败:{message}";
56
+ readonly archiveChannel: "归档频道";
57
+ readonly archiveChannelTitle: "归档频道:{name}";
58
+ readonly archiveChannelNotice: "将把 {name} 及其全部讨论从所有列表收起:数据保留、所有成员在此频道的活跃 Claim 会释放,但暂无恢复入口。";
59
+ readonly archiveChannelConfirm: "归档频道";
60
+ readonly archiveChannelFailed: "归档频道失败:{message}";
48
61
  readonly optionalSuffix: "(可选)";
49
62
  readonly agentDescriptionPlaceholder: "留空则暂无描述";
50
63
  readonly membersPickerEmpty: "选择初始成员";
@@ -154,6 +167,9 @@ export declare const en: {
154
167
  readonly addAgent: "Add Agent";
155
168
  readonly cancel: "Cancel";
156
169
  readonly close: "Close";
170
+ readonly copyCode: "Copy";
171
+ readonly copiedCode: "Copied";
172
+ readonly markdownFootnotes: "Footnotes";
157
173
  readonly retry: "Retry";
158
174
  readonly agentName: "Name";
159
175
  readonly agentDescription: "Description";
@@ -187,6 +203,16 @@ export declare const en: {
187
203
  readonly clearContextNotice: "This ends {name}'s current session context and starts blank: the previous conversation is archived and stays in the session history. {name}'s identity, private memory and notes, channel and session bindings are untouched, and future collaboration accumulates from the new context.";
188
204
  readonly clearContextConfirm: "Start from new context";
189
205
  readonly clearContextFailed: "Failed to clear context: {message}";
206
+ readonly archiveAgent: "Archive";
207
+ readonly archiveAgentTitle: "Archive Agent: {name}";
208
+ readonly archiveAgentNotice: "This hides {name} from every list: the session log and private memory stay on disk and active Claims release, but there is no restore entry point yet.";
209
+ readonly archiveAgentConfirm: "Archive";
210
+ readonly archiveAgentFailed: "Failed to archive: {message}";
211
+ readonly archiveChannel: "Archive Channel";
212
+ readonly archiveChannelTitle: "Archive Channel: {name}";
213
+ readonly archiveChannelNotice: "This hides {name} and all of its discussions from every list: the data stays, every Member's active Claims in this Channel release, but there is no restore entry point yet.";
214
+ readonly archiveChannelConfirm: "Archive Channel";
215
+ readonly archiveChannelFailed: "Failed to archive Channel: {message}";
190
216
  readonly optionalSuffix: " (optional)";
191
217
  readonly agentDescriptionPlaceholder: "Leave empty if not needed";
192
218
  readonly membersPickerEmpty: "Choose initial members";
@@ -1 +1 @@
1
- {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6IL,CAAA;AAEV,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6IL,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0JL,CAAA;AAEV,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0JL,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,CAAA"}