claude-session-dashboard 0.4.0 → 0.4.2

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 (29) hide show
  1. package/dist/client/assets/{_dashboard-CAikP08_.js → _dashboard-t702m22X.js} +1 -1
  2. package/dist/client/assets/{_sessionId-C3iR5Lrv.js → _sessionId-D4Tpmmb5.js} +2 -2
  3. package/dist/client/assets/app-DREGBD44.css +1 -0
  4. package/dist/client/assets/{createServerFn-wbChEQBm.js → createServerFn-BYTDoNe-.js} +1 -1
  5. package/dist/client/assets/{index-Bk56JBgW.js → index-DnK_zh3s.js} +1 -1
  6. package/dist/client/assets/{main-CT7cRkW3.js → main-CV28H4XG.js} +3 -3
  7. package/dist/client/assets/{sessions.queries-jGqvP0O9.js → sessions.queries-tzrs5GhP.js} +1 -1
  8. package/dist/client/assets/{settings-CR-1d6g6.js → settings-D8yv1q93.js} +1 -1
  9. package/dist/client/assets/{settings.types-BEt_cHU1.js → settings.types-CMYAW0cQ.js} +1 -1
  10. package/dist/client/assets/{stats-7Tm8ZX4J.js → stats-C_6E4jyb.js} +1 -1
  11. package/dist/client/assets/{useSessionCost-CGXrAUii.js → useSessionCost-BBu3AmcX.js} +1 -1
  12. package/dist/server/assets/{_sessionId-BvDwvNyA.js → _sessionId-DyFxvcBN.js} +2 -2
  13. package/dist/server/assets/_tanstack-start-manifest_v-RaGuPsWw.js +4 -0
  14. package/dist/server/assets/{claude-path-B2oho3NT.js → claude-path-BdwflgZ1.js} +2 -2
  15. package/dist/server/assets/{index-Biupny11.js → index-Bx7vBs4O.js} +1 -1
  16. package/dist/server/assets/{project-analytics.server-t1bM6wAa.js → project-analytics.server-BsmZ4xil.js} +3 -3
  17. package/dist/server/assets/{router-kB-tCwY9.js → router-Cd4jLk4T.js} +5 -5
  18. package/dist/server/assets/{session-detail.server-IUw67jz-.js → session-detail.server-BDup9xb0.js} +2 -2
  19. package/dist/server/assets/{session-parser-CIucKYBT.js → session-parser-75iTexM0.js} +91 -17
  20. package/dist/server/assets/{session-scanner-1h9TTTAV.js → session-scanner-CPud4KGP.js} +14 -6
  21. package/dist/server/assets/{sessions.server-Cpffr3MU.js → sessions.server-60puUvjv.js} +3 -3
  22. package/dist/server/assets/{settings-jxAA3KAS.js → settings-KKaz1ty7.js} +1 -1
  23. package/dist/server/assets/{stats-CzGBAoxT.js → stats-Bsrkajci.js} +1 -1
  24. package/dist/server/assets/stats.server-qTOvID9-.js +395 -0
  25. package/dist/server/server.js +13 -13
  26. package/package.json +1 -1
  27. package/dist/client/assets/app-DNBe9Acr.css +0 -1
  28. package/dist/server/assets/_tanstack-start-manifest_v-8fGraPRa.js +0 -4
  29. package/dist/server/assets/stats.server-DXJiLqey.js +0 -144
@@ -4,7 +4,7 @@ import { useQuery } from "@tanstack/react-query";
4
4
  import { Link, useNavigate } from "@tanstack/react-router";
5
5
  import { p as paginatedSessionListQuery, a as activeSessionsQuery } from "./sessions.queries-B5ZBiVJy.js";
6
6
  import { a as formatDuration, b as formatRelativeTime, d as formatBytes } from "./format-DIZHV7IJ.js";
7
- import { u as usePrivacy, a as Route } from "./router-kB-tCwY9.js";
7
+ import { u as usePrivacy, a as Route } from "./router-Cd4jLk4T.js";
8
8
  import "./createSsrRpc-CVg2UDl0.js";
