fleetlens 0.2.8 → 0.3.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 (89) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/build-manifest.json +3 -3
  3. package/app/apps/web/.next/prerender-manifest.json +3 -3
  4. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  5. package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
  6. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
  12. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  13. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/app/apps/web/.next/server/app/page.js +3 -3
  15. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  16. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  17. package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
  18. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  19. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  20. package/app/apps/web/.next/server/app/projects/[slug]/page.js +3 -3
  21. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  22. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  23. package/app/apps/web/.next/server/app/projects/page.js +1 -1
  24. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  25. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  26. package/app/apps/web/.next/server/app/sessions/[id]/page.js +3 -2
  27. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  28. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  29. package/app/apps/web/.next/server/app/sessions/page.js +1 -1
  30. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  31. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  32. package/app/apps/web/.next/server/app/usage/page.js +1 -1
  33. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  34. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  35. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0op9af~._.js +1 -1
  36. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__00z7zlm._.js +3 -0
  37. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__05lbtny._.js +12 -0
  38. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ms7h0~._.js +1 -1
  39. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__08cr2u9._.js → [root-of-the-server]__0p~g4m6._.js} +2 -2
  40. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +1 -1
  41. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wvzyl7._.js +3 -0
  42. package/app/apps/web/.next/server/chunks/ssr/_09n75_5._.js +1 -1
  43. package/app/apps/web/.next/server/chunks/ssr/_0ph19-k._.js +12 -0
  44. package/app/apps/web/.next/server/chunks/ssr/_0u29mdd._.js +3 -0
  45. package/app/apps/web/.next/server/chunks/ssr/_0xies90._.js +1 -1
  46. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_06j3c.0._.js +1 -1
  47. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0-jvt~a._.js +1 -1
  48. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_analytics_0k4dgst.js +1 -1
  49. package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
  50. package/app/apps/web/.next/server/pages/500.html +1 -1
  51. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  52. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  53. package/app/apps/web/.next/static/chunks/03.mv4y4.w-vb.js +6 -0
  54. package/app/apps/web/.next/static/chunks/08983lz4~hffx.js +6 -0
  55. package/app/apps/web/.next/static/chunks/0fc6dk2qtokwh.js +1 -0
  56. package/app/apps/web/.next/static/chunks/0p1lpoh02zh8h.js +10 -0
  57. package/app/apps/web/.next/static/chunks/{03fw7f2obcvq~.js → 14q3xsfpkvuef.js} +2 -2
  58. package/app/apps/web/app/layout.tsx +2 -0
  59. package/app/apps/web/app/projects/[slug]/page.tsx +2 -0
  60. package/app/apps/web/app/sessions/[id]/page.tsx +27 -1
  61. package/app/apps/web/app/sessions/[id]/session-view.tsx +372 -793
  62. package/app/apps/web/app/sessions/[id]/team-tab/adapter.ts +633 -0
  63. package/app/apps/web/app/sessions/[id]/team-tab/format.ts +20 -0
  64. package/app/apps/web/app/sessions/[id]/team-tab/team-minimap.tsx +682 -0
  65. package/app/apps/web/app/sessions/[id]/team-tab/team-tab-client.tsx +78 -0
  66. package/app/apps/web/app/sessions/[id]/team-tab/team-table.tsx +796 -0
  67. package/app/apps/web/app/sessions/[id]/team-tab/turn-drawer.tsx +805 -0
  68. package/app/apps/web/app/sessions/[id]/tool-cards.tsx +461 -0
  69. package/app/apps/web/app/sessions/[id]/turn-steps.tsx +306 -0
  70. package/app/apps/web/app/sessions/sessions-grid.tsx +36 -5
  71. package/app/apps/web/components/live-sessions-widget.tsx +20 -6
  72. package/app/apps/web/components/team-badge.tsx +90 -0
  73. package/app/apps/web/package.json +1 -1
  74. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  75. package/dist/daemon-worker.js +74 -21
  76. package/dist/index.js +93 -23
  77. package/package.json +1 -1
  78. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0b..h_8._.js +0 -3
  79. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0cdd~8n._.js +0 -3
  80. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~a~v00._.js +0 -3
  81. package/app/apps/web/.next/server/chunks/ssr/_0zv~jv-._.js +0 -12
  82. package/app/apps/web/.next/server/chunks/ssr/_12dtryh._.js +0 -12
  83. package/app/apps/web/.next/static/chunks/07oyxajlp3dvb.js +0 -6
  84. package/app/apps/web/.next/static/chunks/0a24elrqoqqep.js +0 -10
  85. package/app/apps/web/.next/static/chunks/0i4zodv86~~~i.js +0 -1
  86. package/app/apps/web/.next/static/chunks/0rbm60-qyshdm.js +0 -6
  87. /package/app/apps/web/.next/static/{CH5VTNGEbso0WpO5B8BTA → 0fPDRTdMQ-Y62h6fHNJXL}/_buildManifest.js +0 -0
  88. /package/app/apps/web/.next/static/{CH5VTNGEbso0WpO5B8BTA → 0fPDRTdMQ-Y62h6fHNJXL}/_clientMiddlewareManifest.js +0 -0
  89. /package/app/apps/web/.next/static/{CH5VTNGEbso0WpO5B8BTA → 0fPDRTdMQ-Y62h6fHNJXL}/_ssgManifest.js +0 -0
@@ -8,7 +8,7 @@ import { execFileSync } from "node:child_process";
8
8
  import { readFileSync } from "node:fs";
9
9
  import { homedir, platform } from "node:os";
10
10
  import { join } from "node:path";
