claude-session-dashboard 0.4.5 → 0.5.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.
Files changed (45) hide show
  1. package/dist/client/assets/{_dashboard-Job6DOd1.js → _dashboard-ChSI7O-o.js} +1 -1
  2. package/dist/client/assets/{_sessionId-CIFXqjVa.js → _sessionId-DxfkocLt.js} +2 -2
  3. package/dist/client/assets/app-BAZLXX_G.css +1 -0
  4. package/dist/client/assets/createServerFn-DJjqV8Yc.js +1 -0
  5. package/dist/client/assets/index-BHwOAB5a.js +1 -0
  6. package/dist/client/assets/main-DMwMzWYr.js +69 -0
  7. package/dist/client/assets/{sessions.queries-ClgzoOt4.js → sessions.queries-D7WObk5d.js} +1 -1
  8. package/dist/client/assets/settings-BM0TBEkW.js +1 -0
  9. package/dist/client/assets/settings.types-BNSfIfFX.js +1 -0
  10. package/dist/client/assets/stats-wLUGXFpZ.js +4 -0
  11. package/dist/client/assets/useSessionCost-BPqnyONZ.js +37 -0
  12. package/dist/server/assets/{_dashboard-61fpMMMe.js → _dashboard-DZJZ9oYy.js} +7 -6
  13. package/dist/server/assets/{_sessionId-B_O50OfN.js → _sessionId-znGcd1Dj.js} +40 -11
  14. package/dist/server/assets/_tanstack-start-manifest_v-BNorjuP4.js +4 -0
  15. package/dist/server/assets/{app-info.api-CdaWsxHl.js → app-info.api-CrHplh0q.js} +31 -16
  16. package/dist/server/assets/{createServerRpc-Bd3B-Ah9.js → createServerRpc-D_-6bKnO.js} +1 -1
  17. package/dist/server/assets/{createSsrRpc-CVg2UDl0.js → createSsrRpc-OFLSk08e.js} +2 -3
  18. package/dist/server/assets/{index-BYcFI9Ho.js → index-BnvjnlZM.js} +27 -10
  19. package/dist/server/assets/{project-analytics.api-QnhRRs7T.js → project-analytics.api-6b5TIBNn.js} +10 -8
  20. package/dist/server/assets/{router-BvYNknMb.js → router-DAepjaOj.js} +6 -6
  21. package/dist/server/assets/{session-detail.api-8plxSeB0.js → session-detail.api-BQts3iQn.js} +38 -33
  22. package/dist/server/assets/{session-parser-DxLcS8VW.js → session-parser-DKZZMuh6.js} +122 -30
  23. package/dist/server/assets/{session-scanner-DRGzVO2T.js → session-scanner-CECpfGFh.js} +4 -4
  24. package/dist/server/assets/{sessions.api-DRmOjipJ.js → sessions.api-CQ-Lrk5S.js} +10 -8
  25. package/dist/server/assets/{sessions.queries-CvAnVbE8.js → sessions.queries-MfPgj6cK.js} +1 -1
  26. package/dist/server/assets/{settings-Ct2BZGxb.js → settings-DsLaw8yg.js} +11 -10
  27. package/dist/server/assets/{settings.api-C9L2GoIE.js → settings.api-Cq5KPUxN.js} +8 -7
  28. package/dist/server/assets/{settings.queries-BVEZA-1G.js → settings.queries-CMWxUDF-.js} +2 -2
  29. package/dist/server/assets/{settings.types-DntadCHo.js → settings.types-CphWe-HW.js} +10 -1
  30. package/dist/server/assets/{stats-CZEpvzmd.js → stats-DKbhSePW.js} +9 -9
  31. package/dist/server/assets/{stats.api-CH-wTCGE.js → stats.api-tIZqhk4B.js} +10 -8
  32. package/dist/server/assets/{useSessionCost-CyWBuljV.js → useSessionCost-iQEg4FRM.js} +2 -2
  33. package/dist/server/server.js +456 -817
  34. package/package.json +3 -2
  35. package/LICENSE +0 -21
  36. package/README.md +0 -194
  37. package/dist/client/assets/app-CkRVT69z.css +0 -1
  38. package/dist/client/assets/createServerFn-6SJrpRCO.js +0 -1
  39. package/dist/client/assets/index-DDr2smLW.js +0 -1
  40. package/dist/client/assets/main-B6FohBFQ.js +0 -69
  41. package/dist/client/assets/settings-DQD2EaIq.js +0 -1
  42. package/dist/client/assets/settings.types-LYd9Z8Y1.js +0 -1
  43. package/dist/client/assets/stats-CrWQ_y2R.js +0 -4
  44. package/dist/client/assets/useSessionCost-Drt0v6oj.js +0 -37
  45. package/dist/server/assets/_tanstack-start-manifest_v-Dva5sIpS.js +0 -4
