@wowyuarm/dsh-agent-team 0.1.14-alpha.2 → 0.1.14

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 (127) hide show
  1. package/README.md +5 -3
  2. package/README.zh.md +5 -3
  3. package/cordis.patch.yml +2 -185
  4. package/package.json +52 -46
  5. package/packages/agent-team/README.md +1 -1
  6. package/packages/agent-team/README.zh.md +1 -1
  7. package/packages/agent-team/core-skills/member-memory-manager/SKILL.md +30 -0
  8. package/packages/agent-team/lib/context-continuity-host.js +91 -0
  9. package/packages/agent-team/lib/context-projection.js +266 -489
  10. package/packages/agent-team/lib/context-source.js +17 -106
  11. package/packages/agent-team/lib/human-avatar.js +61 -0
  12. package/packages/agent-team/lib/human-profile.js +46 -0
  13. package/packages/agent-team/lib/human-update-check.js +119 -0
  14. package/packages/agent-team/lib/index.js +408 -264
  15. package/packages/agent-team/lib/ledger.js +120 -15
  16. package/packages/agent-team/lib/member-context.js +9 -8
  17. package/packages/agent-team/lib/member-runtime.js +1 -1
  18. package/packages/agent-team/lib/member-time-context.js +2 -5
  19. package/packages/agent-team/lib/preset-roster.js +15 -0
  20. package/packages/agent-team/lib/pressure-policy.js +9 -6
  21. package/packages/agent-team/lib/session-remediation.js +493 -0
  22. package/packages/agent-team/lib/stored-session-reader.js +2 -1
  23. package/packages/agent-team/lib/typert.host.js +605 -291
  24. package/packages/agent-team/lib/typert.remote-client.d.ts +15 -6
  25. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  26. package/packages/agent-team/lib/typert.remote-client.js +367 -244
  27. package/packages/agent-team/lib/types/context-continuity-host.d.ts +84 -0
  28. package/packages/agent-team/lib/types/context-continuity-host.d.ts.map +1 -0
  29. package/packages/agent-team/lib/types/context-projection.d.ts +130 -185
  30. package/packages/agent-team/lib/types/context-projection.d.ts.map +1 -1
  31. package/packages/agent-team/lib/types/context-source.d.ts +17 -81
  32. package/packages/agent-team/lib/types/context-source.d.ts.map +1 -1
  33. package/packages/agent-team/lib/types/human-avatar.d.ts +29 -0
  34. package/packages/agent-team/lib/types/human-avatar.d.ts.map +1 -0
  35. package/packages/agent-team/lib/types/human-profile.d.ts +44 -0
  36. package/packages/agent-team/lib/types/human-profile.d.ts.map +1 -0
  37. package/packages/agent-team/lib/types/human-update-check.d.ts +73 -0
  38. package/packages/agent-team/lib/types/human-update-check.d.ts.map +1 -0
  39. package/packages/agent-team/lib/types/index.d.ts +112 -38
  40. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  41. package/packages/agent-team/lib/types/ledger.d.ts +31 -2
  42. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  43. package/packages/agent-team/lib/types/member-context.d.ts +0 -14
  44. package/packages/agent-team/lib/types/member-context.d.ts.map +1 -1
  45. package/packages/agent-team/lib/types/member-time-context.d.ts +0 -15
  46. package/packages/agent-team/lib/types/member-time-context.d.ts.map +1 -1
  47. package/packages/agent-team/lib/types/preset-roster.d.ts +5 -0
  48. package/packages/agent-team/lib/types/preset-roster.d.ts.map +1 -0
  49. package/packages/agent-team/lib/types/pressure-policy.d.ts +6 -0
  50. package/packages/agent-team/lib/types/pressure-policy.d.ts.map +1 -1
  51. package/packages/agent-team/lib/types/session-remediation.d.ts +172 -0
  52. package/packages/agent-team/lib/types/session-remediation.d.ts.map +1 -0
  53. package/packages/agent-team/lib/types/stored-session-reader.d.ts +2 -1
  54. package/packages/agent-team/lib/types/stored-session-reader.d.ts.map +1 -1
  55. package/packages/agent-team/lib/types/types/entities.d.ts +20 -3
  56. package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -1
  57. package/packages/agent-team/lib/types/types/requests-results.d.ts +63 -0
  58. package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
  59. package/packages/agent-team/preset/team-member/agent.cordis.yml +166 -0
  60. package/packages/client-agent-team/lib/client.js +1667 -516
  61. package/packages/client-agent-team/lib/client.js.map +1 -1
  62. package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts +15 -0
  63. package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts.map +1 -0
  64. package/packages/client-agent-team/lib/types/client/HumanSettingsSection.js +115 -0
  65. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
  66. package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +12 -8
  67. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts +22 -1
  68. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts.map +1 -1
  69. package/packages/client-agent-team/lib/types/client/TeamAvatarStack.js +25 -2
  70. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +6 -1
  71. package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
  72. package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +69 -31
  73. package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +4 -4
  74. package/packages/client-agent-team/lib/types/client/TeamComposer.js +3 -3
  75. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
  76. package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
  77. package/packages/client-agent-team/lib/types/client/TeamConversation.js +12 -5
  78. package/packages/client-agent-team/lib/types/client/TeamFooterAction.js +2 -2
  79. package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts +4 -1
  80. package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts.map +1 -1
  81. package/packages/client-agent-team/lib/types/client/TeamInboxPage.js +22 -7
  82. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts +11 -1
  83. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -1
  84. package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +69 -8
  85. package/packages/client-agent-team/lib/types/client/TeamMembersAction.js +2 -2
  86. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +18 -3
  87. package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
  88. package/packages/client-agent-team/lib/types/client/TeamMessage.js +213 -67
  89. package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts.map +1 -1
  90. package/packages/client-agent-team/lib/types/client/TeamRowMenu.js +2 -2
  91. package/packages/client-agent-team/lib/types/client/TeamSidebarSection.js +2 -2
  92. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +5 -0
  93. package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
  94. package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +55 -29
  95. package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +3 -3
  96. package/packages/client-agent-team/lib/types/client/TeamWorkspaceSelector.js +2 -2
  97. package/packages/client-agent-team/lib/types/client/avatar-image.d.ts +21 -0
  98. package/packages/client-agent-team/lib/types/client/avatar-image.d.ts.map +1 -0
  99. package/packages/client-agent-team/lib/types/client/avatar-image.js +9 -0
  100. package/packages/client-agent-team/lib/types/client/human-identity.d.ts +94 -0
  101. package/packages/client-agent-team/lib/types/client/human-identity.d.ts.map +1 -0
  102. package/packages/client-agent-team/lib/types/client/human-identity.js +117 -0
  103. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  104. package/packages/client-agent-team/lib/types/client/index.js +112 -41
  105. package/packages/client-agent-team/lib/types/client/locales.d.ts +72 -2
  106. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
  107. package/packages/client-agent-team/lib/types/client/locales.js +78 -2
  108. package/packages/client-agent-team/lib/types/client/multi-menu-field.js +2 -2
  109. package/packages/client-agent-team/lib/types/client/refs.d.ts +71 -0
  110. package/packages/client-agent-team/lib/types/client/refs.d.ts.map +1 -0
  111. package/packages/client-agent-team/lib/types/client/refs.js +181 -0
  112. package/packages/client-agent-team/lib/types/client/slots.d.ts +8 -2
  113. package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
  114. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +57 -9
  115. package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
  116. package/packages/client-agent-team/lib/types/client/team-formatters.js +85 -17
  117. package/packages/tool-agent-team/README.md +1 -1
  118. package/packages/tool-agent-team/README.zh.md +1 -1
  119. package/packages/tool-agent-team/lib/context-tools.js +20 -6
  120. package/packages/tool-agent-team/lib/index.js +2 -2
  121. package/packages/tool-agent-team/lib/types/context-tools.d.ts.map +1 -1
  122. package/packages/agent-team/lib/context-management.js +0 -371
  123. package/packages/agent-team/lib/types/context-management.d.ts +0 -154
  124. package/packages/agent-team/lib/types/context-management.d.ts.map +0 -1
  125. package/packages/client-agent-team/lib/types/client/task-refs.d.ts +0 -31
  126. package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +0 -1
  127. package/packages/client-agent-team/lib/types/client/task-refs.js +0 -99
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';
3
- import { IconChecklistOutlineRegular, IconPaperclipOutlineRegular, IconSendOutlineRegular, Tooltip, useAnchoredMaxHeight, useDismissOnOutsidePointer } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { IconChecklistOutline14, IconPaperclipOutline16, IconSendOutline16, Tooltip, useAnchoredMaxHeight, useDismissOnOutsidePointer } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import { TeamPresenceDot } from "./TeamPresenceDot.js";
5
5
  import { allMentionMembers, containsAllMention, containsMention, mentionedMemberIds } from "./team-formatters.js";
