agent-session-inspector 0.1.8 → 0.1.9

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 (88) hide show
  1. package/VERSION +1 -1
  2. package/app/.next/BUILD_ID +1 -1
  3. package/app/.next/build-manifest.json +3 -3
  4. package/app/.next/prerender-manifest.json +3 -3
  5. package/app/.next/required-server-files.json +1 -1
  6. package/app/.next/server/app/_global-error.html +1 -1
  7. package/app/.next/server/app/_global-error.rsc +1 -1
  8. package/app/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/app/.next/server/app/_not-found/page.js.nft.json +1 -1
  12. package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/app/.next/server/app/_not-found.html +1 -1
  14. package/app/.next/server/app/_not-found.rsc +14 -14
  15. package/app/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  16. package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  17. package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  18. package/app/.next/server/app/api/analytics/route.js.nft.json +1 -1
  19. package/app/.next/server/app/api/logs/route.js.nft.json +1 -1
  20. package/app/.next/server/app/api/providers/route.js.nft.json +1 -1
  21. package/app/.next/server/app/api/search/route.js.nft.json +1 -1
  22. package/app/.next/server/app/api/sessions/[provider]/[id]/record/route.js.nft.json +1 -1
  23. package/app/.next/server/app/api/sessions/[provider]/[id]/reveal/route.js.nft.json +1 -1
  24. package/app/.next/server/app/api/sessions/[provider]/[id]/route.js.nft.json +1 -1
  25. package/app/.next/server/app/api/sessions/route.js.nft.json +1 -1
  26. package/app/.next/server/app/index.html +1 -1
  27. package/app/.next/server/app/index.rsc +16 -16
  28. package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +15 -15
  29. package/app/.next/server/app/index.segments/_full.segment.rsc +16 -16
  30. package/app/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  31. package/app/.next/server/app/page.js.nft.json +1 -1
  32. package/app/.next/server/app/page_client-reference-manifest.js +1 -1
  33. package/app/.next/server/app/sessions/[provider]/[id]/page.js.nft.json +1 -1
  34. package/app/.next/server/app/sessions/[provider]/[id]/page_client-reference-manifest.js +1 -1
  35. package/app/.next/server/chunks/[root-of-the-server]__0yxic1z._.js +2 -2
  36. package/app/.next/server/chunks/ssr/_0f8nmc3._.js +1 -1
  37. package/app/.next/server/chunks/ssr/_0o294sf._.js +1 -1
  38. package/app/.next/server/chunks/ssr/_0wfo2z0._.js +1 -1
  39. package/app/.next/server/chunks/ssr/src_app_sessions_[provider]_[id]_page_tsx_0uf635h._.js +3 -3
  40. package/app/.next/server/middleware-build-manifest.js +3 -3
  41. package/app/.next/server/pages/404.html +1 -1
  42. package/app/.next/server/pages/500.html +1 -1
  43. package/app/.next/server/server-reference-manifest.js +1 -1
  44. package/app/.next/server/server-reference-manifest.json +1 -1
  45. package/app/.next/static/chunks/{1nuneih_2_kul.js → 0f_9fwik8mxzl.js} +1 -1
  46. package/app/.next/static/chunks/{1fe2mxakoweia.js → 18c6__lhilfeo.js} +1 -1
  47. package/app/.next/static/chunks/28k1og85stfuo.js +6 -0
  48. package/app/.next/static/chunks/3-49ck9kf466m.css +1 -0
  49. package/app/AGENTS.md +9 -0
  50. package/app/CLAUDE.md +1 -0
  51. package/app/CONTRIBUTING.md +90 -0
  52. package/app/Dockerfile +34 -0
  53. package/app/LICENSE +21 -0
  54. package/app/README.md +369 -0
  55. package/app/bin/agent-session-inspector.mjs +185 -0
  56. package/app/components.json +25 -0
  57. package/app/docs/screenshots/analytics-dark.png +0 -0
  58. package/app/docs/screenshots/analytics.png +0 -0
  59. package/app/docs/screenshots/request-table.png +0 -0
  60. package/app/docs/screenshots/session-overview-dark.png +0 -0
  61. package/app/docs/screenshots/session-overview.png +0 -0
  62. package/app/docs/screenshots/sessions-dark.png +0 -0
  63. package/app/docs/screenshots/sessions.png +0 -0
  64. package/app/docs/screenshots/timeline-dark.png +0 -0
  65. package/app/docs/screenshots/timeline.png +0 -0
  66. package/app/docs/screenshots/token-optimizer-dark.png +0 -0
  67. package/app/docs/screenshots/token-optimizer.png +0 -0
  68. package/app/docs/social-preview.png +0 -0
  69. package/app/eslint.config.mjs +20 -0
  70. package/app/install.sh +85 -0
  71. package/app/next.config.ts +17 -0
  72. package/app/package.json +1 -1
  73. package/app/pnpm-lock.yaml +7031 -0
  74. package/app/pnpm-workspace.yaml +3 -0
  75. package/app/postcss.config.mjs +7 -0
  76. package/app/scripts/build-cli.mjs +26 -0
  77. package/app/scripts/demo-data.mjs +337 -0
  78. package/app/scripts/deploy-docker.sh +71 -0
  79. package/app/scripts/package-release.sh +86 -0
  80. package/app/server.js +1 -1
  81. package/app/tsconfig.json +34 -0
  82. package/cli/cli.mjs +192 -74
  83. package/package.json +1 -1
  84. package/app/.next/static/chunks/1lmw5sxsr57p6.css +0 -1
  85. package/app/.next/static/chunks/21ckxredfe3pr.js +0 -6
  86. /package/app/.next/static/{muuOFZsnyOfIG_5aUuqFV → 7UozMfIH3Lk8P6-UWWQXF}/_buildManifest.js +0 -0
  87. /package/app/.next/static/{muuOFZsnyOfIG_5aUuqFV → 7UozMfIH3Lk8P6-UWWQXF}/_clientMiddlewareManifest.js +0 -0
  88. /package/app/.next/static/{muuOFZsnyOfIG_5aUuqFV → 7UozMfIH3Lk8P6-UWWQXF}/_ssgManifest.js +0 -0
