argus-code 0.7.0__tar.gz → 0.7.1__tar.gz

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 (229) hide show
  1. {argus_code-0.7.0 → argus_code-0.7.1}/PKG-INFO +25 -24
  2. {argus_code-0.7.0 → argus_code-0.7.1}/README.md +22 -21
  3. argus_code-0.7.1/dashboard-dist/assets/AlertsPage-hQBct4uk.js +1 -0
  4. argus_code-0.7.0/dashboard-dist/assets/AreaLine-DVivOkZb.js → argus_code-0.7.1/dashboard-dist/assets/AreaLine-BKfPVgnO.js +1 -1
  5. argus_code-0.7.0/dashboard-dist/assets/AttentionStrip-C4S2Lszh.js → argus_code-0.7.1/dashboard-dist/assets/AttentionStrip-DQUV5LTN.js +1 -1
  6. argus_code-0.7.0/dashboard-dist/assets/Bars-BavaWNhM.js → argus_code-0.7.1/dashboard-dist/assets/Bars-CwquOD-V.js +1 -1
  7. argus_code-0.7.0/dashboard-dist/assets/Button-D2qCw3Bg.js → argus_code-0.7.1/dashboard-dist/assets/Button-BY-h2O0Z.js +1 -1
  8. argus_code-0.7.0/dashboard-dist/assets/ChartTable-Cs4_Bkur.js → argus_code-0.7.1/dashboard-dist/assets/ChartTable-iQFTYj1d.js +1 -1
  9. argus_code-0.7.0/dashboard-dist/assets/Chip-BfVZybGP.js → argus_code-0.7.1/dashboard-dist/assets/Chip-C_zmBEC6.js +1 -1
  10. argus_code-0.7.0/dashboard-dist/assets/ErrorPanel-B-6j7s5W.js → argus_code-0.7.1/dashboard-dist/assets/ErrorPanel-lb1Tt_Cg.js +1 -1
  11. argus_code-0.7.0/dashboard-dist/assets/ModelsPage-ZckGDACZ.js → argus_code-0.7.1/dashboard-dist/assets/ModelsPage-DwKKIQAH.js +1 -1
  12. argus_code-0.7.1/dashboard-dist/assets/MultiLine-Bp4Mitsq.js +1 -0
  13. argus_code-0.7.0/dashboard-dist/assets/OverviewPage-BZXbesGh.js → argus_code-0.7.1/dashboard-dist/assets/OverviewPage-CAx6S0a6.js +1 -1
  14. argus_code-0.7.0/dashboard-dist/assets/Panel-D9OW_N0O.js → argus_code-0.7.1/dashboard-dist/assets/Panel-rzVYig0L.js +1 -1
  15. argus_code-0.7.1/dashboard-dist/assets/SearchPage-DIj0iG5P.js +1 -0
  16. argus_code-0.7.0/dashboard-dist/assets/SessionPage-DQZVoIDZ.js → argus_code-0.7.1/dashboard-dist/assets/SessionPage-B5py8aO_.js +2 -2
  17. argus_code-0.7.0/dashboard-dist/assets/SessionsPage-CiIJBE2Z.js → argus_code-0.7.1/dashboard-dist/assets/SessionsPage-Br0MV0yN.js +1 -1
  18. argus_code-0.7.0/dashboard-dist/assets/SettingsPage-kFOEzh7m.js → argus_code-0.7.1/dashboard-dist/assets/SettingsPage-BFb2-hq_.js +1 -1
  19. argus_code-0.7.0/dashboard-dist/assets/StackedColumns-CFuYUdeJ.js → argus_code-0.7.1/dashboard-dist/assets/StackedColumns-Di1FeFpF.js +1 -1
  20. argus_code-0.7.0/dashboard-dist/assets/Tile-CTKO3Y6u.js → argus_code-0.7.1/dashboard-dist/assets/Tile-BlnGo9bN.js +1 -1
  21. argus_code-0.7.0/dashboard-dist/assets/TimelineTab-CZ-cy_B_.js → argus_code-0.7.1/dashboard-dist/assets/TimelineTab-Cwp4_Kwm.js +1 -1
  22. argus_code-0.7.0/dashboard-dist/assets/ToolsPage-B8LTs6p5.js → argus_code-0.7.1/dashboard-dist/assets/ToolsPage-1lP1X2_y.js +1 -1
  23. argus_code-0.7.0/dashboard-dist/assets/TrendsPage-8sE0AOTG.js → argus_code-0.7.1/dashboard-dist/assets/TrendsPage-C-GToldA.js +1 -1
  24. argus_code-0.7.1/dashboard-dist/assets/agents-CDuRxAZi.js +1 -0
  25. argus_code-0.7.0/dashboard-dist/assets/index-CpQkAwD7.css → argus_code-0.7.1/dashboard-dist/assets/index-B8TteJkn.css +1 -1
  26. argus_code-0.7.0/dashboard-dist/assets/index-KIvNrQPN.js → argus_code-0.7.1/dashboard-dist/assets/index-kRaX6JLH.js +13 -13
  27. argus_code-0.7.0/dashboard-dist/assets/uplotTheme-Danfgh6n.js → argus_code-0.7.1/dashboard-dist/assets/uplotTheme-Dv4lAb8e.js +1 -1
  28. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/index.html +3 -3
  29. argus_code-0.7.1/pricing/2026-10-26.json +74 -0
  30. {argus_code-0.7.0 → argus_code-0.7.1}/pyproject.toml +3 -3
  31. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/__init__.py +1 -1
  32. {argus_code-0.7.0 → argus_code-0.7.1}/tests/pricing/test_load.py +34 -1
  33. {argus_code-0.7.0 → argus_code-0.7.1}/uv.lock +1 -1
  34. argus_code-0.7.0/dashboard-dist/assets/AlertsPage-BzxuOIP5.js +0 -1
  35. argus_code-0.7.0/dashboard-dist/assets/MultiLine-C0zPyGoR.js +0 -1
  36. argus_code-0.7.0/dashboard-dist/assets/SearchPage-BDwLqLRp.js +0 -1
  37. argus_code-0.7.0/dashboard-dist/assets/agents-DLrqrj4h.js +0 -1
  38. {argus_code-0.7.0 → argus_code-0.7.1}/.gitignore +0 -0
  39. {argus_code-0.7.0 → argus_code-0.7.1}/LICENSE +0 -0
  40. {argus_code-0.7.0 → argus_code-0.7.1}/NOTICE +0 -0
  41. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/cumulative-C3-3HW0n.js +0 -0
  42. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  43. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  44. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  45. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  46. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  47. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  48. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  49. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  50. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  51. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  52. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/rollups-Dqiwg3gD.js +0 -0
  53. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/series-BjP-80tt.js +0 -0
  54. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/uplotTheme-D1GxaB_c.css +0 -0
  55. {argus_code-0.7.0 → argus_code-0.7.1}/dashboard-dist/assets/windows-B3y4OLGl.js +0 -0
  56. {argus_code-0.7.0 → argus_code-0.7.1}/pricing/2026-05-02.json +0 -0
  57. {argus_code-0.7.0 → argus_code-0.7.1}/pricing/2026-06-12.json +0 -0
  58. {argus_code-0.7.0 → argus_code-0.7.1}/pricing/2026-09-22.json +0 -0
  59. {argus_code-0.7.0 → argus_code-0.7.1}/pricing/2026-10-04.json +0 -0
  60. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/AGENTS.md +0 -0
  61. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/AGENTS.md +0 -0
  62. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/__init__.py +0 -0
  63. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/base.py +0 -0
  64. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/__init__.py +0 -0
  65. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/adapter.py +0 -0
  66. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/discover.py +0 -0
  67. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/extract_tool_calls.py +0 -0
  68. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/extract_transcript.py +0 -0
  69. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/extract_turns.py +0 -0
  70. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/history_jsonl.py +0 -0
  71. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/ingest_file.py +0 -0
  72. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/model.py +0 -0
  73. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/claude_code/schemas.py +0 -0
  74. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/codex/__init__.py +0 -0
  75. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/codex/adapter.py +0 -0
  76. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/codex/discover.py +0 -0
  77. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/codex/ingest_file.py +0 -0
  78. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/codex/lines.py +0 -0
  79. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/codex/records.py +0 -0
  80. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/codex/state.py +0 -0
  81. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/adapters/registry.py +0 -0
  82. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/cli.py +0 -0
  83. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/AGENTS.md +0 -0
  84. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/__init__.py +0 -0
  85. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/aggregate.py +0 -0
  86. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/first_run.py +0 -0
  87. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/pipeline.py +0 -0
  88. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/rollup_subagents.py +0 -0
  89. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/scheduler.py +0 -0
  90. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/search_backfill.py +0 -0
  91. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/session_files.py +0 -0
  92. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/collector/watcher.py +0 -0
  93. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/core/__init__.py +0 -0
  94. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/core/runtime.py +0 -0
  95. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/daemon/__init__.py +0 -0
  96. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/daemon/logging.py +0 -0
  97. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/daemon/pidfile.py +0 -0
  98. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/daemon/process.py +0 -0
  99. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/daemon/service.py +0 -0
  100. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/detectors/__init__.py +0 -0
  101. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/detectors/base.py +0 -0
  102. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/detectors/cache_hit_drop.py +0 -0
  103. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/detectors/cost_spike.py +0 -0
  104. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/detectors/registry.py +0 -0
  105. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/detectors/tool_error_rate_spike.py +0 -0
  106. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/pricing/__init__.py +0 -0
  107. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/pricing/compute.py +0 -0
  108. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/pricing/load.py +0 -0
  109. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/pricing/refresh.py +0 -0
  110. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/pricing/types.py +0 -0
  111. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/scaffold/__init__.py +0 -0
  112. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/scaffold/scaffolder.py +0 -0
  113. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/scaffold/snapshot.py +0 -0
  114. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/scaffold/storage.py +0 -0
  115. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/schema/__init__.py +0 -0
  116. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/schema/types.py +0 -0
  117. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/server/AGENTS.md +0 -0
  118. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/server/__init__.py +0 -0
  119. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/server/api.py +0 -0
  120. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/server/app.py +0 -0
  121. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/store/AGENTS.md +0 -0
  122. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/store/__init__.py +0 -0
  123. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/store/db.py +0 -0
  124. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/store/migrations/__init__.py +0 -0
  125. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/store/migrations/inline.py +0 -0
  126. {argus_code-0.7.0 → argus_code-0.7.1}/python/argus/store/repository.py +0 -0
  127. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/agents/code-reviewer.md +0 -0
  128. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/agents/security-auditor.md +0 -0
  129. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/commands/commit.md +0 -0
  130. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/commands/deploy.md +0 -0
  131. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/commands/fix-issue.md +0 -0
  132. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/commands/pr.md +0 -0
  133. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/commands/review.md +0 -0
  134. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/rules/api-conventions.md +0 -0
  135. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/rules/code-style.md +0 -0
  136. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/rules/testing.md +0 -0
  137. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/settings.json +0 -0
  138. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/.claude/skills/example/SKILL.md +0 -0
  139. {argus_code-0.7.0 → argus_code-0.7.1}/templates/default/CLAUDE.md +0 -0
  140. {argus_code-0.7.0 → argus_code-0.7.1}/tests/AGENTS.md +0 -0
  141. {argus_code-0.7.0 → argus_code-0.7.1}/tests/__init__.py +0 -0
  142. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/__init__.py +0 -0
  143. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/__init__.py +0 -0
  144. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_adapter.py +0 -0
  145. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_discover.py +0 -0
  146. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_extract_tool_calls.py +0 -0
  147. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_extract_transcript.py +0 -0
  148. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_extract_turns.py +0 -0
  149. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_history_jsonl.py +0 -0
  150. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_ingest_file.py +0 -0
  151. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_integration.py +0 -0
  152. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_model.py +0 -0
  153. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_path_containment.py +0 -0
  154. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/claude_code/test_schemas.py +0 -0
  155. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/__init__.py +0 -0
  156. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/test_adapter.py +0 -0
  157. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/test_discover.py +0 -0
  158. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/test_ingest_file.py +0 -0
  159. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/test_lines.py +0 -0
  160. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/test_real_root.py +0 -0
  161. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/test_records.py +0 -0
  162. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/codex/test_state.py +0 -0
  163. {argus_code-0.7.0 → argus_code-0.7.1}/tests/adapters/test_registry.py +0 -0
  164. {argus_code-0.7.0 → argus_code-0.7.1}/tests/cli/__init__.py +0 -0
  165. {argus_code-0.7.0 → argus_code-0.7.1}/tests/cli/test_indexing_cli.py +0 -0
  166. {argus_code-0.7.0 → argus_code-0.7.1}/tests/cli/test_pricing_refresh_cli.py +0 -0
  167. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/__init__.py +0 -0
  168. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_aggregate.py +0 -0
  169. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_codex_incremental_invariant.py +0 -0
  170. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_first_run.py +0 -0
  171. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_first_run_shutdown.py +0 -0
  172. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_fork_dedup.py +0 -0
  173. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_fork_dedup_db.py +0 -0
  174. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_incremental_invariant.py +0 -0
  175. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_incremental_repairs.py +0 -0
  176. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_pipeline.py +0 -0
  177. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_pipeline_codex.py +0 -0
  178. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_rollup_subagents.py +0 -0
  179. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_scheduler.py +0 -0
  180. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_session_files.py +0 -0
  181. {argus_code-0.7.0 → argus_code-0.7.1}/tests/collector/test_watcher.py +0 -0
  182. {argus_code-0.7.0 → argus_code-0.7.1}/tests/conftest.py +0 -0
  183. {argus_code-0.7.0 → argus_code-0.7.1}/tests/core/__init__.py +0 -0
  184. {argus_code-0.7.0 → argus_code-0.7.1}/tests/core/test_runtime.py +0 -0
  185. {argus_code-0.7.0 → argus_code-0.7.1}/tests/core/test_runtime_shutdown.py +0 -0
  186. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/__init__.py +0 -0
  187. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_logs.py +0 -0
  188. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_no_claude_dir.py +0 -0
  189. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_pidfile.py +0 -0
  190. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_pidfile_identity.py +0 -0
  191. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_process.py +0 -0
  192. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_service.py +0 -0
  193. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_spawn_safe_path.py +0 -0
  194. {argus_code-0.7.0 → argus_code-0.7.1}/tests/daemon/test_yield.py +0 -0
  195. {argus_code-0.7.0 → argus_code-0.7.1}/tests/dashboard/__init__.py +0 -0
  196. {argus_code-0.7.0 → argus_code-0.7.1}/tests/dashboard/test_no_raw_html.py +0 -0
  197. {argus_code-0.7.0 → argus_code-0.7.1}/tests/detectors/__init__.py +0 -0
  198. {argus_code-0.7.0 → argus_code-0.7.1}/tests/detectors/test_base_helpers.py +0 -0
  199. {argus_code-0.7.0 → argus_code-0.7.1}/tests/detectors/test_cache_hit_drop.py +0 -0
  200. {argus_code-0.7.0 → argus_code-0.7.1}/tests/detectors/test_cost_spike.py +0 -0
  201. {argus_code-0.7.0 → argus_code-0.7.1}/tests/detectors/test_registry.py +0 -0
  202. {argus_code-0.7.0 → argus_code-0.7.1}/tests/detectors/test_tool_error_rate_spike.py +0 -0
  203. {argus_code-0.7.0 → argus_code-0.7.1}/tests/pricing/__init__.py +0 -0
  204. {argus_code-0.7.0 → argus_code-0.7.1}/tests/pricing/test_compute.py +0 -0
  205. {argus_code-0.7.0 → argus_code-0.7.1}/tests/pricing/test_refresh.py +0 -0
  206. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/__init__.py +0 -0
  207. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/test_bundled_template.py +0 -0
  208. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/test_cli_claude.py +0 -0
  209. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/test_scaffold_containment.py +0 -0
  210. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/test_scaffolder.py +0 -0
  211. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/test_snapshot.py +0 -0
  212. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/test_snapshot_secrets.py +0 -0
  213. {argus_code-0.7.0 → argus_code-0.7.1}/tests/scaffold/test_storage.py +0 -0
  214. {argus_code-0.7.0 → argus_code-0.7.1}/tests/schema/__init__.py +0 -0
  215. {argus_code-0.7.0 → argus_code-0.7.1}/tests/schema/test_types.py +0 -0
  216. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/__init__.py +0 -0
  217. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_api.py +0 -0
  218. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_api_search.py +0 -0
  219. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_day_buckets.py +0 -0
  220. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_param_bounds.py +0 -0
  221. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_read_cache.py +0 -0
  222. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_server.py +0 -0
  223. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_spa_fallback.py +0 -0
  224. {argus_code-0.7.0 → argus_code-0.7.1}/tests/server/test_week_of.py +0 -0
  225. {argus_code-0.7.0 → argus_code-0.7.1}/tests/store/__init__.py +0 -0
  226. {argus_code-0.7.0 → argus_code-0.7.1}/tests/store/test_db.py +0 -0
  227. {argus_code-0.7.0 → argus_code-0.7.1}/tests/store/test_repository.py +0 -0
  228. {argus_code-0.7.0 → argus_code-0.7.1}/tests/store/test_transactions.py +0 -0
  229. {argus_code-0.7.0 → argus_code-0.7.1}/tests/test_e2e.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: argus-code
3
- Version: 0.7.0
4
- Summary: Local-first dashboard for Claude Code cost, token, tool-usage, and full-text search analytics
3
+ Version: 0.7.1
4
+ Summary: Local-first observability for Claude Code and OpenAI Codex: per-session forensics, cost, tokens, tool health, sub-agents, alerts and full-text search
5
5
  Project-URL: Homepage, https://github.com/KrishBhimani/argus-code
6
6
  Project-URL: Repository, https://github.com/KrishBhimani/argus-code.git
7
7
  Project-URL: Issues, https://github.com/KrishBhimani/argus-code/issues
@@ -29,7 +29,7 @@ License: MIT License
29
29
  SOFTWARE.