6
6
  import css from './composer.module.css';
@@ -259,9 +259,9 @@ export function TeamComposer({ members, followerMemberIds, drafts, draftKey, pen
259
259
  if (chosen.length > 0 && pendingFiles !== undefined)
260
260
  onFilesChange([...pendingFiles, ...chosen]);
261
261
  event.target.value = '';
262
- } }), _jsx(Tooltip, { label: t('attachFiles'), side: "top", delayMs: 500, children: _jsx("button", { type: "button", className: css.attachButton, "aria-label": t('attachFiles'), disabled: pending, onClick: () => { fileInputRef.current?.click(); }, children: _jsx(IconPaperclipOutlineRegular, { size: 14 }) }) })] })), onAsTaskChange !== undefined && (_jsxs("button", { type: "button", className: asTask === true ? `${css.asTaskPill} ${css.asTaskPillOn}` : css.asTaskPill, "aria-label": t('asTask'), "aria-pressed": asTask === true, title: t('asTask'), disabled: pending, onClick: () => { onAsTaskChange(asTask !== true); }, children: [_jsx(IconChecklistOutlineRegular, { size: 14 }), _jsx("span", { className: css.asTaskLabel, children: t('asTask') })] })), _jsx("button", { type: "submit", className: css.sendButton, "aria-label": pending ? t('sendingMessage') : t('sendMessage'), disabled: pending || draft.trim() === '', onMouseDown: event => {
262
+ } }), _jsx(Tooltip, { label: t('attachFiles'), side: "top", delayMs: 500, children: _jsx("button", { type: "button", className: css.attachButton, "aria-label": t('attachFiles'), disabled: pending, onClick: () => { fileInputRef.current?.click(); }, children: _jsx(IconPaperclipOutline16, { size: 14 }) }) })] })), onAsTaskChange !== undefined && (_jsxs("button", { type: "button", className: asTask === true ? `${css.asTaskPill} ${css.asTaskPillOn}` : css.asTaskPill, "aria-label": t('asTask'), "aria-pressed": asTask === true, title: t('asTask'), disabled: pending, onClick: () => { onAsTaskChange(asTask !== true); }, children: [_jsx(IconChecklistOutline14, { size: 14 }), _jsx("span", { className: css.asTaskLabel, children: t('asTask') })] })), _jsx("button", { type: "submit", className: css.sendButton, "aria-label": pending ? t('sendingMessage') : t('sendMessage'), disabled: pending || draft.trim() === '', onMouseDown: event => {
263
263
  // Keep the composer focused when the send control is clicked.
264
264
  event.preventDefault();
265
265
  inputRef.current?.focus({ preventScroll: true });
266
- }, children: _jsx(IconSendOutlineRegular, { size: 16 }) })] })] }), error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] });
266
+ }, children: _jsx(IconSendOutline16, { size: 16 }) })] })] }), error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] });
267
267
  }
@@ -1,3 +1,3 @@
1
1
  import type { TeamConversationProps } from './slots.ts';
2
- export declare function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, threadObservations, subscribeChanges, loadMembers, loadInbox, sendMessage, joinChannel, removeChannelMember, reply, changeTask, promoteThread, selectThread, selectChannel, selectWorkspace, backToWorkspace, backToChannels, resolveTaskRefs }: TeamConversationProps): import("react").JSX.Element;
2
+ export declare function TeamConversation({ t, useWorkspaces, navigation, drafts, humanIdentity, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, threadObservations, subscribeChanges, loadMembers, loadInbox, sendMessage, joinChannel, removeChannelMember, reply, changeTask, promoteThread, selectThread, selectChannel, selectWorkspace, backToWorkspace, backToChannels, resolveTaskRefs, resolveThreadRefs, openMemberSession }: TeamConversationProps): import("react").JSX.Element;
3
3
  //# sourceMappingURL=TeamConversation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamConversation.d.ts","sourceRoot":"","sources":["../../../src/client/TeamConversation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAMvD,wBAAgB,gBAAgB,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,EAAE,qBAAqB,+BA0BzZ"}