@@ -1,6 +1,7 @@
1
1
  import * as path from "node:path";
2
2
  import * as os from "node:os";
3
- import * as fs from "node:fs";
3
+ import * as fs from "node:fs/promises";
4
+ import * as fs$1 from "node:fs";
4
5
  import * as readline from "node:readline";
5
6
  function resolveClaudeDir() {
6
7
  if (process.env.CLAUDE_HOME) {
@@ -9,14 +10,25 @@ function resolveClaudeDir() {
9
10
  return path.join(os.homedir(), ".claude");
10
11
  }
11
12
  const CLAUDE_DIR = resolveClaudeDir();
13
+ function getClaudeDir() {
14
+ return CLAUDE_DIR;
15
+ }
12
16
  function getProjectsDir() {
13
17
  return path.join(CLAUDE_DIR, "projects");
14
18
  }
15
19
  function getStatsPath() {
16
20
  return path.join(CLAUDE_DIR, "stats-cache.json");
17
21
  }
22
+ function getProjectsDirFor(source) {
23
+ return path.join(source.claudeDir, "projects");
24
+ }
18
25
  function decodeProjectDirName(dirName) {
19
- return dirName.replace(/^-/, "/").replace(/-/g, "/");
26
+ const decoded = dirName.replace(/^-/, "/").replace(/-/g, "/");
27
+ const windowsDrive = decoded.match(/^\/([A-Z])\/(.*)$/);
28
+ if (windowsDrive) {
29
+ return `${windowsDrive[1]}:/${windowsDrive[2]}`;
30
+ }
31
+ return decoded;
20
32
  }
21
33
  function extractProjectName(decodedPath) {
22
34
  return path.basename(decodedPath);
@@ -24,6 +36,75 @@ function extractProjectName(decodedPath) {
24
36
  function extractSessionId(filename) {
25
37
  return filename.replace(/\.jsonl$/, "");
26
38
  }
39
+ async function detectCurrentPlatform() {
40
+ if (process.platform === "win32") return "windows";
41
+ if (process.platform === "darwin") return "macos";
42
+ try {
43
+ const procVersion = await fs.readFile("/proc/version", "utf8");
44
+ if (procVersion.toLowerCase().includes("microsoft") || procVersion.toLowerCase().includes("wsl")) {
45
+ return "wsl";
46
+ }
47
+ } catch {
48
+ }
49
+ return "linux";
50
+ }
51
+ async function detectWslDistros() {
52
+ if (process.platform !== "win32") return [];
53
+ const wslRoot = "\\\\wsl$";
54
+ let distros;
55
+ try {
56
+ distros = await fs.readdir(wslRoot);
57
+ } catch {
58
+ return [];
59
+ }
60
+ const sources = [];
61
+ for (const distro of distros) {
62
+ const homeDir = `${wslRoot}\\${distro}\\home`;
63
+ let users;
64
+ try {
65
+ users = await fs.readdir(homeDir);
66
+ } catch {
67
+ continue;
68
+ }
69
+ for (const user of users) {
70
+ const claudeDir = `${wslRoot}\\${distro}\\home\\${user}\\.claude`;
71
+ try {
72
+ await fs.access(claudeDir);
73
+ sources.push({
74
+ id: `wsl-${distro.toLowerCase()}-${user}`,
75
+ label: `WSL - ${distro}`,
76
+ claudeDir,
77
+ platform: "wsl",
78
+ available: true
79
+ });
80
+ } catch {
81
+ }
82
+ }
83
+ }
84
+ return sources;
85
+ }
86
+ async function getDataSources() {
87
+ const claudeDir = getClaudeDir();
88
+ const platform = await detectCurrentPlatform();
89
+ let available = false;
90
+ try {
91
+ await fs.access(claudeDir);
92
+ available = true;
93
+ } catch {
94
+ available = false;
95
+ }
96
+ const primarySource = {
97
+ id: "primary",
98
+ label: platform === "windows" ? "Windows" : platform === "macos" ? "macOS" : platform === "wsl" ? "WSL" : "Linux",
99
+ claudeDir,
100
+ platform,
101
+ available
102
+ };
103
+ const sources = [primarySource];
104
+ const wslSources = await detectWslDistros();
105
+ sources.push(...wslSources);
106
+ return sources;
107
+ }
27
108
  const AGENT_FILE_PATTERN = /^agent-(.+)\.jsonl$/;
28
109
  async function discoverSubagentFiles(sessionDir) {
29
110
  const result = /* @__PURE__ */ new Map();
@@ -33,7 +114,7 @@ async function discoverSubagentFiles(sessionDir) {
33
114
  ];
34
115
  for (const dir of candidateDirs) {
35
116
  try {
36
- const entries = await fs.promises.readdir(dir);
117
+ const entries = await fs$1.promises.readdir(dir);
37
118
  for (const entry of entries) {
38
119
  const match = AGENT_FILE_PATTERN.exec(entry);
39
120
  if (match) {
@@ -131,7 +212,8 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
131
212
  const taskById = /* @__PURE__ */ new Map();
132
213
  const contextSnapshots = [];
133
214
  let assistantTurnIndex = 0;
134
- const stream = fs.createReadStream(filePath, { encoding: "utf-8" });
215
+ const seenRequestIds = /* @__PURE__ */ new Set();
216
+ const stream = fs$1.createReadStream(filePath, { encoding: "utf-8" });
135
217
  const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
136
218
  for await (const line of rl) {
137
219
  const msg = safeParse(line);
@@ -147,8 +229,11 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
147
229
  if (progressModel && parentId) {
148
230
  agentProgressModel.set(parentId, progressModel);
149
231
  }
232
+ const progressRequestId = msg.requestId;
233
+ const isNewProgressRequest = !progressRequestId || !seenRequestIds.has(progressRequestId);
234
+ if (progressRequestId) seenRequestIds.add(progressRequestId);
150
235
  const usage = msg.data?.message?.message?.usage;
151
- if (usage) {
236
+ if (usage && isNewProgressRequest) {
152
237
  const existing = agentProgressTokens.get(parentId) ?? {
153
238
  inputTokens: 0,
154
239
  outputTokens: 0,
@@ -266,23 +351,28 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
266
351
  cacheReadInputTokens: u.cache_read_input_tokens ?? 0,
267
352
  cacheCreationInputTokens: u.cache_creation_input_tokens ?? 0
268
353
  };
269
- totalTokens.inputTokens += tokens.inputTokens;
270
- totalTokens.outputTokens += tokens.outputTokens;
271
- totalTokens.cacheReadInputTokens += tokens.cacheReadInputTokens;
272
- totalTokens.cacheCreationInputTokens += tokens.cacheCreationInputTokens;
273
- if (msg.message.model) {
274
- const modelId = msg.message.model;
275
- const existing = tokensByModel[modelId] ?? {
276
- inputTokens: 0,
277
- outputTokens: 0,
278
- cacheReadInputTokens: 0,
279
- cacheCreationInputTokens: 0
280
- };
281
- existing.inputTokens += tokens.inputTokens;
282
- existing.outputTokens += tokens.outputTokens;
283
- existing.cacheReadInputTokens += tokens.cacheReadInputTokens;
284
- existing.cacheCreationInputTokens += tokens.cacheCreationInputTokens;
285
- tokensByModel[modelId] = existing;
354
+ const requestId = msg.requestId;
355
+ const isNewRequest = !requestId || !seenRequestIds.has(requestId);
356
+ if (requestId) seenRequestIds.add(requestId);
357
+ if (isNewRequest) {
358
+ totalTokens.inputTokens += tokens.inputTokens;
359
+ totalTokens.outputTokens += tokens.outputTokens;
360
+ totalTokens.cacheReadInputTokens += tokens.cacheReadInputTokens;
361
+ totalTokens.cacheCreationInputTokens += tokens.cacheCreationInputTokens;
362
+ if (msg.message.model) {
363
+ const modelId = msg.message.model;
364
+ const existing = tokensByModel[modelId] ?? {
365
+ inputTokens: 0,
366
+ outputTokens: 0,
367
+ cacheReadInputTokens: 0,
368
+ cacheCreationInputTokens: 0
369
+ };
370
+ existing.inputTokens += tokens.inputTokens;
371
+ existing.outputTokens += tokens.outputTokens;
372
+ existing.cacheReadInputTokens += tokens.cacheReadInputTokens;
373
+ existing.cacheCreationInputTokens += tokens.cacheCreationInputTokens;
374
+ tokensByModel[modelId] = existing;
375
+ }
286
376
  }
287
377
  const contextSize = tokens.inputTokens + tokens.cacheReadInputTokens + tokens.cacheCreationInputTokens;
288
378
  const lastSnapshot = contextSnapshots[contextSnapshots.length - 1];
@@ -301,7 +391,7 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
301
391
  timestamp: msg.timestamp ?? "",
302
392
  model: msg.message.model,
303
393
  toolCalls,
304
- tokens,
394
+ tokens: isNewRequest ? tokens : void 0,
305
395
  stopReason: msg.message.stop_reason
306
396
  });
307
397
  continue;
@@ -473,7 +563,7 @@ async function parseSubagentDetail(subagentFilePath) {
473
563
  let model;
474
564
  let totalToolUseCount = 0;
475
565
  const seenRequestIds = /* @__PURE__ */ new Set();
476
- const stream = fs.createReadStream(subagentFilePath, { encoding: "utf-8" });
566
+ const stream = fs$1.createReadStream(subagentFilePath, { encoding: "utf-8" });
477
567
  const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
478
568
  let lineCount = 0;
479
569
  const MAX_LINES_FOR_INJECTED = 20;
@@ -616,7 +706,7 @@ function mergeSubagentData(agent, detail, progressTokens, totalTokens, tokensByM
616
706
  }
617
707
  async function readHeadLines(filePath, count) {
618
708
  const lines = [];
619
- const stream = fs.createReadStream(filePath, { encoding: "utf-8" });
709
+ const stream = fs$1.createReadStream(filePath, { encoding: "utf-8" });
620
710
  const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
621
711
  for await (const line of rl) {
622
712
  lines.push(line);
@@ -627,10 +717,10 @@ async function readHeadLines(filePath, count) {
627
717
  return lines;
628
718
  }
629
719
  async function readTailLines(filePath, count) {
630
- const stat = await fs.promises.stat(filePath);
720
+ const stat = await fs$1.promises.stat(filePath);
631
721
  const readSize = Math.min(stat.size, 65536);
632
722
  const buffer = Buffer.alloc(readSize);
633
- const fd = await fs.promises.open(filePath, "r");
723
+ const fd = await fs$1.promises.open(filePath, "r");
634
724
  try {
635
725
  await fd.read(buffer, 0, readSize, Math.max(0, stat.size - readSize));
636
726
  } finally {
@@ -664,11 +754,13 @@ function extractTextContent(msg) {
664
754
  return texts.length > 0 ? texts.join("\n").slice(0, 500) : void 0;
665
755
  }
666
756
  export {
667
- getProjectsDir as a,
668
- extractSessionId as b,
669
- parseSummary as c,
757
+ getDataSources as a,
758
+ getProjectsDirFor as b,
759
+ getProjectsDir as c,
670
760
  decodeProjectDirName as d,
671
761
  extractProjectName as e,
762
+ extractSessionId as f,
672
763
  getStatsPath as g,
764
+ parseSummary as h,
673
765
  parseDetail as p
674
766
  };
@@ -1,6 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { a as getProjectsDir, d as decodeProjectDirName, e as extractProjectName, b as extractSessionId, c as parseSummary } from "./session-parser-DxLcS8VW.js";
3
+ import { c as getProjectsDir, d as decodeProjectDirName, e as extractProjectName, f as extractSessionId, h as parseSummary } from "./session-parser-DKZZMuh6.js";
4
4
  async function scanProjects() {
5
5
  const projectsDir = getProjectsDir();
6
6
  let entries;
@@ -28,7 +28,7 @@ async function scanProjects() {
28
28
  return projects;
29
29
  }
30
30
  const ACTIVE_THRESHOLD_MS = 12e4;
31
- async function isSessionActive(projectDirName, sessionId) {
31
+ async function isSessionActive(projectDirName, sessionId, projectsDirOverride) {
32
32
  const projectsDir = getProjectsDir();
33
33
  const jsonlPath = path.join(projectsDir, projectDirName, `${sessionId}.jsonl`);
34
34
  const lockDirPath = path.join(projectsDir, projectDirName, sessionId);
@@ -94,7 +94,7 @@ async function getActiveSessions() {
94
94
  return all.filter((s) => s.isActive);
95
95
  }
96
96
  export {
97
- scanAllSessions as a,
97
+ scanAllSessionsWithPaths as a,
98
98
  getActiveSessions as g,
99
- scanAllSessionsWithPaths as s
99
+ scanAllSessions as s
100
100
  };
@@ -1,23 +1,25 @@
1
- import { c as createServerRpc } from "./createServerRpc-Bd3B-Ah9.js";
1
+ import { c as createServerRpc } from "./createServerRpc-D_-6bKnO.js";
2
2
  import { z } from "zod";
3
- import { a as scanAllSessions, g as getActiveSessions } from "./session-scanner-DRGzVO2T.js";
3
+ import { s as scanAllSessions, g as getActiveSessions } from "./session-scanner-CECpfGFh.js";
4
4
  import { c as createServerFn } from "../server.js";
5
5
  import "node:fs";
6
6
  import "node:path";
7
- import "./session-parser-DxLcS8VW.js";
7
+ import "./session-parser-DKZZMuh6.js";
8
8
  import "node:os";
9
+ import "node:fs/promises";
9
10
  import "node:readline";
10
- import "@tanstack/history";
11
- import "@tanstack/router-core/ssr/client";
12
- import "@tanstack/router-core";
13
11
  import "node:async_hooks";
14
- import "@tanstack/router-core/ssr/server";
15
12
  import "h3-v2";
13
+ import "@tanstack/router-core";
16
14
  import "tiny-invariant";
17
15
  import "seroval";
16
+ import "@tanstack/history";
17
+ import "@tanstack/router-core/ssr/client";
18
+ import "@tanstack/router-core/ssr/server";
19
+ import "react";
20
+ import "@tanstack/react-router";
18
21
  import "react/jsx-runtime";
19
22
  import "@tanstack/react-router/ssr/server";
20
- import "@tanstack/react-router";
21
23
  const getSessionList_createServerFn_handler = createServerRpc({
22
24
  id: "8fd6c4e5b4d5590acf1ec73da75f249978e8aced6dd2be23de06ade8431033be",
23
25
  name: "getSessionList",
@@ -1,5 +1,5 @@
1
1
  import { queryOptions, keepPreviousData } from "@tanstack/react-query";
2
- import { c as createSsrRpc } from "./createSsrRpc-CVg2UDl0.js";
2
+ import { c as createSsrRpc } from "./createSsrRpc-OFLSk08e.js";
3
3
  import { z } from "zod";
4
4
  import { c as createServerFn } from "../server.js";
5
5
  const getSessionList = createServerFn({
@@ -1,21 +1,21 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { useQuery } from "@tanstack/react-query";
4
- import { s as settingsQuery, u as useSettingsMutation } from "./settings.queries-BVEZA-1G.js";
5
- import { a as SUBSCRIPTION_TIERS, b as DEFAULT_PRICING, D as DEFAULT_SETTINGS } from "./settings.types-DntadCHo.js";
6
- import { u as usePrivacy, a as useTheme } from "./router-BvYNknMb.js";
7
- import "./createSsrRpc-CVg2UDl0.js";
4
+ import { s as settingsQuery, u as useSettingsMutation } from "./settings.queries-CMWxUDF-.js";
5
+ import { a as SUBSCRIPTION_TIERS, b as DEFAULT_PRICING, D as DEFAULT_SETTINGS } from "./settings.types-CphWe-HW.js";
6
+ import { u as usePrivacy, a as useTheme } from "./router-DAepjaOj.js";
7
+ import "./createSsrRpc-OFLSk08e.js";
8
8
  import "../server.js";
9
- import "@tanstack/history";
10
- import "@tanstack/router-core/ssr/client";
11
- import "@tanstack/router-core";
12
9
  import "node:async_hooks";
13
- import "@tanstack/router-core/ssr/server";
14
10
  import "h3-v2";
11
+ import "@tanstack/router-core";
15
12
  import "tiny-invariant";
16
13
  import "seroval";
17
- import "@tanstack/react-router/ssr/server";
14
+ import "@tanstack/history";
15
+ import "@tanstack/router-core/ssr/client";
16
+ import "@tanstack/router-core/ssr/server";
18
17
  import "@tanstack/react-router";
18
+ import "@tanstack/react-router/ssr/server";
19
19
  import "zod";
20
20
  function TierSelector({ value, onChange }) {
21
21
  return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-4", children: SUBSCRIPTION_TIERS.map((tier) => {
@@ -137,7 +137,8 @@ function SettingsForm({ settings }) {
137
137
  const updated = {
138
138
  version: 1,
139
139
  subscriptionTier: tier,
140
- pricingOverrides: overrides
140
+ pricingOverrides: overrides,
141
+ dataSources: []
141
142
  };
142
143
  mutation.mutate(updated, {
143
144
  onSuccess: () => {
@@ -1,21 +1,22 @@
1
- import { c as createServerRpc } from "./createServerRpc-Bd3B-Ah9.js";
1
+ import { c as createServerRpc } from "./createServerRpc-D_-6bKnO.js";
2
2
  import * as path from "node:path";
3
3
  import * as fs from "node:fs";
4
4
  import * as os from "node:os";
5
- import { S as SettingsSchema, D as DEFAULT_SETTINGS } from "./settings.types-DntadCHo.js";
5
+ import { S as SettingsSchema, D as DEFAULT_SETTINGS } from "./settings.types-CphWe-HW.js";
6
6
  import { c as createServerFn } from "../server.js";
7
7
  import "zod";
8
- import "@tanstack/history";
9
- import "@tanstack/router-core/ssr/client";
10
- import "@tanstack/router-core";
11
8
  import "node:async_hooks";
12
- import "@tanstack/router-core/ssr/server";
13
9
  import "h3-v2";
10
+ import "@tanstack/router-core";
14
11
  import "tiny-invariant";
15
12
  import "seroval";
13
+ import "@tanstack/history";
14
+ import "@tanstack/router-core/ssr/client";
15
+ import "@tanstack/router-core/ssr/server";
16
+ import "react";
17
+ import "@tanstack/react-router";
16
18
  import "react/jsx-runtime";
17
19
  import "@tanstack/react-router/ssr/server";
18
- import "@tanstack/react-router";
19
20
  const SETTINGS_DIR = ".claude-dashboard";
20
21
  const SETTINGS_FILE = "settings.json";
21
22
  function getSettingsPath() {
@@ -1,6 +1,6 @@
1
1
  import { queryOptions, useQueryClient, useMutation } from "@tanstack/react-query";
2
- import { c as createSsrRpc } from "./createSsrRpc-CVg2UDl0.js";
3
- import { S as SettingsSchema } from "./settings.types-DntadCHo.js";
2
+ import { c as createSsrRpc } from "./createSsrRpc-OFLSk08e.js";
3
+ import { S as SettingsSchema } from "./settings.types-CphWe-HW.js";
4
4
  import { c as createServerFn } from "../server.js";
5
5
  const getSettings = createServerFn({
6
6
  method: "GET"
@@ -9,6 +9,14 @@ const SettingsSchema = z.object({
9
9
  version: z.literal(1),
10
10
  subscriptionTier: z.enum(["free", "pro", "max-5x", "max-20x", "teams", "enterprise", "api"]).default("pro"),
11
11
  pricingOverrides: z.record(z.string(), ModelPricingOverrideSchema).default({}),
12
+ dataSources: z.array(
13
+ z.object({
14
+ id: z.string(),
15
+ label: z.string(),
16
+ path: z.string(),
17
+ enabled: z.boolean().default(true)
18
+ })
19
+ ).default([]),
12
20
  updatedAt: z.string().datetime().optional()
13
21
  });
14
22
  const DEFAULT_PRICING = [
@@ -97,7 +105,8 @@ const SUBSCRIPTION_TIERS = [
97
105
  const DEFAULT_SETTINGS = {
98
106
  version: 1,
99
107
  subscriptionTier: "pro",
100
- pricingOverrides: {}
108
+ pricingOverrides: {},
109
+ dataSources: []
101
110
  };
102
111
  function normalizeModelId(raw) {
103
112
  return raw.replace(/-\d{8}$/, "");
@@ -1,27 +1,27 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { useState, useMemo } from "react";
3
3
  import { queryOptions, useQuery } from "@tanstack/react-query";
4
- import { c as createSsrRpc } from "./createSsrRpc-CVg2UDl0.js";
4
+ import { c as createSsrRpc } from "./createSsrRpc-OFLSk08e.js";
5
5
  import { c as createServerFn } from "../server.js";
6
6
  import { ResponsiveContainer, BarChart, CartesianGrid, XAxis, YAxis, Tooltip, Bar, AreaChart, Area, PieChart, Pie, Cell, Legend } from "recharts";
7
7
  import { format, addDays, getDay, parseISO, startOfISOWeek } from "date-fns";
8
8
  import { createPortal } from "react-dom";
9
9
  import { f as formatTokenCount, a as formatDuration, b as formatRelativeTime, c as formatUSD } from "./format-DIZHV7IJ.js";
10
10
  import { Link } from "@tanstack/react-router";
11
- import { u as usePrivacy, R as Route } from "./router-BvYNknMb.js";
12
- import { u as useSessionCost, E as ExportDropdown, d as downloadFile, a as dailyActivityToCSV, b as dailyTokensToCSV, m as modelUsageToCSV, s as statsToJSON } from "./useSessionCost-CyWBuljV.js";
13
- import "@tanstack/history";
14
- import "@tanstack/router-core/ssr/client";
15
- import "@tanstack/router-core";
11
+ import { u as usePrivacy, R as Route } from "./router-DAepjaOj.js";
12
+ import { u as useSessionCost, E as ExportDropdown, d as downloadFile, a as dailyActivityToCSV, b as dailyTokensToCSV, m as modelUsageToCSV, s as statsToJSON } from "./useSessionCost-iQEg4FRM.js";
16
13
  import "node:async_hooks";
17
- import "@tanstack/router-core/ssr/server";
18
14
  import "h3-v2";
15
+ import "@tanstack/router-core";
19
16
  import "tiny-invariant";
20
17
  import "seroval";
18
+ import "@tanstack/history";
19
+ import "@tanstack/router-core/ssr/client";
20
+ import "@tanstack/router-core/ssr/server";
21
21
  import "@tanstack/react-router/ssr/server";
22
22
  import "zod";
23
- import "./settings.queries-BVEZA-1G.js";
24
- import "./settings.types-DntadCHo.js";
23
+ import "./settings.queries-CMWxUDF-.js";
24
+ import "./settings.types-CphWe-HW.js";
25
25
  const getStats = createServerFn({
26
26
  method: "GET"
27
27
  }).handler(createSsrRpc("44af69d3bfcf3ec46fffb3f297d2b12cd7fe4db36c654b8a322df34d549c6493"));
@@ -1,23 +1,25 @@
1
- import { c as createServerRpc } from "./createServerRpc-Bd3B-Ah9.js";
1
+ import { c as createServerRpc } from "./createServerRpc-D_-6bKnO.js";
2
2
  import * as fs from "node:fs";
3
- import { g as getStatsPath, p as parseDetail } from "./session-parser-DxLcS8VW.js";
3
+ import { g as getStatsPath, p as parseDetail } from "./session-parser-DKZZMuh6.js";
4
4
  import * as path from "node:path";
5
5
  import * as os from "node:os";
6
6
  import { z } from "zod";
7
- import { s as scanAllSessionsWithPaths } from "./session-scanner-DRGzVO2T.js";
7
+ import { a as scanAllSessionsWithPaths } from "./session-scanner-CECpfGFh.js";
8
8
  import { c as createServerFn } from "../server.js";
9
+ import "node:fs/promises";
9
10
  import "node:readline";
10
- import "@tanstack/history";
11
- import "@tanstack/router-core/ssr/client";
12
- import "@tanstack/router-core";
13
11
  import "node:async_hooks";
14
- import "@tanstack/router-core/ssr/server";
15
12
  import "h3-v2";
13
+ import "@tanstack/router-core";
16
14
  import "tiny-invariant";
17
15
  import "seroval";
16
+ import "@tanstack/history";
17
+ import "@tanstack/router-core/ssr/client";
18
+ import "@tanstack/router-core/ssr/server";
19
+ import "react";
20
+ import "@tanstack/react-router";
18
21
  import "react/jsx-runtime";
19
22
  import "@tanstack/react-router/ssr/server";
20
- import "@tanstack/react-router";
21
23
  const CACHE_VERSION = 1;
22
24
  function getCacheDir() {
23
25
  return path.join(os.homedir(), ".claude-dashboard", "cache");
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useState, useRef, useEffect, useMemo } from "react";
3
3
  import { useQuery } from "@tanstack/react-query";
4
- import { s as settingsQuery } from "./settings.queries-BVEZA-1G.js";
5
- import { b as DEFAULT_PRICING, n as normalizeModelId } from "./settings.types-DntadCHo.js";
4
+ import { s as settingsQuery } from "./settings.queries-CMWxUDF-.js";
5
+ import { b as DEFAULT_PRICING, n as normalizeModelId } from "./settings.types-CphWe-HW.js";
6
6
  function escapeCSVField(value) {
7
7
  if (value.includes(",") || value.includes('"') || value.includes("\n")) {
8
8
  return `"${value.replace(/"/g, '""')}"`;