@wowyuarm/dsh-agent-team 0.1.1 → 0.1.3
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 -0
- package/README.zh.md +2 -0
- package/package.json +42 -25
- package/packages/agent-team/README.md +1 -1
- package/packages/agent-team/README.zh.md +1 -1
- package/packages/agent-team/lib/attachments.js +11 -12
- package/packages/agent-team/lib/auto-compaction.js +163 -0
- package/packages/agent-team/lib/index.js +262 -189
- package/packages/agent-team/lib/ledger.js +140 -109
- package/packages/agent-team/lib/recovery.js +30 -35
- package/packages/agent-team/lib/spec.js +10 -4
- package/packages/agent-team/lib/typert.host.js +68 -71
- package/packages/agent-team/lib/typert.remote-client.d.ts +3 -3
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +41 -56
- package/packages/agent-team/lib/types/attachments.d.ts +2 -2
- package/packages/agent-team/lib/types/attachments.d.ts.map +1 -1
- package/packages/agent-team/lib/types/auto-compaction.d.ts +38 -0
- package/packages/agent-team/lib/types/auto-compaction.d.ts.map +1 -0
- package/packages/agent-team/lib/types/index.d.ts +49 -24
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/ledger.d.ts +24 -11
- package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
- package/packages/agent-team/lib/types/recovery.d.ts +15 -16
- package/packages/agent-team/lib/types/recovery.d.ts.map +1 -1
- package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types.d.ts +20 -12
- package/packages/agent-team/lib/types/types.d.ts.map +1 -1
- package/packages/agent-team/preset/team-member/agent.cordis.yml +8 -3
- package/packages/client-agent-team/README.md +3 -2
- package/packages/client-agent-team/README.zh.md +3 -2
- package/packages/client-agent-team/lib/client.js +1507 -525
- 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 +24 -182
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +3 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +27 -5
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +19 -4
- package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamComposer.js +22 -2
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts +34 -0
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +169 -0
- package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts +17 -0
- package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.js +120 -0
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +7 -2
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMessage.js +170 -18
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +4 -0
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +70 -13
- 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 +72 -2
- package/packages/client-agent-team/lib/types/client/locales.d.ts +8 -2
- package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/locales.js +8 -2
- package/packages/client-agent-team/lib/types/client/member-session-input.d.ts +22 -0
- package/packages/client-agent-team/lib/types/client/member-session-input.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/member-session-input.js +98 -0
- package/packages/client-agent-team/lib/types/client/requests.d.ts +16 -0
- package/packages/client-agent-team/lib/types/client/requests.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/requests.js +22 -0
- package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts +35 -0
- package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/sidebar-drag.js +70 -0
- package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts +27 -0
- package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/sidebar-order.js +170 -0
- package/packages/client-agent-team/lib/types/client/slots.d.ts +2 -2
- package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts +25 -0
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/task-refs.js +77 -0
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +54 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.js +83 -2
- package/packages/client-agent-team/lib/types/client/team-membership.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-membership.js +2 -1
- package/packages/tool-agent-team/lib/index.js +4 -4
- package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts +0 -13
- package/packages/client-agent-team/lib/types/client/TeamInboxPanel.d.ts.map +0 -1
- package/packages/client-agent-team/lib/types/client/TeamInboxPanel.js +0 -90
|
@@ -9,7 +9,6 @@ interface TeamAgentsPanelProps {
|
|
|
9
9
|
readonly addMember: TeamSidebarProps['addMember'];
|
|
10
10
|
readonly updateMember: TeamSidebarProps['updateMember'];
|
|
11
11
|
readonly recoverMember: TeamSidebarProps['recoverMember'];
|
|
12
|
-
readonly restartMember: TeamSidebarProps['restartMember'];
|
|
13
12
|
readonly joinChannel: TeamSidebarProps['joinChannel'];
|
|
14
13
|
readonly removeChannelMember: TeamSidebarProps['removeChannelMember'];
|
|
15
14
|
readonly loadModels: TeamSidebarProps['loadModels'];
|
|
@@ -19,6 +18,6 @@ interface TeamAgentsPanelProps {
|
|
|
19
18
|
readonly onCreatingChange: (request: AgentTeamAddMemberRequest, creating: boolean) => void;
|
|
20
19
|
readonly t: TeamSidebarProps['t'];
|
|
21
20
|
}
|
|
22
|
-
export declare function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember,
|
|
21
|
+
export declare function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }: TeamAgentsPanelProps): import("react").JSX.Element;
|
|
23
22
|
export {};
|
|
24
23
|
//# 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,
|
|
1
|
+
{"version":3,"file":"TeamAgentsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/TeamAgentsPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAG5B,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEzE,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,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;IACvD,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,WAAW,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IACrD,QAAQ,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAA;IACrE,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,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC,EAAE,EAAE,oBAAoB,+BAiLhQ"}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { Button,
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { Button, IconEditOutline16, IconPlayOutline16, IconPlusOutline16, Input, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamMemberAvatar } from "./TeamMemberAvatar.js";
|
|
5
|
+
import { SortableRow, useSidebarRowDrag } from "./sidebar-drag.js";
|
|
6
|
+
import { moveSidebarItem, useSidebarOrder } from "./sidebar-order.js";
|
|
7
|
+
import { mintRequestId } from "./requests.js";
|
|
5
8
|
import { TeamRowMenu } from "./TeamRowMenu.js";
|
|
6
9
|
import { TeamSidebarSection } from "./TeamSidebarSection.js";
|
|
7
10
|
import { MultiMenuField } from "./multi-menu-field.js";
|
|
8
|
-
import {
|
|
11
|
+
import { AgentEditorDialog, ModelPickerField, sameModel } from "./TeamMemberEditor.js";
|
|
9
12
|
import createCss from './create.module.css';
|
|
10
13
|
import css from './sidebar.module.css';
|
|
11
|
-
export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember,
|
|
14
|
+
export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }) {
|
|
12
15
|
const [members, setMembers] = useState([]);
|
|
13
16
|
const [channels, setChannels] = useState([]);
|
|
14
17
|
const [channelRefs, setChannelRefs] = useState([]);
|
|
@@ -21,6 +24,18 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, lo
|
|
|
21
24
|
const [creating, setCreating] = useState(false);
|
|
22
25
|
const [retryRequest, setRetryRequest] = useState();
|
|
23
26
|
const triggerRef = useRef(null);
|
|
27
|
+
// Same presentation-preference ordering as the Channels list; the drag
|
|
28
|
+
// commits through one shared mutation.
|
|
29
|
+
const agentRefs = useMemo(() => members.map(status => status.member.memberId), [members]);
|
|
30
|
+
const orderedAgentRefs = useSidebarOrder(workspaceId, 'agents', agentRefs);
|
|
31
|
+
const orderedMembers = useMemo(() => {
|
|
32
|
+
const byId = new Map(members.map(status => [status.member.memberId, status]));
|
|
33
|
+
return orderedAgentRefs.map(memberId => byId.get(memberId)).filter(status => status !== undefined);
|
|
34
|
+
}, [orderedAgentRefs, members]);
|
|
35
|
+
const applyMove = (movedRef, targetRef, marker) => {
|
|
36
|
+
void moveSidebarItem(workspaceId, 'agents', orderedAgentRefs, movedRef, targetRef, marker);
|
|
37
|
+
};
|
|
38
|
+
const drag = useSidebarRowDrag({ refs: orderedAgentRefs, onCommit: applyMove });
|
|
24
39
|
const refresh = useCallback(async () => {
|
|
25
40
|
setLoading(true);
|
|
26
41
|
const result = await loadMembers({ workspaceId });
|
|
@@ -105,7 +120,7 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, lo
|
|
|
105
120
|
&& sameModel(retryRequest.model, model)
|
|
106
121
|
&& retryRequest.channelRefs.length === channelRefs.length && retryRequest.channelRefs.every(ref => channelRefs.includes(ref));
|
|
107
122
|
void provision(sameRequest ? retryRequest : {
|
|
108
|
-
requestId:
|
|
123
|
+
requestId: mintRequestId(),
|
|
109
124
|
workspaceId,
|
|
110
125
|
handle: normalizedHandle,
|
|
111
126
|
description: normalizedDescription,
|
|
@@ -117,204 +132,31 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, lo
|
|
|
117
132
|
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 }), _jsx(MultiMenuField, { label: `${t('initialChannels')}${t('optionalSuffix')}`, disabled: creating, options: channels.map(channel => ({ id: channel.channelRef, label: channel.name })), selected: channelRefs, onToggle: ref => {
|
|
118
133
|
setChannelRefs(current => current.includes(ref) ? current.filter(item => item !== ref) : [...current, ref]);
|
|
119
134
|
setRetryRequest(undefined);
|
|
120
|
-
}, emptyText: t('noChannelsForAgent'), triggerEmptyLabel: t('channelsPickerEmpty'), formatCount: count => t('channelsPickerCount', { count }) }), formOpen && error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('agents'), 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:
|
|
135
|
+
}, emptyText: t('noChannelsForAgent'), triggerEmptyLabel: t('channelsPickerEmpty'), formatCount: count => t('channelsPickerCount', { count }) }), formOpen && error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('agents'), 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 }), channels: channels, loadChannels: loadChannels, updateMember: updateMember, recoverMember: recoverMember, joinChannel: joinChannel, removeChannelMember: removeChannelMember, 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') })] }))] }));
|
|
121
136
|
}
|
|
122
137
|
/**
|
|
123
138
|
* One sidebar Agent row: the select button opens the Member's own Session
|
|
124
139
|
* conversation page, the avatar carries identity plus the presence badge, and
|
|
125
140
|
* the row menu opens the editor.
|
|
126
141
|
*/
|
|
127
|
-
function AgentRow({ status, current, channels, loadChannels, updateMember, recoverMember,
|
|
142
|
+
function AgentRow({ status, current, channels, loadChannels, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, openMemberSession, onUpdated, t }) {
|
|
128
143
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
129
144
|
const [editing, setEditing] = useState(false);
|
|
130
145
|
const resume = async () => {
|
|
131
146
|
await recoverMember({
|
|
132
|
-
requestId:
|
|
133
|
-
workspaceId: status.member.workspaceId,
|
|
134
|
-
memberId: status.member.memberId,
|
|
135
|
-
});
|
|
136
|
-
await onUpdated();
|
|
137
|
-
};
|
|
138
|
-
const restart = async () => {
|
|
139
|
-
await restartMember({
|
|
140
|
-
requestId: crypto.randomUUID(),
|
|
147
|
+
requestId: mintRequestId(),
|
|
141
148
|
workspaceId: status.member.workspaceId,
|
|
142
149
|
memberId: status.member.memberId,
|
|
143
150
|
});
|
|
144
151
|
await onUpdated();
|
|
145
152
|
};
|
|
146
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.agentRow, "data-menu-open": menuOpen || undefined, children: [_jsxs("button", { type: "button", className: css.agentSelect, "aria-label": t('openAgentSession', { name: status.member.handle }), "aria-current": current ? 'page' : undefined, onClick: () => { openMemberSession(status.member.sessionId); }, children: [_jsx(TeamMemberAvatar, { status: status, t: t }), _jsxs("span", { className: css.agentCopy, children: [_jsx("strong", { children: status.member.handle }), _jsx("small", { children: status.member.description })] })] }), _jsx("span", { className: css.rowMenu, children: _jsx(TeamRowMenu, { label: t('actionsAgent', { name: status.member.handle }), items: [
|
|
153
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.agentRow, "data-menu-open": menuOpen || undefined, children: [_jsxs("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(TeamMemberAvatar, { status: status, t: t }), _jsxs("span", { className: css.agentCopy, children: [_jsx("strong", { children: status.member.handle }), _jsx("small", { children: status.member.description })] })] }), _jsx("span", { className: css.rowMenu, children: _jsx(TeamRowMenu, { label: t('actionsAgent', { name: status.member.handle }), items: [
|
|
147
154
|
{ id: 'edit', label: t('editAgent'), icon: _jsx(IconEditOutline16, {}) },
|
|
148
155
|
...(status.presence === 'error' ? [{ id: 'resume', label: t('resumeAgent'), icon: _jsx(IconPlayOutline16, {}) }] : []),
|
|
149
|
-
{ id: 'restart', label: t('restartAgent'), icon: _jsx(IconRefreshOutline14, {}) },
|
|
150
156
|
], onSelect: (id) => {
|
|
151
157
|
if (id === 'resume')
|
|
152
158
|
void resume();
|
|
153
|
-
else if (id === 'restart')
|
|
154
|
-
void restart();
|
|
155
159
|
else
|
|
156
160
|
setEditing(true);
|
|
157
161
|
}, onOpenChange: setMenuOpen }) })] }), editing && (_jsx(AgentEditorDialog, { status: status, channels: channels, loadChannels: loadChannels, updateMember: updateMember, joinChannel: joinChannel, removeChannelMember: removeChannelMember, loadModels: loadModels, onCommitted: onUpdated, onClose: () => { setEditing(false); }, t: t }))] }));
|
|
158
162
|
}
|
|
159
|
-
/** Model option key inside one editor; opaque and resolved against the loaded groups. */
|
|
160
|
-
function modelKey(provider, model) {
|
|
161
|
-
return `${provider}\u0000${model}`;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Shared provider/model dropdown for the create and edit forms. The option
|
|
165
|
-
* list rides the shared Menu primitive (one leading "follow Host default"
|
|
166
|
-
* row, then non-selectable provider headings) with a capped, internally
|
|
167
|
-
* scrolling card so growing model catalogs cannot stretch the dialog.
|
|
168
|
-
*/
|
|
169
|
-
function ModelPickerField({ model, onModelChange, loadModels, disabled, t }) {
|
|
170
|
-
const [groups, setGroups] = useState();
|
|
171
|
-
const [modelsError, setModelsError] = useState();
|
|
172
|
-
const [open, setModelOpen] = useState(false);
|
|
173
|
-
const [effortOpen, setEffortOpen] = useState(false);
|
|
174
|
-
useEffect(() => {
|
|
175
|
-
let mounted = true;
|
|
176
|
-
void loadModels().then(result => {
|
|
177
|
-
if (!mounted)
|
|
178
|
-
return;
|
|
179
|
-
if (result.ok) {
|
|
180
|
-
setGroups(result.value.groups);
|
|
181
|
-
setModelsError(undefined);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
setModelsError(result.error.message);
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
return () => { mounted = false; };
|
|
188
|
-
}, [loadModels]);
|
|
189
|
-
const items = [{ id: '', label: t('modelFollowDefault') }];
|
|
190
|
-
const byKey = new Map();
|
|
191
|
-
for (const group of groups ?? []) {
|
|
192
|
-
items.push({ type: 'label', id: `model-group:${group.id}`, text: group.name });
|
|
193
|
-
for (const entry of group.models) {
|
|
194
|
-
const key = modelKey(group.id, entry.id);
|
|
195
|
-
byKey.set(key, { provider: group.id, id: entry.id, name: entry.name, efforts: entry.reasoning?.efforts ?? [] });
|
|
196
|
-
items.push({ id: key, label: entry.name });
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
const selectedModelKey = model === undefined ? '' : modelKey(model.provider, model.model);
|
|
200
|
-
const triggerLabel = model === undefined
|
|
201
|
-
? t('modelFollowDefault')
|
|
202
|
-
: byKey.get(selectedModelKey)?.name ?? `${model.provider} / ${model.model}`;
|
|
203
|
-
// The effort sub-row only makes sense for a pinned model with adapter-exposed
|
|
204
|
-
// efforts; following the Host default inherits the operator's whole selection.
|
|
205
|
-
const efforts = model === undefined ? [] : byKey.get(selectedModelKey)?.efforts ?? [];
|
|
206
|
-
const effortItems = [{ id: '', label: t('effortFollowDefault') }, ...efforts.map(effort => ({ id: effort.id, label: effort.name }))];
|
|
207
|
-
const selectedEffort = model?.reasoningEffort ?? '';
|
|
208
|
-
const effortTriggerLabel = model === undefined || selectedEffort === ''
|
|
209
|
-
? t('effortFollowDefault')
|
|
210
|
-
: efforts.find(effort => effort.id === selectedEffort)?.name ?? selectedEffort;
|
|
211
|
-
return _jsxs("div", { className: createCss.field, children: [_jsx("span", { children: t('memberModel') }), groups === undefined && modelsError === undefined && _jsx("small", { className: css.editHint, children: t('modelsLoading') }), modelsError !== undefined && _jsx("small", { className: css.editHint, children: t('modelsLoadFailed', { message: modelsError }) }), groups !== undefined && (_jsx(Menu, { open: open, portal: true, className: createCss.menuCap, items: items, selectedId: selectedModelKey, onSelect: key => {
|
|
212
|
-
setModelOpen(false);
|
|
213
|
-
const choice = byKey.get(key);
|
|
214
|
-
onModelChange(choice === undefined ? undefined : { provider: choice.provider, model: choice.id });
|
|
215
|
-
}, onClose: () => { setModelOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('memberModel'), "aria-haspopup": "listbox", "aria-expanded": open, disabled: disabled, onClick: () => { setModelOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: triggerLabel }), _jsx("span", { className: `${createCss.chevron} ${open ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutline14, {}) })] }) })), model !== undefined && efforts.length > 0 && (_jsx(Menu, { open: effortOpen, portal: true, className: createCss.menuCap, items: effortItems, selectedId: selectedEffort, onSelect: key => {
|
|
216
|
-
setEffortOpen(false);
|
|
217
|
-
onModelChange(key === ''
|
|
218
|
-
? { provider: model.provider, model: model.model }
|
|
219
|
-
: { provider: model.provider, model: model.model, reasoningEffort: key });
|
|
220
|
-
}, onClose: () => { setEffortOpen(false); }, anchor: _jsxs("button", { type: "button", className: createCss.selectTrigger, "aria-label": t('reasoningEffort'), "aria-haspopup": "listbox", "aria-expanded": effortOpen, disabled: disabled, onClick: () => { setEffortOpen(value => !value); }, children: [_jsx("span", { className: createCss.selectValue, children: `${t('reasoningEffort')} · ${effortTriggerLabel}` }), _jsx("span", { className: `${createCss.chevron} ${effortOpen ? createCss.chevronOpen : ''}`, "aria-hidden": true, children: _jsx(IconChevronDownOutline14, {}) })] }) }))] });
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Agent editor: handle, description, and per-Member model selection commit
|
|
224
|
-
* through one durable update; Channel membership below keeps its own
|
|
225
|
-
* immediate add/remove flow.
|
|
226
|
-
*/
|
|
227
|
-
function AgentEditorDialog({ status, channels, loadChannels, updateMember, joinChannel, removeChannelMember, loadModels, onCommitted, onClose, t }) {
|
|
228
|
-
const memberId = status.member.memberId;
|
|
229
|
-
const [handle, setHandle] = useState(status.member.handle);
|
|
230
|
-
const [description, setDescription] = useState(status.member.description);
|
|
231
|
-
const [model, setModel] = useState(status.member.model);
|
|
232
|
-
const [saving, setSaving] = useState(false);
|
|
233
|
-
const [error, setError] = useState();
|
|
234
|
-
const pendingRequest = useRef();
|
|
235
|
-
// Membership comes from a fresh projection at open time so stale checkbox
|
|
236
|
-
// state never flips a committed fact backwards.
|
|
237
|
-
const [memberships, setMemberships] = useState();
|
|
238
|
-
const [loadError, setLoadError] = useState();
|
|
239
|
-
useEffect(() => {
|
|
240
|
-
let mounted = true;
|
|
241
|
-
void loadChannels({ workspaceId: status.member.workspaceId, topLevelOnly: true, includeActivities: false, limit: 1 }).then(result => {
|
|
242
|
-
if (!mounted)
|
|
243
|
-
return;
|
|
244
|
-
if (result.ok) {
|
|
245
|
-
setMemberships(result.value.members);
|
|
246
|
-
setLoadError(undefined);
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
setLoadError(result.error.message);
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
return () => { mounted = false; };
|
|
253
|
-
}, [loadChannels, status.member.workspaceId]);
|
|
254
|
-
const membership = useChannelMembership({ joinChannel, removeChannelMember }, change => change.channelRef, change => {
|
|
255
|
-
setMemberships(current => {
|
|
256
|
-
const base = current ?? [];
|
|
257
|
-
return change.joined
|
|
258
|
-
? base.filter(item => !(item.channelRef === change.channelRef && item.memberId === change.memberId))
|
|
259
|
-
: [...base, { channelRef: change.channelRef, memberId: change.memberId }];
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
// A successful join appends the durable fact; removal filters it out above.
|
|
263
|
-
const joinedChannels = new Set((memberships ?? []).filter(item => item.memberId === memberId).map(item => item.channelRef));
|
|
264
|
-
const dirty = handle.trim() !== status.member.handle || description.trim() !== status.member.description
|
|
265
|
-
|| !sameModel(model, status.member.model);
|
|
266
|
-
const submit = async (event) => {
|
|
267
|
-
event.preventDefault();
|
|
268
|
-
const normalizedHandle = handle.trim();
|
|
269
|
-
const normalizedDescription = description.trim();
|
|
270
|
-
if (saving || !dirty || normalizedHandle.length === 0)
|
|
271
|
-
return;
|
|
272
|
-
const payload = {
|
|
273
|
-
memberId,
|
|
274
|
-
handle: normalizedHandle,
|
|
275
|
-
description: normalizedDescription,
|
|
276
|
-
...(model === undefined ? {} : { model }),
|
|
277
|
-
};
|
|
278
|
-
const samePending = pendingRequest.current !== undefined && pendingRequest.current.memberId === payload.memberId
|
|
279
|
-
&& pendingRequest.current.handle === payload.handle && pendingRequest.current.description === payload.description
|
|
280
|
-
&& sameModel(pendingRequest.current.model, model);
|
|
281
|
-
const request = samePending ? pendingRequest.current : {
|
|
282
|
-
requestId: crypto.randomUUID(),
|
|
283
|
-
...payload,
|
|
284
|
-
};
|
|
285
|
-
pendingRequest.current = request;
|
|
286
|
-
setSaving(true);
|
|
287
|
-
setError(undefined);
|
|
288
|
-
try {
|
|
289
|
-
const result = await updateMember(request);
|
|
290
|
-
if (result.ok) {
|
|
291
|
-
pendingRequest.current = undefined;
|
|
292
|
-
await onCommitted();
|
|
293
|
-
onClose();
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
setError(result.error.message);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
catch (cause) {
|
|
300
|
-
setError(cause instanceof Error ? cause.message : String(cause));
|
|
301
|
-
}
|
|
302
|
-
finally {
|
|
303
|
-
setSaving(false);
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
return (_jsx(Modal, { open: true, onClose: onClose, title: t('editAgent'), description: `@${status.member.handle}`, closeLabel: t('close'), contentClassName: createCss.dialogContent, footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", disabled: saving, onClick: onClose, children: t('cancel') }), _jsx(Button, { type: "submit", form: "team-agent-edit-form", variant: "primary", disabled: saving || !dirty || handle.trim().length === 0, children: saving ? t('editSaving') : t('editSave') })] }), children: _jsxs("form", { id: "team-agent-edit-form", className: createCss.form, onSubmit: event => { void submit(event); }, 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); pendingRequest.current = undefined; }, disabled: saving, 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); pendingRequest.current = undefined; }, disabled: saving })] }), _jsx(ModelPickerField, { model: model, onModelChange: choice => { pendingRequest.current = undefined; setModel(choice); }, loadModels: loadModels, disabled: saving, t: t }), _jsxs("fieldset", { className: createCss.memberPicker, disabled: saving, children: [_jsx("legend", { children: t('channelMembersSection') }), channels.map(channel => {
|
|
307
|
-
const joined = joinedChannels.has(channel.channelRef);
|
|
308
|
-
const rowPending = membership.pending.has(channel.channelRef);
|
|
309
|
-
const disabled = rowPending || (!joined && status.presence === 'unavailable');
|
|
310
|
-
const rowError = membership.errors.get(channel.channelRef);
|
|
311
|
-
return _jsxs("div", { className: `${css.editMemberRow} ${css.editMemberRowChannels}`, children: [_jsxs("strong", { className: css.editChannelName, children: ["# ", channel.name] }), _jsx(Button, { size: "sm", variant: "outline", disabled: disabled, onClick: () => { void membership.change({ workspaceId: status.member.workspaceId, channelRef: channel.channelRef, memberId, joined }); }, children: rowPending ? t('membershipUpdating') : joined ? t('removeFromChannel') : t('addToChannel') }), rowError !== undefined && _jsx("p", { className: css.rowError, role: "alert", children: rowError })] }, channel.channelRef);
|
|
312
|
-
}), channels.length === 0 && _jsx("small", { children: t('noChannelsForAgent') }), loadError !== undefined && _jsx("p", { className: css.rowError, role: "alert", children: loadError })] }), error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }));
|
|
313
|
-
}
|
|
314
|
-
function sameModel(left, right) {
|
|
315
|
-
if (left === undefined && right === undefined)
|
|
316
|
-
return true;
|
|
317
|
-
if (left === undefined || right === undefined)
|
|
318
|
-
return false;
|
|
319
|
-
return left.provider === right.provider && left.model === right.model && left.reasoningEffort === right.reasoningEffort;
|
|
320
|
-
}
|
|
@@ -15,9 +15,11 @@ interface TeamChannelPageProps {
|
|
|
15
15
|
readonly joinChannel: TeamConversationProps['joinChannel'];
|
|
16
16
|
readonly removeChannelMember: TeamConversationProps['removeChannelMember'];
|
|
17
17
|
readonly selectThread: TeamConversationProps['selectThread'];
|
|
18
|
+
readonly selectChannel: TeamConversationProps['selectChannel'];
|
|
19
|
+
readonly resolveTaskRefs: TeamConversationProps['resolveTaskRefs'];
|
|
18
20
|
readonly backToChannels: TeamConversationProps['backToChannels'];
|
|
19
21
|
readonly t: TeamConversationProps['t'];
|
|
20
22
|
}
|
|
21
|
-
export declare function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, backToChannels, t }: TeamChannelPageProps): import("react").JSX.Element;
|
|
23
|
+
export declare function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, selectChannel, backToChannels, resolveTaskRefs, t }: TeamChannelPageProps): import("react").JSX.Element;
|
|
22
24
|
export {};
|
|
23
25
|
//# sourceMappingURL=TeamChannelPage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamChannelPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamChannelPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA+B,mBAAmB,
|
|
1
|
+
{"version":3,"file":"TeamChannelPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamChannelPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA+B,mBAAmB,EAE7D,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAIvD,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,aAAa,CAAA;AAc/D,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAA;IACxC,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;IACpE,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAA;IAC1D,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAA;IAC1D,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAA;IAC1D,QAAQ,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,qBAAqB,CAAC,CAAA;IAC1E,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,cAAc,EAAE,qBAAqB,CAAC,gBAAgB,CAAC,CAAA;IAChE,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC;AAmBD,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC,EAAE,EAAE,oBAAoB,+BAqTnR"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Fragment, useEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
3
3
|
import { Button, IconChevronLeftOutline14, IconChevronRightOutline14, Modal, StateDot } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { bytesToBase64 } from "./attachment-preview.js";
|
|
5
|
+
import { mintRequestId } from "./requests.js";
|
|
5
6
|
import { TeamComposer } from "./TeamComposer.js";
|
|
6
7
|
import { TeamPresenceDot } from "./TeamPresenceDot.js";
|
|
7
8
|
import { TeamMessage } from "./TeamMessage.js";
|
|
@@ -9,6 +10,7 @@ import { TeamRunDivider } from "./TeamRunDivider.js";
|
|
|
9
10
|
import { formatTaskStatus, taskStatusDot, mentionNamesOf } from "./team-formatters.js";
|
|
10
11
|
import { useChannelMembership } from "./team-membership.js";
|
|
11
12
|
import { useTimelineScroll } from "./timeline-scroll.js";
|
|
13
|
+
import { hostTaskRefLookup, jumpToTaskThread } from "./task-refs.js";
|
|
12
14
|
import { chunkRunsWithDays, isRunGap } from "./team-separators.js";
|
|
13
15
|
import channelCss from './channel.module.css';
|
|
14
16
|
import css from './conversation.module.css';
|
|
@@ -29,7 +31,7 @@ function mergeChannelView(current, fresh) {
|
|
|
29
31
|
hasMore: fresh.hasMore || current.cursor < fresh.cursor,
|
|
30
32
|
};
|
|
31
33
|
}
|
|
32
|
-
export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, backToChannels, t }) {
|
|
34
|
+
export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscribeChanges, loadMembers, drafts, putAttachment, getAttachment, sendMessage, joinChannel, removeChannelMember, selectThread, selectChannel, backToChannels, resolveTaskRefs, t }) {
|
|
33
35
|
const [view, setView] = useState();
|
|
34
36
|
const [members, setMembers] = useState([]);
|
|
35
37
|
const [error, setError] = useState();
|
|
@@ -48,6 +50,27 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
48
50
|
const mountedRef = useRef(false);
|
|
49
51
|
const refreshSequenceRef = useRef(0);
|
|
50
52
|
const channelLastItem = view?.items[view.items.length - 1];
|
|
53
|
+
// Branded-ref navigation for message bodies: channel refs hop directly,
|
|
54
|
+
// task refs resolve against this Channel's loaded timeline and degrade to a
|
|
55
|
+
// no-op when the target is not reachable from here.
|
|
56
|
+
const openRef = (ref) => {
|
|
57
|
+
if (ref.startsWith('channel:')) {
|
|
58
|
+
if (ref !== channelRef)
|
|
59
|
+
selectChannel(ref);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (ref.startsWith('task:')) {
|
|
63
|
+
const match = view?.items.find(item => item.task.taskRef === ref);
|
|
64
|
+
if (match !== undefined) {
|
|
65
|
+
selectThread(match.task.taskRef, match.thread.threadRef, channelRef, match.taskNumber);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Not in the loaded timeline: resolve through the Host and jump to the
|
|
69
|
+
// Task's home Channel.
|
|
70
|
+
jumpToTaskThread(resolveTaskRefs, workspaceId, ref, selectThread);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const lookupTaskRefs = hostTaskRefLookup(resolveTaskRefs, workspaceId);
|
|
51
74
|
const timeline = useTimelineScroll(`${view?.items.length ?? 0}:${channelLastItem?.message.messageRef ?? ''}`);
|
|
52
75
|
const channel = view?.channels.find(item => item.channelRef === channelRef);
|
|
53
76
|
const channelMemberIds = new Set(view?.members.filter(item => item.channelRef === channelRef).map(item => item.memberId) ?? []);
|
|
@@ -183,11 +206,10 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
183
206
|
// definitive outcomes (committed or rejected) start the next send fresh.
|
|
184
207
|
const pendingSendId = useRef();
|
|
185
208
|
const send = async () => {
|
|
186
|
-
console.log('DBG send entry pending=%s draft=%j files=%d', pending, draft, pendingFiles.length);
|
|
187
209
|
if (pending || draft.trim() === '')
|
|
188
210
|
return;
|
|
189
211
|
const recipientIds = [...recipients].sort();
|
|
190
|
-
const requestId = pendingSendId.current ??
|
|
212
|
+
const requestId = pendingSendId.current ?? mintRequestId();
|
|
191
213
|
pendingSendId.current = requestId;
|
|
192
214
|
setPending(true);
|
|
193
215
|
setError(undefined);
|
|
@@ -198,7 +220,7 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
198
220
|
const attachmentIds = [];
|
|
199
221
|
for (const file of pendingFiles) {
|
|
200
222
|
const uploaded = await putAttachment({
|
|
201
|
-
requestId:
|
|
223
|
+
requestId: mintRequestId(),
|
|
202
224
|
workspaceId,
|
|
203
225
|
name: file.name,
|
|
204
226
|
mediaType: file.type === '' ? undefined : file.type,
|
|
@@ -258,7 +280,7 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
258
280
|
const human = item.message.sender === view.humanMemberId;
|
|
259
281
|
const sender = human ? t('human') : senderStatus?.member.handle ?? item.message.sender;
|
|
260
282
|
return _jsxs(Fragment, { children: [isRunGap(index > 0 ? block.items[index - 1].message.occurredAt : undefined, item.message.occurredAt)
|
|
261
|
-
&& _jsx(TeamRunDivider, { occurredAt: item.message.occurredAt }), _jsx(TeamMessage, { senderName: sender, memberId: item.message.sender, human: human, body: item.message.body, attachments: item.message.attachments, loadAttachment: getAttachment, t: t, occurredAt: item.message.occurredAt, mentionNames: mentionNamesOf(item.mentions, mentionHandlesMap), grouped: index > 0, ...(senderStatus === undefined ? {} : { senderTitle: senderStatus.member.description }), children: item.message.topLevel && _jsxs("button", { type: "button", className: channelCss.taskFooter, "aria-label": t('openTask', { number: item.taskNumber }), onClick: () => { selectThread(item.task.taskRef, item.thread.threadRef, channelRef, item.taskNumber); }, children: [_jsx("span", { className: channelCss.taskDot, children: (() => {
|
|
283
|
+
&& _jsx(TeamRunDivider, { occurredAt: item.message.occurredAt }), _jsx(TeamMessage, { senderName: sender, memberId: item.message.sender, human: human, body: item.message.body, attachments: item.message.attachments, loadAttachment: getAttachment, t: t, occurredAt: item.message.occurredAt, mentionNames: mentionNamesOf(item.mentions, mentionHandlesMap), onOpenRef: openRef, onResolveTaskRefs: lookupTaskRefs, grouped: index > 0, ...(senderStatus === undefined ? {} : { senderTitle: senderStatus.member.description }), children: item.message.topLevel && _jsxs("button", { type: "button", className: channelCss.taskFooter, "aria-label": t('openTask', { number: item.taskNumber }), onClick: () => { selectThread(item.task.taskRef, item.thread.threadRef, channelRef, item.taskNumber); }, children: [_jsx("span", { className: channelCss.taskDot, children: (() => {
|
|
262
284
|
const dot = taskStatusDot(item.task.status);
|
|
263
285
|
return dot === 'ongoing' || dot === 'warning' || dot === 'done'
|
|
264
286
|
? _jsx(StateDot, { size: 8, state: dot })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamChannelsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/TeamChannelsPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,yBAAyB,EAEzB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"TeamChannelsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/TeamChannelsPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,yBAAyB,EAEzB,mBAAmB,EAMpB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAYlD,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IACrD,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;IACvD,wGAAwG;IACxG,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,CAAA;IAC/D,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAA;IACzD,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAA;IACzD,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IACrD,QAAQ,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAA;IACrE,QAAQ,CAAC,cAAc,EAAE,SAAS,yBAAyB,EAAE,CAAA;IAC7D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,mBAAmB,CAAA;IACjD,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAA;IACzD,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAA;CAClC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,+BA2L9D"}
|
|
@@ -3,6 +3,9 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
3
3
|
import { Button, IconEditOutline16, IconPlusOutline16, Input, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamPresenceDot } from "./TeamPresenceDot.js";
|
|
5
5
|
import { MultiMenuField } from "./multi-menu-field.js";
|
|
6
|
+
import { SortableRow, useSidebarRowDrag } from "./sidebar-drag.js";
|
|
7
|
+
import { moveSidebarItem, useSidebarOrder } from "./sidebar-order.js";
|
|
8
|
+
import { mintRequestId } from "./requests.js";
|
|
6
9
|
import { TeamRowMenu } from "./TeamRowMenu.js";
|
|
7
10
|
import { TeamSidebarSection } from "./TeamSidebarSection.js";
|
|
8
11
|
import { useChannelMembership } from "./team-membership.js";
|
|
@@ -22,6 +25,18 @@ export function TeamChannelsPanel(props) {
|
|
|
22
25
|
const [pendingCreate, setPendingCreate] = useState();
|
|
23
26
|
const previousCreatingKey = useRef(creatingAgents.map(request => request.requestId).join(','));
|
|
24
27
|
const triggerRef = useRef(null);
|
|
28
|
+
// Row order is this browser's presentation preference; the drag commits
|
|
29
|
+
// through the single shared mutation below.
|
|
30
|
+
const channelRefs = useMemo(() => view?.channels.map(channel => channel.channelRef) ?? [], [view]);
|
|
31
|
+
const orderedChannelRefs = useSidebarOrder(workspaceId, 'channels', channelRefs);
|
|
32
|
+
const orderedChannels = useMemo(() => {
|
|
33
|
+
const byRef = new Map((view?.channels ?? []).map(channel => [channel.channelRef, channel]));
|
|
34
|
+
return orderedChannelRefs.map(channelRef => byRef.get(channelRef)).filter(channel => channel !== undefined);
|
|
35
|
+
}, [orderedChannelRefs, view]);
|
|
36
|
+
const applyMove = (movedRef, targetRef, marker) => {
|
|
37
|
+
void moveSidebarItem(workspaceId, 'channels', orderedChannelRefs, movedRef, targetRef, marker);
|
|
38
|
+
};
|
|
39
|
+
const drag = useSidebarRowDrag({ refs: orderedChannelRefs, onCommit: applyMove });
|
|
25
40
|
const refresh = useCallback(async () => {
|
|
26
41
|
setLoading(true);
|
|
27
42
|
const [channelResult, memberResult] = await Promise.all([
|
|
@@ -84,7 +99,7 @@ export function TeamChannelsPanel(props) {
|
|
|
84
99
|
&& pendingCreate.name === payload.name && pendingCreate.description === payload.description
|
|
85
100
|
&& JSON.stringify(pendingCreate.memberIds) === JSON.stringify(payload.memberIds);
|
|
86
101
|
const request = samePending ? pendingCreate : {
|
|
87
|
-
requestId:
|
|
102
|
+
requestId: mintRequestId(), ...payload,
|
|
88
103
|
};
|
|
89
104
|
setPendingCreate(request);
|
|
90
105
|
setMutating(true);
|
|
@@ -129,9 +144,9 @@ export function TeamChannelsPanel(props) {
|
|
|
129
144
|
return next;
|
|
130
145
|
});
|
|
131
146
|
setPendingCreate(undefined);
|
|
132
|
-
}, triggerEmptyLabel: t('membersPickerEmpty'), formatCount: count => t('membersPickerCount', { count }) }), error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('channels'), 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(IconPlusOutline16, { size: 14 }) }) })), children: [loading && view === undefined && _jsx("p", { className: css.emptyState, children: t('loadingChannels') }), !loading && (view?.channels.length ?? 0) === 0 && _jsx("p", { className: css.emptyState, children: t('emptyChannels') }), _jsx("div", { className: css.channelList, children:
|
|
147
|
+
}, triggerEmptyLabel: t('membersPickerEmpty'), formatCount: count => t('membersPickerCount', { count }) }), error !== undefined && _jsx("p", { className: createCss.error, role: "alert", children: error })] }) }), _jsxs(TeamSidebarSection, { title: t('channels'), 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(IconPlusOutline16, { size: 14 }) }) })), children: [loading && view === undefined && _jsx("p", { className: css.emptyState, children: t('loadingChannels') }), !loading && (view?.channels.length ?? 0) === 0 && _jsx("p", { className: css.emptyState, children: t('emptyChannels') }), _jsx("div", { className: css.channelList, children: orderedChannels.map(channel => {
|
|
133
148
|
const joined = membership.get(channel.channelRef) ?? new Set();
|
|
134
|
-
return (_jsx(ChannelRow, { channel: channel, members: members, joinedIds: joined, selected: selectedChannelRef === channel.channelRef, updateChannel: updateChannel, joinChannel: props.joinChannel, removeChannelMember: props.removeChannelMember, onCommitted: () => { void refresh(); }, selectChannel: selectChannel, t: t }, channel.channelRef));
|
|
149
|
+
return (_jsx(SortableRow, { drag: drag, orderKey: channel.channelRef, children: _jsx(ChannelRow, { channel: channel, members: members, joinedIds: joined, selected: selectedChannelRef === channel.channelRef, updateChannel: updateChannel, joinChannel: props.joinChannel, removeChannelMember: props.removeChannelMember, onCommitted: () => { void refresh(); }, selectChannel: selectChannel, t: t }) }, channel.channelRef));
|
|
135
150
|
}) })] }), !formOpen && error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] }));
|
|
136
151
|
}
|
|
137
152
|
/**
|
|
@@ -164,7 +179,7 @@ function ChannelEditorDialog({ channel, members, joinedIds, updateChannel, joinC
|
|
|
164
179
|
const samePending = pendingRequest.current !== undefined && pendingRequest.current.channelRef === channel.channelRef
|
|
165
180
|
&& pendingRequest.current.name === normalizedName && pendingRequest.current.description === normalizedDescription;
|
|
166
181
|
const request = samePending ? pendingRequest.current : {
|
|
167
|
-
requestId:
|
|
182
|
+
requestId: mintRequestId(),
|
|
168
183
|
workspaceId: channel.workspaceId,
|
|
169
184
|
channelRef: channel.channelRef,
|
|
170
185
|
name: normalizedName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamComposer.d.ts","sourceRoot":"","sources":["../../../src/client/TeamComposer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"TeamComposer.d.ts","sourceRoot":"","sources":["../../../src/client/TeamComposer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAkDvD,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE;IACtK,QAAQ,CAAC,OAAO,EAAE,SAAS,2BAA2B,EAAE,CAAA;IACxD,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAA;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/C,QAAQ,CAAC,kBAAkB,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAA;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;IAC7B,gGAAgG;IAChG,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,IAAI,EAAE,CAAA;IACvC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,KAAK,IAAI,CAAA;IACzD,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC,+BAgOA"}
|
|
@@ -3,6 +3,7 @@ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
|
3
3
|
import { IconPlusOutline16, IconSendOutline16, useAnchoredMaxHeight, useDismissOnOutsidePointer } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamPresenceDot } from "./TeamPresenceDot.js";
|
|
5
5
|
import css from './composer.module.css';
|
|
6
|
+
import { formatByteSize } from "./attachment-preview.js";
|
|
6
7
|
function findMention(draft, caret) {
|
|
7
8
|
const beforeCaret = draft.slice(0, caret);
|
|
8
9
|
if (beforeCaret.length === 0 || /\s/u.test(beforeCaret.at(-1) ?? ''))
|
|
@@ -29,6 +30,18 @@ function mentionCandidates(members, query) {
|
|
|
29
30
|
&& status.member.state !== 'inactive'
|
|
30
31
|
&& status.member.handle.toLocaleLowerCase().startsWith(normalized));
|
|
31
32
|
}
|
|
33
|
+
/** One object URL per draft file; revoked when the draft is removed. */
|
|
34
|
+
const draftPreviewUrls = new WeakMap();
|
|
35
|
+
function draftPreviewUrl(file) {
|
|
36
|
+
if (!file.type.startsWith('image/'))
|
|
37
|
+
return undefined;
|
|
38
|
+
let url = draftPreviewUrls.get(file);
|
|
39
|
+
if (url === undefined) {
|
|
40
|
+
url = URL.createObjectURL(file);
|
|
41
|
+
draftPreviewUrls.set(file, url);
|
|
42
|
+
}
|
|
43
|
+
return url;
|
|
44
|
+
}
|
|
32
45
|
export function TeamComposer({ members, recipients, draft, pending, confirmation, error, onDraftChange, onRecipientsChange, onSubmit, pendingFiles, onFilesChange, t }) {
|
|
33
46
|
const inputRef = useRef(null);
|
|
34
47
|
const fileInputRef = useRef(null);
|
|
@@ -159,7 +172,6 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
159
172
|
onSubmit();
|
|
160
173
|
};
|
|
161
174
|
return _jsxs("form", { ref: rootRef, className: css.root, onSubmit: event => {
|
|
162
|
-
console.log('DBG composer submit pending=%s draft=%j', pending, draft);
|
|
163
175
|
event.preventDefault();
|
|
164
176
|
if (!pending && draft.trim() !== '')
|
|
165
177
|
onSubmit();
|
|
@@ -167,7 +179,15 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
167
179
|
const optionId = `${listId}-${status.member.memberId}`;
|
|
168
180
|
const selected = index === highlight;
|
|
169
181
|
return _jsxs("button", { id: optionId, type: "button", role: "option", "aria-selected": selected, className: css.mentionOption, onMouseDown: event => { event.preventDefault(); }, onClick: () => { selectMention(status); }, children: [_jsx(TeamPresenceDot, { status: status, t: t }), _jsxs("span", { className: css.mentionName, children: ["@", status.member.handle] }), _jsx("span", { className: css.mentionDescription, children: status.member.description })] }, status.member.memberId);
|
|
170
|
-
}) }), _jsx("textarea", { ref: inputRef, "aria-label": t('messageDraft'), "aria-autocomplete": "list", "aria-controls": menuOpen ? listId : undefined, "aria-activedescendant": menuOpen && activeCandidate !== undefined ? `${listId}-${activeCandidate.member.memberId}` : undefined, "aria-expanded": menuOpen, value: draft, readOnly: pending, placeholder: t('messagePlaceholder'), rows: 1, onChange: onChange, onKeyDown: onKeyDown, onSelect: event => { updateMention(event.currentTarget.value, event.currentTarget.selectionStart ?? event.currentTarget.value.length); }, onCompositionStart: () => { composingRef.current = true; }, onCompositionEnd: () => { setTimeout(() => { composingRef.current = false; }, 10); } })] }), recipients.size > 0 && _jsx("p", { className: css.notifyRow, "data-team-notify": true, children: t('composerNotify', { ids: [...recipients].sort().map(memberId => `@${members.find(candidate => candidate.member.memberId === memberId)?.member.handle ?? memberId}`).join(', ') }) }), onFilesChange !== undefined && pendingFiles !== undefined && pendingFiles.length > 0 && (_jsx("ul", { className: css.fileChips, "aria-label": t('attachFiles'), children: pendingFiles.map((file, index) =>
|
|
182
|
+
}) }), _jsx("textarea", { ref: inputRef, "aria-label": t('messageDraft'), "aria-autocomplete": "list", "aria-controls": menuOpen ? listId : undefined, "aria-activedescendant": menuOpen && activeCandidate !== undefined ? `${listId}-${activeCandidate.member.memberId}` : undefined, "aria-expanded": menuOpen, value: draft, readOnly: pending, placeholder: t('messagePlaceholder'), rows: 1, onChange: onChange, onKeyDown: onKeyDown, onSelect: event => { updateMention(event.currentTarget.value, event.currentTarget.selectionStart ?? event.currentTarget.value.length); }, onCompositionStart: () => { composingRef.current = true; }, onCompositionEnd: () => { setTimeout(() => { composingRef.current = false; }, 10); } })] }), recipients.size > 0 && _jsx("p", { className: css.notifyRow, "data-team-notify": true, children: t('composerNotify', { ids: [...recipients].sort().map(memberId => `@${members.find(candidate => candidate.member.memberId === memberId)?.member.handle ?? memberId}`).join(', ') }) }), onFilesChange !== undefined && pendingFiles !== undefined && pendingFiles.length > 0 && (_jsx("ul", { className: css.fileChips, "aria-label": t('attachFiles'), children: pendingFiles.map((file, index) => {
|
|
183
|
+
const previewUrl = draftPreviewUrl(file);
|
|
184
|
+
return _jsxs("li", { className: `${css.fileChip} ${previewUrl !== undefined ? css.imageChip : ''}`, children: [previewUrl !== undefined && _jsx("img", { src: previewUrl, alt: "", className: css.imageChipPreview }), _jsxs("span", { className: css.fileChipName, title: file.name, children: [file.name, _jsx("span", { className: css.fileChipSize, children: formatByteSize(file.size) })] }), _jsx("button", { type: "button", className: css.fileChipRemove, "aria-label": t('removeFile', { name: file.name }), disabled: pending, onClick: () => {
|
|
185
|
+
const url = draftPreviewUrls.get(file);
|
|
186
|
+
if (url !== undefined)
|
|
187
|
+
URL.revokeObjectURL(url);
|
|
188
|
+
onFilesChange(pendingFiles.filter((_, candidate) => candidate !== index));
|
|
189
|
+
}, children: "\u00D7" })] }, `${file.name}-${index}`);
|
|
190
|
+
}) })), _jsxs("div", { className: css.toolbar, children: [onFilesChange !== undefined && (_jsxs(_Fragment, { children: [_jsx("input", { ref: fileInputRef, type: "file", multiple: true, className: css.fileInput, "aria-hidden": "true", tabIndex: -1, onChange: event => {
|
|
171
191
|
const chosen = [...event.target.files ?? []];
|
|
172
192
|
if (chosen.length > 0 && pendingFiles !== undefined)
|
|
173
193
|
onFilesChange([...pendingFiles, ...chosen]);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { TeamConversationProps } from './slots.ts';
|
|
2
|
-
export declare function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, sendMessage, joinChannel, removeChannelMember, reply, changeTask, selectThread, backToWorkspace, backToChannels }: TeamConversationProps): import("react").JSX.Element;
|
|
2
|
+
export declare function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, sendMessage, joinChannel, removeChannelMember, reply, changeTask, selectThread, selectChannel, backToWorkspace, backToChannels, resolveTaskRefs }: TeamConversationProps): import("react").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=TeamConversation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamConversation.d.ts","sourceRoot":"","sources":["../../../src/client/TeamConversation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAKvD,wBAAgB,gBAAgB,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,EAAE,qBAAqB,+
|
|
1
|
+
{"version":3,"file":"TeamConversation.d.ts","sourceRoot":"","sources":["../../../src/client/TeamConversation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAKvD,wBAAgB,gBAAgB,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,EAAE,qBAAqB,+BAoB1V"}
|
|
@@ -3,15 +3,15 @@ import { useSyncExternalStore } from 'react';
|
|
|
3
3
|
import { TeamChannelPage } from "./TeamChannelPage.js";
|
|
4
4
|
import { TeamThreadPage } from "./TeamThreadPage.js";
|
|
5
5
|
import css from './conversation.module.css';
|
|
6
|
-
export function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, sendMessage, joinChannel, removeChannelMember, reply, changeTask, selectThread, backToWorkspace, backToChannels }) {
|
|
6
|
+
export function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, sendMessage, joinChannel, removeChannelMember, reply, changeTask, selectThread, selectChannel, backToWorkspace, backToChannels, resolveTaskRefs }) {
|
|
7
7
|
const navigationState = useSyncExternalStore(navigation.subscribe, navigation.getSnapshot, navigation.getSnapshot);
|
|
8
8
|
const workspaces = useWorkspaces(state => state.items);
|
|
9
9
|
const current = workspaces.find(workspace => workspace.workspaceId === navigationState.workspaceId);
|
|
10
10
|
if (current !== undefined && navigationState.taskRef !== undefined && navigationState.threadRef !== undefined) {
|
|
11
|
-
return _jsx(TeamThreadPage, { workspaceId: current.workspaceId, taskRef: navigationState.taskRef, threadRef: navigationState.threadRef, backToWorkspace: backToWorkspace, ...(navigationState.channelRef === undefined ? {} : { channelRef: navigationState.channelRef }), ...(navigationState.taskNumber === undefined ? {} : { taskNumber: navigationState.taskNumber }), drafts: drafts, getAttachment: getAttachment, readThread: readThread, loadChannels: loadChannels, loadThreadHistory: loadThreadHistory, subscribeChanges: subscribeChanges, loadMembers: loadMembers, reply: reply, changeTask: changeTask, t: t }, navigationState.threadRef);
|
|
11
|
+
return _jsx(TeamThreadPage, { workspaceId: current.workspaceId, putAttachment: putAttachment, taskRef: navigationState.taskRef, threadRef: navigationState.threadRef, backToWorkspace: backToWorkspace, selectChannel: selectChannel, selectThread: selectThread, resolveTaskRefs: resolveTaskRefs, ...(navigationState.channelRef === undefined ? {} : { channelRef: navigationState.channelRef }), ...(navigationState.taskNumber === undefined ? {} : { taskNumber: navigationState.taskNumber }), drafts: drafts, getAttachment: getAttachment, readThread: readThread, loadChannels: loadChannels, loadThreadHistory: loadThreadHistory, subscribeChanges: subscribeChanges, loadMembers: loadMembers, reply: reply, changeTask: changeTask, t: t }, navigationState.threadRef);
|
|
12
12
|
}
|
|
13
13
|
if (current !== undefined && navigationState.channelRef !== undefined) {
|
|
14
|
-
return _jsx(TeamChannelPage, { workspaceId: current.workspaceId, channelRef: navigationState.channelRef, drafts: drafts, putAttachment: putAttachment, getAttachment: getAttachment, loadChannels: loadChannels, subscribeChanges: subscribeChanges, loadMembers: loadMembers, sendMessage: sendMessage, joinChannel: joinChannel, removeChannelMember: removeChannelMember, selectThread: selectThread, backToChannels: backToChannels, t: t }, navigationState.channelRef);
|
|
14
|
+
return _jsx(TeamChannelPage, { workspaceId: current.workspaceId, channelRef: navigationState.channelRef, drafts: drafts, putAttachment: putAttachment, getAttachment: getAttachment, loadChannels: loadChannels, subscribeChanges: subscribeChanges, loadMembers: loadMembers, sendMessage: sendMessage, joinChannel: joinChannel, removeChannelMember: removeChannelMember, selectThread: selectThread, selectChannel: selectChannel, backToChannels: backToChannels, resolveTaskRefs: resolveTaskRefs, t: t }, navigationState.channelRef);
|
|
15
15
|
}
|
|
16
16
|
const welcome = current === undefined
|
|
17
17
|
? { eyebrow: t('teamMode'), title: t('team'), body: t('empty') }
|