1
+ {"version":3,"file":"TeamConversation.d.ts","sourceRoot":"","sources":["../../../src/client/TeamConversation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAOvD,wBAAgB,gBAAgB,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,EAAE,qBAAqB,+BAgC9c"}
@@ -1,24 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useSyncExternalStore } from 'react';
3
+ import { useHumanIdentity } from "./human-identity.js";
3
4
  import { TeamChannelPage } from "./TeamChannelPage.js";
4
5
  import { TeamInboxPage } from "./TeamInboxPage.js";
5
6
  import { TeamThreadPage } from "./TeamThreadPage.js";
6
7
  import css from './conversation.module.css';
7
- export function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, threadObservations, subscribeChanges, loadMembers, loadInbox, sendMessage, joinChannel, removeChannelMember, reply, changeTask, promoteThread, selectThread, selectChannel, selectWorkspace, backToWorkspace, backToChannels, resolveTaskRefs }) {
8
+ export function TeamConversation({ t, useWorkspaces, navigation, drafts, humanIdentity, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, threadObservations, subscribeChanges, loadMembers, loadInbox, sendMessage, joinChannel, removeChannelMember, reply, changeTask, promoteThread, selectThread, selectChannel, selectWorkspace, backToWorkspace, backToChannels, resolveTaskRefs, resolveThreadRefs, openMemberSession }) {
8
9
  const navigationState = useSyncExternalStore(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
10
+ // Every seat names and draws the Human from this one projection: the
11
+ // localized fallback stands only until the first profile read lands.
12
+ const identity = useHumanIdentity(humanIdentity);
13
+ const humanName = identity.name ?? t('human');
9
14
  const workspaces = useWorkspaces(state => state.items);
10
15
  const current = workspaces.find(workspace => workspace.workspaceId === navigationState.workspaceId);
11
16
  if (navigationState.inbox === true) {
12
17
  // The Inbox page is global: it merges every visible Workspace and needs no
13
18
  // selected Workspace. Selecting Inbox clears the Channel/Thread faces, so
14
- // this face owns the seat while the flag stands.
15
- return _jsx(TeamInboxPage, { useWorkspaces: useWorkspaces, loadInbox: loadInbox, subscribeChanges: subscribeChanges, selectWorkspace: selectWorkspace, selectThread: selectThread, t: t }, "inbox");
19
+ // this face owns the seat while the flag stands. The Human identity rides
20
+ // along for the same reason it rides on the other two faces: a row that
21
+ // names or draws the reader must draw the one identity every seat draws.
22
+ return _jsx(TeamInboxPage, { useWorkspaces: useWorkspaces, loadInbox: loadInbox, subscribeChanges: subscribeChanges, selectWorkspace: selectWorkspace, selectThread: selectThread, humanName: humanName, ...(identity.avatarUrl === undefined ? {} : { humanAvatarUrl: identity.avatarUrl }), t: t }, "inbox");
16
23
  }
17
24
  if (current !== undefined && navigationState.threadRef !== undefined) {
18
- return _jsx(TeamThreadPage, { workspaceId: current.workspaceId, putAttachment: putAttachment, threadRef: navigationState.threadRef, backToWorkspace: backToWorkspace, selectChannel: selectChannel, selectThread: selectThread, resolveTaskRefs: resolveTaskRefs, ...(navigationState.channelRef === undefined ? {} : { channelRef: navigationState.channelRef }), ...(navigationState.taskRef === undefined ? {} : { taskRef: navigationState.taskRef }), ...(navigationState.taskNumber === undefined ? {} : { taskNumber: navigationState.taskNumber }), drafts: drafts, getAttachment: getAttachment, readThread: readThread, loadChannels: loadChannels, loadThreadHistory: loadThreadHistory, threadObservations: threadObservations, subscribeChanges: subscribeChanges, loadMembers: loadMembers, reply: reply, changeTask: changeTask, promoteThread: promoteThread, t: t }, navigationState.threadRef);
25
+ return _jsx(TeamThreadPage, { humanName: humanName, ...(identity.avatarUrl === undefined ? {} : { humanAvatarUrl: identity.avatarUrl }), workspaceId: current.workspaceId, putAttachment: putAttachment, threadRef: navigationState.threadRef, backToWorkspace: backToWorkspace, selectChannel: selectChannel, selectThread: selectThread, resolveTaskRefs: resolveTaskRefs, resolveThreadRefs: resolveThreadRefs, openMemberSession: openMemberSession, ...(navigationState.channelRef === undefined ? {} : { channelRef: navigationState.channelRef }), ...(navigationState.taskRef === undefined ? {} : { taskRef: navigationState.taskRef }), ...(navigationState.taskNumber === undefined ? {} : { taskNumber: navigationState.taskNumber }), drafts: drafts, getAttachment: getAttachment, readThread: readThread, loadChannels: loadChannels, loadThreadHistory: loadThreadHistory, threadObservations: threadObservations, subscribeChanges: subscribeChanges, loadMembers: loadMembers, reply: reply, changeTask: changeTask, promoteThread: promoteThread, t: t }, navigationState.threadRef);
19
26
  }
20
27
  if (current !== undefined && navigationState.channelRef !== undefined) {
21
- return _jsx(TeamChannelPage, { workspaceId: current.workspaceId, channelRef: navigationState.channelRef, drafts: drafts, putAttachment: putAttachment, getAttachment: getAttachment, loadChannels: loadChannels, subscribeChanges: subscribeChanges, loadMembers: loadMembers, loadInbox: loadInbox, sendMessage: sendMessage, joinChannel: joinChannel, removeChannelMember: removeChannelMember, selectThread: selectThread, selectChannel: selectChannel, backToChannels: backToChannels, resolveTaskRefs: resolveTaskRefs, t: t }, navigationState.channelRef);
28
+ return _jsx(TeamChannelPage, { humanName: humanName, ...(identity.avatarUrl === undefined ? {} : { humanAvatarUrl: identity.avatarUrl }), workspaceId: current.workspaceId, channelRef: navigationState.channelRef, drafts: drafts, putAttachment: putAttachment, getAttachment: getAttachment, loadChannels: loadChannels, subscribeChanges: subscribeChanges, loadMembers: loadMembers, loadInbox: loadInbox, sendMessage: sendMessage, joinChannel: joinChannel, removeChannelMember: removeChannelMember, selectThread: selectThread, selectChannel: selectChannel, backToChannels: backToChannels, resolveTaskRefs: resolveTaskRefs, resolveThreadRefs: resolveThreadRefs, openMemberSession: openMemberSession, t: t }, navigationState.channelRef);
22
29
  }
23
30
  const welcome = current === undefined
24
31
  ? { eyebrow: t('teamMode'), title: t('team'), body: t('empty') }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useLayoutEffect, useSyncExternalStore } from 'react';
3
- import { IconAgentPresetOutlineRegular, IconChevronLeftOutlineRegular, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { IconAgentPresetOutline16, IconChevronLeftOutline14, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import css from './team.module.css';
5
5
  export function TeamFooterAction({ wide, navigation, enterTeam, leaveTeam, t }) {
6
6
  const state = useSyncExternalStore(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
@@ -15,5 +15,5 @@ export function TeamFooterAction({ wide, navigation, enterTeam, leaveTeam, t })
15
15
  }
16
16
  delete document.documentElement.dataset.agentTeamMode;
17
17
  }, [inTeam]);
18
- return (_jsx(_Fragment, { children: _jsx("div", { className: wide ? css.footerStack : `${css.footerStack} ${css.railStack}`, children: _jsx(Tooltip, { label: label, delayMs: 500, disabled: wide, children: _jsxs("button", { type: "button", className: wide ? css.footerAction : `${css.footerAction} ${css.rail}`, "aria-label": label, "data-team-action": inTeam ? 'leave' : 'enter', onClick: inTeam ? leaveTeam : enterTeam, children: [inTeam ? _jsx(IconChevronLeftOutlineRegular, { size: wide ? 16 : 18 }) : _jsx(IconAgentPresetOutlineRegular, { size: wide ? 16 : 18 }), wide && _jsx("span", { children: label })] }) }) }) }));
18
+ return (_jsx(_Fragment, { children: _jsx("div", { className: wide ? css.footerStack : `${css.footerStack} ${css.railStack}`, children: _jsx(Tooltip, { label: label, delayMs: 500, disabled: wide, children: _jsxs("button", { type: "button", className: wide ? css.footerAction : `${css.footerAction} ${css.rail}`, "aria-label": label, "data-team-action": inTeam ? 'leave' : 'enter', onClick: inTeam ? leaveTeam : enterTeam, children: [inTeam ? _jsx(IconChevronLeftOutline14, { size: wide ? 16 : 18 }) : _jsx(IconAgentPresetOutline16, { size: wide ? 16 : 18 }), wide && _jsx("span", { children: label })] }) }) }) }));
19
19
  }
@@ -6,6 +6,9 @@ interface TeamInboxPageProps {
6
6
  readonly subscribeChanges: TeamConversationProps['subscribeChanges'];
7
7
  readonly selectWorkspace: TeamConversationProps['selectWorkspace'];
8
8
  readonly selectThread: TeamConversationProps['selectThread'];
9
+ /** The Human's display name, from the Client's one identity projection. */
10
+ readonly humanName: string;
11
+ readonly humanAvatarUrl?: string | undefined;
9
12
  readonly t: TeamConversationProps['t'];
10
13
  }
11
14
  /**
@@ -20,6 +23,6 @@ interface TeamInboxPageProps {
20
23
  * holding unread is only ever in the queue: the Host already excludes it from
21
24
  * the tail, and this page never re-derives that judgement.
22
25
  */
23
- export declare function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, selectWorkspace, selectThread, t }: TeamInboxPageProps): import("react").JSX.Element;
26
+ export declare function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, selectWorkspace, selectThread, humanName, humanAvatarUrl, t }: TeamInboxPageProps): import("react").JSX.Element;
24
27
  export {};
