claude-discover 1.9.5 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/main/main.js +141 -48
- package/out/renderer/assets/{index-DZ1Gj6hz.css → index-DnYN00T3.css} +6 -0
- package/out/renderer/assets/{index-CX9ZlZGo.js → index-x_-ZeUa3.js} +19 -11
- package/out/renderer/assets/{vendors-JM3FOKMR.js → vendors-D2DMOduT.js} +10 -9
- package/out/renderer/index.html +3 -3
- package/package.json +1 -2
package/out/main/main.js
CHANGED
|
@@ -6,7 +6,6 @@ import fs from "node:fs";
|
|
|
6
6
|
import { sync } from "write-file-atomic";
|
|
7
7
|
import fsp from "node:fs/promises";
|
|
8
8
|
import crypto from "node:crypto";
|
|
9
|
-
import chokidar from "chokidar";
|
|
10
9
|
import which from "which";
|
|
11
10
|
import { execFile } from "node:child_process";
|
|
12
11
|
import { promisify } from "node:util";
|
|
@@ -564,10 +563,10 @@ class RequestParser {
|
|
|
564
563
|
for (const t of fresh) this.seenTools.add(t.name);
|
|
565
564
|
const schema = (t) => t.input_schema ? "```json\n" + JSON.stringify(t.input_schema, null, 2) + "\n```" : "";
|
|
566
565
|
const strip = (file_path, pick) => {
|
|
567
|
-
const list = fresh.filter((t) => pick(t.name));
|
|
566
|
+
const list = fresh.filter((t) => pick(t.name)).map((t) => ({ name: t.name, content: [t.description || "", schema(t)].filter(Boolean).join("\n\n") }));
|
|
568
567
|
if (!list.length) return null;
|
|
569
|
-
const content = list.map((t) => [`## ${t.name}`, t.
|
|
570
|
-
return toStrip(rec, "tools", file_path, `${list.length} tool${list.length === 1 ? "" : "s"}`, content);
|
|
568
|
+
const content = list.map((t) => [`## ${t.name}`, t.content].filter(Boolean).join("\n\n")).join("\n\n");
|
|
569
|
+
return { ...toStrip(rec, "tools", file_path, `${list.length} tool${list.length === 1 ? "" : "s"}`, content), tools: list };
|
|
571
570
|
};
|
|
572
571
|
return [strip("System Tools", (n) => !isMcp(n)), strip("MCP Tools", isMcp)].filter(Boolean);
|
|
573
572
|
}
|
|
@@ -710,6 +709,7 @@ function freshMeta({ sessionId, parentSessionId, filePath, parentFilePath, fileS
|
|
|
710
709
|
aiTitle: null,
|
|
711
710
|
customTitle: null,
|
|
712
711
|
agentName: null,
|
|
712
|
+
tag: null,
|
|
713
713
|
firstUserPrompt: null,
|
|
714
714
|
firstUserCommand: null,
|
|
715
715
|
forkedFrom: null,
|
|
@@ -747,6 +747,7 @@ class SessionParser {
|
|
|
747
747
|
if (t === "ai-title" && obj.aiTitle) meta.aiTitle = obj.aiTitle;
|
|
748
748
|
if (t === "custom-title" && obj.customTitle) meta.customTitle = obj.customTitle;
|
|
749
749
|
if (t === "agent-name" && obj.agentName) meta.agentName = obj.agentName;
|
|
750
|
+
if (t === "tag") meta.tag = obj.tag || null;
|
|
750
751
|
if (t === "queue-operation" && obj.content?.includes("<scheduled-task")) meta.hasScheduledTask = true;
|
|
751
752
|
if (t === "started" && obj.key && obj.agentId) meta.workflowAgents += 1;
|
|
752
753
|
if (obj.cwd && !meta.project) meta.project = obj.cwd;
|
|
@@ -943,25 +944,130 @@ class StatCache {
|
|
|
943
944
|
onProgress?.({ done: 1, total: 1, scanning: false });
|
|
944
945
|
}
|
|
945
946
|
}
|
|
947
|
+
async function listFiles(dir, filter) {
|
|
948
|
+
const entries = await fsp.readdir(dir, { recursive: true, withFileTypes: true });
|
|
949
|
+
return entries.filter((e) => e.isFile() && filter(e.name)).map((e) => path.join(e.parentPath, e.name));
|
|
950
|
+
}
|
|
951
|
+
class FileWatcher {
|
|
952
|
+
#root;
|
|
953
|
+
#opts;
|
|
954
|
+
#watcher = null;
|
|
955
|
+
#closed = false;
|
|
956
|
+
constructor(root, opts) {
|
|
957
|
+
this.#root = root;
|
|
958
|
+
this.#opts = opts;
|
|
959
|
+
try {
|
|
960
|
+
this.#watcher = new EventFileWatcher(root, { ...opts, onFail: (err) => this.#fallBack(err) });
|
|
961
|
+
} catch (err) {
|
|
962
|
+
this.#fallBack(err);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
get mode() {
|
|
966
|
+
return this.#watcher instanceof IntervalFileWatcher ? "interval" : "event";
|
|
967
|
+
}
|
|
968
|
+
// Its first diff against the baseline also catches whatever changed while events were down
|
|
969
|
+
#fallBack(err) {
|
|
970
|
+
if (this.#closed) return;
|
|
971
|
+
console.warn("[watch] checking on an interval instead:", err.message);
|
|
972
|
+
this.#watcher = new IntervalFileWatcher(this.#root, this.#opts);
|
|
973
|
+
}
|
|
974
|
+
close() {
|
|
975
|
+
this.#closed = true;
|
|
976
|
+
this.#watcher?.close();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
class EventFileWatcher {
|
|
980
|
+
#opts;
|
|
981
|
+
#handle = null;
|
|
982
|
+
#timers = /* @__PURE__ */ new Map();
|
|
983
|
+
// filePath -> pending settle timer
|
|
984
|
+
#closed = false;
|
|
985
|
+
// Throws if the OS refuses the watch, e.g. on \\wsl.localhost\...
|
|
986
|
+
constructor(root, opts) {
|
|
987
|
+
this.#opts = { settleMs: 100, ...opts };
|
|
988
|
+
this.#handle = fs.watch(root, { recursive: true }, (_type, name) => {
|
|
989
|
+
if (!name) return this.#opts.onDrop();
|
|
990
|
+
if (this.#opts.filter(name)) this.#settle(path.join(root, name));
|
|
991
|
+
});
|
|
992
|
+
this.#handle.on("error", (err) => {
|
|
993
|
+
this.close();
|
|
994
|
+
this.#opts.onFail(err);
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
// Events carry no stat or kind, so stat each path once its writes settle
|
|
998
|
+
#settle(filePath) {
|
|
999
|
+
const { onChange, onUnlink, settleMs } = this.#opts;
|
|
1000
|
+
clearTimeout(this.#timers.get(filePath));
|
|
1001
|
+
this.#timers.set(filePath, setTimeout(async () => {
|
|
1002
|
+
this.#timers.delete(filePath);
|
|
1003
|
+
const stat = await fsp.stat(filePath).catch(() => null);
|
|
1004
|
+
if (this.#closed) return;
|
|
1005
|
+
if (!stat) onUnlink(filePath);
|
|
1006
|
+
else if (stat.isFile()) onChange(filePath, stat);
|
|
1007
|
+
}, settleMs));
|
|
1008
|
+
}
|
|
1009
|
+
close() {
|
|
1010
|
+
this.#closed = true;
|
|
1011
|
+
for (const timer of this.#timers.values()) {
|
|
1012
|
+
clearTimeout(timer);
|
|
1013
|
+
}
|
|
1014
|
+
this.#timers.clear();
|
|
1015
|
+
this.#handle?.close();
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
class IntervalFileWatcher {
|
|
1019
|
+
#root;
|
|
1020
|
+
#opts;
|
|
1021
|
+
#timer = null;
|
|
1022
|
+
#checks = 0;
|
|
1023
|
+
#closed = false;
|
|
1024
|
+
// Stats on a share are the bulk of a check, so each one stats only new files and those written within hotMs;
|
|
1025
|
+
// every sweepEvery-th check stats them all, catching an idle transcript that grows again (e.g. a resumed session)
|
|
1026
|
+
constructor(root, opts) {
|
|
1027
|
+
this.#root = root;
|
|
1028
|
+
this.#opts = { intervalMs: 2e3, hotMs: 10 * 6e4, sweepEvery: 30, ...opts };
|
|
1029
|
+
this.#schedule();
|
|
1030
|
+
}
|
|
1031
|
+
// Timed from the end of the last check, so a slow share can't pile them up
|
|
1032
|
+
#schedule() {
|
|
1033
|
+
this.#timer = setTimeout(() => this.#check().finally(() => this.#closed || this.#schedule()), this.#opts.intervalMs);
|
|
1034
|
+
}
|
|
1035
|
+
async #check() {
|
|
1036
|
+
const { filter, onChange, onUnlink, baseline } = this.#opts;
|
|
1037
|
+
const known = baseline();
|
|
1038
|
+
if (!known) return;
|
|
1039
|
+
const files = await listFiles(this.#root, filter).catch(() => null);
|
|
1040
|
+
if (!files) return;
|
|
1041
|
+
const sweep = ++this.#checks % this.#opts.sweepEvery === 0;
|
|
1042
|
+
const now = Date.now();
|
|
1043
|
+
await Promise.all(files.map(async (fp) => {
|
|
1044
|
+
const old = known.get(fp);
|
|
1045
|
+
if (!sweep && old && now - old.mtimeMs >= this.#opts.hotMs) return;
|
|
1046
|
+
const stat = await fsp.stat(fp).catch(() => null);
|
|
1047
|
+
if (stat && !this.#closed && (!old || old.size !== stat.size || old.mtimeMs !== stat.mtimeMs)) onChange(fp, stat);
|
|
1048
|
+
}));
|
|
1049
|
+
if (this.#closed) return;
|
|
1050
|
+
const listed = new Set(files);
|
|
1051
|
+
for (const fp of known.keys()) {
|
|
1052
|
+
if (!listed.has(fp)) onUnlink(fp);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
close() {
|
|
1056
|
+
this.#closed = true;
|
|
1057
|
+
clearTimeout(this.#timer);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
946
1060
|
const isJsonl = (p) => p.endsWith(".jsonl");
|
|
947
1061
|
class SessionsScanner {
|
|
948
1062
|
constructor({ root = CLAUDE_PROJECTS_DIR } = {}) {
|
|
949
1063
|
this.root = root;
|
|
950
1064
|
this.watcher = null;
|
|
951
|
-
this.watchWanted = false;
|
|
952
|
-
this.walkDone = Promise.withResolvers();
|
|
953
1065
|
this.statCache = new StatCache();
|
|
954
1066
|
}
|
|
955
1067
|
async _listDirs(p) {
|
|
956
1068
|
const entries = await fsp.readdir(p, { withFileTypes: true }).catch(() => []);
|
|
957
1069
|
return entries.filter((e) => e.isDirectory()).map((e) => path.join(e.parentPath, e.name));
|
|
958
1070
|
}
|
|
959
|
-
// Every .jsonl under `dir`, at any depth — subagent transcripts nest arbitrarily deep. Subtrees
|
|
960
|
-
// can't be pruned by directory mtime: on Windows, appending to a transcript doesn't bump its parent dir.
|
|
961
|
-
async _listJsonl(dir) {
|
|
962
|
-
const entries = await fsp.readdir(dir, { recursive: true, withFileTypes: true }).catch(() => []);
|
|
963
|
-
return entries.filter((e) => e.isFile() && isJsonl(e.name)).map((e) => path.join(e.parentPath, e.name));
|
|
964
|
-
}
|
|
965
1071
|
// Append-only transcripts span [birthtime, mtime], so files outside the period are skipped
|
|
966
1072
|
// Note birthtime is trusted only when well older than mtime, since copies/restores (git checkout, scp, zip) get a fresh birthtime over old content.
|
|
967
1073
|
_inPeriod(stat, day) {
|
|
@@ -973,14 +1079,10 @@ class SessionsScanner {
|
|
|
973
1079
|
// `signal` (a superseded scan) stops everything; once complete with the watcher live, the
|
|
974
1080
|
// StatCache mirrors disk and serves later scans in memory.
|
|
975
1081
|
async scan(day, opts = {}) {
|
|
976
|
-
if (this.statCache.complete
|
|
1082
|
+
if (this.statCache.complete) {
|
|
977
1083
|
return this.statCache.scan((stat) => this._inPeriod(stat, day), opts);
|
|
978
1084
|
}
|
|
979
|
-
|
|
980
|
-
await this._walk(day, opts);
|
|
981
|
-
} finally {
|
|
982
|
-
this.walkDone.resolve();
|
|
983
|
-
}
|
|
1085
|
+
return this._walk(day, opts);
|
|
984
1086
|
}
|
|
985
1087
|
async _walk(day, { onFile, onBatchDone, onProgress, signal } = {}) {
|
|
986
1088
|
const projects = await this._listDirs(this.root);
|
|
@@ -989,7 +1091,8 @@ class SessionsScanner {
|
|
|
989
1091
|
progress();
|
|
990
1092
|
await Promise.all(projects.map(async (projDir) => {
|
|
991
1093
|
if (signal?.aborted) return;
|
|
992
|
-
const
|
|
1094
|
+
const files = await listFiles(projDir, isJsonl).catch(() => []);
|
|
1095
|
+
const results = await Promise.all(files.map(async (fp) => {
|
|
993
1096
|
const stat = signal?.aborted ? null : await fsp.stat(fp).catch(() => null);
|
|
994
1097
|
this.statCache.record(fp, stat);
|
|
995
1098
|
return stat && this._inPeriod(stat, day) && !signal?.aborted ? onFile?.(fp, stat) : null;
|
|
@@ -1004,38 +1107,28 @@ class SessionsScanner {
|
|
|
1004
1107
|
if (onBatchDone) await onBatchDone();
|
|
1005
1108
|
progress();
|
|
1006
1109
|
}
|
|
1007
|
-
// Starts
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1110
|
+
// Starts before the first walk, so that walk already completes the StatCache
|
|
1111
|
+
watch({ onChange, onUnlink }) {
|
|
1112
|
+
try {
|
|
1113
|
+
fs.mkdirSync(this.root, { recursive: true });
|
|
1114
|
+
} catch {
|
|
1115
|
+
}
|
|
1116
|
+
this.watcher = new FileWatcher(this.root, {
|
|
1117
|
+
filter: isJsonl,
|
|
1118
|
+
onChange: (p, stat) => {
|
|
1119
|
+
this.statCache.record(p, stat);
|
|
1120
|
+
onChange(p, stat);
|
|
1121
|
+
},
|
|
1122
|
+
onUnlink: (p) => {
|
|
1123
|
+
this.statCache.remove(p);
|
|
1124
|
+
onUnlink(p);
|
|
1125
|
+
},
|
|
1126
|
+
onDrop: () => this.statCache.clear(),
|
|
1127
|
+
baseline: () => this.statCache.complete ? this.statCache.stats : null
|
|
1128
|
+
// null until a full walk exists to diff against
|
|
1022
1129
|
});
|
|
1023
|
-
const changed = (p, stat) => {
|
|
1024
|
-
if (!isJsonl(p)) return;
|
|
1025
|
-
this.statCache.record(p, stat);
|
|
1026
|
-
onChange?.(p, stat);
|
|
1027
|
-
};
|
|
1028
|
-
const removed = (p) => {
|
|
1029
|
-
if (!isJsonl(p)) return;
|
|
1030
|
-
this.statCache.remove(p);
|
|
1031
|
-
onUnlink?.(p);
|
|
1032
|
-
};
|
|
1033
|
-
this.watcher.on("add", changed);
|
|
1034
|
-
this.watcher.on("change", changed);
|
|
1035
|
-
this.watcher.on("unlink", removed);
|
|
1036
1130
|
}
|
|
1037
1131
|
stop() {
|
|
1038
|
-
this.watchWanted = false;
|
|
1039
1132
|
if (this.watcher) {
|
|
1040
1133
|
this.watcher.close();
|
|
1041
1134
|
this.watcher = null;
|
|
@@ -627,6 +627,8 @@
|
|
|
627
627
|
|
|
628
628
|
.worktree-tag { color: #34d399; }
|
|
629
629
|
|
|
630
|
+
.session-tag { color: #4ade80; }
|
|
631
|
+
|
|
630
632
|
.fork-tag {
|
|
631
633
|
color: var(--accent);
|
|
632
634
|
font-weight: bold;
|
|
@@ -1076,6 +1078,10 @@ button.msg-summary:hover { color: var(--text); background: var(--bg-elev-2); bor
|
|
|
1076
1078
|
.instruction-source:first-child { padding-top: 0; }
|
|
1077
1079
|
|
|
1078
1080
|
/* Full-width toggle so the estimated token count can sit right-aligned, like msg-header-right. */
|
|
1081
|
+
/* Nested tool rows cancel the aux-body's right padding so their counts line up with the strips'. */
|
|
1082
|
+
.instruction-file .instruction-file { border-left-color: var(--border); margin-right: -8px; }
|
|
1083
|
+
/* A rule under the strip's count marks it as the sum of the tool counts below. */
|
|
1084
|
+
.aux-body > .instruction-file:first-child .instruction-tokens { border-top: 1px solid var(--border); padding-top: 2px; }
|
|
1079
1085
|
.instruction-file .aux-toggle { display: flex; width: 100%; align-items: center; }
|
|
1080
1086
|
.instruction-tokens { margin-left: auto; color: var(--text-faint); }
|
|
1081
1087
|
|
|
@@ -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, 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,
|
|
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, w as defaultUrlTransform, T as Terminal, J as JsonView, x as vscodeTheme, y as tippy, z as reactDomExports, A as an, B as qt, Q as Qt, E as nn, F as parse, I as delegate, K as clientExports } from "./vendors-D2DMOduT.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.
|
|
38
|
-
const [MAJOR, MINOR, PATCH] = "1.
|
|
37
|
+
if (version !== "1.10.0") {
|
|
38
|
+
const [MAJOR, MINOR, PATCH] = "1.10.0".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.
|
|
43
|
+
localStorage.setItem(VERSION_KEY, "1.10.0");
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
function useMouseFontScale(storageKey) {
|
|
@@ -248,9 +248,6 @@ function WorkTimeOverlay({
|
|
|
248
248
|
const id = setInterval(() => setNow(Date.now()), 6e4);
|
|
249
249
|
return () => clearInterval(id);
|
|
250
250
|
}, []);
|
|
251
|
-
reactExports.useEffect(() => {
|
|
252
|
-
if (workTime) window.api.setWorkHours({ work_hours: { start: fmtHM(workTime.startMin), end: fmtHM(workTime.endMin) } });
|
|
253
|
-
}, [workTime]);
|
|
254
251
|
const chartRight = chartLeft + chartWidth;
|
|
255
252
|
const xForMin = (min) => chartLeft + (dayStart + min * 6e4 - viewStart) / (viewEnd - viewStart) * chartWidth;
|
|
256
253
|
const xStart = workTime ? xForMin(workTime.startMin) : 0;
|
|
@@ -259,15 +256,18 @@ function WorkTimeOverlay({
|
|
|
259
256
|
e.stopPropagation();
|
|
260
257
|
e.preventDefault();
|
|
261
258
|
setDragging(which);
|
|
259
|
+
let next = null;
|
|
262
260
|
const onMove = (m) => {
|
|
263
261
|
const rect = containerRef.current.getBoundingClientRect();
|
|
264
262
|
const ratio = clamp((m.clientX - rect.left - chartLeft) / chartWidth, 0, 1);
|
|
265
263
|
const ts = viewStart + ratio * (viewEnd - viewStart);
|
|
266
264
|
const min = clamp(Math.round((ts - dayStart) / 6e4 / SNAP_MIN) * SNAP_MIN, 0, 24 * 60);
|
|
267
|
-
|
|
265
|
+
next = which === "start" ? { ...workTime, startMin: Math.min(min, workTime.endMin - SNAP_MIN) } : { ...workTime, endMin: Math.max(min, workTime.startMin + SNAP_MIN) };
|
|
266
|
+
setWorkTime(next);
|
|
268
267
|
};
|
|
269
268
|
const onUp = () => {
|
|
270
269
|
setDragging(null);
|
|
270
|
+
if (next) window.api.setWorkHours({ work_hours: { start: fmtHM(next.startMin), end: fmtHM(next.endMin) } });
|
|
271
271
|
document.removeEventListener("mousemove", onMove);
|
|
272
272
|
document.removeEventListener("mouseup", onUp);
|
|
273
273
|
};
|
|
@@ -1189,6 +1189,7 @@ function SessionList({ sessions, selectedId, deepLink, onSelect }) {
|
|
|
1189
1189
|
const filtered = q ? sessions.filter((s) => [
|
|
1190
1190
|
s.customTitle,
|
|
1191
1191
|
s.agentName,
|
|
1192
|
+
s.tag,
|
|
1192
1193
|
s.aiTitle,
|
|
1193
1194
|
s.summary,
|
|
1194
1195
|
s.firstUserPrompt,
|
|
@@ -1296,6 +1297,10 @@ ${TIPS.time}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 11
|
|
|
1296
1297
|
] }) : sessionLabel(s) })
|
|
1297
1298
|
] }),
|
|
1298
1299
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "session-time-bottom", children: [
|
|
1300
|
+
s.tag && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "session-tag", title: "Session tag", children: [
|
|
1301
|
+
"#",
|
|
1302
|
+
s.tag
|
|
1303
|
+
] }),
|
|
1299
1304
|
s.project && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "session-project", title: s.project, children: s.projectShort }),
|
|
1300
1305
|
s.models?.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "session-model", children: s.models.map((m) => m.replace(/^claude-/, "")).join(", ") }),
|
|
1301
1306
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: format(s.lastActivityAt, "MMM d, HH:mm:ss"), children: fmtAgo(s.lastActivityAt) }),
|
|
@@ -1440,7 +1445,8 @@ function buildLinkComponents(basePath) {
|
|
|
1440
1445
|
}
|
|
1441
1446
|
};
|
|
1442
1447
|
}
|
|
1443
|
-
const
|
|
1448
|
+
const urlTransform = (url, key, node) => node.tagName === "img" && /^data:image\//i.test(url) ? url : defaultUrlTransform(url);
|
|
1449
|
+
const Chunk = React.memo(({ text, components }) => /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown$1, { remarkPlugins: [remarkGfm], rehypePlugins: [rehypeHighlight], components, urlTransform, children: text }));
|
|
1444
1450
|
function Markdown({ text, basePath = null, autoFence = false, className = "", ...rest }) {
|
|
1445
1451
|
const ref = reactExports.useRef(null);
|
|
1446
1452
|
const findOpen = useFindActive();
|
|
@@ -1748,7 +1754,7 @@ function InstructionFile({ it, model, tokens: tokens2 }) {
|
|
|
1748
1754
|
] }),
|
|
1749
1755
|
open && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "aux-body", children: [
|
|
1750
1756
|
it.name && it.name !== it.file_path && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "instruction-path", children: it.file_path }),
|
|
1751
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { className: "block-text", text: it.content || "", basePath: it.file_path })
|
|
1757
|
+
it.tools ? it.tools.map((t) => /* @__PURE__ */ jsxRuntimeExports.jsx(InstructionFile, { it: { file_path: t.name, content: t.content }, model, tokens: countTokens(t.content, it.model ?? model) }, t.name)) : /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { className: "block-text", text: it.content || "", basePath: it.file_path })
|
|
1752
1758
|
] })
|
|
1753
1759
|
] });
|
|
1754
1760
|
}
|
|
@@ -2087,7 +2093,8 @@ ${transcript}`;
|
|
|
2087
2093
|
- Model: ${meta.models.join(", ") || "—"}
|
|
2088
2094
|
- Service tier: ${meta.serviceTier || "—"}
|
|
2089
2095
|
- Speed: ${meta.speed ? meta.speed === "fast" ? meta.fastPricingUnknown ? "fast (pricing unknown)" : "fast" : meta.speed : "—"}
|
|
2090
|
-
|
|
2096
|
+
${meta.tag ? `- Tag: ${meta.tag}
|
|
2097
|
+
` : ""}- Git branch: ${meta.gitBranch || "—"}
|
|
2091
2098
|
- Source: ${meta.source || meta.entrypoint || "—"}
|
|
2092
2099
|
- Scheduled: ${meta.hasScheduledTask ? "yes" : "no"}
|
|
2093
2100
|
- CLI version: ${meta.version || "—"}
|
|
@@ -2332,6 +2339,7 @@ ${body}`);
|
|
|
2332
2339
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Model", value: modelLabel, mono: true }),
|
|
2333
2340
|
meta.serviceTier && /* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Service tier", value: meta.serviceTier }),
|
|
2334
2341
|
meta.speed && /* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Speed", value: meta.speed === "fast" ? meta.fastPricingUnknown ? "fast (pricing unknown)" : "fast" : meta.speed }),
|
|
2342
|
+
meta.tag && /* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Tag", value: meta.tag, mono: true }),
|
|
2335
2343
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Git branch", value: meta.gitBranch || "—", mono: true }),
|
|
2336
2344
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Source", value: meta.source || meta.entrypoint || "—" }),
|
|
2337
2345
|
meta.hasScheduledTask && /* @__PURE__ */ jsxRuntimeExports.jsx(Field, { label: "Scheduled", value: "yes" }),
|
|
@@ -54069,16 +54069,17 @@ var vscodeTheme = {
|
|
|
54069
54069
|
};
|
|
54070
54070
|
var reactDomExports = requireReactDom();
|
|
54071
54071
|
export {
|
|
54072
|
-
|
|
54073
|
-
|
|
54072
|
+
an as A,
|
|
54073
|
+
qt as B,
|
|
54074
54074
|
Clock as C,
|
|
54075
54075
|
DollarSign as D,
|
|
54076
|
-
|
|
54077
|
-
|
|
54076
|
+
nn as E,
|
|
54077
|
+
parse$1 as F,
|
|
54078
54078
|
Gauge as G,
|
|
54079
54079
|
Hourglass as H,
|
|
54080
|
-
|
|
54080
|
+
delegate as I,
|
|
54081
54081
|
JsonView as J,
|
|
54082
|
+
clientExports as K,
|
|
54082
54083
|
MessageSquare as M,
|
|
54083
54084
|
Qt as Q,
|
|
54084
54085
|
React as R,
|
|
@@ -54106,8 +54107,8 @@ export {
|
|
|
54106
54107
|
Markdown as t,
|
|
54107
54108
|
rehypeHighlight as u,
|
|
54108
54109
|
remarkGfm as v,
|
|
54109
|
-
|
|
54110
|
-
|
|
54111
|
-
|
|
54112
|
-
|
|
54110
|
+
defaultUrlTransform as w,
|
|
54111
|
+
vscodeTheme as x,
|
|
54112
|
+
tippy as y,
|
|
54113
|
+
reactDomExports as z
|
|
54113
54114
|
};
|
package/out/renderer/index.html
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
<meta charset="UTF-8" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>Discover</title>
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
-
<link rel="modulepreload" crossorigin href="./assets/vendors-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-x_-ZeUa3.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="./assets/vendors-D2DMOduT.js">
|
|
11
11
|
<link rel="stylesheet" crossorigin href="./assets/vendors-B4XMnGdr.css">
|
|
12
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
12
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DnYN00T3.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-discover",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Claude Discover — a desktop tool to browse your local Claude Code sessions: conversations, token costs, and captured API traffic",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@anthropic-ai/claude-agent-sdk": "^0.3.266",
|
|
34
34
|
"@date-fns/tz": "^1.5.0",
|
|
35
|
-
"chokidar": "^5.0.0",
|
|
36
35
|
"date-fns": "^4.4.0",
|
|
37
36
|
"electron": "43.2.0",
|
|
38
37
|
"electron-context-menu": "^4.1.2",
|