@wowyuarm/dsh-agent-team 0.1.14-alpha.2 → 0.1.14
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 +5 -3
- package/README.zh.md +5 -3
- package/cordis.patch.yml +2 -185
- package/package.json +52 -46
- package/packages/agent-team/README.md +1 -1
- package/packages/agent-team/README.zh.md +1 -1
- package/packages/agent-team/core-skills/member-memory-manager/SKILL.md +30 -0
- package/packages/agent-team/lib/context-continuity-host.js +91 -0
- package/packages/agent-team/lib/context-projection.js +266 -489
- package/packages/agent-team/lib/context-source.js +17 -106
- package/packages/agent-team/lib/human-avatar.js +61 -0
- package/packages/agent-team/lib/human-profile.js +46 -0
- package/packages/agent-team/lib/human-update-check.js +119 -0
- package/packages/agent-team/lib/index.js +408 -264
- package/packages/agent-team/lib/ledger.js +120 -15
- package/packages/agent-team/lib/member-context.js +9 -8
- package/packages/agent-team/lib/member-runtime.js +1 -1
- package/packages/agent-team/lib/member-time-context.js +2 -5
- package/packages/agent-team/lib/preset-roster.js +15 -0
- package/packages/agent-team/lib/pressure-policy.js +9 -6
- package/packages/agent-team/lib/session-remediation.js +493 -0
- package/packages/agent-team/lib/stored-session-reader.js +2 -1
- package/packages/agent-team/lib/typert.host.js +605 -291
- package/packages/agent-team/lib/typert.remote-client.d.ts +15 -6
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +367 -244
- package/packages/agent-team/lib/types/context-continuity-host.d.ts +84 -0
- package/packages/agent-team/lib/types/context-continuity-host.d.ts.map +1 -0
- package/packages/agent-team/lib/types/context-projection.d.ts +130 -185
- package/packages/agent-team/lib/types/context-projection.d.ts.map +1 -1
- package/packages/agent-team/lib/types/context-source.d.ts +17 -81
- package/packages/agent-team/lib/types/context-source.d.ts.map +1 -1
- package/packages/agent-team/lib/types/human-avatar.d.ts +29 -0
- package/packages/agent-team/lib/types/human-avatar.d.ts.map +1 -0
- package/packages/agent-team/lib/types/human-profile.d.ts +44 -0
- package/packages/agent-team/lib/types/human-profile.d.ts.map +1 -0
- package/packages/agent-team/lib/types/human-update-check.d.ts +73 -0
- package/packages/agent-team/lib/types/human-update-check.d.ts.map +1 -0
- package/packages/agent-team/lib/types/index.d.ts +112 -38
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/ledger.d.ts +31 -2
- package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-context.d.ts +0 -14
- package/packages/agent-team/lib/types/member-context.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-time-context.d.ts +0 -15
- package/packages/agent-team/lib/types/member-time-context.d.ts.map +1 -1
- package/packages/agent-team/lib/types/preset-roster.d.ts +5 -0
- package/packages/agent-team/lib/types/preset-roster.d.ts.map +1 -0
- package/packages/agent-team/lib/types/pressure-policy.d.ts +6 -0
- package/packages/agent-team/lib/types/pressure-policy.d.ts.map +1 -1
- package/packages/agent-team/lib/types/session-remediation.d.ts +172 -0
- package/packages/agent-team/lib/types/session-remediation.d.ts.map +1 -0
- package/packages/agent-team/lib/types/stored-session-reader.d.ts +2 -1
- package/packages/agent-team/lib/types/stored-session-reader.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/entities.d.ts +20 -3
- package/packages/agent-team/lib/types/types/entities.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/requests-results.d.ts +63 -0
- package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
- package/packages/agent-team/preset/team-member/agent.cordis.yml +166 -0
- package/packages/client-agent-team/lib/client.js +1667 -516
- package/packages/client-agent-team/lib/client.js.map +1 -1
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts +15 -0
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.js +115 -0
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +12 -8
- package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts +22 -1
- package/packages/client-agent-team/lib/types/client/TeamAvatarStack.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAvatarStack.js +25 -2
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +6 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +69 -31
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +4 -4
- package/packages/client-agent-team/lib/types/client/TeamComposer.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.js +12 -5
- package/packages/client-agent-team/lib/types/client/TeamFooterAction.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts +4 -1
- package/packages/client-agent-team/lib/types/client/TeamInboxPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamInboxPage.js +22 -7
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts +11 -1
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMemberEditor.js +69 -8
- package/packages/client-agent-team/lib/types/client/TeamMembersAction.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +18 -3
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMessage.js +213 -67
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamRowMenu.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamSidebarSection.js +2 -2
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +5 -0
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +55 -29
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceSelector.js +2 -2
- package/packages/client-agent-team/lib/types/client/avatar-image.d.ts +21 -0
- package/packages/client-agent-team/lib/types/client/avatar-image.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/avatar-image.js +9 -0
- package/packages/client-agent-team/lib/types/client/human-identity.d.ts +94 -0
- package/packages/client-agent-team/lib/types/client/human-identity.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/human-identity.js +117 -0
- package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/index.js +112 -41
- package/packages/client-agent-team/lib/types/client/locales.d.ts +72 -2
- package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/locales.js +78 -2
- package/packages/client-agent-team/lib/types/client/multi-menu-field.js +2 -2
- package/packages/client-agent-team/lib/types/client/refs.d.ts +71 -0
- package/packages/client-agent-team/lib/types/client/refs.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/refs.js +181 -0
- package/packages/client-agent-team/lib/types/client/slots.d.ts +8 -2
- package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +57 -9
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.js +85 -17
- package/packages/tool-agent-team/README.md +1 -1
- package/packages/tool-agent-team/README.zh.md +1 -1
- package/packages/tool-agent-team/lib/context-tools.js +20 -6
- package/packages/tool-agent-team/lib/index.js +2 -2
- package/packages/tool-agent-team/lib/types/context-tools.d.ts.map +1 -1
- package/packages/agent-team/lib/context-management.js +0 -371
- package/packages/agent-team/lib/types/context-management.d.ts +0 -154
- package/packages/agent-team/lib/types/context-management.d.ts.map +0 -1
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts +0 -31
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +0 -1
- package/packages/client-agent-team/lib/types/client/task-refs.js +0 -99
|
@@ -2,8 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Fragment, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { MarkdownText, Modal } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { cachedAttachmentDataUrl, formatByteSize, loadAttachmentDataUrl } from "./attachment-preview.js";
|
|
5
|
-
import { cachedResolvedTaskRef, resolveUnknownTaskRefs, useResolvedTaskRefVersion } from "./
|
|
5
|
+
import { cachedResolvedTaskRef, resolveUnknownTaskRefs, useResolvedTaskRefVersion } from "./refs.js";
|
|
6
|
+
import { cachedResolvedThreadRef, resolveUnknownThreadRefs, useResolvedThreadRefVersion } from "./refs.js";
|
|
6
7
|
import { formatMessageTime, isSingleBrandedRef, memberHue, planMessageBody, shouldClampMessage, splitBrandedRefs, splitMentionNames } from "./team-formatters.js";
|
|
8
|
+
import { useAvatarImage } from "./avatar-image.js";
|
|
7
9
|
import css from './conversation.module.css';
|
|
8
10
|
/**
|
|
9
11
|
* One chat message row with identity chrome and sender-appropriate rendering.
|
|
@@ -13,30 +15,49 @@ import css from './conversation.module.css';
|
|
|
13
15
|
* skipping a render here never detaches it. Callers must therefore keep the
|
|
14
16
|
* props they derive per render (mention names, ref callbacks) identity-stable.
|
|
15
17
|
*/
|
|
16
|
-
export const TeamMessage = memo(function TeamMessage({ senderName, memberId, human, body, occurredAt, mentionNames, senderTitle, grouped, showGroupedTime, attachments, loadAttachment, t, onOpenRef, onResolveTaskRefs, children }) {
|
|
18
|
+
export const TeamMessage = memo(function TeamMessage({ senderName, memberId, human, avatarUrl, body, occurredAt, mentionNames, senderTitle, grouped, showGroupedTime, attachments, loadAttachment, t, onOpenRef, onResolveTaskRefs, onResolveThreadRefs, channelNameOf, memberOf, onOpenMemberSession, children }) {
|
|
17
19
|
const avatarStyle = human ? undefined : { '--team-avatar-hue': memberHue(memberId) };
|
|
20
|
+
// Only the Human's own row may draw a picture: the profile owns those bytes,
|
|
21
|
+
// and one seat painting the reader's face for another author would name two
|
|
22
|
+
// people alike. A seat draws it while those bytes decode; anything else keeps
|
|
23
|
+
// the initial, which is what the fallback promises.
|
|
24
|
+
const identityImage = useAvatarImage(human ? avatarUrl : undefined);
|
|
18
25
|
// Literal bodies carry mention chips inline — Human input always, and
|
|
19
26
|
// plain-prose Agent bodies where literal rendering loses nothing. Rich
|
|
20
27
|
// Markdown keeps unmatched structured mentions in the trailing row.
|
|
21
28
|
// The stored body carries machine-facing `[attachment] <path>` prompt lines;
|
|
22
29
|
// humans see the attachment strip rendered from the message metadata instead.
|
|
23
30
|
// One pure plan resolves the stored body into the rendering branch, the
|
|
24
|
-
// trailing fallback rows, and the literal Task refs that resolve in place.
|
|
31
|
+
// trailing fallback rows, and the literal Task/Thread refs that resolve in place.
|
|
25
32
|
const plan = planMessageBody(body, { human, ...(mentionNames === undefined ? {} : { mentionNames }), canOpenRefs: onOpenRef !== undefined });
|
|
26
33
|
const displayBody = plan.displayBody;
|
|
27
34
|
const { richAgentBody } = plan;
|
|
28
|
-
// Resolved refs re-label once the Host lookup lands; the version
|
|
29
|
-
//
|
|
30
|
-
const
|
|
35
|
+
// Resolved refs re-label once the Host lookup lands; the version tokens
|
|
36
|
+
// refresh literal links and rendered Markdown prose.
|
|
37
|
+
const taskRefVersion = useResolvedTaskRefVersion();
|
|
38
|
+
const threadRefVersion = useResolvedThreadRefVersion();
|
|
31
39
|
const bodyTaskRefs = plan.taskRefs;
|
|
32
40
|
const bodyTaskRefKey = bodyTaskRefs.join(',');
|
|
41
|
+
const bodyThreadRefs = plan.threadRefs;
|
|
42
|
+
const bodyThreadRefKey = bodyThreadRefs.join(',');
|
|
33
43
|
useEffect(() => {
|
|
34
|
-
if (onResolveTaskRefs
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
if (onResolveTaskRefs !== undefined && bodyTaskRefKey !== '')
|
|
45
|
+
void resolveUnknownTaskRefs(bodyTaskRefs, onResolveTaskRefs);
|
|
46
|
+
if (onResolveThreadRefs !== undefined && bodyThreadRefKey !== '')
|
|
47
|
+
void resolveUnknownThreadRefs(bodyThreadRefs, onResolveThreadRefs);
|
|
48
|
+
}, [onResolveTaskRefs, onResolveThreadRefs, bodyTaskRefKey, bodyThreadRefKey, taskRefVersion, threadRefVersion]);
|
|
38
49
|
const taskLabel = useCallback((taskNumber) => t?.('taskLabel', { number: taskNumber }) ?? `Task #${taskNumber}`, [t]);
|
|
39
|
-
|
|
50
|
+
// Thread chips carry the cited Thread's opening-line gist, so one taskless
|
|
51
|
+
// Thread no longer reads exactly like the next. Unresolvable refs never
|
|
52
|
+
// reach this label — they stay plain text (see renderRefs).
|
|
53
|
+
const threadChipLabel = useCallback((title) => {
|
|
54
|
+
const base = t?.('threadLabel') ?? 'Thread';
|
|
55
|
+
return title === '' ? base : `${base} · ${title}`;
|
|
56
|
+
}, [t]);
|
|
57
|
+
// Channel chips name the cited Channel; member chips name the cited Member
|
|
58
|
+
// with a handle — deliberately distinct from `@mention` chips, which notify.
|
|
59
|
+
const channelChipLabel = useCallback((name) => t?.('channelLabel', { name }) ?? `Channel · ${name}`, [t]);
|
|
60
|
+
const memberChipLabel = useCallback((name) => t?.('memberLabel', { name }) ?? `Member · @${name}`, [t]);
|
|
40
61
|
// Markdown chrome (code-copy buttons, footnotes heading) is locale copy the
|
|
41
62
|
// cordis-free primitive receives via props. Stable per locale revision — a
|
|
42
63
|
// fresh object per render would rebuild the component table every chunk.
|
|
@@ -61,19 +82,31 @@ export const TeamMessage = memo(function TeamMessage({ senderName, memberId, hum
|
|
|
61
82
|
.flatMap(text => splitBrandedRefs(text)
|
|
62
83
|
.filter(segment => segment.ref?.startsWith('task:') === true)
|
|
63
84
|
.map(segment => segment.ref)))];
|
|
85
|
+
const threadRefs = [...new Set([...textNodes.map(node => node.data), ...styledRefCodes.map(code => code.textContent ?? '')]
|
|
86
|
+
.flatMap(text => splitBrandedRefs(text)
|
|
87
|
+
.filter(segment => segment.ref?.startsWith('thread:') === true)
|
|
88
|
+
.map(segment => segment.ref)))];
|
|
64
89
|
if (onResolveTaskRefs !== undefined && taskRefs.length > 0)
|
|
65
90
|
void resolveUnknownTaskRefs(taskRefs, onResolveTaskRefs);
|
|
91
|
+
if (onResolveThreadRefs !== undefined && threadRefs.length > 0)
|
|
92
|
+
void resolveUnknownThreadRefs(threadRefs, onResolveThreadRefs);
|
|
66
93
|
for (const code of styledRefCodes)
|
|
67
|
-
renderResolvedMarkdownCodeRef(code, taskLabel,
|
|
94
|
+
renderResolvedMarkdownCodeRef(code, taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf);
|
|
68
95
|
for (const node of textNodes)
|
|
69
|
-
renderResolvedMarkdownText(node, mentionNames ?? [], taskLabel,
|
|
96
|
+
renderResolvedMarkdownText(node, mentionNames ?? [], taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf);
|
|
70
97
|
for (const button of root.querySelectorAll('button[data-task-ref]')) {
|
|
71
98
|
const taskRef = button.dataset.taskRef;
|
|
72
99
|
const hit = taskRef === undefined ? undefined : cachedResolvedTaskRef(taskRef);
|
|
73
100
|
if (taskRef !== undefined && hit !== undefined)
|
|
74
101
|
button.textContent = taskLabel(hit.taskNumber);
|
|
75
102
|
}
|
|
76
|
-
|
|
103
|
+
for (const button of root.querySelectorAll('button[data-thread-ref]')) {
|
|
104
|
+
const threadRef = button.dataset.threadRef;
|
|
105
|
+
const hit = threadRef === undefined ? undefined : cachedResolvedThreadRef(threadRef);
|
|
106
|
+
if (threadRef !== undefined && hit !== undefined)
|
|
107
|
+
button.textContent = threadChipLabel(hit.title);
|
|
108
|
+
}
|
|
109
|
+
}, [richAgentBody, onOpenRef, onResolveTaskRefs, onResolveThreadRefs, taskRefVersion, threadRefVersion, taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf, mentionNames]);
|
|
77
110
|
useEffect(() => {
|
|
78
111
|
const root = markdownRef.current;
|
|
79
112
|
if (!richAgentBody || root === null || onOpenRef === undefined)
|
|
@@ -82,24 +115,35 @@ export const TeamMessage = memo(function TeamMessage({ senderName, memberId, hum
|
|
|
82
115
|
const target = event.target;
|
|
83
116
|
if (!(target instanceof Element))
|
|
84
117
|
return;
|
|
85
|
-
const button = target.closest('button[data-ref], button[data-task-ref]');
|
|
118
|
+
const button = target.closest('button[data-ref], button[data-task-ref], button[data-thread-ref], button[data-member-session]');
|
|
86
119
|
if (button === null || !root.contains(button))
|
|
87
120
|
return;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
onOpenRef
|
|
121
|
+
if (button instanceof HTMLElement) {
|
|
122
|
+
// Member chips carry their session, not a Team ref: the same jump
|
|
123
|
+
// the agent card performs. Every other chip resolves to onOpenRef.
|
|
124
|
+
const sessionId = button.dataset.memberSession;
|
|
125
|
+
if (sessionId !== undefined) {
|
|
126
|
+
onOpenMemberSession?.(sessionId);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const ref = button.dataset.ref ?? button.dataset.taskRef ?? button.dataset.threadRef;
|
|
130
|
+
if (ref !== undefined)
|
|
131
|
+
onOpenRef(ref);
|
|
132
|
+
}
|
|
91
133
|
};
|
|
92
134
|
root.addEventListener('click', openTask);
|
|
93
135
|
return () => { root.removeEventListener('click', openTask); };
|
|
94
|
-
}, [richAgentBody, onOpenRef]);
|
|
136
|
+
}, [richAgentBody, onOpenRef, onOpenMemberSession]);
|
|
95
137
|
const bodyNode = plan.render === 'inline' && plan.inline !== undefined
|
|
96
138
|
? _jsx("div", { className: css.messageText, children: plan.inline.segments.map((segment, index) => segment.mention
|
|
97
139
|
? _jsx("span", { className: css.mention, children: segment.text }, index)
|
|
98
|
-
: _jsx(Fragment, { children: renderRefs(segment.text, onOpenRef, taskLabel,
|
|
140
|
+
: _jsx(Fragment, { children: renderRefs(segment.text, onOpenRef, onOpenMemberSession, taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf) }, index)) })
|
|
99
141
|
: plan.render === 'literal'
|
|
100
|
-
? _jsx("div", { className: css.messageText, children: onOpenRef === undefined ? displayBody : renderRefs(displayBody, onOpenRef, taskLabel,
|
|
142
|
+
? _jsx("div", { className: css.messageText, children: onOpenRef === undefined ? displayBody : renderRefs(displayBody, onOpenRef, onOpenMemberSession, taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf) })
|
|
101
143
|
: _jsx("div", { ref: markdownRef, className: css.messageMarkdown, children: _jsx(MarkdownText, { text: displayBody, labels: markdownLabels }, `${displayBody}:${onOpenRef === undefined ? 'literal' : 'refs'}`) });
|
|
102
|
-
return (_jsxs("article", { className: css.messageRow, "data-human": human || undefined, "data-grouped": grouped || undefined, children: [
|
|
144
|
+
return (_jsxs("article", { className: css.messageRow, "data-human": human || undefined, "data-grouped": grouped || undefined, children: [identityImage.src === undefined
|
|
145
|
+
? _jsx("div", { className: css.messageIdentity, "data-avatar": "initial", style: avatarStyle, "aria-hidden": "true", children: senderName.replace('@', '').slice(0, 1).toUpperCase() })
|
|
146
|
+
: _jsx("img", { className: css.messageIdentityImage, "data-avatar": "image", src: identityImage.src, alt: "", "aria-hidden": "true", onError: identityImage.failed }), _jsxs("div", { className: css.messageBody, children: [(!grouped || showGroupedTime === true) && (_jsxs("div", { className: css.nameRow, children: [!grouped && _jsx("strong", { ...(senderTitle === undefined ? {} : { title: senderTitle }), children: senderName }), occurredAt !== undefined && _jsx("span", { className: css.messageTime, children: formatMessageTime(occurredAt) })] })), clampable ? _jsx("div", { className: clamped ? css.messageClamp : undefined, children: bodyNode }) : bodyNode, clampable && (_jsx("button", { type: "button", className: css.messageExpand, "data-message-expand": "true", "aria-expanded": expanded, onClick: () => { setExpanded(value => !value); }, children: expanded ? (t?.('collapseMessage') ?? 'Show less') : (t?.('expandMessage') ?? 'Show more') })), (plan.fallbackNames.length > 0 || plan.fallbackRefs.length > 0) && (_jsxs("div", { className: css.mentionsRow, children: [plan.fallbackNames.map(name => _jsxs("span", { className: css.mention, children: ["@", name] }, name)), plan.fallbackRefs.map(ref => {
|
|
103
147
|
const resolved = cachedResolvedTaskRef(ref);
|
|
104
148
|
const label = resolved !== undefined && ref.startsWith('task:') ? taskLabel(resolved.taskNumber) : ref;
|
|
105
149
|
return _jsx("button", { type: "button", className: css.refLink, title: ref, onClick: () => { onOpenRef(ref); }, children: label }, ref);
|
|
@@ -146,32 +190,89 @@ function resolvedTaskRefButton(taskRef, label) {
|
|
|
146
190
|
button.textContent = label;
|
|
147
191
|
return button;
|
|
148
192
|
}
|
|
149
|
-
/**
|
|
150
|
-
function
|
|
193
|
+
/** One resolved Thread-ref chip built outside React, matching the styled ref link. */
|
|
194
|
+
function resolvedThreadRefButton(threadRef, label) {
|
|
195
|
+
const button = document.createElement('button');
|
|
196
|
+
button.type = 'button';
|
|
197
|
+
if (css.refLink !== undefined)
|
|
198
|
+
button.className = css.refLink;
|
|
199
|
+
button.dataset.threadRef = threadRef;
|
|
200
|
+
button.title = threadRef;
|
|
201
|
+
button.textContent = label;
|
|
202
|
+
return button;
|
|
203
|
+
}
|
|
204
|
+
/** One roster-resolved Channel chip built outside React, matching the styled ref link. */
|
|
205
|
+
function resolvedChannelRefButton(channelRef, label) {
|
|
206
|
+
const button = document.createElement('button');
|
|
207
|
+
button.type = 'button';
|
|
208
|
+
if (css.refLink !== undefined)
|
|
209
|
+
button.className = css.refLink;
|
|
210
|
+
button.dataset.ref = channelRef;
|
|
211
|
+
button.title = channelRef;
|
|
212
|
+
button.textContent = label;
|
|
213
|
+
return button;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* One roster-resolved Member chip built outside React. Openable Members jump
|
|
217
|
+
* to their session through the delegated click listener; everyone else gets
|
|
218
|
+
* a labelled but inert span, never a link-shaped misfire.
|
|
219
|
+
*/
|
|
220
|
+
function resolvedMemberRefChip(memberRef, label, sessionId) {
|
|
221
|
+
if (sessionId === undefined) {
|
|
222
|
+
const span = document.createElement('span');
|
|
223
|
+
span.title = memberRef;
|
|
224
|
+
span.textContent = label;
|
|
225
|
+
return span;
|
|
226
|
+
}
|
|
227
|
+
const button = document.createElement('button');
|
|
228
|
+
button.type = 'button';
|
|
229
|
+
if (css.refLink !== undefined)
|
|
230
|
+
button.className = css.refLink;
|
|
231
|
+
button.dataset.memberSession = sessionId;
|
|
232
|
+
button.title = memberRef;
|
|
233
|
+
button.textContent = label;
|
|
234
|
+
return button;
|
|
235
|
+
}
|
|
236
|
+
/** Replace a whole-ref code span with its resolved chip once known. */
|
|
237
|
+
function renderResolvedMarkdownCodeRef(code, taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf) {
|
|
151
238
|
const segments = splitBrandedRefs((code.textContent ?? '').trim());
|
|
152
239
|
const segment = segments.length === 1 ? segments[0] : undefined;
|
|
153
240
|
const ref = segment?.ref;
|
|
154
241
|
if (ref === undefined)
|
|
155
242
|
return;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
243
|
+
// Task and Thread refs need Host resolution before becoming human-readable
|
|
244
|
+
// links; Channel and Member refs resolve against the loaded rosters, and
|
|
245
|
+
// anything the roster does not know stays untouched plain text.
|
|
246
|
+
if (ref.startsWith('task:')) {
|
|
247
|
+
const resolved = cachedResolvedTaskRef(ref);
|
|
248
|
+
if (resolved === undefined)
|
|
249
|
+
return;
|
|
250
|
+
code.replaceWith(resolvedTaskRefButton(ref, taskLabel(resolved.taskNumber)));
|
|
159
251
|
return;
|
|
160
|
-
|
|
161
|
-
|
|
252
|
+
}
|
|
253
|
+
if (ref.startsWith('thread:')) {
|
|
254
|
+
const resolved = cachedResolvedThreadRef(ref);
|
|
255
|
+
if (resolved === undefined)
|
|
256
|
+
return;
|
|
257
|
+
code.replaceWith(resolvedThreadRefButton(ref, threadChipLabel(resolved.title)));
|
|
162
258
|
return;
|
|
163
259
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
260
|
+
if (ref.startsWith('channel:')) {
|
|
261
|
+
const name = channelNameOf?.(ref);
|
|
262
|
+
if (name === undefined)
|
|
263
|
+
return;
|
|
264
|
+
code.replaceWith(resolvedChannelRefButton(ref, channelChipLabel(name)));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (ref.startsWith('member:')) {
|
|
268
|
+
const resolved = memberOf?.(ref);
|
|
269
|
+
if (resolved === undefined)
|
|
270
|
+
return;
|
|
271
|
+
code.replaceWith(resolvedMemberRefChip(ref, memberChipLabel(resolved.handle), resolved.openable ? resolved.sessionId : undefined));
|
|
272
|
+
}
|
|
172
273
|
}
|
|
173
|
-
/** Replace resolved Task refs and structured mention handles in one prose text node without changing Markdown structure. */
|
|
174
|
-
function renderResolvedMarkdownText(node, mentionNames, taskLabel,
|
|
274
|
+
/** Replace resolved Task/Thread/Channel/Member refs and structured mention handles in one prose text node without changing Markdown structure. */
|
|
275
|
+
function renderResolvedMarkdownText(node, mentionNames, taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf) {
|
|
175
276
|
let changed = false;
|
|
176
277
|
const fragment = document.createDocumentFragment();
|
|
177
278
|
for (const refSegment of splitBrandedRefs(node.data)) {
|
|
@@ -190,48 +291,93 @@ function renderResolvedMarkdownText(node, mentionNames, taskLabel, refLabel) {
|
|
|
190
291
|
}
|
|
191
292
|
continue;
|
|
192
293
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
294
|
+
// Task and Thread refs need Host resolution before becoming human-readable
|
|
295
|
+
// links; Channel and Member refs resolve against the loaded rosters.
|
|
296
|
+
// Unresolvable refs stay plain text so prose never misfires as a link.
|
|
297
|
+
if (refSegment.ref.startsWith('task:')) {
|
|
298
|
+
const resolved = cachedResolvedTaskRef(refSegment.ref);
|
|
299
|
+
if (resolved === undefined) {
|
|
300
|
+
fragment.append(refSegment.text);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
changed = true;
|
|
304
|
+
fragment.append(resolvedTaskRefButton(refSegment.ref, taskLabel(resolved.taskNumber)));
|
|
305
|
+
}
|
|
306
|
+
else if (refSegment.ref.startsWith('thread:')) {
|
|
307
|
+
const resolved = cachedResolvedThreadRef(refSegment.ref);
|
|
308
|
+
if (resolved === undefined) {
|
|
309
|
+
fragment.append(refSegment.text);
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
changed = true;
|
|
313
|
+
fragment.append(resolvedThreadRefButton(refSegment.ref, threadChipLabel(resolved.title)));
|
|
201
314
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
315
|
+
else if (refSegment.ref.startsWith('channel:')) {
|
|
316
|
+
const name = channelNameOf?.(refSegment.ref);
|
|
317
|
+
if (name === undefined) {
|
|
318
|
+
fragment.append(refSegment.text);
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
changed = true;
|
|
322
|
+
fragment.append(resolvedChannelRefButton(refSegment.ref, channelChipLabel(name)));
|
|
323
|
+
}
|
|
324
|
+
else if (refSegment.ref.startsWith('member:')) {
|
|
325
|
+
const resolved = memberOf?.(refSegment.ref);
|
|
326
|
+
if (resolved === undefined) {
|
|
327
|
+
fragment.append(refSegment.text);
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
changed = true;
|
|
331
|
+
fragment.append(resolvedMemberRefChip(refSegment.ref, memberChipLabel(resolved.handle), resolved.openable ? resolved.sessionId : undefined));
|
|
205
332
|
}
|
|
206
333
|
else {
|
|
207
|
-
|
|
208
|
-
button.type = 'button';
|
|
209
|
-
if (css.refLink !== undefined)
|
|
210
|
-
button.className = css.refLink;
|
|
211
|
-
button.dataset.ref = refSegment.ref;
|
|
212
|
-
button.title = refSegment.ref;
|
|
213
|
-
button.textContent = refLabel(refSegment.ref);
|
|
214
|
-
fragment.append(button);
|
|
334
|
+
fragment.append(refSegment.text);
|
|
215
335
|
}
|
|
216
336
|
}
|
|
217
337
|
if (changed)
|
|
218
338
|
node.replaceWith(fragment);
|
|
219
339
|
}
|
|
220
340
|
/** Render one literal text run, linkifying branded refs when navigation is available. */
|
|
221
|
-
function renderRefs(text, onOpenRef, taskLabel,
|
|
341
|
+
function renderRefs(text, onOpenRef, onOpenMemberSession, taskLabel, threadChipLabel, channelChipLabel, memberChipLabel, channelNameOf, memberOf) {
|
|
222
342
|
if (onOpenRef === undefined)
|
|
223
343
|
return text;
|
|
224
344
|
return splitBrandedRefs(text).map((segment, index) => {
|
|
225
345
|
if (segment.ref === undefined)
|
|
226
346
|
return _jsx(Fragment, { children: segment.text }, index);
|
|
227
|
-
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
347
|
+
// Task and Thread refs link only once the Host confirms them; Channel and
|
|
348
|
+
// Member refs link once the loaded roster knows them. Anything unknown
|
|
349
|
+
// stays plain text so prose never misfires as a link.
|
|
350
|
+
if (segment.ref.startsWith('task:')) {
|
|
351
|
+
const resolved = cachedResolvedTaskRef(segment.ref);
|
|
352
|
+
if (resolved === undefined)
|
|
353
|
+
return _jsx(Fragment, { children: segment.text }, index);
|
|
354
|
+
return _jsx("button", { type: "button", className: css.refLink, title: segment.ref, onClick: () => { onOpenRef(segment.ref); }, children: taskLabel(resolved.taskNumber) }, index);
|
|
355
|
+
}
|
|
356
|
+
if (segment.ref.startsWith('thread:')) {
|
|
357
|
+
const resolved = cachedResolvedThreadRef(segment.ref);
|
|
358
|
+
if (resolved === undefined)
|
|
359
|
+
return _jsx(Fragment, { children: segment.text }, index);
|
|
360
|
+
return _jsx("button", { type: "button", className: css.refLink, title: segment.ref, onClick: () => { onOpenRef(segment.ref); }, children: threadChipLabel(resolved.title) }, index);
|
|
361
|
+
}
|
|
362
|
+
if (segment.ref.startsWith('channel:')) {
|
|
363
|
+
const name = channelNameOf?.(segment.ref);
|
|
364
|
+
if (name === undefined)
|
|
365
|
+
return _jsx(Fragment, { children: segment.text }, index);
|
|
366
|
+
return _jsx("button", { type: "button", className: css.refLink, title: segment.ref, onClick: () => { onOpenRef(segment.ref); }, children: channelChipLabel(name) }, index);
|
|
367
|
+
}
|
|
368
|
+
if (segment.ref.startsWith('member:')) {
|
|
369
|
+
const resolved = memberOf?.(segment.ref);
|
|
370
|
+
if (resolved === undefined)
|
|
371
|
+
return _jsx(Fragment, { children: segment.text }, index);
|
|
372
|
+
// Known but not openable (suspended Members, the Human): a labelled
|
|
373
|
+
// span, informative without promising a jump that cannot happen.
|
|
374
|
+
if (!resolved.openable || resolved.sessionId === undefined || onOpenMemberSession === undefined) {
|
|
375
|
+
return _jsx("span", { title: segment.ref, children: memberChipLabel(resolved.handle) }, index);
|
|
376
|
+
}
|
|
377
|
+
const sessionId = resolved.sessionId;
|
|
378
|
+
return _jsx("button", { type: "button", className: css.refLink, title: segment.ref, onClick: () => { onOpenMemberSession(sessionId); }, children: memberChipLabel(resolved.handle) }, index);
|
|
379
|
+
}
|
|
380
|
+
return _jsx(Fragment, { children: segment.text }, index);
|
|
235
381
|
});
|
|
236
382
|
}
|
|
237
383
|
/** One message's attachment strip: image thumbnails with a large view, or name chips when bytes are gone. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamRowMenu.d.ts","sourceRoot":"","sources":["../../../src/client/TeamRowMenu.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"TeamRowMenu.d.ts","sourceRoot":"","sources":["../../../src/client/TeamRowMenu.tsx"],"names":[],"mappings":"AACA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,uCAAuC,CAAA;AAGnG;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;IACpE,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;IACpC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,sEAAsE;IACtE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CAChD,+BAkCA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { IconEllipsisOutline16, Menu } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import css from './sidebar.module.css';
|
|
5
5
|
/**
|
|
6
6
|
* Row-level overflow menu shared by sidebar Channel and Agent rows, mirroring
|
|
@@ -19,5 +19,5 @@ export function TeamRowMenu({ label, items, onSelect, onOpenChange }) {
|
|
|
19
19
|
setOpen(false);
|
|
20
20
|
onOpenChange?.(false);
|
|
21
21
|
};
|
|
22
|
-
return (_jsx(Menu, { open: open, onClose: close, items: items, onSelect: (id) => { close(); onSelect(id); }, portal: true, closeOnPointerLeave: true, anchor: (_jsx("button", { type: "button", className: css.rowMenuButton, "aria-label": label, "aria-haspopup": "menu", "aria-expanded": open, onClick: (event) => { event.stopPropagation(); toggle(); }, children: _jsx(
|
|
22
|
+
return (_jsx(Menu, { open: open, onClose: close, items: items, onSelect: (id) => { close(); onSelect(id); }, portal: true, closeOnPointerLeave: true, anchor: (_jsx("button", { type: "button", className: css.rowMenuButton, "aria-label": label, "aria-haspopup": "menu", "aria-expanded": open, onClick: (event) => { event.stopPropagation(); toggle(); }, children: _jsx(IconEllipsisOutline16, {}) })) }));
|
|
23
23
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
3
3
|
import css from './sidebar.module.css';
|
|
4
4
|
/** Collapsible sidebar section header: disclosure toggle plus trailing actions. */
|
|
5
5
|
export function TeamSidebarSection({ title, actions, open, onToggle, children }) {
|
|
6
|
-
return (_jsxs("section", { className: css.section, children: [_jsxs("div", { className: css.sectionHeader, children: [_jsxs("button", { type: "button", className: css.sectionToggle, "aria-expanded": open, onClick: () => { onToggle(!open); }, children: [_jsx(
|
|
6
|
+
return (_jsxs("section", { className: css.section, children: [_jsxs("div", { className: css.sectionHeader, children: [_jsxs("button", { type: "button", className: css.sectionToggle, "aria-expanded": open, onClick: () => { onToggle(!open); }, children: [_jsx(IconChevronDownOutline14, { className: css.sectionChevron }), _jsx("span", { className: css.sectionTitle, children: title })] }), actions !== undefined && _jsx("span", { className: css.sectionActions, children: actions })] }), open && children] }));
|
|
7
7
|
}
|
|
@@ -4,6 +4,9 @@ import type { TeamConversationProps } from './slots.ts';
|
|
|
4
4
|
import type { TeamDraftStore } from './drafts.ts';
|
|
5
5
|
interface TeamThreadPageProps {
|
|
6
6
|
readonly workspaceId: WorkspaceId;
|
|
7
|
+
/** The Human's own display name and avatar, from the shared identity projection. */
|
|
8
|
+
readonly humanName: string;
|
|
9
|
+
readonly humanAvatarUrl?: string | undefined;
|
|
7
10
|
readonly channelRef?: AgentTeamChannelRef;
|
|
8
11
|
readonly taskRef?: AgentTeamTaskRef;
|
|
9
12
|
readonly threadRef: AgentTeamThreadRef;
|
|
@@ -24,6 +27,8 @@ interface TeamThreadPageProps {
|
|
|
24
27
|
readonly selectChannel: TeamConversationProps['selectChannel'];
|
|
25
28
|
readonly selectThread: TeamConversationProps['selectThread'];
|
|
26
29
|
readonly resolveTaskRefs: TeamConversationProps['resolveTaskRefs'];
|
|
30
|
+
readonly resolveThreadRefs: TeamConversationProps['resolveThreadRefs'];
|
|
31
|
+
readonly openMemberSession: TeamConversationProps['openMemberSession'];
|
|
27
32
|
readonly t: TeamConversationProps['t'];
|
|
28
33
|
}
|
|
29
34
|
export declare function TeamThreadPage(props: TeamThreadPageProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamThreadPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamThreadPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,mBAAmB,EAInB,gBAAgB,EAGhB,kBAAkB,EAEnB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"TeamThreadPage.d.ts","sourceRoot":"","sources":["../../../src/client/TeamThreadPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,mBAAmB,EAInB,gBAAgB,EAGhB,kBAAkB,EAEnB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,aAAa,CAAA;AAgB/D,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAA;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAA;IACnC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACxD,QAAQ,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAA;IACtE,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,oBAAoB,CAAC,CAAA;IACxE,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,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAA;IAC9C,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACxD,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAA;IAC9D,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IAClE,QAAQ,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAA;IACtE,QAAQ,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAA;IACtE,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CACvC;AA+CD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,+BA6wBxD"}
|