25
28
  //# sourceMappingURL=TeamInboxPage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamInboxPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamInboxPage.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAavD,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAA;IACtD,mGAAmG;IACnG,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;IACpE,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC;AA0BD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,kBAAkB,+BA0GjI"}
1
+ {"version":3,"file":"TeamInboxPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamInboxPage.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAavD,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAA;IACtD,mGAAmG;IACnG,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;IACpE,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC;AA0BD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,EAAE,EAAE,kBAAkB,+BAqH5J"}
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useCallback, useEffect, useRef, useState } from 'react';
3
3
  import { Button } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import { claimersLabel, formatAbsoluteTime, formatInboxTime } from "./team-formatters.js";
5
- import { TeamAvatarStack } from "./TeamAvatarStack.js";
5
+ import { namedAvatarOwners, TeamAvatarStack } from "./TeamAvatarStack.js";
6
6
  import { TeamCountBadge } from "./TeamCountBadge.js";
7
7
  import css from './conversation.module.css';
8
8
  import inboxCss from './inbox.module.css';
@@ -40,10 +40,14 @@ function compareInboxRows(left, right) {
40
40
  * holding unread is only ever in the queue: the Host already excludes it from
41
41
  * the tail, and this page never re-derives that judgement.
42
42
  */
43
- export function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, selectWorkspace, selectThread, t }) {
43
+ export function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, selectWorkspace, selectThread, humanName, humanAvatarUrl, t }) {
44
44
  const workspaces = useWorkspaces(state => state.items);
45
45
  const [rows, setRows] = useState();
46
46
  const [recentRows, setRecentRows] = useState([]);
47
+ // The Host names the Human's Member id on every Inbox row's payload; the
48
+ // page keeps it so a row can draw that one actor from the Client's own
49
+ // Human identity instead of the initials the stack gives every Agent.
50
+ const [humanMemberId, setHumanMemberId] = useState();
47
51
  const [loading, setLoading] = useState(true);
48
52
  const [error, setError] = useState();
49
53
  // Only the first refresh owns the loading surface; later wakes refresh the
@@ -55,10 +59,11 @@ export function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, sele
55
59
  const results = await Promise.all(workspaces.map(async (workspace) => {
56
60
  const result = await loadInbox({ workspaceId: workspace.workspaceId, limit: 100 });
57
61
  return result.ok
58
- ? { ok: true, workspaceId: workspace.workspaceId, workspaceTitle: workspace.title, items: result.value.items, recent: result.value.recent }
62
+ ? { ok: true, workspaceId: workspace.workspaceId, workspaceTitle: workspace.title, items: result.value.items, recent: result.value.recent, humanMemberId: result.value.humanMemberId }
59
63
  : { ok: false, message: result.error.message };
60
64
  }));
61
65
  const failure = results.find(result => !result.ok);
66
+ setHumanMemberId(results.find(result => result.ok)?.humanMemberId);
62
67
  const asRows = (items, workspaceId, workspaceTitle) => items.map(item => ({ workspaceId, workspaceTitle, item }));
63
68
  setRows(results.flatMap(result => result.ok ? asRows(result.items, result.workspaceId, result.workspaceTitle) : []).sort(compareInboxRows));
64
69
  // The tail is one global bound rather than one per Workspace: the reader was
@@ -100,9 +105,15 @@ export function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, sele
100
105
  for (const row of recentRows)
101
106
  shownWorkspaces.add(row.workspaceTitle);
102
107
  const showWorkspace = shownWorkspaces.size > 1;
108
+ // One identity for every row on the page: the Host tells the rows which
109
+ // actor is the reader, the Client's identity projection says what that actor
110
+ // looks like. Either half missing leaves the stack on its initials fallback.
111
+ const human = humanMemberId === undefined
112
+ ? undefined
113
+ : { memberId: humanMemberId, name: humanName, ...(humanAvatarUrl === undefined ? {} : { avatarUrl: humanAvatarUrl }) };
103
114
  return _jsxs("main", { className: css.surface, "data-team-inbox": true, children: [_jsx("div", { className: css.surfaceHeader, children: _jsx("header", { className: css.headerRow, children: _jsxs("div", { className: css.headerCopy, children: [_jsx("h1", { children: t('inboxTitle') }), rows !== undefined && rows.length > 0 && _jsxs("p", { className: inboxCss.headerMeta, children: [_jsx("span", { children: t('inboxHeaderThreads', { count: rows.length }) }), _jsx("span", { className: inboxCss.headerUnread, children: t('inboxHeaderUnread', { count: totalUnread }) }), totalMentions > 0 && _jsx("span", { children: t('inboxHeaderMentions', { count: totalMentions }) })] })] }) }) }), _jsx("div", { className: css.timeline, children: _jsxs("div", { className: css.timelineContent, children: [loading && rows === undefined && error === undefined && _jsx("div", { className: css.emptySurface, children: _jsxs("p", { className: css.loadingState, children: [_jsx("span", { className: css.loadingMark, "aria-hidden": "true" }), t('loadingInbox')] }) }), !loading && rows === undefined && error !== undefined && _jsxs("div", { className: css.errorState, role: "alert", children: [_jsx("span", { children: error }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => { void refresh(); }, children: t('retry') })] }), rows !== undefined && (rows.length === 0 && recentRows.length === 0
104
115
  ? _jsx("div", { className: css.emptySurface, children: _jsxs("div", { className: css.emptyState, children: [_jsx("strong", { children: t('inboxEmptyTitle') }), _jsx("span", { children: t('inboxEmptyHint') })] }) })
105
- : _jsxs(_Fragment, { children: [rows.length > 0 && _jsxs("section", { className: inboxCss.section, children: [_jsxs("h2", { className: inboxCss.sectionTitle, children: [t('inboxSectionNeedsMe'), _jsx("span", { className: inboxCss.sectionCount, children: rows.length })] }), _jsx("div", { className: inboxCss.list, children: rows.map(row => _jsx(InboxQueueRow, { row: row, t: t, showWorkspace: showWorkspace, onOpen: () => { open(row); } }, `${row.workspaceId} ${row.item.thread.threadRef}`)) })] }), recentRows.length > 0 && _jsxs("section", { className: inboxCss.section, children: [_jsxs("h2", { className: inboxCss.sectionTitle, children: [t('inboxSectionRecent'), _jsx("span", { className: inboxCss.sectionCount, children: recentRows.length })] }), _jsx("div", { className: inboxCss.list, children: recentRows.map(row => _jsx(InboxQueueRow, { row: row, t: t, showWorkspace: showWorkspace, onOpen: () => { open(row); } }, `${row.workspaceId} ${row.item.thread.threadRef}`)) })] })] })), rows !== undefined && error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] }) })] });
116
+ : _jsxs(_Fragment, { children: [rows.length > 0 && _jsxs("section", { className: inboxCss.section, children: [_jsxs("h2", { className: inboxCss.sectionTitle, children: [t('inboxSectionNeedsMe'), _jsx("span", { className: inboxCss.sectionCount, children: rows.length })] }), _jsx("div", { className: inboxCss.list, children: rows.map(row => _jsx(InboxQueueRow, { row: row, t: t, showWorkspace: showWorkspace, human: human, onOpen: () => { open(row); } }, `${row.workspaceId} ${row.item.thread.threadRef}`)) })] }), recentRows.length > 0 && _jsxs("section", { className: inboxCss.section, children: [_jsxs("h2", { className: inboxCss.sectionTitle, children: [t('inboxSectionRecent'), _jsx("span", { className: inboxCss.sectionCount, children: recentRows.length })] }), _jsx("div", { className: inboxCss.list, children: recentRows.map(row => _jsx(InboxQueueRow, { row: row, t: t, showWorkspace: showWorkspace, human: human, onOpen: () => { open(row); } }, `${row.workspaceId} ${row.item.thread.threadRef}`)) })] })] })), rows !== undefined && error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] }) })] });
106
117
  }
