@wowyuarm/dsh-agent-team 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +17 -4
  2. package/README.zh.md +17 -4
  3. package/package.json +53 -47
  4. package/packages/agent-team/README.md +6 -4
  5. package/packages/agent-team/README.zh.md +6 -4
  6. package/packages/agent-team/lib/context-management.js +40 -50
  7. package/packages/agent-team/lib/context-projection.js +15 -1
  8. package/packages/agent-team/lib/index.js +244 -154
  9. package/packages/agent-team/lib/invariant.js +38 -4
  10. package/packages/agent-team/lib/ledger.js +775 -383
  11. package/packages/agent-team/lib/member-context.js +6 -2
  12. package/packages/agent-team/lib/member-runtime.js +47 -9
  13. package/packages/agent-team/lib/member-time-context.js +20 -5
  14. package/packages/agent-team/lib/mentions.js +56 -0
  15. package/packages/agent-team/lib/pressure-policy.js +33 -9
  16. package/packages/agent-team/lib/session-event-cursor.js +116 -0
  17. package/packages/agent-team/lib/session-remediation.js +38 -26
  18. package/packages/agent-team/lib/spec.js +47 -34
  19. package/packages/agent-team/lib/stored-session-reader.js +138 -0
  20. package/packages/agent-team/lib/typert.host.js +157 -41
  21. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  22. package/packages/agent-team/lib/typert.remote-client.js +129 -32
  23. package/packages/agent-team/lib/types/context-management.d.ts +7 -0
  24. package/packages/agent-team/lib/types/context-management.d.ts.map +1 -1
  25. package/packages/agent-team/lib/types/context-projection.d.ts +8 -0
  26. package/packages/agent-team/lib/types/context-projection.d.ts.map +1 -1
  27. package/packages/agent-team/lib/types/index.d.ts +77 -7
  28. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  29. package/packages/agent-team/lib/types/invariant.d.ts.map +1 -1
  30. package/packages/agent-team/lib/types/ledger.d.ts +251 -20
  31. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  32. package/packages/agent-team/lib/types/member-context.d.ts.map +1 -1
  33. package/packages/agent-team/lib/types/member-runtime.d.ts +2 -1
  34. package/packages/agent-team/lib/types/member-runtime.d.ts.map +1 -1
  35. package/packages/agent-team/lib/types/member-time-context.d.ts.map +1 -1
  36. package/packages/agent-team/lib/types/mentions.d.ts +34 -0
  37. package/packages/agent-team/lib/types/mentions.d.ts.map +1 -0
  38. package/packages/agent-team/lib/types/pressure-policy.d.ts +18 -0
  39. package/packages/agent-team/lib/types/pressure-policy.d.ts.map +1 -1
  40. package/packages/agent-team/lib/types/session-event-cursor.d.ts +119 -0
  41. package/packages/agent-team/lib/types/session-event-cursor.d.ts.map +1 -0
  42. package/packages/agent-team/lib/types/session-remediation.d.ts +23 -0
  43. package/packages/agent-team/lib/types/session-remediation.d.ts.map +1 -1
  44. package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
  45. package/packages/agent-team/lib/types/stored-session-reader.d.ts +92 -0
  46. package/packages/agent-team/lib/types/stored-session-reader.d.ts.map +1 -0
  47. package/packages/agent-team/lib/types/types/entities.d.ts +28 -20
  48. package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -1
  49. package/packages/agent-team/lib/types/types/operations.d.ts +45 -19
  50. package/packages/agent-team/lib/types/types/operations.d.ts.map +1 -1
  51. package/packages/agent-team/lib/types/types/requests-results.d.ts +87 -4
  52. package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
  53. package/packages/agent-team/preset/team-member/agent.cordis.yml +49 -7
  54. package/packages/client-agent-team/README.md +1 -1
  55. package/packages/client-agent-team/README.zh.md +1 -1
  56. package/packages/client-agent-team/lib/client.js +2357 -1207
  57. package/packages/client-agent-team/lib/client.js.map +1 -1
  58. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
  59. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +27 -7
  60. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts +18 -0
  61. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts.map +1 -0
  62. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.js +22 -0
  63. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +3 -1
  64. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
  65. package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +167 -35
  66. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
  67. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +23 -27
  68. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts +11 -5
  69. package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
  70. package/packages/client-agent-team/lib/types/client/TeamComposer.js +26 -26
  71. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
  72. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
  73. package/packages/client-agent-team/lib/types/client/TeamConversation.js +9 -2
  74. package/packages/client-agent-team/lib/types/client/TeamCountBadge.d.ts +20 -0
  75. package/packages/client-agent-team/lib/types/client/TeamCountBadge.d.ts.map +1 -0
  76. package/packages/client-agent-team/lib/types/client/TeamCountBadge.js +25 -0
  77. package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts +25 -0
  78. package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts.map +1 -0
  79. package/packages/client-agent-team/lib/types/client/TeamInboxPage.js +139 -0
  80. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -1
  81. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +8 -24
  82. package/packages/client-agent-team/lib/types/client/TeamMemberRow.d.ts +43 -0
  83. package/packages/client-agent-team/lib/types/client/TeamMemberRow.d.ts.map +1 -0
  84. package/packages/client-agent-team/lib/types/client/TeamMemberRow.js +27 -0
  85. package/packages/client-agent-team/lib/types/client/TeamMembersAction.d.ts +2 -2
  86. package/packages/client-agent-team/lib/types/client/TeamMembersAction.d.ts.map +1 -1
  87. package/packages/client-agent-team/lib/types/client/TeamMembersAction.js +2 -2
  88. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +9 -2
  89. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
  90. package/packages/client-agent-team/lib/types/client/TeamMessage.js +11 -4
  91. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.d.ts +8 -0
  92. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.d.ts.map +1 -1
  93. package/packages/client-agent-team/lib/types/client/TeamPresenceDot.js +21 -1
  94. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
  95. package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +108 -30
  96. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts +1 -1
  97. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
  98. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +68 -7
  99. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  100. package/packages/client-agent-team/lib/types/client/index.js +19 -9
  101. package/packages/client-agent-team/lib/types/client/locales.d.ts +40 -2
  102. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
  103. package/packages/client-agent-team/lib/types/client/locales.js +40 -2
  104. package/packages/client-agent-team/lib/types/client/navigation.d.ts +10 -0
  105. package/packages/client-agent-team/lib/types/client/navigation.d.ts.map +1 -1
  106. package/packages/client-agent-team/lib/types/client/navigation.js +18 -7
  107. package/packages/client-agent-team/lib/types/client/scope-coverage.d.ts +41 -0
  108. package/packages/client-agent-team/lib/types/client/scope-coverage.d.ts.map +1 -0
  109. package/packages/client-agent-team/lib/types/client/scope-coverage.js +64 -0
  110. package/packages/client-agent-team/lib/types/client/slots.d.ts +7 -2
  111. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
  112. package/packages/client-agent-team/lib/types/client/team-changes.d.ts +33 -2
  113. package/packages/client-agent-team/lib/types/client/team-changes.d.ts.map +1 -1
  114. package/packages/client-agent-team/lib/types/client/team-changes.js +107 -25
  115. package/packages/client-agent-team/lib/types/client/team-dialog-save.d.ts +20 -0
  116. package/packages/client-agent-team/lib/types/client/team-dialog-save.d.ts.map +1 -0
  117. package/packages/client-agent-team/lib/types/client/team-dialog-save.js +36 -0
  118. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +43 -1
  119. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
  120. package/packages/client-agent-team/lib/types/client/team-formatters.js +81 -6
  121. package/packages/tool-agent-team/README.md +2 -2
  122. package/packages/tool-agent-team/README.zh.md +2 -2
  123. package/packages/tool-agent-team/lib/context-tools.js +18 -14
  124. package/packages/tool-agent-team/lib/host-access.js +20 -0
  125. package/packages/tool-agent-team/lib/index.js +44 -32
  126. package/packages/tool-agent-team/lib/types/context-tools.d.ts.map +1 -1
  127. package/packages/tool-agent-team/lib/types/host-access.d.ts +14 -0
  128. package/packages/tool-agent-team/lib/types/host-access.d.ts.map +1 -0
  129. package/packages/tool-agent-team/lib/types/index.d.ts.map +1 -1
  130. package/packages/agent-team/lib/progress-nudge.js +0 -328
  131. package/packages/agent-team/lib/types/progress-nudge.d.ts +0 -136
  132. package/packages/agent-team/lib/types/progress-nudge.d.ts.map +0 -1
  133. package/packages/client-agent-team/lib/types/client/TeamSettings.d.ts +0 -3
  134. package/packages/client-agent-team/lib/types/client/TeamSettings.d.ts.map +0 -1
  135. package/packages/client-agent-team/lib/types/client/TeamSettings.js +0 -5
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from 'react';
2
+ import { useEffect, useState } from 'react';
3
3
  import { Button, IconChevronDownOutline14, Input, Menu, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import { mintRequestId } from "./requests.js";
5
+ import { useEditDialogSave } from "./team-dialog-save.js";
5
6
  import createCss from './create.module.css';
6
7
  import css from './sidebar.module.css';
7
8
  /** Model option key inside one editor; opaque and resolved against the loaded groups. */
@@ -77,9 +78,11 @@ export function AgentEditorDialog({ status, updateMember, loadModels, onCommitte
77
78
  const [handle, setHandle] = useState(status.member.handle);
78
79
  const [description, setDescription] = useState(status.member.description);
79
80
  const [model, setModel] = useState(status.member.model);
80
- const [saving, setSaving] = useState(false);
81
- const [error, setError] = useState();
82
- const pendingRequest = useRef();
81
+ const { saving, error, pendingRequest, save } = useEditDialogSave({
82
+ save: updateMember,
83
+ onCommitted,
84
+ onClose,
85
+ });
83
86
  const dirty = handle.trim() !== status.member.handle || description.trim() !== status.member.description
84
87
  || !sameModel(model, status.member.model);
85
88
  const submit = async (event) => {
@@ -104,26 +107,7 @@ export function AgentEditorDialog({ status, updateMember, loadModels, onCommitte
104
107
  requestId: mintRequestId(),
105
108
  ...payload,
106
109
  };
107
- pendingRequest.current = request;
108
- setSaving(true);
109
- setError(undefined);
110
- try {
111
- const result = await updateMember(request);
112
- if (result.ok) {
113
- pendingRequest.current = undefined;
114
- await onCommitted();
115
- onClose();
116
- }
117
- else {
118
- setError(result.error.message);
119
- }
120
- }
121
- catch (cause) {
122
- setError(cause instanceof Error ? cause.message : String(cause));
123
- }
124
- finally {
125
- setSaving(false);
126
- }
110
+ await save(request);
127
111
  };
128
112
  return (_jsx(Modal, { open: true, onClose: onClose, title: t('editAgent'), description: `@${status.member.handle}`, closeLabel: t('close'), contentClassName: createCss.dialogContent, footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", disabled: saving, onClick: onClose, children: t('cancel') }), _jsx(Button, { type: "submit", form: "team-agent-edit-form", variant: "primary", disabled: saving || !dirty || handle.trim().length === 0, children: saving ? t('editSaving') : t('editSave') })] }), children: _jsxs("form", { id: "team-agent-edit-form", className: createCss.form, onSubmit: event => { void submit(event); }, children: [_jsxs("label", { className: createCss.field, children: [_jsx("span", { children: t('agentName') }), _jsx(Input, { className: createCss.input, value: handle, onChange: event => { setHandle(event.target.value); pendingRequest.current = undefined; }, disabled: saving, autoFocus: true })] }), _jsxs("label", { className: createCss.field, children: [_jsxs("span", { children: [t('agentDescription'), t('optionalSuffix')] }), _jsx(Input, { className: createCss.input, value: description, placeholder: t('agentDescriptionPlaceholder'), onChange: event => { setDescription(event.target.value); pendingRequest.current = undefined; }, disabled: saving })] }), _jsx(ModelPickerField, { model: model, onModelChange: choice => { pendingRequest.current = undefined; setModel(choice); }, loadModels: loadModels, disabled: saving, t: t }), error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }));
129
113
  }
@@ -0,0 +1,43 @@
1
+ import type { AgentTeamClientMemberStatus } from '@wowyuarm/dsh-agent-team/types';
2
+ import type { TeamSidebarProps } from './slots.ts';
3
+ /** One membership action: what it says and which Member it acts on. */
4
+ export interface TeamMemberAction {
5
+ readonly label: string;
6
+ readonly onSelect: () => void;
7
+ readonly disabled?: boolean;
8
+ }
9
+ /**
10
+ * The one place a Member's identity is drawn: the presence-bearing avatar plus
11
+ * the handle over its description. Read-only rosters, the rosters with a
12
+ * membership action, and the sidebar Agent list all render this, so identity,
13
+ * tone and truncation cannot drift between surfaces that show the same person.
14
+ *
15
+ * A fragment, not a row: each surface owns its own row element, hit target and
16
+ * grid, and places this identity in that grid's first two tracks. The handle
17
+ * spelling is the surface's call — rosters address Members the way the
18
+ * composer does (`@handle`), the sidebar names them as the directory does.
19
+ */
20
+ export declare function TeamMemberIdentity({ status, name, className, t }: {
21
+ readonly status: AgentTeamClientMemberStatus;
22
+ /** Handle spelling for this surface; defaults to the mention form. */
23
+ readonly name?: string | undefined;
24
+ /** Surface-local copy hook (sidebar line heights, dialog density). */
25
+ readonly className?: string | undefined;
26
+ readonly t: TeamSidebarProps['t'];
27
+ }): import("react").JSX.Element;
28
+ /**
29
+ * The one roster row: identity, an optional membership action, and the row's
30
+ * own failure line. The action is the row's only chrome, so the eye lands on
31
+ * the handle first and on the action second. A read-only roster omits it and
32
+ * the trailing track collapses, handing its width back to the description.
33
+ */
34
+ export declare function TeamMemberRow({ status, action, error, className, t }: {
35
+ readonly status: AgentTeamClientMemberStatus;
36
+ readonly action?: TeamMemberAction | undefined;
37
+ /** Transport failure for this row's last mutation, announced in place. */
38
+ readonly error?: string | undefined;
39
+ /** Surface-local hook (dialog, sidebar, footer) for its own row rules. */
40
+ readonly className?: string | undefined;
41
+ readonly t: TeamSidebarProps['t'];
42
+ }): import("react").JSX.Element;
43
+ //# sourceMappingURL=TeamMemberRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TeamMemberRow.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMemberRow.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAA;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAIlD,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE;IACjE,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,sEAAsE;IACtE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BAQA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE;IACrE,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAA;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BAMA"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Button } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { TeamMemberAvatar } from "./TeamMemberAvatar.js";
4
+ import css from './member-row.module.css';
5
+ /**
6
+ * The one place a Member's identity is drawn: the presence-bearing avatar plus
7
+ * the handle over its description. Read-only rosters, the rosters with a
8
+ * membership action, and the sidebar Agent list all render this, so identity,
9
+ * tone and truncation cannot drift between surfaces that show the same person.
10
+ *
11
+ * A fragment, not a row: each surface owns its own row element, hit target and
12
+ * grid, and places this identity in that grid's first two tracks. The handle
13
+ * spelling is the surface's call — rosters address Members the way the
14
+ * composer does (`@handle`), the sidebar names them as the directory does.
15
+ */
16
+ export function TeamMemberIdentity({ status, name, className, t }) {
17
+ return _jsxs(_Fragment, { children: [_jsx(TeamMemberAvatar, { status: status, t: t }), _jsxs("span", { className: className === undefined ? css.copy : `${css.copy} ${className}`, children: [_jsx("strong", { children: name ?? `@${status.member.handle.replace(/^@/, '')}` }), _jsx("small", { children: status.member.description })] })] });
18
+ }
19
+ /**
20
+ * The one roster row: identity, an optional membership action, and the row's
21
+ * own failure line. The action is the row's only chrome, so the eye lands on
22
+ * the handle first and on the action second. A read-only roster omits it and
23
+ * the trailing track collapses, handing its width back to the description.
24
+ */
25
+ export function TeamMemberRow({ status, action, error, className, t }) {
26
+ return _jsxs("div", { className: className === undefined ? css.row : `${css.row} ${className}`, "data-team-member-row": true, children: [_jsx(TeamMemberIdentity, { status: status, t: t }), action !== undefined && _jsx(Button, { size: "sm", variant: "outline", className: css.action, disabled: action.disabled === true, onClick: action.onSelect, children: action.label }), error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] });
27
+ }
@@ -1,5 +1,5 @@
1
- import type { TeamFooterProps } from './slots.ts';
2
- type TeamMembersActionProps = Pick<TeamFooterProps, 'wide' | 'loadMemberGroups' | 't'>;
1
+ import type { TeamSettingsProps } from './slots.ts';
2
+ type TeamMembersActionProps = Pick<TeamSettingsProps, 'wide' | 'loadMemberGroups' | 't'>;
3
3
  export declare function TeamMembersAction({ wide, loadMemberGroups, t }: TeamMembersActionProps): import("react").JSX.Element;
4
4
  export {};
5
5
  //# sourceMappingURL=TeamMembersAction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamMembersAction.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMembersAction.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAKjD,KAAK,sBAAsB,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,kBAAkB,GAAG,GAAG,CAAC,CAAA;AAEtF,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,EAAE,EAAE,sBAAsB,+BAuDtF"}
1
+ {"version":3,"file":"TeamMembersAction.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMembersAction.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAKnD,KAAK,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,GAAG,GAAG,CAAC,CAAA;AAExF,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,EAAE,EAAE,sBAAsB,+BAkDtF"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from 'react';
3
3
  import { IconUserOutline16, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
4
- import { TeamPresenceDot } from "./TeamPresenceDot.js";
4
+ import { TeamMemberRow } from "./TeamMemberRow.js";
5
5
  import membersCss from './members.module.css';
6
6
  import css from './team.module.css';
7
7
  export function TeamMembersAction({ wide, loadMemberGroups, t }) {
@@ -28,5 +28,5 @@ export function TeamMembersAction({ wide, loadMemberGroups, t }) {
28
28
  setPanelOpen(false);
29
29
  queueMicrotask(() => { triggerRef.current?.focus(); });
30
30
  };
31
- return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { label: t('members'), delayMs: 500, disabled: wide, children: _jsxs("button", { ref: triggerRef, type: "button", className: wide ? css.settingsAction : `${css.settingsAction} ${css.rail}`, "aria-label": t('members'), "aria-haspopup": "dialog", onClick: openMembers, children: [_jsx(IconUserOutline16, { size: wide ? 16 : 18 }), wide && _jsx("span", { children: t('members') })] }) }), _jsx(Modal, { open: panelOpen, onClose: closeMembers, title: t('members'), closeLabel: t('close'), contentClassName: membersCss.body, children: _jsxs("div", { ref: contentRef, className: membersCss.content, tabIndex: -1, children: [loading && _jsx("p", { className: membersCss.state, role: "status", children: t('loadingAgents') }), !loading && groups.length === 0 && error === undefined && _jsx("p", { className: membersCss.state, children: t('emptyAgents') }), !loading && groups.map(group => (_jsxs("section", { className: membersCss.group, "aria-labelledby": `team-members-${group.workspaceId}`, children: [_jsx("h3", { id: `team-members-${group.workspaceId}`, children: group.workspaceTitle }), group.members.map(status => (_jsxs("div", { className: membersCss.member, children: [_jsx(TeamPresenceDot, { status: status, t: t }), _jsxs("span", { className: membersCss.copy, children: [_jsxs("strong", { children: ["@", status.member.handle] }), _jsx("small", { children: status.member.description })] })] }, status.member.memberId)))] }, group.workspaceId))), error !== undefined && _jsx("p", { className: membersCss.error, role: "alert", children: error })] }) })] }));
31
+ return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { label: t('members'), delayMs: 500, disabled: wide, children: _jsxs("button", { ref: triggerRef, type: "button", className: wide ? css.settingsAction : `${css.settingsAction} ${css.rail}`, "aria-label": t('members'), "aria-haspopup": "dialog", onClick: openMembers, children: [_jsx(IconUserOutline16, { size: wide ? 16 : 18 }), wide && _jsx("span", { children: t('members') })] }) }), _jsx(Modal, { open: panelOpen, onClose: closeMembers, title: t('members'), closeLabel: t('close'), contentClassName: membersCss.body, children: _jsxs("div", { ref: contentRef, className: membersCss.content, tabIndex: -1, children: [loading && _jsx("p", { className: membersCss.state, role: "status", children: t('loadingAgents') }), !loading && groups.length === 0 && error === undefined && _jsx("p", { className: membersCss.state, children: t('emptyAgents') }), !loading && groups.map(group => (_jsxs("section", { className: membersCss.group, "aria-labelledby": `team-members-${group.workspaceId}`, children: [_jsx("h3", { id: `team-members-${group.workspaceId}`, children: group.workspaceTitle }), group.members.map(status => _jsx(TeamMemberRow, { status: status, className: membersCss.member, t: t }, status.member.memberId))] }, group.workspaceId))), error !== undefined && _jsx("p", { className: membersCss.error, role: "alert", children: error })] }) })] }));
32
32
  }
