dsh-context 0.32.0 → 0.33.1
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 +7 -3
- package/lib/client.js +785 -178
- package/lib/index.d.ts +0 -8
- package/lib/index.js +14 -17
- package/package.json +8 -3
package/lib/client.js
CHANGED
|
@@ -39,8 +39,6 @@ window.__ModuleLoader__.load({
|
|
|
39
39
|
"plugin.hint": "The best DSH context plugin ⭐",
|
|
40
40
|
"plugin.name": "插件",
|
|
41
41
|
"plugin.github": "GitHub",
|
|
42
|
-
"tools.top": "工具定义 Top:",
|
|
43
|
-
"tools.more": "等 {n} 个",
|
|
44
42
|
"trend.title": "上下文趋势",
|
|
45
43
|
"gran.step": "步骤",
|
|
46
44
|
"gran.turn": "轮次",
|
|
@@ -48,6 +46,7 @@ window.__ModuleLoader__.load({
|
|
|
48
46
|
"settings.desc": "上下文面板的展示偏好",
|
|
49
47
|
"settings.gran": "趋势图默认粒度",
|
|
50
48
|
"settings.mode": "趋势图默认展示",
|
|
49
|
+
"settings.fileSort": "文件活动默认排序",
|
|
51
50
|
"settings.expand": "展开",
|
|
52
51
|
"settings.collapse": "收起",
|
|
53
52
|
"settings.readOnly": "当前环境的设置为只读",
|
|
@@ -81,10 +80,30 @@ window.__ModuleLoader__.load({
|
|
|
81
80
|
"kind.prune": "剪枝",
|
|
82
81
|
"kind.model": "切换",
|
|
83
82
|
"kind.mode": "模式",
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
83
|
+
"files.title": "文件活动",
|
|
84
|
+
"files.scopeLatest": "截至最新 · 跟随趋势图的选择",
|
|
85
|
+
"files.kind.all": "全部",
|
|
86
|
+
"files.kind.read": "读取",
|
|
87
|
+
"files.kind.write": "写入",
|
|
88
|
+
"files.kind.search": "搜索",
|
|
89
|
+
"files.kind.image": "图片",
|
|
90
|
+
"files.chipTip": "{files} 个文件 · {ops} 次操作",
|
|
91
|
+
"files.search": "按路径过滤…",
|
|
92
|
+
"files.sort.count": "按次数",
|
|
93
|
+
"files.sort.latest": "按最新",
|
|
94
|
+
"files.sort.path": "按路径",
|
|
95
|
+
"files.sortTip": "文件排序:按操作次数(选中分类时按该分类的次数)、最近操作时间或路径",
|
|
96
|
+
"files.files": "{n} 个文件",
|
|
97
|
+
"files.deltaTip": "按 edit/write 调用参数估算的累计行数变化:+ 新增 / − 删除",
|
|
98
|
+
"files.unresolved": "… 另有 {n} 次文件操作的路径超出保留窗口",
|
|
99
|
+
"files.empty": "该范围内没有文件读取、写入或搜索操作",
|
|
100
|
+
"files.noMatch": "没有匹配当前过滤条件的文件",
|
|
101
|
+
"files.locate": "在上下文浏览器中查看此次操作",
|
|
102
|
+
"files.moreOps": "+{n} 次更早操作",
|
|
103
|
+
"files.errs": "{n} 次失败",
|
|
104
|
+
"files.form.image": "图片",
|
|
105
|
+
"files.form.dir": "目录",
|
|
106
|
+
"files.form.text": "文件",
|
|
88
107
|
"loading": "正在读取会话日志…",
|
|
89
108
|
"error": "上下文数据读取失败:",
|
|
90
109
|
"error.retry": "重试",
|
|
@@ -126,6 +145,8 @@ window.__ModuleLoader__.load({
|
|
|
126
145
|
"browser.noEpoch": "该步骤的头部内容(系统提示词 / 工具定义)不在保留范围内",
|
|
127
146
|
"browser.noContent": "完整内容不在当前加载的消息窗口内(在聊天页加载更早历史后可查看)",
|
|
128
147
|
"browser.loading": "正在从更早的会话历史加载完整内容…",
|
|
148
|
+
"browser.notInLog": "会话日志中未找到该条目的完整内容(可能已被压缩或清理)",
|
|
149
|
+
"browser.loadFailed": "内容加载失败,点击重试",
|
|
129
150
|
"browser.preview": "预览",
|
|
130
151
|
"tool.desc": "描述",
|
|
131
152
|
"tool.params": "参数",
|
|
@@ -194,8 +215,6 @@ window.__ModuleLoader__.load({
|
|
|
194
215
|
"plugin.hint": "The best DSH context plugin ⭐",
|
|
195
216
|
"plugin.name": "Plugin",
|
|
196
217
|
"plugin.github": "GitHub",
|
|
197
|
-
"tools.top": "Top Tool Schemas:",
|
|
198
|
-
"tools.more": "of {n}",
|
|
199
218
|
"trend.title": "Context Trend",
|
|
200
219
|
"gran.step": "Step",
|
|
201
220
|
"gran.turn": "Turn",
|
|
@@ -203,6 +222,7 @@ window.__ModuleLoader__.load({
|
|
|
203
222
|
"settings.desc": "Display preferences for the Context panel",
|
|
204
223
|
"settings.gran": "Default trend granularity",
|
|
205
224
|
"settings.mode": "Default trend display",
|
|
225
|
+
"settings.fileSort": "File Activity default sort",
|
|
206
226
|
"settings.expand": "Expand",
|
|
207
227
|
"settings.collapse": "Collapse",
|
|
208
228
|
"settings.readOnly": "Settings are read-only in this environment",
|
|
@@ -236,10 +256,30 @@ window.__ModuleLoader__.load({
|
|
|
236
256
|
"kind.prune": "Prune",
|
|
237
257
|
"kind.model": "Switch",
|
|
238
258
|
"kind.mode": "Mode",
|
|
239
|
-
"
|
|
240
|
-
"
|
|
241
|
-
"
|
|
242
|
-
"
|
|
259
|
+
"files.title": "File Activity",
|
|
260
|
+
"files.scopeLatest": "Up to latest · follows the trend chart pick",
|
|
261
|
+
"files.kind.all": "All",
|
|
262
|
+
"files.kind.read": "Read",
|
|
263
|
+
"files.kind.write": "Written",
|
|
264
|
+
"files.kind.search": "Searched",
|
|
265
|
+
"files.kind.image": "Images",
|
|
266
|
+
"files.chipTip": "{files} files · {ops} ops",
|
|
267
|
+
"files.search": "Filter by path…",
|
|
268
|
+
"files.sort.count": "Most active",
|
|
269
|
+
"files.sort.latest": "Latest",
|
|
270
|
+
"files.sort.path": "By path",
|
|
271
|
+
"files.sortTip": "Sort files by operation counts (of the selected kind when a kind chip is active), most recent activity, or path",
|
|
272
|
+
"files.files": "{n} files",
|
|
273
|
+
"files.deltaTip": "Cumulative line change estimated from edit/write call arguments: + added / − removed",
|
|
274
|
+
"files.unresolved": "… {n} more file ops have paths outside the retained window",
|
|
275
|
+
"files.empty": "No file reads, writes, or searches in this range",
|
|
276
|
+
"files.noMatch": "No files match the current filters",
|
|
277
|
+
"files.locate": "Reveal this operation in the Context Browser",
|
|
278
|
+
"files.moreOps": "+{n} earlier ops",
|
|
279
|
+
"files.errs": "{n} failed",
|
|
280
|
+
"files.form.image": "Image",
|
|
281
|
+
"files.form.dir": "Directory",
|
|
282
|
+
"files.form.text": "File",
|
|
243
283
|
"loading": "Reading the session log…",
|
|
244
284
|
"error": "Failed to read context data: ",
|
|
245
285
|
"error.retry": "Retry",
|
|
@@ -281,6 +321,8 @@ window.__ModuleLoader__.load({
|
|
|
281
321
|
"browser.noEpoch": "The header content (System Prompt / Tool Schemas) of this step is outside retention",
|
|
282
322
|
"browser.noContent": "Full content is outside the loaded message window (load older history in Chat to view)",
|
|
283
323
|
"browser.loading": "Loading full content from older session history…",
|
|
324
|
+
"browser.notInLog": "This item is not in the session log anymore (it may have been compacted away or cleared)",
|
|
325
|
+
"browser.loadFailed": "Load failed — click to retry",
|
|
284
326
|
"browser.preview": "Preview",
|
|
285
327
|
"tool.desc": "Description",
|
|
286
328
|
"tool.params": "Parameters",
|
|
@@ -435,8 +477,7 @@ window.__ModuleLoader__.load({
|
|
|
435
477
|
"assistant",
|
|
436
478
|
"tool"
|
|
437
479
|
];
|
|
438
|
-
|
|
439
|
-
const CAT_COLORS = Object.fromEntries(CATS.map((c) => [c.key, c.color]));
|
|
480
|
+
Object.fromEntries(CATS.map((c) => [c.key, c.color]));
|
|
440
481
|
function partsOf(breakdown) {
|
|
441
482
|
return CATS.map((c) => {
|
|
442
483
|
return {
|
|
@@ -478,6 +519,9 @@ window.__ModuleLoader__.load({
|
|
|
478
519
|
return CATS.map((c) => ({
|
|
479
520
|
key: c.key,
|
|
480
521
|
color: c.color,
|
|
522
|
+
/* v8 ignore next 1 -- `shares` is initialized with system/tools and both
|
|
523
|
+
foldSurface arms assign every MESSAGE_CATS key, so each key is always
|
|
524
|
+
defined; the fallback is defensive. */
|
|
481
525
|
value: shares[c.key] ?? 0
|
|
482
526
|
}));
|
|
483
527
|
}
|
|
@@ -574,7 +618,7 @@ window.__ModuleLoader__.load({
|
|
|
574
618
|
"assistant",
|
|
575
619
|
"tool",
|
|
576
620
|
"total"
|
|
577
|
-
].every((k) => typeof current[k] === "number") && Array.isArray(data.requests) && Array.isArray(data.events) && Array.isArray(data.nodes) && Array.isArray(data.archive)
|
|
621
|
+
].every((k) => typeof current[k] === "number") && Array.isArray(data.requests) && Array.isArray(data.events) && Array.isArray(data.nodes) && Array.isArray(data.archive)) return data;
|
|
578
622
|
const safeCurrent = current !== null && typeof current === "object" ? current : {};
|
|
579
623
|
const cost = typeof data.cost === "object" && data.cost !== null && !Array.isArray(data.cost) ? data.cost : void 0;
|
|
580
624
|
return {
|
|
@@ -591,7 +635,6 @@ window.__ModuleLoader__.load({
|
|
|
591
635
|
tool: numOf(safeCurrent.tool),
|
|
592
636
|
total: numOf(safeCurrent.total)
|
|
593
637
|
},
|
|
594
|
-
toolList: objectsOf(data.toolList),
|
|
595
638
|
requests: objectsOf(data.requests),
|
|
596
639
|
events: objectsOf(data.events),
|
|
597
640
|
nodes: objectsOf(data.nodes),
|
|
@@ -666,6 +709,157 @@ window.__ModuleLoader__.load({
|
|
|
666
709
|
return headers;
|
|
667
710
|
}
|
|
668
711
|
//#endregion
|
|
712
|
+
//#region src/client/historyPage.ts
|
|
713
|
+
/** Narrow one served row to a validated durable event envelope, or null. */
|
|
714
|
+
function eventOf(entry) {
|
|
715
|
+
if (entry === null || typeof entry !== "object") return null;
|
|
716
|
+
const ev = entry.event;
|
|
717
|
+
if (ev === null || typeof ev !== "object") return null;
|
|
718
|
+
const e = ev;
|
|
719
|
+
if (typeof e.type !== "string" || typeof e.seq !== "number" || !Number.isFinite(e.seq)) return null;
|
|
720
|
+
const data = e.data !== null && typeof e.data === "object" ? e.data : {};
|
|
721
|
+
return {
|
|
722
|
+
type: e.type,
|
|
723
|
+
seq: e.seq,
|
|
724
|
+
data
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
/** All string texts of an event's message-content shape joined (compaction summaries). */
|
|
728
|
+
function textOf(blocks) {
|
|
729
|
+
if (!Array.isArray(blocks)) return null;
|
|
730
|
+
let out = "";
|
|
731
|
+
for (const b of blocks) {
|
|
732
|
+
const text = b !== null && typeof b === "object" ? b.text : void 0;
|
|
733
|
+
if (typeof text === "string") out += text;
|
|
734
|
+
}
|
|
735
|
+
return out.trim() === "" ? null : out;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* One assistant content block → the snapshot block vocabulary the browser
|
|
739
|
+
* already renders (`kind`: text/reasoning/image/tool-call); unmappable
|
|
740
|
+
* blocks pass through raw and degrade to the generic JSON section.
|
|
741
|
+
*/
|
|
742
|
+
function assistantBlockOf(block) {
|
|
743
|
+
const b = block !== null && typeof block === "object" ? block : null;
|
|
744
|
+
switch (b?.type) {
|
|
745
|
+
case "text":
|
|
746
|
+
case "reasoning": return {
|
|
747
|
+
kind: b.type,
|
|
748
|
+
...typeof b.text === "string" ? { text: b.text } : {}
|
|
749
|
+
};
|
|
750
|
+
case "image": return {
|
|
751
|
+
kind: "image",
|
|
752
|
+
...b.attachment !== void 0 ? { attachment: b.attachment } : {}
|
|
753
|
+
};
|
|
754
|
+
case "tool-call": return {
|
|
755
|
+
kind: "tool-call",
|
|
756
|
+
name: typeof b.name === "string" ? b.name : "?",
|
|
757
|
+
argsRaw: b.arguments
|
|
758
|
+
};
|
|
759
|
+
default: return block !== null && typeof block === "object" ? block : { value: block };
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Map one history page into joined conversation nodes keyed by their event
|
|
764
|
+
* seq — the display subset of the browser's join: user messages, assistant
|
|
765
|
+
* blocks, tool results paired with their in-page call head, and compaction
|
|
766
|
+
* checkpoints paired with their summary event. Everything else (headers,
|
|
767
|
+
* boundaries, chunks, bare calls) projects to nothing.
|
|
768
|
+
*/
|
|
769
|
+
function pageNodesOf(entries) {
|
|
770
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
771
|
+
const calls = /* @__PURE__ */ new Map();
|
|
772
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
773
|
+
for (const entry of entries) {
|
|
774
|
+
const ev = eventOf(entry);
|
|
775
|
+
if (ev === null) continue;
|
|
776
|
+
const { type, seq, data } = ev;
|
|
777
|
+
if (type === "tool/call") {
|
|
778
|
+
if (typeof data.callId === "string") calls.set(data.callId, {
|
|
779
|
+
name: typeof data.name === "string" ? data.name : "?",
|
|
780
|
+
argsRaw: typeof data.arguments === "string" ? data.arguments : ""
|
|
781
|
+
});
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
if (type === "compaction/summary") {
|
|
785
|
+
if (typeof data.compactionId === "string") {
|
|
786
|
+
const summary = textOf(data.summary);
|
|
787
|
+
if (summary !== null) summaries.set(data.compactionId, summary);
|
|
788
|
+
}
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
if (type === "user/message") {
|
|
792
|
+
const source = data.source !== null && typeof data.source === "object" ? data.source : null;
|
|
793
|
+
const compactionId = source !== null && source.kind === "plugin" && typeof source.compactionId === "string" ? source.compactionId : null;
|
|
794
|
+
if (compactionId !== null) {
|
|
795
|
+
nodes.set(seq, {
|
|
796
|
+
kind: "compaction",
|
|
797
|
+
seq,
|
|
798
|
+
summary: summaries.get(compactionId) ?? null
|
|
799
|
+
});
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
nodes.set(seq, {
|
|
803
|
+
kind: "user",
|
|
804
|
+
seq,
|
|
805
|
+
content: Array.isArray(data.content) ? data.content : []
|
|
806
|
+
});
|
|
807
|
+
continue;
|
|
808
|
+
}
|
|
809
|
+
if (type === "assistant/message") {
|
|
810
|
+
const message = data.message !== null && typeof data.message === "object" ? data.message : null;
|
|
811
|
+
const content = message !== null && Array.isArray(message.content) ? message.content : [];
|
|
812
|
+
nodes.set(seq, {
|
|
813
|
+
kind: "assistant",
|
|
814
|
+
seq,
|
|
815
|
+
blocks: content.map(assistantBlockOf)
|
|
816
|
+
});
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
if (type === "tool/result") {
|
|
820
|
+
const message = data.message !== null && typeof data.message === "object" ? data.message : null;
|
|
821
|
+
const source = message?.source !== null && typeof message?.source === "object" ? message.source : null;
|
|
822
|
+
const first = Array.isArray(message?.content) ? message.content[0] : void 0;
|
|
823
|
+
const block = first !== null && typeof first === "object" ? first : null;
|
|
824
|
+
const callId = typeof source?.callId === "string" ? source.callId : typeof block?.toolCallId === "string" ? block.toolCallId : null;
|
|
825
|
+
const call = callId !== null ? calls.get(callId) ?? null : null;
|
|
826
|
+
nodes.set(seq, {
|
|
827
|
+
kind: "tool-result",
|
|
828
|
+
seq,
|
|
829
|
+
call,
|
|
830
|
+
content: block !== null && Array.isArray(block.content) ? block.content : [],
|
|
831
|
+
isError: block?.isError === true || data.error === true
|
|
832
|
+
});
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
return nodes;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Build the browser's per-session fetcher over the shared api client.
|
|
840
|
+
* Undefined when the connection face or the history verb is absent (older
|
|
841
|
+
* hosts) — the caller keeps its static preview-plus-hint degradation. Found
|
|
842
|
+
* nodes cache in the closure: one mount re-reading a row never re-fetches.
|
|
843
|
+
*/
|
|
844
|
+
function makeContentFetcher(ctx, sessionId) {
|
|
845
|
+
const sessions = ctx.get("connection")?.api?.sessions;
|
|
846
|
+
if (typeof sessions?.history !== "function") return void 0;
|
|
847
|
+
const cache = /* @__PURE__ */ new Map();
|
|
848
|
+
return async (seq) => {
|
|
849
|
+
const hit = cache.get(seq);
|
|
850
|
+
if (hit !== void 0) return hit;
|
|
851
|
+
const result = (await sessions.history({
|
|
852
|
+
sessionId,
|
|
853
|
+
beforeSeq: seq + 1
|
|
854
|
+
})).result;
|
|
855
|
+
if (result === null || typeof result !== "object" || result.ok !== true || result.value === null || typeof result.value !== "object") throw new Error("history rpc failed");
|
|
856
|
+
const events = result.value.events;
|
|
857
|
+
const node = pageNodesOf(Array.isArray(events) ? events : []).get(seq) ?? null;
|
|
858
|
+
if (node !== null) cache.set(seq, node);
|
|
859
|
+
return node;
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
//#endregion
|
|
669
863
|
//#region src/client/assemble.ts
|
|
670
864
|
/** The header epoch in force at `seq` (last logged before it), or the newest. */
|
|
671
865
|
function headerAt(headers, seq) {
|
|
@@ -767,24 +961,6 @@ window.__ModuleLoader__.load({
|
|
|
767
961
|
return t("node.nonText");
|
|
768
962
|
};
|
|
769
963
|
}
|
|
770
|
-
function makeNodeList(kit) {
|
|
771
|
-
const { t, fmt, fmtTime } = kit;
|
|
772
|
-
const nodeText = makeNodeText(kit);
|
|
773
|
-
return function NodeList(props) {
|
|
774
|
-
if (props.nodes.length === 0) return /* @__PURE__ */ React.createElement("div", { className: "lc-empty" }, t("nodes.empty"));
|
|
775
|
-
const rows = props.nodes.slice().reverse();
|
|
776
|
-
return /* @__PURE__ */ React.createElement("div", { className: "lc-nodes" }, props.dropped > 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-nodes-more" }, t("nodes.more", { n: props.dropped })) : null, rows.map((n) => {
|
|
777
|
-
const text = nodeText(n);
|
|
778
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
779
|
-
key: n.seq,
|
|
780
|
-
className: "lc-node"
|
|
781
|
-
}, /* @__PURE__ */ React.createElement("i", { style: { background: CAT_COLORS[n.cat] || "#999" } }), /* @__PURE__ */ React.createElement("span", {
|
|
782
|
-
className: "lc-node-preview",
|
|
783
|
-
title: text
|
|
784
|
-
}, text), typeof n.time === "number" ? /* @__PURE__ */ React.createElement("span", { className: "lc-node-time" }, fmtTime(n.time)) : null, /* @__PURE__ */ React.createElement("span", { className: "lc-node-tokens" }, fmt(n.tokens)));
|
|
785
|
-
}));
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
964
|
//#endregion
|
|
789
965
|
//#region src/client/format.ts
|
|
790
966
|
/** `fmt`: the k/M suffix style shared by bars/details/stats; `fmtTime`: local HH:MM:SS. */
|
|
@@ -865,6 +1041,8 @@ window.__ModuleLoader__.load({
|
|
|
865
1041
|
let bestWidth;
|
|
866
1042
|
if (gridW < 1) {
|
|
867
1043
|
let rows = floorDiv(budget - 2, 2);
|
|
1044
|
+
/* v8 ignore else -- budget enters at 381 and the tall solve always fits
|
|
1045
|
+
(never decrements), so rows is always odd here; parity-defensive. */
|
|
868
1046
|
if (rows % 2 === 1) rows -= 1;
|
|
869
1047
|
bestWidth = unit;
|
|
870
1048
|
bestHeight = rows * unit;
|
|
@@ -944,6 +1122,8 @@ window.__ModuleLoader__.load({
|
|
|
944
1122
|
}
|
|
945
1123
|
return null;
|
|
946
1124
|
} catch {
|
|
1125
|
+
/* v8 ignore next -- the only throw site is the clamped-away budget guard
|
|
1126
|
+
above; the catch keeps a hostile dimension from ever breaking the fold. */
|
|
947
1127
|
return null;
|
|
948
1128
|
}
|
|
949
1129
|
}
|
|
@@ -1189,18 +1369,22 @@ window.__ModuleLoader__.load({
|
|
|
1189
1369
|
*/
|
|
1190
1370
|
function Section(props) {
|
|
1191
1371
|
const right = props.actions !== void 0 || props.meta !== void 0;
|
|
1192
|
-
return /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card-head" }, /* @__PURE__ */ React.createElement("b", { className: props.labelClass }, props.label), right ? /* @__PURE__ */ React.createElement("span", { className: "lc-ts-card-right" }, props.meta
|
|
1372
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card-head" }, /* @__PURE__ */ React.createElement("b", { className: props.labelClass }, props.label), right ? /* @__PURE__ */ React.createElement("span", { className: "lc-ts-card-right" }, props.meta, props.actions) : null, props.count !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-ts-card-count" }, props.count) : null), props.children);
|
|
1373
|
+
}
|
|
1374
|
+
function lineCountOf(text) {
|
|
1375
|
+
return text.split(/\r\n|\r|\n/).length;
|
|
1193
1376
|
}
|
|
1194
1377
|
function TextSection(props) {
|
|
1195
1378
|
const { rich } = props;
|
|
1196
1379
|
const [mode, setMode] = rich.useRichMode();
|
|
1380
|
+
const lineCount = React.useMemo(() => lineCountOf(props.text), [props.text]);
|
|
1197
1381
|
return /* @__PURE__ */ React.createElement(Section, {
|
|
1198
1382
|
label: props.label,
|
|
1199
1383
|
actions: /* @__PURE__ */ React.createElement(rich.RichSwitch, {
|
|
1200
1384
|
mode,
|
|
1201
1385
|
onPick: setMode
|
|
1202
1386
|
}),
|
|
1203
|
-
meta: props.
|
|
1387
|
+
meta: /* @__PURE__ */ React.createElement("span", { className: "lc-ts-card-meta" }, props.lines(lineCount))
|
|
1204
1388
|
}, /* @__PURE__ */ React.createElement(rich.RichText, {
|
|
1205
1389
|
text: props.text,
|
|
1206
1390
|
mode
|
|
@@ -1238,7 +1422,8 @@ window.__ModuleLoader__.load({
|
|
|
1238
1422
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, props.description !== void 0 ? /* @__PURE__ */ React.createElement(TextSection, {
|
|
1239
1423
|
label: props.labels.desc,
|
|
1240
1424
|
text: props.description,
|
|
1241
|
-
rich
|
|
1425
|
+
rich,
|
|
1426
|
+
lines: props.lines
|
|
1242
1427
|
}) : null, params !== null && rows.length > 0 ? /* @__PURE__ */ React.createElement(Section, {
|
|
1243
1428
|
label: props.labels.title,
|
|
1244
1429
|
count: rows.length
|
|
@@ -1257,8 +1442,8 @@ window.__ModuleLoader__.load({
|
|
|
1257
1442
|
}
|
|
1258
1443
|
/**
|
|
1259
1444
|
* Both block vocabularies normalize here — raw durable blocks (`type`: text/reasoning/tool-call/tool-result/image) and snapshot assistant
|
|
1260
|
-
* blocks (`kind`: text/reasoning/tool-call/image, argsRaw). Consecutive images group into one grid;
|
|
1261
|
-
* switch + line count; nested tool-result blocks flatten into the same flow.
|
|
1445
|
+
* blocks (`kind`: text/reasoning/tool-call/image, argsRaw). Consecutive images group into one grid; every
|
|
1446
|
+
* rich text block carries the Raw/MD switch + line count; nested tool-result blocks flatten into the same flow.
|
|
1262
1447
|
*/
|
|
1263
1448
|
function BlocksBody(props) {
|
|
1264
1449
|
const { rich, img, labels } = props;
|
|
@@ -1294,7 +1479,7 @@ window.__ModuleLoader__.load({
|
|
|
1294
1479
|
label,
|
|
1295
1480
|
text: blk.text,
|
|
1296
1481
|
rich,
|
|
1297
|
-
|
|
1482
|
+
lines: labels.lines
|
|
1298
1483
|
}));
|
|
1299
1484
|
continue;
|
|
1300
1485
|
}
|
|
@@ -1412,6 +1597,8 @@ window.__ModuleLoader__.load({
|
|
|
1412
1597
|
}
|
|
1413
1598
|
function CallArgRow(props) {
|
|
1414
1599
|
const v = props.value;
|
|
1600
|
+
/* v8 ignore next 2 -- the only caller maps Object.keys of a JSON.parse'd
|
|
1601
|
+
object, which never holds undefined values; defensive. */
|
|
1415
1602
|
const text = typeof v === "string" ? v : v === void 0 ? "" : JSON.stringify(v);
|
|
1416
1603
|
return /* @__PURE__ */ React.createElement("div", { className: "lc-ts-arg-row" }, /* @__PURE__ */ React.createElement("span", { className: "lc-ts-param-name" }, props.name), /* @__PURE__ */ React.createElement("span", { className: "lc-ts-arg-val" }, text));
|
|
1417
1604
|
}
|
|
@@ -1422,7 +1609,8 @@ window.__ModuleLoader__.load({
|
|
|
1422
1609
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TextSection, {
|
|
1423
1610
|
label: labels.content,
|
|
1424
1611
|
text: node.text,
|
|
1425
|
-
rich
|
|
1612
|
+
rich,
|
|
1613
|
+
lines: labels.lines
|
|
1426
1614
|
}), /* @__PURE__ */ React.createElement("div", { className: "lc-br-note" }, props.hint));
|
|
1427
1615
|
}
|
|
1428
1616
|
if (conv.kind === "assistant" && Array.isArray(conv.blocks)) return /* @__PURE__ */ React.createElement(BlocksBody, {
|
|
@@ -1452,7 +1640,8 @@ window.__ModuleLoader__.load({
|
|
|
1452
1640
|
if (conv.kind === "compaction") return typeof conv.summary === "string" && conv.summary !== "" ? /* @__PURE__ */ React.createElement(TextSection, {
|
|
1453
1641
|
label: labels.summary,
|
|
1454
1642
|
text: conv.summary,
|
|
1455
|
-
rich
|
|
1643
|
+
rich,
|
|
1644
|
+
lines: labels.lines
|
|
1456
1645
|
}) : /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
1457
1646
|
if (Array.isArray(conv.content)) return /* @__PURE__ */ React.createElement(BlocksBody, {
|
|
1458
1647
|
blocks: conv.content,
|
|
@@ -1483,52 +1672,51 @@ window.__ModuleLoader__.load({
|
|
|
1483
1672
|
const nodeText = makeNodeText(kit);
|
|
1484
1673
|
const rich = makeRichText(kit);
|
|
1485
1674
|
const ImageCard = makeImageCard(kit);
|
|
1486
|
-
const
|
|
1675
|
+
const lineLabel = (n) => t(n === 1 ? "block.line" : "block.lines", { n });
|
|
1487
1676
|
return function ContextBrowser(props) {
|
|
1488
1677
|
const { data, headers } = props;
|
|
1489
1678
|
const [sel, setSel] = React.useState("live");
|
|
1490
1679
|
const [openCat, setOpenCat] = React.useState(null);
|
|
1491
1680
|
const [openElem, setOpenElem] = React.useState(null);
|
|
1492
1681
|
const convNodes = typeof props.useSession === "function" ? props.useSession((s) => s.nodes) : void 0;
|
|
1682
|
+
const [fetched, setFetched] = React.useState(() => /* @__PURE__ */ new Map());
|
|
1493
1683
|
const bySeq = React.useMemo(() => {
|
|
1494
1684
|
const m = /* @__PURE__ */ new Map();
|
|
1495
1685
|
for (const n of convNodes ?? []) m.set(n.seq, n);
|
|
1686
|
+
for (const [seq, n] of fetched) if (!m.has(seq)) m.set(seq, n);
|
|
1496
1687
|
return m;
|
|
1497
|
-
}, [convNodes]);
|
|
1498
|
-
const hasMore = typeof props.useSession === "function" ? props.useSession((s) => s.hasMore === true) : false;
|
|
1499
|
-
const loadingOlder = typeof props.useSession === "function" ? props.useSession((s) => s.loadingOlder === true) : false;
|
|
1688
|
+
}, [convNodes, fetched]);
|
|
1500
1689
|
const openSeq = openElem !== null && openElem.startsWith("n") ? Number(openElem.slice(1)) : null;
|
|
1501
1690
|
const missingSeq = openSeq !== null && !bySeq.has(openSeq) ? openSeq : null;
|
|
1502
|
-
const
|
|
1503
|
-
const
|
|
1504
|
-
React.
|
|
1505
|
-
pagesRef.current = 0;
|
|
1506
|
-
setExhausted(false);
|
|
1507
|
-
}, [openElem]);
|
|
1508
|
-
const loadOlderHistory = props.loadOlderHistory;
|
|
1509
|
-
React.useEffect(() => {
|
|
1510
|
-
if (missingSeq === null || !hasMore || loadingOlder || exhausted) return;
|
|
1511
|
-
if (loadOlderHistory === void 0) return;
|
|
1512
|
-
if (pagesRef.current >= MAX_AUTO_PAGES) {
|
|
1513
|
-
setExhausted(true);
|
|
1514
|
-
return;
|
|
1515
|
-
}
|
|
1516
|
-
pagesRef.current += 1;
|
|
1517
|
-
loadOlderHistory();
|
|
1518
|
-
}, [
|
|
1519
|
-
missingSeq,
|
|
1520
|
-
hasMore,
|
|
1521
|
-
loadingOlder,
|
|
1522
|
-
exhausted,
|
|
1523
|
-
bySeq,
|
|
1524
|
-
loadOlderHistory
|
|
1525
|
-
]);
|
|
1691
|
+
const fetchContent = props.fetchContent;
|
|
1692
|
+
const [missState, setMissState] = React.useState("idle");
|
|
1693
|
+
const [retry, setRetry] = React.useState(0);
|
|
1526
1694
|
React.useEffect(() => {
|
|
1527
|
-
if (
|
|
1695
|
+
if (missingSeq === null || fetchContent === void 0) return;
|
|
1696
|
+
let live = true;
|
|
1697
|
+
setMissState("loading");
|
|
1698
|
+
fetchContent(missingSeq).then((node) => {
|
|
1699
|
+
if (!live) return;
|
|
1700
|
+
if (node === null) {
|
|
1701
|
+
setMissState("absent");
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
setFetched((prev) => {
|
|
1705
|
+
const next = new Map(prev);
|
|
1706
|
+
next.set(missingSeq, node);
|
|
1707
|
+
return next;
|
|
1708
|
+
});
|
|
1709
|
+
setMissState("idle");
|
|
1710
|
+
}, () => {
|
|
1711
|
+
if (live) setMissState("failed");
|
|
1712
|
+
});
|
|
1713
|
+
return () => {
|
|
1714
|
+
live = false;
|
|
1715
|
+
};
|
|
1528
1716
|
}, [
|
|
1529
|
-
hasMore,
|
|
1530
1717
|
missingSeq,
|
|
1531
|
-
|
|
1718
|
+
fetchContent,
|
|
1719
|
+
retry
|
|
1532
1720
|
]);
|
|
1533
1721
|
const pinSeq = props.pinSeq;
|
|
1534
1722
|
React.useEffect(() => {
|
|
@@ -1536,14 +1724,6 @@ window.__ModuleLoader__.load({
|
|
|
1536
1724
|
setOpenCat(null);
|
|
1537
1725
|
setOpenElem(null);
|
|
1538
1726
|
}, [pinSeq]);
|
|
1539
|
-
const toolFocus = props.toolFocus;
|
|
1540
|
-
React.useEffect(() => {
|
|
1541
|
-
if (toolFocus === null || toolFocus === void 0) return;
|
|
1542
|
-
setSel("live");
|
|
1543
|
-
setOpenCat("tools");
|
|
1544
|
-
setOpenElem(toolFocus.tool !== void 0 ? "tool:" + toolFocus.tool : null);
|
|
1545
|
-
if (props.onToolFocusHandled !== void 0) props.onToolFocusHandled();
|
|
1546
|
-
}, [toolFocus, props.onToolFocusHandled]);
|
|
1547
1727
|
const rootRef = React.useRef(null);
|
|
1548
1728
|
const focusScrollRef = React.useRef(false);
|
|
1549
1729
|
const nodeFocus = props.nodeFocus;
|
|
@@ -1560,7 +1740,13 @@ window.__ModuleLoader__.load({
|
|
|
1560
1740
|
focusScrollRef.current = false;
|
|
1561
1741
|
rootRef.current?.querySelector(".lc-br-elem-on")?.scrollIntoView({ block: "nearest" });
|
|
1562
1742
|
});
|
|
1563
|
-
const
|
|
1743
|
+
const missNote = fetchContent === void 0 ? t("browser.noContent") : missState === "loading" ? t("browser.loading") : missState === "absent" ? t("browser.notInLog") : missState === "failed" ? /* @__PURE__ */ React.createElement("button", {
|
|
1744
|
+
type: "button",
|
|
1745
|
+
className: "lc-br-retry",
|
|
1746
|
+
onClick: () => {
|
|
1747
|
+
setRetry((r) => r + 1);
|
|
1748
|
+
}
|
|
1749
|
+
}, t("browser.loadFailed")) : t("browser.noContent");
|
|
1564
1750
|
const requests = data.requests;
|
|
1565
1751
|
const hoverReq = props.previewSeq !== null && props.previewSeq !== void 0 ? requests.find((r) => r.seq === props.previewSeq) ?? null : null;
|
|
1566
1752
|
const req = hoverReq ?? (sel === "live" ? null : requests.find((r) => r.seq === sel) ?? null);
|
|
@@ -1583,8 +1769,13 @@ window.__ModuleLoader__.load({
|
|
|
1583
1769
|
const toolCount = (c) => countOf(view, byCat, c);
|
|
1584
1770
|
const toggleCat = (c) => {
|
|
1585
1771
|
if (!(toolCount(c) > 0 || (c === "system" || c === "tools") && view.header === null)) return;
|
|
1586
|
-
|
|
1587
|
-
|
|
1772
|
+
if (openCat === c) {
|
|
1773
|
+
setOpenCat(null);
|
|
1774
|
+
setOpenElem(null);
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
setOpenCat(c);
|
|
1778
|
+
setOpenElem(c === "system" && view.header?.system !== void 0 ? "sys" : null);
|
|
1588
1779
|
};
|
|
1589
1780
|
const toggleElem = (key) => {
|
|
1590
1781
|
setOpenElem(openElem === key ? null : key);
|
|
@@ -1613,11 +1804,14 @@ window.__ModuleLoader__.load({
|
|
|
1613
1804
|
if (c === "system") {
|
|
1614
1805
|
if (view.header === null) return /* @__PURE__ */ React.createElement("div", { className: "lc-br-note" }, t(headers === null ? "browser.noHeader" : "browser.noEpoch"));
|
|
1615
1806
|
const system = view.header.system;
|
|
1807
|
+
/* v8 ignore next 1 -- the category opens only when its count > 0
|
|
1808
|
+
(countOf ⟺ system defined); the undefined arm is defensive. */
|
|
1616
1809
|
if (system === void 0) return null;
|
|
1617
1810
|
return elemRow("sys", null, system.replace(/\s+/g, " ").trim().slice(0, 80), breakdown.system, void 0, /* @__PURE__ */ React.createElement(TextSection, {
|
|
1618
1811
|
label: catLabel("system"),
|
|
1619
1812
|
text: system,
|
|
1620
|
-
rich
|
|
1813
|
+
rich,
|
|
1814
|
+
lines: lineLabel
|
|
1621
1815
|
}));
|
|
1622
1816
|
}
|
|
1623
1817
|
if (c === "tools") {
|
|
@@ -1634,6 +1828,7 @@ window.__ModuleLoader__.load({
|
|
|
1634
1828
|
description: tool.description,
|
|
1635
1829
|
schema: tool.schema,
|
|
1636
1830
|
rich,
|
|
1831
|
+
lines: lineLabel,
|
|
1637
1832
|
labels
|
|
1638
1833
|
}));
|
|
1639
1834
|
});
|
|
@@ -1673,10 +1868,10 @@ window.__ModuleLoader__.load({
|
|
|
1673
1868
|
summary: t("block.summary"),
|
|
1674
1869
|
images: t("attach.images"),
|
|
1675
1870
|
other: t("attach.other"),
|
|
1676
|
-
lines:
|
|
1871
|
+
lines: lineLabel,
|
|
1677
1872
|
callState: (err, exit) => /* @__PURE__ */ React.createElement("span", { className: "lc-ts-call-state " + (err ? "lc-ts-call-err" : "lc-ts-call-ok") }, /* @__PURE__ */ React.createElement("i", null), err ? t("call.fail") + (exit !== null ? " · " + t("call.exit", { n: exit }) : "") : t("call.ok"))
|
|
1678
1873
|
},
|
|
1679
|
-
hint: conv === void 0
|
|
1874
|
+
hint: conv === void 0 ? missNote : t("browser.noContent")
|
|
1680
1875
|
}), rowErr);
|
|
1681
1876
|
});
|
|
1682
1877
|
};
|
|
@@ -1719,12 +1914,15 @@ window.__ModuleLoader__.load({
|
|
|
1719
1914
|
}, /* @__PURE__ */ React.createElement("button", {
|
|
1720
1915
|
type: "button",
|
|
1721
1916
|
className: "lc-br-cat-row" + (linked && props.hoverKey === c.key ? " lc-br-cat-on" : ""),
|
|
1917
|
+
/* v8 ignore start -- the handlers exist only when linked,
|
|
1918
|
+
and linked already requires onHoverKey defined (above). */
|
|
1722
1919
|
onMouseEnter: linked ? () => {
|
|
1723
1920
|
if (props.onHoverKey !== void 0) props.onHoverKey(c.key);
|
|
1724
1921
|
} : void 0,
|
|
1725
1922
|
onMouseLeave: linked ? () => {
|
|
1726
1923
|
if (props.onHoverKey !== void 0) props.onHoverKey(null);
|
|
1727
1924
|
} : void 0,
|
|
1925
|
+
/* v8 ignore stop */
|
|
1728
1926
|
onClick: () => {
|
|
1729
1927
|
toggleCat(c.key);
|
|
1730
1928
|
}
|
|
@@ -1880,26 +2078,7 @@ window.__ModuleLoader__.load({
|
|
|
1880
2078
|
parts: head.parts,
|
|
1881
2079
|
hoverKey: props.hoverKey,
|
|
1882
2080
|
onHoverKey: props.onHoverKey
|
|
1883
|
-
})
|
|
1884
|
-
type: "button",
|
|
1885
|
-
className: "lc-tools-label",
|
|
1886
|
-
onClick: () => {
|
|
1887
|
-
if (props.onToolFocus !== void 0) props.onToolFocus({});
|
|
1888
|
-
}
|
|
1889
|
-
}, t("tools.top")), props.tools.slice().sort((a, b) => b.tokens - a.tokens).slice(0, 5).map((tool) => /* @__PURE__ */ React.createElement("button", {
|
|
1890
|
-
key: tool.name,
|
|
1891
|
-
type: "button",
|
|
1892
|
-
className: "lc-tool-chip",
|
|
1893
|
-
onClick: () => {
|
|
1894
|
-
if (props.onToolFocus !== void 0) props.onToolFocus({ tool: tool.name });
|
|
1895
|
-
}
|
|
1896
|
-
}, tool.name + " " + fmt(tool.tokens))), props.tools.length > 5 ? /* @__PURE__ */ React.createElement("button", {
|
|
1897
|
-
type: "button",
|
|
1898
|
-
className: "lc-tools-more",
|
|
1899
|
-
onClick: () => {
|
|
1900
|
-
if (props.onToolFocus !== void 0) props.onToolFocus({});
|
|
1901
|
-
}
|
|
1902
|
-
}, t("tools.more", { n: props.tools.length })) : null) : null);
|
|
2081
|
+
}));
|
|
1903
2082
|
};
|
|
1904
2083
|
}
|
|
1905
2084
|
//#endregion
|
|
@@ -1943,7 +2122,7 @@ window.__ModuleLoader__.load({
|
|
|
1943
2122
|
const breakdown = typeof props.useProjection === "function" ? contextBreakdownOf(props.useProjection("contextBreakdown")) : null;
|
|
1944
2123
|
const headers = typeof props.useProjection === "function" ? headersOf(props.useProjection("contextHeaders")) : null;
|
|
1945
2124
|
const [hoverCat, setHoverCat] = React.useState(null);
|
|
1946
|
-
const
|
|
2125
|
+
const fetchContent = React.useMemo(() => sessionId !== "" ? makeContentFetcher(ctx, sessionId) : void 0, [ctx, sessionId]);
|
|
1947
2126
|
const close = React.useCallback(() => {
|
|
1948
2127
|
if (sessionId === "") return;
|
|
1949
2128
|
modalStoreOf(sessionId).set(false);
|
|
@@ -1986,20 +2165,14 @@ window.__ModuleLoader__.load({
|
|
|
1986
2165
|
head,
|
|
1987
2166
|
subtitle,
|
|
1988
2167
|
hoverKey: hoverCat,
|
|
1989
|
-
onHoverKey: setHoverCat
|
|
1990
|
-
tools: data.toolList,
|
|
1991
|
-
onToolFocus: setToolFocus
|
|
2168
|
+
onHoverKey: setHoverCat
|
|
1992
2169
|
}), /* @__PURE__ */ React.createElement(ContextBrowser, {
|
|
1993
2170
|
data,
|
|
1994
2171
|
headers,
|
|
1995
2172
|
useSession: props.useSession,
|
|
1996
|
-
|
|
2173
|
+
fetchContent,
|
|
1997
2174
|
hoverKey: hoverCat,
|
|
1998
|
-
onHoverKey: setHoverCat
|
|
1999
|
-
toolFocus,
|
|
2000
|
-
onToolFocusHandled: () => {
|
|
2001
|
-
setToolFocus(null);
|
|
2002
|
-
}
|
|
2175
|
+
onHoverKey: setHoverCat
|
|
2003
2176
|
}))));
|
|
2004
2177
|
}
|
|
2005
2178
|
return function ContextModal(props) {
|
|
@@ -2082,6 +2255,27 @@ window.__ModuleLoader__.load({
|
|
|
2082
2255
|
onPick: (id) => {
|
|
2083
2256
|
props.set?.("defaultTrendMode", id);
|
|
2084
2257
|
}
|
|
2258
|
+
}), /* @__PURE__ */ React.createElement(PrefRow, {
|
|
2259
|
+
label: t("settings.fileSort"),
|
|
2260
|
+
value: state.fileSort,
|
|
2261
|
+
disabled,
|
|
2262
|
+
options: [
|
|
2263
|
+
{
|
|
2264
|
+
id: "count",
|
|
2265
|
+
label: t("files.sort.count")
|
|
2266
|
+
},
|
|
2267
|
+
{
|
|
2268
|
+
id: "latest",
|
|
2269
|
+
label: t("files.sort.latest")
|
|
2270
|
+
},
|
|
2271
|
+
{
|
|
2272
|
+
id: "path",
|
|
2273
|
+
label: t("files.sort.path")
|
|
2274
|
+
}
|
|
2275
|
+
],
|
|
2276
|
+
onPick: (id) => {
|
|
2277
|
+
props.set?.("defaultFileSort", id);
|
|
2278
|
+
}
|
|
2085
2279
|
})) : null);
|
|
2086
2280
|
};
|
|
2087
2281
|
}
|
|
@@ -2092,7 +2286,8 @@ window.__ModuleLoader__.load({
|
|
|
2092
2286
|
const v = value;
|
|
2093
2287
|
return {
|
|
2094
2288
|
...v.defaultGranularity === "step" || v.defaultGranularity === "turn" ? { granularity: v.defaultGranularity } : {},
|
|
2095
|
-
...v.defaultTrendMode === "total" || v.defaultTrendMode === "delta" ? { mode: v.defaultTrendMode } : {}
|
|
2289
|
+
...v.defaultTrendMode === "total" || v.defaultTrendMode === "delta" ? { mode: v.defaultTrendMode } : {},
|
|
2290
|
+
...v.defaultFileSort === "count" || v.defaultFileSort === "latest" || v.defaultFileSort === "path" ? { fileSort: v.defaultFileSort } : {}
|
|
2096
2291
|
};
|
|
2097
2292
|
}
|
|
2098
2293
|
function createContextSettings() {
|
|
@@ -2100,12 +2295,13 @@ window.__ModuleLoader__.load({
|
|
|
2100
2295
|
status: "loading",
|
|
2101
2296
|
granularity: "step",
|
|
2102
2297
|
mode: "total",
|
|
2298
|
+
fileSort: "count",
|
|
2103
2299
|
writable: false
|
|
2104
2300
|
};
|
|
2105
2301
|
let scope;
|
|
2106
2302
|
const listeners = /* @__PURE__ */ new Set();
|
|
2107
2303
|
const publish = (next) => {
|
|
2108
|
-
if (next.status === state.status && next.granularity === state.granularity && next.mode === state.mode && next.writable === state.writable) return;
|
|
2304
|
+
if (next.status === state.status && next.granularity === state.granularity && next.mode === state.mode && next.fileSort === state.fileSort && next.writable === state.writable) return;
|
|
2109
2305
|
state = next;
|
|
2110
2306
|
for (const listener of listeners) listener();
|
|
2111
2307
|
};
|
|
@@ -2121,6 +2317,7 @@ window.__ModuleLoader__.load({
|
|
|
2121
2317
|
},
|
|
2122
2318
|
defaultGranularity: () => state.granularity,
|
|
2123
2319
|
defaultTrendMode: () => state.mode,
|
|
2320
|
+
defaultFileSort: () => state.fileSort,
|
|
2124
2321
|
attach(bound) {
|
|
2125
2322
|
scope = bound;
|
|
2126
2323
|
const sync = () => {
|
|
@@ -2130,6 +2327,7 @@ window.__ModuleLoader__.load({
|
|
|
2130
2327
|
status: snap.status === "ready" || snap.status === "unavailable" ? snap.status : "loading",
|
|
2131
2328
|
granularity: prefs.granularity ?? state.granularity,
|
|
2132
2329
|
mode: prefs.mode ?? state.mode,
|
|
2330
|
+
fileSort: prefs.fileSort ?? state.fileSort,
|
|
2133
2331
|
writable: snap.writable
|
|
2134
2332
|
});
|
|
2135
2333
|
};
|
|
@@ -2213,6 +2411,190 @@ window.__ModuleLoader__.load({
|
|
|
2213
2411
|
return m;
|
|
2214
2412
|
}
|
|
2215
2413
|
//#endregion
|
|
2414
|
+
//#region src/client/fileActivity.ts
|
|
2415
|
+
const KIND_BY_TOOL = {
|
|
2416
|
+
read: "read",
|
|
2417
|
+
read_image: "read",
|
|
2418
|
+
write: "write",
|
|
2419
|
+
edit: "write",
|
|
2420
|
+
grep: "search",
|
|
2421
|
+
glob: "search"
|
|
2422
|
+
};
|
|
2423
|
+
/** The file purpose of a tool, or null for non-file tools (bash, web_search…). */
|
|
2424
|
+
function kindOfTool(tool) {
|
|
2425
|
+
if (tool === void 0) return null;
|
|
2426
|
+
return KIND_BY_TOOL[tool] ?? null;
|
|
2427
|
+
}
|
|
2428
|
+
/**
|
|
2429
|
+
* The operation's target path: the path-ish argument of read/write tools;
|
|
2430
|
+
* for searches the narrowing `path`, else the pattern itself (a pathless
|
|
2431
|
+
* grep/glob's target IS the pattern — the workspace-wide search text).
|
|
2432
|
+
*/
|
|
2433
|
+
function pathOfArgs(tool, args) {
|
|
2434
|
+
if (args === null) return null;
|
|
2435
|
+
if (tool === "grep" || tool === "glob") {
|
|
2436
|
+
const p = args.path;
|
|
2437
|
+
if (typeof p === "string" && p !== "") return p;
|
|
2438
|
+
const pattern = args.pattern;
|
|
2439
|
+
return typeof pattern === "string" && pattern !== "" ? pattern : null;
|
|
2440
|
+
}
|
|
2441
|
+
for (const k of [
|
|
2442
|
+
"file_path",
|
|
2443
|
+
"filePath",
|
|
2444
|
+
"path"
|
|
2445
|
+
]) {
|
|
2446
|
+
const v = args[k];
|
|
2447
|
+
if (typeof v === "string" && v !== "") return v;
|
|
2448
|
+
}
|
|
2449
|
+
return null;
|
|
2450
|
+
}
|
|
2451
|
+
/** Rendered line count: '' is 0, a trailing newline closes its own line. */
|
|
2452
|
+
function linesOf(s) {
|
|
2453
|
+
if (s === "") return 0;
|
|
2454
|
+
let n = 0;
|
|
2455
|
+
for (let i = 0; i < s.length; i++) if (s[i] === "\n") n++;
|
|
2456
|
+
return s.endsWith("\n") ? n : n + 1;
|
|
2457
|
+
}
|
|
2458
|
+
/**
|
|
2459
|
+
* The signed line footprint of one call: an edit removes its old string and
|
|
2460
|
+
* adds its new one; a write adds its content (the pre-existing body, if any,
|
|
2461
|
+
* is unknowable from the arguments — the estimate stays honest about that).
|
|
2462
|
+
* Callers reach here only with parsed args (a null parse yields no path).
|
|
2463
|
+
*/
|
|
2464
|
+
function deltaOf(tool, args) {
|
|
2465
|
+
if (tool === "edit") {
|
|
2466
|
+
const oldS = args.old_string;
|
|
2467
|
+
const newS = args.new_string;
|
|
2468
|
+
return {
|
|
2469
|
+
added: typeof newS === "string" ? linesOf(newS) : 0,
|
|
2470
|
+
removed: typeof oldS === "string" ? linesOf(oldS) : 0
|
|
2471
|
+
};
|
|
2472
|
+
}
|
|
2473
|
+
if (tool === "write") {
|
|
2474
|
+
const content = args.content;
|
|
2475
|
+
return {
|
|
2476
|
+
added: typeof content === "string" ? linesOf(content) : 0,
|
|
2477
|
+
removed: 0
|
|
2478
|
+
};
|
|
2479
|
+
}
|
|
2480
|
+
return {
|
|
2481
|
+
added: 0,
|
|
2482
|
+
removed: 0
|
|
2483
|
+
};
|
|
2484
|
+
}
|
|
2485
|
+
const IMAGE_EXT = /\.(png|jpe?g|gif|webp|svg|bmp|ico|avif)$/i;
|
|
2486
|
+
/** The file's form — multimodal reads and image extensions scan apart; a trailing slash marks a directory target. */
|
|
2487
|
+
function formOf(tool, path) {
|
|
2488
|
+
if (tool === "read_image" || IMAGE_EXT.test(path)) return "image";
|
|
2489
|
+
if (path.endsWith("/")) return "dir";
|
|
2490
|
+
return "text";
|
|
2491
|
+
}
|
|
2492
|
+
/** Fold every served tool-result node into per-file activity. */
|
|
2493
|
+
function activityOf(nodes, convOf, before) {
|
|
2494
|
+
const totals = {
|
|
2495
|
+
read: {
|
|
2496
|
+
files: 0,
|
|
2497
|
+
ops: 0
|
|
2498
|
+
},
|
|
2499
|
+
write: {
|
|
2500
|
+
files: 0,
|
|
2501
|
+
ops: 0
|
|
2502
|
+
},
|
|
2503
|
+
search: {
|
|
2504
|
+
files: 0,
|
|
2505
|
+
ops: 0
|
|
2506
|
+
},
|
|
2507
|
+
image: {
|
|
2508
|
+
files: 0,
|
|
2509
|
+
ops: 0
|
|
2510
|
+
},
|
|
2511
|
+
added: 0,
|
|
2512
|
+
removed: 0
|
|
2513
|
+
};
|
|
2514
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
2515
|
+
let unresolved = 0;
|
|
2516
|
+
for (const n of nodes) {
|
|
2517
|
+
if (n.cat !== "tool") continue;
|
|
2518
|
+
if (before !== null && n.seq >= before) continue;
|
|
2519
|
+
const kind = kindOfTool(n.tool);
|
|
2520
|
+
if (kind === null) continue;
|
|
2521
|
+
const tool = n.tool;
|
|
2522
|
+
totals[kind].ops++;
|
|
2523
|
+
const conv = convOf(n.seq);
|
|
2524
|
+
const args = parseCallArgs(conv?.call?.argsRaw);
|
|
2525
|
+
const path = pathOfArgs(tool, args);
|
|
2526
|
+
if (args === null || path === null) {
|
|
2527
|
+
unresolved++;
|
|
2528
|
+
continue;
|
|
2529
|
+
}
|
|
2530
|
+
const { added, removed } = deltaOf(tool, args);
|
|
2531
|
+
const detail = kind === "search" && typeof args.path === "string" && args.path !== "" && typeof args.pattern === "string" && args.pattern !== "" ? args.pattern : void 0;
|
|
2532
|
+
const op = {
|
|
2533
|
+
seq: n.seq,
|
|
2534
|
+
...n.gone !== void 0 ? { gone: n.gone } : {},
|
|
2535
|
+
kind,
|
|
2536
|
+
tool,
|
|
2537
|
+
...n.time !== void 0 ? { time: n.time } : {},
|
|
2538
|
+
err: n.err === true || conv.isError === true,
|
|
2539
|
+
added,
|
|
2540
|
+
removed,
|
|
2541
|
+
...detail !== void 0 ? { detail } : {}
|
|
2542
|
+
};
|
|
2543
|
+
let entry = byPath.get(path);
|
|
2544
|
+
if (entry === void 0) {
|
|
2545
|
+
entry = {
|
|
2546
|
+
path,
|
|
2547
|
+
form: formOf(tool, path),
|
|
2548
|
+
reads: 0,
|
|
2549
|
+
writes: 0,
|
|
2550
|
+
searches: 0,
|
|
2551
|
+
added: 0,
|
|
2552
|
+
removed: 0,
|
|
2553
|
+
errs: 0,
|
|
2554
|
+
ops: []
|
|
2555
|
+
};
|
|
2556
|
+
byPath.set(path, entry);
|
|
2557
|
+
}
|
|
2558
|
+
if (kind === "read") entry.reads++;
|
|
2559
|
+
else if (kind === "write") entry.writes++;
|
|
2560
|
+
else entry.searches++;
|
|
2561
|
+
entry.added += added;
|
|
2562
|
+
entry.removed += removed;
|
|
2563
|
+
if (op.err) entry.errs++;
|
|
2564
|
+
entry.ops.push(op);
|
|
2565
|
+
}
|
|
2566
|
+
const entries = [...byPath.values()];
|
|
2567
|
+
for (const e of entries) {
|
|
2568
|
+
e.ops.sort((a, b) => b.seq - a.seq);
|
|
2569
|
+
if (e.reads > 0) totals.read.files++;
|
|
2570
|
+
if (e.writes > 0) totals.write.files++;
|
|
2571
|
+
if (e.searches > 0) totals.search.files++;
|
|
2572
|
+
if (e.form === "image") {
|
|
2573
|
+
totals.image.files++;
|
|
2574
|
+
totals.image.ops += e.ops.length;
|
|
2575
|
+
}
|
|
2576
|
+
totals.added += e.added;
|
|
2577
|
+
totals.removed += e.removed;
|
|
2578
|
+
}
|
|
2579
|
+
entries.sort((a, b) => b.ops[0].seq - a.ops[0].seq);
|
|
2580
|
+
return {
|
|
2581
|
+
entries,
|
|
2582
|
+
totals,
|
|
2583
|
+
unresolved
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
/**
|
|
2587
|
+
* The browser step whose assembled surface SHOWS an op's result node: the
|
|
2588
|
+
* first request dispatched after it while it was still alive (that step's
|
|
2589
|
+
* brief is where the result landed). A live node no request has consumed
|
|
2590
|
+
* yet reveals on the live surface; an archived node no retained step still
|
|
2591
|
+
* contains is not viewable anywhere (null → the row stays inert).
|
|
2592
|
+
*/
|
|
2593
|
+
function locateStepOf(requests, seq, gone) {
|
|
2594
|
+
for (const r of requests) if (r.seq > seq && (gone === void 0 || gone > r.seq)) return r.seq;
|
|
2595
|
+
return gone === void 0 ? "live" : null;
|
|
2596
|
+
}
|
|
2597
|
+
//#endregion
|
|
2216
2598
|
//#region src/client/components/events.tsx
|
|
2217
2599
|
const EVENT_ICONS = {
|
|
2218
2600
|
compaction: "✂",
|
|
@@ -2306,6 +2688,160 @@ window.__ModuleLoader__.load({
|
|
|
2306
2688
|
}));
|
|
2307
2689
|
};
|
|
2308
2690
|
}
|
|
2691
|
+
//#endregion
|
|
2692
|
+
//#region src/client/components/fileCard.tsx
|
|
2693
|
+
/** An expanded file lists at most this many ops before a "+n earlier" line. */
|
|
2694
|
+
const MAX_OPS = 8;
|
|
2695
|
+
function makeFileCard(kit, settings) {
|
|
2696
|
+
const { t, fmt, fmtTime } = kit;
|
|
2697
|
+
function formGlyph(form) {
|
|
2698
|
+
return form === "image" ? "🖼" : form === "dir" ? "📁" : "📄";
|
|
2699
|
+
}
|
|
2700
|
+
function matches(e, f) {
|
|
2701
|
+
if (f === "all") return true;
|
|
2702
|
+
if (f === "image") return e.form === "image";
|
|
2703
|
+
if (f === "read") return e.reads > 0;
|
|
2704
|
+
if (f === "write") return e.writes > 0;
|
|
2705
|
+
return e.searches > 0;
|
|
2706
|
+
}
|
|
2707
|
+
/** Signed line pair, harness diff semantics: growth on the success token, shrinkage on the error token. */
|
|
2708
|
+
function DeltaPair(props) {
|
|
2709
|
+
return /* @__PURE__ */ React.createElement("span", { className: "lc-fa-delta" }, props.added > 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-fa-up" }, "+" + fmt(props.added)) : null, props.removed > 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-fa-down" }, "−" + fmt(props.removed)) : null);
|
|
2710
|
+
}
|
|
2711
|
+
return function FileCard(props) {
|
|
2712
|
+
const { activity } = props;
|
|
2713
|
+
const [filter, setFilter] = React.useState("all");
|
|
2714
|
+
const [sort, setSort] = React.useState(() => settings.defaultFileSort());
|
|
2715
|
+
const [query, setQuery] = React.useState("");
|
|
2716
|
+
const [openPath, setOpenPath] = React.useState(null);
|
|
2717
|
+
const q = query.trim().toLowerCase();
|
|
2718
|
+
const countOf = (e) => filter === "read" ? e.reads : filter === "write" ? e.writes : filter === "search" ? e.searches : e.ops.length;
|
|
2719
|
+
const shown = activity.entries.filter((e) => matches(e, filter) && (q === "" || e.path.toLowerCase().includes(q))).sort((a, b) => sort === "count" ? countOf(b) - countOf(a) || b.ops[0].seq - a.ops[0].seq : sort === "latest" ? b.ops[0].seq - a.ops[0].seq : a.path < b.path ? -1 : 1);
|
|
2720
|
+
const chips = [
|
|
2721
|
+
{
|
|
2722
|
+
key: "all",
|
|
2723
|
+
files: activity.entries.length,
|
|
2724
|
+
ops: activity.totals.read.ops + activity.totals.write.ops + activity.totals.search.ops
|
|
2725
|
+
},
|
|
2726
|
+
{
|
|
2727
|
+
key: "read",
|
|
2728
|
+
files: activity.totals.read.files,
|
|
2729
|
+
ops: activity.totals.read.ops
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
key: "write",
|
|
2733
|
+
files: activity.totals.write.files,
|
|
2734
|
+
ops: activity.totals.write.ops
|
|
2735
|
+
},
|
|
2736
|
+
{
|
|
2737
|
+
key: "search",
|
|
2738
|
+
files: activity.totals.search.files,
|
|
2739
|
+
ops: activity.totals.search.ops
|
|
2740
|
+
},
|
|
2741
|
+
{
|
|
2742
|
+
key: "image",
|
|
2743
|
+
files: activity.totals.image.files,
|
|
2744
|
+
ops: activity.totals.image.ops
|
|
2745
|
+
}
|
|
2746
|
+
];
|
|
2747
|
+
const opLine = (op) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { className: "lc-fa-op-time" }, op.time !== void 0 ? fmtTime(op.time) : "—"), /* @__PURE__ */ React.createElement("span", { className: "lc-fa-op-tool" }, op.tool), op.detail !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-fa-op-detail" }, op.detail) : null, op.added + op.removed > 0 ? /* @__PURE__ */ React.createElement(DeltaPair, {
|
|
2748
|
+
added: op.added,
|
|
2749
|
+
removed: op.removed
|
|
2750
|
+
}) : null, op.err ? /* @__PURE__ */ React.createElement("span", {
|
|
2751
|
+
className: "lc-br-err-dot",
|
|
2752
|
+
title: t("node.failed")
|
|
2753
|
+
}) : null);
|
|
2754
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("files.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, props.scope)), activity.entries.length === 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-empty" }, t("files.empty")) : /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "lc-fa-ctl" }, /* @__PURE__ */ React.createElement("div", { className: "lc-gran" }, chips.map((c) => /* @__PURE__ */ React.createElement("button", {
|
|
2755
|
+
key: c.key,
|
|
2756
|
+
type: "button",
|
|
2757
|
+
className: "lc-gran-btn" + (filter === c.key ? " lc-gran-on" : "") + (c.key === "read" || c.key === "write" || c.key === "search" ? " lc-fa-chip-" + c.key : ""),
|
|
2758
|
+
title: t("files.chipTip", {
|
|
2759
|
+
files: c.files,
|
|
2760
|
+
ops: c.ops
|
|
2761
|
+
}),
|
|
2762
|
+
onClick: () => {
|
|
2763
|
+
setFilter((cur) => cur === c.key ? "all" : c.key);
|
|
2764
|
+
}
|
|
2765
|
+
}, t("files.kind." + c.key), /* @__PURE__ */ React.createElement("b", { className: "lc-fa-n" }, fmt(c.ops))))), /* @__PURE__ */ React.createElement("input", {
|
|
2766
|
+
className: "lc-fa-search",
|
|
2767
|
+
value: query,
|
|
2768
|
+
placeholder: t("files.search"),
|
|
2769
|
+
onChange: (ev) => {
|
|
2770
|
+
setQuery(ev.target.value);
|
|
2771
|
+
}
|
|
2772
|
+
})), /* @__PURE__ */ React.createElement("div", { className: "lc-fa-meta" }, /* @__PURE__ */ React.createElement("span", null, t("files.files", { n: activity.entries.length })), activity.totals.added + activity.totals.removed > 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-fa-meta-delta" }, /* @__PURE__ */ React.createElement(DeltaPair, {
|
|
2773
|
+
added: activity.totals.added,
|
|
2774
|
+
removed: activity.totals.removed
|
|
2775
|
+
}), /* @__PURE__ */ React.createElement("span", {
|
|
2776
|
+
className: "lc-fa-meta-tip",
|
|
2777
|
+
role: "tooltip"
|
|
2778
|
+
}, t("files.deltaTip"))) : null, /* @__PURE__ */ React.createElement("span", {
|
|
2779
|
+
className: "lc-gran lc-fa-sort",
|
|
2780
|
+
role: "group",
|
|
2781
|
+
title: t("files.sortTip")
|
|
2782
|
+
}, [
|
|
2783
|
+
"count",
|
|
2784
|
+
"latest",
|
|
2785
|
+
"path"
|
|
2786
|
+
].map((k) => /* @__PURE__ */ React.createElement("button", {
|
|
2787
|
+
key: k,
|
|
2788
|
+
type: "button",
|
|
2789
|
+
className: "lc-gran-btn" + (sort === k ? " lc-gran-on" : ""),
|
|
2790
|
+
onClick: () => {
|
|
2791
|
+
setSort(k);
|
|
2792
|
+
}
|
|
2793
|
+
}, t("files.sort." + k))))), shown.length === 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-empty" }, t("files.noMatch")) : /* @__PURE__ */ React.createElement("div", { className: "lc-fa-list" }, shown.map((e) => {
|
|
2794
|
+
const open = openPath === e.path;
|
|
2795
|
+
const trimmed = e.path.endsWith("/") ? e.path.slice(0, -1) : e.path;
|
|
2796
|
+
const slash = trimmed.lastIndexOf("/");
|
|
2797
|
+
const dir = slash >= 0 ? trimmed.slice(0, slash + 1) : "";
|
|
2798
|
+
const base = slash >= 0 ? trimmed.slice(slash + 1) : trimmed;
|
|
2799
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
2800
|
+
key: e.path,
|
|
2801
|
+
className: "lc-fa-item" + (open ? " lc-fa-item-on" : "")
|
|
2802
|
+
}, /* @__PURE__ */ React.createElement("button", {
|
|
2803
|
+
type: "button",
|
|
2804
|
+
className: "lc-fa-row",
|
|
2805
|
+
title: e.path,
|
|
2806
|
+
onClick: () => {
|
|
2807
|
+
setOpenPath(open ? null : e.path);
|
|
2808
|
+
}
|
|
2809
|
+
}, /* @__PURE__ */ React.createElement("span", { className: "lc-br-chev" + (open ? " lc-br-chev-on" : "") }, "▸"), /* @__PURE__ */ React.createElement("span", {
|
|
2810
|
+
className: "lc-fa-form",
|
|
2811
|
+
title: t("files.form." + e.form)
|
|
2812
|
+
}, formGlyph(e.form)), /* @__PURE__ */ React.createElement("span", { className: "lc-fa-path" }, dir !== "" ? /* @__PURE__ */ React.createElement("em", null, dir) : null, /* @__PURE__ */ React.createElement("b", null, base)), e.reads > 0 ? /* @__PURE__ */ React.createElement("span", {
|
|
2813
|
+
className: "lc-fa-badge lc-fa-b-read",
|
|
2814
|
+
title: t("files.kind.read")
|
|
2815
|
+
}, /* @__PURE__ */ React.createElement("i", null), fmt(e.reads)) : null, e.writes > 0 ? /* @__PURE__ */ React.createElement("span", {
|
|
2816
|
+
className: "lc-fa-badge lc-fa-b-write",
|
|
2817
|
+
title: t("files.kind.write")
|
|
2818
|
+
}, /* @__PURE__ */ React.createElement("i", null), fmt(e.writes)) : null, e.searches > 0 ? /* @__PURE__ */ React.createElement("span", {
|
|
2819
|
+
className: "lc-fa-badge lc-fa-b-search",
|
|
2820
|
+
title: t("files.kind.search")
|
|
2821
|
+
}, /* @__PURE__ */ React.createElement("i", null), fmt(e.searches)) : null, e.added + e.removed > 0 ? /* @__PURE__ */ React.createElement(DeltaPair, {
|
|
2822
|
+
added: e.added,
|
|
2823
|
+
removed: e.removed
|
|
2824
|
+
}) : null, e.errs > 0 ? /* @__PURE__ */ React.createElement("span", {
|
|
2825
|
+
className: "lc-br-err-dot",
|
|
2826
|
+
title: t("files.errs", { n: e.errs })
|
|
2827
|
+
}) : null, e.ops[0].time !== void 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-fa-time" }, fmtTime(e.ops[0].time)) : null), open ? /* @__PURE__ */ React.createElement("div", { className: "lc-fa-ops" }, e.ops.slice(0, MAX_OPS).map((op) => {
|
|
2828
|
+
const onLocate = props.onLocate;
|
|
2829
|
+
return onLocate !== void 0 ? /* @__PURE__ */ React.createElement("button", {
|
|
2830
|
+
key: op.seq,
|
|
2831
|
+
type: "button",
|
|
2832
|
+
className: "lc-fa-op lc-fa-op-link",
|
|
2833
|
+
title: t("files.locate"),
|
|
2834
|
+
onClick: () => {
|
|
2835
|
+
onLocate(op);
|
|
2836
|
+
}
|
|
2837
|
+
}, opLine(op)) : /* @__PURE__ */ React.createElement("div", {
|
|
2838
|
+
key: op.seq,
|
|
2839
|
+
className: "lc-fa-op"
|
|
2840
|
+
}, opLine(op));
|
|
2841
|
+
}), e.ops.length > MAX_OPS ? /* @__PURE__ */ React.createElement("div", { className: "lc-fa-more" }, t("files.moreOps", { n: e.ops.length - MAX_OPS })) : null) : null);
|
|
2842
|
+
}))), activity.unresolved > 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-fa-note" }, t("files.unresolved", { n: activity.unresolved })) : null);
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2309
2845
|
const PLUGIN_REPO = "https://github.com/bowenliang123/dsh-context";
|
|
2310
2846
|
const PLUGIN_REPO_SHORT = PLUGIN_REPO.replace(/^https?:\/\/github\.com\//, "");
|
|
2311
2847
|
//#endregion
|
|
@@ -2349,7 +2885,7 @@ window.__ModuleLoader__.load({
|
|
|
2349
2885
|
return function PluginInfo() {
|
|
2350
2886
|
const [latest, setLatest] = React.useState(null);
|
|
2351
2887
|
React.useEffect(() => {
|
|
2352
|
-
if ("0.
|
|
2888
|
+
if ("0.33.1".includes("-dev")) return;
|
|
2353
2889
|
let on = true;
|
|
2354
2890
|
fetchLatestVersion().then((v) => {
|
|
2355
2891
|
if (on && v) setLatest(v);
|
|
@@ -2358,8 +2894,8 @@ window.__ModuleLoader__.load({
|
|
|
2358
2894
|
on = false;
|
|
2359
2895
|
};
|
|
2360
2896
|
}, []);
|
|
2361
|
-
const update = latest !== null && isNewerVersion(latest, "0.
|
|
2362
|
-
const nameValue = ["dsh-context (v0.
|
|
2897
|
+
const update = latest !== null && isNewerVersion(latest, "0.33.1") ? latest : null;
|
|
2898
|
+
const nameValue = ["dsh-context (v0.33.1)"];
|
|
2363
2899
|
if (update) nameValue.push(/* @__PURE__ */ React.createElement("span", {
|
|
2364
2900
|
key: "update",
|
|
2365
2901
|
className: "lc-pi-update"
|
|
@@ -2394,6 +2930,8 @@ window.__ModuleLoader__.load({
|
|
|
2394
2930
|
}
|
|
2395
2931
|
/** One-line identity of a surface node: text preview, call breadcrumb, tool name, or a localized placeholder. */
|
|
2396
2932
|
function nodeLine(n, conv) {
|
|
2933
|
+
/* v8 ignore if -- chipParts returns for tool cats upstream; only
|
|
2934
|
+
inject-with-skill and drift nodes ever reach nodeLine. Defensive. */
|
|
2397
2935
|
if (n.cat === "tool") return callSummaryOf(conv) ?? n.tool ?? t("node.toolResult");
|
|
2398
2936
|
if (n.text !== void 0 && n.text !== "") return n.text;
|
|
2399
2937
|
if (n.skill !== void 0) return t("node.skillTag", { name: n.skill });
|
|
@@ -2401,10 +2939,65 @@ window.__ModuleLoader__.load({
|
|
|
2401
2939
|
const summary = blockSummaryOf(conv);
|
|
2402
2940
|
return n.calls.join(" › ") + (summary !== null ? " · " + summary : "");
|
|
2403
2941
|
}
|
|
2942
|
+
/* v8 ignore if -- chipParts returns for assistant cats upstream. Defensive. */
|
|
2404
2943
|
if (n.cat === "assistant") return t("node.empty");
|
|
2944
|
+
/* v8 ignore if -- inject nodes arrive only WITH a skill (the text/skill
|
|
2945
|
+
arms above return first); inject-without-skill never reaches nodeLine. */
|
|
2405
2946
|
if (n.cat === "inject") return t("form." + (n.form ?? "context"));
|
|
2406
2947
|
return t("node.nonText");
|
|
2407
2948
|
}
|
|
2949
|
+
/**
|
|
2950
|
+
* One line's anatomy — a compact FACT tag plus the preview text, mirroring the Context browser's element rows so a
|
|
2951
|
+
* brief line reads exactly like the browser row its click reveals: tool results tag the tool name (skill results the
|
|
2952
|
+
* skill name), assistant replies tag the call breadcrumb, injections tag the form, user messages tag image attachments.
|
|
2953
|
+
*/
|
|
2954
|
+
function chipParts(n, conv) {
|
|
2955
|
+
if (n.cat === "tool") {
|
|
2956
|
+
const summary = callSummaryOf(conv);
|
|
2957
|
+
if (n.skill !== void 0) return {
|
|
2958
|
+
tag: t("node.skillTag", { name: n.skill }),
|
|
2959
|
+
text: summary ?? ""
|
|
2960
|
+
};
|
|
2961
|
+
if (n.tool !== void 0) return {
|
|
2962
|
+
tag: n.tool,
|
|
2963
|
+
text: summary ?? ""
|
|
2964
|
+
};
|
|
2965
|
+
return {
|
|
2966
|
+
tag: null,
|
|
2967
|
+
text: summary ?? t("node.toolResult")
|
|
2968
|
+
};
|
|
2969
|
+
}
|
|
2970
|
+
if (n.cat === "assistant") {
|
|
2971
|
+
const names = n.calls !== void 0 && n.calls.length > 0 ? n.calls : callNamesOf(conv);
|
|
2972
|
+
const own = n.text !== void 0 && n.text !== "" ? n.text : blockSummaryOf(conv) ?? "";
|
|
2973
|
+
return {
|
|
2974
|
+
tag: names.length > 0 ? names.join(" › ") : null,
|
|
2975
|
+
text: own !== "" ? own : names.length > 0 ? "" : t("node.empty")
|
|
2976
|
+
};
|
|
2977
|
+
}
|
|
2978
|
+
if (n.cat === "inject" && n.skill === void 0) {
|
|
2979
|
+
const text = n.text !== void 0 && n.text !== "" ? n.form === "snapshot" ? t("node.snapshot") + n.text : n.text : "";
|
|
2980
|
+
return {
|
|
2981
|
+
tag: t("form." + (n.form ?? "context")),
|
|
2982
|
+
text
|
|
2983
|
+
};
|
|
2984
|
+
}
|
|
2985
|
+
if (n.cat === "user") {
|
|
2986
|
+
const imgs = n.imgs ?? 0;
|
|
2987
|
+
return {
|
|
2988
|
+
tag: imgs > 0 ? t("attach.image") + (imgs > 1 ? " ×" + String(imgs) : "") : null,
|
|
2989
|
+
text: n.text ?? ""
|
|
2990
|
+
};
|
|
2991
|
+
}
|
|
2992
|
+
return {
|
|
2993
|
+
tag: null,
|
|
2994
|
+
text: nodeLine(n, conv)
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2997
|
+
/** The native-title line for a fact+text pair: 'tag · text', degrading to whichever half exists. */
|
|
2998
|
+
function factTitle(tag, text) {
|
|
2999
|
+
return tag !== null ? text !== "" ? tag + " · " + text : tag : text;
|
|
3000
|
+
}
|
|
2408
3001
|
function BriefSection(props) {
|
|
2409
3002
|
const { opener, inputs, response } = props.brief;
|
|
2410
3003
|
if (opener === void 0 && inputs.length === 0 && response === void 0) return null;
|
|
@@ -2415,47 +3008,43 @@ window.__ModuleLoader__.load({
|
|
|
2415
3008
|
props.onLocate?.(n, false);
|
|
2416
3009
|
};
|
|
2417
3010
|
const MAX_CHIPS = 3;
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
3011
|
+
/**
|
|
3012
|
+
* The ONE content unit of the brief — inputs and the reply share the same chip anatomy (error dot, fact tag,
|
|
3013
|
+
* preview text). Input chips are compact and individually clickable (each locates its own node); the reply is a
|
|
3014
|
+
* single chip grown to the row's width, left inert because the row button already locates it.
|
|
3015
|
+
*/
|
|
3016
|
+
const nodeChip = (n, onClick, grow = false) => {
|
|
3017
|
+
const { tag, text } = chipParts(n, convOf(n.seq));
|
|
3018
|
+
return /* @__PURE__ */ React.createElement("span", {
|
|
3019
|
+
key: n.seq,
|
|
3020
|
+
className: "lc-brief-chip" + (grow ? " lc-brief-chip-grow" : "") + (onClick !== void 0 ? " lc-brief-chip-link" : ""),
|
|
3021
|
+
title: factTitle(tag, text) + hint,
|
|
3022
|
+
onClick
|
|
3023
|
+
}, n.err === true ? /* @__PURE__ */ React.createElement("span", { className: "lc-br-err-dot" }) : null, tag !== null ? /* @__PURE__ */ React.createElement("span", { className: "lc-brief-chip-tag" }, tag) : null, text !== "" ? /* @__PURE__ */ React.createElement("span", { className: "lc-brief-chip-text" }, text) : null);
|
|
3024
|
+
};
|
|
3025
|
+
const openerParts = opener !== void 0 ? chipParts(opener, convOf(opener.seq)) : null;
|
|
3026
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-brief" }, opener !== void 0 && openerParts !== null ? /* @__PURE__ */ React.createElement(BriefRow, {
|
|
2430
3027
|
tag: t("brief.turn"),
|
|
2431
3028
|
tagTip: t("brief.turnTip"),
|
|
2432
3029
|
node: opener,
|
|
2433
3030
|
isResponse: false,
|
|
2434
3031
|
onLocate: props.onLocate
|
|
2435
|
-
}, /* @__PURE__ */ React.createElement("span", {
|
|
3032
|
+
}, openerParts.tag !== null ? /* @__PURE__ */ React.createElement("span", { className: "lc-brief-fact" }, openerParts.tag) : null, openerParts.text !== "" ? /* @__PURE__ */ React.createElement("span", {
|
|
2436
3033
|
className: "lc-brief-text",
|
|
2437
|
-
title:
|
|
2438
|
-
},
|
|
3034
|
+
title: factTitle(openerParts.tag, openerParts.text) + hint
|
|
3035
|
+
}, openerParts.text) : null) : null, inputs.length > 0 ? /* @__PURE__ */ React.createElement(BriefRow, {
|
|
2439
3036
|
tag: t("brief.input"),
|
|
2440
3037
|
tagTip: t("brief.inputTip"),
|
|
2441
3038
|
node: inputs[0],
|
|
2442
3039
|
isResponse: false,
|
|
2443
3040
|
onLocate: props.onLocate
|
|
2444
|
-
}, inputs.slice(0, MAX_CHIPS).map((n) => /* @__PURE__ */ React.createElement("span", {
|
|
2445
|
-
key: n.seq,
|
|
2446
|
-
className: "lc-brief-chip" + (props.onLocate !== void 0 ? " lc-brief-chip-link" : ""),
|
|
2447
|
-
title: nodeLine(n, convOf(n.seq)) + hint,
|
|
2448
|
-
onClick: locateChip !== void 0 ? locateChip(n) : void 0
|
|
2449
|
-
}, n.err === true ? /* @__PURE__ */ React.createElement("span", { className: "lc-br-err-dot" }) : null, nodeLine(n, convOf(n.seq)))), inputs.length > MAX_CHIPS ? /* @__PURE__ */ React.createElement("span", { className: "lc-brief-more" }, t("brief.more", { n: inputs.length - MAX_CHIPS })) : null) : null, response !== void 0 ? /* @__PURE__ */ React.createElement(BriefRow, {
|
|
3041
|
+
}, inputs.slice(0, MAX_CHIPS).map((n) => nodeChip(n, locateChip?.(n))), inputs.length > MAX_CHIPS ? /* @__PURE__ */ React.createElement("span", { className: "lc-brief-more" }, t("brief.more", { n: inputs.length - MAX_CHIPS })) : null) : null, response !== void 0 ? /* @__PURE__ */ React.createElement(BriefRow, {
|
|
2450
3042
|
tag: t("brief.reply"),
|
|
2451
3043
|
tagTip: t("brief.replyTip"),
|
|
2452
3044
|
node: response,
|
|
2453
3045
|
isResponse: true,
|
|
2454
3046
|
onLocate: props.onLocate
|
|
2455
|
-
},
|
|
2456
|
-
className: "lc-brief-text",
|
|
2457
|
-
title: replyText + hint
|
|
2458
|
-
}, replyArrow ? "→ " : "", replyText)) : null);
|
|
3047
|
+
}, nodeChip(response, void 0, true)) : null);
|
|
2459
3048
|
}
|
|
2460
3049
|
return function RequestDetail(props) {
|
|
2461
3050
|
const req = props.request;
|
|
@@ -2463,6 +3052,8 @@ window.__ModuleLoader__.load({
|
|
|
2463
3052
|
const isTurn = req.stepCount !== void 0 && req.stepCount > 1;
|
|
2464
3053
|
const head = isTurn ? t("detail.turn", {
|
|
2465
3054
|
t: req.turn ?? 0,
|
|
3055
|
+
/* v8 ignore next -- isTurn already guarantees stepCount !== undefined;
|
|
3056
|
+
the fallback is defensive. */
|
|
2466
3057
|
n: req.stepCount ?? 0
|
|
2467
3058
|
}) : t("detail.step", {
|
|
2468
3059
|
t: req.turn ?? 0,
|
|
@@ -2894,6 +3485,8 @@ window.__ModuleLoader__.load({
|
|
|
2894
3485
|
};
|
|
2895
3486
|
React.useLayoutEffect(() => {
|
|
2896
3487
|
const el = scrollRef.current;
|
|
3488
|
+
/* v8 ignore next 1 -- the scroll div renders unconditionally and React
|
|
3489
|
+
attaches refs before layout effects run; el is never null here. */
|
|
2897
3490
|
if (el === null) return;
|
|
2898
3491
|
if (props.granularity !== lastGranRef.current) {
|
|
2899
3492
|
lastGranRef.current = props.granularity;
|
|
@@ -2925,6 +3518,8 @@ window.__ModuleLoader__.load({
|
|
|
2925
3518
|
const reply = props.replyTips?.get(req.seq);
|
|
2926
3519
|
const tail = reply !== void 0 ? " · “" + (reply.length > 48 ? reply.slice(0, 48) + "…" : reply) + "”" : "";
|
|
2927
3520
|
if (delta) {
|
|
3521
|
+
/* v8 ignore next 1 -- delta mode only receives records from
|
|
3522
|
+
deltaOf, which always assigns net; the fallback is defensive. */
|
|
2928
3523
|
const n = req.net ?? 0;
|
|
2929
3524
|
return head + " · " + fmtTime(req.time) + " · " + t("tip.delta", { n: (n > 0 ? "+" : "") + fmt(n) }) + tail;
|
|
2930
3525
|
}
|
|
@@ -3008,7 +3603,7 @@ window.__ModuleLoader__.load({
|
|
|
3008
3603
|
const TrendChart = makeTrendChart(kit);
|
|
3009
3604
|
const RequestDetail = makeRequestDetail(kit, StackedBar);
|
|
3010
3605
|
const EventList = makeEventList(kit);
|
|
3011
|
-
const
|
|
3606
|
+
const FileCard = makeFileCard(kit, settings);
|
|
3012
3607
|
const StatsBoard = makeStatsBoard(kit);
|
|
3013
3608
|
const PluginInfo = makePluginInfo(kit);
|
|
3014
3609
|
const ContextBrowser = makeContextBrowser(kit, StackedBar);
|
|
@@ -3035,10 +3630,6 @@ window.__ModuleLoader__.load({
|
|
|
3035
3630
|
return p.length === 1 ? [...EVENT_KINDS] : p.filter((x) => x !== k);
|
|
3036
3631
|
});
|
|
3037
3632
|
};
|
|
3038
|
-
const [toolFocus, setToolFocus] = React.useState(null);
|
|
3039
|
-
const clearToolFocus = React.useCallback(() => {
|
|
3040
|
-
setToolFocus(null);
|
|
3041
|
-
}, []);
|
|
3042
3633
|
const [nodeFocus, setNodeFocus] = React.useState(null);
|
|
3043
3634
|
const clearNodeFocus = React.useCallback(() => {
|
|
3044
3635
|
setNodeFocus(null);
|
|
@@ -3049,6 +3640,7 @@ window.__ModuleLoader__.load({
|
|
|
3049
3640
|
if (conversation === void 0 || typeof conversation.resolveImage !== "function") return void 0;
|
|
3050
3641
|
return (attachment) => conversation.resolveImage(sessionId, attachment);
|
|
3051
3642
|
}, [sessionId]);
|
|
3643
|
+
const fetchContent = React.useMemo(() => typeof sessionId === "string" && sessionId !== "" ? makeContentFetcher(ctx, sessionId) : void 0, [ctx, sessionId]);
|
|
3052
3644
|
const rootRef = React.useRef(null);
|
|
3053
3645
|
const scrollerRef = React.useRef(null);
|
|
3054
3646
|
const restoredRef = React.useRef(null);
|
|
@@ -3056,6 +3648,8 @@ window.__ModuleLoader__.load({
|
|
|
3056
3648
|
if (typeof sessionId !== "string" || sessionId === "" || data === null) return;
|
|
3057
3649
|
if (restoredRef.current === sessionId) return;
|
|
3058
3650
|
restoredRef.current = sessionId;
|
|
3651
|
+
/* v8 ignore next 3 -- a layout effect body only runs while mounted and
|
|
3652
|
+
both render paths attach rootRef, so the null arm cannot fire. */
|
|
3059
3653
|
const scroller = rootRef.current !== null ? rootRef.current.closest("[data-conversation-scroll]") : null;
|
|
3060
3654
|
if (scroller === null) return;
|
|
3061
3655
|
scrollerRef.current = scroller;
|
|
@@ -3072,7 +3666,6 @@ window.__ModuleLoader__.load({
|
|
|
3072
3666
|
const requests = data ? data.requests : [];
|
|
3073
3667
|
const events = data ? data.events : [];
|
|
3074
3668
|
const shownEvents = pickedKinds.length === EVENT_KINDS.length ? events : events.filter((e) => pickedKinds.includes(e.kind));
|
|
3075
|
-
const nodes = data ? data.nodes : [];
|
|
3076
3669
|
const displayRequests = React.useMemo(() => granularity === "turn" ? aggregateByTurn(requests) : requests, [requests, granularity]);
|
|
3077
3670
|
const markers = React.useMemo(() => attachMarkers(displayRequests, events), [displayRequests, events]);
|
|
3078
3671
|
const briefList = React.useMemo(() => data ? briefNodes(data) : [], [data]);
|
|
@@ -3089,6 +3682,8 @@ window.__ModuleLoader__.load({
|
|
|
3089
3682
|
}, /* @__PURE__ */ React.createElement("div", { className: "lc-empty" }, t("loading")));
|
|
3090
3683
|
const markerOf = (req) => {
|
|
3091
3684
|
const i = displayRequests.indexOf(req);
|
|
3685
|
+
/* v8 ignore next 1 -- the only caller passes displayRequests[activeIdx],
|
|
3686
|
+
an element of the very array indexOf scans. */
|
|
3092
3687
|
return i >= 0 ? markers[i] : void 0;
|
|
3093
3688
|
};
|
|
3094
3689
|
let pinnedIdx = -1;
|
|
@@ -3106,7 +3701,32 @@ window.__ModuleLoader__.load({
|
|
|
3106
3701
|
const activeReq = activeIdx >= 0 ? displayRequests[activeIdx] : null;
|
|
3107
3702
|
const brief = activeReq !== null ? briefOf(briefList, displayRequests, activeIdx) : null;
|
|
3108
3703
|
const convOf = (seq) => bySeq.get(seq);
|
|
3704
|
+
let filesBefore = null;
|
|
3705
|
+
if (activeReq !== null) {
|
|
3706
|
+
const ri = requests.findIndex((r) => r.seq === activeReq.seq);
|
|
3707
|
+
filesBefore = ri + 1 < requests.length ? requests[ri + 1].seq : null;
|
|
3708
|
+
}
|
|
3709
|
+
let fileScope = t("files.scopeLatest");
|
|
3710
|
+
if (activeReq !== null && filesBefore !== null) fileScope = activeReq.stepCount !== void 0 && activeReq.stepCount > 1 ? t("detail.turn", {
|
|
3711
|
+
t: activeReq.turn ?? 0,
|
|
3712
|
+
n: activeReq.stepCount
|
|
3713
|
+
}) : t("detail.step", {
|
|
3714
|
+
t: activeReq.turn ?? 0,
|
|
3715
|
+
s: activeReq.step ?? 0
|
|
3716
|
+
});
|
|
3717
|
+
const fileActivity = activityOf(briefList, convOf, filesBefore);
|
|
3718
|
+
const locateFileOp = (op) => {
|
|
3719
|
+
const step = locateStepOf(requests, op.seq, op.gone);
|
|
3720
|
+
if (step === null) return;
|
|
3721
|
+
setNodeFocus({
|
|
3722
|
+
step,
|
|
3723
|
+
seq: op.seq,
|
|
3724
|
+
cat: "tool"
|
|
3725
|
+
});
|
|
3726
|
+
};
|
|
3109
3727
|
const locateNode = (node, isResponse) => {
|
|
3728
|
+
/* v8 ignore next 1 -- locateNode is only wired to brief rows, and
|
|
3729
|
+
brief !== null guarantees activeReq !== null in the same closure. */
|
|
3110
3730
|
if (activeReq === null) return;
|
|
3111
3731
|
const next = isResponse && activeIdx + 1 < displayRequests.length ? displayRequests[activeIdx + 1] : null;
|
|
3112
3732
|
const step = isResponse ? next !== null ? next.seq : "live" : activeReq.seq;
|
|
@@ -3141,9 +3761,7 @@ window.__ModuleLoader__.load({
|
|
|
3141
3761
|
head,
|
|
3142
3762
|
subtitle: (data.model ? data.model : "") + (data.provider ? " · " + data.provider : ""),
|
|
3143
3763
|
hoverKey: hoverCat,
|
|
3144
|
-
onHoverKey: setHoverCat
|
|
3145
|
-
tools: data.toolList,
|
|
3146
|
-
onToolFocus: setToolFocus
|
|
3764
|
+
onHoverKey: setHoverCat
|
|
3147
3765
|
}), /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("trend.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("trend.hint")), /* @__PURE__ */ React.createElement("div", { className: "lc-trend-ctl" }, /* @__PURE__ */ React.createElement("div", { className: "lc-gran" }, /* @__PURE__ */ React.createElement("button", {
|
|
3148
3766
|
className: "lc-gran-btn" + (granularity === "step" ? " lc-gran-on" : ""),
|
|
3149
3767
|
onClick: () => {
|
|
@@ -3191,6 +3809,9 @@ window.__ModuleLoader__.load({
|
|
|
3191
3809
|
}), /* @__PURE__ */ React.createElement(RequestDetail, {
|
|
3192
3810
|
request: activeReq,
|
|
3193
3811
|
prev: trendMode === "delta" && activeIdx >= 0 ? activeIdx > 0 ? displayRequests[activeIdx - 1] : null : void 0,
|
|
3812
|
+
/* v8 ignore next 1 -- RequestDetail renders only when
|
|
3813
|
+
displayRequests.length > 0, which forces activeReq
|
|
3814
|
+
non-null via the activeIdx fallback above. */
|
|
3194
3815
|
marker: activeReq !== null ? markerOf(activeReq) : void 0,
|
|
3195
3816
|
brief,
|
|
3196
3817
|
convOf,
|
|
@@ -3199,13 +3820,11 @@ window.__ModuleLoader__.load({
|
|
|
3199
3820
|
data,
|
|
3200
3821
|
headers,
|
|
3201
3822
|
useSession: props.useSession,
|
|
3202
|
-
|
|
3823
|
+
fetchContent,
|
|
3203
3824
|
previewSeq: hoveredSeq,
|
|
3204
3825
|
pinSeq: pinnedReq !== null ? pinnedReq.seq : null,
|
|
3205
3826
|
hoverKey: hoverCat,
|
|
3206
3827
|
onHoverKey: setHoverCat,
|
|
3207
|
-
toolFocus,
|
|
3208
|
-
onToolFocusHandled: clearToolFocus,
|
|
3209
3828
|
nodeFocus,
|
|
3210
3829
|
onNodeFocusHandled: clearNodeFocus,
|
|
3211
3830
|
loadImage
|
|
@@ -3215,10 +3834,11 @@ window.__ModuleLoader__.load({
|
|
|
3215
3834
|
onClick: () => {
|
|
3216
3835
|
toggleKind(k);
|
|
3217
3836
|
}
|
|
3218
|
-
}, t("kind." + k))))), /* @__PURE__ */ React.createElement(EventList, { events: shownEvents })), /* @__PURE__ */ React.createElement(
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3837
|
+
}, t("kind." + k))))), /* @__PURE__ */ React.createElement(EventList, { events: shownEvents })), /* @__PURE__ */ React.createElement(FileCard, {
|
|
3838
|
+
activity: fileActivity,
|
|
3839
|
+
scope: fileScope,
|
|
3840
|
+
onLocate: locateFileOp
|
|
3841
|
+
})), /* @__PURE__ */ React.createElement("div", { className: "lc-foot" }, t("footer")));
|
|
3222
3842
|
}
|
|
3223
3843
|
return function ContextView(props) {
|
|
3224
3844
|
return h(ErrorBoundary, null, h(ContextViewBody, props));
|
|
@@ -3239,7 +3859,7 @@ window.__ModuleLoader__.load({
|
|
|
3239
3859
|
}
|
|
3240
3860
|
//#endregion
|
|
3241
3861
|
//#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles.css.mjs
|
|
3242
|
-
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{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,.lc-node 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-tools{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:6px;margin-top:10px;display:flex}.lc-tools-label,.lc-tools-more{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;padding:0;font-family:inherit;font-size:12px}.lc-tools-label:hover,.lc-tools-more:hover{text-decoration:underline}.lc-tool-chip{background:var(--dsw-alias-bg-layer-2);font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:0;border-radius:4px;padding:1px 7px;font-size:12px}.lc-tool-chip:hover{text-decoration:underline}.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-scroll{scrollbar-width:thin;scrollbar-gutter:stable;flex:1;min-width:0;padding-bottom:8px;position:relative;overflow:auto hidden}.lc-chart-fade{pointer-events:none;z-index:2;width:26px;position:absolute;top:0;bottom:0}.lc-chart-fade-l{background:linear-gradient(to right, var(--dsw-alias-bg-layer-1), transparent);left:0}.lc-chart-fade-r{background:linear-gradient(to left, var(--dsw-alias-bg-layer-1), transparent);right:0}.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;transform:translate(-50%);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:1fr 1fr;gap:4px 24px;margin-top:10px;display:grid}.lc-brief{flex-direction:column;gap:2px;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-chip{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);max-width:220px;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-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-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-nodes{flex-direction:column;gap:2px;max-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-node{align-items:center;gap:8px;padding:3px 0;display:flex}.lc-node-preview{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);flex:1;overflow:hidden}.lc-node-time{color:var(--dsw-alias-label-secondary);text-align:right;min-width:54px;font-size:12px}.lc-node-tokens{color:var(--dsw-alias-label-secondary)}.lc-nodes-more{color:var(--dsw-alias-label-secondary);padding:3px 0}.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-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;color:var(--dsw-alias-label-secondary);flex:none;transition:transform .12s}.lc-br-chev-on{transform:rotate(90deg)}.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{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;flex:none;max-width:220px;padding:0 6px;font-size:11px;overflow:hidden}.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-param-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:140px 90px 56px 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);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;white-space:pre-line;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{margin:6px 0}.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}";
|
|
3862
|
+
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{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-scroll{scrollbar-width:thin;scrollbar-gutter:stable;flex:1;min-width:0;padding-bottom:8px;position:relative;overflow:auto hidden}.lc-chart-fade{pointer-events:none;z-index:2;width:26px;position:absolute;top:0;bottom:0}.lc-chart-fade-l{background:linear-gradient(to right, var(--dsw-alias-bg-layer-1), transparent);left:0}.lc-chart-fade-r{background:linear-gradient(to left, var(--dsw-alias-bg-layer-1), transparent);right:0}.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;transform:translate(-50%);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:1fr 1fr;gap:4px 24px;margin-top:10px;display:grid}.lc-brief{flex-direction:column;gap:2px;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-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-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;max-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{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{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{border-color:var(--dsw-alias-label-dimmed)}.lc-fa-meta{color:var(--dsw-alias-label-secondary);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{text-align:center;opacity:.85;flex:none;width:16px;font-size:11px}.lc-fa-path{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.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{width:58px;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none}.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-more{color:var(--dsw-alias-label-secondary);padding:2px 6px;font-size:11px}.lc-fa-note{color:var(--dsw-alias-label-secondary);margin-top:8px;font-size:12px}.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;color:var(--dsw-alias-label-secondary);flex:none;transition:transform .12s}.lc-br-chev-on{transform:rotate(90deg)}.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{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;flex:none;max-width:220px;padding:0 6px;font-size:11px;overflow:hidden}.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-param-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:140px 90px 56px 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);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;white-space:pre-line;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{margin:6px 0}.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}";
|
|
3243
3863
|
const tagId = "dsh-context/styles.css";
|
|
3244
3864
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
3245
3865
|
const tag = document.createElement("style");
|
|
@@ -3284,19 +3904,6 @@ window.__ModuleLoader__.load({
|
|
|
3284
3904
|
const kit = makeViewKit(t);
|
|
3285
3905
|
const settings = createContextSettings();
|
|
3286
3906
|
const ContextView = makeContextView(ctx, kit, settings);
|
|
3287
|
-
ctx.effect(() => {
|
|
3288
|
-
const noop = () => {};
|
|
3289
|
-
const sessions = ctx.get("sessions");
|
|
3290
|
-
if (sessions === void 0 || typeof sessions.provide !== "function") return noop;
|
|
3291
|
-
try {
|
|
3292
|
-
return sessions.provide({
|
|
3293
|
-
props: ["loadOlderHistory"],
|
|
3294
|
-
resolve: (binding) => ({ props: { loadOlderHistory: () => binding.session.loadOlder() } })
|
|
3295
|
-
});
|
|
3296
|
-
} catch {
|
|
3297
|
-
return noop;
|
|
3298
|
-
}
|
|
3299
|
-
}, "dsh-context: loadOlderHistory prop");
|
|
3300
3907
|
ctx.slots.inject("conversation.view", () => {
|
|
3301
3908
|
return ctx.slots.register({
|
|
3302
3909
|
name: "conversation.view",
|
|
@@ -3314,7 +3921,7 @@ window.__ModuleLoader__.load({
|
|
|
3314
3921
|
id: "context-modal",
|
|
3315
3922
|
order: 10,
|
|
3316
3923
|
locale: NS,
|
|
3317
|
-
inject: (sessionId) => ({ hooks: { contextModal: modalStoreOf(sessionId) } })
|
|
3924
|
+
inject: (sessionId = "") => ({ hooks: { contextModal: modalStoreOf(sessionId) } })
|
|
3318
3925
|
}, (props) => h(ContextModal, props));
|
|
3319
3926
|
});
|
|
3320
3927
|
ctx.inject(["settingsScope"], (raw) => {
|