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.
- {clawmetry-0.12.485 → clawmetry-0.12.487}/CHANGELOG.md +5 -0
- {clawmetry-0.12.485/clawmetry.egg-info → clawmetry-0.12.487}/PKG-INFO +1 -1
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/local_store.py +19 -17
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/app.js +12 -12
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/sync.py +7 -6
- {clawmetry-0.12.485 → clawmetry-0.12.487/clawmetry.egg-info}/PKG-INFO +1 -1
- {clawmetry-0.12.485 → clawmetry-0.12.487}/dashboard.py +21 -3
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/local_query.py +9 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_model_rollup_uncapped.py +5 -5
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_spans_otlp_edge_cases.py +64 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/ARCHITECTURE.md +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/CLAUDE.md +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/LICENSE +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/MANIFEST.in +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/README.md +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/__main__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/_gate.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/base.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/nemo.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/openclaw.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/adapters/registry.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/alert_evaluator.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/approvals.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/audit.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/blueprints/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/ccr.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/cli.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/config.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/connector_health.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/dives_prompt.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/dives_sql_safety.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/entitlements.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/error_patterns.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/error_signal.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/eval_regression_replay.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/eval_runner.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/eval_suite_runner.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/evaluators.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/extensions.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/gateway_tap.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/harness_templates.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/insights.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/interceptor.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/latency_tracker.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/license.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/local_server.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/otel_exporter.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/otel_push.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/outcome_classifier.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/base.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/local.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers/turso.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/providers_pricing.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/proxy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/py.typed +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/redaction.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/relay.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/resources/add-nemoclaw-clawmetry-preset.sh +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/risk.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/siem.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/css/dashboard.css +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/img/logo.svg +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/alerts.js +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/auth-bootstrap.js +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/dives.js +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/gw-setup.js +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/i18n.js +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/js/nav-dropdown.js +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/_glossary.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/_meta.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ar.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/bn.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/de.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/el.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/en.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/es-419.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/es.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/fa.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/fil.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/fr.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/gu.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/he.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/hi.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/id.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/it.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ja.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/kn.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ko.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ml.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/mr.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/nl.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pa.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pl.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pt-BR.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/pt-PT.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ru.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/sv.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ta.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/te.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/th.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/tr.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/uk.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/ur.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/vi.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/zh-CN.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/locales/zh-TW.json +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/v2/dist/assets/index-Dtt_uBk_.js +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/v2/dist/assets/index-NbINX9rU.css +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/v2/dist/index.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/telemetry.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/README.md +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/banners.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/budget-modal.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/cloud-modal.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/overlays.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/partials/paywall_modal.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/alerts.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/approvals.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/brain.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/clusters.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/context-economics.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/context.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/crons.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/dives.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/flow.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/harness.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/history.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/inventory.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/logs.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/memory.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/models.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/nemoclaw.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/notifications.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/overview.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/policy.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/security.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/selfevolve.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/skills.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/subagents.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/swimlane.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/tool-catalog.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/tracing.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/transcripts.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/turn-anatomy.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/usage.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/templates/tabs/version-impact.html +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/e2e/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/e2e/test_cloud_sync_resilience.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/integration/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/tests/integration/test_fast_paths_cross_process.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/token_confidence.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/track.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/v2/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/v2/routes.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/waste_flags.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/SOURCES.txt +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/dependency_links.txt +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/entry_points.txt +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/requires.txt +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry.egg-info/top_level.txt +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/gateway.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/hardware.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/logs.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/openapi.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/pricing.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/streams.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/helpers/system.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/_dedupe.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/advisor.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/agents.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/alerts.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/assets.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/audit.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/autonomy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/bootstrap.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/brain.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/channels.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/components.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/context_economics.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/crons.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/device.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/dives.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/entitlement.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/evals.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/fleet_history.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/harness.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/health.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/heartbeat.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/hitl.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/infra.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/insights.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/inventory.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/meta.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/nemoclaw.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/otel_export.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/overview.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/plugins.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/policy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/reasoning.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/review.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/runtime_ingest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/scheduler.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/selfconfig.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/selfevolve.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/sessions.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/skills.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/sla.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/tool_catalog.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/tracing.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/turn_anatomy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/update_check.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/usage.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/routes/workspaces.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/setup.cfg +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/setup.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/__init__.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/_moat_perf_fixture.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/conftest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/eval_ci_mock_agent.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adapter_gating.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adapter_registry_override.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adapters.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_adaptive_heartbeat.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_advertised_runtimes_match_catalogue.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_advisor_auth_resolution.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_aesgcm_swallow_fix.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_agent_inventory.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_aggregate_cache.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_alert_evaluator_unit.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_alert_rules_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_alerts_evaluator_duckdb.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_anon_auth_fail_ping.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_api.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_appjs_units.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_approvals_duckdb_watcher.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_approvals_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_audit.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_audit_producers.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_auth_detected_token.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_auto_update.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_automation_analysis_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_autonomy_v3_shape.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_backfill_family_cost.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_blueprint_uniqueness.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_bootstrap_capture.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_cache_push.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_cache_push_channel_events.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_clusters_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_history_v3_event_detail.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_llm_call_timeline.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_local_fastpath.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_no_log_keyword_noise.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_brain_sse_reconnect.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_budget_cap.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cache_trends.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_ccr.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_bluebubbles_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_config_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_event_chokepoint.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_signal_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_telegram_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_tui_duckdb_fastpath.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channel_whatsapp_duckdb_fastpath.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_channels_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_circular_import.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_class_bug_parent_sid_drain.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_claude_sessions_privacy_boundary.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_claudecode.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_claudecode_loads_plugins.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cli.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cli_banner.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_component_gateway_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_component_tool_model_completed.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_component_tool_timeout.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_compression_potential.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_connector_health.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_context_anatomy_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_context_econ_per_runtime.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_context_window_model_aware.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cost_optimizer_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cron_health.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cron_runs_duckdb_ingest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_cron_runs_events_only.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_crons_cache_push.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_crons_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_crons_runs_endpoint.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_daemon_error_event_pipeline.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_daemon_health_endpoint.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_dashboard_perf_hotfix.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_decoding_config_extract.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_delegation_tree_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_detected_runtimes_no_phantom.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_device_snapshot.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_device_summary_snapshot.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_dives_prompt.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_dives_sql_safety.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_batch_2026_05_13.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase2_2026_05_13.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase3_2026_05_13.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase4_channels_2026_05_13.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_coverage_phase5_channels_2026_05_13.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_cpu_cap.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_fastpath_v3_invariants.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_duckdb_relay_integration.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_browserstack.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_cross_repo_handoff.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_nightly_workflow.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_oss_all_tabs.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_oss_golden_path.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_real_openclaw_pipeline.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_e2e_telegram_brain_ingest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_entitlement_api.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_entitlements.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_entitlements_catalogue.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_error_patterns.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_error_triage.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_judge_httpx_fallback.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_judge_key_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_redact_before_judge.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_regression_replay.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_runner.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_skip_without_key.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_eval_suite_runner.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_evaluate_alerts_integration.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_evaluators_catalogue.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_event_id_unification_and_dedup.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_event_metrics_extraction.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_events_only_computation.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_extensions.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_fallbacks_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_family_runtime_ingest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_first_heartbeat_onboarding.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_flow_events_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_flow_runs_endpoint.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_flow_sse_reconnect.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_forward_progress.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_health.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_health_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_metric_history.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_tap.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_tap_opt_in_banner.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_token_fallback.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_gateway_ws_handshake_client_id.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_hallucination_risk.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_harness_manifest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_harness_templates.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_health_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_agent_install_piggyback.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_dispatch.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_envelope.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_loop_detector.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_heartbeat_relay_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_i18n_catalog.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_i18n_no_raw_codes.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_insights.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_install_script_linux_restart.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_install_script_no_duplicate_daemon.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_integrity_hash_chain.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_interceptor.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_issue_1127_ux_dead_ends.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_latency_tracker.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_license.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_license_api.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_max_bytes_auto_vacuum.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_query_api.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_query_dispatch_edge_cases.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_server_proxy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_concurrent_flush_1590.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_default_on.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_missing_writers.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_multi_agent.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_rename.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_local_store_sync_integration.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_log_sse_reconnect.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_loop_signals_integration.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_memory_cache_push.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_memory_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_memory_rag.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_bug_class_v3_event_shape_gate.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cloud_robustness.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cloud_roundtrip_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cloud_sync_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_component_tool_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_cross_repo_version_skew.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_daemon_crash_recovery.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_event_shape_manifest_guard.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_live_openclaw_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_perf_benchmark.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_real_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_regression_1129.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_send_message_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_moat_tier1_daemon_proxy_sweep.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_model_transitions_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_multi_workspace_discovery.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemo_adapter.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemo_adapter_pro_gate.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemoclaw_events_metrics.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemoclaw_governance.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_nemoclaw_runtime_adapter.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_no_agent_detected_state.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_no_direct_get_store_in_routes.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_oauth_detection.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_obs_gap_talk_sandbox.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_claude_session_ingest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_detection_real.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_list_events.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_session_cost_from_gw.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_sessions_followup.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_openclaw_tool_catalog_kind.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_oss_routes_source_canary.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_oss_stubs_after_pro_move.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otel_export.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_logs.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_metrics_edge_cases.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_rollup_cpu_budget.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_otlp_traces_cost.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_outcome_classifier.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_overview_autonomy_score.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_overview_heartbeat.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_overview_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_pending_query_dispatch.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_per_agent_budget.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_per_runtime_filter.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase2_stubs.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase3_stubs.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase4_adapter_move.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_phase_2_to_5_live_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_plugins_invocations_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_pro_install_fallback.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_providers_pricing.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_budget_abort.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_cache_risk.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_enforcement.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_proxy_loads_plugins.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_query_sessions_message_count.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_rate_limits_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_read_cloud_token_fallback.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_real_openclaw_binary_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_reasoning_v3_shape.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_redaction.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_relay.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_reliability.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_retention_prune.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_review_queue.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_route_gates.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_routes_runtimes.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_run_compare.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_run_daemon_uniqueness.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_activity_status.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_detection_snapshot.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_filter_no_leak.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_switcher_gating.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_runtime_tab_capability_parity.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_schema_migration_failure_integrity.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_security_threat_heuristics.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_selfconfig_session_attribution.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_cost_intel.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_export.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_export_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_insight.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_session_tools_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_by_type_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_clusters_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_local_fastpath.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sessions_retention_cap.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sigterm_ring_flush.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_skills_fidelity_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_skills_fidelity_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_skills_multi_dir_discovery.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_spans_e2e.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_spans_ingest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_status_account_email.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_status_live.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_stuck_detection.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_stuck_heartbeat_payload.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subagent_attribution_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subagents_events_only.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subagents_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_subscribe_queue_bounded.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_cloud_plan_cache.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_daemon_crash_recovery.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_family_session_limit.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_loads_plugins.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_main_block_at_eof.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_progress_sticky.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_reliability.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_skip_sidecar_jsonls.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_sync_trial_gating.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_system_snapshot_dlq.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_task_runs_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_telegram_gatewaylog_parser.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_telegram_ingest.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_telemetry.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tier1_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tier_pro_paywall_no_flash.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_attribution_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_confidence.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_spike_rules.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_token_velocity_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_alternatives.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_catalog_per_runtime.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_catalog_provenance_and_calls.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tool_modal_fastpath_2026_05_13.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_tracing_accuracy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_track.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_track_source.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_transcript_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_transcript_openclaw_shapes.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_transcripts_list_detail_count_parity.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_trial_copy_consistency.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_turn_anatomy_cost.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_update_banner_live_version.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_uptime_portable.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_cache_trends_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_forecast_local_store_v3.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_local_store.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_usage_per_session.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_v3_schema_parser.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_verify_integrity_cli_proxy.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_version_impact.py +0 -0
- {clawmetry-0.12.485 → clawmetry-0.12.487}/tests/test_version_impact_local_store_v3.py +0 -0
- {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.
|
|
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
|
-
"
|
|
4083
|
-
"
|
|
4082
|
+
"cost_24h_usd": 0.0,
|
|
4083
|
+
"tokens_24h": 0,
|
|
4084
4084
|
}
|
|
4085
|
-
#
|
|
4086
|
-
#
|
|
4087
|
-
#
|
|
4088
|
-
#
|
|
4089
|
-
#
|
|
4090
|
-
#
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
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
|
|
4096
|
-
SUM(COALESCE(token_count, 0)) AS
|
|
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(
|
|
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
|
-
"
|
|
4106
|
-
b["
|
|
4107
|
-
b["
|
|
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
|
-
//
|
|
8498
|
-
// folds under a "Show N inactive" expander so the roster reads like the
|
|
8499
|
-
// calm view instead of every runtime ever used
|
|
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.
|
|
8503
|
-
|| (Number(a.
|
|
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
|
-
//
|
|
8515
|
-
// used to be labeled "Cost today" but rendered the lifetime total
|
|
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
|
|
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
|
|
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">▸</span> '
|
|
8558
8558
|
+ 'Show ' + inactive.length + ' inactive agent' + (inactive.length === 1 ? '' : 's')
|
|
8559
|
-
+ ' <span class="inv-fold-hint">(no activity
|
|
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.
|
|
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;
|
|
10960
|
-
|
|
10961
|
-
"
|
|
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
|
|
11167
|
-
"
|
|
11168
|
-
"
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
142
|
-
"""by_runtime carries a
|
|
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
|
|
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["
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/resources/add-nemoclaw-clawmetry-preset.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clawmetry-0.12.485 → clawmetry-0.12.487}/clawmetry/static/v2/dist/assets/index-NbINX9rU.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|