@@ -27,6 +27,13 @@ export interface TeamMessageProps {
27
27
  readonly onResolveTaskRefs?: ((taskRefs: readonly AgentTeamTaskRef[]) => Promise<readonly ResolvedTaskRef[]>) | undefined;
28
28
  readonly children?: ReactNode;
29
29
  }
30
- /** One chat message row with identity chrome and sender-appropriate rendering. */
31
- export declare function TeamMessage({ senderName, memberId, human, body, occurredAt, mentionNames, senderTitle, grouped, showGroupedTime, attachments, loadAttachment, t, onOpenRef, onResolveTaskRefs, children }: TeamMessageProps): import("react").JSX.Element;
30
+ /**
31
+ * One chat message row with identity chrome and sender-appropriate rendering.
32
+ *
33
+ * Memoized because a timeline row is rendered by the page that owns the whole
34
+ * Thread: the Task-ref subscription below lives inside this component, so
35
+ * skipping a render here never detaches it. Callers must therefore keep the
36
+ * props they derive per render (mention names, ref callbacks) identity-stable.
37
+ */
38
+ export declare const TeamMessage: import("react").NamedExoticComponent<TeamMessageProps>;
32
39
  //# sourceMappingURL=TeamMessage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamMessage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoG,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGxI,OAAO,KAAK,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACrH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEvD,OAAO,EAA4E,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAI/H,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;IACpC,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B;2DACuD;IACvD,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,0BAA0B,EAAE,GAAG,SAAS,CAAA;IACxE,6EAA6E;IAC7E,QAAQ,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IAC5E,QAAQ,CAAC,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;IACnD,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACxD,sFAAsF;IACtF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,KAAK,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IACzH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAC9B;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,EAAE,gBAAgB,+BAqH3N"}