9
9
  import "../server.js";
10
10
  import "@tanstack/history";
@@ -1,11 +1,11 @@
1
1
  import { c as createServerRpc } from "./createServerRpc-Bd3B-Ah9.js";
2
- import { s as scanAllSessions } from "./session-scanner-1h9TTTAV.js";
2
+ import { s as scanAllSessions } from "./session-scanner-CPud4KGP.js";
3
3
  import { c as createServerFn } from "../server.js";
4
4
  import "node:fs";
5
5
  import "node:path";
6
- import "./claude-path-B2oho3NT.js";
6
+ import "./claude-path-BdwflgZ1.js";
7
7
  import "node:os";
8
- import "./session-parser-CIucKYBT.js";
8
+ import "./session-parser-75iTexM0.js";
9
9
  import "node:readline";
10
10
  import "@tanstack/history";
11
11
  import "@tanstack/router-core/ssr/client";
@@ -96,7 +96,7 @@ function usePrivacy() {
96
96
  }
97
97
  return ctx;
98
98
  }
99
- const appCss = "/assets/app-DNBe9Acr.css";
99
+ const appCss = "/assets/app-DREGBD44.css";
100
100
  const queryClient = new QueryClient({
101
101
  defaultOptions: {
102
102
  queries: {
@@ -145,7 +145,7 @@ const Route$4 = createFileRoute("/")({
145
145
  throw redirect({ to: "/sessions" });
146
146
  }
147
147
  });
148
- const $$splitComponentImporter$3 = () => import("./stats-CzGBAoxT.js");
148
+ const $$splitComponentImporter$3 = () => import("./stats-Bsrkajci.js");
149
149
  const statsSearchSchema = z.object({
150
150
  tab: z.enum(["overview", "projects"]).default("overview").catch("overview")
151
151
  });
@@ -153,11 +153,11 @@ const Route$3 = createFileRoute("/_dashboard/stats")({
153
153
  validateSearch: statsSearchSchema,
154
154
  component: lazyRouteComponent($$splitComponentImporter$3, "component")
155
155
  });
156
- const $$splitComponentImporter$2 = () => import("./settings-jxAA3KAS.js");
156
+ const $$splitComponentImporter$2 = () => import("./settings-KKaz1ty7.js");
157
157
  const Route$2 = createFileRoute("/_dashboard/settings")({
158
158
  component: lazyRouteComponent($$splitComponentImporter$2, "component")
159
159
  });
160
- const $$splitComponentImporter$1 = () => import("./index-Biupny11.js");
160
+ const $$splitComponentImporter$1 = () => import("./index-Bx7vBs4O.js");
161
161
  const sessionsSearchSchema = z.object({
162
162
  page: z.number().int().min(1).default(1).catch(1),
163
163
  pageSize: z.number().int().min(5).max(100).default(5).catch(5),
@@ -169,7 +169,7 @@ const Route$1 = createFileRoute("/_dashboard/sessions/")({
169
169
  validateSearch: sessionsSearchSchema,
170
170
  component: lazyRouteComponent($$splitComponentImporter$1, "component")
171
171
  });
172
- const $$splitComponentImporter = () => import("./_sessionId-BvDwvNyA.js");
172
+ const $$splitComponentImporter = () => import("./_sessionId-DyFxvcBN.js");
173
173
  const searchSchema = z.object({
174
174
  project: z.string().optional()
175
175
  });
@@ -1,8 +1,8 @@
1
1
  import { c as createServerRpc } from "./createServerRpc-Bd3B-Ah9.js";
2
2
  import * as path from "node:path";
3
3
  import * as fs from "node:fs";
4
- import { e as extractProjectName, g as getProjectsDir, d as decodeProjectDirName } from "./claude-path-B2oho3NT.js";
5
- import { p as parseDetail } from "./session-parser-CIucKYBT.js";
4
+ import { e as extractProjectName, a as getProjectsDir, d as decodeProjectDirName } from "./claude-path-BdwflgZ1.js";
5
+ import { a as parseDetail } from "./session-parser-75iTexM0.js";
6
6
  import { c as createServerFn } from "../server.js";
7
7
  import "node:os";
8
8
  import "node:readline";
@@ -274,6 +274,12 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
274
274
  }
275
275
  }
276
276
  }
277
+ if (resultText && toolUseId) {
278
+ const agentIdMatch = resultText.match(/agentId:\s*(\w+)/);
279
+ if (agentIdMatch) {
280
+ agentIdByToolUseId.set(String(toolUseId), agentIdMatch[1]);
281
+ }
282
+ }
277
283
  if (msg.toolUseResult && toolUseId) {
278
284
  const agent = agentByToolUseId.get(String(toolUseId));
279
285
  if (agent) {
@@ -281,6 +287,12 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
281
287
  if (result.totalTokens) agent.totalTokens = result.totalTokens;
282
288
  if (result.totalToolUseCount) agent.totalToolUseCount = result.totalToolUseCount;
283
289
  if (result.totalDurationMs) agent.durationMs = result.totalDurationMs;
290
+ if (result.isAsync === true && result.agentId) {
291
+ agentIdByToolUseId.set(String(toolUseId), result.agentId);
292
+ }
293
+ if (result.retrieval_status && result.task?.task_id) {
294
+ agentIdByToolUseId.set(String(toolUseId), result.task.task_id);
295
+ }
284
296
  }
285
297
  }
286
298
  }
@@ -326,7 +338,38 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
326
338
  agent.agentId = agentId;
327
339
  const subagentFilePath = `${subagentDir}/subagents/agent-${agentId}.jsonl`;
328
340
  try {
329
- agent.skills = await parseSubagentSkills(subagentFilePath);
341
+ const detail = await parseSubagentDetail(subagentFilePath);
342
+ agent.skills = detail.skills;
343
+ if (!agent.tokens) {
344
+ agent.tokens = detail.tokens;
345
+ totalTokens.inputTokens += detail.tokens.inputTokens;
346
+ totalTokens.outputTokens += detail.tokens.outputTokens;
347
+ totalTokens.cacheReadInputTokens += detail.tokens.cacheReadInputTokens;
348
+ totalTokens.cacheCreationInputTokens += detail.tokens.cacheCreationInputTokens;
349
+ if (detail.model) {
350
+ const modelId = detail.model;
351
+ const existing = tokensByModel[modelId] ?? {
352
+ inputTokens: 0,
353
+ outputTokens: 0,
354
+ cacheReadInputTokens: 0,
355
+ cacheCreationInputTokens: 0
356
+ };
357
+ existing.inputTokens += detail.tokens.inputTokens;
358
+ existing.outputTokens += detail.tokens.outputTokens;
359
+ existing.cacheReadInputTokens += detail.tokens.cacheReadInputTokens;
360
+ existing.cacheCreationInputTokens += detail.tokens.cacheCreationInputTokens;
361
+ tokensByModel[modelId] = existing;
362
+ }
363
+ }
364
+ if (!agent.toolCalls) {
365
+ agent.toolCalls = detail.toolCalls;
366
+ }
367
+ if (!agent.model && detail.model) {
368
+ agent.model = detail.model;
369
+ }
370
+ if (!agent.totalToolUseCount && detail.totalToolUseCount > 0) {
371
+ agent.totalToolUseCount = detail.totalToolUseCount;
372
+ }
330
373
  } catch {
331
374
  }
332
375
  })
