dsh-auto-collapse 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js ADDED
@@ -0,0 +1,1440 @@
1
+ window.__ModuleLoader__.load({id:"dsh-auto-collapse",factory:function(require){
2
+ "use strict";
3
+ var __dshcfBundle = (() => {
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name2 in all)
10
+ __defProp(target, name2, { get: all[name2], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/client.ts
23
+ var client_exports = {};
24
+ __export(client_exports, {
25
+ apply: () => apply,
26
+ inject: () => inject,
27
+ name: () => name
28
+ });
29
+
30
+ // src/fold.ts
31
+ var STYLE_ID = "dshcf-style";
32
+ var TOOL_LABELS = {
33
+ bash: "Bash",
34
+ pwsh: "Pwsh",
35
+ read: "Read",
36
+ web_fetch: "Read",
37
+ web_search: "Search",
38
+ grep: "Search",
39
+ glob: "Search",
40
+ write: "Write",
41
+ edit: "Edit",
42
+ run_code: "Code",
43
+ cordis_package_inspect: "Inspect",
44
+ cordis_runtime_inspect: "Inspect",
45
+ cordis_run: "Run",
46
+ cordis_stop: "Stop",
47
+ cordis_undefine: "Remove"
48
+ };
49
+ var CHIP_CSS = `
50
+ .dshcf-chip {
51
+ box-sizing: border-box;
52
+ display: flex;
53
+ align-self: flex-start;
54
+ align-items: center;
55
+ gap: 6px;
56
+ width: fit-content;
57
+ max-width: 100%;
58
+ min-height: 24px;
59
+ /* chip \u63D2\u5728\u5757\u5BBF\u4E3B\uFF08flowItem\uFF09\u5185\uFF0C\u4EAB\u53D7\u4E0D\u5230\u884C\u7684 row-gap 16px\uFF1B
60
+ \u5C55\u5F00\u6001\u8865 margin-bottom \u5BF9\u9F50\u884C\u95F4\u8282\u594F\uFF1B\u6536\u8D77\u6001\u884C\u5DF2\u9690\u85CF\uFF0C\u82E5\u4ECD\u8865
61
+ margin \u4F1A\u4E0E\u5757\u95F4 gap \u53E0\u52A0\u6210 32px\uFF0C\u6240\u4EE5\u6536\u8D77\u6001\u4E3A 0\u3002 */
62
+ margin-bottom: 0;
63
+ padding: 0;
64
+ border: none;
65
+ background: transparent;
66
+ color: var(--dsw-alias-label-primary);
67
+ font: 400 14px/24px system-ui, -apple-system, "Segoe UI", sans-serif;
68
+ text-align: left;
69
+ cursor: pointer;
70
+ user-select: none;
71
+ }
72
+ .dshcf-chip[aria-expanded="true"],
73
+ .dshcf-chip.dshcf-has-body {
74
+ margin-bottom: 16px;
75
+ }
76
+ /* context \u7B49 before-mounted chip \u662F flow \u7684\u76F4\u63A5\u5B50\u9879\uFF0C\u5DF2\u7ECF\u4EAB\u53D7\u5BBF\u4E3B
77
+ row-gap: 16px\uFF1B\u5C55\u5F00\u65F6\u4E0D\u80FD\u518D\u53E0\u52A0\u81EA\u8EAB margin\uFF0C\u5426\u5219\u4E8C\u7EA7\u5230\u4E09\u7EA7\u4F1A\u53D8 32px\u3002 */
78
+ .dshcf-chip.dshcf-flow-chip {
79
+ margin-bottom: 0;
80
+ }
81
+ .dshcf-chip:hover {
82
+ background: transparent;
83
+ }
84
+
85
+ /* leading\uFF1A\u56FA\u5B9A 14x14\uFF08\u601D\u8003\u5757 = \u539F\u751F think \u56FE\u6807\uFF1B\u5DE5\u5177\u5757 = \u539F\u751F command
86
+ \u56FE\u6807 IconApiOutline14\uFF0C\u514B\u9686\u81EA\u771F\u5B9E GenericCommandCard leading\uFF0C\u627E\u4E0D\u5230\u65F6
87
+ \u9000\u56DE\u7EC8\u7AEF\u5C0F\u65B9\u5757\uFF09\uFF0C\u884C\u9AD8 24px \u4E0E\u539F\u751F\u884C\u5BF9\u9F50\uFF1B\u8FD0\u884C\u4E2D\u8DF3\u52A8\u3002svg \u5C3A\u5BF8\u7531\u5404\u81EA
88
+ width/height \u5C5E\u6027\u51B3\u5B9A\uFF08command 14x14\u3001think 14x14\u3001\u7EC8\u7AEF 12x10 \u515C\u5E95\uFF09\uFF0C
89
+ \u4E0D\u5728\u6B64\u5904\u5F3A\u5236\u3002 */
90
+ .dshcf-chip .dshcf-leading {
91
+ flex: none;
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ width: 16px;
96
+ height: 16px;
97
+ }
98
+ .dshcf-chip .dshcf-leading svg {
99
+ display: block;
100
+ color: var(--dsw-alias-label-tertiary);
101
+ }
102
+ .dshcf-chip.running .dshcf-leading svg {
103
+ /* \u8FD0\u884C\u8272\u4FDD\u7559\uFF1B\u56FE\u6807\u8DF3\u52A8\u52A8\u753B\u5DF2\u6309\u7528\u6237\u8981\u6C42\u79FB\u9664\u3002 */
104
+ color: var(--dsw-static-deepseek-500, #4d6bfe);
105
+ }
106
+
107
+ /* \u8FD0\u884C\u6307\u793A\u4E09\u4E2A\u70B9\uFF1A\u5DF2\u6309\u7528\u6237\u8981\u6C42\u79FB\u9664\uFF08\u4E0D\u518D\u521B\u5EFA/\u663E\u793A\uFF09\u3002 */
108
+
109
+ /* \u51FA\u9519\u7EA2 / \u4E2D\u65AD\u7425\u73C0\uFF08\u9759\u6B62\u6001\uFF09\u3002 */
110
+ .dshcf-chip.error:not(.running) .dshcf-leading svg {
111
+ color: var(--dsw-alias-state-error-primary, #e5484d);
112
+ }
113
+ .dshcf-chip.stopped:not(.running) .dshcf-leading svg {
114
+ color: var(--dsw-alias-state-warning-primary, #f5a524);
115
+ }
116
+
117
+ .dshcf-chip .dshcf-chip-title {
118
+ flex: none;
119
+ font-weight: 400;
120
+ max-width: 70%;
121
+ overflow: hidden;
122
+ text-overflow: ellipsis;
123
+ white-space: nowrap;
124
+ }
125
+ .dshcf-chip .dshcf-chip-sep {
126
+ flex: none;
127
+ width: 2px;
128
+ height: 2px;
129
+ border-radius: 1px;
130
+ background: var(--dsw-alias-label-caption, rgba(127, 127, 127, 0.5));
131
+ }
132
+ /* \u6458\u8981\u4E0D\u6491\u6EE1\uFF08flex 0 1\uFF09\uFF0C\u8BA9 chevron \u7D27\u8DDF\u5728\u6587\u672C\u53F3\u65B9\u800C\u975E\u884C\u5C3E\u3002 */
133
+ .dshcf-chip .dshcf-chip-summary {
134
+ flex: 0 1 auto;
135
+ min-width: 0;
136
+ max-width: 100%;
137
+ overflow: hidden;
138
+ text-overflow: ellipsis;
139
+ white-space: nowrap;
140
+ }
141
+ /* running \u6458\u8981\uFF1A\u8DDF\u968F\u6EDA\u52A8\u663E\u793A\u6700\u65B0\u5185\u5BB9\uFF08text-overflow: clip\uFF0C\u539F\u751F\u540C\u6B3E\uFF09\u3002 */
142
+ .dshcf-chip.running .dshcf-chip-summary {
143
+ text-overflow: clip;
144
+ }
145
+ /* \u6298\u53E0\u884C\u6587\u5B57\uFF1A\u590D\u7528 DSH \u539F\u751F label token\uFF08\u5DE5\u5177\u884C\u540C\u6E90\uFF09\uFF0C\u533A\u522B\u4E8E\u6B63\u6587\u7EAF\u767D\u3002 */
146
+ .dshcf-chip .dshcf-chip-title {
147
+ color: var(--dsw-alias-label-primary);
148
+ }
149
+ .dshcf-chip .dshcf-chip-summary {
150
+ color: var(--dsw-alias-label-tertiary);
151
+ }
152
+ /* \u5DE5\u5177\u884C\u6458\u8981\uFF08\u547D\u4EE4/\u8DEF\u5F84\uFF09\u7B49\u5BBD\u5B57\u4F53 + \u4EE3\u7801\u886C\u5E95\uFF08\u7D20\u6750 Codex \u540C\u6B3E\uFF09\u3002
153
+ \u884C\u9AD8\u4E0E chip \u4E00\u81F4\uFF0824px\uFF09\uFF0C\u6D41\u5F0F\u66F4\u65B0\u65F6\u6458\u8981\u5355\u884C ellipsis \u4E0D\u6362\u884C\u4E0D\u6491\u9AD8\u3002 */
154
+ .dshcf-chip[data-kind="tool"] .dshcf-chip-summary {
155
+ font-family: ui-monospace, SFMono-Regular, Consolas, "Courier New", monospace;
156
+ font-size: 12px;
157
+ line-height: 24px;
158
+ background: rgba(127, 127, 127, 0.14);
159
+ border-radius: 4px;
160
+ padding: 0 6px;
161
+ }
162
+ .dshcf-chip[data-kind="tool"] .dshcf-chip-summary:empty {
163
+ background: none;
164
+ padding: 0;
165
+ }
166
+
167
+ /* \u8FD0\u884C\u4E2D\u6587\u5B57\u4F7F\u7528\u5E73\u6ED1\u547C\u5438\u52A8\u753B\uFF08Pulse\uFF09\uFF0C\u9002\u914D\u6D45\u8272/\u6DF1\u8272\u4E3B\u9898\uFF0C\u907F\u514D background-clip \u88C1\u5207\u95EE\u9898\u3002 */
168
+ .dshcf-chip.running .dshcf-chip-title,
169
+ .dshcf-chip.running .dshcf-chip-summary {
170
+ color: var(--dsw-alias-label-tertiary, #8b8f99);
171
+ -webkit-text-fill-color: currentColor;
172
+ animation: dshcf-pulse 1.6s ease-in-out infinite;
173
+ }
174
+ .dshcf-chip.running[data-kind="tool"] .dshcf-chip-summary {
175
+ background: transparent;
176
+ }
177
+ @keyframes dshcf-pulse {
178
+ 0%, 100% { opacity: 1; }
179
+ 50% { opacity: 0.5; }
180
+ }
181
+
182
+ /* "\u5DF2\u5904\u7406"\u884C\uFF1A\u6700\u7EC8\u8F93\u51FA\u51FA\u73B0\u540E\u5DE5\u4F5C\u8FC7\u7A0B\u6574\u4F53\u9690\u85CF\uFF0C\u53EA\u7559\u8FD9\u4E00\u884C + \u65F6\u957F\u3002
183
+ \u5B57\u4F53\u4E0E\u4E8C\u7EA7 chip \u5BF9\u9F50\uFF0814px/24px\uFF09\uFF0C\u5DE6\u53F3\u65E0\u5185\u8FB9\u8DDD\uFF08\u4E0E\u6B63\u6587\u5DE6\u7F18\u5BF9\u9F50\uFF09\u3002 */
184
+ .dshcf-processed {
185
+ display: inline-flex;
186
+ align-self: flex-start;
187
+ width: fit-content;
188
+ max-width: 100%;
189
+ align-items: center;
190
+ gap: 6px;
191
+ padding: 2px 0;
192
+ border: none;
193
+ background: none;
194
+ font: 400 14px/24px system-ui, -apple-system, "Segoe UI", sans-serif;
195
+ /* \u5BF9\u9F50 DSH \u539F\u751F\u5DE5\u5177\u884C\u6458\u8981\u7684\u6B21\u7EA7\u5C42\u7EA7\uFF08label-tertiary\uFF09\u3002 */
196
+ color: var(--dsw-alias-label-tertiary);
197
+ cursor: pointer;
198
+ user-select: none;
199
+ border-radius: 4px;
200
+ transition: color 0.15s ease;
201
+ }
202
+ .dshcf-processed:hover {
203
+ color: var(--dsw-alias-label-primary);
204
+ background: transparent;
205
+ }
206
+ .dshcf-processed:focus-visible {
207
+ outline: 2px solid var(--dsw-alias-state-focus-ring, rgba(77, 107, 254, 0.8));
208
+ outline-offset: 2px;
209
+ }
210
+ /* \u6298\u53E0\u7BAD\u5934\uFF1A\u4F7F\u7528 DSH \u539F\u751F IconChevronDownOutline14 \u7684 14x14 path\u3002 */
211
+ .dshcf-processed .dshcf-processed-chevron {
212
+ display: inline-flex;
213
+ flex: none;
214
+ width: 14px;
215
+ height: 14px;
216
+ color: var(--dsw-alias-label-tertiary);
217
+ opacity: 0.55;
218
+ transform: rotate(-90deg);
219
+ transition: transform 0.12s ease, opacity 0.1s ease;
220
+ }
221
+ .dshcf-processed:hover .dshcf-processed-chevron {
222
+ opacity: 0.9;
223
+ }
224
+ .dshcf-processed[aria-expanded="true"] .dshcf-processed-chevron {
225
+ transform: rotate(0deg);
226
+ }
227
+
228
+ /* \u4E09\u7EA7\u5408\u5E76\u601D\u8003\u884C\uFF1A\u5C55\u5F00\u4E8C\u7EA7\u540E\u8FDE\u7EED\u601D\u8003\u5408\u5E76\u4E3A\u4E00\u884C\uFF08\u6807\u9898 = \u7B2C\u4E00\u884C\u601D\u8003\u5185\u5BB9\uFF09\u3002
229
+ \u6837\u5F0F\u4E0E chip \u540C\u65CF\uFF0816px \u56FE\u6807\u76D2\u300114px/24px\u3001\u539F\u751F label token \u8272\uFF09\u3002 */
230
+ .dshcf-merged-think {
231
+ box-sizing: border-box;
232
+ display: flex;
233
+ align-self: flex-start;
234
+ align-items: center;
235
+ gap: 6px;
236
+ width: fit-content;
237
+ max-width: 100%;
238
+ min-height: 24px;
239
+ margin: 0;
240
+ padding: 0;
241
+ border: none;
242
+ background: transparent;
243
+ color: var(--dsw-alias-label-primary);
244
+ font: 400 14px/24px system-ui, -apple-system, "Segoe UI", sans-serif;
245
+ text-align: left;
246
+ cursor: pointer;
247
+ user-select: none;
248
+ }
249
+ .dshcf-merged-think .dshcf-leading {
250
+ flex: none;
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: center;
254
+ width: 16px;
255
+ height: 16px;
256
+ }
257
+ .dshcf-merged-think .dshcf-leading svg {
258
+ display: block;
259
+ color: var(--dsw-alias-label-tertiary);
260
+ }
261
+ .dshcf-merged-think .dshcf-merged-title {
262
+ flex: 0 1 auto;
263
+ min-width: 0;
264
+ max-width: 85%;
265
+ overflow: hidden;
266
+ text-overflow: ellipsis;
267
+ white-space: nowrap;
268
+ color: var(--dsw-alias-label-secondary);
269
+ font-weight: 400;
270
+ }
271
+ .dshcf-merged-think .dshcf-chevron {
272
+ flex: none;
273
+ width: 14px;
274
+ height: 14px;
275
+ color: var(--dsw-alias-label-secondary);
276
+ opacity: 0.55;
277
+ transform: rotate(-90deg);
278
+ transition: transform 0.12s ease, opacity 0.1s ease;
279
+ }
280
+ .dshcf-merged-think:hover .dshcf-chevron,
281
+ .dshcf-merged-think:focus-visible .dshcf-chevron {
282
+ opacity: 0.9;
283
+ }
284
+ .dshcf-merged-think[aria-expanded="true"] .dshcf-chevron {
285
+ transform: rotate(0deg);
286
+ }
287
+ /* \u5408\u5E76\u601D\u8003\u5185\u5BB9\u5757\uFF1A\u56DB\u4E2A\u601D\u8003\u5408\u5E76\u4E3A\u4E00\u4E2A\u6574\u4F53\uFF08\u5BF9\u9F50\u56FE\u6807\u53F3\u4FA7\u7F29\u8FDB\uFF09\u3002 */
288
+ .dshcf-merged-body {
289
+ margin: 0 0 16px;
290
+ padding-left: 22px;
291
+ color: var(--dsw-alias-label-secondary);
292
+ font: 400 13px/22px system-ui, -apple-system, "Segoe UI", sans-serif;
293
+ white-space: pre-wrap;
294
+ word-break: break-word;
295
+ }
296
+
297
+ /* chevron\uFF1A\u9ED8\u8BA4\u9690\u85CF\uFF0Chover/focus \u6D6E\u73B0\uFF0C\u5C55\u5F00\u65F6\u65CB\u8F6C 90\xB0\uFF08Codex \u540C\u6B3E\uFF09\u3002 */
298
+ .dshcf-chip .dshcf-chevron {
299
+ flex: none;
300
+ width: 14px;
301
+ height: 14px;
302
+ color: var(--dsw-alias-label-tertiary);
303
+ opacity: 0.5;
304
+ transform: rotate(-90deg);
305
+ transition: opacity 0.1s ease, transform 0.12s ease;
306
+ }
307
+ .dshcf-chip:hover .dshcf-chevron,
308
+ .dshcf-chip:focus-visible .dshcf-chevron,
309
+ .dshcf-chip[aria-expanded="true"] .dshcf-chevron {
310
+ opacity: 0.9;
311
+ }
312
+ .dshcf-chip[aria-expanded="true"] .dshcf-chevron {
313
+ transform: rotate(0deg);
314
+ }
315
+ .dshcf-chip:focus-visible {
316
+ outline: 2px solid var(--dsw-alias-state-focus-ring, rgba(77, 107, 254, 0.8));
317
+ outline-offset: 2px;
318
+ border-radius: 4px;
319
+ }
320
+
321
+ @media (prefers-reduced-motion: reduce) {
322
+ .dshcf-chip.running .dshcf-leading svg { animation: none; }
323
+ .dshcf-chip.running .dshcf-chip-title,
324
+ .dshcf-chip.running .dshcf-chip-summary {
325
+ animation: none;
326
+ opacity: 1;
327
+ }
328
+ }
329
+ `;
330
+ var FoldController = class {
331
+ constructor() {
332
+ this.observer = null;
333
+ this.raf = 0;
334
+ this.timer = 0;
335
+ this.disposed = false;
336
+ this.lastPassError = "";
337
+ this.flow = null;
338
+ /** 稳定 block key → 当前 React 渲染中的 chip/host。 */
339
+ this.chips = /* @__PURE__ */ new Map();
340
+ this.currentBlocks = /* @__PURE__ */ new Map();
341
+ this.blockExpanded = /* @__PURE__ */ new Map();
342
+ /** host → 三级合并思考行(展开二级后连续思考合并显示为一个三级行)。 */
343
+ this.mergedThinks = /* @__PURE__ */ new Map();
344
+ /** 合并思考行的展开状态(true = 显示合并内容块)。 */
345
+ this.mergedExpanded = /* @__PURE__ */ new WeakSet();
346
+ /** 合并内容缓存(首次从原生行读取后保存,pass 重建内容块时不再重新展开原生行)。 */
347
+ this.mergedBodyTexts = /* @__PURE__ */ new WeakMap();
348
+ /** 合并行标题缓存(原生行展开态提取不到摘要时保持首次标题,不丢成“思考”)。 */
349
+ this.mergedTitles = /* @__PURE__ */ new WeakMap();
350
+ /** 稳定 segment key → 一级折叠行与展开状态。 */
351
+ this.segmentStates = /* @__PURE__ */ new Map();
352
+ /** segment 首次观察到 running 的时间,用于没有官方时长的实时回合。 */
353
+ this.runningSince = /* @__PURE__ */ new Map();
354
+ /** 插件改写 display 前的精确原值;受控集合用于分类漂移和 stop() 恢复。 */
355
+ this.originalDisplay = /* @__PURE__ */ new WeakMap();
356
+ this.controlledDisplay = /* @__PURE__ */ new Set();
357
+ /** 被改写为 Deep sleeping 的原生状态文本,卸载时按节点恢复。 */
358
+ this.turnStatusTexts = /* @__PURE__ */ new Map();
359
+ }
360
+ start() {
361
+ if (this.disposed) return;
362
+ injectStyle();
363
+ try {
364
+ this.observer = new MutationObserver((records) => {
365
+ if (this.shouldSchedule(records)) this.schedule();
366
+ });
367
+ this.observer.observe(document.body, {
368
+ childList: true,
369
+ subtree: true,
370
+ attributes: true,
371
+ attributeFilter: ["data-selected", "data-state"],
372
+ // 流式文本更新(React 改 text node 的 data)属于 characterData
373
+ // mutation:不观察则二级摘要/滚动跟随只能靠偶发结构变化驱动,
374
+ // 变成“隔几秒跳一次”。所有文本写入都有守卫(值不变不写),
375
+ // 不会自激。
376
+ characterData: true
377
+ });
378
+ this.schedule();
379
+ } catch (error) {
380
+ this.reportError(error);
381
+ throw error;
382
+ }
383
+ }
384
+ stop() {
385
+ this.disposed = true;
386
+ if (this.raf !== 0) cancelAnimationFrame(this.raf);
387
+ if (this.timer !== 0) clearTimeout(this.timer);
388
+ this.observer?.disconnect();
389
+ this.switchFlow(null);
390
+ removeStyle();
391
+ }
392
+ /** body 级 observer 只负责发现 flow 替换;已有 flow 外的文本变化不再触发全量扫描。 */
393
+ shouldSchedule(records) {
394
+ if (records.length === 0 || this.flow === null || !this.flow.isConnected) return true;
395
+ return records.some((record) => nodeWithin(record.target, this.flow) || nodeWithin(this.flow, record.target));
396
+ }
397
+ schedule() {
398
+ if (this.disposed || this.raf !== 0) return;
399
+ this.raf = requestAnimationFrame(() => {
400
+ this.raf = 0;
401
+ if (this.timer !== 0) {
402
+ clearTimeout(this.timer);
403
+ this.timer = 0;
404
+ }
405
+ this.runPass();
406
+ });
407
+ if (this.timer !== 0) clearTimeout(this.timer);
408
+ this.timer = setTimeout(() => {
409
+ this.timer = 0;
410
+ if (this.raf !== 0) {
411
+ cancelAnimationFrame(this.raf);
412
+ this.raf = 0;
413
+ this.runPass();
414
+ }
415
+ }, 60);
416
+ }
417
+ /** 异步 observer 异常不能静默杀死协调器;保留非可视诊断并允许后续 mutation 重试。 */
418
+ runPass() {
419
+ try {
420
+ this.pass();
421
+ this.lastPassError = "";
422
+ const style = document.getElementById(STYLE_ID);
423
+ style?.setAttribute("data-dshcf-state", "active");
424
+ style?.removeAttribute("data-dshcf-error");
425
+ } catch (error) {
426
+ this.reportError(error);
427
+ }
428
+ }
429
+ reportError(error) {
430
+ const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
431
+ const style = document.getElementById(STYLE_ID);
432
+ style?.setAttribute("data-dshcf-state", "error");
433
+ style?.setAttribute("data-dshcf-error", message.slice(0, 500));
434
+ if (message === this.lastPassError) return;
435
+ this.lastPassError = message;
436
+ console.error("[dsh-auto-collapse] fold pass failed", error);
437
+ }
438
+ /** 一轮重放:重算堆积 → 应用折叠/展开 → 摆放并更新 chip → 替换状态行。 */
439
+ pass() {
440
+ if (this.disposed) return;
441
+ const nextFlow = findFlow();
442
+ if (nextFlow !== this.flow) this.switchFlow(nextFlow);
443
+ const flow = this.flow;
444
+ if (flow === null) return;
445
+ const blocks = findBlocks(flow);
446
+ this.currentBlocks = new Map(blocks.map((block) => [block.key, block]));
447
+ const segments = buildSegments(flow, blocks);
448
+ const liveSegmentKeys = new Set(segments.map((segment) => segment.key));
449
+ for (const segment of segments) {
450
+ if (segment.running && !this.runningSince.has(segment.key)) {
451
+ this.runningSince.set(segment.key, Date.now());
452
+ }
453
+ }
454
+ const completedKeys = /* @__PURE__ */ new Set();
455
+ for (const snapshot of segments) {
456
+ if (!snapshot.closed || snapshot.running || !snapshot.hasWork) continue;
457
+ completedKeys.add(snapshot.key);
458
+ let state = this.segmentStates.get(snapshot.key);
459
+ if (state === void 0) {
460
+ state = { key: snapshot.key, row: null, expanded: false, snapshot };
461
+ this.segmentStates.set(snapshot.key, state);
462
+ } else {
463
+ state.snapshot = snapshot;
464
+ }
465
+ const started = this.runningSince.get(snapshot.key);
466
+ const parsed = snapshot.boundary === null ? void 0 : parseTurnDuration(snapshot.boundary);
467
+ if (parsed !== void 0) state.duration = parsed;
468
+ else if (started !== void 0) state.duration = Date.now() - started;
469
+ if (state.row === null || !state.row.isConnected) state.row = this.createProcessedRow(state);
470
+ this.syncProcessedRow(state);
471
+ }
472
+ for (const [key, state] of [...this.segmentStates]) {
473
+ if (completedKeys.has(key)) continue;
474
+ state.row?.remove();
475
+ this.segmentStates.delete(key);
476
+ }
477
+ const segmentByBlock = /* @__PURE__ */ new Map();
478
+ for (const segment of segments) {
479
+ for (const block of segment.blocks) segmentByBlock.set(block.key, segment);
480
+ }
481
+ const desiredHidden = /* @__PURE__ */ new Set();
482
+ const seenBlocks = /* @__PURE__ */ new Set();
483
+ for (const block of blocks) {
484
+ seenBlocks.add(block.key);
485
+ this.reconcileBlock(block, segmentByBlock.get(block.key) ?? null, desiredHidden);
486
+ }
487
+ for (const segment of segments) {
488
+ const state = this.segmentStates.get(segment.key);
489
+ const collapse = state !== void 0 && !state.expanded;
490
+ for (const middle of segment.middleSteps) {
491
+ if (collapse) this.hideElement(middle, desiredHidden);
492
+ else this.restoreElement(middle);
493
+ }
494
+ if (segment.finalStep !== null) this.restoreElement(segment.finalStep);
495
+ }
496
+ for (const segment of segments) {
497
+ if (segment.hasWork && hasVisibleSegmentWork(segment)) continue;
498
+ const state = this.segmentStates.get(segment.key);
499
+ if (state !== void 0 && state.row !== null) {
500
+ state.row.remove();
501
+ state.row = null;
502
+ }
503
+ for (const block of segment.blocks) this.suppressBlock(block, desiredHidden);
504
+ for (const middle of segment.middleSteps) this.retainDisplayControl(middle, desiredHidden);
505
+ if (segment.finalStep !== null) this.retainDisplayControl(segment.finalStep, desiredHidden);
506
+ }
507
+ this.cleanupStaleChips(seenBlocks);
508
+ this.restoreUnusedDisplays(desiredHidden);
509
+ for (const state of this.segmentStates.values()) this.placeProcessedRow(flow, state);
510
+ for (const key of [...this.runningSince.keys()]) {
511
+ if (!liveSegmentKeys.has(key)) this.runningSince.delete(key);
512
+ }
513
+ for (const [node] of [...this.turnStatusTexts]) {
514
+ if (!node.isConnected) this.turnStatusTexts.delete(node);
515
+ }
516
+ replaceTurnStatus(flow, this.turnStatusTexts);
517
+ }
518
+ /** flow 元素变化即视为会话切换:完整恢复旧 flow,再从新 DOM 重建。 */
519
+ switchFlow(next) {
520
+ if (next === this.flow) return;
521
+ for (const record of this.chips.values()) record.chip.remove();
522
+ this.chips.clear();
523
+ for (const host of [...this.mergedThinks.keys()]) this.removeMergedThink(host);
524
+ for (const state of this.segmentStates.values()) state.row?.remove();
525
+ this.segmentStates.clear();
526
+ this.currentBlocks.clear();
527
+ this.blockExpanded.clear();
528
+ this.runningSince.clear();
529
+ this.restoreAllDisplays();
530
+ restoreTurnStatus(this.turnStatusTexts);
531
+ this.flow = next;
532
+ }
533
+ createProcessedRow(state) {
534
+ const row = createProcessedRowElement(state.duration);
535
+ row.addEventListener("click", () => {
536
+ state.expanded = !state.expanded;
537
+ if (state.expanded) {
538
+ for (const block of state.snapshot.blocks) {
539
+ this.blockExpanded.set(block.key, false);
540
+ this.removeMergedThink(block.host);
541
+ }
542
+ }
543
+ this.syncProcessedRow(state);
544
+ this.schedule();
545
+ });
546
+ return row;
547
+ }
548
+ syncProcessedRow(state) {
549
+ const row = state.row;
550
+ if (row === null) return;
551
+ const text = row.firstElementChild;
552
+ const label = state.duration === void 0 ? "\u5DF2\u5904\u7406" : `\u5DF2\u5904\u7406 ${formatDuration(state.duration)}`;
553
+ if (text !== null && text.textContent !== label) text.textContent = label;
554
+ const expanded = String(state.expanded);
555
+ if (row.getAttribute("aria-expanded") !== expanded) row.setAttribute("aria-expanded", expanded);
556
+ row.title = state.expanded ? "\u6536\u8D77\u5DE5\u4F5C\u8FC7\u7A0B" : "\u5C55\u5F00\u5DE5\u4F5C\u8FC7\u7A0B";
557
+ }
558
+ placeProcessedRow(flow, state) {
559
+ const row = state.row;
560
+ if (row === null) return;
561
+ if (!state.snapshot.hasWork || !hasVisibleSegmentWork(state.snapshot)) {
562
+ row.remove();
563
+ state.row = null;
564
+ return;
565
+ }
566
+ let target = state.snapshot.firstWork ?? state.snapshot.finalStep ?? state.snapshot.boundary;
567
+ if (target === null || target.parentElement !== flow) return;
568
+ while (target.previousElementSibling?.classList.contains("dshcf-flow-chip") === true) {
569
+ target = target.previousElementSibling;
570
+ }
571
+ if (row.parentElement !== flow || row.nextElementSibling !== target) target.before(row);
572
+ }
573
+ reconcileBlock(block, segment, desiredHidden) {
574
+ const state = segment === null ? void 0 : this.segmentStates.get(segment.key);
575
+ const levelCollapsed = state !== void 0 && !state.expanded;
576
+ if (levelCollapsed) {
577
+ const existing = this.chips.get(block.key)?.chip;
578
+ if (existing !== void 0 && existing.style.display !== "none") existing.style.display = "none";
579
+ for (const row of block.rows) this.hideElement(row, desiredHidden);
580
+ for (const container of block.containers) this.hideElement(container, desiredHidden);
581
+ const keepHost = segment?.finalStep === block.host && hasBodyContent(block.host);
582
+ if (keepHost) this.restoreElement(block.host);
583
+ else this.hideElement(block.host, desiredHidden);
584
+ this.removeMergedThink(block.host);
585
+ return;
586
+ }
587
+ const chip = this.ensureChip(block);
588
+ this.restoreElement(block.host);
589
+ if (chip.style.display !== "") chip.style.display = "";
590
+ let expanded = this.blockExpanded.get(block.key) ?? false;
591
+ if (!expanded && block.rows.some((row) => row.hasAttribute("data-selected"))) {
592
+ expanded = true;
593
+ this.blockExpanded.set(block.key, true);
594
+ }
595
+ for (const row of block.rows) {
596
+ if (expanded) this.restoreElement(row);
597
+ else this.hideElement(row, desiredHidden);
598
+ }
599
+ for (const container of block.containers) {
600
+ if (expanded) this.restoreElement(container);
601
+ else this.hideElement(container, desiredHidden);
602
+ }
603
+ if (expanded && block.rows.length > 1 && block.rows.every((row) => isThinkRow(row))) {
604
+ this.syncMergedThink(block.host, block.rows, desiredHidden);
605
+ } else {
606
+ this.removeMergedThink(block.host);
607
+ }
608
+ chip.classList.toggle("dshcf-has-body", block.mount === "inside" && hasBodyContent(block.host));
609
+ updateChip(chip, block.rows, expanded);
610
+ }
611
+ ensureChip(block) {
612
+ let record = this.chips.get(block.key);
613
+ const validParent = record !== void 0 && (block.mount === "inside" ? record.chip.parentElement === block.host : record.chip.parentElement === block.host.parentElement);
614
+ if (record === void 0 || record.host !== block.host || !record.chip.isConnected || !validParent) {
615
+ if (record !== void 0) {
616
+ record.chip.remove();
617
+ this.removeMergedThink(record.host);
618
+ }
619
+ const chip2 = document.createElement("button");
620
+ chip2.type = "button";
621
+ chip2.className = block.mount === "before" ? "dshcf-chip dshcf-flow-chip" : "dshcf-chip";
622
+ chip2.setAttribute("aria-expanded", "false");
623
+ chip2.setAttribute("data-dshcf-block-key", block.key);
624
+ const leading = document.createElement("span");
625
+ leading.className = "dshcf-leading";
626
+ leading.appendChild(createTerminalIcon());
627
+ chip2.appendChild(leading);
628
+ chip2.appendChild(createSpan("dshcf-chip-title"));
629
+ chip2.appendChild(createSpan("dshcf-chip-sep"));
630
+ chip2.appendChild(createSpan("dshcf-chip-summary"));
631
+ chip2.appendChild(createChevronIcon("dshcf-chevron"));
632
+ chip2.addEventListener("click", () => {
633
+ this.blockExpanded.set(block.key, !(this.blockExpanded.get(block.key) ?? false));
634
+ this.schedule();
635
+ });
636
+ record = { host: block.host, chip: chip2 };
637
+ this.chips.set(block.key, record);
638
+ }
639
+ const chip = record.chip;
640
+ if (block.mount === "inside") {
641
+ if (chip.parentElement !== block.host || block.host.firstElementChild !== chip) block.host.prepend(chip);
642
+ chip.classList.remove("dshcf-flow-chip");
643
+ } else {
644
+ if (chip.parentElement !== block.host.parentElement || chip.nextElementSibling !== block.host) block.host.before(chip);
645
+ chip.classList.add("dshcf-flow-chip");
646
+ }
647
+ return chip;
648
+ }
649
+ suppressBlock(block, desiredHidden) {
650
+ const existing = this.chips.get(block.key)?.chip;
651
+ if (existing !== void 0 && existing.style.display !== "none") existing.style.display = "none";
652
+ this.removeMergedThink(block.host);
653
+ this.retainDisplayControl(block.host, desiredHidden);
654
+ for (const row of block.rows) this.retainDisplayControl(row, desiredHidden);
655
+ for (const container of block.containers) this.retainDisplayControl(container, desiredHidden);
656
+ }
657
+ retainDisplayControl(el, desiredHidden) {
658
+ if (this.controlledDisplay.has(el)) desiredHidden.add(el);
659
+ }
660
+ cleanupStaleChips(seen) {
661
+ for (const [key, record] of [...this.chips]) {
662
+ if (seen.has(key)) continue;
663
+ record.chip.remove();
664
+ this.removeMergedThink(record.host);
665
+ this.chips.delete(key);
666
+ this.blockExpanded.delete(key);
667
+ }
668
+ }
669
+ /** 连续思考合并行:插在第一个思考行前,标题用第一行思考内容;
670
+ * 点击切换显示/隐藏全部原始思考行。 */
671
+ syncMergedThink(host, rows, desiredHidden) {
672
+ let row = this.mergedThinks.get(host);
673
+ if (row === void 0 || !row.isConnected) {
674
+ row = document.createElement("button");
675
+ row.type = "button";
676
+ row.className = "dshcf-merged-think";
677
+ row.setAttribute("aria-expanded", "false");
678
+ const leading = document.createElement("span");
679
+ leading.className = "dshcf-leading";
680
+ leading.appendChild(createThinkIcon());
681
+ const title = document.createElement("span");
682
+ title.className = "dshcf-merged-title";
683
+ const chevron = createChevronIcon("dshcf-chevron");
684
+ row.append(leading, title, chevron);
685
+ const btn = row;
686
+ btn.addEventListener("click", () => {
687
+ const next = !this.mergedExpanded.has(host);
688
+ if (next) this.mergedExpanded.add(host);
689
+ else this.mergedExpanded.delete(host);
690
+ btn.setAttribute("aria-expanded", String(next));
691
+ if (next) this.expandMergedBody(host, btn);
692
+ else this.collapseMergedBody(host);
693
+ });
694
+ rows[0].before(row);
695
+ this.mergedThinks.set(host, row);
696
+ row = btn;
697
+ }
698
+ const titleEl = row.querySelector(".dshcf-merged-title");
699
+ if (titleEl !== null) {
700
+ let title = this.mergedTitles.get(host);
701
+ if (title === void 0) {
702
+ const first = truncateSummary(stripMarkdown(thinkSummary(rows[0])), 36);
703
+ if (first !== "" && first !== "\u601D\u8003") {
704
+ title = `Think \xB7 ${first}`;
705
+ this.mergedTitles.set(host, title);
706
+ } else {
707
+ title = "\u601D\u8003";
708
+ }
709
+ }
710
+ if (titleEl.textContent !== title) titleEl.textContent = title;
711
+ }
712
+ const expanded = this.mergedExpanded.has(host);
713
+ if (row.getAttribute("aria-expanded") !== String(expanded)) row.setAttribute("aria-expanded", String(expanded));
714
+ if (row.style.display !== "") row.style.display = "";
715
+ for (const r of rows) this.hideElement(r, desiredHidden);
716
+ if (expanded) this.ensureMergedBody(host, row, false);
717
+ }
718
+ /** 展开合并行:直接读各思考行文本合成内容块(不依赖原生行展开:
719
+ * 程序化 click 不触发 React 展开,且后台 tab 的 rAF 不执行)。 */
720
+ expandMergedBody(host, btn) {
721
+ const cached = this.mergedBodyTexts.get(host);
722
+ if (cached !== void 0) {
723
+ this.ensureMergedBody(host, btn, true);
724
+ return;
725
+ }
726
+ const parts = this.currentThinkRows(host).map((r) => r.textContent.replace(/^Think\s*/, "").trim()).filter(Boolean);
727
+ if (parts.length === 0) return;
728
+ this.mergedBodyTexts.set(host, parts.join("\n\n"));
729
+ this.ensureMergedBody(host, btn, true);
730
+ }
731
+ /** 创建/更新合并内容块(缓存优先,不重新展开原生行)。 */
732
+ ensureMergedBody(host, btn, force) {
733
+ const cached = this.mergedBodyTexts.get(host);
734
+ if (cached === void 0) return;
735
+ let body = btn.nextElementSibling;
736
+ if (body === null || !body.classList.contains("dshcf-merged-body")) {
737
+ body = document.createElement("div");
738
+ body.className = "dshcf-merged-body";
739
+ btn.after(body);
740
+ }
741
+ if (force || body.textContent !== cached) body.textContent = cached;
742
+ }
743
+ /** 收起合并行:移除内容块(原生行保持隐藏)。 */
744
+ collapseMergedBody(host) {
745
+ const btn = this.mergedThinks.get(host);
746
+ if (btn !== void 0) {
747
+ const body = btn.nextElementSibling;
748
+ if (body !== null && body.classList.contains("dshcf-merged-body")) body.remove();
749
+ }
750
+ }
751
+ /** 当前宿主内的思考行(现取,React 重渲染后引用仍然有效)。 */
752
+ currentThinkRows(host) {
753
+ return [...host.querySelectorAll('[data-variant="think"]:not([data-tool])')].filter(
754
+ (r) => r.closest("[data-chat-call-id]") === null && r.closest("[data-subcalls]") === null
755
+ );
756
+ }
757
+ /** 移除合并思考行(二级收起 / 一级收起时),恢复行由 applyRows 控制。
758
+ * 合并内容块(btn 的兄弟节点)一并移除,避免宿主展开后残留文本。 */
759
+ removeMergedThink(host) {
760
+ const row = this.mergedThinks.get(host);
761
+ if (row !== void 0) {
762
+ const body = row.nextElementSibling;
763
+ if (body !== null && body.classList.contains("dshcf-merged-body")) body.remove();
764
+ row.remove();
765
+ this.mergedThinks.delete(host);
766
+ }
767
+ this.mergedExpanded.delete(host);
768
+ this.mergedBodyTexts.delete(host);
769
+ }
770
+ hideElement(el, desired) {
771
+ if (!this.originalDisplay.has(el) && !isDisplayed(el)) return;
772
+ if (!this.originalDisplay.has(el)) this.originalDisplay.set(el, el.style.display);
773
+ this.controlledDisplay.add(el);
774
+ desired.add(el);
775
+ if (el.style.display !== "none") el.style.display = "none";
776
+ }
777
+ restoreElement(el) {
778
+ if (!this.originalDisplay.has(el)) return;
779
+ const original = this.originalDisplay.get(el);
780
+ if (el.style.display !== original) el.style.display = original;
781
+ this.originalDisplay.delete(el);
782
+ this.controlledDisplay.delete(el);
783
+ }
784
+ restoreUnusedDisplays(desired) {
785
+ for (const el of [...this.controlledDisplay]) {
786
+ if (!desired.has(el)) this.restoreElement(el);
787
+ }
788
+ }
789
+ restoreAllDisplays() {
790
+ for (const el of [...this.controlledDisplay]) this.restoreElement(el);
791
+ this.controlledDisplay.clear();
792
+ this.originalDisplay = /* @__PURE__ */ new WeakMap();
793
+ }
794
+ };
795
+ function createSpan(cls) {
796
+ const span = document.createElement("span");
797
+ span.className = cls;
798
+ return span;
799
+ }
800
+ function createTerminalIcon() {
801
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
802
+ svg.setAttribute("viewBox", "0 0 12 10");
803
+ svg.setAttribute("width", "12");
804
+ svg.setAttribute("height", "10");
805
+ const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
806
+ rect.setAttribute("x", "0.5");
807
+ rect.setAttribute("y", "0.5");
808
+ rect.setAttribute("width", "11");
809
+ rect.setAttribute("height", "9");
810
+ rect.setAttribute("rx", "1.5");
811
+ rect.setAttribute("fill", "none");
812
+ rect.setAttribute("stroke", "currentColor");
813
+ const prompt = document.createElementNS("http://www.w3.org/2000/svg", "text");
814
+ prompt.setAttribute("x", "2");
815
+ prompt.setAttribute("y", "7.5");
816
+ prompt.setAttribute("font-size", "7");
817
+ prompt.setAttribute("fill", "currentColor");
818
+ prompt.textContent = ">_";
819
+ svg.append(rect, prompt);
820
+ return svg;
821
+ }
822
+ var NATIVE_CHEVRON_DOWN_PATH = "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z";
823
+ function createChevronIcon(className) {
824
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
825
+ svg.setAttribute("width", "14");
826
+ svg.setAttribute("height", "14");
827
+ svg.setAttribute("class", className);
828
+ svg.setAttribute("viewBox", "0 0 14 14");
829
+ svg.setAttribute("fill", "none");
830
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
831
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
832
+ path.setAttribute("d", NATIVE_CHEVRON_DOWN_PATH);
833
+ path.setAttribute("fill", "currentColor");
834
+ svg.appendChild(path);
835
+ return svg;
836
+ }
837
+ var THINK_ICON_PATHS = [
838
+ {
839
+ d: "M7.06431 5.93342C7.68763 5.93342 8.19307 6.43904 8.19322 7.06233C8.19322 7.68573 7.68772 8.19123 7.06431 8.19123C6.44099 8.19113 5.9354 7.68567 5.9354 7.06233C5.93555 6.43911 6.44108 5.93353 7.06431 5.93342Z"
840
+ },
841
+ {
842
+ evenodd: true,
843
+ d: "M8.6815 0.963693C10.1169 0.447019 11.6266 0.374829 12.5633 1.31135C13.5 2.24805 13.4277 3.75776 12.911 5.19319C12.7126 5.74431 12.4386 6.31796 12.0965 6.89729C12.4969 7.54638 12.8141 8.19018 13.036 8.80647C13.5527 10.2419 13.6251 11.7516 12.6883 12.6883C11.7516 13.625 10.242 13.5527 8.8065 13.036C8.19022 12.8141 7.54641 12.4969 6.89732 12.0965C6.31797 12.4386 5.74435 12.7125 5.19322 12.911C3.75777 13.4276 2.2481 13.5 1.31138 12.5633C0.374859 11.6266 0.447049 10.1168 0.963724 8.68147C1.17185 8.10338 1.46321 7.50063 1.82896 6.8924C1.52182 6.35711 1.27235 5.82825 1.08872 5.31819C0.572068 3.88278 0.499714 2.37306 1.43638 1.43635C2.37308 0.499655 3.8828 0.572044 5.31822 1.08869C5.82828 1.27232 6.35715 1.5218 6.89243 1.82893C7.50066 1.46318 8.10341 1.17181 8.6815 0.963693ZM11.3573 8.01154C10.9083 8.62253 10.3901 9.22873 9.80943 9.8094C9.22877 10.3901 8.62255 10.9083 8.01158 11.3572C8.4257 11.5841 8.8287 11.7688 9.21275 11.9071C10.5456 12.3868 11.4246 12.2547 11.8397 11.8397C12.2548 11.4246 12.3869 10.5456 11.9071 9.21272C11.7688 8.82866 11.5841 8.42568 11.3573 8.01154ZM2.56529 8.02912C2.37344 8.39322 2.21495 8.74796 2.09263 9.08772C1.61291 10.4204 1.74512 11.2995 2.16001 11.7147C2.57505 12.1297 3.45415 12.2618 4.78697 11.7821C5.11057 11.6656 5.44786 11.5164 5.7938 11.3367C5.249 10.9223 4.70922 10.4533 4.19029 9.9344C3.57578 9.31987 3.03169 8.67633 2.56529 8.02912ZM6.90708 3.2469C6.24065 3.70479 5.5646 4.26321 4.91392 4.91389C4.26325 5.56456 3.70482 6.24063 3.24693 6.90705C3.72674 7.63325 4.32777 8.37459 5.03892 9.08576C5.64943 9.69627 6.28183 10.2265 6.90806 10.6678C7.59368 10.2025 8.2908 9.63076 8.96079 8.96076C9.6308 8.29075 10.2025 7.59366 10.6678 6.90803C10.2265 6.2818 9.69631 5.6494 9.08579 5.03889C8.37462 4.32773 7.63328 3.72672 6.90708 3.2469ZM11.7147 2.15998C11.2996 1.74509 10.4204 1.61288 9.08775 2.0926C8.74835 2.21479 8.39382 2.37271 8.03013 2.56428C8.67728 3.03065 9.31995 3.5758 9.93443 4.19026C10.4534 4.7092 10.9223 5.24896 11.3368 5.79377C11.5164 5.44785 11.6656 5.11052 11.7821 4.78694C12.2618 3.45416 12.1297 2.57502 11.7147 2.15998ZM4.91197 2.2176C3.57922 1.73788 2.70004 1.86995 2.28501 2.28498C1.87001 2.70003 1.73791 3.5792 2.21763 4.91194C2.31709 5.18822 2.44112 5.47427 2.58677 5.7674C3.01931 5.1887 3.51474 4.6158 4.06529 4.06526C4.61584 3.5147 5.18872 3.01928 5.76743 2.58674C5.47431 2.4411 5.18824 2.31706 4.91197 2.2176Z"
844
+ }
845
+ ];
846
+ function findNativeThinkSvg() {
847
+ for (const drow of document.querySelectorAll('[data-variant="think"] [data-disclosure-row]')) {
848
+ for (const svg of drow.querySelectorAll("svg")) {
849
+ if (svg.querySelectorAll("path").length >= 2) return svg;
850
+ }
851
+ }
852
+ return null;
853
+ }
854
+ function createThinkIcon() {
855
+ const native = findNativeThinkSvg();
856
+ if (native !== null) return native.cloneNode(true);
857
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
858
+ svg.setAttribute("viewBox", "0 0 14 14");
859
+ svg.setAttribute("width", "14");
860
+ svg.setAttribute("height", "14");
861
+ svg.setAttribute("fill", "none");
862
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
863
+ for (const p of THINK_ICON_PATHS) {
864
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
865
+ if (p.evenodd === true) {
866
+ path.setAttribute("fill-rule", "evenodd");
867
+ path.setAttribute("clip-rule", "evenodd");
868
+ }
869
+ path.setAttribute("d", p.d);
870
+ path.setAttribute("fill", "currentColor");
871
+ svg.appendChild(path);
872
+ }
873
+ return svg;
874
+ }
875
+ function findNativeCommandSvg() {
876
+ const selector = '[data-chat-call-id] [data-disclosure-row], [data-chat-flow-kind="command"] [data-disclosure-row], [data-chat-flow-kind="manual-compaction"] [data-disclosure-row]';
877
+ for (const drow of document.querySelectorAll(selector)) {
878
+ for (const svg of drow.querySelectorAll("svg")) {
879
+ if (svg.querySelectorAll("path").length === 3 && isIcon14(svg)) return svg;
880
+ }
881
+ }
882
+ return null;
883
+ }
884
+ function isIcon14(svg) {
885
+ if (svg.getAttribute("width") === "14" && svg.getAttribute("height") === "14") return true;
886
+ const vb = (svg.getAttribute("viewBox") ?? "").trim().split(/\s+/);
887
+ return vb.length === 4 && Number(vb[2]) === 14 && Number(vb[3]) === 14;
888
+ }
889
+ function createCommandIcon() {
890
+ const native = findNativeCommandSvg();
891
+ if (native !== null) return native.cloneNode(true);
892
+ return createTerminalIcon();
893
+ }
894
+ var CONTEXT_ICON_PATHS = [
895
+ {
896
+ d: "M11.2426 4.80473V6.10551H4.75819V4.80473H11.2426Z"
897
+ },
898
+ {
899
+ d: "M9.40858 7.84478V9.14557H4.75819V7.84478H9.40858Z"
900
+ },
901
+ {
902
+ d: "M9.23438 0.546389C10.1941 0.546389 10.9683 0.544914 11.5859 0.611819C12.2161 0.680096 12.7634 0.825745 13.2393 1.17139C13.5172 1.3733 13.7619 1.61812 13.9639 1.896C14.3096 2.37183 14.4551 2.91922 14.5234 3.54932C14.5903 4.16686 14.5889 4.94133 14.5889 5.90088V10.0981C14.5889 11.0576 14.5903 11.8321 14.5234 12.4497C14.4552 13.0798 14.3094 13.6272 13.9639 14.103C13.7619 14.381 13.5172 14.6257 13.2393 14.8276C12.7633 15.1734 12.2163 15.3189 11.5859 15.3872C10.9683 15.4541 10.1942 15.4536 9.23438 15.4536H6.76563C5.80591 15.4536 5.03168 15.4541 4.41407 15.3872C3.78385 15.3189 3.23665 15.1734 2.76074 14.8276C2.48291 14.6257 2.23802 14.3809 2.03614 14.103C1.69066 13.6272 1.54483 13.0798 1.47657 12.4497C1.40973 11.8321 1.41114 11.0576 1.41114 10.0981V5.90088C1.41113 4.94132 1.40966 4.16686 1.47657 3.54932C1.54488 2.91921 1.69042 2.37184 2.03614 1.896C2.2381 1.61807 2.4828 1.37333 2.76074 1.17139C3.23665 0.825682 3.78386 0.680109 4.41407 0.611819C5.03168 0.544905 5.80591 0.546389 6.76563 0.546389H9.23438ZM6.76563 1.896C5.77586 1.896 5.0876 1.89738 4.55957 1.95459C4.0443 2.01043 3.76214 2.11349 3.55469 2.26416C3.39135 2.38284 3.24761 2.52662 3.12891 2.68994C2.97821 2.89736 2.8752 3.17967 2.81934 3.69483C2.76214 4.22279 2.76075 4.91131 2.76074 5.90088V10.0981C2.76074 11.0876 2.76221 11.7762 2.81934 12.3042C2.87516 12.8194 2.97829 13.1026 3.12891 13.3101C3.24754 13.4733 3.39147 13.6172 3.55469 13.7358C3.76213 13.8865 4.04438 13.9896 4.55957 14.0454C5.0876 14.1026 5.77586 14.103 6.76563 14.103H9.23438C10.2242 14.103 10.9124 14.1026 11.4404 14.0454C11.9556 13.9896 12.2379 13.8865 12.4453 13.7358C12.6086 13.6172 12.7525 13.4733 12.8711 13.3101C13.0217 13.1026 13.1248 12.8195 13.1807 12.3042C13.2378 11.7762 13.2393 11.0876 13.2393 10.0981V5.90088C13.2393 4.91131 13.2379 4.22279 13.1807 3.69483C13.1248 3.17969 13.0218 2.89736 12.8711 2.68994C12.7524 2.52667 12.6086 2.38281 12.4453 2.26416C12.2379 2.11355 11.9556 2.01041 11.4404 1.95459C10.9124 1.8974 10.2241 1.896 9.23438 1.896H6.76563Z"
903
+ }
904
+ ];
905
+ function findNativeContextSvg() {
906
+ for (const ctx of document.querySelectorAll('[data-chat-flow-kind="context"]')) {
907
+ const drow = ctx.querySelector("[data-disclosure-row]");
908
+ if (drow === null) continue;
909
+ for (const svg of drow.querySelectorAll("svg")) {
910
+ if (svg.querySelectorAll("path").length >= 2) return svg;
911
+ }
912
+ }
913
+ return null;
914
+ }
915
+ function createContextIcon() {
916
+ const native = findNativeContextSvg();
917
+ if (native !== null) return native.cloneNode(true);
918
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
919
+ svg.setAttribute("viewBox", "0 0 16 16");
920
+ svg.setAttribute("width", "14");
921
+ svg.setAttribute("height", "14");
922
+ svg.setAttribute("fill", "none");
923
+ for (const p of CONTEXT_ICON_PATHS) {
924
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
925
+ path.setAttribute("d", p.d);
926
+ path.setAttribute("fill", "currentColor");
927
+ svg.appendChild(path);
928
+ }
929
+ return svg;
930
+ }
931
+ function syncLeadingIcon(chip, kind) {
932
+ const leading = chip.querySelector(".dshcf-leading");
933
+ if (leading === null) return;
934
+ const existing = leading.querySelector("svg");
935
+ if (existing !== null && existing.getAttribute("data-dshcf-icon") === kind) return;
936
+ for (const child of [...leading.childNodes]) child.remove();
937
+ const svg = kind === "think" ? createThinkIcon() : kind === "context" ? createContextIcon() : createCommandIcon();
938
+ svg.setAttribute("data-dshcf-icon", kind);
939
+ leading.appendChild(svg);
940
+ }
941
+ function findFlow() {
942
+ const flows = document.querySelectorAll("[data-chat-flow]");
943
+ for (const flow of flows) {
944
+ if (flow.offsetParent !== null || flow.getBoundingClientRect().width > 0) return flow;
945
+ }
946
+ return flows[0] ?? null;
947
+ }
948
+ function nodeWithin(node, ancestor) {
949
+ for (let current = node; current !== null; current = current.parentNode) {
950
+ if (current === ancestor) return true;
951
+ }
952
+ return false;
953
+ }
954
+ function flowItems(flow) {
955
+ return [...flow.children].filter((el) => el instanceof HTMLElement && !el.classList.contains("dshcf-processed") && !el.classList.contains("dshcf-flow-chip"));
956
+ }
957
+ function isDisplayed(el) {
958
+ if (typeof getComputedStyle === "function") return getComputedStyle(el).display !== "none";
959
+ return el.style.display !== "none";
960
+ }
961
+ function stableElementKey(el, fallbackIndex) {
962
+ const kind = el.getAttribute("data-chat-flow-kind") ?? "node";
963
+ const key = el.getAttribute("data-chat-flow-key") ?? el.getAttribute("data-chat-anchor-key") ?? `${kind}:${fallbackIndex}`;
964
+ return `${kind}:${key}`;
965
+ }
966
+ function hasLeadingTurnWork(items) {
967
+ return items.some((el) => {
968
+ const kind = el.getAttribute("data-chat-flow-kind");
969
+ return kind === "assistant-step" || kind === "assistant" || kind === "tool-call" || kind === "command" || kind === "manual-compaction";
970
+ });
971
+ }
972
+ function buildSegments(flow, blocks) {
973
+ const items = flowItems(flow);
974
+ const itemIndex = new Map(items.map((el, index) => [el, index]));
975
+ const snapshots = [];
976
+ let contentStart = 0;
977
+ let startMarker = null;
978
+ const append = (end, boundary, closed) => {
979
+ if (end < contentStart) return;
980
+ const range = items.slice(contentStart, end);
981
+ const inRange = new Set(range);
982
+ const segmentBlocks = blocks.filter((block) => inRange.has(block.host));
983
+ const bodySteps = range.filter((el) => {
984
+ const kind = el.getAttribute("data-chat-flow-kind");
985
+ return (kind === "assistant-step" || kind === "assistant") && hasBodyContent(el);
986
+ });
987
+ const finalStep = bodySteps.length > 0 ? bodySteps[bodySteps.length - 1] : null;
988
+ const middleSteps = new Set(bodySteps.slice(0, -1));
989
+ const workHosts = /* @__PURE__ */ new Set([
990
+ ...segmentBlocks.map((block) => block.host),
991
+ ...middleSteps
992
+ ]);
993
+ const firstWork = range.find((el) => workHosts.has(el)) ?? finalStep;
994
+ const identity = startMarker ?? range.find((el) => hasLeadingTurnWork([el])) ?? boundary;
995
+ const identityIndex = identity === null ? contentStart : itemIndex.get(identity) ?? contentStart;
996
+ const prefix = startMarker === null ? "leading" : "segment";
997
+ const key = `${prefix}:${identity === null ? `open:${contentStart}` : stableElementKey(identity, identityIndex)}`;
998
+ snapshots.push({
999
+ key,
1000
+ boundary,
1001
+ startMarker,
1002
+ blocks: segmentBlocks,
1003
+ middleSteps,
1004
+ finalStep,
1005
+ firstWork,
1006
+ closed,
1007
+ running: segmentBlocks.some((block) => block.rows.some((row) => rowState(row) === "running")),
1008
+ hasWork: segmentBlocks.length > 0 || middleSteps.size > 0
1009
+ });
1010
+ };
1011
+ for (let index = 0; index < items.length; index++) {
1012
+ const el = items[index];
1013
+ const kind = el.getAttribute("data-chat-flow-kind");
1014
+ if (kind === "user" || kind === "steering") {
1015
+ if (startMarker !== null) {
1016
+ append(index, el, true);
1017
+ contentStart = index + 1;
1018
+ } else {
1019
+ const leading = items.slice(contentStart, index);
1020
+ if (hasLeadingTurnWork(leading)) {
1021
+ append(index, el, true);
1022
+ contentStart = index + 1;
1023
+ }
1024
+ }
1025
+ startMarker = el;
1026
+ continue;
1027
+ }
1028
+ if (kind === "turn-tail") {
1029
+ append(index, el, true);
1030
+ contentStart = index + 1;
1031
+ startMarker = null;
1032
+ }
1033
+ }
1034
+ if (contentStart < items.length) append(items.length, null, false);
1035
+ return snapshots;
1036
+ }
1037
+ function hasVisibleSegmentWork(segment) {
1038
+ const workHosts = /* @__PURE__ */ new Set([
1039
+ ...segment.blocks.map((block) => block.host),
1040
+ ...segment.middleSteps
1041
+ ]);
1042
+ if (segment.startMarker !== null) workHosts.add(segment.startMarker);
1043
+ if (segment.finalStep !== null) workHosts.add(segment.finalStep);
1044
+ return [...workHosts].some(isDisplayed);
1045
+ }
1046
+ function findBlocks(flow) {
1047
+ const blocks = [];
1048
+ const children = flowItems(flow);
1049
+ let run = null;
1050
+ let carry = [];
1051
+ let carryHost = null;
1052
+ const makeBlock = (host, category) => {
1053
+ const block = {
1054
+ key: "",
1055
+ host,
1056
+ rows: [],
1057
+ containers: [],
1058
+ mount: "inside",
1059
+ category
1060
+ };
1061
+ blocks.push(block);
1062
+ return block;
1063
+ };
1064
+ const flushCarry = () => {
1065
+ if (carry.length === 0 || carryHost === null) return;
1066
+ let own = blocks.find((block) => block.host === carryHost && block.category === "work");
1067
+ if (own === void 0) own = makeBlock(carryHost, "work");
1068
+ own.rows.push(...carry);
1069
+ carry = [];
1070
+ carryHost = null;
1071
+ };
1072
+ for (const el of children) {
1073
+ const kind = el.getAttribute("data-chat-flow-kind");
1074
+ if (kind === "user" || kind === "steering" || kind === "turn-tail") {
1075
+ flushCarry();
1076
+ run = null;
1077
+ continue;
1078
+ }
1079
+ const thinkRows = thinkRowsIn(el);
1080
+ const workRows = [...callRowsIn(el), ...commandRowsIn(el)];
1081
+ const isToolPile = workRows.length > 0;
1082
+ const isContext = kind === "context";
1083
+ const hasBody = !isToolPile ? hasBodyContent(el) : false;
1084
+ if (isContext) {
1085
+ flushCarry();
1086
+ if (run === null || run.category !== "context") run = makeBlock(el, "context");
1087
+ run.rows.push(el);
1088
+ run.mount = "before";
1089
+ continue;
1090
+ }
1091
+ if (isToolPile || thinkRows.length > 0 && !hasBody) {
1092
+ if (run === null || run.category !== "work") run = makeBlock(el, "work");
1093
+ if (carry.length > 0) {
1094
+ run.rows.push(...carry);
1095
+ carry = [];
1096
+ carryHost = null;
1097
+ }
1098
+ run.rows.push(...thinkRows, ...workRows);
1099
+ if (el !== run.host && !workRows.includes(el)) {
1100
+ run.containers.push(el);
1101
+ }
1102
+ if (workRows.includes(el)) run.mount = "before";
1103
+ } else if (el.hasAttribute("data-chat-anchor-key") && (thinkRows.length > 0 || hasBody) || hasBody && kind !== null) {
1104
+ flushCarry();
1105
+ if (thinkRows.length > 0) {
1106
+ const segments = splitThinkByBody(el, thinkRows);
1107
+ if (run === null || run.category !== "work") run = makeBlock(el, "work");
1108
+ run.rows.push(...segments[0]);
1109
+ carry = segments.slice(1).flat();
1110
+ carryHost = el;
1111
+ }
1112
+ run = null;
1113
+ } else if (kind !== null && kind !== "assistant-step" && kind !== "assistant") {
1114
+ flushCarry();
1115
+ run = null;
1116
+ }
1117
+ }
1118
+ flushCarry();
1119
+ const indexByHost = new Map(children.map((el, index) => [el, index]));
1120
+ const counts = /* @__PURE__ */ new Map();
1121
+ for (const block of blocks) {
1122
+ block.mount = block.rows.includes(block.host) ? "before" : block.mount;
1123
+ const base = `${stableElementKey(block.host, indexByHost.get(block.host) ?? 0)}:${block.category}`;
1124
+ const ordinal = counts.get(base) ?? 0;
1125
+ counts.set(base, ordinal + 1);
1126
+ block.key = `${base}:block:${ordinal}`;
1127
+ }
1128
+ return blocks;
1129
+ }
1130
+ function splitThinkByBody(el, rows) {
1131
+ const segments = [];
1132
+ let current = [];
1133
+ for (let i = 0; i < rows.length; i++) {
1134
+ current.push(rows[i]);
1135
+ if (i + 1 < rows.length && hasBodyBetween(el, rows[i], rows[i + 1])) {
1136
+ segments.push(current);
1137
+ current = [];
1138
+ }
1139
+ }
1140
+ if (current.length > 0) segments.push(current);
1141
+ return segments.length > 0 ? segments : [rows];
1142
+ }
1143
+ function hasBodyBetween(el, a, b) {
1144
+ const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
1145
+ let node;
1146
+ while ((node = walker.nextNode()) !== null) {
1147
+ if (node.data.trim() === "") continue;
1148
+ const parent = node.parentElement;
1149
+ if (parent !== null && parent.closest('[data-variant="think"], [data-chat-call-id], .dshcf-chip, .dshcf-merged-think, .dshcf-merged-body') !== null) continue;
1150
+ const posA = a.compareDocumentPosition(node);
1151
+ const posB = b.compareDocumentPosition(node);
1152
+ if ((posA & Node.DOCUMENT_POSITION_FOLLOWING) !== 0 && (posB & Node.DOCUMENT_POSITION_PRECEDING) !== 0) {
1153
+ return true;
1154
+ }
1155
+ }
1156
+ return false;
1157
+ }
1158
+ function hasBodyText(el) {
1159
+ const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
1160
+ let node;
1161
+ while ((node = walker.nextNode()) !== null) {
1162
+ if (node.data.trim() === "") continue;
1163
+ const parent = node.parentElement;
1164
+ if (parent !== null && parent.closest('[data-variant="think"], [data-chat-call-id], .dshcf-chip, .dshcf-merged-think, .dshcf-merged-body') !== null) continue;
1165
+ return true;
1166
+ }
1167
+ return false;
1168
+ }
1169
+ function hasBodyContent(el) {
1170
+ const kind = el.getAttribute("data-chat-flow-kind");
1171
+ if (kind === "command" || kind === "manual-compaction") return false;
1172
+ if (hasBodyText(el)) return true;
1173
+ const excluded = '[data-variant="think"], [data-chat-call-id], [data-variant="others"][data-state], .dshcf-chip, .dshcf-merged-think, .dshcf-merged-body';
1174
+ for (const media of el.querySelectorAll("img, video, audio, canvas")) {
1175
+ if (media.closest(excluded) === null) return true;
1176
+ }
1177
+ return false;
1178
+ }
1179
+ function thinkRowsIn(el) {
1180
+ const rows = [];
1181
+ for (const row of el.querySelectorAll('[data-variant="think"]:not([data-tool])')) {
1182
+ if (row.closest("[data-chat-call-id]") !== null) continue;
1183
+ if (row.closest("[data-subcalls]") !== null) continue;
1184
+ rows.push(row);
1185
+ }
1186
+ return rows;
1187
+ }
1188
+ function callRowsIn(el) {
1189
+ const rows = [];
1190
+ for (const row of el.querySelectorAll("[data-chat-call-id]")) {
1191
+ if (row.closest("[data-subcalls]") !== null) continue;
1192
+ if (row.closest("[data-chat-call-id]") !== row) continue;
1193
+ rows.push(row);
1194
+ }
1195
+ return rows;
1196
+ }
1197
+ function commandRowsIn(el) {
1198
+ const kind = el.getAttribute("data-chat-flow-kind");
1199
+ if (kind !== "command" && kind !== "manual-compaction") return [];
1200
+ const rows = [];
1201
+ for (const row of el.querySelectorAll('[data-variant="others"][data-state]')) {
1202
+ const parent = row.parentElement?.closest('[data-variant="others"][data-state]');
1203
+ if (parent !== null && parent !== void 0 && parent !== row) continue;
1204
+ rows.push(row);
1205
+ }
1206
+ return rows.length > 0 ? rows : [el];
1207
+ }
1208
+ function deriveRowInfo(row) {
1209
+ const isThink = row.matches('[data-variant="think"]') && !row.hasAttribute("data-tool");
1210
+ if (isThink) {
1211
+ return { kind: "think", label: "Think", summary: thinkSummary(row), state: row.getAttribute("data-state") ?? "ok" };
1212
+ }
1213
+ if (row.getAttribute("data-chat-flow-kind") === "context") {
1214
+ return { kind: "tool", label: "\u4E0A\u4E0B\u6587\u6CE8\u5165", summary: toolSummary(row), state: "ok" };
1215
+ }
1216
+ const commandSeat = row.closest('[data-chat-flow-kind="command"], [data-chat-flow-kind="manual-compaction"]');
1217
+ if (commandSeat !== null) {
1218
+ const commandKind = commandSeat.getAttribute("data-chat-flow-kind");
1219
+ return {
1220
+ kind: "tool",
1221
+ label: commandKind === "manual-compaction" ? "Compact" : "Command",
1222
+ summary: toolSummary(row),
1223
+ state: row.getAttribute("data-state") ?? "ok"
1224
+ };
1225
+ }
1226
+ const root = row.querySelector("[data-tool]") ?? row;
1227
+ const tool = root.getAttribute("data-tool") ?? "";
1228
+ const state = root.getAttribute("data-state") ?? "ok";
1229
+ const label = TOOL_LABELS[tool] ?? tool;
1230
+ return { kind: "tool", label: label !== "" ? label : "Tool", summary: toolSummary(row), state };
1231
+ }
1232
+ function thinkSummary(row) {
1233
+ const follow = row.querySelector("[data-follow-end]");
1234
+ if (follow !== null) {
1235
+ const text = (follow.textContent ?? "").trim();
1236
+ if (text !== "") return text;
1237
+ }
1238
+ return summaryFallback(row);
1239
+ }
1240
+ function toolSummary(row) {
1241
+ const drow = row.querySelector("[data-disclosure-row]");
1242
+ if (drow !== null) {
1243
+ const children = [...drow.children].filter((el) => el instanceof HTMLElement);
1244
+ for (const child of children.slice(2)) {
1245
+ const text = (child.textContent ?? "").trim();
1246
+ if (text !== "") return text;
1247
+ }
1248
+ }
1249
+ return summaryFallback(row);
1250
+ }
1251
+ function summaryFallback(row) {
1252
+ const walker = document.createTreeWalker(row, NodeFilter.SHOW_TEXT);
1253
+ let best = "";
1254
+ let node;
1255
+ while ((node = walker.nextNode()) !== null) {
1256
+ if (node.parentElement?.closest('[data-open="true"]') !== null) continue;
1257
+ const text = node.data.trim();
1258
+ if (text === "") continue;
1259
+ if (text.length > best.length) best = text;
1260
+ }
1261
+ return best;
1262
+ }
1263
+ function deriveBlockInfo(rows) {
1264
+ const infos = rows.map(deriveRowInfo);
1265
+ const runningTool = infos.find((i) => i.kind === "tool" && i.state === "running") ?? null;
1266
+ const runningThink = infos.find((i) => i.kind === "think" && i.state === "running") ?? null;
1267
+ const tools = [...new Set(infos.filter((i) => i.kind === "tool").map((i) => i.label))];
1268
+ return {
1269
+ runningTool,
1270
+ runningThink,
1271
+ tools,
1272
+ count: rows.length,
1273
+ hasError: infos.some((i) => i.state === "error"),
1274
+ hasStopped: infos.some((i) => i.state === "stopped"),
1275
+ allContext: infos.length > 0 && infos.every((i) => i.label === "\u4E0A\u4E0B\u6587\u6CE8\u5165")
1276
+ };
1277
+ }
1278
+ function updateChip(chip, rows, expanded) {
1279
+ const info = deriveBlockInfo(rows);
1280
+ const title = chip.querySelector(".dshcf-chip-title");
1281
+ const summary = chip.querySelector(".dshcf-chip-summary");
1282
+ const sep = chip.querySelector(".dshcf-chip-sep");
1283
+ if (title === null || summary === null) return;
1284
+ const running = info.runningTool ?? info.runningThink;
1285
+ const collapsed = !expanded;
1286
+ let titleText;
1287
+ let summaryText;
1288
+ if (info.runningTool !== null) {
1289
+ titleText = "\u6B63\u5728\u8FD0\u884C";
1290
+ summaryText = collapsed ? info.runningTool.summary : "";
1291
+ } else if (info.runningThink !== null) {
1292
+ titleText = "\u6B63\u5728\u601D\u8003";
1293
+ summaryText = collapsed ? info.runningThink.summary : "";
1294
+ } else if (info.tools.length > 0) {
1295
+ titleText = info.allContext ? "\u4E0A\u4E0B\u6587\u6CE8\u5165" : info.tools.some((tool) => tool === "Edit" || tool === "Write") ? "\u7F16\u8F91\u4E86\u6587\u4EF6" : "\u8FD0\u884C\u4E86\u547D\u4EE4";
1296
+ summaryText = "";
1297
+ } else {
1298
+ titleText = "\u5DF2\u601D\u8003";
1299
+ summaryText = "";
1300
+ }
1301
+ const kind = running !== null ? running.kind : info.allContext ? "context" : info.tools.length > 0 ? "tool" : "think";
1302
+ if (title.textContent !== titleText) title.textContent = titleText;
1303
+ if (summary.textContent !== summaryText) summary.textContent = summaryText;
1304
+ if (sep !== null) {
1305
+ const sepDisplay = summaryText === "" ? "none" : "";
1306
+ if (sep.style.display !== sepDisplay) sep.style.display = sepDisplay;
1307
+ }
1308
+ summary.scrollLeft = running !== null ? summary.scrollWidth - summary.clientWidth : 0;
1309
+ const expandedAttr = String(expanded);
1310
+ if (chip.getAttribute("aria-expanded") !== expandedAttr) {
1311
+ chip.setAttribute("aria-expanded", expandedAttr);
1312
+ }
1313
+ if (chip.dataset.kind !== kind) {
1314
+ chip.dataset.kind = kind;
1315
+ syncLeadingIcon(chip, kind);
1316
+ }
1317
+ const tip = expanded ? "\u6536\u8D77\u8FD9\u4E9B\u5361\u7247" : "\u5C55\u5F00\u8FD9\u4E9B\u5361\u7247";
1318
+ if (chip.title !== tip) chip.title = tip;
1319
+ setClass(chip, "running", running !== null);
1320
+ setClass(chip, "error", !running && info.hasError);
1321
+ setClass(chip, "stopped", !running && info.hasStopped && !info.hasError);
1322
+ }
1323
+ function setClass(el, cls, on) {
1324
+ if (el.classList.contains(cls) !== on) el.classList.toggle(cls, on);
1325
+ }
1326
+ function truncateSummary(text, max) {
1327
+ const t = text.replace(/\s+/g, " ").trim();
1328
+ return t.length > max ? t.slice(0, max) + "\u2026" : t;
1329
+ }
1330
+ function stripMarkdown(text) {
1331
+ return text.replace(/\*\*/g, "").replace(/^#{1,3}\s+/, "").trim();
1332
+ }
1333
+ function isThinkRow(row) {
1334
+ return row.matches('[data-variant="think"]') && !row.hasAttribute("data-tool");
1335
+ }
1336
+ function parseTurnDuration(boundary) {
1337
+ const text = boundary.textContent ?? "";
1338
+ const m = text.match(/用时\s*(\d+)分(\d+)秒|用时\s*(\d+)秒/);
1339
+ if (m !== null) {
1340
+ if (m[1] !== void 0 && m[2] !== void 0) return Number(m[1]) * 6e4 + Number(m[2]) * 1e3;
1341
+ if (m[3] !== void 0) return Number(m[3]) * 1e3;
1342
+ return void 0;
1343
+ }
1344
+ const end = parseTimeText(text);
1345
+ const start = findTurnStart(boundary);
1346
+ if (end !== void 0 && start !== void 0 && end > start) return end - start;
1347
+ return void 0;
1348
+ }
1349
+ function parseTimeText(text) {
1350
+ const m = text.match(/(?:(\d{4})年)?(\d{1,2})月(\d{1,2})日\s*(\d{1,2}):(\d{2})/);
1351
+ if (m === null) return void 0;
1352
+ const year = m[1] !== void 0 ? Number(m[1]) : (/* @__PURE__ */ new Date()).getFullYear();
1353
+ const t = new Date(year, Number(m[2]) - 1, Number(m[3]), Number(m[4]), Number(m[5])).getTime();
1354
+ return Number.isNaN(t) ? void 0 : t;
1355
+ }
1356
+ function findTurnStart(boundary) {
1357
+ const flow = boundary.parentElement;
1358
+ if (flow === null) return void 0;
1359
+ let best = null;
1360
+ for (const s of flow.querySelectorAll('[class*="timeStart"]')) {
1361
+ const pos = s.compareDocumentPosition(boundary);
1362
+ if ((pos & Node.DOCUMENT_POSITION_FOLLOWING) !== 0 || (pos & Node.DOCUMENT_POSITION_CONTAINED_BY) !== 0 || s === boundary) best = s;
1363
+ else break;
1364
+ }
1365
+ if (best === null) return void 0;
1366
+ return parseTimeText(best.textContent ?? "");
1367
+ }
1368
+ function rowState(row) {
1369
+ if (row.matches('[data-variant="think"]') && !row.hasAttribute("data-tool")) {
1370
+ return row.getAttribute("data-state") ?? "ok";
1371
+ }
1372
+ const root = row.querySelector("[data-tool]") ?? row;
1373
+ return root.getAttribute("data-state") ?? "ok";
1374
+ }
1375
+ function createProcessedRowElement(duration) {
1376
+ const btn = document.createElement("button");
1377
+ btn.type = "button";
1378
+ btn.className = "dshcf-processed";
1379
+ btn.setAttribute("aria-expanded", "false");
1380
+ const text = document.createElement("span");
1381
+ text.textContent = duration !== void 0 ? `\u5DF2\u5904\u7406 ${formatDuration(duration)}` : "\u5DF2\u5904\u7406";
1382
+ const chevron = createChevronIcon("dshcf-processed-chevron");
1383
+ btn.append(text, chevron);
1384
+ btn.title = "\u5C55\u5F00\u5DE5\u4F5C\u8FC7\u7A0B";
1385
+ return btn;
1386
+ }
1387
+ function formatDuration(ms) {
1388
+ const s = Math.round(ms / 1e3);
1389
+ if (s < 60) return `${s}\u79D2`;
1390
+ const h = Math.floor(s / 3600);
1391
+ const m = Math.floor(s % 3600 / 60);
1392
+ const r = s % 60;
1393
+ if (h > 0) {
1394
+ return m > 0 ? `${h}\u5C0F\u65F6${m}\u5206` : `${h}\u5C0F\u65F6`;
1395
+ }
1396
+ if (r === 0) return `${m}\u5206`;
1397
+ return `${m}\u5206${String(r).padStart(2, "0")}\u79D2`;
1398
+ }
1399
+ function injectStyle() {
1400
+ if (document.getElementById(STYLE_ID) !== null) return;
1401
+ const style = document.createElement("style");
1402
+ style.id = STYLE_ID;
1403
+ style.textContent = CHIP_CSS;
1404
+ document.head.appendChild(style);
1405
+ }
1406
+ function replaceTurnStatus(flow, originals) {
1407
+ const statuses = flow.matches('[role="status"]') ? [flow, ...flow.querySelectorAll('[role="status"]')] : [...flow.querySelectorAll('[role="status"]')];
1408
+ for (const status of statuses) {
1409
+ for (const node of status.childNodes) {
1410
+ if (node instanceof Text && node.data.includes("Deep diving")) {
1411
+ if (!originals.has(node)) originals.set(node, node.data);
1412
+ const next = node.data.replace("Deep diving", "Deep sleeping");
1413
+ if (node.data !== next) node.data = next;
1414
+ }
1415
+ }
1416
+ }
1417
+ }
1418
+ function restoreTurnStatus(originals) {
1419
+ for (const [node, original] of originals) {
1420
+ if (node.isConnected && node.data.includes("Deep sleeping")) node.data = original;
1421
+ }
1422
+ originals.clear();
1423
+ }
1424
+ function removeStyle() {
1425
+ document.getElementById(STYLE_ID)?.remove();
1426
+ }
1427
+
1428
+ // src/client.ts
1429
+ var name = "dsh-auto-collapse";
1430
+ var inject = [];
1431
+ function apply(ctx) {
1432
+ ctx.effect(() => {
1433
+ const controller = new FoldController();
1434
+ controller.start();
1435
+ return () => controller.stop();
1436
+ }, "dsh-auto-collapse: fold observer");
1437
+ }
1438
+ return __toCommonJS(client_exports);
1439
+ })();
1440
+ return __dshcfBundle;}});