30
30
  License-File: LICENSE
31
31
  License-File: NOTICE
32
- Keywords: ai-tools,analytics,anthropic,claude,claude-code,cli,cost,dashboard,llm,local-first,tokens,usage
32
+ Keywords: ai-tools,analytics,anthropic,claude,claude-code,cli,codex,cost,dashboard,llm,local-first,openai,tokens,usage
33
33
  Classifier: Development Status :: 4 - Beta
34
34
  Classifier: Environment :: Console
35
35
  Classifier: Environment :: Web Environment
@@ -56,7 +56,7 @@ Description-Content-Type: text/markdown
56
56
 
57
57
  <h1>Argus</h1>
58
58
 
59
- <p><strong>The observability console for Claude Code — local-first, permanent, and honest about cost.</strong></p>
59
+ <p><strong>The observability console for Claude Code and Codex — local-first, permanent, and honest about cost.</strong></p>
60
60
 
61
61
  <p>
62
62
  <a href="#-quick-start"><b>Quick start</b></a> ·
@@ -77,12 +77,12 @@ Description-Content-Type: text/markdown
77
77
 
78
78
  </div>
79
79
 
80
- Claude Code writes a detailed transcript of every session to `~/.claude/` — every turn,
81
- every token, every tool call, every sub-agent it spawned — and then tells you almost
82
- nothing about it. Argus tails those files into a SQLite archive on your machine, prices
83
- each turn, and serves a dashboard at `http://localhost:4242` that answers the questions
84
- the transcripts never do: *what am I spending, where did it go, and which turn made it
85
- so?*
80
+ Claude Code and OpenAI Codex write a detailed transcript of every session to disk
81
+ (`~/.claude/`, `~/.codex/`) — every turn, every token, every tool call, every sub-agent
82
+ they spawned — and then tell you almost nothing about it. Argus tails those files into
83
+ a SQLite archive on your machine, prices each turn, and serves a dashboard at
84
+ `http://localhost:4242` that answers the questions the transcripts never do: *what am I
85
+ spending, where did it go, and which turn made it so?*
86
86
 
87
87
  Nothing leaves your computer. No telemetry, no API calls, no embeddings — SQLite and a
88
88
  static web app, bound to `127.0.0.1`.
@@ -100,13 +100,14 @@ Your browser opens once the first pass finishes (5–10 s for a typical install)
100
100
  then on, every session you run is ingested live. All you need is Python ≥ 3.11 and a
101
101
  `~/.claude/` directory or a Codex home — i.e. you've used Claude Code or Codex at least once.
102
102
 
103
- **Codex too.** Argus also reads OpenAI Codex rollouts from `$CODEX_HOME` (default
104
- `~/.codex`; only `sessions/` and `archived_sessions/` are read — never `auth.json`,
105
- config or state databases). Codex sessions get the same treatment: per-response
106
- turns and estimated cost (OpenAI's standard-tier API rates; Codex plans are usually
107
- billed differently, so treat it as an API-equivalent figure), tool health, and
108
- sub-agents folded under their parent thread. With both agents present the Sessions
109
- page gains an agent filter and column.
103
+ **Supported agents.** Argus detects whichever you use, no configuration needed:
104
+
105
+ | Agent | Reads from | Notes |
106
+ |---|---|---|
107
+ | **Claude Code** | `~/.claude/` (session transcripts under `projects/`, prompt history) | Sessions, sub-agents and your typed prompts. |
108
+ | **OpenAI Codex** | `$CODEX_HOME` (default `~/.codex`) — only `sessions/` and `archived_sessions/` | Never opens `auth.json`, config or state databases. Costs use OpenAI's standard-tier API rates — an API-equivalent figure, since Codex plans are usually billed by subscription. |
109
+
110
+ Use both and the Sessions page gains an agent filter and column.
110
111
 
111
112
  ## ✨ Why Argus
112
113
 
@@ -149,8 +150,8 @@ chronological thread.
149
150
 
150
151
  When a session delegates to sub-agents, Argus keeps each one: the **task as it was
151
152
  given**, its tools, tokens, cost, shape and full timeline — with an at-a-glance strip
152
- that turns red where an agent failed. No more guessing what that `Task` call actually
153
- did.
153
+ that turns red where an agent failed. No more guessing what that `Task` or
154
+ `spawn_agent` call actually did.
154
155
 
155
156
  <img src="https://raw.githubusercontent.com/KrishBhimani/argus-code/main/assets/screenshots/subagents.png" alt="Sub-agents — task given, tools used, per-agent shape and cost">
156
157
 
@@ -290,9 +291,9 @@ Vulnerability reports: [SECURITY.md](./SECURITY.md).
290
291
 
291
292
  ## ⚙️ How it works
292
293
 
