claude-discover 1.9.4 → 1.9.5
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/out/preload/preload.cjs
CHANGED
|
@@ -14,8 +14,8 @@ electron.contextBridge.exposeInMainWorld("api", {
|
|
|
14
14
|
deactivateSwitch: (name) => electron.ipcRenderer.invoke("switch:deactivate", name),
|
|
15
15
|
setSwitchKeepActive: (name, value) => electron.ipcRenderer.invoke("switch:keep-active", name, value),
|
|
16
16
|
listSessions: (date, granularity = "day") => electron.ipcRenderer.invoke("sessions:list", date, granularity),
|
|
17
|
-
readSession: (
|
|
18
|
-
readRequests: (
|
|
17
|
+
readSession: (filePath, date = null, granularity = "day") => electron.ipcRenderer.invoke("sessions:read", filePath, date, granularity),
|
|
18
|
+
readRequests: (filePath, date = null, granularity = "day") => electron.ipcRenderer.invoke("sessions:read-requests", filePath, date, granularity),
|
|
19
19
|
onSessionsUpdate: subscribe("sessions:update"),
|
|
20
20
|
onScanProgress: subscribe("sessions:scan-progress"),
|
|
21
21
|
getWorkHours: () => electron.ipcRenderer.invoke("work-hours:get"),
|
|
@@ -9,7 +9,7 @@ const SOURCE_COLORS = {
|
|
|
9
9
|
other: "#94a3b8"
|
|
10
10
|
};
|
|
11
11
|
const SOURCE_ORDER = ["cli", "claude-desktop", "sdk-cli", "sdk-ts", "sdk-py", "scheduled", "other"];
|
|
12
|
-
const SOURCE_LABELS = {
|
|
12
|
+
const SOURCE_LABELS$1 = {
|
|
13
13
|
scheduled: "Scheduled",
|
|
14
14
|
cli: "CLI",
|
|
15
15
|
"claude-desktop": "Desktop",
|
|
@@ -34,13 +34,13 @@ function useLocalStorage(key, initial) {
|
|
|
34
34
|
}
|
|
35
35
|
function clearOutdatedLocalStorage() {
|
|
36
36
|
const version = localStorage.getItem(VERSION_KEY);
|
|
37
|
-
if (version !== "1.9.
|
|
38
|
-
const [MAJOR, MINOR, PATCH] = "1.9.
|
|
37
|
+
if (version !== "1.9.5") {
|
|
38
|
+
const [MAJOR, MINOR, PATCH] = "1.9.5".split(".");
|
|
39
39
|
const [major, minor, patch] = (version ?? "").split(".");
|
|
40
40
|
if (MAJOR !== major || MINOR !== minor) {
|
|
41
41
|
localStorage.clear();
|
|
42
42
|
}
|
|
43
|
-
localStorage.setItem(VERSION_KEY, "1.9.
|
|
43
|
+
localStorage.setItem(VERSION_KEY, "1.9.5");
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
function useMouseFontScale(storageKey) {
|
|
@@ -104,12 +104,12 @@ function useMouse(ref, handlers) {
|
|
|
104
104
|
}
|
|
105
105
|
const isJournal = (s) => s.sessionId.endsWith("-journal");
|
|
106
106
|
function subagentsByParent(sessions) {
|
|
107
|
-
const
|
|
107
|
+
const parents = new Set(sessions.map((s) => s.filePath));
|
|
108
108
|
const byParent = /* @__PURE__ */ new Map();
|
|
109
109
|
for (const s of sessions) {
|
|
110
|
-
if (!
|
|
111
|
-
let arr = byParent.get(s.
|
|
112
|
-
if (!arr) byParent.set(s.
|
|
110
|
+
if (!parents.has(s.parentFilePath)) continue;
|
|
111
|
+
let arr = byParent.get(s.parentFilePath);
|
|
112
|
+
if (!arr) byParent.set(s.parentFilePath, arr = []);
|
|
113
113
|
arr.push(s);
|
|
114
114
|
}
|
|
115
115
|
return byParent;
|
|
@@ -365,7 +365,7 @@ function GanttChart({
|
|
|
365
365
|
}, []);
|
|
366
366
|
const { groups, totalHeight } = reactExports.useMemo(() => {
|
|
367
367
|
const clusters = subagentClusters(sessions, SUBAGENT_SPLIT_GAP).filter((c) => c.length >= 2);
|
|
368
|
-
const collapsed = new Set(clusters.flat().map((s) => s.
|
|
368
|
+
const collapsed = new Set(clusters.flat().map((s) => s.filePath));
|
|
369
369
|
const byKey = /* @__PURE__ */ new Map();
|
|
370
370
|
const addItem = (s, item, cost) => {
|
|
371
371
|
const key = s.project || "(no project)";
|
|
@@ -375,9 +375,9 @@ function GanttChart({
|
|
|
375
375
|
group.cost += cost || 0;
|
|
376
376
|
};
|
|
377
377
|
for (const s of sessions) {
|
|
378
|
-
if (collapsed.has(s.
|
|
378
|
+
if (collapsed.has(s.filePath)) continue;
|
|
379
379
|
addItem(s, {
|
|
380
|
-
id: s.
|
|
380
|
+
id: s.filePath,
|
|
381
381
|
label: s.summary || s.firstUserPrompt || s.firstUserCommand || s.sessionId,
|
|
382
382
|
start: s.startedAt,
|
|
383
383
|
end: endOf(s),
|
|
@@ -388,7 +388,7 @@ function GanttChart({
|
|
|
388
388
|
for (const subs of clusters) {
|
|
389
389
|
const periods = subs.map((c) => ({ start: c.startedAt, end: endOf(c) }));
|
|
390
390
|
addItem(subs[0], {
|
|
391
|
-
id: `${subs[0].
|
|
391
|
+
id: `${subs[0].filePath}::subagents`,
|
|
392
392
|
start: periods[0].start,
|
|
393
393
|
end: Math.max(...periods.map((p) => p.end)),
|
|
394
394
|
source: subs[0].source,
|
|
@@ -498,7 +498,7 @@ function GanttChart({
|
|
|
498
498
|
g.placed.map(({ item, lane }) => {
|
|
499
499
|
const y = g.yOffset + lane * (bar.height + bar.row_gap);
|
|
500
500
|
const color = SOURCE_COLORS[item.source] || SOURCE_COLORS.other;
|
|
501
|
-
const isSelected = item.subs ? item.subs.some((c) => c.
|
|
501
|
+
const isSelected = item.subs ? item.subs.some((c) => c.filePath === selectedId) : item.id === selectedId;
|
|
502
502
|
const periods = item.activityPeriods?.length ? item.activityPeriods : [{ start: item.start, end: item.end }];
|
|
503
503
|
const rawX1 = xFor(item.start);
|
|
504
504
|
const rawX2 = xFor(item.end);
|
|
@@ -509,7 +509,7 @@ function GanttChart({
|
|
|
509
509
|
"g",
|
|
510
510
|
{
|
|
511
511
|
className: `bar ${isSelected ? "selected" : ""}`,
|
|
512
|
-
onClick: () => onSelect(item.subs ? item.subs.at(-1).
|
|
512
|
+
onClick: () => onSelect(item.subs ? item.subs.at(-1).filePath : item.id),
|
|
513
513
|
children: [
|
|
514
514
|
/* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x, y, width: w, height: bar.height, rx: bar.radius, fill: color, className: "bar-fill" }),
|
|
515
515
|
periods.slice(0, -1).map((p, i) => {
|
|
@@ -521,7 +521,7 @@ function GanttChart({
|
|
|
521
521
|
item.subs && /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x, y, width: w, height: bar.height, rx: bar.radius, fill: "url(#gantt-subagent-hatch)", opacity: 0.5, pointerEvents: "none" }),
|
|
522
522
|
item.subs && /* @__PURE__ */ jsxRuntimeExports.jsx("text", { x: x + w / 2, y: y + bar.height / 2, textAnchor: "middle", dominantBaseline: "central", className: "gantt-bar-count", children: item.subCount }),
|
|
523
523
|
isSelected && /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x, y, width: w, height: bar.height, rx: bar.radius, className: "bar-outline" }),
|
|
524
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: `${item.subs ? `${item.subCount} subagents` : `${SOURCE_LABELS[item.source] || item.source} · ${item.label}`}
|
|
524
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: `${item.subs ? `${item.subCount} subagents` : `${SOURCE_LABELS$1[item.source] || item.source} · ${item.label}`}
|
|
525
525
|
${g.key}
|
|
526
526
|
${new Date(item.start).toLocaleString()} → ${new Date(item.end).toLocaleString()}` })
|
|
527
527
|
]
|
|
@@ -616,7 +616,7 @@ function Toolbar({
|
|
|
616
616
|
const dim = sourceFilter && !active2;
|
|
617
617
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: `legend-chip ${active2 ? "active" : ""} ${dim ? "dim" : ""}`, onClick: () => onToggleSourceFilter?.(k), children: [
|
|
618
618
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "swatch", style: { background: SOURCE_COLORS[k] || SOURCE_COLORS.other } }),
|
|
619
|
-
SOURCE_LABELS[k] || k
|
|
619
|
+
SOURCE_LABELS$1[k] || k
|
|
620
620
|
] }, k);
|
|
621
621
|
}) }),
|
|
622
622
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "gantt-toolbar-nav", children: [
|
|
@@ -701,6 +701,9 @@ function fmtNum(n) {
|
|
|
701
701
|
if (n == null) return "—";
|
|
702
702
|
return n.toLocaleString();
|
|
703
703
|
}
|
|
704
|
+
function fmtToolCalls({ toolCalls, skillCalls }) {
|
|
705
|
+
return skillCalls ? `${fmtNum(toolCalls)}, ${fmtNum(skillCalls)} skill${skillCalls === 1 ? "" : "s"}` : fmtNum(toolCalls);
|
|
706
|
+
}
|
|
704
707
|
function fmtUSD(n) {
|
|
705
708
|
if (n == null) return "—";
|
|
706
709
|
return `$${n.toFixed(2)}`;
|
|
@@ -882,6 +885,7 @@ const queuedPrompt = (it) => it.type === "attachment" && it.attachment?.type ===
|
|
|
882
885
|
function flatten(items, instructions = []) {
|
|
883
886
|
const turns = [];
|
|
884
887
|
const results = {};
|
|
888
|
+
const companions = {};
|
|
885
889
|
for (const it of items) {
|
|
886
890
|
const queued = queuedPrompt(it);
|
|
887
891
|
if (queued) {
|
|
@@ -901,6 +905,7 @@ function flatten(items, instructions = []) {
|
|
|
901
905
|
continue;
|
|
902
906
|
}
|
|
903
907
|
if (it.type === "attachment" && it.attachment) {
|
|
908
|
+
if (it.attachment.type === "structured_output" && it.attachment.toolUseID) continue;
|
|
904
909
|
const block = { type: "attachment", attachment: it.attachment };
|
|
905
910
|
const last = turns[turns.length - 1];
|
|
906
911
|
if (last && last.isMeta && last.blocks.every((b) => b.type === "attachment")) {
|
|
@@ -939,9 +944,19 @@ ${text}` }]
|
|
|
939
944
|
});
|
|
940
945
|
continue;
|
|
941
946
|
}
|
|
947
|
+
if (it.turnCompanion && it.sourceToolUseID) {
|
|
948
|
+
companions[it.sourceToolUseID] = companionText(it);
|
|
949
|
+
continue;
|
|
950
|
+
}
|
|
951
|
+
const command = it.turnCompanion && turns.findLast((t) => t.uuid === it.parentUuid);
|
|
952
|
+
if (command) {
|
|
953
|
+
const name = command.blocks.map((b) => parseCommand(b.text)?.name).find(Boolean)?.replace(/^\//, "");
|
|
954
|
+
command.blocks.push({ type: "skill", name, text: companionText(it) });
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
942
957
|
if (it.type !== "user" && it.type !== "assistant") continue;
|
|
943
958
|
const msg = it.message || {};
|
|
944
|
-
const blocks = normalizeContent(msg.content)
|
|
959
|
+
const blocks = collapseRedactedThinking(normalizeContent(msg.content));
|
|
945
960
|
if (blocks.length === 0) continue;
|
|
946
961
|
for (const b of blocks) {
|
|
947
962
|
if (b.type === "tool_result" && b.tool_use_id) results[b.tool_use_id] = b;
|
|
@@ -961,21 +976,21 @@ ${text}` }]
|
|
|
961
976
|
});
|
|
962
977
|
}
|
|
963
978
|
for (const t of turns) {
|
|
964
|
-
t.blocks = t.blocks.map((b) => b.type === "tool_use" ? { ...b, result: results[b.id] } : b).filter((b) => !(b.type === "tool_result" && results[b.tool_use_id]));
|
|
979
|
+
t.blocks = t.blocks.map((b) => b.type === "tool_use" ? { ...b, result: withCompanion(results[b.id], companions[b.id]) } : b).filter((b) => !(b.type === "tool_result" && results[b.tool_use_id]));
|
|
965
980
|
}
|
|
966
981
|
const out = turns.filter((t) => t.blocks.length > 0);
|
|
967
|
-
|
|
982
|
+
if (instructions.length) {
|
|
983
|
+
const first = instructions.find((it) => it.timestamp);
|
|
968
984
|
const turn = {
|
|
969
|
-
uuid:
|
|
970
|
-
// system prompts share a file_path, their hash disambiguates
|
|
985
|
+
uuid: "instructions",
|
|
971
986
|
role: "instruction",
|
|
972
987
|
isMeta: true,
|
|
973
|
-
ts:
|
|
988
|
+
ts: first ? Date.parse(first.timestamp) - 500 : null,
|
|
974
989
|
model: null,
|
|
975
990
|
usage: null,
|
|
976
991
|
tokenDelta: null,
|
|
977
992
|
tokenTotal: null,
|
|
978
|
-
blocks:
|
|
993
|
+
blocks: instructions.map((it) => ({ type: "instruction", it }))
|
|
979
994
|
};
|
|
980
995
|
const i = out.findIndex((t) => t.ts != null && t.ts > turn.ts);
|
|
981
996
|
i === -1 ? out.push(turn) : out.splice(i, 0, turn);
|
|
@@ -1003,6 +1018,21 @@ function contextWindow(models = []) {
|
|
|
1003
1018
|
const is200k = (model) => SMALL_CONTEXT.has(model.replace(/[-@]\d{8}.*$/, ""));
|
|
1004
1019
|
return models.some((m) => m && !is200k(m)) ? 1e6 : 2e5;
|
|
1005
1020
|
}
|
|
1021
|
+
function collapseRedactedThinking(blocks) {
|
|
1022
|
+
const out = [];
|
|
1023
|
+
for (const b of blocks) {
|
|
1024
|
+
if (!(b.type === "thinking" && !b.thinking?.trim())) {
|
|
1025
|
+
out.push(b);
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
const last = out[out.length - 1];
|
|
1029
|
+
if (last?.redacted) last.redacted++;
|
|
1030
|
+
else out.push({ type: "thinking", redacted: 1 });
|
|
1031
|
+
}
|
|
1032
|
+
return out;
|
|
1033
|
+
}
|
|
1034
|
+
const companionText = (it) => normalizeContent(it.message?.content).filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
1035
|
+
const withCompanion = (result, text) => text ? { ...result ?? { type: "tool_result" }, content: [...normalizeContent(result?.content), { type: "text", text }] } : result;
|
|
1006
1036
|
function normalizeContent(content) {
|
|
1007
1037
|
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
1008
1038
|
if (!Array.isArray(content)) return [];
|
|
@@ -1050,6 +1080,10 @@ function parseCommand(text) {
|
|
|
1050
1080
|
caveat: field("local-command-caveat")
|
|
1051
1081
|
};
|
|
1052
1082
|
}
|
|
1083
|
+
const SOURCE_LABELS = { system: "system prompt", tools: "tools", message: "user message" };
|
|
1084
|
+
function groupInstructions(strips) {
|
|
1085
|
+
return Object.entries(SOURCE_LABELS).map(([source, label]) => [label, strips.filter((it) => it.source === source)]).filter(([, list]) => list.length);
|
|
1086
|
+
}
|
|
1053
1087
|
function instructionTitle(it, model) {
|
|
1054
1088
|
const parts = [it.memory_type, it.model && it.model !== model && it.model].filter(Boolean).join(", ");
|
|
1055
1089
|
return parts ? `${it.name ?? it.file_path} (${parts})` : it.name ?? it.file_path;
|
|
@@ -1071,9 +1105,7 @@ function groupTurns(turns) {
|
|
|
1071
1105
|
else pending.push(t);
|
|
1072
1106
|
} else if (t.role === "instruction") {
|
|
1073
1107
|
flush();
|
|
1074
|
-
|
|
1075
|
-
if (prev?.kind === "instruction" && prev.turns.at(-1).ts === t.ts) prev.turns.push(t);
|
|
1076
|
-
else groups.push({ kind: "instruction", turns: [t] });
|
|
1108
|
+
groups.push({ kind: "instruction", turns: [t] });
|
|
1077
1109
|
} else if (t.role === "user") {
|
|
1078
1110
|
flush();
|
|
1079
1111
|
groups.push({ kind: "user", turns: [...pending, t] });
|
|
@@ -1148,11 +1180,11 @@ function SessionList({ sessions, selectedId, deepLink, onSelect }) {
|
|
|
1148
1180
|
const t = setInterval(() => tick((n) => n + 1), 6e4);
|
|
1149
1181
|
return () => clearInterval(t);
|
|
1150
1182
|
}, []);
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1183
|
+
const labelCommand = (s) => !(s.aiTitle || s.summary || s.firstUserPrompt) && parseCommand(s.firstUserCommand);
|
|
1184
|
+
const sessionLabel = (s) => {
|
|
1185
|
+
const c = labelCommand(s);
|
|
1186
|
+
return c ? `${c.name || c.message} ${c.args}` : s.aiTitle || s.summary || s.firstUserPrompt || s.sessionId || "";
|
|
1154
1187
|
};
|
|
1155
|
-
const sessionLabel = (s) => s.aiTitle || s.summary || s.firstUserPrompt || cmd(s.firstUserCommand) || s.sessionId || "";
|
|
1156
1188
|
const q = filter.trim().toLowerCase();
|
|
1157
1189
|
const filtered = q ? sessions.filter((s) => [
|
|
1158
1190
|
s.customTitle,
|
|
@@ -1170,9 +1202,9 @@ function SessionList({ sessions, selectedId, deepLink, onSelect }) {
|
|
|
1170
1202
|
const sorted = sortBy === "cost" ? [...filtered].sort((a, b) => (b.cost || 0) - (a.cost || 0)) : sortBy === "tokens" ? [...filtered].sort((a, b) => (b.totalTokens || 0) - (a.totalTokens || 0)) : sortBy === "name" ? [...filtered].sort((a, b) => sessionLabel(a).toLowerCase().localeCompare(sessionLabel(b).toLowerCase())) : filtered;
|
|
1171
1203
|
const grouped = reactExports.useMemo(() => {
|
|
1172
1204
|
const byParent = subagentsByParent(sorted);
|
|
1173
|
-
return sorted.flatMap((s) => byParent.has(s.
|
|
1205
|
+
return sorted.flatMap((s) => byParent.has(s.parentFilePath) ? [] : [
|
|
1174
1206
|
{ session: s, isChild: false },
|
|
1175
|
-
...(byParent.get(s.
|
|
1207
|
+
...(byParent.get(s.filePath) ?? []).map((c) => ({ session: c, isChild: true }))
|
|
1176
1208
|
]);
|
|
1177
1209
|
}, [sorted]);
|
|
1178
1210
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-list", children: [
|
|
@@ -1211,16 +1243,17 @@ function SessionList({ sessions, selectedId, deepLink, onSelect }) {
|
|
|
1211
1243
|
const isSubagent = s.sessionId.startsWith("agent-");
|
|
1212
1244
|
const journal = isJournal(s);
|
|
1213
1245
|
const isFork = !!s.forkedFrom;
|
|
1214
|
-
const linked = deepLink
|
|
1246
|
+
const linked = !!deepLink && s.filePath === selectedId;
|
|
1215
1247
|
const linkTip = linked && `Opened from deep link
|
|
1216
1248
|
claude-discover://session?id=${deepLink.id}${deepLink.date ? `&date=${deepLink.date}` : ""}`;
|
|
1249
|
+
const command = labelCommand(s);
|
|
1217
1250
|
const sessionName = s.customTitle && s.agentName && s.customTitle !== s.agentName ? `${s.customTitle} [${s.agentName}]` : s.customTitle || s.agentName || "";
|
|
1218
1251
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1219
1252
|
"div",
|
|
1220
1253
|
{
|
|
1221
|
-
ref: selectedId === s.
|
|
1222
|
-
className: `session-row ${selectedId === s.
|
|
1223
|
-
onClick: () => onSelect(selectedId === s.
|
|
1254
|
+
ref: selectedId === s.filePath ? selectedRef : null,
|
|
1255
|
+
className: `session-row ${selectedId === s.filePath ? "selected" : ""} ${isChild ? "is-subagent-child" : ""} ${linked ? "deep-linked" : ""}`,
|
|
1256
|
+
onClick: () => onSelect(selectedId === s.filePath ? null : s.filePath),
|
|
1224
1257
|
style: { borderLeftColor: SOURCE_COLORS[s.source] || SOURCE_COLORS.other },
|
|
1225
1258
|
children: [
|
|
1226
1259
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-row-main", children: [
|
|
@@ -1256,7 +1289,11 @@ ${TIPS.time}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 11
|
|
|
1256
1289
|
] }),
|
|
1257
1290
|
isFork && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "fork-tag", title: `Forked from session ${s.forkedFrom.sessionId}`, children: "↳" }),
|
|
1258
1291
|
sessionName && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "session-name", children: sessionName }),
|
|
1259
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "session-label-text", children:
|
|
1292
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "session-label-text", children: command ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
1293
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "session-command", children: command.name || command.message }),
|
|
1294
|
+
" ",
|
|
1295
|
+
command.args
|
|
1296
|
+
] }) : sessionLabel(s) })
|
|
1260
1297
|
] }),
|
|
1261
1298
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-time-bottom", children: [
|
|
1262
1299
|
s.project && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "session-project", title: s.project, children: s.projectShort }),
|
|
@@ -1271,7 +1308,7 @@ ${TIPS.time}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 11
|
|
|
1271
1308
|
] })
|
|
1272
1309
|
]
|
|
1273
1310
|
},
|
|
1274
|
-
s.
|
|
1311
|
+
s.filePath
|
|
1275
1312
|
);
|
|
1276
1313
|
})
|
|
1277
1314
|
] })
|
|
@@ -1342,7 +1379,9 @@ function fenceTags(text) {
|
|
|
1342
1379
|
if (close < 0) continue;
|
|
1343
1380
|
const end = close + m[1].length + 3;
|
|
1344
1381
|
if (end !== text.length && text[end] !== "\n" && text[end] !== "\r") continue;
|
|
1345
|
-
|
|
1382
|
+
const gap = text.slice(cursor, m.index);
|
|
1383
|
+
if (out && !gap.trim()) out = out.slice(0, -4) + gap + text.slice(m.index, end) + "\n```";
|
|
1384
|
+
else out += gap + "```xml\n" + text.slice(m.index, end) + "\n```";
|
|
1346
1385
|
cursor = startRe.lastIndex = end;
|
|
1347
1386
|
}
|
|
1348
1387
|
out += text.slice(cursor);
|
|
@@ -1495,6 +1534,7 @@ function AssistantCard({ turns, point, ctxLimit, duration: duration2, showAuthor
|
|
|
1495
1534
|
const [open, setOpen] = useCollapsed(false);
|
|
1496
1535
|
const toolBlocks = turns.flatMap((t) => t.blocks.filter((b) => b.type === "tool_use"));
|
|
1497
1536
|
const errorCount = toolBlocks.filter((b) => b.result?.is_error).length;
|
|
1537
|
+
const skillCount = toolBlocks.filter((b) => b.name === "Skill").length;
|
|
1498
1538
|
const isAux = (t) => !t.blocks.some((b) => b.type === "text");
|
|
1499
1539
|
const foldable = toolBlocks.length > 0 && turns.some(isAux);
|
|
1500
1540
|
const end = turns.findLast((t) => t.ts != null)?.ts ?? null;
|
|
@@ -1506,6 +1546,7 @@ function AssistantCard({ turns, point, ctxLimit, duration: duration2, showAuthor
|
|
|
1506
1546
|
const anyVisible = turns.some((t) => !hidden(t));
|
|
1507
1547
|
const parts = [
|
|
1508
1548
|
toolBlocks.length > 0 && `${toolBlocks.length} tool call${toolBlocks.length === 1 ? "" : "s"}`,
|
|
1549
|
+
skillCount > 0 && `${skillCount} skill${skillCount === 1 ? "" : "s"}`,
|
|
1509
1550
|
errorCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "msg-errors", children: [
|
|
1510
1551
|
errorCount,
|
|
1511
1552
|
" error",
|
|
@@ -1550,21 +1591,25 @@ function Block({ block }) {
|
|
|
1550
1591
|
const cmd = parseCommand(block.text);
|
|
1551
1592
|
if (cmd) {
|
|
1552
1593
|
if (!cmd.name && !cmd.args && !cmd.stdout && !cmd.caveat) return null;
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
" ",
|
|
1557
|
-
cmd.args
|
|
1594
|
+
const promptArgs = cmd.args.trim().includes("\n");
|
|
1595
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
1596
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "block-command", children: [
|
|
1597
|
+
cmd.name && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "cmd-name", children: cmd.name }),
|
|
1598
|
+
cmd.args && !promptArgs && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "cmd-args", children: [
|
|
1599
|
+
" ",
|
|
1600
|
+
cmd.args
|
|
1601
|
+
] }),
|
|
1602
|
+
cmd.stdout && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cmd-stdout", children: cmd.stdout }),
|
|
1603
|
+
cmd.caveat && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cmd-stdout", children: cmd.caveat })
|
|
1558
1604
|
] }),
|
|
1559
|
-
|
|
1560
|
-
cmd.caveat && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cmd-stdout", children: cmd.caveat })
|
|
1605
|
+
promptArgs && /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { className: "block-text", text: cmd.args, autoFence: true })
|
|
1561
1606
|
] });
|
|
1562
1607
|
}
|
|
1563
1608
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { className: "block-text", text: block.text, autoFence: true });
|
|
1564
1609
|
}
|
|
1565
1610
|
if (block.type === "thinking") {
|
|
1566
|
-
if (
|
|
1567
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { title: "
|
|
1611
|
+
if (block.redacted) return /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { title: `Thinking (encrypted${block.redacted > 1 ? ` · ${block.redacted}` : ""})` });
|
|
1612
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { title: "Thinking", defaultOpen: false, children: /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { children: block.thinking }) });
|
|
1568
1613
|
}
|
|
1569
1614
|
if (block.type === "tool_use") {
|
|
1570
1615
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Collapsible, { title: toolSummary(block.name, block.input), defaultOpen: false, children: [
|
|
@@ -1572,6 +1617,9 @@ function Block({ block }) {
|
|
|
1572
1617
|
block.result && /* @__PURE__ */ jsxRuntimeExports.jsx(Block, { block: block.result })
|
|
1573
1618
|
] });
|
|
1574
1619
|
}
|
|
1620
|
+
if (block.type === "skill") {
|
|
1621
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { title: block.name ? `Skill: ${block.name}` : "Skill", defaultOpen: false, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { className: "block-text", text: block.text }) });
|
|
1622
|
+
}
|
|
1575
1623
|
if (block.type === "tool_result") {
|
|
1576
1624
|
const c = block.content;
|
|
1577
1625
|
const parts = Array.isArray(c) ? c : [typeof c === "string" ? { type: "text", text: c } : c];
|
|
@@ -1675,12 +1723,15 @@ function JsonBlock({ value }) {
|
|
|
1675
1723
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { className: "block-text", text: "```json\n" + safeJson(value) + "\n```" });
|
|
1676
1724
|
}
|
|
1677
1725
|
function InstructionRun({ turns, model }) {
|
|
1678
|
-
const
|
|
1726
|
+
const strips = turns.flatMap((t) => t.blocks).map(({ it }) => ({ ...it, tokens: countTokens(it.content, it.model ?? model) }));
|
|
1679
1727
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
1680
|
-
|
|
1681
|
-
|
|
1728
|
+
groupInstructions(strips).map(([label, list]) => /* @__PURE__ */ jsxRuntimeExports.jsxs(React.Fragment, { children: [
|
|
1729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "aux instruction-source", children: label }),
|
|
1730
|
+
list.map((it) => /* @__PURE__ */ jsxRuntimeExports.jsx(InstructionFile, { it, model, tokens: it.tokens }, `${it.hash ?? it.file_path}-${it.timestamp}`))
|
|
1731
|
+
] }, label)),
|
|
1732
|
+
strips.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "aux instruction-total", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "instruction-tokens", children: [
|
|
1682
1733
|
"~ ",
|
|
1683
|
-
fmtCompact(
|
|
1734
|
+
fmtCompact(strips.reduce((a, it) => a + it.tokens, 0))
|
|
1684
1735
|
] }) })
|
|
1685
1736
|
] });
|
|
1686
1737
|
}
|
|
@@ -1883,7 +1934,7 @@ const Pane = React.memo(function Pane2({ value, headers, seen, expandAll }) {
|
|
|
1883
1934
|
] })
|
|
1884
1935
|
] });
|
|
1885
1936
|
});
|
|
1886
|
-
function RequestsView({
|
|
1937
|
+
function RequestsView({ filePath, date, granularity = "day", fileSize = 0, expandAll = null }) {
|
|
1887
1938
|
const [records, setRecords] = reactExports.useState(null);
|
|
1888
1939
|
const [selected, setSelected] = reactExports.useState(0);
|
|
1889
1940
|
const [tab, setTab] = reactExports.useState("request");
|
|
@@ -1894,16 +1945,16 @@ function RequestsView({ sessionId, date, granularity = "day", fileSize = 0, expa
|
|
|
1894
1945
|
reactExports.useEffect(() => {
|
|
1895
1946
|
setRecords(null);
|
|
1896
1947
|
setSelected(0);
|
|
1897
|
-
}, [
|
|
1948
|
+
}, [filePath, date, granularity]);
|
|
1898
1949
|
reactExports.useEffect(() => {
|
|
1899
1950
|
let cancelled = false;
|
|
1900
|
-
window.api.readRequests(
|
|
1951
|
+
window.api.readRequests(filePath, date || null, granularity).then((res) => {
|
|
1901
1952
|
if (!cancelled) setRecords(res);
|
|
1902
1953
|
});
|
|
1903
1954
|
return () => {
|
|
1904
1955
|
cancelled = true;
|
|
1905
1956
|
};
|
|
1906
|
-
}, [
|
|
1957
|
+
}, [filePath, date, granularity, fileSize]);
|
|
1907
1958
|
if (!records) return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "requests-view", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "requests-empty", children: "Loading…" }) });
|
|
1908
1959
|
if (!records.length) {
|
|
1909
1960
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "requests-view", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "requests-empty", children: "No captured requests for this session. Requests are recorded only while the capture proxy is running." }) });
|
|
@@ -1949,8 +2000,8 @@ function resultText(r) {
|
|
|
1949
2000
|
}
|
|
1950
2001
|
function renderBlock(b) {
|
|
1951
2002
|
if (b.type === "text") return truncate(b.text || "");
|
|
1952
|
-
if (b.type === "thinking") return `
|
|
1953
|
-
${fence(b.thinking
|
|
2003
|
+
if (b.type === "thinking") return b.redacted ? `_Thinking (encrypted${b.redacted > 1 ? ` · ${b.redacted}` : ""})_` : `Thinking:
|
|
2004
|
+
${fence(b.thinking)}`;
|
|
1954
2005
|
if (b.type === "tool_use") {
|
|
1955
2006
|
const tail = b.result ? `
|
|
1956
2007
|
${b.result.is_error ? "error" : "result"}:
|
|
@@ -1961,6 +2012,8 @@ ${fence(JSON.stringify(b.input, null, 2), "json")}${tail}`;
|
|
|
1961
2012
|
}
|
|
1962
2013
|
if (b.type === "tool_result") return `${b.is_error ? "error" : "result"}:
|
|
1963
2014
|
${fence(resultText(b))}`;
|
|
2015
|
+
if (b.type === "skill") return `Skill${b.name ? `: ${b.name}` : ""}:
|
|
2016
|
+
${fence(b.text)}`;
|
|
1964
2017
|
if (b.type === "image") return "[image]";
|
|
1965
2018
|
if (b.type === "instruction") {
|
|
1966
2019
|
const it = b.it;
|
|
@@ -1972,9 +2025,11 @@ ${fence(it.error ? `error: ${it.error}` : it.content || "")}`;
|
|
|
1972
2025
|
return fence(JSON.stringify(b, null, 2), "json");
|
|
1973
2026
|
}
|
|
1974
2027
|
function renderTurn(t) {
|
|
1975
|
-
if (t.role === "instruction")
|
|
2028
|
+
if (t.role === "instruction") {
|
|
2029
|
+
return groupInstructions(t.blocks.map((b) => b.it)).map(([label, list]) => `**Instructions loaded (${label}):**
|
|
1976
2030
|
|
|
1977
|
-
${
|
|
2031
|
+
${list.map((it) => renderBlock({ type: "instruction", it })).join("\n\n")}`).join("\n\n");
|
|
2032
|
+
}
|
|
1978
2033
|
const role = t.role === "user" ? t.queued ? "User (queued)" : "User" : `Assistant`;
|
|
1979
2034
|
const tokens2 = t.tokenTotal > 0 && t.tokenDelta != null ? ` (${t.tokenDelta >= 0 ? "+" : ""}${fmtCompact(t.tokenDelta)} / ${fmtCompact(t.tokenTotal)} tokens)` : "";
|
|
1980
2035
|
return `**${role}${tokens2}:**
|
|
@@ -2026,7 +2081,7 @@ ${transcript}`;
|
|
|
2026
2081
|
- Wall duration: ${fmtDuration(wallDuration)}
|
|
2027
2082
|
- Active periods: ${fmtNum(meta.activityPeriods.length)}
|
|
2028
2083
|
- Messages: ${fmtNum(meta.messageCount)}
|
|
2029
|
-
- Tool calls: ${
|
|
2084
|
+
- Tool calls: ${fmtToolCalls(meta)}
|
|
2030
2085
|
|
|
2031
2086
|
## Identity
|
|
2032
2087
|
- Model: ${meta.models.join(", ") || "—"}
|
|
@@ -2271,7 +2326,7 @@ ${body}`);
|
|
|
2271
2326
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Wall duration", value: fmtDuration(wallDuration) }),
|
|
2272
2327
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Active periods", value: fmtNum(meta.activityPeriods.length) }),
|
|
2273
2328
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Messages", value: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: tone(meta.messageCount, THRESHOLDS.messages), children: fmtNum(meta.messageCount) }) }),
|
|
2274
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Tool calls", value:
|
|
2329
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Tool calls", value: fmtToolCalls(meta) })
|
|
2275
2330
|
] }),
|
|
2276
2331
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Section, { title: "Identity", children: [
|
|
2277
2332
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Model", value: modelLabel, mono: true }),
|
|
@@ -2363,17 +2418,17 @@ function Session({ meta, missing, date, granularity = "day" }) {
|
|
|
2363
2418
|
const [mode, setMode] = useLocalStorage("session.view-mode", "conversation");
|
|
2364
2419
|
const [agentOpen, setAgentOpen] = reactExports.useState(false);
|
|
2365
2420
|
const [expandAll, setExpandAll] = reactExports.useState(null);
|
|
2366
|
-
const
|
|
2421
|
+
const filePath = meta?.filePath;
|
|
2367
2422
|
const fileSize = meta?.fileSize;
|
|
2368
|
-
const agent = useAgent(`${
|
|
2423
|
+
const agent = useAgent(`${filePath}|${date}`);
|
|
2369
2424
|
reactExports.useEffect(() => {
|
|
2370
2425
|
setItems(null);
|
|
2371
2426
|
setInstructions([]);
|
|
2372
|
-
}, [
|
|
2427
|
+
}, [filePath, date, granularity]);
|
|
2373
2428
|
reactExports.useEffect(() => {
|
|
2374
|
-
if (!
|
|
2429
|
+
if (!filePath) return;
|
|
2375
2430
|
let cancelled = false;
|
|
2376
|
-
window.api.readSession(
|
|
2431
|
+
window.api.readSession(filePath, date || null, granularity).then((res) => {
|
|
2377
2432
|
if (cancelled || !res) return;
|
|
2378
2433
|
setItems(res.items);
|
|
2379
2434
|
setInstructions(res.instructions || []);
|
|
@@ -2381,7 +2436,7 @@ function Session({ meta, missing, date, granularity = "day" }) {
|
|
|
2381
2436
|
return () => {
|
|
2382
2437
|
cancelled = true;
|
|
2383
2438
|
};
|
|
2384
|
-
}, [
|
|
2439
|
+
}, [filePath, date, granularity, fileSize]);
|
|
2385
2440
|
if (!meta) {
|
|
2386
2441
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "session-view empty", children: missing?.warn ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-missing", children: [
|
|
2387
2442
|
"⚠ ",
|
|
@@ -2410,7 +2465,7 @@ function Session({ meta, missing, date, granularity = "day" }) {
|
|
|
2410
2465
|
}
|
|
2411
2466
|
)
|
|
2412
2467
|
] }),
|
|
2413
|
-
mode === "conversation" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "view-tab-pane-content", children: items ? /* @__PURE__ */ jsxRuntimeExports.jsx(ConversationView, { items, instructions, expandAll }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "empty", children: "Loading conversation…" }) }) : mode === "jsonl" ? /* @__PURE__ */ jsxRuntimeExports.jsx(JsonlView, { items, expandAll }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RequestsView, {
|
|
2468
|
+
mode === "conversation" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "view-tab-pane-content", children: items ? /* @__PURE__ */ jsxRuntimeExports.jsx(ConversationView, { items, instructions, expandAll }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "empty", children: "Loading conversation…" }) }) : mode === "jsonl" ? /* @__PURE__ */ jsxRuntimeExports.jsx(JsonlView, { items, expandAll }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RequestsView, { filePath, date, granularity, fileSize, expandAll })
|
|
2414
2469
|
] }),
|
|
2415
2470
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SessionSummary, { meta, items, instructions, agent, onOpenAgent: () => setAgentOpen(true), granularity })
|
|
2416
2471
|
] }) }) }) }) });
|
|
@@ -2477,10 +2532,9 @@ function StatusSwitch({ service, on, warn, button, className = "", tooltip, chan
|
|
|
2477
2532
|
)
|
|
2478
2533
|
] });
|
|
2479
2534
|
}
|
|
2480
|
-
const proxyTooltip = /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2481
|
-
"Captures Claude Code's raw API traffic - system prompt, tool definitions, injected reminders, responses.",
|
|
2482
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", {})
|
|
2483
|
-
"Applies only to newly started Claude Code sessions."
|
|
2535
|
+
const proxyTooltip = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
2536
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Captures Claude Code's raw API traffic - system prompt, tool definitions, injected reminders, responses." }),
|
|
2537
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Applies only to newly started Claude Code sessions." })
|
|
2484
2538
|
] });
|
|
2485
2539
|
const proxyChanges = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
2486
2540
|
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { children: `"env": {
|
|
@@ -2578,6 +2632,15 @@ function App() {
|
|
|
2578
2632
|
const end = endOfPeriod(anchor, granularity);
|
|
2579
2633
|
return { start, end };
|
|
2580
2634
|
}, [anchor, granularity]);
|
|
2635
|
+
reactExports.useEffect(() => {
|
|
2636
|
+
const shown = startOfPeriod(Date.now(), granularity);
|
|
2637
|
+
if (anchor !== shown) return;
|
|
2638
|
+
const id = setInterval(() => {
|
|
2639
|
+
const current = startOfPeriod(Date.now(), granularity);
|
|
2640
|
+
if (current !== shown) setAnchor(current);
|
|
2641
|
+
}, 6e4);
|
|
2642
|
+
return () => clearInterval(id);
|
|
2643
|
+
}, [anchor, granularity]);
|
|
2581
2644
|
reactExports.useEffect(() => {
|
|
2582
2645
|
let cancelled = false;
|
|
2583
2646
|
setScanProgress(null);
|
|
@@ -2609,7 +2672,7 @@ function App() {
|
|
|
2609
2672
|
return { sourceFiltered, past, availableSources };
|
|
2610
2673
|
}, [sessions, sourceFilter, projectFilter]);
|
|
2611
2674
|
const selected = reactExports.useMemo(
|
|
2612
|
-
() => sessions.find((s) => s.sessionId === selectedId) || null,
|
|
2675
|
+
() => sessions.find((s) => s.filePath === selectedId || s.sessionId === selectedId) || null,
|
|
2613
2676
|
[sessions, selectedId]
|
|
2614
2677
|
);
|
|
2615
2678
|
let missing = null;
|
|
@@ -2682,7 +2745,7 @@ function App() {
|
|
|
2682
2745
|
dayRange,
|
|
2683
2746
|
sessions: dayItems.sourceFiltered,
|
|
2684
2747
|
onSelect: selectSession,
|
|
2685
|
-
selectedId,
|
|
2748
|
+
selectedId: selected?.filePath ?? null,
|
|
2686
2749
|
dayAnchor: anchor,
|
|
2687
2750
|
granularity,
|
|
2688
2751
|
projectFilter,
|
|
@@ -2705,7 +2768,7 @@ function App() {
|
|
|
2705
2768
|
SessionList,
|
|
2706
2769
|
{
|
|
2707
2770
|
sessions: dayItems.past,
|
|
2708
|
-
selectedId,
|
|
2771
|
+
selectedId: selected?.filePath ?? null,
|
|
2709
2772
|
deepLink,
|
|
2710
2773
|
onSelect: selectSession
|
|
2711
2774
|
}
|
|
@@ -616,6 +616,8 @@
|
|
|
616
616
|
color: var(--accent, #4ea1ff);
|
|
617
617
|
}
|
|
618
618
|
|
|
619
|
+
.session-command { color: var(--accent); }
|
|
620
|
+
|
|
619
621
|
.subagent-tag,
|
|
620
622
|
.worktree-tag {
|
|
621
623
|
font-family: var(--font-mono), monospace;
|
|
@@ -721,7 +723,7 @@
|
|
|
721
723
|
}
|
|
722
724
|
|
|
723
725
|
.conv-row + .conv-row { margin-top: 15px; }
|
|
724
|
-
/*
|
|
726
|
+
/* The session's one instruction row (see flatten) — the gap keeps its strips off the first message. */
|
|
725
727
|
.conv-row-instruction + .conv-row { margin-top: 20px; }
|
|
726
728
|
.conv-row-assistant + .conv-row-user { margin-top: 60px; }
|
|
727
729
|
.conv-row-assistant + .conv-row-assistant { margin-top: 0; }
|
|
@@ -921,6 +923,7 @@ button.msg-summary:hover { color: var(--text); background: var(--bg-elev-2); bor
|
|
|
921
923
|
text-align: left;
|
|
922
924
|
margin: 0;
|
|
923
925
|
}
|
|
926
|
+
& .block-command + .block-text { margin-top: 4px; }
|
|
924
927
|
}
|
|
925
928
|
|
|
926
929
|
.turn-assistant .block-text { color: var(--text); }
|
|
@@ -1052,13 +1055,26 @@ button.msg-summary:hover { color: var(--text); background: var(--bg-elev-2); bor
|
|
|
1052
1055
|
}
|
|
1053
1056
|
}
|
|
1054
1057
|
|
|
1055
|
-
/* Instruction files (system prompt / CLAUDE.md / memory) extracted from the captured API requests
|
|
1056
|
-
.
|
|
1058
|
+
/* Instruction files (system prompt / CLAUDE.md / memory) extracted from the captured API requests,
|
|
1059
|
+
and the label over each group — one unbroken strip down the whole run. */
|
|
1060
|
+
.instruction-file,
|
|
1061
|
+
.instruction-source {
|
|
1057
1062
|
border-left: 2px solid #a78bfa;
|
|
1058
1063
|
padding-left: 8px;
|
|
1059
1064
|
margin-left: -10px;
|
|
1060
1065
|
}
|
|
1061
1066
|
|
|
1067
|
+
/* Group label over the strips read from one part of the request (system prompt / tools / user message). */
|
|
1068
|
+
.instruction-source {
|
|
1069
|
+
font-family: var(--font-mono), monospace;
|
|
1070
|
+
font-size: calc(10.5px * var(--font-scale, 1));
|
|
1071
|
+
color: var(--text-faint);
|
|
1072
|
+
text-transform: uppercase;
|
|
1073
|
+
letter-spacing: 0.04em;
|
|
1074
|
+
padding-top: 6px;
|
|
1075
|
+
}
|
|
1076
|
+
.instruction-source:first-child { padding-top: 0; }
|
|
1077
|
+
|
|
1062
1078
|
/* Full-width toggle so the estimated token count can sit right-aligned, like msg-header-right. */
|
|
1063
1079
|
.instruction-file .aux-toggle { display: flex; width: 100%; align-items: center; }
|
|
1064
1080
|
.instruction-tokens { margin-left: auto; color: var(--text-faint); }
|
|
@@ -2319,4 +2335,4 @@ button:hover { background: var(--border); }
|
|
|
2319
2335
|
.kind-suggest { color: #6ea882; }
|
|
2320
2336
|
.kind-web { color: #5fa8ad; }
|
|
2321
2337
|
.kind-security { color: #c4937b; }
|
|
2322
|
-
.kind-quota, .kind-status, .kind-count { color: var(--text-faint); }
|
|
2338
|
+
.kind-quota, .kind-status, .kind-count, .kind-aux { color: var(--text-faint); }
|