@wowyuarm/dsh-agent-team 0.1.14-alpha.2 → 0.1.15
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 +6 -4
- package/README.zh.md +6 -4
- package/cordis.patch.yml +3 -1
- package/package.json +51 -46
- package/packages/agent-team/README.md +2 -2
- package/packages/agent-team/README.zh.md +2 -2
- package/packages/agent-team/core-skills/member-memory-manager/SKILL.md +30 -0
- package/packages/agent-team/lib/context-continuity-host.js +90 -0
- package/packages/agent-team/lib/context-projection.js +266 -489
- package/packages/agent-team/lib/context-source.js +4 -72
- package/packages/agent-team/lib/human-avatar.js +61 -0
- package/packages/agent-team/lib/human-profile.js +157 -0
- package/packages/agent-team/lib/human-update-check.js +119 -0
- package/packages/agent-team/lib/index.js +464 -254
- package/packages/agent-team/lib/ledger.js +120 -15
- package/packages/agent-team/lib/member-context.js +6 -3
- package/packages/agent-team/lib/member-runtime.js +1 -1
- package/packages/agent-team/lib/pressure-policy.js +6 -1
- package/packages/agent-team/lib/typert.host.js +489 -33
- package/packages/agent-team/lib/typert.remote-client.d.ts +15 -3
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +250 -28
- 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 +4 -35
- 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 +116 -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 +153 -41
- 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.map +1 -1
- 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/types/entities.d.ts +17 -0
- package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/requests-results.d.ts +81 -0
- package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
- package/packages/client-agent-team/README.md +1 -1
- package/packages/client-agent-team/README.zh.md +1 -1
- package/packages/client-agent-team/lib/client.js +1545 -303
- 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 +6 -2
- 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 +67 -29
- package/packages/client-agent-team/lib/types/client/TeamComposer.js +2 -2
- 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/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 +66 -5
- 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/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 +52 -26
- 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 +90 -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 +96 -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 +76 -4
- 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/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 +9 -3
- 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 +2 -2
- package/packages/tool-agent-team/README.zh.md +2 -2
- 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
|
@@ -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"}
|
|
@@ -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,7 +118,7 @@ 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 });
|
|
@@ -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,wDA8JtB,CAAA"}
|