@wowyuarm/dsh-agent-team 0.1.13 → 0.1.14-alpha.2
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 +1 -1
- package/README.zh.md +1 -1
- package/cordis.patch.yml +185 -2
- package/package.json +45 -49
- package/packages/agent-team/lib/context-management.js +2 -3
- package/packages/agent-team/lib/context-projection.js +7 -11
- package/packages/agent-team/lib/context-source.js +36 -17
- package/packages/agent-team/lib/index.js +26 -64
- package/packages/agent-team/lib/member-context.js +5 -3
- package/packages/agent-team/lib/member-time-context.js +5 -2
- package/packages/agent-team/lib/pressure-policy.js +5 -3
- package/packages/agent-team/lib/stored-session-reader.js +1 -2
- package/packages/agent-team/lib/typert.host.js +289 -211
- package/packages/agent-team/lib/typert.remote-client.d.ts +3 -2
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +243 -189
- package/packages/agent-team/lib/types/context-management.d.ts.map +1 -1
- package/packages/agent-team/lib/types/context-projection.d.ts.map +1 -1
- package/packages/agent-team/lib/types/context-source.d.ts +46 -13
- package/packages/agent-team/lib/types/context-source.d.ts.map +1 -1
- package/packages/agent-team/lib/types/index.d.ts +0 -8
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-context.d.ts +14 -0
- package/packages/agent-team/lib/types/member-context.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-time-context.d.ts +15 -0
- package/packages/agent-team/lib/types/member-time-context.d.ts.map +1 -1
- package/packages/agent-team/lib/types/pressure-policy.d.ts.map +1 -1
- package/packages/agent-team/lib/types/stored-session-reader.d.ts +1 -2
- package/packages/agent-team/lib/types/stored-session-reader.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/entities.d.ts +3 -3
- package/packages/client-agent-team/lib/client.js +467 -341
- package/packages/client-agent-team/lib/client.js.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +6 -6
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +4 -4
- package/packages/client-agent-team/lib/types/client/TeamComposer.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamFooterAction.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamMembersAction.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamSidebarSection.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +5 -8
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceSelector.d.ts +37 -0
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceSelector.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceSelector.js +58 -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 +37 -18
- package/packages/client-agent-team/lib/types/client/locales.d.ts +2 -0
- package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/locales.js +2 -0
- package/packages/client-agent-team/lib/types/client/multi-menu-field.js +2 -2
- package/packages/client-agent-team/lib/types/client/sidebar-sections.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/sidebar-sections.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/sidebar-sections.js +4 -3
- package/packages/agent-team/lib/preset-roster.js +0 -15
- package/packages/agent-team/lib/session-remediation.js +0 -493
- package/packages/agent-team/lib/types/preset-roster.d.ts +0 -5
- package/packages/agent-team/lib/types/preset-roster.d.ts.map +0 -1
- package/packages/agent-team/lib/types/session-remediation.d.ts +0 -172
- package/packages/agent-team/lib/types/session-remediation.d.ts.map +0 -1
- package/packages/agent-team/preset/team-member/agent.cordis.yml +0 -164
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.d.ts +0 -11
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.d.ts.map +0 -1
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceRow.js +0 -6
|
@@ -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,
|
|
3
|
+
import { Button, IconArchiveOutlineRegular, IconEditOutlineRegular, IconPlayOutlineRegular, IconPlusOutlineRegular, IconRefreshOutlineRegular, Input, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamMemberIdentity } from "./TeamMemberRow.js";
|
|
5
5
|
import { SortableRow, useSidebarRowDrag } from "./sidebar-drag.js";
|
|
6
6
|
import { moveSidebarItem, useSidebarOrder } from "./sidebar-order.js";
|
|
@@ -196,7 +196,7 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, ad
|
|
|
196
196
|
...(model === undefined ? {} : { model }),
|
|
197
197
|
});
|
|
198
198
|
};
|
|
199
|
-
return (_jsxs("div", { className: css.panel, children: [_jsxs(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') }), !importing && _jsx(Button, { type: "submit", form: "team-agent-create-form", variant: "primary", disabled: creating || handle.trim().length === 0, children: creating ? t('creatingAgent') : t('createAgent') })] }), children: [_jsx(Button, { className: createCss.modeSwitch, variant: "outline", disabled: creating, "aria-expanded": importing, onClick: () => { setImporting(value => !value); setError(undefined); }, children: importing ? t('createAgent') : t('importAgentTitle') }), formOpen && importing ? _jsx(TeamAgentImport, { workspaceId: workspaceId, loadMembers: loadMembers, joinWorkspace: joinWorkspace, onPending: setCreating, onJoined: async () => { await refresh(); setFormOpen(false); queueMicrotask(() => { triggerRef.current?.focus(); }); }, t: t }) : _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); setImporting(false); setFormOpen(true); }, children: _jsx(
|
|
199
|
+
return (_jsxs("div", { className: css.panel, children: [_jsxs(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') }), !importing && _jsx(Button, { type: "submit", form: "team-agent-create-form", variant: "primary", disabled: creating || handle.trim().length === 0, children: creating ? t('creatingAgent') : t('createAgent') })] }), children: [_jsx(Button, { className: createCss.modeSwitch, variant: "outline", disabled: creating, "aria-expanded": importing, onClick: () => { setImporting(value => !value); setError(undefined); }, children: importing ? t('createAgent') : t('importAgentTitle') }), formOpen && importing ? _jsx(TeamAgentImport, { workspaceId: workspaceId, loadMembers: loadMembers, joinWorkspace: joinWorkspace, onPending: setCreating, onJoined: async () => { await refresh(); setFormOpen(false); queueMicrotask(() => { triggerRef.current?.focus(); }); }, t: t }) : _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); setImporting(false); setFormOpen(true); }, children: _jsx(IconPlusOutlineRegular, { size: 14 }) }) })), children: [loading && members.length === 0 && _jsx("p", { className: css.emptyState, children: t('loadingAgents') }), !loading && error === undefined && 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, { workspaceId: workspaceId, leaveWorkspace: leaveWorkspace, status: status, ...(memberSessionId === undefined ? {} : { current: status.member.sessionId === memberSessionId }), updateMember: updateMember, recoverMember: recoverMember, archiveMember: archiveMember, loadModels: loadModels, openMemberSession: openMemberSession, onUpdated: 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') })] }))] }));
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
202
|
* One sidebar Agent row: the select button opens the Member's own Session
|
|
@@ -267,10 +267,10 @@ function AgentRow({ workspaceId, leaveWorkspace, status, current, updateMember,
|
|
|
267
267
|
}
|
|
268
268
|
};
|
|
269
269
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.agentRow, "data-agent-row": true, "data-menu-open": menuOpen || undefined, children: [_jsx("button", { type: "button", className: css.agentSelect, "aria-label": t('openAgentSession', { name: status.member.handle }), "aria-current": current ? 'page' : undefined, disabled: status.availability !== 'active', onClick: () => { openMemberSession(status.member.sessionId); }, children: _jsx(TeamMemberIdentity, { status: status, name: status.member.handle.replace(/^@/, ''), className: css.agentCopy, t: t }) }), _jsx("span", { className: css.rowMenu, children: _jsx(TeamRowMenu, { label: t('actionsAgent', { name: status.member.handle }), items: [
|
|
270
|
-
{ id: 'edit', label: t('editAgent'), icon: _jsx(
|
|
271
|
-
...(status.presence === 'error' ? [{ id: 'resume', label: t('resumeAgent'), icon: _jsx(
|
|
272
|
-
...(status.availability === 'unavailable' && restartOffered(status) ? [{ id: 'restart', label: t('restartAgent'), icon: _jsx(
|
|
273
|
-
{ id: 'archive', label: t(withdrawing ? 'withdrawAgent' : 'archiveAgent'), icon: _jsx(
|
|
270
|
+
{ id: 'edit', label: t('editAgent'), icon: _jsx(IconEditOutlineRegular, {}) },
|
|
271
|
+
...(status.presence === 'error' ? [{ id: 'resume', label: t('resumeAgent'), icon: _jsx(IconPlayOutlineRegular, {}) }] : []),
|
|
272
|
+
...(status.availability === 'unavailable' && restartOffered(status) ? [{ id: 'restart', label: t('restartAgent'), icon: _jsx(IconRefreshOutlineRegular, {}) }] : []),
|
|
273
|
+
{ id: 'archive', label: t(withdrawing ? 'withdrawAgent' : 'archiveAgent'), icon: _jsx(IconArchiveOutlineRegular, { size: 16 }), danger: true },
|
|
274
274
|
], onSelect: (id) => {
|
|
275
275
|
if (id === 'edit')
|
|
276
276
|
setEditing(true);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment, useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { Button,
|
|
3
|
+
import { Button, IconChevronLeftOutlineRegular, IconChevronRightOutlineRegular, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { mintRequestId, uploadComposerFiles } from "./requests.js";
|
|
5
5
|
import { TeamComposer } from "./TeamComposer.js";
|
|
6
6
|
import { TeamMemberRow } from "./TeamMemberRow.js";
|
|
@@ -346,7 +346,7 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
346
346
|
setPending(false);
|
|
347
347
|
}
|
|
348
348
|
};
|
|
349
|
-
return _jsxs("main", { className: css.surface, "data-team-channel": channelRef, children: [_jsxs("div", { className: css.surfaceHeader, children: [_jsx("div", { className: css.backRow, children: _jsx(Button, { size: "sm", icon: _jsx(
|
|
349
|
+
return _jsxs("main", { className: css.surface, "data-team-channel": channelRef, children: [_jsxs("div", { className: css.surfaceHeader, children: [_jsx("div", { className: css.backRow, children: _jsx(Button, { size: "sm", icon: _jsx(IconChevronLeftOutlineRegular, {}), onClick: backToChannels, children: t('backToChannels') }) }), _jsxs("header", { className: css.headerRow, children: [_jsxs("div", { className: css.headerCopy, children: [_jsx("h1", { children: channel === undefined ? '# …' : `# ${channel.name}` }), channel !== undefined && _jsx("p", { children: channel.description }), channel !== undefined && _jsxs("div", { className: channelCss.headerMeta, children: [_jsx("span", { children: t('memberCount', { count: channelMembers.length }) }), _jsx("span", { children: t('onlineCount', { count: onlineCount }) })] })] }), channel !== undefined && _jsx("span", { ref: manageTriggerRef, children: _jsx(Button, { size: "sm", variant: "outline", "aria-haspopup": "dialog", onClick: () => { setManagingMembers(true); }, children: t('manageMembers') }) })] })] }), _jsx(Modal, { open: managingMembers, onClose: closeMembers, title: t('channelMembers'), ...(channel === undefined ? {} : { description: `# ${channel.name} · ${t('memberCount', { count: channelMembers.length })}` }), closeLabel: t('close'), contentClassName: channelCss.modalBody, children: _jsx("div", { ref: memberListRef, className: channelCss.memberList, children: members.filter(status => status.member.state !== 'inactive' && status.member.state !== 'archived').map(status => {
|
|
350
350
|
const joined = channelMemberIds.has(status.member.memberId);
|
|
351
351
|
const rowPending = membership.pending.has(status.member.memberId);
|
|
352
352
|
// Joining needs an active Member — the Host refuses any other
|
|
@@ -413,5 +413,5 @@ function ThreadEntryRow({ item, owners, unread, t, onOpen }) {
|
|
|
413
413
|
// owner stack keeps its own accessible name — a labeled button prunes its
|
|
414
414
|
// descendants from the accessibility tree — and so the control's name says
|
|
415
415
|
// exactly what clicking it does.
|
|
416
|
-
return _jsxs("span", { className: css.entryLine, "data-thread-entry": "", children: [_jsx(ThreadStateCluster, { task: item.task, owners: owners, unread: unread, t: t }), _jsxs("button", { type: "button", className: css.entryRow, "aria-label": openLabel, ...(followUp === undefined ? {} : { title: formatAbsoluteTime(followUp) }), onClick: onOpen, children: [_jsx("span", { children: text }), _jsx("span", { className: css.entryArrow, "aria-hidden": "true", children: _jsx(
|
|
416
|
+
return _jsxs("span", { className: css.entryLine, "data-thread-entry": "", children: [_jsx(ThreadStateCluster, { task: item.task, owners: owners, unread: unread, t: t }), _jsxs("button", { type: "button", className: css.entryRow, "aria-label": openLabel, ...(followUp === undefined ? {} : { title: formatAbsoluteTime(followUp) }), onClick: onOpen, children: [_jsx("span", { children: text }), _jsx("span", { className: css.entryArrow, "aria-hidden": "true", children: _jsx(IconChevronRightOutlineRegular, { size: 12 }) })] })] });
|
|
417
417
|
}
|
|
@@ -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,
|
|
3
|
+
import { Button, IconArchiveOutlineRegular, IconEditOutlineRegular, IconPlusOutlineRegular, Input, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamPresenceDot } from "./TeamPresenceDot.js";
|
|
5
5
|
import { TeamMemberRow } from "./TeamMemberRow.js";
|
|
6
6
|
import { MultiMenuField } from "./multi-menu-field.js";
|
|
@@ -153,7 +153,7 @@ export function TeamChannelsPanel(props) {
|
|
|
153
153
|
return next;
|
|
154
154
|
});
|
|
155
155
|
setPendingCreate(undefined);
|
|
156
|
-
}, triggerEmptyLabel: t('membersPickerEmpty'), formatCount: count => t('membersPickerCount', { count }) }), error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('channels'), open: sectionOpen, onToggle: open => { setSidebarSectionOpen(workspaceId, 'channels', open); }, actions: (_jsx(Tooltip, { label: t('addChannel'), delayMs: 500, children: _jsx("button", { ref: triggerRef, type: "button", className: css.iconButton, "aria-label": t('addChannel'), onClick: () => { setError(undefined); setFormOpen(true); }, children: _jsx(
|
|
156
|
+
}, triggerEmptyLabel: t('membersPickerEmpty'), formatCount: count => t('membersPickerCount', { count }) }), error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('channels'), open: sectionOpen, onToggle: open => { setSidebarSectionOpen(workspaceId, 'channels', open); }, actions: (_jsx(Tooltip, { label: t('addChannel'), delayMs: 500, children: _jsx("button", { ref: triggerRef, type: "button", className: css.iconButton, "aria-label": t('addChannel'), onClick: () => { setError(undefined); setFormOpen(true); }, children: _jsx(IconPlusOutlineRegular, { size: 14 }) }) })), children: [loading && view === undefined && _jsx("p", { className: css.emptyState, children: t('loadingChannels') }), !loading && error === undefined && view !== undefined && view.channels.length === 0 && _jsx("p", { className: css.emptyState, children: t('emptyChannels') }), _jsx("div", { className: css.channelList, children: orderedChannels.map(channel => {
|
|
157
157
|
const joined = membership.get(channel.channelRef) ?? new Set();
|
|
158
158
|
return (_jsx(SortableRow, { drag: drag, orderKey: channel.channelRef, children: _jsx(ChannelRow, { channel: channel, members: members, joinedIds: joined, selected: selectedChannelRef === channel.channelRef, updateChannel: updateChannel, archiveChannel: props.archiveChannel, joinChannel: props.joinChannel, removeChannelMember: props.removeChannelMember, onCommitted: () => { void refresh(); }, selectChannel: selectChannel, t: t }) }, channel.channelRef));
|
|
159
159
|
}) })] }), !formOpen && error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] }));
|
|
@@ -184,8 +184,8 @@ function ChannelRow({ channel, members, joinedIds, selected, updateChannel, arch
|
|
|
184
184
|
}
|
|
185
185
|
};
|
|
186
186
|
return (_jsxs(_Fragment, { children: [_jsxs("article", { className: css.channelRow, "data-menu-open": menuOpen || undefined, "aria-current": selected ? 'page' : undefined, children: [_jsx("button", { type: "button", className: css.channelSelect, "aria-label": `# ${channel.name}`, onClick: () => { selectChannel(channel.channelRef); }, children: _jsxs("strong", { className: css.channelName, children: ["# ", channel.name] }) }), _jsx("span", { className: css.rowMenu, children: _jsx(TeamRowMenu, { label: t('actionsChannel', { name: channel.name }), items: [
|
|
187
|
-
{ id: 'edit', label: t('editChannel'), icon: _jsx(
|
|
188
|
-
{ id: 'archive', label: t('archiveChannel'), icon: _jsx(
|
|
187
|
+
{ id: 'edit', label: t('editChannel'), icon: _jsx(IconEditOutlineRegular, {}) },
|
|
188
|
+
{ id: 'archive', label: t('archiveChannel'), icon: _jsx(IconArchiveOutlineRegular, { size: 16 }), danger: true },
|
|
189
189
|
], onSelect: (id) => {
|
|
190
190
|
if (id === 'edit')
|
|
191
191
|
setEditing(true);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { IconChecklistOutlineRegular, IconPaperclipOutlineRegular, IconSendOutlineRegular, Tooltip, useAnchoredMaxHeight, useDismissOnOutsidePointer } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamPresenceDot } from "./TeamPresenceDot.js";
|
|
5
5
|
import { allMentionMembers, containsAllMention, containsMention, mentionedMemberIds } from "./team-formatters.js";
|
|
6
6
|
import css from './composer.module.css';
|
|
@@ -259,9 +259,9 @@ export function TeamComposer({ members, followerMemberIds, drafts, draftKey, pen
|
|
|
259
259
|
if (chosen.length > 0 && pendingFiles !== undefined)
|
|
260
260
|
onFilesChange([...pendingFiles, ...chosen]);
|
|
261
261
|
event.target.value = '';
|
|
262
|
-
} }), _jsx(Tooltip, { label: t('attachFiles'), side: "top", delayMs: 500, children: _jsx("button", { type: "button", className: css.attachButton, "aria-label": t('attachFiles'), disabled: pending, onClick: () => { fileInputRef.current?.click(); }, children: _jsx(
|
|
262
|
+
} }), _jsx(Tooltip, { label: t('attachFiles'), side: "top", delayMs: 500, children: _jsx("button", { type: "button", className: css.attachButton, "aria-label": t('attachFiles'), disabled: pending, onClick: () => { fileInputRef.current?.click(); }, children: _jsx(IconPaperclipOutlineRegular, { size: 14 }) }) })] })), onAsTaskChange !== undefined && (_jsxs("button", { type: "button", className: asTask === true ? `${css.asTaskPill} ${css.asTaskPillOn}` : css.asTaskPill, "aria-label": t('asTask'), "aria-pressed": asTask === true, title: t('asTask'), disabled: pending, onClick: () => { onAsTaskChange(asTask !== true); }, children: [_jsx(IconChecklistOutlineRegular, { size: 14 }), _jsx("span", { className: css.asTaskLabel, children: t('asTask') })] })), _jsx("button", { type: "submit", className: css.sendButton, "aria-label": pending ? t('sendingMessage') : t('sendMessage'), disabled: pending || draft.trim() === '', onMouseDown: event => {
|
|
263
263
|
// Keep the composer focused when the send control is clicked.
|
|
264
264
|
event.preventDefault();
|
|
265
265
|
inputRef.current?.focus({ preventScroll: true });
|
|
266
|
-
}, children: _jsx(
|
|
266
|
+
}, children: _jsx(IconSendOutlineRegular, { size: 16 }) })] })] }), error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] });
|
|
267
267
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useLayoutEffect, useSyncExternalStore } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { IconAgentPresetOutlineRegular, IconChevronLeftOutlineRegular, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import css from './team.module.css';
|
|
5
5
|
export function TeamFooterAction({ wide, navigation, enterTeam, leaveTeam, t }) {
|
|
6
6
|
const state = useSyncExternalStore(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
|
|
@@ -15,5 +15,5 @@ export function TeamFooterAction({ wide, navigation, enterTeam, leaveTeam, t })
|
|
|
15
15
|
}
|
|
16
16
|
delete document.documentElement.dataset.agentTeamMode;
|
|
17
17
|
}, [inTeam]);
|
|
18
|
-
return (_jsx(_Fragment, { children: _jsx("div", { className: wide ? css.footerStack : `${css.footerStack} ${css.railStack}`, children: _jsx(Tooltip, { label: label, delayMs: 500, disabled: wide, children: _jsxs("button", { type: "button", className: wide ? css.footerAction : `${css.footerAction} ${css.rail}`, "aria-label": label, "data-team-action": inTeam ? 'leave' : 'enter', onClick: inTeam ? leaveTeam : enterTeam, children: [inTeam ? _jsx(
|
|
18
|
+
return (_jsx(_Fragment, { children: _jsx("div", { className: wide ? css.footerStack : `${css.footerStack} ${css.railStack}`, children: _jsx(Tooltip, { label: label, delayMs: 500, disabled: wide, children: _jsxs("button", { type: "button", className: wide ? css.footerAction : `${css.footerAction} ${css.rail}`, "aria-label": label, "data-team-action": inTeam ? 'leave' : 'enter', onClick: inTeam ? leaveTeam : enterTeam, children: [inTeam ? _jsx(IconChevronLeftOutlineRegular, { size: wide ? 16 : 18 }) : _jsx(IconAgentPresetOutlineRegular, { size: wide ? 16 : 18 }), wide && _jsx("span", { children: label })] }) }) }) }));
|
|
19
19
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
-
import { Button,
|
|
3
|
+
import { Button, IconChevronDownOutlineRegular, Input, Menu, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { mintRequestId } from "./requests.js";
|
|
5
5
|
import { useEditDialogSave } from "./team-dialog-save.js";
|
|
6
6
|
import createCss from './create.module.css';
|
|
@@ -61,12 +61,12 @@ export function ModelPickerField({ model, onModelChange, loadModels, disabled, t
|
|
|
61
61
|
setModelOpen(false);
|
|
62
62
|
const choice = byKey.get(key);
|
|
63
63
|
onModelChange(choice === undefined ? undefined : { provider: choice.provider, model: choice.id });
|
|
64
|
-
}, onClose: () => { setModelOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('memberModel'), "aria-haspopup": "
|
|
64
|
+
}, onClose: () => { setModelOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('memberModel'), "aria-haspopup": "menu", "aria-expanded": open, disabled: disabled, onClick: () => { setModelOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: triggerLabel }), _jsx("span", { className: `${createCss.chevron} ${open ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutlineRegular, {}) })] }) })), model !== undefined && efforts.length > 0 && (_jsx(Menu, { open: effortOpen, portal: true, className: createCss.menuCap, items: effortItems, selectedId: selectedEffort, onSelect: key => {
|
|
65
65
|
setEffortOpen(false);
|
|
66
66
|
onModelChange(key === ''
|
|
67
67
|
? { provider: model.provider, model: model.model }
|
|
68
68
|
: { provider: model.provider, model: model.model, reasoningEffort: key });
|
|
69
|
-
}, onClose: () => { setEffortOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('reasoningEffort'), "aria-haspopup": "
|
|
69
|
+
}, onClose: () => { setEffortOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('reasoningEffort'), "aria-haspopup": "menu", "aria-expanded": effortOpen, disabled: disabled, onClick: () => { setEffortOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: `${t('reasoningEffort')} · ${effortTriggerLabel}` }), _jsx("span", { className: `${createCss.chevron} ${effortOpen ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutlineRegular, {}) })] }) }))] });
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
72
|
* Agent editor: handle, description, and per-Member model selection commit
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { IconUserOutlineRegular, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamMemberRow } from "./TeamMemberRow.js";
|
|
5
5
|
import membersCss from './members.module.css';
|
|
6
6
|
import css from './team.module.css';
|
|
@@ -28,5 +28,5 @@ export function TeamMembersAction({ wide, loadMemberGroups, t }) {
|
|
|
28
28
|
setPanelOpen(false);
|
|
29
29
|
queueMicrotask(() => { triggerRef.current?.focus(); });
|
|
30
30
|
};
|
|
31
|
-
return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { label: t('members'), delayMs: 500, disabled: wide, children: _jsxs("button", { ref: triggerRef, type: "button", className: wide ? css.settingsAction : `${css.settingsAction} ${css.rail}`, "aria-label": t('members'), "aria-haspopup": "dialog", onClick: openMembers, children: [_jsx(
|
|
31
|
+
return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { label: t('members'), delayMs: 500, disabled: wide, children: _jsxs("button", { ref: triggerRef, type: "button", className: wide ? css.settingsAction : `${css.settingsAction} ${css.rail}`, "aria-label": t('members'), "aria-haspopup": "dialog", onClick: openMembers, children: [_jsx(IconUserOutlineRegular, { size: wide ? 16 : 18 }), wide && _jsx("span", { children: t('members') })] }) }), _jsx(Modal, { open: panelOpen, onClose: closeMembers, title: t('members'), closeLabel: t('close'), contentClassName: membersCss.body, children: _jsxs("div", { ref: contentRef, className: membersCss.content, tabIndex: -1, children: [loading && _jsx("p", { className: membersCss.state, role: "status", children: t('loadingAgents') }), !loading && groups.length === 0 && error === undefined && _jsx("p", { className: membersCss.state, children: t('emptyAgents') }), !loading && groups.map(group => (_jsxs("section", { className: membersCss.group, "aria-labelledby": `team-members-${group.workspaceId}`, children: [_jsx("h3", { id: `team-members-${group.workspaceId}`, children: group.workspaceTitle }), group.members.map(status => _jsx(TeamMemberRow, { status: status, className: membersCss.member, t: t }, status.member.memberId))] }, group.workspaceId))), error !== undefined && _jsx("p", { className: membersCss.error, role: "alert", children: error })] }) })] }));
|
|
32
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamRowMenu.d.ts","sourceRoot":"","sources":["../../../src/client/TeamRowMenu.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"TeamRowMenu.d.ts","sourceRoot":"","sources":["../../../src/client/TeamRowMenu.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,uCAAuC,CAAA;AAGxG;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;IACpE,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;IACpC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,sEAAsE;IACtE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CAChD,+BAkCA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { IconEllipsisOutlineRegular, Menu } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import css from './sidebar.module.css';
|
|
5
5
|
/**
|
|
6
6
|
* Row-level overflow menu shared by sidebar Channel and Agent rows, mirroring
|
|
@@ -19,5 +19,5 @@ export function TeamRowMenu({ label, items, onSelect, onOpenChange }) {
|
|
|
19
19
|
setOpen(false);
|
|
20
20
|
onOpenChange?.(false);
|
|
21
21
|
};
|
|
22
|
-
return (_jsx(Menu, { open: open, onClose: close, items: items, onSelect: (id) => { close(); onSelect(id); }, portal: true, closeOnPointerLeave: true, anchor: (_jsx("button", { type: "button", className: css.rowMenuButton, "aria-label": label, "aria-haspopup": "menu", "aria-expanded": open, onClick: (event) => { event.stopPropagation(); toggle(); }, children: _jsx(
|
|
22
|
+
return (_jsx(Menu, { open: open, onClose: close, items: items, onSelect: (id) => { close(); onSelect(id); }, portal: true, closeOnPointerLeave: true, anchor: (_jsx("button", { type: "button", className: css.rowMenuButton, "aria-label": label, "aria-haspopup": "menu", "aria-expanded": open, onClick: (event) => { event.stopPropagation(); toggle(); }, children: _jsx(IconEllipsisOutlineRegular, {}) })) }));
|
|
23
23
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { IconChevronDownOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
3
3
|
import css from './sidebar.module.css';
|
|
4
4
|
/** Collapsible sidebar section header: disclosure toggle plus trailing actions. */
|
|
5
5
|
export function TeamSidebarSection({ title, actions, open, onToggle, children }) {
|
|
6
|
-
return (_jsxs("section", { className: css.section, children: [_jsxs("div", { className: css.sectionHeader, children: [_jsxs("button", { type: "button", className: css.sectionToggle, "aria-expanded": open, onClick: () => { onToggle(!open); }, children: [_jsx(
|
|
6
|
+
return (_jsxs("section", { className: css.section, children: [_jsxs("div", { className: css.sectionHeader, children: [_jsxs("button", { type: "button", className: css.sectionToggle, "aria-expanded": open, onClick: () => { onToggle(!open); }, children: [_jsx(IconChevronDownOutlineRegular, { className: css.sectionChevron }), _jsx("span", { className: css.sectionTitle, children: title })] }), actions !== undefined && _jsx("span", { className: css.sectionActions, children: actions })] }), open && children] }));
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { Button, DisclosureRow,
|
|
3
|
+
import { Button, DisclosureRow, IconChevronLeftOutlineRegular, IconChecklistOutlineRegular, Modal, Pill } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamComposer } from "./TeamComposer.js";
|
|
5
5
|
import { diagnosticText, TeamPresenceDot } from "./TeamPresenceDot.js";
|
|
6
6
|
import { TeamMessage } from "./TeamMessage.js";
|
|
@@ -703,7 +703,7 @@ export function TeamThreadPage(props) {
|
|
|
703
703
|
// Threads are always entered through a Channel page, so a Channel origin
|
|
704
704
|
// returns to its timeline; a Thread restored without one returns further.
|
|
705
705
|
const backLabel = channelRef === undefined ? t('backToWorkspace') : t('backToChannel');
|
|
706
|
-
return _jsxs("main", { className: css.surface, "data-team-thread": threadRef, children: [_jsxs("div", { className: css.surfaceHeader, children: [_jsx("div", { className: css.backRow, children: _jsx(Button, { size: "sm", icon: _jsx(
|
|
706
|
+
return _jsxs("main", { className: css.surface, "data-team-thread": threadRef, children: [_jsxs("div", { className: css.surfaceHeader, children: [_jsx("div", { className: css.backRow, children: _jsx(Button, { size: "sm", icon: _jsx(IconChevronLeftOutlineRegular, {}), onClick: backToWorkspace, children: backLabel }) }), _jsxs("header", { className: css.headerRow, children: [_jsxs("div", { className: css.headerCopy, children: [_jsxs("div", { className: threadCss.titleLine, children: [_jsx("h1", { children: task === undefined ? t('threadLabel') : t('taskLabel', { number: resolvedTaskNumber ?? '…' }) }), task !== undefined && _jsxs(Pill, { children: [_jsx(TeamStateDot, { size: 8, state: taskStatusDot(task.status) }), formatTaskStatus(task.status, t)] })] }), taskTitle !== undefined && taskTitle !== '' && _jsx("p", { className: threadCss.taskTitle, title: taskTitle, children: taskTitle })] }), task === undefined && thread !== undefined && _jsx("div", { className: css.headerActions, children: _jsx(Button, { size: "sm", variant: "primary", disabled: pending, onClick: () => { void convertToTask(); }, children: mutating === 'promote' ? t('promotingTask') : t('promoteToTask') }) }), task !== undefined && thread !== undefined && task.resolution !== 'closed' && _jsxs("div", { className: css.headerActions, children: [(() => {
|
|
707
707
|
const activeClaims = projection?.claims.filter(claim => claim.taskRef === task.taskRef && claim.state === 'active') ?? [];
|
|
708
708
|
const earlyAccept = task.resolution === 'open' && task.status === 'in_progress' && activeClaims.length > 0;
|
|
709
709
|
// todo Tasks accept directly: the work finished outside the
|
|
@@ -723,7 +723,7 @@ export function TeamThreadPage(props) {
|
|
|
723
723
|
const activeClaims = projection?.claims.filter(claim => claim.taskRef === task.taskRef && claim.state === 'active') ?? [];
|
|
724
724
|
return _jsxs(Modal, { open: confirmingAccept, onClose: () => { if (!pending)
|
|
725
725
|
setConfirmingAccept(false); }, title: t('acceptEarlyTitle'), closeLabel: t('cancel'), footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", disabled: pending, onClick: () => { setConfirmingAccept(false); }, children: t('cancel') }), _jsx(Button, { variant: "primary", disabled: pending, onClick: () => { void mutateTask('accept'); }, children: mutating === 'accept' ? t('acceptingTask') : t('acceptTask') })] }), children: [_jsx("p", { className: css.confirmBody, children: t('acceptEarlyBody', { count: activeClaims.length }) }), _jsx("ul", { className: css.confirmList, children: activeClaims.map(claim => (_jsxs("li", { children: [memberName(claim.owner), " \u00B7 ", claim.direction] }, claim.claimRef))) })] });
|
|
726
|
-
})(), task !== undefined && thread !== undefined && _jsx("section", { className: threadCss.workSection, "aria-label": t('claims'), children: _jsx(DisclosureRow, { expandOnRowClick: true, expandable: true, open: claimsOpen, onToggle: () => { setClaimsOpen(current => !current); }, icon: _jsx(
|
|
726
|
+
})(), task !== undefined && thread !== undefined && _jsx("section", { className: threadCss.workSection, "aria-label": t('claims'), children: _jsx(DisclosureRow, { expandOnRowClick: true, expandable: true, open: claimsOpen, onToggle: () => { setClaimsOpen(current => !current); }, icon: _jsx(IconChecklistOutlineRegular, { size: 14 }), title: `${t('claims')} · ${taskClaims.length}`, children: _jsxs("div", { className: threadCss.claimList, children: [taskClaims.length === 0 && _jsx("p", { className: threadCss.emptyClaims, children: t('noClaims') }), taskClaims.map(claim => {
|
|
727
727
|
const ownerStatus = members.find(status => status.member.memberId === claim.owner);
|
|
728
728
|
return _jsxs("article", { className: threadCss.claimRow, children: [ownerStatus === undefined ? _jsx("span", {}) : _jsx(TeamPresenceDot, { status: ownerStatus, t: t }), _jsx("strong", { className: threadCss.claimOwner, children: memberName(claim.owner) }), _jsx("span", { className: threadCss.claimDirection, children: claim.direction }), _jsx("small", { className: threadCss.claimState, children: formatClaimState(claim.state, t) })] }, claim.claimRef);
|
|
729
729
|
})] }) }) })] }), _jsx("section", { ref: timeline.ref, onScroll: handleTimelineScroll, className: css.timeline, "aria-label": t('timelineLabel'), children: _jsxs("div", { className: css.timelineContent, children: [loading && projection === undefined && error === undefined && _jsx("div", { className: css.emptySurface, children: _jsxs("p", { className: css.loadingState, children: [_jsx("span", { className: css.loadingMark, "aria-hidden": "true" }), t('loadingThread')] }) }), projection === undefined && error !== undefined && _jsxs("div", { className: css.errorState, role: "alert", children: [_jsx("span", { children: error }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => { void readCurrent(); }, children: t('retry') })] }), olderFacts.length > 0 && _jsxs("section", { className: threadCss.historySection, "aria-label": t('olderHistory'), children: [_jsx("h2", { children: t('olderHistory') }), renderFactBlocks(olderFacts, undefined)] }), historyHasMore && _jsx("div", { className: css.timelineAction, children: _jsx(Button, { size: "sm", onClick: () => { void loadOlder(); }, children: t('loadOlder') }) }), currentFactsWithAnchor.length > 0 && _jsx("section", { className: threadCss.publicSection, children: renderFactBlocks(currentFactsWithAnchor, unreadBoundary) }), autoReadExhausted && _jsxs("div", { className: css.timelineAction, role: "alert", children: [_jsx("span", { children: t('autoReadIncomplete') }), _jsx(Button, { size: "sm", onClick: () => { setAutoReadExhausted(false); void drainUnread(); }, disabled: loading, children: t('retry') })] }), newFactsCount > 0 && _jsx("div", { className: threadCss.newUpdates, role: "status", children: _jsx("button", { type: "button", className: threadCss.newUpdatesJump, onClick: () => { setNewFactsCount(0); timeline.scrollToBottom(); }, children: t('newUpdatesJump', { count: newFactsCount }) }) })] }) }), projection !== undefined && thread !== undefined ? (task?.resolution === 'closed'
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"TeamWorkspaceBrowser.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceBrowser.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAuBlD,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,+BAiHra"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { TeamSidebarSection } from "./TeamSidebarSection.js";
|
|
6
|
-
import { useSidebarSectionOpen, setSidebarSectionOpen } from "./sidebar-sections.js";
|
|
3
|
+
import { IconAgentPresetOutlineRegular, IconListPenOutlineRegular, IconQueueOutlineRegular, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
|
+
import { TeamWorkspaceSelector } from "./TeamWorkspaceSelector.js";
|
|
7
5
|
import { TeamAgentsPanel } from "./TeamAgentsPanel.js";
|
|
8
6
|
import { TeamChannelsPanel } from "./TeamChannelsPanel.js";
|
|
9
7
|
import css from './sidebar.module.css';
|
|
@@ -16,7 +14,7 @@ import css from './sidebar.module.css';
|
|
|
16
14
|
* on the same corner of the same glyph.
|
|
17
15
|
*/
|
|
18
16
|
function InboxMark({ unread }) {
|
|
19
|
-
return _jsxs("span", { className: css.inboxMark, children: [_jsx(
|
|
17
|
+
return _jsxs("span", { className: css.inboxMark, children: [_jsx(IconQueueOutlineRegular, { size: 16 }), unread > 0 && _jsx("span", { className: css.inboxDot, "data-team-inbox-dot": true, "aria-hidden": "true" })] });
|
|
20
18
|
}
|
|
21
19
|
export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWorkspace, selectChannel, selectInbox, t, useWorkspaces, loadMembers, loadInbox, subscribeChanges, subscribeReads, addMember, loadChannels, createChannel, updateChannel, archiveChannel, updateMember, recoverMember, archiveMember, joinWorkspace, leaveWorkspace, joinChannel, removeChannelMember, loadModels, openMemberSession }) {
|
|
22
20
|
const navigationState = useSyncExternalStore(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
|
|
@@ -39,7 +37,6 @@ export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWo
|
|
|
39
37
|
const [pendingSection, setPendingSection] = useState();
|
|
40
38
|
const channelsRef = useRef(null);
|
|
41
39
|
const agentsRef = useRef(null);
|
|
42
|
-
const workspacesOpen = useSidebarSectionOpen(undefined, 'workspaces');
|
|
43
40
|
// The cross-Workspace Inbox badge: one scope-less subscription while the
|
|
44
41
|
// Team sidebar stands; every wake re-pulls each Workspace's unread total
|
|
45
42
|
// (limit 1 — totals cover every row, never the list). Same-burst wakes
|
|
@@ -98,7 +95,7 @@ export function TeamWorkspaceBrowser({ wide, expandSidebar, navigation, selectWo
|
|
|
98
95
|
queueMicrotask(() => { node?.querySelector('button')?.focus(); });
|
|
99
96
|
}, [wide, pendingSection]);
|
|
100
97
|
if (!wide) {
|
|
101
|
-
return _jsxs("nav", { className: css.railWorkspace, "aria-label": t('workspaceSections'), children: [_jsx(Tooltip, { label: inboxLabel, side: "right", children: _jsx("button", { type: "button", className: css.railButton, "aria-label": inboxLabel, "aria-current": inboxIsCurrent ? 'page' : undefined, onClick: () => { selectInbox(); expandSidebar(); }, children: _jsx(InboxMark, { unread: inboxTotal }) }) }), _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(
|
|
98
|
+
return _jsxs("nav", { className: css.railWorkspace, "aria-label": t('workspaceSections'), children: [_jsx(Tooltip, { label: inboxLabel, side: "right", children: _jsx("button", { type: "button", className: css.railButton, "aria-label": inboxLabel, "aria-current": inboxIsCurrent ? 'page' : undefined, onClick: () => { selectInbox(); expandSidebar(); }, children: _jsx(InboxMark, { unread: inboxTotal }) }) }), _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(IconListPenOutlineRegular, { 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(IconAgentPresetOutlineRegular, { size: 16 }) }) })] });
|
|
102
99
|
}
|
|
103
|
-
return _jsxs("section", { className: css.workspaceBrowser, "aria-label": t('workspaces'), children: [_jsxs("button", { type: "button", className: css.inboxCard, "aria-label": inboxLabel, "aria-current": inboxIsCurrent ? 'page' : undefined, onClick: selectInbox, children: [_jsx(InboxMark, { unread: inboxTotal }), _jsx("span", { className: css.inboxCardLabel, children: t('inboxTitle') })] }), _jsx(
|
|
100
|
+
return _jsxs("section", { className: css.workspaceBrowser, "aria-label": t('workspaces'), children: [_jsxs("button", { type: "button", className: css.inboxCard, "aria-label": inboxLabel, "aria-current": inboxIsCurrent ? 'page' : undefined, onClick: selectInbox, children: [_jsx(InboxMark, { unread: inboxTotal }), _jsx("span", { className: css.inboxCardLabel, children: t('inboxTitle') })] }), _jsx(TeamWorkspaceSelector, { workspaces: workspaces, selectedId: selectedId, current: overviewIsCurrent, onSelect: selectWorkspace, t: t }), 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, joinWorkspace: joinWorkspace, leaveWorkspace: leaveWorkspace, 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) })] })] });
|
|
104
101
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { WorkspaceId } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
2
|
+
/** One selectable Workspace, in the order the Workspace list already carries. */
|
|
3
|
+
export interface TeamWorkspaceChoice {
|
|
4
|
+
readonly workspaceId: WorkspaceId;
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly path: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The single-line Workspace selector that scopes the Team sidebar.
|
|
10
|
+
*
|
|
11
|
+
* The sections below it — Channels and Agents — belong to exactly one
|
|
12
|
+
* Workspace, so a flat list of every Workspace above them states a global
|
|
13
|
+
* scope over local content. Collapsing that list into one selector makes the
|
|
14
|
+
* sidebar read as "you are in X, and here is X's content", and returns the
|
|
15
|
+
* rows a low-frequency switch was holding. Nothing is hidden by the collapse:
|
|
16
|
+
* Workspace rows carry no unread mark of their own, and cross-Workspace unread
|
|
17
|
+
* is summarized by the Inbox entry above — the one destination that outlives
|
|
18
|
+
* this scope, which is why it stays outside the selector's reach.
|
|
19
|
+
*
|
|
20
|
+
* The trigger is a field rather than a row: the line that states where the
|
|
21
|
+
* reader is must not read as the first entry of the Channels list below it,
|
|
22
|
+
* and its accessible name states the Workspace it is showing, because that
|
|
23
|
+
* value is otherwise unavailable to a reader who cannot see the field. The
|
|
24
|
+
* menu is the only way to switch Workspaces, so it takes focus on open and
|
|
25
|
+
* hands it back to the trigger on Escape.
|
|
26
|
+
*/
|
|
27
|
+
export declare function TeamWorkspaceSelector({ workspaces, selectedId, current, onSelect, t }: {
|
|
28
|
+
readonly workspaces: readonly TeamWorkspaceChoice[];
|
|
29
|
+
readonly selectedId: WorkspaceId | undefined;
|
|
30
|
+
/** The Team center shows the selected Workspace's overview (no Channel is open). */
|
|
31
|
+
readonly current: boolean;
|
|
32
|
+
readonly onSelect: (workspaceId: WorkspaceId) => void;
|
|
33
|
+
readonly t: (key: 'empty' | 'workspaceSelectorWithValue', params?: {
|
|
34
|
+
title: string;
|
|
35
|
+
}) => string;
|
|
36
|
+
}): import("react").JSX.Element;
|
|
37
|
+
//# sourceMappingURL=TeamWorkspaceSelector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TeamWorkspaceSelector.d.ts","sourceRoot":"","sources":["../../../src/client/TeamWorkspaceSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAGnF,iFAAiF;AACjF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE;IACtF,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAA;IACnD,QAAQ,CAAC,UAAU,EAAE,WAAW,GAAG,SAAS,CAAA;IAC5C,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAA;IACrD,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,4BAA4B,EAAE,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;CAChG,+BA0DA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { IconChevronDownOutlineRegular, IconFolderOpenRegular, Menu } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
|
+
import css from './sidebar.module.css';
|
|
5
|
+
/**
|
|
6
|
+
* The single-line Workspace selector that scopes the Team sidebar.
|
|
7
|
+
*
|
|
8
|
+
* The sections below it — Channels and Agents — belong to exactly one
|
|
9
|
+
* Workspace, so a flat list of every Workspace above them states a global
|
|
10
|
+
* scope over local content. Collapsing that list into one selector makes the
|
|
11
|
+
* sidebar read as "you are in X, and here is X's content", and returns the
|
|
12
|
+
* rows a low-frequency switch was holding. Nothing is hidden by the collapse:
|
|
13
|
+
* Workspace rows carry no unread mark of their own, and cross-Workspace unread
|
|
14
|
+
* is summarized by the Inbox entry above — the one destination that outlives
|
|
15
|
+
* this scope, which is why it stays outside the selector's reach.
|
|
16
|
+
*
|
|
17
|
+
* The trigger is a field rather than a row: the line that states where the
|
|
18
|
+
* reader is must not read as the first entry of the Channels list below it,
|
|
19
|
+
* and its accessible name states the Workspace it is showing, because that
|
|
20
|
+
* value is otherwise unavailable to a reader who cannot see the field. The
|
|
21
|
+
* menu is the only way to switch Workspaces, so it takes focus on open and
|
|
22
|
+
* hands it back to the trigger on Escape.
|
|
23
|
+
*/
|
|
24
|
+
export function TeamWorkspaceSelector({ workspaces, selectedId, current, onSelect, t }) {
|
|
25
|
+
const [open, setOpen] = useState(false);
|
|
26
|
+
// A portaled Menu list is laid out `visibility: hidden` and placed by the
|
|
27
|
+
// primitive's own layout effect, so its `autoFocus` effect runs one render
|
|
28
|
+
// too early: `focus()` on a hidden row is a no-op. The menu would then open
|
|
29
|
+
// with focus still on the trigger, and the primitive's arrow keys — which
|
|
30
|
+
// index from `document.activeElement` — stay dead, leaving a keyboard reader
|
|
31
|
+
// no way to reach another Workspace. Focusing the opened row once the list is
|
|
32
|
+
// on screen restores what `autoFocus` is for; it does nothing when focus is
|
|
33
|
+
// already inside the list.
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!open)
|
|
36
|
+
return;
|
|
37
|
+
const frame = requestAnimationFrame(() => {
|
|
38
|
+
// Portaled lists are children of the portal target, and the list this
|
|
39
|
+
// open mounted is the last of them.
|
|
40
|
+
const lists = document.querySelectorAll('body > [role="menu"]');
|
|
41
|
+
const list = lists[lists.length - 1];
|
|
42
|
+
if (list === undefined || list.contains(document.activeElement))
|
|
43
|
+
return;
|
|
44
|
+
list.querySelector('button:not(:disabled)')?.focus();
|
|
45
|
+
});
|
|
46
|
+
return () => { cancelAnimationFrame(frame); };
|
|
47
|
+
}, [open]);
|
|
48
|
+
const selected = workspaces.find(workspace => workspace.workspaceId === selectedId);
|
|
49
|
+
// Nothing to state — no Workspace, or a selection the list no longer carries —
|
|
50
|
+
// so the browser says that in the selector's own seat instead of a dead field.
|
|
51
|
+
if (selected === undefined)
|
|
52
|
+
return _jsx("p", { className: css.emptyState, children: t('empty') });
|
|
53
|
+
const items = workspaces.map(workspace => ({
|
|
54
|
+
id: workspace.workspaceId,
|
|
55
|
+
label: workspace.title,
|
|
56
|
+
}));
|
|
57
|
+
return (_jsx(Menu, { open: open, portal: true, autoFocus: true, items: items, selectedIds: [selected.workspaceId], onSelect: id => { setOpen(false); onSelect(id); }, onClose: () => { setOpen(false); }, anchor: (_jsxs("button", { type: "button", className: css.workspaceTrigger, "data-team-workspace-trigger": true, "aria-label": t('workspaceSelectorWithValue', { title: selected.title }), "aria-haspopup": "menu", "aria-expanded": open, "aria-current": current ? 'page' : undefined, title: `${selected.title} · ${selected.path}`, onClick: () => { setOpen(value => !value); }, children: [_jsx("span", { className: css.workspaceIcon, "aria-hidden": "true", children: _jsx(IconFolderOpenRegular, { size: 16 }) }), _jsx("span", { className: css.workspaceValue, children: selected.title }), _jsx("span", { className: `${css.workspaceChevron} ${open ? css.workspaceChevronOpen : ''}`, "aria-hidden": "true", children: _jsx(IconChevronDownOutlineRegular, {}) })] })) }));
|
|
58
|
+
}
|
|
@@ -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;AAuCnE,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;
|
|
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;AAuCnE,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;AAuBD,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;AAqMD,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7D"}
|
|
@@ -10,8 +10,27 @@ import { en, zh } from "./locales.js";
|
|
|
10
10
|
export { TeamNavigation } from "./navigation.js";
|
|
11
11
|
const NS = 'team';
|
|
12
12
|
export const inject = [
|
|
13
|
-
'slots', 'workspaces', 'locale', 'remote', 'remote.session', 'sessions', 'connection', 'conversation',
|
|
13
|
+
'slots', 'workspaces', 'locale', 'remote', 'remote.session', 'sessions', 'connection', 'conversation', 'uiWorkspace',
|
|
14
14
|
];
|
|
15
|
+
/**
|
|
16
|
+
* 0.1.7 moved the conversation selection into the workspace service: the
|
|
17
|
+
* rendered session is the one holding its `mainView` reference (the shipped
|
|
18
|
+
* consumers read the same projection), so the Team client reads the selection
|
|
19
|
+
* through retention instead of a service-owned `current`.
|
|
20
|
+
*/
|
|
21
|
+
function currentMainSessionId(ctx) {
|
|
22
|
+
const sessions = ctx.sessions;
|
|
23
|
+
return Object.values(sessions.list.getSnapshot().byId)
|
|
24
|
+
.find(session => (session.retainedBy.mainView ?? 0) > 0)?.id;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Session ids this client opened as Member views, per client instance. The
|
|
28
|
+
* 0.1.7 workspace service exposes no clear, so a dead return target leaves
|
|
29
|
+
* the departed Member selection in place; excluding Member sessions from the
|
|
30
|
+
* next capture keeps that stale selection from becoming a false return
|
|
31
|
+
* target.
|
|
32
|
+
*/
|
|
33
|
+
const openedMemberSessions = new WeakMap();
|
|
15
34
|
function registerModeShadow(ctx, navigation, changes, reads, drafts, name, component, extraInject,
|
|
16
35
|
// Keyed seats (`main`) address one panel by key; the reserved 'conversation'
|
|
17
36
|
// key is where the shipped Conversation registers, so the Team seat shadows
|
|
@@ -21,14 +40,16 @@ entryKey) {
|
|
|
21
40
|
// views (see registerModeShadow), so the shipped conversation root renders
|
|
22
41
|
// the selected Member Session inside the Team shell.
|
|
23
42
|
const openMemberSessionImpl = (sessionId) => {
|
|
24
|
-
const sessions = ctx.sessions;
|
|
25
43
|
const snapshot = navigation.getSnapshot();
|
|
26
|
-
const current =
|
|
44
|
+
const current = currentMainSessionId(ctx);
|
|
27
45
|
// The return target is captured on first entry only — switching between
|
|
28
46
|
// Member Sessions must keep pointing at the Human's original session.
|
|
29
|
-
const
|
|
47
|
+
const memberSessions = openedMemberSessions.get(ctx) ?? new Set();
|
|
48
|
+
openedMemberSessions.set(ctx, memberSessions);
|
|
49
|
+
memberSessions.add(sessionId);
|
|
50
|
+
const returnTo = snapshot.memberSessionId === undefined && current !== undefined && current !== sessionId && !memberSessions.has(current) ? current : undefined;
|
|
30
51
|
navigation.actions().enterMemberSession(sessionId, returnTo);
|
|
31
|
-
|
|
52
|
+
ctx.uiWorkspace.openSession(sessionId);
|
|
32
53
|
};
|
|
33
54
|
// Remote bindings shared by every Team slot; surface-specific entries extend it below.
|
|
34
55
|
const sharedRemotes = {
|
|
@@ -125,12 +146,13 @@ function applyUi(ctx) {
|
|
|
125
146
|
void disposeDrafts();
|
|
126
147
|
}, 'agent-team: navigation service');
|
|
127
148
|
// The one restore owner: leaving an embedded Member Session view must
|
|
128
|
-
// rebind the underlying
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
149
|
+
// rebind the underlying selection, or the departed Member session stays the
|
|
150
|
+
// workspace service's `mainView` retention into the next Member entry's
|
|
151
|
+
// return-target capture. Takeover is conditional — only when the selection
|
|
152
|
+
// still IS the departed Member session — so a selection someone else made
|
|
153
|
+
// in the meantime survives. A dead return target keeps the departed
|
|
154
|
+
// selection: 0.1.7 exposes no public clear, and the retention is inert
|
|
155
|
+
// behind the Team seat until the next open.
|
|
134
156
|
ctx.effect(() => {
|
|
135
157
|
let previous = navigation.getSnapshot();
|
|
136
158
|
const restore = () => {
|
|
@@ -140,13 +162,10 @@ function applyUi(ctx) {
|
|
|
140
162
|
previous = snapshot;
|
|
141
163
|
if (departed === undefined || snapshot.memberSessionId !== undefined)
|
|
142
164
|
return;
|
|
143
|
-
|
|
144
|
-
if (sessions.list.getSnapshot().current !== departed)
|
|
165
|
+
if (currentMainSessionId(ctx) !== departed)
|
|
145
166
|
return;
|
|
146
|
-
if (returnTo !== undefined && sessions.list.getSnapshot().byId[returnTo] !== undefined)
|
|
147
|
-
|
|
148
|
-
else
|
|
149
|
-
sessions.clear();
|
|
167
|
+
if (returnTo !== undefined && ctx.sessions.list.getSnapshot().byId[returnTo] !== undefined)
|
|
168
|
+
ctx.uiWorkspace.openSession(returnTo);
|
|
150
169
|
};
|
|
151
170
|
const unsubscribe = navigation.subscribe(restore);
|
|
152
171
|
return () => {
|
|
@@ -183,7 +202,7 @@ function applyUi(ctx) {
|
|
|
183
202
|
navigation,
|
|
184
203
|
...navigation.actions(),
|
|
185
204
|
// The footer is the only surface that leaves Team mode; closing the
|
|
186
|
-
// embedded Member Session view rebinds the underlying
|
|
205
|
+
// embedded Member Session view rebinds the underlying selection through
|
|
187
206
|
// the same root-scope restore owner, so there is exactly one restore
|
|
188
207
|
// path and no double open.
|
|
189
208
|
leaveTeam: () => {
|
|
@@ -2,6 +2,7 @@ export declare const zh: {
|
|
|
2
2
|
readonly team: "团队";
|
|
3
3
|
readonly backToConversations: "对话";
|
|
4
4
|
readonly workspaces: "工作区";
|
|
5
|
+
readonly workspaceSelectorWithValue: "工作区,{title}";
|
|
5
6
|
readonly channels: "频道";
|
|
6
7
|
readonly agents: "Agents";
|
|
7
8
|
readonly members: "成员";
|
|
@@ -178,6 +179,7 @@ export declare const en: {
|
|
|
178
179
|
readonly team: "Team";
|
|
179
180
|
readonly backToConversations: "Conversations";
|
|
180
181
|
readonly workspaces: "Workspaces";
|
|
182
|
+
readonly workspaceSelectorWithValue: "Workspace, {title}";
|
|
181
183
|
readonly channels: "Channels";
|
|
182
184
|
readonly agents: "Agents";
|
|
183
185
|
readonly members: "Members";
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgLL,CAAA;AAEV,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgLL,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,CAAA"}
|