293
- 1. **Ingest.** A `watchdog` observer tails `~/.claude/projects/<project>/<session>.jsonl`. Lines are validated with `pydantic`, de-duplicated by `message.id`, and normalised into session / turn rows in SQLite (WAL mode). Resumed sessions and sub-agent files are folded into their parent.
294
- 2. **Cost.** Per-turn cost comes from a bundled price table sourced from [LiteLLM](https://github.com/BerriAI/litellm). Tokens are exact; costs are estimates.
295
- 3. **Tools.** Each `tool_use` block becomes a row; errors come from the matching `tool_result`. MCP servers are parsed from `mcp__<server>__<tool>`; the `Agent` tool's `subagent_type` is kept so delegation is visible.
294
+ 1. **Ingest.** A `watchdog` observer tails each agent's transcripts through a per-agent adapter — Claude Code's `~/.claude/projects/<project>/<session>.jsonl` and Codex's rollouts under `$CODEX_HOME/sessions/`. Lines are validated, de-duplicated by the agent's own ids (Claude's `message.id`, Codex's `response_id`), and normalised into session / turn rows in SQLite (WAL mode). Resumed or continued sessions and sub-agent files are folded into their parent.
295
+ 2. **Cost.** Per-turn cost comes from a bundled price table (Anthropic's and OpenAI's published rates; `argus pricing refresh` can pull [LiteLLM](https://github.com/BerriAI/litellm)'s). Tokens are exact; costs are estimates.
296
+ 3. **Tools.** For Claude Code, each `tool_use` block becomes a row and errors come from the matching `tool_result`; for Codex, each completed action (shell command with its exit code, file change, MCP call, web search, `spawn_agent`) becomes a row, with errors only from explicit failure signals. MCP servers are shown as `mcp__<server>__<tool>`; sub-agent types are kept so delegation is visible.
296
297
  4. **Search (opt-in).** Two FTS5 tables — one over your prompt history, one over transcript text — indexed incrementally during the normal ingest tick.
297
298
  5. **Detection.** A scheduler runs registered *detectors* every 10 minutes; findings land in an alerts inbox with a seen / resolved lifecycle, so an issue that recovers and recurs fires again instead of staying silent.
298
299
  6. **Dashboard.** A Vite + React single-page app (uPlot and hand-drawn SVG charts), statically built and served by the FastAPI app. No Node at runtime, no network beyond `/api/*`.
@@ -330,7 +331,7 @@ Argus keeps its own copy regardless — this only widens what Claude itself reta
330
331
  git clone https://github.com/KrishBhimani/argus-code.git
331
332
  cd argus-code
332
333
  uv sync # install deps + create venv
333
- uv run pytest # ~490 tests, ~35 s
334
+ uv run pytest # ~700 tests, ~45 s
334
335
  uv run argus start # runs directly from source
335
336
  ```
336
337
 
@@ -373,6 +374,6 @@ tests/ pytest suite, mirrors python/argus/ layout
373
374
 
374
375
  <p><i>Named for Argus Panoptes — the watchman with a hundred eyes, who never slept.</i></p>
375
376
 
376
- <p>If it keeps good watch for you, a ⭐ helps other Claude Code users find it.</p>
377
+ <p>If it keeps good watch for you, a ⭐ helps other Claude Code and Codex users find it.</p>
377
378
 
378
379
  </div>
@@ -4,7 +4,7 @@
4
4
 
5
5
  <h1>Argus</h1>
6
6
 
7
- <p><strong>The observability console for Claude Code — local-first, permanent, and honest about cost.</strong></p>
7
+ <p><strong>The observability console for Claude Code and Codex — local-first, permanent, and honest about cost.</strong></p>
8
8
 
9
9
  <p>
10
10
  <a href="#-quick-start"><b>Quick start</b></a> ·
@@ -25,12 +25,12 @@
25
25
 
26
26
  </div>
27
27
 
28
- Claude Code writes a detailed transcript of every session to `~/.claude/` — every turn,
29
- every token, every tool call, every sub-agent it spawned — and then tells you almost
30
- nothing about it. Argus tails those files into a SQLite archive on your machine, prices
31
- each turn, and serves a dashboard at `http://localhost:4242` that answers the questions
32
- the transcripts never do: *what am I spending, where did it go, and which turn made it
33
- so?*
28
+ Claude Code and OpenAI Codex write a detailed transcript of every session to disk
29
+ (`~/.claude/`, `~/.codex/`) — every turn, every token, every tool call, every sub-agent
30
+ they spawned — and then tell you almost nothing about it. Argus tails those files into
31
+ a SQLite archive on your machine, prices each turn, and serves a dashboard at
32
+ `http://localhost:4242` that answers the questions the transcripts never do: *what am I
33
+ spending, where did it go, and which turn made it so?*
34
34
 
35
35
  Nothing leaves your computer. No telemetry, no API calls, no embeddings — SQLite and a
36
36
  static web app, bound to `127.0.0.1`.
@@ -48,13 +48,14 @@ Your browser opens once the first pass finishes (5–10 s for a typical install)
48
48
  then on, every session you run is ingested live. All you need is Python ≥ 3.11 and a
49
49
  `~/.claude/` directory or a Codex home — i.e. you've used Claude Code or Codex at least once.
50
50
 
51
- **Codex too.** Argus also reads OpenAI Codex rollouts from `$CODEX_HOME` (default
52
- `~/.codex`; only `sessions/` and `archived_sessions/` are read — never `auth.json`,
53
- config or state databases). Codex sessions get the same treatment: per-response
54
- turns and estimated cost (OpenAI's standard-tier API rates; Codex plans are usually
55
- billed differently, so treat it as an API-equivalent figure), tool health, and
56
- sub-agents folded under their parent thread. With both agents present the Sessions
57
- page gains an agent filter and column.
51
+ **Supported agents.** Argus detects whichever you use, no configuration needed:
52
+
53
+ | Agent | Reads from | Notes |
54
+ |---|---|---|
55
+ | **Claude Code** | `~/.claude/` (session transcripts under `projects/`, prompt history) | Sessions, sub-agents and your typed prompts. |
56
+ | **OpenAI Codex** | `$CODEX_HOME` (default `~/.codex`) — only `sessions/` and `archived_sessions/` | Never opens `auth.json`, config or state databases. Costs use OpenAI's standard-tier API rates — an API-equivalent figure, since Codex plans are usually billed by subscription. |
57
+
58
+ Use both and the Sessions page gains an agent filter and column.
58
59
 
59
60
  ## ✨ Why Argus
60
61
 
@@ -97,8 +98,8 @@ chronological thread.
97
98
 
98
99
  When a session delegates to sub-agents, Argus keeps each one: the **task as it was
99
100
  given**, its tools, tokens, cost, shape and full timeline — with an at-a-glance strip
100
- that turns red where an agent failed. No more guessing what that `Task` call actually
101
- did.
101
+ that turns red where an agent failed. No more guessing what that `Task` or
102
+ `spawn_agent` call actually did.
102
103
 
103
104
  <img src="https://raw.githubusercontent.com/KrishBhimani/argus-code/main/assets/screenshots/subagents.png" alt="Sub-agents — task given, tools used, per-agent shape and cost">
104
105
 
@@ -238,9 +239,9 @@ Vulnerability reports: [SECURITY.md](./SECURITY.md).
238
239
 
239
240
  ## ⚙️ How it works
240
241
 
241
- 1. **Ingest.** A `watchdog` observer tails `~/.claude/projects/<project>/<session>.jsonl`. Lines are validated with `pydantic`, de-duplicated by `message.id`, and normalised into session / turn rows in SQLite (WAL mode). Resumed sessions and sub-agent files are folded into their parent.
242
- 2. **Cost.** Per-turn cost comes from a bundled price table sourced from [LiteLLM](https://github.com/BerriAI/litellm). Tokens are exact; costs are estimates.
243
- 3. **Tools.** Each `tool_use` block becomes a row; errors come from the matching `tool_result`. MCP servers are parsed from `mcp__<server>__<tool>`; the `Agent` tool's `subagent_type` is kept so delegation is visible.
242
+ 1. **Ingest.** A `watchdog` observer tails each agent's transcripts through a per-agent adapter — Claude Code's `~/.claude/projects/<project>/<session>.jsonl` and Codex's rollouts under `$CODEX_HOME/sessions/`. Lines are validated, de-duplicated by the agent's own ids (Claude's `message.id`, Codex's `response_id`), and normalised into session / turn rows in SQLite (WAL mode). Resumed or continued sessions and sub-agent files are folded into their parent.
243
+ 2. **Cost.** Per-turn cost comes from a bundled price table (Anthropic's and OpenAI's published rates; `argus pricing refresh` can pull [LiteLLM](https://github.com/BerriAI/litellm)'s). Tokens are exact; costs are estimates.
244
+ 3. **Tools.** For Claude Code, each `tool_use` block becomes a row and errors come from the matching `tool_result`; for Codex, each completed action (shell command with its exit code, file change, MCP call, web search, `spawn_agent`) becomes a row, with errors only from explicit failure signals. MCP servers are shown as `mcp__<server>__<tool>`; sub-agent types are kept so delegation is visible.
244
245
  4. **Search (opt-in).** Two FTS5 tables — one over your prompt history, one over transcript text — indexed incrementally during the normal ingest tick.
245
246
  5. **Detection.** A scheduler runs registered *detectors* every 10 minutes; findings land in an alerts inbox with a seen / resolved lifecycle, so an issue that recovers and recurs fires again instead of staying silent.
246
247
  6. **Dashboard.** A Vite + React single-page app (uPlot and hand-drawn SVG charts), statically built and served by the FastAPI app. No Node at runtime, no network beyond `/api/*`.
@@ -278,7 +279,7 @@ Argus keeps its own copy regardless — this only widens what Claude itself reta
278
279
  git clone https://github.com/KrishBhimani/argus-code.git
279
280
  cd argus-code
280
281
  uv sync # install deps + create venv
281
- uv run pytest # ~490 tests, ~35 s
282
+ uv run pytest # ~700 tests, ~45 s
282
283
  uv run argus start # runs directly from source
283
284
  ```
284
285
 
@@ -321,6 +322,6 @@ tests/ pytest suite, mirrors python/argus/ layout
321
322
 
322
323
  <p><i>Named for Argus Panoptes — the watchman with a hundred eyes, who never slept.</i></p>
323
324
 
324
- <p>If it keeps good watch for you, a ⭐ helps other Claude Code users find it.</p>
325
+ <p>If it keeps good watch for you, a ⭐ helps other Claude Code and Codex users find it.</p>
325
326
 
326
327
  </div>
@@ -0,0 +1 @@
1
+ import{j as e,g as y,h as N,r as h}from"./index-kRaX6JLH.js";import{T as u,a as g,P as p}from"./Panel-rzVYig0L.js";import{E as k,S as _}from"./ErrorPanel-lb1Tt_Cg.js";import{B as v,P as f}from"./Button-BY-h2O0Z.js";import{a as d}from"./AttentionStrip-DQUV5LTN.js";const $={info:"#3987e5",warning:"#fab219",critical:"#d03b3b"};function A({alerts:s,days:a=30,end:n=new Date,className:m=""}){const c=n.getTime(),l=c-a*864e5;return e.jsxs("svg",{className:`block w-full ${m}`,width:"100%",viewBox:"0 0 300 36",style:{aspectRatio:"300 / 36"},role:"img","aria-label":`Alerts, last ${a} days`,children:[e.jsx("line",{x1:0,y1:36/2,x2:300,y2:36/2,stroke:"#232934"}),s.filter(r=>r.at>=l&&r.at<=c).map((r,t)=>e.jsx("circle",{cx:(r.at-l)/(c-l)*292+4,cy:36/2,r:r.severity==="critical"?5:r.severity==="warning"?4:3,fill:$[r.severity],stroke:"#10131a",strokeWidth:2,children:e.jsx("title",{children:`${new Date(r.at).toLocaleDateString()} · ${r.severity}`})},t)),e.jsx("text",{x:0,y:34,fontSize:9,fill:"#667184",fontFamily:"var(--font-mono)",children:`-${a}d`}),e.jsx("text",{x:300,y:34,fontSize:9,fill:"#667184",textAnchor:"end",fontFamily:"var(--font-mono)",children:"now"})]})}const C={info:"info",warning:"warn",critical:"crit"},S={info:"shadow-[inset_3px_0_0_var(--color-s1)]",warning:"shadow-[inset_3px_0_0_var(--color-warn)]",critical:"shadow-[inset_3px_0_0_var(--color-crit)]"},w=({children:s})=>e.jsx("span",{className:"font-mono text-[11px] text-ink-1 bg-bg-3 px-1.5 rounded-sm",children:s}),D=[{n:"tool_error_rate_spike",on:!0,note:"7d vs 28d"},{n:"cost_spike",on:!0,note:"7d vs 28d/wk"},{n:"cache_hit_drop",on:!0,note:"7d vs 28d"}],E=s=>{const a=typeof s.metadata?.tool_name=="string"?s.metadata.tool_name:null,n=typeof s.metadata?.project=="string"?s.metadata.project:null;return[a&&`tool=${a}`,n&&`project=${n}`].filter(Boolean)};function z(){const s=y(),a=N(),[n,m]=h.useState("unseen"),i=h.useMemo(()=>new Set((s.data??[]).filter(t=>!t.seen_at).map(t=>t.id)),[s.data]),o=h.useMemo(()=>[...s.data??[]].sort((t,x)=>d(x).localeCompare(d(t))),[s.data]),c=n==="all"?o:n==="unseen"?o.filter(t=>i.has(t.id)):o.filter(t=>t.severity===n),l=o.filter(t=>Date.now()-new Date(d(t)).getTime()<30*864e5),r=t=>d(t)?new Date(d(t)).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}):"";return s.error?e.jsxs(e.Fragment,{children:[e.jsx(u,{crumbs:["Monitor","Alerts"]}),e.jsx(g,{children:e.jsx(k,{error:s.error})})]}):e.jsxs(e.Fragment,{children:[e.jsxs(u,{crumbs:["Monitor","Alerts"],children:[e.jsx(_,{options:[{value:"unseen",label:`Unseen · ${i.size}`},{value:"all",label:`All · ${o.length}`},{value:"warning",label:"Warning"},{value:"critical",label:"Critical"}],value:n,onChange:m}),e.jsx(v,{variant:"ghost",disabled:!i.size,onClick:()=>i.forEach(t=>a.mutate(t)),children:"Mark all seen"})]}),e.jsxs(g,{row:!0,children:[e.jsxs(p,{padded:!1,className:"flex-1 self-start",children:[c.length===0&&e.jsxs("div",{className:"text-center text-ink-2 py-10 flex items-center justify-center gap-2",children:[e.jsx(f,{kind:"good",children:"ALL CLEAR"}),"nothing ",n==="all"?"recorded":n]}),c.map(t=>{const x=!i.has(t.id),b=E(t);return e.jsxs("div",{className:`flex items-start gap-3.5 p-3.5 border-b border-line ${x?"opacity-70":S[t.severity]}`,children:[e.jsx(f,{kind:C[t.severity],className:"mt-px",children:t.severity.toUpperCase()}),e.jsxs("div",{className:"flex flex-col gap-1 flex-1 min-w-0",children:[e.jsx("span",{className:"font-semibold",children:t.title}),e.jsx("span",{className:"text-ink-1",children:t.message}),e.jsxs("div",{className:"flex gap-2 mt-1.5 items-center",children:[e.jsx(w,{children:t.detector}),b.map(j=>e.jsx(w,{children:j},j))]})]}),e.jsxs("div",{className:"flex flex-col items-end gap-2",children:[e.jsx("span",{className:"font-mono text-[11px] text-ink-2 whitespace-nowrap",children:r(t)}),x?e.jsx(f,{kind:"mute",children:"seen"}):e.jsx(v,{size:"sm",onClick:()=>a.mutate(t.id),children:"Mark seen"})]})]},t.id)})]}),e.jsxs("div",{className:"w-[300px] shrink-0 flex flex-col gap-3",children:[e.jsx(p,{title:"Detectors",sub:"run after each ingest",padded:!1,children:D.map(t=>e.jsxs("div",{className:`flex items-center gap-2.5 px-3.5 py-2.5 border-b border-line last:border-b-0 ${t.on?"":"text-ink-2"}`,children:[e.jsx("span",{className:`w-[7px] h-[7px] rounded-full ${t.on?"bg-good":"border border-line-2"}`}),e.jsx("span",{className:"font-mono text-[11.5px]",children:t.n}),e.jsxs("span",{className:`ml-auto font-mono text-[11px] ${t.on?"text-good":""}`,children:[t.on?"on":"off"," · ",t.note]})]},t.n))}),e.jsxs(p,{title:"Last 30 days",children:[e.jsx(A,{alerts:l.map(t=>({at:new Date(d(t)).getTime(),severity:t.severity}))}),e.jsxs("div",{className:"flex flex-col gap-2 mt-3 text-xs",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-ink-1",children:"Alerts raised"}),e.jsx("span",{className:"font-mono num",children:l.length})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-ink-1",children:"Critical"}),e.jsx("span",{className:"font-mono num",children:l.filter(t=>t.severity==="critical").length})]})]})]})]})]})]})}export{z as default};
@@ -1 +1 @@
1
- import{r as f,t as A,j as r}from"./index-KIvNrQPN.js";import{A as h,S as e,h as j,L as w,U as E}from"./uplotTheme-Danfgh6n.js";function v({labels:s,series:o,stacked:l=!1,fill:u=!0,share:m=!1,format:x=A,height:i=220}){const c=f.useMemo(()=>{const t=s.map((n,p)=>p);if(!l)return[t,...o.map(n=>n.values)];const a=Array(s.length).fill(0);return[t,...o.map(n=>n.values.map((p,d)=>a[d]+=p))]},[s,o,l]),g=f.useMemo(()=>({cursor:{points:{size:8}},legend:{show:!1},padding:[8,12,0,0],scales:{x:{time:!1},y:m?{range:[0,1]}:{}},axes:[{...h,values:(t,a)=>a.map(n=>n==null?"":s[n]??"")},{...h,size:52,values:(t,a)=>a.map(n=>n==null?"":m?`${Math.round(n*100)}%`:x(n))}],series:[{},...o.map((t,a)=>({label:t.name,stroke:e[a%e.length],width:2,points:{show:!1},fill:u?j(e[a%e.length],l?.35:.1):void 0,...l&&a>0?{band:!0}:{}}))]}),[s,o,l,u,m,x]);return r.jsxs("div",{className:"flex flex-col gap-2 min-w-0",children:[o.length>=2&&r.jsx(w,{names:o.map(t=>t.name),colors:o.map((t,a)=>e[a%e.length])}),r.jsx(E,{options:g,data:c,height:i})]})}export{v as A};
1
+ import{r as f,t as A,j as r}from"./index-kRaX6JLH.js";import{A as h,S as e,h as j,L as w,U as E}from"./uplotTheme-Dv4lAb8e.js";function v({labels:s,series:o,stacked:l=!1,fill:u=!0,share:m=!1,format:x=A,height:i=220}){const c=f.useMemo(()=>{const t=s.map((n,p)=>p);if(!l)return[t,...o.map(n=>n.values)];const a=Array(s.length).fill(0);return[t,...o.map(n=>n.values.map((p,d)=>a[d]+=p))]},[s,o,l]),g=f.useMemo(()=>({cursor:{points:{size:8}},legend:{show:!1},padding:[8,12,0,0],scales:{x:{time:!1},y:m?{range:[0,1]}:{}},axes:[{...h,values:(t,a)=>a.map(n=>n==null?"":s[n]??"")},{...h,size:52,values:(t,a)=>a.map(n=>n==null?"":m?`${Math.round(n*100)}%`:x(n))}],series:[{},...o.map((t,a)=>({label:t.name,stroke:e[a%e.length],width:2,points:{show:!1},fill:u?j(e[a%e.length],l?.35:.1):void 0,...l&&a>0?{band:!0}:{}}))]}),[s,o,l,u,m,x]);return r.jsxs("div",{className:"flex flex-col gap-2 min-w-0",children:[o.length>=2&&r.jsx(w,{names:o.map(t=>t.name),colors:o.map((t,a)=>e[a%e.length])}),r.jsx(E,{options:g,data:c,height:i})]})}export{v as A};
@@ -1 +1 @@
1
- import{h as p,g as x,i as m,j as e,s as i,L as h}from"./index-KIvNrQPN.js";import{P as j}from"./Panel-D9OW_N0O.js";import{P as l,B as u}from"./Button-D2qCw3Bg.js";const f={info:"info",warning:"warn",critical:"crit"},n=t=>t.created_at??t.first_seen_at??"";function N(){const t=p().data??[],o=x().data??[],c=m(),r=t.slice(0,3),a=[...o].sort((s,d)=>n(d).localeCompare(n(s)))[0];return e.jsx(j,{title:"Needs attention",sub:`${t.length} unseen`,right:e.jsx(h,{to:"/alerts",className:"text-[11px]",children:"All alerts →"}),padded:!1,children:r.length===0?e.jsxs("div",{className:"flex items-center gap-3 px-3.5 py-2.5 text-ink-1",children:[e.jsx(l,{kind:"good",children:"ALL CLEAR"}),a?e.jsxs("span",{children:["last alert ",i(n(a)),": ",a.title]}):e.jsx("span",{children:"no alerts recorded yet"})]}):r.map(s=>e.jsxs("div",{className:"flex items-center gap-3 px-3.5 py-2.5 border-b border-line last:border-b-0 min-w-0",children:[e.jsx(l,{kind:f[s.severity],children:s.severity.toUpperCase()}),e.jsx("span",{className:"font-medium whitespace-nowrap",children:s.title}),e.jsx("span",{className:"text-ink-1 truncate",children:s.message}),e.jsx("span",{className:"ml-auto font-mono text-[11px] text-ink-1 bg-bg-3 px-1.5 rounded-sm whitespace-nowrap",children:s.detector}),e.jsx("span",{className:"font-mono text-[11px] text-ink-2 whitespace-nowrap",children:n(s)?i(n(s)):""}),e.jsx(u,{size:"sm",variant:"ghost",onClick:()=>c.mutate(s.id),children:"Mark seen"})]},s.id))})}export{N as A,n as a};
1
+ import{i as p,g as x,h as m,j as e,s as i,L as h}from"./index-kRaX6JLH.js";import{P as j}from"./Panel-rzVYig0L.js";import{P as l,B as u}from"./Button-BY-h2O0Z.js";const f={info:"info",warning:"warn",critical:"crit"},n=t=>t.created_at??t.first_seen_at??"";function N(){const t=p().data??[],o=x().data??[],c=m(),r=t.slice(0,3),a=[...o].sort((s,d)=>n(d).localeCompare(n(s)))[0];return e.jsx(j,{title:"Needs attention",sub:`${t.length} unseen`,right:e.jsx(h,{to:"/alerts",className:"text-[11px]",children:"All alerts →"}),padded:!1,children:r.length===0?e.jsxs("div",{className:"flex items-center gap-3 px-3.5 py-2.5 text-ink-1",children:[e.jsx(l,{kind:"good",children:"ALL CLEAR"}),a?e.jsxs("span",{children:["last alert ",i(n(a)),": ",a.title]}):e.jsx("span",{children:"no alerts recorded yet"})]}):r.map(s=>e.jsxs("div",{className:"flex items-center gap-3 px-3.5 py-2.5 border-b border-line last:border-b-0 min-w-0",children:[e.jsx(l,{kind:f[s.severity],children:s.severity.toUpperCase()}),e.jsx("span",{className:"font-medium whitespace-nowrap",children:s.title}),e.jsx("span",{className:"text-ink-1 truncate",children:s.message}),e.jsx("span",{className:"ml-auto font-mono text-[11px] text-ink-1 bg-bg-3 px-1.5 rounded-sm whitespace-nowrap",children:s.detector}),e.jsx("span",{className:"font-mono text-[11px] text-ink-2 whitespace-nowrap",children:n(s)?i(n(s)):""}),e.jsx(u,{size:"sm",variant:"ghost",onClick:()=>c.mutate(s.id),children:"Mark seen"})]},s.id))})}export{N as A,n as a};
@@ -1 +1 @@
1
- import{j as s,t as o,I as m}from"./index-KIvNrQPN.js";function d({rows:a,format:n=o,max:l,color:r="var(--color-s1)",className:i=""}){const t=l??Math.max(1,...a.map(e=>e.value));return s.jsx("div",{className:`flex flex-col gap-2.5 ${i}`,children:a.map(e=>s.jsxs("div",{className:"grid grid-cols-[minmax(0,200px)_1fr_auto] items-center gap-3 text-xs",children:[s.jsx("span",{className:"font-mono text-ink-0 truncate",title:e.name,children:e.name}),s.jsxs("div",{className:"relative h-1.5 rounded-sm bg-bg-3 overflow-hidden",children:[s.jsx("i",{"data-testid":"bar-fill",className:"absolute inset-y-0 left-0 rounded-r-sm",style:{width:`${e.value/t*100}%`,background:r}}),e.error?s.jsx("i",{"data-testid":"bar-error",className:"absolute inset-y-0 left-0",style:{width:`${e.error/t*100}%`,background:"var(--color-crit)"}}):null]}),s.jsxs("span",{className:"font-mono num text-ink-1 text-right min-w-16",children:[n(e.value),e.error?s.jsxs("span",{className:"text-crit-ink ml-2 inline-flex items-center gap-0.5",children:[s.jsx(m,{name:"x",size:9}),e.error]}):null]})]},e.name))})}export{d as B};
1
+ import{j as s,t as o,I as m}from"./index-kRaX6JLH.js";function d({rows:a,format:n=o,max:l,color:r="var(--color-s1)",className:i=""}){const t=l??Math.max(1,...a.map(e=>e.value));return s.jsx("div",{className:`flex flex-col gap-2.5 ${i}`,children:a.map(e=>s.jsxs("div",{className:"grid grid-cols-[minmax(0,200px)_1fr_auto] items-center gap-3 text-xs",children:[s.jsx("span",{className:"font-mono text-ink-0 truncate",title:e.name,children:e.name}),s.jsxs("div",{className:"relative h-1.5 rounded-sm bg-bg-3 overflow-hidden",children:[s.jsx("i",{"data-testid":"bar-fill",className:"absolute inset-y-0 left-0 rounded-r-sm",style:{width:`${e.value/t*100}%`,background:r}}),e.error?s.jsx("i",{"data-testid":"bar-error",className:"absolute inset-y-0 left-0",style:{width:`${e.error/t*100}%`,background:"var(--color-crit)"}}):null]}),s.jsxs("span",{className:"font-mono num text-ink-1 text-right min-w-16",children:[n(e.value),e.error?s.jsxs("span",{className:"text-crit-ink ml-2 inline-flex items-center gap-0.5",children:[s.jsx(m,{name:"x",size:9}),e.error]}):null]})]},e.name))})}export{d as B};
@@ -1 +1 @@
1
- import{j as o,I as a}from"./index-KIvNrQPN.js";const s={warn:"text-warn bg-warn/10 border-warn/25",crit:"text-crit-ink bg-crit/12 border-crit/30",info:"text-s1 bg-s1/12 border-s1/30",good:"text-good bg-good/12 border-good/30",mute:"text-ink-1 bg-bg-3 border-line-2"},c={warn:"warn",crit:"x",info:"info",good:"check"};function x({kind:t,children:e,icon:r=!0,className:n=""}){const i=c[t];return o.jsxs("span",{className:`inline-flex items-center gap-1.5 h-5 px-2 rounded-sm text-[11px] font-medium font-mono border whitespace-nowrap ${s[t]} ${n}`,children:[r&&i&&o.jsx(a,{name:i,size:11}),e]})}const d={default:"bg-bg-2 border-line-2 text-ink-0 hover:border-accent",primary:"bg-accent border-accent text-[#1a0f06]",ghost:"bg-transparent border-line-2 text-ink-0 hover:border-accent",danger:"bg-transparent border-crit text-crit-ink"};function g({variant:t="default",size:e="md",className:r="",...n}){return o.jsx("button",{type:"button",...n,className:`inline-flex items-center gap-1.5 ${e==="sm"?"h-6 px-2 text-[11px]":"h-7 px-2.5 text-xs"} rounded-md border font-medium whitespace-nowrap disabled:opacity-50 ${d[t]} ${r}`})}export{g as B,x as P};
1
+ import{j as o,I as a}from"./index-kRaX6JLH.js";const s={warn:"text-warn bg-warn/10 border-warn/25",crit:"text-crit-ink bg-crit/12 border-crit/30",info:"text-s1 bg-s1/12 border-s1/30",good:"text-good bg-good/12 border-good/30",mute:"text-ink-1 bg-bg-3 border-line-2"},c={warn:"warn",crit:"x",info:"info",good:"check"};function x({kind:t,children:e,icon:r=!0,className:n=""}){const i=c[t];return o.jsxs("span",{className:`inline-flex items-center gap-1.5 h-5 px-2 rounded-sm text-[11px] font-medium font-mono border whitespace-nowrap ${s[t]} ${n}`,children:[r&&i&&o.jsx(a,{name:i,size:11}),e]})}const d={default:"bg-bg-2 border-line-2 text-ink-0 hover:border-accent",primary:"bg-accent border-accent text-[#1a0f06]",ghost:"bg-transparent border-line-2 text-ink-0 hover:border-accent",danger:"bg-transparent border-crit text-crit-ink"};function g({variant:t="default",size:e="md",className:r="",...n}){return o.jsx("button",{type:"button",...n,className:`inline-flex items-center gap-1.5 ${e==="sm"?"h-6 px-2 text-[11px]":"h-7 px-2.5 text-xs"} rounded-md border font-medium whitespace-nowrap disabled:opacity-50 ${d[t]} ${r}`})}export{g as B,x as P};
@@ -1 +1 @@
1
- import{j as e,r as n}from"./index-KIvNrQPN.js";import{C as o}from"./Chip-BfVZybGP.js";function x({columns:s,rows:a}){return e.jsx("div",{className:"overflow-auto max-h-72",children:e.jsxs("table",{className:"w-full border-collapse",children:[e.jsx("thead",{children:e.jsx("tr",{children:s.map((t,r)=>e.jsx("th",{className:`text-[10px] tracking-[0.08em] text-ink-2 font-medium px-3 py-2 border-b border-line bg-bg-1 sticky top-0 whitespace-nowrap ${r?"text-right":"text-left"}`,children:t},t))})}),e.jsx("tbody",{children:a.map((t,r)=>e.jsx("tr",{children:t.map((l,i)=>e.jsx("td",{className:`px-3 h-8 border-b border-line text-xs whitespace-nowrap ${i?"text-right font-mono num":"font-mono text-ink-1"}`,children:l},i))},r))})]})})}function h({chart:s,table:a}){const[t,r]=n.useState(!1);return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("div",{className:"flex justify-end",children:e.jsx(o,{active:t,onClick:()=>r(!t),children:"Table"})}),t?e.jsx(x,{...a}):s]})}export{h as C,x as a};
1
+ import{j as e,r as n}from"./index-kRaX6JLH.js";import{C as o}from"./Chip-C_zmBEC6.js";function x({columns:s,rows:a}){return e.jsx("div",{className:"overflow-auto max-h-72",children:e.jsxs("table",{className:"w-full border-collapse",children:[e.jsx("thead",{children:e.jsx("tr",{children:s.map((t,r)=>e.jsx("th",{className:`text-[10px] tracking-[0.08em] text-ink-2 font-medium px-3 py-2 border-b border-line bg-bg-1 sticky top-0 whitespace-nowrap ${r?"text-right":"text-left"}`,children:t},t))})}),e.jsx("tbody",{children:a.map((t,r)=>e.jsx("tr",{children:t.map((l,i)=>e.jsx("td",{className:`px-3 h-8 border-b border-line text-xs whitespace-nowrap ${i?"text-right font-mono num":"font-mono text-ink-1"}`,children:l},i))},r))})]})})}function h({chart:s,table:a}){const[t,r]=n.useState(!1);return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("div",{className:"flex justify-end",children:e.jsx(o,{active:t,onClick:()=>r(!t),children:"Table"})}),t?e.jsx(x,{...a}):s]})}export{h as C,x as a};
@@ -1 +1 @@
1
- import{j as t,I as a}from"./index-KIvNrQPN.js";function i({active:e=!1,onClick:n,children:r,caret:s=!1}){return t.jsxs("button",{type:"button",onClick:n,"aria-pressed":e,className:`inline-flex items-center gap-1.5 h-6 px-2 rounded-md border text-[11px] whitespace-nowrap ${e?"border-accent text-accent-ink bg-accent/12":"border-line-2 text-ink-1 bg-bg-2 hover:text-ink-0"}`,children:[r,s&&t.jsx(a,{name:"chevron",size:10})]})}export{i as C};
1
+ import{j as t,I as a}from"./index-kRaX6JLH.js";function i({active:e=!1,onClick:n,children:r,caret:s=!1}){return t.jsxs("button",{type:"button",onClick:n,"aria-pressed":e,className:`inline-flex items-center gap-1.5 h-6 px-2 rounded-md border text-[11px] whitespace-nowrap ${e?"border-accent text-accent-ink bg-accent/12":"border-line-2 text-ink-1 bg-bg-2 hover:text-ink-0"}`,children:[r,s&&t.jsx(a,{name:"chevron",size:10})]})}export{i as C};
@@ -1 +1 @@
1
- import{j as n}from"./index-KIvNrQPN.js";function l({options:e,value:r,onChange:a}){return n.jsx("div",{role:"tablist",className:"inline-flex border border-line-2 rounded-md overflow-hidden font-mono text-[11px]",children:e.map(t=>n.jsx("button",{role:"tab",type:"button","aria-selected":t.value===r,onClick:()=>a(t.value),className:`px-2.5 py-[5px] whitespace-nowrap ${t.value===r?"bg-bg-3 text-ink-0":"text-ink-1 hover:text-ink-0"}`,children:t.label},t.value))})}const s=({error:e})=>n.jsxs("div",{role:"alert",className:"border border-crit/40 bg-crit/8 rounded-md p-3 text-xs text-ink-1",children:[n.jsx("span",{className:"text-crit-ink font-medium",children:"Could not load."})," ",e instanceof Error?e.message:String(e)]});export{s as E,l as S};
1
+ import{j as n}from"./index-kRaX6JLH.js";function l({options:e,value:r,onChange:a}){return n.jsx("div",{role:"tablist",className:"inline-flex border border-line-2 rounded-md overflow-hidden font-mono text-[11px]",children:e.map(t=>n.jsx("button",{role:"tab",type:"button","aria-selected":t.value===r,onClick:()=>a(t.value),className:`px-2.5 py-[5px] whitespace-nowrap ${t.value===r?"bg-bg-3 text-ink-0":"text-ink-1 hover:text-ink-0"}`,children:t.label},t.value))})}const s=({error:e})=>n.jsxs("div",{role:"alert",className:"border border-crit/40 bg-crit/8 rounded-md p-3 text-xs text-ink-1",children:[n.jsx("span",{className:"text-crit-ink font-medium",children:"Could not load."})," ",e instanceof Error?e.message:String(e)]});export{s as E,l as S};
@@ -1 +1 @@
1
- import{r as u,u as _,f as P,j as s,W as $,S as j,e as p,t as C,n as E}from"./index-KIvNrQPN.js";import{T as b,a as f,P as m}from"./Panel-D9OW_N0O.js";import{E as O,S as y}from"./ErrorPanel-B-6j7s5W.js";import{B as k}from"./Bars-BavaWNhM.js";import{S as W}from"./StackedColumns-CFuYUdeJ.js";import{M as B}from"./MultiLine-C0zPyGoR.js";import{a as v}from"./ChartTable-Cs4_Bkur.js";import{p as g}from"./rollups-Dqiwg3gD.js";import{d as D,w as z}from"./windows-B3y4OLGl.js";import{t as A,s as F}from"./series-BjP-80tt.js";import"./uplotTheme-Danfgh6n.js";import"./AreaLine-DVivOkZb.js";import"./Chip-BfVZybGP.js";function Z(){const[d,M]=u.useState("30d"),[x,S]=u.useState("lines"),a=_(d),n=z(d),N=n!=null?"day":"week",c=P(N,"model"),l=u.useMemo(()=>Object.keys({...a.data?.tokens_by_model,...a.data?.cost_by_model}).map(e=>({model:e,tokens:a.data?.tokens_by_model[e]??0,cost:a.data?.cost_by_model[e]??0})).sort((e,t)=>t.cost-e.cost),[a.data]),o=u.useMemo(()=>{if(!c.data)return null;const e=n!=null?new Set(D(new Date,n)):null,t=e?c.data.points.filter(i=>e.has(i.bucket)):c.data.points.slice(-26),r=A(t,"tokens"),T=F(r.rows);return{labels:r.labels,raw:r.names.map((i,h)=>({name:i,values:r.rows[h]})),pct:r.names.map((i,h)=>({name:i,values:T[h]}))}},[c.data,n]),w=l.reduce((e,t)=>e+t.cost,0);return a.error?s.jsxs(s.Fragment,{children:[s.jsx(b,{crumbs:["Analyze","Models"]}),s.jsx(f,{children:s.jsx(O,{error:a.error})})]}):s.jsxs(s.Fragment,{children:[s.jsx(b,{crumbs:["Analyze","Models"],children:s.jsx(y,{options:$.map(e=>({value:e,label:e})),value:d,onChange:M})}),s.jsxs(f,{children:[s.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[s.jsx(m,{title:"Tokens by model",children:a.data?l.length?s.jsx(k,{rows:l.map(e=>({name:e.model,value:e.tokens}))}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}):s.jsx(j,{w:"100%",h:"160px"})}),s.jsx(m,{title:"Estimated cost by model",children:a.data?l.length?s.jsx(k,{rows:l.map(e=>({name:e.model,value:e.cost})),format:p,color:"#285a95"}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}):s.jsx(j,{w:"100%",h:"160px"})})]}),s.jsx(m,{title:"Price efficiency",sub:"$ per million tokens, as experienced in this window",children:l.some(e=>e.tokens>0)?s.jsx(k,{rows:l.filter(e=>e.tokens>0).map(e=>({name:e.model,value:g(e.cost,e.tokens)??0})),format:p,color:"#3173c4"}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."})}),s.jsx(m,{title:n!=null?"Model share by day":"Model share by week",sub:`% of each ${n!=null?"day":"week"}'s fresh + output tokens · last ${d}`,right:s.jsx(y,{options:[{value:"lines",label:"lines"},{value:"columns",label:"columns"},{value:"table",label:"table"}],value:x,onChange:S}),children:o?o.raw.length?x==="lines"?s.jsx(B,{labels:o.labels,series:o.pct,share:!0,height:240}):x==="columns"?s.jsx(W,{labels:o.labels,series:o.raw,share:!0,format:C}):s.jsx(v,{columns:[n!=null?"day":"week",...o.raw.map(e=>e.name)],rows:o.labels.map((e,t)=>[e,...o.pct.map(r=>`${Math.round((r.values[t]??0)*100)}%`)])}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}):s.jsx(j,{w:"100%",h:"240px"})}),s.jsx(m,{title:"Per-model details",padded:!1,children:s.jsx(v,{columns:["model","tokens","est. cost","$ / M tokens","share of cost"],rows:l.map(e=>{const t=g(e.cost,e.tokens);return[e.model,E(e.tokens),p(e.cost),t==null?"—":p(t),w?`${Math.round(e.cost/w*100)}%`:"—"]})})})]})]})}export{Z as default};
1
+ import{r as u,u as _,f as P,j as s,W as $,S as j,e as p,t as C,n as E}from"./index-kRaX6JLH.js";import{T as b,a as f,P as m}from"./Panel-rzVYig0L.js";import{E as O,S as y}from"./ErrorPanel-lb1Tt_Cg.js";import{B as k}from"./Bars-CwquOD-V.js";import{S as W}from"./StackedColumns-Di1FeFpF.js";import{M as B}from"./MultiLine-Bp4Mitsq.js";import{a as v}from"./ChartTable-iQFTYj1d.js";import{p as g}from"./rollups-Dqiwg3gD.js";import{d as D,w as z}from"./windows-B3y4OLGl.js";import{t as A,s as F}from"./series-BjP-80tt.js";import"./uplotTheme-Dv4lAb8e.js";import"./AreaLine-BKfPVgnO.js";import"./Chip-C_zmBEC6.js";function Z(){const[d,M]=u.useState("30d"),[x,S]=u.useState("lines"),a=_(d),n=z(d),N=n!=null?"day":"week",c=P(N,"model"),l=u.useMemo(()=>Object.keys({...a.data?.tokens_by_model,...a.data?.cost_by_model}).map(e=>({model:e,tokens:a.data?.tokens_by_model[e]??0,cost:a.data?.cost_by_model[e]??0})).sort((e,t)=>t.cost-e.cost),[a.data]),o=u.useMemo(()=>{if(!c.data)return null;const e=n!=null?new Set(D(new Date,n)):null,t=e?c.data.points.filter(i=>e.has(i.bucket)):c.data.points.slice(-26),r=A(t,"tokens"),T=F(r.rows);return{labels:r.labels,raw:r.names.map((i,h)=>({name:i,values:r.rows[h]})),pct:r.names.map((i,h)=>({name:i,values:T[h]}))}},[c.data,n]),w=l.reduce((e,t)=>e+t.cost,0);return a.error?s.jsxs(s.Fragment,{children:[s.jsx(b,{crumbs:["Analyze","Models"]}),s.jsx(f,{children:s.jsx(O,{error:a.error})})]}):s.jsxs(s.Fragment,{children:[s.jsx(b,{crumbs:["Analyze","Models"],children:s.jsx(y,{options:$.map(e=>({value:e,label:e})),value:d,onChange:M})}),s.jsxs(f,{children:[s.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[s.jsx(m,{title:"Tokens by model",children:a.data?l.length?s.jsx(k,{rows:l.map(e=>({name:e.model,value:e.tokens}))}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}):s.jsx(j,{w:"100%",h:"160px"})}),s.jsx(m,{title:"Estimated cost by model",children:a.data?l.length?s.jsx(k,{rows:l.map(e=>({name:e.model,value:e.cost})),format:p,color:"#285a95"}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}):s.jsx(j,{w:"100%",h:"160px"})})]}),s.jsx(m,{title:"Price efficiency",sub:"$ per million tokens, as experienced in this window",children:l.some(e=>e.tokens>0)?s.jsx(k,{rows:l.filter(e=>e.tokens>0).map(e=>({name:e.model,value:g(e.cost,e.tokens)??0})),format:p,color:"#3173c4"}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."})}),s.jsx(m,{title:n!=null?"Model share by day":"Model share by week",sub:`% of each ${n!=null?"day":"week"}'s fresh + output tokens · last ${d}`,right:s.jsx(y,{options:[{value:"lines",label:"lines"},{value:"columns",label:"columns"},{value:"table",label:"table"}],value:x,onChange:S}),children:o?o.raw.length?x==="lines"?s.jsx(B,{labels:o.labels,series:o.pct,share:!0,height:240}):x==="columns"?s.jsx(W,{labels:o.labels,series:o.raw,share:!0,format:C}):s.jsx(v,{columns:[n!=null?"day":"week",...o.raw.map(e=>e.name)],rows:o.labels.map((e,t)=>[e,...o.pct.map(r=>`${Math.round((r.values[t]??0)*100)}%`)])}):s.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}):s.jsx(j,{w:"100%",h:"240px"})}),s.jsx(m,{title:"Per-model details",padded:!1,children:s.jsx(v,{columns:["model","tokens","est. cost","$ / M tokens","share of cost"],rows:l.map(e=>{const t=g(e.cost,e.tokens);return[e.model,E(e.tokens),p(e.cost),t==null?"—":p(t),w?`${Math.round(e.cost/w*100)}%`:"—"]})})})]})]})}export{Z as default};
@@ -0,0 +1 @@
1
+ import{j as i}from"./index-kRaX6JLH.js";import{A as o}from"./AreaLine-BKfPVgnO.js";const e=s=>i.jsx(o,{...s,fill:!1});export{e as M};
@@ -1 +1 @@
1
- import{j as e,p as O,t as k,u as A,a as M,b as B,r as p,c as C,s as H,d as K,e as $,L,f as z,W as J,n as g,S as T}from"./index-KIvNrQPN.js";import{P as w,T as W,a as R}from"./Panel-D9OW_N0O.js";import{E as G,S as U}from"./ErrorPanel-B-6j7s5W.js";import{d as N,T as _}from"./Tile-CTKO3Y6u.js";import{C as q}from"./Chip-BfVZybGP.js";import{A as Q}from"./AreaLine-DVivOkZb.js";import{B as V}from"./Bars-BavaWNhM.js";import{d as E,w as S,a as X}from"./windows-B3y4OLGl.js";import{C as Y}from"./ChartTable-Cs4_Bkur.js";import{i as Z}from"./rollups-Dqiwg3gD.js";import{A as ee}from"./AttentionStrip-C4S2Lszh.js";import{t as se}from"./series-BjP-80tt.js";import"./uplotTheme-Danfgh6n.js";import"./Button-D2qCw3Bg.js";const te=({children:t})=>e.jsx("kbd",{className:"font-mono text-[10px] border border-line-2 rounded-sm px-1 text-ink-2",children:t});function ae({parts:t,className:o=""}){const a=t.reduce((n,s)=>n+s.value,0)||1;return e.jsxs("div",{className:`flex flex-col gap-2 ${o}`,children:[e.jsx("div",{className:"flex h-2 rounded-sm overflow-hidden gap-[2px] bg-bg-0",children:t.map(n=>e.jsx("i",{style:{width:`${n.value/a*100}%`,background:n.color}},n.name))}),e.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1 text-[11px] text-ink-1",children:t.map(n=>e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx("b",{className:"w-2 h-2 rounded-[2px] inline-block",style:{background:n.color}}),n.name," ",e.jsx("span",{className:"font-mono text-ink-0",children:O(n.value/a,0)})]},n.name))})]})}const D=["#141a24","#1f3c63","#285a95","#3173c4","#3987e5"],F=(t,o)=>t<=0?D[0]:D[Math.min(4,1+Math.floor(t/o*3.999))];function oe({byDay:t,days:o=90,end:a=new Date,className:n=""}){const s=E(a,o),l=Math.max(1,...s.map(i=>t[i]??0)),d=(new Date(s[0]+"T00:00:00").getDay()+6)%7,r=11,m=2,x=Math.ceil((o+d)/7);return e.jsxs("svg",{className:`block w-full ${n}`,width:"100%",viewBox:`0 0 ${x*(r+m)+28} ${7*(r+m)+4}`,style:{aspectRatio:`${x*(r+m)+28} / ${7*(r+m)+4}`},role:"img","aria-label":`Activity, last ${o} days`,children:[["M","W","F"].map((i,f)=>e.jsx("text",{x:0,y:f*2*(r+m)+r,fontSize:9,fill:"#667184",fontFamily:"var(--font-mono)",children:i},i)),s.map((i,f)=>{const c=f+d,v=24+Math.floor(c/7)*(r+m),y=c%7*(r+m),b=t[i]??0;return e.jsx("rect",{"data-day":i,x:v,y,width:r,height:r,rx:2,fill:F(b,l),children:e.jsx("title",{children:`${i} · ${k(b)} tokens`})},i)})]})}function ne({matrix:t,rowLabels:o,colLabels:a,className:n=""}){const s=Math.max(1,...t.flat()),l=16,d=14,r=2,m=26;return e.jsxs("svg",{className:`block w-full ${n}`,width:"100%",viewBox:`0 0 ${m+a.length*(l+r)} ${t.length*(d+r)+14}`,style:{aspectRatio:`${m+a.length*(l+r)} / ${t.length*(d+r)+14}`},role:"img","aria-label":"Sessions by weekday and hour",children:[o.map((x,i)=>e.jsx("text",{x:0,y:i*(d+r)+d-3,fontSize:9,fill:"#667184",fontFamily:"var(--font-mono)",children:x},x)),a.map((x,i)=>i%3===0?e.jsx("text",{x:m+i*(l+r),y:t.length*(d+r)+10,fontSize:9,fill:"#667184",fontFamily:"var(--font-mono)",children:x},x):null),t.map((x,i)=>x.map((f,c)=>e.jsx("rect",{x:m+c*(l+r),y:i*(d+r),width:l,height:d,rx:2,fill:F(f,s),children:e.jsx("title",{children:`${o[i]} ${a[c]}:00 · ${f}`})},`${i}-${c}`)))]})}const I={tokens:null,cost:null,sessions:null,errorRate:null};function re(t,o,a,n){if(S(o)==null||!t.prior_window)return I;const s=t.prior_window;let l=null;if(a&&n){const d=a.total_calls?a.total_errors/a.total_calls:0,r=n.total_calls-a.total_calls,m=n.total_errors-a.total_errors,x=r>0?m/r:null;l=x==null?null:{abs:d-x,pct:x?(d-x)/x:null,dir:d>x?"up":d<x?"down":"flat"}}return{tokens:N(t.total_tokens,s.tokens),cost:N(t.total_cost_usd,s.cost_usd),sessions:N(t.session_count,s.sessions),errorRate:l}}function le(t,o=new Date){const a=A(t),n=M(t),s=M(X(t)),l=B(),d=p.useMemo(()=>a.data?re(a.data,t,n.data,s.data):I,[a.data,n.data,s.data,t]),r=p.useMemo(()=>l.data?Z(l.data,t,o):[],[l.data,t]);return{cur:a.data,tiles:d,tools:n.data,sessionsInWindow:r,allSessions:l.data??[],isLoading:a.isLoading,error:a.error??n.error??l.error}}const ie=["STARTED","PROJECT","MODEL","TOKENS","EST. COST"];function ce({rows:t}){const o=Math.max(1,...t.map(s=>s.window_tokens)),a=C(),n=s=>a({to:"/sessions/$id",params:{id:s},search:{tab:"overview"}});return e.jsx(w,{title:"Top sessions",sub:"by tokens in window",right:e.jsx(L,{to:"/sessions",className:"text-[11px]",children:"All sessions →"}),padded:!1,children:e.jsxs("table",{className:"w-full border-collapse",children:[e.jsx("thead",{children:e.jsx("tr",{children:ie.map((s,l)=>e.jsx("th",{className:`text-[10px] tracking-[0.08em] text-ink-2 font-medium px-3 py-2 border-b border-line ${l>=3?"text-right":"text-left"} ${l===3?"w-56":""}`,children:s},s))})}),e.jsxs("tbody",{children:[t.slice(0,8).map(s=>e.jsxs("tr",{className:"hover:bg-bg-2 cursor-pointer",onClick:()=>n(s.id),onKeyDown:l=>l.key==="Enter"&&n(s.id),tabIndex:0,children:[e.jsxs("td",{className:"px-3 h-[34px] border-b border-line font-mono text-xs whitespace-nowrap",children:[e.jsx("span",{className:"text-ink-0",children:H(s.started_at)}),s.days_active>1&&e.jsxs("span",{className:"text-ink-2 text-[10px] ml-1",children:["+",s.days_active-1,"d"]})]}),e.jsx("td",{className:"px-3 border-b border-line font-mono text-xs text-ink-1 truncate max-w-[360px]",title:s.project_path,children:K(s.project_path)}),e.jsx("td",{className:"px-3 border-b border-line",children:e.jsx("span",{className:"font-mono text-[11.5px] text-ink-1 bg-bg-3 px-1.5 rounded-sm",children:s.primary_model})}),e.jsx("td",{className:"px-3 border-b border-line",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"relative h-1.5 flex-1 rounded-sm bg-bg-3 overflow-hidden",children:e.jsx("i",{className:"absolute inset-y-0 left-0 bg-s1 rounded-r-sm",style:{width:`${s.window_tokens/o*100}%`}})}),e.jsx("span",{className:"font-mono num text-xs w-14 text-right",children:k(s.window_tokens)})]})}),e.jsx("td",{className:"px-3 border-b border-line text-right font-mono num text-xs",children:$(s.window_cost_usd)})]},s.id)),t.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:5,className:"text-center text-ink-2 py-8",children:"No sessions in this window."})})]})]})})}function de(t){const o={fresh:0,cacheWrite:0,cacheRead:0,output:0,total:0};for(const a of t)o.fresh+=a.total_fresh_input_tokens,o.cacheWrite+=a.total_cache_write_tokens,o.cacheRead+=a.total_cache_read_tokens,o.output+=a.total_output_tokens;return o.total=o.fresh+o.cacheWrite+o.cacheRead+o.output,o}function xe(t,o=()=>1){const a=Array.from({length:7},()=>Array(24).fill(0));for(const n of t){const s=new Date(n.started_at),l=(s.getDay()+6)%7;a[l][s.getHours()]+=o(n)}return a}const me=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],ue=Array.from({length:24},(t,o)=>String(o).padStart(2,"0"));function Me(){const[t,o]=p.useState("7d"),[a,n]=p.useState(!1),s=le(t),l=A("all"),d=z("day","model"),r=p.useMemo(()=>{const u=S(t);return u?E(new Date,u):Object.keys(s.cur?.tokens_by_day??{}).sort()},[t,s.cur]),m=p.useMemo(()=>{if(a&&d.data){const u=d.data.points.filter(j=>r.includes(j.bucket)),h=se(u,"tokens");return{labels:h.labels,series:h.names.map((j,P)=>({name:j,values:h.rows[P]}))}}return{labels:r,series:[{name:"tokens",values:r.map(u=>s.cur?.tokens_by_day[u]??0)}]}},[a,d.data,r,s.cur]),x=p.useMemo(()=>Object.entries(s.cur?.tokens_by_model??{}).map(([u,h])=>({name:u,value:h})).sort((u,h)=>h.value-u.value),[s.cur]),i=p.useMemo(()=>de(s.sessionsInWindow),[s.sessionsInWindow]),f=p.useMemo(()=>xe(s.sessionsInWindow),[s.sessionsInWindow]);if(s.error)return e.jsxs(e.Fragment,{children:[e.jsx(W,{crumbs:["Monitor","Overview"]}),e.jsx(R,{children:e.jsx(G,{error:s.error})})]});const c=s.cur,v=S(t),y=c&&c.session_count?Math.round(c.total_tokens/c.session_count):0,b=s.tools?s.tools.total_calls?s.tools.total_errors/s.tools.total_calls:0:null;return e.jsxs(e.Fragment,{children:[e.jsxs(W,{crumbs:["Monitor","Overview"],children:[e.jsx(U,{options:J.map(u=>({value:u,label:u})),value:t,onChange:o}),e.jsxs("span",{className:"text-ink-2 text-xs flex items-center gap-2",children:["Jump anywhere ",e.jsx(te,{children:"Ctrl K"})]})]}),e.jsxs(R,{children:[e.jsxs("div",{className:"grid grid-cols-4 gap-3",children:[e.jsx(_,{label:"Tokens",value:c?k(c.total_tokens):"—",delta:s.tiles.tokens,sub:"vs prior window",note:c?`${k(y)} / session`:void 0}),e.jsx(_,{label:"Estimated cost",value:c?$(c.total_cost_usd):"—",delta:s.tiles.cost,upIsBad:!0,sub:"vs prior window",note:c&&v?`${$(c.total_cost_usd/v)} / day`:void 0}),e.jsx(_,{label:"Sessions",value:c?g(c.session_count):"—",delta:s.tiles.sessions,sub:"vs prior window"}),e.jsx(_,{label:"Tool error rate",value:b==null?"—":O(b),delta:s.tiles.errorRate,upIsBad:!0,fmt:u=>`${u.abs>=0?"+":"−"}${(Math.abs(u.abs)*100).toFixed(1)} pt`,sub:s.tools?`${g(s.tools.total_errors)} of ${g(s.tools.total_calls)} calls`:void 0})]}),e.jsx(ee,{}),e.jsxs("div",{className:"grid grid-cols-[2fr_1fr] gap-3",children:[e.jsx(w,{title:"Tokens per day",sub:a?"fresh + output, by model":"all token kinds",right:e.jsx(q,{active:a,onClick:()=>n(!a),children:"Stack by model"}),children:c?e.jsx(Y,{chart:e.jsx(Q,{labels:m.labels,series:m.series,stacked:a}),table:{columns:["day",...m.series.map(u=>u.name)],rows:m.labels.map((u,h)=>[u,...m.series.map(j=>g(j.values[h]??0))])}}):e.jsx(T,{w:"100%",h:"220px"})}),e.jsxs(w,{title:"Models",sub:"share of tokens",children:[x.length?e.jsx(V,{rows:x}):e.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}),e.jsx("div",{className:"mt-auto pt-3 border-t border-line",children:e.jsx(ae,{parts:[{name:"cache read",value:i.cacheRead,color:"#3987e5"},{name:"cache write",value:i.cacheWrite,color:"#285a95"},{name:"fresh",value:i.fresh,color:"#1f3c63"},{name:"output",value:i.output,color:"#9ec5f4"}]})})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(w,{title:"Activity",sub:"last 90 days",children:l.data?e.jsx(oe,{byDay:l.data.tokens_by_day,days:90}):e.jsx(T,{w:"100%",h:"100px"})}),e.jsx(w,{title:"When you work",sub:"sessions started, by weekday × hour",children:e.jsx(ne,{matrix:f,rowLabels:me,colLabels:ue})})]}),e.jsx(ce,{rows:c?.top_sessions??[]})]})]})}export{Me as default};
1
+ import{j as e,p as O,t as k,u as A,a as M,b as B,r as p,c as C,s as H,d as K,e as $,L,f as z,W as J,n as g,S as T}from"./index-kRaX6JLH.js";import{P as w,T as W,a as R}from"./Panel-rzVYig0L.js";import{E as G,S as U}from"./ErrorPanel-lb1Tt_Cg.js";import{d as N,T as _}from"./Tile-BlnGo9bN.js";import{C as q}from"./Chip-C_zmBEC6.js";import{A as Q}from"./AreaLine-BKfPVgnO.js";import{B as V}from"./Bars-CwquOD-V.js";import{d as E,w as S,a as X}from"./windows-B3y4OLGl.js";import{C as Y}from"./ChartTable-iQFTYj1d.js";import{i as Z}from"./rollups-Dqiwg3gD.js";import{A as ee}from"./AttentionStrip-DQUV5LTN.js";import{t as se}from"./series-BjP-80tt.js";import"./uplotTheme-Dv4lAb8e.js";import"./Button-BY-h2O0Z.js";const te=({children:t})=>e.jsx("kbd",{className:"font-mono text-[10px] border border-line-2 rounded-sm px-1 text-ink-2",children:t});function ae({parts:t,className:o=""}){const a=t.reduce((n,s)=>n+s.value,0)||1;return e.jsxs("div",{className:`flex flex-col gap-2 ${o}`,children:[e.jsx("div",{className:"flex h-2 rounded-sm overflow-hidden gap-[2px] bg-bg-0",children:t.map(n=>e.jsx("i",{style:{width:`${n.value/a*100}%`,background:n.color}},n.name))}),e.jsx("div",{className:"flex flex-wrap gap-x-4 gap-y-1 text-[11px] text-ink-1",children:t.map(n=>e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx("b",{className:"w-2 h-2 rounded-[2px] inline-block",style:{background:n.color}}),n.name," ",e.jsx("span",{className:"font-mono text-ink-0",children:O(n.value/a,0)})]},n.name))})]})}const D=["#141a24","#1f3c63","#285a95","#3173c4","#3987e5"],F=(t,o)=>t<=0?D[0]:D[Math.min(4,1+Math.floor(t/o*3.999))];function oe({byDay:t,days:o=90,end:a=new Date,className:n=""}){const s=E(a,o),l=Math.max(1,...s.map(i=>t[i]??0)),d=(new Date(s[0]+"T00:00:00").getDay()+6)%7,r=11,m=2,x=Math.ceil((o+d)/7);return e.jsxs("svg",{className:`block w-full ${n}`,width:"100%",viewBox:`0 0 ${x*(r+m)+28} ${7*(r+m)+4}`,style:{aspectRatio:`${x*(r+m)+28} / ${7*(r+m)+4}`},role:"img","aria-label":`Activity, last ${o} days`,children:[["M","W","F"].map((i,f)=>e.jsx("text",{x:0,y:f*2*(r+m)+r,fontSize:9,fill:"#667184",fontFamily:"var(--font-mono)",children:i},i)),s.map((i,f)=>{const c=f+d,v=24+Math.floor(c/7)*(r+m),y=c%7*(r+m),b=t[i]??0;return e.jsx("rect",{"data-day":i,x:v,y,width:r,height:r,rx:2,fill:F(b,l),children:e.jsx("title",{children:`${i} · ${k(b)} tokens`})},i)})]})}function ne({matrix:t,rowLabels:o,colLabels:a,className:n=""}){const s=Math.max(1,...t.flat()),l=16,d=14,r=2,m=26;return e.jsxs("svg",{className:`block w-full ${n}`,width:"100%",viewBox:`0 0 ${m+a.length*(l+r)} ${t.length*(d+r)+14}`,style:{aspectRatio:`${m+a.length*(l+r)} / ${t.length*(d+r)+14}`},role:"img","aria-label":"Sessions by weekday and hour",children:[o.map((x,i)=>e.jsx("text",{x:0,y:i*(d+r)+d-3,fontSize:9,fill:"#667184",fontFamily:"var(--font-mono)",children:x},x)),a.map((x,i)=>i%3===0?e.jsx("text",{x:m+i*(l+r),y:t.length*(d+r)+10,fontSize:9,fill:"#667184",fontFamily:"var(--font-mono)",children:x},x):null),t.map((x,i)=>x.map((f,c)=>e.jsx("rect",{x:m+c*(l+r),y:i*(d+r),width:l,height:d,rx:2,fill:F(f,s),children:e.jsx("title",{children:`${o[i]} ${a[c]}:00 · ${f}`})},`${i}-${c}`)))]})}const I={tokens:null,cost:null,sessions:null,errorRate:null};function re(t,o,a,n){if(S(o)==null||!t.prior_window)return I;const s=t.prior_window;let l=null;if(a&&n){const d=a.total_calls?a.total_errors/a.total_calls:0,r=n.total_calls-a.total_calls,m=n.total_errors-a.total_errors,x=r>0?m/r:null;l=x==null?null:{abs:d-x,pct:x?(d-x)/x:null,dir:d>x?"up":d<x?"down":"flat"}}return{tokens:N(t.total_tokens,s.tokens),cost:N(t.total_cost_usd,s.cost_usd),sessions:N(t.session_count,s.sessions),errorRate:l}}function le(t,o=new Date){const a=A(t),n=M(t),s=M(X(t)),l=B(),d=p.useMemo(()=>a.data?re(a.data,t,n.data,s.data):I,[a.data,n.data,s.data,t]),r=p.useMemo(()=>l.data?Z(l.data,t,o):[],[l.data,t]);return{cur:a.data,tiles:d,tools:n.data,sessionsInWindow:r,allSessions:l.data??[],isLoading:a.isLoading,error:a.error??n.error??l.error}}const ie=["STARTED","PROJECT","MODEL","TOKENS","EST. COST"];function ce({rows:t}){const o=Math.max(1,...t.map(s=>s.window_tokens)),a=C(),n=s=>a({to:"/sessions/$id",params:{id:s},search:{tab:"overview"}});return e.jsx(w,{title:"Top sessions",sub:"by tokens in window",right:e.jsx(L,{to:"/sessions",className:"text-[11px]",children:"All sessions →"}),padded:!1,children:e.jsxs("table",{className:"w-full border-collapse",children:[e.jsx("thead",{children:e.jsx("tr",{children:ie.map((s,l)=>e.jsx("th",{className:`text-[10px] tracking-[0.08em] text-ink-2 font-medium px-3 py-2 border-b border-line ${l>=3?"text-right":"text-left"} ${l===3?"w-56":""}`,children:s},s))})}),e.jsxs("tbody",{children:[t.slice(0,8).map(s=>e.jsxs("tr",{className:"hover:bg-bg-2 cursor-pointer",onClick:()=>n(s.id),onKeyDown:l=>l.key==="Enter"&&n(s.id),tabIndex:0,children:[e.jsxs("td",{className:"px-3 h-[34px] border-b border-line font-mono text-xs whitespace-nowrap",children:[e.jsx("span",{className:"text-ink-0",children:H(s.started_at)}),s.days_active>1&&e.jsxs("span",{className:"text-ink-2 text-[10px] ml-1",children:["+",s.days_active-1,"d"]})]}),e.jsx("td",{className:"px-3 border-b border-line font-mono text-xs text-ink-1 truncate max-w-[360px]",title:s.project_path,children:K(s.project_path)}),e.jsx("td",{className:"px-3 border-b border-line",children:e.jsx("span",{className:"font-mono text-[11.5px] text-ink-1 bg-bg-3 px-1.5 rounded-sm",children:s.primary_model})}),e.jsx("td",{className:"px-3 border-b border-line",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"relative h-1.5 flex-1 rounded-sm bg-bg-3 overflow-hidden",children:e.jsx("i",{className:"absolute inset-y-0 left-0 bg-s1 rounded-r-sm",style:{width:`${s.window_tokens/o*100}%`}})}),e.jsx("span",{className:"font-mono num text-xs w-14 text-right",children:k(s.window_tokens)})]})}),e.jsx("td",{className:"px-3 border-b border-line text-right font-mono num text-xs",children:$(s.window_cost_usd)})]},s.id)),t.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:5,className:"text-center text-ink-2 py-8",children:"No sessions in this window."})})]})]})})}function de(t){const o={fresh:0,cacheWrite:0,cacheRead:0,output:0,total:0};for(const a of t)o.fresh+=a.total_fresh_input_tokens,o.cacheWrite+=a.total_cache_write_tokens,o.cacheRead+=a.total_cache_read_tokens,o.output+=a.total_output_tokens;return o.total=o.fresh+o.cacheWrite+o.cacheRead+o.output,o}function xe(t,o=()=>1){const a=Array.from({length:7},()=>Array(24).fill(0));for(const n of t){const s=new Date(n.started_at),l=(s.getDay()+6)%7;a[l][s.getHours()]+=o(n)}return a}const me=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],ue=Array.from({length:24},(t,o)=>String(o).padStart(2,"0"));function Me(){const[t,o]=p.useState("7d"),[a,n]=p.useState(!1),s=le(t),l=A("all"),d=z("day","model"),r=p.useMemo(()=>{const u=S(t);return u?E(new Date,u):Object.keys(s.cur?.tokens_by_day??{}).sort()},[t,s.cur]),m=p.useMemo(()=>{if(a&&d.data){const u=d.data.points.filter(j=>r.includes(j.bucket)),h=se(u,"tokens");return{labels:h.labels,series:h.names.map((j,P)=>({name:j,values:h.rows[P]}))}}return{labels:r,series:[{name:"tokens",values:r.map(u=>s.cur?.tokens_by_day[u]??0)}]}},[a,d.data,r,s.cur]),x=p.useMemo(()=>Object.entries(s.cur?.tokens_by_model??{}).map(([u,h])=>({name:u,value:h})).sort((u,h)=>h.value-u.value),[s.cur]),i=p.useMemo(()=>de(s.sessionsInWindow),[s.sessionsInWindow]),f=p.useMemo(()=>xe(s.sessionsInWindow),[s.sessionsInWindow]);if(s.error)return e.jsxs(e.Fragment,{children:[e.jsx(W,{crumbs:["Monitor","Overview"]}),e.jsx(R,{children:e.jsx(G,{error:s.error})})]});const c=s.cur,v=S(t),y=c&&c.session_count?Math.round(c.total_tokens/c.session_count):0,b=s.tools?s.tools.total_calls?s.tools.total_errors/s.tools.total_calls:0:null;return e.jsxs(e.Fragment,{children:[e.jsxs(W,{crumbs:["Monitor","Overview"],children:[e.jsx(U,{options:J.map(u=>({value:u,label:u})),value:t,onChange:o}),e.jsxs("span",{className:"text-ink-2 text-xs flex items-center gap-2",children:["Jump anywhere ",e.jsx(te,{children:"Ctrl K"})]})]}),e.jsxs(R,{children:[e.jsxs("div",{className:"grid grid-cols-4 gap-3",children:[e.jsx(_,{label:"Tokens",value:c?k(c.total_tokens):"—",delta:s.tiles.tokens,sub:"vs prior window",note:c?`${k(y)} / session`:void 0}),e.jsx(_,{label:"Estimated cost",value:c?$(c.total_cost_usd):"—",delta:s.tiles.cost,upIsBad:!0,sub:"vs prior window",note:c&&v?`${$(c.total_cost_usd/v)} / day`:void 0}),e.jsx(_,{label:"Sessions",value:c?g(c.session_count):"—",delta:s.tiles.sessions,sub:"vs prior window"}),e.jsx(_,{label:"Tool error rate",value:b==null?"—":O(b),delta:s.tiles.errorRate,upIsBad:!0,fmt:u=>`${u.abs>=0?"+":"−"}${(Math.abs(u.abs)*100).toFixed(1)} pt`,sub:s.tools?`${g(s.tools.total_errors)} of ${g(s.tools.total_calls)} calls`:void 0})]}),e.jsx(ee,{}),e.jsxs("div",{className:"grid grid-cols-[2fr_1fr] gap-3",children:[e.jsx(w,{title:"Tokens per day",sub:a?"fresh + output, by model":"all token kinds",right:e.jsx(q,{active:a,onClick:()=>n(!a),children:"Stack by model"}),children:c?e.jsx(Y,{chart:e.jsx(Q,{labels:m.labels,series:m.series,stacked:a}),table:{columns:["day",...m.series.map(u=>u.name)],rows:m.labels.map((u,h)=>[u,...m.series.map(j=>g(j.values[h]??0))])}}):e.jsx(T,{w:"100%",h:"220px"})}),e.jsxs(w,{title:"Models",sub:"share of tokens",children:[x.length?e.jsx(V,{rows:x}):e.jsx("div",{className:"text-ink-2 text-center py-6",children:"No data."}),e.jsx("div",{className:"mt-auto pt-3 border-t border-line",children:e.jsx(ae,{parts:[{name:"cache read",value:i.cacheRead,color:"#3987e5"},{name:"cache write",value:i.cacheWrite,color:"#285a95"},{name:"fresh",value:i.fresh,color:"#1f3c63"},{name:"output",value:i.output,color:"#9ec5f4"}]})})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(w,{title:"Activity",sub:"last 90 days",children:l.data?e.jsx(oe,{byDay:l.data.tokens_by_day,days:90}):e.jsx(T,{w:"100%",h:"100px"})}),e.jsx(w,{title:"When you work",sub:"sessions started, by weekday × hour",children:e.jsx(ne,{matrix:f,rowLabels:me,colLabels:ue})})]}),e.jsx(ce,{rows:c?.top_sessions??[]})]})]})}export{Me as default};
@@ -1 +1 @@
1
- import{j as e,L as i}from"./index-KIvNrQPN.js";function o({crumbs:n,children:a}){return e.jsxs("div",{className:"h-12 shrink-0 border-b border-line flex items-center gap-3 px-5 bg-bg-1",children:[e.jsx("span",{className:"text-[13px] text-ink-1 flex items-center gap-1.5 min-w-0",children:n.map((s,l)=>e.jsxs("span",{className:"flex items-center gap-1.5 min-w-0",children:[l>0&&e.jsx("span",{children:"/"}),typeof s=="string"?l===n.length-1?e.jsx("b",{className:"text-ink-0 font-semibold truncate",children:s}):e.jsx("span",{children:s}):e.jsx(i,{to:s.to,className:"text-ink-1 hover:text-ink-0",children:s.label})]},l))}),e.jsx("div",{className:"ml-auto flex items-center gap-2",children:a})]})}const c=({children:n,row:a=!1})=>e.jsx("div",{id:"page-scroll",className:`p-5 flex ${a?"flex-row":"flex-col"} gap-4 flex-1 min-h-0 overflow-auto ${a?"":"[&>*]:shrink-0"}`,children:n});function m({title:n,sub:a,right:s,children:l,className:t="",padded:r=!0}){return e.jsxs("section",{className:`bg-bg-1 border border-line rounded-md flex flex-col overflow-hidden min-w-0 ${t}`,children:[n&&e.jsxs("header",{className:"flex items-center gap-2.5 h-9 px-3.5 border-b border-line shrink-0",children:[e.jsx("h3",{className:"m-0 text-xs font-semibold text-ink-0 whitespace-nowrap",children:n}),a&&e.jsx("span",{className:"text-[11px] text-ink-2 font-mono truncate",children:a}),s&&e.jsx("div",{className:"ml-auto flex items-center gap-1.5",children:s})]}),e.jsx("div",{className:`${r?"p-3.5":""} min-h-0 flex-1 flex flex-col`,children:l})]})}export{m as P,o as T,c as a};
1
+ import{j as e,L as i}from"./index-kRaX6JLH.js";function o({crumbs:n,children:a}){return e.jsxs("div",{className:"h-12 shrink-0 border-b border-line flex items-center gap-3 px-5 bg-bg-1",children:[e.jsx("span",{className:"text-[13px] text-ink-1 flex items-center gap-1.5 min-w-0",children:n.map((s,l)=>e.jsxs("span",{className:"flex items-center gap-1.5 min-w-0",children:[l>0&&e.jsx("span",{children:"/"}),typeof s=="string"?l===n.length-1?e.jsx("b",{className:"text-ink-0 font-semibold truncate",children:s}):e.jsx("span",{children:s}):e.jsx(i,{to:s.to,className:"text-ink-1 hover:text-ink-0",children:s.label})]},l))}),e.jsx("div",{className:"ml-auto flex items-center gap-2",children:a})]})}const c=({children:n,row:a=!1})=>e.jsx("div",{id:"page-scroll",className:`p-5 flex ${a?"flex-row":"flex-col"} gap-4 flex-1 min-h-0 overflow-auto ${a?"":"[&>*]:shrink-0"}`,children:n});function m({title:n,sub:a,right:s,children:l,className:t="",padded:r=!0}){return e.jsxs("section",{className:`bg-bg-1 border border-line rounded-md flex flex-col overflow-hidden min-w-0 ${t}`,children:[n&&e.jsxs("header",{className:"flex items-center gap-2.5 h-9 px-3.5 border-b border-line shrink-0",children:[e.jsx("h3",{className:"m-0 text-xs font-semibold text-ink-0 whitespace-nowrap",children:n}),a&&e.jsx("span",{className:"text-[11px] text-ink-2 font-mono truncate",children:a}),s&&e.jsx("div",{className:"ml-auto flex items-center gap-1.5",children:s})]}),e.jsx("div",{className:`${r?"p-3.5":""} min-h-0 flex-1 flex flex-col`,children:l})]})}export{m as P,o as T,c as a};
@@ -0,0 +1 @@
1
+ import{j as e,r as i,k as I,l as P,m as E,o as F,q as L,v as T,I as $,d as b,L as C}from"./index-kRaX6JLH.js";import{T as D,a as M,P as O}from"./Panel-rzVYig0L.js";import{C as N}from"./Chip-C_zmBEC6.js";import{P as y,B as q}from"./Button-BY-h2O0Z.js";import{d as B}from"./windows-B3y4OLGl.js";import{a as Q,b as R}from"./agents-CDuRxAZi.js";function A({values:s,width:a=120,height:r=28,className:o=""}){if(!s.length)return null;const n=Math.max(1,...s),j=s.length>1?(a-4)/(s.length-1):0,c=s.map((x,u)=>[2+u*j,r-2-x/n*(r-4)]),k=c.map((x,u)=>`${u?"L":"M"}${x[0].toFixed(1)} ${x[1].toFixed(1)}`).join(" "),h=c[c.length-1];return e.jsxs("svg",{className:o,width:a,height:r,viewBox:`0 0 ${a} ${r}`,"aria-hidden":"true",children:[e.jsx("path",{d:k,fill:"none",stroke:"#3987e5",strokeWidth:2,strokeLinejoin:"round",strokeLinecap:"round"}),e.jsx("circle",{cx:h[0],cy:h[1],r:3,fill:"#3987e5",stroke:"#10131a",strokeWidth:2})]})}function K(s){return s.replace(/<command-(name|message|args)>[\s\S]*?<\/command-\1>/g,"").replace(/<local-command-caveat>[\s\S]*?<\/local-command-caveat>/g,"").replace(/<\/?local-command-stdout>/g,"").replace(/\s+/g," ").trim()}function Y(s){const a=[],r=/<mark>([\s\S]*?)<\/mark>/g;let o=0,n;for(;n=r.exec(s);)n.index>o&&a.push({t:s.slice(o,n.index),m:!1}),a.push({t:n[1],m:!0}),o=r.lastIndex;return o<s.length&&a.push({t:s.slice(o),m:!1}),a}const W=[{k:"prompt",l:"Your prompts"},{k:"user",l:"Your replies"},{k:"assistant",l:"Assistant"},{k:"thinking",l:"Thinking"},{k:"tool_result",l:"Tool output"}],z={prompt:"good",user:"good",assistant:"info"},G=(s,a)=>s==="assistant"?a?Q(R(a)):"assistant":s==="prompt"||s==="user"?"you":s;function X(s,a=250){const[r,o]=i.useState(s);return i.useEffect(()=>{const n=setTimeout(()=>o(s),a);return()=>clearTimeout(n)},[s,a]),r}function te(){const[s,a]=i.useState(""),[r,o]=i.useState(""),[n,j]=i.useState(["prompt","user","assistant"]),[c,k]=i.useState(!1),h=X(s),x=I().data??[],u=P(),v=E(),w=F({mutationFn:L.searchIndexEnable,onSuccess:()=>v.invalidateQueries({queryKey:["searchIndex"]})}),S=h.trim().length>=2,d=T({q:h,limit:200,project:r||void 0,includeSlash:c,roles:n},S),f=i.useMemo(()=>d.data?.results??[],[d.data]),_=i.useMemo(()=>{const t=B(new Date,30),m=Object.fromEntries(t.map(l=>[l,0]));for(const l of f){const p=new Date(l.timestamp_ms),g=`${p.getFullYear()}-${String(p.getMonth()+1).padStart(2,"0")}-${String(p.getDate()).padStart(2,"0")}`;g in m&&m[g]++}return t.map(l=>m[l])},[f]);return e.jsxs(e.Fragment,{children:[e.jsx(D,{crumbs:["Search","Transcripts"]}),e.jsxs(M,{children:[e.jsx("p",{className:"text-ink-2 text-xs m-0",children:"Searches every prompt you typed and every transcript your agents wrote. 100% local — SQLite FTS5, no embeddings, no API calls."}),u.data&&!u.data.enabled&&e.jsxs("div",{className:"flex items-center gap-3 border border-warn/30 bg-warn/8 rounded-md px-3.5 py-2.5 text-xs",children:[e.jsx(y,{kind:"warn",children:"INDEXING OFF"}),e.jsx("span",{className:"text-ink-1",children:"Only your prompts are searchable. Enable transcript indexing to search agent replies and tool output."}),e.jsx(q,{className:"ml-auto",onClick:()=>w.mutate(),children:"Enable indexing"})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsxs("label",{className:"flex items-center gap-2 h-8 px-2.5 border border-line-2 rounded-md flex-1 min-w-72 text-ink-2",children:[e.jsx($,{name:"search",size:13}),e.jsx("input",{autoFocus:!0,value:s,onChange:t=>a(t.target.value),placeholder:"Search…",className:"bg-transparent outline-none text-ink-0 text-sm w-full placeholder:text-ink-2"})]}),e.jsxs("select",{value:r,onChange:t=>o(t.target.value),className:"h-8 bg-bg-2 border border-line-2 rounded-md text-xs text-ink-1 px-2 max-w-72",children:[e.jsx("option",{value:"",children:"All projects"}),x.map(t=>e.jsx("option",{value:t,children:b(t,60)},t))]})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap text-xs",children:[e.jsx("span",{className:"text-ink-2",children:"Show:"}),W.map(t=>e.jsx(N,{active:n.includes(t.k),onClick:()=>j(n.includes(t.k)?n.filter(m=>m!==t.k):[...n,t.k]),children:t.l},t.k)),e.jsx(N,{active:c,onClick:()=>k(!c),children:"Include slash commands"}),d.data&&e.jsxs("span",{className:"ml-auto flex items-center gap-3 font-mono text-[11px] text-ink-2",children:[d.data.total," matches · ",d.data.prompt_total," prompts · ",d.data.transcript_total," transcript",e.jsx("span",{title:"hits per day, last 30 days",children:e.jsx(A,{values:_})})]})]}),e.jsxs(O,{padded:!1,className:"grow",children:[f.length===0&&e.jsx("div",{className:"text-center text-ink-2 py-10",children:S?d.isFetching?"Searching…":"No matches.":"Type at least two characters to search."}),f.map((t,m)=>{const l=K(t.snippet||t.text);return l?e.jsxs("div",{className:"grid grid-cols-[90px_1fr_160px] gap-3 px-3.5 py-2.5 border-b border-line items-start",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(y,{kind:z[t.role]??"mute",icon:!1,children:G(t.role,t.session_id)}),e.jsx("span",{className:"font-mono text-[10px] text-ink-2",children:new Date(t.timestamp_ms).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})})]}),e.jsxs("div",{className:"text-xs leading-relaxed break-words",children:[Y(l).map((p,g)=>p.m?e.jsx("mark",{className:"bg-accent/25 text-ink-0 rounded-sm px-0.5",children:p.t},g):e.jsx("span",{children:p.t},g)),t.pasted_chars>0&&e.jsxs("span",{className:"text-ink-2 font-mono text-[10px] ml-2",children:["+",t.pasted_chars," pasted chars"]})]}),e.jsxs("div",{className:"text-right flex flex-col gap-1 items-end min-w-0",children:[e.jsx("span",{className:"font-mono text-[11px] text-ink-2 truncate max-w-full",title:t.project_path??"",children:t.project_path?b(t.project_path):""}),t.session_id&&e.jsx(C,{to:"/sessions/$id",params:{id:t.session_id},search:{tab:"overview"},className:"text-[11px]",children:"Open session →"})]})]},m):null})]})]})]})}export{te as default};
@@ -1,2 +1,2 @@
1
- import{r as g,j as e,I as T,t as S,R as C,n as f,T as D,L as X,p as B,e as M,P as F,S as A,U as Y,V as Z,c as G,X as J,Y as ee,d as te}from"./index-KIvNrQPN.js";import{P as w,T as L,a as q}from"./Panel-D9OW_N0O.js";import{S as H,E as se}from"./ErrorPanel-B-6j7s5W.js";import{T as _}from"./Tile-CTKO3Y6u.js";import{P as E}from"./Button-D2qCw3Bg.js";import{r as ne,c as re,a as z}from"./agents-DLrqrj4h.js";import{a as R,b as O,c as P,d as ae,e as oe,o as W,T as V,f as le}from"./TimelineTab-CZ-cy_B_.js";import{A as ie}from"./AreaLine-DVivOkZb.js";import{L as K}from"./uplotTheme-Danfgh6n.js";import{B as U}from"./Bars-BavaWNhM.js";import{C as ce}from"./Chip-BfVZybGP.js";import"./cumulative-C3-3HW0n.js";function I({value:t,chars:o=8}){const[m,x]=g.useState(!1),d=t.includes(":")?t.slice(t.indexOf(":")+1):t,l=async()=>{try{await navigator.clipboard.writeText(d),x(!0),setTimeout(()=>x(!1),1400)}catch{window.prompt("Copy the session id",d)}};return e.jsxs("button",{type:"button",onClick:l,title:(()=>{const a=ne(re(t),d);return`Session id ${d}
2
- Click to copy${a?` (use with: ${a})`:""}`})(),className:`inline-flex items-center gap-1.5 font-mono text-[11px] px-1.5 h-5 rounded-sm border transition-colors ${m?"text-good border-good/40 bg-good/10":"text-ink-1 bg-bg-3 border-transparent hover:border-line-2 hover:text-ink-0"}`,children:[m?e.jsx(T,{name:"check",size:10}):null,m?"copied":o?d.slice(0,o):"copy"]})}function Q({turns:t,onPick:o,active:m}){const x=Math.max(1,t.length),d=1160,l=96,a=80,u=(d-8)/x,n=Math.max(2,Math.min(46,u-3)),h=Math.max(1,...t.map(R)),b=x>60?10:5;return e.jsxs("svg",{width:"100%",viewBox:`0 0 ${d} ${l}`,role:"img","aria-label":"Tokens per turn",className:"block w-full",style:{aspectRatio:`${d} / ${l}`},children:[e.jsx("line",{x1:0,y1:a,x2:d,y2:a,stroke:"#232934"}),t.map((c,p)=>{const j=4+p*u,y=R(c)/h*70,$=O(c)/h*70,r=P(c);return e.jsxs("g",{"data-turn":c.sequence,onClick:()=>o(c.sequence),className:"cursor-pointer",children:[e.jsx("title",{children:`#${c.sequence} · ${S(O(c))} fresh+output · ${S(c.cache_read_tokens)} cache read`}),m===c.sequence&&e.jsx("rect",{x:j-2,y:2,width:n+4,height:a-2,fill:"none",stroke:"#f0883e"}),e.jsx("rect",{x:j,y:a-y,width:n,height:y,fill:"#1f3c63"}),e.jsx("rect",{"data-kind":"top",x:j,y:a-y,width:n,height:Math.max(2,$),rx:1,fill:r?"#d03b3b":"#3987e5"}),(p%b===0||p===t.length-1)&&e.jsx("text",{x:j+n/2,y:l-2,fontSize:10,textAnchor:"middle",fill:r?"#ff7a7a":"#667184",fontFamily:"var(--font-mono)",children:c.sequence})]},c.sequence)})]})}function de({session:t,turns:o}){const m=Intl.DateTimeFormat().resolvedOptions().timeZone,x=[["Project",t.project_path],["Primary model",t.primary_model],[z(t.agent),t.agent_version??"—"],["Started",`${C(t.started_at)} (${m})`],["Ended",t.ended_at?C(t.ended_at):"running"],["Fresh input",`${f(t.total_fresh_input_tokens)} tokens`],["Output",`${f(t.total_output_tokens)} tokens`],["Cache writes",`${f(t.total_cache_write_tokens)} tokens`],["Cache reads",`${f(t.total_cache_read_tokens)} tokens`],["Pricing version",t.pricing_table_version]],d=ae(o);return e.jsxs("div",{className:"grid grid-cols-[1fr_1fr] gap-3",children:[e.jsx(w,{title:"Session",padded:!1,children:e.jsxs("dl",{className:"grid grid-cols-[140px_1fr] text-xs m-0",children:[x.map(([l,a])=>e.jsxs("div",{className:"contents",children:[e.jsx("dt",{className:"px-3.5 py-2 border-b border-line text-ink-1",children:l}),e.jsx("dd",{className:"px-3.5 py-2 border-b border-line font-mono m-0 break-all",children:a})]},l)),e.jsxs("div",{className:"contents",children:[e.jsx("dt",{className:"px-3.5 py-2 border-b border-line text-ink-1",children:"Session id"}),e.jsxs("dd",{className:"px-3.5 py-2 border-b border-line font-mono m-0 break-all flex items-center gap-2",children:[e.jsx("span",{children:t.id}),e.jsx(I,{value:t.id,chars:0})]})]})]})}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(w,{title:"Tool mix",sub:"calls · red segment = errors",children:d.length?e.jsx(U,{rows:d,format:f}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No tool calls."})}),e.jsx(w,{title:"Cache ratio per turn",sub:"share of each turn read from cache",children:e.jsx("svg",{className:"block w-full",viewBox:"0 0 1000 48",preserveAspectRatio:"none",style:{aspectRatio:"1000 / 48"},role:"img","aria-label":"Cache ratio per turn",children:o.map((l,a)=>{const u=1e3/Math.max(1,o.length),n=oe(l);return e.jsxs("g",{children:[e.jsx("title",{children:`#${l.sequence} · ${Math.round(n*100)}%`}),e.jsx("rect",{x:a*u,y:0,width:Math.max(.5,u-.5),height:48,fill:"#1d222c"}),e.jsx("rect",{x:a*u,y:48-n*48,width:Math.max(.5,u-.5),height:n*48,fill:"#3987e5"})]},l.sequence)})})})]})]})}const v=t=>t.total_tokens??t.tokens.fresh_input+t.tokens.output+t.tokens.cache_read+t.tokens.cache_write,xe=t=>t.tool_calls??t.tools.reduce((o,m)=>o+m.count,0);function me({subs:t,selected:o,onPick:m}){const l=Math.max(1,t.length),a=300/l,u=Math.max(1,a-(l>80?.5:1)),n=Math.max(1,...t.map(v));return e.jsx("svg",{className:"block w-full",viewBox:"0 0 300 40",preserveAspectRatio:"none",style:{aspectRatio:"300 / 40"},role:"img","aria-label":"Tokens per sub-agent",children:t.map((h,b)=>{const c=Math.max(2,v(h)/n*36),p=h.id===o;return e.jsxs("g",{onClick:()=>m(h.id),className:"cursor-pointer",children:[e.jsx("title",{children:`#${b+1} · ${S(v(h))} · ${h.errors} errors`}),e.jsx("rect",{x:b*a,y:0,width:u,height:40,fill:p?"rgba(240,136,62,0.18)":"transparent"}),e.jsx("rect",{x:b*a,y:40-c,width:u,height:c,fill:h.errors?"#d03b3b":p?"#ffb177":"#3987e5"})]},h.id)})})}function ue({sa:t,index:o}){const m=D(t.id),x=g.useMemo(()=>W(m.data?.turns??[]),[m.data]),[d,l]=g.useState(),a=v(t),u=n=>{l(n),requestAnimationFrame(()=>document.getElementById(`turn-${n}`)?.scrollIntoView({block:"center"}))};return e.jsxs("div",{className:"flex flex-col gap-3 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 text-xs text-ink-1",children:[e.jsxs("span",{className:"font-mono text-ink-2",children:["#",o+1]}),e.jsx(E,{kind:t.status==="ok"?"good":"crit",children:t.status==="ok"?"OK":`${t.errors} ERR`}),e.jsx("span",{className:"font-mono text-[11px] text-ink-1 bg-bg-3 px-1.5 rounded-sm",children:t.model}),e.jsx(I,{value:t.id}),e.jsx(X,{to:"/sessions/$id",params:{id:t.id},search:{tab:"timeline"},className:"ml-auto text-[11px]",children:"Open as its own session →"})]}),e.jsxs("div",{className:"grid grid-cols-5 gap-3",children:[e.jsx(_,{label:"Tokens",value:S(a),sub:`${B(a?t.tokens.cache_read/a:0,0)} cache read`}),e.jsx(_,{label:"Estimated cost",value:M(t.cost_usd??0)}),e.jsx(_,{label:"Turns",value:f(t.turns),sub:`${f(xe(t))} tool calls`}),e.jsx(_,{label:"Duration",value:F(t.duration_sec??null)}),e.jsx(_,{label:"Tool errors",value:f(t.errors),tone:t.errors?"crit":"default",sub:t.errors?"see red turns below":"none"})]}),e.jsx(w,{title:"Task given",sub:"first user message to the sub-agent",children:t.task_given?e.jsx("p",{className:"m-0 text-xs leading-relaxed whitespace-pre-wrap break-words max-h-40 overflow-auto",children:t.task_given}):e.jsx("span",{className:"text-ink-2 text-xs",children:"Not available — enable transcript indexing in Settings to keep sub-agent prompts."})}),e.jsxs("div",{className:"grid grid-cols-[1fr_2fr] gap-3",children:[e.jsx(w,{title:"Tools used",sub:"calls · red = errors",children:t.tools.length?e.jsx(U,{rows:t.tools.map(n=>({name:n.name,value:n.count,error:n.errors})),format:f}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No tool calls recorded."})}),e.jsx(w,{title:"Sub-agent shape",sub:"tokens per turn · click to jump",right:e.jsx(K,{names:["fresh + output","cache read","tool error"],colors:["#3987e5","#1f3c63","#d03b3b"]}),children:x.length?e.jsx(Q,{turns:x,onPick:u,active:d}):m.isLoading?e.jsx(A,{w:"100%",h:"96px"}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No turns recorded."})})]}),e.jsx(V,{id:t.id,turns:x,active:d})]})}function he({subs:t}){const[o,m]=g.useState(null),[x,d]=g.useState(""),[l,a]=g.useState(!1),[u,n]=g.useState("order"),h=g.useRef(null),b=g.useMemo(()=>new Map(t.map((s,k)=>[s.id,k])),[t]),c=g.useMemo(()=>{const s=x.trim().toLowerCase(),k=t.filter(i=>(!l||i.errors>0)&&(!s||(i.task_given??"").toLowerCase().includes(s)||i.model.toLowerCase().includes(s)));return u==="tokens"&&k.sort((i,N)=>v(N)-v(i)),u==="errors"&&k.sort((i,N)=>N.errors-i.errors||v(N)-v(i)),k},[t,x,l,u]),p=t.find(s=>s.id===o)??c[0]??t[0],j=s=>{m(s),document.getElementById("page-scroll")?.scrollTo({top:0,behavior:"smooth"}),h.current?.querySelector(`[data-sa="${CSS.escape(s)}"]`)?.scrollIntoView({block:"nearest"})},y=s=>{if(!p||s.key!=="ArrowDown"&&s.key!=="ArrowUp"&&s.key!=="j"&&s.key!=="k")return;const k=c.findIndex(N=>N.id===p.id),i=c[Math.max(0,Math.min(c.length-1,k+(s.key==="ArrowDown"||s.key==="j"?1:-1)))];i&&j(i.id),s.preventDefault()};if(g.useEffect(()=>{o&&!t.some(s=>s.id===o)&&m(null)},[t,o]),!t.length)return e.jsx(w,{title:"Sub-agents",children:e.jsx("div",{className:"text-ink-2 text-center py-6",children:"This session did not spawn sub-agents."})});if(!p)return null;const $=Math.max(1,...t.map(v)),r=t.filter(s=>s.errors>0).length;return e.jsxs("div",{className:"grid grid-cols-[340px_1fr] gap-3 items-start",children:[e.jsxs(w,{title:"Sub-agents",sub:`${t.length}${r?` · ${r} with errors`:""}`,padded:!1,className:"sticky top-0 max-h-[calc(100vh-7.5rem)]",children:[e.jsxs("div",{className:"px-3.5 pt-3 pb-2 border-b border-line flex flex-col gap-2 shrink-0",children:[e.jsx(me,{subs:t,selected:p.id,onPick:j}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsxs("label",{className:"flex items-center gap-1.5 h-6 px-2 border border-line-2 rounded-md text-ink-2 flex-1 min-w-28",children:[e.jsx(T,{name:"search",size:11}),e.jsx("input",{value:x,onChange:s=>d(s.target.value),placeholder:"Filter tasks",className:"bg-transparent outline-none text-ink-0 text-[11px] w-full placeholder:text-ink-2"})]}),e.jsx(ce,{active:l,onClick:()=>a(!l),children:"Errors"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{options:[{value:"order",label:"order"},{value:"tokens",label:"tokens"},{value:"errors",label:"errors"}],value:u,onChange:n}),e.jsxs("span",{className:"ml-auto font-mono text-[10px] text-ink-2",children:["↑↓ to step · ",c.length," shown"]})]})]}),e.jsxs("div",{ref:h,tabIndex:0,onKeyDown:y,className:"overflow-auto min-h-0 flex-1 outline-none focus-visible:shadow-[inset_0_0_0_1px_var(--color-accent)]",children:[c.map(s=>{const k=b.get(s.id)??0,i=s.id===p.id;return e.jsxs("button",{type:"button","data-sa":s.id,onClick:()=>j(s.id),title:s.task_given??void 0,className:`w-full text-left px-3.5 h-[34px] border-b border-line flex items-center gap-2 hover:bg-bg-2 ${i?"bg-bg-2 shadow-[inset_2px_0_0_var(--color-accent)]":""}`,children:[e.jsxs("span",{className:"font-mono text-[11px] text-ink-2 w-8 shrink-0",children:["#",k+1]}),s.errors?e.jsxs("span",{className:"text-crit-ink inline-flex items-center gap-0.5 font-mono text-[11px] w-8 shrink-0",children:[e.jsx(T,{name:"x",size:9}),s.errors]}):e.jsx("span",{className:"text-good inline-flex items-center w-8 shrink-0",children:e.jsx(T,{name:"check",size:10})}),e.jsx("span",{className:"text-[11px] text-ink-1 truncate flex-1 min-w-0",children:s.task_given?s.task_given.replace(/\s+/g," "):e.jsx("span",{className:"text-ink-2",children:s.model})}),e.jsx("span",{className:"relative h-1.5 w-14 shrink-0 rounded-sm bg-bg-3 overflow-hidden",children:e.jsx("i",{className:"absolute inset-y-0 left-0 bg-s1 rounded-r-sm",style:{width:`${v(s)/$*100}%`}})}),e.jsx("span",{className:"font-mono num text-[11px] w-12 text-right shrink-0",children:S(v(s))})]},s.id)}),c.length===0&&e.jsx("div",{className:"text-ink-2 text-center py-6 text-xs",children:"No sub-agents match."})]})]}),e.jsx(ue,{sa:p,index:b.get(p.id)??0},p.id)]})}function Se(){const{id:t}=Y({from:"/sessions/$id"}),{tab:o}=Z({from:"/sessions/$id"}),m=G(),x=J(t),d=D(t),l=ee(t),[a,u]=g.useState(),n=g.useMemo(()=>W(d.data?.turns??[]),[d.data]),h=n.filter(P).length,b=g.useMemo(()=>le(n),[n]),c=g.useMemo(()=>[{name:"cumulative cost",values:b}],[b]),p=g.useMemo(()=>n.map(i=>`#${i.sequence}`),[n]),j=i=>m({to:"/sessions/$id",params:{id:t},search:{tab:i}}),y=i=>{u(i),o!=="timeline"&&j("timeline"),requestAnimationFrame(()=>document.getElementById(`turn-${i}`)?.scrollIntoView({block:"center"}))},$=["Analyze",{label:"Sessions",to:"/sessions"},x.data?te(x.data.session.project_path,30):"…"];if(x.error)return e.jsxs(e.Fragment,{children:[e.jsx(L,{crumbs:[...$]}),e.jsx(q,{children:e.jsx(se,{error:x.error})})]});const r=x.data?.session,s=r?r.total_fresh_input_tokens+r.total_output_tokens+r.total_cache_read_tokens+r.total_cache_write_tokens:0,k=n.reduce((i,N)=>i+N.tool_calls.length,0);return e.jsxs(e.Fragment,{children:[e.jsxs(L,{crumbs:[...$],children:[e.jsx(I,{value:t}),e.jsx(H,{options:[{value:"overview",label:"Overview"},{value:"timeline",label:"Timeline"},{value:"subagents",label:`Sub-agents · ${l.data?.length??0}`}],value:o,onChange:j}),r&&e.jsx(E,{kind:"mute",children:r.primary_model}),r?.agent_version&&e.jsxs(E,{kind:"mute",children:[z(r.agent)," ",r.agent_version]})]}),e.jsxs(q,{children:[r?e.jsxs("div",{className:"grid grid-cols-5 gap-3",children:[e.jsx(_,{label:"Tokens",value:S(s),sub:`${f(s)} · ${B(s?r.total_cache_read_tokens/s:0,0)} cache read`}),e.jsx(_,{label:"Estimated cost",value:M(r.total_cost_usd),sub:r.turn_count?`${M(r.total_cost_usd/r.turn_count)} / turn`:void 0}),e.jsx(_,{label:"Turns",value:n.length?f(n.length):f(r.turn_count),sub:`${f(k)} tool calls`,note:n.length&&n.length!==r.turn_count?`${f(r.turn_count)} raw`:void 0}),e.jsx(_,{label:"Duration",value:r.ended_at?F(r.duration_sec):"live",sub:C(r.started_at)}),e.jsx(_,{label:"Tool errors",value:String(h),tone:h?"crit":"default",sub:h?`first at turn #${n.find(P)?.sequence}`:"none"})]}):e.jsx(A,{w:"100%",h:"80px"}),e.jsx(w,{title:"Session shape",sub:"tokens per turn · click to jump",right:e.jsx(K,{names:["fresh + output","cache read","tool error"],colors:["#3987e5","#1f3c63","#d03b3b"]}),children:n.length?e.jsxs(e.Fragment,{children:[e.jsx(Q,{turns:n,onPick:y,active:a}),e.jsx("div",{className:"mt-2",children:e.jsx(ie,{labels:p,series:c,format:i=>i===0?"$0":M(i),height:110})})]}):d.isLoading?e.jsx(A,{w:"100%",h:"96px"}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No turns recorded."})}),o==="overview"&&r&&e.jsx(de,{session:r,turns:n}),o==="timeline"&&e.jsx(V,{id:t,turns:n,active:a}),o==="subagents"&&e.jsx(he,{subs:l.data??[]})]})]})}export{Se as default};
1
+ import{r as g,j as e,I as T,t as S,R as C,n as f,T as D,L as X,p as B,e as M,P as F,S as A,U as Y,V as Z,c as G,X as J,Y as ee,d as te}from"./index-kRaX6JLH.js";import{P as w,T as L,a as q}from"./Panel-rzVYig0L.js";import{S as H,E as se}from"./ErrorPanel-lb1Tt_Cg.js";import{T as _}from"./Tile-BlnGo9bN.js";import{P as E}from"./Button-BY-h2O0Z.js";import{r as ne,b as re,c as z}from"./agents-CDuRxAZi.js";import{a as R,b as O,c as P,d as oe,e as ae,o as W,T as V,f as le}from"./TimelineTab-Cwp4_Kwm.js";import{A as ie}from"./AreaLine-BKfPVgnO.js";import{L as K}from"./uplotTheme-Dv4lAb8e.js";import{B as U}from"./Bars-CwquOD-V.js";import{C as ce}from"./Chip-C_zmBEC6.js";import"./cumulative-C3-3HW0n.js";function I({value:t,chars:a=8}){const[m,x]=g.useState(!1),d=t.includes(":")?t.slice(t.indexOf(":")+1):t,l=async()=>{try{await navigator.clipboard.writeText(d),x(!0),setTimeout(()=>x(!1),1400)}catch{window.prompt("Copy the session id",d)}};return e.jsxs("button",{type:"button",onClick:l,title:(()=>{const o=ne(re(t),d);return`Session id ${d}
2
+ Click to copy${o?` (use with: ${o})`:""}`})(),className:`inline-flex items-center gap-1.5 font-mono text-[11px] px-1.5 h-5 rounded-sm border transition-colors ${m?"text-good border-good/40 bg-good/10":"text-ink-1 bg-bg-3 border-transparent hover:border-line-2 hover:text-ink-0"}`,children:[m?e.jsx(T,{name:"check",size:10}):null,m?"copied":a?d.slice(0,a):"copy"]})}function Q({turns:t,onPick:a,active:m}){const x=Math.max(1,t.length),d=1160,l=96,o=80,u=(d-8)/x,n=Math.max(2,Math.min(46,u-3)),h=Math.max(1,...t.map(R)),b=x>60?10:5;return e.jsxs("svg",{width:"100%",viewBox:`0 0 ${d} ${l}`,role:"img","aria-label":"Tokens per turn",className:"block w-full",style:{aspectRatio:`${d} / ${l}`},children:[e.jsx("line",{x1:0,y1:o,x2:d,y2:o,stroke:"#232934"}),t.map((c,p)=>{const j=4+p*u,y=R(c)/h*70,$=O(c)/h*70,r=P(c);return e.jsxs("g",{"data-turn":c.sequence,onClick:()=>a(c.sequence),className:"cursor-pointer",children:[e.jsx("title",{children:`#${c.sequence} · ${S(O(c))} fresh+output · ${S(c.cache_read_tokens)} cache read`}),m===c.sequence&&e.jsx("rect",{x:j-2,y:2,width:n+4,height:o-2,fill:"none",stroke:"#f0883e"}),e.jsx("rect",{x:j,y:o-y,width:n,height:y,fill:"#1f3c63"}),e.jsx("rect",{"data-kind":"top",x:j,y:o-y,width:n,height:Math.max(2,$),rx:1,fill:r?"#d03b3b":"#3987e5"}),(p%b===0||p===t.length-1)&&e.jsx("text",{x:j+n/2,y:l-2,fontSize:10,textAnchor:"middle",fill:r?"#ff7a7a":"#667184",fontFamily:"var(--font-mono)",children:c.sequence})]},c.sequence)})]})}function de({session:t,turns:a}){const m=Intl.DateTimeFormat().resolvedOptions().timeZone,x=[["Project",t.project_path],["Primary model",t.primary_model],[z(t.agent),t.agent_version??"—"],["Started",`${C(t.started_at)} (${m})`],["Ended",t.ended_at?C(t.ended_at):"running"],["Fresh input",`${f(t.total_fresh_input_tokens)} tokens`],["Output",`${f(t.total_output_tokens)} tokens`],["Cache writes",`${f(t.total_cache_write_tokens)} tokens`],["Cache reads",`${f(t.total_cache_read_tokens)} tokens`],["Pricing version",t.pricing_table_version]],d=oe(a);return e.jsxs("div",{className:"grid grid-cols-[1fr_1fr] gap-3",children:[e.jsx(w,{title:"Session",padded:!1,children:e.jsxs("dl",{className:"grid grid-cols-[140px_1fr] text-xs m-0",children:[x.map(([l,o])=>e.jsxs("div",{className:"contents",children:[e.jsx("dt",{className:"px-3.5 py-2 border-b border-line text-ink-1",children:l}),e.jsx("dd",{className:"px-3.5 py-2 border-b border-line font-mono m-0 break-all",children:o})]},l)),e.jsxs("div",{className:"contents",children:[e.jsx("dt",{className:"px-3.5 py-2 border-b border-line text-ink-1",children:"Session id"}),e.jsxs("dd",{className:"px-3.5 py-2 border-b border-line font-mono m-0 break-all flex items-center gap-2",children:[e.jsx("span",{children:t.id}),e.jsx(I,{value:t.id,chars:0})]})]})]})}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(w,{title:"Tool mix",sub:"calls · red segment = errors",children:d.length?e.jsx(U,{rows:d,format:f}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No tool calls."})}),e.jsx(w,{title:"Cache ratio per turn",sub:"share of each turn read from cache",children:e.jsx("svg",{className:"block w-full",viewBox:"0 0 1000 48",preserveAspectRatio:"none",style:{aspectRatio:"1000 / 48"},role:"img","aria-label":"Cache ratio per turn",children:a.map((l,o)=>{const u=1e3/Math.max(1,a.length),n=ae(l);return e.jsxs("g",{children:[e.jsx("title",{children:`#${l.sequence} · ${Math.round(n*100)}%`}),e.jsx("rect",{x:o*u,y:0,width:Math.max(.5,u-.5),height:48,fill:"#1d222c"}),e.jsx("rect",{x:o*u,y:48-n*48,width:Math.max(.5,u-.5),height:n*48,fill:"#3987e5"})]},l.sequence)})})})]})]})}const v=t=>t.total_tokens??t.tokens.fresh_input+t.tokens.output+t.tokens.cache_read+t.tokens.cache_write,xe=t=>t.tool_calls??t.tools.reduce((a,m)=>a+m.count,0);function me({subs:t,selected:a,onPick:m}){const l=Math.max(1,t.length),o=300/l,u=Math.max(1,o-(l>80?.5:1)),n=Math.max(1,...t.map(v));return e.jsx("svg",{className:"block w-full",viewBox:"0 0 300 40",preserveAspectRatio:"none",style:{aspectRatio:"300 / 40"},role:"img","aria-label":"Tokens per sub-agent",children:t.map((h,b)=>{const c=Math.max(2,v(h)/n*36),p=h.id===a;return e.jsxs("g",{onClick:()=>m(h.id),className:"cursor-pointer",children:[e.jsx("title",{children:`#${b+1} · ${S(v(h))} · ${h.errors} errors`}),e.jsx("rect",{x:b*o,y:0,width:u,height:40,fill:p?"rgba(240,136,62,0.18)":"transparent"}),e.jsx("rect",{x:b*o,y:40-c,width:u,height:c,fill:h.errors?"#d03b3b":p?"#ffb177":"#3987e5"})]},h.id)})})}function ue({sa:t,index:a}){const m=D(t.id),x=g.useMemo(()=>W(m.data?.turns??[]),[m.data]),[d,l]=g.useState(),o=v(t),u=n=>{l(n),requestAnimationFrame(()=>document.getElementById(`turn-${n}`)?.scrollIntoView({block:"center"}))};return e.jsxs("div",{className:"flex flex-col gap-3 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 text-xs text-ink-1",children:[e.jsxs("span",{className:"font-mono text-ink-2",children:["#",a+1]}),e.jsx(E,{kind:t.status==="ok"?"good":"crit",children:t.status==="ok"?"OK":`${t.errors} ERR`}),e.jsx("span",{className:"font-mono text-[11px] text-ink-1 bg-bg-3 px-1.5 rounded-sm",children:t.model}),e.jsx(I,{value:t.id}),e.jsx(X,{to:"/sessions/$id",params:{id:t.id},search:{tab:"timeline"},className:"ml-auto text-[11px]",children:"Open as its own session →"})]}),e.jsxs("div",{className:"grid grid-cols-5 gap-3",children:[e.jsx(_,{label:"Tokens",value:S(o),sub:`${B(o?t.tokens.cache_read/o:0,0)} cache read`}),e.jsx(_,{label:"Estimated cost",value:M(t.cost_usd??0)}),e.jsx(_,{label:"Turns",value:f(t.turns),sub:`${f(xe(t))} tool calls`}),e.jsx(_,{label:"Duration",value:F(t.duration_sec??null)}),e.jsx(_,{label:"Tool errors",value:f(t.errors),tone:t.errors?"crit":"default",sub:t.errors?"see red turns below":"none"})]}),e.jsx(w,{title:"Task given",sub:"first user message to the sub-agent",children:t.task_given?e.jsx("p",{className:"m-0 text-xs leading-relaxed whitespace-pre-wrap break-words max-h-40 overflow-auto",children:t.task_given}):e.jsx("span",{className:"text-ink-2 text-xs",children:"Not available — enable transcript indexing in Settings to keep sub-agent prompts."})}),e.jsxs("div",{className:"grid grid-cols-[1fr_2fr] gap-3",children:[e.jsx(w,{title:"Tools used",sub:"calls · red = errors",children:t.tools.length?e.jsx(U,{rows:t.tools.map(n=>({name:n.name,value:n.count,error:n.errors})),format:f}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No tool calls recorded."})}),e.jsx(w,{title:"Sub-agent shape",sub:"tokens per turn · click to jump",right:e.jsx(K,{names:["fresh + output","cache read","tool error"],colors:["#3987e5","#1f3c63","#d03b3b"]}),children:x.length?e.jsx(Q,{turns:x,onPick:u,active:d}):m.isLoading?e.jsx(A,{w:"100%",h:"96px"}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No turns recorded."})})]}),e.jsx(V,{id:t.id,turns:x,active:d})]})}function he({subs:t}){const[a,m]=g.useState(null),[x,d]=g.useState(""),[l,o]=g.useState(!1),[u,n]=g.useState("order"),h=g.useRef(null),b=g.useMemo(()=>new Map(t.map((s,k)=>[s.id,k])),[t]),c=g.useMemo(()=>{const s=x.trim().toLowerCase(),k=t.filter(i=>(!l||i.errors>0)&&(!s||(i.task_given??"").toLowerCase().includes(s)||i.model.toLowerCase().includes(s)));return u==="tokens"&&k.sort((i,N)=>v(N)-v(i)),u==="errors"&&k.sort((i,N)=>N.errors-i.errors||v(N)-v(i)),k},[t,x,l,u]),p=t.find(s=>s.id===a)??c[0]??t[0],j=s=>{m(s),document.getElementById("page-scroll")?.scrollTo({top:0,behavior:"smooth"}),h.current?.querySelector(`[data-sa="${CSS.escape(s)}"]`)?.scrollIntoView({block:"nearest"})},y=s=>{if(!p||s.key!=="ArrowDown"&&s.key!=="ArrowUp"&&s.key!=="j"&&s.key!=="k")return;const k=c.findIndex(N=>N.id===p.id),i=c[Math.max(0,Math.min(c.length-1,k+(s.key==="ArrowDown"||s.key==="j"?1:-1)))];i&&j(i.id),s.preventDefault()};if(g.useEffect(()=>{a&&!t.some(s=>s.id===a)&&m(null)},[t,a]),!t.length)return e.jsx(w,{title:"Sub-agents",children:e.jsx("div",{className:"text-ink-2 text-center py-6",children:"This session did not spawn sub-agents."})});if(!p)return null;const $=Math.max(1,...t.map(v)),r=t.filter(s=>s.errors>0).length;return e.jsxs("div",{className:"grid grid-cols-[340px_1fr] gap-3 items-start",children:[e.jsxs(w,{title:"Sub-agents",sub:`${t.length}${r?` · ${r} with errors`:""}`,padded:!1,className:"sticky top-0 max-h-[calc(100vh-7.5rem)]",children:[e.jsxs("div",{className:"px-3.5 pt-3 pb-2 border-b border-line flex flex-col gap-2 shrink-0",children:[e.jsx(me,{subs:t,selected:p.id,onPick:j}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsxs("label",{className:"flex items-center gap-1.5 h-6 px-2 border border-line-2 rounded-md text-ink-2 flex-1 min-w-28",children:[e.jsx(T,{name:"search",size:11}),e.jsx("input",{value:x,onChange:s=>d(s.target.value),placeholder:"Filter tasks",className:"bg-transparent outline-none text-ink-0 text-[11px] w-full placeholder:text-ink-2"})]}),e.jsx(ce,{active:l,onClick:()=>o(!l),children:"Errors"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{options:[{value:"order",label:"order"},{value:"tokens",label:"tokens"},{value:"errors",label:"errors"}],value:u,onChange:n}),e.jsxs("span",{className:"ml-auto font-mono text-[10px] text-ink-2",children:["↑↓ to step · ",c.length," shown"]})]})]}),e.jsxs("div",{ref:h,tabIndex:0,onKeyDown:y,className:"overflow-auto min-h-0 flex-1 outline-none focus-visible:shadow-[inset_0_0_0_1px_var(--color-accent)]",children:[c.map(s=>{const k=b.get(s.id)??0,i=s.id===p.id;return e.jsxs("button",{type:"button","data-sa":s.id,onClick:()=>j(s.id),title:s.task_given??void 0,className:`w-full text-left px-3.5 h-[34px] border-b border-line flex items-center gap-2 hover:bg-bg-2 ${i?"bg-bg-2 shadow-[inset_2px_0_0_var(--color-accent)]":""}`,children:[e.jsxs("span",{className:"font-mono text-[11px] text-ink-2 w-8 shrink-0",children:["#",k+1]}),s.errors?e.jsxs("span",{className:"text-crit-ink inline-flex items-center gap-0.5 font-mono text-[11px] w-8 shrink-0",children:[e.jsx(T,{name:"x",size:9}),s.errors]}):e.jsx("span",{className:"text-good inline-flex items-center w-8 shrink-0",children:e.jsx(T,{name:"check",size:10})}),e.jsx("span",{className:"text-[11px] text-ink-1 truncate flex-1 min-w-0",children:s.task_given?s.task_given.replace(/\s+/g," "):e.jsx("span",{className:"text-ink-2",children:s.model})}),e.jsx("span",{className:"relative h-1.5 w-14 shrink-0 rounded-sm bg-bg-3 overflow-hidden",children:e.jsx("i",{className:"absolute inset-y-0 left-0 bg-s1 rounded-r-sm",style:{width:`${v(s)/$*100}%`}})}),e.jsx("span",{className:"font-mono num text-[11px] w-12 text-right shrink-0",children:S(v(s))})]},s.id)}),c.length===0&&e.jsx("div",{className:"text-ink-2 text-center py-6 text-xs",children:"No sub-agents match."})]})]}),e.jsx(ue,{sa:p,index:b.get(p.id)??0},p.id)]})}function Se(){const{id:t}=Y({from:"/sessions/$id"}),{tab:a}=Z({from:"/sessions/$id"}),m=G(),x=J(t),d=D(t),l=ee(t),[o,u]=g.useState(),n=g.useMemo(()=>W(d.data?.turns??[]),[d.data]),h=n.filter(P).length,b=g.useMemo(()=>le(n),[n]),c=g.useMemo(()=>[{name:"cumulative cost",values:b}],[b]),p=g.useMemo(()=>n.map(i=>`#${i.sequence}`),[n]),j=i=>m({to:"/sessions/$id",params:{id:t},search:{tab:i}}),y=i=>{u(i),a!=="timeline"&&j("timeline"),requestAnimationFrame(()=>document.getElementById(`turn-${i}`)?.scrollIntoView({block:"center"}))},$=["Analyze",{label:"Sessions",to:"/sessions"},x.data?te(x.data.session.project_path,30):"…"];if(x.error)return e.jsxs(e.Fragment,{children:[e.jsx(L,{crumbs:[...$]}),e.jsx(q,{children:e.jsx(se,{error:x.error})})]});const r=x.data?.session,s=r?r.total_fresh_input_tokens+r.total_output_tokens+r.total_cache_read_tokens+r.total_cache_write_tokens:0,k=n.reduce((i,N)=>i+N.tool_calls.length,0);return e.jsxs(e.Fragment,{children:[e.jsxs(L,{crumbs:[...$],children:[e.jsx(I,{value:t}),e.jsx(H,{options:[{value:"overview",label:"Overview"},{value:"timeline",label:"Timeline"},{value:"subagents",label:`Sub-agents · ${l.data?.length??0}`}],value:a,onChange:j}),r&&e.jsx(E,{kind:"mute",children:r.primary_model}),r?.agent_version&&e.jsxs(E,{kind:"mute",children:[z(r.agent)," ",r.agent_version]})]}),e.jsxs(q,{children:[r?e.jsxs("div",{className:"grid grid-cols-5 gap-3",children:[e.jsx(_,{label:"Tokens",value:S(s),sub:`${f(s)} · ${B(s?r.total_cache_read_tokens/s:0,0)} cache read`}),e.jsx(_,{label:"Estimated cost",value:M(r.total_cost_usd),sub:r.turn_count?`${M(r.total_cost_usd/r.turn_count)} / turn`:void 0}),e.jsx(_,{label:"Turns",value:n.length?f(n.length):f(r.turn_count),sub:`${f(k)} tool calls`,note:n.length&&n.length!==r.turn_count?`${f(r.turn_count)} raw`:void 0}),e.jsx(_,{label:"Duration",value:r.ended_at?F(r.duration_sec):"live",sub:C(r.started_at)}),e.jsx(_,{label:"Tool errors",value:String(h),tone:h?"crit":"default",sub:h?`first at turn #${n.find(P)?.sequence}`:"none"})]}):e.jsx(A,{w:"100%",h:"80px"}),e.jsx(w,{title:"Session shape",sub:"tokens per turn · click to jump",right:e.jsx(K,{names:["fresh + output","cache read","tool error"],colors:["#3987e5","#1f3c63","#d03b3b"]}),children:n.length?e.jsxs(e.Fragment,{children:[e.jsx(Q,{turns:n,onPick:y,active:o}),e.jsx("div",{className:"mt-2",children:e.jsx(ie,{labels:p,series:c,format:i=>i===0?"$0":M(i),height:110})})]}):d.isLoading?e.jsx(A,{w:"100%",h:"96px"}):e.jsx("div",{className:"text-ink-2 text-center py-4",children:"No turns recorded."})}),a==="overview"&&r&&e.jsx(de,{session:r,turns:n}),a==="timeline"&&e.jsx(V,{id:t,turns:n,active:o}),a==="subagents"&&e.jsx(he,{subs:l.data??[]})]})]})}export{Se as default};