1
+ {"version":3,"file":"TeamMessage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0G,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAG9I,OAAO,KAAK,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACrH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEvD,OAAO,EAA4E,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAI/H,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;IACpC,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B;2DACuD;IACvD,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,0BAA0B,EAAE,GAAG,SAAS,CAAA;IACxE,6EAA6E;IAC7E,QAAQ,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAC,eAAe,CAAC,GAAG,SAAS,CAAA;IAC5E,QAAQ,CAAC,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;IACnD,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACxD,sFAAsF;IACtF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,KAAK,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IACzH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAC9B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,wDAqHtB,CAAA"}
@@ -1,12 +1,19 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
2
+ import { Fragment, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
3
3
  import { MarkdownText, 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";
6
6
  import { formatMessageTime, isSingleBrandedRef, memberHue, planMessageBody, shouldClampMessage, splitBrandedRefs, splitMentionNames } from "./team-formatters.js";
7
7
  import css from './conversation.module.css';
8
- /** One chat message row with identity chrome and sender-appropriate rendering. */
9
- export function TeamMessage({ senderName, memberId, human, body, occurredAt, mentionNames, senderTitle, grouped, showGroupedTime, attachments, loadAttachment, t, onOpenRef, onResolveTaskRefs, children }) {
8
+ /**
9
+ * One chat message row with identity chrome and sender-appropriate rendering.
10
+ *
11
+ * Memoized because a timeline row is rendered by the page that owns the whole
12
+ * Thread: the Task-ref subscription below lives inside this component, so
13
+ * skipping a render here never detaches it. Callers must therefore keep the
14
+ * props they derive per render (mention names, ref callbacks) identity-stable.
15
+ */
16
+ export const TeamMessage = memo(function TeamMessage({ senderName, memberId, human, body, occurredAt, mentionNames, senderTitle, grouped, showGroupedTime, attachments, loadAttachment, t, onOpenRef, onResolveTaskRefs, children }) {
10
17
  const avatarStyle = human ? undefined : { '--team-avatar-hue': memberHue(memberId) };
11
18
  // Literal bodies carry mention chips inline — Human input always, and
12
19
  // plain-prose Agent bodies where literal rendering loses nothing. Rich
@@ -97,7 +104,7 @@ export function TeamMessage({ senderName, memberId, human, body, occurredAt, men
97
104
  const label = resolved !== undefined && ref.startsWith('task:') ? taskLabel(resolved.taskNumber) : ref;
98
105
  return _jsx("button", { type: "button", className: css.refLink, title: ref, onClick: () => { onOpenRef(ref); }, children: label }, ref);
99
106
  })] })), attachments !== undefined && attachments.length > 0 && _jsx(TeamAttachmentStrip, { attachments: attachments, ...(loadAttachment === undefined ? {} : { loadAttachment }), ...(t === undefined ? {} : { t }) }), children] })] }));
