@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.
- package/README.md +5 -3
- package/README.zh.md +5 -3
- package/cordis.patch.yml +2 -185
- package/package.json +52 -46
- package/packages/agent-team/README.md +1 -1
- package/packages/agent-team/README.zh.md +1 -1
- package/packages/agent-team/core-skills/member-memory-manager/SKILL.md +30 -0
- package/packages/agent-team/lib/context-continuity-host.js +91 -0
- package/packages/agent-team/lib/context-projection.js +266 -489
- package/packages/agent-team/lib/context-source.js +17 -106
- package/packages/agent-team/lib/human-avatar.js +61 -0
- package/packages/agent-team/lib/human-profile.js +46 -0
- package/packages/agent-team/lib/human-update-check.js +119 -0
- package/packages/agent-team/lib/index.js +408 -264
- package/packages/agent-team/lib/ledger.js +120 -15
- package/packages/agent-team/lib/member-context.js +9 -8
- package/packages/agent-team/lib/member-runtime.js +1 -1
- package/packages/agent-team/lib/member-time-context.js +2 -5
- package/packages/agent-team/lib/preset-roster.js +15 -0
- package/packages/agent-team/lib/pressure-policy.js +9 -6
- package/packages/agent-team/lib/session-remediation.js +493 -0
- package/packages/agent-team/lib/stored-session-reader.js +2 -1
- package/packages/agent-team/lib/typert.host.js +605 -291
- package/packages/agent-team/lib/typert.remote-client.d.ts +15 -6
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +367 -244
- package/packages/agent-team/lib/types/context-continuity-host.d.ts +84 -0
- package/packages/agent-team/lib/types/context-continuity-host.d.ts.map +1 -0
- package/packages/agent-team/lib/types/context-projection.d.ts +130 -185
- package/packages/agent-team/lib/types/context-projection.d.ts.map +1 -1
- package/packages/agent-team/lib/types/context-source.d.ts +17 -81
- package/packages/agent-team/lib/types/context-source.d.ts.map +1 -1
- package/packages/agent-team/lib/types/human-avatar.d.ts +29 -0
- package/packages/agent-team/lib/types/human-avatar.d.ts.map +1 -0
- package/packages/agent-team/lib/types/human-profile.d.ts +44 -0
- package/packages/agent-team/lib/types/human-profile.d.ts.map +1 -0
- package/packages/agent-team/lib/types/human-update-check.d.ts +73 -0
- package/packages/agent-team/lib/types/human-update-check.d.ts.map +1 -0
- package/packages/agent-team/lib/types/index.d.ts +112 -38
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/ledger.d.ts +31 -2
- package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-context.d.ts +0 -14
- package/packages/agent-team/lib/types/member-context.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-time-context.d.ts +0 -15
- package/packages/agent-team/lib/types/member-time-context.d.ts.map +1 -1
- package/packages/agent-team/lib/types/preset-roster.d.ts +5 -0
- package/packages/agent-team/lib/types/preset-roster.d.ts.map +1 -0
- package/packages/agent-team/lib/types/pressure-policy.d.ts +6 -0
- package/packages/agent-team/lib/types/pressure-policy.d.ts.map +1 -1
- package/packages/agent-team/lib/types/session-remediation.d.ts +172 -0
- package/packages/agent-team/lib/types/session-remediation.d.ts.map +1 -0
- package/packages/agent-team/lib/types/stored-session-reader.d.ts +2 -1
- package/packages/agent-team/lib/types/stored-session-reader.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/entities.d.ts +20 -3
- package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/requests-results.d.ts +63 -0
- package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
- package/packages/agent-team/preset/team-member/agent.cordis.yml +166 -0
- package/packages/client-agent-team/lib/client.js +1667 -516
- package/packages/client-agent-team/lib/client.js.map +1 -1
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts +15 -0
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.js +115 -0
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +12 -8
- package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts +22 -1
- package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAvatarStack.js +25 -2
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +6 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +69 -31
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +4 -4
- package/packages/client-agent-team/lib/types/client/TeamComposer.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.js +12 -5
- package/packages/client-agent-team/lib/types/client/TeamFooterAction.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts +4 -1
- package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamInboxPage.js +22 -7
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts +11 -1
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +69 -8
- package/packages/client-agent-team/lib/types/client/TeamMembersAction.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +18 -3
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMessage.js +213 -67
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamSidebarSection.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +5 -0
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +55 -29
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceSelector.js +2 -2
- package/packages/client-agent-team/lib/types/client/avatar-image.d.ts +21 -0
- package/packages/client-agent-team/lib/types/client/avatar-image.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/avatar-image.js +9 -0
- package/packages/client-agent-team/lib/types/client/human-identity.d.ts +94 -0
- package/packages/client-agent-team/lib/types/client/human-identity.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/human-identity.js +117 -0
- package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/index.js +112 -41
- package/packages/client-agent-team/lib/types/client/locales.d.ts +72 -2
- package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/locales.js +78 -2
- package/packages/client-agent-team/lib/types/client/multi-menu-field.js +2 -2
- package/packages/client-agent-team/lib/types/client/refs.d.ts +71 -0
- package/packages/client-agent-team/lib/types/client/refs.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/refs.js +181 -0
- package/packages/client-agent-team/lib/types/client/slots.d.ts +8 -2
- package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +57 -9
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.js +85 -17
- package/packages/tool-agent-team/README.md +1 -1
- package/packages/tool-agent-team/README.zh.md +1 -1
- package/packages/tool-agent-team/lib/context-tools.js +20 -6
- package/packages/tool-agent-team/lib/index.js +2 -2
- package/packages/tool-agent-team/lib/types/context-tools.d.ts.map +1 -1
- package/packages/agent-team/lib/context-management.js +0 -371
- package/packages/agent-team/lib/types/context-management.d.ts +0 -154
- package/packages/agent-team/lib/types/context-management.d.ts.map +0 -1
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts +0 -31
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +0 -1
- 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 {
|
|
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(
|
|
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(
|
|
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;
|
|
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
|
-
|
|
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 {
|
|
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(
|
|
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,+
|
|
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:
|
|
139
|
-
: _jsx(TeamAvatarStack, { owners: [
|
|
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;
|
|
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,
|
|
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
|
-
|
|
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 &&
|
|
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(
|
|
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(
|
|
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 {
|
|
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(
|
|
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 {
|
|
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 {
|
|
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
|
|
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;
|
|
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"}
|