107
118
  /**
108
119
  * One queue row, shaped like the shipped two-line result row: who is on this
@@ -126,15 +137,19 @@ export function TeamInboxPage({ useWorkspaces, loadInbox, subscribeChanges, sele
126
137
  * because a second visible count beside the first would cost the row the one
127
138
  * thing it needs to stay scannable.
128
139
  */
129
- function InboxQueueRow({ row, t, showWorkspace, onOpen }) {
140
+ function InboxQueueRow({ row, t, showWorkspace, human, onOpen }) {
130
141
  const { item } = row;
131
142
  const actor = item.newestActor;
132
143
  const owners = item.claimOwners;
144
+ // The row's names come from the Client's Human identity where it applies, so
145
+ // the chip's letter and the label's name move together on a rename.
146
+ const namedOwners = namedAvatarOwners(owners, human);
147
+ const namedActor = namedAvatarOwners([actor], human)[0];
133
148
  const named = item.directCount > 0;
134
149
  const countLabel = named
135
150
  ? t('inboxRowUnreadMentions', { count: item.unreadCount, mentions: item.directCount })
136
151
  : t('inboxRowUnread', { count: item.unreadCount });
137
152
  return _jsxs("button", { type: "button", className: inboxCss.row, "data-named": named || undefined, onClick: onOpen, children: [_jsx("span", { className: inboxCss.rowActor, children: owners.length > 0
138
- ? _jsx(TeamAvatarStack, { owners: owners, label: claimersLabel(owners, t) })
139
- : _jsx(TeamAvatarStack, { owners: [actor], label: t('inboxRowActor', { name: `@${actor.name}` }) }) }), _jsxs("span", { className: inboxCss.rowLine, children: [_jsxs("span", { className: inboxCss.rowCrumb, children: [showWorkspace && _jsx("span", { className: inboxCss.rowWorkspace, children: row.workspaceTitle }), showWorkspace && ' / ', _jsxs("span", { className: inboxCss.rowChannel, children: ["#", item.channelName] }), ' ', item.taskNumber !== undefined && _jsx("span", { className: inboxCss.rowTask, children: t('taskLabel', { number: item.taskNumber }) })] }), _jsx(TeamCountBadge, { count: item.unreadCount, tone: named ? 'solid' : 'hairline', label: countLabel }), _jsx("time", { className: inboxCss.rowTime, dateTime: item.newestOccurredAt, title: formatAbsoluteTime(item.newestOccurredAt), children: formatInboxTime(item.newestOccurredAt, t) })] }), _jsx("span", { className: inboxCss.rowPreview, children: item.previewText })] });
153
+ ? _jsx(TeamAvatarStack, { owners: namedOwners, label: claimersLabel(namedOwners, t), human: human })
154
+ : _jsx(TeamAvatarStack, { owners: [namedActor], label: t('inboxRowActor', { name: `@${namedActor.name}` }), human: human }) }), _jsxs("span", { className: inboxCss.rowLine, children: [_jsxs("span", { className: inboxCss.rowCrumb, children: [showWorkspace && _jsx("span", { className: inboxCss.rowWorkspace, children: row.workspaceTitle }), showWorkspace && ' / ', _jsxs("span", { className: inboxCss.rowChannel, children: ["#", item.channelName] }), ' ', item.taskNumber !== undefined && _jsx("span", { className: inboxCss.rowTask, children: t('taskLabel', { number: item.taskNumber }) })] }), _jsx(TeamCountBadge, { count: item.unreadCount, tone: named ? 'solid' : 'hairline', label: countLabel }), _jsx("time", { className: inboxCss.rowTime, dateTime: item.newestOccurredAt, title: formatAbsoluteTime(item.newestOccurredAt), children: formatInboxTime(item.newestOccurredAt, t) })] }), _jsx("span", { className: inboxCss.rowPreview, children: item.previewText })] });
140
155
  }