100
- }
107
+ });
101
108
  /** Text nodes that Markdown rendered as prose rather than code or a link. */
102
109
  function markdownProseTextNodes(root) {
103
110
  const nodes = [];
@@ -2,6 +2,14 @@ import type { AgentTeamClientMemberStatus } from '@wowyuarm/dsh-agent-team/types
2
2
  import type { TeamSidebarProps } from './slots.ts';
3
3
  import type { TeamStateDotState } from './TeamStateDot.tsx';
4
4
  export declare function presenceLabel(status: AgentTeamClientMemberStatus, t: TeamSidebarProps['t']): string;
5
+ /** One line of human-readable diagnostic text: the reason, plus the refused artifact path when one was reported. */
6
+ export declare function diagnosticText(status: AgentTeamClientMemberStatus): string;
7
+ /**
8
+ * Whether the restart action can help an unavailable Member: it heals
9
+ * transient and repairable failures, but not a transient rollover window
10
+ * (which resolves on its own) or a refusal already proven non-remediable.
11
+ */
12
+ export declare function restartOffered(status: AgentTeamClientMemberStatus): boolean;
5
13
  /** Shared presence → indicator mapping for dots and avatar badges. */
6
14
  export declare function presenceDotState(presence: AgentTeamClientMemberStatus['presence']): TeamStateDotState;
7
15
  export declare function TeamPresenceDot({ status, t }: {
@@ -1 +1 @@
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
+ {"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,oHAAoH;AACpH,wBAAgB,cAAc,CAAC,MAAM,EAAE,2BAA2B,GAAG,MAAM,CAI1E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAK3E;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"}
@@ -6,7 +6,27 @@ export function presenceLabel(status, t) {
6
6
  const label = status.presence === 'available' ? t('statusAvailable')
7
7
  : status.presence === 'working' ? t('statusWorking')
8
8
  : status.presence === 'error' ? t('statusError') : t('statusUnavailable');
9
- return status.diagnostic === undefined ? label : `${label}: ${status.diagnostic}`;
9
+ return status.diagnostic === undefined ? label : `${label}: ${diagnosticText(status)}`;
10
+ }
11
+ /** One line of human-readable diagnostic text: the reason, plus the refused artifact path when one was reported. */
12
+ export function diagnosticText(status) {
13
+ const diagnostic = status.diagnostic;
14
+ if (diagnostic === undefined)
15
+ return '';
16
+ return diagnostic.location === undefined ? diagnostic.detail : `${diagnostic.detail} (${diagnostic.location.path})`;
17
+ }
18
+ /**
19
+ * Whether the restart action can help an unavailable Member: it heals
20
+ * transient and repairable failures, but not a transient rollover window
21
+ * (which resolves on its own) or a refusal already proven non-remediable.
22
+ */
23
+ export function restartOffered(status) {
24
+ const diagnostic = status.diagnostic;
25
+ if (diagnostic === undefined)
26
+ return true;
27
+ if (diagnostic.class === 'rollover')
28
+ return false;
29
+ return !(diagnostic.class === 'session-refused' && diagnostic.remediable === false);
10
30
  }
11
31
  /** Shared presence → indicator mapping for dots and avatar badges. */
12
32
  export function presenceDotState(presence) {
@@ -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,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"}
1
+ {"version":3,"file":"TeamThreadPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamThreadPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,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;AA+CD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,+BAuvBxD"}
@@ -1,17 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Fragment, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
2
+ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { Button, DisclosureRow, IconChevronLeftOutline14, IconChecklistOutline14, Modal, Pill } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import { TeamComposer } from "./TeamComposer.js";
5
- import { TeamPresenceDot } from "./TeamPresenceDot.js";
5
+ import { diagnosticText, 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, taskStatusDot } from "./team-formatters.js";
8
+ import { formatActivity, formatClaimState, formatTaskStatus, formatTaskTitle, mentionNamesOf, mentionedMemberIds, taskStatusDot } from "./team-formatters.js";
9
9
  import { TeamStateDot } from "./TeamStateDot.js";
10
- import { mintRequestId } from "./requests.js";
10
+ import { mintRequestId, uploadComposerFiles } from "./requests.js";
11
+ import { ScopeCoverage } from "./scope-coverage.js";
11
12
  import { daySeparatorLabel, isRunGap, timelineDayKey } from "./team-separators.js";
12
13
  import { useTimelineScroll } from "./timeline-scroll.js";
13
14
  import { hostTaskRefLookup, jumpToTaskThread } from "./task-refs.js";
14
- import { bytesToBase64 } from "./attachment-preview.js";
15
15
  import css from './conversation.module.css';
16
16
  import threadCss from './thread.module.css';
17
17
  function factKey(fact) {
@@ -20,6 +20,22 @@ function factKey(fact) {
20
20
  function messageFact(message, mentions = []) {
21
21
  return { kind: 'message', sequence: message.sequence, message, mentions, occurredAt: message.occurredAt };
22
22
  }
23
+ /**
24
+ * A fact owns its mention array, so the rendered name list is cached against
25
+ * that array. Every roster refresh replaces the handles map with a fresh Map of
26
+ * identical content, so the cache compares the resolved names rather than the
27
+ * map identity: identity stays stable while the names are unchanged, which is
28
+ * what keeps a memoized row from re-rendering on every refresh.
29
+ */
30
+ const mentionNamesCache = new WeakMap();
31
+ function stableMentionNames(mentions, handles) {
32
+ const names = mentionNamesOf(mentions, handles);
33
+ const cached = mentionNamesCache.get(mentions);
34
+ if (cached !== undefined && cached.length === names.length && cached.every((name, index) => name === names[index]))
35
+ return cached;
36
+ mentionNamesCache.set(mentions, names);
37
+ return names;
38
+ }
23
39
  function mergeFacts(...groups) {
24
40
  const byKey = new Map();
25
41
  for (const group of groups)
@@ -57,8 +73,9 @@ export function TeamThreadPage(props) {
57
73
  const [newFactsCount, setNewFactsCount] = useState(0);
58
74
  // The reply draft lives in the keyed draft cache: view switches unmount
59
75
  // this page, and a refresh must not cost the half-written message either.
76
+ // The composer owns the subscription — this page only reads a snapshot when
77
+ // it sends, so typing never re-renders the timeline.
60
78
  const draftKey = `thread:${threadRef}`;
61
- const { draft, recipients } = useSyncExternalStore(drafts.subscribe, () => drafts.getSnapshot(draftKey));
62
79
  const [claimsOpen, setClaimsOpen] = useState(false);
63
80
  // Early acceptance: the Human may accept while Claims are still open; the
64
81
  // confirm dialog lists exactly what will be completed with the Task.
@@ -148,14 +165,15 @@ export function TeamThreadPage(props) {
148
165
  setLoading(false);
149
166
  }
150
167
  };
151
- const refreshSupplemental = async () => {
168
+ /** One roster + view read. Answers false once the page is gone. */
169
+ const applySupplemental = async () => {
152
170
  try {
153
171
  const [loadedMembers, loadedView] = await Promise.all([
154
172
  loadMembers({ workspaceId }),
155
173
  loadChannels({ workspaceId, ...(channelRef === undefined ? {} : { channelRef }), threadRef, includeActivities: false, limit: 1 }),
156
174
  ]);
157
175
  if (!mountedRef.current)
158
- return;
176
+ return false;
159
177
  if (loadedMembers.ok)
160
178
  setMembers(loadedMembers.value);
161
179
  if (loadedView.ok)
@@ -163,12 +181,49 @@ export function TeamThreadPage(props) {
163
181
  const failure = [loadedMembers, loadedView].find(result => !result.ok);
164
182
  if (failure !== undefined && !failure.ok)
165
183
  setError(failure.error.message);
184
+ return true;
166
185
  }
167
186
  catch (cause) {
168
187
  if (mountedRef.current)
169
188
  setError(cause instanceof Error ? cause.message : String(cause));
189
+ return mountedRef.current;
170
190
  }
171
191
  };
192
+ // One Host change event wakes every scope it matches: here a workspace commit
193
+ // and a presence transition, whose separate polls both deliver that event's
194
+ // version. Both asks are the same roster and view read, so each round answers
195
+ // one version per scope, and a newer version arriving mid-round runs one
196
+ // trailing round instead of being dropped. The two scopes count different
197
+ // domains, so coverage and pending versions are tracked per scope.
198
+ const supplementalRef = useRef();
199
+ const supplementalCoverageRef = useRef(new ScopeCoverage());
200
+ const refreshSupplemental = (wake) => {
201
+ const inFlight = supplementalRef.current;
202
+ if (wake === undefined) {
203
+ if (inFlight !== undefined)
204
+ return inFlight;
205
+ }
206
+ else if (!supplementalCoverageRef.current.wake(wake.scope, wake.version)) {
207
+ return inFlight ?? Promise.resolve();
208
+ }
209
+ const coverage = supplementalCoverageRef.current;
210
+ const round = (async () => {
211
+ for (;;) {
212
+ coverage.beginRound();
213
+ const applied = await applySupplemental();
214
+ // A newer change landed while this round fetched: cover it too, and
215
+ // keep going only while the page is still the one asking.
216
+ if (!applied || !coverage.finishRound())
217
+ return;
218
+ }
219
+ })().finally(() => {
220
+ // A remount may already own a newer round; only this one clears itself.
221
+ if (supplementalRef.current === round)
222
+ supplementalRef.current = undefined;
223
+ });
224
+ supplementalRef.current = round;
225
+ return round;
226
+ };
172
227
  const refreshPassiveFacts = async () => {
173
228
  try {
174
229
  const result = await loadThreadHistory({ workspaceId, ...threadRequest, limit: 100 });
@@ -226,6 +281,9 @@ export function TeamThreadPage(props) {
226
281
  };
227
282
  useEffect(() => {
228
283
  mountedRef.current = true;
284
+ // The previous mount's supplemental round must not answer for this one.
285
+ supplementalRef.current = undefined;
286
+ supplementalCoverageRef.current.reset();
229
287
  projectionRef.current = undefined;
230
288
  setProjection(undefined);
231
289
  setChannelView(undefined);
@@ -298,7 +356,19 @@ export function TeamThreadPage(props) {
298
356
  setError(update.message);
299
357
  return;
300
358
  }
301
- void refreshSupplemental();
359
+ void refreshSupplemental({ scope: 'workspace', version: update.version });
360
+ }),
361
+ // Presence transitions commit nothing: only the member rows move, so
362
+ // the roster refresh rides the same supplemental fetch as workspace
363
+ // membership changes, leaving the timeline untouched.
364
+ subscribeChanges({ kind: 'presence', workspaceId }, update => {
365
+ if (!mountedRef.current)
366
+ return;
367
+ if (update.type === 'failed') {
368
+ setError(update.message);
369
+ return;
370
+ }
371
+ void refreshSupplemental({ scope: 'presence', version: update.version });
302
372
  }),
303
373
  ];
304
374
  return () => {
@@ -378,7 +448,8 @@ export function TeamThreadPage(props) {
378
448
  // Branded-ref navigation for message bodies: channel refs hop to the
379
449
  // Channel; the open Task's own refs are already on screen, and other Tasks
380
450
  // are not resolvable from this surface, so they degrade to a no-op.
381
- const openRef = (ref) => {
451
+ // Identity-stable: a fresh closure per render would defeat TeamMessage's memo.
452
+ const openRef = useCallback((ref) => {
382
453
  if (ref.startsWith('channel:') && ref !== channelRef) {
383
454
  selectChannel(ref);
384
455
  return;
@@ -402,13 +473,13 @@ export function TeamThreadPage(props) {
402
473
  // Another Task cited here: resolve its home Channel and jump.
403
474
  jumpToTaskThread(resolveTaskRefs, workspaceId, ref, selectThread);
404
475
  }
405
- };
406
- const lookupTaskRefs = hostTaskRefLookup(resolveTaskRefs, workspaceId);
476
+ }, [channelRef, threadRef, taskRef, workspaceId, selectChannel, selectThread, loadChannels, resolveTaskRefs]);
477
+ const lookupTaskRefs = useMemo(() => hostTaskRefLookup(resolveTaskRefs, workspaceId), [resolveTaskRefs, workspaceId]);
407
478
  const renderFact = (fact, grouped = false) => {
408
479
  if (fact.kind === 'message') {
409
480
  const sender = memberName(fact.message.sender);
410
481
  const senderStatus = members.find(candidate => candidate.member.memberId === fact.message.sender);
411
- return _jsx(TeamMessage, { senderName: sender, memberId: fact.message.sender, human: fact.message.sender === channelView?.humanMemberId, body: fact.message.body, attachments: fact.message.attachments, loadAttachment: getAttachment, t: t, occurredAt: fact.message.occurredAt, mentionNames: mentionNamesOf(fact.mentions, mentionHandlesMap), onOpenRef: openRef, onResolveTaskRefs: lookupTaskRefs, grouped: grouped, ...(senderStatus === undefined ? {} : { senderTitle: senderStatus.member.description }) }, factKey(fact));
482
+ return _jsx(TeamMessage, { senderName: sender, memberId: fact.message.sender, human: fact.message.sender === channelView?.humanMemberId, body: fact.message.body, attachments: fact.message.attachments, loadAttachment: getAttachment, t: t, occurredAt: fact.message.occurredAt, mentionNames: stableMentionNames(fact.mentions, mentionHandlesMap), onOpenRef: openRef, onResolveTaskRefs: lookupTaskRefs, grouped: grouped, ...(senderStatus === undefined ? {} : { senderTitle: senderStatus.member.description }) }, factKey(fact));
412
483
  }
413
484
  return _jsxs("p", { className: threadCss.activityRow, children: [_jsx("span", { className: threadCss.activityMark, "aria-hidden": "true" }), _jsx("span", { className: threadCss.activityText, children: formatActivity(fact.activity, { t, actorName: memberName, claims: taskClaims }) })] }, factKey(fact));
414
485
  };
@@ -553,7 +624,19 @@ export function TeamThreadPage(props) {
553
624
  setMutating(undefined);
554
625
  }
555
626
  };
627
+ // Editing the draft invalidates one-shot send state: a confirmation token,
628
+ // the retained requestId, and the status line. Every setter returns the same
629
+ // state when there is nothing to clear, so a keystroke does not re-render the
630
+ // timeline now that the composer owns the draft.
631
+ const clearSendState = useCallback(() => {
632
+ setConfirmation(current => current === undefined ? current : undefined);
633
+ setReplyRequestId(current => current === undefined ? current : undefined);
634
+ setStatusMessage(current => current === undefined ? current : undefined);
635
+ }, []);
556
636
  const sendReply = async () => {
637
+ // Read the draft at send time: this page no longer subscribes to it, so a
638
+ // captured render value would be stale after the composer's own edits.
639
+ const { draft, recipients } = drafts.getSnapshot(draftKey);
557
640
  if (pending || thread === undefined || draft.trim() === '')
558
641
  return;
559
642
  const id = replyRequestId ?? mintRequestId();
@@ -563,21 +646,12 @@ export function TeamThreadPage(props) {
563
646
  try {
564
647
  // Upload chosen files first; any failure aborts the reply with the
565
648
  // existing error surface and keeps the chips for a retry.
566
- const attachmentIds = [];
567
- for (const file of pendingFiles) {
568
- const uploaded = await putAttachment({
569
- requestId: mintRequestId(),
570
- workspaceId,
571
- name: file.name,
572
- mediaType: file.type === '' ? undefined : file.type,
573
- bytesBase64: bytesToBase64(new Uint8Array(await file.arrayBuffer())),
574
- });
575
- if (!uploaded.ok) {
576
- setError(uploaded.error.message);
577
- return;
578
- }
579
- attachmentIds.push(uploaded.value.attachmentId);
649
+ const upload = await uploadComposerFiles(putAttachment, workspaceId, pendingFiles);
650
+ if (!upload.ok) {
651
+ setError(upload.error);
652
+ return;
580
653
  }
654
+ const attachmentIds = upload.attachmentIds;
581
655
  const result = await reply({ requestId: id, workspaceId, threadRef, ...(task === undefined ? {} : { taskRef: task.taskRef }), body: draft.trim(), baseRevision: thread.revision, recipients: [...recipients].sort(), ...(attachmentIds.length === 0 ? {} : { attachments: attachmentIds }), ...(confirmation === undefined ? {} : { confirmationToken: confirmation }) });
582
656
  if (!result.ok) {
583
657
  setError(result.error.message);
@@ -585,8 +659,12 @@ export function TeamThreadPage(props) {
585
659
  }
586
660
  if (result.value.kind === 'committed') {
587
661
  const committed = result.value;
662
+ // The optimistic row chips what the Host is about to report: a
663
+ // hand-typed `@Handle` delivers exactly like a picked recipient, and the
664
+ // committed facts replace this row as soon as they arrive.
665
+ const optimisticMentions = [...new Set([...recipients, ...mentionedMemberIds(draft, channelMembers)])].sort();
588
666
  setCurrentFacts(current => {
589
- const merged = mergeFacts(current, [{ kind: 'message', sequence: committed.message.sequence, message: committed.message, mentions: [...recipients].sort(), occurredAt: committed.receipt.occurredAt }]);
667
+ const merged = mergeFacts(current, [{ kind: 'message', sequence: committed.message.sequence, message: committed.message, mentions: optimisticMentions, occurredAt: committed.receipt.occurredAt }]);
590
668
  currentFactsRef.current = merged;
591
669
  return merged;
592
670
  });
@@ -654,7 +732,7 @@ export function TeamThreadPage(props) {
654
732
  } }, children: t('acceptTask') });
655
733
  })(), task.resolution === 'open'
656
734
  ? _jsx(Button, { size: "sm", variant: "outline", disabled: pending, onClick: () => { void mutateTask('close'); }, children: t('closeTask') })
657
- : _jsx(Button, { size: "sm", variant: "primary", disabled: pending, onClick: () => { void mutateTask('reopen'); }, children: t('reopenTask') })] })] }), risks.length > 0 && _jsxs("section", { className: threadCss.riskSection, "aria-label": t('runtimeRisk'), children: [_jsx("h2", { children: t('runtimeRisk') }), risks.map(({ claim, status }) => _jsxs("p", { className: threadCss.riskRow, children: [_jsx(TeamPresenceDot, { status: status, t: t }), _jsxs("span", { children: [t('runtimeRiskDetail', { member: status.member.handle, diagnostic: status.diagnostic ?? t('statusError') }), " \u00B7 ", claim.direction] })] }, claim.claimRef))] }), task !== undefined && thread !== undefined && (() => {
735
+ : _jsx(Button, { size: "sm", variant: "primary", disabled: pending, onClick: () => { void mutateTask('reopen'); }, children: t('reopenTask') })] })] }), risks.length > 0 && _jsxs("section", { className: threadCss.riskSection, "aria-label": t('runtimeRisk'), children: [_jsx("h2", { children: t('runtimeRisk') }), risks.map(({ claim, status }) => _jsxs("p", { className: threadCss.riskRow, children: [_jsx(TeamPresenceDot, { status: status, t: t }), _jsxs("span", { children: [t('runtimeRiskDetail', { member: status.member.handle, diagnostic: diagnosticText(status) || t('statusError') }), " \u00B7 ", claim.direction] })] }, claim.claimRef))] }), task !== undefined && thread !== undefined && (() => {
658
736
  // Recomputed here so the confirm list never shows stale rows.
659
737
  const activeClaims = projection?.claims.filter(claim => claim.taskRef === task.taskRef && claim.state === 'active') ?? [];
660
738
  return _jsxs(Modal, { open: confirmingAccept, onClose: () => { if (!pending)
@@ -664,5 +742,5 @@ export function TeamThreadPage(props) {
664
742
  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);
665
743
  })] }) }) })] }), _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'
666
744
  ? _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') })] })] })
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", {})] });
745
+ : _jsx(TeamComposer, { members: channelMembers, followerMemberIds: followerIds, drafts: drafts, draftKey: draftKey, pending: pending, ...(statusMessage === undefined ? {} : { confirmation: statusMessage }), ...(error === undefined ? {} : { error }), onEdit: clearSendState, onSubmit: () => { void sendReply(); }, placeholder: t('replyPlaceholder'), pendingFiles: pendingFiles, onFilesChange: setPendingFiles, t: t }, draftKey)) : _jsx("div", {})] });
668
746
  }
@@ -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, archiveChannel, updateMember, recoverMember, archiveMember, joinChannel, removeChannelMember, loadModels, openMemberSession }: TeamSidebarProps): import("react").JSX.Element;
2
+ export declare function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, selectInbox, t, useWorkspaces, loadMembers, loadInbox, subscribeChanges, subscribeReads, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember, archiveMember, joinChannel, removeChannelMember, loadModels, openMemberSession }: 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,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,+BA8D9V"}
1
+ {"version":3,"file":"TeamWorkspaceBrowser.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceBrowser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAyBlD,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,+BAoHtY"}