dsh-context 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/lib/client.js +587 -49
- package/lib/index.d.ts +65 -5
- package/lib/index.js +119 -7
- package/package.json +2 -2
package/lib/client.js
CHANGED
|
@@ -20,7 +20,7 @@ window.__ModuleLoader__.load({
|
|
|
20
20
|
"overview.ofUsed": "占已用上下文",
|
|
21
21
|
"overview.compactReserve": "自动压缩预留:占用达 {pct}% 窗口时触发压缩,此区域一般不实际占用",
|
|
22
22
|
"stats.title": "上下文统计",
|
|
23
|
-
"stats.hint": "
|
|
23
|
+
"stats.hint": "轮次、步骤与上下文事件",
|
|
24
24
|
"stats.turns": "轮次",
|
|
25
25
|
"stats.steps": "步数",
|
|
26
26
|
"stats.injects": "注入",
|
|
@@ -28,22 +28,38 @@ window.__ModuleLoader__.load({
|
|
|
28
28
|
"stats.prunes": "剪枝",
|
|
29
29
|
"stats.toolCalls": "工具调用",
|
|
30
30
|
"stats.images": "图片",
|
|
31
|
-
"stats.cacheHit": "缓存命中",
|
|
32
31
|
"stats.cost": "预估费用",
|
|
33
32
|
"stats.costTip": "按 DeepSeek 官方刊例价估算整个会话的累计费用:输入区分缓存命中/未命中,输出含思考;按请求时间区分高峰(北京时间工作日 9:00–12:00、14:00–18:00)与空闲时段(半价,周末全天均为空闲时段)。适用于 deepseek-v4-flash / deepseek-v4-pro(不限 provider),价格写死在代码中,仅供参考。",
|
|
34
33
|
"stats.costPriceHead": "每百万 tokens 价格(高峰 | 空闲半价):",
|
|
35
34
|
"stats.costHit": "命中",
|
|
36
35
|
"stats.costMiss": "未命中",
|
|
37
36
|
"stats.costOut": "输出",
|
|
37
|
+
"timing.title": "耗时统计",
|
|
38
|
+
"timing.hint": "整个会话的活跃时长分布",
|
|
39
|
+
"timing.total": "总活跃时长",
|
|
40
|
+
"timing.lm": "模型调用",
|
|
41
|
+
"timing.tools": "工具执行",
|
|
42
|
+
"timing.other": "其他开销",
|
|
43
|
+
"timing.times": "{n}次",
|
|
44
|
+
"timing.empty": "暂无耗时数据 · 对话开始后这里会显示时长分布",
|
|
45
|
+
"tokens.title": "Token 统计",
|
|
46
|
+
"tokens.hint": "供应商上报的累计计费用量",
|
|
47
|
+
"tokens.cacheHit": "缓存命中",
|
|
48
|
+
"tokens.cacheRead": "缓存读取",
|
|
49
|
+
"tokens.cacheWrite": "缓存写入",
|
|
50
|
+
"tokens.uncached": "未命中输入",
|
|
51
|
+
"tokens.output": "输出(含思考)",
|
|
38
52
|
"plugin.title": "插件信息",
|
|
39
53
|
"plugin.hint": "The best DSH context plugin ⭐",
|
|
40
54
|
"plugin.name": "插件",
|
|
41
55
|
"plugin.github": "GitHub",
|
|
56
|
+
"plugin.settings": "设置",
|
|
57
|
+
"plugin.settingsOpen": "打开设置",
|
|
42
58
|
"trend.title": "上下文趋势",
|
|
43
59
|
"gran.step": "步骤",
|
|
44
60
|
"gran.turn": "轮次",
|
|
45
61
|
"settings.title": "上下文",
|
|
46
|
-
"settings.desc": "
|
|
62
|
+
"settings.desc": "dsh-context 插件中上下文面板的偏好设置",
|
|
47
63
|
"settings.gran": "趋势图默认粒度",
|
|
48
64
|
"settings.mode": "趋势图默认展示",
|
|
49
65
|
"settings.fileSort": "文件活动默认排序",
|
|
@@ -68,6 +84,7 @@ window.__ModuleLoader__.load({
|
|
|
68
84
|
"brief.more": "+{n}",
|
|
69
85
|
"brief.noInputs": "(无新增)",
|
|
70
86
|
"brief.locate": "在上下文浏览器中查看",
|
|
87
|
+
"jump.title": "在上下文标签页中查看此轮",
|
|
71
88
|
"brief.turnTip": "这一轮开场时用户发送的消息;回合内的每一步都会回显同一条",
|
|
72
89
|
"brief.inputTip": "上一步回复之后、本次请求发出前新进入上下文的内容——通常是上一步所调工具的结果;每轮的第一步无新增",
|
|
73
90
|
"brief.replyTip": "这一步模型返回的内容(文本回复或工具调用);此步发起的调用,其结果会出现在下一柱的「输入」行",
|
|
@@ -271,7 +288,7 @@ window.__ModuleLoader__.load({
|
|
|
271
288
|
"overview.ofUsed": "of used context",
|
|
272
289
|
"overview.compactReserve": "Auto-compaction reserve: auto-compaction triggers at {pct}% of the window — this area is normally kept as headroom, not actually used",
|
|
273
290
|
"stats.title": "Context Stats",
|
|
274
|
-
"stats.hint": "
|
|
291
|
+
"stats.hint": "Turns, steps, and context events",
|
|
275
292
|
"stats.turns": "Turns",
|
|
276
293
|
"stats.steps": "Steps",
|
|
277
294
|
"stats.injects": "Injections",
|
|
@@ -279,22 +296,38 @@ window.__ModuleLoader__.load({
|
|
|
279
296
|
"stats.prunes": "Prunes",
|
|
280
297
|
"stats.toolCalls": "Tool Calls",
|
|
281
298
|
"stats.images": "Images",
|
|
282
|
-
"stats.cacheHit": "Cache Hit",
|
|
283
299
|
"stats.cost": "Cost",
|
|
284
300
|
"stats.costTip": "Rough cumulative cost of the whole session at DeepSeek’s list prices: input split by cache hit/miss, output includes reasoning; each request is priced at the peak (Beijing Time weekdays 09:00–12:00, 14:00–18:00) or half-price off-peak rate by its time — weekends bill at off-peak all day. Applies to deepseek-v4-flash / deepseek-v4-pro on any provider; prices are hardcoded, for reference only.",
|
|
285
301
|
"stats.costPriceHead": "Per-1M-token rates (peak | off-peak at half price):",
|
|
286
302
|
"stats.costHit": "hit",
|
|
287
303
|
"stats.costMiss": "miss",
|
|
288
304
|
"stats.costOut": "output",
|
|
305
|
+
"timing.title": "Timing Stats",
|
|
306
|
+
"timing.hint": "Whole-session active-time split",
|
|
307
|
+
"timing.total": "active time",
|
|
308
|
+
"timing.lm": "Model calls",
|
|
309
|
+
"timing.tools": "Tool runs",
|
|
310
|
+
"timing.other": "Overhead",
|
|
311
|
+
"timing.times": "{n}×",
|
|
312
|
+
"timing.empty": "No timing data yet — durations appear as the conversation runs",
|
|
313
|
+
"tokens.title": "Token Stats",
|
|
314
|
+
"tokens.hint": "Cumulative provider-reported usage",
|
|
315
|
+
"tokens.cacheHit": "Cache hit",
|
|
316
|
+
"tokens.cacheRead": "Cache read",
|
|
317
|
+
"tokens.cacheWrite": "Cache write",
|
|
318
|
+
"tokens.uncached": "Uncached input",
|
|
319
|
+
"tokens.output": "Output (incl. reasoning)",
|
|
289
320
|
"plugin.title": "Plugin Info",
|
|
290
321
|
"plugin.hint": "The best DSH context plugin ⭐",
|
|
291
322
|
"plugin.name": "Plugin",
|
|
292
323
|
"plugin.github": "GitHub",
|
|
324
|
+
"plugin.settings": "Settings",
|
|
325
|
+
"plugin.settingsOpen": "Open in Settings",
|
|
293
326
|
"trend.title": "Context Trend",
|
|
294
327
|
"gran.step": "Step",
|
|
295
328
|
"gran.turn": "Turn",
|
|
296
329
|
"settings.title": "Context",
|
|
297
|
-
"settings.desc": "
|
|
330
|
+
"settings.desc": "Preferences for Context panel in dsh-context plugin",
|
|
298
331
|
"settings.gran": "Default trend granularity",
|
|
299
332
|
"settings.mode": "Default trend display",
|
|
300
333
|
"settings.fileSort": "File Activity default sort",
|
|
@@ -319,6 +352,7 @@ window.__ModuleLoader__.load({
|
|
|
319
352
|
"brief.more": "+{n}",
|
|
320
353
|
"brief.noInputs": "(nothing new)",
|
|
321
354
|
"brief.locate": "Reveal in Context Browser",
|
|
355
|
+
"jump.title": "View this turn in the Context tab",
|
|
322
356
|
"brief.turnTip": "The user message that opened this turn — every step of the turn recalls it",
|
|
323
357
|
"brief.inputTip": "What entered after the previous reply and before this request went out — usually the previous tool-call results; a turn opener has nothing new",
|
|
324
358
|
"brief.replyTip": "What the model returned on this step (a text reply or tool calls) — results of calls made here appear in the In row of the next bar",
|
|
@@ -819,9 +853,10 @@ window.__ModuleLoader__.load({
|
|
|
819
853
|
"assistant",
|
|
820
854
|
"tool",
|
|
821
855
|
"total"
|
|
822
|
-
].every((k) => typeof current[k] === "number") && Array.isArray(data.requests) && Array.isArray(data.events) && Array.isArray(data.nodes) && Array.isArray(data.archive)) return data;
|
|
856
|
+
].every((k) => typeof current[k] === "number") && Array.isArray(data.requests) && Array.isArray(data.events) && Array.isArray(data.nodes) && Array.isArray(data.archive) && timingFastOk(data.timing)) return data;
|
|
823
857
|
const safeCurrent = current !== null && typeof current === "object" ? current : {};
|
|
824
858
|
const cost = typeof data.cost === "object" && data.cost !== null && !Array.isArray(data.cost) ? data.cost : void 0;
|
|
859
|
+
const timing = timingOf(data.timing);
|
|
825
860
|
return {
|
|
826
861
|
ok: true,
|
|
827
862
|
...typeof data.model === "string" ? { model: data.model } : {},
|
|
@@ -844,6 +879,7 @@ window.__ModuleLoader__.load({
|
|
|
844
879
|
...typeof data.toolCalls === "number" ? { toolCalls: data.toolCalls } : {},
|
|
845
880
|
archive: objectsOf(data.archive),
|
|
846
881
|
...cost !== void 0 ? { cost } : {},
|
|
882
|
+
...timing !== null ? { timing } : {},
|
|
847
883
|
...typeof data.surfaceFloor === "number" ? { surfaceFloor: data.surfaceFloor } : {},
|
|
848
884
|
...typeof data.archiveFloor === "number" ? { archiveFloor: data.archiveFloor } : {}
|
|
849
885
|
};
|
|
@@ -888,6 +924,73 @@ window.__ModuleLoader__.load({
|
|
|
888
924
|
return asRecord$1(value);
|
|
889
925
|
}
|
|
890
926
|
/**
|
|
927
|
+
* A non-negative finite number (the timing totals' every field): NaN or a
|
|
928
|
+
* negative degrades to 0 instead of leaking into donut shares.
|
|
929
|
+
*/
|
|
930
|
+
function msNumOf(value) {
|
|
931
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Cheap whole-value check for the pass-through path of `timelineOf`: absent
|
|
935
|
+
* timing passes; present timing must already be well-formed (every scalar
|
|
936
|
+
* numeric, every per-name row shaped) — anything else sends the payload down
|
|
937
|
+
* the sanitizing slow path.
|
|
938
|
+
*/
|
|
939
|
+
function timingFastOk(value) {
|
|
940
|
+
if (value === void 0) return true;
|
|
941
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
942
|
+
const t = value;
|
|
943
|
+
for (const k of [
|
|
944
|
+
"wallMs",
|
|
945
|
+
"lmMs",
|
|
946
|
+
"calls",
|
|
947
|
+
"toolsMs",
|
|
948
|
+
"toolCalls"
|
|
949
|
+
]) if (typeof t[k] !== "number") return false;
|
|
950
|
+
const tools = t.tools;
|
|
951
|
+
if (tools === null || typeof tools !== "object" || Array.isArray(tools)) return false;
|
|
952
|
+
for (const k in tools) {
|
|
953
|
+
const row = tools[k];
|
|
954
|
+
if (row === null || typeof row !== "object") return false;
|
|
955
|
+
if (typeof row.calls !== "number") return false;
|
|
956
|
+
if (typeof row.ms !== "number") return false;
|
|
957
|
+
}
|
|
958
|
+
return true;
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Narrow a delivered timing totals value (see TimingTotals) to a RENDER-SAFE
|
|
962
|
+
* shape — the timing card's no-white-screen guarantee. A value that is not a
|
|
963
|
+
* record stays null (the card renders its empty state); wrong-typed scalars
|
|
964
|
+
* zero out and per-name rows failing the shape drop individually, so one
|
|
965
|
+
* hostile row never blanks the ranking.
|
|
966
|
+
*/
|
|
967
|
+
function timingOf(value) {
|
|
968
|
+
const data = asRecord$1(value);
|
|
969
|
+
if (data === null) return null;
|
|
970
|
+
const tools = {};
|
|
971
|
+
const rawTools = data.tools;
|
|
972
|
+
if (rawTools !== null && typeof rawTools === "object" && !Array.isArray(rawTools)) for (const k in rawTools) {
|
|
973
|
+
if (k === "__proto__" || !Object.hasOwn(rawTools, k)) continue;
|
|
974
|
+
const row = rawTools[k];
|
|
975
|
+
if (row === null || typeof row !== "object") continue;
|
|
976
|
+
const calls = row.calls;
|
|
977
|
+
const ms = row.ms;
|
|
978
|
+
if (typeof calls !== "number" || !(calls >= 0) || typeof ms !== "number" || !(ms >= 0)) continue;
|
|
979
|
+
tools[k] = {
|
|
980
|
+
calls,
|
|
981
|
+
ms
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
return {
|
|
985
|
+
wallMs: msNumOf(data.wallMs),
|
|
986
|
+
lmMs: msNumOf(data.lmMs),
|
|
987
|
+
calls: msNumOf(data.calls),
|
|
988
|
+
toolsMs: msNumOf(data.toolsMs),
|
|
989
|
+
toolCalls: msNumOf(data.toolCalls),
|
|
990
|
+
tools
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
891
994
|
* Narrow a delivered projection value to the plugin's `contextHeaders`
|
|
892
995
|
* (request-header content epochs). Absent key = an older Host half without
|
|
893
996
|
* the companion unit — the Context browser degrades its system/tools
|
|
@@ -1271,7 +1374,7 @@ window.__ModuleLoader__.load({
|
|
|
1271
1374
|
* nothing was billed. The 1e-9 epsilon absorbs only float noise (integer
|
|
1272
1375
|
* token counts never sit that close to a boundary).
|
|
1273
1376
|
*/
|
|
1274
|
-
function cacheHitPercent
|
|
1377
|
+
function cacheHitPercent(reads, billed) {
|
|
1275
1378
|
if (!(billed > 0)) return null;
|
|
1276
1379
|
const hundredths = Math.trunc(reads / billed * 1e4 + 1e-9);
|
|
1277
1380
|
return `${Math.floor(hundredths / 100)}.${String(hundredths % 100).padStart(2, "0")}`;
|
|
@@ -1281,6 +1384,37 @@ window.__ModuleLoader__.load({
|
|
|
1281
1384
|
if (isNaN(d.getTime())) return "—";
|
|
1282
1385
|
return d.toLocaleTimeString("en-GB", { hour12: false });
|
|
1283
1386
|
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Share of a whole as a compact leading percentage for the slice rows:
|
|
1389
|
+
* '—' when nothing totals, '0%' for empty slices, '<1%' for non-zero crumbs
|
|
1390
|
+
* a rounded-down integer would erase. Shares cap at 100% (parallel tool time
|
|
1391
|
+
* can over-run the wall it belongs to).
|
|
1392
|
+
*/
|
|
1393
|
+
function fmtShare(part, total) {
|
|
1394
|
+
if (!Number.isFinite(part) || !Number.isFinite(total) || total <= 0) return "—";
|
|
1395
|
+
if (part <= 0) return "0%";
|
|
1396
|
+
const pct = Math.min(1, part / total) * 100;
|
|
1397
|
+
if (pct < 1) return "<1%";
|
|
1398
|
+
return `${Math.round(pct)}%`;
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* Whole-session durations for the timing card, in the locale's units: raw ms
|
|
1402
|
+
* under a second, one-decimal seconds under a minute, then m/s and h/m.
|
|
1403
|
+
* Non-finite or non-positive input shows the dash (callers render their empty
|
|
1404
|
+
* state anyway).
|
|
1405
|
+
*/
|
|
1406
|
+
function fmtDuration$1(ms, lang) {
|
|
1407
|
+
if (!Number.isFinite(ms) || ms <= 0) return "—";
|
|
1408
|
+
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
1409
|
+
const zh = lang === "zh";
|
|
1410
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}${zh ? "秒" : "s"}`;
|
|
1411
|
+
const totalSec = Math.floor(ms / 1e3);
|
|
1412
|
+
const m = Math.floor(totalSec / 60);
|
|
1413
|
+
const s = totalSec % 60;
|
|
1414
|
+
if (ms < 36e5) return zh ? `${m}分${s}秒` : `${m}m ${s}s`;
|
|
1415
|
+
const h = Math.floor(m / 60);
|
|
1416
|
+
return zh ? `${h}时${m % 60}分` : `${h}h ${m % 60}m`;
|
|
1417
|
+
}
|
|
1284
1418
|
//#endregion
|
|
1285
1419
|
//#region src/shared/imageTokens.ts
|
|
1286
1420
|
/**
|
|
@@ -2096,6 +2230,17 @@ window.__ModuleLoader__.load({
|
|
|
2096
2230
|
const prevByCat = prevView !== null ? byCatOf(prevView) : null;
|
|
2097
2231
|
const byCat = byCatOf(view);
|
|
2098
2232
|
const toolCount = (c) => countOf(view, byCat, c);
|
|
2233
|
+
const singleKeyOf = (c) => {
|
|
2234
|
+
if (c === "system") return view.header?.system !== void 0 ? "sys" : null;
|
|
2235
|
+
if (c === "tools") {
|
|
2236
|
+
const tools = view.header?.tools;
|
|
2237
|
+
return tools !== void 0 && tools.length === 1 ? "tool:" + tools[0].name : null;
|
|
2238
|
+
}
|
|
2239
|
+
/* v8 ignore next 1 -- reached only through toggleCat's openable guard
|
|
2240
|
+
(count > 0 ⟺ byCat[c] exists); the fallback is defensive. */
|
|
2241
|
+
const nodes = byCat[c] ?? [];
|
|
2242
|
+
return nodes.length === 1 ? "n" + String(nodes[0].seq) : null;
|
|
2243
|
+
};
|
|
2099
2244
|
const toggleCat = (c) => {
|
|
2100
2245
|
if (!(toolCount(c) > 0 || (c === "system" || c === "tools") && view.header === null)) return;
|
|
2101
2246
|
if (openCat === c) {
|
|
@@ -2105,7 +2250,7 @@ window.__ModuleLoader__.load({
|
|
|
2105
2250
|
}
|
|
2106
2251
|
setOpenCat(c);
|
|
2107
2252
|
setRowQuery("");
|
|
2108
|
-
setOpenElem(c
|
|
2253
|
+
setOpenElem(singleKeyOf(c));
|
|
2109
2254
|
};
|
|
2110
2255
|
const toggleElem = (key) => {
|
|
2111
2256
|
setOpenElem(openElem === key ? null : key);
|
|
@@ -4224,6 +4369,58 @@ window.__ModuleLoader__.load({
|
|
|
4224
4369
|
return /* @__PURE__ */ React.createElement("div", { className: "lc-agents-inspector" }, /* @__PURE__ */ React.createElement("b", { className: "lc-agents-inspector-name" }, node.label), node.isCurrent ? /* @__PURE__ */ React.createElement("span", { className: "lc-agents-badge" }, t("agents.self")) : null, node.running ? /* @__PURE__ */ React.createElement("span", { className: "lc-agents-badge lc-agents-badge-on" }, t("agents.running")) : null, node.identity !== null ? /* @__PURE__ */ React.createElement("span", { className: "lc-agents-badge" }, t(node.identity.mode === "one-shot" ? "agents.oneshot" : "agents.continuable")) : null, /* @__PURE__ */ React.createElement("span", { className: "lc-agents-inspector-stats" }, bits.join(" · ")), !node.isCurrent ? /* @__PURE__ */ React.createElement("span", { className: "lc-agents-inspector-open" }, t("agents.open")) : null);
|
|
4225
4370
|
}
|
|
4226
4371
|
//#endregion
|
|
4372
|
+
//#region src/client/components/donut.tsx
|
|
4373
|
+
function makeDonut(kit) {
|
|
4374
|
+
return function Donut(props) {
|
|
4375
|
+
const size = props.size ?? 118;
|
|
4376
|
+
let total = 0;
|
|
4377
|
+
for (const s of props.segments) if (Number.isFinite(s.value) && s.value > 0) total += s.value;
|
|
4378
|
+
const arcs = [];
|
|
4379
|
+
let acc = 0;
|
|
4380
|
+
if (total > 0) for (const s of props.segments) {
|
|
4381
|
+
const v = Number.isFinite(s.value) && s.value > 0 ? s.value : 0;
|
|
4382
|
+
if (v === 0) continue;
|
|
4383
|
+
const pct = v / total * 100;
|
|
4384
|
+
arcs.push({
|
|
4385
|
+
key: s.key,
|
|
4386
|
+
color: s.color,
|
|
4387
|
+
pct,
|
|
4388
|
+
offset: 100 - acc + 25
|
|
4389
|
+
});
|
|
4390
|
+
acc += pct;
|
|
4391
|
+
}
|
|
4392
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
4393
|
+
className: "lc-donut",
|
|
4394
|
+
style: {
|
|
4395
|
+
width: size,
|
|
4396
|
+
height: size
|
|
4397
|
+
}
|
|
4398
|
+
}, /* @__PURE__ */ React.createElement("svg", {
|
|
4399
|
+
viewBox: "0 0 42 42",
|
|
4400
|
+
width: size,
|
|
4401
|
+
height: size,
|
|
4402
|
+
"aria-hidden": "true"
|
|
4403
|
+
}, arcs.length === 0 ? /* @__PURE__ */ React.createElement("circle", {
|
|
4404
|
+
className: "lc-donut-track",
|
|
4405
|
+
cx: "21",
|
|
4406
|
+
cy: "21",
|
|
4407
|
+
r: "15.9155",
|
|
4408
|
+
fill: "none",
|
|
4409
|
+
strokeWidth: "4"
|
|
4410
|
+
}) : arcs.map((a) => /* @__PURE__ */ React.createElement("circle", {
|
|
4411
|
+
key: a.key,
|
|
4412
|
+
cx: "21",
|
|
4413
|
+
cy: "21",
|
|
4414
|
+
r: "15.9155",
|
|
4415
|
+
fill: "none",
|
|
4416
|
+
stroke: a.color,
|
|
4417
|
+
strokeWidth: "4",
|
|
4418
|
+
strokeDasharray: `${a.pct} ${100 - a.pct}`,
|
|
4419
|
+
strokeDashoffset: a.offset
|
|
4420
|
+
}))), /* @__PURE__ */ React.createElement("div", { className: "lc-donut-center" }, /* @__PURE__ */ React.createElement("b", { style: { fontSize: Math.max(11, Math.round(size * .13)) } }, props.centerTop), props.centerSub !== void 0 ? /* @__PURE__ */ React.createElement("span", { style: { fontSize: Math.max(9, Math.round(size * .105)) } }, props.centerSub) : null));
|
|
4421
|
+
};
|
|
4422
|
+
}
|
|
4423
|
+
//#endregion
|
|
4227
4424
|
//#region src/client/components/events.tsx
|
|
4228
4425
|
const EVENT_ICONS = {
|
|
4229
4426
|
compaction: "✂",
|
|
@@ -4545,6 +4742,46 @@ window.__ModuleLoader__.load({
|
|
|
4545
4742
|
return false;
|
|
4546
4743
|
}
|
|
4547
4744
|
//#endregion
|
|
4745
|
+
//#region src/client/settingsJump.ts
|
|
4746
|
+
/**
|
|
4747
|
+
* Best-effort jump to this plugin's settings page (Settings → Plugins →
|
|
4748
|
+
* Plugin configuration). The harness settings panel keeps its open state
|
|
4749
|
+
* inside the shell component — no plugin-facing open face exists — so the
|
|
4750
|
+
* jump drives the real chrome: click the sidebar's settings trigger, then
|
|
4751
|
+
* the Plugins section nav row, both found by their shipped attributes and
|
|
4752
|
+
* labels. EVERY step is individually guarded: a shell that doesn't match
|
|
4753
|
+
* (older host, different layout, missing sidebar) degrades the whole jump
|
|
4754
|
+
* to a silent no-op — this path must never throw into the caller's render.
|
|
4755
|
+
*/
|
|
4756
|
+
/** The Plugins settings section's shipped nav labels (en/zh locales). */
|
|
4757
|
+
const SECTION_LABELS = /* @__PURE__ */ new Set(["Plugins", "插件"]);
|
|
4758
|
+
/** Buttons the jump may operate on, in document order. */
|
|
4759
|
+
function buttonsOf(doc) {
|
|
4760
|
+
return [...doc.querySelectorAll("button")];
|
|
4761
|
+
}
|
|
4762
|
+
/** The sidebar's settings triggers: dialog semantics plus an expanded flag. */
|
|
4763
|
+
function findTriggers(doc) {
|
|
4764
|
+
return buttonsOf(doc).filter((b) => b.getAttribute("aria-haspopup") === "dialog" && b.hasAttribute("aria-expanded"));
|
|
4765
|
+
}
|
|
4766
|
+
/** The Plugins section's nav row, matched by its shipped label. */
|
|
4767
|
+
function findSectionRow(doc) {
|
|
4768
|
+
return buttonsOf(doc).find((b) => SECTION_LABELS.has(b.textContent.trim()));
|
|
4769
|
+
}
|
|
4770
|
+
function openPluginSettings(doc = document, schedule = (run, ms) => {
|
|
4771
|
+
window.setTimeout(run, ms);
|
|
4772
|
+
}) {
|
|
4773
|
+
try {
|
|
4774
|
+
const triggers = findTriggers(doc);
|
|
4775
|
+
if (triggers.find((b) => b.getAttribute("aria-expanded") === "true") === void 0 && triggers.length === 0) return;
|
|
4776
|
+
triggers.find((b) => b.getAttribute("aria-expanded") !== "true")?.click();
|
|
4777
|
+
schedule(() => {
|
|
4778
|
+
try {
|
|
4779
|
+
findSectionRow(doc)?.click();
|
|
4780
|
+
} catch {}
|
|
4781
|
+
}, 80);
|
|
4782
|
+
} catch {}
|
|
4783
|
+
}
|
|
4784
|
+
//#endregion
|
|
4548
4785
|
//#region src/client/components/pluginInfo.tsx
|
|
4549
4786
|
function makePluginInfo(kit) {
|
|
4550
4787
|
const { t } = kit;
|
|
@@ -4557,7 +4794,7 @@ window.__ModuleLoader__.load({
|
|
|
4557
4794
|
return function PluginInfo() {
|
|
4558
4795
|
const [latest, setLatest] = React.useState(null);
|
|
4559
4796
|
React.useEffect(() => {
|
|
4560
|
-
if ("0.
|
|
4797
|
+
if ("0.38.0".includes("-dev")) return;
|
|
4561
4798
|
let on = true;
|
|
4562
4799
|
fetchLatestVersion().then((v) => {
|
|
4563
4800
|
if (on && v) setLatest(v);
|
|
@@ -4566,8 +4803,8 @@ window.__ModuleLoader__.load({
|
|
|
4566
4803
|
on = false;
|
|
4567
4804
|
};
|
|
4568
4805
|
}, []);
|
|
4569
|
-
const update = latest !== null && isNewerVersion(latest, "0.
|
|
4570
|
-
const nameValue = ["dsh-context (v0.
|
|
4806
|
+
const update = latest !== null && isNewerVersion(latest, "0.38.0") ? latest : null;
|
|
4807
|
+
const nameValue = ["dsh-context (v0.38.0)"];
|
|
4571
4808
|
if (update) nameValue.push(/* @__PURE__ */ React.createElement("span", {
|
|
4572
4809
|
key: "update",
|
|
4573
4810
|
className: "lc-pi-update"
|
|
@@ -4577,7 +4814,13 @@ window.__ModuleLoader__.load({
|
|
|
4577
4814
|
href: PLUGIN_REPO,
|
|
4578
4815
|
target: "_blank",
|
|
4579
4816
|
rel: "noreferrer"
|
|
4580
|
-
}, t("plugin.hint"))), /* @__PURE__ */ React.createElement("div", { className: "lc-pi-grid" }, row(t("plugin.name"), nameValue, PLUGIN_REPO + "/releases"), row(t("plugin.github"), PLUGIN_REPO_SHORT, PLUGIN_REPO)
|
|
4817
|
+
}, t("plugin.hint"))), /* @__PURE__ */ React.createElement("div", { className: "lc-pi-grid" }, row(t("plugin.name"), nameValue, PLUGIN_REPO + "/releases"), row(t("plugin.github"), PLUGIN_REPO_SHORT, PLUGIN_REPO), /* @__PURE__ */ React.createElement("button", {
|
|
4818
|
+
type: "button",
|
|
4819
|
+
className: "lc-pi-row lc-pi-row-btn",
|
|
4820
|
+
onClick: () => {
|
|
4821
|
+
openPluginSettings();
|
|
4822
|
+
}
|
|
4823
|
+
}, /* @__PURE__ */ React.createElement("div", { className: "lc-pi-label" }, t("plugin.settings")), /* @__PURE__ */ React.createElement("div", { className: "lc-pi-value" }, t("plugin.settingsOpen")))));
|
|
4581
4824
|
};
|
|
4582
4825
|
}
|
|
4583
4826
|
//#endregion
|
|
@@ -4759,19 +5002,21 @@ window.__ModuleLoader__.load({
|
|
|
4759
5002
|
return /* @__PURE__ */ React.createElement("div", { className: "lc-detail" }, /* @__PURE__ */ React.createElement("div", { className: "lc-detail-head" }, /* @__PURE__ */ React.createElement("b", null, head), marker !== null && markerAt !== null ? /* @__PURE__ */ React.createElement("span", {
|
|
4760
5003
|
className: "lc-detail-marker",
|
|
4761
5004
|
title: eventLabel(marker)
|
|
4762
|
-
}, "✂ " + markerAt) : null, isTurn ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-tag" }, t("detail.lastStep")) : null, delta ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-tag" }, t("gran.delta")) : null, /* @__PURE__ */ React.createElement("span", { className: "lc-detail-time" }, fmtTime(req.time)), delta ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" + (net > 0 ? " lc-detail-metric-up" : net < 0 ? " lc-detail-metric-down" : "") }, t("tip.delta", { n: (net > 0 ? "+" : "") + fmt(net) })) : null, !delta && req.prompt !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" }, t("detail.actual", { n: fmt(req.prompt) })) : null, !delta && req.output !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" }, t("detail.output", { n: fmt(req.output) })) : null, !delta && req.prompt !== void 0 && req.cacheRead !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" }, t("detail.cache", { n: cacheHitPercent
|
|
5005
|
+
}, "✂ " + markerAt) : null, isTurn ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-tag" }, t("detail.lastStep")) : null, delta ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-tag" }, t("gran.delta")) : null, /* @__PURE__ */ React.createElement("span", { className: "lc-detail-time" }, fmtTime(req.time)), delta ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" + (net > 0 ? " lc-detail-metric-up" : net < 0 ? " lc-detail-metric-down" : "") }, t("tip.delta", { n: (net > 0 ? "+" : "") + fmt(net) })) : null, !delta && req.prompt !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" }, t("detail.actual", { n: fmt(req.prompt) })) : null, !delta && req.output !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" }, t("detail.output", { n: fmt(req.output) })) : null, !delta && req.prompt !== void 0 && req.cacheRead !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-detail-metric" }, t("detail.cache", { n: cacheHitPercent(req.cacheRead, req.prompt) ?? "—" })) : null), /* @__PURE__ */ React.createElement(BriefSection, {
|
|
4763
5006
|
brief: props.brief,
|
|
4764
5007
|
convOf: props.convOf,
|
|
4765
5008
|
onLocate: props.onLocate
|
|
4766
5009
|
}), /* @__PURE__ */ React.createElement(StackedBar, {
|
|
4767
5010
|
parts,
|
|
4768
|
-
height: 10
|
|
5011
|
+
height: 10,
|
|
5012
|
+
hoverKey: props.hoverKey,
|
|
5013
|
+
tip: false
|
|
4769
5014
|
}), /* @__PURE__ */ React.createElement("div", { className: "lc-detail-rows" }, CATS.map((c, i) => {
|
|
4770
5015
|
const v = delta ? deltas[i] : req[c.key] || 0;
|
|
4771
5016
|
const mag = Math.abs(v);
|
|
4772
5017
|
return /* @__PURE__ */ React.createElement("div", {
|
|
4773
5018
|
key: c.key,
|
|
4774
|
-
className: "lc-detail-row"
|
|
5019
|
+
className: "lc-detail-row" + (props.hoverKey === c.key ? " lc-detail-row-on" : "")
|
|
4775
5020
|
}, /* @__PURE__ */ React.createElement("i", { style: { background: c.color } }), /* @__PURE__ */ React.createElement("span", { className: "lc-detail-label" }, catLabel(c.key)), /* @__PURE__ */ React.createElement("span", { className: "lc-bar-track" }, delta ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { className: "lc-bar-zero" }), v !== 0 ? /* @__PURE__ */ React.createElement("span", {
|
|
4776
5021
|
className: "lc-bar-fill " + (v > 0 ? "lc-bar-fill-up" : "lc-bar-fill-down"),
|
|
4777
5022
|
style: {
|
|
@@ -4889,40 +5134,20 @@ window.__ModuleLoader__.load({
|
|
|
4889
5134
|
return formatCost(amount, currency).replace(/0+$/, "").replace(/\.$/, "");
|
|
4890
5135
|
}
|
|
4891
5136
|
//#endregion
|
|
4892
|
-
//#region src/client/components/
|
|
4893
|
-
|
|
4894
|
-
* Cache-hit share of billed prompt-side input — same three disjoint buckets
|
|
4895
|
-
* as the harness chat line (`cacheReadTokens` over uncached + reads + writes)
|
|
4896
|
-
* and the step line's 缓存 figure; null when nothing was billed.
|
|
4897
|
-
*/
|
|
4898
|
-
function cacheHitPercent(usage) {
|
|
4899
|
-
const uncached = numOf(usage.uncachedInputTokens);
|
|
4900
|
-
const reads = numOf(usage.cacheReadTokens);
|
|
4901
|
-
const writes = numOf(usage.cacheWriteTokens);
|
|
4902
|
-
return cacheHitPercent$1(reads, uncached + reads + writes);
|
|
4903
|
-
}
|
|
4904
|
-
function cell(label, value, tip) {
|
|
4905
|
-
return /* @__PURE__ */ React.createElement("div", { className: "lc-stat" + (tip === void 0 ? "" : " lc-stat-tipped") }, /* @__PURE__ */ React.createElement("span", { className: "lc-stat-label" }, label, tip !== void 0 && /* @__PURE__ */ React.createElement("i", {
|
|
4906
|
-
className: "lc-stat-q",
|
|
4907
|
-
"aria-hidden": "true"
|
|
4908
|
-
}, "?")), /* @__PURE__ */ React.createElement("b", { className: "lc-stat-value" }, value), tip !== void 0 && /* @__PURE__ */ React.createElement("span", {
|
|
4909
|
-
className: "lc-stat-tip",
|
|
4910
|
-
role: "tooltip"
|
|
4911
|
-
}, tip));
|
|
4912
|
-
}
|
|
4913
|
-
function makeStatsBoard(kit) {
|
|
5137
|
+
//#region src/client/components/statsContext.tsx
|
|
5138
|
+
function makeStatsContext(kit) {
|
|
4914
5139
|
const { t, fmt } = kit;
|
|
4915
|
-
return function
|
|
5140
|
+
return function StatsContext(props) {
|
|
4916
5141
|
const turns = /* @__PURE__ */ new Set();
|
|
4917
|
-
let steps = 0
|
|
5142
|
+
let steps = 0;
|
|
4918
5143
|
for (const req of props.requests) {
|
|
4919
5144
|
turns.add(req.turn ?? 0);
|
|
4920
5145
|
steps++;
|
|
4921
5146
|
}
|
|
4922
|
-
|
|
5147
|
+
let injects = 0, compactions = 0, prunes = 0;
|
|
5148
|
+
for (const ev of props.events) if (ev.kind === "inject") injects++;
|
|
5149
|
+
else if (ev.kind === "compaction") compactions++;
|
|
4923
5150
|
else if (ev.kind === "prune") prunes++;
|
|
4924
|
-
else if (ev.kind === "inject") injects++;
|
|
4925
|
-
const hit = props.usage !== null ? cacheHitPercent(props.usage) : null;
|
|
4926
5151
|
const currency = props.locale === "zh" ? "cny" : "usd";
|
|
4927
5152
|
const cost = estimateSessionCost(props.cost, currency);
|
|
4928
5153
|
const fmtRate = (n) => formatPriceRate(n, currency);
|
|
@@ -4933,7 +5158,149 @@ window.__ModuleLoader__.load({
|
|
|
4933
5158
|
key: r.family,
|
|
4934
5159
|
className: "lc-stat-tip-row"
|
|
4935
5160
|
}, /* @__PURE__ */ React.createElement("b", { className: "lc-stat-tip-model" }, r.family), " ", t("stats.costHit"), " ", fmtRate(r.peak.hit), "/", fmtRate(r.off.hit), " · ", t("stats.costMiss"), " ", fmtRate(r.peak.miss), "/", fmtRate(r.off.miss), " · ", t("stats.costOut"), " ", fmtRate(r.peak.out), "/", fmtRate(r.off.out))))];
|
|
4936
|
-
|
|
5161
|
+
const cell = (label, value, tip) => /* @__PURE__ */ React.createElement("div", { className: "lc-stat" + (tip === void 0 ? "" : " lc-stat-tipped") }, /* @__PURE__ */ React.createElement("span", { className: "lc-stat-label" }, label, tip !== void 0 && /* @__PURE__ */ React.createElement("i", {
|
|
5162
|
+
className: "lc-stat-q",
|
|
5163
|
+
"aria-hidden": "true"
|
|
5164
|
+
}, "?")), /* @__PURE__ */ React.createElement("b", { className: "lc-stat-value" }, typeof value === "number" ? fmt(value) : value), tip !== void 0 && /* @__PURE__ */ React.createElement("span", {
|
|
5165
|
+
className: "lc-stat-tip",
|
|
5166
|
+
role: "tooltip"
|
|
5167
|
+
}, tip));
|
|
5168
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col-stats" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("stats.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("stats.hint"))), /* @__PURE__ */ React.createElement("div", { className: "lc-stats" }, cell(t("stats.turns"), turns.size), cell(t("stats.steps"), steps), cell(t("stats.toolCalls"), props.toolCalls ?? 0), cell(t("stats.images"), props.images ?? 0), cell(t("stats.cost"), cost === null ? "—" : formatCost(cost, currency), costTip), cell(t("stats.injects"), injects), cell(t("stats.compactions"), compactions), cell(t("stats.prunes"), prunes)));
|
|
5169
|
+
};
|
|
5170
|
+
}
|
|
5171
|
+
//#endregion
|
|
5172
|
+
//#region src/client/components/sliceList.tsx
|
|
5173
|
+
function makeSliceList(kit) {
|
|
5174
|
+
return function SliceList(props) {
|
|
5175
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-sl" }, props.rows.map((r) => /* @__PURE__ */ React.createElement("div", {
|
|
5176
|
+
key: r.key,
|
|
5177
|
+
className: "lc-sl-row"
|
|
5178
|
+
}, /* @__PURE__ */ React.createElement("i", {
|
|
5179
|
+
className: "lc-sl-dot",
|
|
5180
|
+
style: { background: r.color }
|
|
5181
|
+
}), /* @__PURE__ */ React.createElement("span", { className: "lc-sl-label" }, r.label), r.count !== "" ? /* @__PURE__ */ React.createElement("span", { className: "lc-sl-count" }, r.count) : null, /* @__PURE__ */ React.createElement("span", { className: "lc-sl-pct" }, r.pct))));
|
|
5182
|
+
};
|
|
5183
|
+
}
|
|
5184
|
+
//#endregion
|
|
5185
|
+
//#region src/client/components/statsTiming.tsx
|
|
5186
|
+
function makeStatsTiming(kit, Donut) {
|
|
5187
|
+
const { t, fmt, fmtDuration, fmtShare } = kit;
|
|
5188
|
+
const SliceList = makeSliceList(kit);
|
|
5189
|
+
return function StatsTiming(props) {
|
|
5190
|
+
const lang = props.locale === "zh" ? "zh" : "en";
|
|
5191
|
+
const timing = props.timing;
|
|
5192
|
+
const wall = timing !== null && Number.isFinite(timing.wallMs) && timing.wallMs > 0 ? timing.wallMs : 0;
|
|
5193
|
+
let segments = [];
|
|
5194
|
+
let rows = [];
|
|
5195
|
+
if (timing !== null && (wall > 0 || timing.calls > 0 || timing.toolCalls > 0)) {
|
|
5196
|
+
const lm = Math.min(timing.lmMs, wall);
|
|
5197
|
+
const toolRing = Math.max(0, Math.min(timing.toolsMs, wall - lm));
|
|
5198
|
+
const other = Math.max(0, wall - lm - toolRing);
|
|
5199
|
+
const share = (ms) => wall > 0 ? ms / wall : 0;
|
|
5200
|
+
segments = [
|
|
5201
|
+
{
|
|
5202
|
+
key: "lm",
|
|
5203
|
+
color: "#3b82f6",
|
|
5204
|
+
value: share(lm)
|
|
5205
|
+
},
|
|
5206
|
+
{
|
|
5207
|
+
key: "tools",
|
|
5208
|
+
color: "#14b8a6",
|
|
5209
|
+
value: share(toolRing)
|
|
5210
|
+
},
|
|
5211
|
+
{
|
|
5212
|
+
key: "other",
|
|
5213
|
+
color: "#94a3b8",
|
|
5214
|
+
value: share(other)
|
|
5215
|
+
}
|
|
5216
|
+
];
|
|
5217
|
+
rows = [
|
|
5218
|
+
{
|
|
5219
|
+
key: "lm",
|
|
5220
|
+
color: "#3b82f6",
|
|
5221
|
+
label: `${t("timing.lm")} ${t("timing.times", { n: fmt(timing.calls) })}`,
|
|
5222
|
+
pct: fmtShare(timing.lmMs, wall),
|
|
5223
|
+
count: fmtDuration(timing.lmMs, lang)
|
|
5224
|
+
},
|
|
5225
|
+
{
|
|
5226
|
+
key: "tools",
|
|
5227
|
+
color: "#14b8a6",
|
|
5228
|
+
label: `${t("timing.tools")} ${t("timing.times", { n: fmt(timing.toolCalls) })}`,
|
|
5229
|
+
pct: fmtShare(timing.toolsMs, wall),
|
|
5230
|
+
count: fmtDuration(timing.toolsMs, lang)
|
|
5231
|
+
},
|
|
5232
|
+
{
|
|
5233
|
+
key: "other",
|
|
5234
|
+
color: "#94a3b8",
|
|
5235
|
+
label: t("timing.other"),
|
|
5236
|
+
pct: fmtShare(other, wall),
|
|
5237
|
+
count: fmtDuration(other, lang)
|
|
5238
|
+
}
|
|
5239
|
+
];
|
|
5240
|
+
}
|
|
5241
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col-stats lc-col-donut" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("timing.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("timing.hint"))), rows.length === 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-empty" }, t("timing.empty")) : /* @__PURE__ */ React.createElement("div", { className: "lc-donut-row" }, /* @__PURE__ */ React.createElement(Donut, {
|
|
5242
|
+
segments,
|
|
5243
|
+
size: 96,
|
|
5244
|
+
centerTop: wall > 0 ? fmtDuration(wall, lang) : "—",
|
|
5245
|
+
centerSub: t("timing.total")
|
|
5246
|
+
}), /* @__PURE__ */ React.createElement(SliceList, { rows })));
|
|
5247
|
+
};
|
|
5248
|
+
}
|
|
5249
|
+
//#endregion
|
|
5250
|
+
//#region src/client/components/statsTokens.tsx
|
|
5251
|
+
function makeStatsTokens(kit, Donut) {
|
|
5252
|
+
const { t, fmt, fmtShare } = kit;
|
|
5253
|
+
const SliceList = makeSliceList(kit);
|
|
5254
|
+
return function StatsTokens(props) {
|
|
5255
|
+
const reads = props.usage !== null ? numOf(props.usage.cacheReadTokens) : 0;
|
|
5256
|
+
const writes = props.usage !== null ? numOf(props.usage.cacheWriteTokens) : 0;
|
|
5257
|
+
const uncached = props.usage !== null ? numOf(props.usage.uncachedInputTokens) : 0;
|
|
5258
|
+
const output = props.usage !== null ? numOf(props.usage.outputTokens) : 0;
|
|
5259
|
+
const billed = reads + writes + uncached + output;
|
|
5260
|
+
const hit = props.usage !== null ? cacheHitPercent(reads, uncached + reads + writes) : null;
|
|
5261
|
+
const buckets = [
|
|
5262
|
+
{
|
|
5263
|
+
key: "read",
|
|
5264
|
+
color: "#22c55e",
|
|
5265
|
+
label: t("tokens.cacheRead"),
|
|
5266
|
+
value: reads
|
|
5267
|
+
},
|
|
5268
|
+
{
|
|
5269
|
+
key: "write",
|
|
5270
|
+
color: "#f59e0b",
|
|
5271
|
+
label: t("tokens.cacheWrite"),
|
|
5272
|
+
value: writes
|
|
5273
|
+
},
|
|
5274
|
+
{
|
|
5275
|
+
key: "uncached",
|
|
5276
|
+
color: "#6366f1",
|
|
5277
|
+
label: t("tokens.uncached"),
|
|
5278
|
+
value: uncached
|
|
5279
|
+
},
|
|
5280
|
+
{
|
|
5281
|
+
key: "output",
|
|
5282
|
+
color: "#3b82f6",
|
|
5283
|
+
label: t("tokens.output"),
|
|
5284
|
+
value: output
|
|
5285
|
+
}
|
|
5286
|
+
];
|
|
5287
|
+
const rows = buckets.map((b) => ({
|
|
5288
|
+
key: b.key,
|
|
5289
|
+
color: b.color,
|
|
5290
|
+
label: b.label,
|
|
5291
|
+
pct: fmtShare(b.value, billed),
|
|
5292
|
+
count: fmt(b.value)
|
|
5293
|
+
}));
|
|
5294
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col-stats lc-col-donut" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("tokens.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("tokens.hint"))), /* @__PURE__ */ React.createElement("div", { className: "lc-donut-row" }, /* @__PURE__ */ React.createElement(Donut, {
|
|
5295
|
+
segments: buckets.map((b) => ({
|
|
5296
|
+
key: b.key,
|
|
5297
|
+
color: b.color,
|
|
5298
|
+
value: b.value
|
|
5299
|
+
})),
|
|
5300
|
+
size: 96,
|
|
5301
|
+
centerTop: hit === null ? "—" : `${hit}%`,
|
|
5302
|
+
centerSub: t("tokens.cacheHit")
|
|
5303
|
+
}), /* @__PURE__ */ React.createElement(SliceList, { rows })));
|
|
4937
5304
|
};
|
|
4938
5305
|
}
|
|
4939
5306
|
//#endregion
|
|
@@ -4978,6 +5345,15 @@ window.__ModuleLoader__.load({
|
|
|
4978
5345
|
}
|
|
4979
5346
|
return markers;
|
|
4980
5347
|
}
|
|
5348
|
+
/**
|
|
5349
|
+
* The chat→Context jump's target: the turn bar whose closing reply the user clicked — the relayed seq is a turn's LAST step, exactly the
|
|
5350
|
+
* aggregate's record — or, when that turn has aged out of the host's retained window, the oldest retained bar. Resolved against turn
|
|
5351
|
+
* aggregates, since the jump pins in turn granularity. Null only on an empty history.
|
|
5352
|
+
*/
|
|
5353
|
+
function jumpTargetOf(requests, seq) {
|
|
5354
|
+
for (const req of requests) if (req.seq === seq) return req;
|
|
5355
|
+
return requests.length > 0 ? requests[0] : null;
|
|
5356
|
+
}
|
|
4981
5357
|
function makeTrendChart(kit) {
|
|
4982
5358
|
const { t, fmt, fmtTime, eventLabel, eventAt } = kit;
|
|
4983
5359
|
const CHART_H = 112;
|
|
@@ -5031,6 +5407,8 @@ window.__ModuleLoader__.load({
|
|
|
5031
5407
|
if (d <= 0) return null;
|
|
5032
5408
|
return /* @__PURE__ */ React.createElement("div", {
|
|
5033
5409
|
key: c.key,
|
|
5410
|
+
"data-cat": c.key,
|
|
5411
|
+
className: "lc-cat-seg",
|
|
5034
5412
|
style: {
|
|
5035
5413
|
height: `${Math.max(1, Math.round(d * props.deltaScale))}px`,
|
|
5036
5414
|
background: c.color
|
|
@@ -5044,6 +5422,8 @@ window.__ModuleLoader__.load({
|
|
|
5044
5422
|
if (d >= 0) return null;
|
|
5045
5423
|
return /* @__PURE__ */ React.createElement("div", {
|
|
5046
5424
|
key: c.key,
|
|
5425
|
+
"data-cat": c.key,
|
|
5426
|
+
className: "lc-cat-seg",
|
|
5047
5427
|
style: {
|
|
5048
5428
|
height: `${Math.max(1, Math.round(-d * props.deltaScale))}px`,
|
|
5049
5429
|
background: c.color
|
|
@@ -5054,6 +5434,8 @@ window.__ModuleLoader__.load({
|
|
|
5054
5434
|
if (!v) return null;
|
|
5055
5435
|
return /* @__PURE__ */ React.createElement("div", {
|
|
5056
5436
|
key: c.key,
|
|
5437
|
+
"data-cat": c.key,
|
|
5438
|
+
className: "lc-cat-seg",
|
|
5057
5439
|
style: {
|
|
5058
5440
|
height: `${Math.max(1, Math.round(v / props.maxTotal * CHART_H))}px`,
|
|
5059
5441
|
background: c.color
|
|
@@ -5237,6 +5619,7 @@ window.__ModuleLoader__.load({
|
|
|
5237
5619
|
}
|
|
5238
5620
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
5239
5621
|
className: "lc-chart",
|
|
5622
|
+
"data-catdim": props.hoverCat ?? void 0,
|
|
5240
5623
|
onMouseLeave: () => {
|
|
5241
5624
|
props.onHover(null);
|
|
5242
5625
|
}
|
|
@@ -5282,6 +5665,43 @@ window.__ModuleLoader__.load({
|
|
|
5282
5665
|
};
|
|
5283
5666
|
}
|
|
5284
5667
|
//#endregion
|
|
5668
|
+
//#region src/client/viewFocus.ts
|
|
5669
|
+
/**
|
|
5670
|
+
* Chat → Context jump relay. The assistant-message action records the clicked
|
|
5671
|
+
* reply's request seq here and activates the Context tab; the Context view
|
|
5672
|
+
* consumes the one-shot focus once its projection data is in. Module-level
|
|
5673
|
+
* per-session map — the same life pattern as the modal open-state stores.
|
|
5674
|
+
*/
|
|
5675
|
+
const pendingFocus = /* @__PURE__ */ new Map();
|
|
5676
|
+
/** Record the Context step (request seq) to reveal for `sessionId` — replaces any unconsumed request. */
|
|
5677
|
+
function requestContextFocus(sessionId, seq) {
|
|
5678
|
+
pendingFocus.set(sessionId, seq);
|
|
5679
|
+
}
|
|
5680
|
+
/** Take the pending focus request, if any — one-shot, the map entry is consumed. */
|
|
5681
|
+
function takeContextFocus(sessionId) {
|
|
5682
|
+
const seq = pendingFocus.get(sessionId);
|
|
5683
|
+
if (seq === void 0) return null;
|
|
5684
|
+
pendingFocus.delete(sessionId);
|
|
5685
|
+
return seq;
|
|
5686
|
+
}
|
|
5687
|
+
/**
|
|
5688
|
+
* Activate the Context tab by clicking its own tab-bar button (the semantic
|
|
5689
|
+
* `button[role="tab"]` chrome the conversation shell renders for every view).
|
|
5690
|
+
* The harness hands `openView` only to the ACTIVE view entry, so a nested
|
|
5691
|
+
* chat action cannot call it — this rides the same button a user click would.
|
|
5692
|
+
* Already-active is a no-op that still reports success; no matching tab (any
|
|
5693
|
+
* dsh layout without the tab bar) reports failure and nothing happens.
|
|
5694
|
+
*/
|
|
5695
|
+
function activateContextTab(label) {
|
|
5696
|
+
const tabs = document.querySelectorAll("button[role=\"tab\"]");
|
|
5697
|
+
for (const tab of tabs) {
|
|
5698
|
+
if (tab.textContent.trim() !== label) continue;
|
|
5699
|
+
if (tab.getAttribute("aria-selected") !== "true") tab.click();
|
|
5700
|
+
return true;
|
|
5701
|
+
}
|
|
5702
|
+
return false;
|
|
5703
|
+
}
|
|
5704
|
+
//#endregion
|
|
5285
5705
|
//#region src/client/components/contextView.tsx
|
|
5286
5706
|
const viewScroll = /* @__PURE__ */ new Map();
|
|
5287
5707
|
const EVENT_KINDS = [
|
|
@@ -5299,7 +5719,10 @@ window.__ModuleLoader__.load({
|
|
|
5299
5719
|
const RequestDetail = makeRequestDetail(kit, StackedBar);
|
|
5300
5720
|
const EventList = makeEventList(kit);
|
|
5301
5721
|
const FileCard = makeFileCard(kit, settings);
|
|
5302
|
-
const
|
|
5722
|
+
const Donut = makeDonut(kit);
|
|
5723
|
+
const StatsContext = makeStatsContext(kit);
|
|
5724
|
+
const StatsTiming = makeStatsTiming(kit, Donut);
|
|
5725
|
+
const StatsTokens = makeStatsTokens(kit, Donut);
|
|
5303
5726
|
const PluginInfo = makePluginInfo(kit);
|
|
5304
5727
|
const ContextBrowser = makeContextBrowser(kit, StackedBar);
|
|
5305
5728
|
const AgentGraph = makeAgentGraph(ctx, kit);
|
|
@@ -5317,6 +5740,7 @@ window.__ModuleLoader__.load({
|
|
|
5317
5740
|
const [granularity, setGranularity] = React.useState(() => settings.defaultGranularity());
|
|
5318
5741
|
const [trendMode, setTrendMode] = React.useState(() => settings.defaultTrendMode());
|
|
5319
5742
|
const [focusTurn, setFocusTurn] = React.useState(null);
|
|
5743
|
+
const [jumpSeq, setJumpSeq] = React.useState(null);
|
|
5320
5744
|
const [hoverCat, setHoverCat] = React.useState(null);
|
|
5321
5745
|
const [pickedKinds, setPickedKinds] = React.useState([...EVENT_KINDS]);
|
|
5322
5746
|
const toggleKind = (k) => {
|
|
@@ -5359,6 +5783,25 @@ window.__ModuleLoader__.load({
|
|
|
5359
5783
|
const shownEvents = pickedKinds.length === EVENT_KINDS.length ? events : events.filter((e) => pickedKinds.includes(e.kind));
|
|
5360
5784
|
const displayRequests = React.useMemo(() => granularity === "turn" ? aggregateByTurn(requests) : requests, [requests, granularity]);
|
|
5361
5785
|
const markers = React.useMemo(() => attachMarkers(displayRequests, events), [displayRequests, events]);
|
|
5786
|
+
React.useEffect(() => {
|
|
5787
|
+
if (typeof sessionId !== "string" || sessionId === "") return;
|
|
5788
|
+
const seq = takeContextFocus(sessionId);
|
|
5789
|
+
if (seq !== null) setJumpSeq(seq);
|
|
5790
|
+
}, [sessionId]);
|
|
5791
|
+
React.useEffect(() => {
|
|
5792
|
+
if (jumpSeq === null || data === null) return;
|
|
5793
|
+
setJumpSeq(null);
|
|
5794
|
+
const target = jumpTargetOf(aggregateByTurn(requests), jumpSeq);
|
|
5795
|
+
if (target === null) return;
|
|
5796
|
+
setGranularity("turn");
|
|
5797
|
+
setSelectedSeq(target.seq);
|
|
5798
|
+
setFocusTurn(target.turn ?? 0);
|
|
5799
|
+
if (scrollerRef.current !== null) scrollerRef.current.scrollTop = 0;
|
|
5800
|
+
}, [
|
|
5801
|
+
jumpSeq,
|
|
5802
|
+
data,
|
|
5803
|
+
requests
|
|
5804
|
+
]);
|
|
5362
5805
|
const briefList = React.useMemo(() => data ? briefNodes(data) : [], [data]);
|
|
5363
5806
|
const replyTips = React.useMemo(() => replyTipsOf(briefList), [briefList]);
|
|
5364
5807
|
const convNodes = conversationNodesOf(props);
|
|
@@ -5451,20 +5894,23 @@ window.__ModuleLoader__.load({
|
|
|
5451
5894
|
break;
|
|
5452
5895
|
}
|
|
5453
5896
|
}
|
|
5897
|
+
const trendHoverCat = hoverCat !== null && hoverCat !== "free" ? hoverCat : null;
|
|
5454
5898
|
const localeSvc = ctx.get("locale");
|
|
5455
5899
|
const activeLocale = localeSvc !== void 0 && typeof localeSvc.getLocale === "function" ? localeSvc.getLocale().active : "en";
|
|
5456
5900
|
const subtitle = (data.model ?? "") + (data.provider ? " · " + data.provider : "");
|
|
5457
5901
|
return /* @__PURE__ */ React.createElement("div", {
|
|
5458
5902
|
className: "lc-root",
|
|
5459
5903
|
ref: rootRef
|
|
5460
|
-
}, /* @__PURE__ */ React.createElement("div", { className: "lc-cols lc-head" }, /* @__PURE__ */ React.createElement(
|
|
5904
|
+
}, /* @__PURE__ */ React.createElement("div", { className: "lc-cols lc-head" }, /* @__PURE__ */ React.createElement(StatsContext, {
|
|
5461
5905
|
requests,
|
|
5462
5906
|
events,
|
|
5463
|
-
usage,
|
|
5464
5907
|
toolCalls: data.toolCalls,
|
|
5465
5908
|
images: data.images,
|
|
5466
5909
|
cost: data.cost,
|
|
5467
5910
|
locale: activeLocale
|
|
5911
|
+
}), /* @__PURE__ */ React.createElement(StatsTokens, { usage }), /* @__PURE__ */ React.createElement(StatsTiming, {
|
|
5912
|
+
timing: data.timing ?? null,
|
|
5913
|
+
locale: activeLocale
|
|
5468
5914
|
}), /* @__PURE__ */ React.createElement(PluginInfo, null)), /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement("div", { className: "lc-col" }, /* @__PURE__ */ React.createElement(CurrentComposition, {
|
|
5469
5915
|
head,
|
|
5470
5916
|
subtitle,
|
|
@@ -5503,6 +5949,7 @@ window.__ModuleLoader__.load({
|
|
|
5503
5949
|
granularity,
|
|
5504
5950
|
mode: trendMode,
|
|
5505
5951
|
focusTurn,
|
|
5952
|
+
hoverCat: trendHoverCat,
|
|
5506
5953
|
onSelect: setSelectedSeq,
|
|
5507
5954
|
onHover: setHoveredSeq,
|
|
5508
5955
|
onHoverTurn: setHoverTurn,
|
|
@@ -5523,7 +5970,8 @@ window.__ModuleLoader__.load({
|
|
|
5523
5970
|
marker: activeReq !== null ? markerOf(activeReq) : void 0,
|
|
5524
5971
|
brief,
|
|
5525
5972
|
convOf,
|
|
5526
|
-
onLocate: locateNode
|
|
5973
|
+
onLocate: locateNode,
|
|
5974
|
+
hoverKey: trendHoverCat
|
|
5527
5975
|
})))), /* @__PURE__ */ React.createElement("div", { className: "lc-col lc-col-browser" }, /* @__PURE__ */ React.createElement(ContextBrowser, {
|
|
5528
5976
|
data,
|
|
5529
5977
|
headers,
|
|
@@ -5562,6 +6010,85 @@ window.__ModuleLoader__.load({
|
|
|
5562
6010
|
};
|
|
5563
6011
|
}
|
|
5564
6012
|
//#endregion
|
|
6013
|
+
//#region src/client/components/contextJump.tsx
|
|
6014
|
+
/**
|
|
6015
|
+
* The assistant-message action that jumps to the Context tab at this reply's
|
|
6016
|
+
* turn. Registered on the harness `conversation.chat.assistant-actions` seat
|
|
6017
|
+
* (the icon row beside copy/branch), it receives the finalized reply's durable
|
|
6018
|
+
* message id, resolves the matching assistant node's seq off whichever node
|
|
6019
|
+
* seat the running harness serves (`useChat` on 0.1.2+, the session snapshot
|
|
6020
|
+
* before it), records it in the viewFocus relay, and activates the Context
|
|
6021
|
+
* tab — where the jump pins the reply's TURN (see contextView's leg 2). An
|
|
6022
|
+
* unresolvable seq still switches tabs, just without a pin; a message id that
|
|
6023
|
+
* is not a plain string renders nothing at all.
|
|
6024
|
+
*/
|
|
6025
|
+
/**
|
|
6026
|
+
* The reply's request seq by its durable message id, or null when no served node proves the pair. Join/log nodes are untrusted input: each
|
|
6027
|
+
* element is isolated, so one hostile object that throws on property access is skipped — the jump keeps its pin, never its click.
|
|
6028
|
+
*/
|
|
6029
|
+
function seqOfMessageId(nodes, messageId) {
|
|
6030
|
+
for (const node of nodes ?? []) try {
|
|
6031
|
+
if (node.kind !== "assistant" || node.messageId !== messageId) continue;
|
|
6032
|
+
return typeof node.seq === "number" && Number.isFinite(node.seq) ? node.seq : null;
|
|
6033
|
+
} catch {
|
|
6034
|
+
continue;
|
|
6035
|
+
}
|
|
6036
|
+
return null;
|
|
6037
|
+
}
|
|
6038
|
+
/** The jump glyph: the plugin's mini stacked composition bars, same 16px outline family as the shipped row icons. */
|
|
6039
|
+
function JumpIcon() {
|
|
6040
|
+
return /* @__PURE__ */ React.createElement("svg", {
|
|
6041
|
+
width: "16",
|
|
6042
|
+
height: "16",
|
|
6043
|
+
viewBox: "0 0 16 16",
|
|
6044
|
+
fill: "none",
|
|
6045
|
+
"aria-hidden": "true"
|
|
6046
|
+
}, /* @__PURE__ */ React.createElement("rect", {
|
|
6047
|
+
x: "2",
|
|
6048
|
+
y: "3",
|
|
6049
|
+
width: "12",
|
|
6050
|
+
height: "2",
|
|
6051
|
+
rx: "1",
|
|
6052
|
+
fill: "currentColor"
|
|
6053
|
+
}), /* @__PURE__ */ React.createElement("rect", {
|
|
6054
|
+
x: "2",
|
|
6055
|
+
y: "7",
|
|
6056
|
+
width: "8.5",
|
|
6057
|
+
height: "2",
|
|
6058
|
+
rx: "1",
|
|
6059
|
+
fill: "currentColor"
|
|
6060
|
+
}), /* @__PURE__ */ React.createElement("rect", {
|
|
6061
|
+
x: "2",
|
|
6062
|
+
y: "11",
|
|
6063
|
+
width: "5.5",
|
|
6064
|
+
height: "2",
|
|
6065
|
+
rx: "1",
|
|
6066
|
+
fill: "currentColor"
|
|
6067
|
+
}));
|
|
6068
|
+
}
|
|
6069
|
+
function makeContextJumpButton(kit) {
|
|
6070
|
+
const { t } = kit;
|
|
6071
|
+
return function ContextJump(props) {
|
|
6072
|
+
const messageId = props.messageId;
|
|
6073
|
+
if (typeof messageId !== "string" || messageId === "") return null;
|
|
6074
|
+
const jump = () => {
|
|
6075
|
+
const seq = seqOfMessageId(conversationNodesOf(props), messageId);
|
|
6076
|
+
const sessionId = props.sessionId;
|
|
6077
|
+
if (seq !== null && typeof sessionId === "string" && sessionId !== "") requestContextFocus(sessionId, seq);
|
|
6078
|
+
activateContextTab(t("tab"));
|
|
6079
|
+
};
|
|
6080
|
+
return /* @__PURE__ */ React.createElement(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
6081
|
+
label: t("jump.title"),
|
|
6082
|
+
side: "bottom"
|
|
6083
|
+
}, /* @__PURE__ */ React.createElement("button", {
|
|
6084
|
+
type: "button",
|
|
6085
|
+
className: "lc-jump",
|
|
6086
|
+
"aria-label": t("jump.title"),
|
|
6087
|
+
onClick: jump
|
|
6088
|
+
}, /* @__PURE__ */ React.createElement(JumpIcon, null)));
|
|
6089
|
+
};
|
|
6090
|
+
}
|
|
6091
|
+
//#endregion
|
|
5565
6092
|
//#region src/client/viewkit.ts
|
|
5566
6093
|
function makeViewKit(t) {
|
|
5567
6094
|
const { eventLabel, eventAt } = makeEventText(t);
|
|
@@ -5569,6 +6096,8 @@ window.__ModuleLoader__.load({
|
|
|
5569
6096
|
t,
|
|
5570
6097
|
fmt,
|
|
5571
6098
|
fmtTime,
|
|
6099
|
+
fmtDuration: fmtDuration$1,
|
|
6100
|
+
fmtShare,
|
|
5572
6101
|
catLabel: (key) => t("cat." + key),
|
|
5573
6102
|
eventLabel,
|
|
5574
6103
|
eventAt
|
|
@@ -5576,7 +6105,7 @@ window.__ModuleLoader__.load({
|
|
|
5576
6105
|
}
|
|
5577
6106
|
//#endregion
|
|
5578
6107
|
//#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles.css.mjs
|
|
5579
|
-
const css = ".lc-root{box-sizing:border-box;height:100%;color:var(--dsw-alias-label-primary);padding:16px 20px 32px;font-size:13px;overflow-y:auto}.lc-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;margin-bottom:14px;padding:14px 16px}.lc-card-title{flex-wrap:wrap;align-items:baseline;gap:8px;margin-bottom:10px;font-weight:600;display:flex}.lc-card-title-text{white-space:nowrap;flex:none}.lc-stats{grid-template-columns:repeat(auto-fit,minmax(62px,1fr));gap:6px;display:grid}.lc-stat{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-direction:column;gap:2px;min-width:0;padding:6px;display:flex}.lc-stat-label{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:11px;font-weight:600;overflow:hidden}.lc-stat-value{color:var(--dsw-alias-label-primary);white-space:nowrap;text-overflow:ellipsis;text-align:center;font-size:14px;font-weight:600;overflow:hidden}.lc-stat-sub{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:11px;overflow:hidden}.lc-stat-tipped{position:relative}.lc-stat-q{text-align:center;width:11px;height:11px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);cursor:help;border-radius:50%;margin-left:4px;font-size:9px;font-style:normal;font-weight:700;line-height:11px;display:inline-block}.lc-stat-tipped:hover .lc-stat-q{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary)}.lc-stat-tip{z-index:6;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;max-width:280px;color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:6px 10px;font-size:12px;font-weight:400;line-height:1.5;transition:opacity .12s;position:absolute;top:calc(100% + 6px);left:0;box-shadow:0 2px 8px #0000002e}.lc-stat-tipped:hover .lc-stat-tip{opacity:1}.lc-stat-tip-prices{border-top:1px dashed var(--dsw-alias-border-l1);margin-top:5px;padding-top:5px;display:block}.lc-stat-tip-head{font-weight:600;display:block}.lc-stat-tip-row{margin-top:2px;display:block}.lc-stat-tip-model{color:var(--dsw-alias-label-primary)}.lc-card-sub{color:var(--dsw-alias-label-secondary);margin-left:auto;font-size:12px;font-weight:400}.lc-gran,.lc-kinds{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-trend-ctl{align-items:center;gap:6px;margin-left:auto;display:flex}.lc-trend-ctl .lc-gran{margin-left:0}.lc-gran-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-gran-btn:hover{color:var(--dsw-alias-label-primary)}.lc-gran-on,.lc-gran-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-settings-card{background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;transition:border-color .16s,background .16s}.lc-settings-card:hover{border-color:var(--dsw-alias-label-dimmed)}.lc-settings-open,.lc-settings-open:hover{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.lc-settings-head{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.lc-settings-headtext{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.lc-settings-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.lc-settings-desc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.lc-settings-chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.lc-settings-open .lc-settings-chevron{transform:rotate(180deg)}.lc-settings-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding:4px 0 12px}.lc-settings-row{align-items:center;gap:8px;padding:8px 0;display:flex}.lc-settings-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:14px}.lc-settings-select{background:var(--dsw-alias-bg-module-platform);height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.lc-settings-select:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.lc-settings-select:disabled{opacity:.5;cursor:default}.lc-settings-note{color:var(--dsw-alias-label-tertiary);margin:12px 0 4px;font-size:12px;line-height:1.5}.lc-overview-num{align-items:baseline;gap:6px;margin-bottom:8px;display:flex}.lc-overview-num>b{font-size:20px}.lc-overview-num span{color:var(--dsw-alias-label-secondary)}.lc-overview-pct{margin-left:auto;font-size:11px}.lc-overview-pct b{color:var(--dsw-alias-label-primary);margin-right:4px;font-size:20px}.lc-stacked-wrap{width:100%;position:relative}.lc-stacked{background:#8080802e;border-radius:5px;width:100%;display:flex;position:relative;overflow:hidden}.lc-occupied-box{border:2px solid var(--dsw-alias-label-tertiary);box-sizing:border-box;pointer-events:none;opacity:0;box-shadow:0 0 0 1px var(--dsw-alias-bg-layer-2);border-radius:5px;transition:opacity .12s;position:absolute;top:0;bottom:0;left:0}.lc-occupied-box-on{opacity:1}.lc-bar-tip{z-index:5;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:3px 8px;font-size:12px;transition:opacity .12s;position:absolute;bottom:calc(100% + 6px);transform:translate(-50%);box-shadow:0 2px 8px #0000002e}.lc-bar-tip-on{opacity:1}.lc-stacked>div{height:100%}.lc-stacked-seg{transition:filter .12s,opacity .12s}.lc-stacked-free{box-sizing:border-box;transition:box-shadow .12s,opacity .12s}.lc-stacked-seg-on{filter:brightness(1.18)}.lc-reserve{z-index:1;pointer-events:auto;cursor:help;background:repeating-linear-gradient(45deg, color-mix(in srgb, var(--dsw-alias-state-warn-primary) 24%, transparent) 0 5px, transparent 5px 10px);position:absolute;top:0;bottom:0}.lc-stacked-free-on{border:2px dashed var(--dsw-alias-label-secondary);border-radius:3px}.lc-stacked-dim .lc-stacked-seg{opacity:.35}.lc-stacked-dim .lc-stacked-seg-on{opacity:1}.lc-stacked-dim .lc-stacked-free{opacity:.35}.lc-stacked-dim .lc-stacked-free-on{opacity:1}.lc-legend{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:6px 14px;margin-top:10px;display:grid}.lc-chip{min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:5px;padding:1px 6px;transition:background-color .12s;display:flex}.lc-chip-label{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:600;overflow:hidden}.lc-chip-nums{white-space:nowrap;flex:none;align-items:baseline;gap:6px;margin-left:auto;display:inline-flex}.lc-chip i,.lc-detail-row i{border-radius:2px;width:8px;height:8px;display:inline-block}.lc-chip i{transition:box-shadow .12s}.lc-chip em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-chip-on{background:var(--dsw-alias-interactive-bg-hover);font-weight:600}.lc-chip-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-chartrow{align-items:stretch;gap:6px;display:flex}.lc-axis{box-sizing:border-box;width:40px;height:150px;color:var(--dsw-alias-label-secondary);padding-top:18px;font-size:11px;position:relative}.lc-axis span{line-height:1;position:absolute;right:0}.lc-axis-top{top:13px}.lc-axis-mid{top:69px}.lc-axis-bot{top:125px}.lc-chart-wrap{flex:1;min-width:0;position:relative}.lc-chart-scroll{scrollbar-gutter:stable;padding-bottom:var(--dsh-scrollbar-width,8px);overflow:auto hidden}.lc-chart{box-sizing:border-box;align-items:flex-end;gap:2px;width:max-content;min-width:100%;height:130px;padding-top:18px;display:flex;position:relative}.lc-grid{border-top:1px dashed var(--dsw-alias-border-l1);pointer-events:none;position:absolute;left:0;right:0}.lc-grid-top{top:18px}.lc-grid-mid{top:74px}.lc-grid-zero{border-top-style:solid;border-top-color:#80808080}.lc-bar{cursor:pointer;border-radius:2px;flex:none;align-items:flex-end;width:14px;height:100%;transition:opacity .12s,background-color .12s;display:flex;position:relative}.lc-chart-dim .lc-bar{opacity:.35}.lc-chart-dim .lc-bar-in-turn{opacity:1}.lc-chart-dim .lc-turn{opacity:.35}.lc-chart-dim .lc-turn-on{opacity:1}.lc-chart-tip{z-index:5;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);pointer-events:none;border-radius:6px;padding:3px 8px;font-size:12px;position:absolute;top:0;left:0;box-shadow:0 2px 8px #0000002e}.lc-bar:hover{background:var(--dsw-alias-bg-layer-2)}.lc-bar-hovered{outline:1px dashed var(--dsw-alias-brand-primary);outline-offset:1px}.lc-bar-selected{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.lc-bar-in-turn{background:#80808024}.lc-bar-stack{flex-direction:column-reverse;width:100%;display:flex}.lc-bar-stack>div{width:100%}.lc-bar-up,.lc-bar-down{width:100%;display:flex;position:absolute;left:0}.lc-bar-up{flex-direction:column-reverse}.lc-bar-down{flex-direction:column}.lc-bar-up>div,.lc-bar-down>div{width:100%}.lc-bar-marker{color:var(--dsw-alias-state-warn-primary);font-size:11px;position:absolute;top:-16px;left:50%;transform:translate(-50%)}.lc-turns{gap:2px;width:max-content;min-width:100%;margin-top:4px;display:flex}.lc-turn{box-sizing:border-box;text-align:center;color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;cursor:pointer;border-radius:3px;flex:none;height:14px;font-size:10px;font-weight:600;line-height:14px;transition:filter .12s,opacity .12s;overflow:hidden}.lc-turn-on{filter:brightness(1.35);color:var(--dsw-alias-label-primary)}.lc-turn-label{text-overflow:ellipsis;max-width:100%;display:inline-block;overflow:hidden}.lc-detail{border-top:1px solid var(--dsw-alias-border-l1);margin-top:12px;padding-top:12px}.lc-detail-head{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:6px 8px;margin-bottom:10px;display:flex}.lc-detail-head b{color:var(--dsw-alias-label-primary);font-size:13px}.lc-detail-time{font-variant-numeric:tabular-nums;white-space:nowrap;margin-left:auto;font-size:12px}.lc-detail-marker{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);border-radius:6px;padding:1px 7px;font-size:11px}.lc-detail-tag{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:4px;padding:0 6px;font-size:11px}.lc-detail-metric{font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--dsw-alias-label-primary);background:color-mix(in srgb, var(--dsw-alias-label-secondary) 14%, transparent);border-radius:6px;padding:2px 8px;font-size:12px;font-weight:600}.lc-detail-metric-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-detail-metric-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-detail-rows{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:4px 24px;margin-top:10px;display:grid}.lc-brief{flex-direction:column;gap:2px;min-height:76px;margin:-4px 0 10px;display:flex}.lc-brief-row{min-width:0;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;margin-left:-6px;margin-right:-6px;padding:3px 6px;font-family:inherit;font-size:12px;line-height:1.5;transition:background-color .12s;display:flex}.lc-brief-row-link:hover{background:var(--dsw-alias-interactive-bg-hover)}button.lc-brief-row-link{cursor:pointer}.lc-brief-tag{box-sizing:border-box;text-align:center;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:56px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;position:relative}.lc-brief-tip{z-index:6;white-space:normal;text-align:left;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;max-width:240px;color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:6px 10px;font-size:12px;font-weight:400;line-height:1.5;transition:opacity .12s;position:absolute;bottom:calc(100% + 6px);left:0;box-shadow:0 2px 8px #0000002e}.lc-brief-tag:hover .lc-brief-tip{opacity:1}.lc-brief-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-empty{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;overflow:hidden}.lc-brief-fact{box-sizing:border-box;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);max-width:160px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:0;max-width:260px;color:var(--dsw-alias-label-primary);border-radius:5px;align-items:center;gap:5px;padding:0 7px;font-size:12px;transition:background-color .12s;display:inline-flex;overflow:hidden}.lc-brief-chip-grow{flex:1;max-width:none}.lc-brief-chip-tag{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);max-width:120px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-chip-link{cursor:pointer}.lc-brief-chip-link:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-brief-more{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-detail-row{align-items:center;gap:8px;display:flex}.lc-detail-label{white-space:nowrap;min-width:70px;color:var(--dsw-alias-label-secondary)}.lc-bar-track{background:#8080802e;border-radius:3px;flex:1;height:5px;display:block;position:relative;overflow:hidden}.lc-bar-fill{border-radius:3px;height:100%;display:block}.lc-bar-zero{border-left:1px solid #80808073;position:absolute;top:0;bottom:0;left:50%}.lc-bar-fill-up,.lc-bar-fill-down{height:100%;display:block;position:absolute;top:0}.lc-bar-fill-up{border-radius:0 3px 3px 0;left:50%}.lc-bar-fill-down{border-radius:3px 0 0 3px;right:50%}.lc-detail-num{text-align:right;font-variant-numeric:tabular-nums;width:52px}.lc-detail-num-up{color:var(--dsw-alias-state-success-primary)}.lc-detail-num-down{color:var(--dsw-alias-state-error-primary)}.lc-detail-pct{text-align:right;width:34px;color:var(--dsw-alias-label-secondary)}.lc-cols{flex-wrap:wrap;gap:14px;margin-bottom:14px;display:flex}.lc-col{flex:1;min-width:280px}.lc-cols>.lc-card,.lc-col>.lc-card:last-child{margin-bottom:0}.lc-col-browser{flex-direction:column;display:flex}.lc-col-browser>.lc-card{flex:1}.lc-head>.lc-card:first-child{flex:7 1 0;min-width:360px}.lc-head>.lc-card:last-child{flex:3 1 0;min-width:220px}.lc-pi-grid{grid-template-columns:1fr;gap:8px;display:grid}.lc-pi-row{min-width:0;color:inherit;flex-direction:row;justify-content:space-between;align-items:baseline;gap:12px;text-decoration:none;display:flex}.lc-pi-row:hover .lc-pi-value{text-decoration:underline}.lc-pi-hint{text-decoration:none}.lc-pi-hint:hover{text-decoration:underline}.lc-pi-update{color:var(--dsw-alias-state-warn-primary);white-space:nowrap;margin-left:6px;font-size:11px}.lc-pi-label{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;flex:none;font-size:11px;font-weight:600;overflow:hidden}.lc-pi-value{min-width:0;color:var(--dsw-alias-label-primary);white-space:nowrap;text-overflow:ellipsis;text-align:right;font-size:13px;font-weight:600;overflow:hidden}.lc-events,.lc-fa-list{flex-direction:column;gap:2px;height:320px;display:flex;overflow-y:auto}.lc-event{align-items:center;gap:8px;padding:3px 0;display:flex}.lc-event-icon{text-align:center;width:18px;color:var(--dsw-alias-state-warn-primary)}.lc-event-icon.lc-event-inject{color:#a855f7}.lc-event-icon.lc-event-model{color:var(--dsw-alias-brand-primary)}.lc-event-icon.lc-event-mode{color:var(--dsw-alias-label-secondary)}.lc-kind{white-space:nowrap;border-radius:4px;flex:none;padding:1px 6px;font-size:10px;font-weight:600}.lc-kind-inject{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent);color:var(--dsw-alias-state-success-primary)}.lc-kind-compaction{background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent);color:var(--dsw-alias-state-error-primary)}.lc-kind-prune{color:#8b5cf6;background:#8b5cf626}.lc-kind-model{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 15%, transparent);color:var(--dsw-alias-brand-primary)}.lc-kind-mode{background:color-mix(in srgb, var(--dsw-alias-label-secondary) 15%, transparent);color:var(--dsw-alias-label-secondary)}.lc-event-label{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.lc-event-at{color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:none;font-size:11px}.lc-event-tokens{color:var(--dsw-alias-state-success-primary);white-space:nowrap;font-weight:600}.lc-event-tokens.lc-up{color:var(--dsw-alias-state-warn-primary)}.lc-event-time{color:var(--dsw-alias-label-secondary);font-size:12px}.lc-fa-ctl,.lc-br-toolctl{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:8px;display:flex}.lc-fa-ctl .lc-gran{margin-left:0}.lc-fa-n{opacity:.75;margin-left:4px;font-weight:700}.lc-fa-search,.lc-br-tool-search{min-width:80px;font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;outline:none;flex:1;padding:3px 8px;font-size:12px}.lc-fa-search:focus,.lc-br-tool-search:focus{border-color:var(--dsw-alias-label-dimmed)}.lc-fa-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:6px;font-size:12px;display:flex}.lc-fa-meta .lc-fa-sort{flex:none}.lc-fa-meta-delta{position:relative}.lc-fa-meta-tip{z-index:6;white-space:normal;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;max-width:260px;color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:6px 10px;font-size:12px;line-height:1.5;transition:opacity .12s;position:absolute;top:calc(100% + 6px);left:0;box-shadow:0 2px 8px #0000002e}.lc-fa-meta-delta:hover .lc-fa-meta-tip{opacity:1}.lc-fa-item{border:1px solid #0000;border-radius:8px;transition:background-color .12s,border-color .12s}.lc-fa-item-on{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l1)}.lc-fa-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:7px;align-items:center;gap:7px;padding:6px 8px;font-size:12px;transition:background-color .12s;display:flex}.lc-fa-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-fa-form{opacity:.85;flex:none;justify-content:center;align-items:center;width:20px;height:14px;font-size:11px;display:flex}.lc-fa-lang{border-radius:4px;justify-content:center;align-items:center;min-width:16px;height:13px;padding:0 2px;font-size:8px;font-weight:700;line-height:1;display:inline-flex}.lc-fa-row .lc-br-chev{margin-right:-2px}.lc-fa-path{word-break:break-all;flex:1;min-width:0}.lc-fa-file{cursor:pointer}.lc-fa-file:hover{text-decoration:underline}.lc-fa-path em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-fa-badge{font-variant-numeric:tabular-nums;white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:1px 7px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-badge i{background:currentColor;border-radius:50%;width:5px;height:5px;display:inline-block}.lc-fa-b-read{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent)}.lc-fa-b-write{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent)}.lc-fa-b-search{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent)}.lc-fa-chip-read,.lc-fa-chip-read:hover{color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write,.lc-fa-chip-write:hover{color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search,.lc-fa-chip-search:hover{color:var(--dsw-alias-state-warn-primary)}.lc-fa-chip-read.lc-gran-on,.lc-fa-chip-read.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write.lc-gran-on,.lc-fa-chip-write.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search.lc-gran-on,.lc-fa-chip-search.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);color:var(--dsw-alias-state-warn-primary)}.lc-fa-delta{font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;gap:5px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-up{color:var(--dsw-alias-state-success-primary)}.lc-fa-down{color:var(--dsw-alias-state-error-primary)}.lc-fa-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.lc-fa-ops{border-left:2px solid var(--dsw-alias-border-l1);flex-direction:column;gap:1px;margin:0 8px 8px 15px;padding:2px 0 2px 10px;display:flex}.lc-fa-op{min-width:0;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;background:0 0;border:0;border-radius:5px;align-items:center;gap:8px;padding:3px 6px;font-size:11px;transition:background-color .12s;display:flex}.lc-fa-op-link{cursor:pointer}.lc-fa-op-link:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-fa-op-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto}.lc-fa-op-tool{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:0 6px;font-size:11px}.lc-fa-op-detail{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary);flex:1;overflow:hidden}.lc-fa-read{color:var(--dsw-alias-brand-primary);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;font-size:11px;font-weight:600}.lc-empty{color:var(--dsw-alias-label-secondary);text-align:center;padding:18px 0}.lc-error{flex-direction:column;align-items:center;gap:8px;padding:40px 16px;display:flex}.lc-error-msg{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);overflow-wrap:anywhere;border-radius:6px;max-width:100%;padding:4px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.lc-error-retry{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:6px;padding:4px 14px;font-size:12px}.lc-error-retry:hover{border-color:var(--dsw-alias-label-primary)}.lc-foot{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:12px}.lc-modal-backdrop{z-index:200;background:#00000073;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.lc-modal-card{box-sizing:border-box;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);width:min(720px,100vw - 48px);max-height:min(82vh,760px);box-shadow:var(--dsw-shadow-lv3,0 12px 32px #0006);color:var(--dsw-alias-label-primary);border-radius:12px;padding:16px 18px 18px;font-size:13px;overflow-y:auto}.lc-modal-head{align-items:baseline;gap:8px;margin-bottom:12px;display:flex}.lc-modal-title{font-size:14px;font-weight:600}.lc-modal-close{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;margin-left:auto;padding:2px 6px;font-family:inherit;font-size:18px;line-height:1}.lc-modal-close:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}.lc-br-hint{color:var(--dsw-alias-label-secondary);white-space:nowrap;margin-left:auto;font-size:11px;font-weight:400}.lc-br-pick{font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;max-width:240px;padding:3px 6px;font-size:12px}.lc-br-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:6px 16px;margin-bottom:8px;display:flex}.lc-br-meta b{color:var(--dsw-alias-label-primary)}.lc-br-meta .lc-actual{color:var(--dsw-alias-state-success-primary)}.lc-br-note{color:var(--dsw-alias-label-secondary);margin-top:8px;font-size:12px}.lc-br-retry{color:var(--dsw-alias-brand-primary);font:inherit;cursor:pointer;text-underline-offset:2px;background:0 0;border:0;padding:0;font-size:12px;text-decoration:underline}.lc-br-retry:hover{filter:brightness(1.15)}.lc-br-cats{flex-direction:column;gap:4px;margin-top:10px;display:flex}.lc-br-cat{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:8px;overflow:hidden}.lc-br-cat-empty{opacity:.55}.lc-br-cat-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:0;align-items:center;gap:8px;padding:7px 10px;transition:background-color .12s;display:flex}.lc-br-cat-row:hover,.lc-br-cat-on{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-cat-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-br-cat-row i{border-radius:2px;flex:none;width:8px;height:8px;transition:box-shadow .12s;display:inline-block}.lc-br-cat-label{font-weight:600}.lc-br-cat-count{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:12px}.lc-br-count-grp{flex:1;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-chev{width:12px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:flex}.lc-br-chev:before{content:\"\";border-bottom:1px solid;border-right:1px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)}.lc-br-chev-on:before{transform:rotate(45deg)}.lc-br-tokens{color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-delta,.lc-br-tdelta{white-space:nowrap;border-radius:4px;flex:none;padding:0 5px;font-size:11px;font-weight:600}.lc-br-delta-up,.lc-br-tdelta-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-br-delta-down,.lc-br-tdelta-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-br-tokens-grp{flex:none;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-pct{text-align:right;width:36px;color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-body{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:2px;padding:4px 6px;display:flex}.lc-br-elem{border-radius:6px}.lc-br-elem-on{background:var(--dsw-alias-interactive-bg-active)}.lc-br-elem-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;padding:5px 6px;font-size:12px;transition:background-color .12s;display:flex}.lc-br-elem-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-err-dot{background:var(--dsw-alias-state-error-primary);width:6px;height:6px;box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);border-radius:50%;flex:none}.lc-br-tag{min-width:0;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);text-overflow:ellipsis;white-space:nowrap;border-radius:4px;max-width:220px;padding:0 6px;font-size:11px;overflow:hidden}.lc-br-tool-plugin{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);border-color:#0000;border-radius:6px;font-size:12px}.lc-br-preview{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-br-time{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-br-content{flex-direction:column;gap:6px;padding:2px 6px 8px 26px;display:flex}.lc-br-dim{color:var(--dsw-alias-label-secondary)}.lc-ts-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;min-width:0;overflow:hidden}.lc-ts-card-head{color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:8px;padding:6px 10px;font-size:11px;font-weight:600;display:flex}.lc-ts-card-head b{color:var(--dsw-alias-label-primary)}.lc-ts-call-name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px}.lc-ts-card-count{margin-left:auto}.lc-ts-card-right{align-items:center;gap:8px;margin-left:auto;display:inline-flex}.lc-ts-card-meta{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;font-weight:400}.lc-ts-call-state{white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:2px 7px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;font-weight:600;line-height:1;display:inline-flex}.lc-ts-call-state i{background:currentColor;border-radius:50%;flex:none;width:6px;height:6px}.lc-ts-call-ok{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent)}.lc-ts-call-err{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.lc-ts-desc-body{color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:320px;margin:0;padding:8px 10px;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-lines{counter-reset:lc-line}.lc-ts-line{padding-left:26px;display:block;position:relative}.lc-ts-line:before{content:counter(lc-line);counter-increment:lc-line;text-align:right;width:20px;color:var(--dsw-alias-label-tertiary);user-select:none;padding-right:6px;font-size:11px;position:absolute;left:0}.lc-ts-line:empty:after{content:\"\"}.lc-ts-param-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,140px) minmax(0,90px) 56px minmax(0,1fr);align-items:baseline;gap:2px 10px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-param-row:first-of-type{border-top:0}.lc-ts-param-name{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.lc-ts-param-type{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;overflow:hidden}.lc-ts-param-req{color:var(--dsw-alias-state-warn-primary);font-size:11px;font-weight:600}.lc-ts-param-req-off{color:var(--dsw-alias-label-secondary);font-size:11px}.lc-ts-param-desc{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;grid-column:1/-1;line-height:1.5}.lc-ts-params-empty{color:var(--dsw-alias-label-secondary);padding:8px 10px;font-size:12px}.lc-ts-arg-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,96px) 1fr;align-items:start;column-gap:12px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-arg-row:first-of-type{border-top:0}.lc-ts-arg-row .lc-ts-param-name{text-overflow:unset;white-space:normal;overflow-wrap:anywhere;overflow:visible}.lc-ts-arg-val{color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:200px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-json{flex-direction:column;gap:4px;display:flex}.lc-ts-json-toggle{color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-self:flex-start;padding:0;font-size:11px}.lc-ts-json-toggle:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.lc-rich-seg{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-rich-seg-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-rich-seg-btn:hover{color:var(--dsw-alias-label-primary)}.lc-rich-seg-on,.lc-rich-seg-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-ts-desc-md{color:var(--dsw-alias-label-primary);word-break:break-word;overflow-wrap:anywhere;scrollbar-width:thin;min-width:0;max-height:320px;padding:4px 10px;font-size:12px;line-height:1.55;overflow:hidden auto}.lc-ts-desc-md>div{font-size:13px;line-height:1.55}.lc-ts-desc-md div :is(h1,h2,h3,h4,h5,h6){margin:10px 0 4px;font-size:13px;font-weight:600}.lc-ts-desc-md div p{white-space:pre-line;margin:6px 0}.lc-ts-desc-md div p br{display:none}.lc-ts-desc-md div pre{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;margin:6px 0}.lc-ts-desc-md div :not(pre)>code{box-decoration-break:clone;padding:1px 5px;line-height:1.3;font-size:1em!important}.lc-ts-desc-md div table code{font-size:inherit}.lc-att-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:8px 10px;display:grid}.lc-att-item{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l1);width:100%;min-width:0;font:inherit;text-align:left;cursor:pointer;background:0 0;border-radius:8px;align-items:center;gap:8px;padding:6px;display:flex}.lc-att-item:hover{border-color:var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2))}.lc-att-thumb{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:6px;flex:none;justify-content:center;align-items:center;width:64px;height:64px;padding:0;display:flex;overflow:hidden}.lc-att-thumb img{object-fit:cover;width:100%;height:100%;display:block}.lc-att-ph,.lc-att-err{color:var(--dsw-alias-label-secondary);text-align:center;padding:2px;font-size:10px}.lc-att-meta{flex-direction:column;gap:2px;min-width:0;display:flex}.lc-att-name{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;word-break:break-word;font-size:12px;line-height:1.3}.lc-att-row{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:11px}.lc-att-row-label{min-width:3.2em;font-weight:400;display:inline-block}.lc-att-lightbox{z-index:1000;place-items:center;padding:40px;display:grid;position:fixed;inset:0}.lc-att-lightbox-mask{background:var(--dsw-alias-bg-mask-1,#00000073);backdrop-filter:var(--dsw-mask-blur,blur(2px));position:absolute;inset:0}.lc-att-lightbox-img{object-fit:contain;background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));max-width:min(100%,1600px);max-height:calc(100vh - 80px);box-shadow:var(--dsw-shadow-lv3,0 12px 32px #0006);border-radius:12px;position:relative}.lc-att-lightbox-close{z-index:1;border:1px solid var(--dsw-alias-border-l2-darkmode-thin,var(--dsw-alias-border-l1));background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));width:36px;height:36px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:999px;place-items:center;padding:0;display:grid;position:fixed;top:20px;right:20px}[data-conversation-scroll]:has(.lc-root)>[data-composer-seat]:not(:has([data-approval-key],[data-question-key],[data-plan-review-key])){display:none}.lc-agents-chips{flex-wrap:wrap;gap:6px;margin-bottom:10px;display:flex}.lc-agents-chip{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;border-radius:999px;padding:2px 8px;font-size:11px}.lc-agents-chip-on{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent)}.lc-agents-stage{margin:0 -4px;padding:0 4px;overflow-x:auto}.lc-agents-svg{max-width:none;margin:0 auto;display:block}.lc-agents-link{stroke-width:1.5px;stroke-opacity:.45}.lc-agents-link-live{stroke-opacity:.85}.lc-agents-flow{stroke-width:2px;stroke-linecap:round;stroke-dasharray:2 7;animation:.9s linear infinite lc-agent-flow}@keyframes lc-agent-flow{to{stroke-dashoffset:-9px}}.lc-agent-node{outline:none}.lc-agent-clickable{cursor:pointer}.lc-agent-halo{fill:#0000;transition:fill .12s}.lc-agent-hover .lc-agent-halo,.lc-agent-node:focus-visible .lc-agent-halo{fill:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2))}.lc-agent-self .lc-agent-halo{fill:var(--dsw-alias-bg-layer-2)}.lc-agent-running .lc-agent-halo{fill:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent);animation:1.8s ease-in-out infinite lc-agent-glow}.lc-agent-done .lc-agent-halo{fill:color-mix(in srgb, var(--dsw-alias-state-success-primary) 7%, transparent)}@keyframes lc-agent-glow{0%,to{opacity:1}50%{opacity:.4}}.lc-agent-track{fill:var(--dsw-alias-bg-layer-1);stroke:var(--dsw-alias-border-l1);stroke-width:1.5px}.lc-agent-seg{fill:none;stroke-width:9px;transition:stroke-dasharray .3s,stroke-dashoffset .3s}.lc-agent-free{stroke:color-mix(in srgb, var(--dsw-alias-label-secondary) 18%, transparent)}.lc-agent-pct{fill:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;pointer-events:none;font-size:11px;font-weight:600}.lc-agent-caption{text-align:center;pointer-events:none;width:100%;line-height:1.25}.lc-agent-label{color:var(--dsw-alias-label-primary);overflow-wrap:break-word;-webkit-line-clamp:3;-webkit-box-orient:vertical;font-size:11px;display:-webkit-box;overflow:hidden}.lc-agent-tokens{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:10px}.lc-agents-solo{padding:4px 0 10px}.lc-agents-inspector{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:8px;flex-wrap:wrap;align-items:baseline;gap:4px 8px;min-width:0;margin-top:10px;padding:7px 10px;font-size:12px;display:flex}.lc-agents-inspector-name{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere}.lc-agents-badge{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 6px;font-size:10px}.lc-agent-self-badge{vertical-align:1px;margin-left:5px}.lc-agents-badge-on{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent)}.lc-agents-inspector-stats{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.lc-agents-inspector-open{color:var(--dsw-alias-brand-primary,#3b82f6);flex:none;margin-left:auto}.lc-agents-legend{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:4px 14px;margin-top:8px;font-size:11px;display:flex}.lc-agents-legend-item{align-items:center;gap:5px;display:inline-flex}.lc-agents-legend-item i{border-radius:2px;width:8px;height:8px}.lc-agents-legend-free{background:color-mix(in srgb, var(--dsw-alias-label-secondary) 18%, transparent)}.lc-agents-legend-edge{border-top:2px dashed var(--dsw-alias-label-secondary);border-radius:0!important;width:14px!important;height:0!important}";
|
|
6108
|
+
const css = ".lc-root{box-sizing:border-box;height:100%;color:var(--dsw-alias-label-primary);padding:16px 20px 32px;font-size:13px;overflow-y:auto}.lc-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;margin-bottom:14px;padding:14px 16px}.lc-card-title{flex-wrap:wrap;align-items:baseline;gap:8px;margin-bottom:10px;font-weight:600;display:flex}.lc-card-title-text{white-space:nowrap;flex:none}.lc-stats{grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;display:grid}.lc-stat{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;flex-direction:column;gap:2px;min-width:0;padding:6px;display:flex}.lc-stats .lc-stat{padding:6px 3px}.lc-stats .lc-stat-q{margin:0;position:absolute;top:3px;right:4px}.lc-stat-label{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:11px;font-weight:600;overflow:hidden}.lc-stat-value{color:var(--dsw-alias-label-primary);white-space:nowrap;text-overflow:ellipsis;text-align:center;font-size:14px;font-weight:600;overflow:hidden}.lc-stat-sub{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:11px;overflow:hidden}.lc-stat-tipped{position:relative}.lc-stat-q{text-align:center;width:11px;height:11px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);cursor:help;border-radius:50%;margin-left:4px;font-size:9px;font-style:normal;font-weight:700;line-height:11px;display:inline-block}.lc-stat-tipped:hover .lc-stat-q{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary)}.lc-stat-tip{z-index:6;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;max-width:280px;color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:6px 10px;font-size:12px;font-weight:400;line-height:1.5;transition:opacity .12s;position:absolute;top:calc(100% + 6px);left:0;box-shadow:0 2px 8px #0000002e}.lc-stat-tipped:hover .lc-stat-tip{opacity:1}.lc-stat-tip-prices{border-top:1px dashed var(--dsw-alias-border-l1);margin-top:5px;padding-top:5px;display:block}.lc-stat-tip-head{font-weight:600;display:block}.lc-stat-tip-row{margin-top:2px;display:block}.lc-stat-tip-model{color:var(--dsw-alias-label-primary)}.lc-card-sub{color:var(--dsw-alias-label-secondary);margin-left:auto;font-size:12px;font-weight:400}.lc-gran,.lc-kinds{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-trend-ctl{align-items:center;gap:6px;margin-left:auto;display:flex}.lc-trend-ctl .lc-gran{margin-left:0}.lc-gran-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-gran-btn:hover{color:var(--dsw-alias-label-primary)}.lc-gran-on,.lc-gran-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-jump{width:calc(28px + var(--dsh-content-font-delta,0px));height:calc(28px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:28px;justify-content:center;align-items:center;padding:6px;display:inline-flex}.lc-jump svg{width:calc(16px + var(--dsh-content-font-delta,0px));height:calc(16px + var(--dsh-content-font-delta,0px))}.lc-jump:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.lc-settings-card{background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;transition:border-color .16s,background .16s}.lc-settings-card:hover{border-color:var(--dsw-alias-label-dimmed)}.lc-settings-open,.lc-settings-open:hover{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.lc-settings-head{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.lc-settings-headtext{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.lc-settings-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.lc-settings-desc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.lc-settings-chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.lc-settings-open .lc-settings-chevron{transform:rotate(180deg)}.lc-settings-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding:4px 0 12px}.lc-settings-row{align-items:center;gap:8px;padding:8px 0;display:flex}.lc-settings-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:14px}.lc-settings-select{background:var(--dsw-alias-bg-module-platform);height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.lc-settings-select:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.lc-settings-select:disabled{opacity:.5;cursor:default}.lc-settings-note{color:var(--dsw-alias-label-tertiary);margin:12px 0 4px;font-size:12px;line-height:1.5}.lc-overview-num{align-items:baseline;gap:6px;margin-bottom:8px;display:flex}.lc-overview-num>b{font-size:20px}.lc-overview-num span{color:var(--dsw-alias-label-secondary)}.lc-overview-pct{margin-left:auto;font-size:11px}.lc-overview-pct b{color:var(--dsw-alias-label-primary);margin-right:4px;font-size:20px}.lc-stacked-wrap{width:100%;position:relative}.lc-stacked{background:#8080802e;border-radius:5px;width:100%;display:flex;position:relative;overflow:hidden}.lc-occupied-box{border:2px solid var(--dsw-alias-label-tertiary);box-sizing:border-box;pointer-events:none;opacity:0;box-shadow:0 0 0 1px var(--dsw-alias-bg-layer-2);border-radius:5px;transition:opacity .12s;position:absolute;top:0;bottom:0;left:0}.lc-occupied-box-on{opacity:1}.lc-bar-tip{z-index:5;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:3px 8px;font-size:12px;transition:opacity .12s;position:absolute;bottom:calc(100% + 6px);transform:translate(-50%);box-shadow:0 2px 8px #0000002e}.lc-bar-tip-on{opacity:1}.lc-stacked>div{height:100%}.lc-stacked-seg{transition:filter .12s,opacity .12s}.lc-stacked-free{box-sizing:border-box;transition:box-shadow .12s,opacity .12s}.lc-stacked-seg-on{filter:brightness(1.18)}.lc-reserve{z-index:1;pointer-events:auto;cursor:help;background:repeating-linear-gradient(45deg, color-mix(in srgb, var(--dsw-alias-state-warn-primary) 24%, transparent) 0 5px, transparent 5px 10px);position:absolute;top:0;bottom:0}.lc-stacked-free-on{border:2px dashed var(--dsw-alias-label-secondary);border-radius:3px}.lc-stacked-dim .lc-stacked-seg{opacity:.35}.lc-stacked-dim .lc-stacked-seg-on{opacity:1}.lc-stacked-dim .lc-stacked-free{opacity:.35}.lc-stacked-dim .lc-stacked-free-on{opacity:1}.lc-legend{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:6px 14px;margin-top:10px;display:grid}.lc-chip{min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:5px;padding:1px 6px;transition:background-color .12s;display:flex}.lc-chip-label{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:600;overflow:hidden}.lc-chip-nums{white-space:nowrap;flex:none;align-items:baseline;gap:6px;margin-left:auto;display:inline-flex}.lc-chip i,.lc-detail-row i{border-radius:2px;width:8px;height:8px;display:inline-block}.lc-chip i{transition:box-shadow .12s}.lc-chip em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-chip-on{background:var(--dsw-alias-interactive-bg-hover);font-weight:600}.lc-chip-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-chartrow{align-items:stretch;gap:6px;display:flex}.lc-axis{box-sizing:border-box;width:40px;height:150px;color:var(--dsw-alias-label-secondary);padding-top:18px;font-size:11px;position:relative}.lc-axis span{line-height:1;position:absolute;right:0}.lc-axis-top{top:13px}.lc-axis-mid{top:69px}.lc-axis-bot{top:125px}.lc-chart-wrap{flex:1;min-width:0;position:relative}.lc-chart-scroll{scrollbar-gutter:stable;padding-bottom:var(--dsh-scrollbar-width,8px);overflow:auto hidden}.lc-chart{box-sizing:border-box;align-items:flex-end;gap:2px;width:max-content;min-width:100%;height:130px;padding-top:18px;display:flex;position:relative}.lc-grid{border-top:1px dashed var(--dsw-alias-border-l1);pointer-events:none;position:absolute;left:0;right:0}.lc-grid-top{top:18px}.lc-grid-mid{top:74px}.lc-grid-zero{border-top-style:solid;border-top-color:#80808080}.lc-bar{cursor:pointer;border-radius:2px;flex:none;align-items:flex-end;width:14px;height:100%;transition:opacity .12s,background-color .12s;display:flex;position:relative}.lc-chart-dim .lc-bar{opacity:.35}.lc-chart-dim .lc-bar-in-turn{opacity:1}.lc-chart-dim .lc-turn{opacity:.35}.lc-chart-dim .lc-turn-on{opacity:1}.lc-chart-tip{z-index:5;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);pointer-events:none;border-radius:6px;padding:3px 8px;font-size:12px;position:absolute;top:0;left:0;box-shadow:0 2px 8px #0000002e}.lc-bar:hover{background:var(--dsw-alias-bg-layer-2)}.lc-bar-hovered{outline:1px dashed var(--dsw-alias-brand-primary);outline-offset:1px}.lc-bar-selected{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.lc-bar-in-turn{background:#80808024}.lc-bar-stack{flex-direction:column-reverse;width:100%;display:flex}.lc-bar-stack>div{width:100%}.lc-bar-up,.lc-bar-down{width:100%;display:flex;position:absolute;left:0}.lc-bar-up{flex-direction:column-reverse}.lc-bar-down{flex-direction:column}.lc-bar-up>div,.lc-bar-down>div{width:100%}.lc-cat-seg{transition:filter .12s,opacity .12s}.lc-chart[data-catdim] .lc-cat-seg{opacity:.35}.lc-chart[data-catdim=system] .lc-cat-seg[data-cat=system],.lc-chart[data-catdim=tools] .lc-cat-seg[data-cat=tools],.lc-chart[data-catdim=user] .lc-cat-seg[data-cat=user],.lc-chart[data-catdim=inject] .lc-cat-seg[data-cat=inject],.lc-chart[data-catdim=assistant] .lc-cat-seg[data-cat=assistant],.lc-chart[data-catdim=tool] .lc-cat-seg[data-cat=tool]{opacity:1;filter:brightness(1.18)}.lc-bar-marker{color:var(--dsw-alias-state-warn-primary);font-size:11px;position:absolute;top:-16px;left:50%;transform:translate(-50%)}.lc-turns{gap:2px;width:max-content;min-width:100%;margin-top:4px;display:flex}.lc-turn{box-sizing:border-box;text-align:center;color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;cursor:pointer;border-radius:3px;flex:none;height:14px;font-size:10px;font-weight:600;line-height:14px;transition:filter .12s,opacity .12s;overflow:hidden}.lc-turn-on{filter:brightness(1.35);color:var(--dsw-alias-label-primary)}.lc-turn-label{text-overflow:ellipsis;max-width:100%;display:inline-block;overflow:hidden}.lc-detail{border-top:1px solid var(--dsw-alias-border-l1);margin-top:12px;padding-top:12px}.lc-detail-head{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:6px 8px;margin-bottom:10px;display:flex}.lc-detail-head b{color:var(--dsw-alias-label-primary);font-size:13px}.lc-detail-time{font-variant-numeric:tabular-nums;white-space:nowrap;margin-left:auto;font-size:12px}.lc-detail-marker{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);border-radius:6px;padding:1px 7px;font-size:11px}.lc-detail-tag{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:4px;padding:0 6px;font-size:11px}.lc-detail-metric{font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--dsw-alias-label-primary);background:color-mix(in srgb, var(--dsw-alias-label-secondary) 14%, transparent);border-radius:6px;padding:2px 8px;font-size:12px;font-weight:600}.lc-detail-metric-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-detail-metric-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-detail-rows{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:4px 24px;margin-top:10px;display:grid}.lc-brief{flex-direction:column;gap:2px;min-height:76px;margin:-4px 0 10px;display:flex}.lc-brief-row{min-width:0;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;margin-left:-6px;margin-right:-6px;padding:3px 6px;font-family:inherit;font-size:12px;line-height:1.5;transition:background-color .12s;display:flex}.lc-brief-row-link:hover{background:var(--dsw-alias-interactive-bg-hover)}button.lc-brief-row-link{cursor:pointer}.lc-brief-tag{box-sizing:border-box;text-align:center;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:56px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;position:relative}.lc-brief-tip{z-index:6;white-space:normal;text-align:left;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;max-width:240px;color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:6px 10px;font-size:12px;font-weight:400;line-height:1.5;transition:opacity .12s;position:absolute;bottom:calc(100% + 6px);left:0;box-shadow:0 2px 8px #0000002e}.lc-brief-tag:hover .lc-brief-tip{opacity:1}.lc-brief-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-empty{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;overflow:hidden}.lc-brief-fact{box-sizing:border-box;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);max-width:160px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:0;max-width:260px;color:var(--dsw-alias-label-primary);border-radius:5px;align-items:center;gap:5px;padding:0 7px;font-size:12px;transition:background-color .12s;display:inline-flex;overflow:hidden}.lc-brief-chip-grow{flex:1;max-width:none}.lc-brief-chip-tag{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);max-width:120px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-chip-link{cursor:pointer}.lc-brief-chip-link:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-brief-more{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-detail-row{border-radius:4px;align-items:center;gap:8px;margin:-1px -4px;padding:1px 4px;transition:background-color .12s;display:flex}.lc-detail-row i{transition:box-shadow .12s}.lc-detail-row-on{background:var(--dsw-alias-interactive-bg-hover)}.lc-detail-row-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-detail-row-on .lc-detail-label{font-weight:600}.lc-detail-label{white-space:nowrap;min-width:70px;color:var(--dsw-alias-label-secondary)}.lc-bar-track{background:#8080802e;border-radius:3px;flex:1;height:5px;display:block;position:relative;overflow:hidden}.lc-bar-fill{border-radius:3px;height:100%;display:block}.lc-bar-zero{border-left:1px solid #80808073;position:absolute;top:0;bottom:0;left:50%}.lc-bar-fill-up,.lc-bar-fill-down{height:100%;display:block;position:absolute;top:0}.lc-bar-fill-up{border-radius:0 3px 3px 0;left:50%}.lc-bar-fill-down{border-radius:3px 0 0 3px;right:50%}.lc-detail-num{text-align:right;font-variant-numeric:tabular-nums;width:52px}.lc-detail-num-up{color:var(--dsw-alias-state-success-primary)}.lc-detail-num-down{color:var(--dsw-alias-state-error-primary)}.lc-detail-pct{text-align:right;width:34px;color:var(--dsw-alias-label-secondary)}.lc-cols{flex-wrap:wrap;gap:14px;margin-bottom:14px;display:flex}.lc-col{flex:1;min-width:280px}.lc-cols>.lc-card,.lc-col>.lc-card:last-child{margin-bottom:0}.lc-col-browser{flex-direction:column;display:flex}.lc-col-browser>.lc-card{flex:1}.lc-head>.lc-card{flex:1 1 0;min-width:0}.lc-head>.lc-card:first-child{flex-direction:column;display:flex}.lc-head>.lc-card:first-child .lc-stats{flex:1;align-content:stretch}.lc-head>.lc-card:first-child .lc-stat{justify-content:center}.lc-stat-head{color:var(--dsw-alias-label-secondary);margin:12px 0 8px;font-size:11px;font-weight:600}.lc-donut-row{justify-content:flex-start;align-items:center;gap:12px;min-width:0;display:flex}.lc-col-donut{flex-direction:column;display:flex}.lc-col-donut .lc-donut-row{flex:1}.lc-donut-row .lc-sl{flex:auto}.lc-donut{flex:none;position:relative}.lc-donut svg{display:block}.lc-donut-track{stroke:#8080802e}.lc-donut-center{pointer-events:none;text-align:center;box-sizing:border-box;flex-direction:column;justify-content:center;align-items:center;gap:1px;padding:0 7px;display:flex;position:absolute;inset:0}.lc-donut-center b{white-space:nowrap;text-overflow:ellipsis;max-width:100%;line-height:1.15;overflow:hidden}.lc-donut-center span{color:var(--dsw-alias-label-secondary);white-space:nowrap}.lc-sl{flex-direction:column;gap:5px;min-width:0;display:flex}.lc-sl-row{align-items:baseline;gap:6px;min-width:0;font-size:12px;display:flex}.lc-sl-dot{border-radius:2px;flex:none;align-self:flex-start;width:8px;height:8px;margin-top:2px}.lc-sl-label{flex:0 auto;min-width:80px;line-height:1.25;overflow:hidden}.lc-sl-count{text-align:right;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;text-overflow:ellipsis;flex:auto;overflow:hidden}.lc-sl-pct{text-align:right;font-variant-numeric:tabular-nums;flex:none;min-width:30px;font-weight:700}.lc-pi-grid{grid-template-columns:1fr;gap:8px;display:grid}.lc-pi-row-btn{appearance:none;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;width:100%;padding:0}.lc-pi-row{min-width:0;color:inherit;flex-direction:row;justify-content:space-between;align-items:baseline;gap:12px;text-decoration:none;display:flex}.lc-pi-row:hover .lc-pi-value{text-decoration:underline}.lc-pi-hint{text-decoration:none}.lc-pi-hint:hover{text-decoration:underline}.lc-pi-update{color:var(--dsw-alias-state-warn-primary);white-space:nowrap;margin-left:6px;font-size:11px}.lc-pi-label{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;flex:none;font-size:11px;font-weight:600;overflow:hidden}.lc-pi-value{min-width:0;color:var(--dsw-alias-label-primary);white-space:nowrap;text-overflow:ellipsis;text-align:right;font-size:13px;font-weight:600;overflow:hidden}.lc-pi-row-btn .lc-pi-value{font-weight:400}.lc-events,.lc-fa-list{flex-direction:column;gap:2px;height:320px;display:flex;overflow-y:auto}.lc-event{align-items:center;gap:8px;padding:3px 0;display:flex}.lc-event-icon{text-align:center;width:18px;color:var(--dsw-alias-state-warn-primary)}.lc-event-icon.lc-event-inject{color:#a855f7}.lc-event-icon.lc-event-model{color:var(--dsw-alias-brand-primary)}.lc-event-icon.lc-event-mode{color:var(--dsw-alias-label-secondary)}.lc-kind{white-space:nowrap;border-radius:4px;flex:none;padding:1px 6px;font-size:10px;font-weight:600}.lc-kind-inject{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent);color:var(--dsw-alias-state-success-primary)}.lc-kind-compaction{background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent);color:var(--dsw-alias-state-error-primary)}.lc-kind-prune{color:#8b5cf6;background:#8b5cf626}.lc-kind-model{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 15%, transparent);color:var(--dsw-alias-brand-primary)}.lc-kind-mode{background:color-mix(in srgb, var(--dsw-alias-label-secondary) 15%, transparent);color:var(--dsw-alias-label-secondary)}.lc-event-label{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.lc-event-at{color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:none;font-size:11px}.lc-event-tokens{color:var(--dsw-alias-state-success-primary);white-space:nowrap;font-weight:600}.lc-event-tokens.lc-up{color:var(--dsw-alias-state-warn-primary)}.lc-event-time{color:var(--dsw-alias-label-secondary);font-size:12px}.lc-fa-ctl,.lc-br-toolctl{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:8px;display:flex}.lc-fa-ctl .lc-gran{margin-left:0}.lc-fa-n{opacity:.75;margin-left:4px;font-weight:700}.lc-fa-search,.lc-br-tool-search{min-width:80px;font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;outline:none;flex:1;padding:3px 8px;font-size:12px}.lc-fa-search:focus,.lc-br-tool-search:focus{border-color:var(--dsw-alias-label-dimmed)}.lc-fa-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:6px;font-size:12px;display:flex}.lc-fa-meta .lc-fa-sort{flex:none}.lc-fa-meta-delta{position:relative}.lc-fa-meta-tip{z-index:6;white-space:normal;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;max-width:260px;color:var(--dsw-alias-label-primary);pointer-events:none;opacity:0;border-radius:6px;padding:6px 10px;font-size:12px;line-height:1.5;transition:opacity .12s;position:absolute;top:calc(100% + 6px);left:0;box-shadow:0 2px 8px #0000002e}.lc-fa-meta-delta:hover .lc-fa-meta-tip{opacity:1}.lc-fa-item{border:1px solid #0000;border-radius:8px;transition:background-color .12s,border-color .12s}.lc-fa-item-on{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l2)}.lc-fa-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:7px;align-items:center;gap:7px;padding:6px 8px;font-size:12px;transition:background-color .12s;display:flex}.lc-fa-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-fa-form{opacity:.85;flex:none;justify-content:center;align-items:center;width:20px;height:14px;font-size:11px;display:flex}.lc-fa-lang{border-radius:4px;justify-content:center;align-items:center;min-width:16px;height:13px;padding:0 2px;font-size:8px;font-weight:700;line-height:1;display:inline-flex}.lc-fa-row .lc-br-chev{margin-right:-2px}.lc-fa-path{word-break:break-all;flex:1;min-width:0}.lc-fa-file{cursor:pointer}.lc-fa-file:hover{text-decoration:underline}.lc-fa-path em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-fa-badge{font-variant-numeric:tabular-nums;white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:1px 7px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-badge i{background:currentColor;border-radius:50%;width:5px;height:5px;display:inline-block}.lc-fa-b-read{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent)}.lc-fa-b-write{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent)}.lc-fa-b-search{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent)}.lc-fa-chip-read,.lc-fa-chip-read:hover{color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write,.lc-fa-chip-write:hover{color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search,.lc-fa-chip-search:hover{color:var(--dsw-alias-state-warn-primary)}.lc-fa-chip-read.lc-gran-on,.lc-fa-chip-read.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write.lc-gran-on,.lc-fa-chip-write.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search.lc-gran-on,.lc-fa-chip-search.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);color:var(--dsw-alias-state-warn-primary)}.lc-fa-delta{font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;gap:5px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-up{color:var(--dsw-alias-state-success-primary)}.lc-fa-down{color:var(--dsw-alias-state-error-primary)}.lc-fa-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.lc-fa-ops{border-left:2px solid var(--dsw-alias-border-l1);flex-direction:column;gap:1px;margin:0 8px 8px 15px;padding:2px 0 2px 10px;display:flex}.lc-fa-op{min-width:0;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;background:0 0;border:0;border-radius:5px;align-items:center;gap:8px;padding:3px 6px;font-size:11px;transition:background-color .12s;display:flex}.lc-fa-op-link{cursor:pointer}.lc-fa-op-link:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-fa-op-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto}.lc-fa-op-tool{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:0 6px;font-size:11px}.lc-fa-op-detail{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary);flex:1;overflow:hidden}.lc-fa-read{color:var(--dsw-alias-brand-primary);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;font-size:11px;font-weight:600}.lc-empty{color:var(--dsw-alias-label-secondary);text-align:center;padding:18px 0}.lc-error{flex-direction:column;align-items:center;gap:8px;padding:40px 16px;display:flex}.lc-error-msg{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);overflow-wrap:anywhere;border-radius:6px;max-width:100%;padding:4px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.lc-error-retry{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:6px;padding:4px 14px;font-size:12px}.lc-error-retry:hover{border-color:var(--dsw-alias-label-primary)}.lc-foot{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:12px}.lc-modal-backdrop{z-index:200;background:#00000073;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.lc-modal-card{box-sizing:border-box;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);width:min(720px,100vw - 48px);max-height:min(82vh,760px);box-shadow:var(--dsw-shadow-lv3,0 12px 32px #0006);color:var(--dsw-alias-label-primary);border-radius:12px;padding:16px 18px 18px;font-size:13px;overflow-y:auto}.lc-modal-head{align-items:baseline;gap:8px;margin-bottom:12px;display:flex}.lc-modal-title{font-size:14px;font-weight:600}.lc-modal-close{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;margin-left:auto;padding:2px 6px;font-family:inherit;font-size:18px;line-height:1}.lc-modal-close:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}.lc-br-hint{color:var(--dsw-alias-label-secondary);white-space:nowrap;margin-left:auto;font-size:11px;font-weight:400}.lc-br-pick{font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;max-width:240px;padding:3px 6px;font-size:12px}.lc-br-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:6px 16px;margin-bottom:8px;display:flex}.lc-br-meta b{color:var(--dsw-alias-label-primary)}.lc-br-meta .lc-actual{color:var(--dsw-alias-state-success-primary)}.lc-br-note{color:var(--dsw-alias-label-secondary);margin-top:8px;font-size:12px}.lc-br-retry{color:var(--dsw-alias-brand-primary);font:inherit;cursor:pointer;text-underline-offset:2px;background:0 0;border:0;padding:0;font-size:12px;text-decoration:underline}.lc-br-retry:hover{filter:brightness(1.15)}.lc-br-cats{flex-direction:column;gap:4px;margin-top:10px;display:flex}.lc-br-cat{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:8px;overflow:hidden}.lc-br-cat-empty{opacity:.55}.lc-br-cat-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:0;align-items:center;gap:8px;padding:7px 10px;transition:background-color .12s;display:flex}.lc-br-cat-row:hover,.lc-br-cat-on{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-cat-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-br-cat-row i{border-radius:2px;flex:none;width:8px;height:8px;transition:box-shadow .12s;display:inline-block}.lc-br-cat-label{font-weight:600}.lc-br-cat-count{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:12px}.lc-br-count-grp{flex:1;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-chev{width:12px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:flex}.lc-br-chev:before{content:\"\";border-bottom:1px solid;border-right:1px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)}.lc-br-chev-on:before{transform:rotate(45deg)}.lc-br-tokens{color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-delta,.lc-br-tdelta{white-space:nowrap;border-radius:4px;flex:none;padding:0 5px;font-size:11px;font-weight:600}.lc-br-delta-up,.lc-br-tdelta-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-br-delta-down,.lc-br-tdelta-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-br-tokens-grp{flex:none;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-pct{text-align:right;width:36px;color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-body{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:2px;padding:4px 6px;display:flex}.lc-br-elem{border-radius:6px}.lc-br-elem-on{background:var(--dsw-alias-interactive-bg-active)}.lc-br-elem-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;padding:5px 6px;font-size:12px;transition:background-color .12s;display:flex}.lc-br-elem-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-err-dot{background:var(--dsw-alias-state-error-primary);width:6px;height:6px;box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);border-radius:50%;flex:none}.lc-br-tag{min-width:0;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);text-overflow:ellipsis;white-space:nowrap;border-radius:4px;max-width:220px;padding:0 6px;font-size:11px;overflow:hidden}.lc-br-tool-plugin{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);border-color:#0000;border-radius:6px;font-size:12px}.lc-br-preview{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-br-time{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-br-content{flex-direction:column;gap:6px;padding:2px 6px 8px 26px;display:flex}.lc-br-dim{color:var(--dsw-alias-label-secondary)}.lc-ts-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;min-width:0;overflow:hidden}.lc-ts-card-head{color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:8px;padding:6px 10px;font-size:11px;font-weight:600;display:flex}.lc-ts-card-head b{color:var(--dsw-alias-label-primary)}.lc-ts-call-name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px}.lc-ts-card-count{margin-left:auto}.lc-ts-card-right{align-items:center;gap:8px;margin-left:auto;display:inline-flex}.lc-ts-card-meta{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;font-weight:400}.lc-ts-call-state{white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:2px 7px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;font-weight:600;line-height:1;display:inline-flex}.lc-ts-call-state i{background:currentColor;border-radius:50%;flex:none;width:6px;height:6px}.lc-ts-call-ok{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent)}.lc-ts-call-err{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.lc-ts-desc-body{color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:320px;margin:0;padding:8px 10px;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-lines{counter-reset:lc-line}.lc-ts-line{padding-left:26px;display:block;position:relative}.lc-ts-line:before{content:counter(lc-line);counter-increment:lc-line;text-align:right;width:20px;color:var(--dsw-alias-label-tertiary);user-select:none;padding-right:6px;font-size:11px;position:absolute;left:0}.lc-ts-line:empty:after{content:\"\"}.lc-ts-param-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,140px) minmax(0,90px) 56px minmax(0,1fr);align-items:baseline;gap:2px 10px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-param-row:first-of-type{border-top:0}.lc-ts-param-name{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.lc-ts-param-type{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;overflow:hidden}.lc-ts-param-req{color:var(--dsw-alias-state-warn-primary);font-size:11px;font-weight:600}.lc-ts-param-req-off{color:var(--dsw-alias-label-secondary);font-size:11px}.lc-ts-param-desc{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;grid-column:1/-1;line-height:1.5}.lc-ts-params-empty{color:var(--dsw-alias-label-secondary);padding:8px 10px;font-size:12px}.lc-ts-arg-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,96px) 1fr;align-items:start;column-gap:12px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-arg-row:first-of-type{border-top:0}.lc-ts-arg-row .lc-ts-param-name{text-overflow:unset;white-space:normal;overflow-wrap:anywhere;overflow:visible}.lc-ts-arg-val{color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:200px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-json{flex-direction:column;gap:4px;display:flex}.lc-ts-json-toggle{color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-self:flex-start;padding:0;font-size:11px}.lc-ts-json-toggle:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.lc-rich-seg{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-rich-seg-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-rich-seg-btn:hover{color:var(--dsw-alias-label-primary)}.lc-rich-seg-on,.lc-rich-seg-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-ts-desc-md{color:var(--dsw-alias-label-primary);word-break:break-word;overflow-wrap:anywhere;scrollbar-width:thin;min-width:0;max-height:320px;padding:4px 10px;font-size:12px;line-height:1.55;overflow:hidden auto}.lc-ts-desc-md>div{font-size:13px;line-height:1.55}.lc-ts-desc-md div :is(h1,h2,h3,h4,h5,h6){margin:10px 0 4px;font-size:13px;font-weight:600}.lc-ts-desc-md div p{white-space:pre-line;margin:6px 0}.lc-ts-desc-md div p br{display:none}.lc-ts-desc-md div pre{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;margin:6px 0}.lc-ts-desc-md div :not(pre)>code{box-decoration-break:clone;padding:1px 5px;line-height:1.3;font-size:1em!important}.lc-ts-desc-md div table code{font-size:inherit}.lc-att-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:8px 10px;display:grid}.lc-att-item{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);width:100%;min-width:0;font:inherit;text-align:left;cursor:pointer;background:0 0;border-radius:8px;align-items:center;gap:8px;padding:6px;display:flex}.lc-att-item:hover{border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2))}.lc-att-thumb{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:6px;flex:none;justify-content:center;align-items:center;width:64px;height:64px;padding:0;display:flex;overflow:hidden}.lc-att-thumb img{object-fit:cover;width:100%;height:100%;display:block}.lc-att-ph,.lc-att-err{color:var(--dsw-alias-label-secondary);text-align:center;padding:2px;font-size:10px}.lc-att-meta{flex-direction:column;gap:2px;min-width:0;display:flex}.lc-att-name{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;word-break:break-word;font-size:12px;line-height:1.3}.lc-att-row{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:11px}.lc-att-row-label{min-width:3.2em;font-weight:400;display:inline-block}.lc-att-lightbox{z-index:1000;place-items:center;padding:40px;display:grid;position:fixed;inset:0}.lc-att-lightbox-mask{background:var(--dsw-alias-bg-mask-1,#00000073);backdrop-filter:var(--dsw-mask-blur,blur(2px));position:absolute;inset:0}.lc-att-lightbox-img{object-fit:contain;background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));max-width:min(100%,1600px);max-height:calc(100vh - 80px);box-shadow:var(--dsw-shadow-lv3,0 12px 32px #0006);border-radius:12px;position:relative}.lc-att-lightbox-close{z-index:1;border:1px solid var(--dsw-alias-border-l2-darkmode-thin,var(--dsw-alias-border-l1));background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1));width:36px;height:36px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:999px;place-items:center;padding:0;display:grid;position:fixed;top:20px;right:20px}[data-conversation-scroll]:has(.lc-root)>[data-composer-seat]:not(:has([data-approval-key],[data-question-key],[data-plan-review-key])){display:none}.lc-agents-chips{flex-wrap:wrap;gap:6px;margin-bottom:10px;display:flex}.lc-agents-chip{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;border-radius:999px;padding:2px 8px;font-size:11px}.lc-agents-chip-on{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent)}.lc-agents-stage{margin:0 -4px;padding:0 4px;overflow-x:auto}.lc-agents-svg{max-width:none;margin:0 auto;display:block}.lc-agents-link{stroke-width:1.5px;stroke-opacity:.45}.lc-agents-link-live{stroke-opacity:.85}.lc-agents-flow{stroke-width:2px;stroke-linecap:round;stroke-dasharray:2 7;animation:.9s linear infinite lc-agent-flow}@keyframes lc-agent-flow{to{stroke-dashoffset:-9px}}.lc-agent-node{outline:none}.lc-agent-clickable{cursor:pointer}.lc-agent-halo{fill:#0000;transition:fill .12s}.lc-agent-hover .lc-agent-halo,.lc-agent-node:focus-visible .lc-agent-halo{fill:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2))}.lc-agent-self .lc-agent-halo{fill:var(--dsw-alias-bg-layer-2)}.lc-agent-running .lc-agent-halo{fill:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent);animation:1.8s ease-in-out infinite lc-agent-glow}.lc-agent-done .lc-agent-halo{fill:color-mix(in srgb, var(--dsw-alias-state-success-primary) 7%, transparent)}@keyframes lc-agent-glow{0%,to{opacity:1}50%{opacity:.4}}.lc-agent-track{fill:var(--dsw-alias-bg-layer-1);stroke:var(--dsw-alias-border-l1);stroke-width:1.5px}.lc-agent-seg{fill:none;stroke-width:9px;transition:stroke-dasharray .3s,stroke-dashoffset .3s}.lc-agent-free{stroke:color-mix(in srgb, var(--dsw-alias-label-secondary) 18%, transparent)}.lc-agent-pct{fill:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;pointer-events:none;font-size:11px;font-weight:600}.lc-agent-caption{text-align:center;pointer-events:none;width:100%;line-height:1.25}.lc-agent-label{color:var(--dsw-alias-label-primary);overflow-wrap:break-word;-webkit-line-clamp:3;-webkit-box-orient:vertical;font-size:11px;display:-webkit-box;overflow:hidden}.lc-agent-tokens{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;font-size:10px}.lc-agents-solo{padding:4px 0 10px}.lc-agents-inspector{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:8px;flex-wrap:wrap;align-items:baseline;gap:4px 8px;min-width:0;margin-top:10px;padding:7px 10px;font-size:12px;display:flex}.lc-agents-inspector-name{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere}.lc-agents-badge{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 6px;font-size:10px}.lc-agent-self-badge{vertical-align:1px;margin-left:5px}.lc-agents-badge-on{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent)}.lc-agents-inspector-stats{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.lc-agents-inspector-open{color:var(--dsw-alias-brand-primary,#3b82f6);flex:none;margin-left:auto}.lc-agents-legend{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:4px 14px;margin-top:8px;font-size:11px;display:flex}.lc-agents-legend-item{align-items:center;gap:5px;display:inline-flex}.lc-agents-legend-item i{border-radius:2px;width:8px;height:8px}.lc-agents-legend-free{background:color-mix(in srgb, var(--dsw-alias-label-secondary) 18%, transparent)}.lc-agents-legend-edge{border-top:2px dashed var(--dsw-alias-label-secondary);border-radius:0!important;width:14px!important;height:0!important}";
|
|
5580
6109
|
const tagId = "dsh-context/styles.css";
|
|
5581
6110
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
5582
6111
|
const tag = document.createElement("style");
|
|
@@ -5630,6 +6159,15 @@ window.__ModuleLoader__.load({
|
|
|
5630
6159
|
label: () => t("tab")
|
|
5631
6160
|
}, (props) => h(ContextView, props));
|
|
5632
6161
|
});
|
|
6162
|
+
const ContextJump = makeContextJumpButton(kit);
|
|
6163
|
+
ctx.slots.inject("conversation.chat.assistant-actions", () => {
|
|
6164
|
+
return ctx.slots.register({
|
|
6165
|
+
name: "conversation.chat.assistant-actions",
|
|
6166
|
+
id: "context-jump",
|
|
6167
|
+
order: 20,
|
|
6168
|
+
locale: NS
|
|
6169
|
+
}, (props) => h(ContextJump, props));
|
|
6170
|
+
});
|
|
5633
6171
|
registerContextCommand(ctx, kit);
|
|
5634
6172
|
const ContextModal = makeContextModal(ctx, kit);
|
|
5635
6173
|
ctx.slots.inject("conversation.input.overlay", () => {
|