11
- function readOAuthToken() {
11
+ function readOAuthCredentials() {
12
12
  if (platform() === "darwin") {
13
13
  return readFromMacKeychain() ?? readFromCredentialsFile();
14
14
  }
@@ -21,7 +21,7 @@ function readFromMacKeychain() {
21
21
  ["find-generic-password", "-s", "Claude Code-credentials", "-w"],
22
22
  { stdio: ["ignore", "pipe", "ignore"], encoding: "utf8" }
23
23
  );
24
- return extractToken(blob);
24
+ return extractCredentials(blob);
25
25
  } catch {
26
26
  return null;
27
27
  }
@@ -34,23 +34,32 @@ function readFromCredentialsFile() {
34
34
  for (const path of candidates) {
35
35
  try {
36
36
  const blob = readFileSync(path, "utf8");
37
- const token = extractToken(blob);
38
- if (token) return token;
37
+ const creds = extractCredentials(blob);
38
+ if (creds) return creds;
39
39
  } catch {
40
40
  }
41
41
  }
42
42
  return null;
43
43
  }
44
- function extractToken(blob) {
44
+ function isUsable(creds, now, skewMs = 6e4) {
45
+ return creds.expiresAt - skewMs > now;
46
+ }
47
+ function extractCredentials(blob) {
45
48
  try {
46
49
  const parsed = JSON.parse(blob);
47
- return parsed.claudeAiOauth?.accessToken ?? null;
50
+ const oauth = parsed.claudeAiOauth;
51
+ if (!oauth) return null;
52
+ const accessToken = typeof oauth.accessToken === "string" ? oauth.accessToken : null;
53
+ const expiresAt = typeof oauth.expiresAt === "number" ? oauth.expiresAt : null;
54
+ if (!accessToken || expiresAt === null) return null;
55
+ return { accessToken, expiresAt };
48
56
  } catch {
49
57
  return null;
50
58
  }
51
59
  }
52
60
 
53
61
  // src/usage/api.ts
62
+ var EXPIRY_SKEW_MS = 60 * 1e3;
54
63
  var USAGE_ENDPOINT = "https://api.anthropic.com/api/oauth/usage";
55
64
  var BETA_HEADER = "oauth-2025-04-20";
56
65
  var UsageApiError = class extends Error {
@@ -60,18 +69,24 @@ var UsageApiError = class extends Error {
60
69
  }
61
70
  };
62
71
  async function fetchUsage() {
63
- const token = readOAuthToken();
64
- if (!token) {
72
+ const creds = readOAuthCredentials();
73
+ if (!creds) {
65
74
  throw new UsageApiError(
66
75
  "No Claude Code OAuth token found. Run `claude` to log in first.",
67
76
  "no_token"
68
77
  );
69
78
  }
79
+ if (creds.expiresAt - EXPIRY_SKEW_MS <= Date.now()) {
80
+ throw new UsageApiError(
81
+ "Claude Code OAuth token expired. Open Claude Code to refresh it.",
82
+ "expired"
83
+ );
84
+ }
70
85
  let res;
71
86
  try {
72
87
  res = await fetch(USAGE_ENDPOINT, {
73
88
  headers: {
74
- Authorization: `Bearer ${token}`,
89
+ Authorization: `Bearer ${creds.accessToken}`,
75
90
  "anthropic-beta": BETA_HEADER
76
91
  }
77
92
  });
@@ -132,12 +147,20 @@ function appendSnapshot(filePath, snapshot) {
132
147
  appendFileSync(filePath, JSON.stringify(snapshot) + "\n", "utf8");
133
148
  }
134
149
 
150
+ // src/usage/backoff.ts
151
+ var BASE_INTERVAL_MS = 5 * 60 * 1e3;
152
+ var MAX_INTERVAL_MS = 60 * 60 * 1e3;
153
+ function nextIntervalMs(current, outcome) {
154
+ if (outcome === "success") return BASE_INTERVAL_MS;
155
+ if (outcome === "network") return current;
156
+ return Math.min(Math.max(current, BASE_INTERVAL_MS) * 2, MAX_INTERVAL_MS);
157
+ }
158
+
135
159
  // src/daemon-worker.ts
136
160
  var STATE_DIR = join2(homedir2(), ".cclens");
137
161
  var USAGE_LOG = join2(STATE_DIR, "usage.jsonl");
138
162
  var DAEMON_LOG = join2(STATE_DIR, "daemon.log");
139
- var POLL_INTERVAL_MS = 5 * 60 * 1e3;
140
- var WATCHDOG_INTERVAL_MS = 30 * 1e3;
163
+ var WATCHDOG_INTERVAL_MS = 5 * 1e3;
141
164
  mkdirSync2(dirname2(USAGE_LOG), { recursive: true });
142
165
  function log(level, message) {
143
166
  const line = `${(/* @__PURE__ */ new Date()).toISOString()} ${level.toUpperCase()} ${message}
@@ -147,9 +170,10 @@ function log(level, message) {
147
170
  } catch {
148
171
  }
149
172
  }
150
- var lastPollAtMs = 0;
173
+ var nextPollAtMs = 0;
174
+ var currentIntervalMs = BASE_INTERVAL_MS;
175
+ var waitingForRefresh = false;
151
176
  async function tick() {
152
- lastPollAtMs = Date.now();
153
177
  try {
154
178
  const snapshot = await fetchUsage();
155
179
  appendSnapshot(USAGE_LOG, snapshot);
@@ -157,36 +181,65 @@ async function tick() {
157
181
  "info",
158
182
  `snapshot 5h=${snapshot.five_hour.utilization}% 7d=${snapshot.seven_day.utilization}%`
159
183
  );
184
+ return "success";
160
185
  } catch (err) {
161
186
  if (err instanceof UsageApiError) {
162
187
  log("warn", `poll failed (${err.code}): ${err.message}`);
163
- } else {
164
- log("error", `unexpected error: ${err.stack ?? err}`);
188
+ return err.code === "network" ? "network" : "auth";
165
189
  }
190
+ log("error", `unexpected error: ${err.stack ?? err}`);
191
+ return "auth";
166
192
  }
167
193
  }
194
+ function scheduleAfter(now, outcome) {
195
+ const prev = currentIntervalMs;
196
+ currentIntervalMs = nextIntervalMs(currentIntervalMs, outcome);
197
+ if (currentIntervalMs !== prev) {
198
+ log(
199
+ "info",
200
+ `poll interval ${outcome === "success" ? "reset" : "backoff"} to ${currentIntervalMs / 1e3}s`
201
+ );
202
+ }
203
+ nextPollAtMs = now + currentIntervalMs;
204
+ }
168
205
  function sleep(ms) {
169
206
  return new Promise((resolve) => setTimeout(resolve, ms));
170
207
  }
171
208
  async function runLoop() {
172
209
  while (true) {
173
210
  const now = Date.now();
174
- const elapsed = now - lastPollAtMs;
175
- if (elapsed >= POLL_INTERVAL_MS) {
176
- if (lastPollAtMs > 0 && elapsed > POLL_INTERVAL_MS * 1.5) {
211
+ if (now >= nextPollAtMs) {
212
+ if (nextPollAtMs > 0 && now - nextPollAtMs > currentIntervalMs) {
177
213
  log(
178
214
  "info",
179
- `wake-from-sleep catch-up: ${Math.round(elapsed / 1e3)}s since last poll (expected ${POLL_INTERVAL_MS / 1e3}s)`
215
+ `wake-from-sleep catch-up: ${Math.round((now - nextPollAtMs + currentIntervalMs) / 1e3)}s since last poll`
180
216
  );
181
217
  }
182
- await tick();
218
+ const creds = readOAuthCredentials();
219
+ if (!creds) {
220
+ log("warn", "no Claude Code OAuth token found; waiting");
221
+ waitingForRefresh = true;
222
+ nextPollAtMs = now + BASE_INTERVAL_MS;
223
+ } else if (!isUsable(creds, now)) {
224
+ if (!waitingForRefresh) {
225
+ log("info", "token expired; waiting for Claude Code to refresh it");
226
+ waitingForRefresh = true;
227
+ }
228
+ } else {
229
+ if (waitingForRefresh) {
230
+ log("info", "token refreshed; resuming polls");
231
+ waitingForRefresh = false;
232
+ }
233
+ const outcome = await tick();
234
+ scheduleAfter(Date.now(), outcome);
235
+ }
183
236
  }
184
237
  await sleep(WATCHDOG_INTERVAL_MS);
185
238
  }
186
239
  }
187
240
  log(
188
241
  "info",
189
- `daemon started (pid=${process.pid}, interval=${POLL_INTERVAL_MS / 1e3}s, watchdog=${WATCHDOG_INTERVAL_MS / 1e3}s)`
242
+ `daemon started (pid=${process.pid}, interval=${BASE_INTERVAL_MS / 1e3}s, watchdog=${WATCHDOG_INTERVAL_MS / 1e3}s)`
190
243
  );
191
244
  void runLoop();
192
245
  process.on("SIGTERM", () => {
package/dist/index.js CHANGED
@@ -454,9 +454,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
454
454
  console.warn(
455
455
  ` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
456
456
  );
457
- } else if (verify.installedVersion !== "0.2.8") {
457
+ } else if (verify.installedVersion !== "0.3.0") {
458
458
  console.log(
459
- ` \u2192 This process is still running ${"0.2.8"}. Next invocation will use ${verify.installedVersion}.`
459
+ ` \u2192 This process is still running ${"0.3.0"}. Next invocation will use ${verify.installedVersion}.`
460
460
  );
461
461
  }
462
462
  }
@@ -492,7 +492,7 @@ async function checkForUpdate() {
492
492
  if (process.env.__FLEETLENS_UPDATED === "1" || process.env.__CCLENS_UPDATED === "1") return;
493
493
  const latest = await fetchLatestVersion();
494
494
  if (latest === null) return;
495
- const current = "0.2.8";
495
+ const current = "0.3.0";
496
496
  if (!shouldUpdate(current, latest)) return;
497
497
  console.log(`Updating ${PACKAGE_NAME} ${current} \u2192 ${latest}...`);
498
498
  await stopRunningServices();
@@ -574,7 +574,7 @@ async function restartServices(state) {
574
574
  }
575
575
  async function forceUpdate() {
576
576
  const latest = await fetchLatestVersion();
577
- const current = "0.2.8";
577
+ const current = "0.3.0";
578
578
  if (latest === null) {
579
579
  console.error("Could not reach npm registry. Check your network.");
580
580
  process.exit(1);
@@ -796,6 +796,31 @@ function truncate(s, n = 200) {
796
796
  const one = cleanText(s);
797
797
  return one.length > n ? one.slice(0, n - 1) + "\u2026" : one;
798
798
  }
799
+ function classifyTeammateMessage(text) {
800
+ const m = text.match(TEAMMATE_MSG_RE);
801
+ if (!m)
802
+ return void 0;
803
+ const teammateId = m[1];
804
+ const body = m[2].trim();
805
+ let kind = "message";
806
+ if (body.startsWith("{")) {
807
+ try {
808
+ const parsed = JSON.parse(body);
809
+ if (parsed.type === "idle_notification")
810
+ kind = "idle-notification";
811
+ else if (parsed.type === "shutdown_request")
812
+ kind = "shutdown-request";
813
+ else if (parsed.type === "shutdown_approved")
814
+ kind = "shutdown-approved";
815
+ else if (parsed.type === "task_assignment")
816
+ kind = "task-assignment";
817
+ else if (parsed.type === "teammate_terminated")
818
+ kind = "teammate-terminated";
819
+ } catch {
820
+ }
821
+ }
822
+ return { teammateId, body, kind };
823
+ }
799
824
  function extractUsage(u) {
800
825
  if (!u || typeof u !== "object")
801
826
  return void 0;
@@ -865,6 +890,7 @@ function toEvent(raw, index) {
865
890
  const msg = r.message ?? {};
866
891
  const c = msg.content;
867
892
  if (typeof c === "string") {
893
+ const tm = classifyTeammateMessage(c);
868
894
  return {
869
895
  index,
870
896
  uuid,
@@ -874,7 +900,8 @@ function toEvent(raw, index) {
874
900
  rawType,
875
901
  preview: truncate(c, 200),
876
902
  blocks: [{ type: "text", text: c }],
877
- raw
903
+ raw,
904
+ teammateMessage: tm
878
905
  };
879
906
  }
880
907
  if (Array.isArray(c)) {
@@ -896,6 +923,7 @@ function toEvent(raw, index) {
896
923
  };
897
924
  }
898
925
  const textBlock = c.find((b) => b?.type === "text");
926
+ const tm = textBlock ? classifyTeammateMessage(textBlock.text) : void 0;
899
927
  return {
900
928
  index,
901
929
  uuid,
@@ -905,7 +933,8 @@ function toEvent(raw, index) {
905
933
  rawType,
906
934
  preview: textBlock ? truncate(textBlock.text, 200) : truncate(JSON.stringify(c), 200),
907
935
  blocks: c,
908
- raw
936
+ raw,
937
+ teammateMessage: tm
909
938
  };
910
939
  }
911
940
  }
@@ -995,6 +1024,10 @@ function parseTranscript(rawLines) {
995
1024
  let sessionId = "";
996
1025
  let cwd;
997
1026
  let gitBranch;
1027
+ let teamName;
1028
+ let agentName;
1029
+ let hasTeamCreate = false;
1030
+ let hasOutboundDispatch = false;
998
1031
  let toolCallCount = 0;
999
1032
  let turnCount = 0;
1000
1033
  let firstUserPreview;
@@ -1009,6 +1042,13 @@ function parseTranscript(rawLines) {
1009
1042
  const toolBlock = e.blocks.find((b) => b && b.type === "tool_use");
1010
1043
  if (toolBlock) {
1011
1044
  const input = toolBlock.input ?? {};
1045
+ if (toolBlock.name === "TeamCreate")
1046
+ hasTeamCreate = true;
1047
+ if (toolBlock.name === "SendMessage") {
1048
+ const to = typeof input.to === "string" ? input.to : "";
1049
+ if (to && to !== "team-lead")
1050
+ hasOutboundDispatch = true;
1051
+ }
1012
1052
  const fp = typeof input.file_path === "string" ? input.file_path : void 0;
1013
1053
  if (toolBlock.name === "Edit" && fp) {
1014
1054
  filesEdited.add(fp);
@@ -1028,10 +1068,12 @@ function parseTranscript(rawLines) {
1028
1068
  if (e.role === "user") {
1029
1069
  const rawMsg = e.raw?.message;
1030
1070
  const rawContent = typeof rawMsg?.content === "string" ? rawMsg.content : "";
1031
- const isHidden = rawContent.startsWith("<command-name>") || rawContent.startsWith("Base directory for this skill:") || rawContent.startsWith("<task-notification>");
1032
- if (!isHidden) {
1033
- if (!firstUserPreview)
1034
- firstUserPreview = e.preview;
1071
+ const isHidden = rawContent.startsWith("<command-name>") || rawContent.startsWith("<local-command-caveat>") || rawContent.startsWith("Base directory for this skill:") || rawContent.startsWith("<task-notification>");
1072
+ const isTeamNoise = e.teammateMessage !== void 0 && !agentName;
1073
+ if (!isHidden && !isTeamNoise) {
1074
+ if (!firstUserPreview) {
1075
+ firstUserPreview = e.teammateMessage ? e.teammateMessage.body : e.preview;
1076
+ }
1035
1077
  turnCount++;
1036
1078
  lastUserPreview = e.preview;
1037
1079
  }
@@ -1050,6 +1092,10 @@ function parseTranscript(rawLines) {
1050
1092
  cwd = o.cwd;
1051
1093
  if (typeof o.gitBranch === "string" && !gitBranch)
1052
1094
  gitBranch = o.gitBranch;
1095
+ if (typeof o.teamName === "string" && !teamName)
1096
+ teamName = o.teamName;
1097
+ if (typeof o.agentName === "string" && !agentName)
1098
+ agentName = o.agentName;
1053
1099
  if (o.type === "assistant") {
1054
1100
  const m = o.message;
1055
1101
  if (m) {
@@ -1094,15 +1140,19 @@ function parseTranscript(rawLines) {
1094
1140
  activeSegments,
1095
1141
  linesAdded,
1096
1142
  linesRemoved,
1097
- filesEdited: filesEdited.size
1143
+ filesEdited: filesEdited.size,
1144
+ teamName,
1145
+ agentName,
1146
+ isTeamLead: teamName !== void 0 && agentName === void 0 && (hasTeamCreate || hasOutboundDispatch)
1098
1147
  }
1099
1148
  };
1100
1149
  }
1101
- var BLANK_USAGE;
1150
+ var BLANK_USAGE, TEAMMATE_MSG_RE;
1102
1151
  var init_parser = __esm({
1103
1152
  "../parser/dist/parser.js"() {
1104
1153
  "use strict";
1105
1154
  BLANK_USAGE = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
1155
+ TEAMMATE_MSG_RE = /^\s*<teammate-message\s+teammate_id="([^"]+)"[^>]*>([\s\S]*?)<\/teammate-message>/;
1106
1156
  }
1107
1157
  });
1108
1158
 
@@ -1113,6 +1163,13 @@ var init_analytics = __esm({
1113
1163
  }
1114
1164
  });
1115
1165
 
1166
+ // ../parser/dist/team.js
1167
+ var init_team = __esm({
1168
+ "../parser/dist/team.js"() {
1169
+ "use strict";
1170
+ }
1171
+ });
1172
+
1116
1173
  // ../parser/dist/fs.js
1117
1174
  import { promises as fs } from "node:fs";
1118
1175
  import os from "node:os";
@@ -1270,6 +1327,7 @@ var init_fs = __esm({
1270
1327
  "use strict";
1271
1328
  init_parser();
1272
1329
  init_analytics();
1330
+ init_team();
1273
1331
  DEFAULT_ROOT = path.join(os.homedir(), ".claude", "projects");
1274
1332
  metaCache = /* @__PURE__ */ new Map();
1275
1333
  fileListCache = null;
@@ -1513,7 +1571,7 @@ import { execFileSync } from "node:child_process";
1513
1571
  import { readFileSync as readFileSync5 } from "node:fs";
1514
1572
  import { homedir as homedir3, platform } from "node:os";
1515
1573
  import { join as join4 } from "node:path";
1516
- function readOAuthToken() {
1574
+ function readOAuthCredentials() {
1517
1575
  if (platform() === "darwin") {
1518
1576
  return readFromMacKeychain() ?? readFromCredentialsFile();
1519
1577
  }
@@ -1526,7 +1584,7 @@ function readFromMacKeychain() {
1526
1584
  ["find-generic-password", "-s", "Claude Code-credentials", "-w"],
1527
1585
  { stdio: ["ignore", "pipe", "ignore"], encoding: "utf8" }
1528
1586
  );
1529
- return extractToken(blob);
1587
+ return extractCredentials(blob);
1530
1588
  } catch {
1531
1589
  return null;
1532
1590
  }
@@ -1539,17 +1597,22 @@ function readFromCredentialsFile() {
1539
1597
  for (const path2 of candidates) {
1540
1598
  try {
1541
1599
  const blob = readFileSync5(path2, "utf8");
1542
- const token = extractToken(blob);
1543
- if (token) return token;
1600
+ const creds = extractCredentials(blob);
1601
+ if (creds) return creds;
1544
1602
  } catch {
1545
1603
  }
1546
1604
  }
1547
1605
  return null;
1548
1606
  }
1549
- function extractToken(blob) {
1607
+ function extractCredentials(blob) {
1550
1608
  try {
1551
1609
  const parsed = JSON.parse(blob);
1552
- return parsed.claudeAiOauth?.accessToken ?? null;
1610
+ const oauth = parsed.claudeAiOauth;
1611
+ if (!oauth) return null;
1612
+ const accessToken = typeof oauth.accessToken === "string" ? oauth.accessToken : null;
1613
+ const expiresAt = typeof oauth.expiresAt === "number" ? oauth.expiresAt : null;
1614
+ if (!accessToken || expiresAt === null) return null;
1615
+ return { accessToken, expiresAt };
1553
1616
  } catch {
1554
1617
  return null;
1555
1618
  }
@@ -1562,18 +1625,24 @@ var init_token = __esm({
1562
1625
 
1563
1626
  // src/usage/api.ts
1564
1627
  async function fetchUsage() {
1565
- const token = readOAuthToken();
1566
- if (!token) {
1628
+ const creds = readOAuthCredentials();
1629
+ if (!creds) {
1567
1630
  throw new UsageApiError(
1568
1631
  "No Claude Code OAuth token found. Run `claude` to log in first.",
1569
1632
  "no_token"
1570
1633
  );
1571
1634
  }
1635
+ if (creds.expiresAt - EXPIRY_SKEW_MS <= Date.now()) {
1636
+ throw new UsageApiError(
1637
+ "Claude Code OAuth token expired. Open Claude Code to refresh it.",
1638
+ "expired"
1639
+ );
1640
+ }
1572
1641
  let res;
1573
1642
  try {
1574
1643
  res = await fetch(USAGE_ENDPOINT, {
1575
1644
  headers: {
1576
- Authorization: `Bearer ${token}`,
1645
+ Authorization: `Bearer ${creds.accessToken}`,
1577
1646
  "anthropic-beta": BETA_HEADER
1578
1647
  }
1579
1648
  });
@@ -1625,11 +1694,12 @@ function normalizeExtra(raw) {
1625
1694
  utilization: typeof r.utilization === "number" ? r.utilization : null
1626
1695
  };
1627
1696
  }
1628
- var USAGE_ENDPOINT, BETA_HEADER, UsageApiError;
1697
+ var EXPIRY_SKEW_MS, USAGE_ENDPOINT, BETA_HEADER, UsageApiError;
1629
1698
  var init_api = __esm({
1630
1699
  "src/usage/api.ts"() {
1631
1700
  "use strict";
1632
1701
  init_token();
1702
+ EXPIRY_SKEW_MS = 60 * 1e3;
1633
1703
  USAGE_ENDPOINT = "https://api.anthropic.com/api/oauth/usage";
1634
1704
  BETA_HEADER = "oauth-2025-04-20";
1635
1705
  UsageApiError = class extends Error {
@@ -1812,7 +1882,7 @@ async function main() {
1812
1882
  case "version":
1813
1883
  case "--version":
1814
1884
  case "-v":
1815
- console.log(`fleetlens ${"0.2.8"}`);
1885
+ console.log(`fleetlens ${"0.3.0"}`);
1816
1886
  break;
1817
1887
  case "help":
1818
1888
  case "--help":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetlens",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "description": "fleetlens — local-only dashboard and usage tracker for Claude Code sessions and agent fleets",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,3 +0,0 @@
1
- module.exports=[93695,(a,b,c)=>{b.exports=a.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},71306,(a,b,c)=>{b.exports=a.r(18622)},79847,a=>{a.n(a.i(3343))},9185,a=>{a.n(a.i(29432))},72842,a=>{a.n(a.i(75164))},54897,a=>{a.n(a.i(30106))},56157,a=>{a.n(a.i(18970))},94331,a=>{a.n(a.i(60644))},15988,a=>{a.n(a.i(56952))},25766,a=>{a.n(a.i(77341))},29725,a=>{a.n(a.i(94290))},5785,a=>{a.n(a.i(90588))},74793,a=>{a.n(a.i(33169))},85826,a=>{a.n(a.i(37111))},21565,a=>{a.n(a.i(41763))},65911,a=>{a.n(a.i(8950))},25128,a=>{a.n(a.i(91562))},40781,a=>{a.n(a.i(49670))},69411,a=>{a.n(a.i(75700))},63081,a=>{a.n(a.i(276))},62837,a=>{a.n(a.i(40795))},34607,a=>{a.n(a.i(11614))},96338,a=>{a.n(a.i(21751))},50642,a=>{a.n(a.i(12213))},32242,a=>{a.n(a.i(22693))},88530,a=>{a.n(a.i(10531))},8583,a=>{a.n(a.i(1082))},38534,a=>{a.n(a.i(98175))},70408,a=>{a.n(a.i(9095))},22922,a=>{a.n(a.i(96772))},78294,a=>{a.n(a.i(71717))},16625,a=>{a.n(a.i(85034))},88648,a=>{a.n(a.i(68113))},51914,a=>{a.n(a.i(66482))},25466,a=>{a.n(a.i(91505))},67116,a=>{"use strict";var b=a.i(717),c=a.i(50785);let d=process.env.CCLENS_DATA_DIR||void 0,e=(0,b.cache)(async()=>(0,c.listSessions)({limit:1e3,root:d})),f=(0,b.cache)(async a=>(0,c.getSession)(a,{root:d}));a.s(["getSession",0,f,"listSessions",0,e])},20916,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"ReadonlyURLSearchParams",{enumerable:!0,get:function(){return e}});class d extends Error{constructor(){super("Method unavailable on `ReadonlyURLSearchParams`. Read more: https://nextjs.org/docs/app/api-reference/functions/use-search-params#updating-searchparams")}}class e extends URLSearchParams{append(){throw new d}delete(){throw new d}set(){throw new d}sort(){throw new d}}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},21170,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"RedirectStatusCode",{enumerable:!0,get:function(){return e}});var d,e=((d={})[d.SeeOther=303]="SeeOther",d[d.TemporaryRedirect=307]="TemporaryRedirect",d[d.PermanentRedirect=308]="PermanentRedirect",d);("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},28859,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={REDIRECT_ERROR_CODE:function(){return g},isRedirectError:function(){return h}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(21170),g="NEXT_REDIRECT";function h(a){if("object"!=typeof a||null===a||!("digest"in a)||"string"!=typeof a.digest)return!1;let b=a.digest.split(";"),[c,d]=b,e=b.slice(2,-2).join(";"),h=Number(b.at(-2));return c===g&&("replace"===d||"push"===d)&&"string"==typeof e&&!isNaN(h)&&h in f.RedirectStatusCode}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},44868,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={getRedirectError:function(){return i},getRedirectStatusCodeFromError:function(){return n},getRedirectTypeFromError:function(){return m},getURLFromRedirectError:function(){return l},permanentRedirect:function(){return k},redirect:function(){return j}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(21170),g=a.r(28859),h=a.r(20635).actionAsyncStorage;function i(a,b,c=f.RedirectStatusCode.TemporaryRedirect){let d=Object.defineProperty(Error(g.REDIRECT_ERROR_CODE),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});return d.digest=`${g.REDIRECT_ERROR_CODE};${b};${a};${c};`,d}function j(a,b){throw i(a,b??=h?.getStore()?.isAction?"push":"replace",f.RedirectStatusCode.TemporaryRedirect)}function k(a,b="replace"){throw i(a,b,f.RedirectStatusCode.PermanentRedirect)}function l(a){return(0,g.isRedirectError)(a)?a.digest.split(";").slice(2,-2).join(";"):null}function m(a){if(!(0,g.isRedirectError)(a))throw Object.defineProperty(Error("Not a redirect error"),"__NEXT_ERROR_CODE",{value:"E260",enumerable:!1,configurable:!0});return a.digest.split(";",2)[1]}function n(a){if(!(0,g.isRedirectError)(a))throw Object.defineProperty(Error("Not a redirect error"),"__NEXT_ERROR_CODE",{value:"E260",enumerable:!1,configurable:!0});return Number(a.digest.split(";").at(-2))}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},89798,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={HTTPAccessErrorStatus:function(){return f},HTTP_ERROR_FALLBACK_ERROR_CODE:function(){return h},getAccessFallbackErrorTypeByStatus:function(){return k},getAccessFallbackHTTPStatus:function(){return j},isHTTPAccessFallbackError:function(){return i}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f={NOT_FOUND:404,FORBIDDEN:403,UNAUTHORIZED:401},g=new Set(Object.values(f)),h="NEXT_HTTP_ERROR_FALLBACK";function i(a){if("object"!=typeof a||null===a||!("digest"in a)||"string"!=typeof a.digest)return!1;let[b,c]=a.digest.split(";");return b===h&&g.has(Number(c))}function j(a){return Number(a.digest.split(";")[1])}function k(a){switch(a){case 401:return"unauthorized";case 403:return"forbidden";case 404:return"not-found";default:return}}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},16155,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"notFound",{enumerable:!0,get:function(){return f}});let d=a.r(89798),e=`${d.HTTP_ERROR_FALLBACK_ERROR_CODE};404`;function f(){let a=Object.defineProperty(Error(e),"__NEXT_ERROR_CODE",{value:"E1041",enumerable:!1,configurable:!0});throw a.digest=e,a}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},34557,(a,b,c)=>{"use strict";function d(){throw Object.defineProperty(Error("`forbidden()` is experimental and only allowed to be enabled when `experimental.authInterrupts` is enabled."),"__NEXT_ERROR_CODE",{value:"E488",enumerable:!1,configurable:!0})}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"forbidden",{enumerable:!0,get:function(){return d}}),a.r(89798).HTTP_ERROR_FALLBACK_ERROR_CODE,("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},93845,(a,b,c)=>{"use strict";function d(){throw Object.defineProperty(Error("`unauthorized()` is experimental and only allowed to be used when `experimental.authInterrupts` is enabled."),"__NEXT_ERROR_CODE",{value:"E411",enumerable:!1,configurable:!0})}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"unauthorized",{enumerable:!0,get:function(){return d}}),a.r(89798).HTTP_ERROR_FALLBACK_ERROR_CODE,("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},73808,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"isPostpone",{enumerable:!0,get:function(){return e}});let d=Symbol.for("react.postpone");function e(a){return"object"==typeof a&&null!==a&&a.$$typeof===d}},1567,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"isNextRouterError",{enumerable:!0,get:function(){return f}});let d=a.r(89798),e=a.r(28859);function f(a){return(0,e.isRedirectError)(a)||(0,d.isHTTPAccessFallbackError)(a)}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},94783,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"unstable_rethrow",{enumerable:!0,get:function(){return function a(b){if((0,g.isNextRouterError)(b)||(0,f.isBailoutToCSRError)(b)||(0,i.isDynamicServerError)(b)||(0,h.isDynamicPostpone)(b)||(0,e.isPostpone)(b)||(0,d.isHangingPromiseRejectionError)(b)||(0,h.isPrerenderInterruptedError)(b))throw b;b instanceof Error&&"cause"in b&&a(b.cause)}}});let d=a.r(13091),e=a.r(73808),f=a.r(49640),g=a.r(1567),h=a.r(60384),i=a.r(96556);("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},60968,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"unstable_rethrow",{enumerable:!0,get:function(){return d}});let d=a.r(94783).unstable_rethrow;("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},73727,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={ReadonlyURLSearchParams:function(){return f.ReadonlyURLSearchParams},RedirectType:function(){return m},forbidden:function(){return i.forbidden},notFound:function(){return h.notFound},permanentRedirect:function(){return g.permanentRedirect},redirect:function(){return g.redirect},unauthorized:function(){return j.unauthorized},unstable_isUnrecognizedActionError:function(){return l},unstable_rethrow:function(){return k.unstable_rethrow}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(20916),g=a.r(44868),h=a.r(16155),i=a.r(34557),j=a.r(93845),k=a.r(60968);function l(){throw Object.defineProperty(Error("`unstable_isUnrecognizedActionError` can only be used on the client."),"__NEXT_ERROR_CODE",{value:"E776",enumerable:!1,configurable:!0})}let m={push:"push",replace:"replace"};("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},70396,a=>{"use strict";a.i(73727),a.s([])},30237,a=>{"use strict";a.s(["SessionView",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call SessionView() from the server but SessionView is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/app/sessions/[id]/session-view.tsx <module evaluation>","SessionView")},41422,a=>{"use strict";a.s(["SessionView",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call SessionView() from the server but SessionView is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/app/sessions/[id]/session-view.tsx","SessionView")},12099,a=>{"use strict";a.i(30237);var b=a.i(41422);a.n(b)},83884,a=>{"use strict";var b=a.i(7997);a.i(70396);var c=a.i(73727),d=a.i(67116),e=a.i(12099);async function f({params:a}){let{id:g}=await a,h=await (0,d.getSession)(g);if(!h)return(0,c.notFound)();let i={...h,events:h.events.map(a=>({...a,raw:void 0}))};return(0,b.jsx)(e.SessionView,{session:i})}a.s(["default",0,f,"dynamic",0,"force-dynamic"])},29800,a=>{a.n(a.i(83884))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0b..h_8._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[93695,(a,b,c)=>{b.exports=a.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},71306,(a,b,c)=>{b.exports=a.r(18622)},79847,a=>{a.n(a.i(3343))},9185,a=>{a.n(a.i(29432))},72842,a=>{a.n(a.i(75164))},54897,a=>{a.n(a.i(30106))},56157,a=>{a.n(a.i(18970))},94331,a=>{a.n(a.i(60644))},15988,a=>{a.n(a.i(56952))},25766,a=>{a.n(a.i(77341))},29725,a=>{a.n(a.i(94290))},5785,a=>{a.n(a.i(90588))},74793,a=>{a.n(a.i(33169))},85826,a=>{a.n(a.i(37111))},21565,a=>{a.n(a.i(41763))},65911,a=>{a.n(a.i(8950))},25128,a=>{a.n(a.i(91562))},40781,a=>{a.n(a.i(49670))},69411,a=>{a.n(a.i(75700))},63081,a=>{a.n(a.i(276))},62837,a=>{a.n(a.i(40795))},34607,a=>{a.n(a.i(11614))},96338,a=>{a.n(a.i(21751))},50642,a=>{a.n(a.i(12213))},32242,a=>{a.n(a.i(22693))},88530,a=>{a.n(a.i(10531))},8583,a=>{a.n(a.i(1082))},38534,a=>{a.n(a.i(98175))},70408,a=>{a.n(a.i(9095))},22922,a=>{a.n(a.i(96772))},78294,a=>{a.n(a.i(71717))},16625,a=>{a.n(a.i(85034))},88648,a=>{a.n(a.i(68113))},51914,a=>{a.n(a.i(66482))},25466,a=>{a.n(a.i(91505))},67116,a=>{"use strict";var b=a.i(717),c=a.i(50785);let d=process.env.CCLENS_DATA_DIR||void 0,e=(0,b.cache)(async()=>(0,c.listSessions)({limit:1e3,root:d})),f=(0,b.cache)(async a=>(0,c.getSession)(a,{root:d}));a.s(["getSession",0,f,"listSessions",0,e])},1269,a=>{"use strict";var b=a.i(717);let c=(...a)=>a.filter((a,b,c)=>!!a&&""!==a.trim()&&c.indexOf(a)===b).join(" ").trim();var d={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let e=(0,b.forwardRef)(({color:a="currentColor",size:e=24,strokeWidth:f=2,absoluteStrokeWidth:g,className:h="",children:i,iconNode:j,...k},l)=>(0,b.createElement)("svg",{ref:l,...d,width:e,height:e,stroke:a,strokeWidth:g?24*Number(f)/Number(e):f,className:c("lucide",h),...k},[...j.map(([a,c])=>(0,b.createElement)(a,c)),...Array.isArray(i)?i:[i]]));a.s(["default",0,(a,d)=>{let f=(0,b.forwardRef)(({className:f,...g},h)=>(0,b.createElement)(e,{ref:h,iconNode:d,className:c(`lucide-${a.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}`,f),...g}));return f.displayName=`${a}`,f}],1269)},20916,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"ReadonlyURLSearchParams",{enumerable:!0,get:function(){return e}});class d extends Error{constructor(){super("Method unavailable on `ReadonlyURLSearchParams`. Read more: https://nextjs.org/docs/app/api-reference/functions/use-search-params#updating-searchparams")}}class e extends URLSearchParams{append(){throw new d}delete(){throw new d}set(){throw new d}sort(){throw new d}}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},21170,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"RedirectStatusCode",{enumerable:!0,get:function(){return e}});var d,e=((d={})[d.SeeOther=303]="SeeOther",d[d.TemporaryRedirect=307]="TemporaryRedirect",d[d.PermanentRedirect=308]="PermanentRedirect",d);("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},28859,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={REDIRECT_ERROR_CODE:function(){return g},isRedirectError:function(){return h}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(21170),g="NEXT_REDIRECT";function h(a){if("object"!=typeof a||null===a||!("digest"in a)||"string"!=typeof a.digest)return!1;let b=a.digest.split(";"),[c,d]=b,e=b.slice(2,-2).join(";"),h=Number(b.at(-2));return c===g&&("replace"===d||"push"===d)&&"string"==typeof e&&!isNaN(h)&&h in f.RedirectStatusCode}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},44868,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={getRedirectError:function(){return i},getRedirectStatusCodeFromError:function(){return n},getRedirectTypeFromError:function(){return m},getURLFromRedirectError:function(){return l},permanentRedirect:function(){return k},redirect:function(){return j}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(21170),g=a.r(28859),h=a.r(20635).actionAsyncStorage;function i(a,b,c=f.RedirectStatusCode.TemporaryRedirect){let d=Object.defineProperty(Error(g.REDIRECT_ERROR_CODE),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});return d.digest=`${g.REDIRECT_ERROR_CODE};${b};${a};${c};`,d}function j(a,b){throw i(a,b??=h?.getStore()?.isAction?"push":"replace",f.RedirectStatusCode.TemporaryRedirect)}function k(a,b="replace"){throw i(a,b,f.RedirectStatusCode.PermanentRedirect)}function l(a){return(0,g.isRedirectError)(a)?a.digest.split(";").slice(2,-2).join(";"):null}function m(a){if(!(0,g.isRedirectError)(a))throw Object.defineProperty(Error("Not a redirect error"),"__NEXT_ERROR_CODE",{value:"E260",enumerable:!1,configurable:!0});return a.digest.split(";",2)[1]}function n(a){if(!(0,g.isRedirectError)(a))throw Object.defineProperty(Error("Not a redirect error"),"__NEXT_ERROR_CODE",{value:"E260",enumerable:!1,configurable:!0});return Number(a.digest.split(";").at(-2))}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},89798,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={HTTPAccessErrorStatus:function(){return f},HTTP_ERROR_FALLBACK_ERROR_CODE:function(){return h},getAccessFallbackErrorTypeByStatus:function(){return k},getAccessFallbackHTTPStatus:function(){return j},isHTTPAccessFallbackError:function(){return i}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f={NOT_FOUND:404,FORBIDDEN:403,UNAUTHORIZED:401},g=new Set(Object.values(f)),h="NEXT_HTTP_ERROR_FALLBACK";function i(a){if("object"!=typeof a||null===a||!("digest"in a)||"string"!=typeof a.digest)return!1;let[b,c]=a.digest.split(";");return b===h&&g.has(Number(c))}function j(a){return Number(a.digest.split(";")[1])}function k(a){switch(a){case 401:return"unauthorized";case 403:return"forbidden";case 404:return"not-found";default:return}}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},16155,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"notFound",{enumerable:!0,get:function(){return f}});let d=a.r(89798),e=`${d.HTTP_ERROR_FALLBACK_ERROR_CODE};404`;function f(){let a=Object.defineProperty(Error(e),"__NEXT_ERROR_CODE",{value:"E1041",enumerable:!1,configurable:!0});throw a.digest=e,a}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},34557,(a,b,c)=>{"use strict";function d(){throw Object.defineProperty(Error("`forbidden()` is experimental and only allowed to be enabled when `experimental.authInterrupts` is enabled."),"__NEXT_ERROR_CODE",{value:"E488",enumerable:!1,configurable:!0})}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"forbidden",{enumerable:!0,get:function(){return d}}),a.r(89798).HTTP_ERROR_FALLBACK_ERROR_CODE,("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},93845,(a,b,c)=>{"use strict";function d(){throw Object.defineProperty(Error("`unauthorized()` is experimental and only allowed to be used when `experimental.authInterrupts` is enabled."),"__NEXT_ERROR_CODE",{value:"E411",enumerable:!1,configurable:!0})}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"unauthorized",{enumerable:!0,get:function(){return d}}),a.r(89798).HTTP_ERROR_FALLBACK_ERROR_CODE,("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},73808,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"isPostpone",{enumerable:!0,get:function(){return e}});let d=Symbol.for("react.postpone");function e(a){return"object"==typeof a&&null!==a&&a.$$typeof===d}},1567,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"isNextRouterError",{enumerable:!0,get:function(){return f}});let d=a.r(89798),e=a.r(28859);function f(a){return(0,e.isRedirectError)(a)||(0,d.isHTTPAccessFallbackError)(a)}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},94783,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"unstable_rethrow",{enumerable:!0,get:function(){return function a(b){if((0,g.isNextRouterError)(b)||(0,f.isBailoutToCSRError)(b)||(0,i.isDynamicServerError)(b)||(0,h.isDynamicPostpone)(b)||(0,e.isPostpone)(b)||(0,d.isHangingPromiseRejectionError)(b)||(0,h.isPrerenderInterruptedError)(b))throw b;b instanceof Error&&"cause"in b&&a(b.cause)}}});let d=a.r(13091),e=a.r(73808),f=a.r(49640),g=a.r(1567),h=a.r(60384),i=a.r(96556);("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},60968,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"unstable_rethrow",{enumerable:!0,get:function(){return d}});let d=a.r(94783).unstable_rethrow;("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},73727,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={ReadonlyURLSearchParams:function(){return f.ReadonlyURLSearchParams},RedirectType:function(){return m},forbidden:function(){return i.forbidden},notFound:function(){return h.notFound},permanentRedirect:function(){return g.permanentRedirect},redirect:function(){return g.redirect},unauthorized:function(){return j.unauthorized},unstable_isUnrecognizedActionError:function(){return l},unstable_rethrow:function(){return k.unstable_rethrow}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(20916),g=a.r(44868),h=a.r(16155),i=a.r(34557),j=a.r(93845),k=a.r(60968);function l(){throw Object.defineProperty(Error("`unstable_isUnrecognizedActionError` can only be used on the client."),"__NEXT_ERROR_CODE",{value:"E776",enumerable:!1,configurable:!0})}let m={push:"push",replace:"replace"};("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},70396,a=>{"use strict";a.i(73727),a.s([])},1632,a=>{"use strict";var b=a.i(7997);a.i(70396);var c=a.i(73727),d=a.i(95936),e=a.i(67116),f=a.i(48024),g=a.i(4636),h=a.i(77708),i=a.i(87067);let j=(0,a.i(1269).default)("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]);async function k({params:a}){let{slug:l}=await a,m=decodeURIComponent(l),n=(await (0,e.listSessions)()).filter(a=>(0,f.canonicalProjectName)(a.projectName)===m);if(0===n.length)return(0,c.notFound)();let o=n.slice(0,50),p=await Promise.all(o.map(a=>(0,e.getSession)(a.id))),q=p.filter(a=>!!a).flatMap(a=>(0,f.detectPrMarkers)(a)),r=p.filter(a=>!!a).reduce((a,b)=>a+(0,f.sessionAirTimeMs)(b.events),0),s=n.slice(0,12),t=q.length>0;return(0,b.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:28,maxWidth:1280,padding:"32px 40px"},children:[(0,b.jsx)("div",{style:{fontSize:12,color:"var(--af-text-tertiary)"},children:(0,b.jsxs)(d.default,{href:"/projects",style:{color:"var(--af-text-tertiary)",display:"inline-flex",alignItems:"center",gap:4},children:[(0,b.jsx)(j,{size:12})," Projects"]})}),(0,b.jsxs)("header",{children:[(0,b.jsx)("h1",{style:{fontSize:26,fontWeight:700,letterSpacing:"-0.02em",margin:0},children:(0,i.prettyProjectName)(m)}),(0,b.jsx)("p",{style:{fontSize:12,color:"var(--af-text-tertiary)",marginTop:4,fontFamily:"var(--font-mono)"},children:m})]}),(0,b.jsx)(g.DashboardView,{sessions:n,override:{activeTimeMs:r||void 0}}),(0,b.jsxs)("section",{style:{display:"grid",gridTemplateColumns:t?"1fr 1fr":"1fr",gap:16},children:[t&&(0,b.jsxs)("div",{className:"af-panel",children:[(0,b.jsxs)("div",{className:"af-panel-header",children:[(0,b.jsx)("span",{children:"Pull requests shipped"}),(0,b.jsx)("span",{style:{fontSize:11,color:"var(--af-text-tertiary)",fontWeight:400},children:"detected from `gh pr create` calls"})]}),(0,b.jsx)("div",{style:{padding:14,display:"flex",flexDirection:"column",gap:6},children:q.sort((a,b)=>Date.parse(b.timestamp)-Date.parse(a.timestamp)).slice(0,12).map((a,c)=>(0,b.jsxs)(d.default,{href:`/sessions/${a.sessionId}`,style:{display:"grid",gridTemplateColumns:"90px 1fr 60px",gap:10,padding:"10px 14px",border:"1px solid var(--af-border-subtle)",borderRadius:8,background:"var(--af-surface-hover)",fontSize:12,alignItems:"center"},children:[(0,b.jsx)("div",{style:{fontSize:11,color:"var(--af-text-secondary)",fontFamily:"var(--font-mono)"},suppressHydrationWarning:!0,children:(0,i.formatRelative)(a.timestamp)}),(0,b.jsx)("div",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--af-text)"},title:a.command,children:a.title??a.command.replace(/^gh pr create /,"").slice(0,120)}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",fontFamily:"var(--font-mono)",textAlign:"right"},children:void 0!==a.positionInSession?`${Math.round(100*a.positionInSession)}% in`:"—"})]},c))})]}),(0,b.jsxs)("div",{className:"af-panel",children:[(0,b.jsxs)("div",{className:"af-panel-header",children:[(0,b.jsx)("span",{children:"Recent sessions"}),(0,b.jsx)(d.default,{href:"/sessions",style:{fontSize:11,color:"var(--af-accent)",marginLeft:"auto"},children:"View all →"})]}),(0,b.jsx)("div",{children:s.map(a=>(0,b.jsxs)(d.default,{href:`/sessions/${a.id}`,style:{display:"grid",gridTemplateColumns:"1fr auto auto",gap:12,padding:"10px 18px",fontSize:12,borderBottom:"1px solid var(--af-border-subtle)",alignItems:"center"},children:[(0,b.jsx)("div",{style:{minWidth:0},children:(0,b.jsxs)("div",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--af-text)",display:"flex",alignItems:"center",gap:6},children:[(0,b.jsx)(h.LiveBadge,{mtimeIso:a.lastTimestamp}),(0,b.jsx)("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:a.firstUserPreview||(0,b.jsx)("em",{style:{color:"var(--af-text-tertiary)"},children:"(no user message)"})})]})}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",fontFamily:"var(--font-mono)",textAlign:"right",minWidth:54},title:"Agent time (filters out idle gaps)",children:(0,i.formatDuration)(a.airTimeMs??a.durationMs)}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",textAlign:"right",minWidth:54},suppressHydrationWarning:!0,children:a.firstTimestamp?(0,i.formatRelative)(a.firstTimestamp):"—"})]},`${a.projectDir}/${a.id}`))})]})]})]})}a.s(["default",0,k,"dynamic",0,"force-dynamic"],1632)},35416,a=>{a.n(a.i(1632))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0cdd~8n._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[93695,(a,b,c)=>{b.exports=a.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},71306,(a,b,c)=>{b.exports=a.r(18622)},79847,a=>{a.n(a.i(3343))},9185,a=>{a.n(a.i(29432))},72842,a=>{a.n(a.i(75164))},54897,a=>{a.n(a.i(30106))},56157,a=>{a.n(a.i(18970))},94331,a=>{a.n(a.i(60644))},15988,a=>{a.n(a.i(56952))},25766,a=>{a.n(a.i(77341))},29725,a=>{a.n(a.i(94290))},5785,a=>{a.n(a.i(90588))},74793,a=>{a.n(a.i(33169))},85826,a=>{a.n(a.i(37111))},21565,a=>{a.n(a.i(41763))},65911,a=>{a.n(a.i(8950))},25128,a=>{a.n(a.i(91562))},40781,a=>{a.n(a.i(49670))},69411,a=>{a.n(a.i(75700))},63081,a=>{a.n(a.i(276))},62837,a=>{a.n(a.i(40795))},34607,a=>{a.n(a.i(11614))},96338,a=>{a.n(a.i(21751))},50642,a=>{a.n(a.i(12213))},32242,a=>{a.n(a.i(22693))},88530,a=>{a.n(a.i(10531))},8583,a=>{a.n(a.i(1082))},38534,a=>{a.n(a.i(98175))},70408,a=>{a.n(a.i(9095))},22922,a=>{a.n(a.i(96772))},78294,a=>{a.n(a.i(71717))},16625,a=>{a.n(a.i(85034))},88648,a=>{a.n(a.i(68113))},51914,a=>{a.n(a.i(66482))},25466,a=>{a.n(a.i(91505))},67116,a=>{"use strict";var b=a.i(717),c=a.i(50785);let d=process.env.CCLENS_DATA_DIR||void 0,e=(0,b.cache)(async()=>(0,c.listSessions)({limit:1e3,root:d})),f=(0,b.cache)(async a=>(0,c.getSession)(a,{root:d}));a.s(["getSession",0,f,"listSessions",0,e])},1269,a=>{"use strict";var b=a.i(717);let c=(...a)=>a.filter((a,b,c)=>!!a&&""!==a.trim()&&c.indexOf(a)===b).join(" ").trim();var d={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let e=(0,b.forwardRef)(({color:a="currentColor",size:e=24,strokeWidth:f=2,absoluteStrokeWidth:g,className:h="",children:i,iconNode:j,...k},l)=>(0,b.createElement)("svg",{ref:l,...d,width:e,height:e,stroke:a,strokeWidth:g?24*Number(f)/Number(e):f,className:c("lucide",h),...k},[...j.map(([a,c])=>(0,b.createElement)(a,c)),...Array.isArray(i)?i:[i]]));a.s(["default",0,(a,d)=>{let f=(0,b.forwardRef)(({className:f,...g},h)=>(0,b.createElement)(e,{ref:h,iconNode:d,className:c(`lucide-${a.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}`,f),...g}));return f.displayName=`${a}`,f}],1269)},34476,a=>{"use strict";a.s(["DateRangeFilter",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call DateRangeFilter() from the server but DateRangeFilter is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/date-range-filter.tsx <module evaluation>","DateRangeFilter")},96491,a=>{"use strict";a.s(["DateRangeFilter",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call DateRangeFilter() from the server but DateRangeFilter is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/date-range-filter.tsx","DateRangeFilter")},67598,a=>{"use strict";a.i(34476);var b=a.i(96491);a.n(b)},77739,a=>{"use strict";var b=a.i(7997),c=a.i(48024),d=a.i(4636),e=a.i(67598),f=a.i(77708),g=a.i(67116),h=a.i(87067),i=a.i(95936);async function j({searchParams:a}){let k,{range:l}=await a,m="7d"===(k=Array.isArray(l)?l[0]:l)||"30d"===k||"90d"===k||"all"===k?k:"all",n=function(a,b=Date.now()){if("all"!==a)return b-24*("7d"===a?7:"30d"===a?30:90)*36e5}(m),o=await (0,g.listSessions)(),p=void 0===n?o:o.filter(a=>{if(!a.firstTimestamp)return!1;let b=Date.parse(a.firstTimestamp);return!Number.isNaN(b)&&b>=n}),q=(0,c.groupByProject)(p).sort((a,b)=>{let c=a.metrics.totalTokens.input+a.metrics.totalTokens.output+a.metrics.totalTokens.cacheRead+a.metrics.totalTokens.cacheWrite,d=b.metrics.totalTokens.input+b.metrics.totalTokens.output+b.metrics.totalTokens.cacheRead+b.metrics.totalTokens.cacheWrite;return d!==c?d-c:b.metrics.sessionCount-a.metrics.sessionCount}).slice(0,8),r=p.slice(0,6);return(0,b.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:28,maxWidth:1280,padding:"32px 40px"},children:[(0,b.jsxs)("header",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:18,flexWrap:"wrap"},children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{style:{fontSize:26,fontWeight:700,letterSpacing:"-0.02em",margin:0},children:"Overview"}),(0,b.jsxs)("p",{style:{fontSize:13,color:"var(--af-text-secondary)",marginTop:4},children:[p.length," of ",o.length," session",1===o.length?"":"s",", read from"," ",(0,b.jsx)("code",{style:{fontFamily:"var(--font-mono)",fontSize:11,background:"var(--af-border-subtle)",padding:"1px 6px",borderRadius:4},children:"~/.claude/projects"}),"."]})]}),(0,b.jsx)(e.DateRangeFilter,{current:m})]}),(0,b.jsx)(d.DashboardView,{sessions:p}),(0,b.jsxs)("section",{style:{display:"grid",gridTemplateColumns:"1fr 1.4fr",gap:16},children:[(0,b.jsxs)("div",{className:"af-panel",children:[(0,b.jsxs)("div",{className:"af-panel-header",children:[(0,b.jsx)("span",{children:"Top projects"}),(0,b.jsx)("span",{style:{fontSize:11,color:"var(--af-text-tertiary)",fontWeight:400},children:"by total tokens"}),(0,b.jsx)(i.default,{href:"/projects",style:{fontSize:11,color:"var(--af-accent)",marginLeft:"auto"},children:"View all →"})]}),(0,b.jsx)("div",{children:0===q.length?(0,b.jsx)("div",{className:"af-empty",children:"No projects yet."}):q.map(a=>{let c=a.metrics.totalTokens.input+a.metrics.totalTokens.output+a.metrics.totalTokens.cacheRead+a.metrics.totalTokens.cacheWrite;return(0,b.jsxs)(i.default,{href:`/projects/${encodeURIComponent(a.projectDir)}`,style:{display:"grid",gridTemplateColumns:"1fr auto auto auto",gap:14,padding:"10px 18px",fontSize:12,borderBottom:"1px solid var(--af-border-subtle)",alignItems:"center"},children:[(0,b.jsx)("div",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--af-text)"},title:a.projectName,children:(0,h.prettyProjectName)(a.projectName)}),(0,b.jsxs)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",fontFamily:"var(--font-mono)",minWidth:64,textAlign:"right"},children:[a.sessions.length," sess"]}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",fontFamily:"var(--font-mono)",minWidth:52,textAlign:"right"},title:`${c.toLocaleString()} tokens`,children:(0,h.formatTokens)(c)}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",minWidth:56,textAlign:"right"},suppressHydrationWarning:!0,children:a.lastActiveMs?(0,h.formatRelative)(new Date(a.lastActiveMs).toISOString()):"—"})]},a.projectDir)})})]}),(0,b.jsxs)("div",{className:"af-panel",children:[(0,b.jsxs)("div",{className:"af-panel-header",children:[(0,b.jsx)("span",{children:"Recent sessions"}),(0,b.jsx)(i.default,{href:"/sessions",style:{fontSize:11,color:"var(--af-accent)",marginLeft:"auto"},children:"View all →"})]}),(0,b.jsx)("div",{children:0===r.length?(0,b.jsx)("div",{className:"af-empty",children:"No sessions found in ~/.claude/projects"}):r.map(a=>(0,b.jsxs)(i.default,{href:`/sessions/${a.id}`,style:{display:"grid",gridTemplateColumns:"1fr auto auto",gap:12,padding:"10px 18px",fontSize:12,borderBottom:"1px solid var(--af-border-subtle)",alignItems:"center"},children:[(0,b.jsxs)("div",{style:{minWidth:0},children:[(0,b.jsxs)("div",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--af-text)",display:"flex",alignItems:"center",gap:6},children:[(0,b.jsx)(f.LiveBadge,{mtimeIso:a.lastTimestamp}),(0,b.jsx)("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:a.firstUserPreview||(0,b.jsx)("em",{style:{color:"var(--af-text-tertiary)"},children:"(no user message)"})})]}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",marginTop:2,fontFamily:"var(--font-mono)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:(0,h.prettyProjectName)(a.projectName)})]}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",fontFamily:"var(--font-mono)",textAlign:"right",minWidth:54},title:"Agent time (filters out idle gaps)",children:(0,h.formatDuration)(a.airTimeMs??a.durationMs)}),(0,b.jsx)("div",{style:{fontSize:10,color:"var(--af-text-tertiary)",textAlign:"right",minWidth:54},children:a.firstTimestamp?(0,h.formatRelative)(a.firstTimestamp):"—"})]},`${a.projectDir}/${a.id}`))})]})]})]})}a.s(["default",0,j,"dynamic",0,"force-dynamic"],77739)},67303,a=>{a.n(a.i(77739))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0~a~v00._.js.map
@@ -1,12 +0,0 @@
1
- module.exports=[83885,a=>{"use strict";a.s(["Heatmap",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call Heatmap() from the server but Heatmap is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/heatmap.tsx <module evaluation>","Heatmap")},44467,a=>{"use strict";a.s(["Heatmap",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call Heatmap() from the server but Heatmap is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/heatmap.tsx","Heatmap")},54572,a=>{"use strict";a.i(83885);var b=a.i(44467);a.n(b)},70301,a=>{"use strict";a.s(["ActivityChart",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call ActivityChart() from the server but ActivityChart is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/activity-chart.tsx <module evaluation>","ActivityChart")},37964,a=>{"use strict";a.s(["ActivityChart",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call ActivityChart() from the server but ActivityChart is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/activity-chart.tsx","ActivityChart")},37707,a=>{"use strict";a.i(70301);var b=a.i(37964);a.n(b)},25581,a=>{"use strict";a.s(["MetricCard",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call MetricCard() from the server but MetricCard is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/metric-card.tsx <module evaluation>","MetricCard")},77267,a=>{"use strict";a.s(["MetricCard",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call MetricCard() from the server but MetricCard is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/metric-card.tsx","MetricCard")},94045,a=>{"use strict";a.i(25581);var b=a.i(77267);a.n(b)},4636,87067,a=>{"use strict";var b=a.i(7997),c=a.i(48024),d=a.i(54572),e=a.i(37707),f=a.i(94045);function g(a){return a<1e3?String(a):a<1e4?(a/1e3).toFixed(1)+"k":a<1e6?Math.round(a/1e3)+"k":a<1e7?(a/1e6).toFixed(2)+"M":(a/1e6).toFixed(1)+"M"}function h(a){if(void 0===a)return"—";if(a<1e3)return`${a}ms`;let b=Math.round(a/1e3);if(b<60)return`${b}s`;let c=Math.floor(b/60),d=b%60;if(c<60)return d?`${c}m ${d}s`:`${c}m`;let e=Math.floor(c/60),f=c%60;return f?`${e}h ${f}m`:`${e}h`}let i={input:1,output:5,cacheRead:.1,cacheWrite:1.25},j={input:3,output:15,cacheRead:.3,cacheWrite:3.75},k={input:5,output:25,cacheRead:.5,cacheWrite:6.25};function l(a){return a.reduce((a,b)=>{var c;let d;return a+(c=b.totalUsage,d=function(a){if(!a)return k;let b=a.toLowerCase();return b.includes("haiku")?i:b.includes("sonnet")?j:k}(b.model),c.input/1e6*d.input+c.output/1e6*d.output+c.cacheRead/1e6*d.cacheRead+c.cacheWrite/1e6*d.cacheWrite)},0)}function m(a){return a<.01?"<$0.01":a<1||a<100?`$${a.toFixed(2)}`:a<1e3?`$${a.toFixed(1)}`:`$${a.toLocaleString(void 0,{maximumFractionDigits:0})}`}a.s(["estimateCostMulti",0,l,"formatCost",0,m,"formatDuration",0,h,"formatRelative",0,function(a){let b=Date.parse(a);if(Number.isNaN(b))return a;let c=Math.round((Date.now()-b)/1e3);if(c<60)return`${c}s ago`;let d=Math.round(c/60);if(d<60)return`${d}m ago`;let e=Math.round(d/60);if(e<24)return`${e}h ago`;let f=Math.round(e/24);return`${f}d ago`},"formatTokens",0,g,"prettyProjectName",0,function(a,b=35){let c=a.split("/").filter(Boolean),d=c.lastIndexOf(".worktrees");if(d>0&&d<c.length-1){let a=c[d-1],e=c[d+1],f=`${a}/${e}`;return f.length<=b?f:"…"+f.slice(f.length-b+1)}let e=c.length>=2?`${c[c.length-2]}/${c[c.length-1]}`:c[c.length-1]??a;return e.length<=b?e:"…"+e.slice(e.length-b+1)}],87067);var n=a.i(1269);let o=(0,n.default)("ListTree",[["path",{d:"M21 12h-8",key:"1bmf0i"}],["path",{d:"M21 6H8",key:"1pqkrb"}],["path",{d:"M21 18h-8",key:"1tm79t"}],["path",{d:"M3 6v4c0 1.1.9 2 2 2h3",key:"1ywdgy"}],["path",{d:"M3 10v6c0 1.1.9 2 2 2h3",key:"2wc746"}]]),p=(0,n.default)("Clock",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["polyline",{points:"12 6 12 12 16 14",key:"68esgv"}]]),q=(0,n.default)("Zap",[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]]),r=(0,n.default)("DollarSign",[["line",{x1:"12",x2:"12",y1:"2",y2:"22",key:"7eqyqh"}],["path",{d:"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6",key:"1b0p4s"}]]);function s({line1:a,line2:c}){return(0,b.jsxs)("div",{style:{lineHeight:1.4},children:[(0,b.jsx)("div",{children:a}),(0,b.jsx)("div",{style:{color:"var(--af-text-tertiary)"},children:c})]})}function t(a){return a<1e3?String(a):a<1e6?(a/1e3).toFixed(1)+"k":(a/1e6).toFixed(1)+"M"}function u(a){return a<1e3?String(a):a<1e6?(a/1e3).toFixed(1)+"k":a<1e9?(a/1e6).toFixed(1)+"M":(a/1e9).toFixed(1)+"B"}a.s(["DashboardView",0,function({sessions:a,override:i}){let j=(0,c.highLevelMetrics)(a),k=(0,c.dailyActivity)(a),n=(0,c.summarizeBursts)((0,c.computeBurstsFromSessions)(a)),v=j.totalTokens.input+j.totalTokens.cacheRead+j.totalTokens.cacheWrite,w=i?.activeTimeMs??j.totalAirTimeMs,x=k.filter(a=>a.airTimeMs>0).length;return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("section",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(180px, 1fr))",gap:12},children:[(0,b.jsx)(f.MetricCard,{label:"Sessions",value:j.sessionCount.toLocaleString(),sub:(0,b.jsx)(s,{line1:`${j.totalTurns.toLocaleString()} turns`,line2:`avg ${j.sessionCount?Math.round(j.totalTurns/j.sessionCount):0} / session`}),icon:(0,b.jsx)(o,{size:13}),tooltip:"Total Claude Code sessions (one JSONL file = one session). A 'turn' is one user message that starts an agent response cycle."}),(0,b.jsx)(f.MetricCard,{label:"Agent time",value:h(w),sub:x>0?(0,b.jsx)(s,{line1:`${h(w/x)} / day`,line2:`${x} active days`}):"no activity",icon:(0,b.jsx)(p,{size:13}),tooltip:"Sum of time the Claude agent was actively working across all sessions. Gaps longer than 3 minutes (user away, laptop lid closed) are excluded. This is NOT wall-clock duration. Per-day average is across days with any agent activity."}),(0,b.jsx)(f.MetricCard,{label:"Tool calls",value:j.totalToolCalls.toLocaleString(),sub:(0,b.jsx)(s,{line1:`avg ${j.sessionCount?Math.round(j.totalToolCalls/j.sessionCount):0} / session`,line2:`across ${j.sessionCount.toLocaleString()} sessions`}),icon:(0,b.jsx)(q,{size:13}),tooltip:"Total tool invocations (Bash, Read, Edit, Write, Grep, Glob, Agent, etc.) across all sessions."}),(0,b.jsx)(f.MetricCard,{label:"Parallelism",value:n.burstCount>0?h(n.totalParallelMs):"—",sub:n.burstCount>0?(0,b.jsx)(s,{line1:`peak \xd7${n.peakConcurrent}`,line2:`${Math.round(n.totalParallelMs/Math.max(1,w)*100)}% of active time`}):"no sustained parallelism",tooltip:`Total time ≥2 agents were working in parallel, with peak concurrency as the highest count in any single burst.
2
-
3
- ${n.burstCount} burst${1===n.burstCount?"":"s"} \xb7 ${n.crossProjectBurstCount} spanned multiple projects.`}),(0,b.jsx)(f.MetricCard,{label:"Code changes",value:(0,b.jsxs)("span",{children:[(0,b.jsxs)("span",{style:{color:"var(--af-success)"},children:["+",t(j.totalLinesAdded)]})," ",(0,b.jsxs)("span",{style:{color:"var(--af-danger)"},children:["-",t(j.totalLinesRemoved)]})]}),sub:(0,b.jsx)(s,{line1:`${j.totalFilesEdited.toLocaleString()} files touched`,line2:`${t(j.totalLinesAdded+j.totalLinesRemoved)} total lines`}),tooltip:`Total lines added and removed across all Edit + Write tool calls.
4
- +${j.totalLinesAdded.toLocaleString()} added
5
- -${j.totalLinesRemoved.toLocaleString()} removed
6
- ${j.totalFilesEdited.toLocaleString()} unique files touched`}),(0,b.jsx)(f.MetricCard,{label:"Est. cost",value:m(l(a)),sub:(0,b.jsx)(s,{line1:`${u(v)} in`,line2:`${u(j.totalTokens.output)} out`}),icon:(0,b.jsx)(r,{size:13}),tooltip:`Estimated API spend priced per-model across all sessions.
7
- Input: ${g(j.totalTokens.input)}
8
- Output: ${g(j.totalTokens.output)}
9
- Cache read: ${g(j.totalTokens.cacheRead)}
10
- Cache write: ${g(j.totalTokens.cacheWrite)}`}),i?.extraCards]}),(0,b.jsxs)("section",{style:{display:"grid",gridTemplateColumns:"1fr 2fr",gap:16},children:[(0,b.jsxs)("div",{className:"af-panel",style:{display:"flex",flexDirection:"column"},children:[(0,b.jsxs)("div",{className:"af-panel-header",children:[(0,b.jsx)("span",{children:"Contribution heatmap"}),(0,b.jsx)("span",{style:{fontSize:11,color:"var(--af-text-tertiary)",fontWeight:400},children:"sessions / day"})]}),(0,b.jsx)("div",{style:{padding:18,flex:1,display:"flex",alignItems:"center",justifyContent:"center"},children:(0,b.jsx)(d.Heatmap,{buckets:k,valueKey:"sessions"})})]}),(0,b.jsxs)("div",{className:"af-panel",children:[(0,b.jsxs)("div",{className:"af-panel-header",children:[(0,b.jsx)("span",{children:"Daily activity"}),(0,b.jsx)("span",{style:{fontSize:11,color:"var(--af-text-tertiary)",fontWeight:400},children:"click a metric to switch"})]}),(0,b.jsx)("div",{style:{padding:18},children:(0,b.jsx)(e.ActivityChart,{buckets:k})})]})]})]})}],4636)},41264,a=>{"use strict";a.s(["LiveBadge",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call LiveBadge() from the server but LiveBadge is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/live-badge.tsx <module evaluation>","LiveBadge")},71475,a=>{"use strict";a.s(["LiveBadge",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call LiveBadge() from the server but LiveBadge is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/apps/web/components/live-badge.tsx","LiveBadge")},77708,a=>{"use strict";a.i(41264);var b=a.i(71475);a.n(b)},64240,(a,b,c)=>{"use strict";function d(a){if("function"!=typeof WeakMap)return null;var b=new WeakMap,c=new WeakMap;return(d=function(a){return a?c:b})(a)}c._=function(a,b){if(!b&&a&&a.__esModule)return a;if(null===a||"object"!=typeof a&&"function"!=typeof a)return{default:a};var c=d(b);if(c&&c.has(a))return c.get(a);var e={__proto__:null},f=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var g in a)if("default"!==g&&Object.prototype.hasOwnProperty.call(a,g)){var h=f?Object.getOwnPropertyDescriptor(a,g):null;h&&(h.get||h.set)?Object.defineProperty(e,g,h):e[g]=a[g]}return e.default=a,c&&c.set(a,e),e}},790,(a,b,c)=>{let{createClientModuleProxy:d}=a.r(11857);a.n(d("[project]/node_modules/next/dist/client/app-dir/link.js <module evaluation>"))},84707,(a,b,c)=>{let{createClientModuleProxy:d}=a.r(11857);a.n(d("[project]/node_modules/next/dist/client/app-dir/link.js"))},97647,a=>{"use strict";a.i(790);var b=a.i(84707);a.n(b)},95936,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={default:function(){return i},useLinkStatus:function(){return h.useLinkStatus}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(64240),g=a.r(7997),h=f._(a.r(97647));function i(a){let b=a.legacyBehavior,c="string"==typeof a.children||"number"==typeof a.children||"string"==typeof a.children?.type,d=a.children?.type?.$$typeof===Symbol.for("react.client.reference");return!b||c||d||(a.children?.type?.$$typeof===Symbol.for("react.lazy")?console.error("Using a Lazy Component as a direct child of `<Link legacyBehavior>` from a Server Component is not supported. If you need legacyBehavior, wrap your Lazy Component in a Client Component that renders the Link's `<a>` tag."):console.error("Using a Server Component as a direct child of `<Link legacyBehavior>` is not supported. If you need legacyBehavior, wrap your Server Component in a Client Component that renders the Link's `<a>` tag.")),(0,g.jsx)(h.default,{...a})}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)}];
11
-
12
- //# sourceMappingURL=_0zv~jv-._.js.map