@wowyuarm/dsh-agent-team 0.1.8 → 0.1.10
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 +4 -11
- package/README.zh.md +4 -11
- package/package.json +54 -44
- package/packages/agent-team/README.md +7 -5
- package/packages/agent-team/README.zh.md +7 -4
- package/packages/agent-team/lib/attachments.js +14 -4
- package/packages/agent-team/lib/context-management.js +382 -0
- package/packages/agent-team/lib/context-projection.js +578 -0
- package/packages/agent-team/lib/context-source.js +212 -0
- package/packages/agent-team/lib/index.js +1272 -76
- package/packages/agent-team/lib/ledger.js +333 -44
- package/packages/agent-team/lib/member-context.js +6 -2
- package/packages/agent-team/lib/member-runtime.js +159 -4
- package/packages/agent-team/lib/member-time-context.js +126 -0
- package/packages/agent-team/lib/pressure-policy.js +199 -0
- package/packages/agent-team/lib/progress-nudge.js +12 -4
- package/packages/agent-team/lib/session-remediation.js +481 -0
- package/packages/agent-team/lib/spec.js +21 -2
- package/packages/agent-team/lib/time-format.js +56 -0
- package/packages/agent-team/lib/typert.host.js +168 -54
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +59 -25
- package/packages/agent-team/lib/types/attachments.d.ts +1 -1
- package/packages/agent-team/lib/types/attachments.d.ts.map +1 -1
- package/packages/agent-team/lib/types/context-management.d.ts +147 -0
- package/packages/agent-team/lib/types/context-management.d.ts.map +1 -0
- package/packages/agent-team/lib/types/context-projection.d.ts +219 -0
- package/packages/agent-team/lib/types/context-projection.d.ts.map +1 -0
- package/packages/agent-team/lib/types/context-source.d.ts +117 -0
- package/packages/agent-team/lib/types/context-source.d.ts.map +1 -0
- package/packages/agent-team/lib/types/index.d.ts +300 -2
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/ledger.d.ts +119 -6
- 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/member-runtime.d.ts +30 -2
- package/packages/agent-team/lib/types/member-runtime.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-time-context.d.ts +83 -0
- package/packages/agent-team/lib/types/member-time-context.d.ts.map +1 -0
- package/packages/agent-team/lib/types/pressure-policy.d.ts +106 -0
- package/packages/agent-team/lib/types/pressure-policy.d.ts.map +1 -0
- package/packages/agent-team/lib/types/progress-nudge.d.ts.map +1 -1
- package/packages/agent-team/lib/types/session-remediation.d.ts +149 -0
- package/packages/agent-team/lib/types/session-remediation.d.ts.map +1 -0
- package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
- package/packages/agent-team/lib/types/time-format.d.ts +28 -0
- package/packages/agent-team/lib/types/time-format.d.ts.map +1 -0
- package/packages/agent-team/lib/types/types/entities.d.ts +22 -1
- package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/operations.d.ts +38 -3
- package/packages/agent-team/lib/types/types/operations.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/requests-results.d.ts +58 -1
- package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
- package/packages/agent-team/preset/team-member/agent.cordis.yml +27 -4
- package/packages/client-agent-team/lib/client.js +369 -352
- package/packages/client-agent-team/lib/client.js.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts +1 -2
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +61 -41
- package/packages/client-agent-team/lib/types/client/TeamMessage.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +4 -4
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +2 -2
- package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/index.js +44 -16
- package/packages/client-agent-team/lib/types/client/locales.d.ts +0 -14
- package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/locales.js +0 -14
- package/packages/client-agent-team/lib/types/client/slots.d.ts +6 -1
- package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
- package/packages/tool-agent-team/README.md +11 -6
- package/packages/tool-agent-team/README.zh.md +11 -6
- package/packages/tool-agent-team/lib/context-tools.js +179 -0
- package/packages/tool-agent-team/lib/index.js +369 -58
- package/packages/tool-agent-team/lib/types/context-tools.d.ts +16 -0
- package/packages/tool-agent-team/lib/types/context-tools.d.ts.map +1 -0
- package/packages/tool-agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/auto-compaction.js +0 -201
- package/packages/agent-team/lib/types/auto-compaction.d.ts +0 -47
- package/packages/agent-team/lib/types/auto-compaction.d.ts.map +0 -1
|
@@ -8,7 +8,6 @@ interface TeamAgentsPanelProps {
|
|
|
8
8
|
readonly addMember: TeamSidebarProps['addMember'];
|
|
9
9
|
readonly updateMember: TeamSidebarProps['updateMember'];
|
|
10
10
|
readonly recoverMember: TeamSidebarProps['recoverMember'];
|
|
11
|
-
readonly clearMemberContext: TeamSidebarProps['clearMemberContext'];
|
|
12
11
|
readonly archiveMember: TeamSidebarProps['archiveMember'];
|
|
13
12
|
readonly loadModels: TeamSidebarProps['loadModels'];
|
|
14
13
|
/** The Member Session currently embedded in the conversation seat, if any. */
|
|
@@ -17,6 +16,6 @@ interface TeamAgentsPanelProps {
|
|
|
17
16
|
readonly onCreatingChange: (request: AgentTeamAddMemberRequest, creating: boolean) => void;
|
|
18
17
|
readonly t: TeamSidebarProps['t'];
|
|
19
18
|
}
|
|
20
|
-
export declare function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, addMember, updateMember, recoverMember,
|
|
19
|
+
export declare function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, addMember, updateMember, recoverMember, archiveMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }: TeamAgentsPanelProps): import("react").JSX.Element;
|
|
21
20
|
export {};
|
|
22
21
|
//# sourceMappingURL=TeamAgentsPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamAgentsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/TeamAgentsPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAE5B,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAYlD,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IACrD,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,CAAA;IAC/D,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACjD,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;IACvD,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAA;IACzD,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"TeamAgentsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/TeamAgentsPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAE5B,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAYlD,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IACrD,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,CAAA;IAC/D,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACjD,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;IACvD,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAA;IACzD,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAA;IACzD,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACnD,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,CAAC,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,CAAA;IAC7E,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,mBAAmB,CAAC,CAAA;IACjE,QAAQ,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,yBAAyB,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IAC1F,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC;AAED,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC,EAAE,EAAE,oBAAoB,+BA2N/N"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { Button, IconArchiveOutline20, IconEditOutline16,
|
|
3
|
+
import { Button, IconArchiveOutline20, IconEditOutline16, IconPlayOutline16, IconPlusOutline16, IconRefreshOutline16, Input, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamMemberAvatar } from "./TeamMemberAvatar.js";
|
|
5
5
|
import { SortableRow, useSidebarRowDrag } from "./sidebar-drag.js";
|
|
6
6
|
import { moveSidebarItem, useSidebarOrder } from "./sidebar-order.js";
|
|
@@ -11,7 +11,7 @@ import { TeamSidebarSection } from "./TeamSidebarSection.js";
|
|
|
11
11
|
import { AgentEditorDialog, ModelPickerField, sameModel } from "./TeamMemberEditor.js";
|
|
12
12
|
import createCss from './create.module.css';
|
|
13
13
|
import css from './sidebar.module.css';
|
|
14
|
-
export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, addMember, updateMember, recoverMember,
|
|
14
|
+
export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, addMember, updateMember, recoverMember, archiveMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }) {
|
|
15
15
|
const [members, setMembers] = useState([]);
|
|
16
16
|
const [loading, setLoading] = useState(true);
|
|
17
17
|
const [error, setError] = useState();
|
|
@@ -35,20 +35,74 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, ad
|
|
|
35
35
|
};
|
|
36
36
|
const drag = useSidebarRowDrag({ refs: orderedAgentRefs, onCommit: applyMove });
|
|
37
37
|
const sectionOpen = useSidebarSectionOpen(workspaceId, 'agents');
|
|
38
|
+
// Observed old→new Session binding per Member while this panel is
|
|
39
|
+
// mounted. A model-initiated rollover moves the binding without any
|
|
40
|
+
// Client action; when the conversation seat is showing the Member's
|
|
41
|
+
// previous live Session, the panel follows to the new one exactly once —
|
|
42
|
+
// but only after the refreshed status is actually active, so the commit
|
|
43
|
+
// window (binding moved, new Session not yet live) never redirects to a
|
|
44
|
+
// Session that does not exist. The follow requires the seat to still show
|
|
45
|
+
// the previous Session at completion as well: a rollover observed while
|
|
46
|
+
// unavailable stays pending, and navigating away before it completes
|
|
47
|
+
// cancels the follow instead of pulling the pane back.
|
|
48
|
+
const observedSessionIds = useRef(new Map());
|
|
49
|
+
const pendingFollows = useRef(new Map());
|
|
50
|
+
// The seat's embedded Session id rides a ref: the change subscription may
|
|
51
|
+
// deliver an invalidation through a refresh closure captured before the
|
|
52
|
+
// seat rebinds, and the follow decision must always read the live value.
|
|
53
|
+
const seatSessionIdRef = useRef(memberSessionId);
|
|
54
|
+
seatSessionIdRef.current = memberSessionId;
|
|
55
|
+
const openMemberSessionRef = useRef(openMemberSession);
|
|
56
|
+
openMemberSessionRef.current = openMemberSession;
|
|
57
|
+
const followRollover = useCallback((statuses) => {
|
|
58
|
+
for (const status of statuses) {
|
|
59
|
+
const memberId = status.member.memberId;
|
|
60
|
+
const observed = observedSessionIds.current.get(memberId);
|
|
61
|
+
if (observed === undefined) {
|
|
62
|
+
observedSessionIds.current.set(memberId, status.member.sessionId);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (observed !== status.member.sessionId) {
|
|
66
|
+
observedSessionIds.current.set(memberId, status.member.sessionId);
|
|
67
|
+
// Only the exact previous live page follows; browsing an older
|
|
68
|
+
// archive or another Member stays untouched. A binding change seen
|
|
69
|
+
// before any page is embedded is still recorded so the observation
|
|
70
|
+
// baseline stays current.
|
|
71
|
+
const seatSessionId = seatSessionIdRef.current;
|
|
72
|
+
if (seatSessionId !== undefined && observed === seatSessionId)
|
|
73
|
+
pendingFollows.current.set(memberId, { previousSessionId: observed, nextSessionId: status.member.sessionId });
|
|
74
|
+
else
|
|
75
|
+
pendingFollows.current.delete(memberId);
|
|
76
|
+
}
|
|
77
|
+
const pending = pendingFollows.current.get(memberId);
|
|
78
|
+
if (pending !== undefined && pending.nextSessionId === status.member.sessionId && status.availability === 'active') {
|
|
79
|
+
// The seat must still show the followed Member's previous Session at
|
|
80
|
+
// completion too: the commit window can outlive the user's patience,
|
|
81
|
+
// and navigating away (or onto another Member/archive view) cancels
|
|
82
|
+
// the follow instead of yanking the pane back onto the new Session.
|
|
83
|
+
const seatSessionId = seatSessionIdRef.current;
|
|
84
|
+
pendingFollows.current.delete(memberId);
|
|
85
|
+
if (seatSessionId !== undefined && seatSessionId === pending.previousSessionId)
|
|
86
|
+
openMemberSessionRef.current(pending.nextSessionId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}, []);
|
|
38
90
|
const refresh = useCallback(async () => {
|
|
39
91
|
setLoading(true);
|
|
40
92
|
const result = await loadMembers({ workspaceId });
|
|
41
93
|
if (result.ok) {
|
|
42
94
|
// Archived Members are hidden from every surface; the row disappears
|
|
43
95
|
// the moment the workspace-scope wake delivers the archived state.
|
|
44
|
-
|
|
96
|
+
const next = result.value.filter(status => status.member.state !== 'inactive' && status.member.state !== 'archived');
|
|
97
|
+
setMembers(next);
|
|
98
|
+
followRollover(next);
|
|
45
99
|
setError(undefined);
|
|
46
100
|
}
|
|
47
101
|
else {
|
|
48
102
|
setError(result.error.message);
|
|
49
103
|
}
|
|
50
104
|
setLoading(false);
|
|
51
|
-
}, [loadMembers, workspaceId]);
|
|
105
|
+
}, [loadMembers, workspaceId, followRollover]);
|
|
52
106
|
useEffect(() => { void refresh(); }, [refresh]);
|
|
53
107
|
useEffect(() => subscribeChanges({ kind: 'workspace', workspaceId }, update => {
|
|
54
108
|
if (update.type === 'failed') {
|
|
@@ -126,17 +180,16 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, ad
|
|
|
126
180
|
...(model === undefined ? {} : { model }),
|
|
127
181
|
});
|
|
128
182
|
};
|
|
129
|
-
return (_jsxs("div", { className: css.panel, children: [_jsx(Modal, { open: formOpen, onClose: closeForm, title: t('addAgent'), closeLabel: t('close'), contentClassName: createCss.dialogContent, footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", disabled: creating, onClick: closeForm, children: t('cancel') }), _jsx(Button, { type: "submit", form: "team-agent-create-form", variant: "primary", disabled: creating || handle.trim().length === 0, children: creating ? t('creatingAgent') : t('createAgent') })] }), children: _jsxs("form", { id: "team-agent-create-form", className: createCss.form, onSubmit: submit, children: [_jsxs("label", { className: createCss.field, children: [_jsx("span", { children: t('agentName') }), _jsx(Input, { className: createCss.input, value: handle, onChange: event => { setHandle(event.target.value); setRetryRequest(undefined); }, disabled: creating, autoFocus: true })] }), _jsxs("label", { className: createCss.field, children: [_jsxs("span", { children: [t('agentDescription'), t('optionalSuffix')] }), _jsx(Input, { className: createCss.input, value: description, placeholder: t('agentDescriptionPlaceholder'), onChange: event => { setDescription(event.target.value); setRetryRequest(undefined); }, disabled: creating })] }), _jsx(ModelPickerField, { model: model, onModelChange: choice => { setModel(choice); setRetryRequest(undefined); }, loadModels: loadModels, disabled: creating, t: t }), formOpen && error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('agents'), open: sectionOpen, onToggle: open => { setSidebarSectionOpen(workspaceId, 'agents', open); }, actions: (_jsx(Tooltip, { label: t('addAgent'), delayMs: 500, children: _jsx("button", { ref: triggerRef, type: "button", className: css.iconButton, "aria-label": t('addAgent'), onClick: () => { setError(undefined); setFormOpen(true); }, children: _jsx(IconPlusOutline16, { size: 14 }) }) })), children: [loading && members.length === 0 && _jsx("p", { className: css.emptyState, children: t('loadingAgents') }), !loading && members.length === 0 && _jsx("p", { className: css.emptyState, children: t('emptyAgents') }), _jsx("div", { className: css.agentList, children: orderedMembers.map(status => (_jsx(SortableRow, { drag: drag, orderKey: status.member.memberId, children: _jsx(AgentRow, { status: status, ...(memberSessionId === undefined ? {} : { current: status.member.sessionId === memberSessionId }), updateMember: updateMember, recoverMember: recoverMember,
|
|
183
|
+
return (_jsxs("div", { className: css.panel, children: [_jsx(Modal, { open: formOpen, onClose: closeForm, title: t('addAgent'), closeLabel: t('close'), contentClassName: createCss.dialogContent, footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", disabled: creating, onClick: closeForm, children: t('cancel') }), _jsx(Button, { type: "submit", form: "team-agent-create-form", variant: "primary", disabled: creating || handle.trim().length === 0, children: creating ? t('creatingAgent') : t('createAgent') })] }), children: _jsxs("form", { id: "team-agent-create-form", className: createCss.form, onSubmit: submit, children: [_jsxs("label", { className: createCss.field, children: [_jsx("span", { children: t('agentName') }), _jsx(Input, { className: createCss.input, value: handle, onChange: event => { setHandle(event.target.value); setRetryRequest(undefined); }, disabled: creating, autoFocus: true })] }), _jsxs("label", { className: createCss.field, children: [_jsxs("span", { children: [t('agentDescription'), t('optionalSuffix')] }), _jsx(Input, { className: createCss.input, value: description, placeholder: t('agentDescriptionPlaceholder'), onChange: event => { setDescription(event.target.value); setRetryRequest(undefined); }, disabled: creating })] }), _jsx(ModelPickerField, { model: model, onModelChange: choice => { setModel(choice); setRetryRequest(undefined); }, loadModels: loadModels, disabled: creating, t: t }), formOpen && error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('agents'), open: sectionOpen, onToggle: open => { setSidebarSectionOpen(workspaceId, 'agents', open); }, actions: (_jsx(Tooltip, { label: t('addAgent'), delayMs: 500, children: _jsx("button", { ref: triggerRef, type: "button", className: css.iconButton, "aria-label": t('addAgent'), onClick: () => { setError(undefined); setFormOpen(true); }, children: _jsx(IconPlusOutline16, { size: 14 }) }) })), children: [loading && members.length === 0 && _jsx("p", { className: css.emptyState, children: t('loadingAgents') }), !loading && members.length === 0 && _jsx("p", { className: css.emptyState, children: t('emptyAgents') }), _jsx("div", { className: css.agentList, children: orderedMembers.map(status => (_jsx(SortableRow, { drag: drag, orderKey: status.member.memberId, children: _jsx(AgentRow, { status: status, ...(memberSessionId === undefined ? {} : { current: status.member.sessionId === memberSessionId }), updateMember: updateMember, recoverMember: recoverMember, archiveMember: archiveMember, loadModels: loadModels, openMemberSession: openMemberSession, onUpdated: () => { void refresh(); }, t: t }) }, status.member.memberId))) })] }), !formOpen && error !== undefined && (_jsxs("div", { className: css.retryError, role: "alert", children: [_jsx("span", { children: error }), retryRequest !== undefined && _jsx("button", { type: "button", className: css.textButton, disabled: creating, onClick: () => { setFormOpen(true); }, children: t('retry') })] }))] }));
|
|
130
184
|
}
|
|
131
185
|
/**
|
|
132
186
|
* One sidebar Agent row: the select button opens the Member's own Session
|
|
133
187
|
* conversation page, the avatar carries identity plus the presence badge, and
|
|
134
188
|
* the row menu opens the editor.
|
|
135
189
|
*/
|
|
136
|
-
function AgentRow({ status, current, updateMember, recoverMember,
|
|
190
|
+
function AgentRow({ status, current, updateMember, recoverMember, archiveMember, loadModels, openMemberSession, onUpdated, t }) {
|
|
137
191
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
138
192
|
const [editing, setEditing] = useState(false);
|
|
139
|
-
const [clearing, setClearing] = useState(false);
|
|
140
193
|
const [archiving, setArchiving] = useState(false);
|
|
141
194
|
const [rowAlert, setRowAlert] = useState();
|
|
142
195
|
// Both row actions ride the same runtime remote: the Host steers a live
|
|
@@ -167,35 +220,6 @@ function AgentRow({ status, current, updateMember, recoverMember, clearMemberCon
|
|
|
167
220
|
setRowAlert(t('restartFailed', { message: cause instanceof Error ? cause.message : String(cause) }));
|
|
168
221
|
}
|
|
169
222
|
};
|
|
170
|
-
const clearContext = async () => {
|
|
171
|
-
try {
|
|
172
|
-
const result = await clearMemberContext({
|
|
173
|
-
requestId: mintRequestId(),
|
|
174
|
-
workspaceId: status.member.workspaceId,
|
|
175
|
-
memberId: status.member.memberId,
|
|
176
|
-
});
|
|
177
|
-
await onUpdated();
|
|
178
|
-
if (!result.ok) {
|
|
179
|
-
setRowAlert(t('clearContextFailed', { message: result.error.message }));
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
setRowAlert(undefined);
|
|
183
|
-
// The Host moved the Member onto a fresh Session id (the previous log
|
|
184
|
-
// stays archived on disk). A new id has no resident client instance, so
|
|
185
|
-
// re-entering the member view lazily instantiates it from host truth:
|
|
186
|
-
// blank hero, live updates, and no disposed-generation gray-out.
|
|
187
|
-
if (current === true)
|
|
188
|
-
openMemberSession(result.value.status.member.sessionId);
|
|
189
|
-
}
|
|
190
|
-
catch (cause) {
|
|
191
|
-
setRowAlert(t('clearContextFailed', { message: cause instanceof Error ? cause.message : String(cause) }));
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
// Error Members keep a live idle handle, so starting from a new context
|
|
195
|
-
// is available to them too — it doubles as a recovery path (the broken
|
|
196
|
-
// handle's error markers are dropped with it). Only a running turn or a
|
|
197
|
-
// missing handle gates the entry.
|
|
198
|
-
const contextClearable = status.presence === 'available' || status.presence === 'error';
|
|
199
223
|
const archive = async () => {
|
|
200
224
|
try {
|
|
201
225
|
const result = await archiveMember({
|
|
@@ -215,17 +239,13 @@ function AgentRow({ status, current, updateMember, recoverMember, clearMemberCon
|
|
|
215
239
|
{ id: 'edit', label: t('editAgent'), icon: _jsx(IconEditOutline16, {}) },
|
|
216
240
|
...(status.presence === 'error' ? [{ id: 'resume', label: t('resumeAgent'), icon: _jsx(IconPlayOutline16, {}) }] : []),
|
|
217
241
|
...(status.availability === 'unavailable' ? [{ id: 'restart', label: t('restartAgent'), icon: _jsx(IconRefreshOutline16, {}) }] : []),
|
|
218
|
-
{ id: 'clear-context', label: t('clearContextAgent'), icon: _jsx(IconNewChatOutline16, {}), danger: true, disabled: !contextClearable },
|
|
219
|
-
...(!contextClearable ? [{ type: 'label', id: 'clear-context-reason', text: status.presence === 'working' ? t('clearContextWorkingReason') : t('clearContextUnavailableReason') }] : []),
|
|
220
242
|
{ id: 'archive', label: t('archiveAgent'), icon: _jsx(IconArchiveOutline20, { size: 16 }), danger: true },
|
|
221
243
|
], onSelect: (id) => {
|
|
222
244
|
if (id === 'edit')
|
|
223
245
|
setEditing(true);
|
|
224
|
-
else if (id === 'clear-context')
|
|
225
|
-
setClearing(true);
|
|
226
246
|
else if (id === 'archive')
|
|
227
247
|
setArchiving(true);
|
|
228
248
|
else
|
|
229
249
|
void recover();
|
|
230
|
-
}, onOpenChange: setMenuOpen }) })] }), rowAlert !== undefined && _jsx("div", { className: css.rowAlert, role: "alert", children: rowAlert }),
|
|
250
|
+
}, onOpenChange: setMenuOpen }) })] }), rowAlert !== undefined && _jsx("div", { className: css.rowAlert, role: "alert", children: rowAlert }), archiving && (_jsx(Modal, { open: true, onClose: () => { setArchiving(false); }, title: t('archiveAgentTitle', { name: status.member.handle }), closeLabel: t('close'), contentClassName: createCss.dialogContent, footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: () => { setArchiving(false); }, children: t('cancel') }), _jsx(Button, { variant: "primary", onClick: () => { setArchiving(false); void archive(); }, children: t('archiveAgentConfirm') })] }), children: _jsx("p", { className: createCss.error, children: t('archiveAgentNotice', { name: status.member.handle }) }) })), editing && (_jsx(AgentEditorDialog, { status: status, updateMember: updateMember, loadModels: loadModels, onCommitted: onUpdated, onClose: () => { setEditing(false); }, t: t }))] }));
|
|
231
251
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { MarkdownText,
|
|
3
|
+
import { MarkdownText, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { cachedAttachmentDataUrl, formatByteSize, loadAttachmentDataUrl } from "./attachment-preview.js";
|
|
5
5
|
import { cachedResolvedTaskRef, resolveUnknownTaskRefs, useResolvedTaskRefVersion } from "./task-refs.js";
|
|
6
6
|
import { formatMessageTime, isSingleBrandedRef, memberHue, planMessageBody, shouldClampMessage, splitBrandedRefs, splitMentionNames } from "./team-formatters.js";
|
|
@@ -90,7 +90,7 @@ export function TeamMessage({ senderName, memberId, human, body, occurredAt, men
|
|
|
90
90
|
? _jsx("span", { className: css.mention, children: segment.text }, index)
|
|
91
91
|
: _jsx(Fragment, { children: renderRefs(segment.text, onOpenRef, taskLabel, refLabel) }, index)) })
|
|
92
92
|
: plan.render === 'literal'
|
|
93
|
-
? _jsx("div", { className: css.messageText, children: onOpenRef === undefined ?
|
|
93
|
+
? _jsx("div", { className: css.messageText, children: onOpenRef === undefined ? displayBody : renderRefs(displayBody, onOpenRef, taskLabel, refLabel) })
|
|
94
94
|
: _jsx("div", { ref: markdownRef, className: css.messageMarkdown, children: _jsx(MarkdownText, { text: displayBody, labels: markdownLabels }, `${displayBody}:${onOpenRef === undefined ? 'literal' : 'refs'}`) });
|
|
95
95
|
return (_jsxs("article", { className: css.messageRow, "data-human": human || undefined, "data-grouped": grouped || undefined, children: [_jsx("div", { className: css.messageIdentity, style: avatarStyle, "aria-hidden": "true", children: senderName.replace('@', '').slice(0, 1).toUpperCase() }), _jsxs("div", { className: css.messageBody, children: [(!grouped || showGroupedTime === true) && (_jsxs("div", { className: css.nameRow, children: [!grouped && _jsx("strong", { ...(senderTitle === undefined ? {} : { title: senderTitle }), children: senderName }), occurredAt !== undefined && _jsx("span", { className: css.messageTime, children: formatMessageTime(occurredAt) })] })), clampable ? _jsx("div", { className: clamped ? css.messageClamp : undefined, children: bodyNode }) : bodyNode, clampable && (_jsx("button", { type: "button", className: css.messageExpand, "data-message-expand": "true", "aria-expanded": expanded, onClick: () => { setExpanded(value => !value); }, children: expanded ? (t?.('collapseMessage') ?? 'Show less') : (t?.('expandMessage') ?? 'Show more') })), (plan.fallbackNames.length > 0 || plan.fallbackRefs.length > 0) && (_jsxs("div", { className: css.mentionsRow, children: [plan.fallbackNames.map(name => _jsxs("span", { className: css.mention, children: ["@", name] }, name)), plan.fallbackRefs.map(ref => {
|
|
96
96
|
const resolved = cachedResolvedTaskRef(ref);
|
|
@@ -18,7 +18,7 @@ function factKey(fact) {
|
|
|
18
18
|
return fact.kind === 'message' ? `message:${fact.message.messageRef}` : `activity:${fact.activity.activityRef}`;
|
|
19
19
|
}
|
|
20
20
|
function messageFact(message, mentions = []) {
|
|
21
|
-
return { kind: 'message', sequence: message.sequence, message, mentions };
|
|
21
|
+
return { kind: 'message', sequence: message.sequence, message, mentions, occurredAt: message.occurredAt };
|
|
22
22
|
}
|
|
23
23
|
function mergeFacts(...groups) {
|
|
24
24
|
const byKey = new Map();
|
|
@@ -480,7 +480,7 @@ export function TeamThreadPage(props) {
|
|
|
480
480
|
setProjection(current => current === undefined ? current
|
|
481
481
|
: { ...current, task: committed.task, thread: committed.thread });
|
|
482
482
|
setCurrentFacts(current => {
|
|
483
|
-
const merged = mergeFacts(current, [{ kind: 'activity', sequence: committed.activity.sequence, activity: committed.activity }]);
|
|
483
|
+
const merged = mergeFacts(current, [{ kind: 'activity', sequence: committed.activity.sequence, activity: committed.activity, occurredAt: committed.receipt.occurredAt }]);
|
|
484
484
|
currentFactsRef.current = merged;
|
|
485
485
|
return merged;
|
|
486
486
|
});
|
|
@@ -527,7 +527,7 @@ export function TeamThreadPage(props) {
|
|
|
527
527
|
const committed = result.value;
|
|
528
528
|
setProjection(current => current === undefined ? current : { ...current, task: committed.task, thread: committed.thread, claims: committed.claims });
|
|
529
529
|
setCurrentFacts(current => {
|
|
530
|
-
const merged = mergeFacts(current, [{ kind: 'activity', sequence: committed.activity.sequence, activity: committed.activity }]);
|
|
530
|
+
const merged = mergeFacts(current, [{ kind: 'activity', sequence: committed.activity.sequence, activity: committed.activity, occurredAt: committed.receipt.occurredAt }]);
|
|
531
531
|
currentFactsRef.current = merged;
|
|
532
532
|
return merged;
|
|
533
533
|
});
|
|
@@ -586,7 +586,7 @@ export function TeamThreadPage(props) {
|
|
|
586
586
|
if (result.value.kind === 'committed') {
|
|
587
587
|
const committed = result.value;
|
|
588
588
|
setCurrentFacts(current => {
|
|
589
|
-
const merged = mergeFacts(current, [{ kind: 'message', sequence: committed.message.sequence, message: committed.message, mentions: [...recipients].sort() }]);
|
|
589
|
+
const merged = mergeFacts(current, [{ kind: 'message', sequence: committed.message.sequence, message: committed.message, mentions: [...recipients].sort(), occurredAt: committed.receipt.occurredAt }]);
|
|
590
590
|
currentFactsRef.current = merged;
|
|
591
591
|
return merged;
|
|
592
592
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { TeamSidebarProps } from './slots.ts';
|
|
2
|
-
export declare function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember,
|
|
2
|
+
export declare function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember, archiveMember, joinChannel, removeChannelMember, loadModels, openMemberSession }: TeamSidebarProps): import("react").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=TeamWorkspaceBrowser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamWorkspaceBrowser.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceBrowser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAUlD,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"TeamWorkspaceBrowser.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceBrowser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAUlD,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,+BA8D9V"}
|
|
@@ -7,7 +7,7 @@ import { useSidebarSectionOpen, setSidebarSectionOpen } from "./sidebar-sections
|
|
|
7
7
|
import { TeamAgentsPanel } from "./TeamAgentsPanel.js";
|
|
8
8
|
import { TeamChannelsPanel } from "./TeamChannelsPanel.js";
|
|
9
9
|
import css from './sidebar.module.css';
|
|
10
|
-
export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember,
|
|
10
|
+
export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, t, useWorkspaces, loadMembers, subscribeChanges, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember, archiveMember, joinChannel, removeChannelMember, loadModels, openMemberSession }) {
|
|
11
11
|
const navigationState = useSyncExternalStore(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
|
|
12
12
|
const workspaces = useWorkspaces(state => state.items);
|
|
13
13
|
const selected = navigationState.workspaceId;
|
|
@@ -39,5 +39,5 @@ export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWo
|
|
|
39
39
|
if (!wide) {
|
|
40
40
|
return _jsxs("nav", { className: css.railWorkspace, "aria-label": t('workspaceSections'), children: [_jsx(Tooltip, { label: t('channels'), side: "right", children: _jsx("button", { type: "button", className: css.railButton, "aria-label": t('channels'), onClick: () => { setPendingSection('channels'); expandSidebar(); }, children: _jsx(IconListPenOutline16, { size: 16 }) }) }), _jsx(Tooltip, { label: t('agents'), side: "right", children: _jsx("button", { type: "button", className: css.railButton, "aria-label": t('agents'), onClick: () => { setPendingSection('agents'); expandSidebar(); }, children: _jsx(IconAgentPresetOutline16, { size: 16 }) }) })] });
|
|
41
41
|
}
|
|
42
|
-
return _jsxs("section", { className: css.workspaceBrowser, "aria-label": t('workspaces'), children: [_jsx(TeamSidebarSection, { title: t('workspaces'), open: workspacesOpen, onToggle: open => { setSidebarSectionOpen(undefined, 'workspaces', open); }, children: _jsxs("div", { className: css.workspaceList, children: [workspaces.map(workspace => _jsx(TeamWorkspaceRow, { workspaceId: workspace.workspaceId, title: workspace.title, path: workspace.path, selected: workspace.workspaceId === selectedId, current: workspace.workspaceId === selectedId && overviewIsCurrent, onSelect: selectWorkspace }, workspace.workspaceId)), workspaces.length === 0 && _jsx("p", { className: css.emptyState, children: t('empty') })] }) }), selectedId !== undefined && _jsxs("div", { className: css.workspaceSection, children: [_jsx("div", { ref: channelsRef, children: _jsx(TeamChannelsPanel, { workspaceId: selectedId, loadMembers: loadMembers, loadChannels: loadChannels, subscribeChanges: subscribeChanges, createChannel: createChannel, updateChannel: updateChannel, archiveChannel: archiveChannel, joinChannel: joinChannel, removeChannelMember: removeChannelMember, creatingAgents: creatingAgents.filter(request => request.workspaceId === selectedId), ...(navigationState.memberSessionId !== undefined || navigationState.channelRef === undefined ? {} : { selectedChannelRef: navigationState.channelRef }), selectChannel: selectChannel, t: t }, selectedId) }), _jsx("div", { ref: agentsRef, children: _jsx(TeamAgentsPanel, { workspaceId: selectedId, loadMembers: loadMembers, subscribeChanges: subscribeChanges, addMember: addMember, updateMember: updateMember, recoverMember: recoverMember,
|
|
42
|
+
return _jsxs("section", { className: css.workspaceBrowser, "aria-label": t('workspaces'), children: [_jsx(TeamSidebarSection, { title: t('workspaces'), open: workspacesOpen, onToggle: open => { setSidebarSectionOpen(undefined, 'workspaces', open); }, children: _jsxs("div", { className: css.workspaceList, children: [workspaces.map(workspace => _jsx(TeamWorkspaceRow, { workspaceId: workspace.workspaceId, title: workspace.title, path: workspace.path, selected: workspace.workspaceId === selectedId, current: workspace.workspaceId === selectedId && overviewIsCurrent, onSelect: selectWorkspace }, workspace.workspaceId)), workspaces.length === 0 && _jsx("p", { className: css.emptyState, children: t('empty') })] }) }), selectedId !== undefined && _jsxs("div", { className: css.workspaceSection, children: [_jsx("div", { ref: channelsRef, children: _jsx(TeamChannelsPanel, { workspaceId: selectedId, loadMembers: loadMembers, loadChannels: loadChannels, subscribeChanges: subscribeChanges, createChannel: createChannel, updateChannel: updateChannel, archiveChannel: archiveChannel, joinChannel: joinChannel, removeChannelMember: removeChannelMember, creatingAgents: creatingAgents.filter(request => request.workspaceId === selectedId), ...(navigationState.memberSessionId !== undefined || navigationState.channelRef === undefined ? {} : { selectedChannelRef: navigationState.channelRef }), selectChannel: selectChannel, t: t }, selectedId) }), _jsx("div", { ref: agentsRef, children: _jsx(TeamAgentsPanel, { workspaceId: selectedId, loadMembers: loadMembers, subscribeChanges: subscribeChanges, addMember: addMember, updateMember: updateMember, recoverMember: recoverMember, archiveMember: archiveMember, loadModels: loadModels, ...(navigationState.memberSessionId === undefined ? {} : { memberSessionId: navigationState.memberSessionId }), openMemberSession: openMemberSession, onCreatingChange: (request, creating) => { setCreatingAgents(current => creating ? [...current.filter(item => item.requestId !== request.requestId), request] : current.filter(item => item.requestId !== request.requestId)); }, t: t }, selectedId) })] })] });
|
|
43
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAoCnE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAK5C,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAEnD,YAAY,EAAE,QAAQ,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC9F,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAIhD,eAAO,MAAM,MAAM,UAElB,CAAA;AAED,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,IAAI,EAAE,OAAO,CAAA;KACd;CACF;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,cAAc,EAAE,cAAc,CAAA;QAC9B,UAAU,EAAE,cAAc,CAAA;KAC3B;CACF;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAoCnE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAK5C,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAEnD,YAAY,EAAE,QAAQ,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC9F,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAIhD,eAAO,MAAM,MAAM,UAElB,CAAA;AAED,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,IAAI,EAAE,OAAO,CAAA;KACd;CACF;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,cAAc,EAAE,cAAc,CAAA;QAC9B,UAAU,EAAE,cAAc,CAAA;KAC3B;CACF;AAmLD,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7D"}
|
|
@@ -12,7 +12,11 @@ const NS = 'team';
|
|
|
12
12
|
export const inject = [
|
|
13
13
|
'slots', 'workspaces', 'locale', 'remote', 'remote.session', 'sessions', 'connection', 'conversation',
|
|
14
14
|
];
|
|
15
|
-
function registerModeShadow(ctx, navigation, changes, drafts, name, component, extraInject
|
|
15
|
+
function registerModeShadow(ctx, navigation, changes, drafts, name, component, extraInject,
|
|
16
|
+
// Keyed seats (`main`) address one panel by key; the reserved 'conversation'
|
|
17
|
+
// key is where the shipped Conversation registers, so the Team seat shadows
|
|
18
|
+
// that same panel instead of adding a second one.
|
|
19
|
+
entryKey) {
|
|
16
20
|
// Stay in Team mode: the conversation shadow stands down for Member Session
|
|
17
21
|
// views (see registerModeShadow), so the shipped conversation root renders
|
|
18
22
|
// the selected Member Session inside the Team shell.
|
|
@@ -48,13 +52,14 @@ function registerModeShadow(ctx, navigation, changes, drafts, name, component, e
|
|
|
48
52
|
let dispose;
|
|
49
53
|
const reconcile = () => {
|
|
50
54
|
const snapshot = navigation.getSnapshot();
|
|
51
|
-
// The
|
|
55
|
+
// The main panel seat yields to the shipped conversation root while a
|
|
52
56
|
// Member Session view is embedded; both sidebar seats stay shadowed so
|
|
53
57
|
// the Team chrome keeps working around the Member conversation.
|
|
54
|
-
const active = snapshot.mode === 'team' && !(name === '
|
|
58
|
+
const active = snapshot.mode === 'team' && !(name === 'main' && snapshot.memberSessionId !== undefined);
|
|
55
59
|
if (active && dispose === undefined) {
|
|
56
60
|
dispose = ctx.slots.register({
|
|
57
61
|
name,
|
|
62
|
+
...(entryKey === undefined ? {} : { key: entryKey }),
|
|
58
63
|
priority: -100,
|
|
59
64
|
locale: NS,
|
|
60
65
|
inject: () => ({
|
|
@@ -62,7 +67,7 @@ function registerModeShadow(ctx, navigation, changes, drafts, name, component, e
|
|
|
62
67
|
...extraInject?.(),
|
|
63
68
|
...navigation.actions(),
|
|
64
69
|
...sharedRemotes,
|
|
65
|
-
...(name === '
|
|
70
|
+
...(name === 'main' ? {
|
|
66
71
|
readThread: (request) => ctx.remote.agentTeam.readThread(request),
|
|
67
72
|
loadThreadHistory: (request) => ctx.remote.agentTeam.threadHistory(request),
|
|
68
73
|
threadObservations: (request) => ctx.remote.agentTeam.threadObservations(request),
|
|
@@ -107,6 +112,36 @@ function applyUi(ctx) {
|
|
|
107
112
|
void disposeNavigation();
|
|
108
113
|
void disposeDrafts();
|
|
109
114
|
}, 'agent-team: navigation service');
|
|
115
|
+
// The one restore owner: leaving an embedded Member Session view must
|
|
116
|
+
// rebind the underlying current session, or the stale Member current later
|
|
117
|
+
// masks to undefined when the Host disposes that session (rollover) and
|
|
118
|
+
// the conversation seat remounts. Takeover is conditional — only when the
|
|
119
|
+
// current still IS the departed Member session — so a selection someone
|
|
120
|
+
// else made in the meantime survives. A dead return target clears instead
|
|
121
|
+
// of opening an unknown id.
|
|
122
|
+
ctx.effect(() => {
|
|
123
|
+
let previous = navigation.getSnapshot();
|
|
124
|
+
const restore = () => {
|
|
125
|
+
const snapshot = navigation.getSnapshot();
|
|
126
|
+
const departed = previous.memberSessionId;
|
|
127
|
+
const returnTo = previous.returnToSessionId;
|
|
128
|
+
previous = snapshot;
|
|
129
|
+
if (departed === undefined || snapshot.memberSessionId !== undefined)
|
|
130
|
+
return;
|
|
131
|
+
const sessions = ctx.sessions;
|
|
132
|
+
if (sessions.list.getSnapshot().current !== departed)
|
|
133
|
+
return;
|
|
134
|
+
if (returnTo !== undefined && sessions.list.getSnapshot().byId[returnTo] !== undefined)
|
|
135
|
+
sessions.open(returnTo);
|
|
136
|
+
else
|
|
137
|
+
sessions.clear();
|
|
138
|
+
};
|
|
139
|
+
const unsubscribe = navigation.subscribe(restore);
|
|
140
|
+
return () => {
|
|
141
|
+
unsubscribe();
|
|
142
|
+
restore();
|
|
143
|
+
};
|
|
144
|
+
}, 'agent-team: member session restore');
|
|
110
145
|
const changes = new TeamChangeStream((request, signal) => ctx.remote.agentTeam.changes(request, signal));
|
|
111
146
|
const loadMemberGroups = async () => {
|
|
112
147
|
const workspaces = ctx.workspaces.list.getSnapshot().items;
|
|
@@ -129,26 +164,19 @@ function applyUi(ctx) {
|
|
|
129
164
|
inject: () => ({
|
|
130
165
|
navigation,
|
|
131
166
|
...navigation.actions(),
|
|
132
|
-
// The footer is the only surface that leaves Team mode;
|
|
133
|
-
//
|
|
134
|
-
//
|
|
167
|
+
// The footer is the only surface that leaves Team mode; closing the
|
|
168
|
+
// embedded Member Session view rebinds the underlying current through
|
|
169
|
+
// the same root-scope restore owner, so there is exactly one restore
|
|
170
|
+
// path and no double open.
|
|
135
171
|
leaveTeam: () => {
|
|
136
|
-
const snapshot = navigation.getSnapshot();
|
|
137
|
-
if (snapshot.memberSessionId === undefined) {
|
|
138
|
-
navigation.actions().leaveTeam();
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
const returnTo = snapshot.returnToSessionId;
|
|
142
172
|
navigation.actions().exitMemberSession();
|
|
143
|
-
if (returnTo !== undefined)
|
|
144
|
-
ctx.sessions.open(returnTo);
|
|
145
173
|
navigation.actions().leaveTeam();
|
|
146
174
|
},
|
|
147
175
|
loadMemberGroups,
|
|
148
176
|
}),
|
|
149
177
|
}, TeamFooterAction));
|
|
150
178
|
registerModeShadow(ctx, navigation, changes, drafts, 'sidebar.workspaces', TeamWorkspaceBrowser);
|
|
151
|
-
registerModeShadow(ctx, navigation, changes, drafts, '
|
|
179
|
+
registerModeShadow(ctx, navigation, changes, drafts, 'main', TeamConversation, undefined, 'conversation');
|
|
152
180
|
registerModeShadow(ctx, navigation, changes, drafts, 'sidebar.settings', TeamSettings, () => ({ loadMemberGroups }));
|
|
153
181
|
}
|
|
154
182
|
export async function apply(ctx) {
|
|
@@ -41,13 +41,6 @@ export declare const zh: {
|
|
|
41
41
|
readonly restartAgent: "重启";
|
|
42
42
|
readonly restartStillUnavailable: "重启已执行,成员仍不可用:{diagnostic}";
|
|
43
43
|
readonly restartFailed: "重启执行失败:{message}";
|
|
44
|
-
readonly clearContextAgent: "从全新上下文开始";
|
|
45
|
-
readonly clearContextWorkingReason: "成员正在工作中,完成后才能清空上下文";
|
|
46
|
-
readonly clearContextUnavailableReason: "成员当前不可用,恢复在线且空闲后才能清空上下文";
|
|
47
|
-
readonly clearContextTitle: "从全新上下文开始:{name}";
|
|
48
|
-
readonly clearContextNotice: "将结束 {name} 当前的会话上下文并从空白开始:旧对话会归档保留在会话记录中。{name} 的身份、私有记忆与 notes、频道和会话绑定都保持不变,后续协作从新上下文继续累积。";
|
|
49
|
-
readonly clearContextConfirm: "开始全新上下文";
|
|
50
|
-
readonly clearContextFailed: "清空上下文失败:{message}";
|
|
51
44
|
readonly archiveAgent: "归档";
|
|
52
45
|
readonly archiveAgentTitle: "归档 Agent:{name}";
|
|
53
46
|
readonly archiveAgentNotice: "将把 {name} 从所有列表收起:会话与私有记忆保留在磁盘上、活跃 Claim 会释放,但暂无恢复入口。";
|
|
@@ -196,13 +189,6 @@ export declare const en: {
|
|
|
196
189
|
readonly restartAgent: "Restart";
|
|
197
190
|
readonly restartStillUnavailable: "Restart ran, but the Member is still unavailable: {diagnostic}";
|
|
198
191
|
readonly restartFailed: "Restart failed: {message}";
|
|
199
|
-
readonly clearContextAgent: "Start from new context";
|
|
200
|
-
readonly clearContextWorkingReason: "The Member is working; clear once the current turn ends";
|
|
201
|
-
readonly clearContextUnavailableReason: "The Member is unavailable; only an idle available Member can start from a new context";
|
|
202
|
-
readonly clearContextTitle: "Start from new context: {name}";
|
|
203
|
-
readonly clearContextNotice: "This ends {name}'s current session context and starts blank: the previous conversation is archived and stays in the session history. {name}'s identity, private memory and notes, channel and session bindings are untouched, and future collaboration accumulates from the new context.";
|
|
204
|
-
readonly clearContextConfirm: "Start from new context";
|
|
205
|
-
readonly clearContextFailed: "Failed to clear context: {message}";
|
|
206
192
|
readonly archiveAgent: "Archive";
|
|
207
193
|
readonly archiveAgentTitle: "Archive Agent: {name}";
|
|
208
194
|
readonly archiveAgentNotice: "This hides {name} from every list: the session log and private memory stay on disk and active Claims release, but there is no restore entry point yet.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmJL,CAAA;AAEV,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmJL,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,CAAA"}
|
|
@@ -41,13 +41,6 @@ export const zh = {
|
|
|
41
41
|
restartAgent: '重启',
|
|
42
42
|
restartStillUnavailable: '重启已执行,成员仍不可用:{diagnostic}',
|
|
43
43
|
restartFailed: '重启执行失败:{message}',
|
|
44
|
-
clearContextAgent: '从全新上下文开始',
|
|
45
|
-
clearContextWorkingReason: '成员正在工作中,完成后才能清空上下文',
|
|
46
|
-
clearContextUnavailableReason: '成员当前不可用,恢复在线且空闲后才能清空上下文',
|
|
47
|
-
clearContextTitle: '从全新上下文开始:{name}',
|
|
48
|
-
clearContextNotice: '将结束 {name} 当前的会话上下文并从空白开始:旧对话会归档保留在会话记录中。{name} 的身份、私有记忆与 notes、频道和会话绑定都保持不变,后续协作从新上下文继续累积。',
|
|
49
|
-
clearContextConfirm: '开始全新上下文',
|
|
50
|
-
clearContextFailed: '清空上下文失败:{message}',
|
|
51
44
|
archiveAgent: '归档',
|
|
52
45
|
archiveAgentTitle: '归档 Agent:{name}',
|
|
53
46
|
archiveAgentNotice: '将把 {name} 从所有列表收起:会话与私有记忆保留在磁盘上、活跃 Claim 会释放,但暂无恢复入口。',
|
|
@@ -196,13 +189,6 @@ export const en = {
|
|
|
196
189
|
restartAgent: 'Restart',
|
|
197
190
|
restartStillUnavailable: 'Restart ran, but the Member is still unavailable: {diagnostic}',
|
|
198
191
|
restartFailed: 'Restart failed: {message}',
|
|
199
|
-
clearContextAgent: 'Start from new context',
|
|
200
|
-
clearContextWorkingReason: 'The Member is working; clear once the current turn ends',
|
|
201
|
-
clearContextUnavailableReason: 'The Member is unavailable; only an idle available Member can start from a new context',
|
|
202
|
-
clearContextTitle: 'Start from new context: {name}',
|
|
203
|
-
clearContextNotice: 'This ends {name}\'s current session context and starts blank: the previous conversation is archived and stays in the session history. {name}\'s identity, private memory and notes, channel and session bindings are untouched, and future collaboration accumulates from the new context.',
|
|
204
|
-
clearContextConfirm: 'Start from new context',
|
|
205
|
-
clearContextFailed: 'Failed to clear context: {message}',
|
|
206
192
|
archiveAgent: 'Archive',
|
|
207
193
|
archiveAgentTitle: 'Archive Agent: {name}',
|
|
208
194
|
archiveAgentNotice: 'This hides {name} from every list: the session log and private memory stay on disk and active Claims release, but there is no restore entry point yet.',
|
|
@@ -50,6 +50,11 @@ export type TeamSidebarProps = PropsRuntime<'sidebar.workspaces'> & PropsLocale<
|
|
|
50
50
|
archiveChannel: (request: AgentTeamArchiveChannelRequest) => Promise<RemoteResult<AgentTeamArchiveChannelResult>>;
|
|
51
51
|
updateMember: (request: AgentTeamUpdateMemberRequest) => Promise<RemoteResult<AgentTeamMemberResult>>;
|
|
52
52
|
recoverMember: (request: AgentTeamRecoverMemberRequest) => Promise<RemoteResult<AgentTeamRecoverMemberResult>>;
|
|
53
|
+
/**
|
|
54
|
+
* Host clear-context remote kept as a hidden migration escape hatch.
|
|
55
|
+
* The visible row action is retired: Members manage their own context
|
|
56
|
+
* through the context_rollover tool (see docs/architecture.md).
|
|
57
|
+
*/
|
|
53
58
|
clearMemberContext: (request: AgentTeamClearMemberContextRequest) => Promise<RemoteResult<AgentTeamClearMemberContextResult>>;
|
|
54
59
|
archiveMember: (request: AgentTeamArchiveMemberRequest) => Promise<RemoteResult<AgentTeamArchiveMemberResult>>;
|
|
55
60
|
joinChannel: (request: AgentTeamJoinChannelRequest) => Promise<RemoteResult<AgentTeamJoinChannelResult>>;
|
|
@@ -60,7 +65,7 @@ export type TeamSidebarProps = PropsRuntime<'sidebar.workspaces'> & PropsLocale<
|
|
|
60
65
|
openMemberSession: (sessionId: AgentTeamClientMemberStatus['member']['sessionId']) => void;
|
|
61
66
|
selectedChannelRef?: AgentTeamChannelRef;
|
|
62
67
|
};
|
|
63
|
-
export type TeamConversationProps = PropsRuntime<'
|
|
68
|
+
export type TeamConversationProps = PropsRuntime<'main'> & PropsLocale<'team'> & TeamNavigationActions & {
|
|
64
69
|
navigation: TeamNavigationSource;
|
|
65
70
|
/** Keyed composer draft cache; one store per Client context. */
|
|
66
71
|
drafts: TeamDraftStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../../src/client/slots.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../../src/client/slots.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,15 +6,20 @@ Model-facing tools for Agent Team Members. The package registers tools in the ca
|
|
|
6
6
|
|
|
7
7
|
## Tools
|
|
8
8
|
|
|
9
|
-
- `team_inbox` lists bounded unread Thread summaries for the calling Member, ordered by direct work and then recency; Task
|
|
10
|
-
- `team_thread` reads a Thread, pages history, follows, or unfollows. `threadRef` is primary; a `taskRef` is a Host alias only for released task-only Clients. `
|
|
11
|
-
- `team_message` starts a top-level Thread
|
|
12
|
-
- `team_claim` lists or mutates the calling Member's Direction Claims through `list`, `claim`, `done`, and `release`; it applies only to real Tasks. Direction exclusion uses Unicode NFKC normalization, trim, whitespace compression, and deterministic case folding.
|
|
13
|
-
- `team_view`
|
|
9
|
+
- `team_inbox` lists bounded unread Thread summaries for the calling Member, ordered by direct work and then recency; Task standing appears only where the Thread has a real Task overlay. The header states total unread/direct counts and the number of Threads shown (with a truncation conclusion when unread work lies beyond the bounded list); each item shows its exact unread/direct counts, Channel ref, and Task standing. The footer routes reading to `team_thread read`; the render carries no revision and no write token.
|
|
10
|
+
- `team_thread` reads a Thread, pages history, follows, or unfollows. `threadRef` is primary; a `taskRef` is a Host alias only for released task-only Clients. The five actions render separately: `status`/`follow`/`unfollow` answer only the Attention question in one line; `read` renders outcome, Thread identity, orientation (full anchor when Host-supplied background is present, bounded anchor subject otherwise, never a duplicate of an in-facts anchor), active Claims only, the chronological facts with inline unread/direct markers, and a read-through/remaining-unread footer; `history` renders a historical page with the full anchor on a first page and the bounded subject on continuation pages, never current Claims or advice. `read` advances the durable watermark and is the only read-side source of a next-write token — rendered only when no unread remains; your own committed public mutations hand off a fresh token as well. Activity facts render structured — actor, Task ref, and the Claim refs each activity claimed, completed, accepted, or released. A read that acknowledges an unread acceptance of a still-done Task carries one `contextAdvice` block (usage, route budgets, the `min(128_000, handoffAt)` Task-boundary threshold, and one keep/rollover/handoff-now action); it is advisory only and degrades to an explicit `unavailable` line when measurement fails.
|
|
11
|
+
- `team_message` starts a top-level Thread, replies to an existing Thread, or sends a DM. It defaults to a taskless Thread; pass `asTask: true` for atomic Task creation. A committed start/reply renders one committed-verb outcome (Thread created / reply added) with the Message, Thread, and optional Task refs, and exactly one next-write token hand-off. Replies reject unread work before checking token freshness. Typed rejections begin `Not committed`, keep the structured refs and counts needed to reread and retry, and render no numeric revision or write token — recovery is read-and-reconsider. DMs distinguish `Delivered` from `Recorded, not delivered` (with the delivery note and a no-blind-duplicate warning).
|
|
12
|
+
- `team_claim` lists or mutates the calling Member's Direction Claims through `list`, `claim`, `done`, and `release`; it applies only to real Tasks. `list` renders the Task/Thread identity with active Claims only (the collision surface) and no write token. A committed mutation names its action (Claim created/completed/released), renders the authoritative affected Claim first, and hands off one next-write token. Rejections share the message rejection form. Direction exclusion uses Unicode NFKC normalization, trim, whitespace compression, and deterministic case folding.
|
|
13
|
+
- `team_view` is the address book: bounded, membership-authorized Channel, top-level Thread, and Member summaries — current addresses, not a work queue. Threads are the sole paginated catalog: newest-first rows carrying threadRef, Channel ref, a bounded anchor subject, and Task standing inline (never a second Task index, never revision or message count). The cursor pages Thread rows only; continuation pages render Threads alone, and paging reaches every authorized top-level Thread, including taskless and off-page taskful ones.
|
|
14
|
+
- `context_rollover` schedules one rollover of the calling Member into a fresh context. The tool validates the bounded private `handoff` (plus optional `relatedFiles`, or a `checkpointRef` to return to a recorded checkpoint instead) against the Host, concludes the turn, and returns `status: 'scheduled'`; the Host performs the actual swap only after the successful tool result is durably appended. The `checkpointRef` copy is hardened on both the tool and parameter descriptions: omit it for ordinary generation changes and pressure-driven handoffs, and supply it only when citing the exact ref a `context_timeline` result listed as restorable — never a synthesized or guessed one. A `checkpointRef` that cannot succeed now — fabricated, unresolved, unattributable, nonshrinking, unmeasurable, over-budget, or blocked by multiple active Claims — rejects as a model-visible error result instead of a fake `scheduled`; the mutable guards (jobs, route limits) are revalidated at the swap seam, and a seam failure leaves the Member recoverable through a later-turn fresh rollover. `context_rollover` and `context_checkpoint` both conclude the Agent turn.
|
|
15
|
+
- `context_checkpoint` records one named checkpoint of the calling Member's current context. The durable checkpoint is the successful `tool/call`+`tool/result` pair the Session projection folds; the returned ref is deterministic from the Member Session identity plus the tool call id. It performs no lifecycle side effect in the tool body and concludes the turn: a checkpoint resolves at its containing turn's end, so the model records it as its final action of a completed unit of work.
|
|
16
|
+
- `context_timeline` returns one bounded structural view of the Member's context generations across the current Session and its archived ancestor lineage: recorded checkpoints and handoff/Team/compaction boundaries, with restorability reasons where a return cannot be proven safe. Structural only — no transcript content. A fresh `context_rollover` never requires consulting the timeline first.
|
|
14
17
|
|
|
15
18
|
An Agent cannot silently enroll an unfollowed Agent through a mention; the Host returns `member_not_following`. Human confirmation is a separate Host/Client flow. Closed Tasks reject replies, Claims, and new Attention until a Human reopens them; taskless Threads have no Claim or Task-resolution mutation path.
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
Every agent-facing render carries absolute event instants in the fixed Team coordination zone UTC+8 with an explicit offset (`2026-09-08T17:00:00+08:00`): `team_thread` fact lines and anchors stamp each fact with its committing operation's instant, `team_inbox` rows carry `newestOccurredAt`, `team_view` Thread rows carry `lastActivityAt`, notifications state `Occurred at:`, and committed mutations render `Committed at:` from the receipt. The same stored instant renders byte-identically on every reread path; only absolute timestamps are rendered, never relative text, and sequence and revision — not wall-clock time — remain the ordering authority.
|
|
21
|
+
|
|
22
|
+
Canonical results expose stable refs, optional Task status, Thread revision, Claim history, Attention, and unread facts as structured fields. The model-visible renders follow the action decision surface: the write token appears only on a fully drained `team_thread read` and a committed public mutation; browsing results (`team_view`, `team_inbox`, status/follow/unfollow, `history`, `team_claim list`) and all typed rejections render no revision and no token. Typed `unread_required` and `stale_revision` results keep the structured fields needed to reread and retry deliberately. Tool execution resolves the exact live `exec.agent`; arguments cannot select or impersonate the actor or Workspace. Write request identity derives from sessionId plus tool callId. `context_rollover` and `context_checkpoint` conclude the Agent turn (a rollover must not be followed by old-generation work, and a checkpoint resolves at its containing turn's end); every other Team tool returns to the model loop.
|
|
18
23
|
|
|
19
24
|
The complete implemented protocol is documented in [`../../docs/team-collaboration.md`](../../docs/team-collaboration.md).
|
|
20
25
|
|