@wowyuarm/dsh-agent-team 0.1.3 → 0.1.5
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 +7 -1
- package/README.zh.md +12 -3
- package/package.json +1 -1
- package/packages/agent-team/README.md +3 -3
- package/packages/agent-team/README.zh.md +3 -3
- package/packages/agent-team/lib/auto-compaction.js +39 -1
- package/packages/agent-team/lib/index.js +123 -14
- package/packages/agent-team/lib/ledger.js +355 -110
- package/packages/agent-team/lib/spec.js +39 -11
- package/packages/agent-team/lib/typert.host.js +257 -86
- package/packages/agent-team/lib/typert.remote-client.d.ts +5 -1
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +196 -59
- package/packages/agent-team/lib/types/auto-compaction.d.ts +9 -0
- package/packages/agent-team/lib/types/auto-compaction.d.ts.map +1 -1
- package/packages/agent-team/lib/types/index.d.ts +24 -7
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/ledger.d.ts +36 -2
- package/packages/agent-team/lib/types/ledger.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 +109 -30
- package/packages/agent-team/lib/types/types.d.ts.map +1 -1
- package/packages/agent-team/preset/team-member/agent.cordis.yml +1 -1
- package/packages/client-agent-team/README.md +2 -1
- package/packages/client-agent-team/README.zh.md +2 -1
- package/packages/client-agent-team/lib/client.js +1082 -380
- package/packages/client-agent-team/lib/client.js.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts +2 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +73 -15
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +34 -10
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +3 -1
- package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts +6 -1
- package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamComposer.js +76 -20
- 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/TeamMemberSessionComposer.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMemberSessionComposer.js +16 -1
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +4 -1
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMessage.js +62 -25
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts +3 -2
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamSidebarSection.d.ts +5 -2
- package/packages/client-agent-team/lib/types/client/TeamSidebarSection.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamSidebarSection.js +2 -4
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +2 -1
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +92 -18
- 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 +5 -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 +16 -13
- package/packages/client-agent-team/lib/types/client/locales.d.ts +40 -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 +40 -0
- package/packages/client-agent-team/lib/types/client/navigation.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/navigation.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/navigation.js +12 -6
- package/packages/client-agent-team/lib/types/client/sidebar-sections.d.ts +16 -0
- package/packages/client-agent-team/lib/types/client/sidebar-sections.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/sidebar-sections.js +102 -0
- package/packages/client-agent-team/lib/types/client/slots.d.ts +3 -1
- 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 +1 -1
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/task-refs.js +1 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +9 -0
- 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 +22 -2
- package/packages/tool-agent-team/README.md +7 -7
- package/packages/tool-agent-team/README.zh.md +7 -7
- package/packages/tool-agent-team/lib/index.js +38 -28
- package/packages/tool-agent-team/lib/types/index.d.ts.map +1 -1
|
@@ -9,6 +9,7 @@ interface TeamAgentsPanelProps {
|
|
|
9
9
|
readonly addMember: TeamSidebarProps['addMember'];
|
|
10
10
|
readonly updateMember: TeamSidebarProps['updateMember'];
|
|
11
11
|
readonly recoverMember: TeamSidebarProps['recoverMember'];
|
|
12
|
+
readonly clearMemberContext: TeamSidebarProps['clearMemberContext'];
|
|
12
13
|
readonly joinChannel: TeamSidebarProps['joinChannel'];
|
|
13
14
|
readonly removeChannelMember: TeamSidebarProps['removeChannelMember'];
|
|
14
15
|
readonly loadModels: TeamSidebarProps['loadModels'];
|
|
@@ -18,6 +19,6 @@ interface TeamAgentsPanelProps {
|
|
|
18
19
|
readonly onCreatingChange: (request: AgentTeamAddMemberRequest, creating: boolean) => void;
|
|
19
20
|
readonly t: TeamSidebarProps['t'];
|
|
20
21
|
}
|
|
21
|
-
export declare function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }: TeamAgentsPanelProps): import("react").JSX.Element;
|
|
22
|
+
export declare function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, clearMemberContext, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }: TeamAgentsPanelProps): import("react").JSX.Element;
|
|
22
23
|
export {};
|
|
23
24
|
//# sourceMappingURL=TeamAgentsPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamAgentsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/TeamAgentsPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAG5B,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;
|
|
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;AAalD,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,kBAAkB,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,CAAA;IACnE,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,kBAAkB,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC,EAAE,EAAE,oBAAoB,+BAoLpR"}
|
|
@@ -1,9 +1,10 @@
|
|
|
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, IconEditOutline16, IconPlayOutline16, IconPlusOutline16, Input, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
3
|
+
import { Button, IconEditOutline16, IconNewChatOutline16, IconPlayOutline16, IconPlusOutline16, IconRefreshOutline16, Input, Modal, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { TeamMemberAvatar } from "./TeamMemberAvatar.js";
|
|
5
5
|
import { SortableRow, useSidebarRowDrag } from "./sidebar-drag.js";
|
|
6
6
|
import { moveSidebarItem, useSidebarOrder } from "./sidebar-order.js";
|
|
7
|
+
import { useSidebarSectionOpen, setSidebarSectionOpen } from "./sidebar-sections.js";
|
|
7
8
|
import { mintRequestId } from "./requests.js";
|
|
8
9
|
import { TeamRowMenu } from "./TeamRowMenu.js";
|
|
9
10
|
import { TeamSidebarSection } from "./TeamSidebarSection.js";
|
|
@@ -11,7 +12,7 @@ import { MultiMenuField } from "./multi-menu-field.js";
|
|
|
11
12
|
import { AgentEditorDialog, ModelPickerField, sameModel } from "./TeamMemberEditor.js";
|
|
12
13
|
import createCss from './create.module.css';
|
|
13
14
|
import css from './sidebar.module.css';
|
|
14
|
-
export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }) {
|
|
15
|
+
export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, loadChannels, addMember, updateMember, recoverMember, clearMemberContext, joinChannel, removeChannelMember, loadModels, memberSessionId, openMemberSession, onCreatingChange, t }) {
|
|
15
16
|
const [members, setMembers] = useState([]);
|
|
16
17
|
const [channels, setChannels] = useState([]);
|
|
17
18
|
const [channelRefs, setChannelRefs] = useState([]);
|
|
@@ -36,6 +37,7 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, lo
|
|
|
36
37
|
void moveSidebarItem(workspaceId, 'agents', orderedAgentRefs, movedRef, targetRef, marker);
|
|
37
38
|
};
|
|
38
39
|
const drag = useSidebarRowDrag({ refs: orderedAgentRefs, onCommit: applyMove });
|
|
40
|
+
const sectionOpen = useSidebarSectionOpen(workspaceId, 'agents');
|
|
39
41
|
const refresh = useCallback(async () => {
|
|
40
42
|
setLoading(true);
|
|
41
43
|
const result = await loadMembers({ workspaceId });
|
|
@@ -132,31 +134,87 @@ export function TeamAgentsPanel({ workspaceId, loadMembers, subscribeChanges, lo
|
|
|
132
134
|
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 => {
|
|
133
135
|
setChannelRefs(current => current.includes(ref) ? current.filter(item => item !== ref) : [...current, ref]);
|
|
134
136
|
setRetryRequest(undefined);
|
|
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') })] }))] }));
|
|
137
|
+
}, 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'), open: sectionOpen, onToggle: open => { setSidebarSectionOpen(workspaceId, 'agents', open); }, actions: (_jsx(Tooltip, { label: t('addAgent'), delayMs: 500, children: _jsx("button", { ref: triggerRef, type: "button", className: css.iconButton, "aria-label": t('addAgent'), onClick: () => { setError(undefined); setFormOpen(true); }, children: _jsx(IconPlusOutline16, { size: 14 }) }) })), children: [loading && members.length === 0 && _jsx("p", { className: css.emptyState, children: t('loadingAgents') }), !loading && members.length === 0 && _jsx("p", { className: css.emptyState, children: t('emptyAgents') }), _jsx("div", { className: css.agentList, children: orderedMembers.map(status => (_jsx(SortableRow, { drag: drag, orderKey: status.member.memberId, children: _jsx(AgentRow, { status: status, ...(memberSessionId === undefined ? {} : { current: status.member.sessionId === memberSessionId }), channels: channels, loadChannels: loadChannels, updateMember: updateMember, recoverMember: recoverMember, clearMemberContext: clearMemberContext, 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') })] }))] }));
|
|
136
138
|
}
|
|
137
139
|
/**
|
|
138
140
|
* One sidebar Agent row: the select button opens the Member's own Session
|
|
139
141
|
* conversation page, the avatar carries identity plus the presence badge, and
|
|
140
142
|
* the row menu opens the editor.
|
|
141
143
|
*/
|
|
142
|
-
function AgentRow({ status, current, channels, loadChannels, updateMember, recoverMember, joinChannel, removeChannelMember, loadModels, openMemberSession, onUpdated, t }) {
|
|
144
|
+
function AgentRow({ status, current, channels, loadChannels, updateMember, recoverMember, clearMemberContext, joinChannel, removeChannelMember, loadModels, openMemberSession, onUpdated, t }) {
|
|
143
145
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
144
146
|
const [editing, setEditing] = useState(false);
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
const [clearing, setClearing] = useState(false);
|
|
148
|
+
const [rowAlert, setRowAlert] = useState();
|
|
149
|
+
// Both row actions ride the same runtime remote: the Host steers a live
|
|
150
|
+
// session, rebuilds an orphaned composition, or re-runs a failed activation.
|
|
151
|
+
const recover = async () => {
|
|
152
|
+
try {
|
|
153
|
+
const result = await recoverMember({
|
|
154
|
+
requestId: mintRequestId(),
|
|
155
|
+
workspaceId: status.member.workspaceId,
|
|
156
|
+
memberId: status.member.memberId,
|
|
157
|
+
});
|
|
158
|
+
await onUpdated();
|
|
159
|
+
if (!result.ok) {
|
|
160
|
+
setRowAlert(t('restartFailed', { message: result.error.message }));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (result.value.status.availability === 'unavailable') {
|
|
164
|
+
setRowAlert(t('restartStillUnavailable', { diagnostic: result.value.status.diagnostic ?? t('statusUnavailable') }));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
setRowAlert(undefined);
|
|
168
|
+
// A page opened while the Member was down predates the live Session;
|
|
169
|
+
// re-selecting is a no-op when already bound and rebinds when stale.
|
|
170
|
+
if (current === true)
|
|
171
|
+
openMemberSession(status.member.sessionId);
|
|
172
|
+
}
|
|
173
|
+
catch (cause) {
|
|
174
|
+
setRowAlert(t('restartFailed', { message: cause instanceof Error ? cause.message : String(cause) }));
|
|
175
|
+
}
|
|
152
176
|
};
|
|
177
|
+
const clearContext = async () => {
|
|
178
|
+
try {
|
|
179
|
+
const result = await clearMemberContext({
|
|
180
|
+
requestId: mintRequestId(),
|
|
181
|
+
workspaceId: status.member.workspaceId,
|
|
182
|
+
memberId: status.member.memberId,
|
|
183
|
+
});
|
|
184
|
+
await onUpdated();
|
|
185
|
+
if (!result.ok) {
|
|
186
|
+
setRowAlert(t('clearContextFailed', { message: result.error.message }));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
setRowAlert(undefined);
|
|
190
|
+
// The Host moved the Member onto a fresh Session id (the previous log
|
|
191
|
+
// stays archived on disk). A new id has no resident client instance, so
|
|
192
|
+
// re-entering the member view lazily instantiates it from host truth:
|
|
193
|
+
// blank hero, live updates, and no disposed-generation gray-out.
|
|
194
|
+
if (current === true)
|
|
195
|
+
openMemberSession(result.value.status.member.sessionId);
|
|
196
|
+
}
|
|
197
|
+
catch (cause) {
|
|
198
|
+
setRowAlert(t('clearContextFailed', { message: cause instanceof Error ? cause.message : String(cause) }));
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
// Error Members keep a live idle handle, so starting from a new context
|
|
202
|
+
// is available to them too — it doubles as a recovery path (the broken
|
|
203
|
+
// handle's error markers are dropped with it). Only a running turn or a
|
|
204
|
+
// missing handle gates the entry.
|
|
205
|
+
const contextClearable = status.presence === 'available' || status.presence === 'error';
|
|
153
206
|
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: [
|
|
154
207
|
{ id: 'edit', label: t('editAgent'), icon: _jsx(IconEditOutline16, {}) },
|
|
155
208
|
...(status.presence === 'error' ? [{ id: 'resume', label: t('resumeAgent'), icon: _jsx(IconPlayOutline16, {}) }] : []),
|
|
209
|
+
...(status.availability === 'unavailable' ? [{ id: 'restart', label: t('restartAgent'), icon: _jsx(IconRefreshOutline16, {}) }] : []),
|
|
210
|
+
{ id: 'clear-context', label: t('clearContextAgent'), icon: _jsx(IconNewChatOutline16, {}), danger: true, disabled: !contextClearable },
|
|
211
|
+
...(!contextClearable ? [{ type: 'label', id: 'clear-context-reason', text: status.presence === 'working' ? t('clearContextWorkingReason') : t('clearContextUnavailableReason') }] : []),
|
|
156
212
|
], onSelect: (id) => {
|
|
157
|
-
if (id === '
|
|
158
|
-
void resume();
|
|
159
|
-
else
|
|
213
|
+
if (id === 'edit')
|
|
160
214
|
setEditing(true);
|
|
161
|
-
|
|
215
|
+
else if (id === 'clear-context')
|
|
216
|
+
setClearing(true);
|
|
217
|
+
else
|
|
218
|
+
void recover();
|
|
219
|
+
}, onOpenChange: setMenuOpen }) })] }), rowAlert !== undefined && _jsx("div", { className: css.rowAlert, role: "alert", children: rowAlert }), clearing && (_jsx(Modal, { open: true, onClose: () => { setClearing(false); }, title: t('clearContextTitle', { name: status.member.handle }), closeLabel: t('close'), contentClassName: createCss.dialogContent, footer: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: () => { setClearing(false); }, children: t('cancel') }), _jsx(Button, { variant: "primary", onClick: () => { setClearing(false); void clearContext(); }, children: t('clearContextConfirm') })] }), children: _jsx("p", { className: createCss.error, children: t('clearContextNotice', { name: status.member.handle }) }) })), editing && (_jsx(AgentEditorDialog, { status: status, channels: channels, loadChannels: loadChannels, updateMember: updateMember, joinChannel: joinChannel, removeChannelMember: removeChannelMember, loadModels: loadModels, onCommitted: onUpdated, onClose: () => { setEditing(false); }, t: t }))] }));
|
|
162
220
|
}
|
|
@@ -1 +1 @@
|
|
|
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,+
|
|
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,+BAmVnR"}
|
|
@@ -39,6 +39,7 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
39
39
|
const [statusMessage, setStatusMessage] = useState();
|
|
40
40
|
const [loading, setLoading] = useState(true);
|
|
41
41
|
const [pending, setPending] = useState(false);
|
|
42
|
+
const [asTask, setAsTask] = useState(false);
|
|
42
43
|
const [loadingOlder, setLoadingOlder] = useState(false);
|
|
43
44
|
const [managingMembers, setManagingMembers] = useState(false);
|
|
44
45
|
// The composer draft lives in the keyed draft cache: view switches unmount
|
|
@@ -59,10 +60,30 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
59
60
|
selectChannel(ref);
|
|
60
61
|
return;
|
|
61
62
|
}
|
|
63
|
+
if (ref.startsWith('thread:')) {
|
|
64
|
+
const match = view?.items.find(item => item.thread.threadRef === ref);
|
|
65
|
+
if (match !== undefined) {
|
|
66
|
+
selectThread(match.thread.threadRef, channelRef, match.task?.taskRef, match.taskNumber);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// A ref may point outside the currently loaded Channel window. Ask the
|
|
70
|
+
// Host for the bounded Thread view so it can provide the home Channel.
|
|
71
|
+
void loadChannels({ workspaceId, threadRef: ref, includeActivities: false, limit: 1 }).then(result => {
|
|
72
|
+
if (!result.ok)
|
|
73
|
+
return;
|
|
74
|
+
const target = result.value.items[0];
|
|
75
|
+
if (target !== undefined) {
|
|
76
|
+
const targetChannel = result.value.channels.find(channel => channel.channelRef === target.message.channelRef);
|
|
77
|
+
if (targetChannel !== undefined)
|
|
78
|
+
selectThread(target.thread.threadRef, targetChannel.channelRef, target.task?.taskRef, target.taskNumber);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
62
83
|
if (ref.startsWith('task:')) {
|
|
63
|
-
const match = view?.items.find(item => item.task
|
|
84
|
+
const match = view?.items.find(item => item.task?.taskRef === ref);
|
|
64
85
|
if (match !== undefined) {
|
|
65
|
-
selectThread(match.
|
|
86
|
+
selectThread(match.thread.threadRef, channelRef, match.task?.taskRef, match.taskNumber);
|
|
66
87
|
return;
|
|
67
88
|
}
|
|
68
89
|
// Not in the loaded timeline: resolve through the Host and jump to the
|
|
@@ -236,6 +257,7 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
236
257
|
const request = {
|
|
237
258
|
requestId, workspaceId,
|
|
238
259
|
channelRef, body: draft.trim(), recipients: recipientIds,
|
|
260
|
+
asTask,
|
|
239
261
|
...(attachmentIds.length === 0 ? {} : { attachments: attachmentIds }),
|
|
240
262
|
};
|
|
241
263
|
const result = await sendMessage(request);
|
|
@@ -245,6 +267,7 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
245
267
|
}
|
|
246
268
|
else if (result.value.kind === 'committed') {
|
|
247
269
|
pendingSendId.current = undefined;
|
|
270
|
+
setAsTask(false);
|
|
248
271
|
await refresh();
|
|
249
272
|
drafts.clear(draftKey);
|
|
250
273
|
setPendingFiles([]);
|
|
@@ -279,12 +302,13 @@ export function TeamChannelPage({ workspaceId, channelRef, loadChannels, subscri
|
|
|
279
302
|
const senderStatus = members.find(member => member.member.memberId === item.message.sender);
|
|
280
303
|
const human = item.message.sender === view.humanMemberId;
|
|
281
304
|
const sender = human ? t('human') : senderStatus?.member.handle ?? item.message.sender;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
305
|
+
const turnGap = isRunGap(index > 0 ? block.items[index - 1].message.occurredAt : undefined, item.message.occurredAt);
|
|
306
|
+
// A turn divider already labels the gapped entry; its row stays chrome-free.
|
|
307
|
+
return _jsxs(Fragment, { children: [turnGap && _jsx(TeamRunDivider, { occurredAt: item.message.occurredAt }), _jsxs(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, showGroupedTime: item.message.topLevel === true && !turnGap, ...(senderStatus === undefined ? {} : { senderTitle: senderStatus.member.description }), children: [item.message.topLevel && item.task !== undefined && item.taskNumber !== undefined && _jsxs("button", { type: "button", className: channelCss.taskFooter, "aria-label": t('openTask', { number: item.taskNumber }), onClick: () => { selectThread(item.thread.threadRef, channelRef, item.task?.taskRef, item.taskNumber); }, children: [_jsx("span", { className: channelCss.taskDot, children: (() => {
|
|
308
|
+
const dot = taskStatusDot(item.task.status);
|
|
309
|
+
return dot === 'ongoing' || dot === 'warning' || dot === 'done'
|
|
310
|
+
? _jsx(StateDot, { size: 8, state: dot })
|
|
311
|
+
: _jsx("span", { className: channelCss.taskDotQuiet, "data-variant": dot });
|
|
312
|
+
})() }), _jsx("span", { className: channelCss.taskNumber, children: t('taskLabel', { number: item.taskNumber }) }), _jsx("span", { className: channelCss.taskStatus, children: formatTaskStatus(item.task.status, t) }), _jsx("span", { className: channelCss.taskCount, children: t('taskMessageCount', { count: item.messageCount }) }), _jsx("span", { className: channelCss.taskArrow, "aria-hidden": "true", children: _jsx(IconChevronRightOutline14, { size: 12 }) })] }), item.message.topLevel && item.task === undefined && _jsxs("button", { type: "button", className: channelCss.taskFooter, "aria-label": t('openThread'), onClick: () => { selectThread(item.thread.threadRef, channelRef); }, children: [_jsx("span", { className: channelCss.taskNumber, children: t('threadLabel') }), _jsx("span", { className: channelCss.taskCount, children: t('taskMessageCount', { count: item.messageCount }) }), _jsx("span", { className: channelCss.taskArrow, "aria-hidden": "true", children: _jsx(IconChevronRightOutline14, { size: 12 }) })] })] })] }, item.message.messageRef);
|
|
313
|
+
}) }, `run-${block.items[0].message.messageRef}`))] }) }), channel !== undefined ? _jsx(TeamComposer, { members: channelMembers, recipients: recipients, draft: draft, pending: pending, ...(statusMessage === undefined ? {} : { confirmation: statusMessage }), ...(error === undefined ? {} : { error }), onDraftChange: next => { drafts.writeDraft(draftKey, next); setStatusMessage(undefined); }, onRecipientsChange: next => { drafts.writeRecipients(draftKey, next); setStatusMessage(undefined); }, onSubmit: () => { void send(); }, pendingFiles: pendingFiles, onFilesChange: setPendingFiles, asTask: asTask, onAsTaskChange: setAsTask, t: t }, draftKey) : _jsx("div", {})] });
|
|
290
314
|
}
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAalD,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,+BA8L9D"}
|
|
@@ -5,6 +5,7 @@ import { TeamPresenceDot } from "./TeamPresenceDot.js";
|
|
|
5
5
|
import { MultiMenuField } from "./multi-menu-field.js";
|
|
6
6
|
import { SortableRow, useSidebarRowDrag } from "./sidebar-drag.js";
|
|
7
7
|
import { moveSidebarItem, useSidebarOrder } from "./sidebar-order.js";
|
|
8
|
+
import { useSidebarSectionOpen, setSidebarSectionOpen } from "./sidebar-sections.js";
|
|
8
9
|
import { mintRequestId } from "./requests.js";
|
|
9
10
|
import { TeamRowMenu } from "./TeamRowMenu.js";
|
|
10
11
|
import { TeamSidebarSection } from "./TeamSidebarSection.js";
|
|
@@ -37,6 +38,7 @@ export function TeamChannelsPanel(props) {
|
|
|
37
38
|
void moveSidebarItem(workspaceId, 'channels', orderedChannelRefs, movedRef, targetRef, marker);
|
|
38
39
|
};
|
|
39
40
|
const drag = useSidebarRowDrag({ refs: orderedChannelRefs, onCommit: applyMove });
|
|
41
|
+
const sectionOpen = useSidebarSectionOpen(workspaceId, 'channels');
|
|
40
42
|
const refresh = useCallback(async () => {
|
|
41
43
|
setLoading(true);
|
|
42
44
|
const [channelResult, memberResult] = await Promise.all([
|
|
@@ -144,7 +146,7 @@ export function TeamChannelsPanel(props) {
|
|
|
144
146
|
return next;
|
|
145
147
|
});
|
|
146
148
|
setPendingCreate(undefined);
|
|
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 => {
|
|
149
|
+
}, 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(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 => {
|
|
148
150
|
const joined = membership.get(channel.channelRef) ?? new Set();
|
|
149
151
|
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));
|
|
150
152
|
}) })] }), !formOpen && error !== undefined && _jsx("p", { className: css.error, role: "alert", children: error })] }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentTeamClientMemberStatus, AgentTeamMemberId } from '@wowyuarm/dsh-agent-team/types';
|
|
2
2
|
import type { TeamConversationProps } from './slots.ts';
|
|
3
|
-
export declare function TeamComposer({ members, recipients, draft, pending, confirmation, error, onDraftChange, onRecipientsChange, onSubmit, pendingFiles, onFilesChange, t }: {
|
|
3
|
+
export declare function TeamComposer({ members, recipients, draft, pending, confirmation, error, onDraftChange, onRecipientsChange, onSubmit, placeholder, pendingFiles, onFilesChange, asTask, onAsTaskChange, t }: {
|
|
4
4
|
readonly members: readonly AgentTeamClientMemberStatus[];
|
|
5
5
|
readonly recipients: ReadonlySet<AgentTeamMemberId>;
|
|
6
6
|
readonly draft: string;
|
|
@@ -10,9 +10,14 @@ export declare function TeamComposer({ members, recipients, draft, pending, conf
|
|
|
10
10
|
readonly onDraftChange: (draft: string) => void;
|
|
11
11
|
readonly onRecipientsChange: (recipients: ReadonlySet<AgentTeamMemberId>) => void;
|
|
12
12
|
readonly onSubmit: () => void;
|
|
13
|
+
/** Conversation-specific prompt; the shared default fits Channel surfaces. */
|
|
14
|
+
readonly placeholder?: string;
|
|
13
15
|
/** Upload-capable surfaces pass this to enable the "+" file picker; the reply path omits it. */
|
|
14
16
|
readonly pendingFiles?: readonly File[];
|
|
15
17
|
readonly onFilesChange?: (files: readonly File[]) => void;
|
|
18
|
+
/** Channel-only: create a real Task with the top-level Message. Default off. */
|
|
19
|
+
readonly asTask?: boolean;
|
|
20
|
+
readonly onAsTaskChange?: (asTask: boolean) => void;
|
|
16
21
|
readonly t: TeamConversationProps['t'];
|
|
17
22
|
}): import("react").JSX.Element;
|
|
18
23
|
//# sourceMappingURL=TeamComposer.d.ts.map
|
|
@@ -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;AA8DvD,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,EAAE,EAAE;IAC3M,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,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,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,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IACnD,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC,+BAqSA"}
|
|
@@ -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 } from 'react';
|
|
3
|
-
import { IconPlusOutline16, IconSendOutline16, useAnchoredMaxHeight, useDismissOnOutsidePointer } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
3
|
+
import { Button, 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
6
|
import { formatByteSize } from "./attachment-preview.js";
|
|
@@ -30,6 +30,13 @@ function mentionCandidates(members, query) {
|
|
|
30
30
|
&& status.member.state !== 'inactive'
|
|
31
31
|
&& status.member.handle.toLocaleLowerCase().startsWith(normalized));
|
|
32
32
|
}
|
|
33
|
+
/** Every member a manual handle pick could reach: the @all expansion snapshot. */
|
|
34
|
+
function allMentionMembers(members) {
|
|
35
|
+
return members.filter(status => status.presence !== 'unavailable' && status.member.state !== 'inactive');
|
|
36
|
+
}
|
|
37
|
+
function containsAllMention(draft) {
|
|
38
|
+
return /(?:^|[^\p{L}\p{N}_])@all(?=$|[^\p{L}\p{N}_])/u.test(draft);
|
|
39
|
+
}
|
|
33
40
|
/** One object URL per draft file; revoked when the draft is removed. */
|
|
34
41
|
const draftPreviewUrls = new WeakMap();
|
|
35
42
|
function draftPreviewUrl(file) {
|
|
@@ -42,7 +49,7 @@ function draftPreviewUrl(file) {
|
|
|
42
49
|
}
|
|
43
50
|
return url;
|
|
44
51
|
}
|
|
45
|
-
export function TeamComposer({ members, recipients, draft, pending, confirmation, error, onDraftChange, onRecipientsChange, onSubmit, pendingFiles, onFilesChange, t }) {
|
|
52
|
+
export function TeamComposer({ members, recipients, draft, pending, confirmation, error, onDraftChange, onRecipientsChange, onSubmit, placeholder, pendingFiles, onFilesChange, asTask, onAsTaskChange, t }) {
|
|
46
53
|
const inputRef = useRef(null);
|
|
47
54
|
const fileInputRef = useRef(null);
|
|
48
55
|
const rootRef = useRef(null);
|
|
@@ -50,9 +57,15 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
50
57
|
const composingRef = useRef(false);
|
|
51
58
|
const [mention, setMention] = useState();
|
|
52
59
|
const [highlight, setHighlight] = useState(0);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
60
|
+
// @all is a composer-layer expansion of the same eligibility filter a
|
|
61
|
+
// handle pick uses; the fixed row stays on top of the matching members.
|
|
62
|
+
const memberCandidates = mention === undefined ? [] : mentionCandidates(members, mention.query);
|
|
63
|
+
const options = mention !== undefined && 'all'.startsWith(mention.query.toLocaleLowerCase())
|
|
64
|
+
? [{ kind: 'all' }, ...memberCandidates.map(status => ({ kind: 'member', status }))]
|
|
65
|
+
: memberCandidates.map(status => ({ kind: 'member', status }));
|
|
66
|
+
const menuOpen = mention !== undefined && options.length > 0;
|
|
67
|
+
const activeOption = options[highlight];
|
|
68
|
+
const allCount = allMentionMembers(members).length;
|
|
56
69
|
const listId = 'team-mention-suggestions';
|
|
57
70
|
const menuMaxHeight = useAnchoredMaxHeight(menuRef, 320, menuOpen ? draft : null);
|
|
58
71
|
useDismissOnOutsidePointer(rootRef, menuOpen, open => { if (!open)
|
|
@@ -65,12 +78,12 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
65
78
|
input.style.height = `${Math.min(input.scrollHeight, 180)}px`;
|
|
66
79
|
}, [draft]);
|
|
67
80
|
useEffect(() => {
|
|
68
|
-
if (mention === undefined ||
|
|
81
|
+
if (mention === undefined || options.length === 0) {
|
|
69
82
|
setHighlight(0);
|
|
70
83
|
return;
|
|
71
84
|
}
|
|
72
|
-
setHighlight(current => Math.min(current,
|
|
73
|
-
}, [mention,
|
|
85
|
+
setHighlight(current => Math.min(current, options.length - 1));
|
|
86
|
+
}, [mention, options.length]);
|
|
74
87
|
// Match the resident DSH composer without stealing a later user choice: Team
|
|
75
88
|
// data can load after navigation, so a dialog or another control may already
|
|
76
89
|
// own focus by the time this composer appears.
|
|
@@ -88,6 +101,10 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
88
101
|
inputRef.current?.focus({ preventScroll: true });
|
|
89
102
|
}, [confirmation, pending]);
|
|
90
103
|
const pruneRecipients = (nextDraft) => {
|
|
104
|
+
// An @all marker stands for its expansion snapshot: the member handles it
|
|
105
|
+
// stands for are not in the text, so text-based pruning must stand down.
|
|
106
|
+
if (containsAllMention(nextDraft))
|
|
107
|
+
return;
|
|
91
108
|
const knownMembers = new Map(members.map(status => [status.member.memberId, status.member]));
|
|
92
109
|
const next = new Set([...recipients].filter(memberId => {
|
|
93
110
|
const member = knownMembers.get(memberId);
|
|
@@ -117,9 +134,31 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
117
134
|
pruneRecipients(nextDraft);
|
|
118
135
|
updateMention(nextDraft, event.target.selectionStart ?? nextDraft.length);
|
|
119
136
|
};
|
|
120
|
-
const
|
|
137
|
+
const selectOption = (option) => {
|
|
121
138
|
if (mention === undefined)
|
|
122
139
|
return;
|
|
140
|
+
if (option.kind === 'all') {
|
|
141
|
+
// Expand at pick time: the recipients snapshot is every eligible member
|
|
142
|
+
// a handle pick could reach at this moment.
|
|
143
|
+
const nextDraft = `${draft.slice(0, mention.start)}@all ${draft.slice(mention.end)}`;
|
|
144
|
+
const nextCaret = mention.start + '@all '.length;
|
|
145
|
+
const nextRecipients = new Set(recipients);
|
|
146
|
+
for (const status of allMentionMembers(members))
|
|
147
|
+
nextRecipients.add(status.member.memberId);
|
|
148
|
+
onDraftChange(nextDraft);
|
|
149
|
+
onRecipientsChange(nextRecipients);
|
|
150
|
+
setMention(undefined);
|
|
151
|
+
setHighlight(0);
|
|
152
|
+
requestAnimationFrame(() => {
|
|
153
|
+
const input = inputRef.current;
|
|
154
|
+
if (input === null)
|
|
155
|
+
return;
|
|
156
|
+
input.focus({ preventScroll: true });
|
|
157
|
+
input.setSelectionRange(nextCaret, nextCaret);
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const member = option.status;
|
|
123
162
|
const inserted = `@${member.member.handle} `;
|
|
124
163
|
const nextDraft = `${draft.slice(0, mention.start)}${inserted}${draft.slice(mention.end)}`;
|
|
125
164
|
const nextCaret = mention.start + inserted.length;
|
|
@@ -136,16 +175,31 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
136
175
|
input.setSelectionRange(nextCaret, nextCaret);
|
|
137
176
|
});
|
|
138
177
|
};
|
|
178
|
+
// Pasted files (screenshots, copies) join the same chips the "+" picker
|
|
179
|
+
// fills; only a paste that carries files is intercepted, so plain text
|
|
180
|
+
// keeps the browser's native insertion.
|
|
181
|
+
const onPaste = (event) => {
|
|
182
|
+
if (pending || onFilesChange === undefined || pendingFiles === undefined)
|
|
183
|
+
return;
|
|
184
|
+
const files = Array.from(event.clipboardData.items)
|
|
185
|
+
.filter(item => item.kind === 'file')
|
|
186
|
+
.map(item => item.getAsFile())
|
|
187
|
+
.filter((file) => file !== null);
|
|
188
|
+
if (files.length === 0)
|
|
189
|
+
return;
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
onFilesChange([...pendingFiles, ...files]);
|
|
192
|
+
};
|
|
139
193
|
const onKeyDown = (event) => {
|
|
140
194
|
const composing = composingRef.current || event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229;
|
|
141
195
|
if (menuOpen && event.key === 'ArrowDown') {
|
|
142
196
|
event.preventDefault();
|
|
143
|
-
setHighlight(current => (current + 1) %
|
|
197
|
+
setHighlight(current => (current + 1) % options.length);
|
|
144
198
|
return;
|
|
145
199
|
}
|
|
146
200
|
if (menuOpen && event.key === 'ArrowUp') {
|
|
147
201
|
event.preventDefault();
|
|
148
|
-
setHighlight(current => (current - 1 +
|
|
202
|
+
setHighlight(current => (current - 1 + options.length) % options.length);
|
|
149
203
|
return;
|
|
150
204
|
}
|
|
151
205
|
if (event.key === 'Escape' && menuOpen) {
|
|
@@ -156,15 +210,15 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
156
210
|
// Tab accepts the highlighted candidate; Shift+Tab keeps default focus reversal.
|
|
157
211
|
if (menuOpen && event.key === 'Tab' && !event.shiftKey) {
|
|
158
212
|
event.preventDefault();
|
|
159
|
-
if (
|
|
160
|
-
|
|
213
|
+
if (activeOption !== undefined)
|
|
214
|
+
selectOption(activeOption);
|
|
161
215
|
return;
|
|
162
216
|
}
|
|
163
217
|
if (event.key !== 'Enter' || event.shiftKey || composing || event.repeat)
|
|
164
218
|
return;
|
|
165
|
-
if (menuOpen &&
|
|
219
|
+
if (menuOpen && activeOption !== undefined) {
|
|
166
220
|
event.preventDefault();
|
|
167
|
-
|
|
221
|
+
selectOption(activeOption);
|
|
168
222
|
return;
|
|
169
223
|
}
|
|
170
224
|
event.preventDefault();
|
|
@@ -175,11 +229,13 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
175
229
|
event.preventDefault();
|
|
176
230
|
if (!pending && draft.trim() !== '')
|
|
177
231
|
onSubmit();
|
|
178
|
-
}, children: [_jsxs("div", { className: css.card, "data-team-composer": true, children: [confirmation !== undefined && _jsx("p", { className: css.confirmation, role: "status", children: confirmation }), _jsxs("div", { className: css.inputArea, children: [menuOpen && _jsx("div", { id: listId, ref: menuRef, className: css.mentionMenu, role: "listbox", "aria-label": t('mentionSuggestions'), style: { maxHeight: menuMaxHeight }, children:
|
|
179
|
-
const optionId = `${listId}-${status.member.memberId}`;
|
|
232
|
+
}, children: [_jsxs("div", { className: css.card, "data-team-composer": true, children: [confirmation !== undefined && _jsx("p", { className: css.confirmation, role: "status", children: confirmation }), _jsxs("div", { className: css.inputArea, children: [menuOpen && _jsx("div", { id: listId, ref: menuRef, className: css.mentionMenu, role: "listbox", "aria-label": t('mentionSuggestions'), style: { maxHeight: menuMaxHeight }, children: options.map((option, index) => {
|
|
233
|
+
const optionId = option.kind === 'all' ? `${listId}-all` : `${listId}-${option.status.member.memberId}`;
|
|
180
234
|
const selected = index === highlight;
|
|
181
|
-
return
|
|
182
|
-
|
|
235
|
+
return option.kind === 'all'
|
|
236
|
+
? _jsxs("button", { id: optionId, type: "button", role: "option", "aria-selected": selected, className: css.mentionOption, onMouseDown: event => { event.preventDefault(); }, onClick: () => { selectOption(option); }, children: [_jsx("span", { className: css.mentionAllDot, "aria-hidden": "true" }), _jsx("span", { className: css.mentionName, children: "@all" }), _jsx("span", { className: css.mentionDescription, children: t('mentionAll', { count: allCount }) })] }, "all")
|
|
237
|
+
: _jsxs("button", { id: optionId, type: "button", role: "option", "aria-selected": selected, className: css.mentionOption, onMouseDown: event => { event.preventDefault(); }, onClick: () => { selectOption(option); }, children: [_jsx(TeamPresenceDot, { status: option.status, t: t }), _jsxs("span", { className: css.mentionName, children: ["@", option.status.member.handle] }), _jsx("span", { className: css.mentionDescription, children: option.status.member.description })] }, option.status.member.memberId);
|
|
238
|
+
}) }), _jsx("textarea", { ref: inputRef, "aria-label": t('messageDraft'), "aria-autocomplete": "list", "aria-controls": menuOpen ? listId : undefined, "aria-activedescendant": menuOpen && activeOption !== undefined ? activeOption.kind === 'all' ? `${listId}-all` : `${listId}-${activeOption.status.member.memberId}` : undefined, "aria-expanded": menuOpen, value: draft, readOnly: pending, placeholder: placeholder ?? t('messagePlaceholder'), rows: 1, onChange: onChange, onPaste: onPaste, 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
239
|
const previewUrl = draftPreviewUrl(file);
|
|
184
240
|
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
241
|
const url = draftPreviewUrls.get(file);
|
|
@@ -187,7 +243,7 @@ export function TeamComposer({ members, recipients, draft, pending, confirmation
|
|
|
187
243
|
URL.revokeObjectURL(url);
|
|
188
244
|
onFilesChange(pendingFiles.filter((_, candidate) => candidate !== index));
|
|
189
245
|
}, 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 => {
|
|
246
|
+
}) })), _jsxs("div", { className: css.toolbar, children: [onAsTaskChange !== undefined && (_jsx(Button, { size: "sm", variant: "outline", className: asTask === true ? css.asTaskOn : undefined, "aria-pressed": asTask === true, disabled: pending, onClick: () => { onAsTaskChange(asTask !== true); }, children: t('asTask') })), onFilesChange !== undefined && (_jsxs(_Fragment, { children: [_jsx("input", { ref: fileInputRef, type: "file", multiple: true, className: css.fileInput, "aria-hidden": "true", tabIndex: -1, onChange: event => {
|
|
191
247
|
const chosen = [...event.target.files ?? []];
|
|
192
248
|
if (chosen.length > 0 && pendingFiles !== undefined)
|
|
193
249
|
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, selectChannel, backToWorkspace, backToChannels, resolveTaskRefs }: 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, promoteThread, 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,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,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,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,EAAE,qBAAqB,+BAoBzW"}
|
|
@@ -3,12 +3,12 @@ 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, selectChannel, backToWorkspace, backToChannels, resolveTaskRefs }) {
|
|
6
|
+
export function TeamConversation({ t, useWorkspaces, navigation, drafts, putAttachment, getAttachment, loadChannels, readThread, loadThreadHistory, subscribeChanges, loadMembers, sendMessage, joinChannel, removeChannelMember, reply, changeTask, promoteThread, 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
|
-
if (current !== undefined && navigationState.
|
|
11
|
-
return _jsx(TeamThreadPage, { workspaceId: current.workspaceId, putAttachment: putAttachment,
|
|
10
|
+
if (current !== undefined && navigationState.threadRef !== undefined) {
|
|
11
|
+
return _jsx(TeamThreadPage, { workspaceId: current.workspaceId, putAttachment: putAttachment, threadRef: navigationState.threadRef, backToWorkspace: backToWorkspace, selectChannel: selectChannel, selectThread: selectThread, resolveTaskRefs: resolveTaskRefs, ...(navigationState.channelRef === undefined ? {} : { channelRef: navigationState.channelRef }), ...(navigationState.taskRef === undefined ? {} : { taskRef: navigationState.taskRef }), ...(navigationState.taskNumber === undefined ? {} : { taskNumber: navigationState.taskNumber }), drafts: drafts, getAttachment: getAttachment, readThread: readThread, loadChannels: loadChannels, loadThreadHistory: loadThreadHistory, subscribeChanges: subscribeChanges, loadMembers: loadMembers, reply: reply, changeTask: changeTask, promoteThread: promoteThread, t: t }, navigationState.threadRef);
|
|
12
12
|
}
|
|
13
13
|
if (current !== undefined && navigationState.channelRef !== undefined) {
|
|
14
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);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamMemberSessionComposer.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMemberSessionComposer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACpE,OAAO,KAAK,EAAE,sBAAsB,EAAc,MAAM,iDAAiD,CAAA;AAIzG,+EAA+E;AAC/E,MAAM,MAAM,8BAA8B,GAAG,YAAY,CAAC,2BAA2B,CAAC,GAAG;IACvF,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAA;IAC3C,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAA;IACxC,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,KAAK,IAAI,CAAA;CACxD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,8BAA8B,+
|
|
1
|
+
{"version":3,"file":"TeamMemberSessionComposer.d.ts","sourceRoot":"","sources":["../../../src/client/TeamMemberSessionComposer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACpE,OAAO,KAAK,EAAE,sBAAsB,EAAc,MAAM,iDAAiD,CAAA;AAIzG,+EAA+E;AAC/E,MAAM,MAAM,8BAA8B,GAAG,YAAY,CAAC,2BAA2B,CAAC,GAAG;IACvF,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAA;IAC3C,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAA;IACxC,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,KAAK,IAAI,CAAA;CACxD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,8BAA8B,+BA4HvL"}
|