clawmetry 0.12.485__tar.gz → 0.12.487__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 (533) hide show
  1. {clawmetry-0.12.485 → clawmetry-0.12.487}/CHANGELOG.md +5 -0
  2. {clawmetry-0.12.485/clawmetry.egg-info → clawmetry-0.12.487}/PKG-INFO +1 -1
  3. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/local_store.py +19 -17
  4. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/app.js +12 -12
  5. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/sync.py +7 -6
  6. {clawmetry-0.12.485 → clawmetry-0.12.487/clawmetry.egg-info}/PKG-INFO +1 -1
  7. {clawmetry-0.12.485 → clawmetry-0.12.487}/dashboard.py +21 -3
  8. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/local_query.py +9 -0
  9. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_model_rollup_uncapped.py +5 -5
  10. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_spans_otlp_edge_cases.py +64 -0
  11. {clawmetry-0.12.485 → clawmetry-0.12.487}/ARCHITECTURE.md +0 -0
  12. {clawmetry-0.12.485 → clawmetry-0.12.487}/CLAUDE.md +0 -0
  13. {clawmetry-0.12.485 → clawmetry-0.12.487}/LICENSE +0 -0
  14. {clawmetry-0.12.485 → clawmetry-0.12.487}/MANIFEST.in +0 -0
  15. {clawmetry-0.12.485 → clawmetry-0.12.487}/README.md +0 -0
  16. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/__init__.py +0 -0
  17. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/__main__.py +0 -0
  18. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/_gate.py +0 -0
  19. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/__init__.py +0 -0
  20. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/base.py +0 -0
  21. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/nemo.py +0 -0
  22. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/openclaw.py +0 -0
  23. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/registry.py +0 -0
  24. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/alert_evaluator.py +0 -0
  25. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/approvals.py +0 -0
  26. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/audit.py +0 -0
  27. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/blueprints/__init__.py +0 -0
  28. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/ccr.py +0 -0
  29. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/cli.py +0 -0
  30. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/config.py +0 -0
  31. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/connector_health.py +0 -0
  32. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/dives_prompt.py +0 -0
  33. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/dives_sql_safety.py +0 -0
  34. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/entitlements.py +0 -0
  35. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/error_patterns.py +0 -0
  36. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/error_signal.py +0 -0
  37. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/eval_regression_replay.py +0 -0
  38. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/eval_runner.py +0 -0
  39. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/eval_suite_runner.py +0 -0
  40. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/evaluators.py +0 -0
  41. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/extensions.py +0 -0
  42. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/gateway_tap.py +0 -0
  43. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/harness_templates.py +0 -0
  44. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/insights.py +0 -0
  45. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/interceptor.py +0 -0
  46. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/latency_tracker.py +0 -0
  47. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/license.py +0 -0
  48. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/local_server.py +0 -0
  49. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/otel_exporter.py +0 -0
  50. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/otel_push.py +0 -0
  51. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/outcome_classifier.py +0 -0
  52. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/__init__.py +0 -0
  53. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/base.py +0 -0
  54. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/local.py +0 -0
  55. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/turso.py +0 -0
  56. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers_pricing.py +0 -0
  57. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/proxy.py +0 -0
  58. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/py.typed +0 -0
  59. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/redaction.py +0 -0
  60. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/relay.py +0 -0
  61. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/resources/add-nemoclaw-clawmetry-preset.sh +0 -0
  62. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/risk.py +0 -0
  63. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/siem.py +0 -0
  64. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/css/dashboard.css +0 -0
  65. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/img/logo.svg +0 -0
  66. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/alerts.js +0 -0
  67. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/auth-bootstrap.js +0 -0
  68. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/dives.js +0 -0
  69. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/gw-setup.js +0 -0
  70. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/i18n.js +0 -0
  71. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/nav-dropdown.js +0 -0
  72. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/_glossary.json +0 -0
  73. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/_meta.json +0 -0
  74. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ar.json +0 -0
  75. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/bn.json +0 -0
  76. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/de.json +0 -0
  77. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/el.json +0 -0
  78. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/en.json +0 -0
  79. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/es-419.json +0 -0
  80. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/es.json +0 -0
  81. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/fa.json +0 -0
  82. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/fil.json +0 -0
  83. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/fr.json +0 -0
  84. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/gu.json +0 -0
  85. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/he.json +0 -0
  86. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/hi.json +0 -0
  87. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/id.json +0 -0
  88. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/it.json +0 -0
  89. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ja.json +0 -0
  90. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/kn.json +0 -0
  91. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ko.json +0 -0
  92. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ml.json +0 -0
  93. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/mr.json +0 -0
  94. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/nl.json +0 -0
  95. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pa.json +0 -0
  96. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pl.json +0 -0
  97. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pt-BR.json +0 -0
  98. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pt-PT.json +0 -0
  99. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ru.json +0 -0
  100. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/sv.json +0 -0
  101. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ta.json +0 -0
  102. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/te.json +0 -0
  103. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/th.json +0 -0
  104. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/tr.json +0 -0
  105. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/uk.json +0 -0
  106. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ur.json +0 -0
  107. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/vi.json +0 -0
  108. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/zh-CN.json +0 -0
  109. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/zh-TW.json +0 -0
  110. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/v2/dist/assets/index-Dtt_uBk_.js +0 -0
  111. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/v2/dist/assets/index-NbINX9rU.css +0 -0
  112. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/v2/dist/index.html +0 -0
  113. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/telemetry.py +0 -0
  114. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/README.md +0 -0
  115. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/banners.html +0 -0
  116. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/budget-modal.html +0 -0
  117. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/cloud-modal.html +0 -0
  118. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/overlays.html +0 -0
  119. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/paywall_modal.html +0 -0
  120. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/alerts.html +0 -0
  121. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/approvals.html +0 -0
  122. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/brain.html +0 -0
  123. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/clusters.html +0 -0
  124. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/context-economics.html +0 -0
  125. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/context.html +0 -0
  126. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/crons.html +0 -0
  127. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/dives.html +0 -0
  128. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/flow.html +0 -0
  129. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/harness.html +0 -0
  130. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/history.html +0 -0
  131. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/inventory.html +0 -0
  132. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/logs.html +0 -0
  133. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/memory.html +0 -0
  134. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/models.html +0 -0
  135. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/nemoclaw.html +0 -0
  136. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/notifications.html +0 -0
  137. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/overview.html +0 -0
  138. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/policy.html +0 -0
  139. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/security.html +0 -0
  140. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/selfevolve.html +0 -0
  141. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/skills.html +0 -0
  142. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/subagents.html +0 -0
  143. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/swimlane.html +0 -0
  144. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/tool-catalog.html +0 -0
  145. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/tracing.html +0 -0
  146. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/transcripts.html +0 -0
  147. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/turn-anatomy.html +0 -0
  148. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/usage.html +0 -0
  149. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/version-impact.html +0 -0
  150. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/__init__.py +0 -0
  151. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/e2e/__init__.py +0 -0
  152. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/e2e/test_cloud_sync_resilience.py +0 -0
  153. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/integration/__init__.py +0 -0
  154. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/integration/test_fast_paths_cross_process.py +0 -0
  155. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/token_confidence.py +0 -0
  156. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/track.py +0 -0
  157. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/v2/__init__.py +0 -0
  158. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/v2/routes.py +0 -0
  159. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/waste_flags.py +0 -0
  160. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/SOURCES.txt +0 -0
  161. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/dependency_links.txt +0 -0
  162. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/entry_points.txt +0 -0
  163. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/requires.txt +0 -0
  164. {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/top_level.txt +0 -0
  165. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/__init__.py +0 -0
  166. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/gateway.py +0 -0
  167. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/hardware.py +0 -0
  168. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/logs.py +0 -0
  169. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/openapi.py +0 -0
  170. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/pricing.py +0 -0
  171. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/streams.py +0 -0
  172. {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/system.py +0 -0
  173. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/__init__.py +0 -0
  174. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/_dedupe.py +0 -0
  175. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/advisor.py +0 -0
  176. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/agents.py +0 -0
  177. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/alerts.py +0 -0
  178. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/assets.py +0 -0
  179. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/audit.py +0 -0
  180. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/autonomy.py +0 -0
  181. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/bootstrap.py +0 -0
  182. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/brain.py +0 -0
  183. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/channels.py +0 -0
  184. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/components.py +0 -0
  185. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/context_economics.py +0 -0
  186. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/crons.py +0 -0
  187. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/device.py +0 -0
  188. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/dives.py +0 -0
  189. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/entitlement.py +0 -0
  190. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/evals.py +0 -0
  191. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/fleet_history.py +0 -0
  192. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/harness.py +0 -0
  193. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/health.py +0 -0
  194. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/heartbeat.py +0 -0
  195. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/hitl.py +0 -0
  196. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/infra.py +0 -0
  197. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/insights.py +0 -0
  198. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/inventory.py +0 -0
  199. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/meta.py +0 -0
  200. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/nemoclaw.py +0 -0
  201. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/otel_export.py +0 -0
  202. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/overview.py +0 -0
  203. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/plugins.py +0 -0
  204. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/policy.py +0 -0
  205. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/reasoning.py +0 -0
  206. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/review.py +0 -0
  207. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/runtime_ingest.py +0 -0
  208. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/scheduler.py +0 -0
  209. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/selfconfig.py +0 -0
  210. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/selfevolve.py +0 -0
  211. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/sessions.py +0 -0
  212. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/skills.py +0 -0
  213. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/sla.py +0 -0
  214. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/tool_catalog.py +0 -0
  215. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/tracing.py +0 -0
  216. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/turn_anatomy.py +0 -0
  217. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/update_check.py +0 -0
  218. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/usage.py +0 -0
  219. {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/workspaces.py +0 -0
  220. {clawmetry-0.12.485 → clawmetry-0.12.487}/setup.cfg +0 -0
  221. {clawmetry-0.12.485 → clawmetry-0.12.487}/setup.py +0 -0
  222. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/__init__.py +0 -0
  223. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/_moat_perf_fixture.py +0 -0
  224. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/conftest.py +0 -0
  225. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/eval_ci_mock_agent.py +0 -0
  226. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adapter_gating.py +0 -0
  227. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adapter_registry_override.py +0 -0
  228. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adapters.py +0 -0
  229. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adaptive_heartbeat.py +0 -0
  230. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_advertised_runtimes_match_catalogue.py +0 -0
  231. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_advisor_auth_resolution.py +0 -0
  232. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_aesgcm_swallow_fix.py +0 -0
  233. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_agent_inventory.py +0 -0
  234. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_aggregate_cache.py +0 -0
  235. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_alert_evaluator_unit.py +0 -0
  236. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_alert_rules_local_store.py +0 -0
  237. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_alerts_evaluator_duckdb.py +0 -0
  238. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_anon_auth_fail_ping.py +0 -0
  239. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_api.py +0 -0
  240. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_appjs_units.py +0 -0
  241. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_approvals_duckdb_watcher.py +0 -0
  242. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_approvals_local_store.py +0 -0
  243. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_audit.py +0 -0
  244. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_audit_producers.py +0 -0
  245. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_auth_detected_token.py +0 -0
  246. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_auto_update.py +0 -0
  247. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_automation_analysis_local_store_v3.py +0 -0
  248. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_autonomy_v3_shape.py +0 -0
  249. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_backfill_family_cost.py +0 -0
  250. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_blueprint_uniqueness.py +0 -0
  251. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_bootstrap_capture.py +0 -0
  252. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_cache_push.py +0 -0
  253. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_cache_push_channel_events.py +0 -0
  254. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_clusters_local_store.py +0 -0
  255. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_history_v3_event_detail.py +0 -0
  256. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_llm_call_timeline.py +0 -0
  257. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_local_fastpath.py +0 -0
  258. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_local_store.py +0 -0
  259. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_no_log_keyword_noise.py +0 -0
  260. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_sse_reconnect.py +0 -0
  261. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_budget_cap.py +0 -0
  262. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cache_trends.py +0 -0
  263. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_ccr.py +0 -0
  264. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_bluebubbles_local_store_v3.py +0 -0
  265. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_config_local_store.py +0 -0
  266. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_event_chokepoint.py +0 -0
  267. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_signal_local_store_v3.py +0 -0
  268. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_telegram_local_store_v3.py +0 -0
  269. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_tui_duckdb_fastpath.py +0 -0
  270. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_whatsapp_duckdb_fastpath.py +0 -0
  271. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channels_local_store.py +0 -0
  272. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_circular_import.py +0 -0
  273. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_class_bug_parent_sid_drain.py +0 -0
  274. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_claude_sessions_privacy_boundary.py +0 -0
  275. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_claudecode.py +0 -0
  276. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_claudecode_loads_plugins.py +0 -0
  277. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cli.py +0 -0
  278. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cli_banner.py +0 -0
  279. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_component_gateway_local_store_v3.py +0 -0
  280. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_component_tool_model_completed.py +0 -0
  281. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_component_tool_timeout.py +0 -0
  282. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_compression_potential.py +0 -0
  283. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_connector_health.py +0 -0
  284. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_context_anatomy_local_store.py +0 -0
  285. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_context_econ_per_runtime.py +0 -0
  286. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_context_window_model_aware.py +0 -0
  287. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cost_optimizer_local_store_v3.py +0 -0
  288. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cron_health.py +0 -0
  289. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cron_runs_duckdb_ingest.py +0 -0
  290. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cron_runs_events_only.py +0 -0
  291. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_crons_cache_push.py +0 -0
  292. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_crons_local_store.py +0 -0
  293. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_crons_runs_endpoint.py +0 -0
  294. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_daemon_error_event_pipeline.py +0 -0
  295. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_daemon_health_endpoint.py +0 -0
  296. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_dashboard_perf_hotfix.py +0 -0
  297. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_decoding_config_extract.py +0 -0
  298. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_delegation_tree_local_store.py +0 -0
  299. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_detected_runtimes_no_phantom.py +0 -0
  300. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_device_snapshot.py +0 -0
  301. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_device_summary_snapshot.py +0 -0
  302. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_dives_prompt.py +0 -0
  303. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_dives_sql_safety.py +0 -0
  304. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_batch_2026_05_13.py +0 -0
  305. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase2_2026_05_13.py +0 -0
  306. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase3_2026_05_13.py +0 -0
  307. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase4_channels_2026_05_13.py +0 -0
  308. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase5_channels_2026_05_13.py +0 -0
  309. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_cpu_cap.py +0 -0
  310. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_fastpath_v3_invariants.py +0 -0
  311. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_relay_integration.py +0 -0
  312. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e.py +0 -0
  313. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_browserstack.py +0 -0
  314. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_cross_repo_handoff.py +0 -0
  315. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_nightly_workflow.py +0 -0
  316. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_oss_all_tabs.py +0 -0
  317. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_oss_golden_path.py +0 -0
  318. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_real_openclaw_pipeline.py +0 -0
  319. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_telegram_brain_ingest.py +0 -0
  320. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_entitlement_api.py +0 -0
  321. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_entitlements.py +0 -0
  322. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_entitlements_catalogue.py +0 -0
  323. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_error_patterns.py +0 -0
  324. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_error_triage.py +0 -0
  325. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_judge_httpx_fallback.py +0 -0
  326. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_judge_key_store.py +0 -0
  327. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_redact_before_judge.py +0 -0
  328. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_regression_replay.py +0 -0
  329. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_runner.py +0 -0
  330. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_skip_without_key.py +0 -0
  331. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_suite_runner.py +0 -0
  332. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_evaluate_alerts_integration.py +0 -0
  333. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_evaluators_catalogue.py +0 -0
  334. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_event_id_unification_and_dedup.py +0 -0
  335. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_event_metrics_extraction.py +0 -0
  336. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_events_only_computation.py +0 -0
  337. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_extensions.py +0 -0
  338. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_fallbacks_local_store.py +0 -0
  339. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_family_runtime_ingest.py +0 -0
  340. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_first_heartbeat_onboarding.py +0 -0
  341. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_flow_events_local_store_v3.py +0 -0
  342. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_flow_runs_endpoint.py +0 -0
  343. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_flow_sse_reconnect.py +0 -0
  344. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_forward_progress.py +0 -0
  345. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_health.py +0 -0
  346. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_health_local_store_v3.py +0 -0
  347. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_metric_history.py +0 -0
  348. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_tap.py +0 -0
  349. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_tap_opt_in_banner.py +0 -0
  350. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_token_fallback.py +0 -0
  351. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_ws_handshake_client_id.py +0 -0
  352. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_hallucination_risk.py +0 -0
  353. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_harness_manifest.py +0 -0
  354. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_harness_templates.py +0 -0
  355. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_health_local_store.py +0 -0
  356. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_agent_install_piggyback.py +0 -0
  357. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_dispatch.py +0 -0
  358. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_envelope.py +0 -0
  359. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_local_store.py +0 -0
  360. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_loop_detector.py +0 -0
  361. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_relay_e2e.py +0 -0
  362. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_i18n_catalog.py +0 -0
  363. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_i18n_no_raw_codes.py +0 -0
  364. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_insights.py +0 -0
  365. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_install_script_linux_restart.py +0 -0
  366. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_install_script_no_duplicate_daemon.py +0 -0
  367. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_integrity_hash_chain.py +0 -0
  368. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_interceptor.py +0 -0
  369. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_issue_1127_ux_dead_ends.py +0 -0
  370. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_latency_tracker.py +0 -0
  371. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_license.py +0 -0
  372. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_license_api.py +0 -0
  373. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_max_bytes_auto_vacuum.py +0 -0
  374. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_query_api.py +0 -0
  375. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_query_dispatch_edge_cases.py +0 -0
  376. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_server_proxy.py +0 -0
  377. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store.py +0 -0
  378. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_concurrent_flush_1590.py +0 -0
  379. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_default_on.py +0 -0
  380. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_missing_writers.py +0 -0
  381. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_multi_agent.py +0 -0
  382. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_rename.py +0 -0
  383. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_sync_integration.py +0 -0
  384. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_log_sse_reconnect.py +0 -0
  385. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_loop_signals_integration.py +0 -0
  386. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_memory_cache_push.py +0 -0
  387. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_memory_local_store.py +0 -0
  388. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_memory_rag.py +0 -0
  389. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_bug_class_v3_event_shape_gate.py +0 -0
  390. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cloud_robustness.py +0 -0
  391. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cloud_roundtrip_e2e.py +0 -0
  392. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cloud_sync_e2e.py +0 -0
  393. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_component_tool_e2e.py +0 -0
  394. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cross_repo_version_skew.py +0 -0
  395. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_daemon_crash_recovery.py +0 -0
  396. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_event_shape_manifest_guard.py +0 -0
  397. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_live_openclaw_e2e.py +0 -0
  398. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_perf_benchmark.py +0 -0
  399. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_real_e2e.py +0 -0
  400. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_regression_1129.py +0 -0
  401. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_send_message_e2e.py +0 -0
  402. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_tier1_daemon_proxy_sweep.py +0 -0
  403. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_model_transitions_local_store_v3.py +0 -0
  404. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_multi_workspace_discovery.py +0 -0
  405. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemo_adapter.py +0 -0
  406. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemo_adapter_pro_gate.py +0 -0
  407. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemoclaw_events_metrics.py +0 -0
  408. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemoclaw_governance.py +0 -0
  409. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemoclaw_runtime_adapter.py +0 -0
  410. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_no_agent_detected_state.py +0 -0
  411. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_no_direct_get_store_in_routes.py +0 -0
  412. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_oauth_detection.py +0 -0
  413. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_obs_gap_talk_sandbox.py +0 -0
  414. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_claude_session_ingest.py +0 -0
  415. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_detection_real.py +0 -0
  416. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_list_events.py +0 -0
  417. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_session_cost_from_gw.py +0 -0
  418. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_sessions_followup.py +0 -0
  419. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_tool_catalog_kind.py +0 -0
  420. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_oss_routes_source_canary.py +0 -0
  421. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_oss_stubs_after_pro_move.py +0 -0
  422. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otel_export.py +0 -0
  423. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_logs.py +0 -0
  424. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_metrics_edge_cases.py +0 -0
  425. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_rollup_cpu_budget.py +0 -0
  426. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_traces_cost.py +0 -0
  427. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_outcome_classifier.py +0 -0
  428. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_overview_autonomy_score.py +0 -0
  429. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_overview_heartbeat.py +0 -0
  430. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_overview_local_store.py +0 -0
  431. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_pending_query_dispatch.py +0 -0
  432. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_per_agent_budget.py +0 -0
  433. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_per_runtime_filter.py +0 -0
  434. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase2_stubs.py +0 -0
  435. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase3_stubs.py +0 -0
  436. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase4_adapter_move.py +0 -0
  437. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase_2_to_5_live_e2e.py +0 -0
  438. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_plugins_invocations_local_store.py +0 -0
  439. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_pro_install_fallback.py +0 -0
  440. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_providers_pricing.py +0 -0
  441. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy.py +0 -0
  442. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_budget_abort.py +0 -0
  443. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_cache_risk.py +0 -0
  444. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_enforcement.py +0 -0
  445. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_loads_plugins.py +0 -0
  446. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_query_sessions_message_count.py +0 -0
  447. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_rate_limits_local_store_v3.py +0 -0
  448. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_read_cloud_token_fallback.py +0 -0
  449. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_real_openclaw_binary_e2e.py +0 -0
  450. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_reasoning_v3_shape.py +0 -0
  451. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_redaction.py +0 -0
  452. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_relay.py +0 -0
  453. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_reliability.py +0 -0
  454. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_retention_prune.py +0 -0
  455. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_review_queue.py +0 -0
  456. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_route_gates.py +0 -0
  457. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_routes_runtimes.py +0 -0
  458. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_run_compare.py +0 -0
  459. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_run_daemon_uniqueness.py +0 -0
  460. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_activity_status.py +0 -0
  461. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_detection_snapshot.py +0 -0
  462. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_filter_no_leak.py +0 -0
  463. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_switcher_gating.py +0 -0
  464. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_tab_capability_parity.py +0 -0
  465. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_schema_migration_failure_integrity.py +0 -0
  466. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_security_threat_heuristics.py +0 -0
  467. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_selfconfig_session_attribution.py +0 -0
  468. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_cost_intel.py +0 -0
  469. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_export.py +0 -0
  470. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_export_local_store_v3.py +0 -0
  471. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_insight.py +0 -0
  472. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_tools_local_store_v3.py +0 -0
  473. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_by_type_local_store.py +0 -0
  474. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_clusters_local_store_v3.py +0 -0
  475. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_local_fastpath.py +0 -0
  476. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_retention_cap.py +0 -0
  477. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sigterm_ring_flush.py +0 -0
  478. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_skills_fidelity_local_store.py +0 -0
  479. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_skills_fidelity_local_store_v3.py +0 -0
  480. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_skills_multi_dir_discovery.py +0 -0
  481. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_spans_e2e.py +0 -0
  482. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_spans_ingest.py +0 -0
  483. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_status_account_email.py +0 -0
  484. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_status_live.py +0 -0
  485. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_stuck_detection.py +0 -0
  486. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_stuck_heartbeat_payload.py +0 -0
  487. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subagent_attribution_v3.py +0 -0
  488. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subagents_events_only.py +0 -0
  489. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subagents_local_store_v3.py +0 -0
  490. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subscribe_queue_bounded.py +0 -0
  491. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_cloud_plan_cache.py +0 -0
  492. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_daemon_crash_recovery.py +0 -0
  493. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_family_session_limit.py +0 -0
  494. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_loads_plugins.py +0 -0
  495. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_main_block_at_eof.py +0 -0
  496. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_progress_sticky.py +0 -0
  497. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_reliability.py +0 -0
  498. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_skip_sidecar_jsonls.py +0 -0
  499. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_trial_gating.py +0 -0
  500. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_system_snapshot_dlq.py +0 -0
  501. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_task_runs_local_store_v3.py +0 -0
  502. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_telegram_gatewaylog_parser.py +0 -0
  503. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_telegram_ingest.py +0 -0
  504. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_telemetry.py +0 -0
  505. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tier1_local_store.py +0 -0
  506. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tier_pro_paywall_no_flash.py +0 -0
  507. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_attribution_local_store_v3.py +0 -0
  508. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_confidence.py +0 -0
  509. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_spike_rules.py +0 -0
  510. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_velocity_local_store_v3.py +0 -0
  511. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_alternatives.py +0 -0
  512. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_catalog_per_runtime.py +0 -0
  513. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_catalog_provenance_and_calls.py +0 -0
  514. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_modal_fastpath_2026_05_13.py +0 -0
  515. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tracing_accuracy.py +0 -0
  516. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_track.py +0 -0
  517. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_track_source.py +0 -0
  518. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_transcript_local_store.py +0 -0
  519. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_transcript_openclaw_shapes.py +0 -0
  520. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_transcripts_list_detail_count_parity.py +0 -0
  521. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_trial_copy_consistency.py +0 -0
  522. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_turn_anatomy_cost.py +0 -0
  523. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_update_banner_live_version.py +0 -0
  524. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_uptime_portable.py +0 -0
  525. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_cache_trends_local_store.py +0 -0
  526. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_forecast_local_store_v3.py +0 -0
  527. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_local_store.py +0 -0
  528. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_per_session.py +0 -0
  529. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_v3_schema_parser.py +0 -0
  530. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_verify_integrity_cli_proxy.py +0 -0
  531. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_version_impact.py +0 -0
  532. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_version_impact_local_store_v3.py +0 -0
  533. {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_workspace_switcher_copy.py +0 -0
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ### Release: OTLP spans now actually persist in production (#2896) (2026-06-08)
4
+ - **Bring-your-own-agent was silently dropped:** the /v1/traces receiver runs in the dashboard process, which does not own the DuckDB writer lock, so get_store() returns a proxy that forwards writes to the daemon but only passes keyword args. put_span was called positionally and was not in the daemon allowlist, so every OTLP span no-opped whenever a daemon runs (every real install): the POST returned 200 but nothing persisted, and a foreign OpenLLMetry/OTLP app never appeared in the runtime switcher or Agent Inventory. The OTLP test suite missed it because it forces single-process, where get_store() is the real writer.
5
+ - **Fix:** allowlist put_span in routes/local_query._DAEMON_METHODS and call put_span(span=...) by keyword so the span forwards through the proxy to the daemon writer (same pattern as set_agent_meta). A new regression test forces the proxy path the suite skipped and asserts the span forwards as a keyword plus put_span is allowlisted.
6
+ - **Verified live:** a real OpenLLMetry-shaped OTLP trace sent to a running daemon+dashboard now persists in DuckDB, surfaces via query_otlp_app_rollup with derived cost, flows into runtimeSummary + agentInventory, and renders on the hosted dashboard as an "(OTel)" agent row plus the switcher "OpenLLMetry / OTLP apps" optgroup. Before the fix: zero spans persisted.
7
+
3
8
  ### Release: OpenLLMetry/OTLP apps visible in the runtime switcher + inventory (#2871) (2026-06-08)
4
9
  - **Bring your own agent, now visible:** a foreign OpenLLMetry/OTel-instrumented app (LangChain, CrewAI, OpenAI Agents, custom) that sends OTLP traces now appears as its own entry in the global runtime switcher (under an "OpenLLMetry / OTLP apps" group) and as a real row in the Agent Inventory roster, with its cost, tokens, and session counts. Completes #2822 (which gave such apps an agent_type from service.name) and #2853 (the inventory roster).
5
10
  - **How:** the daemon's cached rollup runs one GROUP BY agent_type over the spans table for agent_types that are not one of the 12 known session-prefix runtimes (top 50 by recent activity, with a logged warning on truncation), never a per-request scan. Native runtimes still filter by session-id prefix; OTLP apps filter by agent_type, so the two paths stay disjoint and the per-runtime no-leak contract holds (extended test asserts no leak in either direction). Rides the existing runtimeSummary + agentInventory snapshot slices, so the hosted dashboard picks it up on the next version pin with no new interceptor.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clawmetry
3
- Version: 0.12.485
3
+ Version: 0.12.487
4
4
  Summary: ClawMetry - Real-time observability for 12 AI agent runtimes (OpenClaw, NVIDIA NemoClaw, Claude Code, Codex & more)
5
5
  Home-page: https://github.com/vivekchand/clawmetry
6
6
  Author: Vivek Chand
@@ -4079,32 +4079,34 @@ class LocalStore:
4079
4079
  "sessions": int(r[1] or 0),
4080
4080
  "tokens": int(r[2] or 0),
4081
4081
  "cost_usd": float(r[3] or 0.0),
4082
- "cost_today_usd": 0.0,
4083
- "tokens_today": 0,
4082
+ "cost_24h_usd": 0.0,
4083
+ "tokens_24h": 0,
4084
4084
  }
4085
- # TODAY's cost/tokens per runtime, from events with ts in the current
4086
- # UTC day. The cost_usd above is LIFETIME (all the runtime's sessions);
4087
- # the UI shows both. True per-day cost needs event-level cost+ts (which
4088
- # the cloud sessions table lacks) so it's computed here on the daemon
4089
- # and rides the snapshot. Event cost is correct post-#web-accuracy
4090
- # re-ingest (deduped + current-gen rates).
4091
- from datetime import datetime as _dt, timezone as _tz
4092
- _today = _dt.now(_tz.utc).strftime("%Y-%m-%dT00:00:00")
4093
- sql_today = f"""
4085
+ # Rolling LAST-24h cost/tokens per runtime, from events in the trailing
4086
+ # 24 hours. (A rolling window, not a calendar "today" a calendar day
4087
+ # starts at an arbitrary UTC midnight that's confusing across
4088
+ # timezones.) cost_usd above is LIFETIME (all the runtime's sessions);
4089
+ # the UI shows both. True windowed cost needs event-level cost+ts
4090
+ # (which the cloud sessions table lacks) — so it's computed here on the
4091
+ # daemon and rides the snapshot. Event cost is correct post-
4092
+ # #web-accuracy re-ingest (deduped + current-gen rates).
4093
+ from datetime import datetime as _dt, timezone as _tz, timedelta as _tdelta
4094
+ _since_24h = (_dt.now(_tz.utc) - _tdelta(hours=24)).isoformat()
4095
+ sql_24h = f"""
4094
4096
  SELECT {rt_case} AS runtime,
4095
- SUM(COALESCE(cost_usd, 0.0)) AS cost_today,
4096
- SUM(COALESCE(token_count, 0)) AS tokens_today
4097
+ SUM(COALESCE(cost_usd, 0.0)) AS cost_24h,
4098
+ SUM(COALESCE(token_count, 0)) AS tokens_24h
4097
4099
  FROM events
4098
4100
  WHERE ts >= ?
4099
4101
  GROUP BY 1
4100
4102
  """
4101
- for r in self._fetch(sql_today, list(prefixes) + [_today]):
4103
+ for r in self._fetch(sql_24h, list(prefixes) + [_since_24h]):
4102
4104
  rt = r[0] or "openclaw"
4103
4105
  b = by_runtime.setdefault(rt, {
4104
4106
  "sessions": 0, "tokens": 0, "cost_usd": 0.0,
4105
- "cost_today_usd": 0.0, "tokens_today": 0})
4106
- b["cost_today_usd"] = float(r[1] or 0.0)
4107
- b["tokens_today"] = int(r[2] or 0)
4107
+ "cost_24h_usd": 0.0, "tokens_24h": 0})
4108
+ b["cost_24h_usd"] = float(r[1] or 0.0)
4109
+ b["tokens_24h"] = int(r[2] or 0)
4108
4110
  by_runtime_model: list[dict[str, Any]] = []
4109
4111
  sql_rtm = f"""
4110
4112
  SELECT {rt_case} AS runtime,
@@ -8493,14 +8493,14 @@ async function _invFetchData() {
8493
8493
  }
8494
8494
  }
8495
8495
 
8496
- // An agent is "active/recent" (shown by default) when it's running, did work
8497
- // today (cost or tokens), or is the currently-selected runtime. Everything else
8498
- // folds under a "Show N inactive" expander so the roster reads like the device's
8499
- // calm view instead of every runtime ever used on this machine (#web-accuracy).
8496
+ // An agent is "active/recent" (shown by default) when it's running, did work in
8497
+ // the last 24h (cost or tokens), or is the currently-selected runtime. Everything
8498
+ // else folds under a "Show N inactive" expander so the roster reads like the
8499
+ // device's calm view instead of every runtime ever used here (#web-accuracy).
8500
8500
  function _invIsRecentlyActive(a, rtFilter) {
8501
8501
  return !!(a.running
8502
- || (Number(a.costTodayUsd || 0) > 0)
8503
- || (Number(a.tokensToday || 0) > 0)
8502
+ || (Number(a.cost24hUsd || 0) > 0)
8503
+ || (Number(a.tokens24h || 0) > 0)
8504
8504
  || (rtFilter !== 'all' && a.agentKey === rtFilter));
8505
8505
  }
8506
8506
 
@@ -8511,10 +8511,10 @@ function _invRosterRow(a, rtFilter) {
8511
8511
  var dot = _invAliveDot(a);
8512
8512
  var owner = _invOwnerLabel(a);
8513
8513
  var hasCost = _invHasCost(rt);
8514
- // TODAY (event-windowed) vs LIFETIME (all the runtime's sessions). The column
8515
- // used to be labeled "Cost today" but rendered the lifetime total — fixed.
8514
+ // LAST 24h (rolling, event-windowed) vs LIFETIME (all the runtime's sessions).
8515
+ // The column used to be labeled "Cost today" but rendered the lifetime total.
8516
8516
  var naTip = '<span class="inv-na" data-i18n-title="inventory.cost_na_tip" title="This runtime does not report cost yet.">--</span>';
8517
- var todayCell = hasCost ? _invFmtUsd(a.costTodayUsd) : naTip;
8517
+ var dayCell = hasCost ? _invFmtUsd(a.cost24hUsd) : naTip;
8518
8518
  var lifeCell = hasCost ? _invFmtUsd(a.costUsd) : naTip;
8519
8519
  var work = (a.sessions || 0) + ((a.sessions === 1) ? ' conversation' : ' conversations');
8520
8520
  var model = a.primaryModel || '--';
@@ -8529,7 +8529,7 @@ function _invRosterRow(a, rtFilter) {
8529
8529
  + '<td class="inv-c-doing"><span class="inv-doing ' + doing.cls + '">' + doing.txt + '</span></td>'
8530
8530
  + '<td class="inv-c-alive"><span class="inv-dot" style="background:' + dot.color + '"></span>'
8531
8531
  + '<span class="inv-alive-lbl" title="For OpenClaw and NemoClaw this is a real heartbeat; for other runtimes it means a process is running.">' + dot.label + '</span></td>'
8532
- + '<td class="inv-c-cost" title="Cost from today\'s activity (API-equivalent)">' + todayCell + '</td>'
8532
+ + '<td class="inv-c-cost" title="Cost from the last 24 hours of activity (API-equivalent)">' + dayCell + '</td>'
8533
8533
  + '<td class="inv-c-cost inv-c-cost-life" title="All-time cost across this agent\'s tracked sessions (API-equivalent)">' + lifeCell + '</td>'
8534
8534
  + '<td class="inv-c-work">' + escHtml(work) + '</td>'
8535
8535
  + '<td class="inv-c-model">' + escHtml(model) + '</td>'
@@ -8556,7 +8556,7 @@ function _invRenderRoster(inv) {
8556
8556
  + '<tr class="inv-fold-toggle" onclick="_invToggleInactive(this)">'
8557
8557
  + '<td colspan="8"><span class="inv-fold-caret">&#9656;</span> '
8558
8558
  + 'Show ' + inactive.length + ' inactive agent' + (inactive.length === 1 ? '' : 's')
8559
- + ' <span class="inv-fold-hint">(no activity today)</span></td>'
8559
+ + ' <span class="inv-fold-hint">(no activity in 24h)</span></td>'
8560
8560
  + '</tr>'
8561
8561
  + '<tbody class="inv-fold-body" style="display:none;">'
8562
8562
  + inactive.map(function (a) { return _invRosterRow(a, rtFilter); }).join('')
@@ -8570,7 +8570,7 @@ function _invRenderRoster(inv) {
8570
8570
  + '<th data-i18n="inventory.col_owner">Owner</th>'
8571
8571
  + '<th data-i18n="inventory.col_doing">Doing now</th>'
8572
8572
  + '<th data-i18n="inventory.col_alive">Alive</th>'
8573
- + '<th data-i18n="inventory.col_cost_today">Cost today</th>'
8573
+ + '<th data-i18n="inventory.col_cost_24h">Cost (24h)</th>'
8574
8574
  + '<th data-i18n="inventory.col_cost_life">Cost (lifetime)</th>'
8575
8575
  + '<th data-i18n="inventory.col_work">Work done</th>'
8576
8576
  + '<th data-i18n="inventory.col_model">Main model</th>'
@@ -10956,9 +10956,10 @@ def _build_runtime_summary(limit: int = 20000):
10956
10956
  "turns": total,
10957
10957
  "tokens": int(totals.get("tokens") or 0),
10958
10958
  "cost_usd": round(float(totals.get("cost_usd") or 0.0), 4),
10959
- # LIFETIME cost_usd above; today's slice for the dual-column UI.
10960
- "cost_today_usd": round(float(totals.get("cost_today_usd") or 0.0), 4),
10961
- "tokens_today": int(totals.get("tokens_today") or 0),
10959
+ # LIFETIME cost_usd above; rolling last-24h slice for the
10960
+ # dual-column UI.
10961
+ "cost_24h_usd": round(float(totals.get("cost_24h_usd") or 0.0), 4),
10962
+ "tokens_24h": int(totals.get("tokens_24h") or 0),
10962
10963
  "primary_model": sorted_models[0][0] if sorted_models else "",
10963
10964
  "total_turns": total,
10964
10965
  "models": models_out,
@@ -11163,9 +11164,9 @@ def _build_agent_inventory(
11163
11164
  "turns": summ.get("turns", 0),
11164
11165
  "tokens": summ.get("tokens", 0),
11165
11166
  "costUsd": round(float(summ.get("cost_usd", 0.0) or 0.0), 4),
11166
- # LIFETIME (costUsd) vs TODAY split for the dual-column roster.
11167
- "costTodayUsd": round(float(summ.get("cost_today_usd", 0.0) or 0.0), 4),
11168
- "tokensToday": summ.get("tokens_today", 0),
11167
+ # LIFETIME (costUsd) vs rolling-24h split for the dual-column roster.
11168
+ "cost24hUsd": round(float(summ.get("cost_24h_usd", 0.0) or 0.0), 4),
11169
+ "tokens24h": summ.get("tokens_24h", 0),
11169
11170
  "primaryModel": summ.get("primary_model", "") or "",
11170
11171
  # already bounded to 15 in runtime_summary; trim to 5 for size.
11171
11172
  "models": (summ.get("models") or [])[:5],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clawmetry
3
- Version: 0.12.485
3
+ Version: 0.12.487
4
4
  Summary: ClawMetry - Real-time observability for 12 AI agent runtimes (OpenClaw, NVIDIA NemoClaw, Claude Code, Codex & more)
5
5
  Home-page: https://github.com/vivekchand/clawmetry
6
6
  Author: Vivek Chand
@@ -235,7 +235,7 @@ def _otlp_service_name_to_agent_type(service_name):
235
235
  return slug or "custom"
236
236
 
237
237
 
238
- __version__ = "0.12.485"
238
+ __version__ = "0.12.487"
239
239
 
240
240
  # Extensions (Phase 2): import the plugin host now, but defer the actual
241
241
  # load_plugins() call until after the Flask app is created below so we can
@@ -2753,7 +2753,16 @@ def _process_otlp_traces(pb_data, content_encoding=None, content_type=None):
2753
2753
  # retries land as INSERT OR REPLACE without duping.
2754
2754
  if _store is not None:
2755
2755
  try:
2756
- _store.put_span(_otel_to_row(span, resource_attrs))
2756
+ # Keyword arg is REQUIRED: in the dashboard process
2757
+ # get_store() returns a _ProxyStore that forwards to the
2758
+ # daemon writer, and the proxy only forwards **kwargs
2759
+ # (positional args are dropped). With a positional span
2760
+ # the write silently no-ops and OTLP spans never persist
2761
+ # whenever the daemon owns the writer lock (i.e. every
2762
+ # real install). put_span is allowlisted in
2763
+ # routes/local_query._DAEMON_METHODS so the daemon
2764
+ # executes the real write.
2765
+ _store.put_span(span=_otel_to_row(span, resource_attrs))
2757
2766
  except Exception as e:
2758
2767
  try:
2759
2768
  import logging as _lg
@@ -10993,7 +11002,16 @@ def _process_otlp_traces(pb_data, content_encoding=None, content_type=None):
10993
11002
  # retries land as INSERT OR REPLACE without duping.
10994
11003
  if _store is not None:
10995
11004
  try:
10996
- _store.put_span(_otel_to_row(span, resource_attrs))
11005
+ # Keyword arg is REQUIRED: in the dashboard process
11006
+ # get_store() returns a _ProxyStore that forwards to the
11007
+ # daemon writer, and the proxy only forwards **kwargs
11008
+ # (positional args are dropped). With a positional span
11009
+ # the write silently no-ops and OTLP spans never persist
11010
+ # whenever the daemon owns the writer lock (i.e. every
11011
+ # real install). put_span is allowlisted in
11012
+ # routes/local_query._DAEMON_METHODS so the daemon
11013
+ # executes the real write.
11014
+ _store.put_span(span=_otel_to_row(span, resource_attrs))
10997
11015
  except Exception as e:
10998
11016
  try:
10999
11017
  import logging as _lg
@@ -569,6 +569,15 @@ _DAEMON_METHODS = frozenset({
569
569
  # ever sent OTLP traces. Daemon snapshot-path use; allowlisted so the
570
570
  # local Inventory route can read it through the proxy too.
571
571
  "query_otlp_app_rollup",
572
+ # OTLP span WRITE-through. The /v1/traces receiver runs in the dashboard
573
+ # process, which does not own the DuckDB writer; get_store() returns a
574
+ # _ProxyStore that forwards put_span here so the daemon (the writer) does
575
+ # the real INSERT. Without this allowlist entry the proxy 400s and the span
576
+ # silently vanishes, so a "bring your own agent" OTLP app never persists or
577
+ # appears in the switcher / Inventory. Same write-through-proxy pattern as
578
+ # set_agent_meta. The handler calls put_span(span=...) by keyword (the proxy
579
+ # only forwards kwargs).
580
+ "put_span",
572
581
  # Issue #1364 (Tier-1 2026-05-15): /api/fallbacks model/provider
573
582
  # transition aggregator. Replaces a JSONL walker that opened up to 100
574
583
  # transcript files per request — multi-second on a busy workspace.
@@ -138,19 +138,19 @@ def test_rollup_includes_every_runtime_with_exact_totals(store):
138
138
  assert round(by_rt["claude_code"]["cost_usd"], 2) == 4.00
139
139
 
140
140
 
141
- def test_rollup_carries_today_cost_split(store):
142
- """by_runtime carries a TODAY slice (events in the current UTC day) distinct
143
- from the LIFETIME cost_usd — the dual-column 'Your agents' view."""
141
+ def test_rollup_carries_24h_cost_split(store):
142
+ """by_runtime carries a rolling LAST-24h slice (events in the trailing 24h)
143
+ distinct from the LIFETIME cost_usd — the dual-column 'Your agents' view."""
144
144
  from datetime import datetime, timezone
145
145
  now = datetime.now(timezone.utc).timestamp()
146
- old = now - 5 * 86400 # 5 days ago → counts toward lifetime, not today
146
+ old = now - 5 * 86400 # 5 days ago → counts toward lifetime, not the 24h window
147
147
  _seed(store, "claude_code:c1", "claude-opus-4-8", now - 60, cost=2.0, eid="t1")
148
148
  _seed(store, "claude_code:c1", "claude-opus-4-8", old, cost=8.0, eid="t2")
149
149
  _seed_session(store, "claude_code:c1", tokens=100, cost=10.0)
150
150
  _wait_flush(store)
151
151
  roll = store.query_model_rollup()
152
152
  cc = roll["by_runtime"]["claude_code"]
153
- assert round(cc["cost_today_usd"], 2) == 2.0, "today = only today's events"
153
+ assert round(cc["cost_24h_usd"], 2) == 2.0, "24h = only the last 24h of events"
154
154
  assert round(cc["cost_usd"], 2) == 10.0, "lifetime = the session total"
155
155
 
156
156
 
@@ -674,3 +674,67 @@ def test_openllmetry_openai_chat_shape_end_to_end(app):
674
674
  sp_body = _spans(c, "?session_id=conv-xyz-789&limit=10")
675
675
  assert sp_body["count"] == 1
676
676
  assert sp_body["spans"][0]["span_id"] == _hx(0x90)
677
+
678
+
679
+ class _RecordingProxy:
680
+ """Stand-in for the dashboard-process _ProxyStore: records every method
681
+ call (args + kwargs) and no-ops, mirroring how the real proxy forwards to
682
+ the daemon. Crucially it lets us assert the OTLP receiver passes the span
683
+ by KEYWORD (the real proxy drops positional args)."""
684
+
685
+ def __init__(self):
686
+ self.calls = []
687
+
688
+ def __getattr__(self, name):
689
+ def _f(*a, **k):
690
+ self.calls.append((name, a, k))
691
+ return None
692
+ return _f
693
+
694
+
695
+ @pytest.mark.skipif(_ts_pb2 is None, reason="opentelemetry-proto not installed")
696
+ def test_otlp_span_write_forwards_through_daemon_proxy(monkeypatch):
697
+ """Regression (caught live 2026-06-08): when the daemon owns the DuckDB
698
+ writer, the dashboard's get_store() returns a _ProxyStore that ONLY
699
+ forwards **kwargs (positional args are dropped). The OTLP /v1/traces
700
+ receiver therefore MUST call put_span(span=...) by keyword, and put_span
701
+ MUST be in routes.local_query._DAEMON_METHODS, or every OTLP span silently
702
+ no-ops and a bring-your-own-agent (OpenLLMetry) app never persists or shows
703
+ up in the runtime switcher / Agent Inventory. The other tests in this file
704
+ force single-process (`_daemon_registered` -> False), which is exactly why
705
+ they missed this; here we force the proxy path."""
706
+ import importlib
707
+ import clawmetry.local_store as ls
708
+ importlib.reload(ls)
709
+ rec = _RecordingProxy()
710
+ monkeypatch.setattr(ls, "get_store", lambda *a, **k: rec)
711
+
712
+ import dashboard as _d
713
+ pb = _build_pb(
714
+ [{
715
+ "span_id_hex": "1111111111111111",
716
+ "name": "openai.chat",
717
+ "start_ts": time.time(),
718
+ "str_attrs": {"gen_ai.system": "openai", "gen_ai.request.model": "gpt-4o"},
719
+ "int_attrs": {
720
+ "gen_ai.usage.input_tokens": 1200,
721
+ "gen_ai.usage.output_tokens": 350,
722
+ },
723
+ }],
724
+ service_name="my-langchain-app",
725
+ )
726
+ _d._process_otlp_traces(pb)
727
+
728
+ put_calls = [c for c in rec.calls if c[0] == "put_span"]
729
+ assert put_calls, "put_span was never called by the OTLP receiver"
730
+ _name, args, kwargs = put_calls[0]
731
+ # The real proxy drops positional args; the span MUST ride as a keyword.
732
+ assert not args, f"positional put_span args are dropped by the proxy: {args!r}"
733
+ assert "span" in kwargs, "put_span must be called as put_span(span=...)"
734
+ row = kwargs["span"]
735
+ # service.name -> per-app agent_type (the bring-your-own-agent identity).
736
+ assert row.get("agent_type") == "my_langchain_app", row.get("agent_type")
737
+
738
+ # And the daemon must accept the write, or the proxy 400s -> silent drop.
739
+ import routes.local_query as lq
740
+ assert "put_span" in lq._DAEMON_METHODS
File without changes
File without changes
File without changes
File without changes