@@ -354,8 +397,18 @@ async function parseDetail(filePath, sessionId, projectPath, projectName) {
354
397
  };
355
398
  }
356
399
  const COMMAND_NAME_RE = /<command-name>([^<]+)<\/command-name>/;
357
- async function parseSubagentSkills(subagentFilePath) {
400
+ async function parseSubagentDetail(subagentFilePath) {
358
401
  const skills = [];
402
+ const tokens = {
403
+ inputTokens: 0,
404
+ outputTokens: 0,
405
+ cacheReadInputTokens: 0,
406
+ cacheCreationInputTokens: 0
407
+ };
408
+ const toolCalls = {};
409
+ let model;
410
+ let totalToolUseCount = 0;
411
+ const seenRequestIds = /* @__PURE__ */ new Set();
359
412
  const stream = fs.createReadStream(subagentFilePath, { encoding: "utf-8" });
360
413
  const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
361
414
  let lineCount = 0;
@@ -385,22 +438,43 @@ async function parseSubagentSkills(subagentFilePath) {
385
438
  }
386
439
  }
387
440
  }
388
- if (msg.type === "assistant" && msg.message?.content) {
389
- for (const block of msg.message.content) {
390
- if (block.type !== "tool_use" || block.name !== "Skill") continue;
391
- const inp = block.input;
392
- if (!inp?.skill) continue;
393
- skills.push({
394
- skill: String(inp.skill),
395
- args: inp.args ? String(inp.args) : null,
396
- timestamp: msg.timestamp ?? "",
397
- toolUseId: block.id ?? "",
398
- source: "invoked"
399
- });
441
+ if (msg.type === "assistant" && msg.message) {
442
+ const requestId = msg.requestId;
443
+ const isNewRequest = !requestId || !seenRequestIds.has(requestId);
444
+ if (requestId) seenRequestIds.add(requestId);
445
+ if (msg.message.model && !model) {
446
+ model = msg.message.model;
447
+ }
448
+ if (isNewRequest && msg.message.usage) {
449
+ const u = msg.message.usage;
450
+ tokens.inputTokens += u.input_tokens ?? 0;
451
+ tokens.outputTokens += u.output_tokens ?? 0;
452
+ tokens.cacheReadInputTokens += u.cache_read_input_tokens ?? 0;
453
+ tokens.cacheCreationInputTokens += u.cache_creation_input_tokens ?? 0;
454
+ }
455
+ if (msg.message.content) {
456
+ for (const block of msg.message.content) {
457
+ if (block.type === "tool_use" && block.name) {
458
+ toolCalls[block.name] = (toolCalls[block.name] ?? 0) + 1;
459
+ totalToolUseCount++;
460
+ if (block.name === "Skill") {
461
+ const inp = block.input;
462
+ if (inp?.skill) {
463
+ skills.push({
464
+ skill: String(inp.skill),
465
+ args: inp.args ? String(inp.args) : null,
466
+ timestamp: msg.timestamp ?? "",
467
+ toolUseId: block.id ?? "",
468
+ source: "invoked"
469
+ });
470
+ }
471
+ }
472
+ }
473
+ }
400
474
  }
401
475
  }
402
476
  }
403
- return skills;
477
+ return { skills, tokens, toolCalls, model, totalToolUseCount };
404
478
  }
