dsh-sidenote 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/client.js +1015 -203
- package/lib/types/client/chat/ToolCard.d.ts +1 -0
- package/lib/types/client/chat/cards.d.ts +25 -0
- package/lib/types/client/locales.d.ts +15 -0
- package/lib/types/client/sidechat/PendingCard.d.ts +4 -0
- package/lib/types/client/sidechat/notify.d.ts +16 -0
- package/lib/types/client/sidechat/pending.d.ts +71 -0
- package/lib/types/client/sidechat/toast.d.ts +5 -0
- package/package.json +1 -1
- package/src/client/chat/FoldCard.tsx +2 -1
- package/src/client/chat/ReasoningRow.tsx +13 -1
- package/src/client/chat/ToolCard.tsx +20 -4
- package/src/client/chat/cards.ts +285 -11
- package/src/client/chat/transcript.ts +1 -0
- package/src/client/locales.ts +32 -2
- package/src/client/sidechat/ComposerBar.tsx +100 -95
- package/src/client/sidechat/ModelMenu.tsx +3 -2
- package/src/client/sidechat/PendingCard.tsx +145 -0
- package/src/client/sidechat/PermissionChip.tsx +4 -2
- package/src/client/sidechat/SideChatPanel.tsx +32 -2
- package/src/client/sidechat/index.tsx +6 -0
- package/src/client/sidechat/notify.ts +91 -0
- package/src/client/sidechat/pending.ts +238 -0
- package/src/client/sidechat/rows.tsx +1 -0
- package/src/client/sidechat/sidechat.module.css +259 -33
- package/src/client/sidechat/toast.tsx +60 -0
package/lib/client.js
CHANGED
|
@@ -78,16 +78,30 @@ window.__ModuleLoader__.load({
|
|
|
78
78
|
stopped: "Stopped",
|
|
79
79
|
toolLabel: "Tool",
|
|
80
80
|
failed: "failed",
|
|
81
|
+
todoTitle: "Tasks",
|
|
82
|
+
todoDone: "{n} done",
|
|
83
|
+
todoDoing: "{n} in progress",
|
|
84
|
+
todoPending: "{n} pending",
|
|
81
85
|
running: "running…",
|
|
82
86
|
inputPlaceholder: "Message… (Enter to send, Shift+Enter for a newline)",
|
|
83
87
|
modelLabel: "Model: {name}",
|
|
84
88
|
modelSwitchTitle: "Switch the side chat model",
|
|
85
89
|
permChipTitle: "Permission mode",
|
|
86
90
|
permFullAccess: "Full access",
|
|
87
|
-
pendingNotice: "⚠
|
|
88
|
-
writeNotice: "
|
|
91
|
+
pendingNotice: "⚠ The side session has a pending approval/question — click to handle it in the main view",
|
|
92
|
+
writeNotice: "The side session shares the main session's permissions and can modify files (current mode: chip next to the input)",
|
|
93
|
+
pendingApprovalTitle: "Waiting for approval",
|
|
94
|
+
pendingApprovalDesc: "Tool {name} requests elevated execution",
|
|
95
|
+
pendingReject: "Reject",
|
|
96
|
+
pendingAllowOnce: "Allow once",
|
|
97
|
+
pendingQuestionTitle: "Question",
|
|
98
|
+
pendingPlanReview: "Plan review",
|
|
99
|
+
pendingQuestionSubmit: "Submit",
|
|
100
|
+
pendingQuestionCancel: "Cancel",
|
|
101
|
+
pendingCustomPlaceholder: "Custom answer…",
|
|
89
102
|
modelFollowsMain: "follows main session",
|
|
90
103
|
stopReply: "Stop",
|
|
104
|
+
sideChatDone: "「{title}」finished replying",
|
|
91
105
|
stopReplyTitle: "Stop the current reply",
|
|
92
106
|
send: "Send",
|
|
93
107
|
attachTitle: "Attach images",
|
|
@@ -164,6 +178,7 @@ window.__ModuleLoader__.load({
|
|
|
164
178
|
reflowAllDone: "Reflowed ✓",
|
|
165
179
|
promote: "Save as session",
|
|
166
180
|
promoteTitle: "Fork this side chat into a standalone session in the main list",
|
|
181
|
+
promoteDone: "Saved as a regular session — it's open in the main view now",
|
|
167
182
|
readWindow: "{shown} of {total} lines",
|
|
168
183
|
searchPathsSummary: "{shown} of {total} paths",
|
|
169
184
|
searchMatchesSummary: "{shown} of {total} matches in {files} files",
|
|
@@ -197,6 +212,10 @@ window.__ModuleLoader__.load({
|
|
|
197
212
|
stopped: "已停止",
|
|
198
213
|
toolLabel: "工具",
|
|
199
214
|
failed: "失败",
|
|
215
|
+
todoTitle: "任务",
|
|
216
|
+
todoDone: "{n} 已完成",
|
|
217
|
+
todoDoing: "{n} 进行中",
|
|
218
|
+
todoPending: "{n} 待处理",
|
|
200
219
|
running: "执行中…",
|
|
201
220
|
inputPlaceholder: "输入消息…(Enter 发送,Shift+Enter 换行)",
|
|
202
221
|
modelLabel: "模型:{name}",
|
|
@@ -205,8 +224,18 @@ window.__ModuleLoader__.load({
|
|
|
205
224
|
permFullAccess: "Full access",
|
|
206
225
|
pendingNotice: "⚠ 侧边会话有审批/提问待处理——点击跳到主视图处理",
|
|
207
226
|
writeNotice: "侧边会话与主会话同权限,可以修改文件(当前模式见输入框旁 chip)",
|
|
227
|
+
pendingApprovalTitle: "等待审批",
|
|
228
|
+
pendingApprovalDesc: "工具 {name} 请求越权执行",
|
|
229
|
+
pendingReject: "拒绝",
|
|
230
|
+
pendingAllowOnce: "允许一次",
|
|
231
|
+
pendingQuestionTitle: "提问",
|
|
232
|
+
pendingPlanReview: "计划审批",
|
|
233
|
+
pendingQuestionSubmit: "提交回答",
|
|
234
|
+
pendingQuestionCancel: "取消",
|
|
235
|
+
pendingCustomPlaceholder: "自定义回答…",
|
|
208
236
|
modelFollowsMain: "跟随主会话",
|
|
209
237
|
stopReply: "停止",
|
|
238
|
+
sideChatDone: "「{title}」回复完成",
|
|
210
239
|
stopReplyTitle: "停止当前回复",
|
|
211
240
|
send: "发送",
|
|
212
241
|
attachTitle: "添加图片附件",
|
|
@@ -283,6 +312,7 @@ window.__ModuleLoader__.load({
|
|
|
283
312
|
reflowAllDone: "已回流 ✓",
|
|
284
313
|
promote: "保存为正式会话",
|
|
285
314
|
promoteTitle: "把侧边聊天转为会话列表里的正式会话",
|
|
315
|
+
promoteDone: "已保存为正式会话——已在主视图打开",
|
|
286
316
|
readWindow: "{shown}/{total} 行",
|
|
287
317
|
searchPathsSummary: "{shown}/{total} 个路径",
|
|
288
318
|
searchMatchesSummary: "{shown}/{total} 处匹配 · {files} 个文件",
|
|
@@ -827,6 +857,57 @@ window.__ModuleLoader__.load({
|
|
|
827
857
|
return `${cwdBase.replace(/\/+$/, "")}/${cwd}`;
|
|
828
858
|
}
|
|
829
859
|
/**
|
|
860
|
+
* 展示态路径缩短:>3 段的绝对路径只保末 3 段(≈仓库相对形态,与主区
|
|
861
|
+
* 「Read · dsh-sidenote/scripts/x.sh」同款)。窄栏标题位只够放语义尾部。
|
|
862
|
+
*/
|
|
863
|
+
function shortPath(p) {
|
|
864
|
+
if (!p.startsWith("/")) return p;
|
|
865
|
+
const segs = p.split("/").filter((s) => s !== "");
|
|
866
|
+
return segs.length > 3 ? segs.slice(-3).join("/") : p;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* 标题整形:「Tool /abs/path」→「Tool · 末3段」(主区同名同款);
|
|
870
|
+
* 裸绝对路径标题 → 末 3 段;不含路径的标题原样。
|
|
871
|
+
*/
|
|
872
|
+
function displayTitle(title) {
|
|
873
|
+
const m = /^([A-Za-z][\w-]*) (\/.+)$/.exec(title);
|
|
874
|
+
const name = m?.[1];
|
|
875
|
+
const path = m?.[2];
|
|
876
|
+
if (name !== void 0 && path !== void 0) return `${name} · ${shortPath(path)}`;
|
|
877
|
+
return title.startsWith("/") ? shortPath(title) : title;
|
|
878
|
+
}
|
|
879
|
+
/** todo_write 入参形状校验(字段不齐即放弃 todo 卡)。两种数据源形状:
|
|
880
|
+
* 0.1.1 wire:callView.rawInput = todos 数组本身(dsh-tool-todo presentCall 实证);
|
|
881
|
+
* 0.1.2 argsRaw:{ todos: [...] }。 */
|
|
882
|
+
function todoItemsOf(raw) {
|
|
883
|
+
const list = Array.isArray(raw) ? raw : typeof raw === "object" && raw !== null ? raw.todos : void 0;
|
|
884
|
+
if (!Array.isArray(list) || list.length === 0) return void 0;
|
|
885
|
+
const items = [];
|
|
886
|
+
for (const it of list) {
|
|
887
|
+
const o = it;
|
|
888
|
+
if (typeof o?.content !== "string" || typeof o?.status !== "string") return void 0;
|
|
889
|
+
items.push({
|
|
890
|
+
content: o.content,
|
|
891
|
+
status: o.status
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
return items;
|
|
895
|
+
}
|
|
896
|
+
/** todo 卡标题:任务 · 非零状态组计数(主区「任务 · N 已完成 · …」同款)。 */
|
|
897
|
+
function todoTitleOf(items) {
|
|
898
|
+
let done = 0;
|
|
899
|
+
let doing = 0;
|
|
900
|
+
let pending = 0;
|
|
901
|
+
for (const it of items) if (it.status === "completed") done += 1;
|
|
902
|
+
else if (it.status === "in_progress") doing += 1;
|
|
903
|
+
else pending += 1;
|
|
904
|
+
const parts = [];
|
|
905
|
+
if (done > 0) parts.push(t("todoDone", { n: done }));
|
|
906
|
+
if (doing > 0) parts.push(t("todoDoing", { n: doing }));
|
|
907
|
+
if (pending > 0) parts.push(t("todoPending", { n: pending }));
|
|
908
|
+
return parts.length === 0 ? t("todoTitle") : `${t("todoTitle")} · ${parts.join(" · ")}`;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
830
911
|
* callView + resultView → 一张卡的视图模型。三层判别全在这里;
|
|
831
912
|
* 结果态优先(title 等字段 result 覆盖 call),缺省逐字段回退。
|
|
832
913
|
*/
|
|
@@ -839,9 +920,11 @@ window.__ModuleLoader__.load({
|
|
|
839
920
|
case "terminal": {
|
|
840
921
|
const rc = result?.card === "terminal" ? result : void 0;
|
|
841
922
|
const cc = call?.card === "terminal" ? call : void 0;
|
|
923
|
+
const command = rc?.title ?? cc?.title ?? input.toolName;
|
|
842
924
|
return {
|
|
843
925
|
kind: "terminal",
|
|
844
|
-
title:
|
|
926
|
+
title: cc?.description !== void 0 ? `${displayToolName(input.toolName)} · ${cc.description}` : command,
|
|
927
|
+
command,
|
|
845
928
|
...cc?.description !== void 0 ? { description: cc.description } : {},
|
|
846
929
|
...resolveCwd(cc?.cwd, input.cwdBase) !== void 0 ? { cwd: resolveCwd(cc?.cwd, input.cwdBase) } : {},
|
|
847
930
|
...rc?.output !== void 0 ? { output: rc.output } : {},
|
|
@@ -854,7 +937,7 @@ window.__ModuleLoader__.load({
|
|
|
854
937
|
const cc = call?.card === "diff" ? call : void 0;
|
|
855
938
|
return {
|
|
856
939
|
kind: "diff",
|
|
857
|
-
title: rc?.title ?? cc?.title ?? input.toolName,
|
|
940
|
+
title: displayTitle(rc?.title ?? cc?.title ?? input.toolName),
|
|
858
941
|
diffs: rc?.diffs ?? cc?.diffs ?? [],
|
|
859
942
|
...cc?.locations !== void 0 ? { locations: cc.locations } : {}
|
|
860
943
|
};
|
|
@@ -886,7 +969,7 @@ window.__ModuleLoader__.load({
|
|
|
886
969
|
if (rc === void 0) return genericModel(input, call, result);
|
|
887
970
|
return {
|
|
888
971
|
kind: "read",
|
|
889
|
-
title:
|
|
972
|
+
title: `Read · ${shortPath(rc.path)}`,
|
|
890
973
|
path: rc.path,
|
|
891
974
|
lines: rc.lines,
|
|
892
975
|
totalLines: rc.totalLines,
|
|
@@ -932,15 +1015,27 @@ window.__ModuleLoader__.load({
|
|
|
932
1015
|
function genericModel(input, call, result) {
|
|
933
1016
|
const gc = call?.card === "generic" ? call : void 0;
|
|
934
1017
|
const gr = result?.card === "generic" ? result : void 0;
|
|
1018
|
+
if (input.toolName === "todo_write") {
|
|
1019
|
+
const items = todoItemsOf(gc?.rawInput);
|
|
1020
|
+
if (items !== void 0) return {
|
|
1021
|
+
kind: "todo",
|
|
1022
|
+
title: todoTitleOf(items),
|
|
1023
|
+
items
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
935
1026
|
return {
|
|
936
1027
|
kind: "generic",
|
|
937
|
-
title: gr?.title ?? gc?.title ?? input.toolName,
|
|
1028
|
+
title: displayTitle(gr?.title ?? gc?.title ?? input.toolName),
|
|
938
1029
|
icon: gc?.kind ?? "other",
|
|
939
1030
|
...gc?.rawInput !== void 0 ? { rawInput: gc.rawInput } : {},
|
|
940
1031
|
bodyText: blocksText(gr?.content) ?? blocksText(gc?.content) ?? input.rawText,
|
|
941
1032
|
...gc?.locations !== void 0 ? { locations: gc.locations } : {}
|
|
942
1033
|
};
|
|
943
1034
|
}
|
|
1035
|
+
/** 工具机器名 → 展示名(主区「Bash · …」的同款首字母大写)。 */
|
|
1036
|
+
function displayToolName(name) {
|
|
1037
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
1038
|
+
}
|
|
944
1039
|
/** 结果正文尾标解析(宿主 parseExitStatus 的线格式)。 */
|
|
945
1040
|
function parseExitStatus(text) {
|
|
946
1041
|
const m = /\n\[(?:exit code: (\d+)|killed by signal: ([A-Z]+))\]\s*$/.exec(text);
|
|
@@ -980,6 +1075,114 @@ window.__ModuleLoader__.load({
|
|
|
980
1075
|
...typeof m.lang === "string" ? { lang: m.lang } : {}
|
|
981
1076
|
};
|
|
982
1077
|
}
|
|
1078
|
+
/**
|
|
1079
|
+
* FsDiffMeta 校验(0.1.2 diff 卡,dsh-tool-fs computeHunkDiffs 产物的忠实子集)。
|
|
1080
|
+
* 返回值三态:{diffs 非空} / 'empty'(空数组——write create/同内容覆写是合法值,
|
|
1081
|
+
* 客户端回退 args 整文件 diff)/ undefined(malformed——降级)。
|
|
1082
|
+
* 逐项校验,一项违规整卡降级(官方 narrowDiffs 同款)。
|
|
1083
|
+
*/
|
|
1084
|
+
function diffMetaOf(meta) {
|
|
1085
|
+
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
1086
|
+
const m = meta;
|
|
1087
|
+
if (!Array.isArray(m.diffs)) return void 0;
|
|
1088
|
+
if (m.diffs.length === 0) return "empty";
|
|
1089
|
+
const diffs = [];
|
|
1090
|
+
for (const raw of m.diffs) {
|
|
1091
|
+
const d = raw;
|
|
1092
|
+
if (typeof d?.path !== "string") return void 0;
|
|
1093
|
+
if (d.oldText !== null && typeof d.oldText !== "string") return void 0;
|
|
1094
|
+
if (typeof d.newText !== "string") return void 0;
|
|
1095
|
+
diffs.push({
|
|
1096
|
+
path: d.path,
|
|
1097
|
+
oldText: d.oldText,
|
|
1098
|
+
newText: d.newText
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
return { diffs };
|
|
1102
|
+
}
|
|
1103
|
+
/** SearchMeta 校验(0.1.2 search 卡;truncated/total 是硬字段;空结果合法)。 */
|
|
1104
|
+
function searchMetaOf(meta) {
|
|
1105
|
+
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
1106
|
+
const m = meta;
|
|
1107
|
+
if (typeof m.truncated !== "boolean") return void 0;
|
|
1108
|
+
if (typeof m.total !== "number" || !Number.isInteger(m.total) || m.total < 0) return void 0;
|
|
1109
|
+
if (m.shape === "matches") {
|
|
1110
|
+
if (!Array.isArray(m.files)) return void 0;
|
|
1111
|
+
const files = [];
|
|
1112
|
+
for (const rawF of m.files) {
|
|
1113
|
+
const f = rawF;
|
|
1114
|
+
if (typeof f?.path !== "string" || !Array.isArray(f.matches)) return void 0;
|
|
1115
|
+
const matches = [];
|
|
1116
|
+
for (const rawM of f.matches) {
|
|
1117
|
+
const mm = rawM;
|
|
1118
|
+
if (typeof mm?.lineNumber !== "number" || !Number.isInteger(mm.lineNumber) || mm.lineNumber < 1) return void 0;
|
|
1119
|
+
if (typeof mm.line !== "string") return void 0;
|
|
1120
|
+
matches.push({
|
|
1121
|
+
lineNumber: mm.lineNumber,
|
|
1122
|
+
line: mm.line
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
files.push({
|
|
1126
|
+
path: f.path,
|
|
1127
|
+
matches
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
return {
|
|
1131
|
+
shape: "matches",
|
|
1132
|
+
files,
|
|
1133
|
+
truncated: m.truncated,
|
|
1134
|
+
total: m.total
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
if (m.shape === "paths") {
|
|
1138
|
+
if (!Array.isArray(m.paths) || !m.paths.every((p) => typeof p === "string")) return void 0;
|
|
1139
|
+
return {
|
|
1140
|
+
shape: "paths",
|
|
1141
|
+
paths: m.paths,
|
|
1142
|
+
truncated: m.truncated,
|
|
1143
|
+
total: m.total
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
/** WebSearchMeta 校验(sources 逐项 url 必填、title/snippet 可选;publishedAt 校验后丢弃)。 */
|
|
1148
|
+
function webSearchMetaOf(meta) {
|
|
1149
|
+
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
1150
|
+
const m = meta;
|
|
1151
|
+
if (typeof m.truncated !== "boolean") return void 0;
|
|
1152
|
+
if (!Array.isArray(m.sources)) return void 0;
|
|
1153
|
+
const sources = [];
|
|
1154
|
+
for (const raw of m.sources) {
|
|
1155
|
+
const s = raw;
|
|
1156
|
+
if (typeof s?.url !== "string") return void 0;
|
|
1157
|
+
if (s.title !== void 0 && typeof s.title !== "string") return void 0;
|
|
1158
|
+
if (s.snippet !== void 0 && typeof s.snippet !== "string") return void 0;
|
|
1159
|
+
if (s.publishedAt !== void 0 && typeof s.publishedAt !== "string") return void 0;
|
|
1160
|
+
sources.push({
|
|
1161
|
+
url: s.url,
|
|
1162
|
+
...s.title !== void 0 ? { title: s.title } : {},
|
|
1163
|
+
...s.snippet !== void 0 ? { snippet: s.snippet } : {}
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
if (m.answer !== void 0 && typeof m.answer !== "string") return void 0;
|
|
1167
|
+
return {
|
|
1168
|
+
sources,
|
|
1169
|
+
truncated: m.truncated,
|
|
1170
|
+
...m.answer !== void 0 ? { answer: m.answer } : {}
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
/** WebFetchMeta 校验(url + 整数 statusCode + truncated 硬字段)。 */
|
|
1174
|
+
function webFetchMetaOf(meta) {
|
|
1175
|
+
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
1176
|
+
const m = meta;
|
|
1177
|
+
if (typeof m.url !== "string") return void 0;
|
|
1178
|
+
if (typeof m.statusCode !== "number" || !Number.isInteger(m.statusCode)) return void 0;
|
|
1179
|
+
if (typeof m.truncated !== "boolean") return void 0;
|
|
1180
|
+
return {
|
|
1181
|
+
url: m.url,
|
|
1182
|
+
statusCode: m.statusCode,
|
|
1183
|
+
truncated: m.truncated
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
983
1186
|
/** argsRaw(JSON 字符串)里尽力提取展示字段。 */
|
|
984
1187
|
function argsSummary(argsRaw) {
|
|
985
1188
|
if (argsRaw === void 0 || argsRaw === "") return {};
|
|
@@ -990,7 +1193,15 @@ window.__ModuleLoader__.load({
|
|
|
990
1193
|
return {
|
|
991
1194
|
...typeof a.command === "string" ? { command: a.command } : {},
|
|
992
1195
|
...typeof a.description === "string" ? { description: a.description } : {},
|
|
993
|
-
...typeof a.file_path === "string" ? { path: a.file_path } : typeof a.path === "string" ? { path: a.path } : {}
|
|
1196
|
+
...typeof a.file_path === "string" ? { path: a.file_path } : typeof a.path === "string" ? { path: a.path } : {},
|
|
1197
|
+
...Array.isArray(a.todos) ? { todos: a.todos } : {},
|
|
1198
|
+
...typeof a.content === "string" ? { content: a.content } : {},
|
|
1199
|
+
...typeof a.old_string === "string" ? { oldString: a.old_string } : {},
|
|
1200
|
+
...typeof a.new_string === "string" ? { newString: a.new_string } : {},
|
|
1201
|
+
...typeof a.pattern === "string" ? { pattern: a.pattern } : {},
|
|
1202
|
+
...typeof a.include === "string" ? { include: a.include } : {},
|
|
1203
|
+
...Array.isArray(a.queries) && a.queries.every((q) => typeof q === "string") ? { queries: a.queries } : {},
|
|
1204
|
+
...typeof a.url === "string" ? { url: a.url } : {}
|
|
994
1205
|
};
|
|
995
1206
|
} catch {
|
|
996
1207
|
return {};
|
|
@@ -1005,9 +1216,11 @@ window.__ModuleLoader__.load({
|
|
|
1005
1216
|
const name = input.name;
|
|
1006
1217
|
if (name === "bash" || name === "bash-persistent" || name === "pwsh" || name === "pwsh-persistent") {
|
|
1007
1218
|
const { output, exitCode, signal } = parseExitStatus(input.rawText);
|
|
1219
|
+
const command = args.command ?? name;
|
|
1008
1220
|
return {
|
|
1009
1221
|
kind: "terminal",
|
|
1010
|
-
title: args.
|
|
1222
|
+
title: args.description !== void 0 ? `${displayToolName(name)} · ${args.description}` : command,
|
|
1223
|
+
command,
|
|
1011
1224
|
...args.description !== void 0 ? { description: args.description } : {},
|
|
1012
1225
|
output,
|
|
1013
1226
|
...exitCode !== void 0 ? { exitCode } : {},
|
|
@@ -1018,33 +1231,113 @@ window.__ModuleLoader__.load({
|
|
|
1018
1231
|
const meta = readMetaOf(input.meta);
|
|
1019
1232
|
if (meta !== void 0) return {
|
|
1020
1233
|
kind: "read",
|
|
1021
|
-
title: `Read ${meta.path}`,
|
|
1234
|
+
title: `Read · ${shortPath(meta.path)}`,
|
|
1022
1235
|
path: meta.path,
|
|
1023
1236
|
lines: meta.lines,
|
|
1024
1237
|
totalLines: meta.totalLines,
|
|
1025
1238
|
...meta.lang !== void 0 ? { lang: meta.lang } : {}
|
|
1026
1239
|
};
|
|
1027
1240
|
}
|
|
1241
|
+
if (name === "todo_write") {
|
|
1242
|
+
const items = todoItemsOf(args.todos);
|
|
1243
|
+
if (items !== void 0) return {
|
|
1244
|
+
kind: "todo",
|
|
1245
|
+
title: todoTitleOf(items),
|
|
1246
|
+
items
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
if ((name === "write" || name === "edit") && input.isError !== true) {
|
|
1250
|
+
const path = args.path;
|
|
1251
|
+
if (path !== void 0 && path.trim() !== "") {
|
|
1252
|
+
const dm = diffMetaOf(input.meta);
|
|
1253
|
+
if (dm !== void 0 && dm !== "empty") return {
|
|
1254
|
+
kind: "diff",
|
|
1255
|
+
title: displayTitle(`${name === "write" ? "Write" : "Edit"} ${path}`),
|
|
1256
|
+
diffs: dm.diffs,
|
|
1257
|
+
locations: [{ path }]
|
|
1258
|
+
};
|
|
1259
|
+
if (name === "write" && args.content !== void 0) return {
|
|
1260
|
+
kind: "diff",
|
|
1261
|
+
title: displayTitle(`Write ${path}`),
|
|
1262
|
+
diffs: [{
|
|
1263
|
+
path,
|
|
1264
|
+
oldText: null,
|
|
1265
|
+
newText: args.content
|
|
1266
|
+
}],
|
|
1267
|
+
locations: [{ path }]
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
if ((name === "grep" || name === "glob") && input.isError !== true) {
|
|
1272
|
+
const sm = searchMetaOf(input.meta);
|
|
1273
|
+
const wantShape = name === "grep" ? "matches" : "paths";
|
|
1274
|
+
if (sm !== void 0 && sm.shape === wantShape && args.pattern !== void 0) {
|
|
1275
|
+
const where = args.path !== void 0 && args.path.trim() !== "" ? ` in ${shortPath(args.path)}` : "";
|
|
1276
|
+
const inc = name === "grep" && args.include !== void 0 && args.include.trim() !== "" ? ` (${args.include})` : "";
|
|
1277
|
+
const title = `${name === "grep" ? "Grep" : "Glob"} ${args.pattern}${where}${inc}`;
|
|
1278
|
+
return sm.shape === "matches" ? {
|
|
1279
|
+
kind: "search",
|
|
1280
|
+
title,
|
|
1281
|
+
shape: "matches",
|
|
1282
|
+
files: sm.files,
|
|
1283
|
+
truncated: sm.truncated,
|
|
1284
|
+
total: sm.total
|
|
1285
|
+
} : {
|
|
1286
|
+
kind: "search",
|
|
1287
|
+
title,
|
|
1288
|
+
shape: "paths",
|
|
1289
|
+
paths: sm.paths,
|
|
1290
|
+
truncated: sm.truncated,
|
|
1291
|
+
total: sm.total
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
if (name === "web_search" && input.isError !== true) {
|
|
1296
|
+
const wm = webSearchMetaOf(input.meta);
|
|
1297
|
+
const queries = args.queries?.filter((q) => q.trim() !== "") ?? [];
|
|
1298
|
+
if (wm !== void 0 && queries.length > 0) return {
|
|
1299
|
+
kind: "web",
|
|
1300
|
+
title: queries.join(", "),
|
|
1301
|
+
webKind: "search",
|
|
1302
|
+
sources: wm.sources,
|
|
1303
|
+
truncated: wm.truncated,
|
|
1304
|
+
...wm.answer !== void 0 ? { answer: wm.answer } : {}
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
if (name === "web_fetch" && input.isError !== true) {
|
|
1308
|
+
const wm = webFetchMetaOf(input.meta);
|
|
1309
|
+
if (wm !== void 0 && args.url !== void 0 && args.url.trim() !== "") return {
|
|
1310
|
+
kind: "web",
|
|
1311
|
+
title: args.url,
|
|
1312
|
+
webKind: "fetch",
|
|
1313
|
+
url: wm.url,
|
|
1314
|
+
statusCode: wm.statusCode,
|
|
1315
|
+
truncated: wm.truncated
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1028
1318
|
return {
|
|
1029
1319
|
kind: "generic",
|
|
1030
|
-
title: args.path !== void 0 ? `${name} ${args.path}` : args.command ?? name,
|
|
1320
|
+
title: args.path !== void 0 ? `${name} · ${shortPath(args.path)}` : args.command ?? name,
|
|
1031
1321
|
icon: KIND_BY_NAME[name] ?? "other",
|
|
1032
1322
|
bodyText: input.rawText === "" ? void 0 : input.rawText
|
|
1033
1323
|
};
|
|
1034
1324
|
}
|
|
1035
|
-
/** 工具名 → 图标类别的静态映射(0.1.2 没有 callView.kind 可用)。
|
|
1325
|
+
/** 工具名 → 图标类别的静态映射(0.1.2 没有 callView.kind 可用)。
|
|
1326
|
+
* wire 名实证:str_replace_editor 是下划线(uitool client.js L381);
|
|
1327
|
+
* web_search 的 0.1.1 wire kind 是 'search'(presentSearchCall),
|
|
1328
|
+
* 'fetch' 是 web_fetch 的(presentFetchCall)。 */
|
|
1036
1329
|
const KIND_BY_NAME = {
|
|
1037
1330
|
read: "read",
|
|
1038
1331
|
write: "edit",
|
|
1039
1332
|
edit: "edit",
|
|
1040
|
-
|
|
1333
|
+
str_replace_editor: "edit",
|
|
1041
1334
|
bash: "execute",
|
|
1042
1335
|
"bash-persistent": "execute",
|
|
1043
1336
|
pwsh: "execute",
|
|
1044
1337
|
"pwsh-persistent": "execute",
|
|
1045
1338
|
grep: "search",
|
|
1046
1339
|
glob: "search",
|
|
1047
|
-
web_search: "
|
|
1340
|
+
web_search: "search",
|
|
1048
1341
|
web_fetch: "fetch"
|
|
1049
1342
|
};
|
|
1050
1343
|
//#endregion
|
|
@@ -1135,7 +1428,8 @@ window.__ModuleLoader__.load({
|
|
|
1135
1428
|
name: toolName,
|
|
1136
1429
|
argsRaw: typeof call?.argsRaw === "string" ? call.argsRaw : void 0,
|
|
1137
1430
|
meta: n.meta,
|
|
1138
|
-
rawText: text
|
|
1431
|
+
rawText: text,
|
|
1432
|
+
...n.isError === true ? { isError: true } : {}
|
|
1139
1433
|
});
|
|
1140
1434
|
return {
|
|
1141
1435
|
key: seqKey("t", n),
|
|
@@ -1390,7 +1684,7 @@ window.__ModuleLoader__.load({
|
|
|
1390
1684
|
}
|
|
1391
1685
|
//#endregion
|
|
1392
1686
|
//#region \0dsh-css:/home/runner/work/dsh-sidenote/dsh-sidenote/src/client/sidechat/sidechat.module.css.mjs
|
|
1393
|
-
const css$1 = "._5KEEsG_root{height:100%;color:var(--dsw-alias-label-primary);flex-direction:column;font-size:13px;display:flex;position:relative}._5KEEsG_body{flex-direction:column;flex:1;padding:12px 10px;display:flex;overflow-y:auto}._5KEEsG_transcript{flex-direction:column;gap:12px;display:flex}._5KEEsG_empty,._5KEEsG_stateScreen{text-align:center;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;padding:24px 16px;display:flex}._5KEEsG_emptyIcon{color:var(--dsw-alias-label-tertiary)}._5KEEsG_emptyTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:600}._5KEEsG_emptyText{color:var(--dsw-alias-label-tertiary);max-width:240px;font-size:12px;line-height:1.6}._5KEEsG_stateDetail{color:var(--dsw-alias-state-error-primary);word-break:break-word;max-width:260px;font-size:12px;line-height:1.6}._5KEEsG_userRow{justify-content:flex-end;display:flex}._5KEEsG_userBubble{background:var(--dsw-specific-bubble,#edf3fe);max-width:88%;color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;border-radius:16px;padding:8px 12px;font-size:13px;line-height:1.55}._5KEEsG_assistantRow{justify-content:flex-start;display:flex;position:relative}._5KEEsG_rowActions{opacity:0;z-index:2;transition:opacity .12s ease-out;position:absolute;top:-8px;right:0}._5KEEsG_assistantRow:hover ._5KEEsG_rowActions{opacity:1}._5KEEsG_reflowButton{border:1px solid var(--dsw-alias-border-l1,#0000001a);background:var(--dsw-alias-bg-layer-1,#fff);width:22px;height:22px;color:var(--dsw-alias-label-tertiary,#8f959e);cursor:pointer;border-radius:999px;place-items:center;padding:0;display:grid;box-shadow:0 2px 8px #00000014}._5KEEsG_reflowButton:hover{color:var(--dsw-alias-state-business-primary,#2f88ff);border-color:var(--dsw-alias-state-business-primary,#2f88ff)}._5KEEsG_assistantBody{word-break:break-word;max-width:100%;font-size:13px;line-height:1.6}._5KEEsG_reasoning{border-left:3px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);margin-bottom:6px;padding-left:8px;font-size:12px}._5KEEsG_reasoning>summary{cursor:pointer;user-select:none}._5KEEsG_reasoningBody{white-space:pre-wrap;word-break:break-word;margin-top:4px}._5KEEsG_streamingHint{color:var(--dsw-alias-label-dimmed)}._5KEEsG_toolCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:8px;overflow:hidden}._5KEEsG_toolHead{background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;padding:5px 10px;font-size:12px;display:flex}._5KEEsG_toolError{color:var(--dsw-alias-state-error-primary)}._5KEEsG_toolRunning{color:var(--dsw-alias-label-tertiary)}._5KEEsG_toolBody{color:var(--dsw-alias-label-tertiary);white-space:pre-wrap;word-break:break-word;max-height:160px;padding:8px 10px;font-size:12px;overflow-y:auto}._5KEEsG_errorRow{color:var(--dsw-alias-state-error-primary);white-space:pre-wrap;padding:4px 2px;font-size:12px}._5KEEsG_noticeRow{color:var(--dsw-alias-label-dimmed);text-align:center;padding:2px 0;font-size:12px}._5KEEsG_composer{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:6px;padding:8px 10px;display:flex;position:relative}._5KEEsG_input{resize:vertical;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);width:100%;min-height:40px;max-height:160px;color:var(--dsw-alias-label-primary);font:inherit;box-sizing:border-box;border-radius:8px;padding:8px 10px}._5KEEsG_input:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}._5KEEsG_composerFoot{justify-content:space-between;align-items:center;gap:8px;display:flex}._5KEEsG_modelLabel{color:var(--dsw-alias-label-dimmed);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}._5KEEsG_sendButton,._5KEEsG_stopButton{appearance:none;border:1px solid var(--dsw-alias-state-business-primary);background:var(--dsw-alias-button-info-fill);color:#fff;cursor:pointer;border-radius:8px;flex:none;align-items:center;gap:4px;padding:6px 12px;font-size:13px;display:inline-flex}._5KEEsG_sendButton:disabled{opacity:.55;cursor:default}._5KEEsG_headerSide{border:1px solid var(--dsw-alias-border-l1,#0000001a);color:var(--dsw-alias-label-secondary,#3f454d);cursor:pointer;user-select:none;background:0 0;border-radius:999px;align-items:center;gap:5px;padding:3px 10px;font-size:12px;line-height:18px;display:inline-flex}._5KEEsG_headerSide:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-primary,#1f2329)}._5KEEsG_sentChipRow{align-items:center;gap:6px;margin-right:8px;display:inline-flex}._5KEEsG_sentChip{border:1px solid var(--dsw-alias-border-l1,#0000001a);background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-secondary,#3f454d);user-select:none;border-radius:999px;align-items:center;gap:4px;padding:1px 8px;font-size:11px;line-height:16px;display:inline-flex}._5KEEsG_toolCardV2{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:8px;font-size:12px;overflow:hidden}._5KEEsG_toolGenericBody{flex-direction:column;gap:6px;padding:8px 10px;display:flex}._5KEEsG_toolBodyText{color:var(--dsw-alias-label-secondary);white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.55;font-family:var(--dsw-alias-font-mono,ui-monospace, monospace);margin:0}._5KEEsG_toolLocations{color:var(--dsw-alias-label-tertiary);white-space:pre-wrap;word-break:break-all;font-size:11px}._5KEEsG_inheritedBody{border-top:1px dashed var(--dsw-alias-border-l2);opacity:.92;padding:6px 0 2px}._5KEEsG_densityRow{justify-content:flex-end;align-items:center;padding:2px 2px 4px;display:flex}._5KEEsG_densityToggle{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:2px 6px;font-size:11px}._5KEEsG_densityToggle:hover{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}._5KEEsG_jumpBottom{z-index:5;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:999px;padding:3px 10px;font-size:11px;position:absolute;bottom:96px;right:12px;box-shadow:0 2px 8px #0000001f}._5KEEsG_jumpBottom:hover{background:var(--dsw-alias-bg-layer-2)}._5KEEsG_modelSelect{color:var(--dsw-alias-label-secondary);cursor:pointer;text-overflow:ellipsis;white-space:nowrap;background:0 0;border:none;border-radius:4px;max-width:180px;padding:2px 6px;font-size:12px;overflow:hidden}._5KEEsG_modelSelect:hover{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}._5KEEsG_composerChips{align-items:center;gap:4px;min-width:0;display:inline-flex;overflow:hidden}._5KEEsG_slashMenu{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);z-index:20;border-radius:10px;max-height:260px;margin-bottom:6px;padding:4px;position:absolute;bottom:100%;left:8px;right:8px;overflow-y:auto;box-shadow:0 8px 24px #00000024}._5KEEsG_slashGroupTitle{color:var(--dsw-alias-label-tertiary);text-transform:none;padding:4px 8px 2px;font-size:11px}._5KEEsG_slashItem,._5KEEsG_slashItemActive{text-align:left;cursor:pointer;width:100%;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:6px;align-items:baseline;gap:8px;padding:6px 8px;font-size:13px;display:flex}._5KEEsG_slashItemActive,._5KEEsG_slashItem:hover{background:var(--dsw-alias-interactive-bg-hover)}._5KEEsG_slashItemName{flex:none;font-weight:500}._5KEEsG_slashItemDetail{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}._5KEEsG_attachRail{flex-wrap:wrap;gap:6px;padding:2px 0;display:flex}._5KEEsG_attachThumb{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;width:44px;height:44px;position:relative;overflow:hidden}._5KEEsG_attachImg{object-fit:cover;width:100%;height:100%;display:block}._5KEEsG_attachRemove{color:#fff;cursor:pointer;background:#0000008c;border:none;border-radius:999px;place-items:center;width:16px;height:16px;padding:0;font-size:11px;line-height:1;display:grid;position:absolute;top:1px;right:1px}._5KEEsG_attachButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:4px;display:inline-flex}._5KEEsG_attachButton:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}._5KEEsG_pendingBar{border:1px solid var(--dsw-alias-state-warning-primary,#d4a017);background:var(--dsw-alias-bg-layer-2);width:calc(100% - 16px);color:var(--dsw-alias-state-warning-primary,#d4a017);text-align:left;cursor:pointer;border-radius:8px;margin:0 8px 6px;padding:6px 10px;font-size:12px;display:block}._5KEEsG_pendingBar:hover{background:var(--dsw-alias-bg-layer-3)}._5KEEsG_writeNotice{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);border-radius:8px;align-items:center;gap:8px;margin:0 8px 6px;padding:6px 10px;font-size:12px;display:flex}._5KEEsG_writeNoticeClose{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;margin-left:auto;padding:0 4px;font-size:13px}._5KEEsG_parentStrip{border:none;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-secondary);cursor:pointer;text-align:left;align-items:center;gap:6px;padding:5px 12px;font-size:11px;display:flex}._5KEEsG_parentStrip:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary)}._5KEEsG_dotRunning,._5KEEsG_dotPending,._5KEEsG_dotIdle{border-radius:999px;flex:none;width:7px;height:7px}._5KEEsG_dotRunning{background:var(--dsw-alias-state-business-primary,#2f88ff);animation:1.2s ease-in-out infinite _5KEEsG_sidechat-pulse}._5KEEsG_dotPending{background:var(--dsw-alias-state-warning-primary,#d4a017)}._5KEEsG_dotIdle{background:var(--dsw-alias-label-dimmed)}@keyframes _5KEEsG_sidechat-pulse{50%{opacity:.45}}._5KEEsG_actionGroup{gap:2px;margin-right:auto;display:inline-flex}";
|
|
1687
|
+
const css$1 = "._5KEEsG_root{height:100%;color:var(--dsw-alias-label-primary);flex-direction:column;font-size:13px;display:flex;position:relative}._5KEEsG_body{flex-direction:column;flex:1;padding:12px 10px;display:flex;overflow-y:auto}._5KEEsG_transcript{flex-direction:column;gap:10px;display:flex}._5KEEsG_empty,._5KEEsG_stateScreen{text-align:center;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;padding:24px 16px;display:flex}._5KEEsG_emptyIcon{color:var(--dsw-alias-label-tertiary)}._5KEEsG_emptyTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:600}._5KEEsG_emptyText{color:var(--dsw-alias-label-tertiary);max-width:240px;font-size:12px;line-height:1.6}._5KEEsG_stateDetail{color:var(--dsw-alias-state-error-primary);word-break:break-word;max-width:260px;font-size:12px;line-height:1.6}._5KEEsG_userRow{justify-content:flex-end;display:flex}._5KEEsG_userBubble{background:var(--dsw-specific-bubble,#edf3fe);max-width:88%;color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;border-radius:16px;padding:8px 12px;font-size:13px;line-height:1.55}._5KEEsG_assistantRow{justify-content:flex-start;display:flex;position:relative}._5KEEsG_rowActions{opacity:0;z-index:2;transition:opacity .12s ease-out;position:absolute;top:-8px;right:0}._5KEEsG_assistantRow:hover ._5KEEsG_rowActions{opacity:1}._5KEEsG_reflowButton{border:1px solid var(--dsw-alias-border-l1,#0000001a);background:var(--dsw-alias-bg-layer-1,#fff);width:22px;height:22px;color:var(--dsw-alias-label-tertiary,#8f959e);cursor:pointer;border-radius:999px;place-items:center;padding:0;display:grid;box-shadow:0 2px 8px #00000014}._5KEEsG_reflowButton:hover{color:var(--dsw-alias-state-business-primary,#2f88ff);border-color:var(--dsw-alias-state-business-primary,#2f88ff)}._5KEEsG_assistantBody{word-break:break-word;max-width:100%;font-size:13px;line-height:1.6}._5KEEsG_reasoning{border-left:3px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);margin-bottom:6px;padding-left:8px;font-size:12px}._5KEEsG_reasoning>summary{cursor:pointer;user-select:none}._5KEEsG_reasoningBody{white-space:pre-wrap;word-break:break-word;color:var(--dsw-alias-label-tertiary);margin-top:2px;padding-bottom:2px;padding-left:22px}._5KEEsG_streamingHint{color:var(--dsw-alias-label-dimmed)}._5KEEsG_toolCard{font-size:12px}._5KEEsG_toolHead{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:12px;display:flex}._5KEEsG_toolError{color:var(--dsw-alias-state-error-primary)}._5KEEsG_toolRunning{color:var(--dsw-alias-label-tertiary)}._5KEEsG_toolBody{color:var(--dsw-alias-label-tertiary);white-space:pre-wrap;word-break:break-word;max-height:160px;padding:2px 0 2px 22px;font-size:12px;overflow-y:auto}._5KEEsG_errorRow{color:var(--dsw-alias-state-error-primary);white-space:pre-wrap;padding:4px 2px;font-size:12px}._5KEEsG_noticeRow{color:var(--dsw-alias-label-dimmed);text-align:center;padding:2px 0;font-size:12px}._5KEEsG_composer{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:6px;padding:8px 10px;display:flex;position:relative}._5KEEsG_composerCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:14px;flex-direction:column;gap:2px;padding:4px 6px 6px;transition:border-color .12s;display:flex}._5KEEsG_composerCard:focus-within{border-color:var(--dsw-alias-state-business-primary)}._5KEEsG_input{resize:none;width:100%;min-height:36px;max-height:160px;color:var(--dsw-alias-label-primary);font:inherit;box-sizing:border-box;background:0 0;border:none;padding:6px 6px 2px}._5KEEsG_input:focus{outline:none}._5KEEsG_composerFoot{justify-content:space-between;align-items:center;gap:8px;padding:0 2px;display:flex}._5KEEsG_modelLabel{color:var(--dsw-alias-label-dimmed);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}._5KEEsG_sendButton,._5KEEsG_stopButton{appearance:none;background:var(--dsw-alias-button-info-fill);color:#fff;cursor:pointer;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;width:28px;height:28px;padding:0;display:inline-flex}._5KEEsG_sendButton:disabled{opacity:.45;cursor:default}._5KEEsG_headerSide{border:1px solid var(--dsw-alias-border-l1,#0000001a);color:var(--dsw-alias-label-secondary,#3f454d);cursor:pointer;user-select:none;background:0 0;border-radius:999px;align-items:center;gap:5px;padding:3px 10px;font-size:12px;line-height:18px;display:inline-flex}._5KEEsG_headerSide:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-primary,#1f2329)}._5KEEsG_sentChipRow{align-items:center;gap:6px;margin-right:8px;display:inline-flex}._5KEEsG_sentChip{border:1px solid var(--dsw-alias-border-l1,#0000001a);background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-secondary,#3f454d);user-select:none;border-radius:999px;align-items:center;gap:4px;padding:1px 8px;font-size:11px;line-height:16px;display:inline-flex}._5KEEsG_flowRow{font-size:12px}._5KEEsG_rowPreview{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-dimmed);flex:1;margin-left:8px;font-size:12px;overflow:hidden}._5KEEsG_flowRowError{color:var(--dsw-alias-state-error-primary)}._5KEEsG_todoBody{flex-direction:column;gap:3px;padding:2px 0 4px 22px;display:flex}._5KEEsG_todoItem{align-items:baseline;gap:7px;min-width:0;font-size:12px;line-height:1.5;display:flex}._5KEEsG_todoDot{background:var(--dsw-alias-label-dimmed);border-radius:50%;flex:none;width:6px;height:6px;transform:translateY(-1px)}._5KEEsG_todoDot[data-status=completed]{background:var(--dsw-alias-state-success-primary,#34a853)}._5KEEsG_todoDot[data-status=in_progress]{background:var(--dsw-alias-state-business-primary)}._5KEEsG_todoText[data-status=completed]{color:var(--dsw-alias-label-dimmed)}._5KEEsG_toolGenericBody{flex-direction:column;gap:6px;padding:4px 0 4px 22px;display:flex}._5KEEsG_toolBodyText{color:var(--dsw-alias-label-secondary);white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.55;font-family:var(--dsw-alias-font-mono,ui-monospace, monospace);margin:0}._5KEEsG_toolLocations{color:var(--dsw-alias-label-tertiary);white-space:pre-wrap;word-break:break-all;font-size:11px}._5KEEsG_inheritedBody{border-top:1px dashed var(--dsw-alias-border-l2);opacity:.92;padding:6px 0 2px}._5KEEsG_densityRow{justify-content:flex-end;align-items:center;padding:2px 2px 4px;display:flex}._5KEEsG_densityToggle{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:2px 6px;font-size:11px}._5KEEsG_densityToggle:hover{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}._5KEEsG_jumpBottom{z-index:5;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:999px;padding:3px 10px;font-size:11px;position:absolute;bottom:96px;right:12px;box-shadow:0 2px 8px #0000001f}._5KEEsG_jumpBottom:hover{background:var(--dsw-alias-bg-layer-2)}._5KEEsG_modelSelect{color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:6px;align-items:center;gap:3px;max-width:180px;padding:3px 6px;font-size:12px;display:inline-flex;overflow:hidden}._5KEEsG_modelSelect>span:first-child{text-overflow:ellipsis;overflow:hidden}._5KEEsG_modelSelect>svg{color:var(--dsw-alias-label-dimmed);flex:none}._5KEEsG_modelSelect:hover{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}._5KEEsG_composerChips{align-items:center;gap:4px;min-width:0;display:inline-flex;overflow:hidden}._5KEEsG_slashMenu{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);z-index:20;border-radius:10px;max-height:260px;margin-bottom:6px;padding:4px;position:absolute;bottom:100%;left:8px;right:8px;overflow-y:auto;box-shadow:0 8px 24px #00000024}._5KEEsG_slashGroupTitle{color:var(--dsw-alias-label-tertiary);text-transform:none;padding:4px 8px 2px;font-size:11px}._5KEEsG_slashItem,._5KEEsG_slashItemActive{text-align:left;cursor:pointer;width:100%;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:6px;align-items:baseline;gap:8px;padding:6px 8px;font-size:13px;display:flex}._5KEEsG_slashItemActive,._5KEEsG_slashItem:hover{background:var(--dsw-alias-interactive-bg-hover)}._5KEEsG_slashItemName{flex:none;font-weight:500}._5KEEsG_slashItemDetail{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}._5KEEsG_attachRail{flex-wrap:wrap;gap:6px;padding:2px 0;display:flex}._5KEEsG_attachThumb{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;width:44px;height:44px;position:relative;overflow:hidden}._5KEEsG_attachImg{object-fit:cover;width:100%;height:100%;display:block}._5KEEsG_attachRemove{color:#fff;cursor:pointer;background:#0000008c;border:none;border-radius:999px;place-items:center;width:16px;height:16px;padding:0;font-size:11px;line-height:1;display:grid;position:absolute;top:1px;right:1px}._5KEEsG_attachButton{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:4px;display:inline-flex}._5KEEsG_attachButton:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}._5KEEsG_pendingCard{border:1px solid var(--dsw-alias-border-l2);border-left:3px solid var(--dsw-alias-state-warning-primary,#e8a13a);background:var(--dsw-alias-bg-layer-2);border-radius:10px;flex-direction:column;gap:6px;margin:0 10px 6px;padding:10px 12px;font-size:12px;display:flex}._5KEEsG_pendingHead{color:var(--dsw-alias-state-warning-primary,#e8a13a);align-items:center;gap:6px;display:flex}._5KEEsG_pendingTitle{color:var(--dsw-alias-label-primary);font-weight:600}._5KEEsG_pendingDesc{color:var(--dsw-alias-label-secondary)}._5KEEsG_pendingReason{color:var(--dsw-alias-label-tertiary);white-space:pre-wrap;word-break:break-word}._5KEEsG_pendingQuestion{flex-direction:column;gap:4px;padding:4px 0;display:flex}._5KEEsG_pendingQHeader{color:var(--dsw-alias-label-primary);font-weight:600}._5KEEsG_pendingQText{color:var(--dsw-alias-label-secondary)}._5KEEsG_pendingOption{text-align:left;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border-radius:6px;flex-direction:column;align-items:flex-start;gap:2px;padding:5px 8px;font-size:12px;display:flex}._5KEEsG_pendingOption:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000d)}._5KEEsG_pendingOptionActive{text-align:left;border:1px solid var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;flex-direction:column;align-items:flex-start;gap:2px;padding:5px 8px;font-size:12px;display:flex}._5KEEsG_pendingOptionDesc{color:var(--dsw-alias-label-dimmed);font-size:11px}._5KEEsG_pendingCustom{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);font-size:12px;font:inherit;background:0 0;border-radius:6px;padding:5px 8px}._5KEEsG_pendingCustom:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}._5KEEsG_pendingActions{justify-content:flex-end;gap:8px;margin-top:2px;display:flex}._5KEEsG_pendingBtnGhost{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border-radius:6px;padding:4px 12px;font-size:12px}._5KEEsG_pendingBtnPrimary{background:var(--dsw-alias-button-info-fill);color:#fff;cursor:pointer;border:none;border-radius:6px;padding:4px 12px;font-size:12px}._5KEEsG_pendingBtnGhost:disabled,._5KEEsG_pendingBtnPrimary:disabled{opacity:.5;cursor:default}._5KEEsG_pendingBar{border:1px solid var(--dsw-alias-state-warning-primary,#d4a017);background:var(--dsw-alias-bg-layer-2);width:calc(100% - 16px);color:var(--dsw-alias-state-warning-primary,#d4a017);text-align:left;cursor:pointer;border-radius:8px;margin:0 8px 6px;padding:6px 10px;font-size:12px;display:block}._5KEEsG_pendingBar:hover{background:var(--dsw-alias-bg-layer-3)}._5KEEsG_writeNotice{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);border-radius:8px;align-items:center;gap:8px;margin:0 8px 6px;padding:6px 10px;font-size:12px;display:flex}._5KEEsG_writeNoticeClose{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;margin-left:auto;padding:0 4px;font-size:13px}._5KEEsG_parentStrip{border:none;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-secondary);cursor:pointer;text-align:left;align-items:center;gap:6px;padding:5px 12px;font-size:11px;display:flex}._5KEEsG_parentStrip:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary)}._5KEEsG_dotRunning,._5KEEsG_dotPending,._5KEEsG_dotIdle{border-radius:999px;flex:none;width:7px;height:7px}._5KEEsG_dotRunning{background:var(--dsw-alias-state-business-primary,#2f88ff);animation:1.2s ease-in-out infinite _5KEEsG_sidechat-pulse}._5KEEsG_dotPending{background:var(--dsw-alias-state-warning-primary,#d4a017)}._5KEEsG_dotIdle{background:var(--dsw-alias-label-dimmed)}@keyframes _5KEEsG_sidechat-pulse{50%{opacity:.45}}._5KEEsG_actionGroup{gap:2px;margin-right:auto;display:inline-flex}";
|
|
1394
1688
|
const tagId$1 = "dsh-sidenote/sidechat.module.css";
|
|
1395
1689
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
1396
1690
|
const tag = document.createElement("style");
|
|
@@ -1400,70 +1694,92 @@ window.__ModuleLoader__.load({
|
|
|
1400
1694
|
document.head.appendChild(tag);
|
|
1401
1695
|
}
|
|
1402
1696
|
var sidechat_module_css_default = {
|
|
1403
|
-
"
|
|
1404
|
-
"
|
|
1405
|
-
"
|
|
1406
|
-
"
|
|
1697
|
+
"composerCard": "_5KEEsG_composerCard",
|
|
1698
|
+
"streamingHint": "_5KEEsG_streamingHint",
|
|
1699
|
+
"stopButton": "_5KEEsG_stopButton",
|
|
1700
|
+
"transcript": "_5KEEsG_transcript",
|
|
1701
|
+
"rowPreview": "_5KEEsG_rowPreview",
|
|
1702
|
+
"toolGenericBody": "_5KEEsG_toolGenericBody",
|
|
1407
1703
|
"densityRow": "_5KEEsG_densityRow",
|
|
1408
|
-
"
|
|
1409
|
-
"
|
|
1410
|
-
"
|
|
1704
|
+
"pendingReason": "_5KEEsG_pendingReason",
|
|
1705
|
+
"toolError": "_5KEEsG_toolError",
|
|
1706
|
+
"pendingOptionDesc": "_5KEEsG_pendingOptionDesc",
|
|
1707
|
+
"empty": "_5KEEsG_empty",
|
|
1411
1708
|
"stateScreen": "_5KEEsG_stateScreen",
|
|
1412
|
-
"
|
|
1413
|
-
"
|
|
1709
|
+
"slashMenu": "_5KEEsG_slashMenu",
|
|
1710
|
+
"userBubble": "_5KEEsG_userBubble",
|
|
1711
|
+
"dotPending": "_5KEEsG_dotPending",
|
|
1712
|
+
"pendingOptionActive": "_5KEEsG_pendingOptionActive",
|
|
1713
|
+
"pendingDesc": "_5KEEsG_pendingDesc",
|
|
1714
|
+
"pendingActions": "_5KEEsG_pendingActions",
|
|
1715
|
+
"todoDot": "_5KEEsG_todoDot",
|
|
1716
|
+
"todoText": "_5KEEsG_todoText",
|
|
1414
1717
|
"emptyIcon": "_5KEEsG_emptyIcon",
|
|
1718
|
+
"reflowButton": "_5KEEsG_reflowButton",
|
|
1719
|
+
"pendingBtnPrimary": "_5KEEsG_pendingBtnPrimary",
|
|
1720
|
+
"reasoningBody": "_5KEEsG_reasoningBody",
|
|
1721
|
+
"inheritedBody": "_5KEEsG_inheritedBody",
|
|
1415
1722
|
"attachRail": "_5KEEsG_attachRail",
|
|
1416
|
-
"
|
|
1417
|
-
"slashItemName": "_5KEEsG_slashItemName",
|
|
1418
|
-
"dotRunning": "_5KEEsG_dotRunning",
|
|
1419
|
-
"modelLabel": "_5KEEsG_modelLabel",
|
|
1420
|
-
"toolLocations": "_5KEEsG_toolLocations",
|
|
1421
|
-
"writeNoticeClose": "_5KEEsG_writeNoticeClose",
|
|
1723
|
+
"pendingBtnGhost": "_5KEEsG_pendingBtnGhost",
|
|
1422
1724
|
"dotIdle": "_5KEEsG_dotIdle",
|
|
1423
|
-
"
|
|
1424
|
-
"toolRunning": "_5KEEsG_toolRunning",
|
|
1725
|
+
"slashItemName": "_5KEEsG_slashItemName",
|
|
1425
1726
|
"sendButton": "_5KEEsG_sendButton",
|
|
1426
|
-
"
|
|
1427
|
-
"attachThumb": "_5KEEsG_attachThumb",
|
|
1428
|
-
"assistantBody": "_5KEEsG_assistantBody",
|
|
1429
|
-
"slashMenu": "_5KEEsG_slashMenu",
|
|
1727
|
+
"slashItemActive": "_5KEEsG_slashItemActive",
|
|
1430
1728
|
"stateDetail": "_5KEEsG_stateDetail",
|
|
1431
|
-
"
|
|
1432
|
-
"
|
|
1433
|
-
"
|
|
1434
|
-
"
|
|
1435
|
-
"
|
|
1729
|
+
"emptyTitle": "_5KEEsG_emptyTitle",
|
|
1730
|
+
"pendingCustom": "_5KEEsG_pendingCustom",
|
|
1731
|
+
"dotRunning": "_5KEEsG_dotRunning",
|
|
1732
|
+
"densityToggle": "_5KEEsG_densityToggle",
|
|
1733
|
+
"pendingOption": "_5KEEsG_pendingOption",
|
|
1734
|
+
"modelLabel": "_5KEEsG_modelLabel",
|
|
1735
|
+
"body": "_5KEEsG_body",
|
|
1736
|
+
"toolHead": "_5KEEsG_toolHead",
|
|
1737
|
+
"reasoning": "_5KEEsG_reasoning",
|
|
1738
|
+
"pendingQHeader": "_5KEEsG_pendingQHeader",
|
|
1739
|
+
"writeNotice": "_5KEEsG_writeNotice",
|
|
1436
1740
|
"input": "_5KEEsG_input",
|
|
1437
|
-
"
|
|
1438
|
-
"
|
|
1439
|
-
"
|
|
1741
|
+
"sentChipRow": "_5KEEsG_sentChipRow",
|
|
1742
|
+
"todoItem": "_5KEEsG_todoItem",
|
|
1743
|
+
"composer": "_5KEEsG_composer",
|
|
1744
|
+
"slashItem": "_5KEEsG_slashItem",
|
|
1745
|
+
"flowRow": "_5KEEsG_flowRow",
|
|
1746
|
+
"pendingHead": "_5KEEsG_pendingHead",
|
|
1747
|
+
"composerChips": "_5KEEsG_composerChips",
|
|
1440
1748
|
"errorRow": "_5KEEsG_errorRow",
|
|
1441
|
-
"noticeRow": "_5KEEsG_noticeRow",
|
|
1442
|
-
"parentStrip": "_5KEEsG_parentStrip",
|
|
1443
|
-
"toolGenericBody": "_5KEEsG_toolGenericBody",
|
|
1444
1749
|
"slashItemDetail": "_5KEEsG_slashItemDetail",
|
|
1445
|
-
"
|
|
1446
|
-
"
|
|
1447
|
-
"
|
|
1448
|
-
"
|
|
1449
|
-
"
|
|
1750
|
+
"toolRunning": "_5KEEsG_toolRunning",
|
|
1751
|
+
"noticeRow": "_5KEEsG_noticeRow",
|
|
1752
|
+
"pendingTitle": "_5KEEsG_pendingTitle",
|
|
1753
|
+
"jumpBottom": "_5KEEsG_jumpBottom",
|
|
1754
|
+
"flowRowError": "_5KEEsG_flowRowError",
|
|
1450
1755
|
"sidechat-pulse": "_5KEEsG_sidechat-pulse",
|
|
1451
|
-
"
|
|
1756
|
+
"root": "_5KEEsG_root",
|
|
1757
|
+
"emptyText": "_5KEEsG_emptyText",
|
|
1758
|
+
"slashGroupTitle": "_5KEEsG_slashGroupTitle",
|
|
1452
1759
|
"toolCard": "_5KEEsG_toolCard",
|
|
1453
|
-
"
|
|
1454
|
-
"
|
|
1455
|
-
"
|
|
1456
|
-
"attachRemove": "_5KEEsG_attachRemove",
|
|
1760
|
+
"assistantBody": "_5KEEsG_assistantBody",
|
|
1761
|
+
"composerFoot": "_5KEEsG_composerFoot",
|
|
1762
|
+
"attachButton": "_5KEEsG_attachButton",
|
|
1457
1763
|
"userRow": "_5KEEsG_userRow",
|
|
1458
|
-
"
|
|
1459
|
-
"
|
|
1460
|
-
"
|
|
1461
|
-
"
|
|
1462
|
-
"
|
|
1463
|
-
"
|
|
1764
|
+
"todoBody": "_5KEEsG_todoBody",
|
|
1765
|
+
"toolBodyText": "_5KEEsG_toolBodyText",
|
|
1766
|
+
"pendingCard": "_5KEEsG_pendingCard",
|
|
1767
|
+
"parentStrip": "_5KEEsG_parentStrip",
|
|
1768
|
+
"toolLocations": "_5KEEsG_toolLocations",
|
|
1769
|
+
"actionGroup": "_5KEEsG_actionGroup",
|
|
1770
|
+
"headerSide": "_5KEEsG_headerSide",
|
|
1464
1771
|
"attachImg": "_5KEEsG_attachImg",
|
|
1465
|
-
"
|
|
1466
|
-
"
|
|
1772
|
+
"attachRemove": "_5KEEsG_attachRemove",
|
|
1773
|
+
"assistantRow": "_5KEEsG_assistantRow",
|
|
1774
|
+
"pendingQuestion": "_5KEEsG_pendingQuestion",
|
|
1775
|
+
"writeNoticeClose": "_5KEEsG_writeNoticeClose",
|
|
1776
|
+
"toolBody": "_5KEEsG_toolBody",
|
|
1777
|
+
"sentChip": "_5KEEsG_sentChip",
|
|
1778
|
+
"pendingBar": "_5KEEsG_pendingBar",
|
|
1779
|
+
"rowActions": "_5KEEsG_rowActions",
|
|
1780
|
+
"modelSelect": "_5KEEsG_modelSelect",
|
|
1781
|
+
"attachThumb": "_5KEEsG_attachThumb",
|
|
1782
|
+
"pendingQText": "_5KEEsG_pendingQText"
|
|
1467
1783
|
};
|
|
1468
1784
|
//#endregion
|
|
1469
1785
|
//#region src/client/chat/ToolCard.tsx
|
|
@@ -1495,15 +1811,17 @@ window.__ModuleLoader__.load({
|
|
|
1495
1811
|
function ToolCard(props) {
|
|
1496
1812
|
const { model, rowKey, fold } = props;
|
|
1497
1813
|
const open = useFoldOpen(fold, rowKey);
|
|
1498
|
-
const icon = model.kind === "terminal" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlayOutline16, { size: 14 }) : model.kind === "diff" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }) : model.kind === "read" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutline16, { size: 14 }) : model.kind === "generic" ? kindIcon(model.icon) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCordisPluginOutline14, { size: 14 });
|
|
1814
|
+
const icon = model.kind === "terminal" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlayOutline16, { size: 14 }) : model.kind === "diff" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }) : model.kind === "read" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutline16, { size: 14 }) : model.kind === "todo" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutline14, { size: 14 }) : model.kind === "generic" ? kindIcon(model.icon) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCordisPluginOutline14, { size: 14 });
|
|
1499
1815
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1500
|
-
className: sidechat_module_css_default.
|
|
1816
|
+
className: sidechat_module_css_default.flowRow,
|
|
1501
1817
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
1502
1818
|
icon,
|
|
1503
1819
|
title: model.title,
|
|
1504
1820
|
open,
|
|
1505
1821
|
expandable: true,
|
|
1506
1822
|
expandOnRowClick: true,
|
|
1823
|
+
previewChevron: true,
|
|
1824
|
+
...props.error === true ? { titleClassName: sidechat_module_css_default.flowRowError } : {},
|
|
1507
1825
|
onToggle: () => {
|
|
1508
1826
|
fold.toggle(rowKey);
|
|
1509
1827
|
},
|
|
@@ -1517,7 +1835,7 @@ window.__ModuleLoader__.load({
|
|
|
1517
1835
|
function ToolCardBody({ model, streaming }) {
|
|
1518
1836
|
switch (model.kind) {
|
|
1519
1837
|
case "terminal": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
|
|
1520
|
-
command: model.
|
|
1838
|
+
command: model.command,
|
|
1521
1839
|
labels: terminalLabels(),
|
|
1522
1840
|
...model.cwd !== void 0 ? { cwd: model.cwd } : {},
|
|
1523
1841
|
...model.output !== void 0 ? { output: model.output } : {},
|
|
@@ -1525,6 +1843,20 @@ window.__ModuleLoader__.load({
|
|
|
1525
1843
|
...model.signal !== void 0 ? { signal: model.signal } : {},
|
|
1526
1844
|
...streaming === true ? { running: true } : {}
|
|
1527
1845
|
});
|
|
1846
|
+
case "todo": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1847
|
+
className: sidechat_module_css_default.todoBody,
|
|
1848
|
+
children: model.items.map((item, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1849
|
+
className: sidechat_module_css_default.todoItem,
|
|
1850
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1851
|
+
className: sidechat_module_css_default.todoDot,
|
|
1852
|
+
"data-status": item.status
|
|
1853
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1854
|
+
className: sidechat_module_css_default.todoText,
|
|
1855
|
+
"data-status": item.status,
|
|
1856
|
+
children: item.content
|
|
1857
|
+
})]
|
|
1858
|
+
}, i))
|
|
1859
|
+
});
|
|
1528
1860
|
case "diff": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DiffBlock, {
|
|
1529
1861
|
labels: diffLabels(),
|
|
1530
1862
|
diffs: model.diffs.map((d) => ({
|
|
@@ -1606,18 +1938,32 @@ window.__ModuleLoader__.load({
|
|
|
1606
1938
|
* (用户在看推理),完成后默认折叠;用户显式收起过就不再自动展开
|
|
1607
1939
|
* (fold.has 区分「未触碰」与「显式收起」)。
|
|
1608
1940
|
*/
|
|
1941
|
+
/** 首行非空文本(折叠态预览——主区「Think · 首行摘要」同款)。 */
|
|
1942
|
+
function firstLineOf(text) {
|
|
1943
|
+
for (const line of text.split("\n")) {
|
|
1944
|
+
const s = line.trim();
|
|
1945
|
+
if (s !== "") return s;
|
|
1946
|
+
}
|
|
1947
|
+
return "";
|
|
1948
|
+
}
|
|
1609
1949
|
function ReasoningRow(props) {
|
|
1610
1950
|
const { rowKey, fold } = props;
|
|
1611
1951
|
const touched = (0, react.useSyncExternalStore)((fn) => fold.subscribe(fn), () => fold.has(rowKey));
|
|
1612
1952
|
const open = (0, react.useSyncExternalStore)((fn) => fold.subscribe(fn), () => fold.isOpen(rowKey)) || props.streaming === true && !touched;
|
|
1953
|
+
const preview = firstLineOf(props.text);
|
|
1613
1954
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1614
|
-
className: sidechat_module_css_default.
|
|
1955
|
+
className: sidechat_module_css_default.flowRow,
|
|
1615
1956
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
1616
1957
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconThinkOutline16, { size: 14 }),
|
|
1617
1958
|
title: t("thinking"),
|
|
1618
1959
|
open,
|
|
1619
1960
|
expandable: true,
|
|
1620
1961
|
expandOnRowClick: true,
|
|
1962
|
+
previewChevron: true,
|
|
1963
|
+
...preview !== "" ? { collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1964
|
+
className: sidechat_module_css_default.rowPreview,
|
|
1965
|
+
children: preview
|
|
1966
|
+
}) } : {},
|
|
1621
1967
|
onToggle: () => {
|
|
1622
1968
|
fold.toggle(rowKey);
|
|
1623
1969
|
},
|
|
@@ -1642,13 +1988,14 @@ window.__ModuleLoader__.load({
|
|
|
1642
1988
|
const { rowKey, fold } = props;
|
|
1643
1989
|
const open = (0, react.useSyncExternalStore)((fn) => fold.subscribe(fn), () => fold.isOpen(rowKey));
|
|
1644
1990
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1645
|
-
className: sidechat_module_css_default.
|
|
1991
|
+
className: sidechat_module_css_default.flowRow,
|
|
1646
1992
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
1647
1993
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, { size: 14 }),
|
|
1648
1994
|
title: t("inheritedLabel", { n: props.count }),
|
|
1649
1995
|
open,
|
|
1650
1996
|
expandable: true,
|
|
1651
1997
|
expandOnRowClick: true,
|
|
1998
|
+
previewChevron: true,
|
|
1652
1999
|
onToggle: () => {
|
|
1653
2000
|
fold.toggle(rowKey);
|
|
1654
2001
|
},
|
|
@@ -1887,7 +2234,8 @@ window.__ModuleLoader__.load({
|
|
|
1887
2234
|
model: message.card,
|
|
1888
2235
|
rowKey: message.key,
|
|
1889
2236
|
fold,
|
|
1890
|
-
...message.streaming === true ? { streaming: true } : {}
|
|
2237
|
+
...message.streaming === true ? { streaming: true } : {},
|
|
2238
|
+
...message.isError === true ? { error: true } : {}
|
|
1891
2239
|
});
|
|
1892
2240
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1893
2241
|
className: sidechat_module_css_default.toolCard,
|
|
@@ -2204,14 +2552,14 @@ window.__ModuleLoader__.load({
|
|
|
2204
2552
|
side: "top",
|
|
2205
2553
|
portal: true,
|
|
2206
2554
|
compact: true,
|
|
2207
|
-
anchor: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2555
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2208
2556
|
type: "button",
|
|
2209
2557
|
className: sidechat_module_css_default.modelSelect,
|
|
2210
2558
|
title: t("modelSwitchTitle"),
|
|
2211
2559
|
onClick: () => {
|
|
2212
2560
|
open ? setOpen(false) : openMenu();
|
|
2213
2561
|
},
|
|
2214
|
-
children: t("modelLabel", { name: props.modelName ?? t("modelFollowsMain") })
|
|
2562
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("modelLabel", { name: props.modelName ?? t("modelFollowsMain") }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 12 })]
|
|
2215
2563
|
}),
|
|
2216
2564
|
items,
|
|
2217
2565
|
onClose: () => {
|
|
@@ -2268,14 +2616,18 @@ window.__ModuleLoader__.load({
|
|
|
2268
2616
|
side: "top",
|
|
2269
2617
|
portal: true,
|
|
2270
2618
|
compact: true,
|
|
2271
|
-
anchor: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2619
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2272
2620
|
type: "button",
|
|
2273
2621
|
className: sidechat_module_css_default.modelSelect,
|
|
2274
2622
|
title: t("permChipTitle"),
|
|
2275
2623
|
onClick: () => {
|
|
2276
2624
|
setOpen(!open);
|
|
2277
2625
|
},
|
|
2278
|
-
children:
|
|
2626
|
+
children: [
|
|
2627
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutline12, { size: 12 }),
|
|
2628
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: presetLabel(effective) }),
|
|
2629
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 12 })
|
|
2630
|
+
]
|
|
2279
2631
|
}),
|
|
2280
2632
|
items,
|
|
2281
2633
|
onClose: () => {
|
|
@@ -2416,110 +2768,110 @@ window.__ModuleLoader__.load({
|
|
|
2416
2768
|
triggerCtl.pick(source, index);
|
|
2417
2769
|
}
|
|
2418
2770
|
}),
|
|
2419
|
-
composer.imagePreviews.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2420
|
-
className: sidechat_module_css_default.attachRail,
|
|
2421
|
-
children: composer.imagePreviews.map((img) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2422
|
-
className: sidechat_module_css_default.attachThumb,
|
|
2423
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
2424
|
-
src: img.url,
|
|
2425
|
-
alt: "",
|
|
2426
|
-
className: sidechat_module_css_default.attachImg
|
|
2427
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2428
|
-
type: "button",
|
|
2429
|
-
className: sidechat_module_css_default.attachRemove,
|
|
2430
|
-
"aria-label": t("attachRemove"),
|
|
2431
|
-
onClick: () => {
|
|
2432
|
-
composer.removeImage(img.id);
|
|
2433
|
-
},
|
|
2434
|
-
children: "×"
|
|
2435
|
-
})]
|
|
2436
|
-
}, img.id))
|
|
2437
|
-
}),
|
|
2438
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
2439
|
-
ref: inputRef,
|
|
2440
|
-
className: sidechat_module_css_default.input,
|
|
2441
|
-
placeholder: t("inputPlaceholder"),
|
|
2442
|
-
value: composer.draft,
|
|
2443
|
-
onChange: (event) => {
|
|
2444
|
-
composer.setDraft(event.target.value);
|
|
2445
|
-
triggerCtl?.track(event.target.value, event.target.selectionStart ?? event.target.value.length, guardOf(composer.phase), composer.draftRev ?? 0);
|
|
2446
|
-
},
|
|
2447
|
-
onKeyDown: (event) => {
|
|
2448
|
-
if (menuOpen && triggerCtl !== null) {
|
|
2449
|
-
const arbKey = arbitrateKeyOf(event.key);
|
|
2450
|
-
if (arbKey !== null) {
|
|
2451
|
-
if (triggerCtl.arbitrate(arbKey, event.nativeEvent.isComposing) !== "pass") {
|
|
2452
|
-
event.preventDefault();
|
|
2453
|
-
return;
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
2456
|
-
}
|
|
2457
|
-
if (event.key !== "Enter" || event.shiftKey) return;
|
|
2458
|
-
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;
|
|
2459
|
-
event.preventDefault();
|
|
2460
|
-
composer.submit(event.metaKey || event.ctrlKey ? "steer" : void 0);
|
|
2461
|
-
}
|
|
2462
|
-
}),
|
|
2463
2771
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2464
|
-
className: sidechat_module_css_default.
|
|
2772
|
+
className: sidechat_module_css_default.composerCard,
|
|
2465
2773
|
children: [
|
|
2466
|
-
composer.
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2774
|
+
composer.imagePreviews.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2775
|
+
className: sidechat_module_css_default.attachRail,
|
|
2776
|
+
children: composer.imagePreviews.map((img) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2777
|
+
className: sidechat_module_css_default.attachThumb,
|
|
2778
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
2779
|
+
src: img.url,
|
|
2780
|
+
alt: "",
|
|
2781
|
+
className: sidechat_module_css_default.attachImg
|
|
2782
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2783
|
+
type: "button",
|
|
2784
|
+
className: sidechat_module_css_default.attachRemove,
|
|
2785
|
+
"aria-label": t("attachRemove"),
|
|
2786
|
+
onClick: () => {
|
|
2787
|
+
composer.removeImage(img.id);
|
|
2788
|
+
},
|
|
2789
|
+
children: "×"
|
|
2790
|
+
})]
|
|
2791
|
+
}, img.id))
|
|
2475
2792
|
}),
|
|
2476
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
2477
|
-
ref:
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
hidden: true,
|
|
2793
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
2794
|
+
ref: inputRef,
|
|
2795
|
+
className: sidechat_module_css_default.input,
|
|
2796
|
+
placeholder: t("inputPlaceholder"),
|
|
2797
|
+
value: composer.draft,
|
|
2482
2798
|
onChange: (event) => {
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2799
|
+
composer.setDraft(event.target.value);
|
|
2800
|
+
triggerCtl?.track(event.target.value, event.target.selectionStart ?? event.target.value.length, guardOf(composer.phase), composer.draftRev ?? 0);
|
|
2801
|
+
},
|
|
2802
|
+
onKeyDown: (event) => {
|
|
2803
|
+
if (menuOpen && triggerCtl !== null) {
|
|
2804
|
+
const arbKey = arbitrateKeyOf(event.key);
|
|
2805
|
+
if (arbKey !== null) {
|
|
2806
|
+
if (triggerCtl.arbitrate(arbKey, event.nativeEvent.isComposing) !== "pass") {
|
|
2807
|
+
event.preventDefault();
|
|
2808
|
+
return;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
if (event.key !== "Enter" || event.shiftKey) return;
|
|
2813
|
+
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;
|
|
2814
|
+
event.preventDefault();
|
|
2815
|
+
composer.submit(event.metaKey || event.ctrlKey ? "steer" : void 0);
|
|
2486
2816
|
}
|
|
2487
2817
|
}),
|
|
2488
|
-
|
|
2489
|
-
className: sidechat_module_css_default.
|
|
2490
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PermissionChip, { session }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelMenu, {
|
|
2491
|
-
ctx: props.ctx,
|
|
2492
|
-
sessionId: childIdForMenu,
|
|
2493
|
-
modelName: props.modelName,
|
|
2494
|
-
onSwitched: props.onModelSwitched
|
|
2495
|
-
})]
|
|
2496
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2497
|
-
className: sidechat_module_css_default.modelLabel,
|
|
2498
|
-
children: t("modelLabel", { name: props.modelName ?? t("modelFollowsMain") })
|
|
2499
|
-
}),
|
|
2500
|
-
running ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2501
|
-
type: "button",
|
|
2502
|
-
className: sidechat_module_css_default.stopButton,
|
|
2503
|
-
title: t("stopReplyTitle"),
|
|
2504
|
-
onClick: () => {
|
|
2505
|
-
session?.cancel().catch(() => {});
|
|
2506
|
-
},
|
|
2818
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2819
|
+
className: sidechat_module_css_default.composerFoot,
|
|
2507
2820
|
children: [
|
|
2508
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2821
|
+
composer.canAttach && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2822
|
+
type: "button",
|
|
2823
|
+
className: sidechat_module_css_default.attachButton,
|
|
2824
|
+
title: t("attachTitle"),
|
|
2825
|
+
"aria-label": t("attachTitle"),
|
|
2826
|
+
onClick: () => {
|
|
2827
|
+
fileInputRef.current?.click();
|
|
2828
|
+
},
|
|
2829
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 14 })
|
|
2830
|
+
}),
|
|
2831
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2832
|
+
ref: fileInputRef,
|
|
2833
|
+
type: "file",
|
|
2834
|
+
accept: "image/*",
|
|
2835
|
+
multiple: true,
|
|
2836
|
+
hidden: true,
|
|
2837
|
+
onChange: (event) => {
|
|
2838
|
+
const files = [...event.target.files ?? []];
|
|
2839
|
+
if (files.length > 0) composer.attachImages(files);
|
|
2840
|
+
event.target.value = "";
|
|
2841
|
+
}
|
|
2842
|
+
}),
|
|
2843
|
+
childIdForMenu !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2844
|
+
className: sidechat_module_css_default.composerChips,
|
|
2845
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PermissionChip, { session }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelMenu, {
|
|
2846
|
+
ctx: props.ctx,
|
|
2847
|
+
sessionId: childIdForMenu,
|
|
2848
|
+
modelName: props.modelName,
|
|
2849
|
+
onSwitched: props.onModelSwitched
|
|
2850
|
+
})]
|
|
2851
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2852
|
+
className: sidechat_module_css_default.modelLabel,
|
|
2853
|
+
children: t("modelLabel", { name: props.modelName ?? t("modelFollowsMain") })
|
|
2854
|
+
}),
|
|
2855
|
+
running ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2856
|
+
type: "button",
|
|
2857
|
+
className: sidechat_module_css_default.stopButton,
|
|
2858
|
+
title: t("stopReplyTitle"),
|
|
2859
|
+
"aria-label": t("stopReplyTitle"),
|
|
2860
|
+
onClick: () => {
|
|
2861
|
+
session?.cancel().catch(() => {});
|
|
2862
|
+
},
|
|
2863
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconStopFill16, { size: 12 })
|
|
2864
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2865
|
+
type: "button",
|
|
2866
|
+
className: sidechat_module_css_default.sendButton,
|
|
2867
|
+
title: t("send"),
|
|
2868
|
+
"aria-label": t("send"),
|
|
2869
|
+
disabled: composer.draft.trim() === "",
|
|
2870
|
+
onClick: () => {
|
|
2871
|
+
composer.submit();
|
|
2872
|
+
},
|
|
2873
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSendOutline16, { size: 14 })
|
|
2874
|
+
})
|
|
2523
2875
|
]
|
|
2524
2876
|
})
|
|
2525
2877
|
]
|
|
@@ -2581,6 +2933,394 @@ window.__ModuleLoader__.load({
|
|
|
2581
2933
|
};
|
|
2582
2934
|
}
|
|
2583
2935
|
//#endregion
|
|
2936
|
+
//#region src/client/sidechat/toast.tsx
|
|
2937
|
+
/**
|
|
2938
|
+
* 全局瞬态通知(P4 确认反馈):body 级独立 React 根,寿命不随任何 Tab——
|
|
2939
|
+
* 「保存为正式会话」后主视图跳转 + 侧聊 Tab 关闭,面板自己的组件树已卸载,
|
|
2940
|
+
* toast 必须挂在更长寿的宿主上(annotate overlay 同款 ctx.effect 模式:
|
|
2941
|
+
* HMR/插件禁用时 fiber 撤销即清理)。
|
|
2942
|
+
*/
|
|
2943
|
+
let current = null;
|
|
2944
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2945
|
+
function emit() {
|
|
2946
|
+
for (const fn of listeners) fn();
|
|
2947
|
+
}
|
|
2948
|
+
/** 全局瞬态通知入口(任何模块可调;未挂载宿主时静默丢弃)。 */
|
|
2949
|
+
function showToast(text) {
|
|
2950
|
+
current = {
|
|
2951
|
+
seq: (current?.seq ?? 0) + 1,
|
|
2952
|
+
text
|
|
2953
|
+
};
|
|
2954
|
+
emit();
|
|
2955
|
+
}
|
|
2956
|
+
function subscribe(fn) {
|
|
2957
|
+
listeners.add(fn);
|
|
2958
|
+
return () => {
|
|
2959
|
+
listeners.delete(fn);
|
|
2960
|
+
};
|
|
2961
|
+
}
|
|
2962
|
+
function ToastHost() {
|
|
2963
|
+
const snap = (0, react.useSyncExternalStore)(subscribe, () => current);
|
|
2964
|
+
if (snap === null) return null;
|
|
2965
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
2966
|
+
text: snap.text,
|
|
2967
|
+
onDone: () => {
|
|
2968
|
+
current = null;
|
|
2969
|
+
emit();
|
|
2970
|
+
}
|
|
2971
|
+
}, snap.seq);
|
|
2972
|
+
}
|
|
2973
|
+
/** 挂载全局 toast 宿主(registerSideChat 里调用一次)。 */
|
|
2974
|
+
function registerToastHost(ctx) {
|
|
2975
|
+
ctx.effect(() => {
|
|
2976
|
+
const host = document.createElement("div");
|
|
2977
|
+
host.dataset.dshSidenoteToast = "";
|
|
2978
|
+
document.body.appendChild(host);
|
|
2979
|
+
const root = (0, react_dom_client.createRoot)(host);
|
|
2980
|
+
root.render(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToastHost, {}));
|
|
2981
|
+
return () => {
|
|
2982
|
+
root.unmount();
|
|
2983
|
+
host.remove();
|
|
2984
|
+
};
|
|
2985
|
+
}, "dsh-sidenote: toast host");
|
|
2986
|
+
}
|
|
2987
|
+
//#endregion
|
|
2988
|
+
//#region src/client/sidechat/pending.ts
|
|
2989
|
+
function adapt012(pending) {
|
|
2990
|
+
if (typeof pending !== "object" || pending === null) return [];
|
|
2991
|
+
const o = pending;
|
|
2992
|
+
if (o.kind === "approval" && typeof o.answer === "function") return [{
|
|
2993
|
+
kind: "approval",
|
|
2994
|
+
key: typeof o.key === "string" ? o.key : "approval",
|
|
2995
|
+
toolName: typeof o.toolName === "string" ? o.toolName : "",
|
|
2996
|
+
...typeof o.reason === "string" ? { reason: o.reason } : {},
|
|
2997
|
+
answer: (outcome) => o.answer.call(o, outcome)
|
|
2998
|
+
}];
|
|
2999
|
+
if ((o.kind === "question" || o.kind === "plan-review") && typeof o.answer === "function" && typeof o.cancel === "function") {
|
|
3000
|
+
const questions = normalizeQuestions(o.questions ?? o.payload?.questions);
|
|
3001
|
+
if (questions === void 0) return [];
|
|
3002
|
+
return [{
|
|
3003
|
+
kind: "question",
|
|
3004
|
+
key: typeof o.key === "string" ? o.key : "question",
|
|
3005
|
+
planReview: o.kind === "plan-review",
|
|
3006
|
+
questions,
|
|
3007
|
+
answer: (answers) => o.answer.call(o, { answers }),
|
|
3008
|
+
cancel: () => o.cancel.call(o)
|
|
3009
|
+
}];
|
|
3010
|
+
}
|
|
3011
|
+
return [];
|
|
3012
|
+
}
|
|
3013
|
+
function adapt011(pending) {
|
|
3014
|
+
const items = [];
|
|
3015
|
+
for (const raw of pending) {
|
|
3016
|
+
const w = raw;
|
|
3017
|
+
if (typeof w.respond !== "function") continue;
|
|
3018
|
+
const respond = w.respond;
|
|
3019
|
+
const sessionId = typeof w.sessionId === "string" ? w.sessionId : void 0;
|
|
3020
|
+
if (sessionId === void 0) continue;
|
|
3021
|
+
const payload = w.payload ?? {};
|
|
3022
|
+
const key = typeof w.key === "string" ? w.key : `pending:${items.length}`;
|
|
3023
|
+
if (w.kind === "approval") {
|
|
3024
|
+
const approvalId = payload.approvalId;
|
|
3025
|
+
if (typeof approvalId !== "string") continue;
|
|
3026
|
+
items.push({
|
|
3027
|
+
kind: "approval",
|
|
3028
|
+
key,
|
|
3029
|
+
toolName: typeof payload.toolName === "string" ? payload.toolName : "",
|
|
3030
|
+
...typeof payload.reason === "string" ? { reason: payload.reason } : {},
|
|
3031
|
+
answer: async (outcome) => {
|
|
3032
|
+
if ((await respond({
|
|
3033
|
+
ok: true,
|
|
3034
|
+
value: {
|
|
3035
|
+
sessionId,
|
|
3036
|
+
approvalId,
|
|
3037
|
+
outcome
|
|
3038
|
+
}
|
|
3039
|
+
})).accepted === false) throw new Error("approval response rejected (not pending)");
|
|
3040
|
+
}
|
|
3041
|
+
});
|
|
3042
|
+
} else if (w.kind === "question") {
|
|
3043
|
+
const questions = normalizeQuestions(payload.questions);
|
|
3044
|
+
if (questions === void 0) continue;
|
|
3045
|
+
items.push({
|
|
3046
|
+
kind: "question",
|
|
3047
|
+
key,
|
|
3048
|
+
planReview: false,
|
|
3049
|
+
questions,
|
|
3050
|
+
answer: async (answers) => {
|
|
3051
|
+
if ((await respond({
|
|
3052
|
+
ok: true,
|
|
3053
|
+
value: {
|
|
3054
|
+
sessionId,
|
|
3055
|
+
answer: { answers }
|
|
3056
|
+
}
|
|
3057
|
+
})).accepted === false) throw new Error("question response rejected (not pending)");
|
|
3058
|
+
},
|
|
3059
|
+
cancel: async () => {
|
|
3060
|
+
await respond({
|
|
3061
|
+
ok: false,
|
|
3062
|
+
error: {
|
|
3063
|
+
code: "cancelled",
|
|
3064
|
+
message: "the user closed this question request",
|
|
3065
|
+
details: {}
|
|
3066
|
+
}
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
return items;
|
|
3073
|
+
}
|
|
3074
|
+
/** questions 字段归一(选项 {label,description?} 与纯字符串两形都收)。 */
|
|
3075
|
+
function normalizeQuestions(raw) {
|
|
3076
|
+
if (!Array.isArray(raw)) return void 0;
|
|
3077
|
+
const out = [];
|
|
3078
|
+
for (const rawQ of raw) {
|
|
3079
|
+
if (typeof rawQ !== "object" || rawQ === null) return void 0;
|
|
3080
|
+
const q = rawQ;
|
|
3081
|
+
if (typeof q.question !== "string") return void 0;
|
|
3082
|
+
const options = [];
|
|
3083
|
+
if (Array.isArray(q.options)) for (const rawO of q.options) if (typeof rawO === "string") options.push({ label: rawO });
|
|
3084
|
+
else if (typeof rawO === "object" && rawO !== null && typeof rawO.label === "string") {
|
|
3085
|
+
const oo = rawO;
|
|
3086
|
+
options.push({
|
|
3087
|
+
label: oo.label,
|
|
3088
|
+
...typeof oo.description === "string" ? { description: oo.description } : {}
|
|
3089
|
+
});
|
|
3090
|
+
} else return void 0;
|
|
3091
|
+
out.push({
|
|
3092
|
+
id: typeof q.id === "string" ? q.id : `q${out.length}`,
|
|
3093
|
+
question: q.question,
|
|
3094
|
+
...typeof q.header === "string" ? { header: q.header } : {},
|
|
3095
|
+
...typeof q.detail === "string" ? { detail: q.detail } : {},
|
|
3096
|
+
options,
|
|
3097
|
+
multiSelect: q.multiSelect === true
|
|
3098
|
+
});
|
|
3099
|
+
}
|
|
3100
|
+
return out;
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* 双版本探测链(chatSourceOf 同款纪律):0.1.2 uiSession.pendingInteractions
|
|
3104
|
+
* (getSnapshot() 是 Map 才认)优先;0.1.1 Session 快照 pending 数组回退;
|
|
3105
|
+
* 双缺席 undefined(面板回退 pendingBar 跳转)。
|
|
3106
|
+
*/
|
|
3107
|
+
function createPendingStore(ctx, session, childId) {
|
|
3108
|
+
try {
|
|
3109
|
+
const pim = (typeof ctx.get === "function" ? ctx.get("uiSession") : void 0)?.pendingInteractions;
|
|
3110
|
+
if (pim !== void 0 && typeof pim.subscribe === "function" && typeof pim.getSnapshot === "function") {
|
|
3111
|
+
const obs = pim;
|
|
3112
|
+
if (obs.getSnapshot() instanceof Map) {
|
|
3113
|
+
let cachedMap = null;
|
|
3114
|
+
let cachedItems = [];
|
|
3115
|
+
return {
|
|
3116
|
+
available: true,
|
|
3117
|
+
subscribe: (fn) => obs.subscribe(fn),
|
|
3118
|
+
getSnapshot: () => {
|
|
3119
|
+
const map = obs.getSnapshot();
|
|
3120
|
+
if (map === cachedMap) return cachedItems;
|
|
3121
|
+
cachedMap = map;
|
|
3122
|
+
cachedItems = map instanceof Map ? adapt012(map.get(childId)) : [];
|
|
3123
|
+
return cachedItems;
|
|
3124
|
+
}
|
|
3125
|
+
};
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
} catch {}
|
|
3129
|
+
if (session === void 0) return void 0;
|
|
3130
|
+
try {
|
|
3131
|
+
const snap = session.getSnapshot();
|
|
3132
|
+
if (Array.isArray(snap?.pending)) {
|
|
3133
|
+
let cachedArr = null;
|
|
3134
|
+
let cachedItems = [];
|
|
3135
|
+
return {
|
|
3136
|
+
available: true,
|
|
3137
|
+
subscribe: (fn) => session.subscribe(fn),
|
|
3138
|
+
getSnapshot: () => {
|
|
3139
|
+
const arr = session.getSnapshot()?.pending;
|
|
3140
|
+
if (arr === cachedArr) return cachedItems;
|
|
3141
|
+
cachedArr = arr;
|
|
3142
|
+
cachedItems = Array.isArray(arr) ? adapt011(arr) : [];
|
|
3143
|
+
return cachedItems;
|
|
3144
|
+
}
|
|
3145
|
+
};
|
|
3146
|
+
}
|
|
3147
|
+
} catch {}
|
|
3148
|
+
}
|
|
3149
|
+
//#endregion
|
|
3150
|
+
//#region src/client/sidechat/PendingCard.tsx
|
|
3151
|
+
/**
|
|
3152
|
+
* R8 审批/提问答复卡(L2 视图):钉在 composer 上方(原 pendingBar 位置)。
|
|
3153
|
+
* 自绘 + primitives 图标(材质同源,不求像素级复刻宿主审批卡)。
|
|
3154
|
+
*
|
|
3155
|
+
* 竞答纪律:先答先得——点击后置 answered 本地态;answer 失败(已被主视图
|
|
3156
|
+
* 抢答/settle)catch 吞错并回退按钮态(宿主 `.catch(() => setAnswered(false))`
|
|
3157
|
+
* 同款);卡片消失由快照驱动(pending 项消失即卸载),UI 不自造状态机。
|
|
3158
|
+
*/
|
|
3159
|
+
function PendingCardList({ items }) {
|
|
3160
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: items.map((item) => item.kind === "approval" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ApprovalCard, { item }, item.key) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuestionCard, { item }, item.key)) });
|
|
3161
|
+
}
|
|
3162
|
+
/** 审批卡:reason + 拒绝 / 允许一次。 */
|
|
3163
|
+
function ApprovalCard({ item }) {
|
|
3164
|
+
useLocaleTick();
|
|
3165
|
+
const [answered, setAnswered] = (0, react.useState)(false);
|
|
3166
|
+
const answer = (outcome) => {
|
|
3167
|
+
setAnswered(true);
|
|
3168
|
+
item.answer(outcome).catch(() => {
|
|
3169
|
+
setAnswered(false);
|
|
3170
|
+
});
|
|
3171
|
+
};
|
|
3172
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3173
|
+
className: sidechat_module_css_default.pendingCard,
|
|
3174
|
+
"data-kind": "approval",
|
|
3175
|
+
children: [
|
|
3176
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3177
|
+
className: sidechat_module_css_default.pendingHead,
|
|
3178
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16, { size: 14 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3179
|
+
className: sidechat_module_css_default.pendingTitle,
|
|
3180
|
+
children: t("pendingApprovalTitle")
|
|
3181
|
+
})]
|
|
3182
|
+
}),
|
|
3183
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3184
|
+
className: sidechat_module_css_default.pendingDesc,
|
|
3185
|
+
children: t("pendingApprovalDesc", { name: item.toolName })
|
|
3186
|
+
}),
|
|
3187
|
+
item.reason !== void 0 && item.reason !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3188
|
+
className: sidechat_module_css_default.pendingReason,
|
|
3189
|
+
children: item.reason
|
|
3190
|
+
}),
|
|
3191
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3192
|
+
className: sidechat_module_css_default.pendingActions,
|
|
3193
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3194
|
+
type: "button",
|
|
3195
|
+
className: sidechat_module_css_default.pendingBtnGhost,
|
|
3196
|
+
disabled: answered,
|
|
3197
|
+
onClick: () => {
|
|
3198
|
+
answer("rejected");
|
|
3199
|
+
},
|
|
3200
|
+
children: t("pendingReject")
|
|
3201
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3202
|
+
type: "button",
|
|
3203
|
+
className: sidechat_module_css_default.pendingBtnPrimary,
|
|
3204
|
+
disabled: answered,
|
|
3205
|
+
onClick: () => {
|
|
3206
|
+
answer("allowed-once");
|
|
3207
|
+
},
|
|
3208
|
+
children: t("pendingAllowOnce")
|
|
3209
|
+
})]
|
|
3210
|
+
})
|
|
3211
|
+
]
|
|
3212
|
+
});
|
|
3213
|
+
}
|
|
3214
|
+
/** 提问卡:选项(单选即点即答语义并入整批提交)+ 自定义 + 整批提交/取消。 */
|
|
3215
|
+
function QuestionCard({ item }) {
|
|
3216
|
+
useLocaleTick();
|
|
3217
|
+
const [selections, setSelections] = (0, react.useState)(/* @__PURE__ */ new Map());
|
|
3218
|
+
const [customs, setCustoms] = (0, react.useState)(/* @__PURE__ */ new Map());
|
|
3219
|
+
const [answered, setAnswered] = (0, react.useState)(false);
|
|
3220
|
+
const toggle = (qid, label, multi) => {
|
|
3221
|
+
const next = new Map(selections);
|
|
3222
|
+
const cur = new Set(next.get(qid) ?? []);
|
|
3223
|
+
if (multi) {
|
|
3224
|
+
if (cur.has(label)) cur.delete(label);
|
|
3225
|
+
else cur.add(label);
|
|
3226
|
+
} else {
|
|
3227
|
+
cur.clear();
|
|
3228
|
+
cur.add(label);
|
|
3229
|
+
}
|
|
3230
|
+
next.set(qid, cur);
|
|
3231
|
+
setSelections(next);
|
|
3232
|
+
};
|
|
3233
|
+
const ready = item.questions.every((q) => (selections.get(q.id)?.size ?? 0) > 0 || (customs.get(q.id)?.trim() ?? "") !== "");
|
|
3234
|
+
const submit = () => {
|
|
3235
|
+
setAnswered(true);
|
|
3236
|
+
item.answer(item.questions.map((q) => ({
|
|
3237
|
+
id: q.id,
|
|
3238
|
+
selected: [...selections.get(q.id) ?? []],
|
|
3239
|
+
...(customs.get(q.id)?.trim() ?? "") !== "" ? { custom: customs.get(q.id).trim() } : {}
|
|
3240
|
+
}))).catch(() => {
|
|
3241
|
+
setAnswered(false);
|
|
3242
|
+
});
|
|
3243
|
+
};
|
|
3244
|
+
const cancel = () => {
|
|
3245
|
+
setAnswered(true);
|
|
3246
|
+
item.cancel().catch(() => {
|
|
3247
|
+
setAnswered(false);
|
|
3248
|
+
});
|
|
3249
|
+
};
|
|
3250
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3251
|
+
className: sidechat_module_css_default.pendingCard,
|
|
3252
|
+
"data-kind": "question",
|
|
3253
|
+
children: [
|
|
3254
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3255
|
+
className: sidechat_module_css_default.pendingHead,
|
|
3256
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQuestionOutline14, { size: 14 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3257
|
+
className: sidechat_module_css_default.pendingTitle,
|
|
3258
|
+
children: item.planReview ? t("pendingPlanReview") : t("pendingQuestionTitle")
|
|
3259
|
+
})]
|
|
3260
|
+
}),
|
|
3261
|
+
item.questions.map((q) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3262
|
+
className: sidechat_module_css_default.pendingQuestion,
|
|
3263
|
+
children: [
|
|
3264
|
+
q.header !== void 0 && q.header !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3265
|
+
className: sidechat_module_css_default.pendingQHeader,
|
|
3266
|
+
children: q.header
|
|
3267
|
+
}),
|
|
3268
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3269
|
+
className: sidechat_module_css_default.pendingQText,
|
|
3270
|
+
children: q.question
|
|
3271
|
+
}),
|
|
3272
|
+
q.detail !== void 0 && q.detail !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3273
|
+
className: sidechat_module_css_default.pendingReason,
|
|
3274
|
+
children: q.detail
|
|
3275
|
+
}),
|
|
3276
|
+
q.options.map((o) => {
|
|
3277
|
+
const active = selections.get(q.id)?.has(o.label) === true;
|
|
3278
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3279
|
+
type: "button",
|
|
3280
|
+
className: active ? sidechat_module_css_default.pendingOptionActive : sidechat_module_css_default.pendingOption,
|
|
3281
|
+
disabled: answered,
|
|
3282
|
+
onClick: () => {
|
|
3283
|
+
toggle(q.id, o.label, q.multiSelect);
|
|
3284
|
+
},
|
|
3285
|
+
children: [o.label, o.description !== void 0 && o.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3286
|
+
className: sidechat_module_css_default.pendingOptionDesc,
|
|
3287
|
+
children: o.description
|
|
3288
|
+
})]
|
|
3289
|
+
}, o.label);
|
|
3290
|
+
}),
|
|
3291
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3292
|
+
className: sidechat_module_css_default.pendingCustom,
|
|
3293
|
+
placeholder: t("pendingCustomPlaceholder"),
|
|
3294
|
+
disabled: answered,
|
|
3295
|
+
value: customs.get(q.id) ?? "",
|
|
3296
|
+
onChange: (event) => {
|
|
3297
|
+
const next = new Map(customs);
|
|
3298
|
+
next.set(q.id, event.target.value);
|
|
3299
|
+
setCustoms(next);
|
|
3300
|
+
}
|
|
3301
|
+
})
|
|
3302
|
+
]
|
|
3303
|
+
}, q.id)),
|
|
3304
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3305
|
+
className: sidechat_module_css_default.pendingActions,
|
|
3306
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3307
|
+
type: "button",
|
|
3308
|
+
className: sidechat_module_css_default.pendingBtnGhost,
|
|
3309
|
+
disabled: answered,
|
|
3310
|
+
onClick: cancel,
|
|
3311
|
+
children: t("pendingQuestionCancel")
|
|
3312
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3313
|
+
type: "button",
|
|
3314
|
+
className: sidechat_module_css_default.pendingBtnPrimary,
|
|
3315
|
+
disabled: answered || !ready,
|
|
3316
|
+
onClick: submit,
|
|
3317
|
+
children: t("pendingQuestionSubmit")
|
|
3318
|
+
})]
|
|
3319
|
+
})
|
|
3320
|
+
]
|
|
3321
|
+
});
|
|
3322
|
+
}
|
|
3323
|
+
//#endregion
|
|
2584
3324
|
//#region src/client/sidechat/SideChatPanel.tsx
|
|
2585
3325
|
/**
|
|
2586
3326
|
* 侧边聊天 Tab 面板(L2 薄视图):相位编排 + 消息流 + composer。
|
|
@@ -2597,6 +3337,8 @@ window.__ModuleLoader__.load({
|
|
|
2597
3337
|
* 否则消息流永远为空(client-runtime 只为 staged 会话开窗的已知偏差)。
|
|
2598
3338
|
*/
|
|
2599
3339
|
const NOOP_UNSUBSCRIBE = () => {};
|
|
3340
|
+
/** uSES 空快照常量(禁产新引用——`?? []` 字面量每次新数组会无限重渲)。 */
|
|
3341
|
+
const NO_PENDING = [];
|
|
2600
3342
|
/** D2 写型工具名(无 diff 卡时的名字兜底)。 */
|
|
2601
3343
|
const WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
2602
3344
|
"edit",
|
|
@@ -2657,6 +3399,12 @@ window.__ModuleLoader__.load({
|
|
|
2657
3399
|
const fold = (0, react.useMemo)(() => createFoldStore(childId === void 0 ? void 0 : `dsh-sidenote:fold:v1:${childId}`), [childId]);
|
|
2658
3400
|
const parentSession = meta.parentSessionId === void 0 ? void 0 : ctx.sessions.binding(meta.parentSessionId)?.session;
|
|
2659
3401
|
const parentSnap = (0, react.useSyncExternalStore)((0, react.useCallback)((notify) => visible && parentSession !== void 0 ? parentSession.subscribe(notify) : NOOP_UNSUBSCRIBE, [visible, parentSession]), () => parentSession === void 0 ? null : parentSession.getSnapshot());
|
|
3402
|
+
const pendingStore = (0, react.useMemo)(() => childId === void 0 || session === void 0 ? void 0 : createPendingStore(ctx, session, childId), [
|
|
3403
|
+
ctx,
|
|
3404
|
+
session,
|
|
3405
|
+
childId
|
|
3406
|
+
]);
|
|
3407
|
+
const pendingItems = (0, react.useSyncExternalStore)((0, react.useCallback)((notify) => visible && pendingStore !== void 0 ? pendingStore.subscribe(notify) : NOOP_UNSUBSCRIBE, [visible, pendingStore]), () => pendingStore?.getSnapshot() ?? NO_PENDING);
|
|
2660
3408
|
const [writeNoticeDismissed, setWriteNoticeDismissed] = (0, react.useState)(() => typeof localStorage !== "undefined" && localStorage.getItem(WRITE_NOTICE_KEY) === "1");
|
|
2661
3409
|
const composer = useComposer(ctx, session, childId);
|
|
2662
3410
|
const [modelName, setModelName] = (0, react.useState)(null);
|
|
@@ -2699,6 +3447,7 @@ window.__ModuleLoader__.load({
|
|
|
2699
3447
|
});
|
|
2700
3448
|
ctx.sessions.open(promoted);
|
|
2701
3449
|
ctx.betterSidebar.closeTab(tab.id, { sessionId: scope.sessionId });
|
|
3450
|
+
showToast(t("promoteDone"));
|
|
2702
3451
|
} catch (error) {
|
|
2703
3452
|
console.warn("[dsh-sidenote] 保存为正式会话失败:", error);
|
|
2704
3453
|
}
|
|
@@ -2829,7 +3578,8 @@ window.__ModuleLoader__.load({
|
|
|
2829
3578
|
children: "×"
|
|
2830
3579
|
})]
|
|
2831
3580
|
}),
|
|
2832
|
-
|
|
3581
|
+
pendingStore !== void 0 && pendingItems.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PendingCardList, { items: pendingItems }),
|
|
3582
|
+
pendingStore === void 0 && pendingCount > 0 && childId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2833
3583
|
type: "button",
|
|
2834
3584
|
className: sidechat_module_css_default.pendingBar,
|
|
2835
3585
|
onClick: () => {
|
|
@@ -3068,6 +3818,66 @@ window.__ModuleLoader__.load({
|
|
|
3068
3818
|
}
|
|
3069
3819
|
}
|
|
3070
3820
|
//#endregion
|
|
3821
|
+
//#region src/client/sidechat/notify.ts
|
|
3822
|
+
/** 挂接保护窗:watcher 建立后该窗口内的翻转不视为「一个真实 turn 跑完」。 */
|
|
3823
|
+
const ATTACH_GRACE_MS = 800;
|
|
3824
|
+
/**
|
|
3825
|
+
* 翻转侦测核心(抽出来纯可测):running true→false 且距挂接超过保护窗
|
|
3826
|
+
* 时返回 true。调用方持状态。
|
|
3827
|
+
*/
|
|
3828
|
+
function shouldNotify(wasRunning, running, attachedAt, now) {
|
|
3829
|
+
return wasRunning && !running && now - attachedAt > ATTACH_GRACE_MS;
|
|
3830
|
+
}
|
|
3831
|
+
function registerCompletionNotify(ctx) {
|
|
3832
|
+
ctx.effect(() => {
|
|
3833
|
+
const watchers = /* @__PURE__ */ new Map();
|
|
3834
|
+
const rescan = () => {
|
|
3835
|
+
let tabs = [];
|
|
3836
|
+
try {
|
|
3837
|
+
tabs = collectSideTabs(ctx.betterSidebar.getSnapshot());
|
|
3838
|
+
} catch {
|
|
3839
|
+
return;
|
|
3840
|
+
}
|
|
3841
|
+
const alive = /* @__PURE__ */ new Set();
|
|
3842
|
+
for (const tab of tabs) {
|
|
3843
|
+
const childId = parseSideChatMeta(tab.meta).childId;
|
|
3844
|
+
if (childId === void 0) continue;
|
|
3845
|
+
alive.add(childId);
|
|
3846
|
+
if (watchers.has(childId)) continue;
|
|
3847
|
+
try {
|
|
3848
|
+
const session = ctx.sessions.binding(childId)?.session;
|
|
3849
|
+
if (session === void 0) continue;
|
|
3850
|
+
openSessionWindow(session);
|
|
3851
|
+
const title = tab.title;
|
|
3852
|
+
const watcher = {
|
|
3853
|
+
unsub: () => {},
|
|
3854
|
+
wasRunning: false,
|
|
3855
|
+
since: Date.now()
|
|
3856
|
+
};
|
|
3857
|
+
watcher.unsub = session.subscribe(() => {
|
|
3858
|
+
const running = session.getSnapshot()?.running === true;
|
|
3859
|
+
if (shouldNotify(watcher.wasRunning, running, watcher.since, Date.now())) showToast(t("sideChatDone", { title }));
|
|
3860
|
+
watcher.wasRunning = running;
|
|
3861
|
+
});
|
|
3862
|
+
watcher.wasRunning = session.getSnapshot()?.running === true;
|
|
3863
|
+
watchers.set(childId, watcher);
|
|
3864
|
+
} catch {}
|
|
3865
|
+
}
|
|
3866
|
+
for (const [id, w] of watchers) if (!alive.has(id)) {
|
|
3867
|
+
w.unsub();
|
|
3868
|
+
watchers.delete(id);
|
|
3869
|
+
}
|
|
3870
|
+
};
|
|
3871
|
+
const offState = ctx.betterSidebar.subscribeState(rescan);
|
|
3872
|
+
rescan();
|
|
3873
|
+
return () => {
|
|
3874
|
+
offState();
|
|
3875
|
+
for (const w of watchers.values()) w.unsub();
|
|
3876
|
+
watchers.clear();
|
|
3877
|
+
};
|
|
3878
|
+
}, "dsh-sidenote: completion notify");
|
|
3879
|
+
}
|
|
3880
|
+
//#endregion
|
|
3071
3881
|
//#region src/client/sidechat/index.tsx
|
|
3072
3882
|
/**
|
|
3073
3883
|
* Workitem 01 — 侧边聊天面板。
|
|
@@ -3125,6 +3935,8 @@ window.__ModuleLoader__.load({
|
|
|
3125
3935
|
registerSideCommand(ctx);
|
|
3126
3936
|
registerSideChatReferenceSource(ctx);
|
|
3127
3937
|
registerHeaderEntry(ctx);
|
|
3938
|
+
registerToastHost(ctx);
|
|
3939
|
+
registerCompletionNotify(ctx);
|
|
3128
3940
|
}
|
|
3129
3941
|
//#endregion
|
|
3130
3942
|
//#region src/client/annotate/model.ts
|
|
@@ -3577,43 +4389,43 @@ window.__ModuleLoader__.load({
|
|
|
3577
4389
|
document.head.appendChild(tag);
|
|
3578
4390
|
}
|
|
3579
4391
|
var annotate_module_css_default = {
|
|
4392
|
+
"toolbarButton": "_SVViG_toolbarButton",
|
|
4393
|
+
"editorSpacer": "_SVViG_editorSpacer",
|
|
4394
|
+
"sentCardTitle": "_SVViG_sentCardTitle",
|
|
4395
|
+
"chipRemove": "_SVViG_chipRemove",
|
|
3580
4396
|
"toolbarBelow": "_SVViG_toolbarBelow",
|
|
3581
|
-
"
|
|
3582
|
-
"editorEdit": "_SVViG_editorEdit",
|
|
3583
|
-
"editorAsk": "_SVViG_editorAsk",
|
|
3584
|
-
"badgeSent": "_SVViG_badgeSent",
|
|
3585
|
-
"sentChip": "_SVViG_sentChip",
|
|
3586
|
-
"chipClearAll": "_SVViG_chipClearAll",
|
|
3587
|
-
"deleteButton": "_SVViG_deleteButton",
|
|
3588
|
-
"dshSidenoteHintIn": "_SVViG_dshSidenoteHintIn",
|
|
3589
|
-
"chipRow": "_SVViG_chipRow",
|
|
3590
|
-
"saveButton": "_SVViG_saveButton",
|
|
3591
|
-
"editorAskRow": "_SVViG_editorAskRow",
|
|
3592
|
-
"chipNote": "_SVViG_chipNote",
|
|
4397
|
+
"editorTextarea": "_SVViG_editorTextarea",
|
|
3593
4398
|
"chipWrap": "_SVViG_chipWrap",
|
|
3594
|
-
"
|
|
4399
|
+
"chipClearAll": "_SVViG_chipClearAll",
|
|
3595
4400
|
"editorNew": "_SVViG_editorNew",
|
|
3596
|
-
"editorInput": "_SVViG_editorInput",
|
|
3597
|
-
"hint": "_SVViG_hint",
|
|
3598
|
-
"sentChipRow": "_SVViG_sentChipRow",
|
|
3599
|
-
"sentCardTitle": "_SVViG_sentCardTitle",
|
|
3600
|
-
"chipText": "_SVViG_chipText",
|
|
3601
|
-
"editorTarget": "_SVViG_editorTarget",
|
|
3602
|
-
"chipPanel": "_SVViG_chipPanel",
|
|
3603
|
-
"confirmButton": "_SVViG_confirmButton",
|
|
3604
4401
|
"badge": "_SVViG_badge",
|
|
3605
|
-
"
|
|
4402
|
+
"editorAskRow": "_SVViG_editorAskRow",
|
|
4403
|
+
"chipText": "_SVViG_chipText",
|
|
4404
|
+
"badgeSent": "_SVViG_badgeSent",
|
|
4405
|
+
"editorError": "_SVViG_editorError",
|
|
3606
4406
|
"cancelButton": "_SVViG_cancelButton",
|
|
3607
|
-
"
|
|
4407
|
+
"deleteButton": "_SVViG_deleteButton",
|
|
4408
|
+
"chipPanel": "_SVViG_chipPanel",
|
|
4409
|
+
"chipNote": "_SVViG_chipNote",
|
|
4410
|
+
"highlight": "_SVViG_highlight",
|
|
4411
|
+
"dshSidenoteHintIn": "_SVViG_dshSidenoteHintIn",
|
|
4412
|
+
"sentChipRow": "_SVViG_sentChipRow",
|
|
4413
|
+
"hintClose": "_SVViG_hintClose",
|
|
3608
4414
|
"chipNumber": "_SVViG_chipNumber",
|
|
3609
|
-
"
|
|
3610
|
-
"sentCardQuote": "_SVViG_sentCardQuote",
|
|
3611
|
-
"editorError": "_SVViG_editorError",
|
|
4415
|
+
"saveButton": "_SVViG_saveButton",
|
|
3612
4416
|
"chip": "_SVViG_chip",
|
|
3613
|
-
"
|
|
3614
|
-
"
|
|
3615
|
-
"
|
|
3616
|
-
"
|
|
4417
|
+
"chipRow": "_SVViG_chipRow",
|
|
4418
|
+
"sentChip": "_SVViG_sentChip",
|
|
4419
|
+
"sentCardQuote": "_SVViG_sentCardQuote",
|
|
4420
|
+
"hint": "_SVViG_hint",
|
|
4421
|
+
"editorInput": "_SVViG_editorInput",
|
|
4422
|
+
"toolbar": "_SVViG_toolbar",
|
|
4423
|
+
"confirmButton": "_SVViG_confirmButton",
|
|
4424
|
+
"editorEdit": "_SVViG_editorEdit",
|
|
4425
|
+
"editorAsk": "_SVViG_editorAsk",
|
|
4426
|
+
"editorTarget": "_SVViG_editorTarget",
|
|
4427
|
+
"sentCardNote": "_SVViG_sentCardNote",
|
|
4428
|
+
"editorFooter": "_SVViG_editorFooter"
|
|
3617
4429
|
};
|
|
3618
4430
|
//#endregion
|
|
3619
4431
|
//#region src/client/annotate/hint.tsx
|