dsh-better-display 0.3.7 → 0.3.9
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/CHANGELOG.md +22 -1
- package/DESIGN.md +43 -3
- package/README.en.md +9 -1
- package/README.md +9 -1
- package/docs/dependency-update-policy.md +9 -0
- package/docs/extension-points.md +172 -0
- package/docs/official-rendering-bridge.md +59 -18
- package/docs/openapi.yaml +147 -0
- package/docs/runbooks/blank-reader.md +39 -0
- package/lib/client.js +1629 -586
- package/lib/client.js.map +1 -1
- package/lib/dsh-better-display.js +535 -57
- package/lib/types/client/AssistantNode.d.ts +20 -0
- package/lib/types/client/AssistantNode.d.ts.map +1 -0
- package/lib/types/client/AssistantNode.js +46 -0
- package/lib/types/client/AssistantNode.js.map +1 -0
- package/lib/types/client/Blocks.d.ts.map +1 -1
- package/lib/types/client/Blocks.js +33 -10
- package/lib/types/client/Blocks.js.map +1 -1
- package/lib/types/client/ChoreographedFlow.d.ts.map +1 -1
- package/lib/types/client/ChoreographedFlow.js +2 -0
- package/lib/types/client/ChoreographedFlow.js.map +1 -1
- package/lib/types/client/ClosedProcessSummary.d.ts.map +1 -1
- package/lib/types/client/ClosedProcessSummary.js +3 -1
- package/lib/types/client/ClosedProcessSummary.js.map +1 -1
- package/lib/types/client/McpAppFrame.d.ts.map +1 -1
- package/lib/types/client/McpAppFrame.js +5 -11
- package/lib/types/client/McpAppFrame.js.map +1 -1
- package/lib/types/client/OfficialContent.d.ts +17 -3
- package/lib/types/client/OfficialContent.d.ts.map +1 -1
- package/lib/types/client/OfficialContent.js +33 -7
- package/lib/types/client/OfficialContent.js.map +1 -1
- package/lib/types/client/Reader.d.ts.map +1 -1
- package/lib/types/client/Reader.js +76 -73
- package/lib/types/client/Reader.js.map +1 -1
- package/lib/types/client/SettingsSection.d.ts.map +1 -1
- package/lib/types/client/SettingsSection.js +0 -5
- package/lib/types/client/SettingsSection.js.map +1 -1
- package/lib/types/client/StickyLane.d.ts +12 -0
- package/lib/types/client/StickyLane.d.ts.map +1 -1
- package/lib/types/client/StickyLane.js +78 -2
- package/lib/types/client/StickyLane.js.map +1 -1
- package/lib/types/client/ToolActivity.d.ts.map +1 -1
- package/lib/types/client/ToolActivity.js +10 -5
- package/lib/types/client/ToolActivity.js.map +1 -1
- package/lib/types/client/deliverables.d.ts.map +1 -1
- package/lib/types/client/deliverables.js +2 -0
- package/lib/types/client/deliverables.js.map +1 -1
- package/lib/types/client/index.d.ts +3 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +15 -1
- package/lib/types/client/index.js.map +1 -1
- package/lib/types/client/live-turn.d.ts +17 -5
- package/lib/types/client/live-turn.d.ts.map +1 -1
- package/lib/types/client/live-turn.js +106 -76
- package/lib/types/client/live-turn.js.map +1 -1
- package/lib/types/client/motion.d.ts +26 -2
- package/lib/types/client/motion.d.ts.map +1 -1
- package/lib/types/client/motion.js +144 -10
- package/lib/types/client/motion.js.map +1 -1
- package/lib/types/client/official-slots.d.ts +9 -0
- package/lib/types/client/official-slots.d.ts.map +1 -1
- package/lib/types/client/official-slots.js +22 -4
- package/lib/types/client/official-slots.js.map +1 -1
- package/lib/types/client/open-file.d.ts.map +1 -1
- package/lib/types/client/open-file.js +1 -6
- package/lib/types/client/open-file.js.map +1 -1
- package/lib/types/client/projection.d.ts +15 -2
- package/lib/types/client/projection.d.ts.map +1 -1
- package/lib/types/client/projection.js +16 -4
- package/lib/types/client/projection.js.map +1 -1
- package/lib/types/client/rewind-cut.d.ts +131 -0
- package/lib/types/client/rewind-cut.d.ts.map +1 -0
- package/lib/types/client/rewind-cut.js +321 -0
- package/lib/types/client/rewind-cut.js.map +1 -0
- package/lib/types/client/styles.d.ts +3 -0
- package/lib/types/client/styles.d.ts.map +1 -0
- package/lib/types/client/styles.js +25 -0
- package/lib/types/client/styles.js.map +1 -0
- package/lib/types/client/text-transform.d.ts +93 -0
- package/lib/types/client/text-transform.d.ts.map +1 -0
- package/lib/types/client/text-transform.js +183 -0
- package/lib/types/client/text-transform.js.map +1 -0
- package/lib/types/client/timeline.d.ts.map +1 -1
- package/lib/types/client/timeline.js.map +1 -1
- package/lib/types/client/tool-activity.d.ts +11 -4
- package/lib/types/client/tool-activity.d.ts.map +1 -1
- package/lib/types/client/tool-activity.js +54 -9
- package/lib/types/client/tool-activity.js.map +1 -1
- package/lib/types/client/turn-slots.d.ts +29 -0
- package/lib/types/client/turn-slots.d.ts.map +1 -0
- package/lib/types/client/turn-slots.js +62 -0
- package/lib/types/client/turn-slots.js.map +1 -0
- package/lib/types/client/types.d.ts +18 -0
- package/lib/types/client/types.d.ts.map +1 -1
- package/lib/types/dsh-better-display.d.ts +4 -1
- package/lib/types/dsh-better-display.d.ts.map +1 -1
- package/lib/types/dsh-better-display.js +55 -43
- package/lib/types/dsh-better-display.js.map +1 -1
- package/lib/types/flags.d.ts +7 -0
- package/lib/types/flags.d.ts.map +1 -0
- package/lib/types/flags.js +37 -0
- package/lib/types/flags.js.map +1 -0
- package/lib/types/log.d.ts +17 -0
- package/lib/types/log.d.ts.map +1 -0
- package/lib/types/log.js +122 -0
- package/lib/types/log.js.map +1 -0
- package/lib/types/metrics.d.ts +18 -0
- package/lib/types/metrics.d.ts.map +1 -0
- package/lib/types/metrics.js +35 -0
- package/lib/types/metrics.js.map +1 -0
- package/lib/types/reveal.d.ts +12 -0
- package/lib/types/reveal.d.ts.map +1 -0
- package/lib/types/reveal.js +147 -0
- package/lib/types/reveal.js.map +1 -0
- package/lib/types/workspace-path.d.ts +3 -0
- package/lib/types/workspace-path.d.ts.map +1 -0
- package/lib/types/workspace-path.js +5 -0
- package/lib/types/workspace-path.js.map +1 -0
- package/package.json +36 -5
- package/scripts/changelog.mjs +20 -0
- package/scripts/check-agents-md.mjs +67 -0
- package/scripts/check-bundle-size.mjs +38 -0
- package/scripts/check-dead-flags.mjs +55 -0
- package/scripts/check-todo-debt.mjs +69 -0
- package/scripts/security-audit-report.mjs +92 -0
- package/scripts/verify-commentary-visible.mjs +627 -0
- package/src/client/AssistantNode.tsx +72 -0
- package/src/client/Blocks.tsx +49 -10
- package/src/client/ChoreographedFlow.tsx +3 -1
- package/src/client/ClosedProcessSummary.tsx +3 -1
- package/src/client/McpAppFrame.tsx +5 -13
- package/src/client/OfficialContent.tsx +47 -9
- package/src/client/Reader.module.css +103 -21
- package/src/client/Reader.tsx +83 -88
- package/src/client/SettingsSection.tsx +1 -7
- package/src/client/StickyLane.tsx +81 -2
- package/src/client/ToolActivity.tsx +10 -6
- package/src/client/deliverables.ts +1 -0
- package/src/client/index.tsx +18 -2
- package/src/client/live-turn.ts +100 -69
- package/src/client/motion.tsx +142 -7
- package/src/client/official-slots.tsx +23 -4
- package/src/client/open-file.ts +2 -8
- package/src/client/projection.ts +16 -4
- package/src/client/rewind-cut.ts +340 -0
- package/src/client/styles.ts +22 -0
- package/src/client/text-transform.ts +265 -0
- package/src/client/timeline.ts +0 -2
- package/src/client/tool-activity.ts +67 -9
- package/src/client/turn-slots.ts +80 -0
- package/src/client/types.ts +19 -0
- package/src/dsh-better-display.ts +57 -42
- package/src/flags.ts +40 -0
- package/src/log.ts +137 -0
- package/src/metrics.ts +50 -0
- package/src/reveal.ts +90 -0
- package/src/workspace-path.ts +4 -0
- package/tests/browser-commentary.tsx +191 -0
- package/tests/chat-flow-hook.test.ts +1 -1
- package/tests/cloud-gate.test.ts +1 -1
- package/tests/context-tool-update.test.ts +1 -1
- package/tests/conversation-scroll.test.ts +1 -1
- package/tests/deliverables.test.ts +1 -1
- package/tests/entry.test.ts +1 -1
- package/tests/fixtures/reader-lane-owners.tsx +46 -0
- package/tests/fixtures/reader-official-users.tsx +234 -0
- package/tests/fixtures/reader-theme-overlap.html +80 -0
- package/tests/fixtures/reader-user-bubble.tsx +222 -0
- package/tests/flags.test.ts +66 -0
- package/tests/fold-choreography.test.ts +32 -8
- package/tests/fold-intensity.test.ts +11 -6
- package/tests/footer-precedence.test.ts +9 -1
- package/tests/history-word-regression.test.ts +1 -1
- package/tests/live-turn.test.ts +125 -54
- package/tests/log.test.ts +99 -0
- package/tests/mcp-apps.test.ts +1 -1
- package/tests/message-chrome.test.ts +1 -1
- package/tests/metrics.test.ts +52 -0
- package/tests/official-slots.test.ts +41 -2
- package/tests/open-file.test.ts +1 -1
- package/tests/pending-submission.test.ts +12 -1
- package/tests/pinned-selection.test.ts +16 -0
- package/tests/platform-media.test.ts +1 -1
- package/tests/projection.test.ts +66 -3
- package/tests/reader-glass-css.test.ts +28 -0
- package/tests/reader-official-users.test.ts +91 -0
- package/tests/reader-sticky-surface.test.ts +377 -0
- package/tests/reader-theme-lanes.test.ts +54 -0
- package/tests/reader-theme-overlap.test.ts +151 -0
- package/tests/reader-user-bubble.test.ts +137 -0
- package/tests/reasoning-follow.test.ts +1 -1
- package/tests/retiring-content.test.ts +229 -0
- package/tests/reveal.test.ts +128 -0
- package/tests/rewind-cut.test.ts +1090 -0
- package/tests/settings-copy.test.ts +1 -1
- package/tests/skill-status.test.ts +1 -1
- package/tests/stock-install.test.ts +9 -1
- package/tests/stream-buffer.test.ts +1 -1
- package/tests/styles.test.ts +75 -0
- package/tests/terminal-input-preview.test.ts +113 -0
- package/tests/text-transform.test.ts +272 -0
- package/tests/timeline.test.ts +1 -1
- package/tests/tool-clock.test.ts +1 -1
- package/tests/tool-diff.test.ts +1 -1
- package/tests/waiting-clock.test.ts +1 -1
- package/tests/word-timeline.test.ts +1 -1
- package/tsdown.config.ts +49 -1
package/lib/client.js
CHANGED
|
@@ -17,9 +17,9 @@ window.__ModuleLoader__.load({
|
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
19
19
|
let react = require("react");
|
|
20
|
+
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
20
21
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
21
22
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
22
|
-
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
23
23
|
//#region node_modules/@deepseek-ai/dsh-util-workspace-path/lib/index.js
|
|
24
24
|
/**
|
|
25
25
|
* The `dsh-resource://file/…` address grammar: how a file is named across the
|
|
@@ -52,7 +52,7 @@ window.__ModuleLoader__.load({
|
|
|
52
52
|
* @module @deepseek-ai/dsh-util-workspace-path
|
|
53
53
|
*/
|
|
54
54
|
/** Whether a path uses a Windows drive or UNC prefix. */
|
|
55
|
-
function isWindowsStylePath
|
|
55
|
+
function isWindowsStylePath(value) {
|
|
56
56
|
return /^[A-Za-z]:[/\\]/.test(value) || value.startsWith("\\\\");
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
@@ -61,7 +61,7 @@ window.__ModuleLoader__.load({
|
|
|
61
61
|
* @returns `true` for an absolute path; `false` for a Workspace-relative one.
|
|
62
62
|
*/
|
|
63
63
|
function isAbsoluteWorkspacePath$1(path) {
|
|
64
|
-
return path.startsWith("/") || isWindowsStylePath
|
|
64
|
+
return path.startsWith("/") || isWindowsStylePath(path);
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
67
|
* Resolve a Workspace-relative path into the Host-facing spelling used by path operations.
|
|
@@ -72,7 +72,7 @@ window.__ModuleLoader__.load({
|
|
|
72
72
|
function resolveWorkspacePath(cwd, path) {
|
|
73
73
|
if (isAbsoluteWorkspacePath$1(path)) return path;
|
|
74
74
|
if (cwd === void 0 || cwd === "") return path;
|
|
75
|
-
const separator = isWindowsStylePath
|
|
75
|
+
const separator = isWindowsStylePath(cwd) && cwd.includes("\\") ? "\\" : "/";
|
|
76
76
|
return `${cwd.replace(/[/\\]+$/, "")}${separator}${path.replace(/^[/\\]+/, "")}`;
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
@@ -83,7 +83,7 @@ window.__ModuleLoader__.load({
|
|
|
83
83
|
*/
|
|
84
84
|
function abbreviateHomePath(path, home) {
|
|
85
85
|
if (home === void 0 || home === "") return path;
|
|
86
|
-
if (isWindowsStylePath
|
|
86
|
+
if (isWindowsStylePath(path) || isWindowsStylePath(home)) return path;
|
|
87
87
|
const root = home.replace(/\/+$/, "");
|
|
88
88
|
if (root === "" || root === "/") return path;
|
|
89
89
|
if (path.replace(/\/+$/, "") === root) return "~";
|
|
@@ -109,12 +109,286 @@ window.__ModuleLoader__.load({
|
|
|
109
109
|
return sessionFileAddress(sessionId, normalized);
|
|
110
110
|
}
|
|
111
111
|
//#endregion
|
|
112
|
+
//#region src/client/rewind-cut.ts
|
|
113
|
+
function asRecord$1(value) {
|
|
114
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
115
|
+
}
|
|
116
|
+
function safeSeq(value) {
|
|
117
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
118
|
+
}
|
|
119
|
+
/** The command payload of a `command` chat node, when it is structurally readable. */
|
|
120
|
+
function commandOf(node) {
|
|
121
|
+
if (node.kind !== "command") return void 0;
|
|
122
|
+
return asRecord$1(node.data);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The engine names an executed rewind command node can carry. The plugin
|
|
126
|
+
* registers its command as `rewind-plugin` (`ENGINE_COMMANDS = new
|
|
127
|
+
* Set(['rewind-plugin', 'rewind'])` in dsh-rewind-plugin's
|
|
128
|
+
* `src/client/hidden.ts`), and that is the name the client projection actually
|
|
129
|
+
* publishes — the session log's `command/run.name` is not what the Reader sees.
|
|
130
|
+
* `rewind` stays accepted because older logs and the bili-side proxy record the
|
|
131
|
+
* shorter spelling.
|
|
132
|
+
*/
|
|
133
|
+
const REWIND_COMMANDS = /* @__PURE__ */ new Set(["rewind-plugin", "rewind"]);
|
|
134
|
+
/** True when a command payload is the rewind engine command, in either spelling. */
|
|
135
|
+
function isRewindCommand(command) {
|
|
136
|
+
return typeof command.name === "string" && REWIND_COMMANDS.has(command.name);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The render POSITION a row is anchored at: the view node's `anchorSeq`, else
|
|
140
|
+
* its payload seq.
|
|
141
|
+
*
|
|
142
|
+
* This is deliberately NOT integer-only. The host anchors synthetic rows at
|
|
143
|
+
* fractional offsets off a real seq (`CHAT_SYNTHETIC_SEQ_OFFSETS` in the
|
|
144
|
+
* official ChatView: `turn-process` at `controlAnchorSeq - 0.1`, `turn-tail` at
|
|
145
|
+
* `seq + 0.1`, an interrupted assistant step at `seq - 0.9`). An integer-only
|
|
146
|
+
* read made those rows invisible to the cut, so the last `turn-process` of a
|
|
147
|
+
* withdrawn turn survived on its own. Log seqs (marker, target) stay integer:
|
|
148
|
+
* see `safeSeq`.
|
|
149
|
+
*/
|
|
150
|
+
function anchorSeqOf(node) {
|
|
151
|
+
const raw = node.anchorSeq ?? asRecord$1(node.data)?.seq;
|
|
152
|
+
return typeof raw === "number" && Number.isFinite(raw) && raw >= 0 ? raw : void 0;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Extract the rewind target seq from a `/rewind` command's structured `args`
|
|
156
|
+
* (e.g. `@5 chat`, `preview @5 both`). Locale-independent: it never parses the
|
|
157
|
+
* host's human outcome copy.
|
|
158
|
+
*/
|
|
159
|
+
function rewindTargetOfArgs(args) {
|
|
160
|
+
if (typeof args !== "string") return void 0;
|
|
161
|
+
const match = args.match(/@(\d+)/);
|
|
162
|
+
return match === null ? void 0 : Number(match[1]);
|
|
163
|
+
}
|
|
164
|
+
/** True for the internal candidate-list probe (`/rewind __candidates`). */
|
|
165
|
+
function isCandidateCommand(command) {
|
|
166
|
+
return typeof command.args === "string" && command.args.includes("__candidates");
|
|
167
|
+
}
|
|
168
|
+
/** True for an impact preview (`/rewind preview @5 both`). */
|
|
169
|
+
function isPreviewCommand(command) {
|
|
170
|
+
return typeof command.args === "string" && command.args.includes("preview");
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Merge overlapping or touching shadow ranges.
|
|
174
|
+
*
|
|
175
|
+
* Spans are kept SEPARATE unless they genuinely overlap: collapsing every cut
|
|
176
|
+
* to `[min target, max marker]` would hide a still-on-surface gap of new traffic
|
|
177
|
+
* between an earlier marker and a later target.
|
|
178
|
+
*/
|
|
179
|
+
function coalesceCutSpans(spans) {
|
|
180
|
+
if (spans.length < 2) return [...spans];
|
|
181
|
+
const sorted = [...spans].sort((left, right) => left.start - right.start || left.end - right.end);
|
|
182
|
+
const merged = [];
|
|
183
|
+
for (const span of sorted) {
|
|
184
|
+
const last = merged.at(-1);
|
|
185
|
+
if (last !== void 0 && span.start <= last.end) {
|
|
186
|
+
if (span.end > last.end) last.end = span.end;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
merged.push({
|
|
190
|
+
start: span.start,
|
|
191
|
+
end: span.end
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return merged;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* True when a row anchored at `seq` falls inside one of the cut spans.
|
|
198
|
+
*
|
|
199
|
+
* A cut runs from the target seq through the marker's own log seq, inclusive
|
|
200
|
+
* (`target <= anchorSeq && anchorSeq <= marker`), the same comparison
|
|
201
|
+
* `dsh-rewind-plugin`'s `RewindVisibilityBuilder` uses. The upper bound stops
|
|
202
|
+
* at the marker. Extending it to the next integer hides the following turn's
|
|
203
|
+
* process row, which the host anchors at `startSeq - 0.1` and therefore in
|
|
204
|
+
* `[marker, marker + 1)`. Fractional anchors inside the closed range still
|
|
205
|
+
* match: `anchorSeqOf` keeps them. A process or tail row parked outside the
|
|
206
|
+
* range is handled by `summaryTurns`, not by widening the cut. Spans stay
|
|
207
|
+
* disjoint, so new traffic between two rewinds survives.
|
|
208
|
+
*/
|
|
209
|
+
function cutContains(cuts, seq) {
|
|
210
|
+
let low = 0;
|
|
211
|
+
let high = cuts.length - 1;
|
|
212
|
+
let found = -1;
|
|
213
|
+
while (low <= high) {
|
|
214
|
+
const middle = low + high >> 1;
|
|
215
|
+
const cut = cuts[middle];
|
|
216
|
+
if (cut === void 0) return false;
|
|
217
|
+
if (seq < cut.start) high = middle - 1;
|
|
218
|
+
else {
|
|
219
|
+
found = middle;
|
|
220
|
+
low = middle + 1;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const span = found < 0 ? void 0 : cuts[found];
|
|
224
|
+
return span !== void 0 && seq <= span.end;
|
|
225
|
+
}
|
|
226
|
+
/** The turn id a node belongs to (absent outside a turn). */
|
|
227
|
+
function turnIdOf(node) {
|
|
228
|
+
const turn = asRecord$1(asRecord$1(node.location)?.turn);
|
|
229
|
+
if (turn === void 0 || !Object.hasOwn(turn, "turn")) return void 0;
|
|
230
|
+
return turn.turn;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Node kinds that SUMMARIZE a turn instead of carrying its content, so the host
|
|
234
|
+
* anchors them at the turn's edges rather than at an event inside it.
|
|
235
|
+
*/
|
|
236
|
+
const TURN_SUMMARY_KINDS = /* @__PURE__ */ new Set(["turn-process", "turn-tail"]);
|
|
237
|
+
/**
|
|
238
|
+
* True for a rewind command row the transcript should not keep.
|
|
239
|
+
*
|
|
240
|
+
* Probes (`preview`, `__candidates`) exist only to feed the popover. An
|
|
241
|
+
* executed rewind — success plus a marker seq — is the command that performed
|
|
242
|
+
* the cut, and the plugin hides that row even when its anchor sits outside
|
|
243
|
+
* the numeric range. A failed or still-running command stays visible.
|
|
244
|
+
*/
|
|
245
|
+
function commandHidden(node) {
|
|
246
|
+
const command = commandOf(node);
|
|
247
|
+
if (command === void 0 || !isRewindCommand(command)) return false;
|
|
248
|
+
if (isPreviewCommand(command) || isCandidateCommand(command)) return true;
|
|
249
|
+
const outcome = asRecord$1(command.outcome);
|
|
250
|
+
return outcome?.kind === "success" && safeSeq(outcome.sourceEventSeq) !== void 0;
|
|
251
|
+
}
|
|
252
|
+
/** True when the row's own anchor falls in a cut, or the row is a rewind command to hide. */
|
|
253
|
+
function anchorWithdrawn(node, cuts) {
|
|
254
|
+
if (commandHidden(node)) return true;
|
|
255
|
+
const seq = anchorSeqOf(node);
|
|
256
|
+
return seq !== void 0 && cutContains(cuts, seq);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Turns whose process and tail rows must leave.
|
|
260
|
+
*
|
|
261
|
+
* The host opens a turn before its user message is logged and anchors
|
|
262
|
+
* `turn-process` at `controlAnchorSeq - 0.1`, below the first withdrawn
|
|
263
|
+
* event, and `turn-tail` at `turn.end.seq + 0.1`, which can sit past the
|
|
264
|
+
* marker. Containment therefore misses those two rows, and the transcript
|
|
265
|
+
* kept announcing `执行过程 / 本轮已停止,已生成的内容仍保留。`
|
|
266
|
+
*
|
|
267
|
+
* A summary leaves only when every content row of its turn is already
|
|
268
|
+
* withdrawn — the same rule as the plugin's `deriveTurnProcess`. One content
|
|
269
|
+
* row before the target (a mid-turn steering rewind) keeps the summary and
|
|
270
|
+
* that earlier message. A turn with no content rows is left alone.
|
|
271
|
+
*/
|
|
272
|
+
function summaryTurns(chat, cuts) {
|
|
273
|
+
const stays = /* @__PURE__ */ new Map();
|
|
274
|
+
for (const key of chat.order) {
|
|
275
|
+
const node = chat.nodes.get(key);
|
|
276
|
+
if (node === void 0 || TURN_SUMMARY_KINDS.has(node.kind ?? "")) continue;
|
|
277
|
+
const id = turnIdOf(node);
|
|
278
|
+
if (id === void 0) continue;
|
|
279
|
+
const visible = node.visibility !== "hidden" && !anchorWithdrawn(node, cuts);
|
|
280
|
+
stays.set(id, (stays.get(id) ?? false) || visible);
|
|
281
|
+
}
|
|
282
|
+
const withdrawn = /* @__PURE__ */ new Set();
|
|
283
|
+
for (const [id, visible] of stays) if (!visible) withdrawn.add(id);
|
|
284
|
+
return withdrawn;
|
|
285
|
+
}
|
|
286
|
+
/** True when this row is a summary of a turn whose content is fully withdrawn. */
|
|
287
|
+
function summaryWithdrawn(node, summaries) {
|
|
288
|
+
if (!TURN_SUMMARY_KINDS.has(node.kind ?? "")) return false;
|
|
289
|
+
const id = turnIdOf(node);
|
|
290
|
+
return id !== void 0 && summaries.has(id);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The shadow ranges a session's executed rewinds produced, newest state last.
|
|
294
|
+
* An executed rewind cuts `[target, marker]` — the target itself is included,
|
|
295
|
+
* because a rewind restores the state *before* that message was sent (its text
|
|
296
|
+
* goes back to the composer).
|
|
297
|
+
*/
|
|
298
|
+
function rewindCutSpans(chat) {
|
|
299
|
+
if (chat === void 0) return [];
|
|
300
|
+
const spans = [];
|
|
301
|
+
for (const key of chat.order) {
|
|
302
|
+
const node = chat.nodes.get(key);
|
|
303
|
+
if (node === void 0) continue;
|
|
304
|
+
const command = commandOf(node);
|
|
305
|
+
if (command === void 0 || !isRewindCommand(command)) continue;
|
|
306
|
+
if (isPreviewCommand(command) || isCandidateCommand(command)) continue;
|
|
307
|
+
const outcome = asRecord$1(command.outcome);
|
|
308
|
+
if (outcome?.kind !== "success") continue;
|
|
309
|
+
const marker = safeSeq(outcome.sourceEventSeq);
|
|
310
|
+
if (marker === void 0) continue;
|
|
311
|
+
const target = rewindTargetOfArgs(command.args);
|
|
312
|
+
if (target === void 0 || target > marker) continue;
|
|
313
|
+
spans.push({
|
|
314
|
+
start: target,
|
|
315
|
+
end: marker
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
return coalesceCutSpans(spans);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* The chat keys the Reader should render, in snapshot order: withdrawn rows and
|
|
322
|
+
* rows the host itself marked hidden are dropped, everything else keeps its
|
|
323
|
+
* position. Returns the snapshot's own `order` array when nothing is filtered,
|
|
324
|
+
* so React selectors see a stable reference.
|
|
325
|
+
*/
|
|
326
|
+
function visibleChatKeys(chat) {
|
|
327
|
+
const cuts = rewindCutSpans(chat);
|
|
328
|
+
const summaries = summaryTurns(chat, cuts);
|
|
329
|
+
const visible = [];
|
|
330
|
+
for (const key of chat.order) {
|
|
331
|
+
const node = chat.nodes.get(key);
|
|
332
|
+
if (node === void 0) continue;
|
|
333
|
+
if (node.visibility === "hidden") continue;
|
|
334
|
+
if (anchorWithdrawn(node, cuts) || summaryWithdrawn(node, summaries)) continue;
|
|
335
|
+
visible.push(key);
|
|
336
|
+
}
|
|
337
|
+
return visible.length === chat.order.length ? chat.order : visible;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* A comparable signal for the visible row set, built for
|
|
341
|
+
* `useSyncExternalStore`-style subscription: the host re-runs a chat selector
|
|
342
|
+
* on every publish and compares the RESULT by `Object.is`, and a rewind
|
|
343
|
+
* publishes an in-place upsert of an existing command row. The snapshot's
|
|
344
|
+
* `order` array and node store are therefore both reference-stable across a
|
|
345
|
+
* rewind, so a selector on them never re-renders; a string does change exactly
|
|
346
|
+
* when the visible set does. Never return the array itself from a selector —
|
|
347
|
+
* a fresh array fails the `Object.is` check on every publish.
|
|
348
|
+
*/
|
|
349
|
+
function visibleChatSignature(chat) {
|
|
350
|
+
return visibleChatKeys(chat).join("\0");
|
|
351
|
+
}
|
|
352
|
+
//#endregion
|
|
112
353
|
//#region src/client/tool-activity.ts
|
|
113
|
-
/**
|
|
114
|
-
|
|
354
|
+
/**
|
|
355
|
+
* callId of a tool-call chat node. Drafts for a call whose node was cut must
|
|
356
|
+
* not be reintroduced after `group.keys` has already dropped that node.
|
|
357
|
+
*/
|
|
358
|
+
function toolCallId(node) {
|
|
359
|
+
const callId = node.data?.root?.callId;
|
|
360
|
+
return typeof callId === "string" && callId.length > 0 ? callId : void 0;
|
|
361
|
+
}
|
|
362
|
+
/** callIds whose tool-call node sits inside a rewind cut. */
|
|
363
|
+
function cutToolCallIds(order, get, spans) {
|
|
364
|
+
const ids = /* @__PURE__ */ new Set();
|
|
365
|
+
for (const key of order) {
|
|
366
|
+
const node = get(key);
|
|
367
|
+
if (node?.kind !== "tool-call") continue;
|
|
368
|
+
const seq = anchorSeqOf(node);
|
|
369
|
+
if (seq === void 0 || !cutContains(spans, seq)) continue;
|
|
370
|
+
const callId = toolCallId(node);
|
|
371
|
+
if (callId !== void 0) ids.add(callId);
|
|
372
|
+
}
|
|
373
|
+
return ids;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Public Step data includes tool-only model output before a chat node exists.
|
|
377
|
+
*
|
|
378
|
+
* `sourceOrder` is the unfiltered chat order. Drafts that belong to a cut step,
|
|
379
|
+
* or to a call whose tool-call node was cut, are not put back. A draft that
|
|
380
|
+
* still has no tool-call node, on a step outside the cut, stays — that is the
|
|
381
|
+
* in-flight call the host has not published a node for yet.
|
|
382
|
+
*/
|
|
383
|
+
function readerFlow(group, turn, get, sourceOrder) {
|
|
115
384
|
const flow = [];
|
|
116
385
|
const calls = /* @__PURE__ */ new Map();
|
|
117
386
|
const assistantOrder = /* @__PURE__ */ new Map();
|
|
387
|
+
const spans = sourceOrder === void 0 ? [] : rewindCutSpans({
|
|
388
|
+
order: sourceOrder,
|
|
389
|
+
nodes: { get }
|
|
390
|
+
});
|
|
391
|
+
const cutCalls = spans.length === 0 || sourceOrder === void 0 ? void 0 : cutToolCallIds(sourceOrder, get, spans);
|
|
118
392
|
for (const key of group.keys) {
|
|
119
393
|
const node = get(key);
|
|
120
394
|
if (!node || node.visibility === "hidden") continue;
|
|
@@ -141,10 +415,13 @@ window.__ModuleLoader__.load({
|
|
|
141
415
|
}
|
|
142
416
|
for (const step of turn?.steps ?? []) {
|
|
143
417
|
const data = step.data.get("assistant-step");
|
|
418
|
+
const stepSeq = step.start?.seq;
|
|
419
|
+
const stepCut = typeof stepSeq === "number" && spans.length > 0 && cutContains(spans, stepSeq);
|
|
144
420
|
let index = 0;
|
|
145
421
|
for (const draft of data?.blocks ?? []) {
|
|
146
422
|
if (draft.kind !== "tool-call" || !draft.callId) continue;
|
|
147
423
|
const previous = calls.get(draft.callId);
|
|
424
|
+
if (!previous && (stepCut || cutCalls?.has(draft.callId) === true)) continue;
|
|
148
425
|
calls.set(draft.callId, previous ? {
|
|
149
426
|
...previous,
|
|
150
427
|
draft
|
|
@@ -169,9 +446,12 @@ window.__ModuleLoader__.load({
|
|
|
169
446
|
}
|
|
170
447
|
/** Read only top-level JSON string values, including an unfinished final string.
|
|
171
448
|
* This never executes input or mistakes escaped/nested content for a path field. */
|
|
172
|
-
function
|
|
449
|
+
function parseInputFields(raw) {
|
|
173
450
|
try {
|
|
174
|
-
return
|
|
451
|
+
return {
|
|
452
|
+
kind: "complete",
|
|
453
|
+
fields: objectValue(JSON.parse(raw)) ?? {}
|
|
454
|
+
};
|
|
175
455
|
} catch {}
|
|
176
456
|
const fields = Object.create(null);
|
|
177
457
|
const prefix = raw.slice(0, 262144);
|
|
@@ -225,13 +505,20 @@ window.__ModuleLoader__.load({
|
|
|
225
505
|
key = void 0;
|
|
226
506
|
}
|
|
227
507
|
}
|
|
228
|
-
return
|
|
508
|
+
return {
|
|
509
|
+
kind: "partial",
|
|
510
|
+
fields
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function inputFields(raw) {
|
|
514
|
+
return parseInputFields(raw).fields;
|
|
229
515
|
}
|
|
516
|
+
/** Name and raw arguments of any call block, whether it has landed or is pending. */
|
|
230
517
|
function toolIdentity(entry) {
|
|
231
518
|
const block = entry.block;
|
|
232
519
|
return {
|
|
233
520
|
name: block ? "kind" in block ? block.call?.name ?? entry.draft?.name ?? "工具调用" : block.name : entry.draft?.name ?? "工具调用",
|
|
234
|
-
raw: block ? "kind" in block ? block.call?.argsRaw ?? entry.draft?.argsRaw ?? "" : "argsRaw" in block ? block.argsRaw : "" : entry.draft?.argsRaw ?? ""
|
|
521
|
+
raw: block ? "kind" in block ? block.call?.argsRaw ?? entry.draft?.argsRaw ?? "" : "argsRaw" in block ? block.argsRaw : entry.draft?.argsRaw ?? "" : entry.draft?.argsRaw ?? ""
|
|
235
522
|
};
|
|
236
523
|
}
|
|
237
524
|
/** Name and raw arguments of any call block, whether it has landed or is pending. */
|
|
@@ -364,7 +651,7 @@ window.__ModuleLoader__.load({
|
|
|
364
651
|
}
|
|
365
652
|
function activityPhase(entry, turnClosed = false) {
|
|
366
653
|
if (!entry.block) return turnClosed ? "interrupted" : "preparing";
|
|
367
|
-
if (!("kind" in entry.block)) return turnClosed ? "interrupted" : "running";
|
|
654
|
+
if (!("kind" in entry.block)) return turnClosed ? "interrupted" : entry.block.phase === "preparing" ? "preparing" : "running";
|
|
368
655
|
if (entry.block.error?.code === "ABORTED" || entry.block.error?.code === "interrupted") return "interrupted";
|
|
369
656
|
const facts = executionFacts(entry.block);
|
|
370
657
|
if (entry.block.isError || facts.signal || facts.exitCode !== void 0 && facts.exitCode !== 0 || entry.block.subCalls.some((block) => activityPhase({ block }, turnClosed) === "failed")) return "failed";
|
|
@@ -411,18 +698,21 @@ window.__ModuleLoader__.load({
|
|
|
411
698
|
}
|
|
412
699
|
function activitySummary(entry) {
|
|
413
700
|
const { name, raw } = toolIdentity(entry);
|
|
414
|
-
const
|
|
701
|
+
const parsed = parseInputFields(raw);
|
|
702
|
+
const args = parsed.fields;
|
|
415
703
|
const target = stringValue(args, "file_path", "path", "filename", "filePath");
|
|
416
704
|
const command = stringValue(args, "command", "cmd", "script");
|
|
417
705
|
const description = stringValue(args, "description");
|
|
418
706
|
const file = target?.split(/[/\\]/).at(-1);
|
|
419
707
|
const category = /^(write|edit|apply_patch|patch|str_replace_editor)$/.test(name) ? "write" : /^(read|read_file)$/.test(name) ? "read" : /^(bash|shell|terminal|terminal_send|exec_command|pwsh)$/.test(name) ? "terminal" : /^(grep|glob|find|search)$/.test(name) ? "search" : /^(web_search|web_fetch|web_open)$/.test(name) ? "web" : /^(run_code|execute_code|code_interpreter|python|node|eval|repl)$/.test(name) ? "code" : "other";
|
|
708
|
+
const title = category === "write" ? `${name === "write" ? "写入" : "修改"}${file ? ` ${file}` : name === "apply_patch" ? "代码补丁" : "文件"}` : category === "read" ? `读取${file ? ` ${file}` : "文件"}` : category === "terminal" ? description || "运行命令" : category === "search" ? name === "glob" ? "查找文件" : "搜索内容" : category === "web" ? name === "web_search" ? "搜索网页" : "读取网页" : category === "code" ? description || "运行代码" : name;
|
|
420
709
|
return {
|
|
421
710
|
name,
|
|
422
711
|
raw,
|
|
423
712
|
args,
|
|
713
|
+
argsState: parsed.kind,
|
|
424
714
|
category,
|
|
425
|
-
title
|
|
715
|
+
title,
|
|
426
716
|
target: target ?? command ?? stringValue(args, "query", "pattern", "url"),
|
|
427
717
|
command,
|
|
428
718
|
cwd: stringValue(args, "workdir", "cwd"),
|
|
@@ -444,6 +734,7 @@ window.__ModuleLoader__.load({
|
|
|
444
734
|
function dirname(path) {
|
|
445
735
|
const normalized = path.replace(/[/\\]+$/, "");
|
|
446
736
|
const at = Math.max(normalized.lastIndexOf("/"), normalized.lastIndexOf("\\"));
|
|
737
|
+
if (at === 0 || at === 2 && /^[A-Za-z]:/.test(normalized)) return normalized.slice(0, at + 1);
|
|
447
738
|
return at === -1 ? "." : normalized.slice(0, at) || ".";
|
|
448
739
|
}
|
|
449
740
|
/**
|
|
@@ -523,6 +814,35 @@ window.__ModuleLoader__.load({
|
|
|
523
814
|
} };
|
|
524
815
|
}
|
|
525
816
|
//#endregion
|
|
817
|
+
//#region src/workspace-path.ts
|
|
818
|
+
/** Absolute paths accepted by both POSIX and Windows hosts. */
|
|
819
|
+
function isAbsoluteWorkspacePath(path) {
|
|
820
|
+
return /^(?:\/|[A-Za-z]:[/\\]|\\\\)/.test(path);
|
|
821
|
+
}
|
|
822
|
+
//#endregion
|
|
823
|
+
//#region src/client/styles.ts
|
|
824
|
+
const plugin = "dsh-better-display";
|
|
825
|
+
const styles$1 = /* @__PURE__ */ new Map();
|
|
826
|
+
/** Retain injected CSS across host cleanup and restore it before Reader paints. */
|
|
827
|
+
function ensureStyles() {
|
|
828
|
+
if (typeof document === "undefined") return;
|
|
829
|
+
const live = /* @__PURE__ */ new Set();
|
|
830
|
+
for (const tag of document.querySelectorAll(`style[data-plugin="${plugin}"][data-plugin-css]`)) {
|
|
831
|
+
const id = tag.dataset.pluginCss;
|
|
832
|
+
if (id === void 0) continue;
|
|
833
|
+
styles$1.set(id, tag.textContent ?? "");
|
|
834
|
+
live.add(id);
|
|
835
|
+
}
|
|
836
|
+
for (const [id, text] of styles$1) {
|
|
837
|
+
if (live.has(id)) continue;
|
|
838
|
+
const tag = document.createElement("style");
|
|
839
|
+
tag.dataset.plugin = plugin;
|
|
840
|
+
tag.dataset.pluginCss = id;
|
|
841
|
+
tag.textContent = text;
|
|
842
|
+
document.head.appendChild(tag);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
//#endregion
|
|
526
846
|
//#region src/client/mcp-app.ts
|
|
527
847
|
/**
|
|
528
848
|
* Core pure functions for SEP-1865 / MCP Apps integration.
|
|
@@ -765,7 +1085,7 @@ ${trimmed}
|
|
|
765
1085
|
}
|
|
766
1086
|
//#endregion
|
|
767
1087
|
//#region \0dshx-css-module:McpAppFrame.module.css.mjs
|
|
768
|
-
const css$7 = ".tyd90a_card{border:1px solid var(--dsw-alias-border-l2,#00000014);background:var(--dsw-alias-bg-module-platform,transparent);border-radius:14px;margin:16px 0;transition:border-color .2s cubic-bezier(.22,1,.36,1),box-shadow .2s cubic-bezier(.22,1,.36,1);position:relative;overflow:hidden}.tyd90a_card:hover{border-color:var(--dsw-alias-border-l1,#00000029);box-shadow:0 2px 10px -2px #0000000a}.tyd90a_header{border-bottom:1px solid var(--dsw-alias-border-l2,#0000000f);background:var(--dsw-alias-interactive-bg-hover,#00000004);user-select:none;justify-content:space-between;align-items:center;height:36px;padding:0 14px;display:flex}.tyd90a_titleArea{align-items:center;gap:7px;min-width:0;display:flex}.tyd90a_icon{color:var(--dsw-alias-label-tertiary,#94a3b8);flex-shrink:0;justify-content:center;align-items:center;display:flex}.tyd90a_title{color:var(--dsw-alias-label-secondary,#64748b);letter-spacing:-.01em;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;overflow:hidden}.tyd90a_actions{align-items:center;gap:4px;display:flex}.tyd90a_iconBtn{width:24px;height:24px;color:var(--dsw-alias-label-tertiary,#94a3b8);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;transition:all .15s;display:inline-flex}.tyd90a_iconBtn:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000f);color:var(--dsw-alias-label-primary,#0f172a)}.tyd90a_iconBtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#2563eb);outline-offset:1px}.tyd90a_iframeWrapper{background:0 0;width:100%;transition:height .25s cubic-bezier(.22,1,.36,1);position:relative}.tyd90a_iframe{background:0 0;border:none;width:100%;height:100%;display:block}.tyd90a_receipt{background:var(--dsw-alias-interactive-bg-hover,#22c55e0d);border-top:1px solid var(--dsw-alias-border-l2,#0000000f);color:var(--dsw-alias-label-primary,#0f172a);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;padding:8px 14px;font-size:12px;line-height:18px;animation:.2s cubic-bezier(.22,1,.36,1) tyd90a_slideUp;display:flex}.tyd90a_receiptPrompt{color:var(--dsw-alias-label-secondary,#64748b);background:var(--dsw-alias-bg-base,#00000008);border:1px solid var(--dsw-alias-border-l2,#0000000f);user-select:text;cursor:text;overflow-wrap:anywhere;border-radius:6px;flex:100%;padding:6px 10px;font-size:12px;line-height:18px}@keyframes tyd90a_slideUp{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.tyd90a_receiptSummary{color:var(--dsw-alias-state-business-primary,#16a34a);text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:6px;font-weight:500;display:flex;overflow:hidden}.tyd90a_receiptHint{align-items:center;gap:6px;display:flex}.tyd90a_sendKbd{color:var(--dsw-alias-label-tertiary,#94a3b8);background:var(--dsw-alias-bg-base,#0000000a);border:1px solid var(--dsw-alias-border-l2,#00000014);cursor:pointer;border-radius:5px;align-items:center;gap:4px;padding:2px 8px;font-family:inherit;font-size:11px;transition:all .15s;display:inline-flex}.tyd90a_sendKbd:hover{background:var(--dsw-alias-interactive-bg-hover,#00000014);color:var(--dsw-alias-label-primary,#0f172a)}.tyd90a_sendKbd:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#2563eb);outline-offset:1px}.tyd90a_streamingPlaceholder{border:1px dashed var(--dsw-alias-border-l2,#0000001f);background:var(--dsw-alias-interactive-bg-hover,#00000004);color:var(--dsw-alias-label-secondary,#64748b);border-radius:14px;align-items:center;gap:10px;margin:16px 0;padding:16px 18px;font-size:13px;display:flex}.tyd90a_pulseDot{background:var(--dsw-alias-state-business-primary,#2563eb);border-radius:50%;width:7px;height:7px;animation:1.5s ease-in-out infinite tyd90a_pulse}@keyframes tyd90a_pulse{0%,to{opacity:.35;transform:scale(.9)}50%{opacity:1;transform:scale(1.15)}}";
|
|
1088
|
+
const css$7 = ".tyd90a_card{border:1px solid var(--dsw-alias-border-l2,#00000014);background:var(--dsw-alias-bg-module-platform,transparent);border-radius:14px;margin:16px 0;transition:border-color .2s cubic-bezier(.22,1,.36,1),box-shadow .2s cubic-bezier(.22,1,.36,1);position:relative;overflow:hidden}.tyd90a_card:hover{border-color:var(--dsw-alias-border-l1,#00000029);box-shadow:0 2px 10px -2px #0000000a}.tyd90a_header{border-bottom:1px solid var(--dsw-alias-border-l2,#0000000f);background:var(--dsw-alias-interactive-bg-hover,#00000004);-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;height:36px;padding:0 14px;display:flex}.tyd90a_titleArea{align-items:center;gap:7px;min-width:0;display:flex}.tyd90a_icon{color:var(--dsw-alias-label-tertiary,#94a3b8);flex-shrink:0;justify-content:center;align-items:center;display:flex}.tyd90a_title{color:var(--dsw-alias-label-secondary,#64748b);letter-spacing:-.01em;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;overflow:hidden}.tyd90a_actions{align-items:center;gap:4px;display:flex}.tyd90a_iconBtn{width:24px;height:24px;color:var(--dsw-alias-label-tertiary,#94a3b8);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;transition:all .15s;display:inline-flex}.tyd90a_iconBtn:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000f);color:var(--dsw-alias-label-primary,#0f172a)}.tyd90a_iconBtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#2563eb);outline-offset:1px}.tyd90a_iframeWrapper{background:0 0;width:100%;transition:height .25s cubic-bezier(.22,1,.36,1);position:relative}.tyd90a_iframe{background:0 0;border:none;width:100%;height:100%;display:block}.tyd90a_receipt{background:var(--dsw-alias-interactive-bg-hover,#22c55e0d);border-top:1px solid var(--dsw-alias-border-l2,#0000000f);color:var(--dsw-alias-label-primary,#0f172a);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;padding:8px 14px;font-size:12px;line-height:18px;animation:.2s cubic-bezier(.22,1,.36,1) tyd90a_slideUp;display:flex}.tyd90a_receiptPrompt{color:var(--dsw-alias-label-secondary,#64748b);background:var(--dsw-alias-bg-base,#00000008);border:1px solid var(--dsw-alias-border-l2,#0000000f);-webkit-user-select:text;user-select:text;cursor:text;overflow-wrap:anywhere;border-radius:6px;flex:100%;padding:6px 10px;font-size:12px;line-height:18px}@keyframes tyd90a_slideUp{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.tyd90a_receiptSummary{color:var(--dsw-alias-state-business-primary,#16a34a);text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:6px;font-weight:500;display:flex;overflow:hidden}.tyd90a_receiptHint{align-items:center;gap:6px;display:flex}.tyd90a_sendKbd{color:var(--dsw-alias-label-tertiary,#94a3b8);background:var(--dsw-alias-bg-base,#0000000a);border:1px solid var(--dsw-alias-border-l2,#00000014);cursor:pointer;border-radius:5px;align-items:center;gap:4px;padding:2px 8px;font-family:inherit;font-size:11px;transition:all .15s;display:inline-flex}.tyd90a_sendKbd:hover{background:var(--dsw-alias-interactive-bg-hover,#00000014);color:var(--dsw-alias-label-primary,#0f172a)}.tyd90a_sendKbd:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#2563eb);outline-offset:1px}.tyd90a_streamingPlaceholder{border:1px dashed var(--dsw-alias-border-l2,#0000001f);background:var(--dsw-alias-interactive-bg-hover,#00000004);color:var(--dsw-alias-label-secondary,#64748b);border-radius:14px;align-items:center;gap:10px;margin:16px 0;padding:16px 18px;font-size:13px;display:flex}.tyd90a_pulseDot{background:var(--dsw-alias-state-business-primary,#2563eb);border-radius:50%;width:7px;height:7px;animation:1.5s ease-in-out infinite tyd90a_pulse}@keyframes tyd90a_pulse{0%,to{opacity:.35;transform:scale(.9)}50%{opacity:1;transform:scale(1.15)}}";
|
|
769
1089
|
const tagId$7 = "dsh-better-display/McpAppFrame.module.css";
|
|
770
1090
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$7) + "]") === null) {
|
|
771
1091
|
const tag = document.createElement("style");
|
|
@@ -806,7 +1126,6 @@ ${trimmed}
|
|
|
806
1126
|
const iframeRef = (0, react.useRef)(null);
|
|
807
1127
|
const lastParamsRef = (0, react.useRef)({});
|
|
808
1128
|
const [height, setHeight] = (0, react.useState)(() => Math.max(60, Math.min(2400, initialHeight)));
|
|
809
|
-
const [ready, setReady] = (0, react.useState)(false);
|
|
810
1129
|
const [receipt, setReceipt] = (0, react.useState)(null);
|
|
811
1130
|
const [lastPrompt, setLastPrompt] = (0, react.useState)(null);
|
|
812
1131
|
const [reloadNonce, setReloadNonce] = (0, react.useState)(0);
|
|
@@ -829,7 +1148,7 @@ ${trimmed}
|
|
|
829
1148
|
}, [title, writeComposer]);
|
|
830
1149
|
const handleUserSubmit = (0, react.useCallback)((params) => {
|
|
831
1150
|
lastParamsRef.current = params;
|
|
832
|
-
let summary
|
|
1151
|
+
let summary;
|
|
833
1152
|
if (typeof params.choice === "string") {
|
|
834
1153
|
const desc = typeof params.desc === "string" ? ` (${params.desc})` : "";
|
|
835
1154
|
summary = `选择: ${params.choice}${desc}`;
|
|
@@ -861,13 +1180,9 @@ ${trimmed}
|
|
|
861
1180
|
}
|
|
862
1181
|
};
|
|
863
1182
|
iframe.contentWindow?.postMessage(response, "*");
|
|
864
|
-
setReady(true);
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
if (data.method === "ui/ready" || data.method === "ui/notifications/initialized") {
|
|
868
|
-
setReady(true);
|
|
869
1183
|
return;
|
|
870
1184
|
}
|
|
1185
|
+
if (data.method === "ui/ready" || data.method === "ui/notifications/initialized") return;
|
|
871
1186
|
if (data.method === "ui/resize" && data.params?.height) {
|
|
872
1187
|
const h = Number(data.params.height);
|
|
873
1188
|
if (Number.isFinite(h) && h > 0) setHeight(Math.max(60, Math.min(2400, Math.round(h))));
|
|
@@ -935,11 +1250,9 @@ ${trimmed}
|
|
|
935
1250
|
styles: { variables: cssTokens }
|
|
936
1251
|
}
|
|
937
1252
|
}, "*");
|
|
938
|
-
setReady(true);
|
|
939
1253
|
}, []);
|
|
940
1254
|
const handleReload = (0, react.useCallback)(() => {
|
|
941
1255
|
setReloadNonce((n) => n + 1);
|
|
942
|
-
setReady(false);
|
|
943
1256
|
setReceipt(null);
|
|
944
1257
|
}, []);
|
|
945
1258
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -10383,7 +10696,7 @@ ${trimmed}
|
|
|
10383
10696
|
return count;
|
|
10384
10697
|
}
|
|
10385
10698
|
//#endregion
|
|
10386
|
-
//#region node_modules/escape-string-regexp/index.js
|
|
10699
|
+
//#region node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp/index.js
|
|
10387
10700
|
function escapeStringRegexp(string) {
|
|
10388
10701
|
if (typeof string !== "string") throw new TypeError("Expected a string");
|
|
10389
10702
|
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
@@ -41815,7 +42128,7 @@ ${trimmed}
|
|
|
41815
42128
|
}
|
|
41816
42129
|
//#endregion
|
|
41817
42130
|
//#region \0dshx-css-module:MarkdownText.module.css.mjs
|
|
41818
|
-
const css$6 = ".zfLqdW_markdown{overflow-wrap:anywhere;min-width:0;font:var(--dsw-font-markdown-base);color:var(--dsw-alias-label-primary)}.zfLqdW_markdown strong{font-weight:600}.zfLqdW_markdown h1{font:var(--dsw-font-markdown-h1);margin:32px 0 16px}.zfLqdW_markdown h2{font:var(--dsw-font-markdown-h2);margin:32px 0 16px}.zfLqdW_markdown h3{font:var(--dsw-font-markdown-h3);margin:32px 0 16px}.zfLqdW_markdown h4{font:var(--dsw-font-markdown-h4);margin:16px 0}.zfLqdW_markdown :where(h5,h6){font:var(--dsw-font-markdown-base-strong);margin:16px 0}.zfLqdW_markdown :where(h1,h2,h3,h4,h5,h6) strong{font-weight:inherit}.zfLqdW_markdown p{margin:16px 0}.zfLqdW_markdown :where(h4,h5,h6)+:where(ul,ol){margin-top:8px}.zfLqdW_markdown :where(h4,h5,h6):has(+:where(ul,ol)){margin-bottom:8px}.zfLqdW_markdown a{color:var(--dsw-alias-state-business-primary);transition:box-shadow var(--ds-transition-duration) var(--ds-ease-in-out);border:2px solid #fff0;border-width:2px 3px;margin-left:-3px;margin-right:-3px;text-decoration:none;position:relative}.zfLqdW_markdown a:hover,.zfLqdW_markdown a:focus{text-decoration:underline var(--dsw-alias-state-business-primary);outline:none}.zfLqdW_markdown a:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-state-business-primary)}.zfLqdW_markdown :where(ul,ol){margin:16px 0;padding-left:18px}.zfLqdW_markdown li:not(:first-child){margin-top:6px}.zfLqdW_markdown li>:where(ul,ol){margin-top:4px}.zfLqdW_markdown li::marker{color:var(--dsw-alias-label-secondary);line-height:28px}.zfLqdW_markdown :where(ul,ol) ol{padding-left:0;list-style-position:inside}.zfLqdW_markdown :where(ul,ol) ol li p{display:inline}.zfLqdW_markdown li>p{margin:8px 0}.zfLqdW_markdown li>:first-child{margin-top:0}.zfLqdW_markdown li>:last-child:not(.md-code-block){margin-bottom:0}.zfLqdW_markdown hr{background:var(--dsw-alias-border-l2);border:none;height:1px;margin:32px 0;display:block}.zfLqdW_markdown blockquote{border-left:2px solid var(--dsw-alias-label-caption);margin:16px 0 0;padding-left:14px}.zfLqdW_markdown pre{font-family:var(--ds-font-family-code);margin:16px 0;overflow:auto}.zfLqdW_markdown :not(pre)>code{box-sizing:border-box;font:var(--dsw-font-markdown-code);font-family:var(--ds-font-family-code);background-color:var(--dsw-alias-markdown-inline-code);border-radius:6px;align-items:center;padding:0 5px;display:inline-flex;font-size:.875em!important}.zfLqdW_markdown :where(h1,h2,h3,h4,h5,h6) code{font:inherit;font-family:var(--ds-font-family-code)}.zfLqdW_markdown .katex-display{max-width:100%;overflow:auto hidden}.zfLqdW_markdown input[type=checkbox]{accent-color:var(--dsw-alias-label-secondary);margin:0 8px 0 0}.zfLqdW_tableScroll{overscroll-behavior-x:contain;max-width:100%;overflow-x:auto}.zfLqdW_tableScroll.md-table-wide{padding-bottom:var(--dsh-scrollbar-width,8px);overflow-x:hidden}.zfLqdW_tableScroll.md-table-wide:hover,.zfLqdW_tableScroll.md-table-wide:focus-visible{padding-bottom:0;overflow-x:auto}.zfLqdW_tableScroll:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-state-business-primary);outline:none}.zfLqdW_tableScroll table{border-collapse:collapse;width:max-content;max-width:max-content}.zfLqdW_tableFill table{width:100%;max-width:none}.zfLqdW_tableScroll th{text-align:start;border-bottom:1px solid var(--dsw-alias-border-l3);font:var(--dsw-font-markdown-table-head);border-top:none;min-width:100px;max-width:min(30vw,320px);padding:10px 16px}.zfLqdW_tableScroll td{border-bottom:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-markdown-table);min-width:100px;max-width:min(30vw,320px);padding:10px 16px}.zfLqdW_tableScroll th:first-child,.zfLqdW_tableScroll td:first-child{padding-left:0}.zfLqdW_tableScroll td:last-child{padding-right:0}.zfLqdW_tableScroll table code{font-size:13px}.zfLqdW_markdown>:first-child,.zfLqdW_markdown p:first-child{margin-top:0!important}.zfLqdW_markdown>:last-child,.zfLqdW_markdown p:last-child{margin-bottom:0!important}.zfLqdW_imageAlt{color:var(--dsw-alias-label-tertiary);font-style:italic}.zfLqdW_image{background:var(--dsw-alias-bg-base);object-fit:contain;border-radius:8px;width:auto;max-width:100%;height:auto;margin:0;display:block}.zfLqdW_fileMention{font:inherit;color:var(--dsw-alias-state-business-primary);cursor:pointer;background:0 0;border:none;margin:0;padding:0;text-decoration:none}.zfLqdW_fileMention:hover,.zfLqdW_fileMention:focus{text-decoration:underline var(--dsw-alias-state-business-primary);text-underline-offset:3px;outline:none}";
|
|
42131
|
+
const css$6 = ".zfLqdW_markdown{overflow-wrap:anywhere;min-width:0;font:var(--dsw-font-markdown-base);color:var(--dsw-alias-label-primary)}.zfLqdW_markdown strong{font-weight:600}.zfLqdW_markdown h1{font:var(--dsw-font-markdown-h1);margin:32px 0 16px}.zfLqdW_markdown h2{font:var(--dsw-font-markdown-h2);margin:32px 0 16px}.zfLqdW_markdown h3{font:var(--dsw-font-markdown-h3);margin:32px 0 16px}.zfLqdW_markdown h4{font:var(--dsw-font-markdown-h4);margin:16px 0}.zfLqdW_markdown :where(h5,h6){font:var(--dsw-font-markdown-base-strong);margin:16px 0}.zfLqdW_markdown :where(h1,h2,h3,h4,h5,h6) strong{font-weight:inherit}.zfLqdW_markdown p{margin:16px 0}.zfLqdW_markdown :where(h4,h5,h6)+:where(ul,ol){margin-top:8px}.zfLqdW_markdown :where(h4,h5,h6):has(+:where(ul,ol)){margin-bottom:8px}.zfLqdW_markdown a{color:var(--dsw-alias-state-business-primary);transition:box-shadow var(--ds-transition-duration) var(--ds-ease-in-out);border:2px solid #fff0;border-width:2px 3px;margin-left:-3px;margin-right:-3px;text-decoration:none;position:relative}.zfLqdW_markdown a:hover,.zfLqdW_markdown a:focus{-webkit-text-decoration:underline var(--dsw-alias-state-business-primary);text-decoration:underline var(--dsw-alias-state-business-primary);outline:none}.zfLqdW_markdown a:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-state-business-primary)}.zfLqdW_markdown :where(ul,ol){margin:16px 0;padding-left:18px}.zfLqdW_markdown li:not(:first-child){margin-top:6px}.zfLqdW_markdown li>:where(ul,ol){margin-top:4px}.zfLqdW_markdown li::marker{color:var(--dsw-alias-label-secondary);line-height:28px}.zfLqdW_markdown :where(ul,ol) ol{padding-left:0;list-style-position:inside}.zfLqdW_markdown :where(ul,ol) ol li p{display:inline}.zfLqdW_markdown li>p{margin:8px 0}.zfLqdW_markdown li>:first-child{margin-top:0}.zfLqdW_markdown li>:last-child:not(.md-code-block){margin-bottom:0}.zfLqdW_markdown hr{background:var(--dsw-alias-border-l2);border:none;height:1px;margin:32px 0;display:block}.zfLqdW_markdown blockquote{border-left:2px solid var(--dsw-alias-label-caption);margin:16px 0 0;padding-left:14px}.zfLqdW_markdown pre{font-family:var(--ds-font-family-code);margin:16px 0;overflow:auto}.zfLqdW_markdown :not(pre)>code{box-sizing:border-box;font:var(--dsw-font-markdown-code);font-family:var(--ds-font-family-code);background-color:var(--dsw-alias-markdown-inline-code);border-radius:6px;align-items:center;padding:0 5px;display:inline-flex;font-size:.875em!important}.zfLqdW_markdown :where(h1,h2,h3,h4,h5,h6) code{font:inherit;font-family:var(--ds-font-family-code)}.zfLqdW_markdown .katex-display{max-width:100%;overflow:auto hidden}.zfLqdW_markdown input[type=checkbox]{accent-color:var(--dsw-alias-label-secondary);margin:0 8px 0 0}.zfLqdW_tableScroll{overscroll-behavior-x:contain;max-width:100%;overflow-x:auto}.zfLqdW_tableScroll.md-table-wide{padding-bottom:var(--dsh-scrollbar-width,8px);overflow-x:hidden}:is(.zfLqdW_tableScroll.md-table-wide:hover,.zfLqdW_tableScroll.md-table-wide:focus-visible){padding-bottom:0;overflow-x:auto}.zfLqdW_tableScroll:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-state-business-primary);outline:none}.zfLqdW_tableScroll table{border-collapse:collapse;width:max-content;max-width:max-content}.zfLqdW_tableFill table{width:100%;max-width:none}.zfLqdW_tableScroll th{text-align:start;border-bottom:1px solid var(--dsw-alias-border-l3);font:var(--dsw-font-markdown-table-head);border-top:none;min-width:100px;max-width:min(30vw,320px);padding:10px 16px}.zfLqdW_tableScroll td{border-bottom:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-markdown-table);min-width:100px;max-width:min(30vw,320px);padding:10px 16px}.zfLqdW_tableScroll th:first-child,.zfLqdW_tableScroll td:first-child{padding-left:0}.zfLqdW_tableScroll td:last-child{padding-right:0}.zfLqdW_tableScroll table code{font-size:13px}.zfLqdW_markdown>:first-child,.zfLqdW_markdown p:first-child{margin-top:0!important}.zfLqdW_markdown>:last-child,.zfLqdW_markdown p:last-child{margin-bottom:0!important}.zfLqdW_imageAlt{color:var(--dsw-alias-label-tertiary);font-style:italic}.zfLqdW_image{background:var(--dsw-alias-bg-base);object-fit:contain;border-radius:8px;width:auto;max-width:100%;height:auto;margin:0;display:block}.zfLqdW_fileMention{font:inherit;color:var(--dsw-alias-state-business-primary);cursor:pointer;background:0 0;border:none;margin:0;padding:0;text-decoration:none}.zfLqdW_fileMention:hover,.zfLqdW_fileMention:focus{-webkit-text-decoration:underline var(--dsw-alias-state-business-primary);text-decoration:underline var(--dsw-alias-state-business-primary);text-underline-offset:3px;outline:none}";
|
|
41819
42132
|
const tagId$6 = "dsh-better-display/MarkdownText.module.css";
|
|
41820
42133
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
|
|
41821
42134
|
const tag = document.createElement("style");
|
|
@@ -42423,7 +42736,7 @@ ${trimmed}
|
|
|
42423
42736
|
const readerPathImages = { resolve: (value) => typeof window === "undefined" ? void 0 : localPathMediaUrl(window.location.protocol, window.location.origin, value) };
|
|
42424
42737
|
//#endregion
|
|
42425
42738
|
//#region \0dshx-css-module:Reader.module.css.mjs
|
|
42426
|
-
const css$5 = ".gNoOdq_root{color:var(--dsw-alias-label-primary);padding:16px calc(var(--dsh-composer-side-clearance,16px) + 16px) 24px;overflow-anchor:auto;flex:none;min-width:0;font-family:inherit;font-size:16px;line-height:28px;container-type:inline-size}.gNoOdq_column{max-width:var(--dsh-chat-content-width,748px);flex-direction:column;gap:22px;width:100%;min-width:0;margin:0 auto;display:flex}.gNoOdq_toolbar{min-height:32px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-base);-webkit-backdrop-filter:blur(12px);justify-content:flex-end;align-items:center;gap:6px;padding:0;font-size:12px;display:flex;position:sticky;top:0}.gNoOdq_turnProcessSticky{background:var(--dsw-alias-bg-base);-webkit-backdrop-filter:blur(12px);align-items:center;min-height:32px;display:flex;position:sticky}.gNoOdq_turnProcessSticky .gNoOdq_disclosureButton{min-height:32px}.gNoOdq_textButton,.gNoOdq_historyButton,.gNoOdq_iconButton,.gNoOdq_jump,.gNoOdq_disclosureButton,.gNoOdq_imageOpen,.gNoOdq_dialogClose{font:inherit;cursor:pointer}.gNoOdq_textButton{color:var(--dsw-alias-label-secondary);white-space:nowrap;background:0 0;border:0;border-radius:6px;padding:2px 6px}.gNoOdq_textButton:hover,.gNoOdq_iconButton:hover,.gNoOdq_disclosureButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_root button:focus-visible,.gNoOdq_root summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px}.gNoOdq_turn{flex-direction:column;gap:14px;min-width:0;display:flex}.gNoOdq_turn+.gNoOdq_turn{margin-top:12px}.gNoOdq_userCluster{flex-direction:column;align-self:flex-end;align-items:flex-end;gap:8px;min-width:0;max-width:min(525px,82%);margin-bottom:4px;display:flex}.gNoOdq_userImages{flex-direction:column;align-items:flex-end;min-width:0;max-width:100%;display:flex}.gNoOdq_userImages .gNoOdq_imageFigure{align-self:flex-end}.gNoOdq_user{background:var(--dsw-specific-bubble);max-width:100%;color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;box-sizing:border-box;border-radius:22px;align-self:flex-end;padding:10px 16px;line-height:24px}.gNoOdq_user .gNoOdq_blocks{gap:10px}.gNoOdq_answer{overflow-wrap:anywhere;flex-direction:column;min-width:0;display:flex}.gNoOdq_readingText{min-width:0}.gNoOdq_reasonPlain{white-space:pre-wrap;overflow-wrap:anywhere;font:inherit;color:inherit}.gNoOdq_readingText button{min-width:24px;min-height:24px}.gNoOdq_streamWord{display:inline-block}.gNoOdq_streamInlineWord{display:inline}.gNoOdq_streamWord,.gNoOdq_streamInlineWord,.gNoOdq_streamAtom{opacity:1;filter:none}.gNoOdq_streamAtom{min-width:0}@media (prefers-reduced-motion:reduce){.gNoOdq_streamWord,.gNoOdq_streamInlineWord,.gNoOdq_streamAtom{opacity:1!important;filter:none!important}}.gNoOdq_retiringContent{min-width:0}.gNoOdq_retiringContent[data-reader-retiring=retiring]{overflow:hidden}.gNoOdq_mainFlow,.gNoOdq_blocks{flex-direction:column;gap:16px;min-width:0;display:flex}.gNoOdq_mainFlow:empty,.gNoOdq_blocks:empty{display:none}.gNoOdq_blocks>:first-child{margin-top:0}.gNoOdq_blocks>:last-child{margin-bottom:0}.gNoOdq_blocks .md-table-wide{max-width:100%}.gNoOdq_disclosure{min-width:0}.gNoOdq_disclosureButton{max-width:100%;min-height:32px;color:var(--dsw-alias-label-tertiary);text-align:left;background:0 0;border:0;border-radius:7px;align-items:center;gap:6px;margin-left:-6px;padding:4px 6px;font-size:14px;font-weight:400;line-height:24px;display:inline-flex}.gNoOdq_disclosure[data-reader-status-only]{align-items:center;min-height:32px;display:flex}.gNoOdq_statusText{min-width:0;max-width:100%;color:var(--dsw-alias-label-secondary);font-size:14px;font-weight:400;line-height:24px;display:inline-flex}.gNoOdq_srOnly{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.gNoOdq_think{--think-swap:.15s;--think-gap:50ms;--think-distance:8px;--think-blur:2px;--think-shimmer:2s;--think-base:var(--dsw-alias-label-secondary);--think-highlight:var(--dsw-alias-label-primary);--think-ease:ease-in-out;text-align:left;max-width:100%;display:inline-block;position:relative}.gNoOdq_thinkSizer{visibility:hidden;white-space:nowrap;display:block}.gNoOdq_thinkText{color:var(--think-base);white-space:nowrap;text-overflow:ellipsis;filter:blur();opacity:1;transition:transform var(--think-swap) var(--think-ease), filter var(--think-swap) var(--think-ease), opacity var(--think-swap) var(--think-ease);display:block;position:absolute;top:0;left:0;right:0;overflow:hidden;transform:translateY(0)}.gNoOdq_think[data-reader-status-phase=running] .gNoOdq_thinkText[data-reader-status-copy=current]{transition-delay:var(--think-gap)}.gNoOdq_think:not([data-reader-status-phase=idle]) .gNoOdq_thinkText{will-change:transform, filter, opacity}@supports (background-clip:text){.gNoOdq_think[data-active=true] .gNoOdq_thinkText:before{content:attr(data-text);pointer-events:none;background-image:linear-gradient(90deg, transparent 0%, transparent 40%, var(--think-highlight) 50%, transparent 60%, transparent 100%);color:#0000;-webkit-text-fill-color:transparent;animation:gNoOdq_thinkShimmer var(--think-shimmer) linear infinite;background-repeat:no-repeat;background-size:400% 100%;-webkit-background-clip:text;background-clip:text;position:absolute;inset:0}}@keyframes gNoOdq_thinkShimmer{0%{background-position:100% 0}to{background-position:0 0}}.gNoOdq_thinkText.gNoOdq_isExit{transform:translateY(calc(var(--think-distance) * -1));filter:blur(var(--think-blur));opacity:0}.gNoOdq_thinkText.gNoOdq_isEnterStart{transform:translateY(var(--think-distance));filter:blur(var(--think-blur));opacity:0;transition:none}[data-motion=off] .gNoOdq_thinkText{filter:none!important;opacity:1!important;transition:none!important;transform:none!important}[data-motion=off] .gNoOdq_thinkText[data-reader-status-copy=outgoing],[data-motion=off] .gNoOdq_thinkText:before{display:none!important}@media (prefers-reduced-motion:reduce),(forced-colors:active){.gNoOdq_thinkText{filter:none!important;opacity:1!important;transition:none!important;transform:none!important}.gNoOdq_thinkText[data-reader-status-copy=outgoing],.gNoOdq_thinkText:before{display:none!important}}.gNoOdq_processMeta{opacity:0;grid-template-rows:0fr;transition:grid-template-rows .26s cubic-bezier(.22,1,.36,1),opacity .16s ease-out;display:grid}.gNoOdq_processMeta[data-open=true]{opacity:1;grid-template-rows:1fr}.gNoOdq_processMetaInner{min-height:0;overflow:hidden}.gNoOdq_processMetaLine{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex-wrap:wrap;align-items:baseline;gap:8px;padding:8px 0 0 16px;font-size:12px;line-height:20px;display:flex}.gNoOdq_processMetaLine .gNoOdq_meta{color:inherit}.gNoOdq_chevron{stroke:currentColor;fill:none;stroke-width:1.4px;stroke-linecap:round;stroke-linejoin:round;flex:none;transition:transform .26s cubic-bezier(.22,1,.36,1)}.gNoOdq_chevron[data-open=true]{transform:rotate(90deg)}.gNoOdq_disclosureBody{transform-origin:top;will-change:height, opacity, transform;height:0;overflow:hidden}.gNoOdq_processContents{border-left:1px solid var(--dsw-alias-border-l2);padding:3px 0 2px var(--reader-gutter,16px);margin:0 0 0 var(--reader-rail,6px);color:var(--dsw-alias-label-secondary);font-size:14px;line-height:24px;display:flow-root}.gNoOdq_processContents>:last-child{margin-bottom:0}.gNoOdq_processCommentary{color:var(--dsw-alias-label-secondary);margin:4px 0 8px var(--reader-rail,6px);padding-left:var(--reader-gutter,16px);border-left:1px solid var(--dsw-alias-border-l2);font-size:14px;line-height:24px}.gNoOdq_processFrame{min-width:0}.gNoOdq_toolActivity{min-width:0;color:var(--dsw-alias-label-secondary)}.gNoOdq_nativeToolRow{min-width:0}.gNoOdq_rowSeparator{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.gNoOdq_nativeToolSummary{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;font-size:14px;line-height:24px;overflow:hidden}.gNoOdq_nativeToolRow:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px;border-radius:4px}.gNoOdq_toolHeading{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:11px;grid-template-columns:20px minmax(0,1fr) auto;align-items:start;gap:10px;padding:10px 14px 4px;display:grid}.gNoOdq_toolHeading:hover{background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_toolHeading:focus-visible{outline-offset:-3px!important}.gNoOdq_toolGlyph{height:22px;color:var(--dsw-alias-label-secondary);justify-content:center;align-items:center;display:flex}.gNoOdq_toolHeadingCopy{flex-direction:column;gap:3px;min-width:0;display:flex}.gNoOdq_toolTitle{overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:22px}.gNoOdq_toolTarget{-webkit-line-clamp:2;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary);-webkit-box-orient:vertical;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:19px;display:-webkit-box;overflow:hidden}.gNoOdq_toolHeadingState{min-height:22px;color:var(--dsw-alias-label-secondary);align-items:center;gap:7px;display:flex}.gNoOdq_diffStat{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;flex:none;gap:6px;margin-left:8px;font-size:11px;line-height:18px;display:inline-flex}.gNoOdq_diffAdded{color:var(--dsw-alias-state-success-primary,#2f9e63)}.gNoOdq_diffRemoved{color:var(--dsw-alias-state-error-primary,#d1483c)}.gNoOdq_summaryRow{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;max-width:100%;display:flex}.gNoOdq_summaryRow>.gNoOdq_diffStatRoot{flex:none;margin-left:auto}.gNoOdq_summaryRow>:first-child{min-width:0}.gNoOdq_diffStatRoot{flex:none;position:relative}.gNoOdq_diffStatButton{cursor:pointer;font:inherit;font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";color:var(--dsw-alias-label-secondary);background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:6px;padding:2px 8px;font-size:11px;line-height:16px;transition:background .12s,border-color .12s;display:inline-flex}.gNoOdq_diffStatButton:hover,.gNoOdq_diffStatButton:focus-visible,.gNoOdq_diffStatButton[aria-expanded=true]{background:var(--dsw-alias-bg-module-platform,#7f7f7f1a);border-color:var(--dsw-alias-border-l2,#7f7f7f47)}.gNoOdq_diffStatButton:focus-visible{outline:none}.gNoOdq_diffStatButton[aria-expanded=true] .gNoOdq_diffCaret{opacity:1}.gNoOdq_diffOverlayRow{box-sizing:border-box;flex:100%;width:100%;min-width:0;max-width:100%;margin-top:6px}.gNoOdq_diffOverlay{box-sizing:border-box;background:var(--dsw-alias-bg-module-platform,#7f7f7f14);border:1px solid var(--dsw-alias-border-l2,#80808038);border-radius:10px;flex-direction:column;width:100%;min-width:0;max-width:100%;padding:8px;display:flex;overflow:hidden}.gNoOdq_diffTabs{scrollbar-width:thin;flex-wrap:nowrap;gap:6px;max-width:100%;margin-bottom:4px;padding-bottom:6px;display:flex;overflow-x:auto}.gNoOdq_diffTab{text-overflow:ellipsis;white-space:nowrap;cursor:pointer;max-width:220px;font:inherit;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-base,#fffc);border:1px solid var(--dsw-alias-border-l2,#80808033);border-radius:6px;flex:none;padding:3px 10px;font-size:11px;line-height:16px;transition:all .12s;overflow:hidden}.gNoOdq_diffTab:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.gNoOdq_diffTab[data-active]{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-state-business-primary,#1e90ff);background:var(--dsw-alias-bg-base);font-weight:500}.gNoOdq_diffScrollArea{overscroll-behavior:contain;-webkit-overflow-scrolling:touch;border:1px solid var(--dsw-alias-border-l2,#80808026);background:var(--dsw-alias-markdown-code-block,#0000000a);border-radius:8px;max-height:420px;overflow:auto}.gNoOdq_diffScrollArea [data-diff]{background:0 0!important;border-radius:0!important;margin:0!important}.gNoOdq_diffCaret{opacity:.6;flex:none;width:10px;font-size:10px}.gNoOdq_diffPath{text-overflow:ellipsis;white-space:nowrap;text-align:left;direction:rtl;flex:auto;min-width:0;overflow:hidden}.gNoOdq_diffStat{font-variant-numeric:tabular-nums;flex:none;gap:6px;font-size:11px;display:inline-flex}.gNoOdq_diffHunkBody{flex-direction:column;gap:4px;padding:2px 7px 7px 25px;display:flex}.gNoOdq_diffLines{font-size:11px;line-height:1.55;font-family:var(--dsw-font-mono,ui-monospace, SFMono-Regular, Menlo, monospace);white-space:pre;border-radius:6px;margin:0;padding:6px 8px;overflow-x:auto}.gNoOdq_diffLines[data-side=removed]{background:#d1483c1f}.gNoOdq_diffLines[data-side=added]{background:#2f9e631f}.gNoOdq_diffLineRemoved,.gNoOdq_diffLineAdded{display:block}.gNoOdq_diffLineRemoved{color:var(--dsw-alias-state-error-primary,#d1483c)}.gNoOdq_diffLineAdded{color:var(--dsw-alias-state-success-primary,#2f9e63)}.gNoOdq_diffEmpty{color:var(--dsw-alias-label-secondary);margin:0;padding:2px 0;font-size:11px}.gNoOdq_nativeToolSummary[data-running]{background-image:linear-gradient(90deg, currentColor 0%, currentColor 35%, color-mix(in srgb, currentColor 35%, transparent) 50%, currentColor 65%, currentColor 100%);-webkit-text-fill-color:transparent;background-position:100% 0;background-repeat:no-repeat;background-size:300% 100%;-webkit-background-clip:text;background-clip:text;animation:1.6s linear infinite gNoOdq_readerStepShimmer}@keyframes gNoOdq_readerStepShimmer{to{background-position:0 0}}.gNoOdq_toolElapsed[data-slow]{opacity:1;color:var(--dsw-alias-state-warning-primary,#d8862c);font-weight:500}.gNoOdq_toolElapsed{opacity:.72;font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;flex:none;margin-left:8px;font-size:11px;line-height:18px}[data-motion=off] .gNoOdq_nativeToolSummary[data-running]{-webkit-text-fill-color:currentColor;background-image:none;animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_nativeToolSummary[data-running]{-webkit-text-fill-color:currentColor;background-image:none;animation:none!important}}.gNoOdq_toolState{white-space:nowrap;flex:none;margin-left:8px;font-size:11px;line-height:18px}.gNoOdq_toolState[data-phase=preparing],.gNoOdq_toolState[data-phase=running]{color:var(--dsw-alias-state-business-primary)}.gNoOdq_toolState[data-phase=preparing]:before,.gNoOdq_toolState[data-phase=running]:before{content:\"\";vertical-align:middle;background:currentColor;border-radius:50%;width:6px;height:6px;margin-right:6px;animation:1.4s ease-in-out infinite gNoOdq_readerRunningGlow;display:inline-block}@keyframes gNoOdq_readerRunningGlow{0%{box-shadow:0 0 0 0 color-mix(in srgb, currentColor 60%, transparent);opacity:1}70%{opacity:.7;box-shadow:0 0 0 7px #0000}to{opacity:1;box-shadow:0 0 #0000}}[data-motion=off] .gNoOdq_toolState[data-phase=preparing]:before,[data-motion=off] .gNoOdq_toolState[data-phase=running]:before{animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_toolState[data-phase=preparing]:before,.gNoOdq_toolState[data-phase=running]:before{animation:none!important}}.gNoOdq_toolState[data-phase=failed]{color:var(--dsw-alias-state-error-primary)}.gNoOdq_toolState[data-phase=interrupted]{color:inherit;opacity:.7}.gNoOdq_toolLedger{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:10px 14px 0;font-size:11px;line-height:18px;display:flex}.gNoOdq_toolEngine{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gNoOdq_toolDetails{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;min-width:0;margin:6px 0 0 22px;overflow:hidden}.gNoOdq_toolTabs{align-items:center;gap:15px;padding:0 14px;display:flex}.gNoOdq_toolTabs>button{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-bottom:2px solid #0000;padding:10px 1px 8px;font-size:12px;line-height:20px}.gNoOdq_toolTabs>button[aria-selected=true]{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsw-alias-state-business-primary)}.gNoOdq_toolPanel{flex-direction:column;gap:12px;min-width:0;padding:12px 14px 14px;font-size:13px;line-height:22px;display:flex}.gNoOdq_toolPanel:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-3px}.gNoOdq_toolDetailNote{color:var(--dsw-alias-label-secondary);margin:0 0 9px;font-size:12px;line-height:20px}.gNoOdq_toolRawLabel{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;font-weight:500}.gNoOdq_toolRaw{background:var(--dsw-alias-bg-module-platform);max-height:400px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;margin:0;padding:12px;font:12px/20px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:auto}.gNoOdq_systemPrompt{background:var(--dsw-alias-bg-module-platform);max-height:320px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;margin:0;padding:12px;font:12px/20px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:auto}.gNoOdq_commandInput{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.gNoOdq_toolReceipt .gNoOdq_blocks,.gNoOdq_toolDocument .gNoOdq_blocks{font-size:13px;line-height:22px}.gNoOdq_toolChildren{margin:0 14px 12px var(--reader-rail,6px);padding-left:var(--reader-gutter,16px);border-left:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:9px;display:flex}@container (width<=420px){.gNoOdq_toolHeading{grid-template-columns:16px minmax(0,1fr) auto;gap:7px;padding:11px 10px 6px}.gNoOdq_toolHeadingState{gap:4px}.gNoOdq_toolLedger{padding-left:33px;padding-right:10px}.gNoOdq_toolPanel{padding:10px}}@media (pointer:coarse){.gNoOdq_toolTabs>button{min-height:44px}}.gNoOdq_reasonCard{--reason-preview-height:224px;--reason-hold:.84s;--reason-step:.5s;--reason-lines:2;--reason-fade:28px;--reason-ease:cubic-bezier(.22, 1, .36, 1);border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);min-width:0;scroll-margin-block:16px calc(var(--dsh-composer-height,152px) + 16px);border-radius:12px;position:relative;overflow:hidden}.gNoOdq_reasonHeading{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:baseline;gap:12px;padding:10px 16px 0;font-size:12px;line-height:20px;display:flex}.gNoOdq_reasonCard[data-overflow=false][data-expanded=false]{background:0 0;border-color:#0000;border-radius:0}.gNoOdq_reasonCard[data-overflow=false][data-expanded=false] .gNoOdq_reasonHeading{padding:0}.gNoOdq_reasonCard[data-overflow=false][data-expanded=false] .gNoOdq_reasonText{padding:4px 0 0 22px}.gNoOdq_reasonLabel{font-weight:500}.gNoOdq_reasonViewport{max-height:var(--reason-preview-height);scroll-behavior:auto;overflow-anchor:none;overscroll-behavior-y:contain;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l1) transparent;position:relative;overflow:auto}.gNoOdq_reasonCard[data-expanded=true] .gNoOdq_reasonViewport{max-height:min(60vh, 560px, var(--reason-reading-height,560px))}.gNoOdq_reasonViewport[data-edges=both],.gNoOdq_reasonCard[data-following=true][data-overflow=true] .gNoOdq_reasonViewport{-webkit-mask-image:linear-gradient(transparent 0, black var(--reason-fade), black calc(100% - var(--reason-fade)), transparent 100%);mask-image:linear-gradient(transparent 0, black var(--reason-fade), black calc(100% - var(--reason-fade)), transparent 100%)}.gNoOdq_reasonViewport[data-edges=top]{-webkit-mask-image:linear-gradient(transparent 0, black var(--reason-fade), black 100%);mask-image:linear-gradient(transparent 0, black var(--reason-fade), black 100%)}.gNoOdq_reasonViewport[data-edges=bottom]{-webkit-mask-image:linear-gradient(black 0, black calc(100% - var(--reason-fade)), transparent 100%);mask-image:linear-gradient(black 0, black calc(100% - var(--reason-fade)), transparent 100%)}.gNoOdq_reasonCard[data-expanded=true] .gNoOdq_reasonViewport{-webkit-mask-image:none;mask-image:none}.gNoOdq_reasonViewport:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-3px}.gNoOdq_reasonTrack{position:relative;transform:translateY(0)}.gNoOdq_reasonCard[data-following=true] .gNoOdq_reasonTrack{will-change:transform}.gNoOdq_reasonText{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;padding:8px 16px 16px;font-size:14px;line-height:24px}.gNoOdq_reasonText .gNoOdq_readingText>div{font-size:inherit;line-height:inherit;color:inherit}.gNoOdq_reasonFooter{color:var(--dsw-alias-label-secondary);justify-content:space-between;align-items:center;gap:8px;padding:2px 10px 8px;font-size:12px;line-height:20px;display:flex}.gNoOdq_reasonAction{min-height:28px;color:inherit;font:inherit;cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:6px;justify-content:center;align-items:center;gap:5px;padding:4px 6px;display:inline-flex}.gNoOdq_reasonAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_reasonAction:disabled{cursor:default;opacity:.65}.gNoOdq_reasonAction svg{fill:none;stroke:currentColor;stroke-width:1.3px;stroke-linecap:round;stroke-linejoin:round;flex:none}.gNoOdq_reasonCaption{padding-left:6px}@container (width<=480px){.gNoOdq_reasonCard{--reason-preview-height:192px}}@media (pointer:coarse){.gNoOdq_reasonAction{min-height:44px}}@media (prefers-reduced-motion:reduce){.gNoOdq_reasonTrack{will-change:auto!important;transition:none!important;transform:none!important}}@media (forced-colors:active){.gNoOdq_reasonViewport{-webkit-mask-image:none!important;mask-image:none!important}}.gNoOdq_processItem,.gNoOdq_tool{min-width:0;margin:0 0 18px}.gNoOdq_processLabel{color:var(--dsw-alias-label-tertiary);align-items:baseline;gap:12px;margin:0 0 6px;font-size:12px;line-height:20px;display:flex}.gNoOdq_processFootnote{color:var(--dsw-alias-label-tertiary);margin:14px 0 0;font-size:12px;line-height:20px}.gNoOdq_detail{color:var(--dsw-alias-label-secondary);font-size:13px;line-height:22px}.gNoOdq_detail>summary{cursor:pointer;padding:3px 0}.gNoOdq_detail[open]>summary{margin-bottom:8px}.gNoOdq_tool>.gNoOdq_tool{margin:10px 0 0 12px}.gNoOdq_meta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}.gNoOdq_stopped{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-tertiary);border-radius:6px;align-self:flex-start;margin-top:12px;padding:0 6px;font-size:11px;line-height:18px}.gNoOdq_compactionRow{box-sizing:border-box;flex-direction:column;align-items:center;width:100%;margin:16px 0;display:flex}.gNoOdq_compactionLine{width:100%;color:var(--dsw-alias-label-tertiary);user-select:none;justify-content:center;align-items:center;gap:12px;font-size:11px;line-height:18px;display:flex}.gNoOdq_compactionLine:before,.gNoOdq_compactionLine:after{content:\"\";background:var(--dsw-alias-border-l1);opacity:.7;flex:1;height:1px}.gNoOdq_compactionRow>.gNoOdq_compactionLine{animation:.52s cubic-bezier(.4,0,.2,1) both gNoOdq_compactionLineIn}.gNoOdq_compactionRow>.gNoOdq_compactionLine>.gNoOdq_compactionPill{animation:.42s cubic-bezier(.34,1.4,.64,1) .12s both gNoOdq_compactionPillIn}.gNoOdq_compactionRow>.gNoOdq_compactionLine .gNoOdq_compactionIcon{animation:.9s cubic-bezier(.4,0,.2,1) .2s both gNoOdq_compactionDial}@keyframes gNoOdq_compactionLineIn{0%{opacity:0;transform:scaleX(.6)}to{opacity:1;transform:scaleX(1)}}@keyframes gNoOdq_compactionPillIn{0%{opacity:0;transform:translateY(-6px)scale(.94)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes gNoOdq_compactionDial{0%{opacity:0;transform:rotate(-140deg)}to{opacity:.7;transform:rotate(0)}}[data-motion=off] .gNoOdq_compactionRow>.gNoOdq_compactionLine,[data-motion=off] .gNoOdq_compactionRow>.gNoOdq_compactionLine>.gNoOdq_compactionPill,[data-motion=off] .gNoOdq_compactionRow>.gNoOdq_compactionLine .gNoOdq_compactionIcon{animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_compactionRow>.gNoOdq_compactionLine,.gNoOdq_compactionRow>.gNoOdq_compactionLine>.gNoOdq_compactionPill,.gNoOdq_compactionRow>.gNoOdq_compactionLine .gNoOdq_compactionIcon{animation:none!important}}.gNoOdq_compactionPill{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);border-radius:12px;align-items:center;gap:6px;padding:2px 10px;font-family:inherit;font-size:11px;line-height:18px;display:inline-flex}.gNoOdq_compactionButton{cursor:pointer;transition:color .14s,border-color .14s,background-color .14s}.gNoOdq_compactionButton:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_compactionIcon{opacity:.7;flex:none;width:12px;height:12px}.gNoOdq_compactionToggle{opacity:.8;margin-left:2px;font-size:10px}.gNoOdq_compactionSummaryBox{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);width:100%;max-width:680px;color:var(--dsw-alias-label-secondary);box-sizing:border-box;border-radius:8px;margin-top:10px;padding:12px 16px;font-size:12px;line-height:20px}.gNoOdq_compactionSummaryHeader{color:var(--dsw-alias-label-tertiary);border-bottom:1px dashed var(--dsw-alias-border-l1);margin-bottom:8px;padding-bottom:4px;font-size:11px;font-weight:500}.gNoOdq_notice,.gNoOdq_error,.gNoOdq_attention{overflow-wrap:anywhere;border-radius:10px;padding:12px 14px;font-size:13px;line-height:20px}.gNoOdq_notice{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border:1px solid var(--dsw-alias-border-l2)}.gNoOdq_error{color:var(--dsw-alias-label-primary);background:#ef44440f;border:1px solid #ef444438;align-items:flex-start;gap:10px;display:flex}.gNoOdq_errorIcon{color:#ef4444;flex:none;width:16px;height:16px;margin-top:2px}.gNoOdq_errorCopy{flex:1;min-width:0}.gNoOdq_errorTitle{color:#dc2626;align-items:center;gap:8px;margin-bottom:2px;font-weight:500;display:flex}.gNoOdq_errorMessage{color:var(--dsw-alias-label-secondary);word-break:break-word;margin:0;font-size:12px;line-height:18px}.gNoOdq_errorCode{color:#dc2626;background:#ef44441f;border-radius:4px;padding:1px 5px;font-family:inherit;font-size:11px}.gNoOdq_attention{border:1px solid var(--dsw-alias-state-business-primary);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);flex-direction:column;gap:3px;display:flex}.gNoOdq_attention span{color:var(--dsw-alias-label-secondary)}.gNoOdq_unknown{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:12px 14px;font-size:13px;line-height:22px}.gNoOdq_unknown p{margin:0 0 6px}.gNoOdq_historyButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0;border-radius:8px;align-self:center;padding:4px 12px;font-size:12px}.gNoOdq_historyButton:disabled{opacity:.55;cursor:default}.gNoOdq_empty{color:var(--dsw-alias-label-tertiary);text-align:center;padding:40px 0}.gNoOdq_answerActions{align-items:center;gap:8px;min-height:28px;margin:13px 0 0 -6px;display:flex}.gNoOdq_userActions{align-items:center;gap:8px;min-height:28px;display:flex}.gNoOdq_messageClock{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:13px;line-height:24px}.gNoOdq_iconButton{color:var(--dsw-alias-label-tertiary);background:0 0;border:0;border-radius:6px;justify-content:center;align-items:center;padding:6px;display:inline-flex}.gNoOdq_iconButton svg{fill:none;stroke:currentColor;stroke-width:1.2px;stroke-linecap:round;stroke-linejoin:round}.gNoOdq_imageFigure{box-sizing:border-box;align-self:flex-start;width:min(100%,360px);max-width:100%;margin:0}.gNoOdq_imageFrame{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);box-sizing:border-box;border-radius:12px;max-width:100%;min-height:96px;max-height:440px;position:relative;overflow:hidden}.gNoOdq_imageOpen{background:0 0;border:0;width:100%;height:100%;padding:0;display:flex;position:absolute;inset:0}.gNoOdq_imageOpen img{object-fit:contain;opacity:0;width:100%;height:100%;transition:opacity .2s cubic-bezier(.4,0,.2,1);display:block}.gNoOdq_imageOpen img[data-ready=true]{opacity:1}.gNoOdq_pendingImage{object-fit:contain;width:100%;max-width:100%;height:100%;display:block}.gNoOdq_imagePlaceholder{color:var(--dsw-alias-label-tertiary);pointer-events:none;flex-direction:column;justify-content:center;align-items:center;gap:8px;font-size:13px;display:flex;position:absolute;inset:0}.gNoOdq_imagePlaceholder button{pointer-events:auto}.gNoOdq_imageFigure figcaption{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin-top:6px;font-size:12px;line-height:20px}.gNoOdq_imageDialog{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border-radius:16px;max-width:90vw;max-height:90vh;padding:38px 20px 20px}.gNoOdq_imageDialog::backdrop{background:var(--dsw-alias-bg-mask-photo)}.gNoOdq_imageDialog img{object-fit:contain;max-width:82vw;max-height:75vh;display:block}.gNoOdq_dialogClose{color:inherit;background:0 0;border:0;border-radius:8px;width:32px;height:32px;font-size:24px;position:absolute;top:4px;right:8px}.gNoOdq_jumpDock{bottom:calc(var(--dsh-composer-height,152px) + 16px);z-index:8;pointer-events:none;justify-content:flex-end;height:0;display:flex;position:sticky}.gNoOdq_deliverablesRoot{grid-template-columns:max-content minmax(0,1fr);align-items:start;column-gap:10px;margin-top:14px;font-size:13px;line-height:22px;display:grid}.gNoOdq_deliverablesLabel{color:var(--dsw-alias-label-tertiary);grid-area:1/1;padding-top:2px;font-size:12px;font-weight:500}.gNoOdq_deliverablesLane{grid-area:1/2;min-width:0}.gNoOdq_deliverablesRow{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;display:flex}.gNoOdq_deliverableChip{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;font-size:12px;line-height:20px;transition:border-color .16s,background-color .16s,color .16s;display:inline-flex;overflow:hidden}.gNoOdq_deliverableChip:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-bg-module-platform);box-shadow:0 1px 4px var(--dsw-alias-border-l1)}.gNoOdq_deliverableChip[data-status=opened]{color:#059669;background:#10b9811f;border-color:#10b981}.gNoOdq_chipMain{max-width:220px;color:inherit;font:inherit;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:5px;padding:3px 6px 3px 8px;display:inline-flex}.gNoOdq_chipMain:hover{color:var(--dsw-alias-label-primary)}.gNoOdq_deliverableIcon,.gNoOdq_statusIcon{opacity:.8;flex:none;width:13px;height:13px}.gNoOdq_statusIcon{color:#10b981}.gNoOdq_deliverableName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.gNoOdq_chipActions{opacity:.65;border-left:1px solid #0000;align-items:center;gap:2px;padding-right:4px;transition:opacity .15s,border-left-color .15s;display:inline-flex}.gNoOdq_deliverableChip:hover .gNoOdq_chipActions{opacity:1;border-left-color:var(--dsw-alias-border-l2)}.gNoOdq_chipActionBtn{width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;transition:color .12s,background-color .12s;display:inline-flex}.gNoOdq_chipActionBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_actionIcon{width:12px;height:12px}.gNoOdq_deliverablesMore{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:12px}.gNoOdq_deliverablesShowFolder{color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:5px;align-items:center;gap:4px;padding:2px 7px;font-size:12px;transition:all .15s;display:inline-flex}.gNoOdq_deliverablesShowFolder:hover{color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}.gNoOdq_deliverablesShowFolder[data-status=opened]{color:#10b981;background:#10b98114;border-color:#10b9814d}.gNoOdq_morphCluster{flex-direction:column;width:100%;min-width:0;display:flex}.gNoOdq_morphDrawer{transform-origin:top;will-change:height, opacity, transform;height:0;overflow:hidden}.gNoOdq_liveFoldImpact{animation:.18s cubic-bezier(.2,0,0,1) both gNoOdq_liveFoldElastic}@keyframes gNoOdq_liveFoldElastic{0%{transform:scale(1)}50%{transform:scale(1.015)}to{transform:scale(1)}}.gNoOdq_liveFoldContainer{top:calc(max(var(--reader-toolbar-height,40px), var(--reader-status-height,40px)) + var(--reader-sticky-lane,40px) * 2);z-index:4;background:var(--dsw-alias-bg-base);-webkit-backdrop-filter:blur(12px);transform-origin:0;will-change:transform, opacity;margin-bottom:6px;padding:4px 0;animation:.32s cubic-bezier(.16,1,.3,1) both gNoOdq_liveFoldPulse;position:sticky}@keyframes gNoOdq_liveFoldPulse{0%{opacity:.8;transform:translateY(-4px)scale(.98)}50%{opacity:1;transform:translateY(0)scale(1.02)}to{opacity:1;transform:translateY(0)scale(1)}}[data-motion=off] .gNoOdq_liveFoldContainer{animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_liveFoldContainer{animation:none!important}}.gNoOdq_priorFoldDrawer{flex-direction:column;gap:14px;width:100%;min-width:0;display:flex}.gNoOdq_jump{width:34px;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-button-floating-fill,var(--dsw-alias-bg-base));box-shadow:var(--dsw-elevation-panel,0 2px 8px var(--dsw-alias-border-l1));pointer-events:auto;border:0;border-radius:100px;flex:none;justify-content:center;align-items:center;margin-top:-34px;padding:0;display:flex}.gNoOdq_jump:hover{background:var(--dsw-alias-button-floating-hover,var(--dsw-alias-interactive-bg-hover))}.gNoOdq_foldSummary{text-overflow:ellipsis;align-items:baseline;max-width:100%;display:inline-flex;overflow:hidden;white-space:nowrap!important}.gNoOdq_foldSummaryPart{flex:none;align-items:baseline;display:inline-flex;white-space:nowrap!important}.gNoOdq_numberRollRoot{vertical-align:baseline;line-height:inherit;font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";text-align:center;flex-shrink:0;justify-content:center;min-width:1.45em;display:inline-flex;position:relative;overflow:hidden;white-space:nowrap!important}.gNoOdq_numberRollSizer{visibility:hidden;user-select:none;pointer-events:none;line-height:inherit;white-space:nowrap}.gNoOdq_numberRollDigit{line-height:inherit;white-space:nowrap;justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.gNoOdq_numberRollExit{animation:.24s cubic-bezier(.16,1,.3,1) forwards gNoOdq_numberRollOut}.gNoOdq_numberRollEnter{animation:.24s cubic-bezier(.16,1,.3,1) forwards gNoOdq_numberRollIn}@keyframes gNoOdq_numberRollOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-100%)}}@keyframes gNoOdq_numberRollIn{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}[data-motion=off] .gNoOdq_chevron,[data-motion=off] .gNoOdq_imageOpen img,[data-motion=off] .gNoOdq_processMeta,[data-motion=off] .gNoOdq_numberRollDigit{transition:none!important;animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_chevron,.gNoOdq_imageOpen img,.gNoOdq_processMeta,.gNoOdq_numberRollDigit{transition:none!important;animation:none!important}}.gNoOdq_turnStatus{white-space:nowrap;flex:none;align-self:flex-start;align-items:center;height:26px;margin:4px 0 12px;padding:0 4px;font-size:14px;line-height:22px;display:inline-flex}.gNoOdq_turnStatusLabel{background:linear-gradient(90deg, var(--dsw-static-deepseek-500,#4d6bfe) 0%, var(--dsw-static-deepseek-500,#4d6bfe) 40%, var(--dsw-static-deepseek-200,#a8c7fa) 50%, var(--dsw-static-deepseek-500,#4d6bfe) 60%, var(--dsw-static-deepseek-500,#4d6bfe) 100%);color:#0000;-webkit-text-fill-color:transparent;background-position:100% 0;background-size:250% 100%;-webkit-background-clip:text;background-clip:text;font-weight:500;animation:1.8s linear infinite gNoOdq_dsh-turn-status-shimmer}.gNoOdq_waitClock{flex:none;align-items:center;margin-left:8px;display:inline-flex}.gNoOdq_waitSeconds{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";color:var(--dsw-alias-label-caption,#86909c);font-size:13px;font-weight:400}.gNoOdq_waitOvertime{color:var(--dsw-alias-state-warning-primary,#d8862c);background:color-mix(in srgb, var(--dsw-alias-state-warning-primary,#d8862c) 16%, transparent);border-radius:5px;margin-left:8px;padding:0 6px;font-size:11px;line-height:16px}.gNoOdq_turnStatusClock{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";color:var(--dsw-alias-label-caption,#86868b);-webkit-text-fill-color:var(--dsw-alias-label-caption,#86868b);margin-left:8px;font-size:13px;font-weight:400}@keyframes gNoOdq_dsh-turn-status-shimmer{to{background-position:0 0}}[data-motion=off] .gNoOdq_turnStatusLabel{color:var(--dsw-static-deepseek-500,#4d6bfe)!important;-webkit-text-fill-color:var(--dsw-static-deepseek-500,#4d6bfe)!important;animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_turnStatusLabel{color:var(--dsw-static-deepseek-500,#4d6bfe)!important;-webkit-text-fill-color:var(--dsw-static-deepseek-500,#4d6bfe)!important;animation:none!important}}@media (pointer:coarse){.gNoOdq_disclosureButton{min-height:44px}}@media (width<=600px){.gNoOdq_root{padding-inline:20px}.gNoOdq_column{gap:18px}.gNoOdq_toolbar{font-size:11px}.gNoOdq_user{max-width:90%}}.gNoOdq_choreographedFlow{overflow-anchor:none;flex-direction:column;min-width:0;display:flex}.gNoOdq_flowCell{min-width:0;display:flow-root;overflow:clip}.gNoOdq_flowCell[hidden]{display:none}.gNoOdq_flowCellInner{flex-direction:column;min-width:0;padding-bottom:16px;display:flex}.gNoOdq_flowCellInner:empty{padding-bottom:0}.gNoOdq_choreographedFlow[data-reader-transition=collapse] .gNoOdq_flowCell *{animation-play-state:paused!important}.gNoOdq_numberRollExit,.gNoOdq_numberRollEnter{animation-duration:.16s}.gNoOdq_foldSummary{align-items:baseline;display:inline-flex;white-space:nowrap!important;flex-wrap:nowrap!important}.gNoOdq_toolbar{box-sizing:border-box;z-index:7;-webkit-backdrop-filter:none;border-bottom:0;align-self:stretch;width:100%;max-width:100%;min-height:40px}.gNoOdq_turnProcessSticky{box-sizing:border-box;width:calc(100% - var(--reader-control-width,148px));top:max(var(--reader-toolbar-height,40px), var(--reader-status-height,40px));z-index:6;-webkit-backdrop-filter:none;min-height:40px;box-shadow:0 -14px 0 var(--dsw-alias-bg-base), var(--reader-control-width,148px) 0 0 var(--dsw-alias-bg-base);background-clip:padding-box;border-bottom:1px solid #0000;padding-right:0}.gNoOdq_flowCell[data-flow-summary],.gNoOdq_closedProcessSummary{top:calc(max(var(--reader-toolbar-height,40px), var(--reader-status-height,40px)) + var(--reader-sticky-lane,40px));z-index:5;box-sizing:border-box;background:var(--dsw-alias-bg-base);border-bottom:0;min-height:40px;padding-block:4px;position:sticky;overflow:visible}.gNoOdq_flowCell[data-flow-summary]{box-shadow:0 -16px 0 var(--dsw-alias-bg-base)}.gNoOdq_closedProcessSummary{box-shadow:0 -14px 0 var(--dsw-alias-bg-base)}.gNoOdq_foldControl{background:var(--dsw-alias-bg-module-platform);border-radius:8px;align-items:center;gap:0;padding:2px;display:inline-flex}.gNoOdq_foldStop{color:var(--dsw-alias-label-secondary);white-space:nowrap;font:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;padding:2px 8px;font-size:12px;line-height:18px}.gNoOdq_foldStop[data-on]{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary)}.gNoOdq_flowCell[data-flow-summary]>.gNoOdq_flowCellInner{padding-bottom:0}.gNoOdq_flowCell[data-flow-summary] .gNoOdq_disclosureButton,.gNoOdq_closedProcessSummary .gNoOdq_disclosureButton{width:auto;max-width:100%}.gNoOdq_flowCell[data-flow-summary] .gNoOdq_foldSummary,.gNoOdq_closedProcessSummary .gNoOdq_foldSummary{min-width:0}.gNoOdq_turnProcessSticky>.gNoOdq_disclosure{flex:auto;min-width:0}.gNoOdq_disclosureButton{width:max-content;max-width:calc(100% + 6px)}.gNoOdq_statusText{flex:0 auto}.gNoOdq_think{width:max-content;min-width:0}.gNoOdq_thinkSizer{white-space:normal;overflow-wrap:anywhere}.gNoOdq_thinkText{white-space:normal;overflow-wrap:anywhere;text-overflow:clip;overflow:visible}.gNoOdq_root[data-reader-glass] .gNoOdq_toolbar,.gNoOdq_root[data-reader-glass] .gNoOdq_turnProcessSticky,.gNoOdq_root[data-reader-glass] .gNoOdq_liveFoldContainer{-webkit-backdrop-filter:blur(16px);box-shadow:none;background:0 0;border:0;border-radius:0}.gNoOdq_root[data-reader-glass] .gNoOdq_flowCell[data-flow-summary],.gNoOdq_root[data-reader-glass] .gNoOdq_closedProcessSummary{box-shadow:none;z-index:auto;border-left:2px solid color-mix(in srgb, var(--dsw-alias-border-l2,#80808059) 80%, transparent);padding-block:2px;background:0 0;border-radius:0;min-height:32px;padding-left:10px;position:static}.gNoOdq_root[data-reader-glass] .gNoOdq_user{background:color-mix(in srgb, var(--dsw-specific-bubble,#00000014) 25%, transparent);-webkit-backdrop-filter:blur(12px);border:1px solid color-mix(in srgb, var(--dsw-alias-border-l1,#8080804d) 30%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_reasonCard{border-color:color-mix(in srgb, var(--dsw-alias-border-l1,#80808059) 65%, transparent);background:0 0}.gNoOdq_root[data-reader-glass] .gNoOdq_toolDetails,.gNoOdq_root[data-reader-glass] .gNoOdq_notice,.gNoOdq_root[data-reader-glass] .gNoOdq_unknown,.gNoOdq_root[data-reader-glass] .gNoOdq_toolRaw,.gNoOdq_root[data-reader-glass] .gNoOdq_systemPrompt,.gNoOdq_root[data-reader-glass] .gNoOdq_compactionSummaryBox,.gNoOdq_root[data-reader-glass] .gNoOdq_attention,.gNoOdq_root[data-reader-glass] .gNoOdq_imageFrame,.gNoOdq_root[data-reader-glass] .gNoOdq_imageDialog{background:0 0}.gNoOdq_root[data-reader-glass] .gNoOdq_diffOverlay{background:color-mix(in srgb, var(--dsw-alias-bg-module-platform,#7f7f7f1a) 20%, transparent);-webkit-backdrop-filter:blur(16px)}.gNoOdq_root[data-reader-glass] .gNoOdq_diffScrollArea{background:0 0}.gNoOdq_root[data-reader-glass] .gNoOdq_diffTab{background:color-mix(in srgb, var(--dsw-alias-bg-base,#fffc) 25%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_diffTab[data-active]{background:color-mix(in srgb, var(--dsw-alias-bg-base,#fff) 45%, transparent)}.gNoOdq_root[data-reader-glass] .md-code-block,.gNoOdq_root[data-reader-glass] [data-diff]{border:1px solid color-mix(in srgb, var(--dsw-alias-border-l1,#80808033) 30%, transparent);-webkit-backdrop-filter:blur(12px);background:color-mix(in srgb, var(--dsw-alias-markdown-code-block,#0000000f) 25%, transparent)!important}.gNoOdq_root[data-reader-glass] .gNoOdq_foldControl{background:color-mix(in srgb, var(--dsw-alias-bg-module-platform,#7f7f7f1a) 25%, transparent);border:1px solid color-mix(in srgb, var(--dsw-alias-border-l2,#80808033) 30%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_foldStop[data-on]{background:color-mix(in srgb, var(--dsw-alias-bg-base,#fff) 35%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_compactionPill,.gNoOdq_root[data-reader-glass] .gNoOdq_deliverableChip,.gNoOdq_root[data-reader-glass] .gNoOdq_toolState,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton{background:0 0;border-color:#0000}.gNoOdq_root[data-reader-glass] .gNoOdq_compactionPill:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_compactionPill:focus-visible,.gNoOdq_root[data-reader-glass] .gNoOdq_deliverableChip:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_deliverableChip:focus-within,.gNoOdq_root[data-reader-glass] .gNoOdq_toolState:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton:focus-visible,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton[aria-expanded=true]{background:var(--dsw-alias-bg-module-platform,#7f7f7f1a);border-color:var(--dsw-alias-border-l2,#7f7f7f47)}";
|
|
42739
|
+
const css$5 = ".gNoOdq_root{color:var(--dsw-alias-label-primary);padding:16px calc(var(--dsh-composer-side-clearance,16px) + 16px) 24px;overflow-anchor:auto;--reader-lane-block:max(40px, calc(40px + var(--dsh-content-font-delta,0px)));--reader-lane-plate:linear-gradient(var(--dsw-alias-bg-base), var(--dsw-alias-bg-base)), linear-gradient(var(--dsw-alias-bg-layer-1,transparent), var(--dsw-alias-bg-layer-1,transparent));flex:none;min-width:0;font-family:inherit;font-size:16px;line-height:28px;container-type:inline-size}.gNoOdq_column{max-width:var(--dsh-chat-content-width,748px);flex-direction:column;gap:22px;width:100%;min-width:0;margin:0 auto;display:flex}.gNoOdq_column:focus,.gNoOdq_column:focus-visible{outline:none}.gNoOdq_toolbar{min-height:32px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-base);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);justify-content:flex-end;align-items:center;gap:6px;padding:0;font-size:12px;display:flex;position:sticky;top:0}.gNoOdq_turnProcessSticky{background:var(--dsw-alias-bg-base);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);align-items:center;min-height:32px;display:flex;position:sticky}.gNoOdq_turnProcessSticky .gNoOdq_disclosureButton{min-height:32px}.gNoOdq_textButton,.gNoOdq_historyButton,.gNoOdq_iconButton,.gNoOdq_jump,.gNoOdq_disclosureButton,.gNoOdq_imageOpen,.gNoOdq_dialogClose{font:inherit;cursor:pointer}.gNoOdq_textButton{color:var(--dsw-alias-label-secondary);white-space:nowrap;background:0 0;border:0;border-radius:6px;padding:2px 6px}.gNoOdq_textButton:hover,.gNoOdq_iconButton:hover,.gNoOdq_disclosureButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_root button:focus-visible,.gNoOdq_root summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px}.gNoOdq_turn,.gNoOdq_turnStickyRegion{flex-direction:column;gap:14px;min-width:0;display:flex}.gNoOdq_turnStickyLanes{top:var(--reader-toolbar-height,var(--reader-lane-block,40px));z-index:6;flex-direction:column;min-width:0;display:flex;position:sticky}.gNoOdq_turn+.gNoOdq_turn,.gNoOdq_retiringContent+.gNoOdq_retiringContent>.gNoOdq_turn{margin-top:12px}.gNoOdq_userCluster{flex-direction:column;align-self:stretch;align-items:flex-end;gap:8px;width:100%;min-width:0;max-width:100%;margin-bottom:4px;display:flex}.gNoOdq_userCluster>[data-slot]>*{box-sizing:border-box;align-self:stretch;width:100%;min-width:0;max-width:100%}.gNoOdq_userImages{flex-direction:column;align-self:flex-end;align-items:flex-end;width:fit-content;min-width:0;max-width:100%;display:flex}.gNoOdq_userImages .gNoOdq_imageFigure{align-self:flex-end}.gNoOdq_user{width:fit-content;max-width:min(calc(var(--dsh-chat-content-width,748px) * .702), 82%);border-radius:var(--dsw-radius-xl,22px);background:var(--dsw-specific-bubble);color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;box-sizing:border-box;align-self:flex-end;margin-left:auto;padding:10px 16px;font-weight:400}.gNoOdq_user .gNoOdq_blocks{gap:10px}.gNoOdq_answer{overflow-wrap:anywhere;flex-direction:column;min-width:0;display:flex}.gNoOdq_readingText{min-width:0}.gNoOdq_reasonPlain{white-space:pre-wrap;overflow-wrap:anywhere;font:inherit;color:inherit}.gNoOdq_readingText button{min-width:24px;min-height:24px}.gNoOdq_streamWord{display:inline-block}.gNoOdq_streamInlineWord{display:inline}.gNoOdq_streamWord,.gNoOdq_streamInlineWord,.gNoOdq_streamAtom{opacity:1;filter:none}.gNoOdq_streamAtom{min-width:0}@media (prefers-reduced-motion:reduce){.gNoOdq_streamWord,.gNoOdq_streamInlineWord,.gNoOdq_streamAtom{opacity:1!important;filter:none!important}}.gNoOdq_retiringContent{min-width:0}.gNoOdq_retiringContent[data-reader-retiring=retiring]{overflow:hidden}.gNoOdq_mainFlow,.gNoOdq_blocks{flex-direction:column;gap:16px;min-width:0;display:flex}.gNoOdq_mainFlow:empty,.gNoOdq_blocks:empty{display:none}.gNoOdq_blocks>:first-child{margin-top:0}.gNoOdq_blocks>:last-child{margin-bottom:0}.gNoOdq_blocks .md-table-wide{max-width:100%}.gNoOdq_disclosure{min-width:0}.gNoOdq_disclosureButton{max-width:100%;min-height:32px;color:var(--dsw-alias-label-tertiary);font-size:calc(14px + var(--dsh-content-font-delta,0px));line-height:calc(24px + var(--dsh-content-font-delta,0px));text-align:left;background:0 0;border:0;border-radius:7px;align-items:center;gap:6px;margin-left:-6px;padding:4px 6px;font-weight:400;display:inline-flex}.gNoOdq_disclosure[data-reader-status-only]{align-items:center;min-height:32px;display:flex}.gNoOdq_statusText{min-width:0;max-width:100%;font-size:calc(14px + var(--dsh-content-font-delta,0px));line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-secondary);font-weight:400;display:inline-flex}.gNoOdq_srOnly{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.gNoOdq_think{--think-swap:.15s;--think-gap:50ms;--think-distance:8px;--think-blur:2px;--think-shimmer:2s;--think-base:var(--dsw-alias-label-secondary);--think-highlight:var(--dsw-alias-label-primary);--think-ease:ease-in-out;text-align:left;max-width:100%;display:inline-block;position:relative}.gNoOdq_thinkSizer{visibility:hidden;white-space:nowrap;display:block}.gNoOdq_thinkText{color:var(--think-base);white-space:nowrap;text-overflow:ellipsis;filter:blur();opacity:1;transition:transform var(--think-swap) var(--think-ease), filter var(--think-swap) var(--think-ease), opacity var(--think-swap) var(--think-ease);display:block;position:absolute;top:0;left:0;right:0;overflow:hidden;transform:translateY(0)}.gNoOdq_think[data-reader-status-phase=running] .gNoOdq_thinkText[data-reader-status-copy=current]{transition-delay:var(--think-gap)}.gNoOdq_think:not([data-reader-status-phase=idle]) .gNoOdq_thinkText{will-change:transform, filter, opacity}@supports (background-clip:text){.gNoOdq_think[data-active=true] .gNoOdq_thinkText:before{content:attr(data-text);pointer-events:none;background-image:linear-gradient(90deg, transparent 0%, transparent 40%, var(--think-highlight) 50%, transparent 60%, transparent 100%);color:#0000;-webkit-text-fill-color:transparent;animation:gNoOdq_thinkShimmer var(--think-shimmer) linear infinite;background-repeat:no-repeat;background-size:400% 100%;background-clip:text;position:absolute;inset:0}}@keyframes gNoOdq_thinkShimmer{0%{background-position:100% 0}to{background-position:0 0}}.gNoOdq_thinkText.gNoOdq_isExit{transform:translateY(calc(var(--think-distance) * -1));filter:blur(var(--think-blur));opacity:0}.gNoOdq_thinkText.gNoOdq_isEnterStart{transform:translateY(var(--think-distance));filter:blur(var(--think-blur));opacity:0;transition:none}[data-motion=off] .gNoOdq_thinkText{filter:none!important;opacity:1!important;transition:none!important;transform:none!important}[data-motion=off] .gNoOdq_thinkText[data-reader-status-copy=outgoing],[data-motion=off] .gNoOdq_thinkText:before{display:none!important}@media (prefers-reduced-motion:reduce),(forced-colors:active){.gNoOdq_thinkText{filter:none!important;opacity:1!important;transition:none!important;transform:none!important}.gNoOdq_thinkText[data-reader-status-copy=outgoing],.gNoOdq_thinkText:before{display:none!important}}.gNoOdq_processMeta{opacity:0;grid-template-rows:0fr;transition:grid-template-rows .26s cubic-bezier(.22,1,.36,1),opacity .16s ease-out;display:grid}.gNoOdq_processMeta[data-open=true]{opacity:1;grid-template-rows:1fr}.gNoOdq_processMetaInner{min-height:0;overflow:hidden}.gNoOdq_processMetaLine{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex-wrap:wrap;align-items:baseline;gap:8px;padding:8px 0 0 16px;font-size:12px;line-height:20px;display:flex}.gNoOdq_processMetaLine .gNoOdq_meta{color:inherit}.gNoOdq_chevron{stroke:currentColor;fill:none;stroke-width:1.4px;stroke-linecap:round;stroke-linejoin:round;flex:none;transition:transform .26s cubic-bezier(.22,1,.36,1)}.gNoOdq_chevron[data-open=true]{transform:rotate(90deg)}.gNoOdq_disclosureBody{transform-origin:top;will-change:height, opacity, transform;height:0;overflow:hidden}.gNoOdq_processContents{border-left:1px solid var(--dsw-alias-border-l2);padding:3px 0 2px var(--reader-gutter,16px);margin:0 0 0 var(--reader-rail,6px);color:var(--dsw-alias-label-secondary);font-size:14px;line-height:24px;display:flow-root}.gNoOdq_processContents>:last-child{margin-bottom:0}.gNoOdq_processSeamRow{min-height:40px;margin-left:var(--reader-rail,6px);padding-left:var(--reader-gutter,16px);border-left:1px solid var(--dsw-alias-border-l2);box-sizing:border-box;align-items:center;display:flex}.gNoOdq_processSeamRow>.gNoOdq_disclosure{align-items:center;min-height:24px;display:flex}.gNoOdq_processSeamRow .gNoOdq_disclosureButton{min-height:24px;color:var(--dsw-alias-label-tertiary);padding-block:2px;font-size:12px;line-height:20px}.gNoOdq_flowCell:has(>.gNoOdq_flowCellInner>[data-reader-seam-after])>.gNoOdq_flowCellInner{padding-bottom:0}.gNoOdq_processFrame{min-width:0}.gNoOdq_toolActivity{min-width:0;color:var(--dsw-alias-label-secondary)}.gNoOdq_nativeToolRow{min-width:0}.gNoOdq_rowSeparator{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.gNoOdq_nativeToolSummary{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;font-size:14px;line-height:24px;overflow:hidden}.gNoOdq_nativeToolRow:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px;border-radius:4px}.gNoOdq_toolHeading{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:11px;grid-template-columns:20px minmax(0,1fr) auto;align-items:start;gap:10px;padding:10px 14px 4px;display:grid}.gNoOdq_toolHeading:hover{background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_toolHeading:focus-visible{outline-offset:-3px!important}.gNoOdq_toolGlyph{height:22px;color:var(--dsw-alias-label-secondary);justify-content:center;align-items:center;display:flex}.gNoOdq_toolHeadingCopy{flex-direction:column;gap:3px;min-width:0;display:flex}.gNoOdq_toolTitle{overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:22px}.gNoOdq_toolTarget{-webkit-line-clamp:2;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary);-webkit-box-orient:vertical;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:19px;display:-webkit-box;overflow:hidden}.gNoOdq_toolHeadingState{min-height:22px;color:var(--dsw-alias-label-secondary);align-items:center;gap:7px;display:flex}.gNoOdq_diffStat{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;flex:none;gap:6px;margin-left:8px;font-size:11px;line-height:18px;display:inline-flex}.gNoOdq_diffAdded{color:var(--dsw-alias-state-success-primary,#2f9e63)}.gNoOdq_diffRemoved{color:var(--dsw-alias-state-error-primary,#d1483c)}.gNoOdq_summaryRow{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;max-width:100%;display:flex}.gNoOdq_summaryRow>.gNoOdq_diffStatRoot{flex:none;margin-left:auto}.gNoOdq_summaryRow>:first-child{min-width:0}.gNoOdq_diffStatRoot{flex:none;position:relative}.gNoOdq_diffStatButton{cursor:pointer;font:inherit;font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";color:var(--dsw-alias-label-secondary);background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:6px;padding:2px 8px;font-size:11px;line-height:16px;transition:background .12s,border-color .12s;display:inline-flex}.gNoOdq_diffStatButton:hover,.gNoOdq_diffStatButton:focus-visible,.gNoOdq_diffStatButton[aria-expanded=true]{background:var(--dsw-alias-bg-module-platform,#7f7f7f1a);border-color:var(--dsw-alias-border-l2,#7f7f7f47)}.gNoOdq_diffStatButton:focus-visible{outline:none}.gNoOdq_diffStatButton[aria-expanded=true] .gNoOdq_diffCaret{opacity:1}.gNoOdq_diffOverlayRow{box-sizing:border-box;flex:100%;width:100%;min-width:0;max-width:100%;margin-top:6px}.gNoOdq_diffOverlay{box-sizing:border-box;background:var(--dsw-alias-bg-module-platform,#7f7f7f14);border:1px solid var(--dsw-alias-border-l2,#80808038);border-radius:10px;flex-direction:column;width:100%;min-width:0;max-width:100%;padding:8px;display:flex;overflow:hidden}.gNoOdq_diffTabs{scrollbar-width:thin;flex-wrap:nowrap;gap:6px;max-width:100%;margin-bottom:4px;padding-bottom:6px;display:flex;overflow-x:auto}.gNoOdq_diffTab{text-overflow:ellipsis;white-space:nowrap;cursor:pointer;max-width:220px;font:inherit;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-base,#fffc);border:1px solid var(--dsw-alias-border-l2,#80808033);border-radius:6px;flex:none;padding:3px 10px;font-size:11px;line-height:16px;transition:all .12s;overflow:hidden}.gNoOdq_diffTab:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.gNoOdq_diffTab[data-active]{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-state-business-primary,#1e90ff);background:var(--dsw-alias-bg-base);font-weight:500}.gNoOdq_diffScrollArea{overscroll-behavior:contain;-webkit-overflow-scrolling:touch;border:1px solid var(--dsw-alias-border-l2,#80808026);background:var(--dsw-alias-markdown-code-block,#0000000a);border-radius:8px;max-height:420px;overflow:auto}.gNoOdq_diffScrollArea [data-diff]{background:0 0!important;border-radius:0!important;margin:0!important}.gNoOdq_diffCaret{opacity:.6;flex:none;width:10px;font-size:10px}.gNoOdq_diffPath{text-overflow:ellipsis;white-space:nowrap;text-align:left;direction:rtl;flex:auto;min-width:0;overflow:hidden}.gNoOdq_diffStat{font-variant-numeric:tabular-nums;flex:none;gap:6px;font-size:11px;display:inline-flex}.gNoOdq_diffHunkBody{flex-direction:column;gap:4px;padding:2px 7px 7px 25px;display:flex}.gNoOdq_diffLines{font-size:11px;line-height:1.55;font-family:var(--dsw-font-mono,ui-monospace, SFMono-Regular, Menlo, monospace);white-space:pre;border-radius:6px;margin:0;padding:6px 8px;overflow-x:auto}.gNoOdq_diffLines[data-side=removed]{background:#d1483c1f}.gNoOdq_diffLines[data-side=added]{background:#2f9e631f}.gNoOdq_diffLineRemoved,.gNoOdq_diffLineAdded{display:block}.gNoOdq_diffLineRemoved{color:var(--dsw-alias-state-error-primary,#d1483c)}.gNoOdq_diffLineAdded{color:var(--dsw-alias-state-success-primary,#2f9e63)}.gNoOdq_diffEmpty{color:var(--dsw-alias-label-secondary);margin:0;padding:2px 0;font-size:11px}.gNoOdq_nativeToolSummary[data-running]{background-image:linear-gradient(90deg, currentColor 0%, currentColor 35%, color-mix(in srgb, currentColor 35%, transparent) 50%, currentColor 65%, currentColor 100%);-webkit-text-fill-color:transparent;background-position:100% 0;background-repeat:no-repeat;background-size:300% 100%;background-clip:text;animation:1.6s linear infinite gNoOdq_readerStepShimmer}@keyframes gNoOdq_readerStepShimmer{to{background-position:0 0}}.gNoOdq_toolElapsed[data-slow]{opacity:1;color:var(--dsw-alias-state-warning-primary,#d8862c);font-weight:500}.gNoOdq_toolElapsed{opacity:.72;font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;flex:none;margin-left:8px;font-size:11px;line-height:18px}[data-motion=off] .gNoOdq_nativeToolSummary[data-running]{-webkit-text-fill-color:currentColor;background-image:none;animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_nativeToolSummary[data-running]{-webkit-text-fill-color:currentColor;background-image:none;animation:none!important}}.gNoOdq_toolState{white-space:nowrap;flex:none;margin-left:8px;font-size:11px;line-height:18px}.gNoOdq_toolState[data-phase=preparing],.gNoOdq_toolState[data-phase=running]{color:var(--dsw-alias-state-business-primary)}.gNoOdq_toolState[data-phase=preparing]:before,.gNoOdq_toolState[data-phase=running]:before{content:\"\";vertical-align:middle;background:currentColor;border-radius:50%;width:6px;height:6px;margin-right:6px;animation:1.4s ease-in-out infinite gNoOdq_readerRunningGlow;display:inline-block}@keyframes gNoOdq_readerRunningGlow{0%{box-shadow:0 0 0 0 color-mix(in srgb, currentColor 60%, transparent);opacity:1}70%{opacity:.7;box-shadow:0 0 0 7px #0000}to{opacity:1;box-shadow:0 0 #0000}}[data-motion=off] .gNoOdq_toolState[data-phase=preparing]:before,[data-motion=off] .gNoOdq_toolState[data-phase=running]:before{animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_toolState[data-phase=preparing]:before,.gNoOdq_toolState[data-phase=running]:before{animation:none!important}}.gNoOdq_toolState[data-phase=failed]{color:var(--dsw-alias-state-error-primary)}.gNoOdq_toolState[data-phase=interrupted]{color:inherit;opacity:.7}.gNoOdq_toolLedger{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:10px 14px 0;font-size:11px;line-height:18px;display:flex}.gNoOdq_toolEngine{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gNoOdq_toolDetails{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;min-width:0;margin:6px 0 0 22px;overflow:hidden}.gNoOdq_toolTabs{align-items:center;gap:15px;padding:0 14px;display:flex}.gNoOdq_toolTabs>button{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-bottom:2px solid #0000;padding:10px 1px 8px;font-size:12px;line-height:20px}.gNoOdq_toolTabs>button[aria-selected=true]{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsw-alias-state-business-primary)}.gNoOdq_toolPanel{flex-direction:column;gap:12px;min-width:0;padding:12px 14px 14px;font-size:13px;line-height:22px;display:flex}.gNoOdq_toolPanel:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-3px}.gNoOdq_toolDetailNote{color:var(--dsw-alias-label-secondary);margin:0 0 9px;font-size:12px;line-height:20px}.gNoOdq_toolRawLabel{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;font-weight:500}.gNoOdq_toolRaw{background:var(--dsw-alias-bg-module-platform);max-height:400px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;margin:0;padding:12px;font:12px/20px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:auto}.gNoOdq_systemPrompt{background:var(--dsw-alias-bg-module-platform);max-height:320px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;margin:0;padding:12px;font:12px/20px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:auto}.gNoOdq_commandInput{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.gNoOdq_toolReceipt .gNoOdq_blocks,.gNoOdq_toolDocument .gNoOdq_blocks{font-size:13px;line-height:22px}.gNoOdq_toolChildren{margin:0 14px 12px var(--reader-rail,6px);padding-left:var(--reader-gutter,16px);border-left:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:9px;display:flex}@container (width<=420px){.gNoOdq_toolHeading{grid-template-columns:16px minmax(0,1fr) auto;gap:7px;padding:11px 10px 6px}.gNoOdq_toolHeadingState{gap:4px}.gNoOdq_toolLedger{padding-left:33px;padding-right:10px}.gNoOdq_toolPanel{padding:10px}}@media (pointer:coarse){.gNoOdq_toolTabs>button{min-height:44px}}.gNoOdq_reasonCard{--reason-preview-height:224px;--reason-hold:.84s;--reason-step:.5s;--reason-lines:2;--reason-fade:28px;--reason-ease:cubic-bezier(.22, 1, .36, 1);border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);min-width:0;scroll-margin-block:16px calc(var(--dsh-composer-height,152px) + 16px);border-radius:12px;position:relative;overflow:hidden}.gNoOdq_reasonHeading{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:baseline;gap:12px;padding:10px 16px 0;font-size:12px;line-height:20px;display:flex}.gNoOdq_reasonCard[data-overflow=false][data-expanded=false]{background:0 0;border-color:#0000;border-radius:0}.gNoOdq_reasonCard[data-overflow=false][data-expanded=false] .gNoOdq_reasonHeading{padding:0}.gNoOdq_reasonCard[data-overflow=false][data-expanded=false] .gNoOdq_reasonText{padding:4px 0 0 22px}.gNoOdq_reasonLabel{font-weight:500}.gNoOdq_reasonViewport{max-height:var(--reason-preview-height);scroll-behavior:auto;overflow-anchor:none;overscroll-behavior-y:contain;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l1) transparent;position:relative;overflow:auto}.gNoOdq_reasonCard[data-expanded=true] .gNoOdq_reasonViewport{max-height:min(60vh, 560px, var(--reason-reading-height,560px))}.gNoOdq_reasonViewport[data-edges=both],.gNoOdq_reasonCard[data-following=true][data-overflow=true] .gNoOdq_reasonViewport{-webkit-mask-image:linear-gradient(transparent 0, black var(--reason-fade), black calc(100% - var(--reason-fade)), transparent 100%);mask-image:linear-gradient(transparent 0, black var(--reason-fade), black calc(100% - var(--reason-fade)), transparent 100%)}.gNoOdq_reasonViewport[data-edges=top]{-webkit-mask-image:linear-gradient(transparent 0, black var(--reason-fade), black 100%);mask-image:linear-gradient(transparent 0, black var(--reason-fade), black 100%)}.gNoOdq_reasonViewport[data-edges=bottom]{-webkit-mask-image:linear-gradient(black 0, black calc(100% - var(--reason-fade)), transparent 100%);mask-image:linear-gradient(black 0, black calc(100% - var(--reason-fade)), transparent 100%)}.gNoOdq_reasonCard[data-expanded=true] .gNoOdq_reasonViewport{mask-image:none}.gNoOdq_reasonViewport:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-3px}.gNoOdq_reasonTrack{position:relative;transform:translateY(0)}.gNoOdq_reasonCard[data-following=true] .gNoOdq_reasonTrack{will-change:transform}.gNoOdq_reasonText{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;padding:8px 16px 16px;font-size:14px;line-height:24px}.gNoOdq_reasonText .gNoOdq_readingText>div{font-size:inherit;line-height:inherit;color:inherit}.gNoOdq_reasonFooter{color:var(--dsw-alias-label-secondary);justify-content:space-between;align-items:center;gap:8px;padding:2px 10px 8px;font-size:12px;line-height:20px;display:flex}.gNoOdq_reasonAction{min-height:28px;color:inherit;font:inherit;cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:6px;justify-content:center;align-items:center;gap:5px;padding:4px 6px;display:inline-flex}.gNoOdq_reasonAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_reasonAction:disabled{cursor:default;opacity:.65}.gNoOdq_reasonAction svg{fill:none;stroke:currentColor;stroke-width:1.3px;stroke-linecap:round;stroke-linejoin:round;flex:none}.gNoOdq_reasonCaption{padding-left:6px}@container (width<=480px){.gNoOdq_reasonCard{--reason-preview-height:192px}}@media (pointer:coarse){.gNoOdq_reasonAction{min-height:44px}}@media (prefers-reduced-motion:reduce){.gNoOdq_reasonTrack{will-change:auto!important;transition:none!important;transform:none!important}}@media (forced-colors:active){.gNoOdq_reasonViewport{mask-image:none!important}}.gNoOdq_processItem,.gNoOdq_tool{min-width:0;margin:0 0 18px}.gNoOdq_processLabel{color:var(--dsw-alias-label-tertiary);align-items:baseline;gap:12px;margin:0 0 6px;font-size:12px;line-height:20px;display:flex}.gNoOdq_processFootnote{color:var(--dsw-alias-label-tertiary);margin:14px 0 0;font-size:12px;line-height:20px}.gNoOdq_detail{color:var(--dsw-alias-label-secondary);font-size:13px;line-height:22px}.gNoOdq_detail>summary{cursor:pointer;padding:3px 0}.gNoOdq_detail[open]>summary{margin-bottom:8px}.gNoOdq_tool>.gNoOdq_tool{margin:10px 0 0 12px}.gNoOdq_meta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}.gNoOdq_stopped{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-tertiary);border-radius:6px;align-self:flex-start;margin-top:12px;padding:0 6px;font-size:11px;line-height:18px}.gNoOdq_compactionRow{box-sizing:border-box;flex-direction:column;align-items:center;width:100%;margin:16px 0;display:flex}.gNoOdq_compactionLine{width:100%;color:var(--dsw-alias-label-tertiary);-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;gap:12px;font-size:11px;line-height:18px;display:flex}.gNoOdq_compactionLine:before,.gNoOdq_compactionLine:after{content:\"\";background:var(--dsw-alias-border-l1);opacity:.7;flex:1;height:1px}.gNoOdq_compactionRow>.gNoOdq_compactionLine{animation:.52s cubic-bezier(.4,0,.2,1) both gNoOdq_compactionLineIn}.gNoOdq_compactionRow>.gNoOdq_compactionLine>.gNoOdq_compactionPill{animation:.42s cubic-bezier(.34,1.4,.64,1) .12s both gNoOdq_compactionPillIn}.gNoOdq_compactionRow>.gNoOdq_compactionLine .gNoOdq_compactionIcon{animation:.9s cubic-bezier(.4,0,.2,1) .2s both gNoOdq_compactionDial}@keyframes gNoOdq_compactionLineIn{0%{opacity:0;transform:scaleX(.6)}to{opacity:1;transform:scaleX(1)}}@keyframes gNoOdq_compactionPillIn{0%{opacity:0;transform:translateY(-6px)scale(.94)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes gNoOdq_compactionDial{0%{opacity:0;transform:rotate(-140deg)}to{opacity:.7;transform:rotate(0)}}[data-motion=off] .gNoOdq_compactionRow>.gNoOdq_compactionLine,[data-motion=off] .gNoOdq_compactionRow>.gNoOdq_compactionLine>.gNoOdq_compactionPill,[data-motion=off] .gNoOdq_compactionRow>.gNoOdq_compactionLine .gNoOdq_compactionIcon{animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_compactionRow>.gNoOdq_compactionLine,.gNoOdq_compactionRow>.gNoOdq_compactionLine>.gNoOdq_compactionPill,.gNoOdq_compactionRow>.gNoOdq_compactionLine .gNoOdq_compactionIcon{animation:none!important}}.gNoOdq_compactionPill{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);border-radius:12px;align-items:center;gap:6px;padding:2px 10px;font-family:inherit;font-size:11px;line-height:18px;display:inline-flex}.gNoOdq_compactionButton{cursor:pointer;transition:color .14s,border-color .14s,background-color .14s}.gNoOdq_compactionButton:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_compactionIcon{opacity:.7;flex:none;width:12px;height:12px}.gNoOdq_compactionToggle{opacity:.8;margin-left:2px;font-size:10px}.gNoOdq_compactionSummaryBox{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);width:100%;max-width:680px;color:var(--dsw-alias-label-secondary);box-sizing:border-box;border-radius:8px;margin-top:10px;padding:12px 16px;font-size:12px;line-height:20px}.gNoOdq_compactionSummaryHeader{color:var(--dsw-alias-label-tertiary);border-bottom:1px dashed var(--dsw-alias-border-l1);margin-bottom:8px;padding-bottom:4px;font-size:11px;font-weight:500}.gNoOdq_notice,.gNoOdq_error,.gNoOdq_attention{overflow-wrap:anywhere;border-radius:10px;padding:12px 14px;font-size:13px;line-height:20px}.gNoOdq_notice{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border:1px solid var(--dsw-alias-border-l2)}.gNoOdq_error{color:var(--dsw-alias-label-primary);background:#ef44440f;border:1px solid #ef444438;align-items:flex-start;gap:10px;display:flex}.gNoOdq_errorIcon{color:#ef4444;flex:none;width:16px;height:16px;margin-top:2px}.gNoOdq_errorCopy{flex:1;min-width:0}.gNoOdq_errorTitle{color:#dc2626;align-items:center;gap:8px;margin-bottom:2px;font-weight:500;display:flex}.gNoOdq_errorMessage{color:var(--dsw-alias-label-secondary);word-break:break-word;margin:0;font-size:12px;line-height:18px}.gNoOdq_errorCode{color:#dc2626;background:#ef44441f;border-radius:4px;padding:1px 5px;font-family:inherit;font-size:11px}.gNoOdq_attention{border:1px solid var(--dsw-alias-state-business-primary);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);flex-direction:column;gap:3px;display:flex}.gNoOdq_attention span{color:var(--dsw-alias-label-secondary)}.gNoOdq_unknown{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:12px 14px;font-size:13px;line-height:22px}.gNoOdq_unknown p{margin:0 0 6px}.gNoOdq_historyButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0;border-radius:8px;align-self:center;padding:4px 12px;font-size:12px}.gNoOdq_historyButton:disabled{opacity:.55;cursor:default}.gNoOdq_empty{color:var(--dsw-alias-label-tertiary);text-align:center;padding:40px 0}.gNoOdq_answerActions{align-items:center;gap:8px;min-height:28px;margin:13px 0 0 -6px;display:flex}.gNoOdq_userActions{align-items:center;gap:8px;min-height:28px;display:flex}.gNoOdq_messageClock{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:13px;line-height:24px}.gNoOdq_iconButton{color:var(--dsw-alias-label-tertiary);background:0 0;border:0;border-radius:6px;justify-content:center;align-items:center;padding:6px;display:inline-flex}.gNoOdq_iconButton svg{fill:none;stroke:currentColor;stroke-width:1.2px;stroke-linecap:round;stroke-linejoin:round}.gNoOdq_imageFigure{box-sizing:border-box;align-self:flex-start;width:min(100%,360px);max-width:100%;margin:0}.gNoOdq_imageFrame{background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);box-sizing:border-box;border-radius:12px;max-width:100%;min-height:96px;max-height:440px;position:relative;overflow:hidden}.gNoOdq_imageOpen{background:0 0;border:0;width:100%;height:100%;padding:0;display:flex;position:absolute;inset:0}.gNoOdq_imageOpen img{object-fit:contain;opacity:0;width:100%;height:100%;transition:opacity .2s cubic-bezier(.4,0,.2,1);display:block}.gNoOdq_imageOpen img[data-ready=true]{opacity:1}.gNoOdq_pendingImage{object-fit:contain;width:100%;max-width:100%;height:100%;display:block}.gNoOdq_imagePlaceholder{color:var(--dsw-alias-label-tertiary);pointer-events:none;flex-direction:column;justify-content:center;align-items:center;gap:8px;font-size:13px;display:flex;position:absolute;inset:0}.gNoOdq_imagePlaceholder button{pointer-events:auto}.gNoOdq_imageFigure figcaption{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin-top:6px;font-size:12px;line-height:20px}.gNoOdq_imageDialog{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border-radius:16px;max-width:90vw;max-height:90vh;padding:38px 20px 20px}.gNoOdq_imageDialog::backdrop{background:var(--dsw-alias-bg-mask-photo)}.gNoOdq_imageDialog img{object-fit:contain;max-width:82vw;max-height:75vh;display:block}.gNoOdq_dialogClose{color:inherit;background:0 0;border:0;border-radius:8px;width:32px;height:32px;font-size:24px;position:absolute;top:4px;right:8px}.gNoOdq_jumpDock{bottom:calc(var(--dsh-composer-height,152px) + 16px);z-index:8;pointer-events:none;justify-content:flex-end;height:0;display:flex;position:sticky}.gNoOdq_deliverablesRoot{grid-template-columns:max-content minmax(0,1fr);align-items:start;column-gap:10px;margin-top:14px;font-size:13px;line-height:22px;display:grid}.gNoOdq_deliverablesLabel{color:var(--dsw-alias-label-tertiary);grid-area:1/1;padding-top:2px;font-size:12px;font-weight:500}.gNoOdq_deliverablesLane{grid-area:1/2;min-width:0}.gNoOdq_deliverablesRow{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;display:flex}.gNoOdq_deliverableChip{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;font-size:12px;line-height:20px;transition:border-color .16s,background-color .16s,color .16s;display:inline-flex;overflow:hidden}.gNoOdq_deliverableChip:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-bg-module-platform);box-shadow:0 1px 4px var(--dsw-alias-border-l1)}.gNoOdq_deliverableChip[data-status=opened]{color:#059669;background:#10b9811f;border-color:#10b981}.gNoOdq_chipMain{max-width:220px;color:inherit;font:inherit;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:5px;padding:3px 6px 3px 8px;display:inline-flex}.gNoOdq_chipMain:hover{color:var(--dsw-alias-label-primary)}.gNoOdq_deliverableIcon,.gNoOdq_statusIcon{opacity:.8;flex:none;width:13px;height:13px}.gNoOdq_statusIcon{color:#10b981}.gNoOdq_deliverableName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.gNoOdq_chipActions{opacity:.65;border-left:1px solid #0000;align-items:center;gap:2px;padding-right:4px;transition:opacity .15s,border-left-color .15s;display:inline-flex}.gNoOdq_deliverableChip:hover .gNoOdq_chipActions{opacity:1;border-left-color:var(--dsw-alias-border-l2)}.gNoOdq_chipActionBtn{width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;transition:color .12s,background-color .12s;display:inline-flex}.gNoOdq_chipActionBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_actionIcon{width:12px;height:12px}.gNoOdq_deliverablesMore{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:12px}.gNoOdq_deliverablesShowFolder{color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:5px;align-items:center;gap:4px;padding:2px 7px;font-size:12px;transition:all .15s;display:inline-flex}.gNoOdq_deliverablesShowFolder:hover{color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}.gNoOdq_deliverablesShowFolder[data-status=opened]{color:#10b981;background:#10b98114;border-color:#10b9814d}.gNoOdq_morphCluster{flex-direction:column;width:100%;min-width:0;display:flex}.gNoOdq_morphDrawer{transform-origin:top;will-change:height, opacity, transform;height:0;overflow:hidden}.gNoOdq_liveFoldImpact{animation:.18s cubic-bezier(.2,0,0,1) both gNoOdq_liveFoldElastic}@keyframes gNoOdq_liveFoldElastic{0%{transform:scale(1)}50%{transform:scale(1.015)}to{transform:scale(1)}}.gNoOdq_liveFoldContainer{top:calc(var(--reader-toolbar-height,var(--reader-lane-block,40px)) + var(--reader-status-height,var(--reader-lane-block,40px)) + var(--reader-summary-height,var(--reader-lane-block,40px)));z-index:4;background:var(--dsw-alias-bg-base);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);transform-origin:0;will-change:transform, opacity;margin-bottom:6px;padding:4px 0;animation:.32s cubic-bezier(.16,1,.3,1) both gNoOdq_liveFoldPulse;position:sticky}@keyframes gNoOdq_liveFoldPulse{0%{opacity:.8;transform:translateY(-4px)scale(.98)}50%{opacity:1;transform:translateY(0)scale(1.02)}to{opacity:1;transform:translateY(0)scale(1)}}[data-motion=off] .gNoOdq_liveFoldContainer{animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_liveFoldContainer{animation:none!important}}.gNoOdq_priorFoldDrawer{flex-direction:column;gap:14px;width:100%;min-width:0;display:flex}.gNoOdq_jump{width:34px;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-button-floating-fill,var(--dsw-alias-bg-base));box-shadow:var(--dsw-elevation-panel,0 2px 8px var(--dsw-alias-border-l1));pointer-events:auto;border:0;border-radius:100px;flex:none;justify-content:center;align-items:center;margin-top:-34px;padding:0;display:flex}.gNoOdq_jump:hover{background:var(--dsw-alias-button-floating-hover,var(--dsw-alias-interactive-bg-hover))}.gNoOdq_foldSummary{text-overflow:ellipsis;align-items:baseline;max-width:100%;display:inline-flex;overflow:hidden;white-space:nowrap!important}.gNoOdq_foldSummaryPart{flex:none;align-items:baseline;display:inline-flex;white-space:nowrap!important}.gNoOdq_numberRollRoot{vertical-align:baseline;line-height:inherit;font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";text-align:center;flex-shrink:0;justify-content:center;min-width:1.45em;display:inline-flex;position:relative;overflow:hidden;white-space:nowrap!important}.gNoOdq_numberRollSizer{visibility:hidden;-webkit-user-select:none;user-select:none;pointer-events:none;line-height:inherit;white-space:nowrap}.gNoOdq_numberRollDigit{line-height:inherit;white-space:nowrap;justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.gNoOdq_numberRollExit{animation:.24s cubic-bezier(.16,1,.3,1) forwards gNoOdq_numberRollOut}.gNoOdq_numberRollEnter{animation:.24s cubic-bezier(.16,1,.3,1) forwards gNoOdq_numberRollIn}@keyframes gNoOdq_numberRollOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-100%)}}@keyframes gNoOdq_numberRollIn{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}[data-motion=off] .gNoOdq_chevron,[data-motion=off] .gNoOdq_imageOpen img,[data-motion=off] .gNoOdq_processMeta,[data-motion=off] .gNoOdq_numberRollDigit{transition:none!important;animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_chevron,.gNoOdq_imageOpen img,.gNoOdq_processMeta,.gNoOdq_numberRollDigit{transition:none!important;animation:none!important}}.gNoOdq_turnStatus{white-space:nowrap;flex:none;align-self:flex-start;align-items:center;height:26px;margin:4px 0 12px;padding:0 4px;font-size:14px;line-height:22px;display:inline-flex}.gNoOdq_turnStatusLabel{background:linear-gradient(90deg, var(--dsw-static-deepseek-500,#4d6bfe) 0%, var(--dsw-static-deepseek-500,#4d6bfe) 40%, var(--dsw-static-deepseek-200,#a8c7fa) 50%, var(--dsw-static-deepseek-500,#4d6bfe) 60%, var(--dsw-static-deepseek-500,#4d6bfe) 100%);color:#0000;-webkit-text-fill-color:transparent;background-position:100% 0;background-size:250% 100%;background-clip:text;font-weight:500;animation:1.8s linear infinite gNoOdq_dsh-turn-status-shimmer}.gNoOdq_waitClock{flex:none;align-items:center;margin-left:8px;display:inline-flex}.gNoOdq_waitSeconds{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";color:var(--dsw-alias-label-caption,#86909c);font-size:13px;font-weight:400}.gNoOdq_waitOvertime{color:var(--dsw-alias-state-warning-primary,#d8862c);background:color-mix(in srgb, var(--dsw-alias-state-warning-primary,#d8862c) 16%, transparent);border-radius:5px;margin-left:8px;padding:0 6px;font-size:11px;line-height:16px}.gNoOdq_turnStatusClock{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";color:var(--dsw-alias-label-caption,#86868b);-webkit-text-fill-color:var(--dsw-alias-label-caption,#86868b);margin-left:8px;font-size:13px;font-weight:400}@keyframes gNoOdq_dsh-turn-status-shimmer{to{background-position:0 0}}[data-motion=off] .gNoOdq_turnStatusLabel{color:var(--dsw-static-deepseek-500,#4d6bfe)!important;-webkit-text-fill-color:var(--dsw-static-deepseek-500,#4d6bfe)!important;animation:none!important}@media (prefers-reduced-motion:reduce){.gNoOdq_turnStatusLabel{color:var(--dsw-static-deepseek-500,#4d6bfe)!important;-webkit-text-fill-color:var(--dsw-static-deepseek-500,#4d6bfe)!important;animation:none!important}}@media (pointer:coarse){.gNoOdq_disclosureButton{min-height:44px}}@media (width<=600px){.gNoOdq_root{padding-inline:20px}.gNoOdq_column{gap:18px}.gNoOdq_toolbar{font-size:11px}}.gNoOdq_choreographedFlow{overflow-anchor:none;flex-direction:column;min-width:0;display:flex}.gNoOdq_flowCell{min-width:0;display:flow-root;overflow:clip}.gNoOdq_flowCell[hidden]{display:none}.gNoOdq_flowCellInner{flex-direction:column;min-width:0;padding-bottom:16px;display:flex}.gNoOdq_flowCellInner:empty{padding-bottom:0}.gNoOdq_choreographedFlow[data-reader-transition=collapse] .gNoOdq_flowCell *{animation-play-state:paused!important}.gNoOdq_numberRollExit,.gNoOdq_numberRollEnter{animation-duration:.16s}.gNoOdq_foldSummary{align-items:baseline;display:inline-flex;white-space:nowrap!important;flex-wrap:nowrap!important}.gNoOdq_toolbar{box-sizing:border-box;width:100%;max-width:100%;min-height:var(--reader-lane-block,40px);z-index:7;-webkit-backdrop-filter:none;backdrop-filter:none;border-bottom:0;align-self:stretch}.gNoOdq_turnProcessSticky{box-sizing:border-box;width:calc(100% - var(--reader-control-width,148px));top:var(--reader-toolbar-height,var(--reader-lane-block,40px));min-height:var(--reader-lane-block,40px);z-index:6;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:0 -14px 0 var(--dsw-alias-bg-base), var(--reader-control-width,148px) 0 0 var(--dsw-alias-bg-base), 0 -14px 0 var(--dsw-alias-bg-layer-1,transparent), var(--reader-control-width,148px) 0 0 var(--dsw-alias-bg-layer-1,transparent), 0 -14px 0 Canvas, var(--reader-control-width,148px) 0 0 Canvas;background-clip:padding-box;border-bottom:1px solid #0000;padding-right:0}.gNoOdq_turnStickyLanes .gNoOdq_turnProcessSticky,.gNoOdq_turnStickyLanes .gNoOdq_closedProcessSummary{z-index:auto;position:static;top:auto}.gNoOdq_flowCell[data-flow-summary],.gNoOdq_closedProcessSummary{top:calc(var(--reader-toolbar-height,var(--reader-lane-block,40px)) + var(--reader-status-height,var(--reader-lane-block,40px)));z-index:5;box-sizing:border-box;min-height:var(--reader-lane-block,40px);background:var(--dsw-alias-bg-base);border-bottom:0;padding-block:4px;position:sticky;overflow:visible}.gNoOdq_root .md-code-block{z-index:0}.gNoOdq_turnStickyRegion:has(>.gNoOdq_turnStickyLanes>.gNoOdq_closedProcessSummary),.gNoOdq_turnStickyRegion:has(.gNoOdq_flowCell[data-flow-summary]){--reader-code-summary-height:var(--reader-summary-height,var(--reader-lane-block,40px))}.gNoOdq_root .md-code-block>:has(+[data-code-block-content]){top:calc(max(var(--reader-toolbar-height,40px), var(--reader-status-height,0px)) + var(--reader-status-height,0px) + var(--reader-code-summary-height,0px))}.gNoOdq_flowCell[data-flow-summary]{box-shadow:0 -16px 0 var(--dsw-alias-bg-base), 0 -16px 0 var(--dsw-alias-bg-layer-1,transparent), 0 -16px 0 Canvas}.gNoOdq_closedProcessSummary{box-shadow:0 -14px 0 var(--dsw-alias-bg-base), 0 -14px 0 var(--dsw-alias-bg-layer-1,transparent), 0 -14px 0 Canvas}.gNoOdq_foldControl{background:var(--dsw-alias-bg-module-platform);border-radius:8px;align-items:center;gap:0;padding:2px;display:inline-flex}.gNoOdq_foldStop{color:var(--dsw-alias-label-secondary);white-space:nowrap;font:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;padding:2px 8px;font-size:12px;line-height:18px}.gNoOdq_foldStop[data-on]{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary)}.gNoOdq_flowCell[data-flow-summary]>.gNoOdq_flowCellInner{padding-bottom:0}.gNoOdq_flowCell[data-flow-summary] .gNoOdq_disclosureButton,.gNoOdq_closedProcessSummary .gNoOdq_disclosureButton{width:auto;max-width:100%}.gNoOdq_flowCell[data-flow-summary] .gNoOdq_foldSummary,.gNoOdq_closedProcessSummary .gNoOdq_foldSummary{min-width:0}.gNoOdq_turnProcessSticky>.gNoOdq_disclosure{flex:auto;min-width:0}.gNoOdq_disclosureButton{width:max-content;max-width:calc(100% + 6px)}.gNoOdq_statusText{flex:0 auto}.gNoOdq_think{width:max-content;min-width:0}.gNoOdq_thinkSizer{white-space:normal;overflow-wrap:anywhere}.gNoOdq_thinkText{white-space:normal;overflow-wrap:anywhere;text-overflow:clip;overflow:visible}.gNoOdq_toolbar,.gNoOdq_turnStickyLanes,.gNoOdq_turnProcessSticky,.gNoOdq_liveFoldContainer,.gNoOdq_flowCell[data-flow-summary],.gNoOdq_closedProcessSummary{background-color:canvas;background-image:var(--reader-lane-plate);background-repeat:no-repeat}.gNoOdq_root[data-reader-glass] .gNoOdq_toolbar,.gNoOdq_root[data-reader-glass] .gNoOdq_turnProcessSticky,.gNoOdq_root[data-reader-glass] .gNoOdq_liveFoldContainer{-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);box-shadow:none;background:0 0;border:0;border-radius:0}.gNoOdq_root[data-reader-glass] .gNoOdq_toolbar,.gNoOdq_root[data-reader-glass] .gNoOdq_turnProcessSticky{-webkit-backdrop-filter:none;backdrop-filter:none}.gNoOdq_root[data-reader-glass] .gNoOdq_toolbar{pointer-events:none}.gNoOdq_root[data-reader-glass] .gNoOdq_toolbar>.gNoOdq_textButton,.gNoOdq_root[data-reader-glass] .gNoOdq_turnProcessSticky .gNoOdq_disclosureButton{pointer-events:auto;background:color-mix(in srgb, var(--dsw-alias-bg-layer-1,#ffffffb3) 80%, transparent);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-radius:999px;padding:2px 10px}.gNoOdq_root[data-reader-glass] .gNoOdq_turnProcessSticky .gNoOdq_disclosureButton{max-width:100%;margin-left:0}.gNoOdq_root[data-reader-glass] .gNoOdq_toolbar>.gNoOdq_textButton:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_turnProcessSticky .gNoOdq_disclosureButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.gNoOdq_root[data-reader-glass] .gNoOdq_flowCell[data-flow-summary],.gNoOdq_root[data-reader-glass] .gNoOdq_closedProcessSummary{box-shadow:none;z-index:auto;border-left:2px solid color-mix(in srgb, var(--dsw-alias-border-l2,#80808059) 80%, transparent);padding-block:2px;background:0 0;border-radius:0;min-height:32px;padding-left:10px;position:static}.gNoOdq_root[data-reader-glass] .gNoOdq_turnStickyLanes{z-index:auto;display:contents;position:static;top:auto}.gNoOdq_root[data-reader-glass] .gNoOdq_turnStickyRegion{--reader-code-summary-height:0px}.gNoOdq_root[data-reader-glass] .gNoOdq_turnStickyLanes .gNoOdq_turnProcessSticky{top:var(--reader-toolbar-height,var(--reader-lane-block,40px));z-index:6;position:sticky}.gNoOdq_root[data-reader-glass] .gNoOdq_user{background:color-mix(in srgb, var(--dsw-specific-bubble,#00000014) 25%, transparent);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid color-mix(in srgb, var(--dsw-alias-border-l1,#8080804d) 30%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_reasonCard{border-color:color-mix(in srgb, var(--dsw-alias-border-l1,#80808059) 65%, transparent);background:0 0}.gNoOdq_root[data-reader-glass] .gNoOdq_toolDetails,.gNoOdq_root[data-reader-glass] .gNoOdq_notice,.gNoOdq_root[data-reader-glass] .gNoOdq_unknown,.gNoOdq_root[data-reader-glass] .gNoOdq_toolRaw,.gNoOdq_root[data-reader-glass] .gNoOdq_systemPrompt,.gNoOdq_root[data-reader-glass] .gNoOdq_compactionSummaryBox,.gNoOdq_root[data-reader-glass] .gNoOdq_attention,.gNoOdq_root[data-reader-glass] .gNoOdq_imageFrame,.gNoOdq_root[data-reader-glass] .gNoOdq_imageDialog{background:0 0}.gNoOdq_root[data-reader-glass] .gNoOdq_diffOverlay{background:color-mix(in srgb, var(--dsw-alias-bg-module-platform,#7f7f7f1a) 20%, transparent);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.gNoOdq_root[data-reader-glass] .gNoOdq_diffScrollArea{background:0 0}.gNoOdq_root[data-reader-glass] .gNoOdq_diffTab{background:color-mix(in srgb, var(--dsw-alias-bg-base,#fffc) 25%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_diffTab[data-active]{background:color-mix(in srgb, var(--dsw-alias-bg-base,#fff) 45%, transparent)}:is(.gNoOdq_root[data-reader-glass] .md-code-block,.gNoOdq_root[data-reader-glass] [data-diff]){border:1px solid color-mix(in srgb, var(--dsw-alias-border-l1,#80808033) 30%, transparent);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);background:color-mix(in srgb, var(--dsw-alias-markdown-code-block,#0000000f) 25%, transparent)!important}.gNoOdq_root[data-reader-glass] .gNoOdq_foldControl{background:color-mix(in srgb, var(--dsw-alias-bg-module-platform,#7f7f7f1a) 25%, transparent);border:1px solid color-mix(in srgb, var(--dsw-alias-border-l2,#80808033) 30%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_foldStop[data-on]{background:color-mix(in srgb, var(--dsw-alias-bg-base,#fff) 35%, transparent)}.gNoOdq_root[data-reader-glass] .gNoOdq_compactionPill,.gNoOdq_root[data-reader-glass] .gNoOdq_deliverableChip,.gNoOdq_root[data-reader-glass] .gNoOdq_toolState,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton{background:0 0;border-color:#0000}.gNoOdq_root[data-reader-glass] .gNoOdq_compactionPill:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_compactionPill:focus-visible,.gNoOdq_root[data-reader-glass] .gNoOdq_deliverableChip:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_deliverableChip:focus-within,.gNoOdq_root[data-reader-glass] .gNoOdq_toolState:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton:hover,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton:focus-visible,.gNoOdq_root[data-reader-glass] .gNoOdq_diffStatButton[aria-expanded=true]{background:var(--dsw-alias-bg-module-platform,#7f7f7f1a);border-color:var(--dsw-alias-border-l2,#7f7f7f47)}";
|
|
42427
42740
|
const tagId$5 = "dsh-better-display/Reader.module.css";
|
|
42428
42741
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
|
|
42429
42742
|
const tag = document.createElement("style");
|
|
@@ -42534,7 +42847,6 @@ ${trimmed}
|
|
|
42534
42847
|
"numberRollSizer": "gNoOdq_numberRollSizer",
|
|
42535
42848
|
"pendingImage": "gNoOdq_pendingImage",
|
|
42536
42849
|
"priorFoldDrawer": "gNoOdq_priorFoldDrawer",
|
|
42537
|
-
"processCommentary": "gNoOdq_processCommentary",
|
|
42538
42850
|
"processContents": "gNoOdq_processContents",
|
|
42539
42851
|
"processFootnote": "gNoOdq_processFootnote",
|
|
42540
42852
|
"processFrame": "gNoOdq_processFrame",
|
|
@@ -42543,6 +42855,7 @@ ${trimmed}
|
|
|
42543
42855
|
"processMeta": "gNoOdq_processMeta",
|
|
42544
42856
|
"processMetaInner": "gNoOdq_processMetaInner",
|
|
42545
42857
|
"processMetaLine": "gNoOdq_processMetaLine",
|
|
42858
|
+
"processSeamRow": "gNoOdq_processSeamRow",
|
|
42546
42859
|
"readerRunningGlow": "gNoOdq_readerRunningGlow",
|
|
42547
42860
|
"readerStepShimmer": "gNoOdq_readerStepShimmer",
|
|
42548
42861
|
"readingText": "gNoOdq_readingText",
|
|
@@ -42600,6 +42913,8 @@ ${trimmed}
|
|
|
42600
42913
|
"turnStatus": "gNoOdq_turnStatus",
|
|
42601
42914
|
"turnStatusClock": "gNoOdq_turnStatusClock",
|
|
42602
42915
|
"turnStatusLabel": "gNoOdq_turnStatusLabel",
|
|
42916
|
+
"turnStickyLanes": "gNoOdq_turnStickyLanes",
|
|
42917
|
+
"turnStickyRegion": "gNoOdq_turnStickyRegion",
|
|
42603
42918
|
"unknown": "gNoOdq_unknown",
|
|
42604
42919
|
"user": "gNoOdq_user",
|
|
42605
42920
|
"userActions": "gNoOdq_userActions",
|
|
@@ -42765,8 +43080,218 @@ ${trimmed}
|
|
|
42765
43080
|
});
|
|
42766
43081
|
}
|
|
42767
43082
|
//#endregion
|
|
43083
|
+
//#region src/client/text-transform.ts
|
|
43084
|
+
/**
|
|
43085
|
+
* Cordis service name. Another client plugin lists this in `inject` and
|
|
43086
|
+
* registers a transformer. The reading view paints the result. The session
|
|
43087
|
+
* block, transcript, and fold inputs stay on the original text.
|
|
43088
|
+
*/
|
|
43089
|
+
const TEXT_TRANSFORM_SERVICE = "dsh-better-display.text-transform";
|
|
43090
|
+
const KINDS = /* @__PURE__ */ new Set(["reasoning", "body"]);
|
|
43091
|
+
function isKind(value) {
|
|
43092
|
+
return KINDS.has(value);
|
|
43093
|
+
}
|
|
43094
|
+
function reportTransformError(error) {
|
|
43095
|
+
console.warn("[dsh-better-display] text transform failed; showing original text", error);
|
|
43096
|
+
}
|
|
43097
|
+
function passthrough(request) {
|
|
43098
|
+
return {
|
|
43099
|
+
text: request.text,
|
|
43100
|
+
final: !request.streaming,
|
|
43101
|
+
transformRevision: 0,
|
|
43102
|
+
motionRevision: 0
|
|
43103
|
+
};
|
|
43104
|
+
}
|
|
43105
|
+
function normalize(value, request) {
|
|
43106
|
+
if (typeof value === "string") return {
|
|
43107
|
+
text: value,
|
|
43108
|
+
final: !request.streaming
|
|
43109
|
+
};
|
|
43110
|
+
if (!value || typeof value.text !== "string") return {
|
|
43111
|
+
text: request.text,
|
|
43112
|
+
final: !request.streaming
|
|
43113
|
+
};
|
|
43114
|
+
return {
|
|
43115
|
+
text: value.text,
|
|
43116
|
+
final: typeof value.final === "boolean" ? value.final : !request.streaming
|
|
43117
|
+
};
|
|
43118
|
+
}
|
|
43119
|
+
/**
|
|
43120
|
+
* Appends keep the motion revision. A replacement gets a new one so the
|
|
43121
|
+
* timeline treats the swapped string as already settled.
|
|
43122
|
+
*/
|
|
43123
|
+
function nextDisplayCursor(previous, display) {
|
|
43124
|
+
if (!previous) return {
|
|
43125
|
+
...display,
|
|
43126
|
+
transformRevision: 0,
|
|
43127
|
+
motionRevision: 0
|
|
43128
|
+
};
|
|
43129
|
+
if (previous.text === display.text && previous.final === display.final) return previous;
|
|
43130
|
+
const appended = display.text.startsWith(previous.text);
|
|
43131
|
+
return {
|
|
43132
|
+
text: display.text,
|
|
43133
|
+
final: display.final,
|
|
43134
|
+
transformRevision: previous.transformRevision + 1,
|
|
43135
|
+
motionRevision: appended ? previous.motionRevision : previous.motionRevision + 1
|
|
43136
|
+
};
|
|
43137
|
+
}
|
|
43138
|
+
/**
|
|
43139
|
+
* Streaming flag fed to the reveal. With no transformer this is the model's
|
|
43140
|
+
* flag. A transformer that reports `final: !streaming` produces the same flag.
|
|
43141
|
+
*/
|
|
43142
|
+
function displayStreaming(sourceStreaming, shown, active) {
|
|
43143
|
+
return active ? !shown.final : sourceStreaming;
|
|
43144
|
+
}
|
|
43145
|
+
var TextTransformRegistryImpl = class {
|
|
43146
|
+
stacks = /* @__PURE__ */ new Map();
|
|
43147
|
+
listeners = /* @__PURE__ */ new Map();
|
|
43148
|
+
cursors = /* @__PURE__ */ new Map();
|
|
43149
|
+
register(kind, transformer) {
|
|
43150
|
+
const requested = [...new Set(Array.isArray(kind) ? kind : [kind])];
|
|
43151
|
+
for (const item of requested) if (!isKind(item)) throw new Error(`Unknown display text kind: ${String(item)}`);
|
|
43152
|
+
const bound = [];
|
|
43153
|
+
for (const item of requested) {
|
|
43154
|
+
const entry = { transformer };
|
|
43155
|
+
try {
|
|
43156
|
+
entry.unsubscribe = transformer.subscribe?.(() => {
|
|
43157
|
+
this.emit(item);
|
|
43158
|
+
});
|
|
43159
|
+
} catch (error) {
|
|
43160
|
+
reportTransformError(error);
|
|
43161
|
+
}
|
|
43162
|
+
const stack = this.stacks.get(item) ?? [];
|
|
43163
|
+
stack.push(entry);
|
|
43164
|
+
this.stacks.set(item, stack);
|
|
43165
|
+
bound.push({
|
|
43166
|
+
kind: item,
|
|
43167
|
+
entry
|
|
43168
|
+
});
|
|
43169
|
+
this.emit(item);
|
|
43170
|
+
}
|
|
43171
|
+
return () => {
|
|
43172
|
+
for (const { kind: item, entry } of bound) {
|
|
43173
|
+
try {
|
|
43174
|
+
entry.unsubscribe?.();
|
|
43175
|
+
} catch (error) {
|
|
43176
|
+
reportTransformError(error);
|
|
43177
|
+
}
|
|
43178
|
+
const stack = this.stacks.get(item);
|
|
43179
|
+
if (!stack) continue;
|
|
43180
|
+
const next = stack.filter((candidate) => candidate !== entry);
|
|
43181
|
+
if (next.length > 0) this.stacks.set(item, next);
|
|
43182
|
+
else this.stacks.delete(item);
|
|
43183
|
+
this.emit(item);
|
|
43184
|
+
}
|
|
43185
|
+
};
|
|
43186
|
+
}
|
|
43187
|
+
has(kind) {
|
|
43188
|
+
return (this.stacks.get(kind)?.length ?? 0) > 0;
|
|
43189
|
+
}
|
|
43190
|
+
read(request) {
|
|
43191
|
+
const transformer = this.stacks.get(request.kind)?.at(-1)?.transformer;
|
|
43192
|
+
if (!transformer) return passthrough(request);
|
|
43193
|
+
let display;
|
|
43194
|
+
try {
|
|
43195
|
+
display = normalize(transformer.read(request), request);
|
|
43196
|
+
} catch (error) {
|
|
43197
|
+
reportTransformError(error);
|
|
43198
|
+
display = {
|
|
43199
|
+
text: request.text,
|
|
43200
|
+
final: !request.streaming
|
|
43201
|
+
};
|
|
43202
|
+
}
|
|
43203
|
+
const key = `${request.kind}\u0000${request.blockKey}`;
|
|
43204
|
+
const next = nextDisplayCursor(this.cursors.get(key), display);
|
|
43205
|
+
this.cursors.set(key, next);
|
|
43206
|
+
return next;
|
|
43207
|
+
}
|
|
43208
|
+
subscribe(kind, listener) {
|
|
43209
|
+
const set = this.listeners.get(kind) ?? /* @__PURE__ */ new Set();
|
|
43210
|
+
set.add(listener);
|
|
43211
|
+
this.listeners.set(kind, set);
|
|
43212
|
+
return () => {
|
|
43213
|
+
set.delete(listener);
|
|
43214
|
+
};
|
|
43215
|
+
}
|
|
43216
|
+
release(kind, blockKey) {
|
|
43217
|
+
this.cursors.delete(`${kind}\u0000${blockKey}`);
|
|
43218
|
+
}
|
|
43219
|
+
emit(kind) {
|
|
43220
|
+
const set = this.listeners.get(kind);
|
|
43221
|
+
if (!set) return;
|
|
43222
|
+
for (const listener of [...set]) listener();
|
|
43223
|
+
}
|
|
43224
|
+
};
|
|
43225
|
+
function createTextTransformRegistry() {
|
|
43226
|
+
return new TextTransformRegistryImpl();
|
|
43227
|
+
}
|
|
43228
|
+
let active;
|
|
43229
|
+
/** Points the reading view at the registry this client plugin provides. */
|
|
43230
|
+
function installTextTransformRegistry(registry) {
|
|
43231
|
+
const previous = active;
|
|
43232
|
+
active = registry;
|
|
43233
|
+
return () => {
|
|
43234
|
+
active = previous;
|
|
43235
|
+
};
|
|
43236
|
+
}
|
|
43237
|
+
function activeTextTransform() {
|
|
43238
|
+
return active;
|
|
43239
|
+
}
|
|
43240
|
+
/**
|
|
43241
|
+
* Subscribe while mounted. The reveal components call this only after
|
|
43242
|
+
* `has(kind)`, so an empty registry adds no hook and no listener.
|
|
43243
|
+
*/
|
|
43244
|
+
function useDisplayText(registry, request) {
|
|
43245
|
+
const [epoch, setEpoch] = (0, react.useState)(0);
|
|
43246
|
+
const { text, streaming, blockKey, kind, source } = request;
|
|
43247
|
+
(0, react.useEffect)(() => registry.subscribe(kind, () => {
|
|
43248
|
+
setEpoch((value) => value + 1);
|
|
43249
|
+
}), [registry, kind]);
|
|
43250
|
+
(0, react.useEffect)(() => () => {
|
|
43251
|
+
registry.release(kind, blockKey);
|
|
43252
|
+
}, [
|
|
43253
|
+
registry,
|
|
43254
|
+
kind,
|
|
43255
|
+
blockKey
|
|
43256
|
+
]);
|
|
43257
|
+
return (0, react.useMemo)(() => registry.read({
|
|
43258
|
+
text,
|
|
43259
|
+
streaming,
|
|
43260
|
+
blockKey,
|
|
43261
|
+
kind,
|
|
43262
|
+
source
|
|
43263
|
+
}), [
|
|
43264
|
+
registry,
|
|
43265
|
+
text,
|
|
43266
|
+
streaming,
|
|
43267
|
+
blockKey,
|
|
43268
|
+
kind,
|
|
43269
|
+
source,
|
|
43270
|
+
epoch
|
|
43271
|
+
]);
|
|
43272
|
+
}
|
|
43273
|
+
/** Chain-slot owner. Extra fields are optional so older callers still type-check. */
|
|
43274
|
+
function readerBlockOwner(block, streaming, source, presentation, holdFormatting) {
|
|
43275
|
+
return {
|
|
43276
|
+
block,
|
|
43277
|
+
streaming,
|
|
43278
|
+
source,
|
|
43279
|
+
presentation: {
|
|
43280
|
+
startedAt: presentation.startedAt,
|
|
43281
|
+
interrupted: presentation.interrupted,
|
|
43282
|
+
liveText: presentation.liveText
|
|
43283
|
+
},
|
|
43284
|
+
holdFormatting,
|
|
43285
|
+
liveText: presentation.liveText
|
|
43286
|
+
};
|
|
43287
|
+
}
|
|
43288
|
+
/** Copy actions read this. Display text never replaces it. */
|
|
43289
|
+
function originalAnswerText(blocks) {
|
|
43290
|
+
return blocks.flatMap((block) => block.kind === "text" && typeof block.text === "string" ? [block.text] : []).join("\n\n");
|
|
43291
|
+
}
|
|
43292
|
+
//#endregion
|
|
42768
43293
|
//#region \0dshx-css-module:TurnMetrics.module.css.mjs
|
|
42769
|
-
const css$4 = "._QZbGG_container{color:var(--dsw-alias-label-tertiary);align-items:center;gap:2px;font-size:13px;line-height:24px;display:inline-flex;position:relative}._QZbGG_pillButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);cursor:pointer;border-radius:12px;outline:none;align-items:center;gap:5px;padding:2px 8px;font-family:inherit;font-size:11px;transition:all .14s;display:inline-flex}._QZbGG_pillButton:hover,._QZbGG_pillButton[data-active=true]{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover)}._QZbGG_timeButton{height:28px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-radius:28px;align-items:center;gap:4px;padding:6px 8px;font-family:inherit;font-size:13px;line-height:24px;display:inline-flex}._QZbGG_timeButton:hover,._QZbGG_timeButton[data-active=true]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}._QZbGG_pillIcon{opacity:.8;flex:none;width:12px;height:12px}._QZbGG_metricsPop{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);backdrop-filter:blur(10px);z-index:50;text-align:left;border-radius:10px;flex-direction:column;gap:8px;width:260px;padding:12px 14px;animation:.14s ease-out _QZbGG_popIn;display:flex;position:absolute;bottom:calc(100% + 8px);left:0;box-shadow:0 6px 20px #00000024}@keyframes _QZbGG_popIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}._QZbGG_popHeader{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);justify-content:space-between;align-items:center;padding-bottom:6px;font-size:12px;font-weight:600;display:flex}._QZbGG_popSection{flex-direction:column;gap:4px;display:flex}._QZbGG_popSectionTitle{text-transform:uppercase;letter-spacing:.5px;color:var(--dsw-alias-label-tertiary);margin-top:2px;font-size:10px;font-weight:600}._QZbGG_popGrid{grid-template-columns:1fr auto;gap:3px 12px;font-size:11px;line-height:18px;display:grid}._QZbGG_popLabel{color:var(--dsw-alias-label-secondary)}._QZbGG_popValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:right;font-weight:500}._QZbGG_popBadge{background:var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:3px;margin-left:4px;padding:0 4px;font-size:10px}";
|
|
43294
|
+
const css$4 = "._QZbGG_container{color:var(--dsw-alias-label-tertiary);align-items:center;gap:2px;font-size:13px;line-height:24px;display:inline-flex;position:relative}._QZbGG_pillButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);cursor:pointer;border-radius:12px;outline:none;align-items:center;gap:5px;padding:2px 8px;font-family:inherit;font-size:11px;transition:all .14s;display:inline-flex}._QZbGG_pillButton:hover,._QZbGG_pillButton[data-active=true]{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover)}._QZbGG_timeButton{height:28px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-radius:28px;align-items:center;gap:4px;padding:6px 8px;font-family:inherit;font-size:13px;line-height:24px;display:inline-flex}._QZbGG_timeButton:hover,._QZbGG_timeButton[data-active=true]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}._QZbGG_pillIcon{opacity:.8;flex:none;width:12px;height:12px}._QZbGG_metricsPop{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);z-index:50;text-align:left;border-radius:10px;flex-direction:column;gap:8px;width:260px;padding:12px 14px;animation:.14s ease-out _QZbGG_popIn;display:flex;position:absolute;bottom:calc(100% + 8px);left:0;box-shadow:0 6px 20px #00000024}@keyframes _QZbGG_popIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}._QZbGG_popHeader{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);justify-content:space-between;align-items:center;padding-bottom:6px;font-size:12px;font-weight:600;display:flex}._QZbGG_popSection{flex-direction:column;gap:4px;display:flex}._QZbGG_popSectionTitle{text-transform:uppercase;letter-spacing:.5px;color:var(--dsw-alias-label-tertiary);margin-top:2px;font-size:10px;font-weight:600}._QZbGG_popGrid{grid-template-columns:1fr auto;gap:3px 12px;font-size:11px;line-height:18px;display:grid}._QZbGG_popLabel{color:var(--dsw-alias-label-secondary)}._QZbGG_popValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:right;font-weight:500}._QZbGG_popBadge{background:var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:3px;margin-left:4px;padding:0 4px;font-size:10px}";
|
|
42770
43295
|
const tagId$4 = "dsh-better-display/TurnMetrics.module.css";
|
|
42771
43296
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
|
|
42772
43297
|
const tag = document.createElement("style");
|
|
@@ -43129,7 +43654,7 @@ ${trimmed}
|
|
|
43129
43654
|
};
|
|
43130
43655
|
});
|
|
43131
43656
|
}
|
|
43132
|
-
function
|
|
43657
|
+
function MarkdownStream({ text, streaming, holdFormatting, startedAt, interrupted = false, liveText = false, kind = "body", fileMentions, transformed = false }) {
|
|
43133
43658
|
const root = (0, react.useRef)(null);
|
|
43134
43659
|
const presentation = useStreamingText(text, streaming, {
|
|
43135
43660
|
startedAt,
|
|
@@ -43153,6 +43678,7 @@ ${trimmed}
|
|
|
43153
43678
|
"data-ud-motion": "reader-text-arrival",
|
|
43154
43679
|
"data-ud-motion-type": "reveal",
|
|
43155
43680
|
"data-ud-motion-no-flash": "true",
|
|
43681
|
+
"data-text-transform": transformed ? streaming ? "live" : "final" : void 0,
|
|
43156
43682
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MotionMarkdown, {
|
|
43157
43683
|
text: presentation.text,
|
|
43158
43684
|
streaming: effectiveMode,
|
|
@@ -43162,7 +43688,32 @@ ${trimmed}
|
|
|
43162
43688
|
})
|
|
43163
43689
|
});
|
|
43164
43690
|
}
|
|
43165
|
-
function
|
|
43691
|
+
function TransformedMarkdown({ registry, blockKey, source, text, streaming, ...props }) {
|
|
43692
|
+
const shown = useDisplayText(registry, {
|
|
43693
|
+
text,
|
|
43694
|
+
streaming,
|
|
43695
|
+
blockKey,
|
|
43696
|
+
kind: "body",
|
|
43697
|
+
source
|
|
43698
|
+
});
|
|
43699
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownStream, {
|
|
43700
|
+
...props,
|
|
43701
|
+
text: shown.text,
|
|
43702
|
+
streaming: displayStreaming(streaming, shown, true),
|
|
43703
|
+
transformed: true
|
|
43704
|
+
});
|
|
43705
|
+
}
|
|
43706
|
+
function ReadingMarkdown({ blockKey, source, ...props }) {
|
|
43707
|
+
const registry = activeTextTransform();
|
|
43708
|
+
if (registry?.has("body")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TransformedMarkdown, {
|
|
43709
|
+
registry,
|
|
43710
|
+
blockKey,
|
|
43711
|
+
source,
|
|
43712
|
+
...props
|
|
43713
|
+
});
|
|
43714
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownStream, { ...props });
|
|
43715
|
+
}
|
|
43716
|
+
function ReasoningStream({ text, streaming, holdFormatting, startedAt, interrupted = false, liveText = false, transformed = false }) {
|
|
43166
43717
|
const presentation = useStreamingText(text, streaming, {
|
|
43167
43718
|
startedAt,
|
|
43168
43719
|
interrupted: interrupted || !liveText,
|
|
@@ -43179,6 +43730,7 @@ ${trimmed}
|
|
|
43179
43730
|
"data-ud-motion": "reader-text-arrival",
|
|
43180
43731
|
"data-ud-motion-type": "reveal",
|
|
43181
43732
|
"data-ud-motion-no-flash": "true",
|
|
43733
|
+
"data-text-transform": transformed ? streaming ? "live" : "final" : void 0,
|
|
43182
43734
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MotionPlainText, {
|
|
43183
43735
|
text: presentation.text,
|
|
43184
43736
|
enabled: liveText && presentation.reveal,
|
|
@@ -43186,7 +43738,32 @@ ${trimmed}
|
|
|
43186
43738
|
})
|
|
43187
43739
|
});
|
|
43188
43740
|
}
|
|
43189
|
-
function
|
|
43741
|
+
function TransformedReasoning({ registry, blockKey, source, text, streaming, ...props }) {
|
|
43742
|
+
const shown = useDisplayText(registry, {
|
|
43743
|
+
text,
|
|
43744
|
+
streaming,
|
|
43745
|
+
blockKey,
|
|
43746
|
+
kind: "reasoning",
|
|
43747
|
+
source
|
|
43748
|
+
});
|
|
43749
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningStream, {
|
|
43750
|
+
...props,
|
|
43751
|
+
text: shown.text,
|
|
43752
|
+
streaming: displayStreaming(streaming, shown, true),
|
|
43753
|
+
transformed: true
|
|
43754
|
+
});
|
|
43755
|
+
}
|
|
43756
|
+
function ReadingReasoning({ blockKey, source, ...props }) {
|
|
43757
|
+
const registry = activeTextTransform();
|
|
43758
|
+
if (registry?.has("reasoning")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TransformedReasoning, {
|
|
43759
|
+
registry,
|
|
43760
|
+
blockKey,
|
|
43761
|
+
source,
|
|
43762
|
+
...props
|
|
43763
|
+
});
|
|
43764
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningStream, { ...props });
|
|
43765
|
+
}
|
|
43766
|
+
function fallback(block, streaming, source, loadImage, fillComposer, holdFormatting, presentation, blockKey, fileMentions) {
|
|
43190
43767
|
switch (block.kind) {
|
|
43191
43768
|
case "text": return source === "user" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, {
|
|
43192
43769
|
text: block.text,
|
|
@@ -43196,7 +43773,9 @@ ${trimmed}
|
|
|
43196
43773
|
streaming,
|
|
43197
43774
|
holdFormatting,
|
|
43198
43775
|
...presentation,
|
|
43199
|
-
fileMentions
|
|
43776
|
+
fileMentions,
|
|
43777
|
+
blockKey,
|
|
43778
|
+
source
|
|
43200
43779
|
});
|
|
43201
43780
|
case "image": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImageBlock, {
|
|
43202
43781
|
attachment: block.attachment,
|
|
@@ -43206,7 +43785,9 @@ ${trimmed}
|
|
|
43206
43785
|
text: block.text,
|
|
43207
43786
|
streaming,
|
|
43208
43787
|
holdFormatting,
|
|
43209
|
-
...presentation
|
|
43788
|
+
...presentation,
|
|
43789
|
+
blockKey,
|
|
43790
|
+
source
|
|
43210
43791
|
});
|
|
43211
43792
|
case "tool-call": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.JsonBlock, {
|
|
43212
43793
|
label: `工具参数 · ${block.name}`,
|
|
@@ -43235,20 +43816,21 @@ ${trimmed}
|
|
|
43235
43816
|
}
|
|
43236
43817
|
}
|
|
43237
43818
|
const Blocks = (0, react.memo)(function Blocks({ blocks, streaming = false, source = "assistant", holdFormatting = false, startedAt, interrupted, liveText, renderSlotChain, loadImage, fillComposer, fileMentions }) {
|
|
43819
|
+
const reactId = (0, react.useId)();
|
|
43238
43820
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComposerFillContext.Provider, {
|
|
43239
43821
|
value: fillComposer,
|
|
43240
43822
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
43241
43823
|
className: Reader_module_css_default.blocks,
|
|
43242
43824
|
"data-streaming": streaming || void 0,
|
|
43243
|
-
children: blocks.map((block, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderSlotChain("dsh-better-display.block", {
|
|
43244
|
-
|
|
43245
|
-
|
|
43246
|
-
|
|
43247
|
-
}, { fallback: fallback(block, streaming, source, loadImage, fillComposer, holdFormatting, {
|
|
43825
|
+
children: blocks.map((block, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderSlotChain("dsh-better-display.block", readerBlockOwner(block, streaming, source, {
|
|
43826
|
+
startedAt,
|
|
43827
|
+
interrupted,
|
|
43828
|
+
liveText
|
|
43829
|
+
}, holdFormatting), { fallback: fallback(block, streaming, source, loadImage, fillComposer, holdFormatting, {
|
|
43248
43830
|
startedAt,
|
|
43249
43831
|
interrupted,
|
|
43250
43832
|
liveText
|
|
43251
|
-
}, fileMentions) }) }) }, block.kind === "image" ? `image:${block.attachment.attachmentId}:${index}` : `${index}:${block.kind}`))
|
|
43833
|
+
}, `${reactId}:${index}:${block.kind}`, fileMentions) }) }) }, block.kind === "image" ? `image:${block.attachment.attachmentId}:${index}` : `${index}:${block.kind}`))
|
|
43252
43834
|
})
|
|
43253
43835
|
});
|
|
43254
43836
|
});
|
|
@@ -43293,7 +43875,7 @@ ${trimmed}
|
|
|
43293
43875
|
}
|
|
43294
43876
|
function CopyAnswer({ blocks, onFork, metrics, extraActions }) {
|
|
43295
43877
|
const { receipt, copy } = useCopyReceipt();
|
|
43296
|
-
const text = blocks
|
|
43878
|
+
const text = originalAnswerText(blocks);
|
|
43297
43879
|
const endedAt = metrics?.endedAt;
|
|
43298
43880
|
const hasMetrics = metrics !== void 0 && (metrics.usage !== void 0 || metrics.runMs !== void 0 || endedAt !== void 0);
|
|
43299
43881
|
if (!text.trim() && !onFork && !hasMetrics) return null;
|
|
@@ -43784,14 +44366,22 @@ ${trimmed}
|
|
|
43784
44366
|
images: "dsh-better-display.official.images/conversation.message.images"
|
|
43785
44367
|
};
|
|
43786
44368
|
const officialSeat = (family, source = OFFICIAL_SLOTS[family]) => `dsh-better-display.official.${family}/${source}`;
|
|
43787
|
-
const
|
|
43788
|
-
"user",
|
|
43789
|
-
"steering",
|
|
43790
|
-
"assistant-step",
|
|
44369
|
+
const READER_OWNED_NODES = /* @__PURE__ */ new Set([
|
|
43791
44370
|
"tool-call",
|
|
43792
44371
|
"turn-tail",
|
|
43793
44372
|
"turn-process"
|
|
43794
44373
|
]);
|
|
44374
|
+
/**
|
|
44375
|
+
* Mirror a chat-node registration into the Reader seat.
|
|
44376
|
+
* Assistant replacements are the entries that would actually replace the
|
|
44377
|
+
* official renderer on the host. The official priority itself stays out, so
|
|
44378
|
+
* Reader keeps its own answer markdown until a plugin opts in.
|
|
44379
|
+
*/
|
|
44380
|
+
function acceptMirroredChatNode(entry) {
|
|
44381
|
+
const key = entry.options.key ?? "";
|
|
44382
|
+
if (key === "assistant-step") return (entry.options.priority ?? 0) < 0;
|
|
44383
|
+
return !READER_OWNED_NODES.has(key);
|
|
44384
|
+
}
|
|
43795
44385
|
const EXPECTED = {
|
|
43796
44386
|
actions: {
|
|
43797
44387
|
kind: "list",
|
|
@@ -43941,7 +44531,7 @@ ${trimmed}
|
|
|
43941
44531
|
const target = officialSeat(family);
|
|
43942
44532
|
const declared = slots.spec(target);
|
|
43943
44533
|
if (spec.kind !== declared?.kind || spec.scope !== declared.scope) throw new Error(`Official slot contract changed: ${source}`);
|
|
43944
|
-
return mirrorOfficialSlot(slots, source, target, `dsh-better-display.official.${family}`, family === "nodes" ?
|
|
44534
|
+
return mirrorOfficialSlot(slots, source, target, `dsh-better-display.official.${family}`, family === "nodes" ? acceptMirroredChatNode : void 0);
|
|
43945
44535
|
}));
|
|
43946
44536
|
}
|
|
43947
44537
|
} catch (error) {
|
|
@@ -44006,11 +44596,8 @@ ${trimmed}
|
|
|
44006
44596
|
})
|
|
44007
44597
|
});
|
|
44008
44598
|
}
|
|
44009
|
-
function
|
|
44010
|
-
|
|
44011
|
-
const [disclosureReset] = (0, react.useState)(() => (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(0));
|
|
44012
|
-
if (!official) return fallback;
|
|
44013
|
-
const owner = {
|
|
44599
|
+
function chatNodeOwner(render, official) {
|
|
44600
|
+
return {
|
|
44014
44601
|
cwd: render.cwd,
|
|
44015
44602
|
openFile: render.openFile ?? (() => {}),
|
|
44016
44603
|
openSkill: () => {},
|
|
@@ -44023,13 +44610,18 @@ ${trimmed}
|
|
|
44023
44610
|
}),
|
|
44024
44611
|
fileMentions: official.officialFileMentions
|
|
44025
44612
|
};
|
|
44613
|
+
}
|
|
44614
|
+
function OfficialNode({ node, fallback, ...render }) {
|
|
44615
|
+
const official = render.official;
|
|
44616
|
+
const [disclosureReset] = (0, react.useState)(() => (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(0));
|
|
44617
|
+
if (!official) return fallback;
|
|
44026
44618
|
const turn = node.location.kind === "turn" || node.location.kind === "step" ? node.location.turn : void 0;
|
|
44027
44619
|
const renderNode = official.renderSlot;
|
|
44028
44620
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
44029
44621
|
"data-reader-official-node": node.kind,
|
|
44030
44622
|
...node.kind === "user" || node.kind === "steering" ? chatSeatProps(node.kind, node.key) : {},
|
|
44031
44623
|
children: renderNode(OFFICIAL_SEATS.nodes, {
|
|
44032
|
-
...
|
|
44624
|
+
...chatNodeOwner(render, official),
|
|
44033
44625
|
node
|
|
44034
44626
|
}, {
|
|
44035
44627
|
entryKey: node.kind,
|
|
@@ -44041,6 +44633,46 @@ ${trimmed}
|
|
|
44041
44633
|
})
|
|
44042
44634
|
});
|
|
44043
44635
|
}
|
|
44636
|
+
/**
|
|
44637
|
+
* Body of one assistant segment. A mirrored assistant-step replacement draws
|
|
44638
|
+
* it; Reader markdown is the fallback when no replacement is registered.
|
|
44639
|
+
* The caller keeps reasoning blocks on the reading card.
|
|
44640
|
+
*/
|
|
44641
|
+
function OfficialAssistantBody({ node, blocks, streaming = false, holdFormatting = false, startedAt, interrupted = false, liveText = false, ...render }) {
|
|
44642
|
+
const official = render.official;
|
|
44643
|
+
const [disclosureReset] = (0, react.useState)(() => (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(0));
|
|
44644
|
+
const fallback = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
44645
|
+
...render,
|
|
44646
|
+
blocks,
|
|
44647
|
+
streaming,
|
|
44648
|
+
holdFormatting,
|
|
44649
|
+
startedAt,
|
|
44650
|
+
interrupted,
|
|
44651
|
+
liveText
|
|
44652
|
+
});
|
|
44653
|
+
if (!official) return fallback;
|
|
44654
|
+
const turn = node.location.kind === "turn" || node.location.kind === "step" ? node.location.turn : void 0;
|
|
44655
|
+
const view = blocks.length === node.data.blocks.length && blocks.every((block, index) => block === node.data.blocks[index]) ? node : {
|
|
44656
|
+
...node,
|
|
44657
|
+
data: {
|
|
44658
|
+
...node.data,
|
|
44659
|
+
blocks
|
|
44660
|
+
}
|
|
44661
|
+
};
|
|
44662
|
+
const renderNode = official.renderSlot;
|
|
44663
|
+
return renderNode(OFFICIAL_SEATS.nodes, {
|
|
44664
|
+
...chatNodeOwner(render, official),
|
|
44665
|
+
node: view,
|
|
44666
|
+
groupPart: "response"
|
|
44667
|
+
}, {
|
|
44668
|
+
entryKey: "assistant-step",
|
|
44669
|
+
hookContext: {
|
|
44670
|
+
turnData: turn?.data,
|
|
44671
|
+
disclosureReset
|
|
44672
|
+
},
|
|
44673
|
+
fallback
|
|
44674
|
+
});
|
|
44675
|
+
}
|
|
44044
44676
|
function OfficialTail({ official, owner, produced }) {
|
|
44045
44677
|
const tailOwner = owner && official ? {
|
|
44046
44678
|
...owner,
|
|
@@ -44054,6 +44686,69 @@ ${trimmed}
|
|
|
44054
44686
|
}) : null;
|
|
44055
44687
|
}
|
|
44056
44688
|
//#endregion
|
|
44689
|
+
//#region src/client/turn-slots.ts
|
|
44690
|
+
/**
|
|
44691
|
+
* Keep live turns in the incoming `groups` order, and keep a departing turn
|
|
44692
|
+
* next to the live neighbour that preceded it.
|
|
44693
|
+
*
|
|
44694
|
+
* A rewind removes turn keys from the visible order. Unmounting them in that
|
|
44695
|
+
* same commit snaps the transcript, so the lane retains the last group object
|
|
44696
|
+
* until the collapse finishes. A re-render, a stream tick, or a reconnect that
|
|
44697
|
+
* still contains the same keys only replaces the group object and leaves
|
|
44698
|
+
* `live` true — those updates must not start a collapse. A key that returns
|
|
44699
|
+
* is live again where `groups` places it. Loading older history therefore
|
|
44700
|
+
* stays in transcript order instead of appending the older turns after the
|
|
44701
|
+
* ones already on screen. A departing slot is inserted immediately after the
|
|
44702
|
+
* nearest preceding slot that is still live, or at the front when it had none,
|
|
44703
|
+
* so several departing neighbours keep their relative order.
|
|
44704
|
+
*
|
|
44705
|
+
* Returns `current` itself when nothing changed, so a React state update can
|
|
44706
|
+
* bail out on `Object.is`.
|
|
44707
|
+
*/
|
|
44708
|
+
function reconcileTurnSlots(current, groups) {
|
|
44709
|
+
const incoming = new Map(groups.map((group) => [group.key, group]));
|
|
44710
|
+
const next = groups.map((group) => ({
|
|
44711
|
+
group,
|
|
44712
|
+
live: true
|
|
44713
|
+
}));
|
|
44714
|
+
for (const slot of current) {
|
|
44715
|
+
if (incoming.has(slot.group.key)) continue;
|
|
44716
|
+
insertDeparting(next, {
|
|
44717
|
+
group: slot.group,
|
|
44718
|
+
live: false
|
|
44719
|
+
}, precedingLiveKey(current, incoming, slot.group.key));
|
|
44720
|
+
}
|
|
44721
|
+
return next.length === current.length && next.every((slot, index) => slot.live === current[index].live && slot.group === current[index].group) ? current : next;
|
|
44722
|
+
}
|
|
44723
|
+
/** Nearest preceding slot that is still in the incoming order, if any. */
|
|
44724
|
+
function precedingLiveKey(current, incoming, key) {
|
|
44725
|
+
const index = current.findIndex((slot) => slot.group.key === key);
|
|
44726
|
+
for (let cursor = index - 1; cursor >= 0; cursor--) {
|
|
44727
|
+
const candidate = current[cursor].group.key;
|
|
44728
|
+
if (incoming.has(candidate)) return candidate;
|
|
44729
|
+
}
|
|
44730
|
+
}
|
|
44731
|
+
/**
|
|
44732
|
+
* Place a departing slot after `anchorKey`, or at the front when the slot had
|
|
44733
|
+
* no preceding live neighbour. Slots that share an anchor keep `current` order
|
|
44734
|
+
* because each one is inserted at the end of the departing run after that anchor.
|
|
44735
|
+
*/
|
|
44736
|
+
function insertDeparting(next, slot, anchorKey) {
|
|
44737
|
+
if (anchorKey === void 0) {
|
|
44738
|
+
const firstLive = next.findIndex((item) => item.live);
|
|
44739
|
+
next.splice(firstLive < 0 ? next.length : firstLive, 0, slot);
|
|
44740
|
+
return;
|
|
44741
|
+
}
|
|
44742
|
+
const anchorIndex = next.findIndex((item) => item.group.key === anchorKey);
|
|
44743
|
+
if (anchorIndex < 0) {
|
|
44744
|
+
next.unshift(slot);
|
|
44745
|
+
return;
|
|
44746
|
+
}
|
|
44747
|
+
let insertAt = anchorIndex + 1;
|
|
44748
|
+
while (insertAt < next.length && next[insertAt]?.live === false) insertAt++;
|
|
44749
|
+
next.splice(insertAt, 0, slot);
|
|
44750
|
+
}
|
|
44751
|
+
//#endregion
|
|
44057
44752
|
//#region src/client/motion.tsx
|
|
44058
44753
|
const EASING = "cubic-bezier(.22,1,.36,1)";
|
|
44059
44754
|
function useMotionAllowed(enabled) {
|
|
@@ -44066,7 +44761,7 @@ ${trimmed}
|
|
|
44066
44761
|
}, []);
|
|
44067
44762
|
return enabled && !reduced;
|
|
44068
44763
|
}
|
|
44069
|
-
function usePinnedSelection(root, selector = "[data-reader-answer], [data-reader-process]") {
|
|
44764
|
+
function usePinnedSelection(root, selector = "[data-reader-answer], [data-reader-body], [data-reader-process]") {
|
|
44070
44765
|
const [keys, setKeys] = (0, react.useState)([]);
|
|
44071
44766
|
(0, react.useEffect)(() => {
|
|
44072
44767
|
const update = () => {
|
|
@@ -44312,12 +45007,14 @@ ${trimmed}
|
|
|
44312
45007
|
});
|
|
44313
45008
|
}
|
|
44314
45009
|
/** Retire only narration that was actually visible; historical rows stay folded. */
|
|
44315
|
-
function RetiringContent({ visible, children }) {
|
|
45010
|
+
function RetiringContent({ visible, children, onRetired }) {
|
|
44316
45011
|
const { enabled } = (0, react.useContext)(StreamMotionContext);
|
|
44317
45012
|
const root = (0, react.useRef)(null);
|
|
44318
45013
|
const animation = (0, react.useRef)(null);
|
|
44319
45014
|
const [present, setPresent] = (0, react.useState)(visible);
|
|
44320
45015
|
const [focusHeld, setFocusHeld] = (0, react.useState)(false);
|
|
45016
|
+
const retired = (0, react.useRef)(onRetired);
|
|
45017
|
+
retired.current = onRetired;
|
|
44321
45018
|
(0, react.useLayoutEffect)(() => {
|
|
44322
45019
|
const element = root.current;
|
|
44323
45020
|
if (visible) {
|
|
@@ -44327,16 +45024,38 @@ ${trimmed}
|
|
|
44327
45024
|
return;
|
|
44328
45025
|
}
|
|
44329
45026
|
if (!element) return;
|
|
44330
|
-
|
|
44331
|
-
|
|
45027
|
+
let retiredNow = false;
|
|
45028
|
+
const retireNow = () => {
|
|
45029
|
+
if (retiredNow) return;
|
|
45030
|
+
retiredNow = true;
|
|
45031
|
+
animation.current?.cancel();
|
|
45032
|
+
animation.current = null;
|
|
45033
|
+
focusSurvivesRetire(element);
|
|
45034
|
+
setPresent(false);
|
|
45035
|
+
retired.current?.();
|
|
45036
|
+
};
|
|
45037
|
+
if (!enabled || document.hidden) {
|
|
45038
|
+
retireNow();
|
|
44332
45039
|
return;
|
|
44333
45040
|
}
|
|
44334
|
-
|
|
45041
|
+
const canListen = typeof document.addEventListener === "function";
|
|
45042
|
+
const holdsFocus = element.contains(document.activeElement);
|
|
45043
|
+
if (holdsFocus || focusHeld) {
|
|
45044
|
+
if (holdsFocus) setFocusHeld(true);
|
|
45045
|
+
const onHiddenWhileHeld = () => {
|
|
45046
|
+
if (document.hidden) retireNow();
|
|
45047
|
+
};
|
|
45048
|
+
if (canListen) document.addEventListener("visibilitychange", onHiddenWhileHeld);
|
|
45049
|
+
return () => {
|
|
45050
|
+
if (canListen) document.removeEventListener("visibilitychange", onHiddenWhileHeld);
|
|
45051
|
+
};
|
|
45052
|
+
}
|
|
44335
45053
|
const from = element.getBoundingClientRect().height;
|
|
44336
45054
|
animation.current?.cancel();
|
|
44337
45055
|
animation.current = null;
|
|
44338
|
-
if (
|
|
45056
|
+
if (from < 1) {
|
|
44339
45057
|
setPresent(false);
|
|
45058
|
+
retired.current?.();
|
|
44340
45059
|
return;
|
|
44341
45060
|
}
|
|
44342
45061
|
const next = element.animate([{
|
|
@@ -44351,12 +45070,26 @@ ${trimmed}
|
|
|
44351
45070
|
fill: "both"
|
|
44352
45071
|
});
|
|
44353
45072
|
animation.current = next;
|
|
44354
|
-
|
|
44355
|
-
|
|
44356
|
-
|
|
44357
|
-
|
|
44358
|
-
|
|
44359
|
-
|
|
45073
|
+
let settled = false;
|
|
45074
|
+
const settle = () => {
|
|
45075
|
+
if (settled || animation.current !== next) return;
|
|
45076
|
+
settled = true;
|
|
45077
|
+
animation.current = null;
|
|
45078
|
+
next.cancel();
|
|
45079
|
+
setPresent(false);
|
|
45080
|
+
retired.current?.();
|
|
45081
|
+
};
|
|
45082
|
+
next.onfinish = settle;
|
|
45083
|
+
const deadline = window.setTimeout(settle, 460);
|
|
45084
|
+
const onHide = () => {
|
|
45085
|
+
if (document.hidden) settle();
|
|
45086
|
+
};
|
|
45087
|
+
if (canListen) document.addEventListener("visibilitychange", onHide);
|
|
45088
|
+
return () => {
|
|
45089
|
+
window.clearTimeout(deadline);
|
|
45090
|
+
if (canListen) document.removeEventListener("visibilitychange", onHide);
|
|
45091
|
+
if (animation.current === next) animation.current = null;
|
|
45092
|
+
next.cancel();
|
|
44360
45093
|
};
|
|
44361
45094
|
}, [
|
|
44362
45095
|
visible,
|
|
@@ -44376,6 +45109,80 @@ ${trimmed}
|
|
|
44376
45109
|
children
|
|
44377
45110
|
});
|
|
44378
45111
|
}
|
|
45112
|
+
/**
|
|
45113
|
+
* Keeps a departing turn mounted for the length of its own collapse.
|
|
45114
|
+
*
|
|
45115
|
+
* A rewind removes turns from the visible order, and unmounting them outright
|
|
45116
|
+
* snapped the transcript: every withdrawn row disappeared in one frame with
|
|
45117
|
+
* nothing to scroll. Instead each departing turn is retained, rendered with
|
|
45118
|
+
* `visible={false}` so it animates to zero height, and released only once the
|
|
45119
|
+
* collapse has settled — so the reader watches the rows fold away and the rows
|
|
45120
|
+
* below glide up into their place.
|
|
45121
|
+
*
|
|
45122
|
+
* Live slots follow the incoming group order, so older history stays above the
|
|
45123
|
+
* tail. A collapsing turn stays next to the live neighbour that preceded it;
|
|
45124
|
+
* appending it would jump it to the bottom for the length of the animation.
|
|
45125
|
+
* Retention is bounded by the animation itself: `onRetired`
|
|
45126
|
+
* drops the slot, so a departing turn lives for one collapse and no longer —
|
|
45127
|
+
* and a key that comes back later is re-added as a live slot.
|
|
45128
|
+
*/
|
|
45129
|
+
function RetiringTurns({ groups, render }) {
|
|
45130
|
+
const [slots, setSlots] = (0, react.useState)(() => groups.map((group) => ({
|
|
45131
|
+
group,
|
|
45132
|
+
live: true
|
|
45133
|
+
})));
|
|
45134
|
+
(0, react.useLayoutEffect)(() => {
|
|
45135
|
+
setSlots((current) => reconcileTurnSlots(current, groups));
|
|
45136
|
+
}, [groups]);
|
|
45137
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: slots.map((slot) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RetiringContent, {
|
|
45138
|
+
visible: slot.live,
|
|
45139
|
+
onRetired: () => setSlots((current) => current.filter((candidate) => candidate.live || candidate.group.key !== slot.group.key)),
|
|
45140
|
+
children: render(slot.group)
|
|
45141
|
+
}, slot.group.key)) });
|
|
45142
|
+
}
|
|
45143
|
+
/** A turn that is still on screen, not one this commit is about to unmount. */
|
|
45144
|
+
function survivingTurn(node) {
|
|
45145
|
+
if (!(node instanceof HTMLElement) || node.dataset.readerRetiring === "retiring") return null;
|
|
45146
|
+
const turn = node.hasAttribute("data-reader-turn") ? node : node.querySelector("[data-reader-turn]");
|
|
45147
|
+
if (turn === null) return null;
|
|
45148
|
+
const retiring = turn.closest("[data-reader-retiring]");
|
|
45149
|
+
if (retiring instanceof HTMLElement && retiring.dataset.readerRetiring === "retiring") return null;
|
|
45150
|
+
return turn;
|
|
45151
|
+
}
|
|
45152
|
+
/**
|
|
45153
|
+
* Where focus goes when cut content is removed without an animation.
|
|
45154
|
+
* Prefer the nearest turn that is still live. Otherwise the reading column
|
|
45155
|
+
* (or the host scrollport) so focus does not fall through to the document.
|
|
45156
|
+
*/
|
|
45157
|
+
function retireFocusTarget(element) {
|
|
45158
|
+
const parent = element.parentElement;
|
|
45159
|
+
if (parent) {
|
|
45160
|
+
const siblings = [...parent.children];
|
|
45161
|
+
const index = siblings.indexOf(element);
|
|
45162
|
+
for (let cursor = index - 1; cursor >= 0; cursor--) {
|
|
45163
|
+
const turn = survivingTurn(siblings[cursor]);
|
|
45164
|
+
if (turn) return turn;
|
|
45165
|
+
}
|
|
45166
|
+
for (let cursor = index + 1; cursor < siblings.length; cursor++) {
|
|
45167
|
+
const turn = survivingTurn(siblings[cursor]);
|
|
45168
|
+
if (turn) return turn;
|
|
45169
|
+
}
|
|
45170
|
+
}
|
|
45171
|
+
const column = element.closest("[data-chat-flow]");
|
|
45172
|
+
if (column && !element.contains(column)) return column;
|
|
45173
|
+
const scroll = element.closest("[data-conversation-scroll]");
|
|
45174
|
+
if (scroll && !element.contains(scroll)) return scroll;
|
|
45175
|
+
return null;
|
|
45176
|
+
}
|
|
45177
|
+
/** Move focus out of `element` before it unmounts. A no-op when focus is elsewhere. */
|
|
45178
|
+
function focusSurvivesRetire(element) {
|
|
45179
|
+
const active = document.activeElement;
|
|
45180
|
+
if (active === null || !element.contains(active)) return;
|
|
45181
|
+
const target = retireFocusTarget(element);
|
|
45182
|
+
if (target === null || element.contains(target)) return;
|
|
45183
|
+
if (target.tabIndex < 0) target.tabIndex = -1;
|
|
45184
|
+
target.focus({ preventScroll: true });
|
|
45185
|
+
}
|
|
44379
45186
|
function useReadingScroll(root, motion) {
|
|
44380
45187
|
const port = (0, react.useRef)(null);
|
|
44381
45188
|
const following = (0, react.useRef)(true);
|
|
@@ -44591,6 +45398,345 @@ ${trimmed}
|
|
|
44591
45398
|
};
|
|
44592
45399
|
}
|
|
44593
45400
|
//#endregion
|
|
45401
|
+
//#region src/client/fold-choreography.ts
|
|
45402
|
+
/** Presentation clock, not model/network time. */
|
|
45403
|
+
const FOLD_TIMING = {
|
|
45404
|
+
collapse: 320,
|
|
45405
|
+
count: 160,
|
|
45406
|
+
settle: 80,
|
|
45407
|
+
reveal: 180,
|
|
45408
|
+
/**
|
|
45409
|
+
* Slack added to every phase deadline before the watchdog forces the next phase.
|
|
45410
|
+
*
|
|
45411
|
+
* The choreography advances on animation promises and rendered frames. Both are
|
|
45412
|
+
* best-effort: a cancelled animation *rejects* and a compositor that never
|
|
45413
|
+
* finishes one leaves its promise pending, while a backgrounded tab stops
|
|
45414
|
+
* delivering frames. Without a deadline the machine would sit in a non-idle
|
|
45415
|
+
* phase forever, and a non-idle phase freezes both the frame source and the text
|
|
45416
|
+
* reveal, so the turn would look stuck until a remount. This is the liveness
|
|
45417
|
+
* guarantee that does not depend on any of them.
|
|
45418
|
+
*/
|
|
45419
|
+
watchdogSlack: 240
|
|
45420
|
+
};
|
|
45421
|
+
/** A step always has the same parent and React key, even when its membership changes. */
|
|
45422
|
+
function flowRows(items) {
|
|
45423
|
+
return items.flatMap((item) => item.kind === "fold" ? [{
|
|
45424
|
+
kind: "summary",
|
|
45425
|
+
key: item.key,
|
|
45426
|
+
item
|
|
45427
|
+
}, ...item.steps.map((step) => ({
|
|
45428
|
+
kind: "step",
|
|
45429
|
+
key: step.key,
|
|
45430
|
+
step,
|
|
45431
|
+
foldKey: item.key
|
|
45432
|
+
}))] : [{
|
|
45433
|
+
kind: "step",
|
|
45434
|
+
key: item.key,
|
|
45435
|
+
step: item.step
|
|
45436
|
+
}]);
|
|
45437
|
+
}
|
|
45438
|
+
function retiringKeys(before, after, open) {
|
|
45439
|
+
const folded = new Set(flowRows(after).filter((row) => row.kind === "step" && row.foldKey && !open[row.foldKey]).map((row) => row.key));
|
|
45440
|
+
return flowRows(before).filter((row) => row.kind === "step" && !row.foldKey && folded.has(row.key)).map((row) => row.key);
|
|
45441
|
+
}
|
|
45442
|
+
/** Insert only new summary slots. Never admit incoming content during shrink. */
|
|
45443
|
+
function collapseRows(before, target) {
|
|
45444
|
+
const rows = flowRows(before);
|
|
45445
|
+
const headers = new Set(rows.filter((row) => row.kind === "summary").map((row) => row.key));
|
|
45446
|
+
for (const item of target) {
|
|
45447
|
+
if (item.kind !== "fold" || headers.has(item.key)) continue;
|
|
45448
|
+
const members = new Set(item.steps.map((step) => step.key));
|
|
45449
|
+
const at = rows.findIndex((row) => members.has(row.key));
|
|
45450
|
+
if (at >= 0) rows.splice(at, 0, {
|
|
45451
|
+
kind: "summary",
|
|
45452
|
+
key: item.key,
|
|
45453
|
+
item: {
|
|
45454
|
+
...item,
|
|
45455
|
+
summary: item.summary.replace(/\d+/g, "0")
|
|
45456
|
+
}
|
|
45457
|
+
});
|
|
45458
|
+
}
|
|
45459
|
+
return rows;
|
|
45460
|
+
}
|
|
45461
|
+
function containsNewUser(before, after) {
|
|
45462
|
+
const users = new Set(before.filter((item) => item.kind === "user").map((item) => item.key));
|
|
45463
|
+
return after.some((item) => item.kind === "user" && !users.has(item.key));
|
|
45464
|
+
}
|
|
45465
|
+
//#endregion
|
|
45466
|
+
//#region src/client/LiveFold.tsx
|
|
45467
|
+
/** Values are presentation commits, never live network counters. */
|
|
45468
|
+
function SubtleNumberRoll({ value, motion }) {
|
|
45469
|
+
const [outgoing, setOutgoing] = (0, react.useState)(null);
|
|
45470
|
+
const previous = (0, react.useRef)(value);
|
|
45471
|
+
(0, react.useLayoutEffect)(() => {
|
|
45472
|
+
if (value === previous.current) return;
|
|
45473
|
+
const old = previous.current;
|
|
45474
|
+
previous.current = value;
|
|
45475
|
+
if (!motion) {
|
|
45476
|
+
setOutgoing(null);
|
|
45477
|
+
return;
|
|
45478
|
+
}
|
|
45479
|
+
setOutgoing(old);
|
|
45480
|
+
const timer = window.setTimeout(() => setOutgoing(null), FOLD_TIMING.count);
|
|
45481
|
+
return () => window.clearTimeout(timer);
|
|
45482
|
+
}, [value, motion]);
|
|
45483
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
45484
|
+
className: Reader_module_css_default.numberRollRoot,
|
|
45485
|
+
"aria-hidden": "true",
|
|
45486
|
+
children: [
|
|
45487
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
45488
|
+
className: Reader_module_css_default.numberRollSizer,
|
|
45489
|
+
children: value
|
|
45490
|
+
}),
|
|
45491
|
+
outgoing !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
45492
|
+
className: `${Reader_module_css_default.numberRollDigit} ${Reader_module_css_default.numberRollExit}`,
|
|
45493
|
+
children: outgoing
|
|
45494
|
+
}, `out-${outgoing}`),
|
|
45495
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
45496
|
+
className: `${Reader_module_css_default.numberRollDigit} ${outgoing !== null ? Reader_module_css_default.numberRollEnter : ""}`,
|
|
45497
|
+
children: value
|
|
45498
|
+
}, `cur-${value}`)
|
|
45499
|
+
]
|
|
45500
|
+
});
|
|
45501
|
+
}
|
|
45502
|
+
function FoldSummaryText({ summary, motion }) {
|
|
45503
|
+
const parts = (0, react.useMemo)(() => {
|
|
45504
|
+
const regex = /([^\d]+)(\d+)/g;
|
|
45505
|
+
const result = [];
|
|
45506
|
+
let end = 0;
|
|
45507
|
+
for (const match of summary.matchAll(regex)) {
|
|
45508
|
+
result.push({
|
|
45509
|
+
text: match[1],
|
|
45510
|
+
number: Number(match[2])
|
|
45511
|
+
});
|
|
45512
|
+
end = match.index + match[0].length;
|
|
45513
|
+
}
|
|
45514
|
+
if (end < summary.length) result.push({ text: summary.slice(end) });
|
|
45515
|
+
return result;
|
|
45516
|
+
}, [summary]);
|
|
45517
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
45518
|
+
className: Reader_module_css_default.foldSummary,
|
|
45519
|
+
"data-reader-fold-summary": summary,
|
|
45520
|
+
"aria-label": summary,
|
|
45521
|
+
children: parts.map((part) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
45522
|
+
className: Reader_module_css_default.foldSummaryPart,
|
|
45523
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: part.text }), part.number !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubtleNumberRoll, {
|
|
45524
|
+
value: part.number,
|
|
45525
|
+
motion
|
|
45526
|
+
})]
|
|
45527
|
+
}, part.text))
|
|
45528
|
+
});
|
|
45529
|
+
}
|
|
45530
|
+
//#endregion
|
|
45531
|
+
//#region src/client/projection.ts
|
|
45532
|
+
function groupNodes(order, get) {
|
|
45533
|
+
const groups = [];
|
|
45534
|
+
const seenTurns = /* @__PURE__ */ new Set();
|
|
45535
|
+
for (const key of order) {
|
|
45536
|
+
const node = get(key);
|
|
45537
|
+
if (!node || node.visibility === "hidden") continue;
|
|
45538
|
+
const turn = node.location.kind === "step" || node.location.kind === "turn" ? node.location.turn.turn : null;
|
|
45539
|
+
const previous = groups.at(-1);
|
|
45540
|
+
if (turn !== null && previous?.turn === turn) previous.keys.push(key);
|
|
45541
|
+
else {
|
|
45542
|
+
groups.push({
|
|
45543
|
+
key: turn === null ? `node:${key}` : seenTurns.has(turn) ? `turn:${turn}:${key}` : `turn:${turn}`,
|
|
45544
|
+
turn,
|
|
45545
|
+
keys: [key]
|
|
45546
|
+
});
|
|
45547
|
+
if (turn !== null) seenTurns.add(turn);
|
|
45548
|
+
}
|
|
45549
|
+
}
|
|
45550
|
+
return groups;
|
|
45551
|
+
}
|
|
45552
|
+
function boundaryOf(turn) {
|
|
45553
|
+
return {
|
|
45554
|
+
status: turn?.status ?? "unknown",
|
|
45555
|
+
reason: turn?.end?.data.reason.kind ?? null,
|
|
45556
|
+
latestStep: turn?.steps.at(-1)?.step ?? -1,
|
|
45557
|
+
closingStep: turn?.data.get("turn-tail")?.closing?.step ?? null
|
|
45558
|
+
};
|
|
45559
|
+
}
|
|
45560
|
+
/**
|
|
45561
|
+
* A settled body step before the closing step of a successful turn.
|
|
45562
|
+
*
|
|
45563
|
+
* This is presentation classification only. Narration is never process content
|
|
45564
|
+
* and never folds. The flag only marks body text that is no longer the turn's
|
|
45565
|
+
* final answer, so copy and fork stay on that final answer.
|
|
45566
|
+
*/
|
|
45567
|
+
function isEarlierNarration(data, boundary) {
|
|
45568
|
+
if (data.status !== "settled" || boundary.status !== "closed" || boundary.reason !== "completed") return false;
|
|
45569
|
+
if (data.blocks.some((block) => block.kind === "image" || block.kind === "other")) return false;
|
|
45570
|
+
return boundary.closingStep !== null && data.step < boundary.closingStep;
|
|
45571
|
+
}
|
|
45572
|
+
function processExpanded(choice, boundary) {
|
|
45573
|
+
return choice ?? !(boundary.status === "closed" && boundary.reason === "completed");
|
|
45574
|
+
}
|
|
45575
|
+
/** Reading while running must not pin the process open after completion. */
|
|
45576
|
+
function processChoiceKey(groupKey, boundary) {
|
|
45577
|
+
return `${groupKey}:${boundary.status}:${boundary.reason ?? "pending"}`;
|
|
45578
|
+
}
|
|
45579
|
+
/**
|
|
45580
|
+
* A body-only assistant step is not a thinking/process disclosure.
|
|
45581
|
+
*
|
|
45582
|
+
* Narration (text/image/other blocks) is always visible, so it never counts as
|
|
45583
|
+
* foldable process content; only literal reasoning does. Tool calls arrive as
|
|
45584
|
+
* their own flow entries and are checked separately by the reader.
|
|
45585
|
+
*/
|
|
45586
|
+
function hasProcessContent(node, _boundary) {
|
|
45587
|
+
if (!node || node.visibility === "hidden") return false;
|
|
45588
|
+
if (node.kind === "assistant-step") return node.data.blocks.some((block) => block.kind === "reasoning" && block.text.trim() !== "");
|
|
45589
|
+
return node.kind === "context" || node.kind === "model-retry" || node.kind === "system-prompt" || node.kind === "turn-process" || node.kind === "command" || node.kind === "manual-compaction" || node.kind === "compaction";
|
|
45590
|
+
}
|
|
45591
|
+
function hasVisibleBody(blocks) {
|
|
45592
|
+
return blocks.some((block) => block.kind === "image" || block.kind === "other" || block.kind === "text" && block.text.trim() !== "");
|
|
45593
|
+
}
|
|
45594
|
+
/** Keep native block order. In particular, never lift a later Think above text. */
|
|
45595
|
+
function assistantSegments(blocks) {
|
|
45596
|
+
const segments = [];
|
|
45597
|
+
let previous;
|
|
45598
|
+
blocks.forEach((block, index) => {
|
|
45599
|
+
if (block.kind === "tool-call") {
|
|
45600
|
+
previous = void 0;
|
|
45601
|
+
return;
|
|
45602
|
+
}
|
|
45603
|
+
const kind = block.kind === "reasoning" ? "reasoning" : "body";
|
|
45604
|
+
if (previous?.kind === kind) previous.blocks.push(block);
|
|
45605
|
+
else {
|
|
45606
|
+
previous = {
|
|
45607
|
+
kind,
|
|
45608
|
+
start: index,
|
|
45609
|
+
blocks: [block]
|
|
45610
|
+
};
|
|
45611
|
+
segments.push(previous);
|
|
45612
|
+
}
|
|
45613
|
+
});
|
|
45614
|
+
return segments;
|
|
45615
|
+
}
|
|
45616
|
+
function terminalLabel(reason) {
|
|
45617
|
+
switch (reason) {
|
|
45618
|
+
case "completed": return null;
|
|
45619
|
+
case "aborted":
|
|
45620
|
+
case "interrupted": return "本轮已停止,已生成的内容仍保留。";
|
|
45621
|
+
case "blocked": return "本轮需要处理阻塞事项;请查看原对话与下方操作区。";
|
|
45622
|
+
case "max-tokens": return "输出达到本轮长度限制,内容可能尚未完整。";
|
|
45623
|
+
case "error": return "本轮未完成;错误信息保留在下方。";
|
|
45624
|
+
case null: return null;
|
|
45625
|
+
default: return `本轮结束状态:${reason}。请在原对话中核对完整记录。`;
|
|
45626
|
+
}
|
|
45627
|
+
}
|
|
45628
|
+
/**
|
|
45629
|
+
* Extract the first usable fork anchor seq from candidate message nodes.
|
|
45630
|
+
* Only the durable closing message seq cuts the intended turn prefix: an
|
|
45631
|
+
* absent anchor must surface as undefined (never as 0 or NaN), because the
|
|
45632
|
+
* host treats a missing atSeq as a whole-session fork.
|
|
45633
|
+
*/
|
|
45634
|
+
function forkAnchorSeq(candidates) {
|
|
45635
|
+
for (const candidate of candidates) {
|
|
45636
|
+
const seq = candidate?.seq;
|
|
45637
|
+
if (typeof seq === "number" && Number.isFinite(seq)) return seq;
|
|
45638
|
+
}
|
|
45639
|
+
}
|
|
45640
|
+
//#endregion
|
|
45641
|
+
//#region src/client/AssistantNode.tsx
|
|
45642
|
+
function isNode$1(node, kind) {
|
|
45643
|
+
return node.kind === kind;
|
|
45644
|
+
}
|
|
45645
|
+
const AssistantNode = (0, react.memo)(function AssistantNode({ useChat, nodeKey, boundary, processOpen = false, pinned = false, folded = false, partStart, seamSummary, seamAfter = false, motion, onRead, returnFocusTo, ...render }) {
|
|
45646
|
+
const node = useChat((snapshot) => snapshot.nodes.get(nodeKey));
|
|
45647
|
+
if (!node || node.visibility === "hidden" || !isNode$1(node, "assistant-step")) return null;
|
|
45648
|
+
const data = node.data;
|
|
45649
|
+
const parts = assistantSegments(data.blocks);
|
|
45650
|
+
const earlier = isEarlierNarration(data, boundary);
|
|
45651
|
+
const hasToolCalls = data.blocks.some((block) => block.kind === "tool-call");
|
|
45652
|
+
const isProcessStep = earlier || folded || hasToolCalls || boundary.latestStep > 0 && data.step < boundary.latestStep;
|
|
45653
|
+
const body = data.blocks.filter((block) => block.kind !== "reasoning" && block.kind !== "tool-call");
|
|
45654
|
+
const visible = partStart === void 0 ? parts : parts.filter((part) => part.start === partStart);
|
|
45655
|
+
const bodyProps = {
|
|
45656
|
+
streaming: data.status === "running",
|
|
45657
|
+
holdFormatting: pinned,
|
|
45658
|
+
startedAt: data.time,
|
|
45659
|
+
interrupted: data.status === "interrupted",
|
|
45660
|
+
liveText: true
|
|
45661
|
+
};
|
|
45662
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: visible.map((part) => {
|
|
45663
|
+
const last = parts.findIndex((item) => item.start === part.start) === parts.length - 1;
|
|
45664
|
+
if (part.kind === "reasoning") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProcessFragment, {
|
|
45665
|
+
open: processOpen,
|
|
45666
|
+
motion,
|
|
45667
|
+
onRead,
|
|
45668
|
+
returnFocusTo,
|
|
45669
|
+
nodeKey,
|
|
45670
|
+
framed: true,
|
|
45671
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningCard, {
|
|
45672
|
+
step: data.step,
|
|
45673
|
+
active: processOpen && boundary.status === "open" && data.step === boundary.latestStep,
|
|
45674
|
+
motion,
|
|
45675
|
+
selected: pinned,
|
|
45676
|
+
onRead,
|
|
45677
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
45678
|
+
...render,
|
|
45679
|
+
blocks: part.blocks,
|
|
45680
|
+
streaming: data.status === "running" && last && data.blocks.at(-1)?.kind === "reasoning",
|
|
45681
|
+
holdFormatting: pinned,
|
|
45682
|
+
startedAt: data.time,
|
|
45683
|
+
interrupted: data.status === "interrupted",
|
|
45684
|
+
liveText: true
|
|
45685
|
+
})
|
|
45686
|
+
})
|
|
45687
|
+
}, part.start);
|
|
45688
|
+
if (!hasVisibleBody(part.blocks)) return null;
|
|
45689
|
+
const isFinalAnswer = !isProcessStep;
|
|
45690
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [seamSummary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
45691
|
+
className: Reader_module_css_default.processSeamRow,
|
|
45692
|
+
"data-reader-process-seam": true,
|
|
45693
|
+
"data-reader-process-seam-summary": seamSummary,
|
|
45694
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Disclosure, {
|
|
45695
|
+
open: false,
|
|
45696
|
+
onChange: () => onRead(),
|
|
45697
|
+
ariaLabel: "被折叠的过程",
|
|
45698
|
+
label: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FoldSummaryText, {
|
|
45699
|
+
summary: seamSummary,
|
|
45700
|
+
motion: false
|
|
45701
|
+
})
|
|
45702
|
+
})
|
|
45703
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
45704
|
+
className: Reader_module_css_default.answer,
|
|
45705
|
+
"data-reader-body": true,
|
|
45706
|
+
"data-reader-anchor": true,
|
|
45707
|
+
"data-reader-key": nodeKey,
|
|
45708
|
+
"data-reader-source-start": part.start,
|
|
45709
|
+
"data-reader-seam-after": seamAfter || void 0,
|
|
45710
|
+
"data-answer-status": data.status,
|
|
45711
|
+
"data-answer-phase": isFinalAnswer ? "body" : "process",
|
|
45712
|
+
children: [
|
|
45713
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(OfficialAssistantBody, {
|
|
45714
|
+
...render,
|
|
45715
|
+
node,
|
|
45716
|
+
blocks: part.blocks,
|
|
45717
|
+
...bodyProps
|
|
45718
|
+
}),
|
|
45719
|
+
isFinalAnswer && last && data.status === "interrupted" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
45720
|
+
className: Reader_module_css_default.stopped,
|
|
45721
|
+
children: "已停止"
|
|
45722
|
+
}),
|
|
45723
|
+
isFinalAnswer && last && data.status !== "running" && boundary.status === "closed" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyAnswer, {
|
|
45724
|
+
blocks: body,
|
|
45725
|
+
onFork: (() => {
|
|
45726
|
+
const anchor = forkAnchorSeq([data.finalNode, { seq: render.forkSeq }]);
|
|
45727
|
+
return render.forkAt && anchor !== void 0 ? () => render.forkAt(anchor) : void 0;
|
|
45728
|
+
})(),
|
|
45729
|
+
metrics: render.metrics,
|
|
45730
|
+
extraActions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OfficialActions, {
|
|
45731
|
+
official: render.official,
|
|
45732
|
+
messageId: data.finalNode?.messageId
|
|
45733
|
+
})
|
|
45734
|
+
})
|
|
45735
|
+
]
|
|
45736
|
+
})] }, part.start);
|
|
45737
|
+
}) });
|
|
45738
|
+
});
|
|
45739
|
+
//#endregion
|
|
44594
45740
|
//#region src/client/native/tool-call-model.ts
|
|
44595
45741
|
/**
|
|
44596
45742
|
* Pure row-model derivation for tool summary rows: variant classification,
|
|
@@ -44801,6 +45947,10 @@ ${trimmed}
|
|
|
44801
45947
|
other: _deepseek_ai_dsh_client_ui_primitives.IconSparkleRegular
|
|
44802
45948
|
};
|
|
44803
45949
|
const number = new Intl.NumberFormat("zh-CN");
|
|
45950
|
+
const preparingTerminalLabels = {
|
|
45951
|
+
...terminalBlockLabels,
|
|
45952
|
+
running: "正在生成命令"
|
|
45953
|
+
};
|
|
44804
45954
|
const language = (path) => path?.split(".").at(-1);
|
|
44805
45955
|
const duration = (ms) => ms < 1e3 ? `${Math.round(ms)} 毫秒` : `${(ms / 1e3).toFixed(ms < 1e4 ? 1 : 0)} 秒`;
|
|
44806
45956
|
function generatedInput(content, target, preparing) {
|
|
@@ -44824,7 +45974,9 @@ ${trimmed}
|
|
|
44824
45974
|
})]
|
|
44825
45975
|
});
|
|
44826
45976
|
}
|
|
44827
|
-
function InputView({ model,
|
|
45977
|
+
function InputView({ model, phase, fillComposer }) {
|
|
45978
|
+
const preparing = phase === "preparing";
|
|
45979
|
+
const inProgress = preparing || phase === "running";
|
|
44828
45980
|
if ((model.name === "render_ui" || model.name === "show_widget") && typeof model.args?.html === "string") return preparing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StreamingMcpAppPlaceholder, { title: typeof model.args.title === "string" ? model.args.title : void 0 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(McpAppFrame, {
|
|
44829
45981
|
html: model.args.html,
|
|
44830
45982
|
title: typeof model.args.title === "string" ? model.args.title : void 0,
|
|
@@ -44839,9 +45991,15 @@ ${trimmed}
|
|
|
44839
45991
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
|
|
44840
45992
|
command: model.command,
|
|
44841
45993
|
cwd: model.cwd,
|
|
44842
|
-
|
|
45994
|
+
running: inProgress,
|
|
45995
|
+
labels: preparing ? preparingTerminalLabels : terminalBlockLabels
|
|
44843
45996
|
})]
|
|
44844
45997
|
});
|
|
45998
|
+
if (model.category === "terminal" && preparing && model.argsState === "partial") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
45999
|
+
className: Reader_module_css_default.toolDetailNote,
|
|
46000
|
+
"data-reader-tool-command-pending": true,
|
|
46001
|
+
children: "命令仍在生成,收到可识别的命令文本后会显示预览。"
|
|
46002
|
+
});
|
|
44845
46003
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.JsonTree, {
|
|
44846
46004
|
data: model.args,
|
|
44847
46005
|
label: preparing ? "已收到的输入字段" : "工具输入",
|
|
@@ -44924,7 +46082,7 @@ ${trimmed}
|
|
|
44924
46082
|
children: phase === "interrupted" ? "已中断,没有工具结果。已生成的输入仍可查看。" : phase === "preparing" ? "模型正在生成工具输入,工具还未开始执行。" : "工具已开始执行,正在等待结果。"
|
|
44925
46083
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InputView, {
|
|
44926
46084
|
model,
|
|
44927
|
-
|
|
46085
|
+
phase,
|
|
44928
46086
|
fillComposer: render.fillComposer
|
|
44929
46087
|
})] });
|
|
44930
46088
|
const meta = objectValue(block.meta);
|
|
@@ -44936,7 +46094,7 @@ ${trimmed}
|
|
|
44936
46094
|
}),
|
|
44937
46095
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InputView, {
|
|
44938
46096
|
model,
|
|
44939
|
-
|
|
46097
|
+
phase,
|
|
44940
46098
|
fillComposer: render.fillComposer
|
|
44941
46099
|
}),
|
|
44942
46100
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
@@ -45299,7 +46457,7 @@ ${trimmed}
|
|
|
45299
46457
|
}),
|
|
45300
46458
|
tab === "input" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InputView, {
|
|
45301
46459
|
model: preview.model,
|
|
45302
|
-
|
|
46460
|
+
phase: preview.phase,
|
|
45303
46461
|
fillComposer: render.fillComposer
|
|
45304
46462
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
45305
46463
|
className: Reader_module_css_default.detail,
|
|
@@ -45372,106 +46530,6 @@ ${trimmed}
|
|
|
45372
46530
|
}, child.callId))] });
|
|
45373
46531
|
}
|
|
45374
46532
|
//#endregion
|
|
45375
|
-
//#region src/client/projection.ts
|
|
45376
|
-
function groupNodes(order, get) {
|
|
45377
|
-
const groups = [];
|
|
45378
|
-
const seenTurns = /* @__PURE__ */ new Set();
|
|
45379
|
-
for (const key of order) {
|
|
45380
|
-
const node = get(key);
|
|
45381
|
-
if (!node || node.visibility === "hidden") continue;
|
|
45382
|
-
const turn = node.location.kind === "step" || node.location.kind === "turn" ? node.location.turn.turn : null;
|
|
45383
|
-
const previous = groups.at(-1);
|
|
45384
|
-
if (turn !== null && previous?.turn === turn) previous.keys.push(key);
|
|
45385
|
-
else {
|
|
45386
|
-
groups.push({
|
|
45387
|
-
key: turn === null ? `node:${key}` : seenTurns.has(turn) ? `turn:${turn}:${key}` : `turn:${turn}`,
|
|
45388
|
-
turn,
|
|
45389
|
-
keys: [key]
|
|
45390
|
-
});
|
|
45391
|
-
if (turn !== null) seenTurns.add(turn);
|
|
45392
|
-
}
|
|
45393
|
-
}
|
|
45394
|
-
return groups;
|
|
45395
|
-
}
|
|
45396
|
-
function boundaryOf(turn) {
|
|
45397
|
-
return {
|
|
45398
|
-
status: turn?.status ?? "unknown",
|
|
45399
|
-
reason: turn?.end?.data.reason.kind ?? null,
|
|
45400
|
-
latestStep: turn?.steps.at(-1)?.step ?? -1,
|
|
45401
|
-
closingStep: turn?.data.get("turn-tail")?.closing?.step ?? null
|
|
45402
|
-
};
|
|
45403
|
-
}
|
|
45404
|
-
function isEarlierNarration(data, boundary) {
|
|
45405
|
-
if (data.status !== "settled" || boundary.status !== "closed" || boundary.reason !== "completed") return false;
|
|
45406
|
-
if (data.blocks.some((block) => block.kind === "image" || block.kind === "other")) return false;
|
|
45407
|
-
return boundary.closingStep !== null && data.step < boundary.closingStep;
|
|
45408
|
-
}
|
|
45409
|
-
function processExpanded(choice, boundary) {
|
|
45410
|
-
return choice ?? !(boundary.status === "closed" && boundary.reason === "completed");
|
|
45411
|
-
}
|
|
45412
|
-
/** Reading while running must not pin the process open after completion. */
|
|
45413
|
-
function processChoiceKey(groupKey, boundary) {
|
|
45414
|
-
return `${groupKey}:${boundary.status}:${boundary.reason ?? "pending"}`;
|
|
45415
|
-
}
|
|
45416
|
-
/** A body-only assistant step is not a thinking/process disclosure. */
|
|
45417
|
-
function hasProcessContent(node, boundary) {
|
|
45418
|
-
if (!node || node.visibility === "hidden") return false;
|
|
45419
|
-
if (node.kind === "assistant-step") {
|
|
45420
|
-
const data = node.data;
|
|
45421
|
-
return data.blocks.some((block) => block.kind === "reasoning" && block.text.trim() !== "") || isEarlierNarration(data, boundary) && hasVisibleBody(data.blocks);
|
|
45422
|
-
}
|
|
45423
|
-
return node.kind === "context" || node.kind === "model-retry" || node.kind === "system-prompt" || node.kind === "turn-process" || node.kind === "command" || node.kind === "manual-compaction" || node.kind === "compaction";
|
|
45424
|
-
}
|
|
45425
|
-
function hasVisibleBody(blocks) {
|
|
45426
|
-
return blocks.some((block) => block.kind === "image" || block.kind === "other" || block.kind === "text" && block.text.trim() !== "");
|
|
45427
|
-
}
|
|
45428
|
-
/** Keep native block order. In particular, never lift a later Think above text. */
|
|
45429
|
-
function assistantSegments(blocks) {
|
|
45430
|
-
const segments = [];
|
|
45431
|
-
let previous;
|
|
45432
|
-
blocks.forEach((block, index) => {
|
|
45433
|
-
if (block.kind === "tool-call") {
|
|
45434
|
-
previous = void 0;
|
|
45435
|
-
return;
|
|
45436
|
-
}
|
|
45437
|
-
const kind = block.kind === "reasoning" ? "reasoning" : "body";
|
|
45438
|
-
if (previous?.kind === kind) previous.blocks.push(block);
|
|
45439
|
-
else {
|
|
45440
|
-
previous = {
|
|
45441
|
-
kind,
|
|
45442
|
-
start: index,
|
|
45443
|
-
blocks: [block]
|
|
45444
|
-
};
|
|
45445
|
-
segments.push(previous);
|
|
45446
|
-
}
|
|
45447
|
-
});
|
|
45448
|
-
return segments;
|
|
45449
|
-
}
|
|
45450
|
-
function terminalLabel(reason) {
|
|
45451
|
-
switch (reason) {
|
|
45452
|
-
case "completed": return null;
|
|
45453
|
-
case "aborted":
|
|
45454
|
-
case "interrupted": return "本轮已停止,已生成的内容仍保留。";
|
|
45455
|
-
case "blocked": return "本轮需要处理阻塞事项;请查看原对话与下方操作区。";
|
|
45456
|
-
case "max-tokens": return "输出达到本轮长度限制,内容可能尚未完整。";
|
|
45457
|
-
case "error": return "本轮未完成;错误信息保留在下方。";
|
|
45458
|
-
case null: return null;
|
|
45459
|
-
default: return `本轮结束状态:${reason}。请在原对话中核对完整记录。`;
|
|
45460
|
-
}
|
|
45461
|
-
}
|
|
45462
|
-
/**
|
|
45463
|
-
* Extract the first usable fork anchor seq from candidate message nodes.
|
|
45464
|
-
* Only the durable closing message seq cuts the intended turn prefix: an
|
|
45465
|
-
* absent anchor must surface as undefined (never as 0 or NaN), because the
|
|
45466
|
-
* host treats a missing atSeq as a whole-session fork.
|
|
45467
|
-
*/
|
|
45468
|
-
function forkAnchorSeq(candidates) {
|
|
45469
|
-
for (const candidate of candidates) {
|
|
45470
|
-
const seq = candidate?.seq;
|
|
45471
|
-
if (typeof seq === "number" && Number.isFinite(seq)) return seq;
|
|
45472
|
-
}
|
|
45473
|
-
}
|
|
45474
|
-
//#endregion
|
|
45475
46533
|
//#region src/client/open-file.ts
|
|
45476
46534
|
function deliverableOpenModeOf(value) {
|
|
45477
46535
|
return value === "sidebar" ? "sidebar" : "external";
|
|
@@ -45487,12 +46545,6 @@ ${trimmed}
|
|
|
45487
46545
|
function isFolderOpenPath(path) {
|
|
45488
46546
|
return path === "." || path === "";
|
|
45489
46547
|
}
|
|
45490
|
-
function isWindowsStylePath(value) {
|
|
45491
|
-
return /^[A-Za-z]:[/\\]/.test(value) || value.startsWith("\\\\");
|
|
45492
|
-
}
|
|
45493
|
-
function isAbsoluteWorkspacePath(path) {
|
|
45494
|
-
return path.startsWith("/") || isWindowsStylePath(path);
|
|
45495
|
-
}
|
|
45496
46548
|
function encodeSegment(segment) {
|
|
45497
46549
|
return encodeURIComponent(segment).replace(/%3A/gi, ":");
|
|
45498
46550
|
}
|
|
@@ -46399,7 +47451,7 @@ ${trimmed}
|
|
|
46399
47451
|
}
|
|
46400
47452
|
//#endregion
|
|
46401
47453
|
//#region \0dshx-css-module:TimelineRail.module.css.mjs
|
|
46402
|
-
const css$1 = ".oG8zJG_slot{z-index:10;pointer-events:none;height:0;position:sticky;top:0}.oG8zJG_frame{--turn-rail-band:calc(var(--dsh-conversation-viewport-height,100dvh) - var(--dsh-composer-height,152px));--turn-preview-height:100px;top:calc(var(--turn-rail-band) / 2);width:26px;height:min(var(--turn-natural-height), max(0px, calc(var(--turn-rail-band) - 64px)), 420px);cursor:pointer;pointer-events:auto;transition:height .22s cubic-bezier(.2,.8,.2,1);position:absolute;right:6px;transform:translateY(-50%)}.oG8zJG_scroller{overscroll-behavior:contain;scrollbar-width:none;position:absolute;inset:0;overflow-y:auto}.oG8zJG_scroller::-webkit-scrollbar{display:none}.oG8zJG_fadeTop{
|
|
47454
|
+
const css$1 = ".oG8zJG_slot{z-index:10;pointer-events:none;height:0;position:sticky;top:0}.oG8zJG_frame{--turn-rail-band:calc(var(--dsh-conversation-viewport-height,100dvh) - var(--dsh-composer-height,152px));--turn-preview-height:100px;top:calc(var(--turn-rail-band) / 2);width:26px;height:min(var(--turn-natural-height), max(0px, calc(var(--turn-rail-band) - 64px)), 420px);cursor:pointer;pointer-events:auto;transition:height .22s cubic-bezier(.2,.8,.2,1);position:absolute;right:6px;transform:translateY(-50%)}.oG8zJG_scroller{overscroll-behavior:contain;scrollbar-width:none;position:absolute;inset:0;overflow-y:auto}.oG8zJG_scroller::-webkit-scrollbar{display:none}.oG8zJG_fadeTop{mask-image:linear-gradient(#0000 0,#000 24px 100%)}.oG8zJG_fadeBottom{mask-image:linear-gradient(#000 0 calc(100% - 24px),#0000 100%)}.oG8zJG_fadeTop.oG8zJG_fadeBottom{mask-image:linear-gradient(#0000 0,#000 24px calc(100% - 24px),#0000 100%)}.oG8zJG_marks{height:var(--turn-natural-height);position:relative}.oG8zJG_markPosition{top:calc(var(--turn-natural-position) + var(--turn-rail-inset));height:12px;transition:top .22s cubic-bezier(.2,.8,.2,1);position:absolute;left:0;right:0;transform:translateY(-50%)}.oG8zJG_mark{cursor:pointer;pointer-events:none;background:0 0;border:0;justify-content:flex-end;align-items:center;width:24px;padding:0;display:flex;position:absolute;inset:0 0 0 auto}.oG8zJG_tick{border-radius:2px;flex:none;transition:width .1s cubic-bezier(.16,1,.3,1),height .1s cubic-bezier(.16,1,.3,1),opacity .1s,background-color .14s}.oG8zJG_markBusy .oG8zJG_tick{animation:1s ease-in-out infinite alternate oG8zJG_markBusyPulse}@keyframes oG8zJG_markBusyPulse{0%{opacity:.4;width:8px}to{opacity:1;width:18px}}.oG8zJG_preview{top:clamp(0px, calc(var(--turn-natural-position) + var(--turn-rail-inset) - var(--turn-scroll-top,0px) - var(--turn-preview-height) / 2), calc(100% - var(--turn-preview-height)));box-sizing:border-box;width:min(280px,100cqw - 120px);max-height:var(--turn-preview-height);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);pointer-events:none;z-index:40;border-radius:10px;padding:10px 12px;transition:top .14s cubic-bezier(.2,.8,.2,1);animation:.12s ease-out oG8zJG_previewFadeIn;position:absolute;right:calc(100% + 10px);overflow:hidden;box-shadow:0 4px 18px #0000001f}@keyframes oG8zJG_previewFadeIn{0%{opacity:0;transform:translate(4px)}to{opacity:1;transform:translate(0)}}.oG8zJG_previewPrompt{-webkit-line-clamp:2;text-overflow:ellipsis;word-break:break-word;-webkit-box-orient:vertical;font-size:12px;font-weight:500;line-height:18px;display:-webkit-box;overflow:hidden}.oG8zJG_previewResponse{color:var(--dsw-alias-label-tertiary);-webkit-line-clamp:2;text-overflow:ellipsis;word-break:break-word;-webkit-box-orient:vertical;margin-top:4px;font-size:11px;line-height:16px;display:-webkit-box;overflow:hidden}@media (width<=960px){.oG8zJG_slot{display:none!important}}";
|
|
46403
47455
|
const tagId$1 = "dsh-better-display/TimelineRail.module.css";
|
|
46404
47456
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
46405
47457
|
const tag = document.createElement("style");
|
|
@@ -46708,27 +47760,6 @@ ${trimmed}
|
|
|
46708
47760
|
if (extra) parts.push(`记录×${extra}`);
|
|
46709
47761
|
return parts.join(" · ") || "此前步骤";
|
|
46710
47762
|
}
|
|
46711
|
-
/** One chain: fold only when a new reasoning step has prior body/tool/reasoning. */
|
|
46712
|
-
function splitChain(chain) {
|
|
46713
|
-
const lastReasoning = chain.findLastIndex((step) => step.kind === "reasoning");
|
|
46714
|
-
if (lastReasoning < 0) return {
|
|
46715
|
-
fold: null,
|
|
46716
|
-
open: chain
|
|
46717
|
-
};
|
|
46718
|
-
const prior = chain.slice(0, lastReasoning);
|
|
46719
|
-
if (!prior.length) return {
|
|
46720
|
-
fold: null,
|
|
46721
|
-
open: chain
|
|
46722
|
-
};
|
|
46723
|
-
if (!prior.some((step) => step.kind === "reasoning" || step.kind === "body" || step.kind === "tool")) return {
|
|
46724
|
-
fold: null,
|
|
46725
|
-
open: chain
|
|
46726
|
-
};
|
|
46727
|
-
return {
|
|
46728
|
-
fold: prior,
|
|
46729
|
-
open: chain.slice(lastReasoning)
|
|
46730
|
-
};
|
|
46731
|
-
}
|
|
46732
47763
|
function skipReasoning(part) {
|
|
46733
47764
|
return part.kind === "reasoning" && !part.blocks.some((block) => block.kind === "reasoning" && block.text.trim() !== "");
|
|
46734
47765
|
}
|
|
@@ -46808,46 +47839,117 @@ ${trimmed}
|
|
|
46808
47839
|
}
|
|
46809
47840
|
return steps;
|
|
46810
47841
|
}
|
|
47842
|
+
/** Only a run that contains real thinking/tool work is worth folding. */
|
|
47843
|
+
function foldableRun(run) {
|
|
47844
|
+
return run.some((step) => step.kind === "reasoning" || step.kind === "tool");
|
|
47845
|
+
}
|
|
47846
|
+
/**
|
|
47847
|
+
* One live chain: narration stays visible, while every earlier reasoning/tool
|
|
47848
|
+
* run collapses into its own box at its original position.
|
|
47849
|
+
*/
|
|
46811
47850
|
function presentLiveTurn(steps, boundary, autoFold = true) {
|
|
46812
47851
|
const live = autoFold && liveFoldEnabled(boundary);
|
|
46813
47852
|
const items = [];
|
|
46814
|
-
|
|
46815
|
-
|
|
46816
|
-
|
|
46817
|
-
|
|
46818
|
-
|
|
46819
|
-
|
|
46820
|
-
|
|
46821
|
-
|
|
46822
|
-
});
|
|
46823
|
-
chain = [];
|
|
46824
|
-
return;
|
|
46825
|
-
}
|
|
46826
|
-
const { fold, open } = splitChain(chain);
|
|
46827
|
-
if (fold?.length) items.push({
|
|
47853
|
+
const open = (step) => items.push({
|
|
47854
|
+
kind: "open",
|
|
47855
|
+
key: step.key,
|
|
47856
|
+
step
|
|
47857
|
+
});
|
|
47858
|
+
const fold = (run) => {
|
|
47859
|
+
if (!run.length) return;
|
|
47860
|
+
if (live && foldableRun(run)) items.push({
|
|
46828
47861
|
kind: "fold",
|
|
46829
|
-
key: `live-fold:${
|
|
46830
|
-
steps:
|
|
46831
|
-
summary: foldSummary(
|
|
47862
|
+
key: `live-fold:${run[0].key}`,
|
|
47863
|
+
steps: run,
|
|
47864
|
+
summary: foldSummary(run)
|
|
46832
47865
|
});
|
|
46833
|
-
for (const step of
|
|
46834
|
-
|
|
46835
|
-
|
|
46836
|
-
|
|
46837
|
-
|
|
46838
|
-
|
|
47866
|
+
else for (const step of run) open(step);
|
|
47867
|
+
};
|
|
47868
|
+
let run = [];
|
|
47869
|
+
const flush = () => {
|
|
47870
|
+
fold(run);
|
|
47871
|
+
run = [];
|
|
46839
47872
|
};
|
|
47873
|
+
const segments = [];
|
|
47874
|
+
let segment = [];
|
|
46840
47875
|
for (const step of steps) if (step.kind === "user") {
|
|
47876
|
+
segments.push(segment);
|
|
47877
|
+
segments.push([step]);
|
|
47878
|
+
segment = [];
|
|
47879
|
+
} else segment.push(step);
|
|
47880
|
+
segments.push(segment);
|
|
47881
|
+
for (const part of segments) {
|
|
47882
|
+
if (!part.length) continue;
|
|
47883
|
+
const first = part[0];
|
|
47884
|
+
if (part.length === 1 && first.kind === "user") {
|
|
47885
|
+
items.push({
|
|
47886
|
+
kind: "user",
|
|
47887
|
+
key: first.key,
|
|
47888
|
+
step: first
|
|
47889
|
+
});
|
|
47890
|
+
continue;
|
|
47891
|
+
}
|
|
47892
|
+
if (!live) {
|
|
47893
|
+
for (const step of part) open(step);
|
|
47894
|
+
continue;
|
|
47895
|
+
}
|
|
47896
|
+
const lastReasoning = part.findLastIndex((step) => step.kind === "reasoning");
|
|
47897
|
+
if (lastReasoning <= 0) {
|
|
47898
|
+
for (const step of part) open(step);
|
|
47899
|
+
continue;
|
|
47900
|
+
}
|
|
47901
|
+
for (let index = 0; index < part.length; index++) {
|
|
47902
|
+
const step = part[index];
|
|
47903
|
+
if (index < lastReasoning) {
|
|
47904
|
+
if (step.kind === "body") {
|
|
47905
|
+
flush();
|
|
47906
|
+
open(step);
|
|
47907
|
+
} else run.push(step);
|
|
47908
|
+
} else {
|
|
47909
|
+
if (index === lastReasoning) flush();
|
|
47910
|
+
open(step);
|
|
47911
|
+
}
|
|
47912
|
+
}
|
|
46841
47913
|
flush();
|
|
46842
|
-
|
|
46843
|
-
kind: "user",
|
|
46844
|
-
key: step.key,
|
|
46845
|
-
step
|
|
46846
|
-
});
|
|
46847
|
-
} else chain.push(step);
|
|
46848
|
-
flush();
|
|
47914
|
+
}
|
|
46849
47915
|
return items;
|
|
46850
47916
|
}
|
|
47917
|
+
/**
|
|
47918
|
+
* Summaries for collapsed process that sits between two narration blocks.
|
|
47919
|
+
*
|
|
47920
|
+
* A live-fold cell already shows that summary while the turn is open. Drawing
|
|
47921
|
+
* the seam as well repeats the same counts, so a run whose every step is
|
|
47922
|
+
* already inside a fold cell contributes neither a seam nor `after`. `after`
|
|
47923
|
+
* is what marks the previous body with `data-reader-seam-after` and drops its
|
|
47924
|
+
* bottom padding; skipping the seam must leave that spacing alone.
|
|
47925
|
+
*/
|
|
47926
|
+
function planProcessSeams(steps, liveItems, expanded) {
|
|
47927
|
+
const before = /* @__PURE__ */ new Map();
|
|
47928
|
+
const after = /* @__PURE__ */ new Set();
|
|
47929
|
+
if (expanded) return {
|
|
47930
|
+
before,
|
|
47931
|
+
after
|
|
47932
|
+
};
|
|
47933
|
+
const liveFolded = new Set(liveItems.flatMap((item) => item.kind === "fold" ? item.steps.map((step) => step.key) : []));
|
|
47934
|
+
let previousBody;
|
|
47935
|
+
let process = [];
|
|
47936
|
+
for (const step of steps) if (step.kind === "body") {
|
|
47937
|
+
const folded = process.filter((item) => item.kind !== "user");
|
|
47938
|
+
if (!(folded.length > 0 && folded.every((item) => liveFolded.has(item.key))) && previousBody && folded.some((item) => item.kind === "reasoning" || item.kind === "tool" || item.kind === "other")) {
|
|
47939
|
+
before.set(step.key, foldSummary(folded));
|
|
47940
|
+
after.add(previousBody.key);
|
|
47941
|
+
}
|
|
47942
|
+
previousBody = step;
|
|
47943
|
+
process = [];
|
|
47944
|
+
} else if (step.kind === "user") {
|
|
47945
|
+
previousBody = void 0;
|
|
47946
|
+
process = [];
|
|
47947
|
+
} else process.push(step);
|
|
47948
|
+
return {
|
|
47949
|
+
before,
|
|
47950
|
+
after
|
|
47951
|
+
};
|
|
47952
|
+
}
|
|
46851
47953
|
//#endregion
|
|
46852
47954
|
//#region src/client/fold-intensity.ts
|
|
46853
47955
|
function frostedGlassOf(state) {
|
|
@@ -46861,136 +47963,6 @@ ${trimmed}
|
|
|
46861
47963
|
return intensity === 2;
|
|
46862
47964
|
}
|
|
46863
47965
|
//#endregion
|
|
46864
|
-
//#region src/client/fold-choreography.ts
|
|
46865
|
-
/** Presentation clock, not model/network time. */
|
|
46866
|
-
const FOLD_TIMING = {
|
|
46867
|
-
collapse: 320,
|
|
46868
|
-
count: 160,
|
|
46869
|
-
settle: 80,
|
|
46870
|
-
reveal: 180,
|
|
46871
|
-
/**
|
|
46872
|
-
* Slack added to every phase deadline before the watchdog forces the next phase.
|
|
46873
|
-
*
|
|
46874
|
-
* The choreography advances on animation promises and rendered frames. Both are
|
|
46875
|
-
* best-effort: a cancelled animation *rejects* and a compositor that never
|
|
46876
|
-
* finishes one leaves its promise pending, while a backgrounded tab stops
|
|
46877
|
-
* delivering frames. Without a deadline the machine would sit in a non-idle
|
|
46878
|
-
* phase forever, and a non-idle phase freezes both the frame source and the text
|
|
46879
|
-
* reveal, so the turn would look stuck until a remount. This is the liveness
|
|
46880
|
-
* guarantee that does not depend on any of them.
|
|
46881
|
-
*/
|
|
46882
|
-
watchdogSlack: 240
|
|
46883
|
-
};
|
|
46884
|
-
/** A step always has the same parent and React key, even when its membership changes. */
|
|
46885
|
-
function flowRows(items) {
|
|
46886
|
-
return items.flatMap((item) => item.kind === "fold" ? [{
|
|
46887
|
-
kind: "summary",
|
|
46888
|
-
key: item.key,
|
|
46889
|
-
item
|
|
46890
|
-
}, ...item.steps.map((step) => ({
|
|
46891
|
-
kind: "step",
|
|
46892
|
-
key: step.key,
|
|
46893
|
-
step,
|
|
46894
|
-
foldKey: item.key
|
|
46895
|
-
}))] : [{
|
|
46896
|
-
kind: "step",
|
|
46897
|
-
key: item.key,
|
|
46898
|
-
step: item.step
|
|
46899
|
-
}]);
|
|
46900
|
-
}
|
|
46901
|
-
function retiringKeys(before, after, open) {
|
|
46902
|
-
const folded = new Set(flowRows(after).filter((row) => row.kind === "step" && row.foldKey && !open[row.foldKey]).map((row) => row.key));
|
|
46903
|
-
return flowRows(before).filter((row) => row.kind === "step" && !row.foldKey && folded.has(row.key)).map((row) => row.key);
|
|
46904
|
-
}
|
|
46905
|
-
/** Insert only new summary slots. Never admit incoming content during shrink. */
|
|
46906
|
-
function collapseRows(before, target) {
|
|
46907
|
-
const rows = flowRows(before);
|
|
46908
|
-
const headers = new Set(rows.filter((row) => row.kind === "summary").map((row) => row.key));
|
|
46909
|
-
for (const item of target) {
|
|
46910
|
-
if (item.kind !== "fold" || headers.has(item.key)) continue;
|
|
46911
|
-
const members = new Set(item.steps.map((step) => step.key));
|
|
46912
|
-
const at = rows.findIndex((row) => members.has(row.key));
|
|
46913
|
-
if (at >= 0) rows.splice(at, 0, {
|
|
46914
|
-
kind: "summary",
|
|
46915
|
-
key: item.key,
|
|
46916
|
-
item: {
|
|
46917
|
-
...item,
|
|
46918
|
-
summary: item.summary.replace(/\d+/g, "0")
|
|
46919
|
-
}
|
|
46920
|
-
});
|
|
46921
|
-
}
|
|
46922
|
-
return rows;
|
|
46923
|
-
}
|
|
46924
|
-
function containsNewUser(before, after) {
|
|
46925
|
-
const users = new Set(before.filter((item) => item.kind === "user").map((item) => item.key));
|
|
46926
|
-
return after.some((item) => item.kind === "user" && !users.has(item.key));
|
|
46927
|
-
}
|
|
46928
|
-
//#endregion
|
|
46929
|
-
//#region src/client/LiveFold.tsx
|
|
46930
|
-
/** Values are presentation commits, never live network counters. */
|
|
46931
|
-
function SubtleNumberRoll({ value, motion }) {
|
|
46932
|
-
const [outgoing, setOutgoing] = (0, react.useState)(null);
|
|
46933
|
-
const previous = (0, react.useRef)(value);
|
|
46934
|
-
(0, react.useLayoutEffect)(() => {
|
|
46935
|
-
if (value === previous.current) return;
|
|
46936
|
-
const old = previous.current;
|
|
46937
|
-
previous.current = value;
|
|
46938
|
-
if (!motion) {
|
|
46939
|
-
setOutgoing(null);
|
|
46940
|
-
return;
|
|
46941
|
-
}
|
|
46942
|
-
setOutgoing(old);
|
|
46943
|
-
const timer = window.setTimeout(() => setOutgoing(null), FOLD_TIMING.count);
|
|
46944
|
-
return () => window.clearTimeout(timer);
|
|
46945
|
-
}, [value, motion]);
|
|
46946
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
46947
|
-
className: Reader_module_css_default.numberRollRoot,
|
|
46948
|
-
"aria-hidden": "true",
|
|
46949
|
-
children: [
|
|
46950
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
46951
|
-
className: Reader_module_css_default.numberRollSizer,
|
|
46952
|
-
children: value
|
|
46953
|
-
}),
|
|
46954
|
-
outgoing !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
46955
|
-
className: `${Reader_module_css_default.numberRollDigit} ${Reader_module_css_default.numberRollExit}`,
|
|
46956
|
-
children: outgoing
|
|
46957
|
-
}, `out-${outgoing}`),
|
|
46958
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
46959
|
-
className: `${Reader_module_css_default.numberRollDigit} ${outgoing !== null ? Reader_module_css_default.numberRollEnter : ""}`,
|
|
46960
|
-
children: value
|
|
46961
|
-
}, `cur-${value}`)
|
|
46962
|
-
]
|
|
46963
|
-
});
|
|
46964
|
-
}
|
|
46965
|
-
function FoldSummaryText({ summary, motion }) {
|
|
46966
|
-
const parts = (0, react.useMemo)(() => {
|
|
46967
|
-
const regex = /([^\d]+)(\d+)/g;
|
|
46968
|
-
const result = [];
|
|
46969
|
-
let end = 0;
|
|
46970
|
-
for (const match of summary.matchAll(regex)) {
|
|
46971
|
-
result.push({
|
|
46972
|
-
text: match[1],
|
|
46973
|
-
number: Number(match[2])
|
|
46974
|
-
});
|
|
46975
|
-
end = match.index + match[0].length;
|
|
46976
|
-
}
|
|
46977
|
-
if (end < summary.length) result.push({ text: summary.slice(end) });
|
|
46978
|
-
return result;
|
|
46979
|
-
}, [summary]);
|
|
46980
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
46981
|
-
className: Reader_module_css_default.foldSummary,
|
|
46982
|
-
"data-reader-fold-summary": summary,
|
|
46983
|
-
"aria-label": summary,
|
|
46984
|
-
children: parts.map((part) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
46985
|
-
className: Reader_module_css_default.foldSummaryPart,
|
|
46986
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: part.text }), part.number !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubtleNumberRoll, {
|
|
46987
|
-
value: part.number,
|
|
46988
|
-
motion
|
|
46989
|
-
})]
|
|
46990
|
-
}, part.text))
|
|
46991
|
-
});
|
|
46992
|
-
}
|
|
46993
|
-
//#endregion
|
|
46994
47966
|
//#region src/client/DiffPanel.tsx
|
|
46995
47967
|
/**
|
|
46996
47968
|
* Reveals and withdraws its child by animating real height, in the plugin's own
|
|
@@ -47159,6 +48131,123 @@ ${trimmed}
|
|
|
47159
48131
|
})] });
|
|
47160
48132
|
}
|
|
47161
48133
|
//#endregion
|
|
48134
|
+
//#region src/client/StickyLane.tsx
|
|
48135
|
+
const MIN_LANE_PX = 40;
|
|
48136
|
+
const LaneOwnerContext = (0, react.createContext)(null);
|
|
48137
|
+
const ownersByRoot = /* @__PURE__ */ new WeakMap();
|
|
48138
|
+
/** One map per Reader, so two roots that both contain turn 1 do not share a writer. */
|
|
48139
|
+
function ReaderLaneScope({ children }) {
|
|
48140
|
+
const owners = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
48141
|
+
(0, react.useLayoutEffect)(() => {
|
|
48142
|
+
const map = owners.current;
|
|
48143
|
+
return () => {
|
|
48144
|
+
map.clear();
|
|
48145
|
+
};
|
|
48146
|
+
}, []);
|
|
48147
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LaneOwnerContext.Provider, {
|
|
48148
|
+
value: owners.current,
|
|
48149
|
+
children
|
|
48150
|
+
});
|
|
48151
|
+
}
|
|
48152
|
+
function laneScope(el) {
|
|
48153
|
+
return el.closest("[data-reader-turn]") ?? el.closest("[data-dsh-better-display]");
|
|
48154
|
+
}
|
|
48155
|
+
function ownersFor(el, scoped) {
|
|
48156
|
+
if (scoped) return scoped;
|
|
48157
|
+
const root = el.closest("[data-dsh-better-display]") ?? el;
|
|
48158
|
+
let owners = ownersByRoot.get(root);
|
|
48159
|
+
if (!owners) {
|
|
48160
|
+
owners = /* @__PURE__ */ new Map();
|
|
48161
|
+
ownersByRoot.set(root, owners);
|
|
48162
|
+
}
|
|
48163
|
+
return owners;
|
|
48164
|
+
}
|
|
48165
|
+
function publishedLanePx(el) {
|
|
48166
|
+
return Math.max(MIN_LANE_PX, Math.ceil(el.getBoundingClientRect().height));
|
|
48167
|
+
}
|
|
48168
|
+
/** One writer per turn inside a single Reader. A retiring summary cannot clear the lane that replaced it. */
|
|
48169
|
+
function publishLaneHeight(el, property, scoped = null) {
|
|
48170
|
+
const scope = laneScope(el);
|
|
48171
|
+
if (!scope) return () => {};
|
|
48172
|
+
const owners = ownersFor(el, scoped);
|
|
48173
|
+
const root = el.closest("[data-dsh-better-display]");
|
|
48174
|
+
const key = `${property}\0${scope.getAttribute("data-reader-turn") ?? "root"}`;
|
|
48175
|
+
const update = () => {
|
|
48176
|
+
if (owners.get(key) !== el) return;
|
|
48177
|
+
scope.style.setProperty(property, `${publishedLanePx(el)}px`);
|
|
48178
|
+
};
|
|
48179
|
+
owners.set(key, el);
|
|
48180
|
+
update();
|
|
48181
|
+
const observer = new ResizeObserver(update);
|
|
48182
|
+
observer.observe(el);
|
|
48183
|
+
return () => {
|
|
48184
|
+
observer.disconnect();
|
|
48185
|
+
if (owners.get(key) !== el) return;
|
|
48186
|
+
owners.delete(key);
|
|
48187
|
+
scope.style.removeProperty(property);
|
|
48188
|
+
if (!scoped && root && owners.size === 0) ownersByRoot.delete(root);
|
|
48189
|
+
};
|
|
48190
|
+
}
|
|
48191
|
+
function usePublishedHeight(property) {
|
|
48192
|
+
const owners = (0, react.useContext)(LaneOwnerContext);
|
|
48193
|
+
const ref = (0, react.useRef)(null);
|
|
48194
|
+
(0, react.useLayoutEffect)(() => {
|
|
48195
|
+
const el = ref.current;
|
|
48196
|
+
if (!el) return;
|
|
48197
|
+
return publishLaneHeight(el, property, owners);
|
|
48198
|
+
}, [owners, property]);
|
|
48199
|
+
return ref;
|
|
48200
|
+
}
|
|
48201
|
+
function useSummaryLane(ref, active) {
|
|
48202
|
+
const owners = (0, react.useContext)(LaneOwnerContext);
|
|
48203
|
+
(0, react.useLayoutEffect)(() => {
|
|
48204
|
+
const el = ref.current;
|
|
48205
|
+
if (!active || !el) return;
|
|
48206
|
+
return publishLaneHeight(el, "--reader-summary-height", owners);
|
|
48207
|
+
}, [
|
|
48208
|
+
active,
|
|
48209
|
+
owners,
|
|
48210
|
+
ref
|
|
48211
|
+
]);
|
|
48212
|
+
}
|
|
48213
|
+
/** Publish real lane geometry; wrapped labels must not collide with statistics. */
|
|
48214
|
+
function StickyLane({ kind, className, children }) {
|
|
48215
|
+
const ref = (0, react.useRef)(null);
|
|
48216
|
+
(0, react.useLayoutEffect)(() => {
|
|
48217
|
+
const el = ref.current;
|
|
48218
|
+
const scope = el?.closest(kind === "toolbar" ? "[data-dsh-better-display]" : "[data-reader-turn]");
|
|
48219
|
+
if (!el || !scope) return;
|
|
48220
|
+
const property = kind === "toolbar" ? "--reader-toolbar-height" : "--reader-status-height";
|
|
48221
|
+
const update = () => {
|
|
48222
|
+
scope.style.setProperty(property, `${Math.max(MIN_LANE_PX, el.getBoundingClientRect().height)}px`);
|
|
48223
|
+
if (kind !== "toolbar") return;
|
|
48224
|
+
const controls = el.querySelectorAll("button");
|
|
48225
|
+
let width = 80;
|
|
48226
|
+
if (controls.length > 0) {
|
|
48227
|
+
const first = controls[0].getBoundingClientRect();
|
|
48228
|
+
width = controls[controls.length - 1].getBoundingClientRect().right - first.left;
|
|
48229
|
+
}
|
|
48230
|
+
scope.style.setProperty("--reader-control-width", `${width + 28}px`);
|
|
48231
|
+
};
|
|
48232
|
+
update();
|
|
48233
|
+
const observer = new ResizeObserver(update);
|
|
48234
|
+
observer.observe(el);
|
|
48235
|
+
if (kind === "toolbar") for (const control of el.querySelectorAll("button")) observer.observe(control);
|
|
48236
|
+
return () => {
|
|
48237
|
+
observer.disconnect();
|
|
48238
|
+
scope.style.removeProperty(property);
|
|
48239
|
+
if (kind === "toolbar") scope.style.removeProperty("--reader-control-width");
|
|
48240
|
+
};
|
|
48241
|
+
}, [kind]);
|
|
48242
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48243
|
+
ref,
|
|
48244
|
+
className,
|
|
48245
|
+
"data-reader-lane": kind,
|
|
48246
|
+
"data-ud-check": kind === "toolbar" ? "reader-toolbar" : void 0,
|
|
48247
|
+
children
|
|
48248
|
+
});
|
|
48249
|
+
}
|
|
48250
|
+
//#endregion
|
|
47162
48251
|
//#region src/client/ChoreographedFlow.tsx
|
|
47163
48252
|
const FlowSnapshot = (0, react.createContext)(null);
|
|
47164
48253
|
/** Public projection only. Descendants cannot leak live data through a frozen frame. */
|
|
@@ -47201,6 +48290,7 @@ ${trimmed}
|
|
|
47201
48290
|
/** Manual disclosure shares the measured-size path; children survive until finish. */
|
|
47202
48291
|
function FlowCell({ hidden, instant, motion, rowKey, children, summary = false }) {
|
|
47203
48292
|
const ref = (0, react.useRef)(null);
|
|
48293
|
+
useSummaryLane(ref, summary);
|
|
47204
48294
|
const [present, setPresent] = (0, react.useState)(!hidden);
|
|
47205
48295
|
const previous = (0, react.useRef)(hidden);
|
|
47206
48296
|
if (!hidden && !present) setPresent(true);
|
|
@@ -47458,9 +48548,11 @@ ${trimmed}
|
|
|
47458
48548
|
/** Keep process counts discoverable after the live-fold presentation retires. */
|
|
47459
48549
|
function ClosedProcessSummary({ steps, open, onChange, controls }) {
|
|
47460
48550
|
const button = (0, react.useRef)(null);
|
|
48551
|
+
const lane = usePublishedHeight("--reader-summary-height");
|
|
47461
48552
|
if (!steps.length) return null;
|
|
47462
48553
|
const summary = foldSummary(steps);
|
|
47463
48554
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48555
|
+
ref: lane,
|
|
47464
48556
|
className: Reader_module_css_default.closedProcessSummary,
|
|
47465
48557
|
"data-reader-closed-summary": summary,
|
|
47466
48558
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -47483,45 +48575,6 @@ ${trimmed}
|
|
|
47483
48575
|
});
|
|
47484
48576
|
}
|
|
47485
48577
|
//#endregion
|
|
47486
|
-
//#region src/client/StickyLane.tsx
|
|
47487
|
-
/** Publish real lane geometry; wrapped labels must not collide with statistics. */
|
|
47488
|
-
function StickyLane({ kind, className, children }) {
|
|
47489
|
-
const ref = (0, react.useRef)(null);
|
|
47490
|
-
(0, react.useLayoutEffect)(() => {
|
|
47491
|
-
const el = ref.current;
|
|
47492
|
-
const scope = el?.closest(kind === "toolbar" ? "[data-dsh-better-display]" : "[data-reader-turn]");
|
|
47493
|
-
if (!el || !scope) return;
|
|
47494
|
-
const property = kind === "toolbar" ? "--reader-toolbar-height" : "--reader-status-height";
|
|
47495
|
-
const update = () => {
|
|
47496
|
-
scope.style.setProperty(property, `${el.getBoundingClientRect().height}px`);
|
|
47497
|
-
if (kind !== "toolbar") return;
|
|
47498
|
-
const controls = el.querySelectorAll("button");
|
|
47499
|
-
let width = 80;
|
|
47500
|
-
if (controls.length > 0) {
|
|
47501
|
-
const first = controls[0].getBoundingClientRect();
|
|
47502
|
-
width = controls[controls.length - 1].getBoundingClientRect().right - first.left;
|
|
47503
|
-
}
|
|
47504
|
-
scope.style.setProperty("--reader-control-width", `${width + 28}px`);
|
|
47505
|
-
};
|
|
47506
|
-
update();
|
|
47507
|
-
const observer = new ResizeObserver(update);
|
|
47508
|
-
observer.observe(el);
|
|
47509
|
-
if (kind === "toolbar") for (const control of el.querySelectorAll("button")) observer.observe(control);
|
|
47510
|
-
return () => {
|
|
47511
|
-
observer.disconnect();
|
|
47512
|
-
scope.style.removeProperty(property);
|
|
47513
|
-
if (kind === "toolbar") scope.style.removeProperty("--reader-control-width");
|
|
47514
|
-
};
|
|
47515
|
-
}, [kind]);
|
|
47516
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47517
|
-
ref,
|
|
47518
|
-
className,
|
|
47519
|
-
"data-reader-lane": kind,
|
|
47520
|
-
"data-ud-check": kind === "toolbar" ? "reader-toolbar" : void 0,
|
|
47521
|
-
children
|
|
47522
|
-
});
|
|
47523
|
-
}
|
|
47524
|
-
//#endregion
|
|
47525
48578
|
//#region src/client/Reader.tsx
|
|
47526
48579
|
function isNode(node, kind) {
|
|
47527
48580
|
return node.kind === kind;
|
|
@@ -47541,6 +48594,9 @@ ${trimmed}
|
|
|
47541
48594
|
return typeof block === "object" && block !== null && block.type === "text" && typeof block.text === "string";
|
|
47542
48595
|
}).map((block) => block.text).join("");
|
|
47543
48596
|
}
|
|
48597
|
+
function inboxAttachmentCount(item) {
|
|
48598
|
+
return (item.content ?? []).filter((block) => typeof block === "object" && block !== null && block.type !== "text").length;
|
|
48599
|
+
}
|
|
47544
48600
|
function cleanErrorMessage(raw) {
|
|
47545
48601
|
if (!raw) return "模型服务暂时无响应或连接中断,请稍后重试。";
|
|
47546
48602
|
let str = raw.trim();
|
|
@@ -47693,102 +48749,9 @@ ${trimmed}
|
|
|
47693
48749
|
children: content
|
|
47694
48750
|
});
|
|
47695
48751
|
});
|
|
47696
|
-
const
|
|
47697
|
-
const node = useChat((snapshot) => snapshot.nodes.get(nodeKey));
|
|
47698
|
-
if (!node || node.visibility === "hidden" || !isNode(node, "assistant-step")) return null;
|
|
47699
|
-
const data = node.data;
|
|
47700
|
-
const parts = assistantSegments(data.blocks);
|
|
47701
|
-
const earlier = isEarlierNarration(data, boundary);
|
|
47702
|
-
const hasToolCalls = data.blocks.some((block) => block.kind === "tool-call");
|
|
47703
|
-
const isProcessStep = earlier || folded || hasToolCalls || boundary.latestStep > 0 && data.step < boundary.latestStep;
|
|
47704
|
-
const body = data.blocks.filter((block) => block.kind !== "reasoning" && block.kind !== "tool-call");
|
|
47705
|
-
const visible = partStart === void 0 ? parts : parts.filter((part) => part.start === partStart);
|
|
47706
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: visible.map((part) => {
|
|
47707
|
-
const last = parts.findIndex((item) => item.start === part.start) === parts.length - 1;
|
|
47708
|
-
return part.kind === "reasoning" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProcessFragment, {
|
|
47709
|
-
open: processOpen,
|
|
47710
|
-
motion,
|
|
47711
|
-
onRead,
|
|
47712
|
-
returnFocusTo,
|
|
47713
|
-
nodeKey,
|
|
47714
|
-
framed: true,
|
|
47715
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningCard, {
|
|
47716
|
-
step: data.step,
|
|
47717
|
-
active: processOpen && boundary.status === "open" && data.step === boundary.latestStep,
|
|
47718
|
-
motion,
|
|
47719
|
-
selected: pinned,
|
|
47720
|
-
onRead,
|
|
47721
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
47722
|
-
...render,
|
|
47723
|
-
blocks: part.blocks,
|
|
47724
|
-
streaming: data.status === "running" && last && data.blocks.at(-1)?.kind === "reasoning",
|
|
47725
|
-
holdFormatting: pinned,
|
|
47726
|
-
startedAt: data.time,
|
|
47727
|
-
interrupted: data.status === "interrupted",
|
|
47728
|
-
liveText: true
|
|
47729
|
-
})
|
|
47730
|
-
})
|
|
47731
|
-
}, part.start) : isProcessStep ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProcessFragment, {
|
|
47732
|
-
open: processOpen,
|
|
47733
|
-
motion,
|
|
47734
|
-
onRead,
|
|
47735
|
-
returnFocusTo,
|
|
47736
|
-
nodeKey,
|
|
47737
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("article", {
|
|
47738
|
-
className: Reader_module_css_default.processCommentary,
|
|
47739
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
47740
|
-
...render,
|
|
47741
|
-
blocks: part.blocks,
|
|
47742
|
-
streaming: data.status === "running",
|
|
47743
|
-
holdFormatting: pinned,
|
|
47744
|
-
startedAt: data.time,
|
|
47745
|
-
interrupted: data.status === "interrupted",
|
|
47746
|
-
liveText: true
|
|
47747
|
-
})
|
|
47748
|
-
})
|
|
47749
|
-
}, part.start) : hasVisibleBody(part.blocks) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RetiringContent, {
|
|
47750
|
-
visible: pinned || processOpen || !earlier && !folded,
|
|
47751
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
47752
|
-
className: Reader_module_css_default.answer,
|
|
47753
|
-
"data-reader-answer": true,
|
|
47754
|
-
"data-reader-anchor": true,
|
|
47755
|
-
"data-reader-key": nodeKey,
|
|
47756
|
-
"data-reader-source-start": part.start,
|
|
47757
|
-
"data-answer-status": data.status,
|
|
47758
|
-
"data-answer-phase": earlier || folded ? "process" : "body",
|
|
47759
|
-
children: [
|
|
47760
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
47761
|
-
...render,
|
|
47762
|
-
blocks: part.blocks,
|
|
47763
|
-
streaming: data.status === "running",
|
|
47764
|
-
holdFormatting: pinned,
|
|
47765
|
-
startedAt: data.time,
|
|
47766
|
-
interrupted: data.status === "interrupted",
|
|
47767
|
-
liveText: true
|
|
47768
|
-
}),
|
|
47769
|
-
last && data.status === "interrupted" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47770
|
-
className: Reader_module_css_default.stopped,
|
|
47771
|
-
children: "已停止"
|
|
47772
|
-
}),
|
|
47773
|
-
last && !earlier && !folded && data.status !== "running" && boundary.status === "closed" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyAnswer, {
|
|
47774
|
-
blocks: body,
|
|
47775
|
-
onFork: (() => {
|
|
47776
|
-
const anchor = forkAnchorSeq([data.finalNode, { seq: render.forkSeq }]);
|
|
47777
|
-
return render.forkAt && anchor !== void 0 ? () => render.forkAt(anchor) : void 0;
|
|
47778
|
-
})(),
|
|
47779
|
-
metrics: render.metrics,
|
|
47780
|
-
extraActions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OfficialActions, {
|
|
47781
|
-
official: render.official,
|
|
47782
|
-
messageId: data.finalNode?.messageId
|
|
47783
|
-
})
|
|
47784
|
-
})
|
|
47785
|
-
]
|
|
47786
|
-
})
|
|
47787
|
-
}, part.start);
|
|
47788
|
-
}) });
|
|
47789
|
-
});
|
|
47790
|
-
const MainNode = (0, react.memo)(function MainNode({ useChat, nodeKey, boundary, pinned, processOpen = false, ...render }) {
|
|
48752
|
+
const MainNode = (0, react.memo)(function MainNode({ useChat, nodeKey, boundary, pinned, processOpen: _processOpen = false, ...render }) {
|
|
47791
48753
|
const node = useChat((snapshot) => snapshot.nodes.get(nodeKey));
|
|
48754
|
+
const [disclosureReset] = (0, react.useState)(() => (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(0));
|
|
47792
48755
|
if (!node || node.visibility === "hidden") return null;
|
|
47793
48756
|
if (isNode(node, "user") || isNode(node, "steering")) {
|
|
47794
48757
|
const blocks = contentBlocks(node.data.content);
|
|
@@ -47796,37 +48759,77 @@ ${trimmed}
|
|
|
47796
48759
|
const otherBlocks = blocks.filter((b) => b.kind !== "image");
|
|
47797
48760
|
const text = otherBlocks.filter((block) => block.kind === "text").map((block) => block.text).join("\n\n");
|
|
47798
48761
|
const time = node.data.time;
|
|
47799
|
-
|
|
48762
|
+
const fallback = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
48763
|
+
node.kind === "steering" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
48764
|
+
className: Reader_module_css_default.meta,
|
|
48765
|
+
children: "补充消息"
|
|
48766
|
+
}),
|
|
48767
|
+
imageBlocks.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48768
|
+
className: Reader_module_css_default.userImages,
|
|
48769
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
48770
|
+
...render,
|
|
48771
|
+
blocks: imageBlocks,
|
|
48772
|
+
source: "user"
|
|
48773
|
+
})
|
|
48774
|
+
}),
|
|
48775
|
+
otherBlocks.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48776
|
+
className: Reader_module_css_default.user,
|
|
48777
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
48778
|
+
...render,
|
|
48779
|
+
blocks: otherBlocks,
|
|
48780
|
+
source: "user"
|
|
48781
|
+
})
|
|
48782
|
+
}),
|
|
48783
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UserMessageActions, {
|
|
48784
|
+
text,
|
|
48785
|
+
time
|
|
48786
|
+
})
|
|
48787
|
+
] });
|
|
48788
|
+
const official = render.official;
|
|
48789
|
+
let rendered = fallback;
|
|
48790
|
+
if (official) {
|
|
48791
|
+
const turn = node.location.kind === "turn" || node.location.kind === "step" ? node.location.turn : void 0;
|
|
48792
|
+
const owner = {
|
|
48793
|
+
cwd: render.cwd,
|
|
48794
|
+
openFile: render.openFile ?? (() => {}),
|
|
48795
|
+
openSkill: () => {},
|
|
48796
|
+
forkAt: render.forkAt ?? (() => {}),
|
|
48797
|
+
inspectCall: (callId) => official.openView("trajectory", callId),
|
|
48798
|
+
loadImage: official.officialImageLoader,
|
|
48799
|
+
renderMessageImages: (images) => official.renderSlot(OFFICIAL_SEATS.images, {
|
|
48800
|
+
...images,
|
|
48801
|
+
loadImage: official.officialImageLoader
|
|
48802
|
+
}),
|
|
48803
|
+
fileMentions: official.officialFileMentions,
|
|
48804
|
+
sessionId: render.sessionId
|
|
48805
|
+
};
|
|
48806
|
+
const options = {
|
|
48807
|
+
hookContext: {
|
|
48808
|
+
turnData: turn?.data,
|
|
48809
|
+
disclosureReset
|
|
48810
|
+
},
|
|
48811
|
+
fallback
|
|
48812
|
+
};
|
|
48813
|
+
rendered = node.kind === "user" ? official.renderSlot(OFFICIAL_SEATS.nodes, {
|
|
48814
|
+
...owner,
|
|
48815
|
+
node
|
|
48816
|
+
}, {
|
|
48817
|
+
...options,
|
|
48818
|
+
entryKey: "user"
|
|
48819
|
+
}) : official.renderSlot(OFFICIAL_SEATS.nodes, {
|
|
48820
|
+
...owner,
|
|
48821
|
+
node
|
|
48822
|
+
}, {
|
|
48823
|
+
...options,
|
|
48824
|
+
entryKey: "steering"
|
|
48825
|
+
});
|
|
48826
|
+
}
|
|
48827
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47800
48828
|
className: Reader_module_css_default.userCluster,
|
|
47801
48829
|
"data-reader-anchor": true,
|
|
47802
48830
|
"data-reader-key": nodeKey,
|
|
47803
48831
|
...chatSeatProps(node.kind, nodeKey),
|
|
47804
|
-
children:
|
|
47805
|
-
node.kind === "steering" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
47806
|
-
className: Reader_module_css_default.meta,
|
|
47807
|
-
children: "补充消息"
|
|
47808
|
-
}),
|
|
47809
|
-
imageBlocks.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47810
|
-
className: Reader_module_css_default.userImages,
|
|
47811
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
47812
|
-
...render,
|
|
47813
|
-
blocks: imageBlocks,
|
|
47814
|
-
source: "user"
|
|
47815
|
-
})
|
|
47816
|
-
}),
|
|
47817
|
-
otherBlocks.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47818
|
-
className: Reader_module_css_default.user,
|
|
47819
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Blocks, {
|
|
47820
|
-
...render,
|
|
47821
|
-
blocks: otherBlocks,
|
|
47822
|
-
source: "user"
|
|
47823
|
-
})
|
|
47824
|
-
}),
|
|
47825
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UserMessageActions, {
|
|
47826
|
-
text,
|
|
47827
|
-
time
|
|
47828
|
-
})
|
|
47829
|
-
]
|
|
48832
|
+
children: rendered
|
|
47830
48833
|
});
|
|
47831
48834
|
}
|
|
47832
48835
|
if (isNode(node, "assistant-step")) return null;
|
|
@@ -47962,7 +48965,7 @@ ${trimmed}
|
|
|
47962
48965
|
}
|
|
47963
48966
|
return 0;
|
|
47964
48967
|
}
|
|
47965
|
-
function GroupStatus({ group,
|
|
48968
|
+
function GroupStatus({ group, useChat, pending, motion }) {
|
|
47966
48969
|
const text = useChat((snapshot) => {
|
|
47967
48970
|
const turn = group.turn === null ? void 0 : snapshot.timeline.turns.get(group.turn);
|
|
47968
48971
|
if (turn?.status === "closed") {
|
|
@@ -48213,11 +49216,12 @@ ${trimmed}
|
|
|
48213
49216
|
const flow = (0, react.useMemo)(() => readerFlow({
|
|
48214
49217
|
...group,
|
|
48215
49218
|
keys: mainKeys
|
|
48216
|
-
}, turn, (key) => nodes.get(key)), [
|
|
49219
|
+
}, turn, (key) => nodes.get(key), snapshot.order), [
|
|
48217
49220
|
nodes,
|
|
48218
49221
|
group,
|
|
48219
49222
|
mainKeys,
|
|
48220
|
-
turn
|
|
49223
|
+
turn,
|
|
49224
|
+
snapshot.order
|
|
48221
49225
|
]);
|
|
48222
49226
|
const steps = (0, react.useMemo)(() => segmentLiveTurn(flow, (key) => nodes.get(key)), [flow, nodes]);
|
|
48223
49227
|
const liveItems = (0, react.useMemo)(() => presentLiveTurn(steps, boundary, autoFold), [
|
|
@@ -48229,8 +49233,15 @@ ${trimmed}
|
|
|
48229
49233
|
return () => {};
|
|
48230
49234
|
}), () => props.openPrefs?.getSnapshot()?.deliverableOpenMode, () => "external"));
|
|
48231
49235
|
const hasProcess = flow.some((item) => item.kind === "tool" || hasProcessContent(nodes.get(item.nodeKey), boundary));
|
|
49236
|
+
const showStatusLane = hasProcess && !isAwaitingModel;
|
|
49237
|
+
const showClosedSummary = boundary.status === "closed" && hasProcess && autoFold;
|
|
48232
49238
|
const holdingSelection = selectedProcessKeys.some((key) => flow.some((item) => item.key === key) || liveItems.some((item) => item.kind === "fold" ? item.key === key || item.steps.some((step) => step.key === key || "nodeKey" in step && step.nodeKey === key) : item.key === key || "nodeKey" in item.step && item.step.nodeKey === key));
|
|
48233
49239
|
const expanded = !autoFold || holdingSelection || processExpanded(expansionChoice, boundary);
|
|
49240
|
+
const seamPlan = (0, react.useMemo)(() => planProcessSeams(steps, liveItems, expanded), [
|
|
49241
|
+
steps,
|
|
49242
|
+
liveItems,
|
|
49243
|
+
expanded
|
|
49244
|
+
]);
|
|
48234
49245
|
const [foldOpenByKey, setFoldOpenByKey] = (0, react.useState)({});
|
|
48235
49246
|
(0, react.useLayoutEffect)(() => {
|
|
48236
49247
|
if (autoFold) setFoldOpenByKey((current) => Object.keys(current).length ? {} : current);
|
|
@@ -48329,6 +49340,7 @@ ${trimmed}
|
|
|
48329
49340
|
fileMentions,
|
|
48330
49341
|
metrics,
|
|
48331
49342
|
official,
|
|
49343
|
+
sessionId: props.sessionId,
|
|
48332
49344
|
cwd
|
|
48333
49345
|
};
|
|
48334
49346
|
const terminal = terminalLabel(boundary.reason);
|
|
@@ -48348,7 +49360,9 @@ ${trimmed}
|
|
|
48348
49360
|
folded,
|
|
48349
49361
|
motion,
|
|
48350
49362
|
onRead: pinProcess,
|
|
48351
|
-
returnFocusTo: processButton
|
|
49363
|
+
returnFocusTo: processButton,
|
|
49364
|
+
seamSummary: step.kind === "body" ? seamPlan.before.get(step.key) : void 0,
|
|
49365
|
+
seamAfter: step.kind === "body" && seamPlan.after.has(step.key)
|
|
48352
49366
|
}) });
|
|
48353
49367
|
if (step.kind === "tool") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ProcessFragment, {
|
|
48354
49368
|
open: processOpen,
|
|
@@ -48401,57 +49415,55 @@ ${trimmed}
|
|
|
48401
49415
|
boundary,
|
|
48402
49416
|
nodeKey: group.keys[0]
|
|
48403
49417
|
}) }),
|
|
48404
|
-
|
|
48405
|
-
|
|
48406
|
-
|
|
48407
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
48408
|
-
|
|
48409
|
-
|
|
48410
|
-
|
|
48411
|
-
|
|
48412
|
-
|
|
48413
|
-
|
|
48414
|
-
|
|
48415
|
-
|
|
48416
|
-
|
|
48417
|
-
|
|
48418
|
-
|
|
48419
|
-
|
|
48420
|
-
|
|
48421
|
-
|
|
48422
|
-
|
|
48423
|
-
|
|
48424
|
-
|
|
48425
|
-
|
|
48426
|
-
|
|
48427
|
-
|
|
48428
|
-
|
|
48429
|
-
|
|
48430
|
-
})
|
|
48431
|
-
|
|
48432
|
-
|
|
48433
|
-
|
|
48434
|
-
|
|
48435
|
-
|
|
48436
|
-
|
|
48437
|
-
|
|
48438
|
-
|
|
48439
|
-
|
|
48440
|
-
|
|
48441
|
-
|
|
48442
|
-
|
|
48443
|
-
|
|
48444
|
-
|
|
48445
|
-
|
|
48446
|
-
}
|
|
48447
|
-
renderStep
|
|
49418
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
49419
|
+
className: Reader_module_css_default.turnStickyRegion,
|
|
49420
|
+
"data-reader-sticky-region": true,
|
|
49421
|
+
children: [(showStatusLane || showClosedSummary) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
49422
|
+
className: Reader_module_css_default.turnStickyLanes,
|
|
49423
|
+
children: [showStatusLane && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StickyLane, {
|
|
49424
|
+
kind: "status",
|
|
49425
|
+
className: Reader_module_css_default.turnProcessSticky,
|
|
49426
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Disclosure, {
|
|
49427
|
+
open: expanded,
|
|
49428
|
+
onChange: setExpanded,
|
|
49429
|
+
controls: flowId,
|
|
49430
|
+
buttonRef: processButton,
|
|
49431
|
+
label: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupStatus, {
|
|
49432
|
+
group,
|
|
49433
|
+
useChat: props.useChat,
|
|
49434
|
+
pending: interaction,
|
|
49435
|
+
motion
|
|
49436
|
+
})
|
|
49437
|
+
})
|
|
49438
|
+
}), showClosedSummary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClosedProcessSummary, {
|
|
49439
|
+
open: expanded,
|
|
49440
|
+
onChange: setExpanded,
|
|
49441
|
+
controls: flowId,
|
|
49442
|
+
steps: steps.filter((step) => step.kind !== "user" && step.kind !== "body")
|
|
49443
|
+
})]
|
|
49444
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChoreographedFlow, {
|
|
49445
|
+
id: flowId,
|
|
49446
|
+
frame: presentation,
|
|
49447
|
+
motion,
|
|
49448
|
+
enabled: autoFold && boundary.status === "open" && !holdingSelection,
|
|
49449
|
+
urgent: hasTurnError || interaction !== void 0 || !sessionRunning,
|
|
49450
|
+
open: foldOpenByKey,
|
|
49451
|
+
processOpen: expanded,
|
|
49452
|
+
onOpenChange: (key, value) => {
|
|
49453
|
+
pinProcess();
|
|
49454
|
+
setFoldOpenByKey((current) => ({
|
|
49455
|
+
...current,
|
|
49456
|
+
[key]: value
|
|
49457
|
+
}));
|
|
49458
|
+
},
|
|
49459
|
+
renderStep
|
|
49460
|
+
})]
|
|
48448
49461
|
}),
|
|
48449
49462
|
!hasProcess && boundary.status === "open" && !isAwaitingModel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48450
49463
|
className: Reader_module_css_default.disclosure,
|
|
48451
49464
|
"data-reader-status-only": true,
|
|
48452
49465
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupStatus, {
|
|
48453
49466
|
group,
|
|
48454
|
-
sessionId: props.sessionId,
|
|
48455
49467
|
useChat: props.useChat,
|
|
48456
49468
|
pending: interaction,
|
|
48457
49469
|
motion
|
|
@@ -48477,10 +49489,22 @@ ${trimmed}
|
|
|
48477
49489
|
});
|
|
48478
49490
|
});
|
|
48479
49491
|
function Reader(props) {
|
|
49492
|
+
(0, react.useInsertionEffect)(() => {
|
|
49493
|
+
ensureStyles();
|
|
49494
|
+
}, []);
|
|
48480
49495
|
const root = (0, react.useRef)(null);
|
|
48481
49496
|
const activatedAt = (0, react.useRef)(Date.now());
|
|
48482
49497
|
const order = props.useChat((snapshot) => snapshot.order);
|
|
48483
49498
|
const nodes = props.useChat((snapshot) => snapshot.nodes);
|
|
49499
|
+
const rewindSignature = props.useChat((snapshot) => visibleChatSignature(snapshot));
|
|
49500
|
+
const renderKeys = (0, react.useMemo)(() => visibleChatKeys({
|
|
49501
|
+
order,
|
|
49502
|
+
nodes
|
|
49503
|
+
}), [
|
|
49504
|
+
order,
|
|
49505
|
+
nodes,
|
|
49506
|
+
rewindSignature
|
|
49507
|
+
]);
|
|
48484
49508
|
const timeline = props.useChat((snapshot) => snapshot.timeline);
|
|
48485
49509
|
const running = props.useSession((snapshot) => snapshot.running);
|
|
48486
49510
|
const pending = props.useSessionStatus((snapshot) => snapshot.get(props.sessionId)?.pendingInteraction);
|
|
@@ -48516,7 +49540,7 @@ ${trimmed}
|
|
|
48516
49540
|
pendingList,
|
|
48517
49541
|
visibleSubmissions
|
|
48518
49542
|
]);
|
|
48519
|
-
const waitAnchor = waitingAnchor(
|
|
49543
|
+
const waitAnchor = waitingAnchor(renderKeys, (key) => nodes.get(key), pendingList);
|
|
48520
49544
|
const motion = useMotionAllowed(props.useStore((state) => state.motion));
|
|
48521
49545
|
const prefsSnap = (0, react.useSyncExternalStore)(props.openPrefs?.subscribe ?? ((fn) => {
|
|
48522
49546
|
return () => {};
|
|
@@ -48534,14 +49558,14 @@ ${trimmed}
|
|
|
48534
49558
|
enabled: motion,
|
|
48535
49559
|
activatedAt: activatedAt.current
|
|
48536
49560
|
}), [motion]);
|
|
48537
|
-
const groups = (0, react.useMemo)(() => groupNodes(
|
|
48538
|
-
|
|
49561
|
+
const groups = (0, react.useMemo)(() => groupNodes(renderKeys, (key) => nodes.get(key)), [
|
|
49562
|
+
renderKeys,
|
|
48539
49563
|
nodes,
|
|
48540
49564
|
timeline
|
|
48541
49565
|
]);
|
|
48542
49566
|
const isAwaitingModel = (0, react.useMemo)(() => {
|
|
48543
49567
|
if (!running && pendingList.length > 0) return true;
|
|
48544
|
-
const lastKey =
|
|
49568
|
+
const lastKey = renderKeys.at(-1);
|
|
48545
49569
|
const lastNode = lastKey ? nodes.get(lastKey) : void 0;
|
|
48546
49570
|
if (!lastKey || !lastNode) return false;
|
|
48547
49571
|
if (lastNode.kind === "assistant-step") {
|
|
@@ -48554,7 +49578,7 @@ ${trimmed}
|
|
|
48554
49578
|
}, [
|
|
48555
49579
|
running,
|
|
48556
49580
|
pendingList,
|
|
48557
|
-
|
|
49581
|
+
renderKeys,
|
|
48558
49582
|
nodes,
|
|
48559
49583
|
groups,
|
|
48560
49584
|
timeline
|
|
@@ -48644,7 +49668,7 @@ ${trimmed}
|
|
|
48644
49668
|
scroll.release,
|
|
48645
49669
|
timelineItems
|
|
48646
49670
|
]);
|
|
48647
|
-
const lastKey =
|
|
49671
|
+
const lastKey = renderKeys.at(-1);
|
|
48648
49672
|
const lastNode = lastKey ? nodes.get(lastKey) : void 0;
|
|
48649
49673
|
const lastSubmissionId = pendingList.length ? pendingList[pendingList.length - 1].requestId : null;
|
|
48650
49674
|
const lastOrderKeyRef = (0, react.useRef)(lastKey);
|
|
@@ -48663,7 +49687,7 @@ ${trimmed}
|
|
|
48663
49687
|
]);
|
|
48664
49688
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StreamMotionContext.Provider, {
|
|
48665
49689
|
value: streamMotion,
|
|
48666
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
49690
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReaderLaneScope, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48667
49691
|
ref: root,
|
|
48668
49692
|
className: Reader_module_css_default.root,
|
|
48669
49693
|
"data-reader-build": "0.3.4",
|
|
@@ -48681,6 +49705,7 @@ ${trimmed}
|
|
|
48681
49705
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48682
49706
|
className: Reader_module_css_default.column,
|
|
48683
49707
|
"data-chat-flow": "",
|
|
49708
|
+
tabIndex: -1,
|
|
48684
49709
|
children: [
|
|
48685
49710
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StickyLane, {
|
|
48686
49711
|
kind: "toolbar",
|
|
@@ -48725,20 +49750,23 @@ ${trimmed}
|
|
|
48725
49750
|
role: "status",
|
|
48726
49751
|
children: "正在读取会话…"
|
|
48727
49752
|
}),
|
|
48728
|
-
|
|
48729
|
-
|
|
48730
|
-
group,
|
|
48731
|
-
|
|
48732
|
-
|
|
48733
|
-
|
|
48734
|
-
|
|
48735
|
-
|
|
48736
|
-
|
|
49753
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RetiringTurns, {
|
|
49754
|
+
groups,
|
|
49755
|
+
render: (group) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TurnGroup, {
|
|
49756
|
+
...props,
|
|
49757
|
+
group,
|
|
49758
|
+
motion,
|
|
49759
|
+
autoFold,
|
|
49760
|
+
pinnedKeys,
|
|
49761
|
+
selectedProcessKeys,
|
|
49762
|
+
isAwaitingModel: isAwaitingModel && group.key === groups.at(-1)?.key
|
|
49763
|
+
})
|
|
49764
|
+
}),
|
|
48737
49765
|
pendingInputs.map((item, index) => {
|
|
48738
49766
|
const submission = "requestId" in item ? item : void 0;
|
|
48739
49767
|
const text = submission?.text ?? inboxText(item);
|
|
48740
49768
|
const images = submission ? pendingSubmissionImages(submission) : [];
|
|
48741
|
-
const attachmentCount = images.length;
|
|
49769
|
+
const attachmentCount = submission ? images.length : inboxAttachmentCount(item);
|
|
48742
49770
|
const requestId = submission?.requestId ?? `inbox-${index}`;
|
|
48743
49771
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48744
49772
|
className: Reader_module_css_default.userCluster,
|
|
@@ -48811,7 +49839,7 @@ ${trimmed}
|
|
|
48811
49839
|
})
|
|
48812
49840
|
]
|
|
48813
49841
|
})]
|
|
48814
|
-
})
|
|
49842
|
+
}) })
|
|
48815
49843
|
});
|
|
48816
49844
|
}
|
|
48817
49845
|
//#endregion
|
|
@@ -49311,7 +50339,12 @@ ${trimmed}
|
|
|
49311
50339
|
"remote",
|
|
49312
50340
|
"remote.session"
|
|
49313
50341
|
];
|
|
50342
|
+
ensureStyles();
|
|
49314
50343
|
function apply(ctx) {
|
|
50344
|
+
const textTransform = createTextTransformRegistry();
|
|
50345
|
+
const restoreTextTransform = installTextTransformRegistry(textTransform);
|
|
50346
|
+
ctx.provide(TEXT_TRANSFORM_SERVICE, textTransform);
|
|
50347
|
+
ctx.effect(() => restoreTextTransform);
|
|
49315
50348
|
const store = createReaderStore();
|
|
49316
50349
|
const prefs = store.create();
|
|
49317
50350
|
installBetterDisplaySettings(ctx, prefs);
|
|
@@ -49394,13 +50427,20 @@ ${trimmed}
|
|
|
49394
50427
|
const res = await fetch("/better-display/reveal", {
|
|
49395
50428
|
method: "POST",
|
|
49396
50429
|
headers: { "Content-Type": "application/json" },
|
|
49397
|
-
body: JSON.stringify({
|
|
50430
|
+
body: JSON.stringify({
|
|
50431
|
+
path: targetPath,
|
|
50432
|
+
sessionId
|
|
50433
|
+
})
|
|
49398
50434
|
});
|
|
49399
50435
|
if (res.ok) {
|
|
49400
50436
|
if ((await res.json()).ok) return;
|
|
49401
50437
|
}
|
|
49402
50438
|
} catch {}
|
|
49403
50439
|
const parentDir = dirname(targetPath);
|
|
50440
|
+
if (!isAbsoluteWorkspacePath(parentDir)) {
|
|
50441
|
+
console.warn("[dsh-better-display] reveal failed; refusing to open a relative parent:", targetPath);
|
|
50442
|
+
return;
|
|
50443
|
+
}
|
|
49404
50444
|
const remoteSession = ctx.remote?.session ?? ctx.get?.("remote.session");
|
|
49405
50445
|
if (remoteSession?.openWorkspacePath) await remoteSession.openWorkspacePath({ path: parentDir });
|
|
49406
50446
|
} catch (error) {
|
|
@@ -49459,9 +50499,12 @@ ${trimmed}
|
|
|
49459
50499
|
}
|
|
49460
50500
|
//#endregion
|
|
49461
50501
|
exports.McpAppFrame = McpAppFrame;
|
|
50502
|
+
exports.TEXT_TRANSFORM_SERVICE = TEXT_TRANSFORM_SERVICE;
|
|
49462
50503
|
exports.apply = apply;
|
|
50504
|
+
exports.createTextTransformRegistry = createTextTransformRegistry;
|
|
49463
50505
|
exports.inject = inject;
|
|
49464
50506
|
exports.name = name;
|
|
50507
|
+
exports.originalAnswerText = originalAnswerText;
|
|
49465
50508
|
return module.exports;
|
|
49466
50509
|
}
|
|
49467
50510
|
});
|