@@ -1,10 +1,20 @@
1
1
  import type { AgentTeamClientMemberStatus, AgentTeamModelSelection } from '@wowyuarm/dsh-agent-team/types';
2
2
  import type { TeamSidebarProps } from './slots.ts';
3
+ /**
4
+ * Best-effort warm of the shared catalog (the agents panel calls this while
5
+ * the roster loads, so the pickers open with rows instead of paying the
6
+ * first read on open). Failures belong to the picker's own error surface.
7
+ */
8
+ export declare function warmModelCatalog(loadModels: TeamSidebarProps['loadModels']): void;
3
9
  /**
4
10
  * Shared provider/model dropdown for the create and edit forms. The option
5
11
  * list rides the shared Menu primitive (one leading "follow Host default"
6
12
  * row, then non-selectable provider headings) with a capped, internally
7
- * scrolling card so growing model catalogs cannot stretch the dialog.
13
+ * scrolling card so growing model catalogs cannot stretch the dialog. Mounts
14
+ * open with the warmed value when one exists and revalidate behind it, so a
15
+ * slow Host read delays a refresh — never the picker itself; a refused or
16
+ * failed read with no warmed value renders a retryable error instead of
17
+ * stranding the field on "loading".
8
18
  */
9
19
  export declare function ModelPickerField({ model, onModelChange, loadModels, disabled, t }: {
10
20
  readonly model: AgentTeamModelSelection | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"TeamMemberEditor.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMemberEditor.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,uBAAuB,EAAgC,MAAM,gCAAgC,CAAA;AACxI,OAAO,KAAK,EAAiD,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAajG;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE;IAClF,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,SAAS,CAAA;IACnD,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,uBAAuB,GAAG,SAAS,KAAK,IAAI,CAAA;IAC7E,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACnD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BA0GA;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE;IAC/F,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;IACvD,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAC5B,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BA4DA;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,uBAAuB,GAAG,SAAS,EAAE,KAAK,EAAE,uBAAuB,GAAG,SAAS,GAAG,OAAO,CAIxH"}
1
+ {"version":3,"file":"TeamMemberEditor.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMemberEditor.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,uBAAuB,EAAgC,MAAM,gCAAgC,CAAA;AAExI,OAAO,KAAK,EAAmE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAkDnH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,GAAG,IAAI,CAQjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE;IAClF,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,SAAS,CAAA;IACnD,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,uBAAuB,GAAG,SAAS,KAAK,IAAI,CAAA;IAC7E,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACnD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BA4IA;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE;IAC/F,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;IACvD,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAC5B,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC,+BA4DA;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,uBAAuB,GAAG,SAAS,EAAE,KAAK,EAAE,uBAAuB,GAAG,SAAS,GAAG,OAAO,CAIxH"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from 'react';
3
- import { Button, IconChevronDownOutlineRegular, Input, Menu, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { Button, IconChevronDownOutline14, Input, Menu, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import { mintRequestId } from "./requests.js";
5
5
  import { useEditDialogSave } from "./team-dialog-save.js";
6
6
  import createCss from './create.module.css';
@@ -9,20 +9,74 @@ import css from './sidebar.module.css';
9
9
  function modelKey(provider, model) {
10
10
  return `${provider}\u0000${model}`;
11
11
  }
12
+ const modelCatalogCaches = new WeakMap();
13
+ function peekCatalogGroups(loadModels) {
14
+ return modelCatalogCaches.get(loadModels)?.value?.groups;
15
+ }
16
+ function sharedCatalog(loadModels) {
17
+ const cached = modelCatalogCaches.get(loadModels);
18
+ if (cached?.inflight !== undefined)
19
+ return cached.inflight;
20
+ const next = loadModels();
21
+ const entry = cached ?? {};
22
+ entry.inflight = next;
23
+ modelCatalogCaches.set(loadModels, entry);
24
+ const forget = (result) => {
25
+ if (modelCatalogCaches.get(loadModels) === entry && entry.inflight === next) {
26
+ delete entry.inflight;
27
+ if (result !== undefined && result.ok)
28
+ entry.value = result.value;
29
+ }
30
+ };
31
+ next.then((result) => { forget(result); }, () => { forget(undefined); });
32
+ return next;
33
+ }
34
+ /**
35
+ * Best-effort warm of the shared catalog (the agents panel calls this while
36
+ * the roster loads, so the pickers open with rows instead of paying the
37
+ * first read on open). Failures belong to the picker's own error surface.
38
+ */
39
+ export function warmModelCatalog(loadModels) {
40
+ try {
41
+ void sharedCatalog(loadModels).catch(() => {
42
+ // The picker that later reads surfaces the failure with its retry entry.
43
+ });
44
+ }
45
+ catch {
46
+ // Same: a synchronously refused warm leaves no trace; the picker reports it.
47
+ }
48
+ }
12
49
  /**
13
50
  * Shared provider/model dropdown for the create and edit forms. The option
14
51
  * list rides the shared Menu primitive (one leading "follow Host default"
15
52
  * row, then non-selectable provider headings) with a capped, internally
16
- * scrolling card so growing model catalogs cannot stretch the dialog.
53
+ * scrolling card so growing model catalogs cannot stretch the dialog. Mounts
54
+ * open with the warmed value when one exists and revalidate behind it, so a
55
+ * slow Host read delays a refresh — never the picker itself; a refused or
56
+ * failed read with no warmed value renders a retryable error instead of
57
+ * stranding the field on "loading".
17
58
  */
18
59
  export function ModelPickerField({ model, onModelChange, loadModels, disabled, t }) {
19
- const [groups, setGroups] = useState();
60
+ const [groups, setGroups] = useState(() => peekCatalogGroups(loadModels));
20
61
  const [modelsError, setModelsError] = useState();
62
+ const [reloadToken, setReloadToken] = useState(0);
21
63
  const [open, setModelOpen] = useState(false);
22
64
  const [effortOpen, setEffortOpen] = useState(false);
23
65
  useEffect(() => {
24
66
  let mounted = true;
25
- void loadModels().then(result => {
67
+ let pending;
68
+ try {
69
+ pending = sharedCatalog(loadModels);
70
+ }
71
+ catch (error) {
72
+ // A synchronously refused read (an undeclared remote, a dead scope)
73
+ // used to strand the field on "loading" forever with no diagnostic;
74
+ // surface it as the same retryable failure an answered refusal gets.
75
+ // Last good rows stay rendered underneath, matching a refused answer.
76
+ setModelsError(error instanceof Error ? error.message : String(error));
77
+ return;
78
+ }
79
+ void pending.then((result) => {
26
80
  if (!mounted)
27
81
  return;
28
82
  if (result.ok) {
@@ -32,9 +86,16 @@ export function ModelPickerField({ model, onModelChange, loadModels, disabled, t
32
86
  else {
33
87
  setModelsError(result.error.message);
34
88
  }
89
+ }, (error) => {
90
+ // A rejected read (a transport that died mid-call) previously fell
91
+ // through as an unhandled rejection behind the same endless loading
92
+ // line; it retries like any other failure.
93
+ if (!mounted)
94
+ return;
95
+ setModelsError(error instanceof Error ? error.message : String(error));
35
96
  });
36
97
  return () => { mounted = false; };
37
- }, [loadModels]);
98
+ }, [loadModels, reloadToken]);
38
99
  const items = [{ id: '', label: t('modelFollowDefault') }];
39
100
  const byKey = new Map();
40
101
  for (const group of groups ?? []) {
@@ -57,16 +118,16 @@ export function ModelPickerField({ model, onModelChange, loadModels, disabled, t
57
118
  const effortTriggerLabel = model === undefined || selectedEffort === ''
58
119
  ? t('effortFollowDefault')
59
120
  : efforts.find(effort => effort.id === selectedEffort)?.name ?? selectedEffort;
60
- return _jsxs("div", { className: createCss.field, children: [_jsx("span", { children: t('memberModel') }), groups === undefined && modelsError === undefined && _jsx("small", { className: css.editHint, children: t('modelsLoading') }), modelsError !== undefined && _jsx("small", { className: css.editHint, children: t('modelsLoadFailed', { message: modelsError }) }), groups !== undefined && (_jsx(Menu, { open: open, portal: true, className: createCss.menuCap, items: items, selectedId: selectedModelKey, onSelect: key => {
121
+ return _jsxs("div", { className: createCss.field, children: [_jsx("span", { children: t('memberModel') }), groups === undefined && modelsError === undefined && _jsx("small", { className: css.editHint, children: t('modelsLoading') }), modelsError !== undefined && (_jsxs("p", { className: css.editHint, children: [_jsx("span", { role: "alert", children: t('modelsLoadFailed', { message: modelsError }) }), ' ', _jsx(Button, { size: "sm", variant: "outline", disabled: disabled, onClick: () => { setModelsError(undefined); setReloadToken(token => token + 1); }, children: t('retry') })] })), groups !== undefined && (_jsx(Menu, { open: open, portal: true, className: createCss.menuCap, items: items, selectedId: selectedModelKey, onSelect: key => {
61
122
  setModelOpen(false);
62
123
  const choice = byKey.get(key);
63
124
  onModelChange(choice === undefined ? undefined : { provider: choice.provider, model: choice.id });
64
- }, onClose: () => { setModelOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('memberModel'), "aria-haspopup": "menu", "aria-expanded": open, disabled: disabled, onClick: () => { setModelOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: triggerLabel }), _jsx("span", { className: `${createCss.chevron} ${open ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutlineRegular, {}) })] }) })), model !== undefined && efforts.length > 0 && (_jsx(Menu, { open: effortOpen, portal: true, className: createCss.menuCap, items: effortItems, selectedId: selectedEffort, onSelect: key => {
125
+ }, onClose: () => { setModelOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('memberModel'), "aria-haspopup": "menu", "aria-expanded": open, disabled: disabled, onClick: () => { setModelOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: triggerLabel }), _jsx("span", { className: `${createCss.chevron} ${open ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutline14, {}) })] }) })), model !== undefined && efforts.length > 0 && (_jsx(Menu, { open: effortOpen, portal: true, className: createCss.menuCap, items: effortItems, selectedId: selectedEffort, onSelect: key => {
65
126
  setEffortOpen(false);
66
127
  onModelChange(key === ''
67
128
  ? { provider: model.provider, model: model.model }
68
129
  : { provider: model.provider, model: model.model, reasoningEffort: key });
69
- }, onClose: () => { setEffortOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('reasoningEffort'), "aria-haspopup": "menu", "aria-expanded": effortOpen, disabled: disabled, onClick: () => { setEffortOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: `${t('reasoningEffort')} · ${effortTriggerLabel}` }), _jsx("span", { className: `${createCss.chevron} ${effortOpen ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutlineRegular, {}) })] }) }))] });
130
+ }, onClose: () => { setEffortOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('reasoningEffort'), "aria-haspopup": "menu", "aria-expanded": effortOpen, disabled: disabled, onClick: () => { setEffortOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: `${t('reasoningEffort')} · ${effortTriggerLabel}` }), _jsx("span", { className: `${createCss.chevron} ${effortOpen ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutline14, {}) })] }) }))] });
70
131
  }
71
132
  /**
72
133
  * Agent editor: handle, description, and per-Member model selection commit
@@ -1,6 +1,6 @@
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
- import { IconUserOutlineRegular, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { IconUserOutline16, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  import { TeamMemberRow } from "./TeamMemberRow.js";
5
5
  import membersCss from './members.module.css';
6
6
  import css from './team.module.css';
@@ -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(IconUserOutlineRegular, { 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 })] }) })] }));
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
  }
@@ -1,7 +1,11 @@
1
1
  import { type ReactNode } from 'react';
2
- import type { AgentTeamMemberId, AgentTeamMessageAttachment, AgentTeamTaskRef } from '@wowyuarm/dsh-agent-team/types';
2
+ import type { SessionId } from '@deepseek-ai/dsh-session';
3
+ import type { AgentTeamChannelRef, AgentTeamMemberId, AgentTeamMessageAttachment, AgentTeamTaskRef, AgentTeamThreadRef } from '@wowyuarm/dsh-agent-team/types';
3
4
  import type { TeamConversationProps } from './slots.ts';
4
- import { type ResolvedTaskRef } from './task-refs.ts';
5
+ import type { ResolvedMemberRef } from './refs.ts';
6
+ import { type ResolvedTaskRef } from './refs.ts';
7
+ import { type ResolvedThreadRef } from './refs.ts';
8
+ import { type MentionHandle } from './team-formatters.ts';
5
9
  export interface TeamMessageProps {
6
10
  readonly senderName: string;
7
11
  readonly memberId: AgentTeamMemberId;
@@ -10,7 +14,7 @@ export interface TeamMessageProps {
10
14
  readonly body: string;
11
15
  readonly occurredAt?: string;
12
16
  /** Structured mention handles of this Message; the only names that render as chips. */
13
- readonly mentionNames?: readonly string[];
17
+ readonly mentionNames?: readonly MentionHandle[];
14
18
  readonly senderTitle?: string;
15
19
  /** Continuation of one same-sender run: suppress repeated identity chrome. */
16
20
  readonly grouped?: boolean;
@@ -18,6 +22,9 @@ export interface TeamMessageProps {
18
22
  hairline-separated entry stays self-identifying. */
19
23
  readonly showGroupedTime?: boolean;
20
24
  readonly attachments?: readonly AgentTeamMessageAttachment[] | undefined;
25
+ /** The Human's uploaded avatar; only the Human's own row draws it, and absent
26
+ * or undecodable bytes draw the initial on the business-tinted chip. */
27
+ readonly avatarUrl?: string | undefined;
21
28
  /** Cache readback for thumbnails; absent on surfaces without the remotes. */
22
29
  readonly loadAttachment?: TeamConversationProps['getAttachment'] | undefined;
23
30
  readonly t?: TeamConversationProps['t'] | undefined;
@@ -25,6 +32,14 @@ export interface TeamMessageProps {
25
32
  readonly onOpenRef?: ((ref: string) => void) | undefined;
26
33
  /** Host lookup turning task refs into human-facing numbers; absent keeps raw refs. */
27
34
  readonly onResolveTaskRefs?: ((taskRefs: readonly AgentTeamTaskRef[]) => Promise<readonly ResolvedTaskRef[]>) | undefined;
35
+ /** Host lookup turning thread refs into titled chips; absent keeps raw refs. */
36
+ readonly onResolveThreadRefs?: ((threadRefs: readonly AgentTeamThreadRef[]) => Promise<readonly ResolvedThreadRef[]>) | undefined;
37
+ /** Roster name for one authored channel ref; absent or unknown keeps plain text. */
38
+ readonly channelNameOf?: ((ref: AgentTeamChannelRef) => string | undefined) | undefined;
39
+ /** Roster facts for one authored member ref; absent or unknown keeps plain text. */
40
+ readonly memberOf?: ((ref: AgentTeamMemberId) => ResolvedMemberRef | undefined) | undefined;
41
+ /** Agent-card session jump for member chips; absent renders them as plain text. */
42
+ readonly onOpenMemberSession?: ((sessionId: SessionId) => void) | undefined;
28
43
  readonly children?: ReactNode;
29
44
  }
30
45
  /**
@@ -1 +1 @@
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
+ {"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,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAC9J,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAElD,OAAO,EAA4E,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAC1H,OAAO,EAAkF,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAClI,OAAO,EAA8H,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAIrL,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,aAAa,EAAE,CAAA;IAChD,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;4EACwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,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,gFAAgF;IAChF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,SAAS,kBAAkB,EAAE,KAAK,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IACjI,oFAAoF;IACpF,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAA;IACvF,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,iBAAiB,KAAK,iBAAiB,GAAG,SAAS,CAAC,GAAG,SAAS,CAAA;IAC3F,mFAAmF;IACnF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAC9B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,wDA4JtB,CAAA"}