package/cli/cli.mjs CHANGED
@@ -4240,7 +4240,8 @@ var ATTACHMENT_LABELS = {
4240
4240
  command_permissions: "Command permissions",
4241
4241
  remote_session_change: "Remote session",
4242
4242
  file: "Attached file",
4243
- image: "Image"
4243
+ image: "Image",
4244
+ synthetic: "Injected context"
4244
4245
  };
4245
4246
  function joinText(value) {
4246
4247
  if (Array.isArray(value)) return value.map((v) => joinText(v)).join("\n");
@@ -4260,6 +4261,7 @@ function describeAttachment(attachment) {
4260
4261
  case "total_tokens_reminder":
4261
4262
  case "batching_reminder_sent":
4262
4263
  case "silent_turn_reminder":
4264
+ case "synthetic":
4263
4265
  case "model":
4264
4266
  body = joinText(attachment.text);
4265
4267
  break;
@@ -4271,7 +4273,9 @@ function describeAttachment(attachment) {
4271
4273
  body = joinText(attachment.snapshot);
4272
4274
  break;
4273
4275
  case "session_context":
4274
- body = Object.values(attachment.context ?? {}).map((v) => joinText(v)).join("\n\n");
4276
+ body = Object.values(
4277
+ attachment.context ?? {}
4278
+ ).map((v) => joinText(v)).join("\n\n");
4275
4279
  break;
4276
4280
  case "deferred_tools_record": {
4277
4281
  const entries = attachment.entries ?? [];
@@ -4368,7 +4372,9 @@ function systemPromptOf(attachment) {
4368
4372
  return sections.filter(Boolean).join("\n\n");
4369
4373
  }
4370
4374
  function describeToolDefinitions(tools, chars) {
4371
- const names = tools.map((tool) => String(tool?.name ?? "tool"));
4375
+ const names = tools.map(
4376
+ (tool) => String(tool?.name ?? "tool")
4377
+ );
4372
4378
  return {
4373
4379
  attachmentType: "tool_definitions",
4374
4380
  label: ATTACHMENT_LABELS.tool_definitions,
@@ -4382,8 +4388,10 @@ function describeToolDefinitions(tools, chars) {
4382
4388
  }
4383
4389
  function instructionFilesText(attachment) {
4384
4390
  const files = attachment.files ?? [];
4385
- return files.map((file) => `# ${file.path ?? "instructions"}${file.type ? ` (${file.type})` : ""}
4386
- ${file.content ?? ""}`).join("\n\n");
4391
+ return files.map(
4392
+ (file) => `# ${file.path ?? "instructions"}${file.type ? ` (${file.type})` : ""}
4393
+ ${file.content ?? ""}`
4394
+ ).join("\n\n");
4387
4395
  }
4388
4396
  function parseClaudeTranscript(filePath, provider = "claude", id = path4.basename(filePath, ".jsonl")) {
4389
4397
  const records = readJsonl(filePath);
@@ -4442,16 +4450,28 @@ function parseClaudeTranscript(filePath, provider = "claude", id = path4.basenam
4442
4450
  continue;
4443
4451
  case "mode":
4444
4452
  case "permission-mode":
4445
- push(ts, "session.mode_change", {
4446
- mode: rec.mode ?? rec.permissionMode
4447
- }, rec.uuid, rec.parentUuid);
4453
+ push(
4454
+ ts,
4455
+ "session.mode_change",
4456
+ {
4457
+ mode: rec.mode ?? rec.permissionMode
4458
+ },
4459
+ rec.uuid,
4460
+ rec.parentUuid
4461
+ );
4448
4462
  continue;
4449
4463
  case "cost-state":
4450
- push(ts, "session.usage_checkpoint", {
4451
- totalCostUSD: rec.totalCostUSD,
4452
- apiDurationMs: rec.totalAPIDuration,
4453
- sessionTotals: { apiDurationMs: rec.totalAPIDuration ?? 0 }
4454
- }, rec.uuid, rec.parentUuid);
4464
+ push(
4465
+ ts,
4466
+ "session.usage_checkpoint",
4467
+ {
4468
+ totalCostUSD: rec.totalCostUSD,
4469
+ apiDurationMs: rec.totalAPIDuration,
4470
+ sessionTotals: { apiDurationMs: rec.totalAPIDuration ?? 0 }
4471
+ },
4472
+ rec.uuid,
4473
+ rec.parentUuid
4474
+ );
4455
4475
  continue;
4456
4476
  case "attachment": {
4457
4477
  const attachment = rec.attachment ?? {};
@@ -4465,12 +4485,18 @@ function parseClaudeTranscript(filePath, provider = "claude", id = path4.basenam
4465
4485
 
4466
4486
  ${prompt}` : prompt
4467
4487
  );
4468
- push(ts, "system.message", {
4469
- role: "system_prompt",
4470
- content: text,
4471
- charLength: chars,
4472
- truncated
4473
- }, rec.uuid, rec.parentUuid);
4488
+ push(
4489
+ ts,
4490
+ "system.message",
4491
+ {
4492
+ role: "system_prompt",
4493
+ content: text,
4494
+ charLength: chars,
4495
+ truncated
4496
+ },
4497
+ rec.uuid,
4498
+ rec.parentUuid
4499
+ );
4474
4500
  }
4475
4501
  if (Array.isArray(attachment.tools)) {
4476
4502
  const serialized = JSON.stringify(attachment.tools);
@@ -4488,60 +4514,126 @@ ${prompt}` : prompt
4488
4514
  continue;
4489
4515
  }
4490
4516
  if (attachment.type === "instructions") {
4491
- const { text, chars, truncated } = capText(instructionFilesText(attachment));
4492
- push(ts, "system.message", {
4493
- role: "instructions",
4494
- content: text,
4495
- charLength: chars,
4496
- truncated
4497
- }, rec.uuid, rec.parentUuid);
4517
+ const { text, chars, truncated } = capText(
4518
+ instructionFilesText(attachment)
4519
+ );
4520
+ push(
4521
+ ts,
4522
+ "system.message",
4523
+ {
4524
+ role: "instructions",
4525
+ content: text,
4526
+ charLength: chars,
4527
+ truncated
4528
+ },
4529
+ rec.uuid,
4530
+ rec.parentUuid
4531
+ );
4498
4532
  continue;
4499
4533
  }
4500
- push(ts, "context.attachment", describeAttachment(attachment), rec.uuid, rec.parentUuid);
4534
+ push(
4535
+ ts,
4536
+ "context.attachment",
4537
+ describeAttachment(attachment),
4538
+ rec.uuid,
4539
+ rec.parentUuid
4540
+ );
4501
4541
  continue;
4502
4542
  }
4503
4543
  case "system": {
4504
4544
  if (rec.subtype === "api_error") {
4505
- push(ts, "session.error", {
4506
- message: rec.error?.message ?? "API error",
4507
- detail: rec.error?.formatted ?? "",
4508
- level: rec.level,
4509
- error: rec.error
4510
- }, rec.uuid, rec.parentUuid);
4545
+ push(
4546
+ ts,
4547
+ "session.error",
4548
+ {
4549
+ message: rec.error?.message ?? "API error",
4550
+ detail: rec.error?.formatted ?? "",
4551
+ level: rec.level,
4552
+ error: rec.error
4553
+ },
4554
+ rec.uuid,
4555
+ rec.parentUuid
4556
+ );
4511
4557
  } else if (rec.subtype === "stop_hook_summary") {
4512
- push(ts, "hook.end", {
4513
- hookType: "Stop",
4514
- hookCount: rec.hookCount,
4515
- success: (rec.hookErrors?.length ?? 0) === 0
4516
- }, rec.uuid, rec.parentUuid);
4558
+ push(
4559
+ ts,
4560
+ "hook.end",
4561
+ {
4562
+ hookType: "Stop",
4563
+ hookCount: rec.hookCount,
4564
+ success: (rec.hookErrors?.length ?? 0) === 0
4565
+ },
4566
+ rec.uuid,
4567
+ rec.parentUuid
4568
+ );
4517
4569
  } else if (rec.subtype === "compact_boundary") {
4518
- push(ts, "session.compaction_start", {
4519
- trigger: rec.compactMetadata?.trigger,
4520
- preTokens: rec.compactMetadata?.preTokens
4521
- }, rec.uuid, rec.parentUuid);
4570
+ push(
4571
+ ts,
4572
+ "session.compaction_start",
4573
+ {
4574
+ trigger: rec.compactMetadata?.trigger,
4575
+ preTokens: rec.compactMetadata?.preTokens
4576
+ },
4577
+ rec.uuid,
4578
+ rec.parentUuid
4579
+ );
4522
4580
  } else if (rec.subtype === "turn_duration") {
4523
- push(ts, "assistant.turn_end", {
4524
- durationMs: rec.durationMs
4525
- }, rec.uuid, rec.parentUuid);
4581
+ push(
4582
+ ts,
4583
+ "assistant.turn_end",
4584
+ {
4585
+ durationMs: rec.durationMs
4586
+ },
4587
+ rec.uuid,
4588
+ rec.parentUuid
4589
+ );
4526
4590
  } else {
4527
4591
  const { text, chars, truncated } = capText(rec.content);
4528
- push(ts, "system.message", {
4529
- role: rec.subtype ?? "system",
4530
- content: text,
4531
- charLength: chars,
4532
- truncated
4533
- }, rec.uuid, rec.parentUuid);
4592
+ push(
4593
+ ts,
4594
+ "system.message",
4595
+ {
4596
+ role: rec.subtype ?? "system",
4597
+ content: text,
4598
+ charLength: chars,
4599
+ truncated
4600
+ },
4601
+ rec.uuid,
4602
+ rec.parentUuid
4603
+ );
4534
4604
  }
4535
4605
  continue;
4536
4606
  }
4537
4607
  case "user": {
4538
4608
  const content = rec.message?.content;
4539
4609
  const pushText = (raw) => {
4610
+ if (rec.isMeta === true) {
4611
+ push(
4612
+ ts,
4613
+ "context.attachment",
4614
+ describeAttachment({ type: "synthetic", text: raw }),
4615
+ rec.uuid,
4616
+ rec.parentUuid
4617
+ );
4618
+ return;
4619
+ }
4540
4620
  const { text } = capText(raw);
4541
4621
  if (INTERRUPTED.test(text)) {
4542
- push(ts, "session.turn_aborted", { reason: "interrupted", message: text }, rec.uuid, rec.parentUuid);
4622
+ push(
4623
+ ts,
4624
+ "session.turn_aborted",
4625
+ { reason: "interrupted", message: text },
4626
+ rec.uuid,
4627
+ rec.parentUuid
4628
+ );
4543
4629
  } else {
4544
- push(ts, "user.message", { content: text }, rec.uuid, rec.parentUuid);
4630
+ push(
4631
+ ts,
4632
+ "user.message",
4633
+ { content: text },
4634
+ rec.uuid,
4635
+ rec.parentUuid
4636
+ );
4545
4637
  }
4546
4638
  };
4547
4639
  if (typeof content === "string") {
@@ -4566,7 +4658,13 @@ ${prompt}` : prompt
4566
4658
  rec.parentUuid
4567
4659
  );
4568
4660
  } else if (block.type === "image") {
4569
- push(ts, "context.attachment", describeAttachment({ type: "image" }), rec.uuid, rec.parentUuid);
4661
+ push(
4662
+ ts,
4663
+ "context.attachment",
4664
+ describeAttachment({ type: "image" }),
4665
+ rec.uuid,
4666
+ rec.parentUuid
4667
+ );
4570
4668
  }
4571
4669
  }
4572
4670
  continue;
@@ -4574,7 +4672,8 @@ ${prompt}` : prompt
4574
4672
  case "assistant": {
4575
4673
  const message = rec.message;
4576
4674
  if (!message) continue;
4577
- if (message.model && message.model !== "<synthetic>") meta.model = message.model;
4675
+ if (message.model && message.model !== "<synthetic>")
4676
+ meta.model = message.model;
4578
4677
  const usage = message.usage;
4579
4678
  const messageKey = message.id ?? rec.requestId ?? rec.uuid ?? "";
4580
4679
  let usageData = {};
@@ -4605,20 +4704,32 @@ ${prompt}` : prompt
4605
4704
  };
4606
4705
  for (const block of blocks) {
4607
4706
  if (block.type === "text") {
4608
- push(ts, "assistant.message", {
4609
- content: capText(block.text).text,
4610
- model: message.model,
4611
- effort: rec.effort,
4612
- requestId: rec.requestId,
4613
- ...attachUsage()
4614
- }, rec.uuid, rec.parentUuid);
4707
+ push(
4708
+ ts,
4709
+ "assistant.message",
4710
+ {
4711
+ content: capText(block.text).text,
4712
+ model: message.model,
4713
+ effort: rec.effort,
4714
+ requestId: rec.requestId,
4715
+ ...attachUsage()
4716
+ },
4717
+ rec.uuid,
4718
+ rec.parentUuid
4719
+ );
4615
4720
  } else if (block.type === "thinking") {
4616
- push(ts, "assistant.thinking", {
4617
- content: capText(block.thinking).text,
4618
- charLength: (block.thinking ?? "").length,
4619
- model: message.model,
4620
- ...attachUsage()
4621
- }, rec.uuid, rec.parentUuid);
4721
+ push(
4722
+ ts,
4723
+ "assistant.thinking",
4724
+ {
4725
+ content: capText(block.thinking).text,
4726
+ charLength: (block.thinking ?? "").length,
4727
+ model: message.model,
4728
+ ...attachUsage()
4729
+ },
4730
+ rec.uuid,
4731
+ rec.parentUuid
4732
+ );
4622
4733
  } else if (block.type === "tool_use") {
4623
4734
  const name = block.name ?? "tool";
4624
4735
  if (block.id) toolNames.set(block.id, name);
@@ -4643,11 +4754,17 @@ ${prompt}` : prompt
4643
4754
  }
4644
4755
  }
4645
4756
  if (!usageAttached && Object.keys(usageData).length > 0) {
4646
- push(ts, "assistant.message", {
4647
- content: "",
4648
- model: message.model,
4649
- ...usageData
4650
- }, rec.uuid, rec.parentUuid);
4757
+ push(
4758
+ ts,
4759
+ "assistant.message",
4760
+ {
4761
+ content: "",
4762
+ model: message.model,
4763
+ ...usageData
4764
+ },
4765
+ rec.uuid,
4766
+ rec.parentUuid
4767
+ );
4651
4768
  }
4652
4769
  continue;
4653
4770
  }
@@ -4675,7 +4792,8 @@ ${prompt}` : prompt
4675
4792
  }
4676
4793
  function parseFile(filePath, projectDir) {
4677
4794
  const parsed = parseClaudeTranscript(filePath);
4678
- if (!parsed.meta.cwd) parsed.meta.cwd = decodeProjectDir(path4.basename(projectDir));
4795
+ if (!parsed.meta.cwd)
4796
+ parsed.meta.cwd = decodeProjectDir(path4.basename(projectDir));
4679
4797
  return parsed;
4680
4798
  }
4681
4799
  var summarize = createFileCache((filePath) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-session-inspector",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "See where a coding-agent session's tokens and dollars went: a local inspector for Claude Code, Codex, GitHub Copilot, Cursor, Gemini CLI, OpenCode and Hermes sessions, with a step-by-step timeline, per-step cost and analytics.",
5
5
  "keywords": [
6
6
  "agent",