dsh-better-display 0.3.6 → 0.3.8
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 +16 -0
- package/docs/official-rendering-bridge.md +16 -0
- package/lib/client.js +564 -394
- package/lib/client.js.map +1 -1
- package/lib/dsh-better-display.js +139 -48
- package/lib/types/client/OfficialContent.d.ts.map +1 -1
- package/lib/types/client/OfficialContent.js +2 -1
- 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 +96 -20
- package/lib/types/client/Reader.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/chat-seat.d.ts +3 -0
- package/lib/types/client/chat-seat.d.ts.map +1 -0
- package/lib/types/client/chat-seat.js +9 -0
- package/lib/types/client/chat-seat.js.map +1 -0
- 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.map +1 -1
- package/lib/types/client/index.js +9 -1
- package/lib/types/client/index.js.map +1 -1
- package/lib/types/client/motion.d.ts.map +1 -1
- package/lib/types/client/motion.js +9 -1
- package/lib/types/client/motion.js.map +1 -1
- package/lib/types/client/official-slots.d.ts.map +1 -1
- package/lib/types/client/official-slots.js +6 -3
- 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/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/tool-activity.d.ts +2 -2
- package/lib/types/client/tool-activity.d.ts.map +1 -1
- package/lib/types/client/tool-activity.js +12 -7
- package/lib/types/client/tool-activity.js.map +1 -1
- package/lib/types/dsh-better-display.d.ts.map +1 -1
- package/lib/types/dsh-better-display.js +2 -39
- package/lib/types/dsh-better-display.js.map +1 -1
- 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 +1 -1
- package/src/client/OfficialContent.tsx +2 -1
- package/src/client/Reader.module.css +41 -9
- package/src/client/Reader.tsx +108 -32
- package/src/client/ToolActivity.tsx +9 -5
- package/src/client/chat-seat.ts +10 -0
- package/src/client/deliverables.ts +1 -0
- package/src/client/index.tsx +10 -1
- package/src/client/motion.tsx +8 -1
- package/src/client/official-slots.tsx +6 -3
- package/src/client/open-file.ts +2 -8
- package/src/client/styles.ts +22 -0
- package/src/client/tool-activity.ts +18 -7
- package/src/dsh-better-display.ts +2 -38
- package/src/reveal.ts +90 -0
- package/src/workspace-path.ts +4 -0
- package/tests/chat-flow-hook.test.ts +13 -0
- package/tests/fixtures/reader-official-users.tsx +170 -0
- package/tests/footer-precedence.test.ts +8 -0
- package/tests/reader-glass-css.test.ts +28 -0
- package/tests/reader-official-users.test.ts +81 -0
- package/tests/retiring-content.test.ts +137 -0
- package/tests/reveal.test.ts +128 -0
- package/tests/stock-install.test.ts +8 -0
- package/tests/styles.test.ts +48 -0
- package/tests/terminal-input-preview.test.ts +113 -0
- package/tsdown.config.ts +55 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
1
|
import { access, readdir } from "node:fs/promises";
|
|
3
2
|
import { existsSync } from "node:fs";
|
|
4
3
|
import { homedir } from "node:os";
|
|
5
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
|
|
6
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
7
|
//#region src/skill-status.ts
|
|
8
8
|
/** Shared generative-mcpapps identity. Plugin-tree presence is not installation. */
|
|
9
9
|
const GENERATIVE_MCPAPPS_SKILL = "generative-mcpapps";
|
|
@@ -156,6 +156,142 @@ async function scanGenerativeMcpappsStatus(options = {}) {
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
//#endregion
|
|
159
|
+
//#region src/workspace-path.ts
|
|
160
|
+
/** Absolute paths accepted by both POSIX and Windows hosts. */
|
|
161
|
+
function isAbsoluteWorkspacePath(path) {
|
|
162
|
+
return /^(?:\/|[A-Za-z]:[/\\]|\\\\)/.test(path);
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region \0@oxc-project+runtime@0.153.0/helpers/esm/usingCtx.js
|
|
166
|
+
function _usingCtx() {
|
|
167
|
+
var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
|
|
168
|
+
var n = Error();
|
|
169
|
+
return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
|
|
170
|
+
}, e = {}, n = [];
|
|
171
|
+
function using(r, e) {
|
|
172
|
+
if (null != e) {
|
|
173
|
+
if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
|
|
174
|
+
if (r) var o = e[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
|
|
175
|
+
if (void 0 === o && (o = e[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r)) var t = o;
|
|
176
|
+
if ("function" != typeof o) throw new TypeError("Object is not disposable.");
|
|
177
|
+
t && (o = function o() {
|
|
178
|
+
try {
|
|
179
|
+
t.call(e);
|
|
180
|
+
} catch (r) {
|
|
181
|
+
return Promise.reject(r);
|
|
182
|
+
}
|
|
183
|
+
}), n.push({
|
|
184
|
+
v: e,
|
|
185
|
+
d: o,
|
|
186
|
+
a: r
|
|
187
|
+
});
|
|
188
|
+
} else r && n.push({
|
|
189
|
+
d: e,
|
|
190
|
+
a: r
|
|
191
|
+
});
|
|
192
|
+
return e;
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
e,
|
|
196
|
+
u: using.bind(null, !1),
|
|
197
|
+
a: using.bind(null, !0),
|
|
198
|
+
d: function d() {
|
|
199
|
+
var o, t = this.e, s = 0;
|
|
200
|
+
function next() {
|
|
201
|
+
for (; o = n.pop();) try {
|
|
202
|
+
if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
|
|
203
|
+
if (o.d) {
|
|
204
|
+
var r = o.d.call(o.v);
|
|
205
|
+
if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
|
|
206
|
+
} else s |= 1;
|
|
207
|
+
} catch (r) {
|
|
208
|
+
return err(r);
|
|
209
|
+
}
|
|
210
|
+
if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
|
|
211
|
+
if (t !== e) throw t;
|
|
212
|
+
}
|
|
213
|
+
function err(n) {
|
|
214
|
+
return t = t !== e ? new r(n, t) : n, next();
|
|
215
|
+
}
|
|
216
|
+
return next();
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region src/reveal.ts
|
|
222
|
+
async function revealRoots(ctx, sessionId) {
|
|
223
|
+
if (sessionId !== void 0) {
|
|
224
|
+
const cwd = (ctx.get?.("sessions"))?.get(sessionId)?.header.cwd;
|
|
225
|
+
if (cwd) return [cwd];
|
|
226
|
+
const query = ctx.get?.("sessionQuery");
|
|
227
|
+
if (query) try {
|
|
228
|
+
var _usingCtx$1 = _usingCtx();
|
|
229
|
+
const observation = _usingCtx$1.u(await query.observeSession(sessionId, { projectionMode: "none" }));
|
|
230
|
+
if (observation.header.cwd) return [observation.header.cwd];
|
|
231
|
+
} catch (_) {
|
|
232
|
+
_usingCtx$1.e = _;
|
|
233
|
+
} finally {
|
|
234
|
+
_usingCtx$1.d();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return ((ctx.get?.("workspaceRegistry"))?.list() ?? []).filter((workspace) => sessionId === void 0 || workspace.sessionIds.includes(sessionId)).map((workspace) => workspace.path);
|
|
238
|
+
}
|
|
239
|
+
function resolveRevealPath(path, roots, exists = existsSync) {
|
|
240
|
+
if (isAbsoluteWorkspacePath(path)) return path;
|
|
241
|
+
if (/^[A-Za-z]:|^\\/.test(path)) throw new Error("Path is not workspace-relative");
|
|
242
|
+
const matches = /* @__PURE__ */ new Set();
|
|
243
|
+
for (const root of roots) {
|
|
244
|
+
if (!isAbsoluteWorkspacePath(root)) continue;
|
|
245
|
+
const candidate = (/^[A-Za-z]:[/\\]|^\\\\/.test(root) ? win32 : posix).resolve(root, path);
|
|
246
|
+
if (exists(candidate)) matches.add(candidate);
|
|
247
|
+
}
|
|
248
|
+
if (matches.size !== 1) throw new Error(matches.size === 0 ? "Workspace path not found" : "Workspace path is ambiguous");
|
|
249
|
+
return [...matches][0];
|
|
250
|
+
}
|
|
251
|
+
function revealPath(path, platform = process.platform, spawnProcess = spawn) {
|
|
252
|
+
const options = {
|
|
253
|
+
detached: true,
|
|
254
|
+
stdio: "ignore"
|
|
255
|
+
};
|
|
256
|
+
if (platform === "darwin") spawnProcess("open", ["-R", path], options);
|
|
257
|
+
else if (platform === "win32") spawnProcess("explorer.exe", [`/select,"${path}"`], {
|
|
258
|
+
...options,
|
|
259
|
+
windowsVerbatimArguments: true
|
|
260
|
+
});
|
|
261
|
+
else spawnProcess("xdg-open", [path], options);
|
|
262
|
+
}
|
|
263
|
+
function createRevealHandler({ roots, reveal = revealPath }) {
|
|
264
|
+
return (req, res) => {
|
|
265
|
+
if (req.method !== "POST") {
|
|
266
|
+
res.statusCode = 405;
|
|
267
|
+
res.end();
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
let body = "";
|
|
271
|
+
req.on("data", (chunk) => {
|
|
272
|
+
body += chunk;
|
|
273
|
+
});
|
|
274
|
+
req.on("end", async () => {
|
|
275
|
+
res.setHeader("Content-Type", "application/json");
|
|
276
|
+
try {
|
|
277
|
+
const data = JSON.parse(body);
|
|
278
|
+
const path = typeof data === "object" && data !== null && "path" in data && typeof data.path === "string" ? data.path.trim() : "";
|
|
279
|
+
if (!path) throw new Error("Empty path");
|
|
280
|
+
const sessionId = typeof data === "object" && data !== null && "sessionId" in data && typeof data.sessionId === "string" ? data.sessionId : void 0;
|
|
281
|
+
reveal(resolveRevealPath(path, isAbsoluteWorkspacePath(path) ? [] : await roots(sessionId)));
|
|
282
|
+
res.statusCode = 200;
|
|
283
|
+
res.end(JSON.stringify({ ok: true }));
|
|
284
|
+
} catch (err) {
|
|
285
|
+
res.statusCode = 400;
|
|
286
|
+
res.end(JSON.stringify({
|
|
287
|
+
ok: false,
|
|
288
|
+
error: String(err)
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
//#endregion
|
|
159
295
|
//#region src/dsh-better-display.ts
|
|
160
296
|
const name = "dsh-better-display";
|
|
161
297
|
const inject = ["webServer"];
|
|
@@ -175,52 +311,7 @@ function apply(ctx) {
|
|
|
175
311
|
const disposeReveal = ctx.webServer.register({
|
|
176
312
|
kind: "exact",
|
|
177
313
|
path: "/better-display/reveal",
|
|
178
|
-
handler:
|
|
179
|
-
if (req.method !== "POST") {
|
|
180
|
-
res.statusCode = 405;
|
|
181
|
-
res.end();
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
let body = "";
|
|
185
|
-
req.on("data", (chunk) => {
|
|
186
|
-
body += chunk;
|
|
187
|
-
});
|
|
188
|
-
req.on("end", () => {
|
|
189
|
-
try {
|
|
190
|
-
const data = JSON.parse(body);
|
|
191
|
-
const targetPath = typeof data.path === "string" ? data.path.trim() : "";
|
|
192
|
-
if (!targetPath) {
|
|
193
|
-
res.statusCode = 400;
|
|
194
|
-
res.end(JSON.stringify({
|
|
195
|
-
ok: false,
|
|
196
|
-
error: "Empty path"
|
|
197
|
-
}));
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
if (process.platform === "darwin") spawn("open", ["-R", targetPath], {
|
|
201
|
-
detached: true,
|
|
202
|
-
stdio: "ignore"
|
|
203
|
-
});
|
|
204
|
-
else if (process.platform === "win32") spawn("explorer.exe", [`/select,${targetPath}`], {
|
|
205
|
-
detached: true,
|
|
206
|
-
stdio: "ignore"
|
|
207
|
-
});
|
|
208
|
-
else spawn("xdg-open", [targetPath], {
|
|
209
|
-
detached: true,
|
|
210
|
-
stdio: "ignore"
|
|
211
|
-
});
|
|
212
|
-
res.setHeader("Content-Type", "application/json");
|
|
213
|
-
res.statusCode = 200;
|
|
214
|
-
res.end(JSON.stringify({ ok: true }));
|
|
215
|
-
} catch (err) {
|
|
216
|
-
res.statusCode = 400;
|
|
217
|
-
res.end(JSON.stringify({
|
|
218
|
-
ok: false,
|
|
219
|
-
error: String(err)
|
|
220
|
-
}));
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
}
|
|
314
|
+
handler: createRevealHandler({ roots: (sessionId) => revealRoots(ctx, sessionId) })
|
|
224
315
|
});
|
|
225
316
|
const disposeSkill = ctx.webServer.register({
|
|
226
317
|
kind: "exact",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OfficialContent.d.ts","sourceRoot":"","sources":["../../../src/client/OfficialContent.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACpF,OAAO,KAAK,EAAE,wBAAwB,EAAsB,kBAAkB,EAAiB,MAAM,wCAAwC,CAAC;AAE9I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACxF,KAAK,SAAS,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"OfficialContent.d.ts","sourceRoot":"","sources":["../../../src/client/OfficialContent.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACpF,OAAO,KAAK,EAAE,wBAAwB,EAAsB,kBAAkB,EAAiB,MAAM,wCAAwC,CAAC;AAE9I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACxF,KAAK,SAAS,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,SAAS,CAAA;CAAE,sCAKtH;AASD,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,gBAAgB,GAAG;IACtG,QAAQ,EAAE,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAC;CAClH,+BAYA;AAED,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,EAAE,gBAAgB,GAAG;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,oGAsBrI;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,sCAK3J"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useCallback, useState, useSyncExternalStore } from 'react';
|
|
3
3
|
import { createSnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
4
4
|
import { OFFICIAL_SEATS } from './official-slots.js';
|
|
5
|
+
import { chatSeatProps } from './chat-seat.js';
|
|
5
6
|
export function OfficialActions({ official, messageId }) {
|
|
6
7
|
if (!official || !messageId)
|
|
7
8
|
return null;
|
|
@@ -44,7 +45,7 @@ export function OfficialNode({ node, fallback, ...render }) {
|
|
|
44
45
|
const turn = node.location.kind === 'turn' || node.location.kind === 'step' ? node.location.turn : undefined;
|
|
45
46
|
// The runtime node domain is open; the public SlotMap enumerates the known kinds.
|
|
46
47
|
const renderNode = official.renderSlot;
|
|
47
|
-
return _jsx("div", { "data-reader-official-node": node.kind,
|
|
48
|
+
return _jsx("div", { "data-reader-official-node": node.kind, ...(node.kind === 'user' || node.kind === 'steering' ? chatSeatProps(node.kind, node.key) : {}), children: renderNode(OFFICIAL_SEATS.nodes, { ...owner, node }, { entryKey: node.kind, hookContext: { turnData: turn?.data, disclosureReset }, fallback }) });
|
|
48
49
|
}
|
|
49
50
|
export function OfficialTail({ official, owner, produced }) {
|
|
50
51
|
const tailOwner = owner && official ? { ...owner, openFile: official.officialPreviewFile, readerProducedPaths: produced } : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OfficialContent.js","sourceRoot":"","sources":["../../../src/client/OfficialContent.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,oBAAoB,EAAkB,MAAM,OAAO,CAAC;AAEpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAIpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"OfficialContent.js","sourceRoot":"","sources":["../../../src/client/OfficialContent.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Reader.d.ts","sourceRoot":"","sources":["../../../src/client/Reader.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Reader.d.ts","sourceRoot":"","sources":["../../../src/client/Reader.tsx"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAoB,WAAW,EAAE,MAAM,YAAY,CAAC;AAooBhE,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,+BAoRxC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment, memo, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
|
|
2
|
+
import { Fragment, memo, useCallback, useEffect, useId, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
|
|
3
|
+
import { createSnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
3
4
|
import { JsonBlock, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
5
|
import { BlockBoundary, Blocks, contentBlocks, CopyAnswer, UserMessageActions } from './Blocks.js';
|
|
5
6
|
import { ReasoningCard } from './ReasoningCard.js';
|
|
6
7
|
import { ToolActivity, ToolMedia } from './ToolActivity.js';
|
|
7
8
|
import { OfficialActions, OfficialNode, OfficialTail } from './OfficialContent.js';
|
|
9
|
+
import { OFFICIAL_SEATS } from './official-slots.js';
|
|
8
10
|
import { preparingLabel, readerFlow } from './tool-activity.js';
|
|
9
11
|
import { Disclosure, ProcessFragment, RetiringContent, StatusText, useMotionAllowed, usePinnedSelection, useReadingScroll } from './motion.js';
|
|
10
12
|
import { StreamMotionContext } from './streaming.js';
|
|
@@ -25,9 +27,31 @@ import { ClosedProcessSummary } from './ClosedProcessSummary.js';
|
|
|
25
27
|
import { StickyLane } from './StickyLane.js';
|
|
26
28
|
import css from './Reader.module.css';
|
|
27
29
|
import { markdownLabels, truncatedJsonLabel } from './primitive-labels.js';
|
|
30
|
+
import { chatSeatProps } from './chat-seat.js';
|
|
31
|
+
import { ensureStyles } from './styles.js';
|
|
28
32
|
function isNode(node, kind) {
|
|
29
33
|
return node.kind === kind;
|
|
30
34
|
}
|
|
35
|
+
function observedInputIds(order, getNode) {
|
|
36
|
+
const ids = new Set();
|
|
37
|
+
for (const key of order) {
|
|
38
|
+
const node = getNode(key);
|
|
39
|
+
if (!node || (node.kind !== 'user' && node.kind !== 'steering' && node.kind !== 'turn-trigger'))
|
|
40
|
+
continue;
|
|
41
|
+
const source = node.data.source;
|
|
42
|
+
if (source?.kind === 'user' && typeof source.rpcId === 'string')
|
|
43
|
+
ids.add(source.rpcId);
|
|
44
|
+
}
|
|
45
|
+
return ids;
|
|
46
|
+
}
|
|
47
|
+
function inboxText(item) {
|
|
48
|
+
return (item.content ?? []).filter((block) => {
|
|
49
|
+
return typeof block === 'object' && block !== null && block.type === 'text' && typeof block.text === 'string';
|
|
50
|
+
}).map(block => block.text).join('');
|
|
51
|
+
}
|
|
52
|
+
function inboxAttachmentCount(item) {
|
|
53
|
+
return (item.content ?? []).filter(block => typeof block === 'object' && block !== null && block.type !== 'text').length;
|
|
54
|
+
}
|
|
31
55
|
function cleanErrorMessage(raw) {
|
|
32
56
|
if (!raw)
|
|
33
57
|
return '模型服务暂时无响应或连接中断,请稍后重试。';
|
|
@@ -120,6 +144,7 @@ const AssistantNode = memo(function AssistantNode({ useChat, nodeKey, boundary,
|
|
|
120
144
|
});
|
|
121
145
|
const MainNode = memo(function MainNode({ useChat, nodeKey, boundary, pinned, processOpen = false, ...render }) {
|
|
122
146
|
const node = useChat(snapshot => snapshot.nodes.get(nodeKey));
|
|
147
|
+
const [disclosureReset] = useState(() => createSnapshotStore(0));
|
|
123
148
|
if (!node || node.visibility === 'hidden')
|
|
124
149
|
return null;
|
|
125
150
|
if (isNode(node, 'user') || isNode(node, 'steering')) {
|
|
@@ -128,7 +153,30 @@ const MainNode = memo(function MainNode({ useChat, nodeKey, boundary, pinned, pr
|
|
|
128
153
|
const otherBlocks = blocks.filter(b => b.kind !== 'image');
|
|
129
154
|
const text = otherBlocks.filter((block) => block.kind === 'text').map(block => block.text).join('\n\n');
|
|
130
155
|
const time = node.data.time;
|
|
131
|
-
|
|
156
|
+
const fallback = _jsxs(_Fragment, { children: [node.kind === 'steering' && _jsx("p", { className: css.meta, children: "\u8865\u5145\u6D88\u606F" }), imageBlocks.length > 0 && _jsx("div", { className: css.userImages, children: _jsx(Blocks, { ...render, blocks: imageBlocks, source: "user" }) }), otherBlocks.length > 0 && _jsx("div", { className: css.user, children: _jsx(Blocks, { ...render, blocks: otherBlocks, source: "user" }) }), _jsx(UserMessageActions, { text: text, time: time })] });
|
|
157
|
+
const official = render.official;
|
|
158
|
+
let rendered = fallback;
|
|
159
|
+
if (official) {
|
|
160
|
+
const turn = node.location.kind === 'turn' || node.location.kind === 'step' ? node.location.turn : undefined;
|
|
161
|
+
const owner = {
|
|
162
|
+
cwd: render.cwd,
|
|
163
|
+
openFile: render.openFile ?? (() => { }),
|
|
164
|
+
openSkill: () => { },
|
|
165
|
+
forkAt: render.forkAt ?? (() => { }),
|
|
166
|
+
inspectCall: callId => official.openView('trajectory', callId),
|
|
167
|
+
loadImage: official.officialImageLoader,
|
|
168
|
+
renderMessageImages: images => official.renderSlot(OFFICIAL_SEATS.images, {
|
|
169
|
+
...images, loadImage: official.officialImageLoader,
|
|
170
|
+
}),
|
|
171
|
+
fileMentions: official.officialFileMentions,
|
|
172
|
+
sessionId: render.sessionId,
|
|
173
|
+
};
|
|
174
|
+
const options = { hookContext: { turnData: turn?.data, disclosureReset }, fallback };
|
|
175
|
+
rendered = node.kind === 'user'
|
|
176
|
+
? official.renderSlot(OFFICIAL_SEATS.nodes, { ...owner, node }, { ...options, entryKey: 'user' })
|
|
177
|
+
: official.renderSlot(OFFICIAL_SEATS.nodes, { ...owner, node }, { ...options, entryKey: 'steering' });
|
|
178
|
+
}
|
|
179
|
+
return _jsx("div", { className: css.userCluster, "data-reader-anchor": true, "data-reader-key": nodeKey, ...chatSeatProps(node.kind, nodeKey), children: rendered });
|
|
132
180
|
}
|
|
133
181
|
if (isNode(node, 'assistant-step'))
|
|
134
182
|
return null;
|
|
@@ -294,6 +342,8 @@ const TurnGroup = memo(function TurnGroup({ group, motion, autoFold, pinnedKeys,
|
|
|
294
342
|
const liveItems = useMemo(() => presentLiveTurn(steps, boundary, autoFold), [steps, boundary, autoFold]);
|
|
295
343
|
const openMode = deliverableOpenModeOf(useSyncExternalStore(props.openPrefs?.subscribe ?? ((fn) => { void fn; return () => { }; }), () => props.openPrefs?.getSnapshot()?.deliverableOpenMode, () => 'external'));
|
|
296
344
|
const hasProcess = flow.some(item => item.kind === 'tool' || hasProcessContent(nodes.get(item.nodeKey), boundary));
|
|
345
|
+
const showStatusLane = hasProcess && !isAwaitingModel;
|
|
346
|
+
const showClosedSummary = boundary.status === 'closed' && hasProcess && autoFold;
|
|
297
347
|
// Only a real, still-active text selection delays folding. Merely clicking,
|
|
298
348
|
// focusing or scrolling the live card does not create a permanent override.
|
|
299
349
|
const holdingSelection = selectedProcessKeys.some(key => flow.some(item => item.key === key)
|
|
@@ -362,6 +412,7 @@ const TurnGroup = memo(function TurnGroup({ group, motion, autoFold, pinnedKeys,
|
|
|
362
412
|
fileMentions,
|
|
363
413
|
metrics,
|
|
364
414
|
official,
|
|
415
|
+
sessionId: props.sessionId,
|
|
365
416
|
cwd,
|
|
366
417
|
};
|
|
367
418
|
const terminal = terminalLabel(boundary.reason);
|
|
@@ -383,18 +434,19 @@ const TurnGroup = memo(function TurnGroup({ group, motion, autoFold, pinnedKeys,
|
|
|
383
434
|
return _jsx(BlockBoundary, { children: _jsx(MainNode, { ...shared, boundary: boundary, nodeKey: step.nodeKey }) });
|
|
384
435
|
return _jsxs(Fragment, { children: [_jsx(BlockBoundary, { children: _jsx(ProcessNode, { useChat: useFlowChat, t: props.t, nodeKey: step.nodeKey, open: processOpen, motion: motion, onRead: pinProcess, returnFocusTo: processButton }) }), _jsx(BlockBoundary, { children: _jsx(MainNode, { ...shared, boundary: boundary, nodeKey: step.nodeKey, pinned: pinnedKeys.includes(step.nodeKey), processOpen: processOpen }) })] });
|
|
385
436
|
};
|
|
386
|
-
return _jsxs("section", { className: css.turn, "data-reader-turn": group.turn ?? 'unresolved', "data-reader-turn-state": boundary.status, "data-reader-turn-result": boundary.reason ?? undefined, children: [startsWithUser && _jsx(BlockBoundary, { children: _jsx(MainNode, { ...shared, useChat: props.useChat, boundary: boundary, nodeKey: group.keys[0] }) }),
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
437
|
+
return _jsxs("section", { className: css.turn, "data-reader-turn": group.turn ?? 'unresolved', "data-reader-turn-state": boundary.status, "data-reader-turn-result": boundary.reason ?? undefined, children: [startsWithUser && _jsx(BlockBoundary, { children: _jsx(MainNode, { ...shared, useChat: props.useChat, boundary: boundary, nodeKey: group.keys[0] }) }), _jsxs("div", { className: css.turnStickyRegion, "data-reader-sticky-region": true, children: [(showStatusLane || showClosedSummary) && _jsxs("div", { className: css.turnStickyLanes, children: [showStatusLane && _jsx(StickyLane, { kind: "status", className: css.turnProcessSticky, children: _jsx(Disclosure, { open: expanded, onChange: setExpanded, controls: flowId, buttonRef: processButton, label: _jsx(GroupStatus, { group: group, sessionId: props.sessionId, useChat: props.useChat, pending: interaction, motion: motion }) }) }), showClosedSummary && _jsx(ClosedProcessSummary, { open: expanded, onChange: setExpanded, controls: flowId, steps: steps.filter(step => {
|
|
438
|
+
if (step.kind === 'user')
|
|
439
|
+
return false;
|
|
440
|
+
if (step.kind !== 'body')
|
|
441
|
+
return true;
|
|
442
|
+
const node = nodes.get(step.nodeKey);
|
|
443
|
+
return !!node && isNode(node, 'assistant-step') && (isEarlierNarration(node.data, boundary)
|
|
444
|
+
|| node.data.blocks.some(block => block.kind === 'tool-call')
|
|
445
|
+
|| (boundary.latestStep > 0 && node.data.step < boundary.latestStep));
|
|
446
|
+
}) })] }), _jsx(ChoreographedFlow, { id: flowId, frame: presentation, motion: motion, enabled: autoFold && boundary.status === 'open' && !holdingSelection, urgent: hasTurnError || interaction !== undefined || !sessionRunning, open: foldOpenByKey, processOpen: expanded, onOpenChange: (key, value) => { pinProcess(); setFoldOpenByKey(current => ({ ...current, [key]: value })); }, renderStep: renderStep })] }), !hasProcess && boundary.status === 'open' && !isAwaitingModel && _jsx("div", { className: css.disclosure, "data-reader-status-only": true, children: _jsx(GroupStatus, { group: group, sessionId: props.sessionId, useChat: props.useChat, pending: interaction, motion: motion }) }), showDeliverablesRow(boundary.status, deliverables) && _jsx(DeliverablesRow, { deliverables: deliverables, openFile: props.openFile, revealFile: props.revealFile, openMode: openMode }), boundary.status === 'closed' && _jsx(BlockBoundary, { children: _jsx(OfficialTail, { official: official, owner: tailOwner, produced: deliverables }) }), showTerminalNotice && _jsx("div", { className: css.notice, "data-reader-terminal": true, children: terminal })] });
|
|
396
447
|
});
|
|
397
448
|
export function Reader(props) {
|
|
449
|
+
useInsertionEffect(() => { ensureStyles(); }, []);
|
|
398
450
|
const root = useRef(null);
|
|
399
451
|
const activatedAt = useRef(Date.now());
|
|
400
452
|
const order = props.useChat(snapshot => snapshot.order);
|
|
@@ -408,6 +460,31 @@ export function Reader(props) {
|
|
|
408
460
|
const loadingOlder = props.useSession(snapshot => snapshot.loadingOlder);
|
|
409
461
|
const pendingSubmissions = props.useSession(snapshot => snapshot.pendingSubmissions);
|
|
410
462
|
const pendingList = asReadonlyArray(pendingSubmissions);
|
|
463
|
+
const inbox = props.useProjection?.('inbox');
|
|
464
|
+
const inboxSteering = asReadonlyArray(inbox?.['next-step']).filter(item => item.source?.kind === 'user');
|
|
465
|
+
const observed = useMemo(() => observedInputIds(order, key => nodes.get(key)), [order, nodes]);
|
|
466
|
+
const visibleSubmissions = useMemo(() => pendingList.filter(sub => sub.placement !== 'queued' && !observed.has(sub.requestId)), [pendingList, observed]);
|
|
467
|
+
const pendingInputs = useMemo(() => {
|
|
468
|
+
const local = new Map(visibleSubmissions.map(sub => [sub.requestId, sub]));
|
|
469
|
+
const localIds = new Set(pendingList.filter(sub => sub.placement !== 'queued').map(sub => sub.requestId));
|
|
470
|
+
const rows = [];
|
|
471
|
+
for (const item of inboxSteering) {
|
|
472
|
+
const rpcId = typeof item.source?.rpcId === 'string' ? item.source.rpcId : undefined;
|
|
473
|
+
if (!rpcId) {
|
|
474
|
+
rows.push(item);
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
const submission = local.get(rpcId);
|
|
478
|
+
if (submission) {
|
|
479
|
+
local.delete(rpcId);
|
|
480
|
+
rows.push(submission);
|
|
481
|
+
}
|
|
482
|
+
else if (!localIds.has(rpcId))
|
|
483
|
+
rows.push(item);
|
|
484
|
+
}
|
|
485
|
+
rows.push(...local.values());
|
|
486
|
+
return rows;
|
|
487
|
+
}, [inboxSteering, pendingList, visibleSubmissions]);
|
|
411
488
|
const waitAnchor = waitingAnchor(order, key => nodes.get(key), pendingList);
|
|
412
489
|
const motionPreference = props.useStore(state => state.motion);
|
|
413
490
|
const motion = useMotionAllowed(motionPreference);
|
|
@@ -576,11 +653,6 @@ export function Reader(props) {
|
|
|
576
653
|
scroll.jump();
|
|
577
654
|
}
|
|
578
655
|
}, [lastKey, lastNode?.kind, lastSubmissionId, scroll]);
|
|
579
|
-
const visibleSubmissions = useMemo(() => {
|
|
580
|
-
if (pendingList.length === 0)
|
|
581
|
-
return [];
|
|
582
|
-
return pendingList.filter(sub => sub.placement !== 'queued');
|
|
583
|
-
}, [pendingList]);
|
|
584
656
|
// ChatView publishes data-chat-flow="" on its column. Skins treat a
|
|
585
657
|
// scrollport without that hook as inspect-only and hide [data-composer-seat].
|
|
586
658
|
return _jsx(StreamMotionContext.Provider, { value: streamMotion, children: _jsxs("div", { ref: root, className: css.root, "data-reader-build": "0.3.4", "data-dsh-better-display": "0.3.4", "data-reader-wait-clock-version": "input-v1", "data-reader-wait-start": waitAnchor.time ?? undefined, "data-motion": motion ? 'on' : 'off', "data-reader-glass": frostedGlass || undefined, "data-reader-auto-fold": autoFold ? 'on' : 'off', children: [_jsx(TimelineRail, { items: timelineItems, activeTurn: activeTurn, busyTurn: busyTurn, onNavigate: onNavigateTurn }), _jsxs("div", { className: css.column, "data-chat-flow": "", children: [_jsx(StickyLane, { kind: "toolbar", className: css.toolbar, children: _jsx("button", { type: "button", className: css.textButton, "aria-pressed": autoFold, onClick: () => {
|
|
@@ -594,9 +666,13 @@ export function Reader(props) {
|
|
|
594
666
|
catch {
|
|
595
667
|
setHistoryError(true);
|
|
596
668
|
}
|
|
597
|
-
}, children: loadingOlder ? '正在加载更早记录' : '加载更早记录' }), historyError && _jsx("div", { className: css.notice, children: "\u5386\u53F2\u8BB0\u5F55\u52A0\u8F7D\u5931\u8D25\uFF0C\u53EF\u518D\u6B21\u5C1D\u8BD5\uFF1B\u73B0\u6709\u5185\u5BB9\u672A\u6539\u53D8\u3002" }), openError && _jsxs("div", { className: css.error, role: "alert", children: ["\u4F1A\u8BDD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\uFF1A", openError.message] }), loading && groups.length === 0 && _jsx("p", { className: css.empty, role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u4F1A\u8BDD\u2026" }), groups.map(group => _jsx(TurnGroup, { ...props, group: group, motion: motion, autoFold: autoFold, pinnedKeys: pinnedKeys, selectedProcessKeys: selectedProcessKeys, isAwaitingModel: isAwaitingModel && group.key === groups.at(-1)?.key }, group.key)),
|
|
598
|
-
const
|
|
599
|
-
|
|
669
|
+
}, children: loadingOlder ? '正在加载更早记录' : '加载更早记录' }), historyError && _jsx("div", { className: css.notice, children: "\u5386\u53F2\u8BB0\u5F55\u52A0\u8F7D\u5931\u8D25\uFF0C\u53EF\u518D\u6B21\u5C1D\u8BD5\uFF1B\u73B0\u6709\u5185\u5BB9\u672A\u6539\u53D8\u3002" }), openError && _jsxs("div", { className: css.error, role: "alert", children: ["\u4F1A\u8BDD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\uFF1A", openError.message] }), loading && groups.length === 0 && _jsx("p", { className: css.empty, role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u4F1A\u8BDD\u2026" }), groups.map(group => _jsx(TurnGroup, { ...props, group: group, motion: motion, autoFold: autoFold, pinnedKeys: pinnedKeys, selectedProcessKeys: selectedProcessKeys, isAwaitingModel: isAwaitingModel && group.key === groups.at(-1)?.key }, group.key)), pendingInputs.map((item, index) => {
|
|
670
|
+
const submission = 'requestId' in item ? item : undefined;
|
|
671
|
+
const text = submission?.text ?? inboxText(item);
|
|
672
|
+
const images = submission ? pendingSubmissionImages(submission) : [];
|
|
673
|
+
const attachmentCount = images.length;
|
|
674
|
+
const requestId = submission?.requestId ?? `inbox-${index}`;
|
|
675
|
+
return (_jsxs("div", { className: css.userCluster, "data-reader-pending-submission": true, "data-pending-steering": submission ? undefined : '', "data-pending-attachment-count": attachmentCount, children: [images.length > 0 && (_jsx("div", { className: css.userImages, children: images.map((item, idx) => (_jsx("figure", { className: css.imageFigure, children: _jsx("div", { className: css.imageFrame, style: { aspectRatio: `${item.width || 4} / ${item.height || 3}` }, children: _jsx("img", { src: item.previewUrl, alt: item.name ?? '发送的图片', className: css.pendingImage }) }) }, idx))) })), text ? (_jsx("div", { className: css.user, children: _jsx("div", { className: css.blocks, children: text }) })) : null, _jsx(UserMessageActions, { text: text, time: submission?.time })] }, requestId));
|
|
600
676
|
}), isAwaitingModel && _jsx(WaitingStatus, { anchor: waitAnchor, label: props.t ? props.t('chat.deepDiving') : '深度求索中...' }), pending !== undefined && _jsxs("div", { className: css.attention, role: "alert", "data-reader-attention": true, children: [_jsx("strong", { children: pending.kind === 'question' ? '需要你回答一个问题' : '需要你的确认' }), _jsx("span", { children: "\u8BF7\u5728\u4E0B\u65B9\u539F\u751F\u64CD\u4F5C\u533A\u5904\u7406\u3002\u6B64\u63D0\u793A\u4E0D\u4F1A\u6536\u8FDB\u6267\u884C\u8FC7\u7A0B\u3002" })] }), scroll.detached && _jsx("div", { className: css.jumpDock, children: _jsx("button", { type: "button", className: css.jump, "aria-label": "\u56DE\u5230\u5E95\u90E8", title: "\u56DE\u5230\u5E95\u90E8", onClick: scroll.jump, children: _jsx("svg", { viewBox: "0 0 14 14", width: "14", height: "14", "aria-hidden": "true", children: _jsx("path", { d: "M3 5.5 7 9.5 11 5.5", fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) })] })] }) });
|
|
601
677
|
}
|
|
602
678
|
//# sourceMappingURL=Reader.js.map
|