claude-discover 1.9.0 → 1.9.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 +1 -1
- package/bin/proxy.mjs +14 -1
- package/out/main/main.js +370 -65
- package/out/preload/preload.cjs +3 -1
- package/out/renderer/assets/{index-0bBLuYQv.css → index-03LlBvFr.css} +27 -1
- package/out/renderer/assets/{index-BLwpO6Wp.js → index-BKTnG3v8.js} +127 -24
- package/out/renderer/assets/vendors-S1fS5xz9.js +52139 -0
- package/out/renderer/index.html +3 -3
- package/package.json +5 -3
- package/out/renderer/assets/vendors-D6iOvAG3.js +0 -49248
|
@@ -557,8 +557,11 @@
|
|
|
557
557
|
&:hover { background: var(--bg-elev-2); }
|
|
558
558
|
&.selected { background: var(--selected); }
|
|
559
559
|
&.is-subagent-child { padding-left: 20px; }
|
|
560
|
+
&.deep-linked { background: rgba(52, 211, 153, 0.12); } /* last, so it wins over :hover and .selected */
|
|
560
561
|
}
|
|
561
562
|
|
|
563
|
+
.deeplink-note { color: #34d399; }
|
|
564
|
+
|
|
562
565
|
.session-row-main { flex: 1; min-width: 0; }
|
|
563
566
|
|
|
564
567
|
.session-row-stats {
|
|
@@ -733,9 +736,9 @@
|
|
|
733
736
|
}
|
|
734
737
|
|
|
735
738
|
.conv-row + .conv-row { margin-top: 15px; }
|
|
739
|
+
/* One instruction row per API call (see groupTurns) — the gap keeps two calls' strips apart. */
|
|
736
740
|
.conv-row-instruction + .conv-row { margin-top: 20px; }
|
|
737
741
|
.conv-row-assistant + .conv-row-user { margin-top: 60px; }
|
|
738
|
-
.conv-row-instruction + .conv-row-instruction,
|
|
739
742
|
.conv-row-assistant + .conv-row-assistant { margin-top: 0; }
|
|
740
743
|
|
|
741
744
|
|
|
@@ -1077,6 +1080,18 @@ button.msg-summary:hover { color: var(--text); background: var(--bg-elev-2); bor
|
|
|
1077
1080
|
margin-left: -10px;
|
|
1078
1081
|
}
|
|
1079
1082
|
|
|
1083
|
+
/* Full-width toggle so the estimated token count can sit right-aligned, like msg-header-right. */
|
|
1084
|
+
.instruction-file .aux-toggle { display: flex; width: 100%; align-items: center; }
|
|
1085
|
+
.instruction-tokens { margin-left: auto; color: var(--text-faint); }
|
|
1086
|
+
|
|
1087
|
+
/* Summed token total under a run of instruction files: a rule over the right-aligned figure. */
|
|
1088
|
+
.instruction-total { display: flex; font-size: calc(11px * var(--font-scale, 1)); }
|
|
1089
|
+
.instruction-total .instruction-tokens {
|
|
1090
|
+
border-top: 1px solid var(--border);
|
|
1091
|
+
padding-top: 2px;
|
|
1092
|
+
font-weight: 600;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1080
1095
|
/* Full path of an expanded memory file, first line of the body — one click selects it for copying. */
|
|
1081
1096
|
.instruction-path {
|
|
1082
1097
|
font-family: var(--font-mono), monospace;
|
|
@@ -1814,6 +1829,17 @@ button.msg-summary:hover { color: var(--text); background: var(--bg-elev-2); bor
|
|
|
1814
1829
|
}
|
|
1815
1830
|
}
|
|
1816
1831
|
|
|
1832
|
+
.session-missing {
|
|
1833
|
+
max-width: 520px;
|
|
1834
|
+
padding: 14px 18px;
|
|
1835
|
+
border: 1px solid rgba(251, 191, 36, 0.35);
|
|
1836
|
+
border-radius: 6px;
|
|
1837
|
+
background: rgba(251, 191, 36, 0.08);
|
|
1838
|
+
color: var(--warn);
|
|
1839
|
+
text-align: center;
|
|
1840
|
+
word-break: break-word;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1817
1843
|
.view-body {
|
|
1818
1844
|
flex: 1;
|
|
1819
1845
|
display: flex;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as reactExports, j as jsxRuntimeExports, f as format, s as startOfWeek, a as startOfMonth, b as startOfDay, e as endOfWeek, c as endOfMonth, d as endOfDay, g as addWeeks, h as addMonths, i as addDays, k as isSameWeek, l as isSameMonth, m as isSameDay, n as intervalToDuration, o as getDaysInMonth, p as addHours, H as Hourglass, G as Gauge, M as MessageSquare, C as Clock, Z as Zap, D as DollarSign, R as React,
|
|
1
|
+
import { r as reactExports, j as jsxRuntimeExports, f as format, s as startOfWeek, a as startOfMonth, b as startOfDay, e as endOfWeek, c as endOfMonth, d as endOfDay, g as addWeeks, h as addMonths, i as addDays, k as isSameWeek, l as isSameMonth, m as isSameDay, n as intervalToDuration, o as getDaysInMonth, p as addHours, q as encode, H as Hourglass, G as Gauge, M as MessageSquare, C as Clock, Z as Zap, D as DollarSign, R as React, t as Markdown$1, u as rehypeHighlight, v as remarkGfm, T as Terminal, J as JsonView, w as vscodeTheme, x as tippy, y as reactDomExports, z as sn, X as Xt, A as Zt, B as tn, E as parse, F as delegate, I as clientExports } from "./vendors-S1fS5xz9.js";
|
|
2
2
|
const SOURCE_COLORS = {
|
|
3
3
|
scheduled: "#14b8a6",
|
|
4
4
|
cli: "#3b82f6",
|
|
@@ -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.1") {
|
|
38
|
+
const [MAJOR, MINOR, PATCH] = "1.9.1".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.1");
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
function useMouseFontScale(storageKey) {
|
|
@@ -721,8 +721,8 @@ function tone(value, { warn, danger }) {
|
|
|
721
721
|
function fmtCompact(n) {
|
|
722
722
|
if (n == null) return "—";
|
|
723
723
|
if (n < 0) return `-${fmtCompact(-n)}`;
|
|
724
|
-
if (n <
|
|
725
|
-
if (n < 1e6) return `${
|
|
724
|
+
if (n < 100) return `${n}`;
|
|
725
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
726
726
|
return `${(n / 1e6).toFixed(1)}M`;
|
|
727
727
|
}
|
|
728
728
|
const BAR_MAX_PX = 52;
|
|
@@ -872,10 +872,34 @@ function PeriodSummary({ sessions, dayAnchor, granularity = "day" }) {
|
|
|
872
872
|
] })
|
|
873
873
|
] });
|
|
874
874
|
}
|
|
875
|
+
const countTokens = (text, model = "") => {
|
|
876
|
+
if (!text) return 0;
|
|
877
|
+
const LEGACY_CLAUDE = /-(3|4)(-|$)/;
|
|
878
|
+
const scale = LEGACY_CLAUDE.test(model) ? 1.13 : 1.5;
|
|
879
|
+
return Math.round(encode(text).length * scale);
|
|
880
|
+
};
|
|
881
|
+
const queuedPrompt = (it) => it.type === "attachment" && it.attachment?.type === "queued_command" && it.attachment.commandMode === "prompt" && (it.attachment.origin?.kind ?? "human") === "human" && it.attachment.prompt?.trim() ? it.attachment.prompt : null;
|
|
875
882
|
function flatten(items, instructions = []) {
|
|
876
883
|
const turns = [];
|
|
877
884
|
const results = {};
|
|
878
885
|
for (const it of items) {
|
|
886
|
+
const queued = queuedPrompt(it);
|
|
887
|
+
if (queued) {
|
|
888
|
+
turns.push({
|
|
889
|
+
uuid: it.uuid,
|
|
890
|
+
role: "user",
|
|
891
|
+
isMeta: false,
|
|
892
|
+
queued: true,
|
|
893
|
+
ts: it.timestamp ? Date.parse(it.timestamp) : null,
|
|
894
|
+
model: null,
|
|
895
|
+
msgId: null,
|
|
896
|
+
usage: null,
|
|
897
|
+
tokenDelta: it._tokenDelta ?? null,
|
|
898
|
+
tokenTotal: it._tokenTotal ?? null,
|
|
899
|
+
blocks: [{ type: "text", text: queued }]
|
|
900
|
+
});
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
879
903
|
if (it.type === "attachment" && it.attachment) {
|
|
880
904
|
const block = { type: "attachment", attachment: it.attachment };
|
|
881
905
|
const last = turns[turns.length - 1];
|
|
@@ -1027,7 +1051,9 @@ function groupTurns(turns) {
|
|
|
1027
1051
|
else pending.push(t);
|
|
1028
1052
|
} else if (t.role === "instruction") {
|
|
1029
1053
|
flush();
|
|
1030
|
-
groups.
|
|
1054
|
+
const prev = groups.at(-1);
|
|
1055
|
+
if (prev?.kind === "instruction" && prev.turns.at(-1).ts === t.ts) prev.turns.push(t);
|
|
1056
|
+
else groups.push({ kind: "instruction", turns: [t] });
|
|
1031
1057
|
} else if (t.role === "user") {
|
|
1032
1058
|
flush();
|
|
1033
1059
|
groups.push({ kind: "user", turns: [...pending, t] });
|
|
@@ -1045,7 +1071,7 @@ function groupTurns(turns) {
|
|
|
1045
1071
|
function cycleDurations(groups) {
|
|
1046
1072
|
let prevEnd = null;
|
|
1047
1073
|
return groups.map((g) => {
|
|
1048
|
-
const tss =
|
|
1074
|
+
const tss = g.turns.map((t) => t.ts).filter((ts) => ts != null);
|
|
1049
1075
|
const end = tss.length ? tss[tss.length - 1] : null;
|
|
1050
1076
|
const duration2 = g.kind === "assistant" && end != null && prevEnd != null ? end - prevEnd : null;
|
|
1051
1077
|
if (end != null) prevEnd = end;
|
|
@@ -1055,7 +1081,7 @@ function cycleDurations(groups) {
|
|
|
1055
1081
|
function tokenPoints(groups) {
|
|
1056
1082
|
let prev = 0;
|
|
1057
1083
|
return groups.map((g) => {
|
|
1058
|
-
const turns = g.turns
|
|
1084
|
+
const turns = g.turns;
|
|
1059
1085
|
let total = null, ctx = null;
|
|
1060
1086
|
const byMsg = /* @__PURE__ */ new Map();
|
|
1061
1087
|
for (const t of turns) {
|
|
@@ -1076,7 +1102,7 @@ function tokenPoints(groups) {
|
|
|
1076
1102
|
usage.cacheCreation5m += u.cache_creation?.ephemeral_5m_input_tokens || 0;
|
|
1077
1103
|
usage.cacheCreation1h += u.cache_creation?.ephemeral_1h_input_tokens || 0;
|
|
1078
1104
|
}
|
|
1079
|
-
if (total == null || total
|
|
1105
|
+
if (total == null || total <= prev) return null;
|
|
1080
1106
|
const delta = total - prev;
|
|
1081
1107
|
prev = total;
|
|
1082
1108
|
if (ctx == null && g.kind !== "assistant") ctx = delta;
|
|
@@ -1090,7 +1116,7 @@ const TIPS = {
|
|
|
1090
1116
|
messages: `Consider sessions below ${fmtCompact(THRESHOLDS.messages.warn)} messages`,
|
|
1091
1117
|
time: `Consider sessions under ${THRESHOLDS.workTime.warn / 6e4}m`
|
|
1092
1118
|
};
|
|
1093
|
-
function SessionList({ sessions, selectedId, onSelect }) {
|
|
1119
|
+
function SessionList({ sessions, selectedId, deepLink, onSelect }) {
|
|
1094
1120
|
const selectedRef = reactExports.useRef(null);
|
|
1095
1121
|
const [sortBy, setSortBy] = useLocalStorage("session-list.sort", "time");
|
|
1096
1122
|
const [filter, setFilter] = reactExports.useState("");
|
|
@@ -1165,12 +1191,15 @@ function SessionList({ sessions, selectedId, onSelect }) {
|
|
|
1165
1191
|
const isSubagent = s.sessionId.startsWith("agent-");
|
|
1166
1192
|
const journal = isJournal(s);
|
|
1167
1193
|
const isFork = !!s.forkedFrom;
|
|
1194
|
+
const linked = deepLink?.id === s.sessionId;
|
|
1195
|
+
const linkTip = linked && `Opened from deep link
|
|
1196
|
+
claude-discover://session?id=${deepLink.id}${deepLink.date ? `&date=${deepLink.date}` : ""}`;
|
|
1168
1197
|
const sessionName = s.customTitle && s.agentName && s.customTitle !== s.agentName ? `${s.customTitle} [${s.agentName}]` : s.customTitle || s.agentName || "";
|
|
1169
1198
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1170
1199
|
"div",
|
|
1171
1200
|
{
|
|
1172
1201
|
ref: selectedId === s.sessionId ? selectedRef : null,
|
|
1173
|
-
className: `session-row ${selectedId === s.sessionId ? "selected" : ""} ${isChild ? "is-subagent-child" : ""}`,
|
|
1202
|
+
className: `session-row ${selectedId === s.sessionId ? "selected" : ""} ${isChild ? "is-subagent-child" : ""} ${linked ? "deep-linked" : ""}`,
|
|
1174
1203
|
onClick: () => onSelect(selectedId === s.sessionId ? null : s.sessionId),
|
|
1175
1204
|
style: { borderLeftColor: SOURCE_COLORS[s.source] || SOURCE_COLORS.other },
|
|
1176
1205
|
children: [
|
|
@@ -1214,7 +1243,8 @@ ${TIPS.time}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 11
|
|
|
1214
1243
|
s.models?.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "session-model", children: [
|
|
1215
1244
|
", ",
|
|
1216
1245
|
s.models.map((m) => m.replace(/^claude-/, "")).join(", ")
|
|
1217
|
-
] })
|
|
1246
|
+
] }),
|
|
1247
|
+
linked && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "deeplink-note", "data-tippy-content": linkTip, "data-tippy-maxWidth": 560, children: ", opened from deep link" })
|
|
1218
1248
|
] })
|
|
1219
1249
|
] }),
|
|
1220
1250
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-row-stats", children: [
|
|
@@ -1383,9 +1413,9 @@ function ConversationView({ items, instructions = [], expandAll = null }) {
|
|
|
1383
1413
|
const [scale, zoomRef] = useMouseFontScale("font-scale.conversation");
|
|
1384
1414
|
const hasTimeline = points.some(Boolean);
|
|
1385
1415
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandAllContext.Provider, { value: expandAll, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: zoomRef, className: `conversation${hasTimeline ? " has-token-timeline" : ""}`, style: { "--font-scale": scale }, children: groups.map((g, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `conv-row conv-row-${g.kind}`, children: [
|
|
1386
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(LazyMount, { eager: i < 8, forceMount: findOpen, placeholderMinHeight: 80, children: g.kind === "user" ? /* @__PURE__ */ jsxRuntimeExports.jsx(UserRow, { turns: g.turns, point: points[i] }) : g.kind === "assistant" ? /* @__PURE__ */ jsxRuntimeExports.jsx(AssistantCard, { turns: g.turns, point: points[i], duration: durations[i], showAuthor: groups[i - 1]?.kind !== "assistant" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1416
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LazyMount, { eager: i < 8, forceMount: findOpen, placeholderMinHeight: 80, children: g.kind === "user" ? /* @__PURE__ */ jsxRuntimeExports.jsx(UserRow, { turns: g.turns, point: points[i] }) : g.kind === "assistant" ? /* @__PURE__ */ jsxRuntimeExports.jsx(AssistantCard, { turns: g.turns, point: points[i], duration: durations[i], showAuthor: groups[i - 1]?.kind !== "assistant" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(InstructionRun, { turns: g.turns, model: currentModel(turns) }) }),
|
|
1387
1417
|
points[i] ? /* @__PURE__ */ jsxRuntimeExports.jsx(TokenPoint, { point: points[i] }) : hasTimeline && g.kind === "user" && g.turns.some(isCommandTurn) && /* @__PURE__ */ jsxRuntimeExports.jsx(TokenPoint, { point: { role: "command", delta: 0 } })
|
|
1388
|
-
] }, g.
|
|
1418
|
+
] }, g.turns[0].uuid)) }) });
|
|
1389
1419
|
}
|
|
1390
1420
|
const ClaudeIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsx("img", { className: "msg-icon claude-icon", src: claudeIcon, alt: "" });
|
|
1391
1421
|
const CTX_LIMIT = THRESHOLDS.context.danger;
|
|
@@ -1423,6 +1453,7 @@ function UserRow({ turns, point }) {
|
|
|
1423
1453
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "msg-header", children: [
|
|
1424
1454
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "msg-icon" }),
|
|
1425
1455
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "msg-author", children: "You" }),
|
|
1456
|
+
msg.queued && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "msg-summary", children: "queued during the previous turn" }),
|
|
1426
1457
|
ctxItems.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "msg-summary", onClick: () => setOpen((v) => !v), children: [
|
|
1427
1458
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "aux-chevron", children: open ? "▾" : "▸" }),
|
|
1428
1459
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
@@ -1558,11 +1589,43 @@ const ATTACHMENT_RENDERERS = {
|
|
|
1558
1589
|
title: `${a.addedNames?.length || 0} deferred tools ${a.removedNames?.length ? `(removed: ${a.removedNames.length})` : ""}`,
|
|
1559
1590
|
body: safeJson({ added: a.addedNames, removed: a.removedNames }),
|
|
1560
1591
|
defaultOpen: false
|
|
1592
|
+
}),
|
|
1593
|
+
// The one nested shape the fallback below can't flatten: files → diagnostics → range.
|
|
1594
|
+
diagnostics: (a) => {
|
|
1595
|
+
const lines = (a.files || []).flatMap((f) => (f.diagnostics || []).map((d) => `${f.uri}:${(d.range?.start?.line ?? 0) + 1} ${d.severity}: ${d.message}${d.source ? ` (${d.source})` : ""}`));
|
|
1596
|
+
return { title: `Diagnostics: ${lines.length} in ${a.files?.length || 0} file${a.files?.length === 1 ? "" : "s"}`, body: lines.join("\n") };
|
|
1597
|
+
},
|
|
1598
|
+
// addedLines carry each agent's one-line description; addedTypes is just their names.
|
|
1599
|
+
agent_listing_delta: (a) => ({
|
|
1600
|
+
title: `${a.addedTypes?.length || 0} agent types${a.removedTypes?.length ? ` (removed: ${a.removedTypes.length})` : ""}`,
|
|
1601
|
+
body: (a.addedLines || a.addedTypes || []).join("\n"),
|
|
1602
|
+
defaultOpen: false
|
|
1561
1603
|
})
|
|
1562
1604
|
};
|
|
1605
|
+
function genericAttachment(att) {
|
|
1606
|
+
const short = [], long = [];
|
|
1607
|
+
const collect = (v, key) => {
|
|
1608
|
+
if (typeof v === "string") {
|
|
1609
|
+
if (v.trim()) (v.length > 100 ? long : short).push([key, v]);
|
|
1610
|
+
} else if (Array.isArray(v)) {
|
|
1611
|
+
for (const x of v) collect(x, key);
|
|
1612
|
+
} else if (v && typeof v === "object") {
|
|
1613
|
+
for (const [k, x] of Object.entries(v)) collect(x, k);
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
for (const [k, v] of Object.entries(att || {})) {
|
|
1617
|
+
if (k !== "type") collect(v, k);
|
|
1618
|
+
}
|
|
1619
|
+
const detail = short.find(([k]) => /path|file|name|dir|uri|url|date/i.test(k))?.[1];
|
|
1620
|
+
const label = (att?.type || "attachment").replace(/_/g, " ").replace(/^./, (c) => c.toUpperCase());
|
|
1621
|
+
return {
|
|
1622
|
+
title: detail ? `${label}: ${detail}` : label,
|
|
1623
|
+
body: long.length ? long.map(([, v]) => v).join("\n\n") : short.length > 1 ? safeJson(att) : null
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1563
1626
|
function Attachment({ att }) {
|
|
1564
1627
|
const render = ATTACHMENT_RENDERERS[att?.type];
|
|
1565
|
-
const { title, body, defaultOpen = false } = render ? render(att) :
|
|
1628
|
+
const { title, body, defaultOpen = false } = render ? render(att) : genericAttachment(att);
|
|
1566
1629
|
if (body == null) return /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { title, className: "attachment" });
|
|
1567
1630
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { title, className: "attachment", defaultOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { children: body }) });
|
|
1568
1631
|
}
|
|
@@ -1592,12 +1655,26 @@ function safeJson(x) {
|
|
|
1592
1655
|
function JsonBlock({ value }) {
|
|
1593
1656
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { className: "block-text", text: "```json\n" + safeJson(value) + "\n```" });
|
|
1594
1657
|
}
|
|
1595
|
-
function
|
|
1658
|
+
function InstructionRun({ turns, model }) {
|
|
1659
|
+
const tokens2 = turns.map((t) => countTokens(t.blocks[0].it.content, t.blocks[0].it.model ?? model));
|
|
1660
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
1661
|
+
turns.map((t, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(InstructionFile, { it: t.blocks[0].it, model, tokens: tokens2[i] }, t.uuid)),
|
|
1662
|
+
turns.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "aux instruction-total", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "instruction-tokens", children: [
|
|
1663
|
+
"~ ",
|
|
1664
|
+
fmtCompact(tokens2.reduce((a, b) => a + b, 0))
|
|
1665
|
+
] }) })
|
|
1666
|
+
] });
|
|
1667
|
+
}
|
|
1668
|
+
function InstructionFile({ it, model, tokens: tokens2 }) {
|
|
1596
1669
|
const [open, setOpen] = useCollapsed(false);
|
|
1597
1670
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "aux instruction-file", children: [
|
|
1598
1671
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "aux-toggle", onClick: () => setOpen((v) => !v), children: [
|
|
1599
1672
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "aux-chevron", children: open ? "▾" : "▸" }),
|
|
1600
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: instructionTitle(it, model) })
|
|
1673
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: instructionTitle(it, model) }),
|
|
1674
|
+
tokens2 > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "instruction-tokens", title: "Approx. tokens", children: [
|
|
1675
|
+
"~ ",
|
|
1676
|
+
fmtCompact(tokens2)
|
|
1677
|
+
] })
|
|
1601
1678
|
] }),
|
|
1602
1679
|
open && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "aux-body", children: [
|
|
1603
1680
|
it.name && it.name !== it.file_path && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "instruction-path", children: it.file_path }),
|
|
@@ -1880,7 +1957,7 @@ function renderTurn(t) {
|
|
|
1880
1957
|
if (t.role === "instruction") return `**Instructions loaded:**
|
|
1881
1958
|
|
|
1882
1959
|
${t.blocks.map(renderBlock).join("\n\n")}`;
|
|
1883
|
-
const role = t.role === "user" ? "User" : `Assistant`;
|
|
1960
|
+
const role = t.role === "user" ? t.queued ? "User (queued)" : "User" : `Assistant`;
|
|
1884
1961
|
const tokens2 = t.tokenTotal > 0 && t.tokenDelta != null ? ` (${t.tokenDelta >= 0 ? "+" : ""}${fmtCompact(t.tokenDelta)} / ${fmtCompact(t.tokenTotal)} tokens)` : "";
|
|
1885
1962
|
return `**${role}${tokens2}:**
|
|
1886
1963
|
|
|
@@ -2261,7 +2338,7 @@ const TABS = [
|
|
|
2261
2338
|
{ key: "jsonl", label: "Raw Logs" },
|
|
2262
2339
|
{ key: "requests", label: "API Requests" }
|
|
2263
2340
|
];
|
|
2264
|
-
function Session({ meta, date, granularity = "day" }) {
|
|
2341
|
+
function Session({ meta, missing, date, granularity = "day" }) {
|
|
2265
2342
|
const [items, setItems] = reactExports.useState(null);
|
|
2266
2343
|
const [instructions, setInstructions] = reactExports.useState([]);
|
|
2267
2344
|
const [mode, setMode] = useLocalStorage("session.view-mode", "conversation");
|
|
@@ -2287,7 +2364,10 @@ function Session({ meta, date, granularity = "day" }) {
|
|
|
2287
2364
|
};
|
|
2288
2365
|
}, [sessionId, date, granularity, fileSize]);
|
|
2289
2366
|
if (!meta) {
|
|
2290
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "session-view empty", children: /* @__PURE__ */ jsxRuntimeExports.
|
|
2367
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "session-view empty", children: missing ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-missing", children: [
|
|
2368
|
+
"⚠ ",
|
|
2369
|
+
missing
|
|
2370
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Select a session to inspect." }) });
|
|
2291
2371
|
}
|
|
2292
2372
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "session-view", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "view-body", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "view-conversation", children: agentOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx(AgentView, { meta, items, instructions, agent, onClose: () => setAgentOpen(false) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "view-tab-pane", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "view-tab-pane-row", children: [
|
|
2293
2373
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "view-tab-pane-main", children: [
|
|
@@ -2471,6 +2551,7 @@ function App() {
|
|
|
2471
2551
|
const [granularity, setGranularity] = useLocalStorage("gantt.granularity", "day");
|
|
2472
2552
|
const [anchor, setAnchor] = reactExports.useState(() => startOfPeriod(Date.now(), granularity));
|
|
2473
2553
|
const [selectedId, setSelectedId] = reactExports.useState(null);
|
|
2554
|
+
const [deepLink, setDeepLink] = reactExports.useState(null);
|
|
2474
2555
|
const [sourceFilter, setSourceFilter] = reactExports.useState(null);
|
|
2475
2556
|
const [projectFilter, setProjectFilter] = reactExports.useState(null);
|
|
2476
2557
|
const { defaultLayout, onLayoutChanged } = sn({ id: "app.body", panelIds: ["list", "detail"], storage: localStorage });
|
|
@@ -2493,7 +2574,7 @@ function App() {
|
|
|
2493
2574
|
setLoading(false);
|
|
2494
2575
|
}
|
|
2495
2576
|
});
|
|
2496
|
-
}, 120);
|
|
2577
|
+
}, loading ? 0 : 120);
|
|
2497
2578
|
const off = window.api.onSessionsUpdate((s) => {
|
|
2498
2579
|
if (!cancelled) setSessions(s || []);
|
|
2499
2580
|
});
|
|
@@ -2514,10 +2595,31 @@ function App() {
|
|
|
2514
2595
|
() => sessions.find((s) => s.sessionId === selectedId) || null,
|
|
2515
2596
|
[sessions, selectedId]
|
|
2516
2597
|
);
|
|
2517
|
-
|
|
2598
|
+
let missing = null;
|
|
2599
|
+
if (!selected && scanProgress?.scanning === false) {
|
|
2600
|
+
const when = granularity === "day" ? `on ${format(anchor, "MMM d, yyyy")}` : `in this ${granularity}`;
|
|
2601
|
+
if (!sessions.length) missing = `No sessions recorded ${when}.`;
|
|
2602
|
+
else if (deepLink?.date === format(anchor, "yyyy-MM-dd")) missing = `Session ${selectedId} has no records ${when}.`;
|
|
2603
|
+
}
|
|
2604
|
+
const selectSession = reactExports.useCallback((id, link = null) => {
|
|
2518
2605
|
closeFind();
|
|
2519
2606
|
setSelectedId(id);
|
|
2607
|
+
setDeepLink(link);
|
|
2520
2608
|
}, []);
|
|
2609
|
+
reactExports.useEffect(() => {
|
|
2610
|
+
const open = ({ id, date }) => {
|
|
2611
|
+
const day = date && parse(date, "yyyy-MM-dd", /* @__PURE__ */ new Date());
|
|
2612
|
+
if (day && !isNaN(day)) {
|
|
2613
|
+
setGranularity("day");
|
|
2614
|
+
setAnchor(startOfPeriod(day, "day"));
|
|
2615
|
+
setSourceFilter(null);
|
|
2616
|
+
setProjectFilter(null);
|
|
2617
|
+
}
|
|
2618
|
+
selectSession(id, { id, date });
|
|
2619
|
+
};
|
|
2620
|
+
window.api.takeDeepLink().then((target) => target && open(target));
|
|
2621
|
+
return window.api.onDeepLink(open);
|
|
2622
|
+
}, [selectSession, setGranularity]);
|
|
2521
2623
|
const shiftPeriod = reactExports.useCallback((delta) => {
|
|
2522
2624
|
setProjectFilter(null);
|
|
2523
2625
|
setAnchor((a) => startOfPeriod(addPeriod(a, granularity, delta), granularity));
|
|
@@ -2587,11 +2689,12 @@ function App() {
|
|
|
2587
2689
|
{
|
|
2588
2690
|
sessions: dayItems.past,
|
|
2589
2691
|
selectedId,
|
|
2692
|
+
deepLink,
|
|
2590
2693
|
onSelect: selectSession
|
|
2591
2694
|
}
|
|
2592
2695
|
) }),
|
|
2593
2696
|
/* @__PURE__ */ jsxRuntimeExports.jsx(tn, { className: "resize-handle resize-handle-v" }),
|
|
2594
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Zt, { id: "detail", minSize: 30, className: "body-pane", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Session, { meta: selected, date: format(anchor, "yyyy-MM-dd"), granularity }) })
|
|
2697
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Zt, { id: "detail", minSize: 30, className: "body-pane", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Session, { meta: selected, missing, date: format(anchor, "yyyy-MM-dd"), granularity }) })
|
|
2595
2698
|
]
|
|
2596
2699
|
}
|
|
2597
2700
|
) })
|