405
479
  function getContextLimit(_modelName) {
406
480
  return 2e5;
@@ -475,6 +549,6 @@ function extractTextContent(msg) {
475
549
  return texts.length > 0 ? texts.join("\n").slice(0, 500) : void 0;
476
550
  }
477
551
  export {
478
- parseSummary as a,
479
- parseDetail as p
552
+ parseDetail as a,
553
+ parseSummary as p
480
554
  };
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { g as getProjectsDir, d as decodeProjectDirName, e as extractProjectName, b as extractSessionId } from "./claude-path-B2oho3NT.js";
4
- import { a as parseSummary } from "./session-parser-CIucKYBT.js";
3
+ import { a as getProjectsDir, d as decodeProjectDirName, e as extractProjectName, b as extractSessionId } from "./claude-path-BdwflgZ1.js";
4
+ import { p as parseSummary } from "./session-parser-75iTexM0.js";
5
5
  async function scanProjects() {
6
6
  const projectsDir = getProjectsDir();
7
7
  let entries;
@@ -41,7 +41,7 @@ async function isSessionActive(projectDirName, sessionId) {
41
41
  return lockStat?.isDirectory() ?? false;
42
42
  }
43
43
  const summaryCache = /* @__PURE__ */ new Map();
44
- async function scanAllSessions() {
44
+ async function scanSessionsInternal() {
45
45
  const projects = await scanProjects();
46
46
  const summaries = [];
47
47
  for (const project of projects) {
@@ -57,7 +57,7 @@ async function scanAllSessions() {
57
57
  const cached = summaryCache.get(sessionId);
58
58
  if (cached && cached.mtimeMs === stat.mtimeMs) {
59
59
  const active = await isSessionActive(project.dirName, sessionId);
60
- summaries.push({ ...cached.summary, isActive: active });
60
+ summaries.push({ ...cached.summary, isActive: active, filePath });
61
61
  continue;
62
62
  }
63
63
  const summary = await parseSummary(
@@ -74,7 +74,7 @@ async function scanAllSessions() {
74
74
  mtimeMs: stat.mtimeMs,
75
75
  summary
76
76
  });
77
- summaries.push(summary);
77
+ summaries.push({ ...summary, filePath });
78
78
  }
79
79
  }
80
80
  }
@@ -83,11 +83,19 @@ async function scanAllSessions() {
83
83
  );
84
84
  return summaries;
85
85
  }
86
+ async function scanAllSessions() {
87
+ const results = await scanSessionsInternal();
88
+ return results.map(({ filePath: _fp, ...rest }) => rest);
89
+ }
90
+ async function scanAllSessionsWithPaths() {
91
+ return scanSessionsInternal();
92
+ }
86
93
  async function getActiveSessions() {
87
94
  const all = await scanAllSessions();
88
95
  return all.filter((s) => s.isActive);
89
96
  }
90
97
  export {
91
98
  getActiveSessions as g,
92
- scanAllSessions as s
99
+ scanAllSessions as s,
100
+ scanAllSessionsWithPaths as w
93
101
  };
@@ -1,12 +1,12 @@
1
1
  import { c as createServerRpc } from "./createServerRpc-Bd3B-Ah9.js";
2
2
  import { z } from "zod";
3
- import { s as scanAllSessions, g as getActiveSessions } from "./session-scanner-1h9TTTAV.js";
3
+ import { s as scanAllSessions, g as getActiveSessions } from "./session-scanner-CPud4KGP.js";
4
4
  import { c as createServerFn } from "../server.js";
5
5
  import "node:fs";
6
6
  import "node:path";
7
- import "./claude-path-B2oho3NT.js";
7
+ import "./claude-path-BdwflgZ1.js";
8
8
  import "node:os";
9
- import "./session-parser-CIucKYBT.js";
9
+ import "./session-parser-75iTexM0.js";
10
10
  import "node:readline";
11
11
  import "@tanstack/history";
12
12
  import "@tanstack/router-core/ssr/client";
@@ -3,7 +3,7 @@ import { useState } from "react";
3
3
  import { useQuery } from "@tanstack/react-query";
4
4
  import { s as settingsQuery, u as useSettingsMutation } from "./settings.queries-DSQd324O.js";
5
5
  import { a as SUBSCRIPTION_TIERS, b as DEFAULT_PRICING, D as DEFAULT_SETTINGS } from "./settings.types-DntadCHo.js";
6
- import { u as usePrivacy } from "./router-kB-tCwY9.js";
6
+ import { u as usePrivacy } from "./router-Cd4jLk4T.js";
7
7
  import "./createSsrRpc-CVg2UDl0.js";
8
8
  import "../server.js";
9
9
  import "@tanstack/history";
@@ -8,7 +8,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-kB-tCwY9.js";
11
+ import { u as usePrivacy, R as Route } from "./router-Cd4jLk4T.js";
12
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-CYs5UOX-.js";
13
13
  import "@tanstack/history";
14
14
  import "@tanstack/router-core/ssr/client";