dsh-sidenote 0.3.1 → 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/lib/client.js CHANGED
@@ -88,10 +88,20 @@ window.__ModuleLoader__.load({
88
88
  modelSwitchTitle: "Switch the side chat model",
89
89
  permChipTitle: "Permission mode",
90
90
  permFullAccess: "Full access",
91
- pendingNotice: "⚠ 侧边会话有审批/提问待处理——点击跳到主视图处理",
92
- writeNotice: "侧边会话与主会话同权限,可以修改文件(当前模式见输入框旁 chip)",
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…",
93
102
  modelFollowsMain: "follows main session",
94
103
  stopReply: "Stop",
104
+ sideChatDone: "「{title}」finished replying",
95
105
  stopReplyTitle: "Stop the current reply",
96
106
  send: "Send",
97
107
  attachTitle: "Attach images",
@@ -214,8 +224,18 @@ window.__ModuleLoader__.load({
214
224
  permFullAccess: "Full access",
215
225
  pendingNotice: "⚠ 侧边会话有审批/提问待处理——点击跳到主视图处理",
216
226
  writeNotice: "侧边会话与主会话同权限,可以修改文件(当前模式见输入框旁 chip)",
227
+ pendingApprovalTitle: "等待审批",
228
+ pendingApprovalDesc: "工具 {name} 请求越权执行",
229
+ pendingReject: "拒绝",
230
+ pendingAllowOnce: "允许一次",
231
+ pendingQuestionTitle: "提问",
232
+ pendingPlanReview: "计划审批",
233
+ pendingQuestionSubmit: "提交回答",
234
+ pendingQuestionCancel: "取消",
235
+ pendingCustomPlaceholder: "自定义回答…",
217
236
  modelFollowsMain: "跟随主会话",
218
237
  stopReply: "停止",
238
+ sideChatDone: "「{title}」回复完成",
219
239
  stopReplyTitle: "停止当前回复",
220
240
  send: "发送",
221
241
  attachTitle: "添加图片附件",
@@ -1055,6 +1075,114 @@ window.__ModuleLoader__.load({
1055
1075
  ...typeof m.lang === "string" ? { lang: m.lang } : {}
1056
1076
  };
1057
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
+ }
1058
1186
  /** argsRaw(JSON 字符串)里尽力提取展示字段。 */
1059
1187
  function argsSummary(argsRaw) {
1060
1188
  if (argsRaw === void 0 || argsRaw === "") return {};
@@ -1066,7 +1194,14 @@ window.__ModuleLoader__.load({
1066
1194
  ...typeof a.command === "string" ? { command: a.command } : {},
1067
1195
  ...typeof a.description === "string" ? { description: a.description } : {},
1068
1196
  ...typeof a.file_path === "string" ? { path: a.file_path } : typeof a.path === "string" ? { path: a.path } : {},
1069
- ...Array.isArray(a.todos) ? { todos: a.todos } : {}
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 } : {}
1070
1205
  };
1071
1206
  } catch {
1072
1207
  return {};
@@ -1111,6 +1246,75 @@ window.__ModuleLoader__.load({
1111
1246
  items
1112
1247
  };
1113
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
+ }
1114
1318
  return {
1115
1319
  kind: "generic",
1116
1320
  title: args.path !== void 0 ? `${name} · ${shortPath(args.path)}` : args.command ?? name,
@@ -1118,19 +1322,22 @@ window.__ModuleLoader__.load({
1118
1322
  bodyText: input.rawText === "" ? void 0 : input.rawText
1119
1323
  };
1120
1324
  }
1121
- /** 工具名 → 图标类别的静态映射(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)。 */
1122
1329
  const KIND_BY_NAME = {
1123
1330
  read: "read",
1124
1331
  write: "edit",
1125
1332
  edit: "edit",
1126
- "str-replace-editor": "edit",
1333
+ str_replace_editor: "edit",
1127
1334
  bash: "execute",
1128
1335
  "bash-persistent": "execute",
1129
1336
  pwsh: "execute",
1130
1337
  "pwsh-persistent": "execute",
1131
1338
  grep: "search",
1132
1339
  glob: "search",
1133
- web_search: "fetch",
1340
+ web_search: "search",
1134
1341
  web_fetch: "fetch"
1135
1342
  };
1136
1343
  //#endregion
@@ -1221,7 +1428,8 @@ window.__ModuleLoader__.load({
1221
1428
  name: toolName,
1222
1429
  argsRaw: typeof call?.argsRaw === "string" ? call.argsRaw : void 0,
1223
1430
  meta: n.meta,
1224
- rawText: text
1431
+ rawText: text,
1432
+ ...n.isError === true ? { isError: true } : {}
1225
1433
  });
1226
1434
  return {
1227
1435
  key: seqKey("t", n),
@@ -1476,7 +1684,7 @@ window.__ModuleLoader__.load({
1476
1684
  }
1477
1685
  //#endregion
1478
1686
  //#region \0dsh-css:/home/runner/work/dsh-sidenote/dsh-sidenote/src/client/sidechat/sidechat.module.css.mjs
1479
- 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_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}";
1480
1688
  const tagId$1 = "dsh-sidenote/sidechat.module.css";
1481
1689
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
1482
1690
  const tag = document.createElement("style");
@@ -1486,77 +1694,92 @@ window.__ModuleLoader__.load({
1486
1694
  document.head.appendChild(tag);
1487
1695
  }
1488
1696
  var sidechat_module_css_default = {
1489
- "noticeRow": "_5KEEsG_noticeRow",
1490
- "toolBody": "_5KEEsG_toolBody",
1491
- "densityRow": "_5KEEsG_densityRow",
1492
- "toolCard": "_5KEEsG_toolCard",
1493
- "sidechat-pulse": "_5KEEsG_sidechat-pulse",
1494
- "slashItemDetail": "_5KEEsG_slashItemDetail",
1495
- "composerFoot": "_5KEEsG_composerFoot",
1496
- "assistantRow": "_5KEEsG_assistantRow",
1697
+ "composerCard": "_5KEEsG_composerCard",
1698
+ "streamingHint": "_5KEEsG_streamingHint",
1699
+ "stopButton": "_5KEEsG_stopButton",
1700
+ "transcript": "_5KEEsG_transcript",
1701
+ "rowPreview": "_5KEEsG_rowPreview",
1497
1702
  "toolGenericBody": "_5KEEsG_toolGenericBody",
1498
- "attachImg": "_5KEEsG_attachImg",
1499
- "slashItemActive": "_5KEEsG_slashItemActive",
1500
- "emptyIcon": "_5KEEsG_emptyIcon",
1703
+ "densityRow": "_5KEEsG_densityRow",
1704
+ "pendingReason": "_5KEEsG_pendingReason",
1501
1705
  "toolError": "_5KEEsG_toolError",
1706
+ "pendingOptionDesc": "_5KEEsG_pendingOptionDesc",
1502
1707
  "empty": "_5KEEsG_empty",
1503
- "flowRow": "_5KEEsG_flowRow",
1504
- "flowRowError": "_5KEEsG_flowRowError",
1505
- "slashItem": "_5KEEsG_slashItem",
1506
- "streamingHint": "_5KEEsG_streamingHint",
1507
- "input": "_5KEEsG_input",
1508
- "sendButton": "_5KEEsG_sendButton",
1509
- "todoBody": "_5KEEsG_todoBody",
1510
- "parentStrip": "_5KEEsG_parentStrip",
1511
- "dotRunning": "_5KEEsG_dotRunning",
1708
+ "stateScreen": "_5KEEsG_stateScreen",
1709
+ "slashMenu": "_5KEEsG_slashMenu",
1710
+ "userBubble": "_5KEEsG_userBubble",
1512
1711
  "dotPending": "_5KEEsG_dotPending",
1513
- "userRow": "_5KEEsG_userRow",
1514
- "toolLocations": "_5KEEsG_toolLocations",
1712
+ "pendingOptionActive": "_5KEEsG_pendingOptionActive",
1713
+ "pendingDesc": "_5KEEsG_pendingDesc",
1714
+ "pendingActions": "_5KEEsG_pendingActions",
1715
+ "todoDot": "_5KEEsG_todoDot",
1515
1716
  "todoText": "_5KEEsG_todoText",
1516
- "actionGroup": "_5KEEsG_actionGroup",
1717
+ "emptyIcon": "_5KEEsG_emptyIcon",
1718
+ "reflowButton": "_5KEEsG_reflowButton",
1719
+ "pendingBtnPrimary": "_5KEEsG_pendingBtnPrimary",
1720
+ "reasoningBody": "_5KEEsG_reasoningBody",
1517
1721
  "inheritedBody": "_5KEEsG_inheritedBody",
1722
+ "attachRail": "_5KEEsG_attachRail",
1723
+ "pendingBtnGhost": "_5KEEsG_pendingBtnGhost",
1724
+ "dotIdle": "_5KEEsG_dotIdle",
1725
+ "slashItemName": "_5KEEsG_slashItemName",
1726
+ "sendButton": "_5KEEsG_sendButton",
1727
+ "slashItemActive": "_5KEEsG_slashItemActive",
1728
+ "stateDetail": "_5KEEsG_stateDetail",
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",
1740
+ "input": "_5KEEsG_input",
1741
+ "sentChipRow": "_5KEEsG_sentChipRow",
1518
1742
  "todoItem": "_5KEEsG_todoItem",
1743
+ "composer": "_5KEEsG_composer",
1744
+ "slashItem": "_5KEEsG_slashItem",
1745
+ "flowRow": "_5KEEsG_flowRow",
1746
+ "pendingHead": "_5KEEsG_pendingHead",
1747
+ "composerChips": "_5KEEsG_composerChips",
1519
1748
  "errorRow": "_5KEEsG_errorRow",
1520
- "attachRemove": "_5KEEsG_attachRemove",
1521
- "sentChipRow": "_5KEEsG_sentChipRow",
1522
- "composerCard": "_5KEEsG_composerCard",
1523
- "stateScreen": "_5KEEsG_stateScreen",
1524
- "headerSide": "_5KEEsG_headerSide",
1525
- "transcript": "_5KEEsG_transcript",
1749
+ "slashItemDetail": "_5KEEsG_slashItemDetail",
1750
+ "toolRunning": "_5KEEsG_toolRunning",
1751
+ "noticeRow": "_5KEEsG_noticeRow",
1752
+ "pendingTitle": "_5KEEsG_pendingTitle",
1753
+ "jumpBottom": "_5KEEsG_jumpBottom",
1754
+ "flowRowError": "_5KEEsG_flowRowError",
1755
+ "sidechat-pulse": "_5KEEsG_sidechat-pulse",
1756
+ "root": "_5KEEsG_root",
1526
1757
  "emptyText": "_5KEEsG_emptyText",
1527
- "toolHead": "_5KEEsG_toolHead",
1528
- "pendingBar": "_5KEEsG_pendingBar",
1758
+ "slashGroupTitle": "_5KEEsG_slashGroupTitle",
1759
+ "toolCard": "_5KEEsG_toolCard",
1529
1760
  "assistantBody": "_5KEEsG_assistantBody",
1761
+ "composerFoot": "_5KEEsG_composerFoot",
1530
1762
  "attachButton": "_5KEEsG_attachButton",
1531
- "dotIdle": "_5KEEsG_dotIdle",
1532
- "root": "_5KEEsG_root",
1533
- "toolRunning": "_5KEEsG_toolRunning",
1534
- "stateDetail": "_5KEEsG_stateDetail",
1535
- "slashMenu": "_5KEEsG_slashMenu",
1536
- "slashItemName": "_5KEEsG_slashItemName",
1537
- "writeNotice": "_5KEEsG_writeNotice",
1538
- "attachRail": "_5KEEsG_attachRail",
1539
- "reasoningBody": "_5KEEsG_reasoningBody",
1763
+ "userRow": "_5KEEsG_userRow",
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",
1771
+ "attachImg": "_5KEEsG_attachImg",
1772
+ "attachRemove": "_5KEEsG_attachRemove",
1773
+ "assistantRow": "_5KEEsG_assistantRow",
1774
+ "pendingQuestion": "_5KEEsG_pendingQuestion",
1775
+ "writeNoticeClose": "_5KEEsG_writeNoticeClose",
1776
+ "toolBody": "_5KEEsG_toolBody",
1540
1777
  "sentChip": "_5KEEsG_sentChip",
1541
- "densityToggle": "_5KEEsG_densityToggle",
1778
+ "pendingBar": "_5KEEsG_pendingBar",
1779
+ "rowActions": "_5KEEsG_rowActions",
1542
1780
  "modelSelect": "_5KEEsG_modelSelect",
1543
- "slashGroupTitle": "_5KEEsG_slashGroupTitle",
1544
- "emptyTitle": "_5KEEsG_emptyTitle",
1545
- "body": "_5KEEsG_body",
1546
- "userBubble": "_5KEEsG_userBubble",
1547
- "reflowButton": "_5KEEsG_reflowButton",
1548
- "toolBodyText": "_5KEEsG_toolBodyText",
1549
- "rowPreview": "_5KEEsG_rowPreview",
1550
1781
  "attachThumb": "_5KEEsG_attachThumb",
1551
- "stopButton": "_5KEEsG_stopButton",
1552
- "rowActions": "_5KEEsG_rowActions",
1553
- "jumpBottom": "_5KEEsG_jumpBottom",
1554
- "reasoning": "_5KEEsG_reasoning",
1555
- "modelLabel": "_5KEEsG_modelLabel",
1556
- "writeNoticeClose": "_5KEEsG_writeNoticeClose",
1557
- "todoDot": "_5KEEsG_todoDot",
1558
- "composerChips": "_5KEEsG_composerChips",
1559
- "composer": "_5KEEsG_composer"
1782
+ "pendingQText": "_5KEEsG_pendingQText"
1560
1783
  };
1561
1784
  //#endregion
1562
1785
  //#region src/client/chat/ToolCard.tsx
@@ -2762,6 +2985,342 @@ window.__ModuleLoader__.load({
2762
2985
  }, "dsh-sidenote: toast host");
2763
2986
  }
2764
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
2765
3324
  //#region src/client/sidechat/SideChatPanel.tsx
2766
3325
  /**
2767
3326
  * 侧边聊天 Tab 面板(L2 薄视图):相位编排 + 消息流 + composer。
@@ -2778,6 +3337,8 @@ window.__ModuleLoader__.load({
2778
3337
  * 否则消息流永远为空(client-runtime 只为 staged 会话开窗的已知偏差)。
2779
3338
  */
2780
3339
  const NOOP_UNSUBSCRIBE = () => {};
3340
+ /** uSES 空快照常量(禁产新引用——`?? []` 字面量每次新数组会无限重渲)。 */
3341
+ const NO_PENDING = [];
2781
3342
  /** D2 写型工具名(无 diff 卡时的名字兜底)。 */
2782
3343
  const WRITE_TOOLS = /* @__PURE__ */ new Set([
2783
3344
  "edit",
@@ -2838,6 +3399,12 @@ window.__ModuleLoader__.load({
2838
3399
  const fold = (0, react.useMemo)(() => createFoldStore(childId === void 0 ? void 0 : `dsh-sidenote:fold:v1:${childId}`), [childId]);
2839
3400
  const parentSession = meta.parentSessionId === void 0 ? void 0 : ctx.sessions.binding(meta.parentSessionId)?.session;
2840
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);
2841
3408
  const [writeNoticeDismissed, setWriteNoticeDismissed] = (0, react.useState)(() => typeof localStorage !== "undefined" && localStorage.getItem(WRITE_NOTICE_KEY) === "1");
2842
3409
  const composer = useComposer(ctx, session, childId);
2843
3410
  const [modelName, setModelName] = (0, react.useState)(null);
@@ -3011,7 +3578,8 @@ window.__ModuleLoader__.load({
3011
3578
  children: "×"
3012
3579
  })]
3013
3580
  }),
3014
- pendingCount > 0 && childId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
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", {
3015
3583
  type: "button",
3016
3584
  className: sidechat_module_css_default.pendingBar,
3017
3585
  onClick: () => {
@@ -3250,6 +3818,66 @@ window.__ModuleLoader__.load({
3250
3818
  }
3251
3819
  }
3252
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
3253
3881
  //#region src/client/sidechat/index.tsx
3254
3882
  /**
3255
3883
  * Workitem 01 — 侧边聊天面板。
@@ -3308,6 +3936,7 @@ window.__ModuleLoader__.load({
3308
3936
  registerSideChatReferenceSource(ctx);
3309
3937
  registerHeaderEntry(ctx);
3310
3938
  registerToastHost(ctx);
3939
+ registerCompletionNotify(ctx);
3311
3940
  }
3312
3941
  //#endregion
3313
3942
  //#region src/client/annotate/model.ts
@@ -3760,43 +4389,43 @@ window.__ModuleLoader__.load({
3760
4389
  document.head.appendChild(tag);
3761
4390
  }
3762
4391
  var annotate_module_css_default = {
3763
- "cancelButton": "_SVViG_cancelButton",
3764
- "editorNew": "_SVViG_editorNew",
3765
- "editorFooter": "_SVViG_editorFooter",
3766
- "confirmButton": "_SVViG_confirmButton",
3767
- "chipClearAll": "_SVViG_chipClearAll",
3768
- "editorTarget": "_SVViG_editorTarget",
3769
- "chipNumber": "_SVViG_chipNumber",
3770
- "chipText": "_SVViG_chipText",
3771
- "editorAskRow": "_SVViG_editorAskRow",
3772
- "chipWrap": "_SVViG_chipWrap",
3773
- "chip": "_SVViG_chip",
3774
- "highlight": "_SVViG_highlight",
3775
4392
  "toolbarButton": "_SVViG_toolbarButton",
3776
- "chipNote": "_SVViG_chipNote",
3777
- "chipPanel": "_SVViG_chipPanel",
3778
- "editorInput": "_SVViG_editorInput",
3779
- "hint": "_SVViG_hint",
3780
- "toolbar": "_SVViG_toolbar",
3781
- "saveButton": "_SVViG_saveButton",
4393
+ "editorSpacer": "_SVViG_editorSpacer",
3782
4394
  "sentCardTitle": "_SVViG_sentCardTitle",
3783
- "sentCardNote": "_SVViG_sentCardNote",
3784
- "deleteButton": "_SVViG_deleteButton",
3785
4395
  "chipRemove": "_SVViG_chipRemove",
3786
- "editorAsk": "_SVViG_editorAsk",
3787
- "hintClose": "_SVViG_hintClose",
3788
4396
  "toolbarBelow": "_SVViG_toolbarBelow",
3789
- "sentChipRow": "_SVViG_sentChipRow",
3790
- "sentChip": "_SVViG_sentChip",
3791
4397
  "editorTextarea": "_SVViG_editorTextarea",
4398
+ "chipWrap": "_SVViG_chipWrap",
4399
+ "chipClearAll": "_SVViG_chipClearAll",
4400
+ "editorNew": "_SVViG_editorNew",
4401
+ "badge": "_SVViG_badge",
4402
+ "editorAskRow": "_SVViG_editorAskRow",
4403
+ "chipText": "_SVViG_chipText",
3792
4404
  "badgeSent": "_SVViG_badgeSent",
4405
+ "editorError": "_SVViG_editorError",
4406
+ "cancelButton": "_SVViG_cancelButton",
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",
4414
+ "chipNumber": "_SVViG_chipNumber",
4415
+ "saveButton": "_SVViG_saveButton",
4416
+ "chip": "_SVViG_chip",
4417
+ "chipRow": "_SVViG_chipRow",
4418
+ "sentChip": "_SVViG_sentChip",
3793
4419
  "sentCardQuote": "_SVViG_sentCardQuote",
4420
+ "hint": "_SVViG_hint",
4421
+ "editorInput": "_SVViG_editorInput",
4422
+ "toolbar": "_SVViG_toolbar",
4423
+ "confirmButton": "_SVViG_confirmButton",
3794
4424
  "editorEdit": "_SVViG_editorEdit",
3795
- "chipRow": "_SVViG_chipRow",
3796
- "dshSidenoteHintIn": "_SVViG_dshSidenoteHintIn",
3797
- "editorSpacer": "_SVViG_editorSpacer",
3798
- "editorError": "_SVViG_editorError",
3799
- "badge": "_SVViG_badge"
4425
+ "editorAsk": "_SVViG_editorAsk",
4426
+ "editorTarget": "_SVViG_editorTarget",
4427
+ "sentCardNote": "_SVViG_sentCardNote",
4428
+ "editorFooter": "_SVViG_editorFooter"
3800
4429
  };
3801
4430
  //#endregion
3802
4431
  //#region src/client/annotate/hint.tsx