@obsunified/collector 2.0.1
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.
- package/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.js +9 -0
- package/dist/auth.js.map +1 -0
- package/dist/chunk-UGWDOGGH.js +319 -0
- package/dist/chunk-UGWDOGGH.js.map +1 -0
- package/dist/chunk-XKQTVIRE.js +671 -0
- package/dist/chunk-XKQTVIRE.js.map +1 -0
- package/dist/index.d.ts +1197 -0
- package/dist/index.js +17707 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest-auth-HFVO1zIp.d.ts +165 -0
- package/dist/openai-FJYOQ7WO.js +384 -0
- package/dist/openai-FJYOQ7WO.js.map +1 -0
- package/package.json +73 -0
- package/src/ai-parity/ai-parity.acceptance.test.ts +449 -0
- package/src/analyses/derive.ts +642 -0
- package/src/analyses/index.ts +50 -0
- package/src/analyses/investigations.ts +277 -0
- package/src/analyses/tier0.ts +568 -0
- package/src/auth/dashboard-auth.ts +269 -0
- package/src/auth/ingest-auth.ts +147 -0
- package/src/durable-objects/tail-hub.test.ts +32 -0
- package/src/durable-objects/tail-hub.ts +158 -0
- package/src/framework/collector.ts +467 -0
- package/src/framework/env.ts +90 -0
- package/src/framework/logger.ts +81 -0
- package/src/index.ts +211 -0
- package/src/lib/action-aggregates.ts +1031 -0
- package/src/lib/action-identity.ts +106 -0
- package/src/lib/actions-store.ts +397 -0
- package/src/lib/ai-pricing.ts +80 -0
- package/src/lib/ai-store/calls.ts +148 -0
- package/src/lib/ai-store/evaluations.test.ts +47 -0
- package/src/lib/ai-store/evaluations.ts +125 -0
- package/src/lib/ai-store/helpers.ts +37 -0
- package/src/lib/ai-store/retention.ts +17 -0
- package/src/lib/ai-store/sessions.ts +277 -0
- package/src/lib/ai-store/spans.ts +109 -0
- package/src/lib/ai-store/types.ts +112 -0
- package/src/lib/ai-store.ts +76 -0
- package/src/lib/alerts-store.ts +458 -0
- package/src/lib/analyses-runner.ts +439 -0
- package/src/lib/analyses-store.test.ts +243 -0
- package/src/lib/analyses-store.ts +454 -0
- package/src/lib/ask.test.ts +302 -0
- package/src/lib/ask.ts +390 -0
- package/src/lib/blob-store-s3.ts +213 -0
- package/src/lib/blob-store.ts +366 -0
- package/src/lib/eval-cases-store.test.ts +171 -0
- package/src/lib/eval-cases-store.ts +1033 -0
- package/src/lib/evidence-references.test.ts +10 -0
- package/src/lib/evidence-references.ts +684 -0
- package/src/lib/hash.ts +26 -0
- package/src/lib/identity-index/action-lookups.ts +805 -0
- package/src/lib/identity-index/constants.ts +1 -0
- package/src/lib/identity-index/key-lookups.ts +199 -0
- package/src/lib/identity-index/mappers.ts +349 -0
- package/src/lib/identity-index/types.ts +196 -0
- package/src/lib/identity-index/user-lookup.ts +137 -0
- package/src/lib/identity-index.test.ts +624 -0
- package/src/lib/identity-index.ts +85 -0
- package/src/lib/json.ts +39 -0
- package/src/lib/llm.ts +263 -0
- package/src/lib/logs-store.ts +188 -0
- package/src/lib/metrics-store.test.ts +189 -0
- package/src/lib/metrics-store.ts +312 -0
- package/src/lib/narrate-gate.test.ts +260 -0
- package/src/lib/narrate-gate.ts +253 -0
- package/src/lib/openai.test.ts +300 -0
- package/src/lib/openai.ts +512 -0
- package/src/lib/otlp.ts +212 -0
- package/src/lib/parse-pprof.test.ts +64 -0
- package/src/lib/parse-pprof.ts +184 -0
- package/src/lib/payload-capture.ts +22 -0
- package/src/lib/projects-store.ts +207 -0
- package/src/lib/propagation-metric.test.ts +196 -0
- package/src/lib/propagation-metric.ts +175 -0
- package/src/lib/sql-db-dialect.test.ts +22 -0
- package/src/lib/sql-db-postgres.ts +229 -0
- package/src/lib/sql-db.ts +166 -0
- package/src/lib/stage6.test.ts +216 -0
- package/src/lib/store/export.ts +65 -0
- package/src/lib/store/helpers.ts +367 -0
- package/src/lib/store/ingest.ts +68 -0
- package/src/lib/store/issues.ts +158 -0
- package/src/lib/store/overview.ts +127 -0
- package/src/lib/store/retention.ts +10 -0
- package/src/lib/store/service-map.ts +384 -0
- package/src/lib/store/trace-detail.bench.ts +76 -0
- package/src/lib/store/trace-detail.test.ts +410 -0
- package/src/lib/store/trace-detail.ts +427 -0
- package/src/lib/store/trace-queries.test.ts +29 -0
- package/src/lib/store/trace-queries.ts +89 -0
- package/src/lib/store-overview.test.ts +77 -0
- package/src/lib/store.ts +96 -0
- package/src/lib/tail-publisher.ts +64 -0
- package/src/lib/test-utils/mem-sql-db.test.ts +93 -0
- package/src/lib/test-utils/mem-sql-db.ts +86 -0
- package/src/lib/ua-parser.ts +61 -0
- package/src/lib/usage-store.ts +567 -0
- package/src/migrations/001_telemetry_spans.sql +28 -0
- package/src/migrations/002_usage_events.sql +24 -0
- package/src/migrations/003_usage_analytics_columns.sql +13 -0
- package/src/migrations/004_logs.sql +19 -0
- package/src/migrations/005_ai_calls.sql +25 -0
- package/src/migrations/006_user_profiles.sql +11 -0
- package/src/migrations/007_session_replay_metadata.sql +10 -0
- package/src/migrations/008_session_replay_storage_bytes.sql +1 -0
- package/src/migrations/009_projects_and_keys.sql +22 -0
- package/src/migrations/010_signal_project_id.sql +15 -0
- package/src/migrations/011_default_project_seed.sql +3 -0
- package/src/migrations/012_alert_rules.sql +17 -0
- package/src/migrations/013_alert_evaluations.sql +13 -0
- package/src/migrations/014_alert_state.sql +9 -0
- package/src/migrations/015_metrics.sql +58 -0
- package/src/migrations/016_metrics_exp_histogram_summary.sql +5 -0
- package/src/migrations/017_span_dropped_counts.sql +11 -0
- package/src/migrations/018_log_flags.sql +8 -0
- package/src/migrations/019_ai_span_payloads.sql +30 -0
- package/src/migrations/020_ai_span_evaluations.sql +33 -0
- package/src/migrations/021_ai_span_session.sql +13 -0
- package/src/migrations/022_span_log_session_id.sql +13 -0
- package/src/migrations/023_service_map_indexes.sql +32 -0
- package/src/migrations/024_analysis_results.sql +49 -0
- package/src/migrations/025_stage6_autopinning_alerts.sql +38 -0
- package/src/migrations/026_obs_dashboard_project_seed.sql +18 -0
- package/src/migrations/027_identity_propagation.sql +50 -0
- package/src/migrations/028_profile_blobs.sql +57 -0
- package/src/migrations/029_telemetry_sdk_name.sql +20 -0
- package/src/migrations/030_analysis_claim.sql +18 -0
- package/src/migrations/031_agent_action_graph.sql +154 -0
- package/src/migrations/032_payload_capture_flags.sql +8 -0
- package/src/migrations/033_eval_cases.sql +52 -0
- package/src/migrations/034_eval_case_results.sql +23 -0
- package/src/migrations/035_metric_exemplars.sql +33 -0
- package/src/migrations/036_trace_instrumentation_gaps.sql +19 -0
- package/src/migrations/037_eval_runs.sql +37 -0
- package/src/migrations/038_tool_call_evidence.sql +11 -0
- package/src/migrations/039_drop_trace_instrumentation_gaps.sql +11 -0
- package/src/migrations/040_evidence_retrieval_refs.sql +50 -0
- package/src/migrations-postgres/001_telemetry_spans.sql +33 -0
- package/src/migrations-postgres/002_usage_events.sql +24 -0
- package/src/migrations-postgres/003_usage_analytics_columns.sql +13 -0
- package/src/migrations-postgres/004_logs.sql +19 -0
- package/src/migrations-postgres/005_ai_calls.sql +25 -0
- package/src/migrations-postgres/006_user_profiles.sql +11 -0
- package/src/migrations-postgres/007_session_replay_metadata.sql +10 -0
- package/src/migrations-postgres/008_session_replay_storage_bytes.sql +2 -0
- package/src/migrations-postgres/009_projects_and_keys.sql +25 -0
- package/src/migrations-postgres/010_signal_project_id.sql +18 -0
- package/src/migrations-postgres/011_default_project_seed.sql +5 -0
- package/src/migrations-postgres/012_alert_rules.sql +17 -0
- package/src/migrations-postgres/013_alert_evaluations.sql +13 -0
- package/src/migrations-postgres/014_alert_state.sql +9 -0
- package/src/migrations-postgres/015_metrics.sql +47 -0
- package/src/migrations-postgres/016_metrics_exp_histogram_summary.sql +1 -0
- package/src/migrations-postgres/017_span_dropped_counts.sql +4 -0
- package/src/migrations-postgres/018_log_flags.sql +2 -0
- package/src/migrations-postgres/019_ai_span_payloads.sql +18 -0
- package/src/migrations-postgres/020_ai_span_evaluations.sql +21 -0
- package/src/migrations-postgres/021_ai_span_session.sql +7 -0
- package/src/migrations-postgres/022_span_log_session_id.sql +7 -0
- package/src/migrations-postgres/023_service_map_indexes.sql +9 -0
- package/src/migrations-postgres/024_analysis_results.sql +41 -0
- package/src/migrations-postgres/025_stage6_autopinning_alerts.sql +17 -0
- package/src/migrations-postgres/026_obs_dashboard_project_seed.sql +14 -0
- package/src/migrations-postgres/027_identity_propagation.sql +27 -0
- package/src/migrations-postgres/028_profile_blobs.sql +48 -0
- package/src/migrations-postgres/029_telemetry_sdk_name.sql +5 -0
- package/src/migrations-postgres/030_analysis_claim.sql +5 -0
- package/src/migrations-postgres/031_agent_action_graph.sql +190 -0
- package/src/migrations-postgres/032_payload_capture_flags.sql +8 -0
- package/src/migrations-postgres/033_eval_cases.sql +55 -0
- package/src/migrations-postgres/034_eval_case_results.sql +26 -0
- package/src/migrations-postgres/035_metric_exemplars.sql +31 -0
- package/src/migrations-postgres/036_trace_instrumentation_gaps.sql +19 -0
- package/src/migrations-postgres/037_eval_runs.sql +40 -0
- package/src/migrations-postgres/038_tool_call_evidence.sql +11 -0
- package/src/migrations-postgres/039_drop_trace_instrumentation_gaps.sql +11 -0
- package/src/migrations-postgres/040_evidence_retrieval_refs.sql +47 -0
- package/src/migrations-postgres/README.md +40 -0
- package/src/otlp/acceptance.test.ts +373 -0
- package/src/otlp/decode/body.ts +127 -0
- package/src/otlp/decode/logs.ts +96 -0
- package/src/otlp/decode/metrics.ts +402 -0
- package/src/otlp/decode/traces.ts +92 -0
- package/src/otlp/decode/values.ts +150 -0
- package/src/otlp/decode.test.ts +800 -0
- package/src/otlp/decode.ts +11 -0
- package/src/otlp/gen/opentelemetry/proto/collector/logs/v1/logs_service_pb.ts +132 -0
- package/src/otlp/gen/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.ts +158 -0
- package/src/otlp/gen/opentelemetry/proto/collector/trace/v1/trace_service_pb.ts +158 -0
- package/src/otlp/gen/opentelemetry/proto/common/v1/common_pb.ts +289 -0
- package/src/otlp/gen/opentelemetry/proto/logs/v1/logs_pb.ts +397 -0
- package/src/otlp/gen/opentelemetry/proto/metrics/v1/metrics_pb.ts +1329 -0
- package/src/otlp/gen/opentelemetry/proto/resource/v1/resource_pb.ts +86 -0
- package/src/otlp/gen/opentelemetry/proto/trace/v1/trace_pb.ts +710 -0
- package/src/otlp/response.test.ts +158 -0
- package/src/otlp/response.ts +129 -0
- package/src/plugins/_context.ts +15 -0
- package/src/plugins/action-graph-processor/enrichers.ts +45 -0
- package/src/plugins/action-graph-processor/redaction.ts +84 -0
- package/src/plugins/action-graph-processor.test.ts +1023 -0
- package/src/plugins/action-graph-processor.ts +1172 -0
- package/src/plugins/action-routes.test.ts +716 -0
- package/src/plugins/action-routes.ts +343 -0
- package/src/plugins/ai-receiver.ts +254 -0
- package/src/plugins/ai-span-payloads-processor.test.ts +90 -0
- package/src/plugins/ai-span-payloads-processor.ts +180 -0
- package/src/plugins/alerts-evaluator.test.ts +91 -0
- package/src/plugins/alerts-evaluator.ts +328 -0
- package/src/plugins/alerts-routes.ts +101 -0
- package/src/plugins/analyses-routes.ts +138 -0
- package/src/plugins/ask-routes.ts +182 -0
- package/src/plugins/bot-filter.ts +19 -0
- package/src/plugins/connected-routes/manifest.ts +531 -0
- package/src/plugins/connected-routes.test.ts +1791 -0
- package/src/plugins/connected-routes.ts +1103 -0
- package/src/plugins/dashboard-routes.ts +41 -0
- package/src/plugins/default-span-enrichment.ts +92 -0
- package/src/plugins/eval-cases-routes.test.ts +391 -0
- package/src/plugins/eval-cases-routes.ts +529 -0
- package/src/plugins/evidence-retrieval-routes.benchmark.test.ts +245 -0
- package/src/plugins/evidence-retrieval-routes.test.ts +932 -0
- package/src/plugins/evidence-retrieval-routes.ts +2179 -0
- package/src/plugins/gen-ai-normalizer.test.ts +680 -0
- package/src/plugins/gen-ai-normalizer.ts +302 -0
- package/src/plugins/identity-receiver.ts +96 -0
- package/src/plugins/issue-enrichment.ts +132 -0
- package/src/plugins/issue-insights.ts +81 -0
- package/src/plugins/logs-receiver.ts +160 -0
- package/src/plugins/metrics-receiver.ts +91 -0
- package/src/plugins/onboarding-routes.ts +54 -0
- package/src/plugins/otlp-receiver.ts +124 -0
- package/src/plugins/platform-routes.ts +165 -0
- package/src/plugins/profile-routes.ts +468 -0
- package/src/plugins/projects-routes.ts +92 -0
- package/src/plugins/query-routes.ts +220 -0
- package/src/plugins/redaction-processor.ts +132 -0
- package/src/plugins/replay-query-routes.test.ts +38 -0
- package/src/plugins/replay-query-routes.ts +199 -0
- package/src/plugins/replay-receiver.ts +81 -0
- package/src/plugins/tail-routes.test.ts +47 -0
- package/src/plugins/tail-routes.ts +42 -0
- package/src/plugins/timeline-routes.ts +244 -0
- package/src/plugins/ua-enrichment.ts +27 -0
- package/src/plugins/usage-normalization.ts +46 -0
- package/src/plugins/usage-privacy.ts +55 -0
- package/src/plugins/usage-query-routes.ts +102 -0
- package/src/plugins/usage-receiver.ts +129 -0
- package/src/plugins/users-query-routes.ts +78 -0
- package/src/plugins/utm-enrichment.ts +36 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/framework/collector.ts","../src/lib/ai-store/types.ts","../src/lib/ai-store/calls.ts","../src/lib/ai-store/evaluations.ts","../src/lib/json.ts","../src/lib/ai-store/retention.ts","../src/lib/ai-pricing.ts","../src/lib/ai-store/helpers.ts","../src/lib/ai-store/sessions.ts","../src/lib/ai-store/spans.ts","../src/lib/ai-store.ts","../src/lib/analyses-store.ts","../src/analyses/derive.ts","../src/analyses/investigations.ts","../src/analyses/tier0.ts","../src/analyses/index.ts","../src/framework/logger.ts","../src/lib/narrate-gate.ts","../src/lib/analyses-runner.ts","../src/lib/logs-store.ts","../src/lib/metrics-store.ts","../src/lib/propagation-metric.ts","../src/lib/store/helpers.ts","../src/lib/store/export.ts","../src/lib/store/ingest.ts","../src/lib/store/trace-queries.ts","../src/lib/store/issues.ts","../src/lib/store/overview.ts","../src/lib/store/retention.ts","../src/lib/store/service-map.ts","../src/lib/store/trace-detail.ts","../src/lib/store.ts","../src/lib/usage-store.ts","../src/plugins/action-graph-processor.ts","../src/lib/action-identity.ts","../src/lib/payload-capture.ts","../src/plugins/action-graph-processor/enrichers.ts","../src/plugins/action-graph-processor/redaction.ts","../src/plugins/action-routes.ts","../src/lib/action-aggregates.ts","../src/lib/identity-index/action-lookups.ts","../src/lib/identity-index/constants.ts","../src/lib/identity-index/mappers.ts","../src/lib/identity-index/key-lookups.ts","../src/lib/identity-index/user-lookup.ts","../src/lib/identity-index.ts","../src/plugins/_context.ts","../src/plugins/ai-receiver.ts","../src/plugins/ai-span-payloads-processor.ts","../src/lib/alerts-store.ts","../src/plugins/alerts-evaluator.ts","../src/plugins/alerts-routes.ts","../src/plugins/analyses-routes.ts","../src/lib/ask.ts","../src/plugins/ask-routes.ts","../src/lib/ua-parser.ts","../src/plugins/bot-filter.ts","../src/plugins/connected-routes.ts","../src/plugins/connected-routes/manifest.ts","../src/plugins/dashboard-routes.ts","../src/plugins/default-span-enrichment.ts","../src/plugins/eval-cases-routes.ts","../src/lib/eval-cases-store.ts","../src/lib/parse-pprof.ts","../src/plugins/replay-query-routes.ts","../src/plugins/evidence-retrieval-routes.ts","../src/plugins/gen-ai-normalizer.ts","../src/plugins/identity-receiver.ts","../src/plugins/issue-enrichment.ts","../src/plugins/issue-insights.ts","../src/plugins/logs-receiver.ts","../src/lib/tail-publisher.ts","../src/otlp/decode/body.ts","../src/otlp/decode/logs.ts","../src/otlp/gen/opentelemetry/proto/collector/logs/v1/logs_service_pb.ts","../src/otlp/gen/opentelemetry/proto/logs/v1/logs_pb.ts","../src/otlp/gen/opentelemetry/proto/common/v1/common_pb.ts","../src/otlp/gen/opentelemetry/proto/resource/v1/resource_pb.ts","../src/otlp/decode/values.ts","../src/otlp/decode/metrics.ts","../src/otlp/gen/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.ts","../src/otlp/gen/opentelemetry/proto/metrics/v1/metrics_pb.ts","../src/otlp/decode/traces.ts","../src/otlp/gen/opentelemetry/proto/collector/trace/v1/trace_service_pb.ts","../src/otlp/gen/opentelemetry/proto/trace/v1/trace_pb.ts","../src/otlp/response.ts","../src/plugins/metrics-receiver.ts","../src/plugins/onboarding-routes.ts","../src/plugins/otlp-receiver.ts","../src/lib/otlp.ts","../src/plugins/platform-routes.ts","../src/plugins/profile-routes.ts","../src/plugins/projects-routes.ts","../src/plugins/query-routes.ts","../src/plugins/redaction-processor.ts","../src/plugins/replay-receiver.ts","../src/plugins/tail-routes.ts","../src/plugins/timeline-routes.ts","../src/plugins/ua-enrichment.ts","../src/plugins/usage-normalization.ts","../src/plugins/usage-privacy.ts","../src/plugins/usage-query-routes.ts","../src/plugins/usage-receiver.ts","../src/plugins/users-query-routes.ts","../src/plugins/utm-enrichment.ts","../src/auth/dashboard-auth.ts","../src/durable-objects/tail-hub.ts","../src/lib/actions-store.ts","../src/lib/blob-store.ts","../src/lib/blob-store-s3.ts","../src/lib/sql-db-postgres.ts","../src/index.ts"],"sourcesContent":["import type { StoredSpan, UsageEventRecord } from \"@obsunified/types\";\nimport { getConfiguredRetentionHours } from \"@obsunified/types/constants\";\nimport type { MiddlewareHandler } from \"hono\";\nimport { Hono } from \"hono\";\nimport { AIStore } from \"../lib/ai-store\";\nimport { runAllDueAnalyses } from \"../lib/analyses-runner\";\nimport { AnalysesStore } from \"../lib/analyses-store\";\nimport { LogsStore } from \"../lib/logs-store\";\nimport { MetricsStore } from \"../lib/metrics-store\";\nimport { aggregatePropagation } from \"../lib/propagation-metric\";\nimport { D1Adapter, dialectFor, type SqlDb, sqlDbFor } from \"../lib/sql-db\";\nimport { TelemetryStore } from \"../lib/store\";\nimport { UsageStore } from \"../lib/usage-store\";\nimport type { CollectorEnv, CollectorRouteContext } from \"./env\";\nimport {\n\ttype ChildSpanRunner,\n\tconsoleLogger,\n\ttype Logger,\n\tpassthroughChildSpan,\n} from \"./logger\";\n\n/**\n * Factory that materializes an `SqlDb` for the request's `env`. Per-request\n * because Cloudflare's `D1Database` binding only exists once `env` is in\n * scope; on Workers this is essentially free since `D1Adapter` is a thin\n * wrapper. Hosts override this to inject a fake DB in tests, a different\n * engine in alternate runtimes, or a tracing wrapper at the storage layer.\n */\nexport type SqlDbFactory = (env: CollectorEnv) => SqlDb;\n\nconst defaultSqlDbFactory: SqlDbFactory = (env) => new D1Adapter(env.DB);\n\nexport interface SpanProcessorPlugin {\n\tname: string;\n\tprocess(\n\t\tspans: StoredSpan[],\n\t\tcontext: CollectorRouteContext,\n\t): Promise<StoredSpan[]> | StoredSpan[];\n}\n\nexport interface UsageEventProcessorPlugin {\n\tname: string;\n\tprocess(\n\t\tevents: UsageEventRecord[],\n\t\tcontext: CollectorRouteContext,\n\t): Promise<UsageEventRecord[]> | UsageEventRecord[];\n}\n\nexport interface CollectorPluginContext {\n\taddSpanProcessor(processor: SpanProcessorPlugin): void;\n\taddUsageEventProcessor(processor: UsageEventProcessorPlugin): void;\n\tgetRegisteredPluginNames(): string[];\n}\n\nexport interface CollectorPlugin {\n\tname: string;\n\tregister(\n\t\tapp: Hono<{ Bindings: CollectorEnv }>,\n\t\tcontext: CollectorRuntime,\n\t): void;\n}\n\nexport interface CollectorAuthConfig {\n\t/** Single middleware applied to both /v1/* (ingest) and /internal/* (query) routes */\n\t// biome-ignore lint/suspicious/noExplicitAny: Hono generic middleware variables require any for contravariant compatibility\n\tmiddleware?: MiddlewareHandler<{ Bindings: CollectorEnv; Variables: any }>;\n\t/** @deprecated Use middleware instead. Ingest-only auth for /v1/* routes. */\n\t// biome-ignore lint/suspicious/noExplicitAny: Hono generic middleware variables require any for contravariant compatibility\n\tingest?: MiddlewareHandler<{ Bindings: CollectorEnv; Variables: any }>;\n\t/** @deprecated Use middleware instead. Query-only auth for /internal/* routes. */\n\t// biome-ignore lint/suspicious/noExplicitAny: Hono generic middleware variables require any for contravariant compatibility\n\tquery?: MiddlewareHandler<{ Bindings: CollectorEnv; Variables: any }>;\n}\n\nexport interface CollectorConfig {\n\tplugins: CollectorPlugin[];\n\tauth?: CollectorAuthConfig;\n\t/** Comma-separated allowed origins for CORS on ingest endpoints */\n\tallowedOrigins?: string;\n\t/** Register dashboard auth routes and middleware */\n\tdashboardAuth?: {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Hono generic middleware variables require any for contravariant compatibility\n\t\tmiddleware: MiddlewareHandler<{ Bindings: CollectorEnv; Variables: any }>;\n\t\tregisterRoutes: (app: Hono<{ Bindings: CollectorEnv }>) => void;\n\t};\n\t/**\n\t * Pluggable structured logger. Defaults to console output. Pass a logger\n\t * from `@obsunified/telemetry-sdk` to ship the collector's own log output as\n\t * OTLP — see apps/collector/SELF_INSTRUMENTATION.md.\n\t */\n\tlogger?: Logger;\n\t/**\n\t * Wraps async work in a child span on the active request span. Wire this\n\t * to `@obsunified/telemetry-sdk`'s `withChildSpan` from the worker entrypoint to\n\t * surface LLM hops + DB-heavy paths as nested spans. Defaults to\n\t * pass-through.\n\t */\n\twithChildSpan?: ChildSpanRunner;\n\t/**\n\t * RFC 0008 — override the storage adapter. Per-request factory because\n\t * `env.DB` only exists once a request lands. Defaults to wrapping\n\t * `env.DB` in `D1Adapter`. Override in tests (use `MemSqlDb`) or to add\n\t * a tracing layer at the storage seam.\n\t */\n\tsqlDb?: SqlDbFactory;\n}\n\nexport class CollectorRuntime implements CollectorPluginContext {\n\tprivate readonly spanProcessors: SpanProcessorPlugin[] = [];\n\tprivate readonly usageEventProcessors: UsageEventProcessorPlugin[] = [];\n\tprivate readonly plugins: string[] = [];\n\tprivate readonly sqlDbFactory: SqlDbFactory;\n\treadonly logger: Logger;\n\treadonly withChildSpan: ChildSpanRunner;\n\n\tconstructor(\n\t\tlogger: Logger = consoleLogger,\n\t\twithChildSpan: ChildSpanRunner = passthroughChildSpan,\n\t\tsqlDbFactory: SqlDbFactory = defaultSqlDbFactory,\n\t) {\n\t\tthis.logger = logger;\n\t\tthis.withChildSpan = withChildSpan;\n\t\tthis.sqlDbFactory = sqlDbFactory;\n\t}\n\n\t/**\n\t * Materialize an `SqlDb` for this request. Stores will accept this\n\t * directly once Phase 1.5 of RFC 0008 lands; until then plugins that\n\t * want to bypass `c.env.DB` can call this to opt in early.\n\t */\n\tgetSqlDb(env: CollectorEnv): SqlDb {\n\t\treturn this.sqlDbFactory(env);\n\t}\n\n\tregisterPlugin(plugin: CollectorPlugin): void {\n\t\tthis.plugins.push(plugin.name);\n\t}\n\n\taddSpanProcessor(processor: SpanProcessorPlugin): void {\n\t\tthis.spanProcessors.push(processor);\n\t}\n\n\taddUsageEventProcessor(processor: UsageEventProcessorPlugin): void {\n\t\tthis.usageEventProcessors.push(processor);\n\t}\n\n\tgetRegisteredPluginNames(): string[] {\n\t\treturn [...this.plugins];\n\t}\n\n\tcreateRouteContext(\n\t\tenv: CollectorEnv,\n\t\thono: CollectorRouteContext[\"hono\"],\n\t): CollectorRouteContext {\n\t\treturn {\n\t\t\thono,\n\t\t\tenv,\n\t\t\tnow: new Date(),\n\t\t\tlogger: this.logger,\n\t\t};\n\t}\n\n\tcreateStore(env: CollectorEnv): TelemetryStore {\n\t\treturn new TelemetryStore(this.getSqlDb(env));\n\t}\n\n\tcreateUsageStore(env: CollectorEnv): UsageStore {\n\t\treturn new UsageStore(this.getSqlDb(env));\n\t}\n\n\tasync runSpanProcessors(\n\t\tspans: StoredSpan[],\n\t\tcontext: CollectorRouteContext,\n\t): Promise<StoredSpan[]> {\n\t\tlet nextSpans = spans;\n\n\t\tfor (const processor of this.spanProcessors) {\n\t\t\tconst inputCount = nextSpans.length;\n\t\t\tnextSpans = await this.withChildSpan(\n\t\t\t\t`process.${processor.name}`,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst out = await processor.process(nextSpans, context);\n\t\t\t\t\tspan.setAttribute(\"processor.kind\", \"span\");\n\t\t\t\t\tspan.setAttribute(\"processor.name\", processor.name);\n\t\t\t\t\tspan.setAttribute(\"processor.input_count\", inputCount);\n\t\t\t\t\tspan.setAttribute(\"processor.output_count\", out.length);\n\t\t\t\t\tif (out.length !== inputCount)\n\t\t\t\t\t\tspan.setAttribute(\"processor.delta_count\", out.length - inputCount);\n\t\t\t\t\treturn out;\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\treturn nextSpans;\n\t}\n\n\tasync runUsageEventProcessors(\n\t\tevents: UsageEventRecord[],\n\t\tcontext: CollectorRouteContext,\n\t): Promise<UsageEventRecord[]> {\n\t\tlet nextEvents = events;\n\n\t\tfor (const processor of this.usageEventProcessors) {\n\t\t\tconst inputCount = nextEvents.length;\n\t\t\tnextEvents = await this.withChildSpan(\n\t\t\t\t`process.${processor.name}`,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst out = await processor.process(nextEvents, context);\n\t\t\t\t\tspan.setAttribute(\"processor.kind\", \"usage\");\n\t\t\t\t\tspan.setAttribute(\"processor.name\", processor.name);\n\t\t\t\t\tspan.setAttribute(\"processor.input_count\", inputCount);\n\t\t\t\t\tspan.setAttribute(\"processor.output_count\", out.length);\n\t\t\t\t\tif (out.length !== inputCount)\n\t\t\t\t\t\tspan.setAttribute(\"processor.delta_count\", out.length - inputCount);\n\t\t\t\t\treturn out;\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\treturn nextEvents;\n\t}\n}\n\nexport const createTelemetryCollectorApp = (\n\tpluginsOrConfig: CollectorPlugin[] | CollectorConfig,\n): Hono<{ Bindings: CollectorEnv }> => {\n\tconst config: CollectorConfig = Array.isArray(pluginsOrConfig)\n\t\t? { plugins: pluginsOrConfig }\n\t\t: pluginsOrConfig;\n\n\tconst app = new Hono<{ Bindings: CollectorEnv }>();\n\tconst runtime = new CollectorRuntime(\n\t\tconfig.logger,\n\t\tconfig.withChildSpan,\n\t\tconfig.sqlDb,\n\t);\n\n\tconst allowedCorsOrigin = (origin: string | undefined, env: CollectorEnv) => {\n\t\tconst allowedOrigins = config.allowedOrigins || env.ALLOWED_ORIGINS || \"\";\n\t\tconst allowList = allowedOrigins\n\t\t\t.split(\",\")\n\t\t\t.map((s) => s.trim())\n\t\t\t.filter(Boolean);\n\t\treturn origin && allowList.includes(origin) ? origin : undefined;\n\t};\n\n\t// Health endpoint — no auth required. Includes millisecond server time so\n\t// browser SDKs can estimate clock offset without relying on coarse Date.\n\tapp.get(\"/health\", (c) => {\n\t\tconst allowedOrigin = allowedCorsOrigin(c.req.header(\"Origin\"), c.env);\n\t\tconst res = c.json({ status: \"ok\", serverTimeMs: Date.now() });\n\t\tif (allowedOrigin)\n\t\t\tres.headers.set(\"Access-Control-Allow-Origin\", allowedOrigin);\n\t\treturn res;\n\t});\n\n\t// CORS for ingest endpoints (browser SDK sends directly)\n\tapp.use(\"/v1/*\", async (c, next) => {\n\t\tconst origin = c.req.header(\"Origin\");\n\t\tconst allowedOrigin = allowedCorsOrigin(origin, c.env);\n\n\t\tif (c.req.method === \"OPTIONS\") {\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\"Access-Control-Allow-Methods\": \"POST, OPTIONS\",\n\t\t\t\t\"Access-Control-Allow-Headers\":\n\t\t\t\t\t\"Content-Type, Authorization, X-API-Key, X-Project-Id, Cache-Control, X-Telemetry-Self, X-Obs-Interaction, X-Obs-Session-Id\",\n\t\t\t\t\"Access-Control-Max-Age\": \"86400\",\n\t\t\t};\n\t\t\tif (allowedOrigin) {\n\t\t\t\theaders[\"Access-Control-Allow-Origin\"] = allowedOrigin;\n\t\t\t}\n\t\t\treturn new Response(null, { status: 204, headers });\n\t\t}\n\n\t\tawait next();\n\n\t\t// Mutate the response headers directly rather than using c.header(),\n\t\t// which queues the header for a response Hono is about to construct —\n\t\t// no-op when downstream middleware already finalized the response via\n\t\t// `c.json(...)` (e.g. auth returning 401). Without this, error\n\t\t// responses ship CORS-naked and browsers misreport them as CORS\n\t\t// blocks instead of the underlying status.\n\t\tif (allowedOrigin) {\n\t\t\tc.res.headers.set(\"Access-Control-Allow-Origin\", allowedOrigin);\n\t\t}\n\t});\n\n\t// Ingest auth (API key) — always on /v1/* when configured.\n\tif (config.auth?.middleware) {\n\t\tapp.use(\"/v1/*\", config.auth.middleware);\n\t} else if (config.auth?.ingest) {\n\t\t// Legacy: explicit ingest-only middleware\n\t\tapp.use(\"/v1/*\", config.auth.ingest);\n\t}\n\n\t// Dashboard auth (session cookie) — owns /internal/* when configured.\n\t// Routes for login/check/logout are always registered so the dashboard\n\t// can authenticate regardless of subsequent middleware placement.\n\tif (config.dashboardAuth) {\n\t\tconfig.dashboardAuth.registerRoutes(app);\n\t\tapp.use(\"/dashboard/*\", config.dashboardAuth.middleware);\n\t\tapp.use(\"/internal/*\", config.dashboardAuth.middleware);\n\t} else if (config.auth?.middleware) {\n\t\t// No dashboard auth configured — fall back to applying the unified\n\t\t// ingest auth to /internal/* too, preserving the earlier single-auth\n\t\t// contract for deployments that haven't adopted dashboard auth yet.\n\t\tapp.use(\"/internal/*\", config.auth.middleware);\n\t} else if (config.auth?.query) {\n\t\tapp.use(\"/internal/*\", config.auth.query);\n\t}\n\n\tfor (const plugin of config.plugins) {\n\t\truntime.registerPlugin(plugin);\n\t\tplugin.register(app, runtime);\n\t}\n\n\tapp.get(\"/internal/collector/plugins\", (c) => {\n\t\treturn c.json({\n\t\t\tplugins: runtime.getRegisteredPluginNames(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t});\n\t});\n\n\treturn app;\n};\n\n/**\n * Scheduled handler that purges expired telemetry and usage rows.\n * Wire into wrangler.toml: `[triggers] crons = [\"0 * * * *\"]`\n * Source: AgentOwl + DecisionOps\n */\nexport const createRetentionCleanupHandler = (options?: {\n\tlogger?: Logger;\n}) => {\n\tconst logger = options?.logger ?? consoleLogger;\n\treturn {\n\t\tasync scheduled(\n\t\t\t_event: ScheduledEvent,\n\t\t\tenv: CollectorEnv,\n\t\t\t_ctx: ExecutionContext,\n\t\t): Promise<void> {\n\t\t\tconst db = sqlDbFor(env);\n\t\t\tconst telemetryStore = new TelemetryStore(db);\n\t\t\tconst usageStore = new UsageStore(db);\n\t\t\tconst logsStore = new LogsStore(db);\n\t\t\tconst aiStore = new AIStore(db);\n\t\t\tconst metricsStore = new MetricsStore(db);\n\t\t\tconst analysesStore = new AnalysesStore(db);\n\n\t\t\tconst [\n\t\t\t\ttelemetryPurged,\n\t\t\t\tusagePurged,\n\t\t\t\tlogsPurged,\n\t\t\t\taiPurged,\n\t\t\t\tmetricsPurged,\n\t\t\t\tanalysesPurged,\n\t\t\t] = await Promise.all([\n\t\t\t\ttelemetryStore.purgeExpired(),\n\t\t\t\tusageStore.purgeExpired(),\n\t\t\t\tlogsStore.purgeExpired(),\n\t\t\t\taiStore.purgeExpired(),\n\t\t\t\tmetricsStore.purgeExpired(),\n\t\t\t\tanalysesStore.purgeExpired(),\n\t\t\t]);\n\n\t\t\t// RFC 0007 Phase 4.10 — profile_blobs retention. Cascade\n\t\t\t// foreign key on profile_trace_index handles the join rows;\n\t\t\t// we still need to delete the R2 blobs, which we do\n\t\t\t// best-effort by reading the URLs first.\n\t\t\tlet profilesPurged = 0;\n\t\t\ttry {\n\t\t\t\tconst dialect = dialectFor(db);\n\t\t\t\tconst expiredProfiles = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT id, blob_url FROM profile_blobs WHERE expires_at < ${dialect.now()} LIMIT 500`,\n\t\t\t\t\t)\n\t\t\t\t\t.all<{ id: string; blob_url: string }>();\n\t\t\t\tif (expiredProfiles.results.length > 0 && env.PROFILES_BUCKET) {\n\t\t\t\t\tawait Promise.allSettled(\n\t\t\t\t\t\texpiredProfiles.results.map((p) =>\n\t\t\t\t\t\t\tenv.PROFILES_BUCKET?.delete(p.blob_url),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst deleted = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`DELETE FROM profile_blobs WHERE expires_at < ${dialect.now()}`,\n\t\t\t\t\t)\n\t\t\t\t\t.run();\n\t\t\t\tprofilesPurged = deleted.meta.changes;\n\t\t\t} catch (err) {\n\t\t\t\tlogger.error(\"[retention-cleanup] profile purge failed\", {\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlogger.info(\"[retention-cleanup] purged expired rows\", {\n\t\t\t\tspans: telemetryPurged,\n\t\t\t\tusage: usagePurged,\n\t\t\t\tlogs: logsPurged,\n\t\t\t\tai_calls: aiPurged,\n\t\t\t\tmetric_points: metricsPurged,\n\t\t\t\tanalysis_results: analysesPurged,\n\t\t\t\tprofile_blobs: profilesPurged,\n\t\t\t});\n\n\t\t\t// RFC 0004 Phase 1.8 — emit interaction_id propagation counters.\n\t\t\t// Hourly aggregation rides the retention cron because cadence\n\t\t\t// matches and both touch the same projects' tables.\n\t\t\ttry {\n\t\t\t\tconst propagation = await aggregatePropagation(db, new Date(), logger);\n\t\t\t\tlogger.info(\"[propagation-metric] hourly aggregation complete\", {\n\t\t\t\t\tprojects: propagation.projects,\n\t\t\t\t\tpoints_written: propagation.pointsWritten,\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tlogger.error(\"[propagation-metric] aggregation failed\", {\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n};\n\n/**\n * RFC 0002 Stage 1 — run any due Analyses. Cheap to call frequently because\n * `runAllDueAnalyses` filters by `last_run + refreshSeconds < now` before\n * touching D1.\n *\n * Wire to a per-minute trigger in wrangler.toml: `crons = [\"* * * * *\"]`.\n * Kept distinct from retention so the per-minute tick doesn't sweep every\n * retention table every cycle.\n */\nexport const createAnalysesRunHandler = (options?: {\n\tlogger?: Logger;\n\ttracer?: ChildSpanRunner;\n}) => {\n\tconst logger = options?.logger ?? consoleLogger;\n\tconst tracer = options?.tracer;\n\treturn {\n\t\tasync scheduled(\n\t\t\t_event: ScheduledEvent,\n\t\t\tenv: CollectorEnv,\n\t\t\t_ctx: ExecutionContext,\n\t\t): Promise<void> {\n\t\t\ttry {\n\t\t\t\tconst retentionHours = getConfiguredRetentionHours(env.RETENTION_HOURS);\n\t\t\t\tconst summary = await runAllDueAnalyses({\n\t\t\t\t\tenv,\n\t\t\t\t\tretentionHours,\n\t\t\t\t\tlogger,\n\t\t\t\t\ttracer,\n\t\t\t\t});\n\t\t\t\tlogger.info(\"[analyses] scheduled run summary\", {\n\t\t\t\t\trefreshed: summary.refreshed,\n\t\t\t\t\tran: summary.ran,\n\t\t\t\t\tfailed: summary.failed,\n\t\t\t\t\tnarrated: summary.narrated,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"[analyses] scheduled run failed\", {\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n};\n","import type { AICallRecord, AIEvaluationSource } from \"@obsunified/types\";\n\nexport interface IngestEvaluation {\n\tprojectId: string;\n\tevaluationId: string;\n\ttraceId: string;\n\tspanId: string;\n\tname: string;\n\tscore: number | null;\n\tlabel: string | null;\n\texplanation: string | null;\n\tsource: AIEvaluationSource;\n\tmetadataJson: string | null;\n\tcreatedAt: string;\n\texpiresAt: string;\n}\n\n/** Clamp an integer to a safe range */\nexport const clampInt = (\n\tvalue: unknown,\n\tmin: number,\n\tmax: number,\n\tfallback: number,\n): number => {\n\tconst n = typeof value === \"number\" ? value : parseInt(String(value), 10);\n\tif (!Number.isFinite(n)) return fallback;\n\treturn Math.max(min, Math.min(max, n));\n};\n\nexport interface AICallRow {\n\tproject_id?: string;\n\tcall_id: string;\n\ttrace_id: string | null;\n\tspan_id: string | null;\n\tservice_name: string | null;\n\tmodel_name: string;\n\tprovider: string;\n\tcall_type: AICallRecord[\"callType\"];\n\trequest_json: string | null;\n\tresponse_json: string | null;\n\tprompt_tokens: number | null;\n\tcompletion_tokens: number | null;\n\ttotal_cost_usd: number | null;\n\tlatency_ms: number | null;\n\tis_error: number;\n\terror_message: string | null;\n\toccurred_at: string;\n\treceived_at: string;\n\texpires_at: string;\n\tsession_id: string | null;\n\tinteraction_id: string | null;\n}\n\nexport interface AICallSummaryRow {\n\ttotalCalls?: number;\n\ttotalCostUsd?: number;\n\ttotalPromptTokens?: number;\n\ttotalCompletionTokens?: number;\n\terrorCalls?: number;\n}\n\nexport interface AISpanRow {\n\ttrace_id: string;\n\tspan_id: string;\n\tparent_span_id: string | null;\n\tservice_name: string | null;\n\tspan_name: string;\n\tspan_kind: string;\n\tstatus_code: number | null;\n\tstatus_message: string | null;\n\tstart_time: string;\n\tend_time: string | null;\n\tduration_ms: number | null;\n\tattributes_json: string | null;\n\tinput_json: string | null;\n\toutput_json: string | null;\n\tuser_id?: string | null;\n}\n\nexport interface AISessionRow {\n\tsession_id: string;\n\tuser_id: string | null;\n\tspan_count: number | null;\n\tllm_span_count: number | null;\n\terror_count: number | null;\n\tprompt_tokens: number | null;\n\tcompletion_tokens: number | null;\n\tcost_usd: number | null;\n\tfirst_span_at: string;\n\tlast_span_at: string;\n\ttrace_count: number | null;\n}\n\nexport interface AISessionPreviewRow {\n\tsession_id: string;\n\tinput_json: string | null;\n}\n\nexport interface AIEvaluationRow {\n\tevaluation_id: string;\n\tproject_id: string;\n\ttrace_id: string;\n\tspan_id: string;\n\tname: string;\n\tscore: number | null;\n\tlabel: string | null;\n\texplanation: string | null;\n\tsource: AIEvaluationSource;\n\tmetadata_json: string | null;\n\tcreated_at: string;\n\texpires_at: string;\n}\n","import type {\n\tAICallRecord,\n\tAICallsOverviewOptions,\n\tAICallsOverviewResponse,\n} from \"@obsunified/types\";\nimport { dialectFor, type SqlDb } from \"../sql-db\";\nimport type { AICallRow, AICallSummaryRow } from \"./types\";\nimport { clampInt } from \"./types\";\n\nexport async function ingestAICallBatch(\n\tdb: SqlDb,\n\tcalls: AICallRecord[],\n): Promise<void> {\n\tif (calls.length === 0) return;\n\n\tconst stmt = db.prepare(`\n INSERT OR IGNORE INTO ai_calls (\n project_id, call_id, trace_id, span_id, service_name, model_name, provider, call_type,\n request_json, response_json, prompt_tokens, completion_tokens, total_cost_usd,\n latency_ms, is_error, error_message, occurred_at, received_at, expires_at,\n session_id, interaction_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n\tconst batch = calls.map((call) => {\n\t\tif (!call.projectId)\n\t\t\tthrow new Error(\"AIStore.ingestBatch: call.projectId is required\");\n\t\treturn stmt.bind(\n\t\t\tcall.projectId,\n\t\t\tcall.callId,\n\t\t\tcall.traceId,\n\t\t\tcall.spanId,\n\t\t\tcall.serviceName,\n\t\t\tcall.modelName,\n\t\t\tcall.provider,\n\t\t\tcall.callType,\n\t\t\tcall.requestJson,\n\t\t\tcall.responseJson,\n\t\t\tcall.promptTokens,\n\t\t\tcall.completionTokens,\n\t\t\tcall.totalCostUsd,\n\t\t\tcall.latencyMs,\n\t\t\tcall.isError ? 1 : 0,\n\t\t\tcall.errorMessage,\n\t\t\tcall.occurredAt,\n\t\t\tcall.receivedAt,\n\t\t\tcall.expiresAt,\n\t\t\tcall.sessionId ?? null,\n\t\t\tcall.interactionId ?? null,\n\t\t);\n\t});\n\n\tawait db.batch(batch);\n}\n\nexport async function getAICallsOverview(\n\tdb: SqlDb,\n\toptions: AICallsOverviewOptions,\n): Promise<AICallsOverviewResponse> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"AIStore.getAICalls: projectId is required\");\n\tconst dialect = dialectFor(db);\n\tconst hours = clampInt(options.hours, 1, 720, 24);\n\tconst limit = clampInt(options.limit, 1, 1000, 100);\n\n\tlet sql = `SELECT * FROM ai_calls WHERE project_id = ? AND received_at >= ${dialect.sinceHours(\"?\")}`;\n\tconst params: unknown[] = [options.projectId, hours];\n\n\tif (options.service) {\n\t\tsql += ` AND service_name = ?`;\n\t\tparams.push(options.service);\n\t}\n\tif (options.model) {\n\t\tsql += ` AND model_name = ?`;\n\t\tparams.push(options.model);\n\t}\n\tif (options.isError !== undefined) {\n\t\tsql += ` AND is_error = ?`;\n\t\tparams.push(options.isError ? 1 : 0);\n\t}\n\tif (options.traceId) {\n\t\tsql += ` AND trace_id = ?`;\n\t\tparams.push(options.traceId);\n\t}\n\n\tsql += ` ORDER BY received_at DESC LIMIT ?`;\n\tparams.push(limit);\n\n\tconst results = await db\n\t\t.prepare(sql)\n\t\t.bind(...params)\n\t\t.all<AICallRow>();\n\n\tconst summarySql = `\n SELECT\n COUNT(*) as totalCalls,\n SUM(total_cost_usd) as totalCostUsd,\n SUM(prompt_tokens) as totalPromptTokens,\n SUM(completion_tokens) as totalCompletionTokens,\n SUM(is_error) as errorCalls\n FROM ai_calls WHERE project_id = ? AND received_at >= ${dialect.sinceHours(\"?\")}\n ${options.service ? \"AND service_name = ?\" : \"\"}\n `;\n\tconst summaryParams: unknown[] = [options.projectId, hours];\n\tif (options.service) summaryParams.push(options.service);\n\tconst summaryResult =\n\t\t(await db\n\t\t\t.prepare(summarySql)\n\t\t\t.bind(...summaryParams)\n\t\t\t.first<AICallSummaryRow>()) || {};\n\n\tconst calls: AICallRecord[] = (results.results || []).map((row) => ({\n\t\tprojectId: row.project_id ?? \"default\",\n\t\tcallId: row.call_id,\n\t\ttraceId: row.trace_id,\n\t\tspanId: row.span_id,\n\t\tserviceName: row.service_name,\n\t\tmodelName: row.model_name,\n\t\tprovider: row.provider,\n\t\tcallType: row.call_type,\n\t\trequestJson: row.request_json,\n\t\tresponseJson: row.response_json,\n\t\tpromptTokens: row.prompt_tokens,\n\t\tcompletionTokens: row.completion_tokens,\n\t\ttotalCostUsd: row.total_cost_usd,\n\t\tlatencyMs: row.latency_ms,\n\t\tisError: row.is_error === 1,\n\t\terrorMessage: row.error_message,\n\t\toccurredAt: row.occurred_at,\n\t\treceivedAt: row.received_at,\n\t\texpiresAt: row.expires_at,\n\t\tsessionId: row.session_id ?? null,\n\t\tinteractionId: row.interaction_id ?? null,\n\t}));\n\n\treturn {\n\t\tcalls,\n\t\tsummary: {\n\t\t\ttotalCalls: summaryResult.totalCalls || 0,\n\t\t\ttotalCostUsd: summaryResult.totalCostUsd || 0,\n\t\t\ttotalPromptTokens: summaryResult.totalPromptTokens || 0,\n\t\t\ttotalCompletionTokens: summaryResult.totalCompletionTokens || 0,\n\t\t\terrorCalls: summaryResult.errorCalls || 0,\n\t\t},\n\t\twindowHours: hours,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n","import type {\n\tAIEvaluationRecord,\n\tAIEvaluationSource,\n\tAIEvaluationsListOptions,\n\tAIEvaluationsListResponse,\n} from \"@obsunified/types\";\nimport { EVIDENCE_REFERENCE_CONTRACT } from \"@obsunified/types\";\nimport { aiEvaluationEvidenceReferences } from \"../evidence-references\";\nimport { parseJsonRecord } from \"../json\";\nimport type { SqlDb } from \"../sql-db\";\nimport type { AIEvaluationRow, IngestEvaluation } from \"./types\";\nimport { clampInt } from \"./types\";\n\nexport async function ingestAIEvaluations(\n\tdb: SqlDb,\n\tevaluations: IngestEvaluation[],\n): Promise<void> {\n\tif (evaluations.length === 0) return;\n\tconst stmt = db.prepare(`\n INSERT INTO ai_span_evaluations (\n evaluation_id, project_id, trace_id, span_id, name,\n score, label, explanation, source, metadata_json,\n created_at, expires_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\tawait db.batch(\n\t\tevaluations.map((evaluation) =>\n\t\t\tstmt.bind(\n\t\t\t\tevaluation.evaluationId,\n\t\t\t\tevaluation.projectId,\n\t\t\t\tevaluation.traceId,\n\t\t\t\tevaluation.spanId,\n\t\t\t\tevaluation.name,\n\t\t\t\tevaluation.score,\n\t\t\t\tevaluation.label,\n\t\t\t\tevaluation.explanation,\n\t\t\t\tevaluation.source,\n\t\t\t\tevaluation.metadataJson,\n\t\t\t\tevaluation.createdAt,\n\t\t\t\tevaluation.expiresAt,\n\t\t\t),\n\t\t),\n\t);\n}\n\nexport async function listAIEvaluations(\n\tdb: SqlDb,\n\toptions: AIEvaluationsListOptions,\n): Promise<AIEvaluationsListResponse> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"AIStore.listEvaluations: projectId is required\");\n\tconst limit = clampInt(options.limit, 1, 1000, 200);\n\n\tlet sql = `SELECT * FROM ai_span_evaluations WHERE project_id = ?`;\n\tconst params: unknown[] = [options.projectId];\n\n\tif (options.traceId) {\n\t\tsql += ` AND trace_id = ?`;\n\t\tparams.push(options.traceId);\n\t}\n\tif (options.spanId) {\n\t\tsql += ` AND span_id = ?`;\n\t\tparams.push(options.spanId);\n\t}\n\tif (options.name) {\n\t\tsql += ` AND name = ?`;\n\t\tparams.push(options.name);\n\t}\n\n\tsql += ` ORDER BY created_at DESC LIMIT ?`;\n\tparams.push(limit);\n\n\tconst results = await db\n\t\t.prepare(sql)\n\t\t.bind(...params)\n\t\t.all<AIEvaluationRow>();\n\n\treturn {\n\t\tevaluations: mapEvaluationRows(results.results || []),\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n\nexport async function getAIEvaluation(\n\tdb: SqlDb,\n\tprojectId: string,\n\tevaluationId: string,\n): Promise<AIEvaluationRecord | null> {\n\tif (!projectId)\n\t\tthrow new Error(\"AIStore.getEvaluation: projectId is required\");\n\tconst row = await db\n\t\t.prepare(\n\t\t\t`SELECT * FROM ai_span_evaluations\n\t\t\t WHERE project_id = ? AND evaluation_id = ?\n\t\t\t LIMIT 1`,\n\t\t)\n\t\t.bind(projectId, evaluationId)\n\t\t.first<AIEvaluationRow>();\n\n\treturn row ? mapEvaluationRows([row])[0] : null;\n}\n\nexport function mapEvaluationRows(\n\trows: AIEvaluationRow[],\n): AIEvaluationRecord[] {\n\treturn rows.map((row) => {\n\t\tconst evaluation: AIEvaluationRecord = {\n\t\t\tevaluationId: row.evaluation_id,\n\t\t\tprojectId: row.project_id,\n\t\t\ttraceId: row.trace_id,\n\t\t\tspanId: row.span_id,\n\t\t\tname: row.name,\n\t\t\tscore: row.score,\n\t\t\tlabel: row.label,\n\t\t\texplanation: row.explanation,\n\t\t\tsource: row.source as AIEvaluationSource,\n\t\t\tmetadata: parseJsonRecord(row.metadata_json),\n\t\t\tcreatedAt: row.created_at,\n\t\t\texpiresAt: row.expires_at,\n\t\t};\n\t\tevaluation.evidenceReferences = aiEvaluationEvidenceReferences(evaluation);\n\t\tevaluation.evidenceContract = EVIDENCE_REFERENCE_CONTRACT;\n\t\treturn evaluation;\n\t});\n}\n","import type { JsonValue } from \"@obsunified/types\";\n\nexport const parseJsonRecord = (\n\tvalue: string | null | undefined,\n): Record<string, JsonValue> => {\n\tif (!value) {\n\t\treturn {};\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(value) as JsonValue;\n\t\treturn parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n\t\t\t? (parsed as Record<string, JsonValue>)\n\t\t\t: {};\n\t} catch {\n\t\treturn {};\n\t}\n};\n\nexport const parseJsonValue = (value: string): JsonValue => {\n\ttry {\n\t\treturn JSON.parse(value) as JsonValue;\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nexport const parseJsonArray = (value: string | null | undefined): unknown[] => {\n\tif (!value) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(value) as unknown;\n\t\treturn Array.isArray(parsed) ? parsed : [];\n\t} catch {\n\t\treturn [];\n\t}\n};\n","import { dialectFor, type SqlDb } from \"../sql-db\";\n\nexport async function purgeExpiredAIData(db: SqlDb): Promise<number> {\n\tconst dialect = dialectFor(db);\n\tconst { meta } = await db\n\t\t.prepare(`DELETE FROM ai_calls WHERE expires_at < ${dialect.now()}`)\n\t\t.run();\n\tconst { meta: payloadMeta } = await db\n\t\t.prepare(`DELETE FROM ai_span_payloads WHERE expires_at < ${dialect.now()}`)\n\t\t.run();\n\tconst { meta: evalMeta } = await db\n\t\t.prepare(\n\t\t\t`DELETE FROM ai_span_evaluations WHERE expires_at < ${dialect.now()}`,\n\t\t)\n\t\t.run();\n\treturn meta.changes + (payloadMeta?.changes ?? 0) + (evalMeta?.changes ?? 0);\n}\n","/**\n * Vendor pricing table for computing llm.cost.total_usd from token counts\n * when a span didn't report cost directly. Conservative — only covers the\n * models we see most often; unknown models get $0 and we log once per model.\n *\n * Prices are USD per 1M tokens. Keep in sync with vendor rate cards.\n * Values as of mid-2026; when stale, bump and add a migration note.\n */\n\nexport interface ModelPricing {\n\tinputPer1M: number;\n\toutputPer1M: number;\n}\n\nconst PRICING: Record<string, ModelPricing> = {\n\t// OpenAI\n\t\"gpt-4o\": { inputPer1M: 2.5, outputPer1M: 10 },\n\t\"gpt-4o-mini\": { inputPer1M: 0.15, outputPer1M: 0.6 },\n\t\"gpt-4-turbo\": { inputPer1M: 10, outputPer1M: 30 },\n\t\"gpt-4\": { inputPer1M: 30, outputPer1M: 60 },\n\t\"gpt-3.5-turbo\": { inputPer1M: 0.5, outputPer1M: 1.5 },\n\to1: { inputPer1M: 15, outputPer1M: 60 },\n\t\"o1-mini\": { inputPer1M: 3, outputPer1M: 12 },\n\n\t// Anthropic\n\t\"claude-3-5-sonnet\": { inputPer1M: 3, outputPer1M: 15 },\n\t\"claude-3-5-haiku\": { inputPer1M: 0.8, outputPer1M: 4 },\n\t\"claude-3-opus\": { inputPer1M: 15, outputPer1M: 75 },\n\t\"claude-3-sonnet\": { inputPer1M: 3, outputPer1M: 15 },\n\t\"claude-3-haiku\": { inputPer1M: 0.25, outputPer1M: 1.25 },\n\t\"claude-opus-4\": { inputPer1M: 15, outputPer1M: 75 },\n\t\"claude-sonnet-4\": { inputPer1M: 3, outputPer1M: 15 },\n\n\t// Google\n\t\"gemini-1.5-pro\": { inputPer1M: 1.25, outputPer1M: 5 },\n\t\"gemini-1.5-flash\": { inputPer1M: 0.075, outputPer1M: 0.3 },\n\t\"gemini-2.0-flash\": { inputPer1M: 0.1, outputPer1M: 0.4 },\n};\n\n// Resolve a model identifier to its pricing by longest-prefix match so\n// `gpt-4o-2024-11-20` hits `gpt-4o`, `claude-3-5-sonnet-20240620` hits\n// `claude-3-5-sonnet`, etc.\nconst lookupCache = new Map<string, ModelPricing | null>();\n\nexport function getModelPricing(\n\tmodel: string | null | undefined,\n): ModelPricing | null {\n\tif (!model) return null;\n\tconst normalized = model.toLowerCase();\n\tconst cached = lookupCache.get(normalized);\n\tif (cached !== undefined) return cached;\n\n\tlet best: { key: string; pricing: ModelPricing } | null = null;\n\tfor (const [key, pricing] of Object.entries(PRICING)) {\n\t\tconst matchesModel = normalized === key || normalized.startsWith(`${key}-`);\n\t\tif (matchesModel && (!best || key.length > best.key.length)) {\n\t\t\tbest = { key, pricing };\n\t\t}\n\t}\n\tconst result = best?.pricing ?? null;\n\tlookupCache.set(normalized, result);\n\treturn result;\n}\n\n/**\n * Compute USD cost from token counts using the pricing table. Returns null\n * when the model is unknown — caller should fall back to the cost attribute\n * on the span (if any) rather than reporting $0.\n */\nexport function computeCost(\n\tmodel: string | null | undefined,\n\tpromptTokens: number | null | undefined,\n\tcompletionTokens: number | null | undefined,\n): number | null {\n\tconst pricing = getModelPricing(model);\n\tif (!pricing) return null;\n\tconst input = ((promptTokens ?? 0) * pricing.inputPer1M) / 1_000_000;\n\tconst output = ((completionTokens ?? 0) * pricing.outputPer1M) / 1_000_000;\n\treturn input + output;\n}\n","import type { JsonValue } from \"@obsunified/types\";\nimport { computeCost } from \"../ai-pricing\";\n\nexport const attrNum = (\n\tattrs: Record<string, JsonValue>,\n\tkey: string,\n): number | null => {\n\tconst v = attrs[key];\n\treturn typeof v === \"number\" && Number.isFinite(v) ? v : null;\n};\n\nexport const attrStr = (\n\tattrs: Record<string, JsonValue>,\n\tkey: string,\n): string | null => {\n\tconst v = attrs[key];\n\treturn typeof v === \"string\" && v.length > 0 ? v : null;\n};\n\n/**\n * Enrich a span's attributes with a computed `llm.cost.total_usd` when the\n * span has token counts but no reported cost. Mutates the passed attrs\n * object and returns the final cost (or null).\n */\nexport const enrichCost = (attrs: Record<string, JsonValue>): number | null => {\n\tconst existing = attrNum(attrs, \"llm.cost.total_usd\");\n\tif (existing !== null) return existing;\n\tconst model = attrStr(attrs, \"llm.model_name\");\n\tconst prompt = attrNum(attrs, \"llm.token_count.prompt\");\n\tconst completion = attrNum(attrs, \"llm.token_count.completion\");\n\tif (prompt === null && completion === null) return null;\n\tconst cost = computeCost(model, prompt, completion);\n\tif (cost === null) return null;\n\tattrs[\"llm.cost.total_usd\"] = cost;\n\tattrs[\"llm.cost.computed\"] = true;\n\treturn cost;\n};\n","import type {\n\tAISessionDetailResponse,\n\tAISessionSummary,\n\tAISessionsListOptions,\n\tAISessionsListResponse,\n\tAISpanRecord,\n\tJsonValue,\n} from \"@obsunified/types\";\nimport { parseJsonRecord } from \"../json\";\nimport { dialectFor, type SqlDb } from \"../sql-db\";\nimport { mapEvaluationRows } from \"./evaluations\";\nimport { attrNum, enrichCost } from \"./helpers\";\nimport type {\n\tAIEvaluationRow,\n\tAISessionPreviewRow,\n\tAISessionRow,\n\tAISpanRow,\n} from \"./types\";\nimport { clampInt } from \"./types\";\n\nexport async function listAISessions(\n\tdb: SqlDb,\n\toptions: AISessionsListOptions,\n): Promise<AISessionsListResponse> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"AIStore.listSessions: projectId is required\");\n\tconst dialect = dialectFor(db);\n\tconst hours = clampInt(options.hours, 1, 720, 24);\n\tconst limit = clampInt(options.limit, 1, 1000, 100);\n\n\tlet sql = `\n SELECT\n p.session_id AS session_id,\n MAX(p.user_id) AS user_id,\n COUNT(*) AS span_count,\n SUM(CASE WHEN p.span_kind = 'LLM' THEN 1 ELSE 0 END) AS llm_span_count,\n SUM(CASE WHEN s.status_code = 2 THEN 1 ELSE 0 END) AS error_count,\n SUM(CAST(${dialect.jsonText(\"s.attributes_json\", '$.\"llm.token_count.prompt\"')} AS REAL)) AS prompt_tokens,\n SUM(CAST(${dialect.jsonText(\"s.attributes_json\", '$.\"llm.token_count.completion\"')} AS REAL)) AS completion_tokens,\n SUM(CAST(${dialect.jsonText(\"s.attributes_json\", '$.\"llm.cost.total_usd\"')} AS REAL)) AS cost_usd,\n MIN(s.start_time) AS first_span_at,\n MAX(s.start_time) AS last_span_at,\n COUNT(DISTINCT s.trace_id) AS trace_count\n FROM ai_span_payloads p\n INNER JOIN telemetry_spans s\n ON s.trace_id = p.trace_id AND s.span_id = p.span_id\n WHERE p.project_id = ?\n AND p.session_id IS NOT NULL\n AND p.received_at >= ${dialect.sinceHours(\"?\")}\n `;\n\tconst params: unknown[] = [options.projectId, hours];\n\tif (options.userId) {\n\t\tsql += ` AND p.user_id = ?`;\n\t\tparams.push(options.userId);\n\t}\n\tsql += ` GROUP BY p.session_id ORDER BY last_span_at DESC LIMIT ?`;\n\tparams.push(limit);\n\n\tconst results = await db\n\t\t.prepare(sql)\n\t\t.bind(...params)\n\t\t.all<AISessionRow>();\n\tconst sessionRows = results.results || [];\n\tconst previewBySession = await loadSessionPreviews(\n\t\tdb,\n\t\tdialect,\n\t\toptions.projectId,\n\t\thours,\n\t\tsessionRows.map((row) => row.session_id),\n\t);\n\n\tconst sessions: AISessionSummary[] = sessionRows.map((row) => ({\n\t\tsessionId: row.session_id,\n\t\tuserId: row.user_id ?? null,\n\t\tspanCount: row.span_count ?? 0,\n\t\tllmSpanCount: row.llm_span_count ?? 0,\n\t\terrorCount: row.error_count ?? 0,\n\t\ttotalPromptTokens: row.prompt_tokens ?? 0,\n\t\ttotalCompletionTokens: row.completion_tokens ?? 0,\n\t\ttotalCostUsd: row.cost_usd ?? 0,\n\t\tfirstSpanAt: row.first_span_at,\n\t\tlastSpanAt: row.last_span_at,\n\t\ttraceCount: row.trace_count ?? 0,\n\t\tlastInputPreview: previewBySession.get(row.session_id) ?? null,\n\t}));\n\n\treturn {\n\t\tsessions,\n\t\twindowHours: hours,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n\nexport async function getAISessionDetail(\n\tdb: SqlDb,\n\tprojectId: string,\n\tsessionId: string,\n): Promise<AISessionDetailResponse> {\n\tif (!projectId) throw new Error(\"AIStore.getSession: projectId is required\");\n\tif (!sessionId) throw new Error(\"AIStore.getSession: sessionId is required\");\n\n\tconst sql = `\n SELECT\n s.trace_id AS trace_id,\n s.span_id AS span_id,\n s.parent_span_id AS parent_span_id,\n s.service_name AS service_name,\n s.span_name AS span_name,\n s.status_code AS status_code,\n s.status_message AS status_message,\n s.start_time AS start_time,\n s.end_time AS end_time,\n s.duration_ms AS duration_ms,\n s.attributes_json AS attributes_json,\n p.span_kind AS span_kind,\n p.input_json AS input_json,\n p.output_json AS output_json,\n p.user_id AS user_id\n FROM ai_span_payloads p\n INNER JOIN telemetry_spans s\n ON s.trace_id = p.trace_id AND s.span_id = p.span_id\n WHERE p.project_id = ? AND p.session_id = ?\n ORDER BY s.start_time ASC\n LIMIT 1000\n `;\n\tconst results = await db\n\t\t.prepare(sql)\n\t\t.bind(projectId, sessionId)\n\t\t.all<AISpanRow>();\n\n\tconst state = {\n\t\tuserId: null as string | null,\n\t\ttotalPromptTokens: 0,\n\t\ttotalCompletionTokens: 0,\n\t\ttotalCostUsd: 0,\n\t\terrorCount: 0,\n\t\tfirstSpanAt: null as string | null,\n\t\tlastSpanAt: null as string | null,\n\t};\n\n\tconst spans: AISpanRecord[] = (results.results || []).map((row) =>\n\t\tmapSessionSpan(row, state),\n\t);\n\tconst evaluations = await loadSessionEvaluations(db, projectId, spans);\n\n\treturn {\n\t\tsessionId,\n\t\tuserId: state.userId,\n\t\tspans,\n\t\tevaluations,\n\t\tsummary: {\n\t\t\tspanCount: spans.length,\n\t\t\ttotalPromptTokens: state.totalPromptTokens,\n\t\t\ttotalCompletionTokens: state.totalCompletionTokens,\n\t\t\ttotalCostUsd: state.totalCostUsd,\n\t\t\terrorCount: state.errorCount,\n\t\t\tfirstSpanAt: state.firstSpanAt,\n\t\t\tlastSpanAt: state.lastSpanAt,\n\t\t},\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n\nasync function loadSessionPreviews(\n\tdb: SqlDb,\n\tdialect: ReturnType<typeof dialectFor>,\n\tprojectId: string,\n\thours: number,\n\tsessionIds: string[],\n) {\n\tconst previewBySession = new Map<string, string>();\n\tif (sessionIds.length === 0) return previewBySession;\n\n\tconst previewRows = await db\n\t\t.prepare(\n\t\t\t`\n SELECT p.session_id, p.input_json, s.start_time\n FROM ai_span_payloads p\n INNER JOIN telemetry_spans s\n ON s.trace_id = p.trace_id AND s.span_id = p.span_id\n WHERE p.project_id = ?\n AND p.session_id IS NOT NULL\n AND p.session_id IN (${sessionIds.map(() => \"?\").join(\", \")})\n AND p.received_at >= ${dialect.sinceHours(\"?\")}\n AND p.input_json IS NOT NULL\n ORDER BY s.start_time DESC\n LIMIT ?\n `,\n\t\t)\n\t\t.bind(projectId, ...sessionIds, hours, sessionIds.length * 5)\n\t\t.all<AISessionPreviewRow>();\n\n\tfor (const row of previewRows.results || []) {\n\t\tif (!previewBySession.has(row.session_id)) {\n\t\t\tconst raw = typeof row.input_json === \"string\" ? row.input_json : \"\";\n\t\t\tpreviewBySession.set(\n\t\t\t\trow.session_id,\n\t\t\t\traw.length > 200 ? `${raw.slice(0, 200)}…` : raw,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn previewBySession;\n}\n\nfunction mapSessionSpan(\n\trow: AISpanRow,\n\tstate: {\n\t\tuserId: string | null;\n\t\ttotalPromptTokens: number;\n\t\ttotalCompletionTokens: number;\n\t\ttotalCostUsd: number;\n\t\terrorCount: number;\n\t\tfirstSpanAt: string | null;\n\t\tlastSpanAt: string | null;\n\t},\n): AISpanRecord {\n\tconst attrs = parseJsonRecord(row.attributes_json) as Record<\n\t\tstring,\n\t\tJsonValue\n\t>;\n\tconst cost = enrichCost(attrs);\n\tif (!state.userId && row.user_id) state.userId = row.user_id;\n\tstate.totalPromptTokens += attrNum(attrs, \"llm.token_count.prompt\") ?? 0;\n\tstate.totalCompletionTokens +=\n\t\tattrNum(attrs, \"llm.token_count.completion\") ?? 0;\n\tif (cost !== null) state.totalCostUsd += cost;\n\tif (row.status_code === 2) state.errorCount++;\n\tif (!state.firstSpanAt || row.start_time < state.firstSpanAt) {\n\t\tstate.firstSpanAt = row.start_time;\n\t}\n\tif (!state.lastSpanAt || row.start_time > state.lastSpanAt) {\n\t\tstate.lastSpanAt = row.start_time;\n\t}\n\n\treturn {\n\t\ttraceId: row.trace_id,\n\t\tspanId: row.span_id,\n\t\tparentSpanId: row.parent_span_id,\n\t\tserviceName: row.service_name,\n\t\tspanName: row.span_name,\n\t\tspanKind: row.span_kind,\n\t\tstatusCode: row.status_code ?? 0,\n\t\tstatusMessage: row.status_message,\n\t\tstartTime: row.start_time,\n\t\tendTime: row.end_time ?? row.start_time,\n\t\tdurationMs: row.duration_ms ?? 0,\n\t\tattributes: attrs,\n\t\tinputJson: row.input_json,\n\t\toutputJson: row.output_json,\n\t};\n}\n\nasync function loadSessionEvaluations(\n\tdb: SqlDb,\n\tprojectId: string,\n\tspans: AISpanRecord[],\n) {\n\tif (spans.length === 0) return [];\n\n\tconst placeholders = spans.map(() => \"(?, ?)\").join(\", \");\n\tconst bindings: unknown[] = [projectId];\n\tfor (const span of spans) {\n\t\tbindings.push(span.traceId, span.spanId);\n\t}\n\tconst sql = `\n SELECT * FROM ai_span_evaluations\n WHERE project_id = ?\n AND (trace_id, span_id) IN (${placeholders})\n ORDER BY created_at DESC\n `;\n\tconst results = await db\n\t\t.prepare(sql)\n\t\t.bind(...bindings)\n\t\t.all<AIEvaluationRow>();\n\treturn mapEvaluationRows(results.results || []);\n}\n","import type {\n\tAISpanRecord,\n\tAISpansOverviewOptions,\n\tAISpansOverviewResponse,\n\tJsonValue,\n} from \"@obsunified/types\";\nimport { parseJsonRecord } from \"../json\";\nimport { dialectFor, type SqlDb } from \"../sql-db\";\nimport { enrichCost } from \"./helpers\";\nimport type { AISpanRow } from \"./types\";\nimport { clampInt } from \"./types\";\n\nexport async function getAISpansOverview(\n\tdb: SqlDb,\n\toptions: AISpansOverviewOptions,\n): Promise<AISpansOverviewResponse> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"AIStore.getAISpans: projectId is required\");\n\tconst dialect = dialectFor(db);\n\tconst hours = clampInt(options.hours, 1, 720, 24);\n\tconst limit = clampInt(options.limit, 1, 1000, 100);\n\n\tlet sql = `\n SELECT\n s.trace_id AS trace_id,\n s.span_id AS span_id,\n s.parent_span_id AS parent_span_id,\n s.service_name AS service_name,\n s.span_name AS span_name,\n s.status_code AS status_code,\n s.status_message AS status_message,\n s.start_time AS start_time,\n s.end_time AS end_time,\n s.duration_ms AS duration_ms,\n s.attributes_json AS attributes_json,\n p.span_kind AS span_kind,\n p.input_json AS input_json,\n p.output_json AS output_json\n FROM ai_span_payloads p\n INNER JOIN telemetry_spans s\n ON s.trace_id = p.trace_id AND s.span_id = p.span_id\n WHERE p.project_id = ?\n AND p.received_at >= ${dialect.sinceHours(\"?\")}\n `;\n\tconst params: unknown[] = [options.projectId, hours];\n\n\tif (options.kind) {\n\t\tsql += ` AND p.span_kind = ?`;\n\t\tparams.push(options.kind);\n\t}\n\tif (options.service) {\n\t\tsql += ` AND s.service_name = ?`;\n\t\tparams.push(options.service);\n\t}\n\tif (options.traceId) {\n\t\tsql += ` AND s.trace_id = ?`;\n\t\tparams.push(options.traceId);\n\t}\n\n\tsql += ` ORDER BY s.start_time DESC LIMIT ?`;\n\tparams.push(limit);\n\n\tconst results = await db\n\t\t.prepare(sql)\n\t\t.bind(...params)\n\t\t.all<AISpanRow>();\n\n\tconst spans: AISpanRecord[] = (results.results || []).map((row) => {\n\t\tconst attrs = parseJsonRecord(row.attributes_json) as Record<\n\t\t\tstring,\n\t\t\tJsonValue\n\t\t>;\n\t\tenrichCost(attrs);\n\t\treturn {\n\t\t\ttraceId: row.trace_id,\n\t\t\tspanId: row.span_id,\n\t\t\tparentSpanId: row.parent_span_id,\n\t\t\tserviceName: row.service_name,\n\t\t\tspanName: row.span_name,\n\t\t\tspanKind: row.span_kind,\n\t\t\tstatusCode: row.status_code ?? 0,\n\t\t\tstatusMessage: row.status_message,\n\t\t\tstartTime: row.start_time,\n\t\t\tendTime: row.end_time ?? row.start_time,\n\t\t\tdurationMs: row.duration_ms ?? 0,\n\t\t\tattributes: attrs,\n\t\t\tinputJson: row.input_json,\n\t\t\toutputJson: row.output_json,\n\t\t};\n\t});\n\n\tconst byKind: Record<string, number> = {};\n\tlet errorSpans = 0;\n\tfor (const span of spans) {\n\t\tbyKind[span.spanKind] = (byKind[span.spanKind] ?? 0) + 1;\n\t\tif (span.statusCode === 2) errorSpans++;\n\t}\n\n\treturn {\n\t\tspans,\n\t\tsummary: {\n\t\t\ttotalSpans: spans.length,\n\t\t\tbyKind,\n\t\t\terrorSpans,\n\t\t},\n\t\twindowHours: hours,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n","import type {\n\tAICallRecord,\n\tAICallsOverviewOptions,\n\tAICallsOverviewResponse,\n\tAIEvaluationsListOptions,\n\tAIEvaluationsListResponse,\n\tAISessionDetailResponse,\n\tAISessionsListOptions,\n\tAISessionsListResponse,\n\tAISpansOverviewOptions,\n\tAISpansOverviewResponse,\n} from \"@obsunified/types\";\nimport { getAICallsOverview, ingestAICallBatch } from \"./ai-store/calls\";\nimport {\n\tgetAIEvaluation,\n\tingestAIEvaluations,\n\tlistAIEvaluations,\n} from \"./ai-store/evaluations\";\nimport { purgeExpiredAIData } from \"./ai-store/retention\";\nimport { getAISessionDetail, listAISessions } from \"./ai-store/sessions\";\nimport { getAISpansOverview } from \"./ai-store/spans\";\nimport type { IngestEvaluation } from \"./ai-store/types\";\nimport type { SqlDb } from \"./sql-db\";\n\nexport type { IngestEvaluation } from \"./ai-store/types\";\n\nexport class AIStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync ingestBatch(calls: AICallRecord[]): Promise<void> {\n\t\treturn ingestAICallBatch(this.db, calls);\n\t}\n\n\tasync getAICalls(\n\t\toptions: AICallsOverviewOptions,\n\t): Promise<AICallsOverviewResponse> {\n\t\treturn getAICallsOverview(this.db, options);\n\t}\n\n\tasync purgeExpired(): Promise<number> {\n\t\treturn purgeExpiredAIData(this.db);\n\t}\n\n\tasync getAISpans(\n\t\toptions: AISpansOverviewOptions,\n\t): Promise<AISpansOverviewResponse> {\n\t\treturn getAISpansOverview(this.db, options);\n\t}\n\n\tasync listSessions(\n\t\toptions: AISessionsListOptions,\n\t): Promise<AISessionsListResponse> {\n\t\treturn listAISessions(this.db, options);\n\t}\n\n\tasync getSession(\n\t\tprojectId: string,\n\t\tsessionId: string,\n\t): Promise<AISessionDetailResponse> {\n\t\treturn getAISessionDetail(this.db, projectId, sessionId);\n\t}\n\n\tasync ingestEvaluations(evaluations: IngestEvaluation[]): Promise<void> {\n\t\treturn ingestAIEvaluations(this.db, evaluations);\n\t}\n\n\tasync listEvaluations(\n\t\toptions: AIEvaluationsListOptions,\n\t): Promise<AIEvaluationsListResponse> {\n\t\treturn listAIEvaluations(this.db, options);\n\t}\n\n\tasync getEvaluation(projectId: string, evaluationId: string) {\n\t\treturn getAIEvaluation(this.db, projectId, evaluationId);\n\t}\n}\n","/**\n * AnalysesStore — RFC 0002 Stage 1 persistence for application-aware Analyses.\n *\n * Two tables:\n * - analysis_definitions: durable registry of (id, title, group, sql, ...).\n * Refreshed on every scheduled tick by the runner from the in-process\n * analysis registry. Mirrored here so the dashboard can list available\n * analyses without coupling to deploy artifacts.\n * - analysis_results: append-only result rows. Reads are \"latest per\n * analysis_id\" (covered by idx_analysis_results_latest); retention is\n * handled by the existing scheduled cron via purgeExpired().\n */\n\nimport type {\n\tAnalysisDefinition,\n\tAnalysisGroup,\n\tAnalysisResult,\n\tAnalysisSource,\n\tAnalysisStatus,\n\tAnalysisView,\n} from \"@obsunified/types\";\nimport { EVIDENCE_REFERENCE_CONTRACT } from \"@obsunified/types\";\nimport { analysisResultEvidenceReferences } from \"./evidence-references\";\nimport { parseJsonRecord } from \"./json\";\nimport type { SqlDb } from \"./sql-db\";\n\ninterface DefinitionRow {\n\tproject_id: string;\n\tid: string;\n\ttitle: string;\n\tgroup: string;\n\tsource: string;\n\tview: string;\n\trefresh_seconds: number | null;\n\tsql: string | null;\n\tscope_json: string | null;\n\tcreated_at: string;\n\tupdated_at: string;\n\tlast_run_at: string | null;\n}\n\ninterface ResultRow {\n\tid: number;\n\tproject_id: string;\n\tanalysis_id: string;\n\tgenerated_at: number;\n\tparams_hash: string | null;\n\tstatus: string;\n\tprimary_value: number | null;\n\tbaseline_value: number | null;\n\tdelta_pct: number | null;\n\tpayload_json: string;\n\tnarrative: string | null;\n\tnarrative_signature: string | null;\n\tduration_ms: number;\n\texpires_at: number;\n}\n\nconst rowToDefinition = (row: DefinitionRow): AnalysisDefinition => {\n\tconst def: AnalysisDefinition = {\n\t\tid: row.id,\n\t\ttitle: row.title,\n\t\tgroup: row.group as AnalysisGroup,\n\t\tsource: row.source as AnalysisSource,\n\t\tview: row.view as AnalysisView,\n\t};\n\tif (row.refresh_seconds !== null && row.refresh_seconds !== undefined) {\n\t\tdef.refreshSeconds = row.refresh_seconds;\n\t}\n\tif (row.sql) {\n\t\tdef.sql = row.sql;\n\t}\n\tif (row.scope_json) {\n\t\tdef.scope = parseJsonRecord(row.scope_json);\n\t}\n\treturn def;\n};\n\nconst rowToResult = (row: ResultRow): AnalysisResult => {\n\tconst result: AnalysisResult = {\n\t\tanalysisId: row.analysis_id,\n\t\tprojectId: row.project_id,\n\t\tgeneratedAt: new Date(row.generated_at).toISOString(),\n\t\tparamsHash: row.params_hash,\n\t\tstatus: row.status as AnalysisStatus,\n\t\tprimaryValue: row.primary_value,\n\t\tbaselineValue: row.baseline_value,\n\t\tdeltaPct: row.delta_pct,\n\t\tpayload: row.payload_json ? parseJsonRecord(row.payload_json) : {},\n\t\tnarrative: row.narrative,\n\t\tnarrativeSignature: row.narrative_signature,\n\t\tdurationMs: row.duration_ms,\n\t};\n\tconst evidenceReferences = analysisResultEvidenceReferences(result);\n\tif (evidenceReferences.length > 0) {\n\t\tresult.evidenceReferences = evidenceReferences;\n\t\tresult.evidenceContract = EVIDENCE_REFERENCE_CONTRACT;\n\t}\n\treturn result;\n};\n\nexport class AnalysesStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync upsertDefinition(\n\t\tprojectId: string,\n\t\tdef: AnalysisDefinition,\n\t): Promise<void> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"AnalysesStore.upsertDefinition: projectId is required\");\n\t\tif (!def.id)\n\t\t\tthrow new Error(\"AnalysesStore.upsertDefinition: def.id is required\");\n\n\t\tconst now = new Date().toISOString();\n\t\tconst scopeJson = def.scope ? JSON.stringify(def.scope) : null;\n\t\tconst refreshSeconds =\n\t\t\tdef.refreshSeconds === undefined || def.refreshSeconds === null\n\t\t\t\t? null\n\t\t\t\t: def.refreshSeconds;\n\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO analysis_definitions (\n\t\t\t\t\tproject_id, id, title, \"group\", source, view,\n\t\t\t\t\trefresh_seconds, sql, scope_json,\n\t\t\t\t\tcreated_at, updated_at, last_run_at\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)\n\t\t\t\tON CONFLICT(project_id, id) DO UPDATE SET\n\t\t\t\t\ttitle = excluded.title,\n\t\t\t\t\t\"group\" = excluded.\"group\",\n\t\t\t\t\tsource = excluded.source,\n\t\t\t\t\tview = excluded.view,\n\t\t\t\t\trefresh_seconds = excluded.refresh_seconds,\n\t\t\t\t\tsql = excluded.sql,\n\t\t\t\t\tscope_json = excluded.scope_json,\n\t\t\t\t\tupdated_at = excluded.updated_at`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\tprojectId,\n\t\t\t\tdef.id,\n\t\t\t\tdef.title,\n\t\t\t\tdef.group,\n\t\t\t\tdef.source,\n\t\t\t\tdef.view,\n\t\t\t\trefreshSeconds,\n\t\t\t\tdef.sql ?? null,\n\t\t\t\tscopeJson,\n\t\t\t\tnow,\n\t\t\t\tnow,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync listDefinitions(projectId: string): Promise<AnalysisDefinition[]> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"AnalysesStore.listDefinitions: projectId is required\");\n\t\tconst result = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT project_id, id, title, \"group\" AS \"group\", source, view,\n\t\t\t\t\trefresh_seconds, sql, scope_json,\n\t\t\t\t\tcreated_at, updated_at, last_run_at\n\t\t\t\tFROM analysis_definitions\n\t\t\t\tWHERE project_id = ?\n\t\t\t\tORDER BY \"group\", id`,\n\t\t\t)\n\t\t\t.bind(projectId)\n\t\t\t.all<DefinitionRow>();\n\t\treturn (result.results ?? []).map(rowToDefinition);\n\t}\n\n\tasync getDueAnalyses(\n\t\tprojectId: string,\n\t\tnow: number,\n\t): Promise<AnalysisDefinition[]> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"AnalysesStore.getDueAnalyses: projectId is required\");\n\t\t// last_run_at is stored as ISO string; we compute due-ness in JS so the\n\t\t// comparison is unambiguous regardless of D1's date function support.\n\t\tconst result = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT project_id, id, title, \"group\" AS \"group\", source, view,\n\t\t\t\t\trefresh_seconds, sql, scope_json,\n\t\t\t\t\tcreated_at, updated_at, last_run_at\n\t\t\t\tFROM analysis_definitions\n\t\t\t\tWHERE project_id = ? AND refresh_seconds IS NOT NULL`,\n\t\t\t)\n\t\t\t.bind(projectId)\n\t\t\t.all<DefinitionRow>();\n\n\t\tconst due: AnalysisDefinition[] = [];\n\t\tfor (const row of result.results ?? []) {\n\t\t\tconst refreshSeconds = row.refresh_seconds;\n\t\t\tif (refreshSeconds === null || refreshSeconds === undefined) continue;\n\t\t\tconst lastRunMs = row.last_run_at ? Date.parse(row.last_run_at) : 0;\n\t\t\tif (lastRunMs + refreshSeconds * 1000 < now) {\n\t\t\t\tdue.push(rowToDefinition(row));\n\t\t\t}\n\t\t}\n\t\treturn due;\n\t}\n\n\tasync markRan(\n\t\tprojectId: string,\n\t\tanalysisId: string,\n\t\tranAt: string,\n\t): Promise<void> {\n\t\t// last_started_at = NULL releases the lease so the next tick is free\n\t\t// to re-evaluate refresh_seconds against last_run_at.\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`UPDATE analysis_definitions\n\t\t\t\tSET last_run_at = ?, last_started_at = NULL\n\t\t\t\tWHERE project_id = ? AND id = ?`,\n\t\t\t)\n\t\t\t.bind(ranAt, projectId, analysisId)\n\t\t\t.run();\n\t}\n\n\t/**\n\t * Attempt to claim an analysis for the current tick. Returns true if\n\t * the row was successfully claimed (i.e., this caller is now responsible\n\t * for running it), false if another tick already holds an active lease.\n\t *\n\t * The atomic operation is a single UPDATE … WHERE that only matches when\n\t * the existing claim is NULL or older than the lease window. We use\n\t * meta.changes to detect whether the row actually moved; D1 returns 0\n\t * when the WHERE clause excluded the row.\n\t */\n\tasync claimAnalysis(\n\t\tprojectId: string,\n\t\tanalysisId: string,\n\t\tnow: number,\n\t\tleaseMs: number,\n\t): Promise<boolean> {\n\t\tconst nowIso = new Date(now).toISOString();\n\t\tconst leaseFloorIso = new Date(now - leaseMs).toISOString();\n\t\tconst result = await this.db\n\t\t\t.prepare(\n\t\t\t\t`UPDATE analysis_definitions\n\t\t\t\t SET last_started_at = ?\n\t\t\t\t WHERE project_id = ? AND id = ?\n\t\t\t\t AND (last_started_at IS NULL OR last_started_at < ?)`,\n\t\t\t)\n\t\t\t.bind(nowIso, projectId, analysisId, leaseFloorIso)\n\t\t\t.run();\n\t\treturn (result.meta?.changes ?? 0) > 0;\n\t}\n\n\t/**\n\t * Release a lease without writing to last_run_at — used when the run\n\t * failed and we want the next tick to retry rather than wait the full\n\t * refresh_seconds window.\n\t */\n\tasync releaseClaim(projectId: string, analysisId: string): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`UPDATE analysis_definitions\n\t\t\t\t SET last_started_at = NULL\n\t\t\t\t WHERE project_id = ? AND id = ?`,\n\t\t\t)\n\t\t\t.bind(projectId, analysisId)\n\t\t\t.run();\n\t}\n\n\tasync getLatestResult(\n\t\tprojectId: string,\n\t\tanalysisId: string,\n\t): Promise<AnalysisResult | null> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"AnalysesStore.getLatestResult: projectId is required\");\n\t\tconst row = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT id, project_id, analysis_id, generated_at, params_hash,\n\t\t\t\t\tstatus, primary_value, baseline_value, delta_pct, payload_json,\n\t\t\t\t\tnarrative, narrative_signature, duration_ms, expires_at\n\t\t\t\tFROM analysis_results\n\t\t\t\tWHERE project_id = ? AND analysis_id = ?\n\t\t\t\tORDER BY generated_at DESC\n\t\t\t\tLIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, analysisId)\n\t\t\t.first<ResultRow>();\n\t\treturn row ? rowToResult(row) : null;\n\t}\n\n\tasync getLatestResultsBulk(\n\t\tprojectId: string,\n\t\tanalysisIds: string[],\n\t): Promise<Map<string, AnalysisResult>> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\n\t\t\t\t\"AnalysesStore.getLatestResultsBulk: projectId is required\",\n\t\t\t);\n\t\tif (analysisIds.length === 0) return new Map();\n\n\t\t// Pull a recent window of rows for the requested analyses then group by\n\t\t// analysis_id, taking the row with the largest generated_at per group.\n\t\t// One query, no per-analysis round-trips.\n\t\tconst placeholders = analysisIds.map(() => \"?\").join(\", \");\n\t\tconst result = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT id, project_id, analysis_id, generated_at, params_hash,\n\t\t\t\t\tstatus, primary_value, baseline_value, delta_pct, payload_json,\n\t\t\t\t\tnarrative, narrative_signature, duration_ms, expires_at\n\t\t\t\tFROM analysis_results\n\t\t\t\tWHERE project_id = ? AND analysis_id IN (${placeholders})\n\t\t\t\tORDER BY generated_at DESC`,\n\t\t\t)\n\t\t\t.bind(projectId, ...analysisIds)\n\t\t\t.all<ResultRow>();\n\n\t\tconst latest = new Map<string, AnalysisResult>();\n\t\tfor (const row of result.results ?? []) {\n\t\t\tif (!latest.has(row.analysis_id)) {\n\t\t\t\tlatest.set(row.analysis_id, rowToResult(row));\n\t\t\t}\n\t\t}\n\t\treturn latest;\n\t}\n\n\tasync insertResult(result: AnalysisResult, expiresAt: number): Promise<void> {\n\t\tif (!result.projectId)\n\t\t\tthrow new Error(\"AnalysesStore.insertResult: projectId is required\");\n\t\tif (!result.analysisId)\n\t\t\tthrow new Error(\"AnalysesStore.insertResult: analysisId is required\");\n\n\t\tconst generatedAtMs = Date.parse(result.generatedAt);\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO analysis_results (\n\t\t\t\t\tproject_id, analysis_id, generated_at, params_hash,\n\t\t\t\t\tstatus, primary_value, baseline_value, delta_pct, payload_json,\n\t\t\t\t\tnarrative, narrative_signature, duration_ms, expires_at\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\tresult.projectId,\n\t\t\t\tresult.analysisId,\n\t\t\t\tNumber.isFinite(generatedAtMs) ? generatedAtMs : Date.now(),\n\t\t\t\tresult.paramsHash,\n\t\t\t\tresult.status,\n\t\t\t\tresult.primaryValue,\n\t\t\t\tresult.baselineValue,\n\t\t\t\tresult.deltaPct,\n\t\t\t\tJSON.stringify(result.payload ?? {}),\n\t\t\t\tresult.narrative,\n\t\t\t\tresult.narrativeSignature,\n\t\t\t\tresult.durationMs,\n\t\t\t\texpiresAt,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\t/**\n\t * Count how many narrative-bearing results we've written for this project\n\t * in the trailing `windowMinutes`. Used as a per-project safety rail\n\t * (RFC 0002 Stage 3 narrative budget) so a misconfigured `only_when` or\n\t * a flapping panel can't run up an LLM bill.\n\t *\n\t * Counts `narrative IS NOT NULL`, including reuse-cached narratives,\n\t * because what we're protecting against is *write rate* — the budget\n\t * caps generation, not display. Reused narratives don't actually call\n\t * the LLM, so the more accurate \"calls in last hour\" reading is just\n\t * a proxy. For Stage 3 this is good enough; if it bites we'll add a\n\t * dedicated `narrative_calls` table.\n\t */\n\tasync countNarrativesInWindow(\n\t\tprojectId: string,\n\t\twindowMinutes: number,\n\t): Promise<number> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\n\t\t\t\t\"AnalysesStore.countNarrativesInWindow: projectId is required\",\n\t\t\t);\n\t\tconst since = Date.now() - windowMinutes * 60 * 1000;\n\t\tconst row = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT COUNT(*) AS n\n\t\t\t\tFROM analysis_results\n\t\t\t\tWHERE project_id = ?\n\t\t\t\t\tAND narrative IS NOT NULL\n\t\t\t\t\tAND generated_at >= ?`,\n\t\t\t)\n\t\t\t.bind(projectId, since)\n\t\t\t.first<{ n: number }>();\n\t\treturn row?.n ?? 0;\n\t}\n\n\t/**\n\t * RFC 0002 Stage 6 — Ask-box auto-pinning input.\n\t *\n\t * Records that an analysis was cited in evidence on a successful Ask\n\t * answer. The Health tab's Pinned group derives from `getTopAskedAnalyses`\n\t * which reads these rows. We deliberately keep this table append-only\n\t * and keyed only by `(project_id, analysis_id, asked_at)` — pinning is\n\t * inherently observational; explicit user pins live elsewhere.\n\t */\n\tasync recordAskEvidence(\n\t\tprojectId: string,\n\t\tanalysisIds: readonly string[],\n\t): Promise<void> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"AnalysesStore.recordAskEvidence: projectId required\");\n\t\tconst unique = Array.from(new Set(analysisIds.filter(Boolean)));\n\t\tif (unique.length === 0) return;\n\t\tconst askedAt = Date.now();\n\t\tconst stmt = this.db.prepare(\n\t\t\t`INSERT INTO ask_evidence_events (project_id, analysis_id, asked_at)\n\t\t\t VALUES (?, ?, ?)`,\n\t\t);\n\t\tfor (const id of unique) {\n\t\t\tawait stmt.bind(projectId, id, askedAt).run();\n\t\t}\n\t}\n\n\t/**\n\t * Top N analyses cited by the Ask box in the trailing window. Used as\n\t * the auto-pin signal — no manual UX, just \"what are people actually\n\t * asking about right now?\"\n\t */\n\tasync getTopAskedAnalyses(\n\t\tprojectId: string,\n\t\twindowDays = 7,\n\t\tlimit = 6,\n\t): Promise<Array<{ analysisId: string; citations: number }>> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"AnalysesStore.getTopAskedAnalyses: projectId required\");\n\t\tconst since = Date.now() - windowDays * 24 * 3600 * 1000;\n\t\tconst result = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT analysis_id, COUNT(*) AS citations\n\t\t\t\tFROM ask_evidence_events\n\t\t\t\tWHERE project_id = ? AND asked_at >= ?\n\t\t\t\tGROUP BY analysis_id\n\t\t\t\tORDER BY citations DESC, MAX(asked_at) DESC\n\t\t\t\tLIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, since, limit)\n\t\t\t.all<{ analysis_id: string; citations: number }>();\n\t\treturn (result.results ?? []).map((r) => ({\n\t\t\tanalysisId: r.analysis_id,\n\t\t\tcitations: r.citations,\n\t\t}));\n\t}\n\n\tasync purgeExpired(): Promise<number> {\n\t\tconst now = Date.now();\n\t\tconst result = await this.db\n\t\t\t.prepare(`DELETE FROM analysis_results WHERE expires_at <= ?`)\n\t\t\t.bind(now)\n\t\t\t.run();\n\t\treturn result.meta?.changes ?? 0;\n\t}\n}\n","// RFC 0002 Stage 1 — Tier 1 derivation engine.\n//\n// `deriveAnalysesForProject` queries the project's recent telemetry to infer\n// its `TelemetryShape` (services, cross-service edges, messaging topics,\n// presence of LLM spans) and emits one or more AnalysisDefinitions per\n// detected dimension. The shape query is cached in module-level memory for\n// 5 minutes per project — the derivation cron runs every ~5min so this\n// avoids re-hitting D1 on the dashboard request path.\n//\n// All emitted SQL is executable as-is by the runner; the project id and\n// the relevant scope (service / edge / topic) are baked in at derivation\n// time. Identifiers in analysis ids are slugged (slashes, colons, spaces\n// → underscores) so they're URL-safe.\n\nimport type { AnalysisDefinition } from \"@obsunified/types\";\n\ninterface TelemetryShape {\n\tservices: string[];\n\tedges: Array<{ source: string; target: string }>;\n\tmessagingTopics: string[];\n\thasLlmSpans: boolean;\n}\n\ninterface CachedShape {\n\tshape: TelemetryShape;\n\texpiresAt: number;\n}\n\nconst SHAPE_CACHE_TTL_MS = 5 * 60 * 1000;\nconst SHAPE_CACHE_MAX_ENTRIES = 200;\nconst shapeCache: Map<string, CachedShape> = new Map();\n\nconst slug = (value: string): string =>\n\tvalue.replace(/[/:\\s]+/g, \"_\").replace(/[^A-Za-z0-9_.-]/g, \"_\");\n\nconst sqlEscape = (value: string): string => value.replace(/'/g, \"''\");\n\ninterface D1Result<T = Record<string, unknown>> {\n\tresults: T[];\n}\n\ninterface D1PreparedStatement {\n\tbind(...values: unknown[]): D1PreparedStatement;\n\tall<T = Record<string, unknown>>(): Promise<D1Result<T>>;\n}\n\ninterface D1Database {\n\tprepare(query: string): D1PreparedStatement;\n}\n\nconst fetchShape = async (\n\tprojectId: string,\n\tdb: D1Database,\n): Promise<TelemetryShape> => {\n\t// Distinct services in the last hour.\n\tconst servicesRes = await db\n\t\t.prepare(\n\t\t\t`SELECT DISTINCT service_name\n\t\t\t FROM telemetry_spans\n\t\t\t WHERE project_id = ?\n\t\t\t AND service_name IS NOT NULL\n\t\t\t AND received_at >= datetime('now', '-1 hour')`,\n\t\t)\n\t\t.bind(projectId)\n\t\t.all<{ service_name: string }>();\n\n\tconst services = servicesRes.results\n\t\t.map((row) => row.service_name)\n\t\t.filter(\n\t\t\t(name): name is string => typeof name === \"string\" && name.length > 0,\n\t\t);\n\n\t// Cross-service edges: parent span's service != child span's service,\n\t// within the same trace, in the last hour. We only keep distinct\n\t// (parent_service, child_service) pairs.\n\tconst edgesRes = await db\n\t\t.prepare(\n\t\t\t`SELECT DISTINCT parent.service_name AS source_service,\n\t\t\t child.service_name AS target_service\n\t\t\t FROM telemetry_spans child\n\t\t\t JOIN telemetry_spans parent\n\t\t\t ON parent.project_id = child.project_id\n\t\t\t AND parent.trace_id = child.trace_id\n\t\t\t AND parent.span_id = child.parent_span_id\n\t\t\t WHERE child.project_id = ?\n\t\t\t AND child.received_at >= datetime('now', '-1 hour')\n\t\t\t AND parent.service_name IS NOT NULL\n\t\t\t AND child.service_name IS NOT NULL\n\t\t\t AND parent.service_name <> child.service_name`,\n\t\t)\n\t\t.bind(projectId)\n\t\t.all<{ source_service: string; target_service: string }>();\n\n\tconst edges = edgesRes.results\n\t\t.filter((row) => row.source_service && row.target_service)\n\t\t.map((row) => ({ source: row.source_service, target: row.target_service }));\n\n\t// Messaging topics: spans that carry a messaging.destination attribute.\n\tconst topicsRes = await db\n\t\t.prepare(\n\t\t\t`SELECT DISTINCT json_extract(attributes_json, '$.\"messaging.destination\"') AS topic\n\t\t\t FROM telemetry_spans\n\t\t\t WHERE project_id = ?\n\t\t\t AND received_at >= datetime('now', '-1 hour')\n\t\t\t AND json_extract(attributes_json, '$.\"messaging.destination\"') IS NOT NULL`,\n\t\t)\n\t\t.bind(projectId)\n\t\t.all<{ topic: string }>();\n\n\tconst messagingTopics = topicsRes.results\n\t\t.map((row) => row.topic)\n\t\t.filter(\n\t\t\t(topic): topic is string => typeof topic === \"string\" && topic.length > 0,\n\t\t);\n\n\t// Are there any LLM-kind spans? OpenInference uses\n\t// `openinference.span.kind` = 'LLM'. We also accept the more general\n\t// `gen_ai.system` attribute as a heuristic.\n\tconst llmRes = await db\n\t\t.prepare(\n\t\t\t`SELECT 1\n\t\t\t FROM telemetry_spans\n\t\t\t WHERE project_id = ?\n\t\t\t AND received_at >= datetime('now', '-1 hour')\n\t\t\t AND (\n\t\t\t json_extract(attributes_json, '$.\"openinference.span.kind\"') = 'LLM'\n\t\t\t OR json_extract(attributes_json, '$.\"gen_ai.system\"') IS NOT NULL\n\t\t\t )\n\t\t\t LIMIT 1`,\n\t\t)\n\t\t.bind(projectId)\n\t\t.all<{ \"1\": number }>();\n\n\treturn {\n\t\tservices,\n\t\tedges,\n\t\tmessagingTopics,\n\t\thasLlmSpans: llmRes.results.length > 0,\n\t};\n};\n\nconst getShape = async (\n\tprojectId: string,\n\tdb: D1Database,\n): Promise<TelemetryShape> => {\n\tconst cached = shapeCache.get(projectId);\n\tconst nowMs = Date.now();\n\tif (cached && cached.expiresAt > nowMs) return cached.shape;\n\n\tconst shape = await fetchShape(projectId, db);\n\tpruneShapeCache(nowMs);\n\tshapeCache.set(projectId, {\n\t\tshape,\n\t\texpiresAt: nowMs + SHAPE_CACHE_TTL_MS,\n\t});\n\treturn shape;\n};\n\nfunction pruneShapeCache(nowMs: number): void {\n\tfor (const [key, entry] of shapeCache) {\n\t\tif (entry.expiresAt <= nowMs) shapeCache.delete(key);\n\t}\n\twhile (shapeCache.size >= SHAPE_CACHE_MAX_ENTRIES) {\n\t\tconst oldestKey = shapeCache.keys().next().value;\n\t\tif (!oldestKey) break;\n\t\tshapeCache.delete(oldestKey);\n\t}\n}\n\n// ── Builders ────────────────────────────────────────────────────────────────\n\nconst makeServiceErrorRate = (\n\tprojectId: string,\n\tservice: string,\n): AnalysisDefinition => ({\n\tid: `service_error_rate::${slug(service)}`,\n\ttitle: `${service} — error rate`,\n\tgroup: \"Services\",\n\tsource: \"tier1\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tscope: { service },\n\tnarrate: {\n\t\tprompt: `${service} error rate moved to {{primary}} (was {{baseline}}, {{delta_pct}}). If the payload names the dominant span/route, call it out. Time anchor.`,\n\t\tonly_when: \"status_changed || delta_pct>25\",\n\t},\n\t// Last 5 minutes vs trailing 1h baseline (excluding the current 5m).\n\t// Status thresholds match overall_error_rate: critical>5%, warn>1%.\n\tsql: `\n\t\tWITH now_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND service_name = '${sqlEscape(service)}'\n\t\t\t\tAND received_at >= datetime('now', '-5 minutes')\n\t\t),\n\t\tbase_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND service_name = '${sqlEscape(service)}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t\t\tAND received_at < datetime('now', '-5 minutes')\n\t\t),\n\t\tspark AS (\n\t\t\tSELECT\n\t\t\t\tstrftime('%Y-%m-%dT%H:%M:00Z', received_at) AS minute,\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND service_name = '${sqlEscape(service)}'\n\t\t\t\tAND received_at >= datetime('now', '-30 minutes')\n\t\t\tGROUP BY minute\n\t\t\tORDER BY minute ASC\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT total FROM now_window) = 0 THEN 'unknown'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.05 THEN 'critical'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.01 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\tCASE WHEN (SELECT total FROM now_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t / (SELECT total FROM now_window) END AS primary_value,\n\t\t\tCASE WHEN (SELECT total FROM base_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM base_window) AS REAL)\n\t\t\t / (SELECT total FROM base_window) END AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'service', '${sqlEscape(service)}',\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '1h',\n\t\t\t\t'currentErrors', (SELECT errors FROM now_window),\n\t\t\t\t'currentTotal', (SELECT total FROM now_window),\n\t\t\t\t'baselineErrors',(SELECT errors FROM base_window),\n\t\t\t\t'baselineTotal', (SELECT total FROM base_window),\n\t\t\t\t'sparkline', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'minute', minute,\n\t\t\t\t\t\t'total', total,\n\t\t\t\t\t\t'errors', errors,\n\t\t\t\t\t\t'rate', CASE WHEN total = 0 THEN 0\n\t\t\t\t\t\t ELSE CAST(errors AS REAL) / total END\n\t\t\t\t\t)) FROM spark\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n});\n\nconst makeServiceLatencyP95 = (\n\tprojectId: string,\n\tservice: string,\n): AnalysisDefinition => ({\n\tid: `service_latency_p95::${slug(service)}`,\n\ttitle: `${service} — p95 latency`,\n\tgroup: \"Services\",\n\tsource: \"tier1\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tscope: { service },\n\tnarrate: {\n\t\tprompt: `${service} p95 moved to {{primary}}ms from {{baseline}}ms ({{delta_pct}}). Name the span pattern dominating the tail if visible. Time anchor.`,\n\t\tonly_when: \"status_changed || delta_pct>30\",\n\t},\n\t// p95 of duration_ms over the last hour vs. same hour yesterday.\n\t// Approximate via ROW_NUMBER (no native percentile in SQLite).\n\t// Status by delta_pct: critical>50%, warn>20%, ok else.\n\tsql: `\n\t\tWITH cur AS (\n\t\t\tSELECT duration_ms,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND service_name = '${sqlEscape(service)}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t),\n\t\tbase AS (\n\t\t\tSELECT duration_ms,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND service_name = '${sqlEscape(service)}'\n\t\t\t\tAND received_at >= datetime('now', '-25 hours')\n\t\t\t\tAND received_at < datetime('now', '-24 hours')\n\t\t),\n\t\tcur_p95 AS (\n\t\t\tSELECT duration_ms FROM cur\n\t\t\tWHERE rn = MAX(1, (95 * n + 99) / 100)\n\t\t\tLIMIT 1\n\t\t),\n\t\tbase_p95 AS (\n\t\t\tSELECT duration_ms FROM base\n\t\t\tWHERE rn = MAX(1, (95 * n + 99) / 100)\n\t\t\tLIMIT 1\n\t\t),\n\t\tcur_val AS (SELECT (SELECT duration_ms FROM cur_p95) AS v),\n\t\tbase_val AS (SELECT (SELECT duration_ms FROM base_p95) AS v),\n\t\tdelta AS (\n\t\t\tSELECT CASE\n\t\t\t\tWHEN (SELECT v FROM cur_val) IS NULL THEN NULL\n\t\t\t\tWHEN (SELECT v FROM base_val) IS NULL OR (SELECT v FROM base_val) = 0 THEN NULL\n\t\t\t\tELSE ((SELECT v FROM cur_val) - (SELECT v FROM base_val))\n\t\t\t\t * 100.0 / (SELECT v FROM base_val)\n\t\t\tEND AS pct\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT v FROM cur_val) IS NULL THEN 'unknown'\n\t\t\t\tWHEN (SELECT pct FROM delta) IS NULL THEN 'ok'\n\t\t\t\tWHEN ABS((SELECT pct FROM delta)) > 50 THEN 'critical'\n\t\t\t\tWHEN ABS((SELECT pct FROM delta)) > 20 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT v FROM cur_val) AS primary_value,\n\t\t\t(SELECT v FROM base_val) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'service', '${sqlEscape(service)}',\n\t\t\t\t'window', '1h',\n\t\t\t\t'baselineWindow', 'same hour yesterday',\n\t\t\t\t'unit', 'ms'\n\t\t\t)) AS payload\n\t`,\n});\n\nconst makeDependencyHealth = (\n\tprojectId: string,\n\tsource: string,\n\ttarget: string,\n): AnalysisDefinition => ({\n\tid: `dependency_health::${slug(source)}->${slug(target)}`,\n\ttitle: `${source} → ${target}`,\n\tgroup: \"Dependencies\",\n\tsource: \"tier1\",\n\tview: \"tile\",\n\t// Dependency edges change shape slowly; sampling every 5 min keeps the\n\t// per-minute analyses tick cheap on installs with many edges.\n\trefreshSeconds: 300,\n\tscope: { source, target },\n\t// Error rate on the child-side spans of the edge over the last 5 minutes\n\t// vs trailing 1h baseline. We identify edges by joining child↔parent on\n\t// trace_id+parent_span_id where parent.service_name = source and\n\t// child.service_name = target.\n\tsql: `\n\t\tWITH edge_now AS (\n\t\t\tSELECT child.status_code AS sc\n\t\t\tFROM telemetry_spans child\n\t\t\tJOIN telemetry_spans parent\n\t\t\t ON parent.project_id = child.project_id\n\t\t\t AND parent.trace_id = child.trace_id\n\t\t\t AND parent.span_id = child.parent_span_id\n\t\t\tWHERE child.project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND parent.service_name = '${sqlEscape(source)}'\n\t\t\t\tAND child.service_name = '${sqlEscape(target)}'\n\t\t\t\tAND child.received_at >= datetime('now', '-5 minutes')\n\t\t),\n\t\tedge_base AS (\n\t\t\tSELECT child.status_code AS sc\n\t\t\tFROM telemetry_spans child\n\t\t\tJOIN telemetry_spans parent\n\t\t\t ON parent.project_id = child.project_id\n\t\t\t AND parent.trace_id = child.trace_id\n\t\t\t AND parent.span_id = child.parent_span_id\n\t\t\tWHERE child.project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND parent.service_name = '${sqlEscape(source)}'\n\t\t\t\tAND child.service_name = '${sqlEscape(target)}'\n\t\t\t\tAND child.received_at >= datetime('now', '-1 hour')\n\t\t\t\tAND child.received_at < datetime('now', '-5 minutes')\n\t\t),\n\t\tnow_agg AS (\n\t\t\tSELECT COUNT(*) AS total,\n\t\t\t SUM(CASE WHEN sc = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM edge_now\n\t\t),\n\t\tbase_agg AS (\n\t\t\tSELECT COUNT(*) AS total,\n\t\t\t SUM(CASE WHEN sc = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM edge_base\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT total FROM now_agg) = 0 THEN 'unknown'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_agg) AS REAL)\n\t\t\t\t / (SELECT total FROM now_agg)) > 0.05 THEN 'critical'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_agg) AS REAL)\n\t\t\t\t / (SELECT total FROM now_agg)) > 0.01 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\tCASE WHEN (SELECT total FROM now_agg) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM now_agg) AS REAL)\n\t\t\t / (SELECT total FROM now_agg) END AS primary_value,\n\t\t\tCASE WHEN (SELECT total FROM base_agg) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM base_agg) AS REAL)\n\t\t\t / (SELECT total FROM base_agg) END AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'source', '${sqlEscape(source)}',\n\t\t\t\t'target', '${sqlEscape(target)}',\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '1h',\n\t\t\t\t'currentTotal', (SELECT total FROM now_agg),\n\t\t\t\t'currentErrors', (SELECT errors FROM now_agg),\n\t\t\t\t'baselineTotal', (SELECT total FROM base_agg),\n\t\t\t\t'baselineErrors',(SELECT errors FROM base_agg)\n\t\t\t)) AS payload\n\t`,\n});\n\nconst makeMessagingLag = (\n\tprojectId: string,\n\ttopic: string,\n): AnalysisDefinition => ({\n\tid: `messaging_lag::${slug(topic)}`,\n\ttitle: `${topic} — messaging lag`,\n\tgroup: \"Async\",\n\tsource: \"tier1\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tscope: { topic },\n\t// Producer span_kind = 4, Consumer span_kind = 5 (OTel SpanKind enum).\n\t// We approximate lag as the time gap between producer end_time and the\n\t// matching consumer start_time on the same trace_id. Spans without a\n\t// matching counterpart are excluded. Status thresholds in seconds:\n\t// critical>30s, warn>5s.\n\tsql: `\n\t\tWITH producers AS (\n\t\t\tSELECT trace_id,\n\t\t\t end_time,\n\t\t\t json_extract(attributes_json, '$.\"messaging.destination\"') AS topic\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND span_kind = 4\n\t\t\t\tAND json_extract(attributes_json, '$.\"messaging.destination\"') = '${sqlEscape(topic)}'\n\t\t\t\tAND received_at >= datetime('now', '-15 minutes')\n\t\t),\n\t\tconsumers AS (\n\t\t\tSELECT trace_id,\n\t\t\t start_time,\n\t\t\t json_extract(attributes_json, '$.\"messaging.destination\"') AS topic\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND span_kind = 5\n\t\t\t\tAND json_extract(attributes_json, '$.\"messaging.destination\"') = '${sqlEscape(topic)}'\n\t\t\t\tAND received_at >= datetime('now', '-15 minutes')\n\t\t),\n\t\tgaps AS (\n\t\t\tSELECT\n\t\t\t\t(julianday(c.start_time) - julianday(p.end_time)) * 86400.0 AS lag_seconds\n\t\t\tFROM producers p\n\t\t\tJOIN consumers c USING (trace_id)\n\t\t\tWHERE c.start_time >= p.end_time\n\t\t),\n\t\tordered AS (\n\t\t\tSELECT lag_seconds,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY lag_seconds ASC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM gaps\n\t\t),\n\t\tp95_row AS (\n\t\t\tSELECT lag_seconds FROM ordered\n\t\t\tWHERE rn = MAX(1, (95 * n + 99) / 100)\n\t\t\tLIMIT 1\n\t\t),\n\t\tstats AS (\n\t\t\tSELECT\n\t\t\t\t(SELECT COUNT(*) FROM gaps) AS pairs,\n\t\t\t\t(SELECT AVG(lag_seconds) FROM gaps) AS avg_lag,\n\t\t\t\t(SELECT lag_seconds FROM p95_row) AS p95_lag,\n\t\t\t\t(SELECT MAX(lag_seconds) FROM gaps) AS max_lag\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT pairs FROM stats) = 0 THEN 'unknown'\n\t\t\t\tWHEN COALESCE((SELECT p95_lag FROM stats), 0) > 30 THEN 'critical'\n\t\t\t\tWHEN COALESCE((SELECT p95_lag FROM stats), 0) > 5 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT p95_lag FROM stats) AS primary_value,\n\t\t\t(SELECT avg_lag FROM stats) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'topic', '${sqlEscape(topic)}',\n\t\t\t\t'unit', 's',\n\t\t\t\t'window', '15m',\n\t\t\t\t'pairs', (SELECT pairs FROM stats),\n\t\t\t\t'avgLag', (SELECT avg_lag FROM stats),\n\t\t\t\t'p95Lag', (SELECT p95_lag FROM stats),\n\t\t\t\t'maxLag', (SELECT max_lag FROM stats)\n\t\t\t)) AS payload\n\t`,\n});\n\nconst makeAiCostBurn = (projectId: string): AnalysisDefinition => ({\n\tid: \"ai_cost_burn\",\n\ttitle: \"AI cost burn\",\n\tgroup: \"AI\",\n\tsource: \"tier1\",\n\tview: \"tile\",\n\t// Cost moves slowly compared to error rates; 5 min cadence keeps the\n\t// per-minute tick cheap.\n\trefreshSeconds: 300,\n\t// USD spent in the last hour vs the prior hour, summed from ai_calls.\n\t// Status by relative delta: critical>50%, warn>20%. unknown if no cost\n\t// signal at all.\n\tsql: `\n\t\tWITH cur AS (\n\t\t\tSELECT COALESCE(SUM(total_cost_usd), 0) AS cost,\n\t\t\t COUNT(*) AS n\n\t\t\tFROM ai_calls\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t),\n\t\tprev AS (\n\t\t\tSELECT COALESCE(SUM(total_cost_usd), 0) AS cost,\n\t\t\t COUNT(*) AS n\n\t\t\tFROM ai_calls\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND received_at >= datetime('now', '-2 hours')\n\t\t\t\tAND received_at < datetime('now', '-1 hour')\n\t\t),\n\t\tdelta AS (\n\t\t\tSELECT CASE\n\t\t\t\tWHEN (SELECT cost FROM prev) = 0 THEN NULL\n\t\t\t\tELSE ((SELECT cost FROM cur) - (SELECT cost FROM prev))\n\t\t\t\t * 100.0 / (SELECT cost FROM prev)\n\t\t\tEND AS pct\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT n FROM cur) = 0 AND (SELECT n FROM prev) = 0 THEN 'unknown'\n\t\t\t\tWHEN (SELECT pct FROM delta) IS NULL THEN 'ok'\n\t\t\t\tWHEN (SELECT pct FROM delta) > 50 THEN 'critical'\n\t\t\t\tWHEN (SELECT pct FROM delta) > 20 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT cost FROM cur) AS primary_value,\n\t\t\t(SELECT cost FROM prev) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'unit', 'usd',\n\t\t\t\t'window', '1h',\n\t\t\t\t'baselineWindow', 'prior 1h',\n\t\t\t\t'currentCalls', (SELECT n FROM cur),\n\t\t\t\t'baselineCalls', (SELECT n FROM prev)\n\t\t\t)) AS payload\n\t`,\n});\n\nconst makeAiErrorRate = (projectId: string): AnalysisDefinition => ({\n\tid: \"ai_error_rate\",\n\ttitle: \"AI error rate\",\n\tgroup: \"AI\",\n\tsource: \"tier1\",\n\tview: \"tile\",\n\t// AI error rate is per-call; 5 min cadence balances signal vs cost on\n\t// installs with hundreds of LLM spans.\n\trefreshSeconds: 300,\n\t// is_error = 1 fraction in the last 5 minutes vs trailing 1h baseline.\n\t// Same thresholds as overall_error_rate.\n\tsql: `\n\t\tWITH now_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN is_error = 1 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM ai_calls\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND received_at >= datetime('now', '-5 minutes')\n\t\t),\n\t\tbase_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN is_error = 1 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM ai_calls\n\t\t\tWHERE project_id = '${sqlEscape(projectId)}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t\t\tAND received_at < datetime('now', '-5 minutes')\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT total FROM now_window) = 0 THEN 'unknown'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.05 THEN 'critical'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.01 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\tCASE WHEN (SELECT total FROM now_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t / (SELECT total FROM now_window) END AS primary_value,\n\t\t\tCASE WHEN (SELECT total FROM base_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM base_window) AS REAL)\n\t\t\t / (SELECT total FROM base_window) END AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '1h',\n\t\t\t\t'currentErrors', (SELECT errors FROM now_window),\n\t\t\t\t'currentTotal', (SELECT total FROM now_window),\n\t\t\t\t'baselineErrors',(SELECT errors FROM base_window),\n\t\t\t\t'baselineTotal', (SELECT total FROM base_window)\n\t\t\t)) AS payload\n\t`,\n});\n\n// ── Public API ──────────────────────────────────────────────────────────────\n\n/** Test hook — clears the per-project shape cache. */\nexport const __resetShapeCache = (): void => {\n\tshapeCache.clear();\n};\n\nexport const deriveAnalysesForProject = async (\n\tprojectId: string,\n\tdb: D1Database,\n): Promise<AnalysisDefinition[]> => {\n\tconst shape = await getShape(projectId, db);\n\tconst out: AnalysisDefinition[] = [];\n\n\tfor (const service of shape.services) {\n\t\tout.push(makeServiceErrorRate(projectId, service));\n\t\tout.push(makeServiceLatencyP95(projectId, service));\n\t}\n\n\tfor (const edge of shape.edges) {\n\t\tout.push(makeDependencyHealth(projectId, edge.source, edge.target));\n\t}\n\n\tfor (const topic of shape.messagingTopics) {\n\t\tout.push(makeMessagingLag(projectId, topic));\n\t}\n\n\tif (shape.hasLlmSpans) {\n\t\tout.push(makeAiCostBurn(projectId));\n\t\tout.push(makeAiErrorRate(projectId));\n\t}\n\n\treturn out;\n};\n","/**\n * RFC 0002 Stage 4 — investigation templates.\n *\n * The RFC originally targeted a Python sidecar for these (Stage 2). We\n * skipped Stage 2; investigations here are pure SQL (multiple result-sets\n * stitched into one structured `payload.evidence` blob) executed by the\n * existing runner. SQLite's window functions + json builders cover what\n * Polars would do for the cohort/funnel/anomaly shapes we ship.\n *\n * Convention used by `InvestigationPage`:\n *\n * payload.evidence = {\n * [section_name]: {\n * title?: string,\n * headers: string[],\n * rows: Array<Array<string | number | null>>,\n * note?: string,\n * }\n * }\n *\n * The runner shapes status / primary / baseline / delta the same way as\n * tile analyses; the page UI renders the headline numbers above the\n * narrative and tables below.\n */\n\nimport type { AnalysisDefinition } from \"@obsunified/types\";\n\n// ── error_top_offenders ────────────────────────────────────────────────────\n// Cohort-comparison investigation. \"Which services contributed the most\n// errors in the last 5 minutes vs the trailing hour, and is the mix\n// shifting?\" Status: critical if current top-3 service error count > 50;\n// warn if > 10; ok otherwise. Primary value is current top-1 error count.\nconst errorTopOffenders: AnalysisDefinition = {\n\tid: \"investigate.error_top_offenders\",\n\ttitle: \"Error top offenders\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"page\",\n\trefreshSeconds: 300,\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"Summarize which services dominate errors right now and how the mix shifted vs the last hour. If one service moved sharply, name it. Time anchor.\",\n\t\tonly_when: \"always\",\n\t},\n\tsql: `\n\t\tWITH cur AS (\n\t\t\tSELECT COALESCE(service_name, '<unknown>') AS service,\n\t\t\t\tCOUNT(*) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-5 minutes')\n\t\t\t\tAND status_code = 2\n\t\t\tGROUP BY service_name\n\t\t\tORDER BY errors DESC\n\t\t\tLIMIT 5\n\t\t),\n\t\tprev AS (\n\t\t\tSELECT COALESCE(service_name, '<unknown>') AS service,\n\t\t\t\tCOUNT(*) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t\t\tAND received_at < datetime('now', '-5 minutes')\n\t\t\t\tAND status_code = 2\n\t\t\tGROUP BY service_name\n\t\t\tORDER BY errors DESC\n\t\t\tLIMIT 5\n\t\t),\n\t\ttop1 AS (\n\t\t\tSELECT errors AS top_errors FROM cur LIMIT 1\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN COALESCE((SELECT top_errors FROM top1), 0) > 50 THEN 'critical'\n\t\t\t\tWHEN COALESCE((SELECT top_errors FROM top1), 0) > 10 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\tCOALESCE((SELECT top_errors FROM top1), 0) AS primary_value,\n\t\t\t(SELECT errors FROM prev LIMIT 1) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '5m–60m ago',\n\t\t\t\t'evidence', json_object(\n\t\t\t\t\t'current_top_services', json_object(\n\t\t\t\t\t\t'title', 'Top error services — last 5 minutes',\n\t\t\t\t\t\t'headers', json_array('service', 'errors'),\n\t\t\t\t\t\t'rows', (\n\t\t\t\t\t\t\tSELECT json_group_array(json_array(service, errors))\n\t\t\t\t\t\t\tFROM cur\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t\t'baseline_top_services', json_object(\n\t\t\t\t\t\t'title', 'Top error services — 5–60 minutes ago',\n\t\t\t\t\t\t'headers', json_array('service', 'errors'),\n\t\t\t\t\t\t'rows', (\n\t\t\t\t\t\t\tSELECT json_group_array(json_array(service, errors))\n\t\t\t\t\t\t\tFROM prev\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── latency_outlier_attribution ───────────────────────────────────────────\n// Funnel-style investigation: of the slow tail (last 15min), which\n// service+span combinations dominate? Helps users go from \"p95 is up\" to\n// \"checkout.submit is the offender\" in one click.\nconst latencyOutlierAttribution: AnalysisDefinition = {\n\tid: \"investigate.latency_outlier_attribution\",\n\ttitle: \"Latency outlier attribution\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"page\",\n\trefreshSeconds: 300,\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"Identify which span(s) dominate the slow tail in the last 15 minutes. Quote concrete duration numbers and span names from the evidence. Time anchor.\",\n\t\tonly_when: \"always\",\n\t},\n\tsql: `\n\t\tWITH ranked AS (\n\t\t\tSELECT\n\t\t\t\tduration_ms,\n\t\t\t\tCOALESCE(service_name, '<unknown>') AS service,\n\t\t\t\tCOALESCE(span_name, '<unknown>') AS span,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY duration_ms DESC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-15 minutes')\n\t\t),\n\t\tp95_cut AS (\n\t\t\t-- Conservatively call \"tail\" the slowest 5% of the window.\n\t\t\tSELECT MIN(duration_ms) AS p95\n\t\t\tFROM ranked\n\t\t\tWHERE rn <= MAX(1, (n + 19) / 20)\n\t\t),\n\t\toffenders AS (\n\t\t\tSELECT service, span,\n\t\t\t\tCOUNT(*) AS tail_count,\n\t\t\t\tMAX(duration_ms) AS max_ms,\n\t\t\t\tROUND(AVG(duration_ms), 1) AS avg_ms\n\t\t\tFROM ranked, p95_cut\n\t\t\tWHERE duration_ms >= COALESCE(p95_cut.p95, 0)\n\t\t\tGROUP BY service, span\n\t\t\tORDER BY tail_count DESC\n\t\t\tLIMIT 8\n\t\t),\n\t\ttop_max AS (\n\t\t\tSELECT max_ms FROM offenders ORDER BY max_ms DESC LIMIT 1\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN COALESCE((SELECT max_ms FROM top_max), 0) > 5000 THEN 'critical'\n\t\t\t\tWHEN COALESCE((SELECT max_ms FROM top_max), 0) > 1000 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\tCOALESCE((SELECT max_ms FROM top_max), 0) AS primary_value,\n\t\t\t(SELECT p95 FROM p95_cut) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '15m',\n\t\t\t\t'unit', 'ms',\n\t\t\t\t'evidence', json_object(\n\t\t\t\t\t'tail_offenders', json_object(\n\t\t\t\t\t\t'title', 'Top tail offenders — slowest 5% of last 15 minutes',\n\t\t\t\t\t\t'headers', json_array('service', 'span', 'count_in_tail', 'max_ms', 'avg_ms'),\n\t\t\t\t\t\t'rows', (\n\t\t\t\t\t\t\tSELECT json_group_array(json_array(service, span, tail_count, max_ms, avg_ms))\n\t\t\t\t\t\t\tFROM offenders\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── log_anomaly_summary ────────────────────────────────────────────────────\n// Anomaly investigation: which ERROR-severity logger names showed up in\n// the last 5 minutes that weren't present in the prior hour? These are\n// the \"first time we've ever seen this fail\" cases — usually the most\n// interesting line in an incident.\nconst logAnomalySummary: AnalysisDefinition = {\n\tid: \"investigate.log_anomaly_summary\",\n\ttitle: \"Log anomaly summary\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"page\",\n\trefreshSeconds: 300,\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"List the new ERROR loggers (those absent from the prior hour). If any look like 'never seen before', call it out. Quote one representative message per logger. Time anchor.\",\n\t\tonly_when: \"always\",\n\t},\n\tsql: `\n\t\tWITH recent AS (\n\t\t\t-- Correlated subquery for sample_message uses the table alias\n\t\t\t-- l1 so SQLite resolves the outer column reference; the AS alias\n\t\t\t-- 'logger' defined in the SELECT list isn't visible inside a\n\t\t\t-- correlated subquery in SQLite.\n\t\t\tSELECT COALESCE(l1.logger_name, '<unknown>') AS logger,\n\t\t\t\tCOUNT(*) AS occurrences,\n\t\t\t\t(SELECT l2.message FROM logs l2\n\t\t\t\t\tWHERE l2.project_id = '{{PROJECT_ID}}'\n\t\t\t\t\t\tAND COALESCE(l2.logger_name, '<unknown>') = COALESCE(l1.logger_name, '<unknown>')\n\t\t\t\t\t\tAND l2.received_at >= datetime('now', '-5 minutes')\n\t\t\t\t\t\tAND l2.severity_number >= 17\n\t\t\t\t\tORDER BY l2.received_at DESC LIMIT 1) AS sample_message\n\t\t\tFROM logs l1\n\t\t\tWHERE l1.project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND l1.received_at >= datetime('now', '-5 minutes')\n\t\t\t\tAND l1.severity_number >= 17\n\t\t\tGROUP BY l1.logger_name\n\t\t),\n\t\tbaseline AS (\n\t\t\tSELECT DISTINCT COALESCE(logger_name, '<unknown>') AS logger\n\t\t\tFROM logs\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t\t\tAND received_at < datetime('now', '-5 minutes')\n\t\t\t\tAND severity_number >= 17\n\t\t),\n\t\tnewcomers AS (\n\t\t\tSELECT recent.*\n\t\t\tFROM recent\n\t\t\tLEFT JOIN baseline ON baseline.logger = recent.logger\n\t\t\tWHERE baseline.logger IS NULL\n\t\t\tORDER BY recent.occurrences DESC\n\t\t\tLIMIT 8\n\t\t),\n\t\tall_recent AS (\n\t\t\tSELECT recent.*,\n\t\t\t\tCASE WHEN baseline.logger IS NULL THEN 1 ELSE 0 END AS is_new\n\t\t\tFROM recent\n\t\t\tLEFT JOIN baseline ON baseline.logger = recent.logger\n\t\t\tORDER BY is_new DESC, occurrences DESC\n\t\t\tLIMIT 12\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT COUNT(*) FROM newcomers) >= 3 THEN 'critical'\n\t\t\t\tWHEN (SELECT COUNT(*) FROM newcomers) >= 1 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT COUNT(*) FROM newcomers) AS primary_value,\n\t\t\t(SELECT COUNT(*) FROM baseline) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '5–60m ago',\n\t\t\t\t'evidence', json_object(\n\t\t\t\t\t'new_error_loggers', json_object(\n\t\t\t\t\t\t'title', 'New ERROR loggers — first seen in last 5 minutes',\n\t\t\t\t\t\t'headers', json_array('logger', 'occurrences', 'sample_message'),\n\t\t\t\t\t\t'note', 'Loggers absent from the prior 5–60 minute window.',\n\t\t\t\t\t\t'rows', (\n\t\t\t\t\t\t\tSELECT json_group_array(json_array(logger, occurrences, sample_message))\n\t\t\t\t\t\t\tFROM newcomers\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t\t'all_recent_loggers', json_object(\n\t\t\t\t\t\t'title', 'All ERROR loggers — last 5 minutes',\n\t\t\t\t\t\t'headers', json_array('logger', 'occurrences', 'is_new', 'sample_message'),\n\t\t\t\t\t\t'rows', (\n\t\t\t\t\t\t\tSELECT json_group_array(json_array(logger, occurrences, is_new, sample_message))\n\t\t\t\t\t\t\tFROM all_recent\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\nexport const INVESTIGATION_ANALYSES: AnalysisDefinition[] = [\n\terrorTopOffenders,\n\tlatencyOutlierAttribution,\n\tlogAnomalySummary,\n];\n","// RFC 0002 Stage 1 — Tier 0 universal analyses.\n//\n// These six analyses apply to any install regardless of detected app shape.\n// Each `sql` string is executable as-is by the runner (Agent 1). The runner\n// substitutes the literal token `{{PROJECT_ID}}` with the active project's\n// id before execution; everything else (time windows, thresholds) is baked\n// into the SQL itself.\n//\n// The runner expects a single-row result with these columns:\n// status TEXT — 'ok' | 'warn' | 'critical' | 'unknown'\n// primary_value REAL — the headline number (NULL allowed)\n// baseline_value REAL — the comparison number (NULL allowed)\n// payload TEXT — JSON string built with json_object(...) /\n// json_group_array(...) for charts, contributors, etc.\n//\n// delta_pct is precomputed by the runner from primary/baseline.\n\nimport type { AnalysisDefinition } from \"@obsunified/types\";\n\n// ── overall_error_rate ──────────────────────────────────────────────────────\n// Error spans in the last 5 minutes vs. the trailing 1h baseline rate.\n// Status: critical if rate>5%, warn if rate>1%, ok otherwise. unknown if\n// no traffic in either window.\nconst overallErrorRate: AnalysisDefinition = {\n\tid: \"overall_error_rate\",\n\ttitle: \"Overall error rate\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"Errors moved to {{primary}} (was {{baseline}}, {{delta_pct}}). Name the dominant offending span name or service if visible in the payload, with a time anchor.\",\n\t\tonly_when: \"status_changed || delta_pct>20\",\n\t},\n\tsql: `\n\t\tWITH now_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-5 minutes')\n\t\t),\n\t\tbase_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t\t\tAND received_at < datetime('now', '-5 minutes')\n\t\t),\n\t\tspark AS (\n\t\t\t-- per-minute error rate over the last 30 minutes for sparkline rendering\n\t\t\tSELECT\n\t\t\t\tstrftime('%Y-%m-%dT%H:%M:00Z', received_at) AS minute,\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-30 minutes')\n\t\t\tGROUP BY minute\n\t\t\tORDER BY minute ASC\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT total FROM now_window) = 0 THEN 'unknown'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.05 THEN 'critical'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.01 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\tCASE WHEN (SELECT total FROM now_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t / (SELECT total FROM now_window) END AS primary_value,\n\t\t\tCASE WHEN (SELECT total FROM base_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM base_window) AS REAL)\n\t\t\t / (SELECT total FROM base_window) END AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '1h',\n\t\t\t\t'currentErrors', (SELECT errors FROM now_window),\n\t\t\t\t'currentTotal', (SELECT total FROM now_window),\n\t\t\t\t'baselineErrors',(SELECT errors FROM base_window),\n\t\t\t\t'baselineTotal', (SELECT total FROM base_window),\n\t\t\t\t'sparkline', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'minute', minute,\n\t\t\t\t\t\t'total', total,\n\t\t\t\t\t\t'errors', errors,\n\t\t\t\t\t\t'rate', CASE WHEN total = 0 THEN 0\n\t\t\t\t\t\t ELSE CAST(errors AS REAL) / total END\n\t\t\t\t\t)) FROM spark\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── top_error_services ──────────────────────────────────────────────────────\n// Top 5 services by error count in the last 5 minutes.\n// Status: critical if any service has >10 errors/min (i.e. >50 in 5min),\n// warn if any has >2 errors/min (i.e. >10 in 5min), ok otherwise. unknown\n// if no errors at all.\nconst topErrorServices: AnalysisDefinition = {\n\tid: \"top_error_services\",\n\ttitle: \"Top error services\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"List the top 1–2 erroring services and their counts (from payload). Include a time anchor like 'in the last 5 minutes'.\",\n\t\tonly_when: \"signature_changed\",\n\t},\n\tsql: `\n\t\tWITH per_service AS (\n\t\t\tSELECT\n\t\t\t\tCOALESCE(service_name, '<unknown>') AS service,\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-5 minutes')\n\t\t\tGROUP BY service\n\t\t),\n\t\ttop5 AS (\n\t\t\tSELECT service, total, errors\n\t\t\tFROM per_service\n\t\t\tWHERE errors > 0\n\t\t\tORDER BY errors DESC\n\t\t\tLIMIT 5\n\t\t),\n\t\tmax_err AS (SELECT COALESCE(MAX(errors), 0) AS m FROM top5)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT m FROM max_err) = 0 THEN 'unknown'\n\t\t\t\t-- thresholds are per-minute averaged over the 5-minute window\n\t\t\t\tWHEN (SELECT m FROM max_err) > 50 THEN 'critical'\n\t\t\t\tWHEN (SELECT m FROM max_err) > 10 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT m FROM max_err) AS primary_value,\n\t\t\tNULL AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '5m',\n\t\t\t\t'services', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'service', service,\n\t\t\t\t\t\t'errors', errors,\n\t\t\t\t\t\t'total', total\n\t\t\t\t\t)) FROM top5\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── latency_p95_overall ─────────────────────────────────────────────────────\n// p95 across all spans this hour vs. the same hour yesterday.\n// SQLite has no native percentile, so we approximate via ROW_NUMBER ordering:\n// pick the row at offset CEIL(0.95 * n) - 1 in ascending duration order.\n// Status by delta_pct: critical>50%, warn>20%, ok else. unknown when either\n// window is empty.\nconst latencyP95Overall: AnalysisDefinition = {\n\tid: \"latency_p95_overall\",\n\ttitle: \"Latency p95 — overall\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"tile\",\n\t// Latency is one of the primary signals; 60s matches Tier 0 spec.\n\trefreshSeconds: 60,\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"p95 moved to {{primary}}ms from {{baseline}}ms ({{delta_pct}}). Name the slowest service or route if visible in the payload, with a time anchor.\",\n\t\tonly_when: \"status_changed || delta_pct>25\",\n\t},\n\tsql: `\n\t\tWITH cur AS (\n\t\t\tSELECT duration_ms,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t),\n\t\tbase AS (\n\t\t\tSELECT duration_ms,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-25 hours')\n\t\t\t\tAND received_at < datetime('now', '-24 hours')\n\t\t),\n\t\tcur_p95 AS (\n\t\t\tSELECT duration_ms FROM cur\n\t\t\tWHERE rn = MAX(1, (95 * n + 99) / 100)\n\t\t\tLIMIT 1\n\t\t),\n\t\tbase_p95 AS (\n\t\t\tSELECT duration_ms FROM base\n\t\t\tWHERE rn = MAX(1, (95 * n + 99) / 100)\n\t\t\tLIMIT 1\n\t\t),\n\t\tspark AS (\n\t\t\t-- per-5-minute approx-p95 buckets across the current hour for sparkline\n\t\t\tSELECT\n\t\t\t\tstrftime('%Y-%m-%dT%H:%M:00Z',\n\t\t\t\t\tdatetime((CAST(strftime('%s', received_at) AS INTEGER) / 300) * 300, 'unixepoch')\n\t\t\t\t) AS bucket,\n\t\t\t\tMAX(duration_ms) AS approx_max,\n\t\t\t\tCOUNT(*) AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t\tGROUP BY bucket\n\t\t\tORDER BY bucket ASC\n\t\t),\n\t\tcur_val AS (SELECT (SELECT duration_ms FROM cur_p95) AS v),\n\t\tbase_val AS (SELECT (SELECT duration_ms FROM base_p95) AS v),\n\t\tdelta AS (\n\t\t\tSELECT CASE\n\t\t\t\tWHEN (SELECT v FROM cur_val) IS NULL THEN NULL\n\t\t\t\tWHEN (SELECT v FROM base_val) IS NULL OR (SELECT v FROM base_val) = 0 THEN NULL\n\t\t\t\tELSE ((SELECT v FROM cur_val) - (SELECT v FROM base_val))\n\t\t\t\t * 100.0 / (SELECT v FROM base_val)\n\t\t\tEND AS pct\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT v FROM cur_val) IS NULL THEN 'unknown'\n\t\t\t\tWHEN (SELECT pct FROM delta) IS NULL THEN 'ok'\n\t\t\t\tWHEN ABS((SELECT pct FROM delta)) > 50 THEN 'critical'\n\t\t\t\tWHEN ABS((SELECT pct FROM delta)) > 20 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT v FROM cur_val) AS primary_value,\n\t\t\t(SELECT v FROM base_val) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '1h',\n\t\t\t\t'baselineWindow', 'same hour yesterday',\n\t\t\t\t'unit', 'ms',\n\t\t\t\t'sparkline', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'bucket', bucket,\n\t\t\t\t\t\t'approxP95Ms', approx_max,\n\t\t\t\t\t\t'samples', n\n\t\t\t\t\t)) FROM spark\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── throughput_slope ────────────────────────────────────────────────────────\n// Spans/minute trend: last 30 minutes vs the prior 30 minutes.\n// Status: warn if slope > 1.5x AND p99 trending up (current p99 > prior p99);\n// ok otherwise. unknown if both windows empty.\nconst throughputSlope: AnalysisDefinition = {\n\tid: \"throughput_slope\",\n\ttitle: \"Throughput slope\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tsql: `\n\t\tWITH cur AS (\n\t\t\tSELECT duration_ms,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-30 minutes')\n\t\t),\n\t\tprev AS (\n\t\t\tSELECT duration_ms,\n\t\t\t\tROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,\n\t\t\t\tCOUNT(*) OVER () AS n\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-60 minutes')\n\t\t\t\tAND received_at < datetime('now', '-30 minutes')\n\t\t),\n\t\tcur_n AS (SELECT COALESCE((SELECT n FROM cur LIMIT 1), 0) AS n),\n\t\tprev_n AS (SELECT COALESCE((SELECT n FROM prev LIMIT 1), 0) AS n),\n\t\tcur_p99 AS (\n\t\t\tSELECT duration_ms FROM cur\n\t\t\tWHERE rn = MAX(1, (99 * n + 99) / 100)\n\t\t\tLIMIT 1\n\t\t),\n\t\tprev_p99 AS (\n\t\t\tSELECT duration_ms FROM prev\n\t\t\tWHERE rn = MAX(1, (99 * n + 99) / 100)\n\t\t\tLIMIT 1\n\t\t),\n\t\trates AS (\n\t\t\tSELECT\n\t\t\t\tCAST((SELECT n FROM cur_n) AS REAL) / 30.0 AS current_rpm,\n\t\t\t\tCAST((SELECT n FROM prev_n) AS REAL) / 30.0 AS prior_rpm\n\t\t),\n\t\tslope_calc AS (\n\t\t\tSELECT\n\t\t\t\tcurrent_rpm,\n\t\t\t\tprior_rpm,\n\t\t\t\tCASE WHEN prior_rpm = 0 THEN NULL\n\t\t\t\t ELSE current_rpm / prior_rpm END AS slope\n\t\t\tFROM rates\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT n FROM cur_n) = 0 AND (SELECT n FROM prev_n) = 0 THEN 'unknown'\n\t\t\t\tWHEN (SELECT slope FROM slope_calc) IS NOT NULL\n\t\t\t\t AND (SELECT slope FROM slope_calc) > 1.5\n\t\t\t\t AND COALESCE((SELECT duration_ms FROM cur_p99), 0)\n\t\t\t\t > COALESCE((SELECT duration_ms FROM prev_p99), 0)\n\t\t\t\tTHEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT current_rpm FROM rates) AS primary_value,\n\t\t\t(SELECT prior_rpm FROM rates) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'currentRpm', (SELECT current_rpm FROM rates),\n\t\t\t\t'priorRpm', (SELECT prior_rpm FROM rates),\n\t\t\t\t'slope', (SELECT slope FROM slope_calc),\n\t\t\t\t'currentP99Ms', (SELECT duration_ms FROM cur_p99),\n\t\t\t\t'priorP99Ms', (SELECT duration_ms FROM prev_p99),\n\t\t\t\t'window', '30m',\n\t\t\t\t'baselineWindow', 'prior 30m'\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── active_sessions ─────────────────────────────────────────────────────────\n// Distinct frontend sessions in usage_events for the last 15 minutes plus\n// per-hour breakdown across the trailing 24h. Always status: 'ok' — this is\n// informational. unknown only if the table is missing data entirely.\nconst activeSessions: AnalysisDefinition = {\n\tid: \"active_sessions\",\n\ttitle: \"Active sessions\",\n\tgroup: \"Frontend\",\n\tsource: \"tier0\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tsql: `\n\t\tWITH active AS (\n\t\t\tSELECT COUNT(DISTINCT session_id) AS n\n\t\t\tFROM usage_events\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-15 minutes')\n\t\t),\n\t\thourly AS (\n\t\t\tSELECT\n\t\t\t\tstrftime('%Y-%m-%dT%H:00:00Z', received_at) AS hour,\n\t\t\t\tCOUNT(DISTINCT session_id) AS sessions\n\t\t\tFROM usage_events\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-24 hours')\n\t\t\tGROUP BY hour\n\t\t\tORDER BY hour ASC\n\t\t)\n\t\tSELECT\n\t\t\t'ok' AS status,\n\t\t\tCAST((SELECT n FROM active) AS REAL) AS primary_value,\n\t\t\tNULL AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'count', (SELECT n FROM active),\n\t\t\t\t'window', '15m',\n\t\t\t\t'hourlyBreakdown', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'hour', hour,\n\t\t\t\t\t\t'sessions', sessions\n\t\t\t\t\t)) FROM hourly\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── log_error_rate ──────────────────────────────────────────────────────────\n// Error+fatal logs in the last 5 minutes vs. the trailing 1h baseline rate.\n// severity_number follows OTel: ERROR=17-20, FATAL=21-24.\n// Status: critical if rate>5%, warn if rate>1%, ok otherwise. unknown if\n// no logs in either window.\nconst logErrorRate: AnalysisDefinition = {\n\tid: \"log_error_rate\",\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"Log error rate is {{primary}} (was {{baseline}}, {{delta_pct}}). If a logger or message pattern dominates the payload, name it. Time anchor.\",\n\t\tonly_when: \"status_changed || delta_pct>25\",\n\t},\n\ttitle: \"Log error rate\",\n\tgroup: \"Health\",\n\tsource: \"tier0\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tsql: `\n\t\tWITH now_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN severity_number >= 17 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM logs\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-5 minutes')\n\t\t),\n\t\tbase_window AS (\n\t\t\tSELECT\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN severity_number >= 17 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM logs\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-1 hour')\n\t\t\t\tAND received_at < datetime('now', '-5 minutes')\n\t\t),\n\t\tspark AS (\n\t\t\tSELECT\n\t\t\t\tstrftime('%Y-%m-%dT%H:%M:00Z', received_at) AS minute,\n\t\t\t\tCOUNT(*) AS total,\n\t\t\t\tSUM(CASE WHEN severity_number >= 17 THEN 1 ELSE 0 END) AS errors\n\t\t\tFROM logs\n\t\t\tWHERE project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND received_at >= datetime('now', '-30 minutes')\n\t\t\tGROUP BY minute\n\t\t\tORDER BY minute ASC\n\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN (SELECT total FROM now_window) = 0 THEN 'unknown'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.05 THEN 'critical'\n\t\t\t\tWHEN (CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t\t / (SELECT total FROM now_window)) > 0.01 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\tCASE WHEN (SELECT total FROM now_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM now_window) AS REAL)\n\t\t\t / (SELECT total FROM now_window) END AS primary_value,\n\t\t\tCASE WHEN (SELECT total FROM base_window) = 0 THEN NULL\n\t\t\t ELSE CAST((SELECT errors FROM base_window) AS REAL)\n\t\t\t / (SELECT total FROM base_window) END AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '1h',\n\t\t\t\t'currentErrors', (SELECT errors FROM now_window),\n\t\t\t\t'currentTotal', (SELECT total FROM now_window),\n\t\t\t\t'baselineErrors',(SELECT errors FROM base_window),\n\t\t\t\t'baselineTotal', (SELECT total FROM base_window),\n\t\t\t\t'sparkline', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'minute', minute,\n\t\t\t\t\t\t'total', total,\n\t\t\t\t\t\t'errors', errors,\n\t\t\t\t\t\t'rate', CASE WHEN total = 0 THEN 0\n\t\t\t\t\t\t ELSE CAST(errors AS REAL) / total END\n\t\t\t\t\t)) FROM spark\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\n// ── service_cpu_utilization ─────────────────────────────────────────────────\n// RFC 0005 Phase 2.6 — fleet-wide process CPU utilization tile.\n// Reads `process.cpu.utilization` gauge points emitted by\n// @obsunified/telemetry-sdk's enableProcessMetrics() helper (or any other OTel\n// runtime-metrics exporter using the standard semconv).\n//\n// Status: critical if any service averaged >0.9 over the last 5 min,\n// warn if >0.7, ok otherwise. unknown if no process.cpu.* series at all\n// (the typical state on a fresh install before enableProcessMetrics\n// is wired into the user's services).\nconst serviceCpuUtilization: AnalysisDefinition = {\n\tid: \"service_cpu_utilization\",\n\ttitle: \"Service CPU utilization\",\n\tgroup: \"Services\",\n\tsource: \"tier0\",\n\tview: \"tile\",\n\trefreshSeconds: 60,\n\tnarrate: {\n\t\tprompt:\n\t\t\t\"Name the busiest service and its average utilization over the last 5 minutes. Mention if it crossed a critical (>0.9) or warn (>0.7) threshold.\",\n\t\tonly_when: \"status_changed\",\n\t},\n\tsql: `\n\t\tWITH cpu_points AS (\n\t\t\tSELECT\n\t\t\t\ts.service_name,\n\t\t\t\tp.value,\n\t\t\t\tp.received_at\n\t\t\tFROM metric_point p\n\t\t\tJOIN metric_series s ON s.id = p.series_id\n\t\t\tWHERE s.project_id = '{{PROJECT_ID}}'\n\t\t\t\tAND s.name = 'process.cpu.utilization'\n\t\t\t\tAND s.service_name IS NOT NULL\n\t\t\t\tAND p.received_at >= datetime('now', '-30 minutes')\n\t\t),\n\t\tnow_window AS (\n\t\t\tSELECT service_name, AVG(value) AS avg_util\n\t\t\tFROM cpu_points\n\t\t\tWHERE received_at >= datetime('now', '-5 minutes')\n\t\t\tGROUP BY service_name\n\t\t),\n\t\tbase_window AS (\n\t\t\tSELECT service_name, AVG(value) AS avg_util\n\t\t\tFROM cpu_points\n\t\t\tWHERE received_at >= datetime('now', '-30 minutes')\n\t\t\t\tAND received_at < datetime('now', '-5 minutes')\n\t\t\tGROUP BY service_name\n\t\t),\n\t\t\ttop_now AS (\n\t\t\t\tSELECT service_name, avg_util\n\t\t\t\tFROM now_window\n\t\t\t\tORDER BY avg_util DESC\n\t\t\t\tLIMIT 5\n\t\t\t),\n\t\t\tfleet_max AS (\n\t\t\t\tSELECT COALESCE(MAX(avg_util), 0) AS m FROM now_window\n\t\t\t),\n\t\t\ttop_service AS (\n\t\t\t\tSELECT service_name\n\t\t\t\tFROM now_window\n\t\t\t\tORDER BY avg_util DESC\n\t\t\t\tLIMIT 1\n\t\t\t),\n\t\t\tspark AS (\n\t\t\t\tSELECT\n\t\t\t\t\tstrftime('%Y-%m-%dT%H:%M:00Z', received_at) AS minute,\n\t\t\t\t\tAVG(value) AS avg_util\n\t\t\t\tFROM cpu_points\n\t\t\t\tWHERE service_name = (SELECT service_name FROM top_service)\n\t\t\t\tGROUP BY minute\n\t\t\t\tORDER BY minute ASC\n\t\t\t)\n\t\tSELECT\n\t\t\tCASE\n\t\t\t\tWHEN NOT EXISTS (SELECT 1 FROM cpu_points) THEN 'unknown'\n\t\t\t\tWHEN (SELECT m FROM fleet_max) > 0.9 THEN 'critical'\n\t\t\t\tWHEN (SELECT m FROM fleet_max) > 0.7 THEN 'warn'\n\t\t\t\tELSE 'ok'\n\t\t\tEND AS status,\n\t\t\t(SELECT m FROM fleet_max) AS primary_value,\n\t\t\t(SELECT AVG(avg_util) FROM base_window) AS baseline_value,\n\t\t\t(SELECT json_object(\n\t\t\t\t'window', '5m',\n\t\t\t\t'baselineWindow', '25m',\n\t\t\t\t'topServices', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'service', service_name,\n\t\t\t\t\t\t'avgUtilization', avg_util\n\t\t\t\t\t)) FROM top_now\n\t\t\t\t),\n\t\t\t\t'sparkline', (\n\t\t\t\t\tSELECT json_group_array(json_object(\n\t\t\t\t\t\t'minute', minute,\n\t\t\t\t\t\t'avgUtilization', avg_util\n\t\t\t\t\t)) FROM spark\n\t\t\t\t)\n\t\t\t)) AS payload\n\t`,\n};\n\nexport const TIER0_ANALYSES: AnalysisDefinition[] = [\n\toverallErrorRate,\n\ttopErrorServices,\n\tlatencyP95Overall,\n\tthroughputSlope,\n\tactiveSessions,\n\tlogErrorRate,\n\tserviceCpuUtilization,\n];\n","// RFC 0002 Stage 1 — Analysis catalog entry point.\n//\n// Combines static Tier 0 (universal) analyses with dynamically derived\n// Tier 1 analyses. Agent 1's runner imports `getAllAnalysesForProject`\n// to pick up the active set for a project on each scheduler tick. Tier 2\n// (user-defined / LLM-suggested) analyses live in `analysis_definitions`\n// directly and are merged in by the runner, not here.\n//\n// Stage 6 augments the merge with auto-pinning: the top analyses cited\n// by the Ask box over the past week get a `pinned: true` flag the\n// dashboard groups separately at the top of the Health tab.\n\nimport type { AnalysisDefinition } from \"@obsunified/types\";\n\nimport { AnalysesStore } from \"../lib/analyses-store\";\nimport type { SqlDb } from \"../lib/sql-db\";\nimport { deriveAnalysesForProject } from \"./derive\";\nimport { INVESTIGATION_ANALYSES } from \"./investigations\";\nimport { TIER0_ANALYSES } from \"./tier0\";\n\nexport interface AnalysisContext {\n\tdb: SqlDb;\n}\n\nexport const getAllAnalysesForProject = async (\n\tprojectId: string,\n\tctx: AnalysisContext,\n): Promise<AnalysisDefinition[]> => {\n\tconst tier1 = await deriveAnalysesForProject(projectId, ctx.db);\n\tconst all = [...TIER0_ANALYSES, ...INVESTIGATION_ANALYSES, ...tier1];\n\n\t// Stage 6 — fold in the auto-pinned set. We tolerate failures on the\n\t// pin lookup (e.g. fresh install before migration 025) so registry\n\t// loading never breaks because the optional signal is missing.\n\tlet pinnedIds = new Set<string>();\n\ttry {\n\t\tconst store = new AnalysesStore(ctx.db);\n\t\tconst top = await store.getTopAskedAnalyses(projectId);\n\t\tpinnedIds = new Set(top.map((t) => t.analysisId));\n\t} catch {\n\t\t// no-op\n\t}\n\n\tif (pinnedIds.size === 0) return all;\n\treturn all.map((d) => (pinnedIds.has(d.id) ? { ...d, pinned: true } : d));\n};\n\nexport { deriveAnalysesForProject } from \"./derive\";\nexport { INVESTIGATION_ANALYSES } from \"./investigations\";\nexport { TIER0_ANALYSES } from \"./tier0\";\n","/**\n * Pluggable logger interface for the collector framework.\n *\n * Structurally compatible with `@obsunified/telemetry-sdk`'s `Logger`, so the worker\n * entrypoint can do:\n *\n * import { createLogger } from \"@obsunified/telemetry-sdk\";\n * createDefaultCollectorApp({ logger: createLogger(\"obs-collector\") });\n *\n * The framework package intentionally does not import telemetry-sdk to keep\n * the dependency graph one-way (SDK depends on collector contracts, not the\n * other way around). Anything that conforms to this interface works.\n *\n * When no logger is supplied, the framework falls back to a console-backed\n * logger so out-of-the-box deployments keep their existing log output.\n */\nexport interface Logger {\n\tdebug(message: string, attributes?: Record<string, unknown>): void;\n\tinfo(message: string, attributes?: Record<string, unknown>): void;\n\twarn(message: string, attributes?: Record<string, unknown>): void;\n\terror(message: string, attributes?: Record<string, unknown>): void;\n}\n\nconst formatAttrs = (attributes?: Record<string, unknown>): string => {\n\tif (!attributes || Object.keys(attributes).length === 0) return \"\";\n\ttry {\n\t\treturn ` ${JSON.stringify(attributes)}`;\n\t} catch {\n\t\treturn \"\";\n\t}\n};\n\nexport const consoleLogger: Logger = {\n\tdebug: (message, attributes) =>\n\t\tconsole.debug(`${message}${formatAttrs(attributes)}`),\n\tinfo: (message, attributes) =>\n\t\tconsole.log(`${message}${formatAttrs(attributes)}`),\n\twarn: (message, attributes) =>\n\t\tconsole.warn(`${message}${formatAttrs(attributes)}`),\n\terror: (message, attributes) =>\n\t\tconsole.error(`${message}${formatAttrs(attributes)}`),\n};\n\n/**\n * Minimal handle exposed to a `ChildSpanRunner` callback so the wrapped fn\n * can stamp attributes / events / status onto the span as it learns about\n * them (e.g., LLM token counts that are only known after the response).\n *\n * Structurally compatible with `ChildSpan` from `@obsunified/telemetry-sdk` so the\n * worker entrypoint can pass the SDK's child span through directly without\n * a bespoke adapter.\n */\nexport interface ChildSpanHandle {\n\tsetAttribute(key: string, value: unknown): void;\n\taddEvent?(name: string, attributes?: Record<string, unknown>): void;\n\tsetStatus?(code: number, message?: string): void;\n}\n\n/**\n * Wraps an async fn in a child span attached to the active parent span.\n * Structurally compatible with `withChildSpan` from `@obsunified/telemetry-sdk`.\n * Default is pass-through — wire from the worker entrypoint to enable.\n *\n * The wrapped fn receives a `ChildSpanHandle` so it can stamp attributes\n * after the fact (e.g., `gen_ai.usage.input_tokens` once the LLM response\n * arrives). When unwired, the handle's setters are no-ops.\n */\nexport type ChildSpanRunner = <T>(\n\tname: string,\n\tfn: (span: ChildSpanHandle) => Promise<T>,\n\tattributes?: Record<string, unknown>,\n) => Promise<T>;\n\nconst NOOP_HANDLE: ChildSpanHandle = {\n\tsetAttribute() {},\n\taddEvent() {},\n\tsetStatus() {},\n};\n\nexport const passthroughChildSpan: ChildSpanRunner = async (_name, fn) =>\n\tfn(NOOP_HANDLE);\n","/**\n * Gate-predicate evaluator for the RFC 0002 Stage 3 narrate layer.\n *\n * The gate is the single most important cost+noise control in the RFC.\n * Naive: every panel narrates every run → 600 sentences/hour at 10\n * panels. Real: only narrate when the system has actually changed.\n *\n * Mini-language (kept small on purpose):\n *\n * status_changed\n * delta_pct<op><number> op ∈ {>, >=, <, <=, ==, !=}\n * signature_changed\n * always (skip the gate, still LLM call)\n * never (don't narrate)\n * <atom> && <atom> [&& ...]\n * <atom> || <atom> [|| ...]\n *\n * `&&` binds tighter than `||` (standard precedence). No parens to\n * keep the parser tiny — if you need parens, split into two analyses.\n *\n * `evaluate()` returns one of three intents the runner needs:\n * - \"call\" : run the LLM\n * - \"reuse\" : keep previous narrative if any, no LLM call\n * - \"skip\" : narrative is null this run\n *\n * Why three states (not just true/false): when the gate doesn't fire\n * we still want to *show* the previous narrative (\"(unchanged for 8 min)\")\n * rather than blanking the panel. That's the \"reuse\" branch.\n */\n\nimport type { AnalysisResult } from \"@obsunified/types\";\n\nexport type NarrativeIntent = \"call\" | \"reuse\" | \"skip\";\n\ninterface GateInputs {\n\tcurrent: AnalysisResult;\n\tprevious: AnalysisResult | null;\n}\n\nconst COMPARATORS = [\"<=\", \">=\", \"==\", \"!=\", \"<\", \">\"] as const;\ntype Comparator = (typeof COMPARATORS)[number];\n\ninterface DeltaPctAtom {\n\tkind: \"delta_pct\";\n\top: Comparator;\n\tvalue: number;\n}\n\ninterface FlagAtom {\n\tkind: \"status_changed\" | \"signature_changed\" | \"always\" | \"never\";\n}\n\ntype Atom = DeltaPctAtom | FlagAtom;\n\ninterface ParseError {\n\tkind: \"error\";\n\tmessage: string;\n}\n\ntype ParseResult = { kind: \"ok\"; conjunctions: Atom[][] } | ParseError;\n\nconst stripWhitespace = (s: string) => s.replace(/\\s+/g, \"\");\n\nconst parseAtom = (raw: string): Atom | ParseError => {\n\tconst t = stripWhitespace(raw);\n\tif (!t) return { kind: \"error\", message: \"empty atom\" };\n\tif (t === \"status_changed\") return { kind: \"status_changed\" };\n\tif (t === \"signature_changed\") return { kind: \"signature_changed\" };\n\tif (t === \"always\") return { kind: \"always\" };\n\tif (t === \"never\") return { kind: \"never\" };\n\n\tif (t.startsWith(\"delta_pct\")) {\n\t\tconst rest = t.slice(\"delta_pct\".length);\n\t\t// Probe operators longest-first so `>=` doesn't match as `>`.\n\t\tfor (const op of COMPARATORS) {\n\t\t\tif (rest.startsWith(op)) {\n\t\t\t\tconst numStr = rest.slice(op.length);\n\t\t\t\tconst value = Number(numStr);\n\t\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkind: \"error\",\n\t\t\t\t\t\tmessage: `delta_pct: not a number after ${op}: \"${numStr}\"`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn { kind: \"delta_pct\", op, value };\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tkind: \"error\",\n\t\t\tmessage: `delta_pct: missing comparator (>, >=, <, <=, ==, !=)`,\n\t\t};\n\t}\n\n\treturn { kind: \"error\", message: `unknown atom: \"${t}\"` };\n};\n\n/**\n * Parse `a && b || c && d` → `[[a, b], [c, d]]` (DNF, OR over ANDs).\n * Returned errors point at the offending atom, not character position —\n * good enough given how short these predicates are.\n */\nexport function parsePredicate(predicate: string): ParseResult {\n\tconst orGroups = predicate.split(\"||\");\n\tconst conjunctions: Atom[][] = [];\n\tfor (const group of orGroups) {\n\t\tconst atoms: Atom[] = [];\n\t\tconst parts = group.split(\"&&\");\n\t\tfor (const part of parts) {\n\t\t\tconst atom = parseAtom(part);\n\t\t\tif (\"kind\" in atom && atom.kind === \"error\") return atom;\n\t\t\tatoms.push(atom as Atom);\n\t\t}\n\t\tconjunctions.push(atoms);\n\t}\n\treturn { kind: \"ok\", conjunctions };\n}\n\nconst compare = (op: Comparator, a: number, b: number): boolean => {\n\tswitch (op) {\n\t\tcase \">\":\n\t\t\treturn a > b;\n\t\tcase \">=\":\n\t\t\treturn a >= b;\n\t\tcase \"<\":\n\t\t\treturn a < b;\n\t\tcase \"<=\":\n\t\t\treturn a <= b;\n\t\tcase \"==\":\n\t\t\treturn a === b;\n\t\tcase \"!=\":\n\t\t\treturn a !== b;\n\t}\n};\n\nconst evalAtom = (atom: Atom, { current, previous }: GateInputs): boolean => {\n\tswitch (atom.kind) {\n\t\tcase \"always\":\n\t\t\treturn true;\n\t\tcase \"never\":\n\t\t\treturn false;\n\t\tcase \"status_changed\":\n\t\t\tif (previous === null) return true;\n\t\t\treturn current.status !== previous.status;\n\t\tcase \"signature_changed\":\n\t\t\tif (previous === null) return true;\n\t\t\treturn current.narrativeSignature !== previous.narrativeSignature;\n\t\tcase \"delta_pct\": {\n\t\t\tconst dp = current.deltaPct;\n\t\t\tif (dp === null || !Number.isFinite(dp)) return false;\n\t\t\treturn compare(atom.op, Math.abs(dp), atom.value);\n\t\t}\n\t}\n};\n\n/**\n * Decide what to do with the narrative this run.\n *\n * - spec missing or `never` → skip\n * - first ever run AND spec present → call (no previous to compare)\n * - signature unchanged → reuse previous narrative\n * (the LLM would say the same\n * thing — don't pay for it)\n * - gate predicate evaluates true → call\n * - otherwise → reuse if previous narrative\n * exists, else skip\n *\n * `signature_changed` short-circuits to skip when signatures match,\n * even if other clauses would fire — this keeps the cache invariant\n * \"same signature ⇒ same narrative\" airtight.\n */\nexport function evaluateGate(\n\tpredicate: string | undefined,\n\tinputs: GateInputs,\n): NarrativeIntent {\n\tconst expr = (predicate ?? \"status_changed\").trim();\n\tif (expr === \"\" || expr === \"never\") return \"skip\";\n\n\tconst { current, previous } = inputs;\n\n\t// Cache: same signature as last result ⇒ reuse the previous narrative\n\t// without LLM call. Even with `always` we don't pay twice for the same\n\t// state of the world.\n\tif (\n\t\tprevious?.narrative &&\n\t\tcurrent.narrativeSignature !== null &&\n\t\tcurrent.narrativeSignature === previous.narrativeSignature\n\t) {\n\t\treturn \"reuse\";\n\t}\n\n\t// First-run-with-spec — no previous to compare to, so narrate.\n\tif (previous === null) return \"call\";\n\n\tconst parsed = parsePredicate(expr);\n\tif (parsed.kind === \"error\") {\n\t\t// Don't blow up the runner over a malformed predicate; fall back to\n\t\t// \"status_changed\" which is the conservative default.\n\t\tconsole.log(`[narrate-gate] bad predicate \"${expr}\": ${parsed.message}`);\n\t\tconst fallback = parsePredicate(\"status_changed\");\n\t\tif (fallback.kind === \"error\") return \"skip\"; // unreachable\n\t\treturn evaluateConjunctions(fallback.conjunctions, inputs)\n\t\t\t? \"call\"\n\t\t\t: previous.narrative\n\t\t\t\t? \"reuse\"\n\t\t\t\t: \"skip\";\n\t}\n\n\tconst fired = evaluateConjunctions(parsed.conjunctions, inputs);\n\tif (fired) return \"call\";\n\treturn previous.narrative ? \"reuse\" : \"skip\";\n}\n\nfunction evaluateConjunctions(\n\tconjunctions: Atom[][],\n\tinputs: GateInputs,\n): boolean {\n\t// DNF: OR over ANDs.\n\tfor (const group of conjunctions) {\n\t\tif (group.every((atom) => evalAtom(atom, inputs))) return true;\n\t}\n\treturn false;\n}\n\n/**\n * Compute a narrative_signature from a result. The signature is what we\n * compare to decide \"did the world actually change in a way the narrative\n * would describe?\" — so it includes status, the rounded primary value,\n * and any caller-supplied identifiers from the payload (top services,\n * top errors, etc).\n *\n * Rounded coarsely so that 1.241% vs 1.243% don't both pay for an LLM call.\n */\nexport function computeSignature(input: {\n\tstatus: string;\n\tprimaryValue: number | null;\n\tbaselineValue: number | null;\n\tpayload: Record<string, unknown>;\n}): string {\n\tconst round = (v: number | null): string => {\n\t\tif (v === null || !Number.isFinite(v)) return \"n\";\n\t\t// 3 sig figs for small numbers, 1% buckets for percentages we present\n\t\t// as such. Keep it simple — over-rounding hurts cache hit rate, under\n\t\t// hurts cost.\n\t\tif (Math.abs(v) >= 100) return Math.round(v).toString();\n\t\tif (Math.abs(v) >= 1) return v.toFixed(1);\n\t\treturn v.toFixed(2);\n\t};\n\tconst sigPayload =\n\t\ttypeof input.payload?.signatureKey === \"string\"\n\t\t\t? (input.payload.signatureKey as string)\n\t\t\t: \"\";\n\treturn `${input.status}|${round(input.primaryValue)}|${round(input.baselineValue)}|${sigPayload}`;\n}\n","/**\n * RFC 0002 Stage 1 — runner that executes SQL-only Analyses on the existing\n * scheduled handler.\n *\n * runSqlAnalysis — execute one definition's `sql` against D1 and shape the\n * row(s) into an AnalysisResult.\n * runAllDueAnalyses — orchestrator: refresh the in-process registry into\n * analysis_definitions, find which ones are due, run them,\n * persist the results. Per-analysis errors are isolated\n * via Promise.allSettled so one bad SQL doesn't kill the\n * batch.\n *\n * Result shape convention: an Analysis SQL is expected to return a single\n * row with the columns:\n *\n * status TEXT | NULL -- 'ok' | 'warn' | 'critical' | 'unknown'\n * primary_value REAL | NULL\n * baseline_value REAL | NULL\n * payload TEXT | NULL -- JSON-serialized object, optional\n *\n * If `status` is NULL we derive it from the magnitude of delta_pct\n * (>=25% → critical, >=10% → warn, else ok). delta_pct itself is computed\n * here from primary/baseline so individual SQL queries don't have to.\n */\n\nimport type {\n\tAnalysisDefinition,\n\tAnalysisResult,\n\tAnalysisStatus,\n} from \"@obsunified/types\";\nimport { getAllAnalysesForProject } from \"../analyses/index\";\nimport type { CollectorEnv } from \"../framework/env\";\nimport {\n\ttype ChildSpanRunner,\n\tconsoleLogger,\n\ttype Logger,\n} from \"../framework/logger\";\nimport { AnalysesStore } from \"./analyses-store\";\nimport { generateNarrative, LlmCallError, type LlmConfig } from \"./llm\";\nimport {\n\tcomputeSignature,\n\tevaluateGate,\n\ttype NarrativeIntent,\n} from \"./narrate-gate\";\nimport { type SqlDb, sqlDbFor } from \"./sql-db\";\n\nexport interface AnalysisRunContext {\n\tdb: SqlDb;\n\tprojectId: string;\n\tretentionHours: number;\n\t/** Stage 3: narrative LLM config. Undefined = narratives disabled. */\n\tllm?: LlmConfig;\n\t/** Stage 3: max narrative-writes per project per hour. Default 50. */\n\tnarrativeBudgetPerHour?: number;\n\t/** Pluggable logger; defaults to console. */\n\tlogger?: Logger;\n}\n\ninterface AnalysisSqlRow {\n\tstatus?: string | null;\n\tprimary_value?: number | null;\n\tbaseline_value?: number | null;\n\tpayload?: string | null;\n}\n\nconst VALID_STATUSES: ReadonlySet<AnalysisStatus> = new Set([\n\t\"ok\",\n\t\"warn\",\n\t\"critical\",\n\t\"unknown\",\n]);\n\nconst deriveStatus = (deltaPct: number | null): AnalysisStatus => {\n\tif (deltaPct === null || !Number.isFinite(deltaPct)) return \"unknown\";\n\tconst magnitude = Math.abs(deltaPct);\n\tif (magnitude >= 25) return \"critical\";\n\tif (magnitude >= 10) return \"warn\";\n\treturn \"ok\";\n};\n\nconst computeDeltaPct = (\n\tprimary: number | null,\n\tbaseline: number | null,\n): number | null => {\n\tif (\n\t\tprimary === null ||\n\t\tbaseline === null ||\n\t\t!Number.isFinite(primary) ||\n\t\t!Number.isFinite(baseline) ||\n\t\tbaseline === 0\n\t) {\n\t\treturn null;\n\t}\n\treturn ((primary - baseline) / baseline) * 100;\n};\n\nconst parsePayload = (\n\tpayload: string | null | undefined,\n): Record<string, unknown> => {\n\tif (!payload) return {};\n\ttry {\n\t\tconst parsed = JSON.parse(payload) as unknown;\n\t\treturn parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n\t\t\t? (parsed as Record<string, unknown>)\n\t\t\t: {};\n\t} catch {\n\t\treturn {};\n\t}\n};\n\nexport async function runSqlAnalysis(\n\tdef: AnalysisDefinition,\n\tctx: AnalysisRunContext,\n): Promise<AnalysisResult> {\n\tif (!def.sql)\n\t\tthrow new Error(\n\t\t\t`Analysis \"${def.id}\" has no sql; cannot run as SQL analysis`,\n\t\t);\n\n\tconst startedAt = Date.now();\n\t// Contract with Agent 2's analysis derivation:\n\t// - Tier 0 SQL is static and references the literal token {{PROJECT_ID}};\n\t// the runner string-replaces it before execution.\n\t// - Tier 1 SQL bakes the project_id in at derivation time (escaped via\n\t// SQL '' quoting) and contains no token.\n\t// Either way, queries expect zero ? bindings. project_id is collector-\n\t// internal (never user-supplied), but we still validate the shape to keep\n\t// future user-defined SQL safe from token-replacement injection.\n\tif (!/^[A-Za-z0-9_-]+$/.test(ctx.projectId)) {\n\t\tthrow new Error(\n\t\t\t`refusing to run analysis: unsafe project_id ${ctx.projectId}`,\n\t\t);\n\t}\n\tconst sqlWithProject = def.sql.replace(/\\{\\{PROJECT_ID\\}\\}/g, ctx.projectId);\n\tconst row = await ctx.db.prepare(sqlWithProject).first<AnalysisSqlRow>();\n\n\tconst primaryValue =\n\t\trow && typeof row.primary_value === \"number\" ? row.primary_value : null;\n\tconst baselineValue =\n\t\trow && typeof row.baseline_value === \"number\" ? row.baseline_value : null;\n\tconst deltaPct = computeDeltaPct(primaryValue, baselineValue);\n\n\tconst rawStatus = row?.status;\n\tconst status: AnalysisStatus =\n\t\trawStatus && VALID_STATUSES.has(rawStatus as AnalysisStatus)\n\t\t\t? (rawStatus as AnalysisStatus)\n\t\t\t: deriveStatus(deltaPct);\n\n\tconst generatedAt = new Date().toISOString();\n\n\tconst payload = parsePayload(row?.payload);\n\tconst narrativeSignature = computeSignature({\n\t\tstatus,\n\t\tprimaryValue,\n\t\tbaselineValue,\n\t\tpayload,\n\t});\n\n\treturn {\n\t\tanalysisId: def.id,\n\t\tprojectId: ctx.projectId,\n\t\tgeneratedAt,\n\t\tparamsHash: null,\n\t\tstatus,\n\t\tprimaryValue,\n\t\tbaselineValue,\n\t\tdeltaPct,\n\t\tpayload,\n\t\tnarrative: null,\n\t\tnarrativeSignature,\n\t\tdurationMs: Date.now() - startedAt,\n\t};\n}\n\n/**\n * RFC 0002 Stage 3 — narrate pass. Decides whether to call the LLM,\n * reuse a cached narrative, or skip; mutates the result in place.\n *\n * Budget is checked once at call time (not pre-decided per panel) so\n * the runner doesn't waste effort computing gates for analyses that\n * won't get a turn anyway. `[narrate]` log lines are the operator's\n * audit trail for \"why didn't this panel narrate?\".\n */\nasync function narratePass(\n\tdef: AnalysisDefinition,\n\tcurrent: AnalysisResult,\n\tprevious: AnalysisResult | null,\n\tctx: AnalysisRunContext,\n\t_store: AnalysesStore,\n\tbudgetState: { remaining: number },\n): Promise<void> {\n\tif (!def.narrate) return;\n\tif (!ctx.llm) return;\n\n\tconst intent: NarrativeIntent = evaluateGate(def.narrate.only_when, {\n\t\tcurrent,\n\t\tprevious,\n\t});\n\n\tif (intent === \"skip\") return;\n\n\tif (intent === \"reuse\" && previous?.narrative) {\n\t\tcurrent.narrative = previous.narrative;\n\t\t// Keep the previous signature so subsequent runs continue to compare\n\t\t// against the state that produced this narrative.\n\t\tcurrent.narrativeSignature = previous.narrativeSignature;\n\t\treturn;\n\t}\n\n\tif (intent !== \"call\") return;\n\n\tif (budgetState.remaining <= 0) {\n\t\t(ctx.logger ?? consoleLogger).warn(\"[narrate] budget exhausted\", {\n\t\t\tanalysis_id: def.id,\n\t\t});\n\t\tif (previous?.narrative) {\n\t\t\tcurrent.narrative = previous.narrative;\n\t\t\tcurrent.narrativeSignature = previous.narrativeSignature;\n\t\t}\n\t\treturn;\n\t}\n\n\ttry {\n\t\tbudgetState.remaining -= 1;\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), 20_000);\n\t\tconst text = await generateNarrative(\n\t\t\t{ definition: def, current, previous },\n\t\t\t{ ...ctx.llm, signal: controller.signal },\n\t\t).finally(() => clearTimeout(timeout));\n\t\tcurrent.narrative = text;\n\t\t// Keep the just-computed signature so cache compare works next run.\n\t} catch (error) {\n\t\tconst msg =\n\t\t\terror instanceof LlmCallError\n\t\t\t\t? `${error.message}`\n\t\t\t\t: error instanceof Error\n\t\t\t\t\t? error.message\n\t\t\t\t\t: String(error);\n\t\t(ctx.logger ?? consoleLogger).error(\"[narrate] LLM call failed\", {\n\t\t\tanalysis_id: def.id,\n\t\t\terror: msg,\n\t\t});\n\t\tif (previous?.narrative) {\n\t\t\tcurrent.narrative = previous.narrative;\n\t\t\tcurrent.narrativeSignature = previous.narrativeSignature;\n\t\t}\n\t}\n}\n\n/**\n * Orchestrator. Refreshes the analysis_definitions registry from the\n * in-process registry (so newly-derived Tier 1 analyses become visible\n * to the dashboard within one tick), then runs whatever's due.\n *\n * Stage 1 has a single project (\"default\"). When a projects table is\n * available we'll iterate it here.\n */\nexport async function runAllDueAnalyses(\n\tctx: {\n\t\tenv: CollectorEnv;\n\t\tretentionHours: number;\n\t\tlogger?: Logger;\n\t\ttracer?: ChildSpanRunner;\n\t},\n\t_runtime?: unknown,\n): Promise<{\n\tran: number;\n\tfailed: number;\n\trefreshed: number;\n\tnarrated: number;\n\tskipped?: number;\n}> {\n\tconst logger = ctx.logger ?? consoleLogger;\n\tconst db = sqlDbFor(ctx.env);\n\tconst store = new AnalysesStore(db);\n\tconst projectId = \"default\";\n\tconst now = Date.now();\n\tconst expiresAt = now + ctx.retentionHours * 3600 * 1000;\n\n\t// 1. Refresh the registry — Agent 2's getAllAnalysesForProject builds the\n\t// union of Tier 0 + derived Tier 1 + user-defined analyses.\n\tlet registered: AnalysisDefinition[] = [];\n\ttry {\n\t\tregistered = await getAllAnalysesForProject(projectId, {\n\t\t\tdb,\n\t\t});\n\t} catch (error) {\n\t\tlogger.error(\"[analyses] failed to load registered analyses\", {\n\t\t\tproject_id: projectId,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t});\n\t}\n\n\tlet refreshed = 0;\n\tfor (const def of registered) {\n\t\ttry {\n\t\t\tawait store.upsertDefinition(projectId, def);\n\t\t\trefreshed += 1;\n\t\t} catch (error) {\n\t\t\tlogger.error(\"[analyses] upsertDefinition failed\", {\n\t\t\t\tanalysis_id: def.id,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t}\n\t}\n\n\t// 2. Find what's due and run them.\n\tconst due = await store.getDueAnalyses(projectId, now);\n\tif (due.length === 0) {\n\t\treturn { ran: 0, failed: 0, refreshed, narrated: 0 };\n\t}\n\n\t// Narrative LLM config — present only when an API key is set on the\n\t// worker. We don't fail the run if it's missing; we just skip the\n\t// narrate pass entirely (every panel still produces numbers).\n\t//\n\t// Provider preference: OpenAI wins when both keys are set — configuring\n\t// both is presumed deliberate. Empty-string env values from .dev.vars\n\t// are coerced to undefined so they don't accidentally override defaults.\n\tconst openaiBase = ctx.env.OPENAI_BASE_URL?.trim()\n\t\t? ctx.env.OPENAI_BASE_URL\n\t\t: undefined;\n\tconst narrativeModel = ctx.env.NARRATIVE_MODEL?.trim()\n\t\t? ctx.env.NARRATIVE_MODEL\n\t\t: undefined;\n\tconst llm: LlmConfig | undefined = ctx.env.OPENAI_API_KEY?.trim()\n\t\t? {\n\t\t\t\tprovider: \"openai\",\n\t\t\t\tapiKey: ctx.env.OPENAI_API_KEY,\n\t\t\t\tmodel: narrativeModel ?? \"gpt-4o-mini\",\n\t\t\t\tapiUrl: openaiBase,\n\t\t\t\ttracer: ctx.tracer,\n\t\t\t}\n\t\t: ctx.env.ANTHROPIC_API_KEY?.trim()\n\t\t\t? {\n\t\t\t\t\tprovider: \"anthropic\",\n\t\t\t\t\tapiKey: ctx.env.ANTHROPIC_API_KEY,\n\t\t\t\t\tmodel: narrativeModel ?? \"claude-3-5-haiku-latest\",\n\t\t\t\t\ttracer: ctx.tracer,\n\t\t\t\t}\n\t\t\t: undefined;\n\tconst parsedNarrativeBudget = Number.parseInt(\n\t\tctx.env.NARRATIVE_BUDGET_PER_HOUR ?? \"\",\n\t\t10,\n\t);\n\tconst narrativeBudgetPerHour = Number.isFinite(parsedNarrativeBudget)\n\t\t? parsedNarrativeBudget\n\t\t: 50;\n\tconst narrativesUsed = llm\n\t\t? await store.countNarrativesInWindow(projectId, 60)\n\t\t: 0;\n\tconst budgetState = {\n\t\tremaining: Math.max(0, narrativeBudgetPerHour - narrativesUsed),\n\t};\n\n\tconst runCtx: AnalysisRunContext = {\n\t\tdb,\n\t\tprojectId,\n\t\tretentionHours: ctx.retentionHours,\n\t\tllm,\n\t\tnarrativeBudgetPerHour,\n\t\tlogger,\n\t};\n\n\t// Run with bounded concurrency. D1 is happy with a handful of parallel\n\t// queries; 45 in flight at once causes the Workers scheduled handler\n\t// to hit its CPU/wall-time cap before any results land. We also log\n\t// per-analysis so a stuck SQL is identifiable in the log rather than\n\t// silently swallowed.\n\tconst CONCURRENCY = 4;\n\t// Lease window for the per-analysis claim. Long enough that a healthy\n\t// narrative pass (LLM roundtrip + result insert) won't get rerun by the\n\t// next tick, short enough that a worker crash unblocks the row within\n\t// two ticks. 90 s sits between the every-minute cron and a typical LLM\n\t// p95.\n\tconst CLAIM_LEASE_MS = 90_000;\n\tlet ran = 0;\n\tlet failed = 0;\n\tlet skipped = 0;\n\tlet narrated = 0;\n\tconst queue = [...due];\n\tconst workers: Promise<void>[] = [];\n\tfor (let w = 0; w < CONCURRENCY; w += 1) {\n\t\tworkers.push(\n\t\t\t(async () => {\n\t\t\t\twhile (queue.length > 0) {\n\t\t\t\t\tconst def = queue.shift();\n\t\t\t\t\tif (!def) return;\n\t\t\t\t\tconst claimed = await store.claimAnalysis(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tdef.id,\n\t\t\t\t\t\tDate.now(),\n\t\t\t\t\t\tCLAIM_LEASE_MS,\n\t\t\t\t\t);\n\t\t\t\t\tif (!claimed) {\n\t\t\t\t\t\tskipped += 1;\n\t\t\t\t\t\tlogger.info(\"[analyses] skipped (lease held by another tick)\", {\n\t\t\t\t\t\t\tanalysis_id: def.id,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await runSqlAnalysis(def, runCtx);\n\t\t\t\t\t\t// Stage 3: narrate pass. Reads previous result from D1 to\n\t\t\t\t\t\t// run gate logic + signature cache; isolated from query\n\t\t\t\t\t\t// failures so a flaky LLM doesn't drop the data row.\n\t\t\t\t\t\tif (def.narrate && runCtx.llm) {\n\t\t\t\t\t\t\tconst previous = await store.getLatestResult(projectId, def.id);\n\t\t\t\t\t\t\tawait narratePass(\n\t\t\t\t\t\t\t\tdef,\n\t\t\t\t\t\t\t\tresult,\n\t\t\t\t\t\t\t\tprevious,\n\t\t\t\t\t\t\t\trunCtx,\n\t\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\t\tbudgetState,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (result.narrative) narrated += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait store.insertResult(result, expiresAt);\n\t\t\t\t\t\t// markRan releases the claim as a side-effect.\n\t\t\t\t\t\tawait store.markRan(projectId, def.id, result.generatedAt);\n\t\t\t\t\t\tran += 1;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tfailed += 1;\n\t\t\t\t\t\tawait store.releaseClaim(projectId, def.id);\n\t\t\t\t\t\tlogger.error(\"[analyses] analysis failed\", {\n\t\t\t\t\t\t\tanalysis_id: def.id,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})(),\n\t\t);\n\t}\n\tawait Promise.all(workers);\n\n\treturn { ran, failed, refreshed, narrated, skipped };\n}\n","import type {\n\tLogRecord,\n\tLogSeverity,\n\tLogsOverviewOptions,\n\tLogsOverviewResponse,\n} from \"@obsunified/types\";\nimport { dialectFor, type SqlDb } from \"./sql-db\";\n\nconst LOG_SEVERITIES = new Set<LogSeverity>([\n\t\"DEBUG\",\n\t\"INFO\",\n\t\"WARN\",\n\t\"ERROR\",\n\t\"FATAL\",\n]);\n\nconst toLogSeverity = (severity: string): LogSeverity =>\n\tLOG_SEVERITIES.has(severity as LogSeverity)\n\t\t? (severity as LogSeverity)\n\t\t: \"INFO\";\n\n/** Clamp an integer to a safe range */\nconst clampInt = (\n\tvalue: unknown,\n\tmin: number,\n\tmax: number,\n\tfallback: number,\n): number => {\n\tconst n = typeof value === \"number\" ? value : parseInt(String(value), 10);\n\tif (!Number.isFinite(n)) return fallback;\n\treturn Math.max(min, Math.min(max, n));\n};\n\ninterface LogRow {\n\tproject_id?: string;\n\tlog_id: string;\n\ttrace_id: string | null;\n\tspan_id: string | null;\n\tservice_name: string | null;\n\tseverity: string;\n\tseverity_number: number;\n\tlogger_name: string | null;\n\tmessage: string;\n\tattributes_json: string | null;\n\tflags: number | null;\n\tdropped_attributes_count: number | null;\n\toccurred_at: string;\n\treceived_at: string;\n\texpires_at: string;\n}\n\ninterface LogsSummaryRow {\n\ttotalLogs?: number;\n\terrorLogs?: number;\n\twarnLogs?: number;\n}\n\nexport class LogsStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync ingestBatch(logs: LogRecord[]): Promise<void> {\n\t\tif (logs.length === 0) return;\n\n\t\tconst stmt = this.db.prepare(`\n INSERT OR IGNORE INTO logs (\n project_id, log_id, trace_id, span_id, service_name, severity, severity_number,\n logger_name, message, attributes_json, flags, dropped_attributes_count,\n occurred_at, received_at, expires_at, session_id, interaction_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n\t\tconst batch = logs.map((l) => {\n\t\t\tif (!l.projectId)\n\t\t\t\tthrow new Error(\"LogsStore.ingestBatch: log.projectId is required\");\n\t\t\treturn stmt.bind(\n\t\t\t\tl.projectId,\n\t\t\t\tl.logId,\n\t\t\t\tl.traceId,\n\t\t\t\tl.spanId,\n\t\t\t\tl.serviceName,\n\t\t\t\tl.severity,\n\t\t\t\tl.severityNumber,\n\t\t\t\tl.loggerName,\n\t\t\t\tl.message,\n\t\t\t\tl.attributesJson,\n\t\t\t\tl.flags,\n\t\t\t\tl.droppedAttributesCount,\n\t\t\t\tl.occurredAt,\n\t\t\t\tl.receivedAt,\n\t\t\t\tl.expiresAt,\n\t\t\t\tl.sessionId ?? null,\n\t\t\t\tl.interactionId ?? null,\n\t\t\t);\n\t\t});\n\n\t\tawait this.db.batch(batch);\n\t}\n\n\tasync getLogs(options: LogsOverviewOptions): Promise<LogsOverviewResponse> {\n\t\tif (!options.projectId)\n\t\t\tthrow new Error(\"LogsStore.getLogs: projectId is required\");\n\t\tconst dialect = dialectFor(this.db);\n\t\tconst hours = clampInt(options.hours, 1, 720, 24);\n\t\tconst limit = clampInt(options.limit, 1, 1000, 100);\n\n\t\tlet sql = `SELECT * FROM logs WHERE project_id = ? AND received_at >= ${dialect.sinceHours(\"?\")}`;\n\t\tconst params: unknown[] = [options.projectId, hours];\n\n\t\tif (options.service) {\n\t\t\tsql += ` AND service_name = ?`;\n\t\t\tparams.push(options.service);\n\t\t}\n\t\tif (options.severity) {\n\t\t\tsql += ` AND severity = ?`;\n\t\t\tparams.push(options.severity);\n\t\t}\n\t\tif (options.traceId) {\n\t\t\tsql += ` AND trace_id = ?`;\n\t\t\tparams.push(options.traceId);\n\t\t}\n\t\tif (options.search) {\n\t\t\tsql += ` AND message LIKE ?`;\n\t\t\tparams.push(`%${options.search}%`);\n\t\t}\n\n\t\tsql += ` ORDER BY received_at DESC LIMIT ?`;\n\t\tparams.push(limit);\n\n\t\tconst results = await this.db\n\t\t\t.prepare(sql)\n\t\t\t.bind(...params)\n\t\t\t.all<LogRow>();\n\n\t\t// Simple summary stats\n\t\tconst summarySql = `\n SELECT\n COUNT(*) as totalLogs,\n SUM(CASE WHEN severity = 'ERROR' OR severity = 'FATAL' THEN 1 ELSE 0 END) as errorLogs,\n SUM(CASE WHEN severity = 'WARN' THEN 1 ELSE 0 END) as warnLogs\n FROM logs WHERE project_id = ? AND received_at >= ${dialect.sinceHours(\"?\")}\n ${options.service ? \"AND service_name = ?\" : \"\"}\n `;\n\t\tconst summaryParams: unknown[] = [options.projectId, hours];\n\t\tif (options.service) summaryParams.push(options.service);\n\t\tconst summaryResult =\n\t\t\t(await this.db\n\t\t\t\t.prepare(summarySql)\n\t\t\t\t.bind(...summaryParams)\n\t\t\t\t.first<LogsSummaryRow>()) || {};\n\n\t\tconst logs: LogRecord[] = (results.results || []).map((r) => ({\n\t\t\tprojectId: r.project_id ?? \"default\",\n\t\t\tlogId: r.log_id,\n\t\t\ttraceId: r.trace_id,\n\t\t\tspanId: r.span_id,\n\t\t\tserviceName: r.service_name,\n\t\t\tseverity: toLogSeverity(r.severity),\n\t\t\tseverityNumber: r.severity_number,\n\t\t\tloggerName: r.logger_name,\n\t\t\tmessage: r.message,\n\t\t\tattributesJson: r.attributes_json,\n\t\t\tflags: r.flags ?? 0,\n\t\t\tdroppedAttributesCount: r.dropped_attributes_count ?? 0,\n\t\t\toccurredAt: r.occurred_at,\n\t\t\treceivedAt: r.received_at,\n\t\t\texpiresAt: r.expires_at,\n\t\t}));\n\n\t\treturn {\n\t\t\tlogs,\n\t\t\tsummary: {\n\t\t\t\ttotalLogs: summaryResult.totalLogs || 0,\n\t\t\t\terrorLogs: summaryResult.errorLogs || 0,\n\t\t\t\twarnLogs: summaryResult.warnLogs || 0,\n\t\t\t},\n\t\t\twindowHours: hours,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\t}\n\n\tasync purgeExpired(): Promise<number> {\n\t\tconst dialect = dialectFor(this.db);\n\t\tconst { meta } = await this.db\n\t\t\t.prepare(`DELETE FROM logs WHERE expires_at < ${dialect.now()}`)\n\t\t\t.run();\n\t\treturn meta.changes;\n\t}\n}\n","/**\n * Metrics storage.\n *\n * Each ingest collapses points to their series identity, upserts the series\n * row, then batch-inserts points. Series upsert is per-unique-identity per\n * request — at small batch sizes this is cheap; a followup can switch to a\n * single SELECT-many + batched INSERT-missing when volume demands it.\n */\n\nimport type { DecodedMetricPoint } from \"../otlp/decode\";\nimport { dialectFor, type SqlDb, type SqlStatement } from \"./sql-db\";\n\ninterface SeriesRow {\n\tid: string;\n\tidentity: string;\n}\n\ninterface StoredExemplar {\n\tvalue: number;\n\ttraceId: string | null;\n\tspanId: string | null;\n\ttsNs: string;\n}\n\nexport interface MetricExemplarPoint {\n\tid: string;\n\tpointId: string;\n\tseriesId: string;\n\tmetricName: string;\n\tserviceName: string | null;\n\ttraceId: string | null;\n\tspanId: string | null;\n\ttsNs: string;\n\tvalue: number;\n\treceivedAt: string;\n}\n\nconst parseExemplars = (raw: string | null): StoredExemplar[] => {\n\tif (!raw) return [];\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\tif (!Array.isArray(parsed)) return [];\n\t\treturn parsed.filter(\n\t\t\t(exemplar): exemplar is StoredExemplar =>\n\t\t\t\ttypeof exemplar === \"object\" &&\n\t\t\t\texemplar !== null &&\n\t\t\t\ttypeof exemplar.value === \"number\" &&\n\t\t\t\tNumber.isFinite(exemplar.value) &&\n\t\t\t\ttypeof exemplar.tsNs === \"string\" &&\n\t\t\t\t(exemplar.traceId === null || typeof exemplar.traceId === \"string\") &&\n\t\t\t\t(exemplar.spanId === null || typeof exemplar.spanId === \"string\"),\n\t\t);\n\t} catch {\n\t\treturn [];\n\t}\n};\n\nexport class MetricsStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync purgeExpired(): Promise<number> {\n\t\tconst dialect = dialectFor(this.db);\n\t\tconst [exemplarResult, pointResult] = await this.db.batch([\n\t\t\tthis.db.prepare(\n\t\t\t\t`DELETE FROM metric_exemplars WHERE expires_at < ${dialect.now()}`,\n\t\t\t),\n\t\t\tthis.db.prepare(\n\t\t\t\t`DELETE FROM metric_point WHERE expires_at < ${dialect.now()}`,\n\t\t\t),\n\t\t]);\n\t\treturn (\n\t\t\t(exemplarResult?.meta.changes ?? 0) + (pointResult?.meta.changes ?? 0)\n\t\t);\n\t}\n\n\tasync ingestBatch(opts: {\n\t\tprojectId: string;\n\t\tpoints: DecodedMetricPoint[];\n\t\treceivedAt: string;\n\t\texpiresAt: string;\n\t}): Promise<void> {\n\t\tconst { projectId, points, receivedAt, expiresAt } = opts;\n\t\tif (points.length === 0) return;\n\n\t\tconst seriesByIdentity = await this.resolveSeries(projectId, points);\n\n\t\tconst pointStmt = this.db.prepare(`\n\t\t\tINSERT INTO metric_point (\n\t\t\t\tid, series_id, project_id, ts_ns, start_ts_ns,\n\t\t\t\tvalue, count, sum, min, max, bounds_json, bucket_counts_json,\n\t\t\t\textra_json, exemplars_json, received_at, expires_at\n\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t`);\n\t\tconst exemplarStmt = this.db.prepare(`\n\t\t\tINSERT INTO metric_exemplars (\n\t\t\t\tid, point_id, series_id, project_id, metric_name, service_name,\n\t\t\t\ttrace_id, span_id, ts_ns, value, received_at, expires_at\n\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t`);\n\n\t\tconst batch: SqlStatement[] = [];\n\t\tfor (const p of points) {\n\t\t\tconst series = seriesByIdentity.get(p.identity);\n\t\t\tif (!series) throw new Error(`series not resolved: ${p.identity}`);\n\t\t\tconst pointId = crypto.randomUUID();\n\t\t\tbatch.push(\n\t\t\t\tpointStmt.bind(\n\t\t\t\t\tpointId,\n\t\t\t\t\tseries.id,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tp.tsNs,\n\t\t\t\t\tp.startTsNs,\n\t\t\t\t\tp.value,\n\t\t\t\t\tp.count,\n\t\t\t\t\tp.sum,\n\t\t\t\t\tp.min,\n\t\t\t\t\tp.max,\n\t\t\t\t\tp.boundsJson,\n\t\t\t\t\tp.bucketCountsJson,\n\t\t\t\t\tp.extraJson,\n\t\t\t\t\tp.exemplarsJson,\n\t\t\t\t\treceivedAt,\n\t\t\t\t\texpiresAt,\n\t\t\t\t),\n\t\t\t);\n\t\t\tfor (const exemplar of parseExemplars(p.exemplarsJson)) {\n\t\t\t\tif (!exemplar.traceId && !exemplar.spanId) continue;\n\t\t\t\tbatch.push(\n\t\t\t\t\texemplarStmt.bind(\n\t\t\t\t\t\tcrypto.randomUUID(),\n\t\t\t\t\t\tpointId,\n\t\t\t\t\t\tseries.id,\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tp.name,\n\t\t\t\t\t\tp.serviceName,\n\t\t\t\t\t\texemplar.traceId,\n\t\t\t\t\t\texemplar.spanId,\n\t\t\t\t\t\texemplar.tsNs,\n\t\t\t\t\t\texemplar.value,\n\t\t\t\t\t\treceivedAt,\n\t\t\t\t\t\texpiresAt,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tawait this.db.batch(batch);\n\t}\n\n\tasync exemplarsForTrace(\n\t\tprojectId: string,\n\t\ttraceId: string,\n\t\tlimit = 50,\n\t): Promise<MetricExemplarPoint[]> {\n\t\tconst rows = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT id, point_id, series_id, metric_name, service_name,\n\t\t\t\t\t\ttrace_id, span_id, ts_ns, value, received_at\n\t\t\t\t\tFROM metric_exemplars\n\t\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\t\tORDER BY ts_ns DESC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, traceId, limit)\n\t\t\t.all<{\n\t\t\t\tid: string;\n\t\t\t\tpoint_id: string;\n\t\t\t\tseries_id: string;\n\t\t\t\tmetric_name: string;\n\t\t\t\tservice_name: string | null;\n\t\t\t\ttrace_id: string | null;\n\t\t\t\tspan_id: string | null;\n\t\t\t\tts_ns: string;\n\t\t\t\tvalue: number;\n\t\t\t\treceived_at: string;\n\t\t\t}>();\n\t\treturn rows.results.map((row) => ({\n\t\t\tid: row.id,\n\t\t\tpointId: row.point_id,\n\t\t\tseriesId: row.series_id,\n\t\t\tmetricName: row.metric_name,\n\t\t\tserviceName: row.service_name,\n\t\t\ttraceId: row.trace_id,\n\t\t\tspanId: row.span_id,\n\t\t\ttsNs: row.ts_ns,\n\t\t\tvalue: row.value,\n\t\t\treceivedAt: row.received_at,\n\t\t}));\n\t}\n\n\tasync recentExemplars(opts: {\n\t\tprojectId: string;\n\t\tserviceName?: string | null;\n\t\tmetricPrefix?: string | null;\n\t\tlimit?: number;\n\t}): Promise<MetricExemplarPoint[]> {\n\t\tconst limit = Math.max(1, Math.min(opts.limit ?? 20, 100));\n\t\tconst where = [\"project_id = ?\"];\n\t\tconst binds: unknown[] = [opts.projectId];\n\t\tif (opts.serviceName) {\n\t\t\twhere.push(\"service_name = ?\");\n\t\t\tbinds.push(opts.serviceName);\n\t\t}\n\t\tif (opts.metricPrefix) {\n\t\t\twhere.push(\"metric_name LIKE ?\");\n\t\t\tbinds.push(`${opts.metricPrefix}%`);\n\t\t}\n\t\tconst rows = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT id, point_id, series_id, metric_name, service_name,\n\t\t\t\t\t\ttrace_id, span_id, ts_ns, value, received_at\n\t\t\t\t\tFROM metric_exemplars\n\t\t\t\t\tWHERE ${where.join(\" AND \")}\n\t\t\t\t\tORDER BY received_at DESC, ts_ns DESC\n\t\t\t\t\tLIMIT ?`,\n\t\t\t)\n\t\t\t.bind(...binds, limit)\n\t\t\t.all<{\n\t\t\t\tid: string;\n\t\t\t\tpoint_id: string;\n\t\t\t\tseries_id: string;\n\t\t\t\tmetric_name: string;\n\t\t\t\tservice_name: string | null;\n\t\t\t\ttrace_id: string | null;\n\t\t\t\tspan_id: string | null;\n\t\t\t\tts_ns: string;\n\t\t\t\tvalue: number;\n\t\t\t\treceived_at: string;\n\t\t\t}>();\n\t\treturn rows.results.map((row) => ({\n\t\t\tid: row.id,\n\t\t\tpointId: row.point_id,\n\t\t\tseriesId: row.series_id,\n\t\t\tmetricName: row.metric_name,\n\t\t\tserviceName: row.service_name,\n\t\t\ttraceId: row.trace_id,\n\t\t\tspanId: row.span_id,\n\t\t\ttsNs: row.ts_ns,\n\t\t\tvalue: row.value,\n\t\t\treceivedAt: row.received_at,\n\t\t}));\n\t}\n\n\t/**\n\t * Ensures a `metric_series` row exists for every unique identity in the\n\t * batch. Returns a map of identity → series row for point linking.\n\t */\n\tprivate async resolveSeries(\n\t\tprojectId: string,\n\t\tpoints: DecodedMetricPoint[],\n\t): Promise<Map<string, SeriesRow>> {\n\t\tconst byIdentity = new Map<string, DecodedMetricPoint>();\n\t\tfor (const p of points) {\n\t\t\tif (!byIdentity.has(p.identity)) byIdentity.set(p.identity, p);\n\t\t}\n\t\tconst identities = Array.from(byIdentity.keys());\n\n\t\t// Lookup existing series in one query (chunked to stay under D1's\n\t\t// ~100-param limit per statement).\n\t\tconst existing = new Map<string, SeriesRow>();\n\t\tfor (let i = 0; i < identities.length; i += 50) {\n\t\t\tconst chunk = identities.slice(i, i + 50);\n\t\t\tconst placeholders = chunk.map(() => \"?\").join(\",\");\n\t\t\tconst rows = await this.db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT id, identity FROM metric_series\n\t\t\t\t\t WHERE project_id = ? AND identity IN (${placeholders})`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...chunk)\n\t\t\t\t.all<SeriesRow>();\n\t\t\tfor (const row of rows.results) {\n\t\t\t\texisting.set(row.identity, row);\n\t\t\t}\n\t\t}\n\n\t\t// Insert missing series.\n\t\tconst insertStmt = this.db.prepare(`\n\t\t\tINSERT INTO metric_series (\n\t\t\t\tid, project_id, name, description, unit, type,\n\t\t\t\tis_monotonic, temporality, scope_name, scope_version, service_name,\n\t\t\t\tresource_attrs_json, attributes_json, identity, created_at\n\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t`);\n\t\tconst toInsert: SqlStatement[] = [];\n\t\tconst createdAt = new Date().toISOString();\n\t\tfor (const [identity, p] of byIdentity.entries()) {\n\t\t\tif (existing.has(identity)) continue;\n\t\t\tconst id = crypto.randomUUID();\n\t\t\texisting.set(identity, { id, identity });\n\t\t\ttoInsert.push(\n\t\t\t\tinsertStmt.bind(\n\t\t\t\t\tid,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tp.name,\n\t\t\t\t\tp.description,\n\t\t\t\t\tp.unit,\n\t\t\t\t\tp.type,\n\t\t\t\t\tp.isMonotonic === null ? null : p.isMonotonic ? 1 : 0,\n\t\t\t\t\tp.temporality,\n\t\t\t\t\tp.scopeName,\n\t\t\t\t\tp.scopeVersion,\n\t\t\t\t\tp.serviceName,\n\t\t\t\t\tp.resourceAttrsJson,\n\t\t\t\t\tp.attributesJson,\n\t\t\t\t\tidentity,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (toInsert.length) await this.db.batch(toInsert);\n\t\treturn existing;\n\t}\n}\n","/**\n * RFC 0004 Phase 1.8 — interaction_id propagation metric.\n *\n * Hourly aggregator: counts how many records in each signal table for\n * each project carry an interaction_id versus null over the last hour.\n * Writes 8 metric points per project per hour to metric_point as the\n * standard OTel counter `obs.interaction.propagation` with attributes\n * `(signal, propagated)`. The Health dashboard's tile (Phase 1.10\n * follow-up or RFC 0006 Connected rail consumer) reads these series and\n * surfaces the ratio per signal.\n *\n * Why aggregate via cron rather than emit per-request:\n * - The signal tables already have the data; a hourly count is two\n * indexed COUNT(*) queries per signal — sub-ms.\n * - Per-request emission adds a ~2x write amplification across every\n * ingest path. The metric is operational, not analytical, and an\n * hourly cadence is enough to surface drift.\n *\n * Series identity is stable so the cron upserts the same series rows\n * each run rather than creating new ones.\n */\n\nimport type { Logger } from \"../framework/logger\";\nimport type { DecodedMetricPoint } from \"../otlp/decode\";\nimport { MetricsStore } from \"./metrics-store\";\nimport type { SqlDb } from \"./sql-db\";\n\nconst PROPAGATION_METRIC_NAME = \"obs.interaction.propagation\";\n\ntype Signal = \"span\" | \"log\" | \"usage\" | \"ai_call\";\n\ninterface SignalQuery {\n\tsignal: Signal;\n\ttable: string;\n}\n\nconst SIGNALS: SignalQuery[] = [\n\t{ signal: \"span\", table: \"telemetry_spans\" },\n\t{ signal: \"log\", table: \"logs\" },\n\t{ signal: \"usage\", table: \"usage_events\" },\n\t{ signal: \"ai_call\", table: \"ai_calls\" },\n];\n\n/**\n * Stable identity string for the (name, attributes) tuple. Mirrors the\n * format MetricsStore writes for OTLP-ingested points so a query joining\n * on metric_series.identity gets a consistent result regardless of\n * source.\n */\nconst propagationIdentity = (signal: Signal, propagated: boolean): string =>\n\t`${PROPAGATION_METRIC_NAME}|signal=${signal}|propagated=${propagated}`;\n\nconst buildPoint = (\n\tsignal: Signal,\n\tpropagated: boolean,\n\tcount: number,\n\ttsNs: string,\n): DecodedMetricPoint => ({\n\tname: PROPAGATION_METRIC_NAME,\n\tdescription:\n\t\t\"Count of signal records ingested in the last hour, partitioned by whether they carry interaction_id (RFC 0004).\",\n\tunit: \"{records}\",\n\ttype: \"sum\",\n\tisMonotonic: false, // delta over a one-hour window, not cumulative\n\ttemporality: 1, // DELTA\n\tscopeName: \"obs.collector\",\n\tscopeVersion: \"1\",\n\tserviceName: \"obs-collector\",\n\tresourceAttrsJson: null,\n\tattributesJson: JSON.stringify({ signal, propagated }),\n\tidentity: propagationIdentity(signal, propagated),\n\ttsNs,\n\tstartTsNs: null,\n\tvalue: count,\n\tcount: null,\n\tsum: null,\n\tmin: null,\n\tmax: null,\n\tboundsJson: null,\n\tbucketCountsJson: null,\n\textraJson: null,\n\texemplarsJson: null,\n});\n\nconst countsForSignal = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\ttable: string,\n\thourCutoffIso: string,\n): Promise<{ propagated: number; missing: number }> => {\n\tconst row = await db\n\t\t.prepare(\n\t\t\t`SELECT\n\t\t\t SUM(CASE WHEN interaction_id IS NOT NULL THEN 1 ELSE 0 END) AS propagated,\n\t\t\t SUM(CASE WHEN interaction_id IS NULL THEN 1 ELSE 0 END) AS missing\n\t\t\tFROM ${table}\n\t\t\tWHERE project_id = ? AND received_at >= ?`,\n\t\t)\n\t\t.bind(projectId, hourCutoffIso)\n\t\t.first<{ propagated: number | null; missing: number | null }>();\n\treturn {\n\t\tpropagated: row?.propagated ?? 0,\n\t\tmissing: row?.missing ?? 0,\n\t};\n};\n\n/**\n * Aggregate propagation counts for a single project and write them as\n * metric points. Idempotent per hour-bucket (each run produces a new\n * point; series identity stays stable).\n */\nexport const aggregatePropagationForProject = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tnow: Date,\n\tlogger?: Logger,\n): Promise<{ pointsWritten: number }> => {\n\tconst hourCutoff = new Date(now.getTime() - 60 * 60 * 1000).toISOString();\n\tconst tsNs = (BigInt(now.getTime()) * 1_000_000n).toString();\n\tconst points: DecodedMetricPoint[] = [];\n\n\tfor (const { signal, table } of SIGNALS) {\n\t\ttry {\n\t\t\tconst { propagated, missing } = await countsForSignal(\n\t\t\t\tdb,\n\t\t\t\tprojectId,\n\t\t\t\ttable,\n\t\t\t\thourCutoff,\n\t\t\t);\n\t\t\tpoints.push(buildPoint(signal, true, propagated, tsNs));\n\t\t\tpoints.push(buildPoint(signal, false, missing, tsNs));\n\t\t} catch (err) {\n\t\t\tlogger?.error(\"[propagation-metric] count failed\", {\n\t\t\t\tsignal,\n\t\t\t\ttable,\n\t\t\t\tprojectId,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t}\n\t}\n\n\tif (points.length === 0) return { pointsWritten: 0 };\n\n\tconst store = new MetricsStore(db);\n\tawait store.ingestBatch({\n\t\tprojectId,\n\t\tpoints,\n\t\treceivedAt: now.toISOString(),\n\t\t// Keep propagation metrics on the same retention as everything else.\n\t\texpiresAt: new Date(now.getTime() + 72 * 60 * 60 * 1000).toISOString(),\n\t});\n\n\treturn { pointsWritten: points.length };\n};\n\n/**\n * Run the aggregation across all known projects. Designed for a once-per-hour\n * cron handler; cheap enough to run alongside retention cleanup.\n */\nexport const aggregatePropagation = async (\n\tdb: SqlDb,\n\tnow: Date,\n\tlogger?: Logger,\n): Promise<{ projects: number; pointsWritten: number }> => {\n\tconst projects = await db\n\t\t.prepare(\"SELECT id FROM projects\")\n\t\t.all<{ id: string }>();\n\n\tlet pointsWritten = 0;\n\tfor (const p of projects.results) {\n\t\tconst r = await aggregatePropagationForProject(db, p.id, now, logger);\n\t\tpointsWritten += r.pointsWritten;\n\t}\n\treturn { projects: projects.results.length, pointsWritten };\n};\n","import type {\n\tJsonValue,\n\tStoredSpan,\n\tTelemetryIssueCategory,\n\tTelemetryIssueOptions,\n\tTelemetryIssueSeverity,\n\tTelemetryIssueSpanSummary,\n\tTelemetryIssueSummary,\n} from \"@obsunified/types\";\nimport { parseJsonArray, parseJsonRecord } from \"../json\";\n\n/** Map D1 snake_case row to camelCase StoredSpan */\nexport const rowToSpan = (row: Record<string, unknown>): StoredSpan => ({\n\tprojectId: (row.project_id as string) ?? \"default\",\n\ttraceId: row.trace_id as string,\n\tspanId: row.span_id as string,\n\tparentSpanId: (row.parent_span_id as string) ?? null,\n\ttraceState: (row.trace_state as string) ?? null,\n\tserviceName: (row.service_name as string) ?? null,\n\tscopeName: (row.scope_name as string) ?? null,\n\tscopeVersion: (row.scope_version as string) ?? null,\n\tspanName: row.span_name as string,\n\tspanKind: (row.span_kind as number) ?? 0,\n\tstatusCode: (row.status_code as number) ?? 0,\n\tstatusMessage: (row.status_message as string) ?? null,\n\tstartTime: row.start_time as string,\n\tendTime: row.end_time as string,\n\tdurationMs: (row.duration_ms as number) ?? 0,\n\tattributesJson: (row.attributes_json as string) ?? \"{}\",\n\tdroppedAttributesCount: (row.dropped_attributes_count as number) ?? 0,\n\tresourceAttributesJson: (row.resource_attributes_json as string) ?? \"{}\",\n\teventsJson: (row.events_json as string) ?? \"[]\",\n\tdroppedEventsCount: (row.dropped_events_count as number) ?? 0,\n\tlinksJson: (row.links_json as string) ?? \"[]\",\n\tdroppedLinksCount: (row.dropped_links_count as number) ?? 0,\n\treceivedAt: row.received_at as string,\n\texpiresAt: row.expires_at as string,\n});\n\nexport type NormalizedIssue = TelemetryIssueSummary & {\n\ttraces: Array<{\n\t\ttraceId: string;\n\t\tserviceName: string;\n\t\trouteLabel: string;\n\t\tstartTime: string;\n\t\tdurationMs: number;\n\t\tstatusCode: number;\n\t\tstatusMessage: string | null;\n\t\trootSpanName: string;\n\t\tculpritSpanName: string;\n\t\tdependencyTarget: string | null;\n\t}>;\n\tculpritSpans: TelemetryIssueSpanSummary[];\n};\n\nexport type ParsedSpan = StoredSpan & {\n\tattributes: Record<string, JsonValue>;\n\tresourceAttributes: Record<string, JsonValue>;\n\tevents: unknown[];\n\tlinks: unknown[];\n};\n\nexport interface TraceCandidateRow {\n\ttrace_id: string;\n\tlatest_received_at: string;\n\terror_span_count: number;\n}\n\n// ── Helpers ──\n\nexport const cutoffIso = (hours: number): string =>\n\tnew Date(Date.now() - hours * 60 * 60 * 1000).toISOString();\n\nexport const percentile = (values: number[], fraction: number): number => {\n\tif (values.length === 0) return 0;\n\tconst sorted = [...values].sort((left, right) => left - right);\n\tconst index = Math.min(\n\t\tsorted.length - 1,\n\t\tMath.max(0, Math.ceil(sorted.length * fraction) - 1),\n\t);\n\treturn sorted[index];\n};\n\nexport const average = (values: number[]): number =>\n\tvalues.length > 0\n\t\t? values.reduce((sum, value) => sum + value, 0) / values.length\n\t\t: 0;\n\nexport const normalizeService = (value: string | null | undefined): string =>\n\tvalue?.trim() || \"unknown\";\n\nexport const toParsedSpan = (row: StoredSpan): ParsedSpan => ({\n\t...row,\n\tattributes: parseJsonRecord(row.attributesJson),\n\tresourceAttributes: parseJsonRecord(row.resourceAttributesJson),\n\tevents: parseJsonArray(row.eventsJson),\n\tlinks: parseJsonArray(row.linksJson),\n});\n\nexport const spanSelectColumns = `\n\tproject_id, trace_id, span_id, parent_span_id, service_name, scope_name,\n\tscope_version, span_name, span_kind, status_code, status_message,\n\tstart_time, end_time, duration_ms, attributes_json,\n\tresource_attributes_json, events_json, links_json,\n\treceived_at, expires_at\n`;\n\nexport const placeholders = (count: number): string =>\n\tArray.from({ length: count }, () => \"?\").join(\",\");\n\nexport const getRouteLabel = (span: ParsedSpan): string => {\n\tconst collectorRoute = span.attributes[\"collector.route_label\"];\n\tif (typeof collectorRoute === \"string\" && collectorRoute.trim())\n\t\treturn collectorRoute.trim();\n\tconst method = span.attributes[\"http.request.method\"];\n\tconst path = span.attributes[\"url.path\"];\n\tif (typeof method === \"string\" && typeof path === \"string\")\n\t\treturn `${method} ${path}`;\n\treturn span.spanName;\n};\n\nexport const isInternalTrace = (span: ParsedSpan): boolean =>\n\tspan.attributes[\"collector.is_internal\"] === true;\n\nexport const getDependencyTarget = (span: ParsedSpan): string | null => {\n\tconst collectorTarget = span.attributes[\"collector.dependency_target\"];\n\tif (typeof collectorTarget === \"string\" && collectorTarget.trim())\n\t\treturn collectorTarget.trim();\n\treturn null;\n};\n\nexport const getSeverity = (\n\tcategory: TelemetryIssueCategory,\n\tcount: number,\n\tdurationMs: number,\n\tstatusCode: number,\n): TelemetryIssueSeverity => {\n\tif (category === \"error\" && (count >= 10 || statusCode === 2))\n\t\treturn \"critical\";\n\tif (category === \"dependency\" && (statusCode === 2 || durationMs >= 2_000))\n\t\treturn \"high\";\n\tif (durationMs >= 3_000 || count >= 5) return \"high\";\n\tif (durationMs >= 1_000 || count >= 2) return \"medium\";\n\treturn \"low\";\n};\n\nexport const buildIssueTitle = (\n\tcategory: TelemetryIssueCategory,\n\trouteLabel: string,\n\tdependencyTarget: string | null,\n): string => {\n\tswitch (category) {\n\t\tcase \"error\":\n\t\t\treturn `Errors on ${routeLabel}`;\n\t\tcase \"dependency\":\n\t\t\treturn dependencyTarget\n\t\t\t\t? `Dependency failures talking to ${dependencyTarget}`\n\t\t\t\t: `Dependency failures on ${routeLabel}`;\n\t\tcase \"latency\":\n\t\t\treturn `Latency spike on ${routeLabel}`;\n\t}\n};\n\nexport const buildIssueId = (\n\tcategory: TelemetryIssueCategory,\n\tserviceName: string,\n\trouteLabel: string,\n\tculpritSpanName: string,\n\tdependencyTarget: string | null,\n): string =>\n\t[\n\t\tcategory,\n\t\tserviceName,\n\t\trouteLabel,\n\t\tculpritSpanName,\n\t\tdependencyTarget ?? \"\",\n\t].join(\"|\");\n\nexport const groupIssues = (\n\tspans: ParsedSpan[],\n\toptions: TelemetryIssueOptions,\n): NormalizedIssue[] => {\n\tconst traces = new Map<string, ParsedSpan[]>();\n\tfor (const span of spans) {\n\t\tconst traceSpans = traces.get(span.traceId) ?? [];\n\t\ttraceSpans.push(span);\n\t\ttraces.set(span.traceId, traceSpans);\n\t}\n\n\tconst grouped = new Map<\n\t\tstring,\n\t\t{\n\t\t\tcategory: TelemetryIssueCategory;\n\t\t\tserviceName: string;\n\t\t\trouteLabel: string;\n\t\t\tdependencyTarget: string | null;\n\t\t\tculpritSpanName: string;\n\t\t\ttitle: string;\n\t\t\ttraces: NormalizedIssue[\"traces\"];\n\t\t}\n\t>();\n\n\tfor (const traceSpans of traces.values()) {\n\t\tconst sorted = [...traceSpans].sort((left, right) =>\n\t\t\tleft.startTime.localeCompare(right.startTime),\n\t\t);\n\t\tconst root = sorted.find((span) => !span.parentSpanId) ?? sorted[0];\n\t\tif (!options.includeInternal && isInternalTrace(root)) continue;\n\n\t\tconst serviceName = normalizeService(root.serviceName);\n\t\tif (options.service && options.service !== serviceName) continue;\n\n\t\tconst routeLabel = getRouteLabel(root);\n\t\tconst errorSpan = sorted.find((span) => span.statusCode === 2);\n\t\tconst dependencySpan = sorted.find(\n\t\t\t(span) =>\n\t\t\t\tspan.attributes[\"collector.span_role\"] === \"dependency\" &&\n\t\t\t\t(span.statusCode === 2 || span.durationMs >= 1_000),\n\t\t);\n\n\t\tconst candidates: Array<{\n\t\t\tcategory: TelemetryIssueCategory;\n\t\t\tculprit: ParsedSpan;\n\t\t\tdependencyTarget: string | null;\n\t\t}> = [];\n\n\t\tif (errorSpan) {\n\t\t\tcandidates.push({\n\t\t\t\tcategory: \"error\",\n\t\t\t\tculprit: errorSpan,\n\t\t\t\tdependencyTarget: getDependencyTarget(errorSpan),\n\t\t\t});\n\t\t}\n\t\tif (dependencySpan) {\n\t\t\tcandidates.push({\n\t\t\t\tcategory: \"dependency\",\n\t\t\t\tculprit: dependencySpan,\n\t\t\t\tdependencyTarget: getDependencyTarget(dependencySpan),\n\t\t\t});\n\t\t}\n\t\tif (root.durationMs >= 1_000) {\n\t\t\tcandidates.push({\n\t\t\t\tcategory: \"latency\",\n\t\t\t\tculprit: dependencySpan ?? root,\n\t\t\t\tdependencyTarget: dependencySpan\n\t\t\t\t\t? getDependencyTarget(dependencySpan)\n\t\t\t\t\t: null,\n\t\t\t});\n\t\t}\n\n\t\tfor (const candidate of candidates) {\n\t\t\tif (\n\t\t\t\toptions.category &&\n\t\t\t\toptions.category !== \"all\" &&\n\t\t\t\tcandidate.category !== options.category\n\t\t\t)\n\t\t\t\tcontinue;\n\n\t\t\tconst issueId = buildIssueId(\n\t\t\t\tcandidate.category,\n\t\t\t\tserviceName,\n\t\t\t\trouteLabel,\n\t\t\t\tcandidate.culprit.spanName,\n\t\t\t\tcandidate.dependencyTarget,\n\t\t\t);\n\t\t\tconst entry = grouped.get(issueId) ?? {\n\t\t\t\tcategory: candidate.category,\n\t\t\t\tserviceName,\n\t\t\t\trouteLabel,\n\t\t\t\tdependencyTarget: candidate.dependencyTarget,\n\t\t\t\tculpritSpanName: candidate.culprit.spanName,\n\t\t\t\ttitle: buildIssueTitle(\n\t\t\t\t\tcandidate.category,\n\t\t\t\t\trouteLabel,\n\t\t\t\t\tcandidate.dependencyTarget,\n\t\t\t\t),\n\t\t\t\ttraces: [],\n\t\t\t};\n\n\t\t\tentry.traces.push({\n\t\t\t\ttraceId: root.traceId,\n\t\t\t\tserviceName,\n\t\t\t\trouteLabel,\n\t\t\t\tstartTime: root.startTime,\n\t\t\t\tdurationMs: root.durationMs,\n\t\t\t\tstatusCode: root.statusCode,\n\t\t\t\tstatusMessage: root.statusMessage,\n\t\t\t\trootSpanName: root.spanName,\n\t\t\t\tculpritSpanName: candidate.culprit.spanName,\n\t\t\t\tdependencyTarget: candidate.dependencyTarget,\n\t\t\t});\n\t\t\tgrouped.set(issueId, entry);\n\t\t}\n\t}\n\n\treturn Array.from(grouped.entries()).map(\n\t\t([issueId, entry]): NormalizedIssue => {\n\t\t\tconst occurrenceCount = entry.traces.length;\n\t\t\tconst durations = entry.traces.map((trace) => trace.durationMs);\n\t\t\tconst latest = [...entry.traces].sort((left, right) =>\n\t\t\t\tright.startTime.localeCompare(left.startTime),\n\t\t\t)[0];\n\t\t\tconst culpritCounts = new Map<string, TelemetryIssueSpanSummary>();\n\n\t\t\tfor (const trace of entry.traces) {\n\t\t\t\tconst culpritKey = `${trace.culpritSpanName}|${trace.dependencyTarget ?? \"\"}|${trace.statusCode}`;\n\t\t\t\tconst existing = culpritCounts.get(culpritKey) ?? {\n\t\t\t\t\tspanName: trace.culpritSpanName,\n\t\t\t\t\tdependencyTarget: trace.dependencyTarget,\n\t\t\t\t\tstatusCode: trace.statusCode,\n\t\t\t\t\toccurrenceCount: 0,\n\t\t\t\t\taverageDurationMs: 0,\n\t\t\t\t\tmaxDurationMs: 0,\n\t\t\t\t};\n\t\t\t\texisting.occurrenceCount += 1;\n\t\t\t\texisting.averageDurationMs += trace.durationMs;\n\t\t\t\texisting.maxDurationMs = Math.max(\n\t\t\t\t\texisting.maxDurationMs,\n\t\t\t\t\ttrace.durationMs,\n\t\t\t\t);\n\t\t\t\tculpritCounts.set(culpritKey, existing);\n\t\t\t}\n\n\t\t\tfor (const culprit of culpritCounts.values()) {\n\t\t\t\tculprit.averageDurationMs = Math.round(\n\t\t\t\t\tculprit.averageDurationMs / culprit.occurrenceCount,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tissueId,\n\t\t\t\tcategory: entry.category,\n\t\t\t\tseverity: getSeverity(\n\t\t\t\t\tentry.category,\n\t\t\t\t\toccurrenceCount,\n\t\t\t\t\taverage(durations),\n\t\t\t\t\tlatest.statusCode,\n\t\t\t\t),\n\t\t\t\ttitle: entry.title,\n\t\t\t\tserviceName: entry.serviceName,\n\t\t\t\trouteLabel: entry.routeLabel,\n\t\t\t\toccurrenceCount,\n\t\t\t\taffectedTraceCount: new Set(entry.traces.map((trace) => trace.traceId))\n\t\t\t\t\t.size,\n\t\t\t\tfirstSeen:\n\t\t\t\t\t[...entry.traces].sort((left, right) =>\n\t\t\t\t\t\tleft.startTime.localeCompare(right.startTime),\n\t\t\t\t\t)[0]?.startTime ?? latest.startTime,\n\t\t\t\tlastSeen: latest.startTime,\n\t\t\t\tlatestStatusMessage: latest.statusMessage,\n\t\t\t\tculpritSpanName: entry.culpritSpanName,\n\t\t\t\tdependencyTarget: entry.dependencyTarget,\n\t\t\t\taverageDurationMs: Math.round(average(durations)),\n\t\t\t\tmaxDurationMs: Math.max(...durations, 0),\n\t\t\t\tsampleTraceId: latest.traceId,\n\t\t\t\ttraces: entry.traces\n\t\t\t\t\t.sort((left, right) => right.startTime.localeCompare(left.startTime))\n\t\t\t\t\t.slice(0, 20),\n\t\t\t\tculpritSpans: Array.from(culpritCounts.values()).sort(\n\t\t\t\t\t(left, right) =>\n\t\t\t\t\t\tright.occurrenceCount - left.occurrenceCount ||\n\t\t\t\t\t\tleft.spanName.localeCompare(right.spanName),\n\t\t\t\t),\n\t\t\t};\n\t\t},\n\t);\n};\n","import type { TelemetryOverviewOptions } from \"@obsunified/types\";\nimport type { SqlDb } from \"../sql-db\";\nimport { cutoffIso } from \"./helpers\";\n\nexport async function getTelemetryExportRows(\n\tdb: SqlDb,\n\toptions: TelemetryOverviewOptions,\n): Promise<string> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"TelemetryStore.getExportRows: projectId is required\");\n\tconst cutoff = cutoffIso(options.hours);\n\tconst now = new Date().toISOString();\n\tlet whereClause =\n\t\t\"WHERE project_id = ? AND received_at > ? AND expires_at > ?\";\n\tconst params: unknown[] = [options.projectId, cutoff, now];\n\n\tif (options.service) {\n\t\twhereClause += \" AND service_name = ?\";\n\t\tparams.push(options.service);\n\t}\n\tif (options.status === \"error\") {\n\t\twhereClause += \" AND status_code = 2\";\n\t} else if (options.status === \"ok\") {\n\t\twhereClause += \" AND status_code != 2\";\n\t}\n\tif (options.search) {\n\t\tconst term = `%${options.search}%`;\n\t\twhereClause +=\n\t\t\t\" AND (span_name LIKE ? OR status_message LIKE ? OR attributes_json LIKE ? OR events_json LIKE ?)\";\n\t\tparams.push(term, term, term, term);\n\t}\n\n\tconst rows = await db\n\t\t.prepare(`\n SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n status_code, status_message, start_time, end_time, duration_ms,\n attributes_json, events_json, received_at\n FROM telemetry_spans\n ${whereClause}\n ORDER BY received_at DESC\n LIMIT 1000\n `)\n\t\t.bind(...params)\n\t\t.all<Record<string, unknown>>();\n\n\treturn (rows.results || [])\n\t\t.map((row) =>\n\t\t\tJSON.stringify({\n\t\t\t\ttrace_id: row.trace_id,\n\t\t\t\tspan_id: row.span_id,\n\t\t\t\tparent_span_id: row.parent_span_id,\n\t\t\t\tservice: row.service_name,\n\t\t\t\tspan_name: row.span_name,\n\t\t\t\tstatus_code: row.status_code,\n\t\t\t\tstatus_message: row.status_message,\n\t\t\t\tstart_time: row.start_time,\n\t\t\t\tend_time: row.end_time,\n\t\t\t\tduration_ms: row.duration_ms,\n\t\t\t\tattributes: JSON.parse((row.attributes_json as string) || \"{}\"),\n\t\t\t\tevents: JSON.parse((row.events_json as string) || \"[]\"),\n\t\t\t\treceived_at: row.received_at,\n\t\t\t}),\n\t\t)\n\t\t.join(\"\\n\");\n}\n","import type { StoredSpan } from \"@obsunified/types\";\nimport type { SqlDb } from \"../sql-db\";\n\nexport async function ingestTelemetrySpans(\n\tdb: SqlDb,\n\tspans: StoredSpan[],\n): Promise<{ inserted: number; traceCount: number }> {\n\tif (spans.length === 0) return { inserted: 0, traceCount: 0 };\n\n\tconst statements = spans.map((span) => {\n\t\tif (!span.projectId)\n\t\t\tthrow new Error(\"TelemetryStore.ingest: span.projectId is required\");\n\t\treturn db\n\t\t\t.prepare(`\n INSERT OR IGNORE INTO telemetry_spans (\n project_id, trace_id, span_id, parent_span_id, trace_state,\n service_name, scope_name, scope_version, span_name, span_kind,\n status_code, status_message, start_time, end_time, duration_ms,\n attributes_json, dropped_attributes_count,\n resource_attributes_json, events_json, dropped_events_count,\n links_json, dropped_links_count, received_at, expires_at,\n session_id, interaction_id, telemetry_sdk_name\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\t\t\t.bind(\n\t\t\t\tspan.projectId,\n\t\t\t\tspan.traceId,\n\t\t\t\tspan.spanId,\n\t\t\t\tspan.parentSpanId,\n\t\t\t\tspan.traceState,\n\t\t\t\tspan.serviceName,\n\t\t\t\tspan.scopeName,\n\t\t\t\tspan.scopeVersion,\n\t\t\t\tspan.spanName,\n\t\t\t\tspan.spanKind,\n\t\t\t\tspan.statusCode,\n\t\t\t\tspan.statusMessage,\n\t\t\t\tspan.startTime,\n\t\t\t\tspan.endTime,\n\t\t\t\tspan.durationMs,\n\t\t\t\tspan.attributesJson,\n\t\t\t\tspan.droppedAttributesCount,\n\t\t\t\tspan.resourceAttributesJson,\n\t\t\t\tspan.eventsJson,\n\t\t\t\tspan.droppedEventsCount,\n\t\t\t\tspan.linksJson,\n\t\t\t\tspan.droppedLinksCount,\n\t\t\t\tspan.receivedAt,\n\t\t\t\tspan.expiresAt,\n\t\t\t\tspan.sessionId ?? null,\n\t\t\t\tspan.interactionId ?? null,\n\t\t\t\tspan.telemetrySdkName ?? null,\n\t\t\t);\n\t});\n\n\tawait db.batch(statements);\n\n\t// Trace instrumentation gaps are computed lazily at read time (see\n\t// `getTelemetryTraceGaps`), not materialized on ingest. This keeps the\n\t// ingest hot path to a single batched span write and avoids recomputing\n\t// gaps for the >99% of traces that are never inspected.\n\tconst uniqueTraces = new Set(spans.map((s) => `${s.projectId}:${s.traceId}`));\n\n\treturn {\n\t\tinserted: spans.length,\n\t\ttraceCount: uniqueTraces.size,\n\t};\n}\n","import type { SqlDb } from \"../sql-db\";\nimport {\n\ttype ParsedSpan,\n\tplaceholders,\n\trowToSpan,\n\tspanSelectColumns,\n\ttype TraceCandidateRow,\n\ttoParsedSpan,\n} from \"./helpers\";\n\nconst MAX_TRACE_ID_BINDINGS = 99;\n\nexport interface TraceCandidateOptions {\n\tprojectId: string;\n\tcutoff: string;\n\tservice?: string;\n\tsearch?: string;\n\tstatus?: \"all\" | \"error\" | \"ok\";\n\tlimit: number;\n}\n\nexport async function selectTraceCandidates(\n\tdb: SqlDb,\n\toptions: TraceCandidateOptions,\n): Promise<TraceCandidateRow[]> {\n\tlet whereClause = \"WHERE project_id = ? AND received_at >= ?\";\n\tconst binds: unknown[] = [options.projectId, options.cutoff];\n\n\tif (options.service) {\n\t\twhereClause += \" AND service_name = ?\";\n\t\tbinds.push(options.service);\n\t}\n\tif (options.search) {\n\t\tconst term = `%${options.search}%`;\n\t\twhereClause +=\n\t\t\t\" AND (span_name LIKE ? OR status_message LIKE ? OR attributes_json LIKE ? OR events_json LIKE ?)\";\n\t\tbinds.push(term, term, term, term);\n\t}\n\n\tconst having =\n\t\toptions.status === \"error\"\n\t\t\t? \"HAVING SUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) > 0\"\n\t\t\t: options.status === \"ok\"\n\t\t\t\t? \"HAVING SUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) = 0\"\n\t\t\t\t: \"\";\n\n\tconst result = await db\n\t\t.prepare(`\n\t\t\t\tSELECT\n\t\t\t\t\ttrace_id,\n\t\t\t\t\tMAX(received_at) AS latest_received_at,\n\t\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS error_span_count\n\t\t\t\tFROM telemetry_spans\n\t\t\t\t${whereClause}\n\t\t\t\tGROUP BY trace_id\n\t\t\t\t${having}\n\t\t\t\tORDER BY latest_received_at DESC\n\t\t\t\tLIMIT ?\n\t\t\t`)\n\t\t.bind(...binds, options.limit)\n\t\t.all<TraceCandidateRow>();\n\n\treturn result.results ?? [];\n}\n\nexport async function fetchSpansForTraceIds(\n\tdb: SqlDb,\n\tprojectId: string,\n\ttraceIds: string[],\n): Promise<ParsedSpan[]> {\n\tif (traceIds.length === 0) return [];\n\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (let i = 0; i < traceIds.length; i += MAX_TRACE_ID_BINDINGS) {\n\t\tconst chunk = traceIds.slice(i, i + MAX_TRACE_ID_BINDINGS);\n\t\tconst result = await db\n\t\t\t.prepare(`\n\t\t\t\tSELECT ${spanSelectColumns}\n\t\t\t\tFROM telemetry_spans\n\t\t\t\tWHERE project_id = ? AND trace_id IN (${placeholders(chunk.length)})\n\t\t\t\tORDER BY received_at DESC, start_time ASC, span_id ASC\n\t\t\t`)\n\t\t\t.bind(projectId, ...chunk)\n\t\t\t.all<Record<string, unknown>>();\n\t\trows.push(...(result.results ?? []));\n\t}\n\n\treturn rows.map(rowToSpan).map(toParsedSpan);\n}\n","import type {\n\tTelemetryIssueDetailResponse,\n\tTelemetryIssueOptions,\n\tTelemetryIssueOverviewResponse,\n} from \"@obsunified/types\";\nimport type { SqlDb } from \"../sql-db\";\nimport { cutoffIso, groupIssues } from \"./helpers\";\nimport { fetchSpansForTraceIds, selectTraceCandidates } from \"./trace-queries\";\n\nexport async function getTelemetryIssueOverview(\n\tdb: SqlDb,\n\toptions: TelemetryIssueOptions,\n): Promise<TelemetryIssueOverviewResponse> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"TelemetryStore.getIssueOverview: projectId is required\");\n\tconst cutoff = cutoffIso(options.hours);\n\tconst issueLimit = options.limit ?? 50;\n\tconst candidateLimit = Math.min(issueLimit * 10, 500);\n\tconst candidates = await selectTraceCandidates(db, {\n\t\tprojectId: options.projectId,\n\t\tcutoff,\n\t\tservice: options.service,\n\t\tlimit: candidateLimit,\n\t});\n\tconst spans = await fetchSpansForTraceIds(\n\t\tdb,\n\t\toptions.projectId,\n\t\tcandidates.map((candidate) => candidate.trace_id),\n\t);\n\n\tconst issues = groupIssues(spans, options)\n\t\t.sort(\n\t\t\t(left, right) =>\n\t\t\t\tright.occurrenceCount - left.occurrenceCount ||\n\t\t\t\tright.lastSeen.localeCompare(left.lastSeen),\n\t\t)\n\t\t.slice(0, options.limit ?? 50);\n\n\tconst services = new Map<\n\t\tstring,\n\t\t{\n\t\t\tissueCount: number;\n\t\t\taffectedTraces: Set<string>;\n\t\t\terror: number;\n\t\t\tlatency: number;\n\t\t\tdependency: number;\n\t\t}\n\t>();\n\n\tfor (const issue of issues) {\n\t\tconst entry = services.get(issue.serviceName) ?? {\n\t\t\tissueCount: 0,\n\t\t\taffectedTraces: new Set<string>(),\n\t\t\terror: 0,\n\t\t\tlatency: 0,\n\t\t\tdependency: 0,\n\t\t};\n\t\tentry.issueCount += 1;\n\t\tfor (const trace of issue.traces) {\n\t\t\tentry.affectedTraces.add(trace.traceId);\n\t\t}\n\t\tentry[issue.category] += 1;\n\t\tservices.set(issue.serviceName, entry);\n\t}\n\n\treturn {\n\t\tsummary: {\n\t\t\ttotalIssues: issues.length,\n\t\t\tcriticalIssues: issues.filter((issue) => issue.severity === \"critical\")\n\t\t\t\t.length,\n\t\t\thighIssues: issues.filter((issue) => issue.severity === \"high\").length,\n\t\t\taffectedTraces: new Set(\n\t\t\t\tissues.flatMap((issue) => issue.traces.map((trace) => trace.traceId)),\n\t\t\t).size,\n\t\t\terrorIssues: issues.filter((issue) => issue.category === \"error\").length,\n\t\t\tlatencyIssues: issues.filter((issue) => issue.category === \"latency\")\n\t\t\t\t.length,\n\t\t\tdependencyIssues: issues.filter(\n\t\t\t\t(issue) => issue.category === \"dependency\",\n\t\t\t).length,\n\t\t},\n\t\tservices: Array.from(services.entries())\n\t\t\t.map(([serviceName, entry]) => ({\n\t\t\t\tserviceName,\n\t\t\t\tissueCount: entry.issueCount,\n\t\t\t\taffectedTraceCount: entry.affectedTraces.size,\n\t\t\t\terrorIssueCount: entry.error,\n\t\t\t\tlatencyIssueCount: entry.latency,\n\t\t\t\tdependencyIssueCount: entry.dependency,\n\t\t\t}))\n\t\t\t.sort(\n\t\t\t\t(left, right) =>\n\t\t\t\t\tright.issueCount - left.issueCount ||\n\t\t\t\t\tleft.serviceName.localeCompare(right.serviceName),\n\t\t\t),\n\t\tissues: issues.map(\n\t\t\t({ traces: _t, culpritSpans: _c, ...summary }) => summary,\n\t\t),\n\t\twindowHours: options.hours,\n\t\tfilters: {\n\t\t\tservice: options.service ?? \"all\",\n\t\t\tcategory: options.category ?? \"all\",\n\t\t\tincludeInternal: options.includeInternal ?? false,\n\t\t},\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n\nexport async function getTelemetryIssueDetail(\n\tdb: SqlDb,\n\tissueId: string,\n\toptions: TelemetryIssueOptions,\n): Promise<TelemetryIssueDetailResponse | null> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"TelemetryStore.getIssueDetail: projectId is required\");\n\tconst cutoff = cutoffIso(options.hours);\n\tconst candidates = await selectTraceCandidates(db, {\n\t\tprojectId: options.projectId,\n\t\tcutoff,\n\t\tservice: options.service,\n\t\tlimit: 500,\n\t});\n\tconst spans = await fetchSpansForTraceIds(\n\t\tdb,\n\t\toptions.projectId,\n\t\tcandidates.map((candidate) => candidate.trace_id),\n\t);\n\n\tconst issue = groupIssues(spans, options).find(\n\t\t(candidate) => candidate.issueId === issueId,\n\t);\n\n\tif (!issue) return null;\n\n\treturn {\n\t\tissue: {\n\t\t\tissueId: issue.issueId,\n\t\t\tcategory: issue.category,\n\t\t\tseverity: issue.severity,\n\t\t\ttitle: issue.title,\n\t\t\tserviceName: issue.serviceName,\n\t\t\trouteLabel: issue.routeLabel,\n\t\t\toccurrenceCount: issue.occurrenceCount,\n\t\t\taffectedTraceCount: issue.affectedTraceCount,\n\t\t\tfirstSeen: issue.firstSeen,\n\t\t\tlastSeen: issue.lastSeen,\n\t\t\tlatestStatusMessage: issue.latestStatusMessage,\n\t\t\tculpritSpanName: issue.culpritSpanName,\n\t\t\tdependencyTarget: issue.dependencyTarget,\n\t\t\taverageDurationMs: issue.averageDurationMs,\n\t\t\tmaxDurationMs: issue.maxDurationMs,\n\t\t\tsampleTraceId: issue.sampleTraceId,\n\t\t},\n\t\ttraces: issue.traces,\n\t\tculpritSpans: issue.culpritSpans,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n","import type {\n\tTelemetryOverviewOptions,\n\tTelemetryOverviewResponse,\n} from \"@obsunified/types\";\nimport type { SqlDb } from \"../sql-db\";\nimport {\n\taverage,\n\tcutoffIso,\n\tnormalizeService,\n\ttype ParsedSpan,\n\tpercentile,\n} from \"./helpers\";\nimport { fetchSpansForTraceIds, selectTraceCandidates } from \"./trace-queries\";\n\nexport async function getTelemetryOverview(\n\tdb: SqlDb,\n\toptions: TelemetryOverviewOptions,\n): Promise<TelemetryOverviewResponse> {\n\tif (!options.projectId)\n\t\tthrow new Error(\"TelemetryStore.getOverview: projectId is required\");\n\tconst cutoff = cutoffIso(options.hours);\n\tconst traceLimit = options.limit ?? 30;\n\tconst candidates = await selectTraceCandidates(db, {\n\t\tprojectId: options.projectId,\n\t\tcutoff,\n\t\tservice: options.service,\n\t\tsearch: options.search,\n\t\tstatus: options.status,\n\t\tlimit: traceLimit,\n\t});\n\tconst candidateOrder = new Map(\n\t\tcandidates.map((candidate, index) => [candidate.trace_id, index]),\n\t);\n\tconst grouped = new Map<string, ParsedSpan[]>();\n\tfor (const parsed of await fetchSpansForTraceIds(\n\t\tdb,\n\t\toptions.projectId,\n\t\tcandidates.map((candidate) => candidate.trace_id),\n\t)) {\n\t\tconst traceSpans = grouped.get(parsed.traceId) ?? [];\n\t\ttraceSpans.push(parsed);\n\t\tgrouped.set(parsed.traceId, traceSpans);\n\t}\n\n\tconst traces = Array.from(grouped.values())\n\t\t.map((traceSpans) => {\n\t\t\tconst sorted = traceSpans.sort((left, right) =>\n\t\t\t\tleft.startTime.localeCompare(right.startTime),\n\t\t\t);\n\t\t\tconst root = sorted.find((span) => !span.parentSpanId) ?? sorted[0];\n\t\t\treturn {\n\t\t\t\ttraceId: root.traceId,\n\t\t\t\tserviceName: normalizeService(root.serviceName),\n\t\t\t\tspanName: root.spanName,\n\t\t\t\tstatusCode: traceSpans.some((span) => span.statusCode === 2)\n\t\t\t\t\t? 2\n\t\t\t\t\t: root.statusCode,\n\t\t\t\tstatusMessage:\n\t\t\t\t\ttraceSpans.find((span) => span.statusCode === 2)?.statusMessage ??\n\t\t\t\t\troot.statusMessage,\n\t\t\t\tstartTime: root.startTime,\n\t\t\t\tendTime: root.endTime,\n\t\t\t\tdurationMs: root.durationMs,\n\t\t\t\treceivedAt: root.receivedAt,\n\t\t\t\tspanCount: traceSpans.length,\n\t\t\t\terrorSpanCount: traceSpans.filter((span) => span.statusCode === 2)\n\t\t\t\t\t.length,\n\t\t\t};\n\t\t})\n\t\t.sort((left, right) => right.receivedAt.localeCompare(left.receivedAt));\n\ttraces.sort(\n\t\t(left, right) =>\n\t\t\t(candidateOrder.get(left.traceId) ?? Number.MAX_SAFE_INTEGER) -\n\t\t\t(candidateOrder.get(right.traceId) ?? Number.MAX_SAFE_INTEGER),\n\t);\n\n\tconst durations = traces.map((trace) => trace.durationMs);\n\tconst errorTraces = traces.filter((trace) => trace.errorSpanCount > 0);\n\tconst serviceMap = new Map<\n\t\tstring,\n\t\t{ traceCount: number; errorTraceCount: number; durations: number[] }\n\t>();\n\tfor (const trace of traces) {\n\t\tconst entry = serviceMap.get(trace.serviceName) ?? {\n\t\t\ttraceCount: 0,\n\t\t\terrorTraceCount: 0,\n\t\t\tdurations: [],\n\t\t};\n\t\tentry.traceCount += 1;\n\t\tentry.errorTraceCount += trace.errorSpanCount > 0 ? 1 : 0;\n\t\tentry.durations.push(trace.durationMs);\n\t\tserviceMap.set(trace.serviceName, entry);\n\t}\n\n\treturn {\n\t\tsummary: {\n\t\t\ttotalTraces: traces.length,\n\t\t\terrorTraces: errorTraces.length,\n\t\t\tsuccessTraces: traces.length - errorTraces.length,\n\t\t\terrorRate: traces.length > 0 ? errorTraces.length / traces.length : 0,\n\t\t\taverageDurationMs: Math.round(average(durations)),\n\t\t\tp95DurationMs: Math.round(percentile(durations, 0.95)),\n\t\t},\n\t\tservices: Array.from(serviceMap.entries())\n\t\t\t.map(([serviceName, entry]) => ({\n\t\t\t\tserviceName,\n\t\t\t\ttraceCount: entry.traceCount,\n\t\t\t\terrorTraceCount: entry.errorTraceCount,\n\t\t\t\terrorRate:\n\t\t\t\t\tentry.traceCount > 0 ? entry.errorTraceCount / entry.traceCount : 0,\n\t\t\t\taverageDurationMs: Math.round(average(entry.durations)),\n\t\t\t\tmaxDurationMs: Math.max(...entry.durations, 0),\n\t\t\t}))\n\t\t\t.sort(\n\t\t\t\t(left, right) =>\n\t\t\t\t\tright.traceCount - left.traceCount ||\n\t\t\t\t\tleft.serviceName.localeCompare(right.serviceName),\n\t\t\t),\n\t\ttraces: traces.slice(0, options.limit ?? 30),\n\t\twindowHours: options.hours,\n\t\tfilters: {\n\t\t\tservice: options.service ?? \"all\",\n\t\t\tstatus: options.status ?? \"all\",\n\t\t},\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n","import type { SqlDb } from \"../sql-db\";\n\nexport async function purgeExpiredTelemetry(db: SqlDb): Promise<number> {\n\tconst now = new Date().toISOString();\n\tconst result = await db\n\t\t.prepare(\"DELETE FROM telemetry_spans WHERE expires_at <= ?\")\n\t\t.bind(now)\n\t\t.run();\n\treturn result.meta?.changes ?? 0;\n}\n","import { dialectFor, type SqlDb } from \"../sql-db\";\nimport { cutoffIso, percentile } from \"./helpers\";\n\nexport interface ServiceMapOptions {\n\tprojectId: string;\n\thours: number;\n\tsource?: \"all\" | \"sdk\" | \"ebpf\";\n}\n\nexport interface ServiceOperationsOptions {\n\tprojectId: string;\n\tservice: string;\n\thours: number;\n}\n\nexport async function getTelemetryServiceMap(\n\tdb: SqlDb,\n\toptions: ServiceMapOptions,\n) {\n\tif (!options.projectId)\n\t\tthrow new Error(\"TelemetryStore.getServiceMap: projectId is required\");\n\tconst cutoff = cutoffIso(options.hours);\n\tconst dialect = dialectFor(db);\n\tconst source = options.source ?? \"all\";\n\n\t// RFC 0009 — eBPF-derived agents identify themselves via\n\t// resource_attribute `telemetry.sdk.name`. The set is small and\n\t// stable enough to inline; expand as new agents land.\n\tconst EBPF_SDK_NAMES = new Set([\"beyla\", \"otel-ebpf-profiler\"]);\n\tconst sourceClause =\n\t\tsource === \"ebpf\"\n\t\t\t? ` AND telemetry_sdk_name IN (${Array.from(EBPF_SDK_NAMES)\n\t\t\t\t\t.map(() => \"?\")\n\t\t\t\t\t.join(\",\")})`\n\t\t\t: source === \"sdk\"\n\t\t\t\t? ` AND (telemetry_sdk_name IS NULL OR telemetry_sdk_name NOT IN (${Array.from(\n\t\t\t\t\t\tEBPF_SDK_NAMES,\n\t\t\t\t\t)\n\t\t\t\t\t\t.map(() => \"?\")\n\t\t\t\t\t\t.join(\",\")}))`\n\t\t\t\t: \"\";\n\tconst sourceBinds: unknown[] =\n\t\tsource === \"all\" ? [] : Array.from(EBPF_SDK_NAMES);\n\n\tconst nodesResult = await db\n\t\t.prepare(\n\t\t\t`SELECT\n\t\t\t\t\tservice_name,\n\t\t\t\t\tCOUNT(*) AS span_count,\n\t\t\t\t\tSUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS error_count,\n\t\t\t\t\tCOUNT(DISTINCT trace_id) AS trace_count\n\t\t\t\tFROM telemetry_spans\n\t\t\t\tWHERE project_id = ? AND received_at >= ? AND service_name IS NOT NULL${sourceClause}\n\t\t\t\tGROUP BY service_name`,\n\t\t)\n\t\t.bind(options.projectId, cutoff, ...sourceBinds)\n\t\t.all<{\n\t\t\tservice_name: string;\n\t\t\tspan_count: number;\n\t\t\terror_count: number;\n\t\t\ttrace_count: number;\n\t\t}>();\n\n\t// Edges come from two relationships:\n\t// 1. Synchronous: child span's parent_span_id points at the parent's\n\t// span_id within the same trace, and they're in different services.\n\t// 2. Asynchronous: child span carries a `link` (in links_json) back\n\t// to a producer span in another service — this is how OpenTelemetry\n\t// represents Kafka / RabbitMQ / SQS / Pub/Sub dispatch, because\n\t// consumers can process messages long after producers close their\n\t// span and a single consume can correspond to many produces.\n\t// We UNION ALL both — duplicates are accumulated as separate calls,\n\t// which matches the synchronous semantics (each child = one call).\n\t// RFC 0009 — applying the source filter to *child* spans for sync\n\t// edges and to *consumer* spans for async edges. The producer\n\t// side is left unfiltered (an SDK-instrumented service that\n\t// publishes to a Kafka topic still belongs in the eBPF view if\n\t// the consumer is Beyla-instrumented; the edge represents the\n\t// kernel-observed call, not the producer's instrumentation).\n\tconst childSourceClause =\n\t\tsource === \"ebpf\"\n\t\t\t? ` AND c.telemetry_sdk_name IN (${Array.from(EBPF_SDK_NAMES)\n\t\t\t\t\t.map(() => \"?\")\n\t\t\t\t\t.join(\",\")})`\n\t\t\t: source === \"sdk\"\n\t\t\t\t? ` AND (c.telemetry_sdk_name IS NULL OR c.telemetry_sdk_name NOT IN (${Array.from(\n\t\t\t\t\t\tEBPF_SDK_NAMES,\n\t\t\t\t\t)\n\t\t\t\t\t\t.map(() => \"?\")\n\t\t\t\t\t\t.join(\",\")}))`\n\t\t\t\t: \"\";\n\tconst consumerSourceClause =\n\t\tsource === \"ebpf\"\n\t\t\t? ` AND telemetry_sdk_name IN (${Array.from(EBPF_SDK_NAMES)\n\t\t\t\t\t.map(() => \"?\")\n\t\t\t\t\t.join(\",\")})`\n\t\t\t: source === \"sdk\"\n\t\t\t\t? ` AND (telemetry_sdk_name IS NULL OR telemetry_sdk_name NOT IN (${Array.from(\n\t\t\t\t\t\tEBPF_SDK_NAMES,\n\t\t\t\t\t)\n\t\t\t\t\t\t.map(() => \"?\")\n\t\t\t\t\t\t.join(\",\")}))`\n\t\t\t\t: \"\";\n\tconst linkEdgesSql =\n\t\tdialect.name === \"postgres\"\n\t\t\t? `link_edges AS (\n\t\t\t\t\tSELECT\n\t\t\t\t\t\tproducer.service_name AS source,\n\t\t\t\t\t\tconsumer.service_name AS target,\n\t\t\t\t\t\tconsumer.status_code AS status_code,\n\t\t\t\t\t\tconsumer.duration_ms AS duration_ms,\n\t\t\t\t\t\tconsumer.received_at AS received_at,\n\t\t\t\t\t\tCASE WHEN consumer.telemetry_sdk_name IN ('beyla', 'otel-ebpf-profiler') THEN 1 ELSE 0 END AS is_ebpf\n\t\t\t\t\tFROM (\n\t\t\t\t\t\tSELECT trace_id, span_id, project_id, service_name,\n\t\t\t\t\t\t\tstatus_code, duration_ms, received_at, links_json, telemetry_sdk_name\n\t\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\t\tWHERE project_id = ?\n\t\t\t\t\t\t\tAND received_at >= ?\n\t\t\t\t\t\t\tAND links_json IS NOT NULL\n\t\t\t\t\t\t\tAND links_json != '[]'${consumerSourceClause}\n\t\t\t\t\t) consumer\n\t\t\t\t\tCROSS JOIN LATERAL jsonb_array_elements(consumer.links_json::jsonb) link(value)\n\t\t\t\t\tJOIN telemetry_spans producer\n\t\t\t\t\t\tON producer.trace_id = link.value ->> 'traceId'\n\t\t\t\t\t\tAND producer.span_id = link.value ->> 'spanId'\n\t\t\t\t\t\tAND producer.project_id = consumer.project_id\n\t\t\t\t\tWHERE producer.received_at >= ?\n\t\t\t\t\t\tAND consumer.service_name IS NOT NULL\n\t\t\t\t\t\tAND producer.service_name IS NOT NULL\n\t\t\t\t\t\tAND producer.service_name != consumer.service_name\n\t\t\t\t)`\n\t\t\t: `link_edges AS (\n\t\t\t\t\tSELECT\n\t\t\t\t\t\tproducer.service_name AS source,\n\t\t\t\t\t\tconsumer.service_name AS target,\n\t\t\t\t\t\tconsumer.status_code AS status_code,\n\t\t\t\t\t\tconsumer.duration_ms AS duration_ms,\n\t\t\t\t\t\tconsumer.received_at AS received_at,\n\t\t\t\t\t\tCASE WHEN consumer.telemetry_sdk_name IN ('beyla', 'otel-ebpf-profiler') THEN 1 ELSE 0 END AS is_ebpf\n\t\t\t\t\t-- Pre-filter consumers in a subquery so json_each is only\n\t\t\t\t\t-- invoked on spans that actually carry links. Without this\n\t\t\t\t\t-- gate the cross product fans out across every span in the\n\t\t\t\t\t-- window and the query times out on tens of thousands of\n\t\t\t\t\t-- rows.\n\t\t\t\t\tFROM (\n\t\t\t\t\t\tSELECT trace_id, span_id, project_id, service_name,\n\t\t\t\t\t\t\tstatus_code, duration_ms, received_at, links_json, telemetry_sdk_name\n\t\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\t\tWHERE project_id = ?\n\t\t\t\t\t\t\tAND received_at >= ?\n\t\t\t\t\t\t\tAND links_json IS NOT NULL\n\t\t\t\t\t\t\tAND links_json != '[]'${consumerSourceClause}\n\t\t\t\t\t) consumer,\n\t\t\t\t\t\tjson_each(consumer.links_json) link\n\t\t\t\t\t-- Match on (trace_id, span_id) so the lookup hits the\n\t\t\t\t\t-- composite PRIMARY KEY index. span_id alone has no index\n\t\t\t\t\t-- (only the composite PK), so a span_id-only join would\n\t\t\t\t\t-- full-scan per link.\n\t\t\t\t\tJOIN telemetry_spans producer\n\t\t\t\t\t\tON producer.trace_id = json_extract(link.value, '$.traceId')\n\t\t\t\t\t\tAND producer.span_id = json_extract(link.value, '$.spanId')\n\t\t\t\t\t\tAND producer.project_id = consumer.project_id\n\t\t\t\t\tWHERE producer.received_at >= ?\n\t\t\t\t\t\tAND consumer.service_name IS NOT NULL\n\t\t\t\t\t\tAND producer.service_name IS NOT NULL\n\t\t\t\t\t\tAND producer.service_name != consumer.service_name\n\t\t\t\t)`;\n\n\tconst edgeRowsResult = await db\n\t\t.prepare(\n\t\t\t`WITH parent_child_edges AS (\n\t\t\t\t\tSELECT\n\t\t\t\t\t\tp.service_name AS source,\n\t\t\t\t\t\tc.service_name AS target,\n\t\t\t\t\t\tc.status_code AS status_code,\n\t\t\t\t\t\tc.duration_ms AS duration_ms,\n\t\t\t\t\t\tc.received_at AS received_at,\n\t\t\t\t\t\tCASE WHEN c.telemetry_sdk_name IN ('beyla', 'otel-ebpf-profiler') THEN 1 ELSE 0 END AS is_ebpf\n\t\t\t\t\tFROM telemetry_spans p\n\t\t\t\t\tJOIN telemetry_spans c\n\t\t\t\t\t\tON c.parent_span_id = p.span_id\n\t\t\t\t\t\tAND c.trace_id = p.trace_id\n\t\t\t\t\t\tAND c.project_id = p.project_id\n\t\t\t\t\tWHERE p.project_id = ?\n\t\t\t\t\t\tAND p.received_at >= ?\n\t\t\t\t\t\tAND c.received_at >= ?\n\t\t\t\t\t\tAND p.service_name IS NOT NULL\n\t\t\t\t\t\tAND c.service_name IS NOT NULL\n\t\t\t\t\t\tAND p.service_name != c.service_name${childSourceClause}\n\t\t\t\t),\n\t\t\t\t${linkEdgesSql}\n\t\t\t\tSELECT * FROM parent_child_edges\n\t\t\t\tUNION ALL\n\t\t\t\tSELECT * FROM link_edges\n\t\t\t\tORDER BY received_at DESC\n\t\t\t\tLIMIT 50000`,\n\t\t)\n\t\t.bind(\n\t\t\toptions.projectId,\n\t\t\tcutoff,\n\t\t\tcutoff,\n\t\t\t...sourceBinds,\n\t\t\toptions.projectId,\n\t\t\tcutoff,\n\t\t\t...sourceBinds,\n\t\t\tcutoff,\n\t\t)\n\t\t.all<{\n\t\t\tsource: string;\n\t\t\ttarget: string;\n\t\t\tstatus_code: number;\n\t\t\tduration_ms: number;\n\t\t\tis_ebpf: number;\n\t\t}>();\n\n\tinterface EdgeAcc {\n\t\tsource: string;\n\t\ttarget: string;\n\t\tcalls: number;\n\t\terrors: number;\n\t\tdurations: number[];\n\t\tisEbpf: boolean;\n\t}\n\tconst edgeMap = new Map<string, EdgeAcc>();\n\tfor (const row of edgeRowsResult.results ?? []) {\n\t\tconst key = `${row.source}|${row.target}`;\n\t\tlet acc = edgeMap.get(key);\n\t\tif (!acc) {\n\t\t\tacc = {\n\t\t\t\tsource: row.source,\n\t\t\t\ttarget: row.target,\n\t\t\t\tcalls: 0,\n\t\t\t\terrors: 0,\n\t\t\t\tdurations: [],\n\t\t\t\tisEbpf: false,\n\t\t\t};\n\t\t\tedgeMap.set(key, acc);\n\t\t}\n\t\tacc.calls += 1;\n\t\tif (row.status_code === 2) acc.errors += 1;\n\t\tacc.durations.push(row.duration_ms ?? 0);\n\t\tif (row.is_ebpf === 1) acc.isEbpf = true;\n\t}\n\n\tconst windowSeconds = Math.max(1, options.hours * 3600);\n\tconst edges = Array.from(edgeMap.values()).map((e) => ({\n\t\tsource: e.source,\n\t\ttarget: e.target,\n\t\tcalls: e.calls,\n\t\terrors: e.errors,\n\t\terrorRate: e.calls > 0 ? e.errors / e.calls : 0,\n\t\tp50DurationMs: percentile(e.durations, 0.5),\n\t\tp95DurationMs: percentile(e.durations, 0.95),\n\t\trps: e.calls / windowSeconds,\n\t\tisEbpf: e.isEbpf,\n\t}));\n\n\tconst nodes = (nodesResult.results ?? []).map((r) => ({\n\t\tservice: r.service_name,\n\t\tspanCount: r.span_count,\n\t\terrorCount: r.error_count,\n\t\ttraceCount: r.trace_count,\n\t\terrorRate: r.span_count > 0 ? r.error_count / r.span_count : 0,\n\t}));\n\n\treturn { nodes, edges };\n}\n\nexport async function getTelemetryServiceOperations(\n\tdb: SqlDb,\n\toptions: ServiceOperationsOptions,\n) {\n\tif (!options.projectId)\n\t\tthrow new Error(\n\t\t\t\"TelemetryStore.getServiceOperations: projectId is required\",\n\t\t);\n\tconst cutoff = cutoffIso(options.hours);\n\n\t// Top operations — group by span_name, accumulate durations in JS.\n\tconst opsResult = await db\n\t\t.prepare(\n\t\t\t// One row per span; calls/errors/percentiles are aggregated per\n\t\t\t// span_name in JS below. Do NOT reintroduce COUNT()/SUM() without\n\t\t\t// a GROUP BY — that collapses the result to a single row in SQLite.\n\t\t\t`SELECT\n\t\t\t\t\tspan_name,\n\t\t\t\t\tstatus_code,\n\t\t\t\t\tduration_ms\n\t\t\t\tFROM telemetry_spans\n\t\t\t\tWHERE project_id = ?\n\t\t\t\t\tAND service_name = ?\n\t\t\t\t\tAND received_at >= ?\n\t\t\t\tORDER BY received_at DESC\n\t\t\t\tLIMIT 20000`,\n\t\t)\n\t\t.bind(options.projectId, options.service, cutoff)\n\t\t.all<{\n\t\t\tspan_name: string;\n\t\t\tstatus_code: number | null;\n\t\t\tduration_ms: number;\n\t\t}>();\n\n\tinterface OpAcc {\n\t\tcalls: number;\n\t\terrors: number;\n\t\tdurations: number[];\n\t}\n\tconst opMap = new Map<string, OpAcc>();\n\tlet totalSpans = 0;\n\tlet totalErrors = 0;\n\tfor (const row of opsResult.results ?? []) {\n\t\tconst isError = row.status_code === 2;\n\t\ttotalSpans += 1;\n\t\tif (isError) totalErrors += 1;\n\t\tlet acc = opMap.get(row.span_name);\n\t\tif (!acc) {\n\t\t\tacc = { calls: 0, errors: 0, durations: [] };\n\t\t\topMap.set(row.span_name, acc);\n\t\t}\n\t\tacc.calls += 1;\n\t\tif (isError) acc.errors += 1;\n\t\tacc.durations.push(row.duration_ms ?? 0);\n\t}\n\tconst operations = Array.from(opMap.entries())\n\t\t.map(([spanName, acc]) => ({\n\t\t\tspanName,\n\t\t\tcalls: acc.calls,\n\t\t\terrors: acc.errors,\n\t\t\terrorRate: acc.calls > 0 ? acc.errors / acc.calls : 0,\n\t\t\tp50DurationMs: percentile(acc.durations, 0.5),\n\t\t\tp95DurationMs: percentile(acc.durations, 0.95),\n\t\t}))\n\t\t.sort((l, r) => r.calls - l.calls)\n\t\t.slice(0, 12);\n\n\t// Recent error spans for triage.\n\tconst errorRows = await db\n\t\t.prepare(\n\t\t\t`SELECT trace_id, span_id, span_name, status_message, duration_ms, start_time\n\t\t\t\tFROM telemetry_spans\n\t\t\t\tWHERE project_id = ?\n\t\t\t\t\tAND service_name = ?\n\t\t\t\t\tAND received_at >= ?\n\t\t\t\t\tAND status_code = 2\n\t\t\t\tORDER BY received_at DESC\n\t\t\t\tLIMIT 10`,\n\t\t)\n\t\t.bind(options.projectId, options.service, cutoff)\n\t\t.all<{\n\t\t\ttrace_id: string;\n\t\t\tspan_id: string;\n\t\t\tspan_name: string;\n\t\t\tstatus_message: string | null;\n\t\t\tduration_ms: number;\n\t\t\tstart_time: string;\n\t\t}>();\n\n\t// Distinct trace count for this service.\n\tconst traceCountRow = await db\n\t\t.prepare(\n\t\t\t`SELECT COUNT(DISTINCT trace_id) AS trace_count\n\t\t\t\tFROM telemetry_spans\n\t\t\t\tWHERE project_id = ? AND service_name = ? AND received_at >= ?`,\n\t\t)\n\t\t.bind(options.projectId, options.service, cutoff)\n\t\t.first<{ trace_count: number }>();\n\n\treturn {\n\t\tservice: options.service,\n\t\tspanCount: totalSpans,\n\t\ttraceCount: traceCountRow?.trace_count ?? 0,\n\t\terrorCount: totalErrors,\n\t\toperations,\n\t\trecentErrors: (errorRows.results ?? []).map((r) => ({\n\t\t\ttraceId: r.trace_id,\n\t\t\tspanId: r.span_id,\n\t\t\tspanName: r.span_name,\n\t\t\tstatusMessage: r.status_message,\n\t\t\tdurationMs: r.duration_ms,\n\t\t\tstartTime: r.start_time,\n\t\t})),\n\t};\n}\n","import type {\n\tJsonValue,\n\tSpanDetailRow,\n\tTelemetryCodeReference,\n\tTelemetryInstrumentationGap,\n\tTelemetryInstrumentationGapsResponse,\n\tTelemetrySpanDetail,\n\tTelemetryTraceDetailResponse,\n} from \"@obsunified/types\";\nimport {\n\tDEFAULT_INSTRUMENTATION_GAP_THRESHOLDS,\n\tisInstrumentationGapCandidate,\n} from \"@obsunified/types\";\nimport { parseJsonArray, parseJsonRecord } from \"../json\";\nimport type { SqlDb } from \"../sql-db\";\nimport { normalizeService } from \"./helpers\";\n\nexport interface TelemetryInstrumentationGapCalibrationOptions {\n\tprojectId: string;\n\thours: number;\n\tlimit?: number;\n}\n\nexport async function getTelemetryTraceDetail(\n\tdb: SqlDb,\n\ttraceId: string,\n\tprojectId: string,\n): Promise<TelemetryTraceDetailResponse | null> {\n\tif (!projectId)\n\t\tthrow new Error(\"TelemetryStore.getTraceDetail: projectId is required\");\n\tconst result = await db\n\t\t.prepare(`\n SELECT project_id, trace_id, span_id, parent_span_id, service_name, scope_name,\n scope_version, span_name, span_kind, status_code, status_message,\n start_time, end_time, duration_ms, attributes_json,\n resource_attributes_json, events_json, links_json,\n received_at, expires_at\n FROM telemetry_spans\n WHERE project_id = ? AND trace_id = ?\n ORDER BY start_time ASC, span_id ASC\n `)\n\t\t.bind(projectId, traceId)\n\t\t.all<SpanDetailRow>();\n\n\tconst rows = result.results ?? [];\n\tif (rows.length === 0) return null;\n\n\tconst spans: TelemetrySpanDetail[] = rows.map((row) => ({\n\t\ttraceId: row.trace_id,\n\t\tspanId: row.span_id,\n\t\tparentSpanId: row.parent_span_id,\n\t\tserviceName: normalizeService(row.service_name),\n\t\tscopeName: row.scope_name,\n\t\tscopeVersion: row.scope_version,\n\t\tspanName: row.span_name,\n\t\tspanKind: row.span_kind,\n\t\tstatusCode: row.status_code,\n\t\tstatusMessage: row.status_message,\n\t\tstartTime: row.start_time,\n\t\tendTime: row.end_time,\n\t\tdurationMs: row.duration_ms,\n\t\tattributes: parseJsonRecord(row.attributes_json),\n\t\tresourceAttributes: parseJsonRecord(row.resource_attributes_json),\n\t\tevents: parseJsonArray(row.events_json),\n\t\tlinks: parseJsonArray(row.links_json),\n\t}));\n\tfor (const span of spans) {\n\t\tconst codeReference = extractCodeReference(span.attributes);\n\t\tif (codeReference) span.codeReference = codeReference;\n\t}\n\n\tconst root = spans.find((span) => !span.parentSpanId) ?? spans[0];\n\tconst timestamp = new Date().toISOString();\n\tconst instrumentationGaps =\n\t\t(await getTelemetryTraceGaps(db, traceId, projectId, spans)) ?? undefined;\n\n\treturn {\n\t\ttrace: {\n\t\t\ttraceId,\n\t\t\tserviceName: root.serviceName,\n\t\t\tspanName: root.spanName,\n\t\t\tstatusCode: spans.some((span) => span.statusCode === 2)\n\t\t\t\t? 2\n\t\t\t\t: root.statusCode,\n\t\t\tstatusMessage:\n\t\t\t\tspans.find((span) => span.statusCode === 2)?.statusMessage ??\n\t\t\t\troot.statusMessage,\n\t\t\tstartTime: root.startTime,\n\t\t\tendTime: root.endTime,\n\t\t\tdurationMs: root.durationMs,\n\t\t\treceivedAt: rows[0]?.received_at ?? root.startTime,\n\t\t\tspanCount: spans.length,\n\t\t\terrorSpanCount: spans.filter((span) => span.statusCode === 2).length,\n\t\t},\n\t\tspans,\n\t\tinstrumentationGaps,\n\t\ttimestamp,\n\t};\n}\n\nexport async function getTelemetryTraceGaps(\n\tdb: SqlDb,\n\ttraceId: string,\n\tprojectId: string,\n\tspans?: TelemetrySpanDetail[],\n): Promise<TelemetryInstrumentationGapsResponse | null> {\n\tif (!projectId)\n\t\tthrow new Error(\"TelemetryStore.getTraceGaps: projectId is required\");\n\n\t// Gaps are derived data: compute them lazily from the trace's spans on\n\t// read, rather than materializing them on the ingest hot path. The\n\t// `spans` arg is passed by `getTelemetryTraceDetail` (which has already\n\t// loaded them); the standalone `/gaps` endpoint omits it, so we load\n\t// them here. The span query is project-scoped, so this avoids the\n\t// `trace_instrumentation_gaps` table's lack of project scoping entirely.\n\tconst timestamp = new Date().toISOString();\n\n\tlet localSpans = spans;\n\tif (!localSpans) {\n\t\tconst result = await db\n\t\t\t.prepare(`\n\t\t\t\tSELECT project_id, trace_id, span_id, parent_span_id, service_name, scope_name,\n\t\t\t\t scope_version, span_name, span_kind, status_code, status_message,\n\t\t\t\t start_time, end_time, duration_ms, attributes_json,\n\t\t\t\t resource_attributes_json, events_json, links_json,\n\t\t\t\t received_at, expires_at\n\t\t\t\tFROM telemetry_spans\n\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\tORDER BY start_time ASC, span_id ASC\n\t\t\t`)\n\t\t\t.bind(projectId, traceId)\n\t\t\t.all<SpanDetailRow>();\n\t\tconst spanRows = result.results ?? [];\n\t\tif (spanRows.length === 0) return null;\n\n\t\tlocalSpans = spanRows.map((row) => ({\n\t\t\ttraceId: row.trace_id,\n\t\t\tspanId: row.span_id,\n\t\t\tparentSpanId: row.parent_span_id,\n\t\t\tserviceName: normalizeService(row.service_name),\n\t\t\tscopeName: row.scope_name,\n\t\t\tscopeVersion: row.scope_version,\n\t\t\tspanName: row.span_name,\n\t\t\tspanKind: row.span_kind,\n\t\t\tstatusCode: row.status_code,\n\t\t\tstatusMessage: row.status_message,\n\t\t\tstartTime: row.start_time,\n\t\t\tendTime: row.end_time,\n\t\t\tdurationMs: row.duration_ms,\n\t\t\tattributes: parseJsonRecord(row.attributes_json),\n\t\t\tresourceAttributes: parseJsonRecord(row.resource_attributes_json),\n\t\t\tevents: parseJsonArray(row.events_json),\n\t\t\tlinks: parseJsonArray(row.links_json),\n\t\t}));\n\t}\n\n\tif (localSpans.length === 0) return null;\n\tconst root = localSpans.find((span) => !span.parentSpanId) ?? localSpans[0];\n\treturn buildTraceInstrumentationGaps(\n\t\ttraceId,\n\t\tlocalSpans,\n\t\troot.durationMs,\n\t\ttimestamp,\n\t);\n}\n\nexport function buildTraceInstrumentationGaps(\n\ttraceId: string,\n\tspans: TelemetrySpanDetail[],\n\ttotalDurationMs: number,\n\ttimestamp = new Date().toISOString(),\n): TelemetryInstrumentationGapsResponse {\n\tconst children = new Map<string | null, TelemetrySpanDetail[]>();\n\tfor (const span of spans) {\n\t\tconst parentKey = span.parentSpanId ?? null;\n\t\tconst bucket = children.get(parentKey) ?? [];\n\t\tbucket.push(span);\n\t\tchildren.set(parentKey, bucket);\n\t}\n\n\tconst blindspots: TelemetryInstrumentationGap[] = [];\n\tfor (const span of spans) {\n\t\tconst childSpans = children.get(span.spanId) ?? [];\n\t\tconst childDurationMs = childSpans.reduce(\n\t\t\t(acc, child) => acc + child.durationMs,\n\t\t\t0,\n\t\t);\n\t\tconst rawSelfMs = span.durationMs - childDurationMs;\n\t\tconst asyncParent = rawSelfMs < 0;\n\t\tconst selfMs = Math.max(0, rawSelfMs);\n\t\tconst ratioOfParent =\n\t\t\tspan.durationMs > 0 ? Math.min(1, selfMs / span.durationMs) : 0;\n\t\tif (\n\t\t\t!isInstrumentationGapCandidate({\n\t\t\t\tdurationMs: span.durationMs,\n\t\t\t\tselfRatio: ratioOfParent,\n\t\t\t\tchildSpanCount: childSpans.length,\n\t\t\t\tasyncParent,\n\t\t\t\tspanKind: span.spanKind,\n\t\t\t})\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\t\tblindspots.push({\n\t\t\ttraceId,\n\t\t\tparentSpanId: span.spanId,\n\t\t\tparentServiceName: span.serviceName,\n\t\t\tparentSpanName: span.spanName,\n\t\t\toffsetMs: 0,\n\t\t\tdurationMs: Math.round(selfMs),\n\t\t\tratioOfParent,\n\t\t\tchildSpanCount: childSpans.length,\n\t\t\tparentSpanKind: span.spanKind,\n\t\t\tasyncParent,\n\t\t\tthresholdVersion: DEFAULT_INSTRUMENTATION_GAP_THRESHOLDS.version,\n\t\t\trecommendation: `Add tracing inside ${span.spanName} or attach a profile for ${span.serviceName}.`,\n\t\t});\n\t}\n\n\tconst uninstrumentedTimeMs = blindspots.reduce(\n\t\t(acc, gap) => acc + gap.durationMs,\n\t\t0,\n\t);\n\treturn {\n\t\ttraceId,\n\t\ttotalDurationMs,\n\t\tuninstrumentedTimeMs,\n\t\tratio: totalDurationMs > 0 ? uninstrumentedTimeMs / totalDurationMs : 0,\n\t\tblindspots,\n\t\tthresholds: DEFAULT_INSTRUMENTATION_GAP_THRESHOLDS,\n\t\ttimestamp,\n\t};\n}\n\nexport async function calibrateTelemetryInstrumentationGaps(\n\tdb: SqlDb,\n\toptions: TelemetryInstrumentationGapCalibrationOptions,\n) {\n\tif (!options.projectId)\n\t\tthrow new Error(\"TelemetryStore.calibrateTraceGaps: projectId is required\");\n\tconst hours = Math.max(1, Math.min(options.hours, 24 * 30));\n\tconst limit = Math.max(1, Math.min(options.limit ?? 5000, 20_000));\n\tconst since = new Date(Date.now() - hours * 60 * 60 * 1000).toISOString();\n\tconst result = await db\n\t\t.prepare(`\n\t\t\tSELECT project_id, trace_id, span_id, parent_span_id, service_name, scope_name,\n\t\t\t scope_version, span_name, span_kind, status_code, status_message,\n\t\t\t start_time, end_time, duration_ms, attributes_json,\n\t\t\t resource_attributes_json, events_json, links_json,\n\t\t\t received_at, expires_at\n\t\t\tFROM telemetry_spans\n\t\t\tWHERE project_id = ? AND received_at >= ?\n\t\t\tORDER BY received_at DESC, trace_id ASC, start_time ASC, span_id ASC\n\t\t\tLIMIT ?\n\t\t`)\n\t\t.bind(options.projectId, since, limit)\n\t\t.all<SpanDetailRow>();\n\n\tconst rows = result.results ?? [];\n\tconst byTrace = new Map<string, TelemetrySpanDetail[]>();\n\tfor (const row of rows) {\n\t\tconst bucket = byTrace.get(row.trace_id) ?? [];\n\t\tbucket.push({\n\t\t\ttraceId: row.trace_id,\n\t\t\tspanId: row.span_id,\n\t\t\tparentSpanId: row.parent_span_id,\n\t\t\tserviceName: normalizeService(row.service_name),\n\t\t\tscopeName: row.scope_name,\n\t\t\tscopeVersion: row.scope_version,\n\t\t\tspanName: row.span_name,\n\t\t\tspanKind: row.span_kind,\n\t\t\tstatusCode: row.status_code,\n\t\t\tstatusMessage: row.status_message,\n\t\t\tstartTime: row.start_time,\n\t\t\tendTime: row.end_time,\n\t\t\tdurationMs: row.duration_ms,\n\t\t\tattributes: parseJsonRecord(row.attributes_json),\n\t\t\tresourceAttributes: parseJsonRecord(row.resource_attributes_json),\n\t\t\tevents: parseJsonArray(row.events_json),\n\t\t\tlinks: parseJsonArray(row.links_json),\n\t\t});\n\t\tbyTrace.set(row.trace_id, bucket);\n\t}\n\n\tconst traceSummaries: Array<{\n\t\ttraceId: string;\n\t\trootSpanName: string;\n\t\tserviceName: string;\n\t\ttotalDurationMs: number;\n\t\tblindspotCount: number;\n\t\tuninstrumentedTimeMs: number;\n\t\tratio: number;\n\t\ttopBlindspot: TelemetryInstrumentationGap | null;\n\t}> = [];\n\tlet flaggedTraceCount = 0;\n\tlet blindspotCount = 0;\n\tlet uninstrumentedTimeMs = 0;\n\n\tfor (const [traceId, spans] of byTrace) {\n\t\tspans.sort((a, b) => a.startTime.localeCompare(b.startTime));\n\t\tconst root = spans.find((span) => !span.parentSpanId) ?? spans[0];\n\t\tif (!root) continue;\n\t\tconst gaps = buildTraceInstrumentationGaps(traceId, spans, root.durationMs);\n\t\tif (gaps.blindspots.length === 0) continue;\n\t\tflaggedTraceCount++;\n\t\tblindspotCount += gaps.blindspots.length;\n\t\tuninstrumentedTimeMs += gaps.uninstrumentedTimeMs;\n\t\ttraceSummaries.push({\n\t\t\ttraceId,\n\t\t\trootSpanName: root.spanName,\n\t\t\tserviceName: root.serviceName,\n\t\t\ttotalDurationMs: root.durationMs,\n\t\t\tblindspotCount: gaps.blindspots.length,\n\t\t\tuninstrumentedTimeMs: gaps.uninstrumentedTimeMs,\n\t\t\tratio: gaps.ratio,\n\t\t\ttopBlindspot: [...gaps.blindspots].sort(\n\t\t\t\t(a, b) => b.durationMs - a.durationMs,\n\t\t\t)[0],\n\t\t});\n\t}\n\n\ttraceSummaries.sort(\n\t\t(a, b) => b.uninstrumentedTimeMs - a.uninstrumentedTimeMs,\n\t);\n\tconst traceCount = byTrace.size;\n\treturn {\n\t\tthresholds: DEFAULT_INSTRUMENTATION_GAP_THRESHOLDS,\n\t\twindowHours: hours,\n\t\tsampledSpanCount: rows.length,\n\t\ttraceCount,\n\t\tflaggedTraceCount,\n\t\tblindspotCount,\n\t\tuninstrumentedTimeMs,\n\t\tflaggedTraceRate: traceCount > 0 ? flaggedTraceCount / traceCount : 0,\n\t\tstatus:\n\t\t\ttraceCount === 0\n\t\t\t\t? \"no_traces\"\n\t\t\t\t: flaggedTraceCount === 0\n\t\t\t\t\t? \"quiet\"\n\t\t\t\t\t: flaggedTraceCount / traceCount > 0.25\n\t\t\t\t\t\t? \"noisy\"\n\t\t\t\t\t\t: \"calibrated\",\n\t\ttopTraces: traceSummaries.slice(0, 20),\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n\nexport function extractCodeReference(\n\tattributes: Record<string, JsonValue>,\n): TelemetryCodeReference | undefined {\n\tconst originalPath = firstString(attributes, [\n\t\t\"code.filepath\",\n\t\t\"code.file.path\",\n\t\t\"code.path\",\n\t\t\"source.file\",\n\t]);\n\tconst symbolName = firstString(attributes, [\n\t\t\"code.function\",\n\t\t\"code.function.name\",\n\t\t\"code.namespace\",\n\t]);\n\tconst lineNumber = firstPositiveInteger(attributes, [\n\t\t\"code.lineno\",\n\t\t\"code.line_number\",\n\t\t\"code.line\",\n\t]);\n\tconst columnNumber = firstPositiveInteger(attributes, [\n\t\t\"code.column\",\n\t\t\"code.column_number\",\n\t]);\n\tconst repoName = firstString(attributes, [\"code.repository\", \"repo.name\"]);\n\n\tif (!originalPath && !symbolName && lineNumber === undefined)\n\t\treturn undefined;\n\n\tconst reference: TelemetryCodeReference = {};\n\tif (repoName) reference.repoName = repoName;\n\tif (originalPath) {\n\t\treference.originalPath = originalPath;\n\t\tif (isAbsolutePath(originalPath)) {\n\t\t\treference.absolutePath = originalPath;\n\t\t} else {\n\t\t\treference.relativePath = normalizeRelativePath(originalPath);\n\t\t}\n\t}\n\tif (symbolName) reference.symbolName = symbolName;\n\tif (lineNumber !== undefined) reference.lineNumber = lineNumber;\n\tif (columnNumber !== undefined) reference.columnNumber = columnNumber;\n\n\treturn reference;\n}\n\nfunction firstString(\n\tattributes: Record<string, JsonValue>,\n\tkeys: string[],\n): string | undefined {\n\tfor (const key of keys) {\n\t\tconst value = attributes[key];\n\t\tif (typeof value === \"string\" && value.trim()) return value.trim();\n\t}\n\treturn undefined;\n}\n\nfunction firstPositiveInteger(\n\tattributes: Record<string, JsonValue>,\n\tkeys: string[],\n): number | undefined {\n\tfor (const key of keys) {\n\t\tconst value = attributes[key];\n\t\tif (typeof value === \"number\" && Number.isInteger(value) && value > 0) {\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\tconst parsed = Number.parseInt(value, 10);\n\t\t\tif (Number.isInteger(parsed) && parsed > 0) return parsed;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction isAbsolutePath(value: string): boolean {\n\treturn value.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(value);\n}\n\nfunction normalizeRelativePath(value: string): string {\n\treturn value.replace(/^\\.\\/+/, \"\");\n}\n","import type {\n\tStoredSpan,\n\tTelemetryInstrumentationGapsResponse,\n\tTelemetryIssueDetailResponse,\n\tTelemetryIssueOptions,\n\tTelemetryIssueOverviewResponse,\n\tTelemetryOverviewOptions,\n\tTelemetryOverviewResponse,\n\tTelemetryTraceDetailResponse,\n} from \"@obsunified/types\";\nimport type { SqlDb } from \"./sql-db\";\nimport { getTelemetryExportRows } from \"./store/export\";\nimport { ingestTelemetrySpans } from \"./store/ingest\";\nimport {\n\tgetTelemetryIssueDetail,\n\tgetTelemetryIssueOverview,\n} from \"./store/issues\";\nimport { getTelemetryOverview } from \"./store/overview\";\nimport { purgeExpiredTelemetry } from \"./store/retention\";\nimport {\n\tgetTelemetryServiceMap,\n\tgetTelemetryServiceOperations,\n\ttype ServiceMapOptions,\n\ttype ServiceOperationsOptions,\n} from \"./store/service-map\";\nimport {\n\tcalibrateTelemetryInstrumentationGaps,\n\tgetTelemetryTraceDetail,\n\tgetTelemetryTraceGaps,\n\ttype TelemetryInstrumentationGapCalibrationOptions,\n} from \"./store/trace-detail\";\n\nexport class TelemetryStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync ingest(\n\t\tspans: StoredSpan[],\n\t): Promise<{ inserted: number; traceCount: number }> {\n\t\treturn ingestTelemetrySpans(this.db, spans);\n\t}\n\n\tasync getOverview(\n\t\toptions: TelemetryOverviewOptions,\n\t): Promise<TelemetryOverviewResponse> {\n\t\treturn getTelemetryOverview(this.db, options);\n\t}\n\n\tasync getTraceDetail(\n\t\ttraceId: string,\n\t\tprojectId: string,\n\t): Promise<TelemetryTraceDetailResponse | null> {\n\t\treturn getTelemetryTraceDetail(this.db, traceId, projectId);\n\t}\n\n\tasync getTraceGaps(\n\t\ttraceId: string,\n\t\tprojectId: string,\n\t): Promise<TelemetryInstrumentationGapsResponse | null> {\n\t\treturn getTelemetryTraceGaps(this.db, traceId, projectId);\n\t}\n\n\tasync calibrateTraceGaps(\n\t\toptions: TelemetryInstrumentationGapCalibrationOptions,\n\t) {\n\t\treturn calibrateTelemetryInstrumentationGaps(this.db, options);\n\t}\n\n\tasync getIssueOverview(\n\t\toptions: TelemetryIssueOptions,\n\t): Promise<TelemetryIssueOverviewResponse> {\n\t\treturn getTelemetryIssueOverview(this.db, options);\n\t}\n\n\tasync getIssueDetail(\n\t\tissueId: string,\n\t\toptions: TelemetryIssueOptions,\n\t): Promise<TelemetryIssueDetailResponse | null> {\n\t\treturn getTelemetryIssueDetail(this.db, issueId, options);\n\t}\n\n\tasync getExportRows(options: TelemetryOverviewOptions): Promise<string> {\n\t\treturn getTelemetryExportRows(this.db, options);\n\t}\n\n\tasync getServiceMap(options: ServiceMapOptions) {\n\t\treturn getTelemetryServiceMap(this.db, options);\n\t}\n\n\tasync getServiceOperations(options: ServiceOperationsOptions) {\n\t\treturn getTelemetryServiceOperations(this.db, options);\n\t}\n\n\tasync purgeExpired(): Promise<number> {\n\t\treturn purgeExpiredTelemetry(this.db);\n\t}\n}\n","/**\n * UsageStore — union of all repos.\n * - A's in-memory aggregation approach (more flexible, handles legacy load time keys)\n * - A's broader error detection (event_type='frontend_error' OR severity='error')\n * - A's multi-key load time parsing (loadTimeMs, load_time_ms, durationMs)\n * - A's purgeExpired()\n * - A's summarizeMap helper\n */\n\nimport type {\n\tUsageBrowserSummary,\n\tUsageCountrySummary,\n\tUsageDeviceSummary,\n\tUsageErrorSummary,\n\tUsageEventRecord,\n\tUsageEventRow,\n\tUsageEventSummary,\n\tUsageOSSummary,\n\tUsageOverviewOptions,\n\tUsageOverviewResponse,\n\tUsagePageSummary,\n\tUsageSessionDetailResponse,\n\tUsageSessionSummary,\n\tUsageUtmCampaignSummary,\n\tUsageUtmMediumSummary,\n\tUsageUtmSourceSummary,\n} from \"@obsunified/types\";\n\nimport { parseJsonRecord } from \"./json\";\nimport { dialectFor, type SqlDb } from \"./sql-db\";\n\nconst cutoffIso = (hours: number): string =>\n\tnew Date(Date.now() - hours * 60 * 60 * 1000).toISOString();\n\nconst summarizeMap = <T>(\n\tmap: Map<string, number>,\n\tbuild: (value: string, count: number) => T,\n): T[] =>\n\tArray.from(map.entries())\n\t\t.map(([value, count]) => build(value, count))\n\t\t.sort((left, right) => {\n\t\t\tconst leftCount = (left as { count: number }).count;\n\t\t\tconst rightCount = (right as { count: number }).count;\n\t\t\treturn rightCount - leftCount;\n\t\t})\n\t\t.slice(0, 10);\n\nconst filterRow = (\n\trow: UsageEventRow,\n\toptions: UsageOverviewOptions,\n\tcutoff: string,\n): boolean => {\n\tif (row.occurred_at < cutoff) return false;\n\tif (options.path && row.page_path !== options.path) return false;\n\tif (!options.includeAdmin) {\n\t\tconst context = parseJsonRecord(row.context_json);\n\t\tif (context[\"collector.is_admin_path\"] === true) return false;\n\t}\n\treturn true;\n};\n\nconst toSessionSummary = (rows: UsageEventRow[]): UsageSessionSummary => {\n\tconst sorted = [...rows].sort((left, right) =>\n\t\tleft.occurred_at.localeCompare(right.occurred_at),\n\t);\n\tconst first = sorted[0];\n\tconst last = sorted[sorted.length - 1];\n\n\treturn {\n\t\tsessionId: first.session_id,\n\t\tvisitorId: first.visitor_id,\n\t\tfirstSeen: first.occurred_at,\n\t\tlastSeen: last.occurred_at,\n\t\teventCount: sorted.length,\n\t\tpageViewCount: sorted.filter((row) => row.event_type === \"page_view\")\n\t\t\t.length,\n\t\terrorCount: sorted.filter(\n\t\t\t(row) => row.event_type === \"frontend_error\" || row.severity === \"error\",\n\t\t).length,\n\t\tlastPath: last.page_path,\n\t\treferrer: first.referrer,\n\t};\n};\n\nexport class UsageStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync ingest(\n\t\tevents: UsageEventRecord[],\n\t): Promise<{ inserted: number; sessionCount: number }> {\n\t\tif (events.length === 0) return { inserted: 0, sessionCount: 0 };\n\n\t\tconst statements = events.map((event) => {\n\t\t\tif (!event.projectId)\n\t\t\t\tthrow new Error(\"UsageStore.ingest: event.projectId is required\");\n\t\t\treturn this.db\n\t\t\t\t.prepare(`\n INSERT OR IGNORE INTO usage_events (\n project_id, event_id, session_id, visitor_id, event_type, event_name,\n page_path, page_title, referrer, severity, source,\n context_json, properties_json, user_agent, occurred_at,\n received_at, expires_at, country, browser, os,\n device_type, is_bot, utm_source, utm_medium, utm_campaign,\n interaction_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\t\t\t\t.bind(\n\t\t\t\t\tevent.projectId,\n\t\t\t\t\tevent.eventId,\n\t\t\t\t\tevent.sessionId,\n\t\t\t\t\tevent.visitorId,\n\t\t\t\t\tevent.eventType,\n\t\t\t\t\tevent.eventName,\n\t\t\t\t\tevent.pagePath,\n\t\t\t\t\tevent.pageTitle,\n\t\t\t\t\tevent.referrer,\n\t\t\t\t\tevent.severity,\n\t\t\t\t\tevent.source,\n\t\t\t\t\tevent.contextJson,\n\t\t\t\t\tevent.propertiesJson,\n\t\t\t\t\tevent.userAgent,\n\t\t\t\t\tevent.occurredAt,\n\t\t\t\t\tevent.receivedAt,\n\t\t\t\t\tevent.expiresAt,\n\t\t\t\t\tevent.country,\n\t\t\t\t\tevent.browser,\n\t\t\t\t\tevent.os,\n\t\t\t\t\tevent.deviceType,\n\t\t\t\t\tevent.isBot ? 1 : 0,\n\t\t\t\t\tevent.utmSource,\n\t\t\t\t\tevent.utmMedium,\n\t\t\t\t\tevent.utmCampaign,\n\t\t\t\t\tevent.interactionId ?? null,\n\t\t\t\t);\n\t\t});\n\n\t\tawait this.db.batch(statements);\n\t\treturn {\n\t\t\tinserted: events.length,\n\t\t\tsessionCount: new Set(events.map((event) => event.sessionId)).size,\n\t\t};\n\t}\n\n\tasync getOverview(\n\t\toptions: UsageOverviewOptions,\n\t): Promise<UsageOverviewResponse> {\n\t\tif (!options.projectId)\n\t\t\tthrow new Error(\"UsageStore.getOverview: projectId is required\");\n\t\tconst cutoff = cutoffIso(options.hours);\n\t\tconst result = await this.db\n\t\t\t.prepare(`\n SELECT project_id, event_id, session_id, visitor_id, event_type, event_name,\n page_path, page_title, referrer, severity, source,\n context_json, properties_json, user_agent, occurred_at,\n received_at, country, browser, os, device_type, is_bot,\n utm_source, utm_medium, utm_campaign\n FROM usage_events\n WHERE project_id = ? AND occurred_at >= ?\n ORDER BY occurred_at DESC\n LIMIT 10000\n `)\n\t\t\t.bind(options.projectId, cutoff)\n\t\t\t.all<UsageEventRow>();\n\n\t\tconst rows = (result.results ?? []).filter((row) =>\n\t\t\tfilterRow(row, options, cutoff),\n\t\t);\n\t\tconst pageMap = new Map<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tpath: string;\n\t\t\t\ttitle: string | null;\n\t\t\t\tviews: number;\n\t\t\t\tsessions: Set<string>;\n\t\t\t\tloadTimes: number[];\n\t\t\t\terrorCount: number;\n\t\t\t}\n\t\t>();\n\t\tconst eventMap = new Map<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\teventName: string;\n\t\t\t\teventType: UsageEventSummary[\"eventType\"];\n\t\t\t\ttotalEvents: number;\n\t\t\t\tsessions: Set<string>;\n\t\t\t}\n\t\t>();\n\t\tconst sessions = new Map<string, UsageEventRow[]>();\n\t\tconst browsers = new Map<string, number>();\n\t\tconst operatingSystems = new Map<string, number>();\n\t\tconst devices = new Map<string, number>();\n\t\tconst countries = new Map<string, number>();\n\t\tconst utmSources = new Map<string, number>();\n\t\tconst utmMediums = new Map<string, number>();\n\t\tconst utmCampaigns = new Map<string, number>();\n\t\tconst hourlyPageViews = new Map<string, number>();\n\t\tconst frontendErrors: UsageErrorSummary[] = [];\n\n\t\tlet pageViews = 0;\n\t\tlet interactions = 0;\n\t\tlet frontendErrorCount = 0;\n\t\tlet botsFiltered = 0;\n\n\t\tfor (const row of rows) {\n\t\t\tif (row.is_bot) botsFiltered += 1;\n\n\t\t\tconst sessionRows = sessions.get(row.session_id) ?? [];\n\t\t\tsessionRows.push(row);\n\t\t\tsessions.set(row.session_id, sessionRows);\n\n\t\t\tconst eventKey = `${row.event_type}:${row.event_name}`;\n\t\t\tconst eventEntry = eventMap.get(eventKey) ?? {\n\t\t\t\teventName: row.event_name,\n\t\t\t\teventType: row.event_type,\n\t\t\t\ttotalEvents: 0,\n\t\t\t\tsessions: new Set<string>(),\n\t\t\t};\n\t\t\teventEntry.totalEvents += 1;\n\t\t\teventEntry.sessions.add(row.session_id);\n\t\t\teventMap.set(eventKey, eventEntry);\n\n\t\t\tif (row.browser)\n\t\t\t\tbrowsers.set(row.browser, (browsers.get(row.browser) ?? 0) + 1);\n\t\t\tif (row.os)\n\t\t\t\toperatingSystems.set(row.os, (operatingSystems.get(row.os) ?? 0) + 1);\n\t\t\tif (row.device_type)\n\t\t\t\tdevices.set(row.device_type, (devices.get(row.device_type) ?? 0) + 1);\n\t\t\tif (row.country)\n\t\t\t\tcountries.set(row.country, (countries.get(row.country) ?? 0) + 1);\n\t\t\tif (row.utm_source)\n\t\t\t\tutmSources.set(\n\t\t\t\t\trow.utm_source,\n\t\t\t\t\t(utmSources.get(row.utm_source) ?? 0) + 1,\n\t\t\t\t);\n\t\t\tif (row.utm_medium)\n\t\t\t\tutmMediums.set(\n\t\t\t\t\trow.utm_medium,\n\t\t\t\t\t(utmMediums.get(row.utm_medium) ?? 0) + 1,\n\t\t\t\t);\n\t\t\tif (row.utm_campaign)\n\t\t\t\tutmCampaigns.set(\n\t\t\t\t\trow.utm_campaign,\n\t\t\t\t\t(utmCampaigns.get(row.utm_campaign) ?? 0) + 1,\n\t\t\t\t);\n\n\t\t\tif (row.event_type === \"page_view\") {\n\t\t\t\tpageViews += 1;\n\t\t\t\tconst hour = `${row.occurred_at.slice(0, 13)}:00:00.000Z`;\n\t\t\t\thourlyPageViews.set(hour, (hourlyPageViews.get(hour) ?? 0) + 1);\n\n\t\t\t\tif (row.page_path) {\n\t\t\t\t\tconst pageEntry = pageMap.get(row.page_path) ?? {\n\t\t\t\t\t\tpath: row.page_path,\n\t\t\t\t\t\ttitle: row.page_title,\n\t\t\t\t\t\tviews: 0,\n\t\t\t\t\t\tsessions: new Set<string>(),\n\t\t\t\t\t\tloadTimes: [],\n\t\t\t\t\t\terrorCount: 0,\n\t\t\t\t\t};\n\t\t\t\t\tpageEntry.views += 1;\n\t\t\t\t\tpageEntry.sessions.add(row.session_id);\n\t\t\t\t\tif (!pageEntry.title && row.page_title)\n\t\t\t\t\t\tpageEntry.title = row.page_title;\n\n\t\t\t\t\t// Multi-key load time parsing (from A)\n\t\t\t\t\tconst properties = parseJsonRecord(row.properties_json);\n\t\t\t\t\tconst loadTimeValue =\n\t\t\t\t\t\tproperties.loadTimeMs ??\n\t\t\t\t\t\tproperties.load_time_ms ??\n\t\t\t\t\t\tproperties.durationMs;\n\t\t\t\t\tconst loadTime =\n\t\t\t\t\t\ttypeof loadTimeValue === \"number\"\n\t\t\t\t\t\t\t? loadTimeValue\n\t\t\t\t\t\t\t: typeof loadTimeValue === \"string\"\n\t\t\t\t\t\t\t\t? Number(loadTimeValue)\n\t\t\t\t\t\t\t\t: NaN;\n\t\t\t\t\tif (Number.isFinite(loadTime)) pageEntry.loadTimes.push(loadTime);\n\n\t\t\t\t\tpageMap.set(row.page_path, pageEntry);\n\t\t\t\t}\n\t\t\t} else if (row.event_type === \"interaction\") {\n\t\t\t\tinteractions += 1;\n\t\t\t} else if (row.event_type === \"frontend_error\") {\n\t\t\t\tfrontendErrorCount += 1;\n\t\t\t\tconst properties = parseJsonRecord(row.properties_json);\n\t\t\t\tfrontendErrors.push({\n\t\t\t\t\teventId: row.event_id,\n\t\t\t\t\tsessionId: row.session_id,\n\t\t\t\t\tpagePath: row.page_path,\n\t\t\t\t\terrorName:\n\t\t\t\t\t\ttypeof properties.errorName === \"string\"\n\t\t\t\t\t\t\t? properties.errorName\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\terrorMessage:\n\t\t\t\t\t\ttypeof properties.errorMessage === \"string\"\n\t\t\t\t\t\t\t? properties.errorMessage\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\tcomponent:\n\t\t\t\t\t\ttypeof properties.component === \"string\"\n\t\t\t\t\t\t\t? properties.component\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\toccurredAt: row.occurred_at,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Broader error detection (from A)\n\t\t\tif (\n\t\t\t\trow.page_path &&\n\t\t\t\t(row.event_type === \"frontend_error\" || row.severity === \"error\")\n\t\t\t) {\n\t\t\t\tconst pageEntry = pageMap.get(row.page_path) ?? {\n\t\t\t\t\tpath: row.page_path,\n\t\t\t\t\ttitle: row.page_title,\n\t\t\t\t\tviews: 0,\n\t\t\t\t\tsessions: new Set<string>(),\n\t\t\t\t\tloadTimes: [],\n\t\t\t\t\terrorCount: 0,\n\t\t\t\t};\n\t\t\t\tpageEntry.errorCount += 1;\n\t\t\t\tpageMap.set(row.page_path, pageEntry);\n\t\t\t}\n\t\t}\n\n\t\tconst pages: UsagePageSummary[] = Array.from(pageMap.values())\n\t\t\t.map((entry) => ({\n\t\t\t\tpath: entry.path,\n\t\t\t\ttitle: entry.title,\n\t\t\t\tviews: entry.views,\n\t\t\t\tuniqueSessions: entry.sessions.size,\n\t\t\t\taverageLoadTimeMs:\n\t\t\t\t\tentry.loadTimes.length > 0\n\t\t\t\t\t\t? Math.round(\n\t\t\t\t\t\t\t\tentry.loadTimes.reduce((sum, v) => sum + v, 0) /\n\t\t\t\t\t\t\t\t\tentry.loadTimes.length,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: 0,\n\t\t\t\terrorCount: entry.errorCount,\n\t\t\t}))\n\t\t\t.sort(\n\t\t\t\t(left, right) =>\n\t\t\t\t\tright.views - left.views || left.path.localeCompare(right.path),\n\t\t\t)\n\t\t\t.slice(0, options.limit ?? 20);\n\n\t\tconst recentSessions = Array.from(sessions.values())\n\t\t\t.map((sessionRows) => toSessionSummary(sessionRows))\n\t\t\t.sort((left, right) => right.lastSeen.localeCompare(left.lastSeen))\n\t\t\t.slice(0, 20);\n\n\t\treturn {\n\t\t\tsummary: {\n\t\t\t\ttotalEvents: rows.length,\n\t\t\t\tuniqueSessions: sessions.size,\n\t\t\t\tuniqueVisitors: new Set(rows.map((row) => row.visitor_id)).size,\n\t\t\t\tpageViews,\n\t\t\t\tfrontendErrors: frontendErrorCount,\n\t\t\t\tinteractions,\n\t\t\t},\n\t\t\tpages,\n\t\t\tevents: Array.from(eventMap.values())\n\t\t\t\t.map((entry) => ({\n\t\t\t\t\teventName: entry.eventName,\n\t\t\t\t\teventType: entry.eventType,\n\t\t\t\t\ttotalEvents: entry.totalEvents,\n\t\t\t\t\tuniqueSessions: entry.sessions.size,\n\t\t\t\t}))\n\t\t\t\t.sort(\n\t\t\t\t\t(left, right) =>\n\t\t\t\t\t\tright.totalEvents - left.totalEvents ||\n\t\t\t\t\t\tleft.eventName.localeCompare(right.eventName),\n\t\t\t\t)\n\t\t\t\t.slice(0, 20),\n\t\t\trecentSessions,\n\t\t\tfrontendErrors: frontendErrors\n\t\t\t\t.sort((left, right) => right.occurredAt.localeCompare(left.occurredAt))\n\t\t\t\t.slice(0, 20),\n\t\t\tbrowsers: summarizeMap<UsageBrowserSummary>(\n\t\t\t\tbrowsers,\n\t\t\t\t(browser, count) => ({ browser, count }),\n\t\t\t),\n\t\t\toperatingSystems: summarizeMap<UsageOSSummary>(\n\t\t\t\toperatingSystems,\n\t\t\t\t(os, count) => ({ os, count }),\n\t\t\t),\n\t\t\tdevices: summarizeMap<UsageDeviceSummary>(devices, (device, count) => ({\n\t\t\t\tdevice,\n\t\t\t\tcount,\n\t\t\t})),\n\t\t\tcountries: summarizeMap<UsageCountrySummary>(\n\t\t\t\tcountries,\n\t\t\t\t(country, count) => ({ country, count }),\n\t\t\t),\n\t\t\tutmSources: summarizeMap<UsageUtmSourceSummary>(\n\t\t\t\tutmSources,\n\t\t\t\t(source, count) => ({ source, count }),\n\t\t\t),\n\t\t\tutmMediums: summarizeMap<UsageUtmMediumSummary>(\n\t\t\t\tutmMediums,\n\t\t\t\t(medium, count) => ({ medium, count }),\n\t\t\t),\n\t\t\tutmCampaigns: summarizeMap<UsageUtmCampaignSummary>(\n\t\t\t\tutmCampaigns,\n\t\t\t\t(campaign, count) => ({ campaign, count }),\n\t\t\t),\n\t\t\thourlyPageViews: Array.from(hourlyPageViews.entries())\n\t\t\t\t.map(([hour, count]) => ({ hour, count }))\n\t\t\t\t.sort((left, right) => left.hour.localeCompare(right.hour)),\n\t\t\tbotsFiltered,\n\t\t\tfilters: {\n\t\t\t\tpath: options.path ?? \"all\",\n\t\t\t\tincludeAdmin: options.includeAdmin ?? false,\n\t\t\t},\n\t\t\twindowHours: options.hours,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\t}\n\n\tasync getSessionDetail(\n\t\tsessionId: string,\n\t\tprojectId: string,\n\t): Promise<UsageSessionDetailResponse | null> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"UsageStore.getSessionDetail: projectId is required\");\n\t\tconst result = await this.db\n\t\t\t.prepare(`\n SELECT project_id, event_id, session_id, visitor_id, event_type, event_name,\n page_path, page_title, referrer, severity, source,\n context_json, properties_json, user_agent, occurred_at,\n received_at, country, browser, os, device_type, is_bot,\n utm_source, utm_medium, utm_campaign, interaction_id\n FROM usage_events\n WHERE project_id = ? AND session_id = ?\n ORDER BY occurred_at ASC\n `)\n\t\t\t.bind(projectId, sessionId)\n\t\t\t.all<UsageEventRow>();\n\n\t\tconst rows = result.results ?? [];\n\t\tif (rows.length === 0) return null;\n\n\t\treturn {\n\t\t\tsession: toSessionSummary(rows),\n\t\t\tevents: rows.map((row) => ({\n\t\t\t\teventId: row.event_id,\n\t\t\t\teventType: row.event_type,\n\t\t\t\teventName: row.event_name,\n\t\t\t\tpagePath: row.page_path,\n\t\t\t\tpageTitle: row.page_title,\n\t\t\t\tseverity: row.severity ?? \"info\",\n\t\t\t\toccurredAt: row.occurred_at,\n\t\t\t\tproperties: parseJsonRecord(row.properties_json),\n\t\t\t\tcontext: parseJsonRecord(row.context_json),\n\t\t\t\tinteractionId: row.interaction_id ?? null,\n\t\t\t})),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\t}\n\n\t/**\n\t * List sessions with an optional qualitative filter.\n\t *\n\t * Aggregates per session_id in a single query; supports three filters\n\t * derived from session-level rollups: sessions that errored, sessions\n\t * with no interactions (engagement drop-off), and sessions with slow\n\t * page loads.\n\t */\n\tasync listSessions(options: {\n\t\tprojectId: string;\n\t\thours: number;\n\t\tfilter: \"all\" | \"ended_in_error\" | \"dropoff\" | \"slow\";\n\t\tslowMs?: number;\n\t\tlimit?: number;\n\t}): Promise<{\n\t\tsessions: Array<\n\t\t\tUsageSessionSummary & {\n\t\t\t\tinteractionCount: number;\n\t\t\t\tmaxLoadTimeMs: number | null;\n\t\t\t}\n\t\t>;\n\t}> {\n\t\tif (!options.projectId)\n\t\t\tthrow new Error(\"UsageStore.listSessions: projectId is required\");\n\t\tconst cutoff = cutoffIso(options.hours);\n\t\tconst dialect = dialectFor(this.db);\n\t\tconst slowMs = options.slowMs ?? 3000;\n\t\tconst limit = Math.max(1, Math.min(1000, options.limit ?? 200));\n\t\tconst loadMsExpr = dialect.jsonText(\"properties_json\", \"$.loadTimeMs\");\n\t\tconst loadTimeMsExpr = dialect.jsonText(\n\t\t\t\"properties_json\",\n\t\t\t\"$.load_time_ms\",\n\t\t);\n\t\tconst durationMsExpr = dialect.jsonText(\"properties_json\", \"$.durationMs\");\n\n\t\tconst result = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT\n\t\t\t\t\tsession_id,\n\t\t\t\t\tMIN(visitor_id) AS visitor_id,\n\t\t\t\t\tMIN(occurred_at) AS first_seen,\n\t\t\t\t\tMAX(occurred_at) AS last_seen,\n\t\t\t\t\tCOUNT(*) AS event_count,\n\t\t\t\t\tSUM(CASE WHEN event_type = 'page_view' THEN 1 ELSE 0 END) AS page_view_count,\n\t\t\t\t\tSUM(CASE WHEN event_type = 'interaction' THEN 1 ELSE 0 END) AS interaction_count,\n\t\t\t\t\tSUM(CASE WHEN event_type = 'frontend_error' OR severity = 'error' THEN 1 ELSE 0 END) AS error_count,\n\t\t\t\t\tMAX(CASE WHEN event_type = 'page_view' THEN CAST(COALESCE(${loadMsExpr}, ${loadTimeMsExpr}, ${durationMsExpr}) AS REAL) ELSE NULL END) AS max_load_ms,\n\t\t\t\t\t(SELECT referrer FROM usage_events ref WHERE ref.project_id = ue.project_id AND ref.session_id = ue.session_id ORDER BY occurred_at ASC LIMIT 1) AS referrer,\n\t\t\t\t\t(SELECT page_path FROM usage_events lp WHERE lp.project_id = ue.project_id AND lp.session_id = ue.session_id ORDER BY occurred_at DESC LIMIT 1) AS last_path\n\t\t\t\tFROM usage_events ue\n\t\t\t\tWHERE project_id = ? AND received_at >= ?\n\t\t\t\tGROUP BY session_id\n\t\t\t\tORDER BY last_seen DESC\n\t\t\t\tLIMIT ?`,\n\t\t\t)\n\t\t\t.bind(options.projectId, cutoff, limit * 3)\n\t\t\t.all<{\n\t\t\t\tsession_id: string;\n\t\t\t\tvisitor_id: string;\n\t\t\t\tfirst_seen: string;\n\t\t\t\tlast_seen: string;\n\t\t\t\tevent_count: number;\n\t\t\t\tpage_view_count: number;\n\t\t\t\tinteraction_count: number;\n\t\t\t\terror_count: number;\n\t\t\t\tmax_load_ms: number | null;\n\t\t\t\treferrer: string | null;\n\t\t\t\tlast_path: string | null;\n\t\t\t}>();\n\n\t\tconst raw = (result.results ?? []).map((r) => ({\n\t\t\tsessionId: r.session_id,\n\t\t\tvisitorId: r.visitor_id,\n\t\t\tfirstSeen: r.first_seen,\n\t\t\tlastSeen: r.last_seen,\n\t\t\teventCount: r.event_count,\n\t\t\tpageViewCount: r.page_view_count,\n\t\t\terrorCount: r.error_count,\n\t\t\tlastPath: r.last_path,\n\t\t\treferrer: r.referrer,\n\t\t\tinteractionCount: r.interaction_count,\n\t\t\tmaxLoadTimeMs: r.max_load_ms,\n\t\t}));\n\n\t\tconst filtered = raw.filter((s) => {\n\t\t\tswitch (options.filter) {\n\t\t\t\tcase \"ended_in_error\":\n\t\t\t\t\treturn s.errorCount > 0;\n\t\t\t\tcase \"dropoff\":\n\t\t\t\t\treturn s.pageViewCount >= 1 && s.interactionCount === 0;\n\t\t\t\tcase \"slow\":\n\t\t\t\t\treturn s.maxLoadTimeMs !== null && s.maxLoadTimeMs >= slowMs;\n\t\t\t\tdefault:\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\n\t\treturn { sessions: filtered.slice(0, limit) };\n\t}\n\n\tasync purgeExpired(): Promise<number> {\n\t\tconst now = new Date().toISOString();\n\t\tconst result = await this.db\n\t\t\t.prepare(\"DELETE FROM usage_events WHERE expires_at <= ?\")\n\t\t\t.bind(now)\n\t\t\t.run();\n\t\treturn result.meta?.changes ?? 0;\n\t}\n}\n","import type { JsonValue, StoredSpan } from \"@obsunified/types\";\nimport {\n\tACTION_CAUSED_BY_ID_KEY,\n\tACTION_CONFIDENCE_KEY,\n\tACTION_ID_KEY,\n\tACTION_KIND_KEY,\n\tACTION_MODEL_NAME_KEY,\n\tACTION_NAME_KEY,\n\tACTION_PROMPT_VERSION_KEY,\n\tACTION_PROVIDER_KEY,\n\tACTION_ROOT_ID_KEY,\n\tACTION_TOTAL_COST_USD_KEY,\n\tACTOR_ID_KEY,\n\tACTOR_TYPE_KEY,\n\tAGENT_AUTONOMY_LEVEL_KEY,\n\tAGENT_GOAL_KEY,\n\tAGENT_ID_KEY,\n\tAGENT_NAME_KEY,\n\tAGENT_OUTCOME_KEY,\n\tAGENT_RUN_ID_KEY,\n\tAGENT_STEP_ID_KEY,\n\tAGENT_VERSION_KEY,\n\tAI_PAYLOAD_INPUT_KEY,\n\tAI_PAYLOAD_OUTPUT_KEY,\n\tARTIFACT_CONTENT_KEY,\n\tARTIFACT_NAME_KEY,\n\tARTIFACT_SHA256_HASH_KEY,\n\tARTIFACT_SIZE_BYTES_KEY,\n\tARTIFACT_STORAGE_REF_KEY,\n\tARTIFACT_TYPE_KEY,\n\tEVAL_EVALUATOR_NAME_KEY,\n\tEVAL_EVALUATOR_VERSION_KEY,\n\tEVAL_PASSED_KEY,\n\tEVAL_REASONING_KEY,\n\tEVAL_RUBRIC_KEY,\n\tEVAL_SCORE_KEY,\n\tOPENINFERENCE_SPAN_KIND_KEY,\n\tRETRIEVAL_DOCUMENTS_KEY,\n\tRETRIEVAL_MAX_RELEVANCE_SCORE_KEY,\n\tRETRIEVAL_NAME_KEY,\n\tRETRIEVAL_QUERY_KEY,\n\tRETRIEVAL_TOTAL_RESULTS_KEY,\n\tTOOL_APPROVAL_STATE_KEY,\n\tTOOL_ARGS_KEY,\n\tTOOL_CALL_ID_KEY,\n\tTOOL_ERROR_TYPE_KEY,\n\tTOOL_NAME_KEY,\n\tTOOL_RESULT_KEY,\n\tTOOL_SIDE_EFFECT_KEY,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { resolveActionIdentity } from \"../lib/action-identity\";\nimport { sha256Hex } from \"../lib/hash\";\nimport { parseJsonRecord } from \"../lib/json\";\nimport { isPayloadCaptureEnabled } from \"../lib/payload-capture\";\nimport { type SqlStatement, sqlDbFor } from \"../lib/sql-db\";\n\nimport { enricherPlugins } from \"./action-graph-processor/enrichers\";\nimport { runRedaction } from \"./action-graph-processor/redaction\";\n\nconst firstAttr = (\n\tattrs: Record<string, JsonValue>,\n\t...keys: string[]\n): JsonValue | undefined => {\n\tfor (const key of keys) {\n\t\tconst value = attrs[key];\n\t\tif (value !== undefined && value !== null) return value;\n\t}\n\treturn undefined;\n};\n\nconst firstStringAttr = (\n\tattrs: Record<string, JsonValue>,\n\t...keys: string[]\n): string | undefined => {\n\tconst value = firstAttr(attrs, ...keys);\n\treturn typeof value === \"string\" ? value : undefined;\n};\n\nconst firstNumberAttr = (\n\tattrs: Record<string, JsonValue>,\n\t...keys: string[]\n): number | null => {\n\tconst value = firstAttr(attrs, ...keys);\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\") {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn null;\n};\n\nconst toFiniteNumber = (value: unknown): number | null => {\n\tif (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n\tif (typeof value === \"string\") {\n\t\tconst parsed = Number(value);\n\t\treturn Number.isFinite(parsed) ? parsed : null;\n\t}\n\treturn null;\n};\n\nconst firstBoolLikeAttr = (\n\tattrs: Record<string, JsonValue>,\n\t...keys: string[]\n): boolean => {\n\tconst value = firstAttr(attrs, ...keys);\n\treturn value === true || value === 1 || value === \"1\" || value === \"true\";\n};\n\nconst firstJsonAttr = (\n\tattrs: Record<string, JsonValue>,\n\t...keys: string[]\n): string | null => {\n\tconst value = firstAttr(attrs, ...keys);\n\tif (value === undefined || value === null) return null;\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\treturn trimmed.length > 0 ? trimmed : null;\n\t}\n\treturn JSON.stringify(value);\n};\n\nconst parseJsonObject = (raw: string): Record<string, JsonValue> | null => {\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\tif (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n\t\t\treturn parsed as Record<string, JsonValue>;\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n\treturn null;\n};\n\nconst normalizeMcpAuditJson = (\n\tattrs: Record<string, JsonValue>,\n): string | null => {\n\tconst raw = firstJsonAttr(\n\t\tattrs,\n\t\t\"obs.mcp.audit\",\n\t\t\"obs.mcp.audit_json\",\n\t\t\"mcp.audit\",\n\t\t\"mcp.audit_json\",\n\t);\n\tif (!raw) return null;\n\n\tconst parsed = parseJsonObject(raw);\n\tif (!parsed) return null;\n\n\tconst presentFields = Array.isArray(parsed.presentFields)\n\t\t? parsed.presentFields.filter(\n\t\t\t\t(field): field is string => typeof field === \"string\",\n\t\t\t)\n\t\t: null;\n\tconst allowedFields =\n\t\tparsed.allowedFields &&\n\t\ttypeof parsed.allowedFields === \"object\" &&\n\t\t!Array.isArray(parsed.allowedFields)\n\t\t\t? (parsed.allowedFields as Record<string, JsonValue>)\n\t\t\t: null;\n\n\tif (!presentFields || !allowedFields) return null;\n\n\tconst redactedFields = Array.isArray(parsed.redactedFields)\n\t\t? parsed.redactedFields.filter(\n\t\t\t\t(field): field is string => typeof field === \"string\",\n\t\t\t)\n\t\t: [];\n\tconst droppedFields = Array.isArray(parsed.droppedFields)\n\t\t? parsed.droppedFields.filter(\n\t\t\t\t(field): field is string => typeof field === \"string\",\n\t\t\t)\n\t\t: [];\n\tconst hashedFields =\n\t\tparsed.hashedFields &&\n\t\ttypeof parsed.hashedFields === \"object\" &&\n\t\t!Array.isArray(parsed.hashedFields)\n\t\t\t? (parsed.hashedFields as Record<string, JsonValue>)\n\t\t\t: {};\n\n\treturn JSON.stringify({\n\t\tschemaVersion: toFiniteNumber(parsed.schemaVersion) ?? 1,\n\t\tpresentFields,\n\t\tallowedFields,\n\t\tredactedFields,\n\t\thashedFields,\n\t\tdroppedFields,\n\t\thasRawMeta: parsed.hasRawMeta === true,\n\t});\n};\n\nconst normalizeMcpAuditEnvelope = (\n\tattrs: Record<string, JsonValue>,\n): Record<string, JsonValue> | null => {\n\tconst json = normalizeMcpAuditJson(attrs);\n\tif (!json) return null;\n\treturn parseJsonObject(json);\n};\n\nconst normalizeMutationArtifactId = (\n\tattrs: Record<string, JsonValue>,\n): string | null =>\n\tfirstStringAttr(\n\t\tattrs,\n\t\t\"obs.tool_call.mutation.artifact_id\",\n\t\t\"obs.tool.mutation.artifact_id\",\n\t\t\"tool.mutation.artifact_id\",\n\t) ?? null;\n\nconst EVIDENCE_ATTR_KEYS = [\n\t\"obs.mcp.audit\",\n\t\"obs.mcp.audit_json\",\n\t\"mcp.audit\",\n\t\"mcp.audit_json\",\n\t\"obs.tool_call.mutation.before\",\n\t\"obs.tool_call.mutation.after\",\n\t\"obs.tool_call.mutation.diff\",\n\t\"obs.tool.mutation.before\",\n\t\"obs.tool.mutation.after\",\n\t\"obs.tool.mutation.diff\",\n\t\"tool.mutation.before\",\n\t\"tool.mutation.after\",\n\t\"tool.mutation.diff\",\n];\n\nconst PAYLOAD_ATTR_KEYS = [\n\tAI_PAYLOAD_INPUT_KEY,\n\tAI_PAYLOAD_OUTPUT_KEY,\n\tAGENT_GOAL_KEY,\n\t\"obs.agent_run.goal\",\n\tAGENT_OUTCOME_KEY,\n\t\"obs.agent_run.outcome\",\n\tTOOL_ARGS_KEY,\n\t\"obs.tool_call.args\",\n\tTOOL_RESULT_KEY,\n\t\"obs.tool_call.result\",\n\tRETRIEVAL_QUERY_KEY,\n\tRETRIEVAL_DOCUMENTS_KEY,\n\tARTIFACT_CONTENT_KEY,\n\tEVAL_REASONING_KEY,\n\tEVAL_RUBRIC_KEY,\n\t...EVIDENCE_ATTR_KEYS,\n];\n\nconst stripPayloadAttrs = (\n\tattrs: Record<string, JsonValue>,\n): Record<string, JsonValue> => {\n\tconst next = { ...attrs };\n\tfor (const key of PAYLOAD_ATTR_KEYS) {\n\t\tdelete next[key];\n\t}\n\treturn next;\n};\n\nexport type { ActionEnricherPlugin } from \"./action-graph-processor/enrichers\";\nexport {\n\tclearActionEnricherPlugins,\n\tregisterActionEnricherPlugin,\n} from \"./action-graph-processor/enrichers\";\nexport type {\n\tPayloadRedactorPlugin,\n\tRedactionContext,\n} from \"./action-graph-processor/redaction\";\nexport {\n\tclearRedactionPlugins,\n\tregisterRedactionPlugin,\n\trunRedaction,\n} from \"./action-graph-processor/redaction\";\n\nexport const actionGraphProcessorPlugin: CollectorPlugin = {\n\tname: \"action-graph-processor\",\n\tregister(_app, runtime) {\n\t\truntime.addSpanProcessor({\n\t\t\tname: \"action-graph-processor\",\n\t\t\tasync process(spans, context) {\n\t\t\t\tconst db = sqlDbFor(context.env);\n\t\t\t\tconst captureByProject = new Map<string, boolean>();\n\t\t\t\tconst projectCaptureEnabled = async (projectId: string) => {\n\t\t\t\t\tconst cached = captureByProject.get(projectId);\n\t\t\t\t\tif (cached !== undefined) return cached;\n\t\t\t\t\tconst enabled = await isPayloadCaptureEnabled(\n\t\t\t\t\t\tdb,\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tcontext.env,\n\t\t\t\t\t);\n\t\t\t\t\tcaptureByProject.set(projectId, enabled);\n\t\t\t\t\treturn enabled;\n\t\t\t\t};\n\n\t\t\t\tconst actionsToInsert: Record<string, unknown>[] = [];\n\t\t\t\tconst agentRunsToInsert: Record<string, unknown>[] = [];\n\t\t\t\tconst toolCallsToInsert: Record<string, unknown>[] = [];\n\t\t\t\tconst retrievalsToInsert: Record<string, unknown>[] = [];\n\t\t\t\tconst evalsToInsert: Record<string, unknown>[] = [];\n\t\t\t\tconst artifactsToInsert: Record<string, unknown>[] = [];\n\n\t\t\t\tconst transformed = await Promise.all(\n\t\t\t\t\tspans.map(async (span): Promise<StoredSpan> => {\n\t\t\t\t\t\tconst attrs = parseJsonRecord(span.attributesJson);\n\t\t\t\t\t\tconst capturePayloads = await projectCaptureEnabled(span.projectId);\n\n\t\t\t\t\t\tconst obsActionId = attrs[ACTION_ID_KEY];\n\t\t\t\t\t\tconst openInferenceKind = attrs[OPENINFERENCE_SPAN_KIND_KEY];\n\t\t\t\t\t\tconst genAiAgentId = attrs[\"gen_ai.agent.id\"];\n\n\t\t\t\t\t\tconst isActionSpan =\n\t\t\t\t\t\t\tobsActionId !== undefined ||\n\t\t\t\t\t\t\topenInferenceKind !== undefined ||\n\t\t\t\t\t\t\tgenAiAgentId !== undefined;\n\t\t\t\t\t\tif (!isActionSpan) return span;\n\n\t\t\t\t\t\tconst actionKind =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, ACTION_KIND_KEY) ??\n\t\t\t\t\t\t\t(openInferenceKind as string) ??\n\t\t\t\t\t\t\t\"agent.step\";\n\t\t\t\t\t\tconst identity = await resolveActionIdentity(span, {\n\t\t\t\t\t\t\t...attrs,\n\t\t\t\t\t\t\t[ACTION_KIND_KEY]: actionKind,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst actionId = identity.actionId;\n\t\t\t\t\t\tconst rootActionId = identity.rootActionId;\n\t\t\t\t\t\tconst causedByActionId = identity.causedByActionId;\n\t\t\t\t\t\tconst trustedAttrs: Record<string, JsonValue> = {\n\t\t\t\t\t\t\t...attrs,\n\t\t\t\t\t\t\t[ACTION_ID_KEY]: actionId,\n\t\t\t\t\t\t\t[ACTION_ROOT_ID_KEY]: rootActionId,\n\t\t\t\t\t\t\t[ACTION_CONFIDENCE_KEY]: identity.confidence,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tconst mcpAuditEnvelope = normalizeMcpAuditEnvelope(attrs);\n\t\t\t\t\t\tif (mcpAuditEnvelope) {\n\t\t\t\t\t\t\ttrustedAttrs[\"obs.mcp.audit_envelope\"] = mcpAuditEnvelope;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (const key of EVIDENCE_ATTR_KEYS) {\n\t\t\t\t\t\t\tdelete trustedAttrs[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdelete trustedAttrs[\"obs.action.agent_run_id\"];\n\t\t\t\t\t\tdelete trustedAttrs[\"obs.agent_run.id\"];\n\t\t\t\t\t\tif (causedByActionId !== undefined) {\n\t\t\t\t\t\t\ttrustedAttrs[ACTION_CAUSED_BY_ID_KEY] = causedByActionId;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst actorType =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, ACTOR_TYPE_KEY, \"obs.action.actor_type\") ??\n\t\t\t\t\t\t\t\"agent\";\n\t\t\t\t\t\tconst actorId =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, ACTOR_ID_KEY, \"obs.action.actor_id\") ??\n\t\t\t\t\t\t\t(genAiAgentId as string) ??\n\t\t\t\t\t\t\tnull;\n\t\t\t\t\t\tconst name =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, ACTION_NAME_KEY) ?? span.spanName;\n\t\t\t\t\t\tconst status = span.statusCode === 2 ? \"error\" : \"ok\";\n\t\t\t\t\t\tconst startedAt = span.startTime;\n\t\t\t\t\t\tconst endedAt = span.endTime;\n\t\t\t\t\t\tconst durationMs = span.durationMs;\n\t\t\t\t\t\tconst traceId = span.traceId;\n\t\t\t\t\t\tconst spanId = span.spanId;\n\t\t\t\t\t\tconst sessionId =\n\t\t\t\t\t\t\tspan.sessionId ?? (attrs[\"session.id\"] as string) ?? null;\n\t\t\t\t\t\tconst interactionId =\n\t\t\t\t\t\t\tspan.interactionId ?? (attrs[\"interaction.id\"] as string) ?? null;\n\t\t\t\t\t\tconst userId =\n\t\t\t\t\t\t\t(attrs[\"user.id\"] as string) ??\n\t\t\t\t\t\t\t(attrs[\"enduser.id\"] as string) ??\n\t\t\t\t\t\t\t(attrs[\"obs.user.id\"] as string) ??\n\t\t\t\t\t\t\tnull;\n\n\t\t\t\t\t\tconst agentRunId =\n\t\t\t\t\t\t\tidentity.agentRunId ??\n\t\t\t\t\t\t\t(actionKind === \"agent.run\" || actionKind === \"agent\"\n\t\t\t\t\t\t\t\t? actionId\n\t\t\t\t\t\t\t\t: null);\n\t\t\t\t\t\tif (agentRunId !== null) {\n\t\t\t\t\t\t\ttrustedAttrs[AGENT_RUN_ID_KEY] = agentRunId;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdelete trustedAttrs[AGENT_RUN_ID_KEY];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst stepId =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, AGENT_STEP_ID_KEY, \"obs.action.step_id\") ??\n\t\t\t\t\t\t\tnull;\n\t\t\t\t\t\tconst toolCallId =\n\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\tTOOL_CALL_ID_KEY,\n\t\t\t\t\t\t\t\t\"obs.action.tool_call_id\",\n\t\t\t\t\t\t\t) ?? null;\n\t\t\t\t\t\tconst promptVersion =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, ACTION_PROMPT_VERSION_KEY) ?? null;\n\t\t\t\t\t\tconst modelName =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, ACTION_MODEL_NAME_KEY) ??\n\t\t\t\t\t\t\t(attrs[\"llm.model_name\"] as string) ??\n\t\t\t\t\t\t\tnull;\n\t\t\t\t\t\tconst provider =\n\t\t\t\t\t\t\tfirstStringAttr(attrs, ACTION_PROVIDER_KEY) ??\n\t\t\t\t\t\t\t(attrs[\"llm.provider\"] as string) ??\n\t\t\t\t\t\t\tnull;\n\t\t\t\t\t\tconst totalCostUsd =\n\t\t\t\t\t\t\tfirstNumberAttr(attrs, ACTION_TOTAL_COST_USD_KEY) ??\n\t\t\t\t\t\t\tfirstNumberAttr(\n\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\"llm.cost.total_usd\",\n\t\t\t\t\t\t\t\t\"gen_ai.usage.cost_usd\",\n\t\t\t\t\t\t\t\t\"llm.total_cost_usd\",\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconst persistedAttrs = capturePayloads\n\t\t\t\t\t\t\t? trustedAttrs\n\t\t\t\t\t\t\t: stripPayloadAttrs(trustedAttrs);\n\t\t\t\t\t\tconst attrsJson = JSON.stringify(persistedAttrs);\n\n\t\t\t\t\t\tconst actionRecord = {\n\t\t\t\t\t\t\tid: actionId,\n\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\trootActionId,\n\t\t\t\t\t\t\tcausedByActionId,\n\t\t\t\t\t\t\tactorType,\n\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\tactionKind,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\tstartedAt,\n\t\t\t\t\t\t\tendedAt,\n\t\t\t\t\t\t\tdurationMs,\n\t\t\t\t\t\t\ttraceId,\n\t\t\t\t\t\t\tspanId,\n\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\tinteractionId,\n\t\t\t\t\t\t\tuserId,\n\t\t\t\t\t\t\tagentRunId,\n\t\t\t\t\t\t\tstepId,\n\t\t\t\t\t\t\ttoolCallId,\n\t\t\t\t\t\t\tpromptVersion,\n\t\t\t\t\t\t\tmodelName,\n\t\t\t\t\t\t\tprovider,\n\t\t\t\t\t\t\ttotalCostUsd,\n\t\t\t\t\t\t\tattrsJson,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tfor (const plugin of enricherPlugins) {\n\t\t\t\t\t\t\tif (plugin.enrichActionRecord) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tawait plugin.enrichActionRecord(\n\t\t\t\t\t\t\t\t\t\tactionRecord,\n\t\t\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\t\t\ttrustedAttrs,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\t`[action-enricher-plugin:${plugin.name}] enrichActionRecord failed`,\n\t\t\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tactionsToInsert.push(actionRecord);\n\n\t\t\t\t\t\t// 1. Agent Runs\n\t\t\t\t\t\tconst isAgentRun =\n\t\t\t\t\t\t\tactionKind === \"agent.run\" ||\n\t\t\t\t\t\t\tactionKind === \"agent\" ||\n\t\t\t\t\t\t\tfirstAttr(attrs, AGENT_ID_KEY, \"obs.agent_run.agent_id\") !==\n\t\t\t\t\t\t\t\tundefined;\n\t\t\t\t\t\tif (isAgentRun) {\n\t\t\t\t\t\t\tconst agentRunRecord = {\n\t\t\t\t\t\t\t\tid: actionId,\n\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\tagentId:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\tAGENT_ID_KEY,\n\t\t\t\t\t\t\t\t\t\t\"obs.agent_run.agent_id\",\n\t\t\t\t\t\t\t\t\t) ??\n\t\t\t\t\t\t\t\t\t(genAiAgentId as string) ??\n\t\t\t\t\t\t\t\t\t\"default-agent\",\n\t\t\t\t\t\t\t\tagentName:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\tAGENT_NAME_KEY,\n\t\t\t\t\t\t\t\t\t\t\"obs.agent_run.agent_name\",\n\t\t\t\t\t\t\t\t\t) ?? span.spanName,\n\t\t\t\t\t\t\t\tagentVersion:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\tAGENT_VERSION_KEY,\n\t\t\t\t\t\t\t\t\t\t\"obs.agent_run.agent_version\",\n\t\t\t\t\t\t\t\t\t) ?? \"1.0.0\",\n\t\t\t\t\t\t\t\tgoal: capturePayloads\n\t\t\t\t\t\t\t\t\t? (firstStringAttr(\n\t\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\t\tAGENT_GOAL_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\"obs.agent_run.goal\",\n\t\t\t\t\t\t\t\t\t\t) ??\n\t\t\t\t\t\t\t\t\t\t(attrs[AI_PAYLOAD_INPUT_KEY] as string) ??\n\t\t\t\t\t\t\t\t\t\tnull)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\toutcome: capturePayloads\n\t\t\t\t\t\t\t\t\t? (firstStringAttr(\n\t\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\t\tAGENT_OUTCOME_KEY,\n\t\t\t\t\t\t\t\t\t\t\t\"obs.agent_run.outcome\",\n\t\t\t\t\t\t\t\t\t\t) ??\n\t\t\t\t\t\t\t\t\t\t(attrs[AI_PAYLOAD_OUTPUT_KEY] as string) ??\n\t\t\t\t\t\t\t\t\t\tnull)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\tautonomyLevel:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\tAGENT_AUTONOMY_LEVEL_KEY,\n\t\t\t\t\t\t\t\t\t\t\"obs.agent_run.autonomy_level\",\n\t\t\t\t\t\t\t\t\t) ?? \"autonomous_write\",\n\t\t\t\t\t\t\t\tstatus: span.statusCode === 2 ? \"failed\" : \"success\",\n\t\t\t\t\t\t\t\terrorMessage: span.statusMessage ?? null,\n\t\t\t\t\t\t\t\ttotalCostUsd: totalCostUsd ?? 0.0,\n\t\t\t\t\t\t\t\ttotalDurationMs: span.durationMs,\n\t\t\t\t\t\t\t\tmetadataJson: attrsJson,\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tfor (const plugin of enricherPlugins) {\n\t\t\t\t\t\t\t\tif (plugin.enrichAgentRunRecord) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait plugin.enrichAgentRunRecord(\n\t\t\t\t\t\t\t\t\t\t\tagentRunRecord,\n\t\t\t\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\t\t\t\ttrustedAttrs,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\t\t`[action-enricher-plugin:${plugin.name}] enrichAgentRunRecord failed`,\n\t\t\t\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tagentRunsToInsert.push(agentRunRecord);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 2. Tool Calls\n\t\t\t\t\t\tconst isToolCall =\n\t\t\t\t\t\t\tactionKind === \"tool\" ||\n\t\t\t\t\t\t\tactionKind === \"tool.call\" ||\n\t\t\t\t\t\t\tfirstAttr(attrs, TOOL_NAME_KEY, \"obs.tool_call.tool_name\") !==\n\t\t\t\t\t\t\t\tundefined;\n\t\t\t\t\t\tif (isToolCall) {\n\t\t\t\t\t\t\tconst rawArgs =\n\t\t\t\t\t\t\t\tfirstStringAttr(attrs, TOOL_ARGS_KEY, \"obs.tool_call.args\") ??\n\t\t\t\t\t\t\t\t(attrs[AI_PAYLOAD_INPUT_KEY] as string) ??\n\t\t\t\t\t\t\t\t\"{}\";\n\t\t\t\t\t\t\tconst rawResult =\n\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\tTOOL_RESULT_KEY,\n\t\t\t\t\t\t\t\t\t\"obs.tool_call.result\",\n\t\t\t\t\t\t\t\t) ??\n\t\t\t\t\t\t\t\t(attrs[AI_PAYLOAD_OUTPUT_KEY] as string) ??\n\t\t\t\t\t\t\t\t\"{}\";\n\n\t\t\t\t\t\t\tconst argsHash = await sha256Hex(rawArgs);\n\t\t\t\t\t\t\tconst resultHash = await sha256Hex(rawResult);\n\n\t\t\t\t\t\t\tconst redactedArgs = capturePayloads\n\t\t\t\t\t\t\t\t? await runRedaction(rawArgs, {\n\t\t\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\t\t\ttraceId: span.traceId,\n\t\t\t\t\t\t\t\t\t\tspanId: span.spanId,\n\t\t\t\t\t\t\t\t\t\tkind: \"tool_call\",\n\t\t\t\t\t\t\t\t\t\tfieldName: \"args\",\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\tconst redactedResult = capturePayloads\n\t\t\t\t\t\t\t\t? await runRedaction(rawResult, {\n\t\t\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\t\t\ttraceId: span.traceId,\n\t\t\t\t\t\t\t\t\t\tspanId: span.spanId,\n\t\t\t\t\t\t\t\t\t\tkind: \"tool_call\",\n\t\t\t\t\t\t\t\t\t\tfieldName: \"result\",\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\t\tconst toolCallRecord = {\n\t\t\t\t\t\t\t\tid: span.spanId,\n\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\ttoolName:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\tTOOL_NAME_KEY,\n\t\t\t\t\t\t\t\t\t\t\"obs.tool_call.tool_name\",\n\t\t\t\t\t\t\t\t\t) ?? span.spanName,\n\t\t\t\t\t\t\t\targsHash,\n\t\t\t\t\t\t\t\tresultHash,\n\t\t\t\t\t\t\t\terrorType:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\tTOOL_ERROR_TYPE_KEY,\n\t\t\t\t\t\t\t\t\t\t\"obs.tool_call.error_type\",\n\t\t\t\t\t\t\t\t\t) ??\n\t\t\t\t\t\t\t\t\tspan.statusMessage ??\n\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\tsideEffect: firstBoolLikeAttr(\n\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\tTOOL_SIDE_EFFECT_KEY,\n\t\t\t\t\t\t\t\t\t\"obs.tool_call.side_effect\",\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t? 1\n\t\t\t\t\t\t\t\t\t: 0,\n\t\t\t\t\t\t\t\tapprovalState:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(\n\t\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\tTOOL_APPROVAL_STATE_KEY,\n\t\t\t\t\t\t\t\t\t\t\"obs.tool_call.approval_state\",\n\t\t\t\t\t\t\t\t\t) ?? \"suggested\",\n\t\t\t\t\t\t\t\targsRedacted:\n\t\t\t\t\t\t\t\t\tredactedArgs === null\n\t\t\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t\t\t: typeof redactedArgs === \"string\"\n\t\t\t\t\t\t\t\t\t\t\t? redactedArgs\n\t\t\t\t\t\t\t\t\t\t\t: JSON.stringify(redactedArgs),\n\t\t\t\t\t\t\t\tresultRedacted:\n\t\t\t\t\t\t\t\t\tredactedResult === null\n\t\t\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t\t\t: typeof redactedResult === \"string\"\n\t\t\t\t\t\t\t\t\t\t\t? redactedResult\n\t\t\t\t\t\t\t\t\t\t\t: JSON.stringify(redactedResult),\n\t\t\t\t\t\t\t\tmcpAuditJson: normalizeMcpAuditJson(attrs),\n\t\t\t\t\t\t\t\tmutationBeforeJson: firstJsonAttr(\n\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\"obs.tool_call.mutation.before\",\n\t\t\t\t\t\t\t\t\t\"obs.tool.mutation.before\",\n\t\t\t\t\t\t\t\t\t\"tool.mutation.before\",\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tmutationAfterJson: firstJsonAttr(\n\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\"obs.tool_call.mutation.after\",\n\t\t\t\t\t\t\t\t\t\"obs.tool.mutation.after\",\n\t\t\t\t\t\t\t\t\t\"tool.mutation.after\",\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tmutationDiffJson: firstJsonAttr(\n\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\t\"obs.tool_call.mutation.diff\",\n\t\t\t\t\t\t\t\t\t\"obs.tool.mutation.diff\",\n\t\t\t\t\t\t\t\t\t\"tool.mutation.diff\",\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tmutationArtifactId: normalizeMutationArtifactId(attrs),\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tfor (const plugin of enricherPlugins) {\n\t\t\t\t\t\t\t\tif (plugin.enrichToolCallRecord) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait plugin.enrichToolCallRecord(\n\t\t\t\t\t\t\t\t\t\t\ttoolCallRecord,\n\t\t\t\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\t\t\t\ttrustedAttrs,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\t\t`[action-enricher-plugin:${plugin.name}] enrichToolCallRecord failed`,\n\t\t\t\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttoolCallsToInsert.push(toolCallRecord);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 3. Retrieval Events\n\t\t\t\t\t\tconst isRetrieval =\n\t\t\t\t\t\t\tactionKind === \"retriever\" ||\n\t\t\t\t\t\t\tactionKind === \"retrieval\" ||\n\t\t\t\t\t\t\tattrs[RETRIEVAL_NAME_KEY] !== undefined;\n\t\t\t\t\t\tif (isRetrieval) {\n\t\t\t\t\t\t\tconst rawQuery =\n\t\t\t\t\t\t\t\tfirstStringAttr(attrs, RETRIEVAL_QUERY_KEY) ??\n\t\t\t\t\t\t\t\t(attrs[AI_PAYLOAD_INPUT_KEY] as string) ??\n\t\t\t\t\t\t\t\t\"\";\n\t\t\t\t\t\t\tconst rawDocs =\n\t\t\t\t\t\t\t\tfirstStringAttr(attrs, RETRIEVAL_DOCUMENTS_KEY) ??\n\t\t\t\t\t\t\t\t(attrs[AI_PAYLOAD_OUTPUT_KEY] as string) ??\n\t\t\t\t\t\t\t\t\"[]\";\n\n\t\t\t\t\t\t\tconst queryHash = await sha256Hex(rawQuery);\n\t\t\t\t\t\t\tconst redactedDocs = capturePayloads\n\t\t\t\t\t\t\t\t? await runRedaction(rawDocs, {\n\t\t\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\t\t\ttraceId: span.traceId,\n\t\t\t\t\t\t\t\t\t\tspanId: span.spanId,\n\t\t\t\t\t\t\t\t\t\tkind: \"retrieval\",\n\t\t\t\t\t\t\t\t\t\tfieldName: \"documents\",\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\t\tconst retrievalRecord = {\n\t\t\t\t\t\t\t\tid: span.spanId,\n\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\tretrieverName:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(attrs, RETRIEVAL_NAME_KEY) ?? span.spanName,\n\t\t\t\t\t\t\t\tqueryHash,\n\t\t\t\t\t\t\t\tdocumentsJson:\n\t\t\t\t\t\t\t\t\tredactedDocs === null\n\t\t\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t\t\t: typeof redactedDocs === \"string\"\n\t\t\t\t\t\t\t\t\t\t\t? redactedDocs\n\t\t\t\t\t\t\t\t\t\t\t: JSON.stringify(redactedDocs),\n\t\t\t\t\t\t\t\ttotalResults:\n\t\t\t\t\t\t\t\t\tfirstNumberAttr(attrs, RETRIEVAL_TOTAL_RESULTS_KEY) ?? 0,\n\t\t\t\t\t\t\t\tmaxRelevanceScore: firstNumberAttr(\n\t\t\t\t\t\t\t\t\tattrs,\n\t\t\t\t\t\t\t\t\tRETRIEVAL_MAX_RELEVANCE_SCORE_KEY,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tdurationMs: span.durationMs,\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tfor (const plugin of enricherPlugins) {\n\t\t\t\t\t\t\t\tif (plugin.enrichRetrievalRecord) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait plugin.enrichRetrievalRecord(\n\t\t\t\t\t\t\t\t\t\t\tretrievalRecord,\n\t\t\t\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\t\t\t\ttrustedAttrs,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\t\t`[action-enricher-plugin:${plugin.name}] enrichRetrievalRecord failed`,\n\t\t\t\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tretrievalsToInsert.push(retrievalRecord);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 4. Evaluation Results\n\t\t\t\t\t\tconst isEval =\n\t\t\t\t\t\t\tactionKind === \"evaluator\" ||\n\t\t\t\t\t\t\tactionKind === \"eval\" ||\n\t\t\t\t\t\t\tattrs[EVAL_EVALUATOR_NAME_KEY] !== undefined;\n\t\t\t\t\t\tif (isEval) {\n\t\t\t\t\t\t\tconst evalRecord = {\n\t\t\t\t\t\t\t\tid: span.spanId,\n\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\tevaluatorName:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(attrs, EVAL_EVALUATOR_NAME_KEY) ??\n\t\t\t\t\t\t\t\t\tspan.spanName,\n\t\t\t\t\t\t\t\tevaluatorVersion:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(attrs, EVAL_EVALUATOR_VERSION_KEY) ?? \"1.0.0\",\n\t\t\t\t\t\t\t\tscore: firstNumberAttr(attrs, EVAL_SCORE_KEY),\n\t\t\t\t\t\t\t\tpassed:\n\t\t\t\t\t\t\t\t\tattrs[EVAL_PASSED_KEY] !== undefined\n\t\t\t\t\t\t\t\t\t\t? firstBoolLikeAttr(attrs, EVAL_PASSED_KEY)\n\t\t\t\t\t\t\t\t\t\t\t? 1\n\t\t\t\t\t\t\t\t\t\t\t: 0\n\t\t\t\t\t\t\t\t\t\t: 1,\n\t\t\t\t\t\t\t\treasoning: firstStringAttr(attrs, EVAL_REASONING_KEY) ?? null,\n\t\t\t\t\t\t\t\trubricJson: firstStringAttr(attrs, EVAL_RUBRIC_KEY) ?? null,\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tfor (const plugin of enricherPlugins) {\n\t\t\t\t\t\t\t\tif (plugin.enrichEvalRecord) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait plugin.enrichEvalRecord(\n\t\t\t\t\t\t\t\t\t\t\tevalRecord,\n\t\t\t\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\t\t\t\ttrustedAttrs,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\t\t`[action-enricher-plugin:${plugin.name}] enrichEvalRecord failed`,\n\t\t\t\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tevalsToInsert.push(evalRecord);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 5. Generated Artifacts\n\t\t\t\t\t\tconst hasArtifact = attrs[ARTIFACT_NAME_KEY] !== undefined;\n\t\t\t\t\t\tif (hasArtifact) {\n\t\t\t\t\t\t\tconst content =\n\t\t\t\t\t\t\t\tfirstStringAttr(attrs, ARTIFACT_CONTENT_KEY) ?? \"\";\n\t\t\t\t\t\t\tconst redactedContent = capturePayloads\n\t\t\t\t\t\t\t\t? await runRedaction(content, {\n\t\t\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\t\t\ttraceId: span.traceId,\n\t\t\t\t\t\t\t\t\t\tspanId: span.spanId,\n\t\t\t\t\t\t\t\t\t\tkind: \"artifact\",\n\t\t\t\t\t\t\t\t\t\tfieldName: \"content\",\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\t\tconst artifactRecord = {\n\t\t\t\t\t\t\t\tid: span.spanId,\n\t\t\t\t\t\t\t\tactionId,\n\t\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\t\tartifactName: attrs[ARTIFACT_NAME_KEY] as string,\n\t\t\t\t\t\t\t\tartifactType:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(attrs, ARTIFACT_TYPE_KEY) ?? \"text\",\n\t\t\t\t\t\t\t\tstorageRef:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(attrs, ARTIFACT_STORAGE_REF_KEY) ?? null,\n\t\t\t\t\t\t\t\tsizeBytes: firstNumberAttr(attrs, ARTIFACT_SIZE_BYTES_KEY),\n\t\t\t\t\t\t\t\tsha256Hash:\n\t\t\t\t\t\t\t\t\tfirstStringAttr(attrs, ARTIFACT_SHA256_HASH_KEY) ??\n\t\t\t\t\t\t\t\t\t(await sha256Hex(content)),\n\t\t\t\t\t\t\t\tcontentPreview:\n\t\t\t\t\t\t\t\t\tredactedContent === null\n\t\t\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t\t\t: typeof redactedContent === \"string\"\n\t\t\t\t\t\t\t\t\t\t\t? redactedContent\n\t\t\t\t\t\t\t\t\t\t\t: JSON.stringify(redactedContent),\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tfor (const plugin of enricherPlugins) {\n\t\t\t\t\t\t\t\tif (plugin.enrichArtifactRecord) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait plugin.enrichArtifactRecord(\n\t\t\t\t\t\t\t\t\t\t\tartifactRecord,\n\t\t\t\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\t\t\t\ttrustedAttrs,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\t\t`[action-enricher-plugin:${plugin.name}] enrichArtifactRecord failed`,\n\t\t\t\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tartifactsToInsert.push(artifactRecord);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Downstream compatibility: ensure payload routing can join action_id.\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...span,\n\t\t\t\t\t\t\tattributesJson: JSON.stringify(trustedAttrs),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tconst statements: SqlStatement[] = [];\n\n\t\t\t\tif (agentRunsToInsert.length > 0 && actionsToInsert.length > 0) {\n\t\t\t\t\tfor (const run of agentRunsToInsert) {\n\t\t\t\t\t\tconst runId = String(run.id);\n\t\t\t\t\t\tconst childActions = actionsToInsert.filter(\n\t\t\t\t\t\t\t(action) =>\n\t\t\t\t\t\t\t\taction.rootActionId === runId ||\n\t\t\t\t\t\t\t\taction.agentRunId === runId ||\n\t\t\t\t\t\t\t\taction.id === runId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst childCost = childActions\n\t\t\t\t\t\t\t.filter((action) => action.id !== runId)\n\t\t\t\t\t\t\t.reduce(\n\t\t\t\t\t\t\t\t(sum, action) =>\n\t\t\t\t\t\t\t\t\tsum + (toFiniteNumber(action.totalCostUsd) ?? 0),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tconst runOwnCost = toFiniteNumber(run.totalCostUsd) ?? 0;\n\t\t\t\t\t\trun.totalCostUsd = Math.max(runOwnCost, childCost);\n\n\t\t\t\t\t\tconst starts = childActions\n\t\t\t\t\t\t\t.map((action) =>\n\t\t\t\t\t\t\t\ttypeof action.startedAt === \"string\"\n\t\t\t\t\t\t\t\t\t? Date.parse(action.startedAt)\n\t\t\t\t\t\t\t\t\t: NaN,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(Number.isFinite);\n\t\t\t\t\t\tconst ends = childActions\n\t\t\t\t\t\t\t.map((action) =>\n\t\t\t\t\t\t\t\ttypeof action.endedAt === \"string\"\n\t\t\t\t\t\t\t\t\t? Date.parse(action.endedAt)\n\t\t\t\t\t\t\t\t\t: NaN,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(Number.isFinite);\n\t\t\t\t\t\tconst wallClockMs =\n\t\t\t\t\t\t\tstarts.length > 0 && ends.length > 0\n\t\t\t\t\t\t\t\t? Math.max(...ends) - Math.min(...starts)\n\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\tconst maxActionDuration = childActions.reduce(\n\t\t\t\t\t\t\t(max, action) =>\n\t\t\t\t\t\t\t\tMath.max(max, toFiniteNumber(action.durationMs) ?? 0),\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst existingDuration = toFiniteNumber(run.totalDurationMs) ?? 0;\n\t\t\t\t\t\trun.totalDurationMs = Math.max(\n\t\t\t\t\t\t\texistingDuration,\n\t\t\t\t\t\t\twallClockMs ?? 0,\n\t\t\t\t\t\t\tmaxActionDuration,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (actionsToInsert.length > 0) {\n\t\t\t\t\tconst stmt = db.prepare(`\n\t\t\t\t\t\tINSERT INTO actions (\n\t\t\t\t\t\t\tid, project_id, root_action_id, caused_by_action_id, actor_type, actor_id,\n\t\t\t\t\t\t\taction_kind, name, status, started_at, ended_at, duration_ms, trace_id,\n\t\t\t\t\t\t\tspan_id, session_id, interaction_id, user_id, agent_run_id, step_id,\n\t\t\t\t\t\t\ttool_call_id, prompt_version, model_name, provider, total_cost_usd, attrs_json\n\t\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\t\t\tON CONFLICT (id) DO UPDATE SET\n\t\t\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\t\t\troot_action_id = excluded.root_action_id,\n\t\t\t\t\t\t\tcaused_by_action_id = excluded.caused_by_action_id,\n\t\t\t\t\t\t\tactor_type = excluded.actor_type,\n\t\t\t\t\t\t\tactor_id = excluded.actor_id,\n\t\t\t\t\t\t\taction_kind = excluded.action_kind,\n\t\t\t\t\t\t\tname = excluded.name,\n\t\t\t\t\t\t\tstatus = excluded.status,\n\t\t\t\t\t\t\tstarted_at = excluded.started_at,\n\t\t\t\t\t\t\tended_at = excluded.ended_at,\n\t\t\t\t\t\t\tduration_ms = excluded.duration_ms,\n\t\t\t\t\t\t\ttrace_id = excluded.trace_id,\n\t\t\t\t\t\t\tspan_id = excluded.span_id,\n\t\t\t\t\t\t\tsession_id = excluded.session_id,\n\t\t\t\t\t\t\tinteraction_id = excluded.interaction_id,\n\t\t\t\t\t\t\tuser_id = excluded.user_id,\n\t\t\t\t\t\t\tagent_run_id = excluded.agent_run_id,\n\t\t\t\t\t\t\tstep_id = excluded.step_id,\n\t\t\t\t\t\t\ttool_call_id = excluded.tool_call_id,\n\t\t\t\t\t\t\tprompt_version = excluded.prompt_version,\n\t\t\t\t\t\t\tmodel_name = excluded.model_name,\n\t\t\t\t\t\t\tprovider = excluded.provider,\n\t\t\t\t\t\t\ttotal_cost_usd = excluded.total_cost_usd,\n\t\t\t\t\t\t\tattrs_json = excluded.attrs_json\n\t\t\t\t\t`);\n\t\t\t\t\tfor (const r of actionsToInsert) {\n\t\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t\tstmt.bind(\n\t\t\t\t\t\t\t\tr.id,\n\t\t\t\t\t\t\t\tr.projectId,\n\t\t\t\t\t\t\t\tr.rootActionId,\n\t\t\t\t\t\t\t\tr.causedByActionId,\n\t\t\t\t\t\t\t\tr.actorType,\n\t\t\t\t\t\t\t\tr.actorId,\n\t\t\t\t\t\t\t\tr.actionKind,\n\t\t\t\t\t\t\t\tr.name,\n\t\t\t\t\t\t\t\tr.status,\n\t\t\t\t\t\t\t\tr.startedAt,\n\t\t\t\t\t\t\t\tr.endedAt,\n\t\t\t\t\t\t\t\tr.durationMs,\n\t\t\t\t\t\t\t\tr.traceId,\n\t\t\t\t\t\t\t\tr.spanId,\n\t\t\t\t\t\t\t\tr.sessionId,\n\t\t\t\t\t\t\t\tr.interactionId,\n\t\t\t\t\t\t\t\tr.userId,\n\t\t\t\t\t\t\t\tr.agentRunId,\n\t\t\t\t\t\t\t\tr.stepId,\n\t\t\t\t\t\t\t\tr.toolCallId,\n\t\t\t\t\t\t\t\tr.promptVersion,\n\t\t\t\t\t\t\t\tr.modelName,\n\t\t\t\t\t\t\t\tr.provider,\n\t\t\t\t\t\t\t\tr.totalCostUsd,\n\t\t\t\t\t\t\t\tr.attrsJson,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (agentRunsToInsert.length > 0) {\n\t\t\t\t\tconst stmt = db.prepare(`\n\t\t\t\t\t\tINSERT INTO agent_runs (\n\t\t\t\t\t\t\tid, project_id, agent_id, agent_name, agent_version, goal, outcome,\n\t\t\t\t\t\t\tautonomy_level, status, error_message, total_cost_usd, total_duration_ms, metadata_json\n\t\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\t\t\tON CONFLICT (id) DO UPDATE SET\n\t\t\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\t\t\tagent_id = excluded.agent_id,\n\t\t\t\t\t\t\tagent_name = excluded.agent_name,\n\t\t\t\t\t\t\tagent_version = excluded.agent_version,\n\t\t\t\t\t\t\tgoal = excluded.goal,\n\t\t\t\t\t\t\toutcome = excluded.outcome,\n\t\t\t\t\t\t\tautonomy_level = excluded.autonomy_level,\n\t\t\t\t\t\t\tstatus = excluded.status,\n\t\t\t\t\t\t\terror_message = excluded.error_message,\n\t\t\t\t\t\t\ttotal_cost_usd = excluded.total_cost_usd,\n\t\t\t\t\t\t\ttotal_duration_ms = excluded.total_duration_ms,\n\t\t\t\t\t\t\tmetadata_json = excluded.metadata_json\n\t\t\t\t\t`);\n\t\t\t\t\tfor (const r of agentRunsToInsert) {\n\t\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t\tstmt.bind(\n\t\t\t\t\t\t\t\tr.id,\n\t\t\t\t\t\t\t\tr.projectId,\n\t\t\t\t\t\t\t\tr.agentId,\n\t\t\t\t\t\t\t\tr.agentName,\n\t\t\t\t\t\t\t\tr.agentVersion,\n\t\t\t\t\t\t\t\tr.goal,\n\t\t\t\t\t\t\t\tr.outcome,\n\t\t\t\t\t\t\t\tr.autonomyLevel,\n\t\t\t\t\t\t\t\tr.status,\n\t\t\t\t\t\t\t\tr.errorMessage,\n\t\t\t\t\t\t\t\tr.totalCostUsd,\n\t\t\t\t\t\t\t\tr.totalDurationMs,\n\t\t\t\t\t\t\t\tr.metadataJson,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (toolCallsToInsert.length > 0) {\n\t\t\t\t\tconst stmt = db.prepare(`\n\t\t\t\t\t\tINSERT INTO tool_calls (\n\t\t\t\t\t\t\tid, action_id, project_id, tool_name, args_hash, result_hash,\n\t\t\t\t\t\t\terror_type, side_effect, approval_state, args_redacted, result_redacted,\n\t\t\t\t\t\t\tmcp_audit_json, mutation_before_json, mutation_after_json,\n\t\t\t\t\t\t\tmutation_diff_json, mutation_artifact_id\n\t\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\t\t\tON CONFLICT (id) DO UPDATE SET\n\t\t\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\t\t\ttool_name = excluded.tool_name,\n\t\t\t\t\t\t\targs_hash = excluded.args_hash,\n\t\t\t\t\t\t\tresult_hash = excluded.result_hash,\n\t\t\t\t\t\t\terror_type = excluded.error_type,\n\t\t\t\t\t\t\tside_effect = excluded.side_effect,\n\t\t\t\t\t\t\tapproval_state = excluded.approval_state,\n\t\t\t\t\t\t\targs_redacted = excluded.args_redacted,\n\t\t\t\t\t\t\tresult_redacted = excluded.result_redacted,\n\t\t\t\t\t\t\tmcp_audit_json = excluded.mcp_audit_json,\n\t\t\t\t\t\t\tmutation_before_json = excluded.mutation_before_json,\n\t\t\t\t\t\t\tmutation_after_json = excluded.mutation_after_json,\n\t\t\t\t\t\t\tmutation_diff_json = excluded.mutation_diff_json,\n\t\t\t\t\t\t\tmutation_artifact_id = excluded.mutation_artifact_id\n\t\t\t\t\t`);\n\t\t\t\t\tfor (const r of toolCallsToInsert) {\n\t\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t\tstmt.bind(\n\t\t\t\t\t\t\t\tr.id,\n\t\t\t\t\t\t\t\tr.actionId,\n\t\t\t\t\t\t\t\tr.projectId,\n\t\t\t\t\t\t\t\tr.toolName,\n\t\t\t\t\t\t\t\tr.argsHash,\n\t\t\t\t\t\t\t\tr.resultHash,\n\t\t\t\t\t\t\t\tr.errorType,\n\t\t\t\t\t\t\t\tr.sideEffect,\n\t\t\t\t\t\t\t\tr.approvalState,\n\t\t\t\t\t\t\t\tr.argsRedacted,\n\t\t\t\t\t\t\t\tr.resultRedacted,\n\t\t\t\t\t\t\t\tr.mcpAuditJson,\n\t\t\t\t\t\t\t\tr.mutationBeforeJson,\n\t\t\t\t\t\t\t\tr.mutationAfterJson,\n\t\t\t\t\t\t\t\tr.mutationDiffJson,\n\t\t\t\t\t\t\t\tr.mutationArtifactId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (retrievalsToInsert.length > 0) {\n\t\t\t\t\tconst stmt = db.prepare(`\n\t\t\t\t\t\tINSERT INTO retrieval_events (\n\t\t\t\t\t\t\tid, action_id, project_id, retriever_name, query_hash, documents_json,\n\t\t\t\t\t\t\ttotal_results, max_relevance_score, duration_ms\n\t\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\t\t\tON CONFLICT (id) DO UPDATE SET\n\t\t\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\t\t\tretriever_name = excluded.retriever_name,\n\t\t\t\t\t\t\tquery_hash = excluded.query_hash,\n\t\t\t\t\t\t\tdocuments_json = excluded.documents_json,\n\t\t\t\t\t\t\ttotal_results = excluded.total_results,\n\t\t\t\t\t\t\tmax_relevance_score = excluded.max_relevance_score,\n\t\t\t\t\t\t\tduration_ms = excluded.duration_ms\n\t\t\t\t\t`);\n\t\t\t\t\tfor (const r of retrievalsToInsert) {\n\t\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t\tstmt.bind(\n\t\t\t\t\t\t\t\tr.id,\n\t\t\t\t\t\t\t\tr.actionId,\n\t\t\t\t\t\t\t\tr.projectId,\n\t\t\t\t\t\t\t\tr.retrieverName,\n\t\t\t\t\t\t\t\tr.queryHash,\n\t\t\t\t\t\t\t\tr.documentsJson,\n\t\t\t\t\t\t\t\tr.totalResults,\n\t\t\t\t\t\t\t\tr.maxRelevanceScore,\n\t\t\t\t\t\t\t\tr.durationMs,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (evalsToInsert.length > 0) {\n\t\t\t\t\tconst stmt = db.prepare(`\n\t\t\t\t\t\tINSERT INTO eval_results (\n\t\t\t\t\t\t\tid, action_id, project_id, evaluator_name, evaluator_version,\n\t\t\t\t\t\t\tscore, passed, reasoning, rubric_json\n\t\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\t\t\tON CONFLICT (id) DO UPDATE SET\n\t\t\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\t\t\tevaluator_name = excluded.evaluator_name,\n\t\t\t\t\t\t\tevaluator_version = excluded.evaluator_version,\n\t\t\t\t\t\t\tscore = excluded.score,\n\t\t\t\t\t\t\tpassed = excluded.passed,\n\t\t\t\t\t\t\treasoning = excluded.reasoning,\n\t\t\t\t\t\t\trubric_json = excluded.rubric_json\n\t\t\t\t\t`);\n\t\t\t\t\tfor (const r of evalsToInsert) {\n\t\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t\tstmt.bind(\n\t\t\t\t\t\t\t\tr.id,\n\t\t\t\t\t\t\t\tr.actionId,\n\t\t\t\t\t\t\t\tr.projectId,\n\t\t\t\t\t\t\t\tr.evaluatorName,\n\t\t\t\t\t\t\t\tr.evaluatorVersion,\n\t\t\t\t\t\t\t\tr.score,\n\t\t\t\t\t\t\t\tr.passed,\n\t\t\t\t\t\t\t\tr.reasoning,\n\t\t\t\t\t\t\t\tr.rubricJson,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (artifactsToInsert.length > 0) {\n\t\t\t\t\tconst stmt = db.prepare(`\n\t\t\t\t\t\tINSERT INTO artifacts (\n\t\t\t\t\t\t\tid, action_id, project_id, artifact_name, artifact_type,\n\t\t\t\t\t\t\tstorage_ref, size_bytes, sha256_hash, content_preview\n\t\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\t\t\tON CONFLICT (id) DO UPDATE SET\n\t\t\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\t\t\tartifact_name = excluded.artifact_name,\n\t\t\t\t\t\t\tartifact_type = excluded.artifact_type,\n\t\t\t\t\t\t\tstorage_ref = excluded.storage_ref,\n\t\t\t\t\t\t\tsize_bytes = excluded.size_bytes,\n\t\t\t\t\t\t\tsha256_hash = excluded.sha256_hash,\n\t\t\t\t\t\t\tcontent_preview = excluded.content_preview\n\t\t\t\t\t`);\n\t\t\t\t\tfor (const r of artifactsToInsert) {\n\t\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t\tstmt.bind(\n\t\t\t\t\t\t\t\tr.id,\n\t\t\t\t\t\t\t\tr.actionId,\n\t\t\t\t\t\t\t\tr.projectId,\n\t\t\t\t\t\t\t\tr.artifactName,\n\t\t\t\t\t\t\t\tr.artifactType,\n\t\t\t\t\t\t\t\tr.storageRef,\n\t\t\t\t\t\t\t\tr.sizeBytes,\n\t\t\t\t\t\t\t\tr.sha256Hash,\n\t\t\t\t\t\t\t\tr.contentPreview,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (statements.length > 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait db.batch(statements);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tcontext.logger.error(\"[action-graph-processor] write failed\", {\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn transformed;\n\t\t\t},\n\t\t});\n\t},\n};\n","import type { JsonValue, StoredSpan } from \"@obsunified/types\";\nimport {\n\tACTION_CAUSED_BY_ID_KEY,\n\tACTION_CONFIDENCE_KEY,\n\tACTION_ID_KEY,\n\tACTION_ID_RE,\n\tACTION_KIND_KEY,\n\tACTION_ROOT_ID_KEY,\n\tActionConfidence,\n\tAGENT_RUN_ID_KEY,\n} from \"@obsunified/types/constants\";\nimport { sha256Hex } from \"./hash\";\n\nexport interface ResolvedActionIdentity {\n\tactionId: string;\n\trootActionId: string;\n\tcausedByActionId: string | null;\n\tagentRunId: string | null;\n\tconfidence: ActionConfidence;\n}\n\nexport async function deriveActionId(\n\tprojectId: string,\n\ttraceId: string,\n\tspanId: string,\n): Promise<string> {\n\tconst input = `${projectId}:${traceId}:${spanId}`;\n\tconst hash = await sha256Hex(input);\n\tconst hex = hash.substring(0, 32);\n\tlet num = BigInt(`0x${hex}`);\n\tconst alphabet = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\tlet encoded = \"\";\n\tfor (let i = 0; i < 26; i++) {\n\t\tconst remainder = Number(num % 32n);\n\t\tencoded = alphabet[remainder] + encoded;\n\t\tnum = num / 32n;\n\t}\n\treturn encoded;\n}\n\nexport const asValidActionId = (value: unknown): string | undefined => {\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn ACTION_ID_RE.test(trimmed) ? trimmed : undefined;\n};\n\nconst asConfidence = (value: unknown): ActionConfidence | undefined =>\n\tvalue === ActionConfidence.Explicit || value === ActionConfidence.Fallback\n\t\t? value\n\t\t: undefined;\n\nexport async function resolveActionIdentity(\n\tspan: Pick<StoredSpan, \"projectId\" | \"traceId\" | \"spanId\" | \"parentSpanId\">,\n\tattrs: Record<string, JsonValue>,\n): Promise<ResolvedActionIdentity> {\n\tconst explicitActionId = asValidActionId(attrs[ACTION_ID_KEY]);\n\tconst actionId =\n\t\texplicitActionId ??\n\t\t(await deriveActionId(span.projectId, span.traceId, span.spanId));\n\tconst confidence =\n\t\tasConfidence(attrs[ACTION_CONFIDENCE_KEY]) ??\n\t\t(explicitActionId ? ActionConfidence.Explicit : ActionConfidence.Fallback);\n\tconst actionKind =\n\t\ttypeof attrs[ACTION_KIND_KEY] === \"string\" ? attrs[ACTION_KIND_KEY] : null;\n\n\tconst rootActionId =\n\t\tasValidActionId(attrs[ACTION_ROOT_ID_KEY]) ??\n\t\tasValidActionId(attrs[AGENT_RUN_ID_KEY]) ??\n\t\tasValidActionId(attrs[\"obs.action.agent_run_id\"]) ??\n\t\tasValidActionId(attrs[\"obs.agent_run.id\"]) ??\n\t\t(actionKind === \"agent.run\" || actionKind === \"agent\"\n\t\t\t? actionId\n\t\t\t: await deriveActionId(\n\t\t\t\t\tspan.projectId,\n\t\t\t\t\tspan.traceId,\n\t\t\t\t\tspan.traceId.substring(0, 16),\n\t\t\t\t));\n\n\tconst explicitCausedByActionId = asValidActionId(\n\t\tattrs[ACTION_CAUSED_BY_ID_KEY],\n\t);\n\tlet causedByActionId: string | null;\n\tif (explicitCausedByActionId) {\n\t\tcausedByActionId = explicitCausedByActionId;\n\t} else if (attrs[ACTION_CAUSED_BY_ID_KEY] === null) {\n\t\tcausedByActionId = null;\n\t} else {\n\t\tcausedByActionId = span.parentSpanId\n\t\t\t? await deriveActionId(span.projectId, span.traceId, span.parentSpanId)\n\t\t\t: null;\n\t}\n\n\tconst agentRunId =\n\t\tasValidActionId(attrs[AGENT_RUN_ID_KEY]) ??\n\t\tasValidActionId(attrs[\"obs.action.agent_run_id\"]) ??\n\t\tasValidActionId(attrs[\"obs.agent_run.id\"]) ??\n\t\t(actionKind === \"agent.run\" || actionKind === \"agent\" ? actionId : null);\n\n\treturn {\n\t\tactionId,\n\t\trootActionId,\n\t\tcausedByActionId,\n\t\tagentRunId,\n\t\tconfidence,\n\t};\n}\n","import type { CollectorEnv } from \"../framework/env\";\nimport type { SqlDb } from \"./sql-db\";\n\nexport const isTruthyFlag = (value: unknown): boolean =>\n\tvalue === true || value === 1 || value === \"1\" || value === \"true\";\n\nexport async function isPayloadCaptureEnabled(\n\tdb: SqlDb,\n\tprojectId: string,\n\tenv?: Partial<CollectorEnv>,\n): Promise<boolean> {\n\tif (isTruthyFlag(env?.OBS_PAYLOAD_CAPTURE_DEFAULT)) return true;\n\n\tconst row = await db\n\t\t.prepare(\n\t\t\t`SELECT payload_capture_enabled FROM projects WHERE id = ? LIMIT 1`,\n\t\t)\n\t\t.bind(projectId)\n\t\t.first<{ payload_capture_enabled: boolean | number | string | null }>();\n\n\treturn isTruthyFlag(row?.payload_capture_enabled);\n}\n","import type { StoredSpan } from \"@obsunified/types\";\n\nexport interface ActionEnricherPlugin {\n\tname: string;\n\tenrichActionRecord?(\n\t\trecord: Record<string, unknown>,\n\t\tspan: StoredSpan,\n\t\tattributes: Record<string, unknown>,\n\t): void | Promise<void>;\n\tenrichAgentRunRecord?(\n\t\trecord: Record<string, unknown>,\n\t\tspan: StoredSpan,\n\t\tattributes: Record<string, unknown>,\n\t): void | Promise<void>;\n\tenrichToolCallRecord?(\n\t\trecord: Record<string, unknown>,\n\t\tspan: StoredSpan,\n\t\tattributes: Record<string, unknown>,\n\t): void | Promise<void>;\n\tenrichRetrievalRecord?(\n\t\trecord: Record<string, unknown>,\n\t\tspan: StoredSpan,\n\t\tattributes: Record<string, unknown>,\n\t): void | Promise<void>;\n\tenrichEvalRecord?(\n\t\trecord: Record<string, unknown>,\n\t\tspan: StoredSpan,\n\t\tattributes: Record<string, unknown>,\n\t): void | Promise<void>;\n\tenrichArtifactRecord?(\n\t\trecord: Record<string, unknown>,\n\t\tspan: StoredSpan,\n\t\tattributes: Record<string, unknown>,\n\t): void | Promise<void>;\n}\n\nexport const enricherPlugins: ActionEnricherPlugin[] = [];\n\nexport function registerActionEnricherPlugin(plugin: ActionEnricherPlugin) {\n\tenricherPlugins.push(plugin);\n}\n\nexport function clearActionEnricherPlugins() {\n\tenricherPlugins.length = 0;\n}\n","export interface RedactionContext {\n\tprojectId: string;\n\tactionId: string;\n\ttraceId: string;\n\tspanId: string;\n\tkind: \"tool_call\" | \"retrieval\" | \"eval\" | \"artifact\" | \"agent_run\";\n\tfieldName: \"args\" | \"result\" | \"query\" | \"documents\" | \"content\";\n}\n\nexport interface PayloadRedactorPlugin {\n\tname: string;\n\tredact(\n\t\tvalue: unknown,\n\t\tcontext: RedactionContext,\n\t): unknown | Promise<unknown> | undefined;\n}\n\nconst redactionPlugins: PayloadRedactorPlugin[] = [];\n\nexport function registerRedactionPlugin(plugin: PayloadRedactorPlugin) {\n\tredactionPlugins.push(plugin);\n}\n\nexport function clearRedactionPlugins() {\n\tredactionPlugins.length = 0;\n}\n\n// Default redactor that performs sensitive key scrubbing.\nconst DEFAULT_REDACT_KEYS = new Set([\n\t\"authorization\",\n\t\"cookie\",\n\t\"set-cookie\",\n\t\"password\",\n\t\"passwd\",\n\t\"secret\",\n\t\"token\",\n\t\"api-key\",\n\t\"x-api-key\",\n\t\"email\",\n\t\"enduser.id\",\n]);\n\nfunction shouldRedactKey(key: string): boolean {\n\tconst normalized = key.toLowerCase();\n\tif (DEFAULT_REDACT_KEYS.has(normalized)) return true;\n\tfor (const k of DEFAULT_REDACT_KEYS) {\n\t\tif (normalized.endsWith(k)) return true;\n\t}\n\treturn false;\n}\n\nfunction redactObj(val: unknown): unknown {\n\tif (Array.isArray(val)) {\n\t\treturn val.map(redactObj);\n\t}\n\tif (val && typeof val === \"object\") {\n\t\tconst nextEntries = Object.entries(val).map(([key, nestedValue]) => {\n\t\t\tif (shouldRedactKey(key)) {\n\t\t\t\treturn [key, \"[REDACTED]\"] as const;\n\t\t\t}\n\t\t\treturn [key, redactObj(nestedValue)] as const;\n\t\t});\n\t\treturn Object.fromEntries(nextEntries);\n\t}\n\treturn val;\n}\n\nexport async function runRedaction(\n\tvalue: unknown,\n\tcontext: RedactionContext,\n): Promise<unknown> {\n\tfor (const plugin of redactionPlugins) {\n\t\ttry {\n\t\t\tconst res = await plugin.redact(value, context);\n\t\t\tif (res !== undefined) {\n\t\t\t\treturn res;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(`[redaction-plugin:${plugin.name}] failed`, err);\n\t\t}\n\t}\n\n\treturn redactObj(value);\n}\n","import {\n\tDEFAULT_WINDOW_HOURS,\n\tgetConfiguredRetentionHours,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport {\n\tgetAutonomousReviewAggregates,\n\tgetCostAttributionAggregates,\n\tgetToolReliabilityAggregates,\n\tgetVersionDiffAggregates,\n} from \"../lib/action-aggregates\";\nimport type {\n\tActionRef,\n\tEntityManifestExtended,\n\tEvalResultRef,\n\tToolCallRef,\n} from \"../lib/identity-index\";\nimport { IdentityIndex } from \"../lib/identity-index\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nconst parsePositiveInt = (\n\traw: string | undefined,\n\tfallback: number,\n\tmin: number,\n\tmax: number,\n): number => {\n\tconst parsed = Number.parseInt(raw ?? \"\", 10);\n\tif (!Number.isFinite(parsed)) return fallback;\n\treturn Math.min(max, Math.max(min, parsed));\n};\n\nconst parseWindowHours = (\n\traw: string | undefined,\n\tretentionHours: string | undefined,\n): number => {\n\tconst maxHours = getConfiguredRetentionHours(retentionHours);\n\treturn parsePositiveInt(raw, DEFAULT_WINDOW_HOURS, 1, maxHours);\n};\n\ninterface CompareStep {\n\tkey: string;\n\tindex: number;\n\tactionId: string;\n\tparentActionId: string | null;\n\tactionKind: string;\n\tname: string | null;\n\tstatus: string;\n\tdurationMs: number | null;\n\ttotalCostUsd: number | null;\n\ttoolName: string | null;\n\ttoolCallId: string | null;\n\tevalPassed: boolean | null;\n\tevalScore: number | null;\n\ttraceId: string | null;\n\tspanId: string | null;\n\tcausalConfidence?: string;\n}\n\nconst sortActionSteps = (actions: ActionRef[]): ActionRef[] =>\n\t[...actions].sort((a, b) => {\n\t\tconst time = a.startedAt.localeCompare(b.startedAt);\n\t\tif (time !== 0) return time;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\nconst stepBaseKey = (\n\taction: ActionRef,\n\ttool: ToolCallRef | undefined,\n): string => {\n\tconst name = tool?.toolName ?? action.stepId ?? action.name ?? \"unnamed\";\n\treturn `${action.actionKind}:${name}`.toLowerCase();\n};\n\nconst buildCompareSteps = (manifest: EntityManifestExtended): CompareStep[] => {\n\tconst toolsByAction = new Map<string, ToolCallRef[]>();\n\tfor (const tool of manifest.toolCalls) {\n\t\tconst tools = toolsByAction.get(tool.actionId) ?? [];\n\t\ttools.push(tool);\n\t\ttoolsByAction.set(tool.actionId, tools);\n\t}\n\n\tconst evalsByAction = new Map<string, EvalResultRef[]>();\n\tfor (const evalResult of manifest.evalResults) {\n\t\tconst evals = evalsByAction.get(evalResult.actionId) ?? [];\n\t\tevals.push(evalResult);\n\t\tevalsByAction.set(evalResult.actionId, evals);\n\t}\n\n\tconst seen = new Map<string, number>();\n\treturn sortActionSteps(manifest.actions).map((action, index) => {\n\t\tconst tool = toolsByAction.get(action.id)?.[0];\n\t\tconst evalResult = evalsByAction.get(action.id)?.[0];\n\t\tconst baseKey = stepBaseKey(action, tool);\n\t\tconst count = seen.get(baseKey) ?? 0;\n\t\tseen.set(baseKey, count + 1);\n\t\treturn {\n\t\t\tkey: `${baseKey}#${count}`,\n\t\t\tindex,\n\t\t\tactionId: action.id,\n\t\t\tparentActionId: action.causedByActionId,\n\t\t\tactionKind: action.actionKind,\n\t\t\tname: action.name,\n\t\t\tstatus: action.status,\n\t\t\tdurationMs: action.durationMs,\n\t\t\ttotalCostUsd: action.totalCostUsd,\n\t\t\ttoolName: tool?.toolName ?? null,\n\t\t\ttoolCallId: tool?.id ?? action.toolCallId,\n\t\t\tevalPassed: evalResult ? evalResult.passed !== 0 : null,\n\t\t\tevalScore: evalResult?.score ?? null,\n\t\t\ttraceId: action.traceId,\n\t\t\tspanId: action.spanId,\n\t\t\tcausalConfidence: action.causalConfidence,\n\t\t};\n\t});\n};\n\nconst changedFields = (left: CompareStep, right: CompareStep): string[] => {\n\tconst fields: (keyof CompareStep)[] = [\n\t\t\"parentActionId\",\n\t\t\"actionKind\",\n\t\t\"name\",\n\t\t\"status\",\n\t\t\"durationMs\",\n\t\t\"totalCostUsd\",\n\t\t\"toolName\",\n\t\t\"evalPassed\",\n\t\t\"evalScore\",\n\t\t\"traceId\",\n\t\t\"causalConfidence\",\n\t];\n\treturn fields.filter((field) => left[field] !== right[field]);\n};\n\nconst compareStepSequences = (\n\tleftSteps: CompareStep[],\n\trightSteps: CompareStep[],\n) => {\n\tconst leftByKey = new Map(leftSteps.map((step) => [step.key, step]));\n\tconst rightByKey = new Map(rightSteps.map((step) => [step.key, step]));\n\tconst keys = Array.from(new Set([...leftByKey.keys(), ...rightByKey.keys()]));\n\treturn keys.map((key) => {\n\t\tconst left = leftByKey.get(key) ?? null;\n\t\tconst right = rightByKey.get(key) ?? null;\n\t\tconst fields = left && right ? changedFields(left, right) : [];\n\t\treturn {\n\t\t\tkey,\n\t\t\tchangeType:\n\t\t\t\tleft && right\n\t\t\t\t\t? fields.length > 0\n\t\t\t\t\t\t? \"changed\"\n\t\t\t\t\t\t: \"same\"\n\t\t\t\t\t: left\n\t\t\t\t\t\t? \"removed\"\n\t\t\t\t\t\t: \"added\",\n\t\t\tchangedFields: fields,\n\t\t\tleft,\n\t\t\tright,\n\t\t};\n\t});\n};\n\nconst manifestForComparableId = async (\n\tindex: IdentityIndex,\n\tprojectId: string,\n\tid: string,\n): Promise<EntityManifestExtended> => {\n\tconst byAction = await index.byAction(projectId, id);\n\tif (byAction.actions.some((action) => action.id === id)) return byAction;\n\treturn index.byAgentRun(projectId, id);\n};\n\nexport const actionRoutesPlugin: CollectorPlugin = {\n\tname: \"action-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/actions/aggregates/tool-reliability\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst hours = parseWindowHours(\n\t\t\t\tc.req.query(\"hours\"),\n\t\t\t\tc.env.RETENTION_HOURS,\n\t\t\t);\n\t\t\tconst limit = parsePositiveInt(c.req.query(\"limit\"), 20, 1, 100);\n\t\t\tconst result = await getToolReliabilityAggregates(\n\t\t\t\tsqlDbFor(c.env),\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tlimit,\n\t\t\t);\n\t\t\treturn c.json(result);\n\t\t});\n\n\t\tapp.get(\"/internal/actions/aggregates/cost-attribution\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst hours = parseWindowHours(\n\t\t\t\tc.req.query(\"hours\"),\n\t\t\t\tc.env.RETENTION_HOURS,\n\t\t\t);\n\t\t\tconst limit = parsePositiveInt(c.req.query(\"limit\"), 20, 1, 100);\n\t\t\tconst result = await getCostAttributionAggregates(\n\t\t\t\tsqlDbFor(c.env),\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tlimit,\n\t\t\t);\n\t\t\treturn c.json(result);\n\t\t});\n\n\t\tapp.get(\"/internal/actions/aggregates/autonomous-review\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst hours = parseWindowHours(\n\t\t\t\tc.req.query(\"hours\"),\n\t\t\t\tc.env.RETENTION_HOURS,\n\t\t\t);\n\t\t\tconst limit = parsePositiveInt(c.req.query(\"limit\"), 50, 1, 200);\n\t\t\tconst result = await getAutonomousReviewAggregates(\n\t\t\t\tsqlDbFor(c.env),\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tlimit,\n\t\t\t);\n\t\t\treturn c.json(result);\n\t\t});\n\n\t\tapp.get(\"/internal/actions/aggregates/version-diff\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst result = await getVersionDiffAggregates(\n\t\t\t\tsqlDbFor(c.env),\n\t\t\t\tprojectId,\n\t\t\t\tc.req.query(\"baseline\"),\n\t\t\t\tc.req.query(\"target\"),\n\t\t\t);\n\t\t\treturn c.json(result);\n\t\t});\n\n\t\tapp.get(\"/internal/actions/compare\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst leftId = c.req.query(\"left\");\n\t\t\tconst rightId = c.req.query(\"right\");\n\t\t\tif (!leftId || !rightId) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"left and right query parameters required\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst index = new IdentityIndex(sqlDbFor(c.env));\n\t\t\tconst [leftManifest, rightManifest] = await Promise.all([\n\t\t\t\tmanifestForComparableId(index, projectId, leftId),\n\t\t\t\tmanifestForComparableId(index, projectId, rightId),\n\t\t\t]);\n\t\t\tconst leftSteps = buildCompareSteps(leftManifest);\n\t\t\tconst rightSteps = buildCompareSteps(rightManifest);\n\n\t\t\tif (leftSteps.length === 0 || rightSteps.length === 0) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: \"Not Found\",\n\t\t\t\t\t\tmessage: \"Both comparable action graphs must exist\",\n\t\t\t\t\t},\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn c.json({\n\t\t\t\tprojectId,\n\t\t\t\tleftId,\n\t\t\t\trightId,\n\t\t\t\tleftManifest,\n\t\t\t\trightManifest,\n\t\t\t\tleftSteps,\n\t\t\t\trightSteps,\n\t\t\t\tstepComparisons: compareStepSequences(leftSteps, rightSteps),\n\t\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/actions/:id\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) return c.json({ error: \"id required\" }, 400);\n\n\t\t\tconst index = new IdentityIndex(sqlDbFor(c.env));\n\t\t\tconst manifest = await index.byAction(projectId, id);\n\t\t\tconst action = manifest.actions.find((a) => a.id === id);\n\t\t\tif (!action) {\n\t\t\t\treturn c.json({ error: \"Not Found\", message: \"Action not found\" }, 404);\n\t\t\t}\n\n\t\t\treturn c.json({ action, manifest });\n\t\t});\n\n\t\tapp.get(\"/internal/agent-runs/:id\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) return c.json({ error: \"id required\" }, 400);\n\n\t\t\tconst index = new IdentityIndex(sqlDbFor(c.env));\n\t\t\tconst manifest = await index.byAgentRun(projectId, id);\n\t\t\tconst agentRun = manifest.agentRuns.find((r) => r.id === id);\n\t\t\tif (!agentRun) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Agent run not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn c.json({ agentRun, manifest });\n\t\t});\n\n\t\tapp.get(\"/internal/tool-calls/:id\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) return c.json({ error: \"id required\" }, 400);\n\n\t\t\tconst db = sqlDbFor(c.env);\n\t\t\tconst toolCallRow = await db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT action_id FROM tool_calls\n\t\t\t\t\t\tWHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, id)\n\t\t\t\t.first<{ action_id: string }>();\n\t\t\tif (!toolCallRow) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Tool call not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst index = new IdentityIndex(db);\n\t\t\tconst manifest = await index.byAction(projectId, toolCallRow.action_id);\n\t\t\tconst toolCall = manifest.toolCalls.find((t) => t.id === id);\n\t\t\tif (!toolCall) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Tool call not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn c.json({ toolCall, manifest });\n\t\t});\n\t},\n};\n","import type { SqlDb } from \"./sql-db\";\nimport { dialectFor } from \"./sql-db\";\n\nconst TOP_CAUSERS_LIMIT = 5;\nconst EXEMPLAR_LIMIT = 3;\n\nexport interface ActionAggregateExemplar {\n\tactionId: string;\n\tagentRunId: string | null;\n\ttraceId: string | null;\n\ttoolCallId: string | null;\n\tevalId: string | null;\n\tlabel: string | null;\n\tstatus: string | null;\n\toccurredAt: string | null;\n}\n\nexport interface ToolReliabilityCauser {\n\tid: string;\n\tlabel: string | null;\n\tcount: number;\n}\n\nexport interface ToolReliabilityAggregate {\n\ttoolName: string;\n\tcallCount: number;\n\tp50LatencyMs: number | null;\n\tp95LatencyMs: number | null;\n\terrorCount: number;\n\terrorRate: number;\n\ttimeoutCount: number;\n\ttimeoutRate: number;\n\tretryCount: number;\n\tmalformedArgumentCount: number;\n\tsideEffectCount: number;\n\ttopCausingAgents: ToolReliabilityCauser[];\n\ttopCausingWorkflows: ToolReliabilityCauser[];\n\texemplars: ActionAggregateExemplar[];\n}\n\nexport interface ToolReliabilityResult {\n\tprojectId: string;\n\twindowHours: number;\n\ttools: ToolReliabilityAggregate[];\n\tgeneratedAt: string;\n}\n\nexport interface CostAttributionRow {\n\tdimension: string;\n\tkey: string | null;\n\tlabel: string | null;\n\ttotalCostUsd: number;\n\tactionCount: number;\n\tagentRunCount: number;\n\ttoolCallCount: number;\n\texemplars: ActionAggregateExemplar[];\n}\n\nexport interface CostAttributionResult {\n\tprojectId: string;\n\twindowHours: number;\n\tbyAgent: CostAttributionRow[];\n\tbyRun: CostAttributionRow[];\n\tbyModel: CostAttributionRow[];\n\tbyProvider: CostAttributionRow[];\n\tbyPromptVersion: CostAttributionRow[];\n\tbyTool: CostAttributionRow[];\n\tbyUser: CostAttributionRow[];\n\tbyTenant: CostAttributionRow[];\n\tbyWorkflow: CostAttributionRow[];\n\tgeneratedAt: string;\n}\n\nexport interface AutonomousReviewRow {\n\tid: string;\n\ttoolName: string;\n\tactionId: string;\n\tactionName: string;\n\tagentRunId: string;\n\tagentName: string;\n\tagentVersion: string;\n\tautonomyLevel: string;\n\tsideEffect: boolean;\n\tapprovalState: string;\n\tstatus: \"ok\" | \"error\";\n\terrorSnippet: string | null;\n\ttraceId: string;\n\toccurredAt: string;\n\tmutationEvidence: boolean;\n\tmutationArtifactId: string | null;\n}\n\nexport interface AutonomousReviewResult {\n\tprojectId: string;\n\twindowHours: number;\n\trows: AutonomousReviewRow[];\n\ttimestamp: string;\n}\n\nexport interface VersionDiffMetric {\n\tlabel: string;\n\tbaselineValue: string | number;\n\ttargetValue: string | number;\n\tdeltaValue: string | number | null;\n\tdeltaDirection: \"positive\" | \"negative\" | \"neutral\";\n}\n\nexport interface VersionComparisonResult {\n\tprojectId: string;\n\tbaselineVersion: string;\n\ttargetVersion: string;\n\tmetrics: VersionDiffMetric[];\n\tbaselineExemplars: ActionAggregateExemplar[];\n\ttargetExemplars: ActionAggregateExemplar[];\n\ttimestamp: string;\n}\n\ninterface ToolAggregateRow {\n\ttool_name: string;\n\tcall_count: number;\n\terror_count: number | null;\n\ttimeout_count: number | null;\n\tmalformed_argument_count: number | null;\n\tside_effect_count: number | null;\n}\n\ninterface ToolDetailRow {\n\ttool_name: string;\n\tduration_ms: number | null;\n\tagent_id: string | null;\n\tagent_label: string | null;\n\tworkflow_id: string | null;\n\tworkflow_label: string | null;\n\taction_id: string | null;\n\tagent_run_id: string | null;\n\ttrace_id: string | null;\n\ttool_call_id: string | null;\n\teval_id: string | null;\n\taction_label: string | null;\n\tstatus: string | null;\n\toccurred_at: string | null;\n}\n\ninterface CostRow {\n\tkey: string | null;\n\tlabel: string | null;\n\ttotal_cost_usd: number | null;\n\taction_count: number | null;\n\tagent_run_count: number | null;\n\ttool_call_count: number | null;\n}\n\ninterface ExemplarSqlRow {\n\tdimension_key?: string | null;\n\taction_id: string | null;\n\tagent_run_id: string | null;\n\ttrace_id: string | null;\n\ttool_call_id: string | null;\n\teval_id: string | null;\n\tlabel: string | null;\n\tstatus: string | null;\n\toccurred_at: string | null;\n}\n\ninterface AutonomousReviewSqlRow {\n\tid: string;\n\ttool_name: string;\n\taction_id: string;\n\taction_name: string | null;\n\tagent_run_id: string | null;\n\tagent_name: string | null;\n\tagent_version: string | null;\n\tautonomy_level: string | null;\n\tside_effect: number | null;\n\tapproval_state: string | null;\n\tstatus: string | null;\n\terror_snippet: string | null;\n\ttrace_id: string | null;\n\toccurred_at: string | null;\n\tmutation_evidence: number | null;\n\tmutation_artifact_id: string | null;\n}\n\ninterface VersionStatsRow {\n\tversion: string;\n\trun_count: number | null;\n\tsuccess_count: number | null;\n\tavg_duration_ms: number | null;\n\tavg_cost_usd: number | null;\n\teval_count: number | null;\n\tpassed_eval_count: number | null;\n\tavg_eval_score: number | null;\n\ttool_count: number | null;\n\ttool_error_count: number | null;\n}\n\nconst toNumber = (value: unknown): number => {\n\tconst n = typeof value === \"number\" ? value : Number(value);\n\treturn Number.isFinite(n) ? n : 0;\n};\n\nconst percentile = (values: number[], p: number): number | null => {\n\tconst sorted = values\n\t\t.filter((v) => Number.isFinite(v) && v >= 0)\n\t\t.sort((a, b) => a - b);\n\tif (sorted.length === 0) return null;\n\tconst index = Math.ceil((p / 100) * sorted.length) - 1;\n\treturn sorted[Math.min(Math.max(index, 0), sorted.length - 1)] ?? null;\n};\n\nconst topCausers = (\n\trows: ToolDetailRow[],\n\tidKey: \"agent_id\" | \"workflow_id\",\n\tlabelKey: \"agent_label\" | \"workflow_label\",\n): ToolReliabilityCauser[] => {\n\tconst counts = new Map<string, { label: string | null; count: number }>();\n\tfor (const row of rows) {\n\t\tconst id = row[idKey];\n\t\tif (!id) continue;\n\t\tconst current = counts.get(id) ?? { label: row[labelKey], count: 0 };\n\t\tcurrent.count += 1;\n\t\tif (!current.label && row[labelKey]) current.label = row[labelKey];\n\t\tcounts.set(id, current);\n\t}\n\treturn [...counts.entries()]\n\t\t.map(([id, value]) => ({ id, label: value.label, count: value.count }))\n\t\t.sort((a, b) => b.count - a.count || a.id.localeCompare(b.id))\n\t\t.slice(0, TOP_CAUSERS_LIMIT);\n};\n\nconst exemplarFromRow = (row: ExemplarSqlRow): ActionAggregateExemplar => ({\n\tactionId: row.action_id ?? \"\",\n\tagentRunId: row.agent_run_id ?? null,\n\ttraceId: row.trace_id ?? null,\n\ttoolCallId: row.tool_call_id ?? null,\n\tevalId: row.eval_id ?? null,\n\tlabel: row.label ?? null,\n\tstatus: row.status ?? null,\n\toccurredAt: row.occurred_at ?? null,\n});\n\nconst exemplarsFromRows = (rows: ExemplarSqlRow[]): ActionAggregateExemplar[] =>\n\trows\n\t\t.filter((row) => row.action_id)\n\t\t.map(exemplarFromRow)\n\t\t.slice(0, EXEMPLAR_LIMIT);\n\nconst appendExemplar = (\n\tmap: Map<string, ActionAggregateExemplar[]>,\n\tkey: string | null,\n\trow: ExemplarSqlRow,\n) => {\n\tif (key === null || key === undefined || !row.action_id) return;\n\tconst current = map.get(key) ?? [];\n\tif (current.length >= EXEMPLAR_LIMIT) return;\n\tcurrent.push(exemplarFromRow(row));\n\tmap.set(key, current);\n};\n\nconst costRows = (\n\tdimension: string,\n\trows: CostRow[],\n\texemplars = new Map<string, ActionAggregateExemplar[]>(),\n): CostAttributionRow[] =>\n\trows.map((row) => ({\n\t\tdimension,\n\t\tkey: row.key,\n\t\tlabel: row.label,\n\t\ttotalCostUsd: toNumber(row.total_cost_usd),\n\t\tactionCount: toNumber(row.action_count),\n\t\tagentRunCount: toNumber(row.agent_run_count),\n\t\ttoolCallCount: toNumber(row.tool_call_count),\n\t\texemplars: row.key ? (exemplars.get(row.key) ?? []) : [],\n\t}));\n\nconst inClause = (values: string[]): string => values.map(() => \"?\").join(\", \");\n\nconst actionTenantExpr = (db: SqlDb, alias = \"a\"): string => {\n\tconst dialect = dialectFor(db);\n\treturn `COALESCE(\n\t\t${dialect.jsonText(`${alias}.attrs_json`, '$.\"obs.tenant.id\"')},\n\t\t${dialect.jsonText(`${alias}.attrs_json`, '$.\"tenant.id\"')},\n\t\t${dialect.jsonText(`${alias}.attrs_json`, \"$.tenant_id\")},\n\t\t${dialect.jsonText(`${alias}.attrs_json`, \"$.target_tenant\")}\n\t)`;\n};\n\nconst actionWorkflowExpr = (db: SqlDb, alias = \"a\"): string => {\n\tconst dialect = dialectFor(db);\n\treturn `COALESCE(\n\t\tCASE WHEN ${alias}.actor_type = 'workflow' THEN ${alias}.actor_id ELSE NULL END,\n\t\t${dialect.jsonText(`${alias}.attrs_json`, '$.\"obs.workflow.id\"')},\n\t\t${dialect.jsonText(`${alias}.attrs_json`, '$.\"workflow.id\"')},\n\t\t${dialect.jsonText(`${alias}.attrs_json`, \"$.workflow_id\")},\n\t\t${dialect.jsonText(`${alias}.attrs_json`, \"$.task_id\")}\n\t)`;\n};\n\nexport const getToolReliabilityAggregates = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\twindowHours: number,\n\tlimit: number,\n): Promise<ToolReliabilityResult> => {\n\tconst dialect = dialectFor(db);\n\tconst since = dialect.sinceHours(\"?\");\n\n\tconst aggregateRows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\tt.tool_name,\n\t\t\t\tCOUNT(*) AS call_count,\n\t\t\t\tSUM(CASE WHEN t.error_type IS NOT NULL AND t.error_type <> '' THEN 1 ELSE 0 END) AS error_count,\n\t\t\t\tSUM(CASE\n\t\t\t\t\tWHEN LOWER(COALESCE(t.error_type, '')) LIKE '%timeout%'\n\t\t\t\t\t\tOR LOWER(COALESCE(t.error_type, '')) = 'deadline_exceeded'\n\t\t\t\t\tTHEN 1 ELSE 0\n\t\t\t\tEND) AS timeout_count,\n\t\t\t\tSUM(CASE\n\t\t\t\t\tWHEN LOWER(COALESCE(t.error_type, '')) LIKE '%malformed%'\n\t\t\t\t\t\tOR LOWER(COALESCE(t.error_type, '')) LIKE '%invalid_argument%'\n\t\t\t\t\t\tOR LOWER(COALESCE(t.error_type, '')) LIKE '%invalid_arguments%'\n\t\t\t\t\t\tOR LOWER(COALESCE(t.error_type, '')) LIKE '%schema_validation%'\n\t\t\t\t\t\tOR LOWER(COALESCE(t.error_type, '')) = 'bad_request'\n\t\t\t\t\tTHEN 1 ELSE 0\n\t\t\t\tEND) AS malformed_argument_count,\n\t\t\t\tSUM(CASE WHEN t.side_effect <> 0 THEN 1 ELSE 0 END) AS side_effect_count\n\t\t\tFROM tool_calls t\n\t\t\tLEFT JOIN actions a ON a.project_id = t.project_id AND a.id = t.action_id\n\t\t\tWHERE t.project_id = ? AND (a.started_at IS NULL OR a.started_at >= ${since})\n\t\t\tGROUP BY t.tool_name\n\t\t\tORDER BY call_count DESC, t.tool_name ASC\n\t\t\tLIMIT ?\n\t\t`)\n\t\t.bind(projectId, windowHours, limit)\n\t\t.all<ToolAggregateRow>();\n\n\tconst toolNames = aggregateRows.results.map((row) => row.tool_name);\n\tif (toolNames.length === 0) {\n\t\treturn {\n\t\t\tprojectId,\n\t\t\twindowHours,\n\t\t\ttools: [],\n\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t};\n\t}\n\n\tconst workflowIdExpr = `COALESCE(\n\t\t${actionWorkflowExpr(db, \"a\")},\n\t\t${actionWorkflowExpr(db, \"root\")}\n\t)`;\n\n\tconst detailRows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\tt.tool_name,\n\t\t\t\ta.duration_ms,\n\t\t\t\tCOALESCE(\n\t\t\t\t\tar.agent_id,\n\t\t\t\t\tCASE WHEN a.actor_type = 'agent' THEN a.actor_id ELSE NULL END,\n\t\t\t\t\tCASE WHEN root.actor_type = 'agent' THEN root.actor_id ELSE NULL END\n\t\t\t\t) AS agent_id,\n\t\t\t\tCOALESCE(\n\t\t\t\t\tar.agent_name,\n\t\t\t\t\tCASE WHEN a.actor_type = 'agent' THEN a.name ELSE NULL END,\n\t\t\t\t\tCASE WHEN root.actor_type = 'agent' THEN root.name ELSE NULL END\n\t\t\t\t) AS agent_label,\n\t\t\t\t${workflowIdExpr} AS workflow_id,\n\t\t\t\t${workflowIdExpr} AS workflow_label,\n\t\t\t\ta.id AS action_id,\n\t\t\t\tCOALESCE(a.agent_run_id, a.root_action_id) AS agent_run_id,\n\t\t\t\tCOALESCE(a.trace_id, root.trace_id) AS trace_id,\n\t\t\t\tt.id AS tool_call_id,\n\t\t\t\ter.id AS eval_id,\n\t\t\t\tCOALESCE(a.name, t.tool_name) AS action_label,\n\t\t\t\ta.status,\n\t\t\t\ta.started_at AS occurred_at\n\t\t\tFROM tool_calls t\n\t\t\tLEFT JOIN actions a ON a.project_id = t.project_id AND a.id = t.action_id\n\t\t\tLEFT JOIN actions root ON root.project_id = t.project_id AND root.id = a.root_action_id\n\t\t\tLEFT JOIN agent_runs ar ON ar.project_id = t.project_id AND ar.id = COALESCE(a.agent_run_id, a.root_action_id)\n\t\t\tLEFT JOIN eval_results er ON er.project_id = t.project_id AND er.action_id = a.id\n\t\t\tWHERE t.project_id = ?\n\t\t\t\tAND (a.started_at IS NULL OR a.started_at >= ${since})\n\t\t\t\tAND t.tool_name IN (${inClause(toolNames)})\n\t\t\tORDER BY\n\t\t\t\tCASE WHEN a.status = 'error' OR t.error_type IS NOT NULL THEN 0 ELSE 1 END,\n\t\t\t\ta.started_at DESC\n\t\t`)\n\t\t.bind(projectId, windowHours, ...toolNames)\n\t\t.all<ToolDetailRow>();\n\n\tconst detailsByTool = new Map<string, ToolDetailRow[]>();\n\tfor (const row of detailRows.results) {\n\t\tconst rows = detailsByTool.get(row.tool_name) ?? [];\n\t\trows.push(row);\n\t\tdetailsByTool.set(row.tool_name, rows);\n\t}\n\n\treturn {\n\t\tprojectId,\n\t\twindowHours,\n\t\ttools: aggregateRows.results.map((row) => {\n\t\t\tconst callCount = toNumber(row.call_count);\n\t\t\tconst errorCount = toNumber(row.error_count);\n\t\t\tconst timeoutCount = toNumber(row.timeout_count);\n\t\t\tconst details = detailsByTool.get(row.tool_name) ?? [];\n\t\t\tconst durations = details\n\t\t\t\t.map((detail) => detail.duration_ms)\n\t\t\t\t.filter((duration): duration is number => duration !== null);\n\t\t\treturn {\n\t\t\t\ttoolName: row.tool_name,\n\t\t\t\tcallCount,\n\t\t\t\tp50LatencyMs: percentile(durations, 50),\n\t\t\t\tp95LatencyMs: percentile(durations, 95),\n\t\t\t\terrorCount,\n\t\t\t\terrorRate: callCount > 0 ? errorCount / callCount : 0,\n\t\t\t\ttimeoutCount,\n\t\t\t\ttimeoutRate: callCount > 0 ? timeoutCount / callCount : 0,\n\t\t\t\tretryCount: 0,\n\t\t\t\tmalformedArgumentCount: toNumber(row.malformed_argument_count),\n\t\t\t\tsideEffectCount: toNumber(row.side_effect_count),\n\t\t\t\ttopCausingAgents: topCausers(details, \"agent_id\", \"agent_label\"),\n\t\t\t\ttopCausingWorkflows: topCausers(\n\t\t\t\t\tdetails,\n\t\t\t\t\t\"workflow_id\",\n\t\t\t\t\t\"workflow_label\",\n\t\t\t\t),\n\t\t\t\texemplars: exemplarsFromRows(\n\t\t\t\t\tdetails.map((detail) => ({\n\t\t\t\t\t\taction_id: detail.action_id,\n\t\t\t\t\t\tagent_run_id: detail.agent_run_id,\n\t\t\t\t\t\ttrace_id: detail.trace_id,\n\t\t\t\t\t\ttool_call_id: detail.tool_call_id,\n\t\t\t\t\t\teval_id: detail.eval_id,\n\t\t\t\t\t\tlabel: detail.action_label,\n\t\t\t\t\t\tstatus: detail.status,\n\t\t\t\t\t\toccurred_at: detail.occurred_at,\n\t\t\t\t\t})),\n\t\t\t\t),\n\t\t\t};\n\t\t}),\n\t\tgeneratedAt: new Date().toISOString(),\n\t};\n};\n\nconst groupByActionDimension = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\twindowHours: number,\n\tlimit: number,\n\tdimension: string,\n\tkeyExpr: string,\n\tlabelExpr = keyExpr,\n): Promise<CostAttributionRow[]> => {\n\tconst dialect = dialectFor(db);\n\tconst since = dialect.sinceHours(\"?\");\n\tconst rows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\t${keyExpr} AS key,\n\t\t\t\t${labelExpr} AS label,\n\t\t\t\tCOALESCE(SUM(COALESCE(a.total_cost_usd, 0)), 0) AS total_cost_usd,\n\t\t\t\tCOUNT(*) AS action_count,\n\t\t\t\tCOUNT(DISTINCT a.agent_run_id) AS agent_run_count,\n\t\t\t\t0 AS tool_call_count\n\t\t\tFROM actions a\n\t\t\tWHERE a.project_id = ? AND a.started_at >= ${since}\n\t\t\tGROUP BY 1, 2\n\t\t\tORDER BY total_cost_usd DESC, action_count DESC\n\t\t\tLIMIT ?\n\t\t`)\n\t\t.bind(projectId, windowHours, limit)\n\t\t.all<CostRow>();\n\tconst keys = rows.results\n\t\t.map((row) => row.key)\n\t\t.filter((key): key is string => !!key);\n\tif (keys.length === 0) return costRows(dimension, rows.results);\n\n\tconst exemplarRows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\t${keyExpr} AS dimension_key,\n\t\t\t\ta.id AS action_id,\n\t\t\t\tCOALESCE(a.agent_run_id, a.root_action_id) AS agent_run_id,\n\t\t\t\ta.trace_id,\n\t\t\t\ta.tool_call_id,\n\t\t\t\ter.id AS eval_id,\n\t\t\t\ta.name AS label,\n\t\t\t\ta.status,\n\t\t\t\ta.started_at AS occurred_at\n\t\t\tFROM actions a\n\t\t\tLEFT JOIN eval_results er ON er.project_id = a.project_id AND er.action_id = a.id\n\t\t\tWHERE a.project_id = ?\n\t\t\t\tAND a.started_at >= ${since}\n\t\t\t\tAND ${keyExpr} IN (${inClause(keys)})\n\t\t\tORDER BY COALESCE(a.total_cost_usd, 0) DESC, a.started_at DESC\n\t\t`)\n\t\t.bind(projectId, windowHours, ...keys)\n\t\t.all<ExemplarSqlRow>();\n\tconst exemplars = new Map<string, ActionAggregateExemplar[]>();\n\tfor (const row of exemplarRows.results) {\n\t\tappendExemplar(exemplars, row.dimension_key ?? null, row);\n\t}\n\treturn costRows(dimension, rows.results, exemplars);\n};\n\nconst getAgentCostExemplars = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\twindowHours: number,\n\tkeys: string[],\n): Promise<Map<string, ActionAggregateExemplar[]>> => {\n\tif (keys.length === 0) return new Map();\n\tconst dialect = dialectFor(db);\n\tconst since = dialect.sinceHours(\"?\");\n\tconst rows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\tar.agent_id AS dimension_key,\n\t\t\t\troot.id AS action_id,\n\t\t\t\tar.id AS agent_run_id,\n\t\t\t\troot.trace_id,\n\t\t\t\troot.tool_call_id,\n\t\t\t\ter.id AS eval_id,\n\t\t\t\tar.agent_name AS label,\n\t\t\t\tar.status,\n\t\t\t\troot.started_at AS occurred_at\n\t\t\tFROM agent_runs ar\n\t\t\tLEFT JOIN actions root ON root.project_id = ar.project_id AND root.id = ar.id\n\t\t\tLEFT JOIN eval_results er ON er.project_id = ar.project_id AND er.action_id = root.id\n\t\t\tWHERE ar.project_id = ?\n\t\t\t\tAND (root.started_at IS NULL OR root.started_at >= ${since})\n\t\t\t\tAND ar.agent_id IN (${inClause(keys)})\n\t\t\tORDER BY COALESCE(ar.total_cost_usd, 0) DESC, root.started_at DESC\n\t\t`)\n\t\t.bind(projectId, windowHours, ...keys)\n\t\t.all<ExemplarSqlRow>();\n\tconst exemplars = new Map<string, ActionAggregateExemplar[]>();\n\tfor (const row of rows.results) {\n\t\tappendExemplar(exemplars, row.dimension_key ?? null, row);\n\t}\n\treturn exemplars;\n};\n\nconst getRunCostExemplars = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\twindowHours: number,\n\tkeys: string[],\n): Promise<Map<string, ActionAggregateExemplar[]>> => {\n\tif (keys.length === 0) return new Map();\n\tconst dialect = dialectFor(db);\n\tconst since = dialect.sinceHours(\"?\");\n\tconst rows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\tar.id AS dimension_key,\n\t\t\t\troot.id AS action_id,\n\t\t\t\tar.id AS agent_run_id,\n\t\t\t\troot.trace_id,\n\t\t\t\troot.tool_call_id,\n\t\t\t\ter.id AS eval_id,\n\t\t\t\tar.agent_name AS label,\n\t\t\t\tar.status,\n\t\t\t\troot.started_at AS occurred_at\n\t\t\tFROM agent_runs ar\n\t\t\tLEFT JOIN actions root ON root.project_id = ar.project_id AND root.id = ar.id\n\t\t\tLEFT JOIN eval_results er ON er.project_id = ar.project_id AND er.action_id = root.id\n\t\t\tWHERE ar.project_id = ?\n\t\t\t\tAND (root.started_at IS NULL OR root.started_at >= ${since})\n\t\t\t\tAND ar.id IN (${inClause(keys)})\n\t\t\tORDER BY COALESCE(ar.total_cost_usd, 0) DESC, root.started_at DESC\n\t\t`)\n\t\t.bind(projectId, windowHours, ...keys)\n\t\t.all<ExemplarSqlRow>();\n\tconst exemplars = new Map<string, ActionAggregateExemplar[]>();\n\tfor (const row of rows.results) {\n\t\tappendExemplar(exemplars, row.dimension_key ?? null, row);\n\t}\n\treturn exemplars;\n};\n\nconst getToolCostExemplars = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\twindowHours: number,\n\tkeys: string[],\n): Promise<Map<string, ActionAggregateExemplar[]>> => {\n\tif (keys.length === 0) return new Map();\n\tconst dialect = dialectFor(db);\n\tconst since = dialect.sinceHours(\"?\");\n\tconst rows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\tt.tool_name AS dimension_key,\n\t\t\t\ta.id AS action_id,\n\t\t\t\tCOALESCE(a.agent_run_id, a.root_action_id) AS agent_run_id,\n\t\t\t\tCOALESCE(a.trace_id, root.trace_id) AS trace_id,\n\t\t\t\tt.id AS tool_call_id,\n\t\t\t\ter.id AS eval_id,\n\t\t\t\tCOALESCE(a.name, t.tool_name) AS label,\n\t\t\t\ta.status,\n\t\t\t\ta.started_at AS occurred_at\n\t\t\tFROM tool_calls t\n\t\t\tLEFT JOIN actions a ON a.project_id = t.project_id AND a.id = t.action_id\n\t\t\tLEFT JOIN actions root ON root.project_id = t.project_id AND root.id = a.root_action_id\n\t\t\tLEFT JOIN eval_results er ON er.project_id = t.project_id AND er.action_id = a.id\n\t\t\tWHERE t.project_id = ?\n\t\t\t\tAND (a.started_at IS NULL OR a.started_at >= ${since})\n\t\t\t\tAND t.tool_name IN (${inClause(keys)})\n\t\t\tORDER BY COALESCE(a.total_cost_usd, 0) DESC, a.started_at DESC\n\t\t`)\n\t\t.bind(projectId, windowHours, ...keys)\n\t\t.all<ExemplarSqlRow>();\n\tconst exemplars = new Map<string, ActionAggregateExemplar[]>();\n\tfor (const row of rows.results) {\n\t\tappendExemplar(exemplars, row.dimension_key ?? null, row);\n\t}\n\treturn exemplars;\n};\n\nexport const getCostAttributionAggregates = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\twindowHours: number,\n\tlimit: number,\n): Promise<CostAttributionResult> => {\n\tconst dialect = dialectFor(db);\n\tconst since = dialect.sinceHours(\"?\");\n\tconst tenantExpr = actionTenantExpr(db, \"a\");\n\tconst workflowExpr = actionWorkflowExpr(db, \"a\");\n\n\tconst [\n\t\tagentRows,\n\t\trunRows,\n\t\tbyModel,\n\t\tbyProvider,\n\t\tbyPromptVersion,\n\t\ttoolRows,\n\t\tbyUser,\n\t\tbyTenant,\n\t\tbyWorkflow,\n\t] = await Promise.all([\n\t\tdb\n\t\t\t.prepare(`\n\t\t\t\tSELECT\n\t\t\t\t\tar.agent_id AS key,\n\t\t\t\t\tar.agent_name AS label,\n\t\t\t\t\tCOALESCE(SUM(COALESCE(ar.total_cost_usd, 0)), 0) AS total_cost_usd,\n\t\t\t\t\t0 AS action_count,\n\t\t\t\t\tCOUNT(*) AS agent_run_count,\n\t\t\t\t\t0 AS tool_call_count\n\t\t\t\tFROM agent_runs ar\n\t\t\t\tLEFT JOIN actions root ON root.project_id = ar.project_id AND root.id = ar.id\n\t\t\t\tWHERE ar.project_id = ? AND (root.started_at IS NULL OR root.started_at >= ${since})\n\t\t\t\tGROUP BY ar.agent_id, ar.agent_name\n\t\t\t\tORDER BY total_cost_usd DESC, agent_run_count DESC\n\t\t\t\tLIMIT ?\n\t\t\t`)\n\t\t\t.bind(projectId, windowHours, limit)\n\t\t\t.all<CostRow>(),\n\t\tdb\n\t\t\t.prepare(`\n\t\t\t\tSELECT\n\t\t\t\t\tar.id AS key,\n\t\t\t\t\tar.agent_name AS label,\n\t\t\t\t\tCOALESCE(ar.total_cost_usd, 0) AS total_cost_usd,\n\t\t\t\t\t0 AS action_count,\n\t\t\t\t\t1 AS agent_run_count,\n\t\t\t\t\t0 AS tool_call_count\n\t\t\t\tFROM agent_runs ar\n\t\t\t\tLEFT JOIN actions root ON root.project_id = ar.project_id AND root.id = ar.id\n\t\t\t\tWHERE ar.project_id = ? AND (root.started_at IS NULL OR root.started_at >= ${since})\n\t\t\t\tORDER BY total_cost_usd DESC\n\t\t\t\tLIMIT ?\n\t\t\t`)\n\t\t\t.bind(projectId, windowHours, limit)\n\t\t\t.all<CostRow>(),\n\t\tgroupByActionDimension(\n\t\t\tdb,\n\t\t\tprojectId,\n\t\t\twindowHours,\n\t\t\tlimit,\n\t\t\t\"model\",\n\t\t\t\"a.model_name\",\n\t\t),\n\t\tgroupByActionDimension(\n\t\t\tdb,\n\t\t\tprojectId,\n\t\t\twindowHours,\n\t\t\tlimit,\n\t\t\t\"provider\",\n\t\t\t\"a.provider\",\n\t\t),\n\t\tgroupByActionDimension(\n\t\t\tdb,\n\t\t\tprojectId,\n\t\t\twindowHours,\n\t\t\tlimit,\n\t\t\t\"prompt_version\",\n\t\t\t\"a.prompt_version\",\n\t\t),\n\t\tdb\n\t\t\t.prepare(`\n\t\t\t\tSELECT\n\t\t\t\t\tt.tool_name AS key,\n\t\t\t\t\tt.tool_name AS label,\n\t\t\t\t\tCOALESCE(SUM(COALESCE(a.total_cost_usd, 0)), 0) AS total_cost_usd,\n\t\t\t\t\tCOUNT(DISTINCT a.id) AS action_count,\n\t\t\t\t\tCOUNT(DISTINCT a.agent_run_id) AS agent_run_count,\n\t\t\t\t\tCOUNT(*) AS tool_call_count\n\t\t\t\tFROM tool_calls t\n\t\t\t\tLEFT JOIN actions a ON a.project_id = t.project_id AND a.id = t.action_id\n\t\t\t\tWHERE t.project_id = ? AND (a.started_at IS NULL OR a.started_at >= ${since})\n\t\t\t\tGROUP BY t.tool_name\n\t\t\t\tORDER BY total_cost_usd DESC, tool_call_count DESC\n\t\t\t\tLIMIT ?\n\t\t\t`)\n\t\t\t.bind(projectId, windowHours, limit)\n\t\t\t.all<CostRow>(),\n\t\tgroupByActionDimension(\n\t\t\tdb,\n\t\t\tprojectId,\n\t\t\twindowHours,\n\t\t\tlimit,\n\t\t\t\"user\",\n\t\t\t\"a.user_id\",\n\t\t),\n\t\tgroupByActionDimension(\n\t\t\tdb,\n\t\t\tprojectId,\n\t\t\twindowHours,\n\t\t\tlimit,\n\t\t\t\"tenant\",\n\t\t\ttenantExpr,\n\t\t),\n\t\tgroupByActionDimension(\n\t\t\tdb,\n\t\t\tprojectId,\n\t\t\twindowHours,\n\t\t\tlimit,\n\t\t\t\"workflow\",\n\t\t\tworkflowExpr,\n\t\t),\n\t]);\n\tconst agentKeys = agentRows.results\n\t\t.map((row) => row.key)\n\t\t.filter((key): key is string => !!key);\n\tconst runKeys = runRows.results\n\t\t.map((row) => row.key)\n\t\t.filter((key): key is string => !!key);\n\tconst toolKeys = toolRows.results\n\t\t.map((row) => row.key)\n\t\t.filter((key): key is string => !!key);\n\tconst [agentExemplars, runExemplars, toolExemplars] = await Promise.all([\n\t\tgetAgentCostExemplars(db, projectId, windowHours, agentKeys),\n\t\tgetRunCostExemplars(db, projectId, windowHours, runKeys),\n\t\tgetToolCostExemplars(db, projectId, windowHours, toolKeys),\n\t]);\n\n\treturn {\n\t\tprojectId,\n\t\twindowHours,\n\t\tbyAgent: costRows(\"agent\", agentRows.results, agentExemplars),\n\t\tbyRun: costRows(\"run\", runRows.results, runExemplars),\n\t\tbyModel,\n\t\tbyProvider,\n\t\tbyPromptVersion,\n\t\tbyTool: costRows(\"tool\", toolRows.results, toolExemplars),\n\t\tbyUser,\n\t\tbyTenant,\n\t\tbyWorkflow,\n\t\tgeneratedAt: new Date().toISOString(),\n\t};\n};\n\nexport const getAutonomousReviewAggregates = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\twindowHours: number,\n\tlimit: number,\n): Promise<AutonomousReviewResult> => {\n\tconst dialect = dialectFor(db);\n\tconst since = dialect.sinceHours(\"?\");\n\tconst rows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\tt.id,\n\t\t\t\tt.tool_name,\n\t\t\t\tt.action_id,\n\t\t\t\ta.name AS action_name,\n\t\t\t\tCOALESCE(a.agent_run_id, a.root_action_id) AS agent_run_id,\n\t\t\t\tar.agent_name,\n\t\t\t\tar.agent_version,\n\t\t\t\tCOALESCE(ar.autonomy_level, 'autonomous_write') AS autonomy_level,\n\t\t\t\tt.side_effect,\n\t\t\t\tCOALESCE(t.approval_state, 'suggested') AS approval_state,\n\t\t\t\tCOALESCE(a.status, 'ok') AS status,\n\t\t\t\tt.error_type AS error_snippet,\n\t\t\t\tCOALESCE(a.trace_id, root.trace_id) AS trace_id,\n\t\t\t\tCOALESCE(a.started_at, root.started_at) AS occurred_at,\n\t\t\t\tCASE\n\t\t\t\t\tWHEN t.mutation_before_json IS NOT NULL\n\t\t\t\t\t\tOR t.mutation_after_json IS NOT NULL\n\t\t\t\t\t\tOR t.mutation_diff_json IS NOT NULL\n\t\t\t\t\t\tOR t.mutation_artifact_id IS NOT NULL\n\t\t\t\t\tTHEN 1 ELSE 0\n\t\t\t\tEND AS mutation_evidence,\n\t\t\t\tt.mutation_artifact_id\n\t\t\tFROM tool_calls t\n\t\t\tLEFT JOIN actions a ON a.project_id = t.project_id AND a.id = t.action_id\n\t\t\tLEFT JOIN actions root ON root.project_id = t.project_id AND root.id = a.root_action_id\n\t\t\tLEFT JOIN agent_runs ar ON ar.project_id = t.project_id AND ar.id = COALESCE(a.agent_run_id, a.root_action_id)\n\t\t\tWHERE t.project_id = ?\n\t\t\t\tAND t.side_effect <> 0\n\t\t\t\tAND COALESCE(ar.autonomy_level, '') = 'autonomous_write'\n\t\t\t\tAND (a.started_at IS NULL OR a.started_at >= ${since})\n\t\t\tORDER BY occurred_at DESC\n\t\t\tLIMIT ?\n\t\t`)\n\t\t.bind(projectId, windowHours, limit)\n\t\t.all<AutonomousReviewSqlRow>();\n\n\treturn {\n\t\tprojectId,\n\t\twindowHours,\n\t\trows: rows.results.map((row) => ({\n\t\t\tid: row.id,\n\t\t\ttoolName: row.tool_name,\n\t\t\tactionId: row.action_id,\n\t\t\tactionName: row.action_name ?? row.tool_name,\n\t\t\tagentRunId: row.agent_run_id ?? \"\",\n\t\t\tagentName: row.agent_name ?? \"Unknown agent\",\n\t\t\tagentVersion: row.agent_version ?? \"unknown\",\n\t\t\tautonomyLevel: row.autonomy_level ?? \"autonomous_write\",\n\t\t\tsideEffect: row.side_effect !== 0,\n\t\t\tapprovalState: row.approval_state ?? \"suggested\",\n\t\t\tstatus: row.status === \"error\" ? \"error\" : \"ok\",\n\t\t\terrorSnippet: row.error_snippet,\n\t\t\ttraceId: row.trace_id ?? \"\",\n\t\t\toccurredAt: row.occurred_at ?? new Date(0).toISOString(),\n\t\t\tmutationEvidence: row.mutation_evidence !== 0,\n\t\t\tmutationArtifactId: row.mutation_artifact_id ?? null,\n\t\t})),\n\t\ttimestamp: new Date().toISOString(),\n\t};\n};\n\nconst formatPercent = (value: number): string => `${(value * 100).toFixed(1)}%`;\nconst directionForHigherBetter = (\n\tbaseline: number,\n\ttarget: number,\n): \"positive\" | \"negative\" | \"neutral\" =>\n\ttarget === baseline ? \"neutral\" : target > baseline ? \"positive\" : \"negative\";\nconst directionForLowerBetter = (\n\tbaseline: number,\n\ttarget: number,\n): \"positive\" | \"negative\" | \"neutral\" =>\n\ttarget === baseline ? \"neutral\" : target < baseline ? \"positive\" : \"negative\";\n\nconst getVersionExemplars = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tversion: string,\n): Promise<ActionAggregateExemplar[]> => {\n\tif (!version || version === \"unknown\") return [];\n\tconst rows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\troot.id AS action_id,\n\t\t\t\tar.id AS agent_run_id,\n\t\t\t\troot.trace_id,\n\t\t\t\troot.tool_call_id,\n\t\t\t\ter.id AS eval_id,\n\t\t\t\tar.agent_name AS label,\n\t\t\t\tar.status,\n\t\t\t\troot.started_at AS occurred_at\n\t\t\tFROM agent_runs ar\n\t\t\tLEFT JOIN actions root ON root.project_id = ar.project_id AND root.id = ar.id\n\t\t\tLEFT JOIN eval_results er ON er.project_id = ar.project_id AND er.action_id = root.id\n\t\t\tWHERE ar.project_id = ? AND ar.agent_version = ?\n\t\t\tORDER BY\n\t\t\t\tCASE WHEN ar.status <> 'success' THEN 0 ELSE 1 END,\n\t\t\t\troot.started_at DESC\n\t\t\tLIMIT ?\n\t\t`)\n\t\t.bind(projectId, version, EXEMPLAR_LIMIT)\n\t\t.all<ExemplarSqlRow>();\n\treturn exemplarsFromRows(rows.results);\n};\n\nexport const getVersionDiffAggregates = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tbaselineVersion?: string,\n\ttargetVersion?: string,\n): Promise<VersionComparisonResult> => {\n\tconst rows = await db\n\t\t.prepare(`\n\t\t\tSELECT\n\t\t\t\tar.agent_version AS version,\n\t\t\t\tCOUNT(DISTINCT ar.id) AS run_count,\n\t\t\t\tSUM(CASE WHEN ar.status = 'success' THEN 1 ELSE 0 END) AS success_count,\n\t\t\t\tAVG(ar.total_duration_ms) AS avg_duration_ms,\n\t\t\t\tAVG(ar.total_cost_usd) AS avg_cost_usd,\n\t\t\t\tCOUNT(er.id) AS eval_count,\n\t\t\t\tSUM(CASE WHEN er.passed <> 0 THEN 1 ELSE 0 END) AS passed_eval_count,\n\t\t\t\tAVG(er.score) AS avg_eval_score,\n\t\t\t\tCOUNT(t.id) AS tool_count,\n\t\t\t\tSUM(CASE WHEN t.error_type IS NOT NULL AND t.error_type <> '' THEN 1 ELSE 0 END) AS tool_error_count\n\t\t\tFROM agent_runs ar\n\t\t\tLEFT JOIN actions a ON a.project_id = ar.project_id AND a.agent_run_id = ar.id\n\t\t\tLEFT JOIN eval_results er ON er.project_id = ar.project_id AND er.action_id = a.id\n\t\t\tLEFT JOIN tool_calls t ON t.project_id = ar.project_id AND t.action_id = a.id\n\t\t\tWHERE ar.project_id = ?\n\t\t\tGROUP BY ar.agent_version\n\t\t\tORDER BY MAX(COALESCE(a.started_at, '')) DESC, ar.agent_version DESC\n\t\t\tLIMIT 20\n\t\t`)\n\t\t.bind(projectId)\n\t\t.all<VersionStatsRow>();\n\n\tconst versions = rows.results.filter((row) => row.version);\n\tconst baseline =\n\t\tversions.find((row) => row.version === baselineVersion) ??\n\t\tversions[1] ??\n\t\tversions[0];\n\tconst target =\n\t\tversions.find((row) => row.version === targetVersion) ??\n\t\tversions[0] ??\n\t\tbaseline;\n\n\tconst metric = (\n\t\tlabel: string,\n\t\tbaselineValue: number,\n\t\ttargetValue: number,\n\t\tformat: (value: number) => string | number,\n\t\tdirection: \"higher\" | \"lower\",\n\t): VersionDiffMetric => ({\n\t\tlabel,\n\t\tbaselineValue: format(baselineValue),\n\t\ttargetValue: format(targetValue),\n\t\tdeltaValue:\n\t\t\ttypeof format(targetValue - baselineValue) === \"number\"\n\t\t\t\t? format(targetValue - baselineValue)\n\t\t\t\t: `${targetValue - baselineValue >= 0 ? \"+\" : \"\"}${format(targetValue - baselineValue)}`,\n\t\tdeltaDirection:\n\t\t\tdirection === \"higher\"\n\t\t\t\t? directionForHigherBetter(baselineValue, targetValue)\n\t\t\t\t: directionForLowerBetter(baselineValue, targetValue),\n\t});\n\n\tconst empty = {\n\t\tversion: \"unknown\",\n\t\trun_count: 0,\n\t\tsuccess_count: 0,\n\t\tavg_duration_ms: 0,\n\t\tavg_cost_usd: 0,\n\t\teval_count: 0,\n\t\tpassed_eval_count: 0,\n\t\tavg_eval_score: 0,\n\t\ttool_count: 0,\n\t\ttool_error_count: 0,\n\t} satisfies VersionStatsRow;\n\tconst b = baseline ?? empty;\n\tconst t = target ?? empty;\n\tconst bRuns = toNumber(b.run_count);\n\tconst tRuns = toNumber(t.run_count);\n\tconst bTools = toNumber(b.tool_count);\n\tconst tTools = toNumber(t.tool_count);\n\tconst bEvals = toNumber(b.eval_count);\n\tconst tEvals = toNumber(t.eval_count);\n\tconst [baselineExemplars, targetExemplars] = await Promise.all([\n\t\tgetVersionExemplars(db, projectId, b.version),\n\t\tgetVersionExemplars(db, projectId, t.version),\n\t]);\n\n\treturn {\n\t\tprojectId,\n\t\tbaselineVersion: b.version,\n\t\ttargetVersion: t.version,\n\t\tmetrics: [\n\t\t\tmetric(\n\t\t\t\t\"Success Rate\",\n\t\t\t\tbRuns > 0 ? toNumber(b.success_count) / bRuns : 0,\n\t\t\t\ttRuns > 0 ? toNumber(t.success_count) / tRuns : 0,\n\t\t\t\tformatPercent,\n\t\t\t\t\"higher\",\n\t\t\t),\n\t\t\tmetric(\n\t\t\t\t\"Evaluation Score\",\n\t\t\t\ttoNumber(b.avg_eval_score),\n\t\t\t\ttoNumber(t.avg_eval_score),\n\t\t\t\t(value) => value.toFixed(2),\n\t\t\t\t\"higher\",\n\t\t\t),\n\t\t\tmetric(\n\t\t\t\t\"Evaluation Pass Rate\",\n\t\t\t\tbEvals > 0 ? toNumber(b.passed_eval_count) / bEvals : 0,\n\t\t\t\ttEvals > 0 ? toNumber(t.passed_eval_count) / tEvals : 0,\n\t\t\t\tformatPercent,\n\t\t\t\t\"higher\",\n\t\t\t),\n\t\t\tmetric(\n\t\t\t\t\"Average Run Latency\",\n\t\t\t\ttoNumber(b.avg_duration_ms),\n\t\t\t\ttoNumber(t.avg_duration_ms),\n\t\t\t\t(value) => `${Math.round(value)}ms`,\n\t\t\t\t\"lower\",\n\t\t\t),\n\t\t\tmetric(\n\t\t\t\t\"Average Run Cost\",\n\t\t\t\ttoNumber(b.avg_cost_usd),\n\t\t\t\ttoNumber(t.avg_cost_usd),\n\t\t\t\t(value) => `$${value.toFixed(4)}`,\n\t\t\t\t\"lower\",\n\t\t\t),\n\t\t\tmetric(\n\t\t\t\t\"Tool Error Rate\",\n\t\t\t\tbTools > 0 ? toNumber(b.tool_error_count) / bTools : 0,\n\t\t\t\ttTools > 0 ? toNumber(t.tool_error_count) / tTools : 0,\n\t\t\t\tformatPercent,\n\t\t\t\t\"lower\",\n\t\t\t),\n\t\t],\n\t\tbaselineExemplars,\n\t\ttargetExemplars,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n};\n","import { ActionConfidence } from \"@obsunified/types/constants\";\nimport type { SqlDb } from \"../sql-db\";\nimport { FETCH_LIMIT } from \"./constants\";\nimport { manifestByInteraction } from \"./key-lookups\";\nimport {\n\tmapAction,\n\tmapAgentRun,\n\tmapAi,\n\tmapArtifact,\n\tmapEvalResult,\n\tmapLog,\n\tmapMetricExemplar,\n\tmapRetrievalEvent,\n\tmapSpan,\n\tmapToolCall,\n} from \"./mappers\";\nimport type { ActionRef, EntityManifestExtended, ReplayRow } from \"./types\";\n\nconst emptyExtendedManifest = (): EntityManifestExtended => ({\n\tspans: [],\n\tlogs: [],\n\tusageEvents: [],\n\taiCalls: [],\n\tmetricExemplars: [],\n\treplay: null,\n\tactions: [],\n\tagentRuns: [],\n\ttoolCalls: [],\n\tretrievalEvents: [],\n\tevalResults: [],\n\tartifacts: [],\n});\n\nconst earliest = (values: Array<string | null | undefined>): string =>\n\tvalues.filter((v): v is string => Boolean(v)).sort()[0] ??\n\tnew Date(0).toISOString();\n\nconst latest = (values: Array<string | null | undefined>): string | null => {\n\tconst sorted = values.filter((v): v is string => Boolean(v)).sort();\n\treturn sorted[sorted.length - 1] ?? null;\n};\n\nconst durationMs = (\n\tstartedAt: string,\n\tendedAt: string | null,\n): number | null => {\n\tif (!endedAt) return null;\n\tconst duration = Date.parse(endedAt) - Date.parse(startedAt);\n\treturn Number.isFinite(duration) && duration >= 0 ? duration : null;\n};\n\nconst projectLegacyInteraction = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tinteractionId: string,\n): Promise<EntityManifestExtended> => {\n\tconst manifest = await manifestByInteraction(db, projectId, interactionId);\n\tconst hasSignals =\n\t\tmanifest.spans.length > 0 ||\n\t\tmanifest.logs.length > 0 ||\n\t\tmanifest.usageEvents.length > 0 ||\n\t\tmanifest.aiCalls.length > 0;\n\n\tif (!hasSignals) return emptyExtendedManifest();\n\n\tconst startedAt = earliest([\n\t\t...manifest.spans.map((s) => s.startTime),\n\t\t...manifest.logs.map((l) => l.occurredAt),\n\t\t...manifest.usageEvents.map((u) => u.occurredAt),\n\t\t...manifest.aiCalls.map((a) => a.occurredAt),\n\t]);\n\tconst endedAt = latest([\n\t\t...manifest.logs.map((l) => l.occurredAt),\n\t\t...manifest.usageEvents.map((u) => u.occurredAt),\n\t\t...manifest.aiCalls.map((a) => a.occurredAt),\n\t]);\n\tconst firstSpan = manifest.spans[0];\n\tconst firstUsage = manifest.usageEvents[0];\n\tconst action: ActionRef = {\n\t\tid: interactionId,\n\t\tprojectId,\n\t\trootActionId: interactionId,\n\t\tcausedByActionId: null,\n\t\tactorType: \"human\",\n\t\tactorId: null,\n\t\tactionKind: \"browser.interaction\",\n\t\tname: firstUsage?.eventName ?? firstSpan?.spanName ?? \"Legacy interaction\",\n\t\tstatus:\n\t\t\tmanifest.logs.some((l) => l.severity.toLowerCase() === \"error\") ||\n\t\t\tmanifest.spans.some((s) => s.statusCode >= 2)\n\t\t\t\t? \"error\"\n\t\t\t\t: \"ok\",\n\t\tstartedAt,\n\t\tendedAt,\n\t\tdurationMs: durationMs(startedAt, endedAt),\n\t\ttraceId: firstSpan?.traceId ?? manifest.aiCalls[0]?.traceId ?? null,\n\t\tspanId: firstSpan?.spanId ?? null,\n\t\tsessionId: firstUsage?.sessionId ?? null,\n\t\tinteractionId,\n\t\tuserId: null,\n\t\tagentRunId: null,\n\t\tstepId: null,\n\t\ttoolCallId: null,\n\t\tpromptVersion: null,\n\t\tmodelName: manifest.aiCalls[0]?.modelName ?? null,\n\t\tprovider: manifest.aiCalls[0]?.provider ?? null,\n\t\ttotalCostUsd:\n\t\t\tmanifest.aiCalls.length > 0\n\t\t\t\t? manifest.aiCalls.reduce(\n\t\t\t\t\t\t(sum, call) => sum + (call.totalCostUsd ?? 0),\n\t\t\t\t\t\t0,\n\t\t\t\t\t)\n\t\t\t\t: null,\n\t\tcausalConfidence: ActionConfidence.Fallback,\n\t\tattrsJson: JSON.stringify({ projectedFrom: \"interaction_id\" }),\n\t};\n\n\treturn {\n\t\t...manifest,\n\t\tactions: [action],\n\t\tagentRuns: [],\n\t\ttoolCalls: [],\n\t\tretrievalEvents: [],\n\t\tevalResults: [],\n\t\tartifacts: [],\n\t};\n};\n\nexport async function manifestByAction(\n\tdb: SqlDb,\n\tprojectId: string,\n\tactionId: string,\n): Promise<EntityManifestExtended> {\n\tconst action = await db\n\t\t.prepare(`SELECT * FROM actions WHERE project_id = ? AND id = ? LIMIT 1`)\n\t\t.bind(projectId, actionId)\n\t\t.first<{\n\t\t\tid: string;\n\t\t\tproject_id: string;\n\t\t\troot_action_id: string;\n\t\t\tcaused_by_action_id: string | null;\n\t\t\tactor_type: string;\n\t\t\tactor_id: string | null;\n\t\t\taction_kind: string;\n\t\t\tname: string | null;\n\t\t\tstatus: string;\n\t\t\tstarted_at: string;\n\t\t\tended_at: string | null;\n\t\t\tduration_ms: number | null;\n\t\t\ttrace_id: string | null;\n\t\t\tspan_id: string | null;\n\t\t\tsession_id: string | null;\n\t\t\tinteraction_id: string | null;\n\t\t\tuser_id: string | null;\n\t\t\tagent_run_id: string | null;\n\t\t\tstep_id: string | null;\n\t\t\ttool_call_id: string | null;\n\t\t\tprompt_version: string | null;\n\t\t\tmodel_name: string | null;\n\t\t\tprovider: string | null;\n\t\t\ttotal_cost_usd: number | null;\n\t\t\tattrs_json: string | null;\n\t\t}>();\n\n\tif (!action) {\n\t\treturn projectLegacyInteraction(db, projectId, actionId);\n\t}\n\n\t// Retrieve all actions that share the same root_action_id\n\tconst actionsRes = await db\n\t\t.prepare(\n\t\t\t`SELECT * FROM actions\n\t\t\t\tWHERE project_id = ? AND root_action_id = ?\n\t\t\t\tORDER BY started_at ASC LIMIT ?`,\n\t\t)\n\t\t.bind(projectId, action.root_action_id, FETCH_LIMIT)\n\t\t.all<Parameters<typeof mapAction>[0]>();\n\n\tconst matchedActions = actionsRes.results;\n\tconst actionIds = matchedActions.map((a) => a.id);\n\n\t// Execute child queries in parallel\n\tconst placeholders = actionIds.map(() => \"?\").join(\", \");\n\tconst [agentRuns, toolCalls, retrievalEvents, evalResults, artifacts] =\n\t\tawait Promise.all([\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM agent_runs\n\t\t\t\t\tWHERE project_id = ? AND id = ?\n\t\t\t\t\tLIMIT 1`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, action.root_action_id)\n\t\t\t\t.all<Parameters<typeof mapAgentRun>[0]>(),\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM tool_calls\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapToolCall>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM retrieval_events\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapRetrievalEvent>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM eval_results\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapEvalResult>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM artifacts\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapArtifact>[0]>()\n\t\t\t\t: { results: [] },\n\t\t]);\n\n\t// Extract unique trace IDs and session IDs\n\tconst traceIds = Array.from(\n\t\tnew Set(\n\t\t\tmatchedActions\n\t\t\t\t.map((a) => a.trace_id)\n\t\t\t\t.filter((t): t is string => Boolean(t)),\n\t\t),\n\t);\n\tconst sessionIds = Array.from(\n\t\tnew Set(\n\t\t\tmatchedActions\n\t\t\t\t.map((a) => a.session_id)\n\t\t\t\t.filter((s): s is string => Boolean(s)),\n\t\t),\n\t);\n\n\tlet spansRes = { results: [] as Parameters<typeof mapSpan>[0][] };\n\tlet logsRes = { results: [] as Parameters<typeof mapLog>[0][] };\n\tlet aiCallsRes = { results: [] as Parameters<typeof mapAi>[0][] };\n\tlet metricExemplarsRes = {\n\t\tresults: [] as Parameters<typeof mapMetricExemplar>[0][],\n\t};\n\tlet replayRes: ReplayRow | null = null;\n\n\tif (traceIds.length > 0) {\n\t\tconst tracePlaceholders = traceIds.map(() => \"?\").join(\", \");\n\t\tconst [s, l, a, e] = await Promise.all([\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n\t\t\t\t\t\t\tstatus_code, status_message, start_time, duration_ms, interaction_id\n\t\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY start_time ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapSpan>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT log_id, trace_id, span_id, service_name, logger_name,\n\t\t\t\t\t\t\tseverity, message, occurred_at, interaction_id, session_id\n\t\t\t\t\t\tFROM logs\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapLog>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT call_id, trace_id, model_name, provider, total_cost_usd,\n\t\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\t\tFROM ai_calls\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapAi>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT id, point_id, series_id, metric_name, service_name,\n\t\t\t\t\t\t\ttrace_id, span_id, ts_ns, value, received_at\n\t\t\t\t\t\tFROM metric_exemplars\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY ts_ns DESC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapMetricExemplar>[0]>(),\n\t\t]);\n\t\tspansRes = s;\n\t\tlogsRes = l;\n\t\taiCallsRes = a;\n\t\tmetricExemplarsRes = e;\n\t}\n\n\tif (sessionIds.length > 0) {\n\t\tconst sessionPlaceholders = sessionIds.map(() => \"?\").join(\", \");\n\t\treplayRes = await db\n\t\t\t.prepare(\n\t\t\t\t`SELECT session_id, first_chunk_at, last_chunk_at, chunk_count, events_count\n\t\t\t\t\tFROM session_replay_metadata\n\t\t\t\t\tWHERE session_id IN (${sessionPlaceholders})\n\t\t\t\t\tORDER BY last_chunk_at DESC LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(...sessionIds)\n\t\t\t.first<{\n\t\t\t\tsession_id: string;\n\t\t\t\tfirst_chunk_at: string;\n\t\t\t\tlast_chunk_at: string;\n\t\t\t\tchunk_count: number;\n\t\t\t\tevents_count: number;\n\t\t\t}>();\n\t}\n\n\tconst sumAiCost = aiCallsRes.results.reduce(\n\t\t(sum, a) => sum + (a.total_cost_usd ?? 0),\n\t\t0,\n\t);\n\tconst startTimes = matchedActions.map((a) => a.started_at).filter(Boolean);\n\tconst endTimes = matchedActions.map((a) => a.ended_at).filter(Boolean);\n\tconst earliestStart = startTimes.sort()[0] ?? null;\n\tconst latestEnd = endTimes.sort()[endTimes.length - 1] ?? null;\n\tconst totalDurationMs =\n\t\tearliestStart && latestEnd\n\t\t\t? Date.parse(latestEnd) - Date.parse(earliestStart)\n\t\t\t: null;\n\n\tconst mappedRuns = agentRuns.results.map((r) => {\n\t\tconst mapped = mapAgentRun(r);\n\t\treturn {\n\t\t\t...mapped,\n\t\t\ttotalCostUsd: sumAiCost || mapped.totalCostUsd || 0.0,\n\t\t\ttotalDurationMs: totalDurationMs || mapped.totalDurationMs,\n\t\t};\n\t});\n\n\treturn {\n\t\tspans: spansRes.results.map(mapSpan),\n\t\tlogs: logsRes.results.map(mapLog),\n\t\tusageEvents: [],\n\t\taiCalls: aiCallsRes.results.map(mapAi),\n\t\tmetricExemplars: metricExemplarsRes.results.map(mapMetricExemplar),\n\t\treplay: replayRes\n\t\t\t? {\n\t\t\t\t\tsessionId: replayRes.session_id,\n\t\t\t\t\tfirstChunkAt: replayRes.first_chunk_at,\n\t\t\t\t\tlastChunkAt: replayRes.last_chunk_at,\n\t\t\t\t\tchunkCount: replayRes.chunk_count,\n\t\t\t\t\teventsCount: replayRes.events_count,\n\t\t\t\t}\n\t\t\t: null,\n\t\tactions: matchedActions.map(mapAction),\n\t\tagentRuns: mappedRuns,\n\t\ttoolCalls: toolCalls.results.map(mapToolCall),\n\t\tretrievalEvents: retrievalEvents.results.map(mapRetrievalEvent),\n\t\tevalResults: evalResults.results.map(mapEvalResult),\n\t\tartifacts: artifacts.results.map(mapArtifact),\n\t};\n}\n\nexport async function manifestByAgentRun(\n\tdb: SqlDb,\n\tprojectId: string,\n\tagentRunId: string,\n): Promise<EntityManifestExtended> {\n\tconst run = await db\n\t\t.prepare(`SELECT * FROM agent_runs WHERE project_id = ? AND id = ? LIMIT 1`)\n\t\t.bind(projectId, agentRunId)\n\t\t.first<{\n\t\t\tid: string;\n\t\t\tproject_id: string;\n\t\t\tagent_id: string;\n\t\t\tagent_name: string;\n\t\t\tagent_version: string;\n\t\t\tgoal: string | null;\n\t\t\toutcome: string | null;\n\t\t\tautonomy_level: string;\n\t\t\tstatus: string;\n\t\t\terror_message: string | null;\n\t\t\ttotal_cost_usd: number | null;\n\t\t\ttotal_duration_ms: number | null;\n\t\t\tmetadata_json: string | null;\n\t\t}>();\n\n\tif (!run) {\n\t\treturn emptyExtendedManifest();\n\t}\n\n\tconst actionsRes = await db\n\t\t.prepare(\n\t\t\t`SELECT * FROM actions\n\t\t\t\tWHERE project_id = ? AND (root_action_id = ? OR agent_run_id = ?)\n\t\t\t\tORDER BY started_at ASC LIMIT ?`,\n\t\t)\n\t\t.bind(projectId, agentRunId, agentRunId, FETCH_LIMIT)\n\t\t.all<Parameters<typeof mapAction>[0]>();\n\n\tconst matchedActions = actionsRes.results;\n\tconst actionIds = matchedActions.map((a) => a.id);\n\n\t// Execute child queries in parallel\n\tconst placeholders = actionIds.map(() => \"?\").join(\", \");\n\tconst [agentRuns, toolCalls, retrievalEvents, evalResults, artifacts] =\n\t\tawait Promise.all([\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM agent_runs\n\t\t\t\t\tWHERE project_id = ? AND id = ?\n\t\t\t\t\tLIMIT 1`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, agentRunId)\n\t\t\t\t.all<Parameters<typeof mapAgentRun>[0]>(),\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM tool_calls\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapToolCall>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM retrieval_events\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapRetrievalEvent>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM eval_results\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapEvalResult>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM artifacts\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapArtifact>[0]>()\n\t\t\t\t: { results: [] },\n\t\t]);\n\n\t// Extract unique trace IDs and session IDs\n\tconst traceIds = Array.from(\n\t\tnew Set(\n\t\t\tmatchedActions\n\t\t\t\t.map((a) => a.trace_id)\n\t\t\t\t.filter((t): t is string => Boolean(t)),\n\t\t),\n\t);\n\tconst sessionIds = Array.from(\n\t\tnew Set(\n\t\t\tmatchedActions\n\t\t\t\t.map((a) => a.session_id)\n\t\t\t\t.filter((s): s is string => Boolean(s)),\n\t\t),\n\t);\n\n\tlet spansRes = { results: [] as Parameters<typeof mapSpan>[0][] };\n\tlet logsRes = { results: [] as Parameters<typeof mapLog>[0][] };\n\tlet aiCallsRes = { results: [] as Parameters<typeof mapAi>[0][] };\n\tlet metricExemplarsRes = {\n\t\tresults: [] as Parameters<typeof mapMetricExemplar>[0][],\n\t};\n\tlet replayRes: ReplayRow | null = null;\n\n\tif (traceIds.length > 0) {\n\t\tconst tracePlaceholders = traceIds.map(() => \"?\").join(\", \");\n\t\tconst [s, l, a, e] = await Promise.all([\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n\t\t\t\t\t\t\tstatus_code, status_message, start_time, duration_ms, interaction_id\n\t\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY start_time ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapSpan>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT log_id, trace_id, span_id, service_name, logger_name,\n\t\t\t\t\t\t\tseverity, message, occurred_at, interaction_id, session_id\n\t\t\t\t\t\tFROM logs\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapLog>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT call_id, trace_id, model_name, provider, total_cost_usd,\n\t\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\t\tFROM ai_calls\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapAi>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT id, point_id, series_id, metric_name, service_name,\n\t\t\t\t\t\t\ttrace_id, span_id, ts_ns, value, received_at\n\t\t\t\t\t\tFROM metric_exemplars\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY ts_ns DESC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapMetricExemplar>[0]>(),\n\t\t]);\n\t\tspansRes = s;\n\t\tlogsRes = l;\n\t\taiCallsRes = a;\n\t\tmetricExemplarsRes = e;\n\t}\n\n\tif (sessionIds.length > 0) {\n\t\tconst sessionPlaceholders = sessionIds.map(() => \"?\").join(\", \");\n\t\treplayRes = await db\n\t\t\t.prepare(\n\t\t\t\t`SELECT session_id, first_chunk_at, last_chunk_at, chunk_count, events_count\n\t\t\t\t\tFROM session_replay_metadata\n\t\t\t\t\tWHERE session_id IN (${sessionPlaceholders})\n\t\t\t\t\tORDER BY last_chunk_at DESC LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(...sessionIds)\n\t\t\t.first<{\n\t\t\t\tsession_id: string;\n\t\t\t\tfirst_chunk_at: string;\n\t\t\t\tlast_chunk_at: string;\n\t\t\t\tchunk_count: number;\n\t\t\t\tevents_count: number;\n\t\t\t}>();\n\t}\n\n\tconst sumAiCost = aiCallsRes.results.reduce(\n\t\t(sum, a) => sum + (a.total_cost_usd ?? 0),\n\t\t0,\n\t);\n\tconst startTimes = matchedActions.map((a) => a.started_at).filter(Boolean);\n\tconst endTimes = matchedActions.map((a) => a.ended_at).filter(Boolean);\n\tconst earliestStart = startTimes.sort()[0] ?? null;\n\tconst latestEnd = endTimes.sort()[endTimes.length - 1] ?? null;\n\tconst totalDurationMs =\n\t\tearliestStart && latestEnd\n\t\t\t? Date.parse(latestEnd) - Date.parse(earliestStart)\n\t\t\t: null;\n\n\tconst mappedRuns = agentRuns.results.map((r) => {\n\t\tconst mapped = mapAgentRun(r);\n\t\treturn {\n\t\t\t...mapped,\n\t\t\ttotalCostUsd: sumAiCost || mapped.totalCostUsd || 0.0,\n\t\t\ttotalDurationMs: totalDurationMs || mapped.totalDurationMs,\n\t\t};\n\t});\n\n\treturn {\n\t\tspans: spansRes.results.map(mapSpan),\n\t\tlogs: logsRes.results.map(mapLog),\n\t\tusageEvents: [],\n\t\taiCalls: aiCallsRes.results.map(mapAi),\n\t\tmetricExemplars: metricExemplarsRes.results.map(mapMetricExemplar),\n\t\treplay: replayRes\n\t\t\t? {\n\t\t\t\t\tsessionId: replayRes.session_id,\n\t\t\t\t\tfirstChunkAt: replayRes.first_chunk_at,\n\t\t\t\t\tlastChunkAt: replayRes.last_chunk_at,\n\t\t\t\t\tchunkCount: replayRes.chunk_count,\n\t\t\t\t\teventsCount: replayRes.events_count,\n\t\t\t\t}\n\t\t\t: null,\n\t\tactions: matchedActions.map(mapAction),\n\t\tagentRuns: mappedRuns,\n\t\ttoolCalls: toolCalls.results.map(mapToolCall),\n\t\tretrievalEvents: retrievalEvents.results.map(mapRetrievalEvent),\n\t\tevalResults: evalResults.results.map(mapEvalResult),\n\t\tartifacts: artifacts.results.map(mapArtifact),\n\t};\n}\n\nexport async function manifestByActor(\n\tdb: SqlDb,\n\tprojectId: string,\n\tactorType: string,\n\tactorId: string,\n): Promise<EntityManifestExtended> {\n\tconst actionsRes = await db\n\t\t.prepare(\n\t\t\t`SELECT * FROM actions\n\t\t\t\tWHERE project_id = ? AND actor_type = ? AND actor_id = ?\n\t\t\t\tORDER BY started_at DESC LIMIT ?`,\n\t\t)\n\t\t.bind(projectId, actorType, actorId, FETCH_LIMIT)\n\t\t.all<Parameters<typeof mapAction>[0]>();\n\n\tconst matchedActions = actionsRes.results;\n\tif (matchedActions.length === 0) {\n\t\treturn emptyExtendedManifest();\n\t}\n\n\tconst actionIds = matchedActions.map((a) => a.id);\n\tconst rootActionIds = Array.from(\n\t\tnew Set(matchedActions.map((a) => a.root_action_id)),\n\t);\n\n\t// Execute child queries in parallel\n\tconst placeholders = actionIds.map(() => \"?\").join(\", \");\n\tconst rootPlaceholders = rootActionIds.map(() => \"?\").join(\", \");\n\tconst [agentRuns, toolCalls, retrievalEvents, evalResults, artifacts] =\n\t\tawait Promise.all([\n\t\t\trootActionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM agent_runs\n\t\t\t\t\t\t\tWHERE project_id = ? AND id IN (${rootPlaceholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...rootActionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapAgentRun>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM tool_calls\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapToolCall>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM retrieval_events\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapRetrievalEvent>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM eval_results\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapEvalResult>[0]>()\n\t\t\t\t: { results: [] },\n\t\t\tactionIds.length > 0\n\t\t\t\t? db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT * FROM artifacts\n\t\t\t\t\t\t\tWHERE project_id = ? AND action_id IN (${placeholders})\n\t\t\t\t\t\t\tLIMIT ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, ...actionIds, FETCH_LIMIT)\n\t\t\t\t\t\t.all<Parameters<typeof mapArtifact>[0]>()\n\t\t\t\t: { results: [] },\n\t\t]);\n\n\t// Extract unique trace IDs and session IDs\n\tconst traceIds = Array.from(\n\t\tnew Set(\n\t\t\tmatchedActions\n\t\t\t\t.map((a) => a.trace_id)\n\t\t\t\t.filter((t): t is string => Boolean(t)),\n\t\t),\n\t);\n\tconst sessionIds = Array.from(\n\t\tnew Set(\n\t\t\tmatchedActions\n\t\t\t\t.map((a) => a.session_id)\n\t\t\t\t.filter((s): s is string => Boolean(s)),\n\t\t),\n\t);\n\n\tlet spansRes = { results: [] as Parameters<typeof mapSpan>[0][] };\n\tlet logsRes = { results: [] as Parameters<typeof mapLog>[0][] };\n\tlet aiCallsRes = { results: [] as Parameters<typeof mapAi>[0][] };\n\tlet metricExemplarsRes = {\n\t\tresults: [] as Parameters<typeof mapMetricExemplar>[0][],\n\t};\n\tlet replayRes: ReplayRow | null = null;\n\n\tif (traceIds.length > 0) {\n\t\tconst tracePlaceholders = traceIds.map(() => \"?\").join(\", \");\n\t\tconst [s, l, a, e] = await Promise.all([\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n\t\t\t\t\t\t\tstatus_code, status_message, start_time, duration_ms, interaction_id\n\t\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY start_time ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapSpan>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT log_id, trace_id, span_id, service_name, logger_name,\n\t\t\t\t\t\t\tseverity, message, occurred_at, interaction_id, session_id\n\t\t\t\t\t\tFROM logs\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapLog>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT call_id, trace_id, model_name, provider, total_cost_usd,\n\t\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\t\tFROM ai_calls\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapAi>[0]>(),\n\t\t\tdb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT id, point_id, series_id, metric_name, service_name,\n\t\t\t\t\t\t\ttrace_id, span_id, ts_ns, value, received_at\n\t\t\t\t\t\tFROM metric_exemplars\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id IN (${tracePlaceholders})\n\t\t\t\t\t\tORDER BY ts_ns DESC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, ...traceIds, FETCH_LIMIT)\n\t\t\t\t.all<Parameters<typeof mapMetricExemplar>[0]>(),\n\t\t]);\n\t\tspansRes = s;\n\t\tlogsRes = l;\n\t\taiCallsRes = a;\n\t\tmetricExemplarsRes = e;\n\t}\n\n\tif (sessionIds.length > 0) {\n\t\tconst sessionPlaceholders = sessionIds.map(() => \"?\").join(\", \");\n\t\treplayRes = await db\n\t\t\t.prepare(\n\t\t\t\t`SELECT session_id, first_chunk_at, last_chunk_at, chunk_count, events_count\n\t\t\t\t\tFROM session_replay_metadata\n\t\t\t\t\tWHERE session_id IN (${sessionPlaceholders})\n\t\t\t\t\tORDER BY last_chunk_at DESC LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(...sessionIds)\n\t\t\t.first<{\n\t\t\t\tsession_id: string;\n\t\t\t\tfirst_chunk_at: string;\n\t\t\t\tlast_chunk_at: string;\n\t\t\t\tchunk_count: number;\n\t\t\t\tevents_count: number;\n\t\t\t}>();\n\t}\n\n\treturn {\n\t\tspans: spansRes.results.map(mapSpan),\n\t\tlogs: logsRes.results.map(mapLog),\n\t\tusageEvents: [],\n\t\taiCalls: aiCallsRes.results.map(mapAi),\n\t\tmetricExemplars: metricExemplarsRes.results.map(mapMetricExemplar),\n\t\treplay: replayRes\n\t\t\t? {\n\t\t\t\t\tsessionId: replayRes.session_id,\n\t\t\t\t\tfirstChunkAt: replayRes.first_chunk_at,\n\t\t\t\t\tlastChunkAt: replayRes.last_chunk_at,\n\t\t\t\t\tchunkCount: replayRes.chunk_count,\n\t\t\t\t\teventsCount: replayRes.events_count,\n\t\t\t\t}\n\t\t\t: null,\n\t\tactions: matchedActions.map(mapAction),\n\t\tagentRuns: agentRuns.results.map(mapAgentRun),\n\t\ttoolCalls: toolCalls.results.map(mapToolCall),\n\t\tretrievalEvents: retrievalEvents.results.map(mapRetrievalEvent),\n\t\tevalResults: evalResults.results.map(mapEvalResult),\n\t\tartifacts: artifacts.results.map(mapArtifact),\n\t};\n}\n","export const FETCH_LIMIT = 200;\n","import {\n\tACTION_CONFIDENCE_KEY,\n\tACTION_ID_KEY,\n\tACTION_ID_RE,\n\tActionConfidence,\n} from \"@obsunified/types/constants\";\nimport type {\n\tActionRef,\n\tAgentRunRef,\n\tAICallRef,\n\tArtifactRef,\n\tEvalResultRef,\n\tLogRef,\n\tMetricExemplarRef,\n\tRetrievalEventRef,\n\tSpanRef,\n\tToolCallRef,\n\tUsageEventRef,\n} from \"./types\";\n\nconst parseAttrs = (attrsJson: string | null): Record<string, unknown> => {\n\tif (!attrsJson) return {};\n\ttry {\n\t\tconst parsed = JSON.parse(attrsJson);\n\t\treturn parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n\t\t\t? (parsed as Record<string, unknown>)\n\t\t\t: {};\n\t} catch {\n\t\treturn {};\n\t}\n};\n\nconst mapCausalConfidence = (action: {\n\tid: string;\n\tattrs_json: string | null;\n}): ActionRef[\"causalConfidence\"] => {\n\tconst attrs = parseAttrs(action.attrs_json);\n\tconst attrConfidence = attrs[ACTION_CONFIDENCE_KEY];\n\tconst attrActionId = attrs[ACTION_ID_KEY];\n\tconst hasTrustedExplicitId =\n\t\ttypeof attrActionId === \"string\" &&\n\t\tattrActionId === action.id &&\n\t\tACTION_ID_RE.test(attrActionId);\n\n\tif (attrConfidence === ActionConfidence.Fallback) {\n\t\treturn ActionConfidence.Fallback;\n\t}\n\tif (attrConfidence === ActionConfidence.Explicit && hasTrustedExplicitId) {\n\t\treturn ActionConfidence.Explicit;\n\t}\n\treturn hasTrustedExplicitId\n\t\t? ActionConfidence.Explicit\n\t\t: ActionConfidence.Fallback;\n};\n\nexport const mapSpan = (r: {\n\ttrace_id: string;\n\tspan_id: string;\n\tparent_span_id: string | null;\n\tservice_name: string | null;\n\tspan_name: string;\n\tstatus_code: number;\n\tstatus_message: string | null;\n\tstart_time: string;\n\tduration_ms: number;\n\tinteraction_id: string | null;\n}): SpanRef => ({\n\ttraceId: r.trace_id,\n\tspanId: r.span_id,\n\tparentSpanId: r.parent_span_id,\n\tserviceName: r.service_name,\n\tspanName: r.span_name,\n\tstatusCode: r.status_code,\n\tstatusMessage: r.status_message,\n\tstartTime: r.start_time,\n\tdurationMs: r.duration_ms,\n\tinteractionId: r.interaction_id,\n});\n\nexport const mapLog = (r: {\n\tlog_id: string;\n\ttrace_id: string | null;\n\tspan_id: string | null;\n\tservice_name: string | null;\n\tlogger_name: string | null;\n\tseverity: string;\n\tmessage: string;\n\toccurred_at: string;\n\tinteraction_id: string | null;\n}): LogRef => ({\n\tlogId: r.log_id,\n\ttraceId: r.trace_id,\n\tspanId: r.span_id,\n\tserviceName: r.service_name,\n\tloggerName: r.logger_name,\n\tseverity: r.severity,\n\tmessage: r.message,\n\toccurredAt: r.occurred_at,\n\tinteractionId: r.interaction_id,\n});\n\nexport const mapUsage = (r: {\n\tevent_id: string;\n\tevent_type: string;\n\tevent_name: string;\n\tpage_path: string | null;\n\tseverity: string | null;\n\toccurred_at: string;\n\tinteraction_id: string | null;\n\tsession_id: string | null;\n}): UsageEventRef => ({\n\teventId: r.event_id,\n\teventType: r.event_type,\n\teventName: r.event_name,\n\tpagePath: r.page_path,\n\tseverity: r.severity,\n\toccurredAt: r.occurred_at,\n\tinteractionId: r.interaction_id,\n\tsessionId: r.session_id,\n});\n\nexport const mapAi = (r: {\n\tcall_id: string;\n\ttrace_id: string | null;\n\tmodel_name: string;\n\tprovider: string;\n\ttotal_cost_usd: number | null;\n\toccurred_at: string;\n\tinteraction_id: string | null;\n}): AICallRef => ({\n\tcallId: r.call_id,\n\ttraceId: r.trace_id,\n\tmodelName: r.model_name,\n\tprovider: r.provider,\n\ttotalCostUsd: r.total_cost_usd,\n\toccurredAt: r.occurred_at,\n\tinteractionId: r.interaction_id,\n});\n\nexport const mapMetricExemplar = (r: {\n\tid: string;\n\tpoint_id: string;\n\tseries_id: string;\n\tmetric_name: string;\n\tservice_name: string | null;\n\ttrace_id: string | null;\n\tspan_id: string | null;\n\tts_ns: string;\n\tvalue: number;\n\treceived_at: string;\n}): MetricExemplarRef => ({\n\tid: r.id,\n\tpointId: r.point_id,\n\tseriesId: r.series_id,\n\tmetricName: r.metric_name,\n\tserviceName: r.service_name,\n\ttraceId: r.trace_id,\n\tspanId: r.span_id,\n\ttsNs: r.ts_ns,\n\tvalue: r.value,\n\treceivedAt: r.received_at,\n});\n\nexport const mapAction = (r: {\n\tid: string;\n\tproject_id: string;\n\troot_action_id: string;\n\tcaused_by_action_id: string | null;\n\tactor_type: string;\n\tactor_id: string | null;\n\taction_kind: string;\n\tname: string | null;\n\tstatus: string;\n\tstarted_at: string;\n\tended_at: string | null;\n\tduration_ms: number | null;\n\ttrace_id: string | null;\n\tspan_id: string | null;\n\tsession_id: string | null;\n\tinteraction_id: string | null;\n\tuser_id: string | null;\n\tagent_run_id: string | null;\n\tstep_id: string | null;\n\ttool_call_id: string | null;\n\tprompt_version: string | null;\n\tmodel_name: string | null;\n\tprovider: string | null;\n\ttotal_cost_usd: number | null;\n\tattrs_json: string | null;\n}): ActionRef => ({\n\tid: r.id,\n\tprojectId: r.project_id,\n\trootActionId: r.root_action_id,\n\tcausedByActionId: r.caused_by_action_id,\n\tactorType: r.actor_type,\n\tactorId: r.actor_id,\n\tactionKind: r.action_kind,\n\tname: r.name,\n\tstatus: r.status,\n\tstartedAt: r.started_at,\n\tendedAt: r.ended_at,\n\tdurationMs: r.duration_ms,\n\ttraceId: r.trace_id,\n\tspanId: r.span_id,\n\tsessionId: r.session_id,\n\tinteractionId: r.interaction_id,\n\tuserId: r.user_id,\n\tagentRunId: r.agent_run_id,\n\tstepId: r.step_id,\n\ttoolCallId: r.tool_call_id,\n\tpromptVersion: r.prompt_version,\n\tmodelName: r.model_name,\n\tprovider: r.provider,\n\ttotalCostUsd: r.total_cost_usd,\n\tcausalConfidence: mapCausalConfidence(r),\n\tattrsJson: r.attrs_json,\n});\n\nexport const mapAgentRun = (r: {\n\tid: string;\n\tproject_id: string;\n\tagent_id: string;\n\tagent_name: string;\n\tagent_version: string;\n\tgoal: string | null;\n\toutcome: string | null;\n\tautonomy_level: string;\n\tstatus: string;\n\terror_message: string | null;\n\ttotal_cost_usd: number | null;\n\ttotal_duration_ms: number | null;\n\tmetadata_json: string | null;\n}): AgentRunRef => ({\n\tid: r.id,\n\tprojectId: r.project_id,\n\tagentId: r.agent_id,\n\tagentName: r.agent_name,\n\tagentVersion: r.agent_version,\n\tgoal: r.goal,\n\toutcome: r.outcome,\n\tautonomyLevel: r.autonomy_level,\n\tstatus: r.status,\n\terrorMessage: r.error_message,\n\ttotalCostUsd: r.total_cost_usd,\n\ttotalDurationMs: r.total_duration_ms,\n\tmetadataJson: r.metadata_json,\n});\n\nexport const mapToolCall = (r: {\n\tid: string;\n\taction_id: string;\n\tproject_id: string;\n\ttool_name: string;\n\targs_hash: string;\n\tresult_hash: string;\n\terror_type: string | null;\n\tside_effect: number;\n\tapproval_state: string | null;\n\targs_redacted: string | null;\n\tresult_redacted: string | null;\n\tmcp_audit_json?: string | null;\n\tmutation_before_json?: string | null;\n\tmutation_after_json?: string | null;\n\tmutation_diff_json?: string | null;\n\tmutation_artifact_id?: string | null;\n}): ToolCallRef => ({\n\tid: r.id,\n\tactionId: r.action_id,\n\tprojectId: r.project_id,\n\ttoolName: r.tool_name,\n\targsHash: r.args_hash,\n\tresultHash: r.result_hash,\n\terrorType: r.error_type,\n\tsideEffect: r.side_effect,\n\tapprovalState: r.approval_state,\n\targsRedacted: r.args_redacted,\n\tresultRedacted: r.result_redacted,\n\tmcpAuditJson: r.mcp_audit_json ?? null,\n\tmutationBeforeJson: r.mutation_before_json ?? null,\n\tmutationAfterJson: r.mutation_after_json ?? null,\n\tmutationDiffJson: r.mutation_diff_json ?? null,\n\tmutationArtifactId: r.mutation_artifact_id ?? null,\n});\n\nexport const mapRetrievalEvent = (r: {\n\tid: string;\n\taction_id: string;\n\tproject_id: string;\n\tretriever_name: string;\n\tquery_hash: string;\n\tdocuments_json: string | null;\n\ttotal_results: number;\n\tmax_relevance_score: number | null;\n\tduration_ms: number | null;\n}): RetrievalEventRef => ({\n\tid: r.id,\n\tactionId: r.action_id,\n\tprojectId: r.project_id,\n\tretrieverName: r.retriever_name,\n\tqueryHash: r.query_hash,\n\tdocumentsJson: r.documents_json,\n\ttotalResults: r.total_results,\n\tmaxRelevanceScore: r.max_relevance_score,\n\tdurationMs: r.duration_ms,\n});\n\nexport const mapEvalResult = (r: {\n\tid: string;\n\taction_id: string;\n\tproject_id: string;\n\tevaluator_name: string;\n\tevaluator_version: string;\n\tscore: number | null;\n\tpassed: number;\n\treasoning: string | null;\n\trubric_json: string | null;\n}): EvalResultRef => ({\n\tid: r.id,\n\tactionId: r.action_id,\n\tprojectId: r.project_id,\n\tevaluatorName: r.evaluator_name,\n\tevaluatorVersion: r.evaluator_version,\n\tscore: r.score,\n\tpassed: r.passed,\n\treasoning: r.reasoning,\n\trubricJson: r.rubric_json,\n});\n\nexport const mapArtifact = (r: {\n\tid: string;\n\taction_id: string;\n\tproject_id: string;\n\tartifact_name: string;\n\tartifact_type: string;\n\tstorage_ref: string | null;\n\tsize_bytes: number | null;\n\tsha256_hash: string | null;\n\tcontent_preview: string | null;\n}): ArtifactRef => ({\n\tid: r.id,\n\tactionId: r.action_id,\n\tprojectId: r.project_id,\n\tartifactName: r.artifact_name,\n\tartifactType: r.artifact_type,\n\tstorageRef: r.storage_ref,\n\tsizeBytes: r.size_bytes,\n\tsha256Hash: r.sha256_hash,\n\tcontentPreview: r.content_preview,\n});\n","import type { SqlDb } from \"../sql-db\";\nimport { FETCH_LIMIT } from \"./constants\";\nimport { mapAi, mapLog, mapMetricExemplar, mapSpan, mapUsage } from \"./mappers\";\nimport type { EntityManifest } from \"./types\";\n\nexport async function manifestBySession(\n\tdb: SqlDb,\n\tprojectId: string,\n\tsessionId: string,\n): Promise<EntityManifest> {\n\tconst [spans, logs, usage, aiCalls, replay] = await Promise.all([\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n\t\t\t\t\t\tstatus_code, status_message, start_time, duration_ms, interaction_id\n\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\tWHERE project_id = ? AND session_id = ?\n\t\t\t\t\tORDER BY start_time ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, sessionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapSpan>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT log_id, trace_id, span_id, service_name, logger_name,\n\t\t\t\t\t\tseverity, message, occurred_at, interaction_id, session_id\n\t\t\t\t\tFROM logs\n\t\t\t\t\tWHERE project_id = ? AND session_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, sessionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapLog>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT event_id, event_type, event_name, page_path, severity,\n\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\tFROM usage_events\n\t\t\t\t\tWHERE project_id = ? AND session_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, sessionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapUsage>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT call_id, trace_id, model_name, provider, total_cost_usd,\n\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\tFROM ai_calls\n\t\t\t\t\tWHERE project_id = ? AND session_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, sessionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapAi>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT first_chunk_at, last_chunk_at, chunk_count, events_count\n\t\t\t\t\tFROM session_replay_metadata\n\t\t\t\t\tWHERE session_id = ?`,\n\t\t\t)\n\t\t\t.bind(sessionId)\n\t\t\t.first<{\n\t\t\t\tfirst_chunk_at: string;\n\t\t\t\tlast_chunk_at: string;\n\t\t\t\tchunk_count: number;\n\t\t\t\tevents_count: number;\n\t\t\t}>(),\n\t]);\n\n\treturn {\n\t\tspans: spans.results.map(mapSpan),\n\t\tlogs: logs.results.map(mapLog),\n\t\tusageEvents: usage.results.map(mapUsage),\n\t\taiCalls: aiCalls.results.map(mapAi),\n\t\tmetricExemplars: [],\n\t\treplay: replay\n\t\t\t? {\n\t\t\t\t\tsessionId,\n\t\t\t\t\tfirstChunkAt: replay.first_chunk_at,\n\t\t\t\t\tlastChunkAt: replay.last_chunk_at,\n\t\t\t\t\tchunkCount: replay.chunk_count,\n\t\t\t\t\teventsCount: replay.events_count,\n\t\t\t\t}\n\t\t\t: null,\n\t};\n}\n\nexport async function manifestByTrace(\n\tdb: SqlDb,\n\tprojectId: string,\n\ttraceId: string,\n): Promise<EntityManifest> {\n\tconst [spans, logs, aiCalls, metricExemplars] = await Promise.all([\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n\t\t\t\t\t\tstatus_code, status_message, start_time, duration_ms, interaction_id\n\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\t\tORDER BY start_time ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, traceId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapSpan>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT log_id, trace_id, span_id, service_name, logger_name,\n\t\t\t\t\t\tseverity, message, occurred_at, interaction_id, session_id\n\t\t\t\t\tFROM logs\n\t\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, traceId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapLog>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT call_id, trace_id, model_name, provider, total_cost_usd,\n\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\tFROM ai_calls\n\t\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, traceId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapAi>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT id, point_id, series_id, metric_name, service_name,\n\t\t\t\t\t\ttrace_id, span_id, ts_ns, value, received_at\n\t\t\t\t\tFROM metric_exemplars\n\t\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\t\tORDER BY ts_ns DESC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, traceId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapMetricExemplar>[0]>(),\n\t]);\n\n\treturn {\n\t\tspans: spans.results.map(mapSpan),\n\t\tlogs: logs.results.map(mapLog),\n\t\tusageEvents: [],\n\t\taiCalls: aiCalls.results.map(mapAi),\n\t\tmetricExemplars: metricExemplars.results.map(mapMetricExemplar),\n\t\treplay: null,\n\t};\n}\n\nexport async function manifestByInteraction(\n\tdb: SqlDb,\n\tprojectId: string,\n\tinteractionId: string,\n): Promise<EntityManifest> {\n\tconst [spans, logs, usage, aiCalls] = await Promise.all([\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n\t\t\t\t\t\tstatus_code, status_message, start_time, duration_ms, interaction_id\n\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\tWHERE project_id = ? AND interaction_id = ?\n\t\t\t\t\tORDER BY start_time ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, interactionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapSpan>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT log_id, trace_id, span_id, service_name, logger_name,\n\t\t\t\t\t\tseverity, message, occurred_at, interaction_id, session_id\n\t\t\t\t\tFROM logs\n\t\t\t\t\tWHERE project_id = ? AND interaction_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, interactionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapLog>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT event_id, event_type, event_name, page_path, severity,\n\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\tFROM usage_events\n\t\t\t\t\tWHERE project_id = ? AND interaction_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, interactionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapUsage>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT call_id, trace_id, model_name, provider, total_cost_usd,\n\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\tFROM ai_calls\n\t\t\t\t\tWHERE project_id = ? AND interaction_id = ?\n\t\t\t\t\tORDER BY occurred_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, interactionId, FETCH_LIMIT)\n\t\t\t.all<Parameters<typeof mapAi>[0]>(),\n\t]);\n\n\treturn {\n\t\tspans: spans.results.map(mapSpan),\n\t\tlogs: logs.results.map(mapLog),\n\t\tusageEvents: usage.results.map(mapUsage),\n\t\taiCalls: aiCalls.results.map(mapAi),\n\t\tmetricExemplars: [],\n\t\treplay: null,\n\t};\n}\n","import type { SqlDb } from \"../sql-db\";\nimport { FETCH_LIMIT } from \"./constants\";\nimport { mapAi, mapLog, mapSpan, mapUsage } from \"./mappers\";\nimport type { EntityManifest } from \"./types\";\n\nexport async function manifestByUser(\n\tdb: SqlDb,\n\tprojectId: string,\n\tuserId: string,\n\topts: { limit?: number; sessions?: number } = {},\n): Promise<EntityManifest> {\n\tconst limit = Math.min(opts.limit ?? 100, FETCH_LIMIT);\n\tconst sessionLimit = Math.max(1, Math.min(opts.sessions ?? 5, 20));\n\n\t// Step 1 — resolve user_id → visitor_id. user_profiles is the only\n\t// table that owns the user_id ↔ visitor_id binding.\n\tconst profile = await db\n\t\t.prepare(`SELECT visitor_id FROM user_profiles WHERE user_id = ? LIMIT 1`)\n\t\t.bind(userId)\n\t\t.first<{ visitor_id: string }>();\n\tif (!profile) {\n\t\treturn {\n\t\t\tspans: [],\n\t\t\tlogs: [],\n\t\t\tusageEvents: [],\n\t\t\taiCalls: [],\n\t\t\tmetricExemplars: [],\n\t\t\treplay: null,\n\t\t};\n\t}\n\n\t// Step 2 — recent session_ids for that visitor. Pull from usage_events\n\t// (the table that always carries visitor_id; ai_span_payloads has\n\t// user_id directly but only when present in AI traffic).\n\tconst sessions = await db\n\t\t.prepare(\n\t\t\t`SELECT DISTINCT session_id, MAX(occurred_at) AS last_at\n\t\t\t\tFROM usage_events\n\t\t\t\tWHERE project_id = ? AND visitor_id = ? AND session_id IS NOT NULL\n\t\t\t\tGROUP BY session_id\n\t\t\t\tORDER BY last_at DESC\n\t\t\t\tLIMIT ?`,\n\t\t)\n\t\t.bind(projectId, profile.visitor_id, sessionLimit)\n\t\t.all<{ session_id: string; last_at: string }>();\n\tconst sessionIds = sessions.results.map((r) => r.session_id);\n\tif (sessionIds.length === 0) {\n\t\treturn {\n\t\t\tspans: [],\n\t\t\tlogs: [],\n\t\t\tusageEvents: [],\n\t\t\taiCalls: [],\n\t\t\tmetricExemplars: [],\n\t\t\treplay: null,\n\t\t};\n\t}\n\n\t// Step 3 — fan out to each signal table with IN (?, ?, …). D1 caps\n\t// bound parameters at 100, so the sessionLimit clamp above (≤20)\n\t// keeps us well under.\n\tconst placeholders = sessionIds.map(() => \"?\").join(\", \");\n\tconst [spans, logs, usage, aiCalls, replay] = await Promise.all([\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT trace_id, span_id, parent_span_id, service_name, span_name,\n\t\t\t\t\t\tstatus_code, status_message, start_time, duration_ms, interaction_id\n\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\tWHERE project_id = ? AND session_id IN (${placeholders})\n\t\t\t\t\tORDER BY start_time DESC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, ...sessionIds, limit)\n\t\t\t.all<Parameters<typeof mapSpan>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT log_id, trace_id, span_id, service_name, logger_name,\n\t\t\t\t\t\tseverity, message, occurred_at, interaction_id, session_id\n\t\t\t\t\tFROM logs\n\t\t\t\t\tWHERE project_id = ? AND session_id IN (${placeholders})\n\t\t\t\t\tORDER BY occurred_at DESC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, ...sessionIds, limit)\n\t\t\t.all<Parameters<typeof mapLog>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT event_id, event_type, event_name, page_path, severity,\n\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\tFROM usage_events\n\t\t\t\t\tWHERE project_id = ? AND session_id IN (${placeholders})\n\t\t\t\t\tORDER BY occurred_at DESC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, ...sessionIds, limit)\n\t\t\t.all<Parameters<typeof mapUsage>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT call_id, trace_id, model_name, provider, total_cost_usd,\n\t\t\t\t\t\toccurred_at, interaction_id, session_id\n\t\t\t\t\tFROM ai_calls\n\t\t\t\t\tWHERE project_id = ? AND session_id IN (${placeholders})\n\t\t\t\t\tORDER BY occurred_at DESC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, ...sessionIds, limit)\n\t\t\t.all<Parameters<typeof mapAi>[0]>(),\n\t\t// Most recent replay across the user's sessions, if any.\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT session_id, first_chunk_at, last_chunk_at, chunk_count, events_count\n\t\t\t\t\tFROM session_replay_metadata\n\t\t\t\t\tWHERE session_id IN (${placeholders})\n\t\t\t\t\tORDER BY last_chunk_at DESC LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(...sessionIds)\n\t\t\t.first<{\n\t\t\t\tsession_id: string;\n\t\t\t\tfirst_chunk_at: string;\n\t\t\t\tlast_chunk_at: string;\n\t\t\t\tchunk_count: number;\n\t\t\t\tevents_count: number;\n\t\t\t}>(),\n\t]);\n\n\treturn {\n\t\tspans: spans.results.map(mapSpan),\n\t\tlogs: logs.results.map(mapLog),\n\t\tusageEvents: usage.results.map(mapUsage),\n\t\taiCalls: aiCalls.results.map(mapAi),\n\t\tmetricExemplars: [],\n\t\treplay: replay\n\t\t\t? {\n\t\t\t\t\tsessionId: replay.session_id,\n\t\t\t\t\tfirstChunkAt: replay.first_chunk_at,\n\t\t\t\t\tlastChunkAt: replay.last_chunk_at,\n\t\t\t\t\tchunkCount: replay.chunk_count,\n\t\t\t\t\teventsCount: replay.events_count,\n\t\t\t\t}\n\t\t\t: null,\n\t};\n}\n","import {\n\tmanifestByAction,\n\tmanifestByActor,\n\tmanifestByAgentRun,\n} from \"./identity-index/action-lookups\";\nimport {\n\tmanifestByInteraction,\n\tmanifestBySession,\n\tmanifestByTrace,\n} from \"./identity-index/key-lookups\";\nimport type {\n\tEntityManifest,\n\tEntityManifestExtended,\n} from \"./identity-index/types\";\nimport { manifestByUser } from \"./identity-index/user-lookup\";\nimport type { SqlDb } from \"./sql-db\";\n\nexport type {\n\tActionRef,\n\tAgentRunRef,\n\tAICallRef,\n\tArtifactRef,\n\tEntityManifest,\n\tEntityManifestExtended,\n\tEvalResultRef,\n\tLogRef,\n\tMetricExemplarRef,\n\tReplayRef,\n\tRetrievalEventRef,\n\tSpanRef,\n\tToolCallRef,\n\tUsageEventRef,\n} from \"./identity-index/types\";\n\nexport class IdentityIndex {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync bySession(\n\t\tprojectId: string,\n\t\tsessionId: string,\n\t): Promise<EntityManifest> {\n\t\treturn manifestBySession(this.db, projectId, sessionId);\n\t}\n\n\tasync byTrace(projectId: string, traceId: string): Promise<EntityManifest> {\n\t\treturn manifestByTrace(this.db, projectId, traceId);\n\t}\n\n\tasync byInteraction(\n\t\tprojectId: string,\n\t\tinteractionId: string,\n\t): Promise<EntityManifest> {\n\t\treturn manifestByInteraction(this.db, projectId, interactionId);\n\t}\n\n\tasync byUser(\n\t\tprojectId: string,\n\t\tuserId: string,\n\t\topts: { limit?: number; sessions?: number } = {},\n\t): Promise<EntityManifest> {\n\t\treturn manifestByUser(this.db, projectId, userId, opts);\n\t}\n\n\tasync byAction(\n\t\tprojectId: string,\n\t\tactionId: string,\n\t): Promise<EntityManifestExtended> {\n\t\treturn manifestByAction(this.db, projectId, actionId);\n\t}\n\n\tasync byAgentRun(\n\t\tprojectId: string,\n\t\tagentRunId: string,\n\t): Promise<EntityManifestExtended> {\n\t\treturn manifestByAgentRun(this.db, projectId, agentRunId);\n\t}\n\n\tasync byActor(\n\t\tprojectId: string,\n\t\tactorType: string,\n\t\tactorId: string,\n\t): Promise<EntityManifestExtended> {\n\t\treturn manifestByActor(this.db, projectId, actorType, actorId);\n\t}\n}\n","/**\n * Extract the project id set by ingest-auth or dashboard-auth middleware.\n * Returns 'default' when no middleware has attached one (e.g. unauth dev).\n *\n * Uses a loose Context typing so plugins don't need to re-declare `Variables`\n * on every route registration. The underlying value is always a string set by\n * the auth middlewares.\n */\ninterface ProjectContext {\n\tget(key: \"projectId\"): string | undefined;\n}\n\nexport function getProjectId(c: ProjectContext): string {\n\treturn (c.get(\"projectId\") as string | undefined) || \"default\";\n}\n","import type {\n\tAICallPayload,\n\tAICallRecord,\n\tAIEvaluationPayload,\n\tToolResponseContract,\n} from \"@obsunified/types\";\nimport {\n\tEVIDENCE_REFERENCE_CONTRACT,\n\tEVIDENCE_REFERENCE_SCHEMA_VERSION,\n\tEvidenceReferenceJsonSchema,\n\tTOOL_RESPONSE_CONTRACT_SCHEMA_VERSION,\n} from \"@obsunified/types\";\nimport { getConfiguredRetentionHours } from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { AIStore, type IngestEvaluation } from \"../lib/ai-store\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport const aiReceiverPlugin: CollectorPlugin = {\n\tname: \"ai-receiver\",\n\tregister(app, _runtime) {\n\t\tapp.post(\"/v1/ai\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tlet payload: AICallPayload;\n\t\t\ttry {\n\t\t\t\tpayload = await c.req.json<AICallPayload>();\n\t\t\t} catch {\n\t\t\t\treturn c.json({ error: \"Invalid JSON body\" }, 400);\n\t\t\t}\n\t\t\tif (!payload.calls || !Array.isArray(payload.calls)) {\n\t\t\t\treturn c.json({ error: \"Missing calls array\" }, 400);\n\t\t\t}\n\t\t\tif (payload.calls.length > 500) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: `Too many AI calls: ${payload.calls.length} (max 500)` },\n\t\t\t\t\t413,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\n\t\t\tconst retentionHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst now = new Date();\n\t\t\tconst nowStr = now.toISOString();\n\t\t\tconst expires = new Date(\n\t\t\t\tnow.getTime() + retentionHours * 60 * 60 * 1000,\n\t\t\t).toISOString();\n\n\t\t\tconst records: AICallRecord[] = payload.calls.map((call) => ({\n\t\t\t\tprojectId,\n\t\t\t\tcallId: crypto.randomUUID(),\n\t\t\t\ttraceId: call.traceId || null,\n\t\t\t\tspanId: call.spanId || null,\n\t\t\t\tserviceName: call.serviceName || null,\n\t\t\t\tmodelName: call.modelName,\n\t\t\t\tprovider: call.provider,\n\t\t\t\tcallType: call.callType,\n\t\t\t\trequestJson: call.request ? JSON.stringify(call.request) : null,\n\t\t\t\tresponseJson: call.response ? JSON.stringify(call.response) : null,\n\t\t\t\tpromptTokens: call.promptTokens || null,\n\t\t\t\tcompletionTokens: call.completionTokens || null,\n\t\t\t\ttotalCostUsd: call.totalCostUsd || null,\n\t\t\t\tlatencyMs: call.latencyMs || null,\n\t\t\t\tisError: call.isError || false,\n\t\t\t\terrorMessage: call.errorMessage || null,\n\t\t\t\toccurredAt: call.occurredAt || nowStr,\n\t\t\t\treceivedAt: nowStr,\n\t\t\t\texpiresAt: expires,\n\t\t\t\t// RFC 0004 — denormalized from the active root span, when the\n\t\t\t\t// SDK was told to propagate it.\n\t\t\t\tsessionId: call.sessionId ?? null,\n\t\t\t\tinteractionId: call.interactionId ?? null,\n\t\t\t}));\n\n\t\t\tawait store.ingestBatch(records);\n\n\t\t\treturn c.json({ accepted: records.length }, 202);\n\t\t});\n\n\t\tapp.get(\"/internal/ai/overview\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\t\t\tconst query = c.req.query();\n\t\t\tconst hours = parseInt(query.hours || \"24\", 10);\n\n\t\t\tconst response = await store.getAICalls({\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tservice: query.service,\n\t\t\t\tmodel: query.model,\n\t\t\t\tisError:\n\t\t\t\t\tquery.isError === \"true\"\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: query.isError === \"false\"\n\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\ttraceId: query.traceId,\n\t\t\t\tlimit: parseInt(query.limit || \"100\", 10),\n\t\t\t});\n\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\t// OpenInference-kind spans (LLM/TOOL/RETRIEVER/CHAIN/AGENT/...) joined\n\t\t// with their payload side-table. This is the replacement for the flat\n\t\t// ai_calls endpoint — it returns typed spans that live inside the\n\t\t// regular trace tree.\n\t\tapp.get(\"/internal/ai/spans\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\t\t\tconst query = c.req.query();\n\n\t\t\tconst response = await store.getAISpans({\n\t\t\t\tprojectId,\n\t\t\t\thours: parseInt(query.hours || \"24\", 10),\n\t\t\t\tkind: query.kind,\n\t\t\t\tservice: query.service,\n\t\t\t\ttraceId: query.traceId,\n\t\t\t\tlimit: parseInt(query.limit || \"100\", 10),\n\t\t\t});\n\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\t// Attach evaluations to AI spans. Accepts a batch of evaluation records\n\t\t// keyed by (traceId, spanId). Caller supplies name (e.g. \"hallucination\"),\n\t\t// one or both of score/label, and optional explanation + metadata.\n\t\tapp.post(\"/v1/ai/evaluations\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tlet payload: AIEvaluationPayload;\n\t\t\ttry {\n\t\t\t\tpayload = await c.req.json<AIEvaluationPayload>();\n\t\t\t} catch {\n\t\t\t\treturn c.json({ error: \"Invalid JSON body\" }, 400);\n\t\t\t}\n\t\t\tif (!payload.evaluations || !Array.isArray(payload.evaluations)) {\n\t\t\t\treturn c.json({ error: \"Missing evaluations array\" }, 400);\n\t\t\t}\n\t\t\tif (payload.evaluations.length > 500) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: `Too many evaluations: ${payload.evaluations.length} (max 500)`,\n\t\t\t\t\t},\n\t\t\t\t\t413,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst retentionHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst now = new Date();\n\t\t\tconst nowStr = now.toISOString();\n\t\t\tconst expires = new Date(\n\t\t\t\tnow.getTime() + retentionHours * 60 * 60 * 1000,\n\t\t\t).toISOString();\n\n\t\t\tconst records: IngestEvaluation[] = [];\n\t\t\tfor (const e of payload.evaluations) {\n\t\t\t\tif (!e.traceId || !e.spanId || !e.name || !e.source) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Each evaluation needs traceId, spanId, name, source\" },\n\t\t\t\t\t\t400,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\trecords.push({\n\t\t\t\t\tprojectId,\n\t\t\t\t\tevaluationId: crypto.randomUUID(),\n\t\t\t\t\ttraceId: e.traceId,\n\t\t\t\t\tspanId: e.spanId,\n\t\t\t\t\tname: e.name,\n\t\t\t\t\tscore: typeof e.score === \"number\" ? e.score : null,\n\t\t\t\t\tlabel: e.label ?? null,\n\t\t\t\t\texplanation: e.explanation ?? null,\n\t\t\t\t\tsource: e.source,\n\t\t\t\t\tmetadataJson: e.metadata ? JSON.stringify(e.metadata) : null,\n\t\t\t\t\tcreatedAt: nowStr,\n\t\t\t\t\texpiresAt: expires,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\t\t\tawait store.ingestEvaluations(records);\n\t\t\treturn c.json({ accepted: records.length }, 202);\n\t\t});\n\n\t\t// List conversation sessions — one row per distinct session.id with\n\t\t// aggregated stats (span count, tokens, cost, error count, etc.).\n\t\tapp.get(\"/internal/ai/sessions\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\t\t\tconst query = c.req.query();\n\t\t\tconst response = await store.listSessions({\n\t\t\t\tprojectId,\n\t\t\t\thours: parseInt(query.hours || \"24\", 10),\n\t\t\t\tuserId: query.userId,\n\t\t\t\tlimit: parseInt(query.limit || \"100\", 10),\n\t\t\t});\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\t// Full detail for a single session: every AI span in timestamp order\n\t\t// (across one or more traces) plus any evaluations attached to them.\n\t\tapp.get(\"/internal/ai/sessions/:sessionId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\t\t\tconst sessionId = c.req.param(\"sessionId\");\n\t\t\tconst response = await store.getSession(projectId, sessionId);\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\t// List evaluations, optionally scoped to a single span or trace.\n\t\tapp.get(\"/internal/ai/evaluations\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\t\t\tconst query = c.req.query();\n\n\t\t\tconst response = await store.listEvaluations({\n\t\t\t\tprojectId,\n\t\t\t\ttraceId: query.traceId,\n\t\t\t\tspanId: query.spanId,\n\t\t\t\tname: query.name,\n\t\t\t\tlimit: parseInt(query.limit || \"200\", 10),\n\t\t\t});\n\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\tapp.get(\"/internal/ai/evaluations/:evaluationId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst evaluationId = c.req.param(\"evaluationId\");\n\t\t\tconst store = new AIStore(sqlDbFor(c.env));\n\t\t\tconst evaluation = await store.getEvaluation(projectId, evaluationId);\n\t\t\tif (!evaluation) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Evaluation not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst contract: ToolResponseContract = {\n\t\t\t\tschemaVersion: TOOL_RESPONSE_CONTRACT_SCHEMA_VERSION,\n\t\t\t\ttransport: \"http\",\n\t\t\t\ttool: \"GET /internal/ai/evaluations/:evaluationId\",\n\t\t\t\tparams: { projectId, evaluationId },\n\t\t\t\treturns:\n\t\t\t\t\t\"{ evaluation: AIEvaluationRecord, evidenceContract: EVIDENCE_REFERENCE_CONTRACT, timestamp: string }\",\n\t\t\t\tevidenceReferenceSchemaVersion: EVIDENCE_REFERENCE_SCHEMA_VERSION,\n\t\t\t\tevidenceReferenceJsonSchema: EvidenceReferenceJsonSchema,\n\t\t\t};\n\t\t\treturn c.json({\n\t\t\t\tevaluation,\n\t\t\t\tevidenceContract: EVIDENCE_REFERENCE_CONTRACT,\n\t\t\t\tcontract,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t});\n\t\t});\n\t},\n};\n","/**\n * Span processor that routes large AI payloads to the ai_span_payloads\n * side table.\n *\n * For every span that has an `openinference.span.kind` attribute, we look\n * for `ai.payload.input` / `ai.payload.output`, write them (plus the kind)\n * to `ai_span_payloads`, and strip them from the span's attributes_json\n * before it hits `telemetry_spans`.\n *\n * This keeps the hot spans table lean while preserving full replay data\n * for AI calls.\n */\n\nimport type { JsonValue, StoredSpan } from \"@obsunified/types\";\nimport {\n\tACTION_ID_KEY,\n\tAI_PAYLOAD_INPUT_KEY,\n\tAI_PAYLOAD_OUTPUT_KEY,\n\tINTERACTION_ID_KEY,\n\tisOpenInferenceSpanKind,\n\tOPENINFERENCE_SPAN_KIND_KEY,\n\tSESSION_ID_KEY,\n\tUSER_ID_KEY,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { sha256Hex } from \"../lib/hash\";\nimport { parseJsonRecord } from \"../lib/json\";\nimport { isPayloadCaptureEnabled } from \"../lib/payload-capture\";\nimport { sqlDbFor } from \"../lib/sql-db\";\n\ninterface PayloadRow {\n\tprojectId: string;\n\ttraceId: string;\n\tspanId: string;\n\tspanKind: string;\n\tinputJson: string | null;\n\toutputJson: string | null;\n\tinputHash: string | null;\n\toutputHash: string | null;\n\tsessionId: string | null;\n\tuserId: string | null;\n\tinteractionId: string | null;\n\tactionId: string | null;\n\treceivedAt: string;\n\texpiresAt: string;\n}\n\nconst asString = (value: JsonValue | undefined): string | null =>\n\ttypeof value === \"string\" && value.length > 0 ? value : null;\n\nconst toJsonString = (value: unknown): string | null => {\n\tif (value === undefined || value === null) return null;\n\tif (typeof value === \"string\") return value;\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn String(value);\n\t}\n};\n\nexport const aiSpanPayloadsProcessorPlugin: CollectorPlugin = {\n\tname: \"ai-span-payloads-processor\",\n\tregister(_app, runtime) {\n\t\truntime.addSpanProcessor({\n\t\t\tname: \"ai-span-payloads-processor\",\n\t\t\tasync process(spans, context) {\n\t\t\t\tconst db = sqlDbFor(context.env);\n\t\t\t\tconst rows: PayloadRow[] = [];\n\t\t\t\tconst captureByProject = new Map<string, boolean>();\n\t\t\t\tconst projectCaptureEnabled = async (projectId: string) => {\n\t\t\t\t\tconst cached = captureByProject.get(projectId);\n\t\t\t\t\tif (cached !== undefined) return cached;\n\t\t\t\t\tconst enabled = await isPayloadCaptureEnabled(\n\t\t\t\t\t\tdb,\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tcontext.env,\n\t\t\t\t\t);\n\t\t\t\t\tcaptureByProject.set(projectId, enabled);\n\t\t\t\t\treturn enabled;\n\t\t\t\t};\n\n\t\t\t\tconst transformed = await Promise.all(\n\t\t\t\t\tspans.map(async (span): Promise<StoredSpan> => {\n\t\t\t\t\t\tconst attrs = parseJsonRecord(span.attributesJson);\n\t\t\t\t\t\tconst kind = attrs[OPENINFERENCE_SPAN_KIND_KEY];\n\t\t\t\t\t\tif (!isOpenInferenceSpanKind(kind)) return span;\n\n\t\t\t\t\t\tconst rawInput = attrs[AI_PAYLOAD_INPUT_KEY];\n\t\t\t\t\t\tconst rawOutput = attrs[AI_PAYLOAD_OUTPUT_KEY];\n\t\t\t\t\t\tconst hasInput = rawInput !== undefined;\n\t\t\t\t\t\tconst hasOutput = rawOutput !== undefined;\n\t\t\t\t\t\tconst inputJson = hasInput ? toJsonString(rawInput) : null;\n\t\t\t\t\t\tconst outputJson = hasOutput ? toJsonString(rawOutput) : null;\n\t\t\t\t\t\tconst capturePayloads = await projectCaptureEnabled(span.projectId);\n\n\t\t\t\t\t\t// Always record the row for OpenInference spans so callers can\n\t\t\t\t\t\t// join on (trace_id, span_id) even when payloads are absent.\n\t\t\t\t\t\trows.push({\n\t\t\t\t\t\t\tprojectId: span.projectId,\n\t\t\t\t\t\t\ttraceId: span.traceId,\n\t\t\t\t\t\t\tspanId: span.spanId,\n\t\t\t\t\t\t\tspanKind: kind,\n\t\t\t\t\t\t\tinputJson: capturePayloads ? inputJson : null,\n\t\t\t\t\t\t\toutputJson: capturePayloads ? outputJson : null,\n\t\t\t\t\t\t\tinputHash: inputJson ? await sha256Hex(inputJson) : null,\n\t\t\t\t\t\t\toutputHash: outputJson ? await sha256Hex(outputJson) : null,\n\t\t\t\t\t\t\tsessionId: asString(attrs[SESSION_ID_KEY]),\n\t\t\t\t\t\t\tuserId: asString(attrs[USER_ID_KEY]),\n\t\t\t\t\t\t\tinteractionId: asString(attrs[INTERACTION_ID_KEY]),\n\t\t\t\t\t\t\tactionId: asString(attrs[ACTION_ID_KEY]),\n\t\t\t\t\t\t\treceivedAt: span.receivedAt,\n\t\t\t\t\t\t\texpiresAt: span.expiresAt,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!hasInput && !hasOutput) return span;\n\n\t\t\t\t\t\t// Strip payload attrs — they live in ai_span_payloads now.\n\t\t\t\t\t\tconst stripped = { ...attrs };\n\t\t\t\t\t\tdelete stripped[AI_PAYLOAD_INPUT_KEY];\n\t\t\t\t\t\tdelete stripped[AI_PAYLOAD_OUTPUT_KEY];\n\t\t\t\t\t\treturn { ...span, attributesJson: JSON.stringify(stripped) };\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tif (rows.length > 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst stmt = db.prepare(\n\t\t\t\t\t\t\t`INSERT INTO ai_span_payloads (\n\t\t\t\t\t\t\t\tproject_id, trace_id, span_id, span_kind,\n\t\t\t\t\t\t\t\tinput_json, output_json, input_hash, output_hash, session_id, user_id,\n\t\t\t\t\t\t\t\treceived_at, expires_at, interaction_id, action_id\n\t\t\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\t\t\t\tON CONFLICT(trace_id, span_id) DO UPDATE SET\n\t\t\t\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\t\t\t\tspan_kind = excluded.span_kind,\n\t\t\t\t\t\t\t\tinput_json = excluded.input_json,\n\t\t\t\t\t\t\t\toutput_json = excluded.output_json,\n\t\t\t\t\t\t\t\tinput_hash = excluded.input_hash,\n\t\t\t\t\t\t\t\toutput_hash = excluded.output_hash,\n\t\t\t\t\t\t\t\tsession_id = excluded.session_id,\n\t\t\t\t\t\t\t\tuser_id = excluded.user_id,\n\t\t\t\t\t\t\t\treceived_at = excluded.received_at,\n\t\t\t\t\t\t\t\texpires_at = excluded.expires_at,\n\t\t\t\t\t\t\t\tinteraction_id = excluded.interaction_id,\n\t\t\t\t\t\t\t\taction_id = excluded.action_id`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait db.batch(\n\t\t\t\t\t\t\trows.map((r) =>\n\t\t\t\t\t\t\t\tstmt.bind(\n\t\t\t\t\t\t\t\t\tr.projectId,\n\t\t\t\t\t\t\t\t\tr.traceId,\n\t\t\t\t\t\t\t\t\tr.spanId,\n\t\t\t\t\t\t\t\t\tr.spanKind,\n\t\t\t\t\t\t\t\t\tr.inputJson,\n\t\t\t\t\t\t\t\t\tr.outputJson,\n\t\t\t\t\t\t\t\t\tr.inputHash,\n\t\t\t\t\t\t\t\t\tr.outputHash,\n\t\t\t\t\t\t\t\t\tr.sessionId,\n\t\t\t\t\t\t\t\t\tr.userId,\n\t\t\t\t\t\t\t\t\tr.receivedAt,\n\t\t\t\t\t\t\t\t\tr.expiresAt,\n\t\t\t\t\t\t\t\t\tr.interactionId,\n\t\t\t\t\t\t\t\t\tr.actionId,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t// Don't fail the whole ingest on payload side-table issues —\n\t\t\t\t\t\t// the spans themselves are still useful.\n\t\t\t\t\t\tcontext.logger.error(\"[ai-span-payloads-processor] write failed\", {\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn transformed;\n\t\t\t},\n\t\t});\n\t},\n};\n","import type {\n\tAlertChannel,\n\tAlertComparison,\n\tAlertEvaluation,\n\tAlertEvaluationRow,\n\tAlertEvaluationsListResponse,\n\tAlertQuery,\n\tAlertQueryAI,\n\tAlertQueryLogs,\n\tAlertQuerySpans,\n\tAlertQueryUsage,\n\tAlertRule,\n\tAlertRuleInput,\n\tAlertRuleRow,\n\tAlertSignal,\n\tAlertState,\n\tAlertStateRow,\n\tLogSeverity,\n} from \"@obsunified/types\";\nimport { EVIDENCE_REFERENCE_CONTRACT } from \"@obsunified/types\";\nimport { alertEvidenceReferences } from \"./evidence-references\";\nimport { randomHex } from \"./hash\";\nimport type { SqlDb } from \"./sql-db\";\n\nconst parseJsonField = <T>(value: unknown): T => {\n\tif (typeof value === \"string\") return JSON.parse(value) as T;\n\treturn value as T;\n};\n\nconst rowToRule = (row: AlertRuleRow, state?: AlertStateRow): AlertRule => ({\n\tid: row.id,\n\tprojectId: row.project_id,\n\tname: row.name,\n\tsignal: row.signal,\n\tquery: parseJsonField<AlertQuery>(row.query_json),\n\tthreshold: row.threshold,\n\twindowMins: row.window_mins,\n\tcomparison: row.comparison,\n\tchannels: parseJsonField<AlertChannel[]>(row.channels_json),\n\tenabled: row.enabled === 1,\n\tcreatedAt: row.created_at,\n\tupdatedAt: row.updated_at,\n\tanalysisId: row.analysis_id ?? null,\n\tcurrentState: state?.current_state,\n\tlastStateChange: state?.last_state_change ?? null,\n});\n\nconst rowToEvaluation = (row: AlertEvaluationRow): AlertEvaluation => ({\n\tid: row.id,\n\truleId: row.rule_id,\n\tprojectId: row.project_id,\n\tevaluatedAt: row.evaluated_at,\n\tvalue: row.value,\n\tstate: row.state,\n\tnotified: row.notified === 1,\n});\n\nconst windowCutoffIso = (windowMins: number): string =>\n\tnew Date(Date.now() - windowMins * 60 * 1000).toISOString();\n\nconst SIGNALS: AlertSignal[] = [\"spans\", \"logs\", \"usage\", \"ai\"];\nconst COMPARISONS: AlertComparison[] = [\">\", \">=\", \"<\", \"<=\"];\n\nexport function compareValue(\n\tvalue: number,\n\tthreshold: number,\n\tcomparison: AlertComparison,\n): boolean {\n\tswitch (comparison) {\n\t\tcase \">\":\n\t\t\treturn value > threshold;\n\t\tcase \">=\":\n\t\t\treturn value >= threshold;\n\t\tcase \"<\":\n\t\t\treturn value < threshold;\n\t\tcase \"<=\":\n\t\t\treturn value <= threshold;\n\t}\n}\n\nexport class AlertsStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tvalidateInput(input: AlertRuleInput): void {\n\t\tif (!input.name?.trim()) throw new Error(\"name is required\");\n\t\tif (!SIGNALS.includes(input.signal))\n\t\t\tthrow new Error(`signal must be one of: ${SIGNALS.join(\", \")}`);\n\t\tif (!Number.isFinite(input.threshold))\n\t\t\tthrow new Error(\"threshold must be a finite number\");\n\t\tif (!Number.isFinite(input.windowMins) || input.windowMins < 1)\n\t\t\tthrow new Error(\"windowMins must be >= 1\");\n\t\tif (!COMPARISONS.includes(input.comparison))\n\t\t\tthrow new Error(`comparison must be one of: ${COMPARISONS.join(\", \")}`);\n\t\tif (!Array.isArray(input.channels) || input.channels.length === 0)\n\t\t\tthrow new Error(\"at least one channel is required\");\n\t\tfor (const ch of input.channels) {\n\t\t\tif (ch.type !== \"webhook\")\n\t\t\t\tthrow new Error(`unknown channel type: ${ch.type}`);\n\t\t\tif (!ch.url || !/^https?:\\/\\//.test(ch.url))\n\t\t\t\tthrow new Error(\"channel.url must be http(s)://\");\n\t\t}\n\t}\n\n\tasync listRules(projectId: string): Promise<AlertRule[]> {\n\t\tconst rs = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM alert_rules WHERE project_id = ? ORDER BY created_at DESC`,\n\t\t\t)\n\t\t\t.bind(projectId)\n\t\t\t.all<AlertRuleRow>();\n\t\tconst rows = rs.results ?? [];\n\t\tif (rows.length === 0) return [];\n\t\tconst stateRs = await this.db\n\t\t\t.prepare(`SELECT * FROM alert_state WHERE project_id = ?`)\n\t\t\t.bind(projectId)\n\t\t\t.all<AlertStateRow>();\n\t\tconst stateByRule = new Map<string, AlertStateRow>(\n\t\t\t(stateRs.results ?? []).map((s) => [s.rule_id, s]),\n\t\t);\n\t\treturn rows.map((r) => rowToRule(r, stateByRule.get(r.id)));\n\t}\n\n\tasync getRule(id: string, projectId: string): Promise<AlertRule | null> {\n\t\tconst row = await this.db\n\t\t\t.prepare(`SELECT * FROM alert_rules WHERE id = ? AND project_id = ?`)\n\t\t\t.bind(id, projectId)\n\t\t\t.first<AlertRuleRow>();\n\t\tif (!row) return null;\n\t\tconst state = await this.db\n\t\t\t.prepare(`SELECT * FROM alert_state WHERE rule_id = ?`)\n\t\t\t.bind(id)\n\t\t\t.first<AlertStateRow>();\n\t\treturn rowToRule(row, state ?? undefined);\n\t}\n\n\tasync createRule(\n\t\tprojectId: string,\n\t\tinput: AlertRuleInput,\n\t): Promise<AlertRule> {\n\t\tthis.validateInput(input);\n\t\tconst id = randomHex(16);\n\t\tconst now = new Date().toISOString();\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO alert_rules (id, project_id, name, signal, query_json, threshold, window_mins, comparison, channels_json, enabled, created_at, updated_at, analysis_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t\tinput.name.trim(),\n\t\t\t\tinput.signal,\n\t\t\t\tJSON.stringify(input.query),\n\t\t\t\tinput.threshold,\n\t\t\t\tinput.windowMins,\n\t\t\t\tinput.comparison,\n\t\t\t\tJSON.stringify(input.channels),\n\t\t\t\tinput.enabled === false ? 0 : 1,\n\t\t\t\tnow,\n\t\t\t\tnow,\n\t\t\t\tinput.analysisId ?? null,\n\t\t\t)\n\t\t\t.run();\n\n\t\tconst created = await this.getRule(id, projectId);\n\t\tif (!created) throw new Error(\"Failed to create rule\");\n\t\treturn created;\n\t}\n\n\tasync updateRule(\n\t\tid: string,\n\t\tprojectId: string,\n\t\tpatch: Partial<AlertRuleInput>,\n\t): Promise<AlertRule | null> {\n\t\tconst existing = await this.getRule(id, projectId);\n\t\tif (!existing) return null;\n\n\t\tconst merged: AlertRuleInput = {\n\t\t\tname: patch.name ?? existing.name,\n\t\t\tsignal: patch.signal ?? existing.signal,\n\t\t\tquery: patch.query ?? existing.query,\n\t\t\tthreshold: patch.threshold ?? existing.threshold,\n\t\t\twindowMins: patch.windowMins ?? existing.windowMins,\n\t\t\tcomparison: patch.comparison ?? existing.comparison,\n\t\t\tchannels: patch.channels ?? existing.channels,\n\t\t\tenabled: patch.enabled ?? existing.enabled,\n\t\t\tanalysisId:\n\t\t\t\t\"analysisId\" in patch ? patch.analysisId : existing.analysisId,\n\t\t};\n\t\tthis.validateInput(merged);\n\n\t\tconst now = new Date().toISOString();\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`UPDATE alert_rules SET\n name = ?, signal = ?, query_json = ?, threshold = ?, window_mins = ?,\n comparison = ?, channels_json = ?, enabled = ?, updated_at = ?, analysis_id = ?\n WHERE id = ? AND project_id = ?`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\tmerged.name.trim(),\n\t\t\t\tmerged.signal,\n\t\t\t\tJSON.stringify(merged.query),\n\t\t\t\tmerged.threshold,\n\t\t\t\tmerged.windowMins,\n\t\t\t\tmerged.comparison,\n\t\t\t\tJSON.stringify(merged.channels),\n\t\t\t\tmerged.enabled === false ? 0 : 1,\n\t\t\t\tnow,\n\t\t\t\tmerged.analysisId ?? null,\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t)\n\t\t\t.run();\n\n\t\treturn this.getRule(id, projectId);\n\t}\n\n\tasync deleteRule(id: string, projectId: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.prepare(`DELETE FROM alert_rules WHERE id = ? AND project_id = ?`)\n\t\t\t.bind(id, projectId)\n\t\t\t.run();\n\t\t// Also clean up state and evaluations for this rule.\n\t\tawait this.db\n\t\t\t.prepare(`DELETE FROM alert_state WHERE rule_id = ?`)\n\t\t\t.bind(id)\n\t\t\t.run();\n\t\tawait this.db\n\t\t\t.prepare(`DELETE FROM alert_evaluations WHERE rule_id = ?`)\n\t\t\t.bind(id)\n\t\t\t.run();\n\t\treturn (result.meta?.changes ?? 0) > 0;\n\t}\n\n\tasync listEnabledRules(): Promise<AlertRule[]> {\n\t\tconst rs = await this.db\n\t\t\t.prepare(`SELECT * FROM alert_rules WHERE enabled = 1`)\n\t\t\t.all<AlertRuleRow>();\n\t\treturn (rs.results ?? []).map((r) => rowToRule(r));\n\t}\n\n\t// ── State ──\n\n\tasync getState(ruleId: string): Promise<AlertStateRow | null> {\n\t\tconst row = await this.db\n\t\t\t.prepare(`SELECT * FROM alert_state WHERE rule_id = ?`)\n\t\t\t.bind(ruleId)\n\t\t\t.first<AlertStateRow>();\n\t\treturn row ?? null;\n\t}\n\n\tasync transitionState(\n\t\truleId: string,\n\t\tprojectId: string,\n\t\tnewState: AlertState,\n\t\tnow: string,\n\t): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO alert_state (rule_id, project_id, current_state, last_state_change)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(rule_id) DO UPDATE SET current_state = excluded.current_state, last_state_change = excluded.last_state_change`,\n\t\t\t)\n\t\t\t.bind(ruleId, projectId, newState, now)\n\t\t\t.run();\n\t}\n\n\tasync recordEvaluation(\n\t\truleId: string,\n\t\tprojectId: string,\n\t\tvalue: number,\n\t\tstate: AlertState,\n\t\tnotified: boolean,\n\t): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO alert_evaluations (id, rule_id, project_id, evaluated_at, value, state, notified)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\trandomHex(16),\n\t\t\t\truleId,\n\t\t\t\tprojectId,\n\t\t\t\tnew Date().toISOString(),\n\t\t\t\tvalue,\n\t\t\t\tstate,\n\t\t\t\tnotified ? 1 : 0,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync listEvaluations(params: {\n\t\truleId: string;\n\t\tprojectId?: string;\n\t\thours: number;\n\t\tlimit?: number;\n\t}): Promise<AlertEvaluationsListResponse> {\n\t\tconst cutoff = new Date(\n\t\t\tDate.now() - params.hours * 60 * 60 * 1000,\n\t\t).toISOString();\n\t\tconst rs = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM alert_evaluations WHERE rule_id = ? AND evaluated_at >= ? ORDER BY evaluated_at DESC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(params.ruleId, cutoff, Math.min(params.limit ?? 500, 1000))\n\t\t\t.all<AlertEvaluationRow>();\n\t\tconst rows = rs.results ?? [];\n\t\tconst projectId = params.projectId ?? rows[0]?.project_id;\n\t\tconst rule = projectId\n\t\t\t? await this.getRule(params.ruleId, projectId)\n\t\t\t: null;\n\t\tconst response: AlertEvaluationsListResponse = {\n\t\t\tevaluations: rows.map(rowToEvaluation),\n\t\t};\n\t\tif (rule) {\n\t\t\tresponse.evidenceReferences = alertEvidenceReferences(rule);\n\t\t\tresponse.evidenceContract = EVIDENCE_REFERENCE_CONTRACT;\n\t\t}\n\t\treturn response;\n\t}\n\n\t// ── Evaluators (count-over-window per signal) ──\n\n\tasync evaluateRule(rule: AlertRule): Promise<number> {\n\t\t// Stage 6 — analysis-bound rule. Read the analysis's latest\n\t\t// primary value instead of running the rule's raw query. Falls\n\t\t// through to the legacy path if no result has landed yet so the\n\t\t// alert behaves as \"metric unknown / 0\" rather than throwing.\n\t\tif (rule.analysisId) {\n\t\t\tconst row = await this.db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT primary_value FROM analysis_results\n\t\t\t\t\tWHERE project_id = ? AND analysis_id = ?\n\t\t\t\t\tORDER BY generated_at DESC LIMIT 1`,\n\t\t\t\t)\n\t\t\t\t.bind(rule.projectId, rule.analysisId)\n\t\t\t\t.first<{ primary_value: number | null }>();\n\t\t\treturn row?.primary_value ?? 0;\n\t\t}\n\t\tswitch (rule.signal) {\n\t\t\tcase \"spans\":\n\t\t\t\treturn this.evaluateSpanRule(rule);\n\t\t\tcase \"logs\":\n\t\t\t\treturn this.evaluateLogRule(rule);\n\t\t\tcase \"usage\":\n\t\t\t\treturn this.evaluateUsageRule(rule);\n\t\t\tcase \"ai\":\n\t\t\t\treturn this.evaluateAIRule(rule);\n\t\t}\n\t}\n\n\t/**\n\t * Stage 6 — fetch the latest narrative associated with this rule's\n\t * bound analysis. Used by the evaluator when firing an analysis-bound\n\t * alert so the webhook payload includes the human-readable\n\t * narrative, not just a threshold crossing.\n\t */\n\tasync getAnalysisNarrative(\n\t\tprojectId: string,\n\t\tanalysisId: string,\n\t): Promise<{ narrative: string | null; status: string | null } | null> {\n\t\tconst row = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT narrative, status FROM analysis_results\n\t\t\t\tWHERE project_id = ? AND analysis_id = ?\n\t\t\t\tORDER BY generated_at DESC LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, analysisId)\n\t\t\t.first<{ narrative: string | null; status: string | null }>();\n\t\tif (!row) return null;\n\t\treturn { narrative: row.narrative ?? null, status: row.status ?? null };\n\t}\n\n\tprivate async evaluateSpanRule(rule: AlertRule): Promise<number> {\n\t\tconst q = rule.query as AlertQuerySpans;\n\t\tconst cutoff = windowCutoffIso(rule.windowMins);\n\t\tlet sql = `SELECT COUNT(*) AS c FROM telemetry_spans WHERE project_id = ? AND received_at >= ?`;\n\t\tconst binds: unknown[] = [rule.projectId, cutoff];\n\t\tif (q.serviceName) {\n\t\t\tsql += ` AND service_name = ?`;\n\t\t\tbinds.push(q.serviceName);\n\t\t}\n\t\tif (q.spanName) {\n\t\t\tsql += ` AND span_name = ?`;\n\t\t\tbinds.push(q.spanName);\n\t\t}\n\t\tif (q.statusCode === \"error\") sql += ` AND status_code = 2`;\n\t\telse if (q.statusCode === \"ok\") sql += ` AND status_code != 2`;\n\t\tconst row = await this.db\n\t\t\t.prepare(sql)\n\t\t\t.bind(...binds)\n\t\t\t.first<{ c: number }>();\n\t\treturn row?.c ?? 0;\n\t}\n\n\tprivate async evaluateLogRule(rule: AlertRule): Promise<number> {\n\t\tconst q = rule.query as AlertQueryLogs;\n\t\tconst cutoff = windowCutoffIso(rule.windowMins);\n\t\tlet sql = `SELECT COUNT(*) AS c FROM logs WHERE project_id = ? AND received_at >= ?`;\n\t\tconst binds: unknown[] = [rule.projectId, cutoff];\n\t\tif (q.serviceName) {\n\t\t\tsql += ` AND service_name = ?`;\n\t\t\tbinds.push(q.serviceName);\n\t\t}\n\t\tif (q.severity) {\n\t\t\tsql += ` AND severity = ?`;\n\t\t\tbinds.push(q.severity as LogSeverity);\n\t\t}\n\t\tconst row = await this.db\n\t\t\t.prepare(sql)\n\t\t\t.bind(...binds)\n\t\t\t.first<{ c: number }>();\n\t\treturn row?.c ?? 0;\n\t}\n\n\tprivate async evaluateUsageRule(rule: AlertRule): Promise<number> {\n\t\tconst q = rule.query as AlertQueryUsage;\n\t\tconst cutoff = windowCutoffIso(rule.windowMins);\n\t\t// Usage alerts fire on 'frontend_error' events (the error signal on the frontend).\n\t\tlet sql = `SELECT COUNT(*) AS c FROM usage_events WHERE project_id = ? AND occurred_at >= ? AND event_type = 'frontend_error'`;\n\t\tconst binds: unknown[] = [rule.projectId, cutoff];\n\t\tif (q.eventName) {\n\t\t\tsql += ` AND event_name = ?`;\n\t\t\tbinds.push(q.eventName);\n\t\t}\n\t\tif (q.pathPattern) {\n\t\t\tsql += ` AND page_path LIKE ?`;\n\t\t\tbinds.push(q.pathPattern);\n\t\t}\n\t\tconst row = await this.db\n\t\t\t.prepare(sql)\n\t\t\t.bind(...binds)\n\t\t\t.first<{ c: number }>();\n\t\treturn row?.c ?? 0;\n\t}\n\n\tprivate async evaluateAIRule(rule: AlertRule): Promise<number> {\n\t\tconst q = rule.query as AlertQueryAI;\n\t\tconst cutoff = windowCutoffIso(rule.windowMins);\n\t\tlet sql = `SELECT COUNT(*) AS c FROM ai_calls WHERE project_id = ? AND received_at >= ?`;\n\t\tconst binds: unknown[] = [rule.projectId, cutoff];\n\t\tif (q.provider) {\n\t\t\tsql += ` AND provider = ?`;\n\t\t\tbinds.push(q.provider);\n\t\t}\n\t\tif (q.model) {\n\t\t\tsql += ` AND model_name = ?`;\n\t\t\tbinds.push(q.model);\n\t\t}\n\t\tif (q.isError === true) sql += ` AND is_error = 1`;\n\t\tconst row = await this.db\n\t\t\t.prepare(sql)\n\t\t\t.bind(...binds)\n\t\t\t.first<{ c: number }>();\n\t\treturn row?.c ?? 0;\n\t}\n}\n","import type {\n\tAlertChannel,\n\tAlertRule,\n\tAlertState,\n\tAlertWebhookChannel,\n} from \"@obsunified/types\";\nimport type { CollectorEnv } from \"../framework/env\";\nimport {\n\ttype ChildSpanRunner,\n\tconsoleLogger,\n\ttype Logger,\n} from \"../framework/logger\";\nimport { AlertsStore, compareValue } from \"../lib/alerts-store\";\nimport { sqlDbFor } from \"../lib/sql-db\";\n\nconst DEFAULT_RULE_CONCURRENCY = 5;\nconst DEFAULT_RULE_TIMEOUT_MS = 10_000;\n\ninterface AlertEvaluatorStore {\n\tlistEnabledRules(): Promise<AlertRule[]>;\n\tevaluateRule(rule: AlertRule): Promise<number>;\n\tgetState(ruleId: string): Promise<{ current_state: AlertState } | null>;\n\tgetAnalysisNarrative(\n\t\tprojectId: string,\n\t\tanalysisId: string,\n\t): Promise<{ narrative: string | null; status: string | null } | null>;\n\ttransitionState(\n\t\truleId: string,\n\t\tprojectId: string,\n\t\tnewState: AlertState,\n\t\tnow: string,\n\t): Promise<void>;\n\trecordEvaluation(\n\t\truleId: string,\n\t\tprojectId: string,\n\t\tvalue: number,\n\t\tstate: AlertState,\n\t\tnotified: boolean,\n\t): Promise<void>;\n}\n\ninterface WebhookPayload {\n\trule: {\n\t\tid: string;\n\t\tname: string;\n\t\tsignal: string;\n\t};\n\tvalue: number;\n\tthreshold: number;\n\tcomparison: string;\n\tstate: AlertState;\n\tevaluatedAt: string;\n\tprojectId: string;\n\t/**\n\t * RFC 0002 Stage 6 — populated when the rule is bound to an Analysis\n\t * (`rule.analysisId` set). The narrative is the gated, LLM-generated\n\t * sentence the dashboard panel was last showing — what's actually\n\t * happening, in plain English. Webhooks consuming this can put the\n\t * narrative in the Slack/PagerDuty body directly.\n\t */\n\tanalysis?: {\n\t\tid: string;\n\t\tnarrative: string | null;\n\t\tstatus: string | null;\n\t};\n}\n\nasync function fireWebhook(\n\tchannel: AlertWebhookChannel,\n\tpayload: WebhookPayload,\n\tlogger: Logger,\n\ttracer?: ChildSpanRunner,\n): Promise<boolean> {\n\tconst exec = async (\n\t\tspan: { setAttribute(k: string, v: unknown): void } | null,\n\t): Promise<boolean> => {\n\t\ttry {\n\t\t\tconst response = await fetch(channel.url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t...(channel.headers ?? {}),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\tsignal: AbortSignal.timeout(5000),\n\t\t\t});\n\t\t\tif (span) span.setAttribute(\"http.response.status_code\", response.status);\n\t\t\treturn response.ok;\n\t\t} catch (err) {\n\t\t\tlogger.error(\"[alerts-evaluator] webhook delivery failed\", {\n\t\t\t\turl: channel.url,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t};\n\tif (!tracer) return exec(null);\n\treturn tracer(\"webhook.alert\", async (span) => exec(span), {\n\t\t\"http.method\": \"POST\",\n\t\t\"http.url\": channel.url,\n\t\t\"alert.state\": payload.state,\n\t});\n}\n\nasync function fireChannels(\n\tchannels: AlertChannel[],\n\tpayload: WebhookPayload,\n\tlogger: Logger,\n\ttracer?: ChildSpanRunner,\n): Promise<boolean> {\n\tif (channels.length === 0) return true;\n\tconst results = await Promise.all(\n\t\tchannels\n\t\t\t.filter((ch): ch is AlertWebhookChannel => ch.type === \"webhook\")\n\t\t\t.map((ch) => fireWebhook(ch, payload, logger, tracer)),\n\t);\n\treturn results.every(Boolean);\n}\n\nasync function withTimeout<T>(\n\tpromise: Promise<T>,\n\tms: number,\n\tmessage: string,\n): Promise<T> {\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\ttry {\n\t\treturn await Promise.race([\n\t\t\tpromise,\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\ttimer = setTimeout(() => reject(new Error(message)), ms);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tif (timer) clearTimeout(timer);\n\t}\n}\n\nasync function mapWithConcurrency<T, R>(\n\titems: T[],\n\tconcurrency: number,\n\tmapper: (item: T) => Promise<R>,\n): Promise<R[]> {\n\tconst results: R[] = new Array(items.length);\n\tlet nextIndex = 0;\n\tconst workerCount = Math.min(concurrency, items.length);\n\tawait Promise.all(\n\t\tArray.from({ length: workerCount }, async () => {\n\t\t\twhile (nextIndex < items.length) {\n\t\t\t\tconst current = nextIndex++;\n\t\t\t\tresults[current] = await mapper(items[current]);\n\t\t\t}\n\t\t}),\n\t);\n\treturn results;\n}\n\nasync function evaluateOneRule(\n\tstore: AlertEvaluatorStore,\n\trule: AlertRule,\n\tlogger: Logger,\n\ttracer: ChildSpanRunner | undefined,\n\truleTimeoutMs: number,\n): Promise<{ fired: number; resolved: number }> {\n\ttry {\n\t\tconst value = await withTimeout(\n\t\t\tstore.evaluateRule(rule),\n\t\t\truleTimeoutMs,\n\t\t\t`rule evaluation timed out after ${ruleTimeoutMs}ms`,\n\t\t);\n\t\tconst shouldFire = compareValue(value, rule.threshold, rule.comparison);\n\t\tconst priorState = await store.getState(rule.id);\n\t\tconst previous: AlertState = priorState?.current_state ?? \"ok\";\n\t\tconst next: AlertState = shouldFire ? \"firing\" : \"ok\";\n\t\tconst now = new Date().toISOString();\n\n\t\t// Stage 6: when the rule is bound to an analysis, pull the\n\t\t// latest narrative + status so the webhook payload describes\n\t\t// what's happening, not just \"value > threshold\".\n\t\tconst analysisAttachment = rule.analysisId\n\t\t\t? await store\n\t\t\t\t\t.getAnalysisNarrative(rule.projectId, rule.analysisId)\n\t\t\t\t\t.then((n) =>\n\t\t\t\t\t\tn\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tid: rule.analysisId as string,\n\t\t\t\t\t\t\t\t\tnarrative: n.narrative,\n\t\t\t\t\t\t\t\t\tstatus: n.status,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t)\n\t\t\t\t\t.catch(() => undefined)\n\t\t\t: undefined;\n\n\t\tif (previous === \"ok\" && next === \"firing\") {\n\t\t\tconst ok = await fireChannels(\n\t\t\t\trule.channels,\n\t\t\t\t{\n\t\t\t\t\trule: { id: rule.id, name: rule.name, signal: rule.signal },\n\t\t\t\t\tvalue,\n\t\t\t\t\tthreshold: rule.threshold,\n\t\t\t\t\tcomparison: rule.comparison,\n\t\t\t\t\tstate: \"firing\",\n\t\t\t\t\tevaluatedAt: now,\n\t\t\t\t\tprojectId: rule.projectId,\n\t\t\t\t\tanalysis: analysisAttachment,\n\t\t\t\t},\n\t\t\t\tlogger,\n\t\t\t\ttracer,\n\t\t\t);\n\t\t\tawait store.transitionState(rule.id, rule.projectId, \"firing\", now);\n\t\t\tawait store.recordEvaluation(\n\t\t\t\trule.id,\n\t\t\t\trule.projectId,\n\t\t\t\tvalue,\n\t\t\t\t\"firing\",\n\t\t\t\tok,\n\t\t\t);\n\t\t\treturn { fired: 1, resolved: 0 };\n\t\t}\n\t\tif (previous === \"firing\" && next === \"ok\") {\n\t\t\tconst ok = await fireChannels(\n\t\t\t\trule.channels,\n\t\t\t\t{\n\t\t\t\t\trule: { id: rule.id, name: rule.name, signal: rule.signal },\n\t\t\t\t\tvalue,\n\t\t\t\t\tthreshold: rule.threshold,\n\t\t\t\t\tcomparison: rule.comparison,\n\t\t\t\t\tstate: \"ok\",\n\t\t\t\t\tevaluatedAt: now,\n\t\t\t\t\tprojectId: rule.projectId,\n\t\t\t\t\tanalysis: analysisAttachment,\n\t\t\t\t},\n\t\t\t\tlogger,\n\t\t\t\ttracer,\n\t\t\t);\n\t\t\tawait store.transitionState(rule.id, rule.projectId, \"ok\", now);\n\t\t\tawait store.recordEvaluation(rule.id, rule.projectId, value, \"ok\", ok);\n\t\t\treturn { fired: 0, resolved: 1 };\n\t\t}\n\n\t\t// Same state — write an evaluation but do not fire channels.\n\t\tawait store.recordEvaluation(rule.id, rule.projectId, value, next, false);\n\t} catch (err) {\n\t\tlogger.error(\"[alerts-evaluator] rule evaluation failed\", {\n\t\t\trule_id: rule.id,\n\t\t\tproject_id: rule.projectId,\n\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t});\n\t}\n\n\treturn { fired: 0, resolved: 0 };\n}\n\nexport async function evaluateRuleBatch(\n\tstore: AlertEvaluatorStore,\n\trules: AlertRule[],\n\toptions?: {\n\t\tlogger?: Logger;\n\t\ttracer?: ChildSpanRunner;\n\t\tconcurrency?: number;\n\t\truleTimeoutMs?: number;\n\t},\n): Promise<{\n\tevaluated: number;\n\tfired: number;\n\tresolved: number;\n}> {\n\tconst logger = options?.logger ?? consoleLogger;\n\tconst concurrency = Math.max(\n\t\t1,\n\t\tMath.floor(options?.concurrency ?? DEFAULT_RULE_CONCURRENCY),\n\t);\n\tconst ruleTimeoutMs = Math.max(\n\t\t1,\n\t\tMath.floor(options?.ruleTimeoutMs ?? DEFAULT_RULE_TIMEOUT_MS),\n\t);\n\tconst results = await mapWithConcurrency(rules, concurrency, (rule) =>\n\t\tevaluateOneRule(store, rule, logger, options?.tracer, ruleTimeoutMs),\n\t);\n\treturn {\n\t\tevaluated: rules.length,\n\t\tfired: results.reduce((sum, result) => sum + result.fired, 0),\n\t\tresolved: results.reduce((sum, result) => sum + result.resolved, 0),\n\t};\n}\n\nexport async function evaluateAllRules(\n\tenv: CollectorEnv,\n\toptions?: {\n\t\tlogger?: Logger;\n\t\ttracer?: ChildSpanRunner;\n\t\tconcurrency?: number;\n\t\truleTimeoutMs?: number;\n\t},\n): Promise<{\n\tevaluated: number;\n\tfired: number;\n\tresolved: number;\n}> {\n\tconst logger = options?.logger ?? consoleLogger;\n\tconst tracer = options?.tracer;\n\tconst store = new AlertsStore(sqlDbFor(env));\n\tconst rules = await store.listEnabledRules();\n\treturn evaluateRuleBatch(store, rules, {\n\t\tlogger,\n\t\ttracer,\n\t\tconcurrency: options?.concurrency,\n\t\truleTimeoutMs: options?.ruleTimeoutMs,\n\t});\n}\n\n/**\n * Scheduled handler suitable for wrangler cron triggers. Dispatches on the\n * cron expression so multiple triggers can share this handler.\n */\nexport function createAlertEvaluatorHandler() {\n\treturn {\n\t\tasync scheduled(\n\t\t\t_event: { cron: string },\n\t\t\tenv: CollectorEnv,\n\t\t\tctx: {\n\t\t\t\twaitUntil(promise: Promise<unknown>): void;\n\t\t\t},\n\t\t) {\n\t\t\tctx.waitUntil(evaluateAllRules(env));\n\t\t},\n\t};\n}\n","import type { AlertRuleInput, AlertTestResponse } from \"@obsunified/types\";\nimport { EVIDENCE_REFERENCE_CONTRACT } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { AlertsStore, compareValue } from \"../lib/alerts-store\";\nimport { alertEvidenceReferences } from \"../lib/evidence-references\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport const alertsRoutesPlugin: CollectorPlugin = {\n\tname: \"alerts-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/alerts/rules\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AlertsStore(sqlDbFor(c.env));\n\t\t\tconst rules = await store.listRules(projectId);\n\t\t\treturn c.json({ rules });\n\t\t});\n\n\t\tapp.post(\"/internal/alerts/rules\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tlet input: AlertRuleInput;\n\t\t\ttry {\n\t\t\t\tinput = await c.req.json<AlertRuleInput>();\n\t\t\t} catch {\n\t\t\t\treturn c.json({ error: \"Invalid JSON body\" }, 400);\n\t\t\t}\n\t\t\tconst store = new AlertsStore(sqlDbFor(c.env));\n\t\t\ttry {\n\t\t\t\tconst rule = await store.createRule(projectId, input);\n\t\t\t\treturn c.json({ rule }, 201);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\treturn c.json({ error: message }, 400);\n\t\t\t}\n\t\t});\n\n\t\tapp.patch(\"/internal/alerts/rules/:id\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tlet patch: Partial<AlertRuleInput>;\n\t\t\ttry {\n\t\t\t\tpatch = await c.req.json<Partial<AlertRuleInput>>();\n\t\t\t} catch {\n\t\t\t\treturn c.json({ error: \"Invalid JSON body\" }, 400);\n\t\t\t}\n\t\t\tconst store = new AlertsStore(sqlDbFor(c.env));\n\t\t\ttry {\n\t\t\t\tconst rule = await store.updateRule(id, projectId, patch);\n\t\t\t\tif (!rule) return c.json({ error: \"Rule not found\" }, 404);\n\t\t\t\treturn c.json({ rule });\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\treturn c.json({ error: message }, 400);\n\t\t\t}\n\t\t});\n\n\t\tapp.delete(\"/internal/alerts/rules/:id\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tconst store = new AlertsStore(sqlDbFor(c.env));\n\t\t\tconst deleted = await store.deleteRule(id, projectId);\n\t\t\tif (!deleted) return c.json({ error: \"Rule not found\" }, 404);\n\t\t\treturn c.json({ success: true });\n\t\t});\n\n\t\tapp.get(\"/internal/alerts/evaluations\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst ruleId = c.req.query(\"ruleId\");\n\t\t\tif (!ruleId) return c.json({ error: \"ruleId is required\" }, 400);\n\t\t\tconst hours = Math.max(\n\t\t\t\t1,\n\t\t\t\tMath.min(720, Number.parseInt(c.req.query(\"hours\") || \"24\", 10) || 24),\n\t\t\t);\n\t\t\tconst store = new AlertsStore(sqlDbFor(c.env));\n\t\t\tconst response = await store.listEvaluations({\n\t\t\t\truleId,\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t});\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\tapp.post(\"/internal/alerts/rules/:id/test\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tconst store = new AlertsStore(sqlDbFor(c.env));\n\t\t\tconst rule = await store.getRule(id, projectId);\n\t\t\tif (!rule) return c.json({ error: \"Rule not found\" }, 404);\n\t\t\tconst value = await store.evaluateRule(rule);\n\t\t\tconst response: AlertTestResponse = {\n\t\t\t\tvalue,\n\t\t\t\twouldFire: compareValue(value, rule.threshold, rule.comparison),\n\t\t\t\tcomparison: rule.comparison,\n\t\t\t\tthreshold: rule.threshold,\n\t\t\t\tevidenceReferences: alertEvidenceReferences(rule),\n\t\t\t\tevidenceContract: EVIDENCE_REFERENCE_CONTRACT,\n\t\t\t};\n\t\t\treturn c.json(response);\n\t\t});\n\t},\n};\n","/**\n * RFC 0002 — HTTP surface for application-aware Analyses.\n *\n * GET /internal/analyses — list registered definitions\n * GET /internal/analyses/:id/result — definition + latest result\n * GET /internal/analyses/results — bulk: every definition + latest\n * POST /internal/analyses/:id/run — Stage 4: on-demand re-run for\n * view: \"page\" investigations\n *\n * Cron writes happen via the scheduled handler (see analyses-runner.ts).\n * The on-demand POST exists so an investigation page's [Re-run] button\n * doesn't have to wait for the next 5-min tick.\n */\n\nimport type {\n\tAnalysesListResponse,\n\tAnalysisResultResponse,\n\tAnalysisResultsBulkResponse,\n} from \"@obsunified/types\";\nimport { getConfiguredRetentionHours } from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { runSqlAnalysis } from \"../lib/analyses-runner\";\nimport { AnalysesStore } from \"../lib/analyses-store\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport const analysesRoutesPlugin: CollectorPlugin = {\n\tname: \"analyses-routes\",\n\tregister(app, runtime) {\n\t\tapp.get(\"/internal/analyses\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AnalysesStore(sqlDbFor(c.env));\n\t\t\tconst analyses = await store.listDefinitions(projectId);\n\t\t\tconst response: AnalysesListResponse = {\n\t\t\t\tanalyses,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t};\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\tapp.get(\"/internal/analyses/results\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new AnalysesStore(sqlDbFor(c.env));\n\t\t\tconst definitions = await store.listDefinitions(projectId);\n\t\t\tconst ids = definitions.map((def) => def.id);\n\t\t\tconst latest = await store.getLatestResultsBulk(projectId, ids);\n\t\t\tconst response: AnalysisResultsBulkResponse = {\n\t\t\t\tresults: definitions.map((definition) => ({\n\t\t\t\t\tdefinition,\n\t\t\t\t\tresult: latest.get(definition.id) ?? null,\n\t\t\t\t})),\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t};\n\t\t\treturn c.json(response);\n\t\t});\n\n\t\t// Stage 4 [Re-run] target. Re-executes the SQL right now and persists\n\t\t// the new result. We deliberately keep this narrow:\n\t\t// - only `view: \"page\"` definitions (tile cron is fast enough)\n\t\t// - no narrate pass on the on-demand path; the page UI uses the most\n\t\t// recent narrative from the cron tick (cheaper, avoids surprise\n\t\t// LLM calls from a button click)\n\t\tapp.post(\"/internal/analyses/:id/run\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) {\n\t\t\t\treturn c.json({ error: \"Bad Request\", message: \"id is required\" }, 400);\n\t\t\t}\n\t\t\tconst store = new AnalysesStore(sqlDbFor(c.env));\n\t\t\tconst definitions = await store.listDefinitions(projectId);\n\t\t\tconst definition = definitions.find((def) => def.id === id);\n\t\t\tif (!definition) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: `Analysis ${id} not found` },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (definition.view !== \"page\") {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: \"Bad Request\",\n\t\t\t\t\t\tmessage: \"on-demand run only supported for view=page analyses\",\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst retentionHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst expiresAt = Date.now() + retentionHours * 3600 * 1000;\n\t\t\ttry {\n\t\t\t\tconst result = await runSqlAnalysis(definition, {\n\t\t\t\t\tdb: sqlDbFor(c.env),\n\t\t\t\t\tprojectId,\n\t\t\t\t\tretentionHours,\n\t\t\t\t});\n\t\t\t\tawait store.insertResult(result, expiresAt);\n\t\t\t\tawait store.markRan(projectId, definition.id, result.generatedAt);\n\t\t\t\tconst response: AnalysisResultResponse = {\n\t\t\t\t\tdefinition,\n\t\t\t\t\tresult,\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t};\n\t\t\t\treturn c.json(response);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\truntime.logger.error(\"[analyses] on-demand run failed\", {\n\t\t\t\t\tanalysis_id: id,\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\terror: message,\n\t\t\t\t});\n\t\t\t\treturn c.json({ error: \"Internal Server Error\", message }, 500);\n\t\t\t}\n\t\t});\n\n\t\tapp.get(\"/internal/analyses/:id/result\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) {\n\t\t\t\treturn c.json({ error: \"Bad Request\", message: \"id is required\" }, 400);\n\t\t\t}\n\t\t\tconst store = new AnalysesStore(sqlDbFor(c.env));\n\t\t\tconst definitions = await store.listDefinitions(projectId);\n\t\t\tconst definition = definitions.find((def) => def.id === id);\n\t\t\tif (!definition) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: `Analysis ${id} not found` },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst result = await store.getLatestResult(projectId, id);\n\t\t\tconst response: AnalysisResultResponse = {\n\t\t\t\tdefinition,\n\t\t\t\tresult,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t};\n\t\t\treturn c.json(response);\n\t\t});\n\t},\n};\n","/**\n * RFC 0002 Stage 5 — Ask box tool-use loop.\n *\n * The user asks \"is checkout slow?\", we hand it to an LLM with two\n * tools that look at the analyses catalog:\n *\n * list_analyses(group?) → AnalysisDefinition[]\n * run_analysis(id) → { definition, result }\n *\n * The loop runs until the model emits a final assistant message or we\n * hit the iteration cap. Why two tools and not one big \"ask anything\"\n * prompt: the analyses we've already derived (60+ panels on the OTel\n * demo) cover most \"is X slow / errors / unhealthy?\" questions, and\n * pointing the model at structured data with known shape is far more\n * reliable than asking it to write SQL from scratch. Ad-hoc SQL lands\n * later as a third tool with SELECT-only validation.\n *\n * The model is instructed to cite analysis ids inline so the UI can\n * link the cited evidence; we surface a flat `queries` audit log so\n * users can verify what was actually consulted.\n */\n\nimport type {\n\tAnalysisDefinition,\n\tAnalysisResult,\n\tAskEvidence,\n\tAskQuery,\n\tAskResponse,\n} from \"@obsunified/types\";\nimport { EVIDENCE_REFERENCE_CONTRACT } from \"@obsunified/types\";\nimport { askEvidenceReferences } from \"./evidence-references\";\nimport type { LlmConfig } from \"./llm\";\n\nconst DEFAULT_API_URL = \"https://api.anthropic.com/v1/messages\";\n\nconst SYSTEM_PROMPT = `You answer operational questions about a self-hosted observability dashboard's telemetry. Use the supplied tools — do not invent numbers.\n\nWorkflow:\n1. Use list_analyses to see what's available. Filter by group when it helps.\n2. Pick the analyses most likely to answer the question. Call run_analysis on each (typically 1–3, max 5).\n3. Read the results. Synthesize a 1–2 sentence answer.\n\nHard rules — violations are unusable:\n1. Never start with \"I\", \"Here's\", \"We\", or any chatbot framing. Write declarative statements about the system.\n2. Cite the analyses you consulted by id, e.g. \"(latency_p95_overall)\".\n3. Include a time anchor when describing a number (\"in the last 5 minutes\", \"vs the prior hour\", \"for the past 24h\").\n4. ≤ 2 sentences, ≤ 280 characters total. Numbers belong in the sentence.\n5. If the available analyses don't cover the question, say exactly that and name the closest analysis you found.\n\nOutput: write only the final answer text. No preamble, no JSON.`;\n\nconst TOOLS = [\n\t{\n\t\tname: \"list_analyses\",\n\t\tdescription:\n\t\t\t\"List registered analyses for the current project. Optionally filter by group (Health, Services, Dependencies, Async, AI, Frontend, Custom). Returns id, title, group, source, view, and scope (when set).\",\n\t\tinput_schema: {\n\t\t\ttype: \"object\" as const,\n\t\t\tproperties: {\n\t\t\t\tgroup: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Filter by group. Omit to see all.\",\n\t\t\t\t},\n\t\t\t\tview: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Filter by view: 'tile' for fast panels, 'page' for investigations.\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tname: \"run_analysis\",\n\t\tdescription:\n\t\t\t\"Read the latest result for one analysis by id. Returns status, primary value, baseline, delta_pct, and the analysis-specific payload (which often contains the most useful data — top services, span names, etc).\",\n\t\tinput_schema: {\n\t\t\ttype: \"object\" as const,\n\t\t\tproperties: {\n\t\t\t\tid: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Analysis id, e.g. 'overall_error_rate'.\",\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: [\"id\"],\n\t\t},\n\t},\n];\n\nconst MAX_ITERATIONS = 5;\n\ninterface AnthropicContentBlock {\n\ttype: \"text\" | \"tool_use\" | \"tool_result\";\n\ttext?: string;\n\tid?: string;\n\tname?: string;\n\tinput?: Record<string, unknown>;\n\ttool_use_id?: string;\n\tcontent?: string;\n}\n\ninterface AnthropicResponse {\n\tcontent?: AnthropicContentBlock[];\n\tstop_reason?: string;\n}\n\nexport interface AskRunDeps {\n\tlistAnalyses: (filters?: {\n\t\tgroup?: string;\n\t\tview?: string;\n\t}) => Promise<AnalysisDefinition[]>;\n\tgetLatestResult: (id: string) => Promise<{\n\t\tdefinition: AnalysisDefinition;\n\t\tresult: AnalysisResult | null;\n\t} | null>;\n\tllm: LlmConfig;\n}\n\nconst summarizeDefinition = (def: AnalysisDefinition) => ({\n\tid: def.id,\n\ttitle: def.title,\n\tgroup: def.group,\n\tsource: def.source,\n\tview: def.view,\n\tscope: def.scope ?? null,\n});\n\nconst summarizeResult = (\n\tdef: AnalysisDefinition,\n\tresult: AnalysisResult | null,\n) => {\n\tif (!result) {\n\t\treturn {\n\t\t\tdefinition: summarizeDefinition(def),\n\t\t\tresult: null,\n\t\t\tnote: \"No result yet — analysis hasn't run.\",\n\t\t};\n\t}\n\treturn {\n\t\tdefinition: summarizeDefinition(def),\n\t\tresult: {\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t\tstatus: result.status,\n\t\t\tprimaryValue: result.primaryValue,\n\t\t\tbaselineValue: result.baselineValue,\n\t\t\tdeltaPct: result.deltaPct,\n\t\t\tpayload: result.payload,\n\t\t\tnarrative: result.narrative,\n\t\t},\n\t};\n};\n\nexport async function runAsk(\n\tquestion: string,\n\tdeps: AskRunDeps,\n): Promise<AskResponse> {\n\tif (deps.llm.provider === \"openai\") {\n\t\t// Lazy import to keep Anthropic-only paths zero-cost.\n\t\tconst { runAskOpenAI } = await import(\"./openai\");\n\t\treturn runAskOpenAI(question, deps);\n\t}\n\treturn runAskAnthropic(question, deps);\n}\n\nasync function runAskAnthropic(\n\tquestion: string,\n\tdeps: AskRunDeps,\n): Promise<AskResponse> {\n\tconst startedAt = new Date().toISOString();\n\tconst queries: AskQuery[] = [];\n\tconst evidence = new Map<string, AskEvidence>();\n\n\tconst messages: Array<{\n\t\trole: \"user\" | \"assistant\";\n\t\tcontent: string | AnthropicContentBlock[];\n\t}> = [{ role: \"user\", content: question }];\n\n\tfor (let iteration = 0; iteration < MAX_ITERATIONS; iteration += 1) {\n\t\tconst response = await callAnthropic(deps.llm, messages, iteration);\n\n\t\tconst toolUses = (response.content ?? []).filter(\n\t\t\t(b) => b.type === \"tool_use\",\n\t\t);\n\t\tconst finalText = (response.content ?? [])\n\t\t\t.filter((b) => b.type === \"text\")\n\t\t\t.map((b) => b.text ?? \"\")\n\t\t\t.join(\"\")\n\t\t\t.trim();\n\n\t\t// Model finished — return the answer.\n\t\tif (response.stop_reason === \"max_tokens\") {\n\t\t\treturn {\n\t\t\t\tanswer: null,\n\t\t\t\tevidence: [...evidence.values()],\n\t\t\t\tevidenceReferences: askEvidenceReferences(evidence.values()),\n\t\t\t\tevidenceContract: EVIDENCE_REFERENCE_CONTRACT,\n\t\t\t\tqueries,\n\t\t\t\terror: \"model response was truncated by max_tokens\",\n\t\t\t\ttimestamp: startedAt,\n\t\t\t};\n\t\t}\n\n\t\tif (response.stop_reason === \"end_turn\" || toolUses.length === 0) {\n\t\t\treturn {\n\t\t\t\tanswer: finalText.length > 0 ? finalText : null,\n\t\t\t\tevidence: [...evidence.values()],\n\t\t\t\tevidenceReferences: askEvidenceReferences(evidence.values()),\n\t\t\t\tevidenceContract: EVIDENCE_REFERENCE_CONTRACT,\n\t\t\t\tqueries,\n\t\t\t\terror: finalText.length > 0 ? null : \"model returned no text\",\n\t\t\t\ttimestamp: startedAt,\n\t\t\t};\n\t\t}\n\n\t\t// Append the assistant's tool_use message verbatim.\n\t\tmessages.push({\n\t\t\trole: \"assistant\",\n\t\t\tcontent: response.content ?? [],\n\t\t});\n\n\t\t// Execute every tool_use the assistant requested in this turn.\n\t\tconst toolResultBlocks: AnthropicContentBlock[] = [];\n\t\tfor (const block of toolUses) {\n\t\t\tconst t0 = Date.now();\n\t\t\tlet resultPayload: unknown;\n\t\t\tconst tracer = deps.llm.tracer;\n\t\t\tconst toolName = block.name;\n\t\t\tconst args = block.input ?? {};\n\t\t\tconst dispatchTool = async (\n\t\t\t\tspan: { setAttribute(k: string, v: unknown): void } | null,\n\t\t\t): Promise<unknown> => {\n\t\t\t\tif (toolName === \"list_analyses\") {\n\t\t\t\t\tconst all = await deps.listAnalyses({\n\t\t\t\t\t\tgroup: typeof args.group === \"string\" ? args.group : undefined,\n\t\t\t\t\t\tview: typeof args.view === \"string\" ? args.view : undefined,\n\t\t\t\t\t});\n\t\t\t\t\tconst out = all.slice(0, 80).map(summarizeDefinition);\n\t\t\t\t\tif (span) span.setAttribute(\"tool.result_count\", out.length);\n\t\t\t\t\tqueries.push({\n\t\t\t\t\t\ttool: \"list_analyses\",\n\t\t\t\t\t\targs,\n\t\t\t\t\t\tdurationMs: Date.now() - t0,\n\t\t\t\t\t});\n\t\t\t\t\treturn out;\n\t\t\t\t}\n\t\t\t\tif (toolName === \"run_analysis\") {\n\t\t\t\t\tconst id = typeof args.id === \"string\" ? args.id : \"\";\n\t\t\t\t\tif (!id) {\n\t\t\t\t\t\tif (span) span.setAttribute(\"tool.outcome\", \"missing_id\");\n\t\t\t\t\t\tqueries.push({\n\t\t\t\t\t\t\ttool: \"run_analysis\",\n\t\t\t\t\t\t\targs,\n\t\t\t\t\t\t\tdurationMs: Date.now() - t0,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn { error: \"id is required\" };\n\t\t\t\t\t}\n\t\t\t\t\tconst found = await deps.getLatestResult(id);\n\t\t\t\t\tqueries.push({\n\t\t\t\t\t\ttool: \"run_analysis\",\n\t\t\t\t\t\targs,\n\t\t\t\t\t\tdurationMs: Date.now() - t0,\n\t\t\t\t\t});\n\t\t\t\t\tif (!found) {\n\t\t\t\t\t\tif (span) span.setAttribute(\"tool.outcome\", \"not_found\");\n\t\t\t\t\t\treturn { error: `analysis ${id} not found` };\n\t\t\t\t\t}\n\t\t\t\t\tif (span) {\n\t\t\t\t\t\tspan.setAttribute(\"tool.outcome\", \"ok\");\n\t\t\t\t\t\tspan.setAttribute(\"analysis.id\", id);\n\t\t\t\t\t\tif (found.result) {\n\t\t\t\t\t\t\tspan.setAttribute(\"analysis.status\", found.result.status);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tevidence.set(id, {\n\t\t\t\t\t\tanalysisId: id,\n\t\t\t\t\t\tdefinition: found.definition,\n\t\t\t\t\t\tresult: found.result,\n\t\t\t\t\t});\n\t\t\t\t\treturn summarizeResult(found.definition, found.result);\n\t\t\t\t}\n\t\t\t\tif (span) span.setAttribute(\"tool.outcome\", \"unknown_tool\");\n\t\t\t\treturn { error: `unknown tool: ${toolName}` };\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tif (tracer) {\n\t\t\t\t\tresultPayload = await tracer(\n\t\t\t\t\t\t`tool.${toolName}`,\n\t\t\t\t\t\tasync (span) => dispatchTool(span),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"openinference.span.kind\": \"TOOL\",\n\t\t\t\t\t\t\t\"tool.name\": toolName,\n\t\t\t\t\t\t\t\"tool.args\": JSON.stringify(args).slice(0, 512),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tresultPayload = await dispatchTool(null);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tresultPayload = {\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t};\n\t\t\t}\n\t\t\ttoolResultBlocks.push({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttool_use_id: block.id,\n\t\t\t\tcontent: JSON.stringify(resultPayload),\n\t\t\t});\n\t\t}\n\n\t\tmessages.push({\n\t\t\trole: \"user\",\n\t\t\tcontent: toolResultBlocks,\n\t\t});\n\t}\n\n\t// Hit iteration cap — return whatever evidence we accumulated with an error.\n\treturn {\n\t\tanswer: null,\n\t\tevidence: [...evidence.values()],\n\t\tevidenceReferences: askEvidenceReferences(evidence.values()),\n\t\tevidenceContract: EVIDENCE_REFERENCE_CONTRACT,\n\t\tqueries,\n\t\terror: `iteration cap (${MAX_ITERATIONS}) reached without final answer`,\n\t\ttimestamp: startedAt,\n\t};\n}\n\nasync function callAnthropic(\n\tconfig: LlmConfig,\n\tmessages: Array<{\n\t\trole: \"user\" | \"assistant\";\n\t\tcontent: string | AnthropicContentBlock[];\n\t}>,\n\tturnIndex?: number,\n): Promise<AnthropicResponse> {\n\tconst url = config.apiUrl ?? DEFAULT_API_URL;\n\tconst exec = async (\n\t\tspan: { setAttribute(k: string, v: unknown): void } | null,\n\t): Promise<AnthropicResponse> => {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"x-api-key\": config.apiKey,\n\t\t\t\t\"anthropic-version\": \"2023-06-01\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmodel: config.model,\n\t\t\t\tmax_tokens: 1024,\n\t\t\t\tsystem: SYSTEM_PROMPT,\n\t\t\t\ttools: TOOLS,\n\t\t\t\tmessages,\n\t\t\t}),\n\t\t});\n\t\tif (span) span.setAttribute(\"http.response.status_code\", response.status);\n\t\tif (!response.ok) {\n\t\t\tconst text = await response.text().catch(() => \"\");\n\t\t\tthrow new Error(`anthropic ${response.status}: ${text.slice(0, 200)}`);\n\t\t}\n\t\tconst json = (await response.json()) as AnthropicResponse & {\n\t\t\tusage?: { input_tokens?: number; output_tokens?: number };\n\t\t};\n\t\tif (span && json.usage) {\n\t\t\tif (typeof json.usage.input_tokens === \"number\")\n\t\t\t\tspan.setAttribute(\"gen_ai.usage.input_tokens\", json.usage.input_tokens);\n\t\t\tif (typeof json.usage.output_tokens === \"number\")\n\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\"gen_ai.usage.output_tokens\",\n\t\t\t\t\tjson.usage.output_tokens,\n\t\t\t\t);\n\t\t}\n\t\tif (span && json.stop_reason)\n\t\t\tspan.setAttribute(\"gen_ai.response.finish_reason\", json.stop_reason);\n\t\treturn json;\n\t};\n\n\tif (!config.tracer) return exec(null);\n\tconst attrs: Record<string, unknown> = {\n\t\t\"openinference.span.kind\": \"LLM\",\n\t\t\"gen_ai.system\": \"anthropic\",\n\t\t\"gen_ai.request.model\": config.model,\n\t\t\"gen_ai.request.max_tokens\": 1024,\n\t\t\"http.url\": url,\n\t};\n\tif (typeof turnIndex === \"number\") attrs[\"llm.turn\"] = turnIndex;\n\treturn config.tracer(\n\t\t\"llm.anthropic.messages\",\n\t\tasync (span) => exec(span),\n\t\tattrs,\n\t);\n}\n","/**\n * RFC 0002 Stage 5 — Ask box HTTP surface.\n *\n * POST /internal/ask { question } → AskResponse\n *\n * The dashboard's top-bar AskBox calls this once per question. Single-turn\n * for v1; the conversational `/ask` thread (with follow-ups + \"Save as\n * panel\") lands in a follow-up commit.\n *\n * The route does no SQL itself — it composes runAsk() from the catalog\n * lookups (AnalysesStore + getAllAnalysesForProject) and the LLM config.\n * If ANTHROPIC_API_KEY is unset we return a structured error rather than\n * 500-ing, so the dashboard can render a \"set ANTHROPIC_API_KEY to\n * enable Ask\" hint instead of a generic failure.\n */\n\nimport type { AskRequest, AskResponse } from \"@obsunified/types\";\nimport { getAllAnalysesForProject } from \"../analyses/index\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { AnalysesStore } from \"../lib/analyses-store\";\nimport { runAsk } from \"../lib/ask\";\nimport type { LlmConfig } from \"../lib/llm\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nconst MAX_QUESTION_CHARS = 1000;\n\nexport const askRoutesPlugin: CollectorPlugin = {\n\tname: \"ask-routes\",\n\tregister(app, runtime) {\n\t\tapp.post(\"/internal/ask\", async (c) => {\n\t\t\tlet body: Partial<AskRequest> = {};\n\t\t\ttry {\n\t\t\t\tbody = (await c.req.json()) as Partial<AskRequest>;\n\t\t\t} catch {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Bad Request\", message: \"body must be JSON\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst question = (body.question ?? \"\").trim();\n\t\t\tif (!question) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Bad Request\", message: \"question is required\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (question.length > MAX_QUESTION_CHARS) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: \"Bad Request\",\n\t\t\t\t\t\tmessage: `question exceeds ${MAX_QUESTION_CHARS} chars`,\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst projectId = getProjectId(c);\n\t\t\t// OpenAI wins if both keys are set.\n\t\t\t// Empty strings in .dev.vars come through as \"\" (not undefined),\n\t\t\t// so coerce to undefined explicitly — otherwise an empty\n\t\t\t// OPENAI_BASE_URL clobbers the default and we end up POSTing\n\t\t\t// to a relative URL.\n\t\t\tconst openaiBase = c.env.OPENAI_BASE_URL?.trim()\n\t\t\t\t? c.env.OPENAI_BASE_URL\n\t\t\t\t: undefined;\n\t\t\tconst narrativeModel = c.env.NARRATIVE_MODEL?.trim()\n\t\t\t\t? c.env.NARRATIVE_MODEL\n\t\t\t\t: undefined;\n\t\t\tconst llm: LlmConfig | null = c.env.OPENAI_API_KEY?.trim()\n\t\t\t\t? {\n\t\t\t\t\t\tprovider: \"openai\",\n\t\t\t\t\t\tapiKey: c.env.OPENAI_API_KEY,\n\t\t\t\t\t\tmodel: narrativeModel ?? \"gpt-4o-mini\",\n\t\t\t\t\t\tapiUrl: openaiBase,\n\t\t\t\t\t\ttracer: runtime.withChildSpan,\n\t\t\t\t\t}\n\t\t\t\t: c.env.ANTHROPIC_API_KEY?.trim()\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tprovider: \"anthropic\",\n\t\t\t\t\t\t\tapiKey: c.env.ANTHROPIC_API_KEY,\n\t\t\t\t\t\t\tmodel: narrativeModel ?? \"claude-haiku-4-5\",\n\t\t\t\t\t\t\ttracer: runtime.withChildSpan,\n\t\t\t\t\t\t}\n\t\t\t\t\t: null;\n\t\t\tif (!llm) {\n\t\t\t\tconst response: AskResponse = {\n\t\t\t\t\tanswer: null,\n\t\t\t\t\tevidence: [],\n\t\t\t\t\tqueries: [],\n\t\t\t\t\terror:\n\t\t\t\t\t\t\"Ask is not configured — set OPENAI_API_KEY or ANTHROPIC_API_KEY on the collector to enable it.\",\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t};\n\t\t\t\treturn c.json(response, 503);\n\t\t\t}\n\n\t\t\tconst store = new AnalysesStore(sqlDbFor(c.env));\n\n\t\t\ttry {\n\t\t\t\tconst startedAt = Date.now();\n\t\t\t\truntime.logger.info(\"[ask] llm call starting\", {\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\tprovider: llm.provider,\n\t\t\t\t\tmodel: llm.model,\n\t\t\t\t\tquestion_chars: question.length,\n\t\t\t\t});\n\t\t\t\tconst result = await runtime.withChildSpan(\n\t\t\t\t\t\"ask.runAsk\",\n\t\t\t\t\t() =>\n\t\t\t\t\t\trunAsk(question, {\n\t\t\t\t\t\t\tllm,\n\t\t\t\t\t\t\tlistAnalyses: async (filters) => {\n\t\t\t\t\t\t\t\t// Pull from the live registry so the model sees Tier 1\n\t\t\t\t\t\t\t\t// panels derived this tick, not stale ones in\n\t\t\t\t\t\t\t\t// `analysis_definitions`.\n\t\t\t\t\t\t\t\tconst all = await getAllAnalysesForProject(projectId, {\n\t\t\t\t\t\t\t\t\tdb: sqlDbFor(c.env),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn all.filter((d) => {\n\t\t\t\t\t\t\t\t\tif (filters?.group && d.group !== filters.group) return false;\n\t\t\t\t\t\t\t\t\tif (filters?.view && d.view !== filters.view) return false;\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tgetLatestResult: async (id) => {\n\t\t\t\t\t\t\t\tconst definitions = await store.listDefinitions(projectId);\n\t\t\t\t\t\t\t\tconst definition = definitions.find((d) => d.id === id);\n\t\t\t\t\t\t\t\tif (!definition) return null;\n\t\t\t\t\t\t\t\tconst r = await store.getLatestResult(projectId, id);\n\t\t\t\t\t\t\t\treturn { definition, result: r };\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\t\"llm.provider\": llm.provider,\n\t\t\t\t\t\t\"llm.model\": llm.model,\n\t\t\t\t\t\t\"openinference.span.kind\": \"LLM\",\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\truntime.logger.info(\"[ask] llm call finished\", {\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\tprovider: llm.provider,\n\t\t\t\t\tmodel: llm.model,\n\t\t\t\t\tlatency_ms: Date.now() - startedAt,\n\t\t\t\t\tevidence_count: result.evidence.length,\n\t\t\t\t\tquery_count: result.queries.length,\n\t\t\t\t\tanswered: Boolean(result.answer),\n\t\t\t\t});\n\n\t\t\t\t// Stage 6 — log evidence citations for the auto-pin derivation.\n\t\t\t\t// Only on successful answers; failed loops would skew the signal\n\t\t\t\t// (the model often calls every tool it has on the way to giving\n\t\t\t\t// up). Best-effort: a write failure here doesn't fail the ask.\n\t\t\t\tif (result.answer && result.evidence.length > 0) {\n\t\t\t\t\tawait store\n\t\t\t\t\t\t.recordAskEvidence(\n\t\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\t\tresult.evidence.map((e) => e.analysisId),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.catch((err) =>\n\t\t\t\t\t\t\truntime.logger.warn(\"[ask] recordAskEvidence failed\", {\n\t\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn c.json(result);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\truntime.logger.error(\"[ask] failed\", { error: message });\n\t\t\t\tconst response: AskResponse = {\n\t\t\t\t\tanswer: null,\n\t\t\t\t\tevidence: [],\n\t\t\t\t\tqueries: [],\n\t\t\t\t\terror: message,\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t};\n\t\t\t\treturn c.json(response, 500);\n\t\t\t}\n\t\t});\n\t},\n};\n","const BOT_PATTERN =\n\t/(?:^|[^\\p{L}\\p{N}])(?:bot|crawler|spider|slurp|facebookexternalhit|headless|monitoring|uptime|curl|wget|python-requests|go-http-client)(?:$|[^\\p{L}\\p{N}])/iu;\n\nexport interface ParsedUserAgent {\n\tbrowser: string | null;\n\tos: string | null;\n\tdeviceType: string | null;\n}\n\nexport const isBot = (userAgent: string | null | undefined): boolean =>\n\tBoolean(userAgent && BOT_PATTERN.test(userAgent));\n\nconst detectBrowser = (userAgent: string): string | null => {\n\tif (/edg\\//i.test(userAgent)) return \"Edge\";\n\tif (/opr\\//i.test(userAgent) || /opera/i.test(userAgent)) return \"Opera\";\n\tif (/samsungbrowser\\//i.test(userAgent)) return \"Samsung Internet\";\n\tif (/chrome\\//i.test(userAgent) || /crios\\//i.test(userAgent))\n\t\treturn \"Chrome\";\n\tif (/firefox\\//i.test(userAgent) || /fxios\\//i.test(userAgent))\n\t\treturn \"Firefox\";\n\tif (/safari\\//i.test(userAgent)) return \"Safari\";\n\treturn null;\n};\n\nconst detectOs = (userAgent: string): string | null => {\n\tif (/windows nt/i.test(userAgent)) return \"Windows\";\n\tif (/(iphone|ipad|ipod)/i.test(userAgent)) return \"iOS\";\n\tif (/android/i.test(userAgent)) return \"Android\";\n\tif (/mac os x/i.test(userAgent) || /macintosh/i.test(userAgent))\n\t\treturn \"macOS\";\n\tif (/linux/i.test(userAgent)) return \"Linux\";\n\treturn null;\n};\n\nconst detectDeviceType = (userAgent: string): string | null => {\n\tif (/ipad|tablet/i.test(userAgent)) return \"tablet\";\n\tif (/mobile|iphone|ipod|android/i.test(userAgent)) return \"mobile\";\n\treturn \"desktop\";\n};\n\nexport const parseUserAgent = (\n\tuserAgent: string | null | undefined,\n): ParsedUserAgent => {\n\tif (!userAgent) {\n\t\treturn { browser: null, os: null, deviceType: null };\n\t}\n\n\tif (isBot(userAgent)) {\n\t\treturn {\n\t\t\tbrowser: detectBrowser(userAgent),\n\t\t\tos: detectOs(userAgent),\n\t\t\tdeviceType: \"bot\",\n\t\t};\n\t}\n\n\treturn {\n\t\tbrowser: detectBrowser(userAgent),\n\t\tos: detectOs(userAgent),\n\t\tdeviceType: detectDeviceType(userAgent),\n\t};\n};\n","import type {\n\tCollectorPlugin,\n\tUsageEventProcessorPlugin,\n} from \"../framework/collector\";\nimport { isBot } from \"../lib/ua-parser\";\n\nconst processor: UsageEventProcessorPlugin = {\n\tname: \"bot-filter\",\n\tprocess(events) {\n\t\treturn events.map((event) => ({ ...event, isBot: isBot(event.userAgent) }));\n\t},\n};\n\nexport const botFilterPlugin: CollectorPlugin = {\n\tname: \"bot-filter\",\n\tregister(_app, runtime) {\n\t\truntime.addUsageEventProcessor(processor);\n\t},\n};\n","/**\n * RFC 0006 Phase 3.1 — Connected rail manifest endpoint.\n *\n * GET /internal/connected/:kind/:id\n *\n * Returns the entity's identity-graph neighbors (Up / Across / Down) +\n * topic neighbors (Related), bundled into the shape the dashboard's\n * <ConnectedRail /> renders directly. Built on `IdentityIndex` so the\n * underlying SQL is shared with `/internal/timeline/:sessionId` and any\n * future cross-signal consumer.\n *\n * The handler is the single read path the rail uses. Sections that have\n * no neighbors render as `links: []` with an `emptyReason` explaining\n * why — never absent. This is the \"informative absence\" pattern from\n * RFC 0006 § Connected rail / Empty-state.\n */\n\nimport { ActionConfidence } from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { IdentityIndex } from \"../lib/identity-index\";\nimport {\n\tmapAction,\n\tmapAgentRun,\n\tmapEvalResult,\n\tmapToolCall,\n} from \"../lib/identity-index/mappers\";\nimport type {\n\tActionRef,\n\tAgentRunRef,\n\tEvalResultRef,\n\tToolCallRef,\n} from \"../lib/identity-index/types\";\nimport type { SqlDb } from \"../lib/sql-db\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nimport {\n\ttype ActionContextLinkMetadata,\n\ttype ConnectedEntityKind,\n\ttype ConnectedManifest,\n\tKNOWN_KINDS,\n\tlinksFromActions,\n\tlinksFromAi,\n\tlinksFromArtifacts,\n\tlinksFromEvalResults,\n\tlinksFromLogs,\n\tlinksFromMetricExemplars,\n\tlinksFromRetrievalEvents,\n\tlinksFromSpans,\n\tlinksFromToolCalls,\n\tlinksFromUsage,\n\tlinkToAction,\n\tlinkToAgentRun,\n\tlinkToSession,\n\tlinkToTrace,\n\tMAX_LINKS_INLINE,\n\tprofileLinksForTrace,\n} from \"./connected-routes/manifest\";\n\nexport type {\n\tConnectedEntityKind,\n\tConnectedLink,\n\tConnectedManifest,\n\tConnectedSection,\n} from \"./connected-routes/manifest\";\n\ninterface SignalActionContext {\n\tactions: ActionRef[];\n\tagentRuns: AgentRunRef[];\n\ttoolCalls: ToolCallRef[];\n\tevalResults: EvalResultRef[];\n\tmatchLevel: \"span\" | \"trace\" | \"none\";\n}\n\nconst emptySignalActionContext = (): SignalActionContext => ({\n\tactions: [],\n\tagentRuns: [],\n\ttoolCalls: [],\n\tevalResults: [],\n\tmatchLevel: \"none\",\n});\n\nconst loadSignalActionContext = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\ttraceId: string | null | undefined,\n\tspanId?: string | null,\n): Promise<SignalActionContext> => {\n\tif (!traceId) return emptySignalActionContext();\n\n\tconst exactRows = spanId\n\t\t? await db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT *\n\t\t\t\t\t FROM actions\n\t\t\t\t\t WHERE project_id = ? AND trace_id = ? AND span_id = ?\n\t\t\t\t\t ORDER BY started_at ASC\n\t\t\t\t\t LIMIT 20`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, traceId, spanId)\n\t\t\t\t.all<Parameters<typeof mapAction>[0]>()\n\t\t: { results: [] as Parameters<typeof mapAction>[0][] };\n\n\tconst traceRows =\n\t\texactRows.results.length > 0\n\t\t\t? exactRows\n\t\t\t: await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT *\n\t\t\t\t\t\t FROM actions\n\t\t\t\t\t\t WHERE project_id = ? AND trace_id = ?\n\t\t\t\t\t\t ORDER BY started_at ASC\n\t\t\t\t\t\t LIMIT 20`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, traceId)\n\t\t\t\t\t.all<Parameters<typeof mapAction>[0]>();\n\n\tconst actionRows = traceRows.results;\n\tif (actionRows.length === 0) return emptySignalActionContext();\n\n\tconst actionIds = actionRows.map((action) => action.id);\n\tconst rootActionIds = Array.from(\n\t\tnew Set(\n\t\t\tactionRows\n\t\t\t\t.map((action) => action.agent_run_id ?? action.root_action_id)\n\t\t\t\t.filter((id): id is string => Boolean(id)),\n\t\t),\n\t);\n\tconst actionPlaceholders = actionIds.map(() => \"?\").join(\", \");\n\tconst rootPlaceholders = rootActionIds.map(() => \"?\").join(\", \");\n\n\tconst [toolCalls, evalResults, agentRuns] = await Promise.all([\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT *\n\t\t\t\t FROM tool_calls\n\t\t\t\t WHERE project_id = ? AND action_id IN (${actionPlaceholders})\n\t\t\t\t ORDER BY id ASC\n\t\t\t\t LIMIT 20`,\n\t\t\t)\n\t\t\t.bind(projectId, ...actionIds)\n\t\t\t.all<Parameters<typeof mapToolCall>[0]>(),\n\t\tdb\n\t\t\t.prepare(\n\t\t\t\t`SELECT *\n\t\t\t\t FROM eval_results\n\t\t\t\t WHERE project_id = ? AND action_id IN (${actionPlaceholders})\n\t\t\t\t ORDER BY id ASC\n\t\t\t\t LIMIT 20`,\n\t\t\t)\n\t\t\t.bind(projectId, ...actionIds)\n\t\t\t.all<Parameters<typeof mapEvalResult>[0]>(),\n\t\trootActionIds.length > 0\n\t\t\t? db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT *\n\t\t\t\t\t\t FROM agent_runs\n\t\t\t\t\t\t WHERE project_id = ? AND id IN (${rootPlaceholders})\n\t\t\t\t\t\t ORDER BY id ASC\n\t\t\t\t\t\t LIMIT 20`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, ...rootActionIds)\n\t\t\t\t\t.all<Parameters<typeof mapAgentRun>[0]>()\n\t\t\t: { results: [] as Parameters<typeof mapAgentRun>[0][] },\n\t]);\n\n\treturn {\n\t\tactions: actionRows.map(mapAction),\n\t\tagentRuns: agentRuns.results.map(mapAgentRun),\n\t\ttoolCalls: toolCalls.results.map(mapToolCall),\n\t\tevalResults: evalResults.results.map(mapEvalResult),\n\t\tmatchLevel: exactRows.results.length > 0 ? \"span\" : \"trace\",\n\t};\n};\n\nconst actionMatchEmptyReason = (context: SignalActionContext): string =>\n\tcontext.matchLevel === \"trace\"\n\t\t? \"No exact span-level action existed, so these links use trace-level action context.\"\n\t\t: \"No action graph records share this signal's trace/span identity.\";\n\nconst actionContextLinkMetadata = (\n\tcontext: SignalActionContext,\n\tentityLabel: string,\n): ActionContextLinkMetadata => {\n\tif (context.matchLevel === \"trace\") {\n\t\treturn {\n\t\t\tsource: \"trace_id\",\n\t\t\tcausalConfidence: ActionConfidence.Fallback,\n\t\t\tconfidence: 0.55,\n\t\t\treason: `No exact span-level action matched this ${entityLabel}; linked by shared trace_id instead.`,\n\t\t};\n\t}\n\treturn {\n\t\tsource: \"trace_id+span_id\",\n\t\tconfidence: 0.95,\n\t\treason: `Action context matched this ${entityLabel} by exact trace_id and span_id.`,\n\t};\n};\n\nconst metadataForSignalActions = (\n\tcontext: SignalActionContext,\n\tentityLabel: string,\n): ((actionId: string) => ActionContextLinkMetadata | undefined) => {\n\tconst byActionId = new Map(\n\t\tcontext.actions.map((action) => {\n\t\t\tconst metadata = actionContextLinkMetadata(context, entityLabel);\n\t\t\treturn [\n\t\t\t\taction.id,\n\t\t\t\tcontext.matchLevel === \"span\"\n\t\t\t\t\t? { ...metadata, causalConfidence: action.causalConfidence }\n\t\t\t\t\t: metadata,\n\t\t\t] as const;\n\t\t}),\n\t);\n\treturn (actionId) => byActionId.get(actionId);\n};\n\nconst traceLevelMetadata = (\n\tentityLabel: string,\n): ActionContextLinkMetadata => ({\n\tsource: \"trace_id\",\n\tcausalConfidence: ActionConfidence.Fallback,\n\tconfidence: 0.55,\n\treason: `Linked ${entityLabel} through sampled trace_id context; no exact span-level causal edge is implied.`,\n});\n\nconst linksForAgentRuns = (\n\truns: AgentRunRef[],\n\tcontext: SignalActionContext,\n\tentityLabel: string,\n) =>\n\truns.slice(0, MAX_LINKS_INLINE).map((run) => ({\n\t\t...linkToAgentRun(run.id, `${run.agentName} (v${run.agentVersion})`),\n\t\t...actionContextLinkMetadata(context, entityLabel),\n\t}));\n\nexport const connectedRoutesPlugin: CollectorPlugin = {\n\tname: \"connected-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/connected/:kind/:id\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst rawKind = c.req.param(\"kind\");\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) {\n\t\t\t\treturn c.json({ error: \"id required\" }, 400);\n\t\t\t}\n\t\t\tif (!KNOWN_KINDS.has(rawKind)) {\n\t\t\t\t// Unknown kinds used to fall through every `if` branch and\n\t\t\t\t// return 200 + empty sections, which hid client bugs.\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: `unknown entity kind: ${rawKind}`,\n\t\t\t\t\t\tknown: [...KNOWN_KINDS],\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst kind = rawKind as ConnectedEntityKind;\n\n\t\t\tconst index = new IdentityIndex(sqlDbFor(c.env));\n\n\t\t\t// Each entity kind starts with a different lookup key. The\n\t\t\t// helpers above shape ref arrays into ConnectedSection.\n\t\t\tconst manifest: ConnectedManifest = {\n\t\t\t\tentity: { kind, id, projectId },\n\t\t\t\tup: [],\n\t\t\t\tacross: [],\n\t\t\t\tdown: [],\n\t\t\t\trelated: [],\n\t\t\t};\n\n\t\t\tif (kind === \"span\") {\n\t\t\t\t// Span: load by trace_id (its parent chain) + by interaction_id\n\t\t\t\t// (the click that caused it). Then bucket.\n\t\t\t\tconst traceManifest = await index.byTrace(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tid.split(\":\")[0] ?? id,\n\t\t\t\t);\n\t\t\t\tconst span = traceManifest.spans.find(\n\t\t\t\t\t(s) => `${s.traceId}:${s.spanId}` === id,\n\t\t\t\t);\n\t\t\t\tif (span) {\n\t\t\t\t\tconst actionContext = await loadSignalActionContext(\n\t\t\t\t\t\tsqlDbFor(c.env),\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tspan.traceId,\n\t\t\t\t\t\tspan.spanId,\n\t\t\t\t\t);\n\t\t\t\t\tconst otherSpans = traceManifest.spans.filter(\n\t\t\t\t\t\t(s) => s.spanId !== span.spanId,\n\t\t\t\t\t);\n\t\t\t\t\tmanifest.up = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Trace\",\n\t\t\t\t\t\t\tlinks: [linkToTrace(span.traceId, \"Parent trace\")],\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\tlinksFromSpans(otherSpans, `Other spans in this trace`),\n\t\t\t\t\t\tlinksFromLogs(traceManifest.logs, \"Logs in this trace\"),\n\t\t\t\t\t\tlinksFromAi(traceManifest.aiCalls, \"AI calls in this trace\"),\n\t\t\t\t\t];\n\t\t\t\t\t// RFC 0009 acceptance #5 — surface pprof profiles\n\t\t\t\t\t// (CPU + off-CPU) covering this trace's window in the\n\t\t\t\t\t// rail's Down section. Each profile_type renders as\n\t\t\t\t\t// its own link so a viewer can see at a glance whether\n\t\t\t\t\t// only CPU was sampled or off-CPU is present too.\n\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\t...(await profileLinksForTrace(\n\t\t\t\t\t\t\tsqlDbFor(c.env),\n\t\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\t\tspan.traceId,\n\t\t\t\t\t\t)),\n\t\t\t\t\t\tlinksFromActions(\n\t\t\t\t\t\t\tactionContext.actions,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Causal actions for this span\"\n\t\t\t\t\t\t\t\t: \"Trace-level actions for this span\",\n\t\t\t\t\t\t\tactionContextLinkMetadata(actionContext, \"span\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromToolCalls(\n\t\t\t\t\t\t\tactionContext.toolCalls,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Tool calls for this span\"\n\t\t\t\t\t\t\t\t: \"Trace-level tool calls for this span\",\n\t\t\t\t\t\t\tmetadataForSignalActions(actionContext, \"span\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromEvalResults(\n\t\t\t\t\t\t\tactionContext.evalResults,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Evaluations for this span\"\n\t\t\t\t\t\t\t\t: \"Trace-level evaluations for this span\",\n\t\t\t\t\t\t\tmetadataForSignalActions(actionContext, \"span\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromMetricExemplars(\n\t\t\t\t\t\t\ttraceManifest.metricExemplars.filter(\n\t\t\t\t\t\t\t\t(e) => !e.spanId || e.spanId === span.spanId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\"Metric exemplars in this trace\",\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\t\t\t\t\tif (span.interactionId) {\n\t\t\t\t\t\tconst interactionManifest = await index.byInteraction(\n\t\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\t\tspan.interactionId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\t\tlinksFromUsage(\n\t\t\t\t\t\t\t\tinteractionManifest.usageEvents,\n\t\t\t\t\t\t\t\t`Click that caused this trace`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"Originating click\",\n\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\"Server-originated work (cron, retry, queue consumer) — not bound to a user click.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\t\t\t\t\tif (actionContext.agentRuns.length > 0) {\n\t\t\t\t\t\tmanifest.related.push({\n\t\t\t\t\t\t\tlabel:\n\t\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t\t? \"Agent runs for this span\"\n\t\t\t\t\t\t\t\t\t: \"Trace-level agent runs for this span\",\n\t\t\t\t\t\t\tlinks: linksForAgentRuns(\n\t\t\t\t\t\t\t\tactionContext.agentRuns,\n\t\t\t\t\t\t\t\tactionContext,\n\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmanifest.related.push({\n\t\t\t\t\t\t\tlabel: \"Agent runs for this span\",\n\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\temptyReason: actionMatchEmptyReason(actionContext),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (kind === \"profile\") {\n\t\t\t\tconst db = sqlDbFor(c.env);\n\t\t\t\tconst profile = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT id, service_name, profile_type, start_ts, end_ts,\n\t\t\t\t\t\t\t\tduration_ms, sample_count, agent\n\t\t\t\t\t\t FROM profile_blobs\n\t\t\t\t\t\t WHERE project_id = ? AND id = ?\n\t\t\t\t\t\t LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, id)\n\t\t\t\t\t.first<{\n\t\t\t\t\t\tid: string;\n\t\t\t\t\t\tservice_name: string | null;\n\t\t\t\t\t\tprofile_type: string;\n\t\t\t\t\t\tstart_ts: string;\n\t\t\t\t\t\tend_ts: string;\n\t\t\t\t\t\tduration_ms: number;\n\t\t\t\t\t\tsample_count: number | null;\n\t\t\t\t\t\tagent: string | null;\n\t\t\t\t\t}>();\n\n\t\t\t\tif (profile) {\n\t\t\t\t\tconst traceRows = await db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`SELECT trace_id\n\t\t\t\t\t\t\t FROM profile_trace_index\n\t\t\t\t\t\t\t WHERE project_id = ? AND profile_id = ?\n\t\t\t\t\t\t\t ORDER BY trace_id ASC\n\t\t\t\t\t\t\t LIMIT 50`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.bind(projectId, id)\n\t\t\t\t\t\t.all<{ trace_id: string }>();\n\t\t\t\t\tconst traceIds = traceRows.results.map((row) => row.trace_id);\n\t\t\t\t\tconst sampledTraceIds = traceIds.slice(0, MAX_LINKS_INLINE);\n\t\t\t\t\tconst traceManifests = await Promise.all(\n\t\t\t\t\t\tsampledTraceIds.map((traceId) => index.byTrace(projectId, traceId)),\n\t\t\t\t\t);\n\t\t\t\t\tconst spans = traceManifests.flatMap((m) => m.spans);\n\t\t\t\t\tconst logs = traceManifests.flatMap((m) => m.logs);\n\t\t\t\t\tconst aiCalls = traceManifests.flatMap((m) => m.aiCalls);\n\t\t\t\t\tconst metricExemplars = traceManifests.flatMap(\n\t\t\t\t\t\t(m) => m.metricExemplars,\n\t\t\t\t\t);\n\n\t\t\t\t\tmanifest.up = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Profile window\",\n\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\temptyReason: `${profile.service_name ?? \"unknown service\"} · ${profile.profile_type} · ${profile.duration_ms}ms · ${profile.sample_count ?? \"unknown\"} samples`,\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\ttraceIds.length > 0\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tlabel: \"Sampled traces\",\n\t\t\t\t\t\t\t\t\tlinks:\n\t\t\t\t\t\t\t\t\t\ttraceIds.length > MAX_LINKS_INLINE\n\t\t\t\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: `${traceIds.length} sampled traces`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thref: `#/traces?trace=${encodeURIComponent(traceIds[0])}`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcount: traceIds.length,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsample: traceIds[0],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t: traceIds.map((traceId) => linkToTrace(traceId)),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tlabel: \"Sampled traces\",\n\t\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\t\"No trace_id labels were indexed for this profile. Push pprof samples with trace_id labels or x-obs-trace-ids to enable trace pivots.\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\tlinksFromSpans(spans, \"Sampled spans\"),\n\t\t\t\t\t\tlinksFromLogs(logs, \"Logs in sampled traces\"),\n\t\t\t\t\t\tlinksFromAi(aiCalls, \"AI calls in sampled traces\"),\n\t\t\t\t\t\tlinksFromMetricExemplars(\n\t\t\t\t\t\t\tmetricExemplars,\n\t\t\t\t\t\t\t\"Metric exemplars in sampled traces\",\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\n\t\t\t\t\tif (traceIds.length > 0) {\n\t\t\t\t\t\tconst placeholders = traceIds.map(() => \"?\").join(\", \");\n\t\t\t\t\t\tconst actions = await db\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT id, action_kind, name\n\t\t\t\t\t\t\t\t FROM actions\n\t\t\t\t\t\t\t\t WHERE project_id = ? AND trace_id IN (${placeholders})\n\t\t\t\t\t\t\t\t ORDER BY started_at ASC\n\t\t\t\t\t\t\t\t LIMIT 20`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(projectId, ...traceIds)\n\t\t\t\t\t\t\t.all<{\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\taction_kind: string;\n\t\t\t\t\t\t\t\tname: string | null;\n\t\t\t\t\t\t\t}>();\n\t\t\t\t\t\tconst actionIds = actions.results.map((action) => action.id);\n\t\t\t\t\t\tconst actionPlaceholders = actionIds.map(() => \"?\").join(\", \");\n\n\t\t\t\t\t\tconst toolCalls =\n\t\t\t\t\t\t\tactionIds.length > 0\n\t\t\t\t\t\t\t\t? await db\n\t\t\t\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t\t\t\t`SELECT id, tool_name\n\t\t\t\t\t\t\t\t\t\t\t FROM tool_calls\n\t\t\t\t\t\t\t\t\t\t\t WHERE project_id = ? AND action_id IN (${actionPlaceholders})\n\t\t\t\t\t\t\t\t\t\t\t ORDER BY id ASC\n\t\t\t\t\t\t\t\t\t\t\t LIMIT 20`,\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t.bind(projectId, ...actionIds)\n\t\t\t\t\t\t\t\t\t\t.all<{ id: string; tool_name: string }>()\n\t\t\t\t\t\t\t\t: { results: [] as Array<{ id: string; tool_name: string }> };\n\n\t\t\t\t\t\tconst agentRuns = await db\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT DISTINCT ar.id, ar.agent_name, ar.agent_version\n\t\t\t\t\t\t\t\t FROM actions a\n\t\t\t\t\t\t\t\t JOIN agent_runs ar\n\t\t\t\t\t\t\t\t ON ar.project_id = a.project_id\n\t\t\t\t\t\t\t\t AND ar.id = COALESCE(a.agent_run_id, a.root_action_id)\n\t\t\t\t\t\t\t\t WHERE a.project_id = ? AND a.trace_id IN (${placeholders})\n\t\t\t\t\t\t\t\t ORDER BY ar.id ASC\n\t\t\t\t\t\t\t\t LIMIT 20`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(projectId, ...traceIds)\n\t\t\t\t\t\t\t.all<{\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\tagent_name: string;\n\t\t\t\t\t\t\t\tagent_version: string;\n\t\t\t\t\t\t\t}>();\n\n\t\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\t\tactions.results.length > 0\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tlabel: \"Causal actions in sampled traces\",\n\t\t\t\t\t\t\t\t\t\tlinks: actions.results\n\t\t\t\t\t\t\t\t\t\t\t.slice(0, MAX_LINKS_INLINE)\n\t\t\t\t\t\t\t\t\t\t\t.map((action) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t...linkToAction(\n\t\t\t\t\t\t\t\t\t\t\t\t\taction.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t`[${action.action_kind}] ${action.name ?? action.id}`,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t...traceLevelMetadata(\"profile action\"),\n\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\tlabel: \"Causal actions in sampled traces\",\n\t\t\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\t\t\"No action graph records share this profile's sampled trace IDs.\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttoolCalls.results.length > 0\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tlabel: \"Tool calls in sampled traces\",\n\t\t\t\t\t\t\t\t\t\tlinks: toolCalls.results\n\t\t\t\t\t\t\t\t\t\t\t.slice(0, MAX_LINKS_INLINE)\n\t\t\t\t\t\t\t\t\t\t\t.map((toolCall) => ({\n\t\t\t\t\t\t\t\t\t\t\t\tlabel: `tool: ${toolCall.tool_name}`,\n\t\t\t\t\t\t\t\t\t\t\t\thref: `#/tool-calls/${toolCall.id}`,\n\t\t\t\t\t\t\t\t\t\t\t\tentityKind: \"tool_call\",\n\t\t\t\t\t\t\t\t\t\t\t\tentityId: toolCall.id,\n\t\t\t\t\t\t\t\t\t\t\t\t...traceLevelMetadata(\"profile tool call\"),\n\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\tlabel: \"Tool calls in sampled traces\",\n\t\t\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\t\t\"No tool calls were attached to actions in this profile.\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\n\t\t\t\t\t\tmanifest.related =\n\t\t\t\t\t\t\tagentRuns.results.length > 0\n\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tlabel: \"Agent runs\",\n\t\t\t\t\t\t\t\t\t\t\tlinks: agentRuns.results\n\t\t\t\t\t\t\t\t\t\t\t\t.slice(0, MAX_LINKS_INLINE)\n\t\t\t\t\t\t\t\t\t\t\t\t.map((run) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t...linkToAgentRun(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trun.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t`${run.agent_name} (v${run.agent_version})`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t...traceLevelMetadata(\"profile agent run\"),\n\t\t\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tlabel: \"Agent runs\",\n\t\t\t\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\t\t\t\"No agent runs were attached to actions in this profile.\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"Causal actions in sampled traces\",\n\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\"No action graph records can be joined because this profile has no indexed trace IDs.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"Tool calls in sampled traces\",\n\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\"No tool calls can be joined because this profile has no indexed trace IDs.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"Agent runs\",\n\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\t\"No agent runs can be joined because this profile has no indexed trace IDs.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (kind === \"log\") {\n\t\t\t\t// Log: resolve direct log ids when the caller did not already carry\n\t\t\t\t// trace/session params, then add exact action graph pivots.\n\t\t\t\tconst db = sqlDbFor(c.env);\n\t\t\t\tconst logRow = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT trace_id, span_id, session_id\n\t\t\t\t\t\t FROM logs\n\t\t\t\t\t\t WHERE project_id = ? AND log_id = ?\n\t\t\t\t\t\t LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, id)\n\t\t\t\t\t.first<{\n\t\t\t\t\t\ttrace_id: string | null;\n\t\t\t\t\t\tspan_id: string | null;\n\t\t\t\t\t\tsession_id: string | null;\n\t\t\t\t\t}>();\n\t\t\t\tconst traceId =\n\t\t\t\t\tc.req.query(\"trace_id\") ?? logRow?.trace_id ?? undefined;\n\t\t\t\tconst spanId = c.req.query(\"span_id\") ?? logRow?.span_id ?? undefined;\n\t\t\t\tconst sessionId =\n\t\t\t\t\tc.req.query(\"session_id\") ?? logRow?.session_id ?? undefined;\n\t\t\t\tif (traceId) {\n\t\t\t\t\tconst traceManifest = await index.byTrace(projectId, traceId);\n\t\t\t\t\tconst actionContext = await loadSignalActionContext(\n\t\t\t\t\t\tdb,\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\ttraceId,\n\t\t\t\t\t\tspanId,\n\t\t\t\t\t);\n\t\t\t\t\tmanifest.up = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Trace\",\n\t\t\t\t\t\t\tlinks: [linkToTrace(traceId, \"Parent trace\")],\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\tlinksFromLogs(\n\t\t\t\t\t\t\ttraceManifest.logs.filter((l) => l.logId !== id),\n\t\t\t\t\t\t\t\"Other logs in this trace\",\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\tlinksFromActions(\n\t\t\t\t\t\t\tactionContext.actions,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Causal actions for this log\"\n\t\t\t\t\t\t\t\t: \"Trace-level actions for this log\",\n\t\t\t\t\t\t\tactionContextLinkMetadata(actionContext, \"log\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromToolCalls(\n\t\t\t\t\t\t\tactionContext.toolCalls,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Tool calls for this log\"\n\t\t\t\t\t\t\t\t: \"Trace-level tool calls for this log\",\n\t\t\t\t\t\t\tmetadataForSignalActions(actionContext, \"log\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromEvalResults(\n\t\t\t\t\t\t\tactionContext.evalResults,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Evaluations for this log\"\n\t\t\t\t\t\t\t\t: \"Trace-level evaluations for this log\",\n\t\t\t\t\t\t\tmetadataForSignalActions(actionContext, \"log\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\tactionContext.agentRuns.length > 0\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tlabel:\n\t\t\t\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t\t\t\t? \"Agent runs for this log\"\n\t\t\t\t\t\t\t\t\t\t\t: \"Trace-level agent runs for this log\",\n\t\t\t\t\t\t\t\t\tlinks: actionContext.agentRuns\n\t\t\t\t\t\t\t\t\t\t.slice(0, MAX_LINKS_INLINE)\n\t\t\t\t\t\t\t\t\t\t.map((run) => ({\n\t\t\t\t\t\t\t\t\t\t\t...linkToAgentRun(\n\t\t\t\t\t\t\t\t\t\t\t\trun.id,\n\t\t\t\t\t\t\t\t\t\t\t\t`${run.agentName} (v${run.agentVersion})`,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t...actionContextLinkMetadata(actionContext, \"log\"),\n\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tlabel: \"Agent runs for this log\",\n\t\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\t\temptyReason: actionMatchEmptyReason(actionContext),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tif (sessionId) {\n\t\t\t\t\tconst sessionManifest = await index.bySession(projectId, sessionId);\n\t\t\t\t\tmanifest.across.push(\n\t\t\t\t\t\tlinksFromUsage(\n\t\t\t\t\t\t\tsessionManifest.usageEvents,\n\t\t\t\t\t\t\t\"Usage events in this session\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tif (sessionManifest.replay) {\n\t\t\t\t\t\tmanifest.across.push({\n\t\t\t\t\t\t\tlabel: \"Replay\",\n\t\t\t\t\t\t\tlinks: [linkToSession(sessionId)],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (kind === \"usage\" || kind === \"replay\") {\n\t\t\t\t// Usage / replay events are session-scoped — load by session_id\n\t\t\t\t// from the query string.\n\t\t\t\tconst sessionId = c.req.query(\"session_id\") ?? id;\n\t\t\t\tconst sessionManifest = await index.bySession(projectId, sessionId);\n\t\t\t\tmanifest.up = [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Session\",\n\t\t\t\t\t\tlinks: [linkToSession(sessionId)],\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t\tmanifest.across = [\n\t\t\t\t\tlinksFromSpans(sessionManifest.spans, \"Spans in this session\"),\n\t\t\t\t\tlinksFromLogs(sessionManifest.logs, \"Logs in this session\"),\n\t\t\t\t\tlinksFromAi(sessionManifest.aiCalls, \"AI calls in this session\"),\n\t\t\t\t];\n\t\t\t\tmanifest.related = [\n\t\t\t\t\tsessionManifest.replay\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tlabel: \"Replay\",\n\t\t\t\t\t\t\t\tlinks: [linkToSession(sessionId)],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tlabel: \"Replay\",\n\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\temptyReason: \"No rrweb replay recorded for this session.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t} else if (kind === \"ai_call\") {\n\t\t\t\tconst db = sqlDbFor(c.env);\n\t\t\t\tconst callRow = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT trace_id, span_id, session_id\n\t\t\t\t\t\t FROM ai_calls\n\t\t\t\t\t\t WHERE project_id = ? AND call_id = ?\n\t\t\t\t\t\t LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, id)\n\t\t\t\t\t.first<{\n\t\t\t\t\t\ttrace_id: string | null;\n\t\t\t\t\t\tspan_id: string | null;\n\t\t\t\t\t\tsession_id: string | null;\n\t\t\t\t\t}>();\n\t\t\t\tconst traceId =\n\t\t\t\t\tc.req.query(\"trace_id\") ?? callRow?.trace_id ?? undefined;\n\t\t\t\tconst spanId = c.req.query(\"span_id\") ?? callRow?.span_id ?? undefined;\n\t\t\t\tif (traceId) {\n\t\t\t\t\tconst traceManifest = await index.byTrace(projectId, traceId);\n\t\t\t\t\tconst actionContext = await loadSignalActionContext(\n\t\t\t\t\t\tdb,\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\ttraceId,\n\t\t\t\t\t\tspanId,\n\t\t\t\t\t);\n\t\t\t\t\tmanifest.up = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Trace\",\n\t\t\t\t\t\t\tlinks: [linkToTrace(traceId, \"Parent trace\")],\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\tlinksFromSpans(traceManifest.spans, \"Spans in this trace\"),\n\t\t\t\t\t\tlinksFromAi(\n\t\t\t\t\t\t\ttraceManifest.aiCalls.filter((a) => a.callId !== id),\n\t\t\t\t\t\t\t\"Other AI calls in this trace\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromMetricExemplars(\n\t\t\t\t\t\t\ttraceManifest.metricExemplars,\n\t\t\t\t\t\t\t\"Metric exemplars in this trace\",\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\tlinksFromActions(\n\t\t\t\t\t\t\tactionContext.actions,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Causal actions for this AI call\"\n\t\t\t\t\t\t\t\t: \"Trace-level actions for this AI call\",\n\t\t\t\t\t\t\tactionContextLinkMetadata(actionContext, \"AI call\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromToolCalls(\n\t\t\t\t\t\t\tactionContext.toolCalls,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Tool calls for this AI call\"\n\t\t\t\t\t\t\t\t: \"Trace-level tool calls for this AI call\",\n\t\t\t\t\t\t\tmetadataForSignalActions(actionContext, \"AI call\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromEvalResults(\n\t\t\t\t\t\t\tactionContext.evalResults,\n\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t? \"Evaluations for this AI call\"\n\t\t\t\t\t\t\t\t: \"Trace-level evaluations for this AI call\",\n\t\t\t\t\t\t\tmetadataForSignalActions(actionContext, \"AI call\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\tactionContext.agentRuns.length > 0\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tlabel:\n\t\t\t\t\t\t\t\t\t\tactionContext.matchLevel === \"span\"\n\t\t\t\t\t\t\t\t\t\t\t? \"Agent runs for this AI call\"\n\t\t\t\t\t\t\t\t\t\t\t: \"Trace-level agent runs for this AI call\",\n\t\t\t\t\t\t\t\t\tlinks: actionContext.agentRuns\n\t\t\t\t\t\t\t\t\t\t.slice(0, MAX_LINKS_INLINE)\n\t\t\t\t\t\t\t\t\t\t.map((run) => ({\n\t\t\t\t\t\t\t\t\t\t\t...linkToAgentRun(\n\t\t\t\t\t\t\t\t\t\t\t\trun.id,\n\t\t\t\t\t\t\t\t\t\t\t\t`${run.agentName} (v${run.agentVersion})`,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t...actionContextLinkMetadata(actionContext, \"AI call\"),\n\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tlabel: \"Agent runs for this AI call\",\n\t\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\t\temptyReason: actionMatchEmptyReason(actionContext),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tconst sessionId =\n\t\t\t\t\tc.req.query(\"session_id\") ?? callRow?.session_id ?? undefined;\n\t\t\t\tif (sessionId) {\n\t\t\t\t\tmanifest.across.push({\n\t\t\t\t\t\tlabel: \"Session\",\n\t\t\t\t\t\tlinks: [linkToSession(sessionId)],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (kind === \"user\") {\n\t\t\t\t// RFC 0006 Scenario B — pivot from a user. Loads the user's\n\t\t\t\t// most recent sessions and surfaces top-line activity in\n\t\t\t\t// `across`. The \"first\" session is the canonical \"latest\n\t\t\t\t// session\" link used by the AI-cost-spike walkthrough.\n\t\t\t\tconst userManifest = await index.byUser(projectId, id, {\n\t\t\t\t\tsessions: 5,\n\t\t\t\t\tlimit: 50,\n\t\t\t\t});\n\t\t\t\tconst recentSessions = Array.from(\n\t\t\t\t\tnew Set(\n\t\t\t\t\t\tuserManifest.usageEvents\n\t\t\t\t\t\t\t.map((e) => e.sessionId)\n\t\t\t\t\t\t\t.filter((s): s is string => Boolean(s)),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tmanifest.up = [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"User\",\n\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\temptyReason: \"User is the root identity — no parent context above.\",\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t\tif (recentSessions.length > 0) {\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Latest session\",\n\t\t\t\t\t\t\tlinks: [linkToSession(recentSessions[0])],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Recent sessions\",\n\t\t\t\t\t\t\tlinks: recentSessions\n\t\t\t\t\t\t\t\t.slice(0, MAX_LINKS_INLINE)\n\t\t\t\t\t\t\t\t.map((sid) => linkToSession(sid)),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tlinksFromSpans(userManifest.spans, \"Recent traces\"),\n\t\t\t\t\t\tlinksFromAi(userManifest.aiCalls, \"Recent AI calls\"),\n\t\t\t\t\t];\n\t\t\t\t} else {\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Sessions\",\n\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\"No sessions found for this user. user_profiles needs a visitor_id, and that visitor needs at least one usage_event with a session_id.\",\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tif (userManifest.replay) {\n\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Replay\",\n\t\t\t\t\t\t\tlinks: [linkToSession(userManifest.replay.sessionId)],\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t} else if (kind === \"action\") {\n\t\t\t\tconst actionManifest = await index.byAction(projectId, id);\n\t\t\t\tconst action = actionManifest.actions.find((a) => a.id === id);\n\t\t\t\tif (action) {\n\t\t\t\t\tmanifest.up = [];\n\t\t\t\t\tif (action.causedByActionId) {\n\t\t\t\t\t\tmanifest.up.push({\n\t\t\t\t\t\t\tlabel: \"Parent Action\",\n\t\t\t\t\t\t\tlinks: [linkToAction(action.causedByActionId)],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (action.agentRunId) {\n\t\t\t\t\t\tmanifest.up.push({\n\t\t\t\t\t\t\tlabel: \"Agent Run\",\n\t\t\t\t\t\t\tlinks: [linkToAgentRun(action.agentRunId)],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (manifest.up.length === 0) {\n\t\t\t\t\t\tmanifest.up.push({\n\t\t\t\t\t\t\tlabel: \"Up\",\n\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\t\"No parent context: this action is the root of its execution tree.\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\tlinksFromActions(\n\t\t\t\t\t\t\tactionManifest.actions.filter(\n\t\t\t\t\t\t\t\t(a) =>\n\t\t\t\t\t\t\t\t\ta.id !== id && a.causedByActionId === action.causedByActionId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\"Sibling Actions\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromLogs(actionManifest.logs, \"Logs in this action context\"),\n\t\t\t\t\t\tlinksFromAi(actionManifest.aiCalls, \"AI Calls in this action\"),\n\t\t\t\t\t];\n\n\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\tlinksFromActions(\n\t\t\t\t\t\t\tactionManifest.actions.filter((a) => a.causedByActionId === id),\n\t\t\t\t\t\t\t\"Sub-actions\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromToolCalls(\n\t\t\t\t\t\t\tactionManifest.toolCalls.filter((t) => t.actionId === id),\n\t\t\t\t\t\t\t\"Tool Calls\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromRetrievalEvents(\n\t\t\t\t\t\t\tactionManifest.retrievalEvents.filter((r) => r.actionId === id),\n\t\t\t\t\t\t\t\"Retrievals\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromEvalResults(\n\t\t\t\t\t\t\tactionManifest.evalResults.filter((e) => e.actionId === id),\n\t\t\t\t\t\t\t\"Evaluations\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromArtifacts(\n\t\t\t\t\t\t\tactionManifest.artifacts.filter((a) => a.actionId === id),\n\t\t\t\t\t\t\t\"Artifacts\",\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\n\t\t\t\t\tif (action.traceId) {\n\t\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"OTel Trace\",\n\t\t\t\t\t\t\t\tlinks: [linkToTrace(action.traceId)],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\t\t\t\t\tmanifest.rawManifest = actionManifest;\n\t\t\t\t}\n\t\t\t} else if (kind === \"agent_run\") {\n\t\t\t\tconst runManifest = await index.byAgentRun(projectId, id);\n\t\t\t\tconst run = runManifest.agentRuns.find((r) => r.id === id);\n\t\t\t\tif (run) {\n\t\t\t\t\tmanifest.up = [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Agent\",\n\t\t\t\t\t\t\tlinks: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tlabel: `${run.agentName} (v${run.agentVersion})`,\n\t\t\t\t\t\t\t\t\thref: `#/agents/${run.agentId}`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\n\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\tlinksFromSpans(runManifest.spans, \"Traces triggered by this run\"),\n\t\t\t\t\t\tlinksFromAi(runManifest.aiCalls, \"AI Calls in this run\"),\n\t\t\t\t\t];\n\n\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\tlinksFromActions(\n\t\t\t\t\t\t\trunManifest.actions.filter((a) => a.rootActionId === id),\n\t\t\t\t\t\t\t\"Actions (Decision Spine)\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlinksFromToolCalls(runManifest.toolCalls, \"Tool Calls Executed\"),\n\t\t\t\t\t];\n\n\t\t\t\t\tif (runManifest.replay) {\n\t\t\t\t\t\tmanifest.related = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"User Session\",\n\t\t\t\t\t\t\t\tlinks: [linkToSession(runManifest.replay.sessionId)],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\t\t\t\t\tmanifest.rawManifest = runManifest;\n\t\t\t\t}\n\t\t\t} else if (kind === \"tool_call\") {\n\t\t\t\tconst db = sqlDbFor(c.env);\n\t\t\t\tconst toolCallRow = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT action_id, tool_name FROM tool_calls WHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, id)\n\t\t\t\t\t.first<{ action_id: string; tool_name: string }>();\n\n\t\t\t\tif (toolCallRow) {\n\t\t\t\t\tconst actionManifest = await index.byAction(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\ttoolCallRow.action_id,\n\t\t\t\t\t);\n\t\t\t\t\tconst toolCall = actionManifest.toolCalls.find((t) => t.id === id);\n\t\t\t\t\tif (toolCall) {\n\t\t\t\t\t\tmanifest.up = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"Causal Action\",\n\t\t\t\t\t\t\t\tlinks: [linkToAction(toolCall.actionId)],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\n\t\t\t\t\t\tmanifest.across = [\n\t\t\t\t\t\t\tlinksFromToolCalls(\n\t\t\t\t\t\t\t\tactionManifest.toolCalls.filter((t) => t.id !== id),\n\t\t\t\t\t\t\t\t\"Other tool calls in this action\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t];\n\n\t\t\t\t\t\tmanifest.down = [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: \"Tool Details\",\n\t\t\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\t\t\temptyReason: `Tool: ${toolCall.toolName} (hash: ${toolCall.argsHash.slice(0, 8)})`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t\tmanifest.rawManifest = actionManifest;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (kind === \"alert\" || kind === \"analysis\") {\n\t\t\t\t// Alerts and Analyses are topic-related, not identity-related.\n\t\t\t\t// Their connections come from the alert_rules.analysis_id and\n\t\t\t\t// analysis_results join, not from the identity graph.\n\t\t\t\t// For now, return empty-explanatory sections. A follow-up\n\t\t\t\t// can route through AlertsStore + AnalysesStore for the\n\t\t\t\t// topic links.\n\t\t\t\tmanifest.related = [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Topic neighbors\",\n\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\"Alert/Analysis topic links are surfaced inside their detail views directly — the connected rail focuses on identity-graph neighbors here.\",\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\n\t\t\t// Always at least set placeholder labels so the rail renders\n\t\t\t// section headers consistently across kinds.\n\t\t\tif (manifest.up.length === 0) {\n\t\t\t\tmanifest.up = [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Up\",\n\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\temptyReason: \"No parent context for this entity.\",\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t\tif (manifest.across.length === 0) {\n\t\t\t\tmanifest.across = [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Across\",\n\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\temptyReason: \"No identity-graph peers under this entity.\",\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t\tif (manifest.down.length === 0) {\n\t\t\t\tmanifest.down = [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Down\",\n\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\temptyReason:\n\t\t\t\t\t\t\t\"No child entities yet (profiles + kernel events arrive with later RFCs).\",\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t\tif (manifest.related.length === 0) {\n\t\t\t\tmanifest.related = [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Related\",\n\t\t\t\t\t\tlinks: [],\n\t\t\t\t\t\temptyReason: \"No topic neighbors found.\",\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\n\t\t\treturn c.json(manifest);\n\t\t});\n\t},\n};\n","import type {\n\tActionRef,\n\tAICallRef,\n\tArtifactRef,\n\tEntityManifestExtended,\n\tEvalResultRef,\n\tLogRef,\n\tMetricExemplarRef,\n\tRetrievalEventRef,\n\tSpanRef,\n\tToolCallRef,\n\tUsageEventRef,\n} from \"../../lib/identity-index\";\nimport type { CausalConfidence } from \"../../lib/identity-index/types\";\nimport type { SqlDb } from \"../../lib/sql-db\";\n\nexport type ConnectedEntityKind =\n\t| \"span\"\n\t| \"profile\"\n\t| \"log\"\n\t| \"usage\"\n\t| \"ai_call\"\n\t| \"replay\"\n\t| \"alert\"\n\t| \"analysis\"\n\t| \"user\"\n\t| \"action\"\n\t| \"agent_run\"\n\t| \"tool_call\";\n\nexport const KNOWN_KINDS: ReadonlySet<string> = new Set<ConnectedEntityKind>([\n\t\"span\",\n\t\"profile\",\n\t\"log\",\n\t\"usage\",\n\t\"ai_call\",\n\t\"replay\",\n\t\"alert\",\n\t\"analysis\",\n\t\"user\",\n\t\"action\",\n\t\"agent_run\",\n\t\"tool_call\",\n]);\n\nexport interface ConnectedLink {\n\tlabel: string;\n\thref: string;\n\tcount?: number;\n\tsample?: string;\n\tentityKind?: ConnectedEntityKind | \"trace\" | \"eval\";\n\tentityId?: string;\n\tsource?: string;\n\tconfidence?: number;\n\treason?: string;\n\tcausalConfidence?: CausalConfidence;\n}\n\nexport interface ConnectedSection {\n\tlabel: string;\n\tlinks: ConnectedLink[];\n\temptyReason?: string;\n}\n\nexport interface ConnectedManifest {\n\tentity: { kind: ConnectedEntityKind; id: string; projectId: string };\n\tup: ConnectedSection[];\n\tacross: ConnectedSection[];\n\tdown: ConnectedSection[];\n\trelated: ConnectedSection[];\n\trawManifest?: EntityManifestExtended;\n}\n\nexport const MAX_LINKS_INLINE = 5;\n\nconst truncate = (s: string, n = 80): string =>\n\ts.length > n ? `${s.slice(0, n - 1)}…` : s;\n\nexport const linkToTrace = (\n\ttraceId: string,\n\tlabel?: string,\n): ConnectedLink => ({\n\tlabel: label ?? `trace ${traceId.slice(0, 12)}`,\n\thref: `#/traces/${traceId}`,\n\tentityKind: \"trace\",\n\tentityId: traceId,\n});\n\n// Show the LAST 12 characters of the session id. ULIDs / UUIDs have most\n// of their entropy in the tail; the prefix is timestamp- or cohort-shared\n// across sessions in the same window. Slicing the head means every link\n// in a busy session looks identical (\"session seed-mp27eaj\" × 4).\nexport const linkToSession = (sessionId: string): ConnectedLink => ({\n\tlabel:\n\t\tsessionId.length > 12\n\t\t\t? `session …${sessionId.slice(-12)}`\n\t\t\t: `session ${sessionId}`,\n\thref: `#/replay?session=${encodeURIComponent(sessionId)}`,\n\tsample: sessionId,\n\tentityKind: \"replay\",\n\tentityId: sessionId,\n});\n\nexport const linksFromSpans = (\n\tspans: SpanRef[],\n\tprefix: string,\n): ConnectedSection => {\n\tif (spans.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No spans matched.\",\n\t\t};\n\t}\n\tif (spans.length > MAX_LINKS_INLINE) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `${spans.length} spans`,\n\t\t\t\t\thref: `#/traces?q=${encodeURIComponent(spans[0].traceId)}`,\n\t\t\t\t\tcount: spans.length,\n\t\t\t\t\tsample: truncate(\n\t\t\t\t\t\t`${spans[0].serviceName ?? \"?\"} · ${spans[0].spanName}`,\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: spans.map((s) => ({\n\t\t\tlabel: `${s.serviceName ?? \"?\"} · ${truncate(s.spanName, 40)}`,\n\t\t\thref: `#/traces/${s.traceId}#span=${s.spanId}`,\n\t\t})),\n\t};\n};\n\nexport const linksFromLogs = (\n\tlogs: LogRef[],\n\tprefix: string,\n): ConnectedSection => {\n\tif (logs.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No logs share this identity key.\",\n\t\t};\n\t}\n\tif (logs.length > MAX_LINKS_INLINE) {\n\t\tconst sample = logs[0];\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `${logs.length} logs`,\n\t\t\t\t\thref: `#/logs?q=${encodeURIComponent(sample.traceId ?? \"\")}`,\n\t\t\t\t\tcount: logs.length,\n\t\t\t\t\tsample: truncate(sample.message),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: logs.map((l) => ({\n\t\t\tlabel: `[${l.severity}] ${truncate(l.message, 60)}`,\n\t\t\thref: `#/logs?id=${l.logId}`,\n\t\t})),\n\t};\n};\n\nexport const linksFromUsage = (\n\tevents: UsageEventRef[],\n\tprefix: string,\n): ConnectedSection => {\n\tif (events.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No usage events share this identity key.\",\n\t\t};\n\t}\n\tif (events.length > MAX_LINKS_INLINE) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `${events.length} usage events`,\n\t\t\t\t\thref: `#/usage`,\n\t\t\t\t\tcount: events.length,\n\t\t\t\t\tsample: truncate(`${events[0].eventType} · ${events[0].eventName}`),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: events.map((e) => ({\n\t\t\tlabel: `${e.eventType} · ${truncate(e.eventName, 50)}`,\n\t\t\thref: `#/usage?id=${e.eventId}`,\n\t\t})),\n\t};\n};\n\nexport const linksFromMetricExemplars = (\n\texemplars: MetricExemplarRef[],\n\tprefix: string,\n): ConnectedSection => {\n\tif (exemplars.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No metric exemplars share this trace.\",\n\t\t};\n\t}\n\tif (exemplars.length > MAX_LINKS_INLINE) {\n\t\tconst sample = exemplars[0];\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `${exemplars.length} metric exemplars`,\n\t\t\t\t\thref: sample.traceId\n\t\t\t\t\t\t? `#/traces/${sample.traceId}`\n\t\t\t\t\t\t: `#/traces?q=${encodeURIComponent(sample.metricName)}`,\n\t\t\t\t\tcount: exemplars.length,\n\t\t\t\t\tsample: truncate(\n\t\t\t\t\t\t`${sample.serviceName ?? \"?\"} · ${sample.metricName}=${sample.value}`,\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: exemplars.map((e) => ({\n\t\t\tlabel: `${e.serviceName ?? \"?\"} · ${truncate(e.metricName, 40)}=${e.value}`,\n\t\t\thref: e.traceId\n\t\t\t\t? e.spanId\n\t\t\t\t\t? `#/traces/${e.traceId}#span=${e.spanId}`\n\t\t\t\t\t: `#/traces/${e.traceId}`\n\t\t\t\t: `#/traces?q=${encodeURIComponent(e.metricName)}`,\n\t\t\tsample: e.tsNs,\n\t\t})),\n\t};\n};\n\n/**\n * RFC 0009 acceptance #5 — query profile_blobs joined with\n * profile_trace_index to find profiles covering a trace, group by\n * profile_type so CPU and off-CPU render as distinct sections.\n * Returns a list of ConnectedSections (one per profile_type) for the\n * Down field of a span manifest.\n */\nexport const profileLinksForTrace = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\ttraceId: string,\n): Promise<ConnectedSection[]> => {\n\tconst rows = await db\n\t\t.prepare(\n\t\t\t`SELECT b.id, b.service_name, b.profile_type, b.duration_ms\n\t\t\t FROM profile_trace_index i\n\t\t\t JOIN profile_blobs b ON b.id = i.profile_id\n\t\t\t WHERE i.project_id = ? AND i.trace_id = ?\n\t\t\t ORDER BY b.end_ts DESC LIMIT 50`,\n\t\t)\n\t\t.bind(projectId, traceId)\n\t\t.all<{\n\t\t\tid: string;\n\t\t\tservice_name: string | null;\n\t\t\tprofile_type: string;\n\t\t\tduration_ms: number;\n\t\t}>();\n\n\tif (rows.results.length === 0) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tlabel: \"Profiles\",\n\t\t\t\tlinks: [],\n\t\t\t\temptyReason:\n\t\t\t\t\t\"No pprof profile covers this trace's window. Wire @obsunified/telemetry-sdk's startProfiler() (or run an eBPF agent) on the producing service to populate.\",\n\t\t\t},\n\t\t];\n\t}\n\n\t// Group by profile_type so CPU and off-CPU surface as distinct rows.\n\tconst byType = new Map<string, typeof rows.results>();\n\tfor (const row of rows.results) {\n\t\tconst list = byType.get(row.profile_type) ?? [];\n\t\tlist.push(row);\n\t\tbyType.set(row.profile_type, list);\n\t}\n\n\tconst sections: ConnectedSection[] = [];\n\tfor (const [type, list] of byType) {\n\t\tconst icon = type === \"offcpu\" ? \"🌊\" : \"🔥\";\n\t\tsections.push({\n\t\t\tlabel: `${icon} ${type === \"offcpu\" ? \"Off-CPU profiles\" : `${type[0].toUpperCase()}${type.slice(1)} profiles`}`,\n\t\t\tlinks: list.map((r) => ({\n\t\t\t\tlabel: `${r.service_name ?? \"?\"} · ${r.duration_ms}ms`,\n\t\t\t\thref: `#/profiles/${r.id}?trace_id=${encodeURIComponent(traceId)}`,\n\t\t\t})),\n\t\t});\n\t}\n\treturn sections;\n};\n\nexport const linksFromAi = (\n\tcalls: AICallRef[],\n\tprefix: string,\n): ConnectedSection => {\n\tif (calls.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No AI calls under this identity key.\",\n\t\t};\n\t}\n\tif (calls.length > MAX_LINKS_INLINE) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `${calls.length} AI calls`,\n\t\t\t\t\thref: `#/ai`,\n\t\t\t\t\tcount: calls.length,\n\t\t\t\t\tsample: truncate(`${calls[0].provider} · ${calls[0].modelName}`),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: calls.map((c) => ({\n\t\t\tlabel: `${c.provider} · ${c.modelName}`,\n\t\t\thref: `#/ai?id=${c.callId}`,\n\t\t})),\n\t};\n};\n\nexport const linkToAction = (\n\tactionId: string,\n\tlabel?: string,\n): ConnectedLink => ({\n\tlabel: label ?? `action ${actionId.slice(0, 12)}`,\n\thref: `#/actions/${actionId}`,\n\tentityKind: \"action\",\n\tentityId: actionId,\n});\n\nexport const linkToAgentRun = (\n\trunId: string,\n\tlabel?: string,\n): ConnectedLink => ({\n\tlabel: label ?? `agent run ${runId.slice(0, 12)}`,\n\thref: `#/agent-runs/${runId}`,\n\tentityKind: \"agent_run\",\n\tentityId: runId,\n});\n\nexport interface ActionContextLinkMetadata {\n\tsource: string;\n\tcausalConfidence?: CausalConfidence;\n\tconfidence?: number;\n\treason: string;\n}\n\nconst actionContextMetadata = (\n\taction: Pick<ActionRef, \"causalConfidence\">,\n\tmetadata?: ActionContextLinkMetadata,\n): Pick<\n\tConnectedLink,\n\t\"source\" | \"confidence\" | \"reason\" | \"causalConfidence\"\n> => ({\n\tsource: metadata?.source,\n\tconfidence: metadata?.confidence,\n\treason: metadata?.reason,\n\tcausalConfidence: metadata?.causalConfidence ?? action.causalConfidence,\n});\n\nexport const linksFromActions = (\n\tactions: ActionRef[],\n\tprefix: string,\n\tmetadata?: ActionContextLinkMetadata,\n): ConnectedSection => {\n\tif (actions.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No actions matched.\",\n\t\t};\n\t}\n\tif (actions.length > MAX_LINKS_INLINE) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `${actions.length} actions`,\n\t\t\t\t\thref: `#/actions`,\n\t\t\t\t\tcount: actions.length,\n\t\t\t\t\tsample: truncate(\n\t\t\t\t\t\t`${actions[0].actionKind} · ${actions[0].name ?? \"unnamed\"}`,\n\t\t\t\t\t),\n\t\t\t\t\tentityKind: \"action\",\n\t\t\t\t\tentityId: actions[0].id,\n\t\t\t\t\t...actionContextMetadata(actions[0], metadata),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: actions.map((a) => ({\n\t\t\tlabel: `[${a.actionKind}] ${truncate(a.name ?? \"unnamed\", 40)}`,\n\t\t\thref: `#/actions/${a.id}`,\n\t\t\tentityKind: \"action\",\n\t\t\tentityId: a.id,\n\t\t\t...actionContextMetadata(a, metadata),\n\t\t})),\n\t};\n};\n\nexport const linksFromToolCalls = (\n\tcalls: ToolCallRef[],\n\tprefix: string,\n\tmetadataForAction?: (\n\t\tactionId: string,\n\t) => ActionContextLinkMetadata | undefined,\n): ConnectedSection => {\n\tif (calls.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No tool calls matched.\",\n\t\t};\n\t}\n\tif (calls.length > MAX_LINKS_INLINE) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `${calls.length} tool calls`,\n\t\t\t\t\thref: `#/tools`,\n\t\t\t\t\tcount: calls.length,\n\t\t\t\t\tsample: truncate(calls[0].toolName),\n\t\t\t\t\tentityKind: \"tool_call\",\n\t\t\t\t\tentityId: calls[0].id,\n\t\t\t\t\t...metadataForAction?.(calls[0].actionId),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: calls.map((t) => ({\n\t\t\tlabel: `tool: ${t.toolName}`,\n\t\t\thref: `#/tool-calls/${t.id}`,\n\t\t\tentityKind: \"tool_call\",\n\t\t\tentityId: t.id,\n\t\t\t...metadataForAction?.(t.actionId),\n\t\t})),\n\t};\n};\n\nexport const linksFromRetrievalEvents = (\n\tevents: RetrievalEventRef[],\n\tprefix: string,\n): ConnectedSection => {\n\tif (events.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No retrievals matched.\",\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: events.map((r) => ({\n\t\t\tlabel: `retrieve: ${r.retrieverName} (${r.totalResults} docs)`,\n\t\t\thref: `#/retrieval-events/${r.id}`,\n\t\t})),\n\t};\n};\n\nexport const linksFromEvalResults = (\n\tresults: EvalResultRef[],\n\tprefix: string,\n\tmetadataForAction?: (\n\t\tactionId: string,\n\t) => ActionContextLinkMetadata | undefined,\n): ConnectedSection => {\n\tif (results.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No evaluations matched.\",\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: results.map((e) => ({\n\t\t\tlabel: `eval: ${e.evaluatorName} (${e.passed ? \"passed\" : \"failed\"})`,\n\t\t\thref: `#/evals/${e.id}`,\n\t\t\tentityKind: \"eval\",\n\t\t\tentityId: e.id,\n\t\t\t...metadataForAction?.(e.actionId),\n\t\t})),\n\t};\n};\n\nexport const linksFromArtifacts = (\n\tarts: ArtifactRef[],\n\tprefix: string,\n): ConnectedSection => {\n\tif (arts.length === 0) {\n\t\treturn {\n\t\t\tlabel: prefix,\n\t\t\tlinks: [],\n\t\t\temptyReason: \"No artifacts matched.\",\n\t\t};\n\t}\n\treturn {\n\t\tlabel: prefix,\n\t\tlinks: arts.map((a) => ({\n\t\t\tlabel: `artifact: ${a.artifactName} (${a.artifactType})`,\n\t\t\thref: `#/artifacts/${a.id}`,\n\t\t})),\n\t};\n};\n","import type { CollectorPlugin } from \"../framework/collector\";\n\n/**\n * Serves the dashboard SPA.\n *\n * For Cloudflare Workers: configure [assets] in wrangler.toml pointing to\n * the @obsunified/dashboard build output. The Workers runtime handles static file\n * serving automatically; this plugin provides the fallback route for SPA\n * client-side routing.\n *\n * For Node.js / other runtimes: serve static files from @obsunified/dashboard/dist\n * using your framework's static file middleware, then mount this plugin for\n * the SPA fallback.\n */\nexport const dashboardRoutesPlugin: CollectorPlugin = {\n\tname: \"dashboard-routes\",\n\tregister(app) {\n\t\t// SPA fallback: any /dashboard/* route that doesn't match a static file\n\t\t// should serve the dashboard index.html\n\t\tapp.get(\"/dashboard/*\", async (c) => {\n\t\t\t// In CF Workers with [assets], the runtime serves static files before\n\t\t\t// hitting this route. If we get here under Workers with ASSETS, we can\n\t\t\t// fetch and return `/dashboard/` (which serves the index.html SPA entrypoint)\n\t\t\t// directly, preserving the client-side URL in the browser address bar.\n\t\t\tconst env = c.env as unknown as Record<string, unknown>;\n\t\t\tconst assets = env?.ASSETS as { fetch: typeof fetch } | undefined;\n\t\t\tif (assets && typeof assets.fetch === \"function\") {\n\t\t\t\tconst url = new URL(c.req.url);\n\t\t\t\turl.pathname = \"/dashboard/\";\n\t\t\t\treturn assets.fetch(new Request(url.toString(), c.req.raw));\n\t\t\t}\n\t\t\t// Fallback: redirects to SPA root\n\t\t\treturn c.redirect(\"/dashboard/\");\n\t\t});\n\n\t\t// Root redirect: visiting the collector root goes to dashboard\n\t\tapp.get(\"/\", (c) => {\n\t\t\treturn c.redirect(\"/dashboard/\");\n\t\t});\n\t},\n};\n","import type { JsonValue, StoredSpan } from \"@obsunified/types\";\nimport {\n\tINTERACTION_ID_KEY,\n\tSESSION_ID_KEY,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { parseJsonRecord } from \"../lib/json\";\n\nexport const defaultSpanEnrichmentPlugin: CollectorPlugin = {\n\tname: \"default-span-enrichment\",\n\tregister(_app, runtime) {\n\t\truntime.addSpanProcessor({\n\t\t\tname: \"default-span-enrichment\",\n\t\t\tprocess(spans) {\n\t\t\t\treturn spans.map((span): StoredSpan => {\n\t\t\t\t\tconst attributes = parseJsonRecord(span.attributesJson);\n\t\t\t\t\tconst resourceAttributes = parseJsonRecord(\n\t\t\t\t\t\tspan.resourceAttributesJson,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst method =\n\t\t\t\t\t\ttypeof attributes[\"http.request.method\"] === \"string\"\n\t\t\t\t\t\t\t? attributes[\"http.request.method\"]\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst path =\n\t\t\t\t\t\ttypeof attributes[\"url.path\"] === \"string\"\n\t\t\t\t\t\t\t? attributes[\"url.path\"]\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\tconst normalizedAttributes: Record<string, JsonValue> = {\n\t\t\t\t\t\t...attributes,\n\t\t\t\t\t\t\"collector.status_label\":\n\t\t\t\t\t\t\tspan.statusCode === 2\n\t\t\t\t\t\t\t\t? \"error\"\n\t\t\t\t\t\t\t\t: span.statusCode === 1\n\t\t\t\t\t\t\t\t\t? \"ok\"\n\t\t\t\t\t\t\t\t\t: \"unset\",\n\t\t\t\t\t\t\"collector.received_at\": span.receivedAt,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (method && path) {\n\t\t\t\t\t\tnormalizedAttributes[\"collector.route_label\"] = `${method} ${path}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst serviceName =\n\t\t\t\t\t\tspan.serviceName ||\n\t\t\t\t\t\t(typeof resourceAttributes[\"service.name\"] === \"string\"\n\t\t\t\t\t\t\t? resourceAttributes[\"service.name\"]\n\t\t\t\t\t\t\t: null) ||\n\t\t\t\t\t\t(typeof attributes[\"server.address\"] === \"string\"\n\t\t\t\t\t\t\t? attributes[\"server.address\"]\n\t\t\t\t\t\t\t: null);\n\n\t\t\t\t\tconst sessionId =\n\t\t\t\t\t\ttypeof attributes[SESSION_ID_KEY] === \"string\" &&\n\t\t\t\t\t\tattributes[SESSION_ID_KEY].length > 0\n\t\t\t\t\t\t\t? (attributes[SESSION_ID_KEY] as string)\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t// RFC 0004 — denormalize obs.interaction.id from attributes\n\t\t\t\t\t// to a top-level column. Stamped by @obsunified/telemetry-sdk's\n\t\t\t\t\t// stampInteractionFromRequest on the inbound request.\n\t\t\t\t\tconst interactionId =\n\t\t\t\t\t\ttypeof attributes[INTERACTION_ID_KEY] === \"string\" &&\n\t\t\t\t\t\tattributes[INTERACTION_ID_KEY].length > 0\n\t\t\t\t\t\t\t? (attributes[INTERACTION_ID_KEY] as string)\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t// RFC 0009 — denormalize telemetry.sdk.name from\n\t\t\t\t\t// resource_attributes. Beyla and other eBPF agents set\n\t\t\t\t\t// this to identify themselves; the service map's\n\t\t\t\t\t// source filter uses it to distinguish kernel-observed\n\t\t\t\t\t// edges from SDK-instrumented ones.\n\t\t\t\t\tconst telemetrySdkName =\n\t\t\t\t\t\ttypeof resourceAttributes[\"telemetry.sdk.name\"] === \"string\" &&\n\t\t\t\t\t\t(resourceAttributes[\"telemetry.sdk.name\"] as string).length > 0\n\t\t\t\t\t\t\t? (resourceAttributes[\"telemetry.sdk.name\"] as string)\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...span,\n\t\t\t\t\t\tserviceName,\n\t\t\t\t\t\tattributesJson: JSON.stringify(normalizedAttributes),\n\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\tinteractionId,\n\t\t\t\t\t\ttelemetrySdkName,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t},\n};\n","import type {\n\tEvidenceReference,\n\tEvidenceReferenceContract as EvidenceReferenceContractType,\n\tJsonValue,\n} from \"@obsunified/types\";\nimport { EVIDENCE_REFERENCE_CONTRACT } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport {\n\ttype EvalCase,\n\ttype EvalCaseInput,\n\tEvalCaseSourceNotFoundError,\n\ttype EvalCaseSourceType,\n\tEvalCasesStore,\n\ttype EvalRunInput,\n\tisEvalCaseSourceType,\n\tisEvalRunStatus,\n} from \"../lib/eval-cases-store\";\nimport { sourceLinkEvidenceReferences } from \"../lib/evidence-references\";\nimport { randomHex } from \"../lib/hash\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\ninterface EvalCaseRequestBody {\n\tsourceEntityType?: unknown;\n\tsourceEntityId?: unknown;\n\tsource?: {\n\t\ttype?: unknown;\n\t\tid?: unknown;\n\t\tagentRunId?: unknown;\n\t\tactionId?: unknown;\n\t\taiCallId?: unknown;\n\t\ttoolCallId?: unknown;\n\t\ttraceId?: unknown;\n\t\tspanId?: unknown;\n\t};\n\tname?: unknown;\n\texpectedOutcome?: unknown;\n\trubric?: JsonValue | null;\n\tredactedPrompt?: JsonValue | null;\n\treferencePayload?: JsonValue | null;\n\tmetadata?: unknown;\n}\n\ninterface EvalCaseResultResponse {\n\tid: string;\n\tprojectId: string;\n\tevalCaseId: string;\n\trunId: string;\n\tpassed: boolean;\n\tscore: number | null;\n\tactualOutcome: string | null;\n\tdetails: unknown;\n\tcreatedAt: string;\n\tevidenceReferences?: EvidenceReference[];\n\tevidenceContract?: EvidenceReferenceContractType;\n}\n\ninterface EvalRunRequestBody {\n\tid?: unknown;\n\trunId?: unknown;\n\tevalCaseId?: unknown;\n\tstatus?: unknown;\n\tcandidate?: unknown;\n\tstartedAt?: unknown;\n\tendedAt?: unknown;\n\ttotalCount?: unknown;\n\tpassCount?: unknown;\n\tfailCount?: unknown;\n\taverageScore?: unknown;\n\tmetadata?: unknown;\n}\n\nconst asOptionalString = (value: unknown): string | null => {\n\tif (value === undefined || value === null) return null;\n\treturn typeof value === \"string\" ? value : null;\n};\n\nconst asRecord = (value: unknown): Record<string, JsonValue> | null => {\n\tif (value === undefined || value === null) return {};\n\tif (typeof value !== \"object\" || Array.isArray(value)) return null;\n\treturn value as Record<string, JsonValue>;\n};\n\nconst asNonNegativeNumber = (value: unknown): number | undefined | null => {\n\tif (value === undefined) return undefined;\n\treturn typeof value === \"number\" && Number.isFinite(value) && value >= 0\n\t\t? value\n\t\t: null;\n};\n\nconst badRequest = (message: string) => ({\n\terror: \"Bad Request\",\n\tmessage,\n});\n\nconst parseLimit = (value: string | undefined): number => {\n\tconst parsed = Number.parseInt(value ?? \"50\", 10);\n\tif (!Number.isFinite(parsed)) return 50;\n\treturn Math.min(200, Math.max(1, parsed));\n};\n\nconst parseJsonMaybe = (value: unknown): unknown => {\n\tif (value === null || value === undefined) return null;\n\treturn typeof value === \"string\" ? JSON.parse(value) : value;\n};\n\nconst evalCaseResultEvidenceReferences = (\n\tevalCase: EvalCase,\n\tresultId: string,\n): EvidenceReference[] =>\n\tsourceLinkEvidenceReferences(\n\t\t{\n\t\t\tsourceLabel: `Eval case result \"${resultId}\"`,\n\t\t\tsourceId: resultId,\n\t\t\tsourceKind: \"eval_case_result\",\n\t\t\tsourceRoute: `#/evaluations?case=${encodeURIComponent(evalCase.id)}&result=${encodeURIComponent(resultId)}`,\n\t\t\tsourceName: evalCase.name,\n\t\t},\n\t\tevalCase,\n\t);\n\nexport const evalCasesRoutesPlugin: CollectorPlugin = {\n\tname: \"eval-cases-routes\",\n\tregister(app) {\n\t\tapp.post(\"/internal/eval-cases\", async (c) => {\n\t\t\tlet body: EvalCaseRequestBody;\n\t\t\ttry {\n\t\t\t\tbody = (await c.req.json()) as EvalCaseRequestBody;\n\t\t\t} catch {\n\t\t\t\treturn c.json(badRequest(\"body must be JSON\"), 400);\n\t\t\t}\n\n\t\t\tconst sourceType = body.sourceEntityType ?? body.source?.type;\n\t\t\tif (!isEvalCaseSourceType(sourceType)) {\n\t\t\t\treturn c.json(\n\t\t\t\t\tbadRequest(\n\t\t\t\t\t\t\"sourceEntityType must be one of: agent_run, action, ai_call, tool_call, trace\",\n\t\t\t\t\t),\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst sourceId = asOptionalString(\n\t\t\t\tbody.sourceEntityId ?? body.source?.id,\n\t\t\t)?.trim();\n\t\t\tif (!sourceId) {\n\t\t\t\treturn c.json(badRequest(\"sourceEntityId is required\"), 400);\n\t\t\t}\n\t\t\tconst name = asOptionalString(body.name)?.trim();\n\t\t\tif (!name) {\n\t\t\t\treturn c.json(badRequest(\"name is required\"), 400);\n\t\t\t}\n\t\t\tconst expectedOutcome = asOptionalString(body.expectedOutcome);\n\t\t\tif (\n\t\t\t\tbody.expectedOutcome !== undefined &&\n\t\t\t\tbody.expectedOutcome !== null &&\n\t\t\t\texpectedOutcome === null\n\t\t\t) {\n\t\t\t\treturn c.json(badRequest(\"expectedOutcome must be a string\"), 400);\n\t\t\t}\n\t\t\tconst metadata = asRecord(body.metadata);\n\t\t\tif (metadata === null) {\n\t\t\t\treturn c.json(badRequest(\"metadata must be a JSON object\"), 400);\n\t\t\t}\n\n\t\t\tconst input: EvalCaseInput = {\n\t\t\t\tsourceEntityType: sourceType,\n\t\t\t\tsourceEntityId: sourceId,\n\t\t\t\tname,\n\t\t\t\texpectedOutcome,\n\t\t\t\trubric: body.rubric ?? null,\n\t\t\t\tredactedPrompt: body.redactedPrompt ?? null,\n\t\t\t\treferencePayload: body.referencePayload ?? null,\n\t\t\t\tmetadata,\n\t\t\t\tsource: {\n\t\t\t\t\tsourceAgentRunId: asOptionalString(body.source?.agentRunId),\n\t\t\t\t\tsourceActionId: asOptionalString(body.source?.actionId),\n\t\t\t\t\tsourceAiCallId: asOptionalString(body.source?.aiCallId),\n\t\t\t\t\tsourceToolCallId: asOptionalString(body.source?.toolCallId),\n\t\t\t\t\tsourceTraceId: asOptionalString(body.source?.traceId),\n\t\t\t\t\tsourceSpanId: asOptionalString(body.source?.spanId),\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst store = new EvalCasesStore(sqlDbFor(c.env));\n\t\t\ttry {\n\t\t\t\tconst evalCase = await store.createCase(getProjectId(c), input);\n\t\t\t\treturn c.json({ evalCase }, 201);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof EvalCaseSourceNotFoundError) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror: \"Not Found\",\n\t\t\t\t\t\t\tmessage: err.message,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\treturn c.json(badRequest(message), 400);\n\t\t\t}\n\t\t});\n\n\t\tapp.get(\"/internal/eval-cases\", async (c) => {\n\t\t\tconst rawSourceType = c.req.query(\"sourceEntityType\");\n\t\t\tconst sourceEntityType =\n\t\t\t\trawSourceType === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: isEvalCaseSourceType(rawSourceType)\n\t\t\t\t\t\t? rawSourceType\n\t\t\t\t\t\t: null;\n\t\t\tif (sourceEntityType === null) {\n\t\t\t\treturn c.json(badRequest(\"sourceEntityType is invalid\"), 400);\n\t\t\t}\n\t\t\tconst store = new EvalCasesStore(sqlDbFor(c.env));\n\t\t\tconst evalCases = await store.listCases({\n\t\t\t\tprojectId: getProjectId(c),\n\t\t\t\tsourceEntityType: sourceEntityType as EvalCaseSourceType | undefined,\n\t\t\t\tsourceEntityId: c.req.query(\"sourceEntityId\"),\n\t\t\t\tlimit: parseLimit(c.req.query(\"limit\")),\n\t\t\t});\n\t\t\treturn c.json({ evalCases });\n\t\t});\n\n\t\tapp.get(\"/internal/eval-cases/:id\", async (c) => {\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) return c.json(badRequest(\"id is required\"), 400);\n\t\t\tconst store = new EvalCasesStore(sqlDbFor(c.env));\n\t\t\tconst evalCase = await store.getCase(getProjectId(c), id);\n\t\t\tif (!evalCase) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Eval case not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn c.json({ evalCase });\n\t\t});\n\n\t\tapp.post(\"/internal/eval-runs\", async (c) => {\n\t\t\tlet body: EvalRunRequestBody;\n\t\t\ttry {\n\t\t\t\tbody = (await c.req.json()) as EvalRunRequestBody;\n\t\t\t} catch {\n\t\t\t\treturn c.json(badRequest(\"body must be JSON\"), 400);\n\t\t\t}\n\n\t\t\tconst id = asOptionalString(body.id ?? body.runId)?.trim();\n\t\t\tif ((body.id ?? body.runId) !== undefined && !id) {\n\t\t\t\treturn c.json(badRequest(\"id must be a non-empty string\"), 400);\n\t\t\t}\n\t\t\tconst evalCaseId = asOptionalString(body.evalCaseId)?.trim() || null;\n\t\t\tif (\n\t\t\t\tbody.evalCaseId !== undefined &&\n\t\t\t\tbody.evalCaseId !== null &&\n\t\t\t\t!evalCaseId\n\t\t\t) {\n\t\t\t\treturn c.json(badRequest(\"evalCaseId must be a string\"), 400);\n\t\t\t}\n\t\t\tconst status = body.status ?? \"running\";\n\t\t\tif (!isEvalRunStatus(status)) {\n\t\t\t\treturn c.json(badRequest(\"status is invalid\"), 400);\n\t\t\t}\n\t\t\tconst metadata = asRecord(body.metadata);\n\t\t\tif (metadata === null) {\n\t\t\t\treturn c.json(badRequest(\"metadata must be a JSON object\"), 400);\n\t\t\t}\n\t\t\tconst candidate = asRecord(body.candidate);\n\t\t\tif (candidate === null) {\n\t\t\t\treturn c.json(badRequest(\"candidate must be a JSON object\"), 400);\n\t\t\t}\n\n\t\t\tconst totalCount = asNonNegativeNumber(body.totalCount);\n\t\t\tconst passCount = asNonNegativeNumber(body.passCount);\n\t\t\tconst failCount = asNonNegativeNumber(body.failCount);\n\t\t\tconst averageScore = asNonNegativeNumber(body.averageScore);\n\t\t\tif (totalCount === null) {\n\t\t\t\treturn c.json(\n\t\t\t\t\tbadRequest(\"totalCount must be a non-negative number\"),\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (passCount === null) {\n\t\t\t\treturn c.json(\n\t\t\t\t\tbadRequest(\"passCount must be a non-negative number\"),\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (failCount === null) {\n\t\t\t\treturn c.json(\n\t\t\t\t\tbadRequest(\"failCount must be a non-negative number\"),\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (averageScore === null && body.averageScore !== null) {\n\t\t\t\treturn c.json(\n\t\t\t\t\tbadRequest(\"averageScore must be a non-negative number\"),\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst input: EvalRunInput = {\n\t\t\t\tid: id ?? undefined,\n\t\t\t\tevalCaseId,\n\t\t\t\tstatus,\n\t\t\t\tcandidate: {\n\t\t\t\t\tagentId: asOptionalString(candidate.agentId),\n\t\t\t\t\tagentVersion: asOptionalString(candidate.agentVersion),\n\t\t\t\t\tpromptId: asOptionalString(candidate.promptId),\n\t\t\t\t\tpromptVersion: asOptionalString(candidate.promptVersion),\n\t\t\t\t\tmodelProvider: asOptionalString(candidate.modelProvider),\n\t\t\t\t\tmodel: asOptionalString(candidate.model),\n\t\t\t\t\tmodelVersion: asOptionalString(candidate.modelVersion),\n\t\t\t\t},\n\t\t\t\tstartedAt: asOptionalString(body.startedAt),\n\t\t\t\tendedAt: asOptionalString(body.endedAt),\n\t\t\t\ttotalCount: totalCount ?? undefined,\n\t\t\t\tpassCount: passCount ?? undefined,\n\t\t\t\tfailCount: failCount ?? undefined,\n\t\t\t\taverageScore: averageScore ?? null,\n\t\t\t\tmetadata,\n\t\t\t};\n\n\t\t\tconst store = new EvalCasesStore(sqlDbFor(c.env));\n\t\t\ttry {\n\t\t\t\tconst evalRun = await store.createRun(getProjectId(c), input);\n\t\t\t\treturn c.json({ evalRun }, 201);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\tif (message.includes(\"does not reference a case\")) {\n\t\t\t\t\treturn c.json({ error: \"Not Found\", message }, 404);\n\t\t\t\t}\n\t\t\t\treturn c.json(badRequest(message), 400);\n\t\t\t}\n\t\t});\n\n\t\tapp.get(\"/internal/eval-runs\", async (c) => {\n\t\t\tconst rawStatus = c.req.query(\"status\");\n\t\t\tconst status =\n\t\t\t\trawStatus === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: isEvalRunStatus(rawStatus)\n\t\t\t\t\t\t? rawStatus\n\t\t\t\t\t\t: null;\n\t\t\tif (status === null) {\n\t\t\t\treturn c.json(badRequest(\"status is invalid\"), 400);\n\t\t\t}\n\t\t\tconst store = new EvalCasesStore(sqlDbFor(c.env));\n\t\t\tconst evalRuns = await store.listRuns({\n\t\t\t\tprojectId: getProjectId(c),\n\t\t\t\tevalCaseId: c.req.query(\"evalCaseId\"),\n\t\t\t\tstatus,\n\t\t\t\tlimit: parseLimit(c.req.query(\"limit\")),\n\t\t\t});\n\t\t\treturn c.json({ evalRuns });\n\t\t});\n\n\t\tapp.get(\"/internal/eval-runs/:id\", async (c) => {\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tif (!id) return c.json(badRequest(\"id is required\"), 400);\n\t\t\tconst store = new EvalCasesStore(sqlDbFor(c.env));\n\t\t\tconst evalRun = await store.getRun(getProjectId(c), id);\n\t\t\tif (!evalRun) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Eval run not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn c.json({ evalRun });\n\t\t});\n\n\t\tapp.post(\"/internal/eval-cases/:id/results\", async (c) => {\n\t\t\tconst evalCaseId = c.req.param(\"id\");\n\t\t\tif (!evalCaseId) return c.json(badRequest(\"id is required\"), 400);\n\n\t\t\tlet body: {\n\t\t\t\trunId?: unknown;\n\t\t\t\tpassed?: unknown;\n\t\t\t\tscore?: unknown;\n\t\t\t\tactualOutcome?: unknown;\n\t\t\t\tdetails?: unknown;\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tbody = (await c.req.json()) as typeof body;\n\t\t\t} catch {\n\t\t\t\treturn c.json(badRequest(\"body must be JSON\"), 400);\n\t\t\t}\n\n\t\t\tif (body.passed === undefined || typeof body.passed !== \"boolean\") {\n\t\t\t\treturn c.json(badRequest(\"passed must be a boolean\"), 400);\n\t\t\t}\n\n\t\t\tconst db = sqlDbFor(c.env);\n\n\t\t\t// Verify case exists\n\t\t\tconst store = new EvalCasesStore(db);\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst evalCase = await store.getCase(getProjectId(c), evalCaseId);\n\t\t\tif (!evalCase) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Eval case not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst id = randomHex(16);\n\t\t\tconst runId =\n\t\t\t\ttypeof body.runId === \"string\" && body.runId.trim()\n\t\t\t\t\t? body.runId.trim()\n\t\t\t\t\t: `run_${randomHex(8)}`;\n\t\t\tconst evalRun = await store.getRun(projectId, runId);\n\t\t\tif (evalRun?.evalCaseId && evalRun.evalCaseId !== evalCaseId) {\n\t\t\t\treturn c.json(\n\t\t\t\t\tbadRequest(\"runId belongs to a different eval case\"),\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst passed = body.passed ? 1 : 0;\n\t\t\tconst score =\n\t\t\t\ttypeof body.score === \"number\" && Number.isFinite(body.score)\n\t\t\t\t\t? body.score\n\t\t\t\t\t: null;\n\t\t\tconst actualOutcome =\n\t\t\t\ttypeof body.actualOutcome === \"string\" ? body.actualOutcome : null;\n\t\t\tconst details_json =\n\t\t\t\tbody.details === undefined ? null : JSON.stringify(body.details);\n\t\t\tconst now = new Date().toISOString();\n\n\t\t\tawait db\n\t\t\t\t.prepare(\n\t\t\t\t\t`INSERT INTO eval_case_results (\n\t\t\t\t\tid, project_id, eval_case_id, run_id, passed, score, actual_outcome, details_json, created_at\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t\t)\n\t\t\t\t.bind(\n\t\t\t\t\tid,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tevalCaseId,\n\t\t\t\t\trunId,\n\t\t\t\t\tpassed,\n\t\t\t\t\tscore,\n\t\t\t\t\tactualOutcome,\n\t\t\t\t\tdetails_json,\n\t\t\t\t\tnow,\n\t\t\t\t)\n\t\t\t\t.run();\n\n\t\t\tif (evalRun) await store.refreshRunSummary(projectId, runId);\n\t\t\tconst refreshedRun = evalRun\n\t\t\t\t? await store.getRun(projectId, runId)\n\t\t\t\t: null;\n\t\t\tconst evalCaseResult: EvalCaseResultResponse = {\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t\tevalCaseId,\n\t\t\t\trunId,\n\t\t\t\tpassed: body.passed,\n\t\t\t\tscore,\n\t\t\t\tactualOutcome,\n\t\t\t\tdetails: body.details ?? null,\n\t\t\t\tcreatedAt: now,\n\t\t\t\tevidenceReferences: evalCaseResultEvidenceReferences(evalCase, id),\n\t\t\t\tevidenceContract: EVIDENCE_REFERENCE_CONTRACT,\n\t\t\t};\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tevalCaseResult,\n\t\t\t\t\tevalRun: refreshedRun,\n\t\t\t\t},\n\t\t\t\t201,\n\t\t\t);\n\t\t});\n\n\t\tapp.get(\"/internal/eval-cases/:id/results\", async (c) => {\n\t\t\tconst evalCaseId = c.req.param(\"id\");\n\t\t\tif (!evalCaseId) return c.json(badRequest(\"id is required\"), 400);\n\n\t\t\tconst db = sqlDbFor(c.env);\n\n\t\t\tconst rows = await db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM eval_case_results\n\t\t\t\tWHERE project_id = ? AND eval_case_id = ?\n\t\t\t\tORDER BY created_at DESC`,\n\t\t\t\t)\n\t\t\t\t.bind(getProjectId(c), evalCaseId)\n\t\t\t\t.all<{\n\t\t\t\t\tid: string;\n\t\t\t\t\tproject_id: string;\n\t\t\t\t\teval_case_id: string;\n\t\t\t\t\trun_id: string;\n\t\t\t\t\tpassed: number;\n\t\t\t\t\tscore: number | null;\n\t\t\t\t\tactual_outcome: string | null;\n\t\t\t\t\tdetails_json: string | null;\n\t\t\t\t\tcreated_at: string;\n\t\t\t\t}>();\n\n\t\t\tconst store = new EvalCasesStore(db);\n\t\t\tconst evalCase = await store.getCase(getProjectId(c), evalCaseId);\n\t\t\tif (!evalCase) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Eval case not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst evalCaseResults: EvalCaseResultResponse[] = rows.results.map(\n\t\t\t\t(row) => ({\n\t\t\t\t\tid: row.id,\n\t\t\t\t\tprojectId: row.project_id,\n\t\t\t\t\tevalCaseId: row.eval_case_id,\n\t\t\t\t\trunId: row.run_id,\n\t\t\t\t\tpassed: row.passed === 1,\n\t\t\t\t\tscore: row.score,\n\t\t\t\t\tactualOutcome: row.actual_outcome,\n\t\t\t\t\tdetails: parseJsonMaybe(row.details_json),\n\t\t\t\t\tcreatedAt: row.created_at,\n\t\t\t\t\tevidenceReferences: evalCaseResultEvidenceReferences(\n\t\t\t\t\t\tevalCase,\n\t\t\t\t\t\trow.id,\n\t\t\t\t\t),\n\t\t\t\t\tevidenceContract: EVIDENCE_REFERENCE_CONTRACT,\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\treturn c.json({ evalCaseResults });\n\t\t});\n\t},\n};\n","import type {\n\tEvidenceReference,\n\tEvidenceReferenceContract as EvidenceReferenceContractType,\n\tJsonValue,\n} from \"@obsunified/types\";\nimport { EVIDENCE_REFERENCE_CONTRACT } from \"@obsunified/types\";\nimport { sourceLinkEvidenceReferences } from \"./evidence-references\";\nimport { randomHex } from \"./hash\";\nimport { parseJsonArray, parseJsonValue } from \"./json\";\nimport type { SqlDb } from \"./sql-db\";\n\nexport type EvalCaseSourceType =\n\t| \"agent_run\"\n\t| \"action\"\n\t| \"ai_call\"\n\t| \"tool_call\"\n\t| \"trace\";\n\nexport interface EvalCaseSourceLinks {\n\tsourceAgentRunId?: string | null;\n\tsourceActionId?: string | null;\n\tsourceAiCallId?: string | null;\n\tsourceToolCallId?: string | null;\n\tsourceTraceId?: string | null;\n\tsourceSpanId?: string | null;\n}\n\nexport interface EvalCaseInput {\n\tsourceEntityType: EvalCaseSourceType;\n\tsourceEntityId: string;\n\tname: string;\n\texpectedOutcome?: string | null;\n\trubric?: JsonValue | null;\n\tredactedPrompt?: JsonValue | null;\n\treferencePayload?: JsonValue | null;\n\tmetadata?: Record<string, JsonValue>;\n\tsource?: EvalCaseSourceLinks;\n}\n\nexport interface EvalCase extends Required<EvalCaseSourceLinks> {\n\tid: string;\n\tprojectId: string;\n\tsourceEntityType: EvalCaseSourceType;\n\tsourceEntityId: string;\n\tname: string;\n\texpectedOutcome: string | null;\n\trubric: JsonValue | null;\n\tredactedPrompt: JsonValue | null;\n\treferencePayload: JsonValue | null;\n\tmetadata: Record<string, JsonValue>;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tevidenceReferences?: EvidenceReference[];\n\tevidenceContract?: EvidenceReferenceContractType;\n}\n\nexport interface EvalCaseListOptions {\n\tprojectId: string;\n\tsourceEntityType?: EvalCaseSourceType;\n\tsourceEntityId?: string;\n\tlimit?: number;\n}\n\nexport type EvalRunStatus =\n\t| \"pending\"\n\t| \"running\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"canceled\";\n\nexport interface EvalRunCandidate {\n\tagentId: string | null;\n\tagentVersion: string | null;\n\tpromptId: string | null;\n\tpromptVersion: string | null;\n\tmodelProvider: string | null;\n\tmodel: string | null;\n\tmodelVersion: string | null;\n}\n\nexport interface EvalRunSourceCase {\n\tid: string;\n\tname: string;\n\tsourceEntityType: string;\n\tsourceEntityId: string;\n\tsourceAgentRunId: string | null;\n\tsourceActionId: string | null;\n\tsourceAiCallId: string | null;\n\tsourceToolCallId: string | null;\n\tsourceTraceId: string | null;\n\tsourceSpanId: string | null;\n\tevidenceReferences?: EvidenceReference[];\n\tevidenceContract?: EvidenceReferenceContractType;\n}\n\nexport interface EvalRun {\n\tid: string;\n\tprojectId: string;\n\tevalCaseId: string | null;\n\tstatus: EvalRunStatus;\n\tcandidate: EvalRunCandidate;\n\tstartedAt: string | null;\n\tendedAt: string | null;\n\ttotalCount: number;\n\tpassCount: number;\n\tfailCount: number;\n\taverageScore: number | null;\n\tmetadata: Record<string, JsonValue>;\n\tcreatedAt: string;\n\tsourceEvalCase?: EvalRunSourceCase | null;\n\tevidenceReferences?: EvidenceReference[];\n\tevidenceContract?: EvidenceReferenceContractType;\n}\n\nexport interface EvalRunInput {\n\tid?: string;\n\tevalCaseId?: string | null;\n\tstatus?: EvalRunStatus;\n\tcandidate?: Partial<EvalRunCandidate>;\n\tstartedAt?: string | null;\n\tendedAt?: string | null;\n\ttotalCount?: number;\n\tpassCount?: number;\n\tfailCount?: number;\n\taverageScore?: number | null;\n\tmetadata?: Record<string, JsonValue>;\n}\n\nexport interface EvalRunsListOptions {\n\tprojectId: string;\n\tevalCaseId?: string;\n\tstatus?: EvalRunStatus;\n\tlimit?: number;\n}\n\ninterface EvalRunRow {\n\tid: string;\n\tproject_id: string;\n\teval_case_id: string | null;\n\tcandidate_agent_id: string | null;\n\tcandidate_agent_version: string | null;\n\tcandidate_prompt_id: string | null;\n\tcandidate_prompt_version: string | null;\n\tcandidate_model_provider: string | null;\n\tcandidate_model: string | null;\n\tcandidate_model_version: string | null;\n\tstatus: string;\n\tstarted_at: string | null;\n\tended_at: string | null;\n\ttotal_count: number;\n\tpass_count: number;\n\tfail_count: number;\n\taverage_score: number | null;\n\tmetadata_json: unknown;\n\tcreated_at: string;\n\tcase_id?: string | null;\n\tcase_name?: string | null;\n\tcase_source_entity_type?: string | null;\n\tcase_source_entity_id?: string | null;\n\tcase_source_agent_run_id?: string | null;\n\tcase_source_action_id?: string | null;\n\tcase_source_ai_call_id?: string | null;\n\tcase_source_tool_call_id?: string | null;\n\tcase_source_trace_id?: string | null;\n\tcase_source_span_id?: string | null;\n}\n\ninterface EvalCaseRow {\n\tid: string;\n\tproject_id: string;\n\tsource_entity_type: string;\n\tsource_entity_id: string;\n\tsource_agent_run_id: string | null;\n\tsource_action_id: string | null;\n\tsource_ai_call_id: string | null;\n\tsource_tool_call_id: string | null;\n\tsource_trace_id: string | null;\n\tsource_span_id: string | null;\n\tname: string;\n\texpected_outcome: string | null;\n\trubric_json: unknown;\n\tredacted_prompt_json: unknown;\n\treference_payload_json: unknown;\n\tmetadata_json: unknown;\n\tcreated_at: string;\n\tupdated_at: string;\n}\n\ninterface ActionSourceRow {\n\tid: string;\n\tagent_run_id: string | null;\n\ttool_call_id: string | null;\n\ttrace_id: string | null;\n\tspan_id: string | null;\n}\n\ninterface AiCallSourceRow {\n\tcall_id: string;\n\ttrace_id: string | null;\n\tspan_id: string | null;\n\trequest_json: unknown;\n\tresponse_json: unknown;\n}\n\ninterface ToolCallSourceRow {\n\tid: string;\n\taction_id: string | null;\n\ttool_name: string | null;\n\targs_hash: string | null;\n\tresult_hash: string | null;\n\tmcp_audit_json?: unknown;\n\tmutation_before_json?: unknown;\n\tmutation_after_json?: unknown;\n\tmutation_diff_json?: unknown;\n\tmutation_artifact_id?: string | null;\n}\n\ninterface SpanSourceRow {\n\ttrace_id: string;\n\tspan_id: string;\n}\n\ninterface PayloadRow {\n\tinput_json: unknown;\n\toutput_json: unknown;\n}\n\ninterface RetrievalEventRow {\n\tdocuments_json: unknown;\n}\n\nexport class EvalCaseSourceNotFoundError extends Error {\n\tconstructor(\n\t\treadonly projectId: string,\n\t\treadonly sourceEntityType: EvalCaseSourceType,\n\t\treadonly sourceEntityId: string,\n\t) {\n\t\tsuper(\n\t\t\t`Source ${sourceEntityType}:${sourceEntityId} not found in project ${projectId}`,\n\t\t);\n\t\tthis.name = \"EvalCaseSourceNotFoundError\";\n\t}\n}\n\nconst SOURCE_TYPES: EvalCaseSourceType[] = [\n\t\"agent_run\",\n\t\"action\",\n\t\"ai_call\",\n\t\"tool_call\",\n\t\"trace\",\n];\n\nconst EVAL_RUN_STATUSES: EvalRunStatus[] = [\n\t\"pending\",\n\t\"running\",\n\t\"completed\",\n\t\"failed\",\n\t\"canceled\",\n];\n\nexport const isEvalCaseSourceType = (\n\tvalue: unknown,\n): value is EvalCaseSourceType =>\n\ttypeof value === \"string\" &&\n\tSOURCE_TYPES.includes(value as EvalCaseSourceType);\n\nexport const isEvalRunStatus = (value: unknown): value is EvalRunStatus =>\n\ttypeof value === \"string\" &&\n\tEVAL_RUN_STATUSES.includes(value as EvalRunStatus);\n\nconst parseJsonField = (value: unknown): JsonValue | null => {\n\tif (value === null || value === undefined) return null;\n\tif (typeof value === \"string\") return parseJsonValue(value);\n\treturn value as JsonValue;\n};\n\nconst parseJsonRecordField = (value: unknown): Record<string, JsonValue> => {\n\tconst parsed = parseJsonField(value);\n\treturn parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n\t\t? (parsed as Record<string, JsonValue>)\n\t\t: {};\n};\n\nconst jsonString = (value: JsonValue | null | undefined): string | null =>\n\tvalue === undefined || value === null ? null : JSON.stringify(value);\n\nconst compactLinks = (\n\tlinks: EvalCaseSourceLinks,\n): Record<string, JsonValue> => {\n\tconst out: Record<string, JsonValue> = {};\n\tif (links.sourceAgentRunId) out.agentRunId = links.sourceAgentRunId;\n\tif (links.sourceActionId) out.actionId = links.sourceActionId;\n\tif (links.sourceAiCallId) out.aiCallId = links.sourceAiCallId;\n\tif (links.sourceToolCallId) out.toolCallId = links.sourceToolCallId;\n\tif (links.sourceTraceId) out.traceId = links.sourceTraceId;\n\tif (links.sourceSpanId) out.spanId = links.sourceSpanId;\n\treturn out;\n};\n\nconst clampLimit = (limit: number | undefined): number =>\n\tMath.min(\n\t\t200,\n\t\tMath.max(1, Number.isFinite(limit ?? NaN) ? (limit ?? 50) : 50),\n\t);\n\nconst nonNegativeInteger = (value: number | undefined): number => {\n\tif (value === undefined) return 0;\n\tif (!Number.isFinite(value) || value < 0) {\n\t\tthrow new Error(\"summary counters must be non-negative numbers\");\n\t}\n\treturn Math.floor(value);\n};\n\nconst optionalScore = (value: number | null | undefined): number | null => {\n\tif (value === undefined || value === null) return null;\n\tif (!Number.isFinite(value)) throw new Error(\"averageScore must be a number\");\n\treturn value;\n};\n\nconst evalCaseEvidenceReferences = (evalCase: EvalCase): EvidenceReference[] =>\n\tsourceLinkEvidenceReferences(\n\t\t{\n\t\t\tsourceLabel: `Eval case \"${evalCase.name}\"`,\n\t\t\tsourceId: evalCase.id,\n\t\t\tsourceKind: \"eval_case\",\n\t\t\tsourceRoute: `#/evaluations?case=${encodeURIComponent(evalCase.id)}`,\n\t\t\tsourceName: evalCase.name,\n\t\t},\n\t\tevalCase,\n\t);\n\nexport const rowToEvalCase = (row: EvalCaseRow): EvalCase => {\n\tconst evalCase: EvalCase = {\n\t\tid: row.id,\n\t\tprojectId: row.project_id,\n\t\tsourceEntityType: row.source_entity_type as EvalCaseSourceType,\n\t\tsourceEntityId: row.source_entity_id,\n\t\tsourceAgentRunId: row.source_agent_run_id ?? null,\n\t\tsourceActionId: row.source_action_id ?? null,\n\t\tsourceAiCallId: row.source_ai_call_id ?? null,\n\t\tsourceToolCallId: row.source_tool_call_id ?? null,\n\t\tsourceTraceId: row.source_trace_id ?? null,\n\t\tsourceSpanId: row.source_span_id ?? null,\n\t\tname: row.name,\n\t\texpectedOutcome: row.expected_outcome ?? null,\n\t\trubric: parseJsonField(row.rubric_json),\n\t\tredactedPrompt: parseJsonField(row.redacted_prompt_json),\n\t\treferencePayload: parseJsonField(row.reference_payload_json),\n\t\tmetadata: parseJsonRecordField(row.metadata_json),\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n\tevalCase.evidenceReferences = evalCaseEvidenceReferences(evalCase);\n\tevalCase.evidenceContract = EVIDENCE_REFERENCE_CONTRACT;\n\treturn evalCase;\n};\n\nconst evalRunEvidenceReferences = (run: EvalRun): EvidenceReference[] => {\n\tif (!run.sourceEvalCase) return [];\n\treturn sourceLinkEvidenceReferences(\n\t\t{\n\t\t\tsourceLabel: `Eval run \"${run.id}\"`,\n\t\t\tsourceId: run.id,\n\t\t\tsourceKind: \"eval_run\",\n\t\t\tsourceRoute: `#/evaluations?run=${encodeURIComponent(run.id)}`,\n\t\t\tsourceName: run.sourceEvalCase.name,\n\t\t},\n\t\trun.sourceEvalCase,\n\t);\n};\n\nconst rowToEvalRun = (row: EvalRunRow): EvalRun => {\n\tconst sourceEvalCase: EvalRunSourceCase | null =\n\t\trow.case_id && row.case_name\n\t\t\t? {\n\t\t\t\t\tid: row.case_id,\n\t\t\t\t\tname: row.case_name,\n\t\t\t\t\tsourceEntityType: row.case_source_entity_type ?? \"\",\n\t\t\t\t\tsourceEntityId: row.case_source_entity_id ?? \"\",\n\t\t\t\t\tsourceAgentRunId: row.case_source_agent_run_id ?? null,\n\t\t\t\t\tsourceActionId: row.case_source_action_id ?? null,\n\t\t\t\t\tsourceAiCallId: row.case_source_ai_call_id ?? null,\n\t\t\t\t\tsourceToolCallId: row.case_source_tool_call_id ?? null,\n\t\t\t\t\tsourceTraceId: row.case_source_trace_id ?? null,\n\t\t\t\t\tsourceSpanId: row.case_source_span_id ?? null,\n\t\t\t\t}\n\t\t\t: null;\n\tif (sourceEvalCase) {\n\t\tsourceEvalCase.evidenceReferences = sourceLinkEvidenceReferences(\n\t\t\t{\n\t\t\t\tsourceLabel: `Eval case \"${sourceEvalCase.name}\"`,\n\t\t\t\tsourceId: sourceEvalCase.id,\n\t\t\t\tsourceKind: \"eval_case\",\n\t\t\t\tsourceRoute: `#/evaluations?case=${encodeURIComponent(sourceEvalCase.id)}`,\n\t\t\t\tsourceName: sourceEvalCase.name,\n\t\t\t},\n\t\t\tsourceEvalCase,\n\t\t);\n\t\tsourceEvalCase.evidenceContract = EVIDENCE_REFERENCE_CONTRACT;\n\t}\n\n\tconst run: EvalRun = {\n\t\tid: row.id,\n\t\tprojectId: row.project_id,\n\t\tevalCaseId: row.eval_case_id ?? null,\n\t\tstatus: isEvalRunStatus(row.status) ? row.status : \"pending\",\n\t\tcandidate: {\n\t\t\tagentId: row.candidate_agent_id ?? null,\n\t\t\tagentVersion: row.candidate_agent_version ?? null,\n\t\t\tpromptId: row.candidate_prompt_id ?? null,\n\t\t\tpromptVersion: row.candidate_prompt_version ?? null,\n\t\t\tmodelProvider: row.candidate_model_provider ?? null,\n\t\t\tmodel: row.candidate_model ?? null,\n\t\t\tmodelVersion: row.candidate_model_version ?? null,\n\t\t},\n\t\tstartedAt: row.started_at ?? null,\n\t\tendedAt: row.ended_at ?? null,\n\t\ttotalCount: row.total_count ?? 0,\n\t\tpassCount: row.pass_count ?? 0,\n\t\tfailCount: row.fail_count ?? 0,\n\t\taverageScore: row.average_score ?? null,\n\t\tmetadata: parseJsonRecordField(row.metadata_json),\n\t\tcreatedAt: row.created_at,\n\t\tsourceEvalCase,\n\t};\n\trun.evidenceReferences = evalRunEvidenceReferences(run);\n\trun.evidenceContract = EVIDENCE_REFERENCE_CONTRACT;\n\treturn run;\n};\n\nexport class EvalCasesStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync createCase(projectId: string, input: EvalCaseInput): Promise<EvalCase> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"EvalCasesStore.createCase: projectId is required\");\n\t\tif (!isEvalCaseSourceType(input.sourceEntityType)) {\n\t\t\tthrow new Error(\"sourceEntityType is invalid\");\n\t\t}\n\t\tconst sourceEntityId = input.sourceEntityId.trim();\n\t\tif (!sourceEntityId) throw new Error(\"sourceEntityId is required\");\n\t\tconst name = input.name.trim();\n\t\tif (!name) throw new Error(\"name is required\");\n\n\t\tconst hydrated = await this.hydrateSource(\n\t\t\tprojectId,\n\t\t\tinput.sourceEntityType,\n\t\t\tsourceEntityId,\n\t\t\tinput.source ?? {},\n\t\t);\n\t\tconst payload = await this.findPayload(projectId, hydrated.links);\n\t\tconst autoMetadata = await this.buildMetadata(projectId, hydrated.links);\n\t\tconst metadata = {\n\t\t\t...(input.metadata ?? {}),\n\t\t\t...autoMetadata,\n\t\t\tsourceLinks: compactLinks(hydrated.links),\n\t\t};\n\t\tconst now = new Date().toISOString();\n\t\tconst evalCase: EvalCase = {\n\t\t\tid: randomHex(16),\n\t\t\tprojectId,\n\t\t\tsourceEntityType: input.sourceEntityType,\n\t\t\tsourceEntityId,\n\t\t\tsourceAgentRunId: hydrated.links.sourceAgentRunId ?? null,\n\t\t\tsourceActionId: hydrated.links.sourceActionId ?? null,\n\t\t\tsourceAiCallId: hydrated.links.sourceAiCallId ?? null,\n\t\t\tsourceToolCallId: hydrated.links.sourceToolCallId ?? null,\n\t\t\tsourceTraceId: hydrated.links.sourceTraceId ?? null,\n\t\t\tsourceSpanId: hydrated.links.sourceSpanId ?? null,\n\t\t\tname,\n\t\t\texpectedOutcome: input.expectedOutcome ?? null,\n\t\t\trubric: input.rubric ?? null,\n\t\t\tredactedPrompt: input.redactedPrompt ?? payload?.input ?? null,\n\t\t\treferencePayload: input.referencePayload ?? payload?.output ?? null,\n\t\t\tmetadata,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t};\n\t\tevalCase.evidenceReferences = evalCaseEvidenceReferences(evalCase);\n\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO eval_cases (\n\t\t\t\t\tid, project_id, source_entity_type, source_entity_id,\n\t\t\t\t\tsource_agent_run_id, source_action_id, source_ai_call_id,\n\t\t\t\t\tsource_tool_call_id, source_trace_id, source_span_id,\n\t\t\t\t\tname, expected_outcome, rubric_json, redacted_prompt_json,\n\t\t\t\t\treference_payload_json, metadata_json, created_at, updated_at\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\tevalCase.id,\n\t\t\t\tevalCase.projectId,\n\t\t\t\tevalCase.sourceEntityType,\n\t\t\t\tevalCase.sourceEntityId,\n\t\t\t\tevalCase.sourceAgentRunId,\n\t\t\t\tevalCase.sourceActionId,\n\t\t\t\tevalCase.sourceAiCallId,\n\t\t\t\tevalCase.sourceToolCallId,\n\t\t\t\tevalCase.sourceTraceId,\n\t\t\t\tevalCase.sourceSpanId,\n\t\t\t\tevalCase.name,\n\t\t\t\tevalCase.expectedOutcome,\n\t\t\t\tjsonString(evalCase.rubric),\n\t\t\t\tjsonString(evalCase.redactedPrompt),\n\t\t\t\tjsonString(evalCase.referencePayload),\n\t\t\t\tJSON.stringify(evalCase.metadata),\n\t\t\t\tevalCase.createdAt,\n\t\t\t\tevalCase.updatedAt,\n\t\t\t)\n\t\t\t.run();\n\n\t\treturn evalCase;\n\t}\n\n\tasync getCase(projectId: string, id: string): Promise<EvalCase | null> {\n\t\tconst row = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM eval_cases WHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, id)\n\t\t\t.first<EvalCaseRow>();\n\t\treturn row ? rowToEvalCase(row) : null;\n\t}\n\n\tasync listCases(options: EvalCaseListOptions): Promise<EvalCase[]> {\n\t\tif (!options.projectId)\n\t\t\tthrow new Error(\"EvalCasesStore.listCases: projectId is required\");\n\t\tconst limit = clampLimit(options.limit);\n\t\tlet sql = `SELECT * FROM eval_cases WHERE project_id = ?`;\n\t\tconst params: unknown[] = [options.projectId];\n\t\tif (options.sourceEntityType) {\n\t\t\tsql += ` AND source_entity_type = ?`;\n\t\t\tparams.push(options.sourceEntityType);\n\t\t}\n\t\tif (options.sourceEntityId) {\n\t\t\tsql += ` AND source_entity_id = ?`;\n\t\t\tparams.push(options.sourceEntityId);\n\t\t}\n\t\tsql += ` ORDER BY created_at DESC LIMIT ?`;\n\t\tparams.push(limit);\n\n\t\tconst rows = await this.db\n\t\t\t.prepare(sql)\n\t\t\t.bind(...params)\n\t\t\t.all<EvalCaseRow>();\n\t\treturn rows.results.map(rowToEvalCase);\n\t}\n\n\tasync createRun(projectId: string, input: EvalRunInput): Promise<EvalRun> {\n\t\tif (!projectId)\n\t\t\tthrow new Error(\"EvalCasesStore.createRun: projectId is required\");\n\t\tconst id = input.id?.trim() || `run_${randomHex(8)}`;\n\t\tconst evalCaseId = input.evalCaseId?.trim() || null;\n\t\tconst status = input.status ?? \"running\";\n\t\tif (!isEvalRunStatus(status)) throw new Error(\"status is invalid\");\n\t\tif (evalCaseId) {\n\t\t\tconst evalCase = await this.getCase(projectId, evalCaseId);\n\t\t\tif (!evalCase) throw new Error(\"evalCaseId does not reference a case\");\n\t\t}\n\n\t\tconst candidate = input.candidate ?? {};\n\t\tconst totalCount = nonNegativeInteger(input.totalCount);\n\t\tconst passCount = nonNegativeInteger(input.passCount);\n\t\tconst failCount = nonNegativeInteger(input.failCount);\n\t\tconst averageScore = optionalScore(input.averageScore);\n\t\tconst now = new Date().toISOString();\n\t\tconst startedAt =\n\t\t\tinput.startedAt === undefined\n\t\t\t\t? status === \"pending\"\n\t\t\t\t\t? null\n\t\t\t\t\t: now\n\t\t\t\t: input.startedAt;\n\t\tconst endedAt = input.endedAt ?? null;\n\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO eval_runs (\n\t\t\t\t\tid, project_id, eval_case_id,\n\t\t\t\t\tcandidate_agent_id, candidate_agent_version,\n\t\t\t\t\tcandidate_prompt_id, candidate_prompt_version,\n\t\t\t\t\tcandidate_model_provider, candidate_model, candidate_model_version,\n\t\t\t\t\tstatus, started_at, ended_at,\n\t\t\t\t\ttotal_count, pass_count, fail_count, average_score,\n\t\t\t\t\tmetadata_json, created_at\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t\tevalCaseId,\n\t\t\t\tcandidate.agentId ?? null,\n\t\t\t\tcandidate.agentVersion ?? null,\n\t\t\t\tcandidate.promptId ?? null,\n\t\t\t\tcandidate.promptVersion ?? null,\n\t\t\t\tcandidate.modelProvider ?? null,\n\t\t\t\tcandidate.model ?? null,\n\t\t\t\tcandidate.modelVersion ?? null,\n\t\t\t\tstatus,\n\t\t\t\tstartedAt,\n\t\t\t\tendedAt,\n\t\t\t\ttotalCount,\n\t\t\t\tpassCount,\n\t\t\t\tfailCount,\n\t\t\t\taverageScore,\n\t\t\t\tJSON.stringify(input.metadata ?? {}),\n\t\t\t\tnow,\n\t\t\t)\n\t\t\t.run();\n\n\t\tconst run = await this.getRun(projectId, id);\n\t\tif (!run) throw new Error(\"EvalCasesStore.createRun: insert failed\");\n\t\treturn run;\n\t}\n\n\tasync getRun(projectId: string, id: string): Promise<EvalRun | null> {\n\t\tconst row = await this.db\n\t\t\t.prepare(\n\t\t\t\t`${this.evalRunSelectSql()}\n\t\t\t\tWHERE r.project_id = ? AND r.id = ?\n\t\t\t\tLIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, id)\n\t\t\t.first<EvalRunRow>();\n\t\treturn row ? rowToEvalRun(row) : null;\n\t}\n\n\tasync listRuns(options: EvalRunsListOptions): Promise<EvalRun[]> {\n\t\tif (!options.projectId)\n\t\t\tthrow new Error(\"EvalCasesStore.listRuns: projectId is required\");\n\t\tif (options.status && !isEvalRunStatus(options.status)) {\n\t\t\tthrow new Error(\"status is invalid\");\n\t\t}\n\t\tconst limit = clampLimit(options.limit);\n\t\tlet sql = `${this.evalRunSelectSql()} WHERE r.project_id = ?`;\n\t\tconst params: unknown[] = [options.projectId];\n\t\tif (options.evalCaseId) {\n\t\t\tsql += ` AND r.eval_case_id = ?`;\n\t\t\tparams.push(options.evalCaseId);\n\t\t}\n\t\tif (options.status) {\n\t\t\tsql += ` AND r.status = ?`;\n\t\t\tparams.push(options.status);\n\t\t}\n\t\tsql += ` ORDER BY r.created_at DESC LIMIT ?`;\n\t\tparams.push(limit);\n\n\t\tconst rows = await this.db\n\t\t\t.prepare(sql)\n\t\t\t.bind(...params)\n\t\t\t.all<EvalRunRow>();\n\t\treturn rows.results.map(rowToEvalRun);\n\t}\n\n\tasync refreshRunSummary(projectId: string, id: string): Promise<void> {\n\t\tconst found = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT id FROM eval_runs WHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, id)\n\t\t\t.first<{ id: string }>();\n\t\tif (!found) return;\n\n\t\tawait this.db\n\t\t\t.prepare(\n\t\t\t\t`UPDATE eval_runs\n\t\t\t\tSET total_count = (\n\t\t\t\t\t\tSELECT COUNT(*) FROM eval_case_results\n\t\t\t\t\t\tWHERE project_id = ? AND run_id = ?\n\t\t\t\t\t),\n\t\t\t\t\tpass_count = (\n\t\t\t\t\t\tSELECT COUNT(*) FROM eval_case_results\n\t\t\t\t\t\tWHERE project_id = ? AND run_id = ? AND passed = 1\n\t\t\t\t\t),\n\t\t\t\t\tfail_count = (\n\t\t\t\t\t\tSELECT COUNT(*) FROM eval_case_results\n\t\t\t\t\t\tWHERE project_id = ? AND run_id = ? AND passed = 0\n\t\t\t\t\t),\n\t\t\t\t\taverage_score = (\n\t\t\t\t\t\tSELECT AVG(score) FROM eval_case_results\n\t\t\t\t\t\tWHERE project_id = ? AND run_id = ? AND score IS NOT NULL\n\t\t\t\t\t)\n\t\t\t\tWHERE project_id = ? AND id = ?`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\tprojectId,\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t\tid,\n\t\t\t\tprojectId,\n\t\t\t\tid,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tprivate evalRunSelectSql(): string {\n\t\treturn `SELECT\n\t\t\tr.*,\n\t\t\tc.id AS case_id,\n\t\t\tc.name AS case_name,\n\t\t\tc.source_entity_type AS case_source_entity_type,\n\t\t\tc.source_entity_id AS case_source_entity_id,\n\t\t\tc.source_agent_run_id AS case_source_agent_run_id,\n\t\t\tc.source_action_id AS case_source_action_id,\n\t\t\tc.source_ai_call_id AS case_source_ai_call_id,\n\t\t\tc.source_tool_call_id AS case_source_tool_call_id,\n\t\t\tc.source_trace_id AS case_source_trace_id,\n\t\t\tc.source_span_id AS case_source_span_id\n\t\tFROM eval_runs r\n\t\tLEFT JOIN eval_cases c\n\t\t\tON c.project_id = r.project_id AND c.id = r.eval_case_id`;\n\t}\n\n\tprivate async hydrateSource(\n\t\tprojectId: string,\n\t\tsourceEntityType: EvalCaseSourceType,\n\t\tsourceEntityId: string,\n\t\texplicit: EvalCaseSourceLinks,\n\t): Promise<{ links: EvalCaseSourceLinks }> {\n\t\tconst links: EvalCaseSourceLinks = { ...explicit };\n\n\t\tswitch (sourceEntityType) {\n\t\t\tcase \"action\": {\n\t\t\t\tconst action = await this.getActionSource(projectId, sourceEntityId);\n\t\t\t\tif (!action)\n\t\t\t\t\tthrow new EvalCaseSourceNotFoundError(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tsourceEntityType,\n\t\t\t\t\t\tsourceEntityId,\n\t\t\t\t\t);\n\t\t\t\tlinks.sourceActionId = action.id;\n\t\t\t\tlinks.sourceAgentRunId ??= action.agent_run_id;\n\t\t\t\tlinks.sourceToolCallId ??= action.tool_call_id;\n\t\t\t\tlinks.sourceTraceId ??= action.trace_id;\n\t\t\t\tlinks.sourceSpanId ??= action.span_id;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"agent_run\": {\n\t\t\t\tconst found = await this.db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT id FROM agent_runs WHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, sourceEntityId)\n\t\t\t\t\t.first<{ id: string }>();\n\t\t\t\tif (!found)\n\t\t\t\t\tthrow new EvalCaseSourceNotFoundError(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tsourceEntityType,\n\t\t\t\t\t\tsourceEntityId,\n\t\t\t\t\t);\n\t\t\t\tlinks.sourceAgentRunId = sourceEntityId;\n\t\t\t\tconst action = await this.db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT id, agent_run_id, tool_call_id, trace_id, span_id\n\t\t\t\t\t\tFROM actions\n\t\t\t\t\t\tWHERE project_id = ? AND (id = ? OR agent_run_id = ?)\n\t\t\t\t\t\tORDER BY started_at ASC LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, sourceEntityId, sourceEntityId)\n\t\t\t\t\t.first<ActionSourceRow>();\n\t\t\t\tif (action) {\n\t\t\t\t\tlinks.sourceActionId ??= action.id;\n\t\t\t\t\tlinks.sourceTraceId ??= action.trace_id;\n\t\t\t\t\tlinks.sourceSpanId ??= action.span_id;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"ai_call\": {\n\t\t\t\tconst call = explicit.sourceTraceId\n\t\t\t\t\t? await this.db\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT call_id, trace_id, span_id, request_json, response_json\n\t\t\t\t\t\t\t\tFROM ai_calls\n\t\t\t\t\t\t\t\tWHERE project_id = ?\n\t\t\t\t\t\t\t\t\tAND trace_id = ?\n\t\t\t\t\t\t\t\t\tAND (call_id = ? OR span_id = ?)\n\t\t\t\t\t\t\t\tLIMIT 1`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(\n\t\t\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\t\t\texplicit.sourceTraceId,\n\t\t\t\t\t\t\t\tsourceEntityId,\n\t\t\t\t\t\t\t\tsourceEntityId,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.first<AiCallSourceRow>()\n\t\t\t\t\t: await this.db\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT call_id, trace_id, span_id, request_json, response_json\n\t\t\t\t\t\t\t\tFROM ai_calls\n\t\t\t\t\t\t\t\tWHERE project_id = ? AND (call_id = ? OR span_id = ?)\n\t\t\t\t\t\t\t\tLIMIT 1`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(projectId, sourceEntityId, sourceEntityId)\n\t\t\t\t\t\t\t.first<AiCallSourceRow>();\n\t\t\t\tif (!call)\n\t\t\t\t\tthrow new EvalCaseSourceNotFoundError(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tsourceEntityType,\n\t\t\t\t\t\tsourceEntityId,\n\t\t\t\t\t);\n\t\t\t\tlinks.sourceAiCallId = call.call_id;\n\t\t\t\tlinks.sourceTraceId ??= call.trace_id;\n\t\t\t\tlinks.sourceSpanId ??= call.span_id;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"tool_call\": {\n\t\t\t\tconst tool = await this.getToolCallSource(projectId, sourceEntityId);\n\t\t\t\tif (!tool)\n\t\t\t\t\tthrow new EvalCaseSourceNotFoundError(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tsourceEntityType,\n\t\t\t\t\t\tsourceEntityId,\n\t\t\t\t\t);\n\t\t\t\tlinks.sourceToolCallId = tool.id;\n\t\t\t\tlinks.sourceActionId ??= tool.action_id;\n\t\t\t\tif (tool.action_id) {\n\t\t\t\t\tconst action = await this.getActionSource(projectId, tool.action_id);\n\t\t\t\t\tlinks.sourceAgentRunId ??= action?.agent_run_id;\n\t\t\t\t\tlinks.sourceTraceId ??= action?.trace_id;\n\t\t\t\t\tlinks.sourceSpanId ??= action?.span_id;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"trace\": {\n\t\t\t\tconst span = await this.db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT trace_id, span_id\n\t\t\t\t\t\tFROM telemetry_spans\n\t\t\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\t\t\tORDER BY start_time ASC LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, sourceEntityId)\n\t\t\t\t\t.first<SpanSourceRow>();\n\t\t\t\tif (!span)\n\t\t\t\t\tthrow new EvalCaseSourceNotFoundError(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tsourceEntityType,\n\t\t\t\t\t\tsourceEntityId,\n\t\t\t\t\t);\n\t\t\t\tlinks.sourceTraceId = span.trace_id;\n\t\t\t\tlinks.sourceSpanId ??= span.span_id;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn { links };\n\t}\n\n\tprivate async getActionSource(\n\t\tprojectId: string,\n\t\tactionId: string,\n\t): Promise<ActionSourceRow | null> {\n\t\treturn this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT id, agent_run_id, tool_call_id, trace_id, span_id\n\t\t\t\tFROM actions\n\t\t\t\tWHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, actionId)\n\t\t\t.first<ActionSourceRow>();\n\t}\n\n\tprivate async getToolCallSource(\n\t\tprojectId: string,\n\t\ttoolCallId: string,\n\t): Promise<ToolCallSourceRow | null> {\n\t\treturn this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT id, action_id, tool_name, args_hash, result_hash,\n\t\t\t\t\tmcp_audit_json, mutation_before_json, mutation_after_json,\n\t\t\t\t\tmutation_diff_json, mutation_artifact_id\n\t\t\t\tFROM tool_calls\n\t\t\t\tWHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, toolCallId)\n\t\t\t.first<ToolCallSourceRow>();\n\t}\n\n\tprivate async findPayload(\n\t\tprojectId: string,\n\t\tlinks: EvalCaseSourceLinks,\n\t): Promise<{ input: JsonValue | null; output: JsonValue | null } | null> {\n\t\tlet row: PayloadRow | null = null;\n\t\tif (links.sourceTraceId && links.sourceSpanId) {\n\t\t\trow = await this.db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT input_json, output_json\n\t\t\t\t\tFROM ai_span_payloads\n\t\t\t\t\tWHERE project_id = ? AND trace_id = ? AND span_id = ?\n\t\t\t\t\tLIMIT 1`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, links.sourceTraceId, links.sourceSpanId)\n\t\t\t\t.first<PayloadRow>();\n\t\t}\n\t\tif (!row && links.sourceActionId) {\n\t\t\trow = await this.db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT input_json, output_json\n\t\t\t\t\tFROM ai_span_payloads\n\t\t\t\t\tWHERE project_id = ? AND action_id = ?\n\t\t\t\t\tORDER BY received_at DESC LIMIT 1`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, links.sourceActionId)\n\t\t\t\t.first<PayloadRow>();\n\t\t}\n\t\tif (!row && links.sourceTraceId) {\n\t\t\trow = await this.db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT input_json, output_json\n\t\t\t\t\tFROM ai_span_payloads\n\t\t\t\t\tWHERE project_id = ? AND trace_id = ?\n\t\t\t\t\tORDER BY received_at DESC LIMIT 1`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, links.sourceTraceId)\n\t\t\t\t.first<PayloadRow>();\n\t\t}\n\t\tif (!row) return null;\n\t\treturn {\n\t\t\tinput: parseJsonField(row.input_json),\n\t\t\toutput: parseJsonField(row.output_json),\n\t\t};\n\t}\n\n\tprivate async buildMetadata(\n\t\tprojectId: string,\n\t\tlinks: EvalCaseSourceLinks,\n\t): Promise<Record<string, JsonValue>> {\n\t\tconst linkedSpans: JsonValue[] = [];\n\t\tif (links.sourceTraceId && links.sourceSpanId) {\n\t\t\tlinkedSpans.push({\n\t\t\t\ttraceId: links.sourceTraceId,\n\t\t\t\tspanId: links.sourceSpanId,\n\t\t\t});\n\t\t}\n\n\t\tconst toolHashes: JsonValue[] = [];\n\t\tif (links.sourceToolCallId) {\n\t\t\tconst tool = await this.getToolCallSource(\n\t\t\t\tprojectId,\n\t\t\t\tlinks.sourceToolCallId,\n\t\t\t);\n\t\t\tif (tool) toolHashes.push(toolHashMetadata(tool));\n\t\t} else if (links.sourceActionId) {\n\t\t\tconst rows = await this.db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT id, action_id, tool_name, args_hash, result_hash,\n\t\t\t\t\t\tmcp_audit_json, mutation_before_json, mutation_after_json,\n\t\t\t\t\t\tmutation_diff_json, mutation_artifact_id\n\t\t\t\t\tFROM tool_calls\n\t\t\t\t\tWHERE project_id = ? AND action_id = ?\n\t\t\t\t\tLIMIT 25`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, links.sourceActionId)\n\t\t\t\t.all<ToolCallSourceRow>();\n\t\t\tfor (const row of rows.results) {\n\t\t\t\ttoolHashes.push(toolHashMetadata(row));\n\t\t\t}\n\t\t}\n\n\t\tconst documentRefs: JsonValue[] = [];\n\t\tif (links.sourceActionId) {\n\t\t\tconst rows = await this.db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT documents_json\n\t\t\t\t\tFROM retrieval_events\n\t\t\t\t\tWHERE project_id = ? AND action_id = ?\n\t\t\t\t\tLIMIT 25`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, links.sourceActionId)\n\t\t\t\t.all<RetrievalEventRow>();\n\t\t\tfor (const row of rows.results) {\n\t\t\t\tfor (const doc of parseJsonArray(\n\t\t\t\t\ttypeof row.documents_json === \"string\"\n\t\t\t\t\t\t? row.documents_json\n\t\t\t\t\t\t: JSON.stringify(row.documents_json ?? []),\n\t\t\t\t)) {\n\t\t\t\t\tdocumentRefs.push(doc as JsonValue);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst metadata: Record<string, JsonValue> = {};\n\t\tif (linkedSpans.length > 0) metadata.linkedSpans = linkedSpans;\n\t\tif (toolHashes.length > 0) metadata.toolHashes = toolHashes;\n\t\tif (documentRefs.length > 0) metadata.documentRefs = documentRefs;\n\t\treturn metadata;\n\t}\n}\n\nconst toolHashMetadata = (tool: ToolCallSourceRow): JsonValue => {\n\tconst metadata: Record<string, JsonValue> = {\n\t\ttoolCallId: tool.id,\n\t\ttoolName: tool.tool_name,\n\t\targsHash: tool.args_hash,\n\t\tresultHash: tool.result_hash,\n\t};\n\n\tconst mcpAudit = parseEvidenceJson(tool.mcp_audit_json);\n\tif (mcpAudit !== null) metadata.mcpAudit = mcpAudit;\n\n\tconst mutationEvidence: Record<string, JsonValue> = {};\n\tconst before = parseEvidenceJson(tool.mutation_before_json);\n\tconst after = parseEvidenceJson(tool.mutation_after_json);\n\tconst diff = parseEvidenceJson(tool.mutation_diff_json);\n\tif (before !== null) mutationEvidence.before = before;\n\tif (after !== null) mutationEvidence.after = after;\n\tif (diff !== null) mutationEvidence.diff = diff;\n\tif (tool.mutation_artifact_id) {\n\t\tmutationEvidence.artifactId = tool.mutation_artifact_id;\n\t}\n\tif (Object.keys(mutationEvidence).length > 0) {\n\t\tmetadata.mutationEvidence = mutationEvidence;\n\t}\n\n\treturn metadata;\n};\n\nconst parseEvidenceJson = (value: unknown): JsonValue | null => {\n\tif (value === null || value === undefined) return null;\n\tif (typeof value === \"string\") return parseJsonValue(value);\n\tif (\n\t\ttypeof value === \"object\" ||\n\t\ttypeof value === \"number\" ||\n\t\ttypeof value === \"boolean\"\n\t) {\n\t\treturn value as JsonValue;\n\t}\n\treturn null;\n};\n","/**\n * Collector-side pprof helpers. The wire-format decoder/encoder lives in\n * `@obsunified/pprof-decoder` and is shared with the dashboard's flame graph\n * viewer; this file adds the server-specific concerns:\n *\n * - extractTraceIdsFromProfile — pulls distinct trace_id labels from a\n * parsed profile so `profile-routes.ts` can populate\n * `profile_trace_index` without trusting the `x-obs-trace-ids` header.\n * - filterPprofByTraceId — drops samples that don't carry the requested\n * trace_id label and re-emits a smaller gzipped pprof. Powers the\n * Phase 4.5 server-side pre-filter for the trace waterfall's 🔥 link.\n */\n\nimport {\n\tdecodePprof,\n\tdecodePprofBlob,\n\tencodePprof,\n\tgzipBytes,\n\ttype PprofFunction,\n\ttype PprofLabel,\n\ttype PprofLocation,\n\ttype PprofProfile,\n\ttype PprofSample,\n\ttype PprofValueType,\n} from \"@obsunified/pprof-decoder\";\n\n// Re-exports keep call sites (profile-routes, tests) importing from one\n// place — they don't need to know whether something lives upstream.\nexport {\n\tdecodePprof,\n\tdecodePprofBlob,\n\tencodePprof,\n\ttype PprofFunction,\n\ttype PprofLabel,\n\ttype PprofLocation,\n\ttype PprofProfile,\n\ttype PprofSample,\n\ttype PprofValueType,\n};\n\nconst TRACE_ID_LABEL_KEYS = [\"trace_id\", \"trace.id\"];\nconst TRACE_ID_RE = /^[0-9a-f]{16,32}$/i;\n\nexport interface ProfileFrameSummary {\n\tname: string;\n\tvalue: number;\n\tsampleCount: number;\n\tcodeReference?: {\n\t\toriginalPath: string;\n\t\trelativePath?: string;\n\t\tabsolutePath?: string;\n\t\tlineNumber?: number;\n\t\tsymbol?: string;\n\t};\n}\n\nconst sampleHasTraceId = (\n\tprofile: PprofProfile,\n\tsample: PprofSample,\n\ttraceIdFilter: string | null,\n): boolean => {\n\tif (!traceIdFilter) return true;\n\tconst want = traceIdFilter.toLowerCase();\n\tconst traceIdKeyIxs = new Set<number>();\n\tfor (let i = 0; i < profile.stringTable.length; i++) {\n\t\tif (TRACE_ID_LABEL_KEYS.includes(profile.stringTable[i])) {\n\t\t\ttraceIdKeyIxs.add(i);\n\t\t}\n\t}\n\treturn sample.labels.some(\n\t\t(label) =>\n\t\t\ttraceIdKeyIxs.has(label.keyIdx) &&\n\t\t\tprofile.stringTable[label.strIdx]?.toLowerCase() === want,\n\t);\n};\n\nexport const summarizeProfileFrames = (\n\tprofile: PprofProfile,\n\topts: { limit?: number; traceIdFilter?: string | null } = {},\n): ProfileFrameSummary[] => {\n\tconst limit = Math.max(1, Math.min(opts.limit ?? 50, 500));\n\tconst byFrame = new Map<string, ProfileFrameSummary>();\n\n\tfor (const sample of profile.samples) {\n\t\tif (!sampleHasTraceId(profile, sample, opts.traceIdFilter ?? null))\n\t\t\tcontinue;\n\t\tconst value = sample.values[0] ?? 0;\n\t\tfor (const locationId of sample.locationIds) {\n\t\t\tconst loc = profile.locations.get(locationId);\n\t\t\tif (!loc) continue;\n\t\t\tconst lines =\n\t\t\t\tloc.lines ||\n\t\t\t\t(loc.functionIds || []).map((functionId) => ({ functionId, line: 0 }));\n\t\t\tfor (const line of lines) {\n\t\t\t\tconst fn = profile.functions.get(line.functionId);\n\t\t\t\tif (!fn) continue;\n\t\t\t\tconst name = profile.stringTable[fn.nameIdx] ?? \"?\";\n\t\t\t\tconst filename = profile.stringTable[fn.filenameIdx] ?? \"\";\n\t\t\t\tconst key = `${name}\\0${filename}\\0${line.line || 0}`;\n\t\t\t\tconst existing = byFrame.get(key) ?? {\n\t\t\t\t\tname,\n\t\t\t\t\tvalue: 0,\n\t\t\t\t\tsampleCount: 0,\n\t\t\t\t\tcodeReference: filename\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\toriginalPath: filename,\n\t\t\t\t\t\t\t\trelativePath: filename.startsWith(\"/\") ? undefined : filename,\n\t\t\t\t\t\t\t\tabsolutePath: filename.startsWith(\"/\") ? filename : undefined,\n\t\t\t\t\t\t\t\tlineNumber: line.line || undefined,\n\t\t\t\t\t\t\t\tsymbol: name,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t};\n\t\t\t\texisting.value += value;\n\t\t\t\texisting.sampleCount += 1;\n\t\t\t\tbyFrame.set(key, existing);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Array.from(byFrame.values())\n\t\t.sort((a, b) => b.value - a.value)\n\t\t.slice(0, limit);\n};\n\n/**\n * Extract distinct trace_id label values from a parsed pprof. Returns\n * an array of valid 16-32 hex-char trace_ids, deduplicated. Defensive\n * against malformed labels — silently ignores anything that doesn't\n * match the hex pattern (a malformed agent shouldn't pollute the index).\n */\nexport const extractTraceIdsFromProfile = (profile: PprofProfile): string[] => {\n\tconst traceIdKeyIxs = new Set<number>();\n\tfor (let i = 0; i < profile.stringTable.length; i++) {\n\t\tif (TRACE_ID_LABEL_KEYS.includes(profile.stringTable[i])) {\n\t\t\ttraceIdKeyIxs.add(i);\n\t\t}\n\t}\n\tif (traceIdKeyIxs.size === 0) return [];\n\n\tconst traceIds = new Set<string>();\n\tfor (const sample of profile.samples) {\n\t\tfor (const label of sample.labels) {\n\t\t\tif (!traceIdKeyIxs.has(label.keyIdx)) continue;\n\t\t\tconst value = profile.stringTable[label.strIdx];\n\t\t\tif (value && TRACE_ID_RE.test(value)) {\n\t\t\t\ttraceIds.add(value.toLowerCase());\n\t\t\t}\n\t\t}\n\t}\n\treturn [...traceIds];\n};\n\n/**\n * Filter a pprof down to samples carrying the requested trace_id label\n * and re-emit a gzipped blob. location/function/string tables are\n * preserved verbatim — unused entries become dead weight in the output\n * but the result is still valid pprof, and the wire savings come almost\n * entirely from the sample list (~80% of a typical blob). Compacting\n * the auxiliary tables is a Phase 4+ optimization.\n */\nexport const filterPprofByTraceId = async (\n\tprofile: PprofProfile,\n\ttraceIdFilter: string,\n): Promise<Uint8Array> => {\n\tconst want = traceIdFilter.toLowerCase();\n\tconst traceIdKeyIxs = new Set<number>();\n\tfor (let i = 0; i < profile.stringTable.length; i++) {\n\t\tif (TRACE_ID_LABEL_KEYS.includes(profile.stringTable[i])) {\n\t\t\ttraceIdKeyIxs.add(i);\n\t\t}\n\t}\n\tconst filtered: PprofProfile = {\n\t\t...profile,\n\t\tsamples: profile.samples.filter((s) =>\n\t\t\ts.labels.some(\n\t\t\t\t(l) =>\n\t\t\t\t\ttraceIdKeyIxs.has(l.keyIdx) &&\n\t\t\t\t\tprofile.stringTable[l.strIdx]?.toLowerCase() === want,\n\t\t\t),\n\t\t),\n\t};\n\treturn gzipBytes(encodePprof(filtered));\n};\n","import type { SessionReplayMetadataRow } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nconst DEFAULT_CHUNK_LIMIT = 100;\nconst MAX_CHUNK_LIMIT = 500;\nconst REPLAY_CHUNK_FETCH_CONCURRENCY = 8;\n\ninterface ReplayChunkObject {\n\tkey: string;\n}\n\ninterface ReplayChunkBody {\n\tjson<T>(): Promise<T>;\n}\n\ninterface ReplayChunkBucket {\n\tget(key: string): Promise<ReplayChunkBody | null>;\n}\n\nasync function mapWithConcurrency<T, R>(\n\titems: T[],\n\tconcurrency: number,\n\tmapper: (item: T) => Promise<R>,\n): Promise<R[]> {\n\tconst results: R[] = new Array(items.length);\n\tlet nextIndex = 0;\n\tconst workerCount = Math.min(Math.max(1, concurrency), items.length);\n\tawait Promise.all(\n\t\tArray.from({ length: workerCount }, async () => {\n\t\t\twhile (nextIndex < items.length) {\n\t\t\t\tconst current = nextIndex++;\n\t\t\t\tresults[current] = await mapper(items[current]);\n\t\t\t}\n\t\t}),\n\t);\n\treturn results;\n}\n\nexport async function fetchReplayChunks(\n\tbucket: ReplayChunkBucket,\n\tobjects: ReplayChunkObject[],\n\tconcurrency = REPLAY_CHUNK_FETCH_CONCURRENCY,\n): Promise<Record<string, unknown>[]> {\n\tconst chunks = await mapWithConcurrency(objects, concurrency, async (obj) => {\n\t\tconst objectData = await bucket.get(obj.key);\n\t\tif (!objectData) return [];\n\t\treturn objectData.json<Record<string, unknown>[]>();\n\t});\n\treturn chunks.flat();\n}\n\nexport const replayQueryRoutesPlugin: CollectorPlugin = {\n\tname: \"replay-query-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/replays\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst limit = Math.max(\n\t\t\t\t1,\n\t\t\t\tMath.min(500, parseInt(c.req.query(\"limit\") ?? \"50\", 10) || 50),\n\t\t\t);\n\t\t\tconst { results } = await sqlDbFor(c.env)\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT\n\t\t\t\t\tr.*,\n\t\t\t\t\t(SELECT page_path FROM usage_events e WHERE e.project_id = r.project_id AND e.session_id = r.session_id AND e.event_type = 'page_view' ORDER BY e.occurred_at ASC LIMIT 1) as starting_link\n\t\t\t\t FROM session_replay_metadata r\n\t\t\t\t WHERE r.project_id = ?\n\t\t\t\t ORDER BY r.last_chunk_at DESC\n\t\t\t\t LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, limit)\n\t\t\t\t.all();\n\n\t\t\treturn c.json({ replays: results });\n\t\t});\n\n\t\tapp.get(\"/internal/replays/:sessionId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst sessionId = c.req.param(\"sessionId\");\n\n\t\t\tif (!c.env.REPLAYS_BUCKET) {\n\t\t\t\treturn c.json({ error: \"Replay storage not configured\" }, 500);\n\t\t\t}\n\n\t\t\tconst metadata = await sqlDbFor(c.env)\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM session_replay_metadata WHERE project_id = ? AND session_id = ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, sessionId)\n\t\t\t\t.first<SessionReplayMetadataRow>();\n\n\t\t\tif (!metadata) {\n\t\t\t\treturn c.json({ error: \"Session replay not found\" }, 404);\n\t\t\t}\n\n\t\t\tconst prefix = `replays/${projectId}/${sessionId}/`;\n\t\t\tconst objects: Array<{ key: string }> = [];\n\t\t\tlet cursor: string | undefined;\n\t\t\tdo {\n\t\t\t\tconst page = await c.env.REPLAYS_BUCKET.list({ prefix, cursor });\n\t\t\t\tobjects.push(...page.objects);\n\t\t\t\tcursor = page.truncated ? page.cursor : undefined;\n\t\t\t} while (cursor);\n\n\t\t\tif (objects.length === 0) {\n\t\t\t\treturn c.json({ error: \"Replay chunks missing in storage\" }, 404);\n\t\t\t}\n\n\t\t\tobjects.sort((a, b) => a.key.localeCompare(b.key));\n\n\t\t\tconst chunkOffset = Math.max(\n\t\t\t\t0,\n\t\t\t\tparseInt(c.req.query(\"chunkOffset\") ?? \"0\", 10) || 0,\n\t\t\t);\n\t\t\tconst chunkLimit = Math.max(\n\t\t\t\t1,\n\t\t\t\tMath.min(\n\t\t\t\t\tMAX_CHUNK_LIMIT,\n\t\t\t\t\tparseInt(\n\t\t\t\t\t\tc.req.query(\"chunkLimit\") ?? String(DEFAULT_CHUNK_LIMIT),\n\t\t\t\t\t\t10,\n\t\t\t\t\t) || DEFAULT_CHUNK_LIMIT,\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst selectedObjects = objects.slice(\n\t\t\t\tchunkOffset,\n\t\t\t\tchunkOffset + chunkLimit,\n\t\t\t);\n\t\t\tconst events = await fetchReplayChunks(\n\t\t\t\tc.env.REPLAYS_BUCKET,\n\t\t\t\tselectedObjects,\n\t\t\t);\n\t\t\tconst nextChunkOffset =\n\t\t\t\tchunkOffset + chunkLimit < objects.length\n\t\t\t\t\t? chunkOffset + chunkLimit\n\t\t\t\t\t: null;\n\n\t\t\treturn c.json({\n\t\t\t\tmetadata,\n\t\t\t\tevents,\n\t\t\t\tchunks: {\n\t\t\t\t\toffset: chunkOffset,\n\t\t\t\t\tlimit: chunkLimit,\n\t\t\t\t\treturned: selectedObjects.length,\n\t\t\t\t\ttotal: objects.length,\n\t\t\t\t\tnextChunkOffset,\n\t\t\t\t},\n\t\t\t});\n\t\t});\n\n\t\tapp.delete(\"/internal/replays/:sessionId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst sessionId = c.req.param(\"sessionId\");\n\n\t\t\tif (!c.env.REPLAYS_BUCKET) {\n\t\t\t\treturn c.json({ error: \"Replay storage not configured\" }, 500);\n\t\t\t}\n\n\t\t\t// 1. Check if it exists\n\t\t\tconst metadata = await sqlDbFor(c.env)\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM session_replay_metadata WHERE project_id = ? AND session_id = ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, sessionId)\n\t\t\t\t.first<SessionReplayMetadataRow>();\n\n\t\t\tif (!metadata) {\n\t\t\t\treturn c.json({ error: \"Session replay not found\" }, 404);\n\t\t\t}\n\n\t\t\t// 2. Delete all chunks from bucket\n\t\t\tconst bucket = c.env.REPLAYS_BUCKET;\n\t\t\tif (!bucket) {\n\t\t\t\treturn c.json({ error: \"Replay storage not configured\" }, 500);\n\t\t\t}\n\t\t\tconst prefix = `replays/${projectId}/${sessionId}/`;\n\t\t\tlet cursor: string | undefined;\n\t\t\tdo {\n\t\t\t\tconst page = await bucket.list({ prefix, cursor });\n\t\t\t\tif (page.objects.length > 0) {\n\t\t\t\t\tawait Promise.all(page.objects.map((obj) => bucket.delete(obj.key)));\n\t\t\t\t}\n\t\t\t\tcursor = page.truncated ? page.cursor : undefined;\n\t\t\t} while (cursor);\n\n\t\t\t// 3. Delete metadata from DB\n\t\t\tawait sqlDbFor(c.env)\n\t\t\t\t.prepare(\n\t\t\t\t\t`DELETE FROM session_replay_metadata WHERE project_id = ? AND session_id = ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, sessionId)\n\t\t\t\t.run();\n\n\t\t\treturn c.json({ success: true });\n\t\t});\n\t},\n};\n","import type {\n\tEvidenceBundle,\n\tEvidenceBundleDetailLevel,\n\tEvidenceBundleIntent,\n\tEvidenceCompaction,\n\tEvidenceEntityKind,\n\tEvidenceNextPivot,\n\tEvidenceReference,\n\tEvidenceRetrievalRef,\n\tLogRecord,\n\tTelemetrySpanDetail,\n\tTelemetryTraceDetailResponse,\n} from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport type {\n\tActionRef,\n\tEntityManifestExtended,\n\tToolCallRef,\n} from \"../lib/identity-index\";\nimport { IdentityIndex } from \"../lib/identity-index\";\nimport { LogsStore } from \"../lib/logs-store\";\nimport { decodePprofBlob, summarizeProfileFrames } from \"../lib/parse-pprof\";\nimport type { SqlDb } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\nimport { fetchReplayChunks } from \"./replay-query-routes\";\n\ninterface EvidenceRefPayload {\n\tkind:\n\t\t| \"logs\"\n\t\t| \"trace\"\n\t\t| \"action_graph\"\n\t\t| \"profile\"\n\t\t| \"replay\"\n\t\t| \"ai_call\"\n\t\t| \"tool_call\";\n\tprojectId: string;\n\ttraceId?: string;\n\tanchorKind?: \"action\" | \"agent_run\" | \"tool_call\";\n\tanchorId?: string;\n\tprofileId?: string;\n\tprofileMode?: \"metadata\" | \"frames\";\n\tsessionId?: string;\n\treplayMode?: \"metadata\" | \"events\";\n\tchunkOffset?: number;\n\tcallId?: string;\n\ttoolCallId?: string;\n\thours?: number;\n\tlimit?: number;\n}\n\ninterface ProfileEvidenceRow {\n\tid: string;\n\tservice_name: string | null;\n\tprofile_type: string;\n\tstart_ts: string;\n\tend_ts: string;\n\tduration_ms: number;\n\tblob_size_bytes: number;\n\tblob_url?: string;\n\tsample_count: number | null;\n\tagent: string | null;\n\treceived_at?: string;\n\texpires_at?: string;\n}\n\ninterface ReplayEvidenceRow {\n\tsession_id: string;\n\tvisitor_id?: string;\n\tfirst_chunk_at: string;\n\tlast_chunk_at: string;\n\tchunk_count: number;\n\tevents_count: number;\n\tstorage_bytes?: number;\n}\n\ninterface AICallEvidenceRow {\n\tcall_id: string;\n\ttrace_id: string | null;\n\tspan_id?: string | null;\n\tservice_name?: string | null;\n\tmodel_name: string;\n\tprovider: string;\n\tcall_type?: string;\n\tprompt_tokens?: number | null;\n\tcompletion_tokens?: number | null;\n\ttotal_cost_usd: number | null;\n\tlatency_ms?: number | null;\n\tis_error?: number | null;\n\terror_message?: string | null;\n\toccurred_at: string;\n\treceived_at?: string;\n\texpires_at?: string;\n\tinteraction_id?: string | null;\n\tsession_id?: string | null;\n}\n\nconst BUNDLE_SCHEMA_VERSION = \"obs-unified.evidence-bundle.v1\" as const;\nconst DEFAULT_TARGET_TOKENS = 4000;\nconst DEFAULT_HOURS = 24;\nconst MAX_LOGS_FOR_BUNDLE = 500;\nconst MAX_LOGS_FOR_RETRIEVAL = 1000;\nconst DEFAULT_REPLAY_EVENT_CHUNKS = 5;\nconst MAX_REPLAY_EVENT_CHUNKS = 25;\nconst DEFAULT_PROFILE_FRAME_LIMIT = 50;\nconst MAX_PROFILE_FRAME_LIMIT = 200;\nconst EVIDENCE_INTENTS = new Set<EvidenceBundleIntent>([\n\t\"debug_failure\",\n\t\"explain_latency\",\n\t\"explain_cost\",\n\t\"inspect_agent_run\",\n\t\"inspect_tool_call\",\n\t\"find_instrumentation_gap\",\n\t\"general\",\n]);\nconst LOG_SEVERITIES = new Set<LogRecord[\"severity\"]>([\n\t\"DEBUG\",\n\t\"INFO\",\n\t\"WARN\",\n\t\"ERROR\",\n\t\"FATAL\",\n]);\n\nconst clampInt = (\n\tvalue: unknown,\n\tmin: number,\n\tmax: number,\n\tfallback: number,\n): number => {\n\tconst parsed =\n\t\ttypeof value === \"number\"\n\t\t\t? value\n\t\t\t: Number.parseInt(typeof value === \"string\" ? value : \"\", 10);\n\tif (!Number.isFinite(parsed)) return fallback;\n\treturn Math.max(min, Math.min(max, parsed));\n};\n\nconst estimateTokens = (value: unknown): number =>\n\tMath.ceil(JSON.stringify(value).length / 4);\n\nconst traceRoute = (traceId: string) =>\n\t`#/traces/${encodeURIComponent(traceId)}`;\nconst spanRoute = (traceId: string, spanId: string) =>\n\t`${traceRoute(traceId)}#span=${encodeURIComponent(spanId)}`;\nconst logRoute = (logId: string) => `#/logs?id=${encodeURIComponent(logId)}`;\nconst actionRoute = (actionId: string) =>\n\t`#/actions/${encodeURIComponent(actionId)}`;\nconst agentRunRoute = (agentRunId: string) =>\n\t`#/agent-runs/${encodeURIComponent(agentRunId)}`;\nconst toolCallRoute = (toolCallId: string) =>\n\t`#/tool-calls/${encodeURIComponent(toolCallId)}`;\nconst replayRoute = (sessionId: string) =>\n\t`#/replay?session=${encodeURIComponent(sessionId)}`;\nconst profileRoute = (profileId: string, traceId?: string) =>\n\t`#/profiles/${encodeURIComponent(profileId)}${\n\t\ttraceId ? `?trace_id=${encodeURIComponent(traceId)}` : \"\"\n\t}`;\nconst aiCallRoute = (callId: string) =>\n\t`#/ai/calls/${encodeURIComponent(callId)}`;\n\nconst evidenceRef = (\n\tevidenceId: string,\n\tentityKind: EvidenceEntityKind,\n\tentityId: string,\n\troute: string,\n\tsource: string,\n\tconfidence: number,\n\treason: string,\n\tcitations: EvidenceReference[\"citations\"] = [],\n\tsuggestedNextPivots: EvidenceNextPivot[] = [],\n): EvidenceReference => ({\n\tevidenceId,\n\tentityKind,\n\tentityId,\n\troute,\n\tsource,\n\tconfidence,\n\treason,\n\tcitations,\n\tsuggestedNextPivots,\n});\n\nconst encodeRef = (payload: EvidenceRefPayload): string => {\n\tconst json = JSON.stringify(payload);\n\tconst bytes = new TextEncoder().encode(json);\n\tlet binary = \"\";\n\tfor (const byte of bytes) binary += String.fromCharCode(byte);\n\treturn `eref_${globalThis\n\t\t.btoa(binary)\n\t\t.replace(/\\+/g, \"-\")\n\t\t.replace(/\\//g, \"_\")\n\t\t.replace(/=+$/, \"\")}`;\n};\n\nconst decodeRef = (refId: string): EvidenceRefPayload | null => {\n\tif (!refId.startsWith(\"eref_\")) return null;\n\ttry {\n\t\tconst encoded = refId\n\t\t\t.slice(\"eref_\".length)\n\t\t\t.replace(/-/g, \"+\")\n\t\t\t.replace(/_/g, \"/\");\n\t\tconst padded = encoded.padEnd(\n\t\t\tencoded.length + ((4 - (encoded.length % 4)) % 4),\n\t\t\t\"=\",\n\t\t);\n\t\tconst binary = globalThis.atob(padded);\n\t\tconst bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));\n\t\treturn JSON.parse(new TextDecoder().decode(bytes)) as EvidenceRefPayload;\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst isProjectScopedRefPayload = (\n\tpayload: EvidenceRefPayload | null,\n): payload is EvidenceRefPayload =>\n\tBoolean(\n\t\tpayload &&\n\t\t\ttypeof payload.projectId === \"string\" &&\n\t\t\tpayload.projectId.length > 0,\n\t);\n\nconst hasTraceId = (\n\tpayload: EvidenceRefPayload,\n): payload is EvidenceRefPayload & { traceId: string } =>\n\ttypeof payload.traceId === \"string\" && payload.traceId.length > 0;\n\nconst expansionId = (): string =>\n\t`exp_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n\nconst jsonOrNull = (value: unknown): string | null =>\n\tvalue === undefined ? null : JSON.stringify(value);\n\nconst materializeRetrievalRefs = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\trefs: EvidenceRetrievalRef[],\n) => {\n\tif (refs.length === 0) return;\n\tconst stmt = db.prepare(\n\t\t`INSERT INTO evidence_retrieval_refs (\n\t\t\tref_id, project_id, kind, anchor_kind, anchor_id, source, query_json,\n\t\t\tcompacted_from_json, returned_json, last_seen_at, expires_at\n\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)\n\t\tON CONFLICT(ref_id) DO UPDATE SET\n\t\t\tlast_seen_at = CURRENT_TIMESTAMP,\n\t\t\tkind = excluded.kind,\n\t\t\tanchor_kind = excluded.anchor_kind,\n\t\t\tanchor_id = excluded.anchor_id,\n\t\t\tsource = excluded.source,\n\t\t\tquery_json = excluded.query_json,\n\t\t\tcompacted_from_json = excluded.compacted_from_json,\n\t\t\treturned_json = excluded.returned_json,\n\t\t\texpires_at = excluded.expires_at`,\n\t);\n\ttry {\n\t\tawait db.batch(\n\t\t\trefs.map((ref) =>\n\t\t\t\tstmt.bind(\n\t\t\t\t\tref.refId,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tref.kind,\n\t\t\t\t\tref.anchor.entityKind,\n\t\t\t\t\tref.anchor.entityId,\n\t\t\t\t\tref.source,\n\t\t\t\t\tjsonOrNull(ref.query),\n\t\t\t\t\tjsonOrNull(ref.compactedFrom),\n\t\t\t\t\tjsonOrNull(ref.returned),\n\t\t\t\t\tref.expiresAt ?? null,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t} catch {\n\t\t// Best-effort: encoded refs remain valid even before the migration lands.\n\t}\n};\n\nconst recordRefExpansion = async (\n\tdb: SqlDb,\n\targs: {\n\t\tprojectId: string;\n\t\trefId: string;\n\t\tkind: EvidenceRefPayload[\"kind\"];\n\t\toperation: \"retrieve\" | \"search\";\n\t\tresultStatus: \"ok\" | \"error\";\n\t\tlimit?: number;\n\t\tquery?: string;\n\t},\n) => {\n\ttry {\n\t\tconst source = await db\n\t\t\t.prepare(\n\t\t\t\t`SELECT source FROM evidence_retrieval_refs\n\t\t\t\t WHERE project_id = ? AND ref_id = ?\n\t\t\t\t LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(args.projectId, args.refId)\n\t\t\t.first<{ source: string }>();\n\t\tawait db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO evidence_ref_expansions (\n\t\t\t\t\tid, ref_id, project_id, kind, source, operation, result_status,\n\t\t\t\t\tlimit_value, query_text, expanded_at\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`,\n\t\t\t)\n\t\t\t.bind(\n\t\t\t\texpansionId(),\n\t\t\t\targs.refId,\n\t\t\t\targs.projectId,\n\t\t\t\targs.kind,\n\t\t\t\tsource?.source ?? null,\n\t\t\t\targs.operation,\n\t\t\t\targs.resultStatus,\n\t\t\t\targs.limit ?? null,\n\t\t\t\targs.query ?? null,\n\t\t\t)\n\t\t\t.run();\n\t} catch {\n\t\t// Best-effort telemetry must not break evidence expansion.\n\t}\n};\n\nconst materializeBundle = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tbundle: EvidenceBundle,\n): Promise<EvidenceBundle> => {\n\tawait materializeRetrievalRefs(db, projectId, bundle.retrievalRefs);\n\treturn bundle;\n};\n\nconst spanLabel = (span: TelemetrySpanDetail): string =>\n\t`${span.serviceName || \"unknown\"}:${span.spanName}`;\n\nconst failedSpans = (spans: TelemetrySpanDetail[]): TelemetrySpanDetail[] =>\n\tspans.filter((span) => span.statusCode > 1 || Boolean(span.statusMessage));\n\nconst criticalPath = (spans: TelemetrySpanDetail[]): TelemetrySpanDetail[] =>\n\t[...spans].sort((a, b) => b.durationMs - a.durationMs).slice(0, 5);\n\nconst normalizeLogSignature = (message: string): string =>\n\tmessage\n\t\t.toLowerCase()\n\t\t.replace(/[0-9a-f]{16,}/g, \"<hex>\")\n\t\t.replace(/\\b\\d+\\b/g, \"<num>\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\nconst clusterLogs = (\n\ttraceId: string,\n\tlogs: LogRecord[],\n\tlogsRefId: string,\n): { compactions: EvidenceCompaction[]; exemplars: LogRecord[] } => {\n\tconst bySignature = new Map<string, LogRecord[]>();\n\tfor (const log of logs) {\n\t\tconst signature = normalizeLogSignature(log.message);\n\t\tconst group = bySignature.get(signature) ?? [];\n\t\tgroup.push(log);\n\t\tbySignature.set(signature, group);\n\t}\n\n\tconst exemplars: LogRecord[] = [];\n\tconst compactions: EvidenceCompaction[] = [];\n\tfor (const [signature, group] of bySignature) {\n\t\tconst severitySorted = [...group].sort((a, b) => {\n\t\t\tconst severityOrder = { FATAL: 5, ERROR: 4, WARN: 3, INFO: 2, DEBUG: 1 };\n\t\t\treturn severityOrder[b.severity] - severityOrder[a.severity];\n\t\t});\n\t\tconst selected = severitySorted.slice(\n\t\t\t0,\n\t\t\tMath.min(3, severitySorted.length),\n\t\t);\n\t\texemplars.push(...selected);\n\t\tif (group.length > selected.length) {\n\t\t\tcompactions.push({\n\t\t\t\tcompactionId: `cmp_logs_${traceId}_${compactions.length + 1}`,\n\t\t\t\tkind: \"logs\",\n\t\t\t\tstrategy: \"signature_cluster\",\n\t\t\t\tinputCount: group.length,\n\t\t\t\toutputCount: selected.length,\n\t\t\t\treason: `Collapsed ${group.length} logs matching signature \"${signature}\" into ${selected.length} exemplar(s).`,\n\t\t\t\texemplarEntityIds: selected.map((log) => log.logId),\n\t\t\t\tretrievalRefIds: [logsRefId],\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { compactions, exemplars: exemplars.slice(0, 20) };\n};\n\nconst profilesForTrace = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\ttraceId: string,\n): Promise<ProfileEvidenceRow[]> => {\n\tconst rows = await db\n\t\t.prepare(\n\t\t\t`SELECT b.id, b.service_name, b.profile_type, b.start_ts, b.end_ts,\n\t\t\t\t\tb.duration_ms, b.blob_size_bytes, b.sample_count, b.agent,\n\t\t\t\t\tb.received_at, b.expires_at\n\t\t\t FROM profile_trace_index i\n\t\t\t JOIN profile_blobs b ON b.id = i.profile_id\n\t\t\t WHERE i.project_id = ? AND i.trace_id = ?\n\t\t\t ORDER BY b.end_ts DESC\n\t\t\t LIMIT 10`,\n\t\t)\n\t\t.bind(projectId, traceId)\n\t\t.all<ProfileEvidenceRow>();\n\treturn rows.results;\n};\n\nconst profileTraceIds = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tprofileId: string,\n): Promise<string[]> => {\n\tconst rows = await db\n\t\t.prepare(\n\t\t\t`SELECT trace_id FROM profile_trace_index\n\t\t\t WHERE profile_id = ? AND project_id = ?\n\t\t\t LIMIT 1000`,\n\t\t)\n\t\t.bind(profileId, projectId)\n\t\t.all<{ trace_id: string }>();\n\treturn rows.results.map((row) => row.trace_id);\n};\n\nconst replayBySession = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tsessionId: string,\n): Promise<ReplayEvidenceRow | null> =>\n\tdb\n\t\t.prepare(\n\t\t\t`SELECT session_id, visitor_id, first_chunk_at, last_chunk_at,\n\t\t\t\t\tchunk_count, events_count, storage_bytes\n\t\t\t FROM session_replay_metadata\n\t\t\t WHERE project_id = ? AND session_id = ?\n\t\t\t LIMIT 1`,\n\t\t)\n\t\t.bind(projectId, sessionId)\n\t\t.first<ReplayEvidenceRow>();\n\nconst replayEventWindow = async (\n\tbucket: R2Bucket,\n\tprojectId: string,\n\tsessionId: string,\n\tchunkOffset: number,\n\tchunkLimit: number,\n): Promise<{\n\tevents: Record<string, unknown>[];\n\tchunks: {\n\t\toffset: number;\n\t\tlimit: number;\n\t\treturned: number;\n\t\ttotal: number;\n\t\tnextChunkOffset: number | null;\n\t};\n}> => {\n\tconst prefix = `replays/${projectId}/${sessionId}/`;\n\tconst objects: Array<{ key: string }> = [];\n\tlet cursor: string | undefined;\n\tdo {\n\t\tconst page = await bucket.list({ prefix, cursor });\n\t\tobjects.push(...page.objects);\n\t\tcursor = page.truncated ? page.cursor : undefined;\n\t} while (cursor);\n\n\tobjects.sort((a, b) => a.key.localeCompare(b.key));\n\tconst offset = Math.max(0, chunkOffset);\n\tconst limit = Math.max(1, Math.min(MAX_REPLAY_EVENT_CHUNKS, chunkLimit));\n\tconst selectedObjects = objects.slice(offset, offset + limit);\n\treturn {\n\t\tevents: await fetchReplayChunks(bucket, selectedObjects),\n\t\tchunks: {\n\t\t\toffset,\n\t\t\tlimit,\n\t\t\treturned: selectedObjects.length,\n\t\t\ttotal: objects.length,\n\t\t\tnextChunkOffset: offset + limit < objects.length ? offset + limit : null,\n\t\t},\n\t};\n};\n\nconst aiCallById = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tcallId: string,\n): Promise<AICallEvidenceRow | null> =>\n\tdb\n\t\t.prepare(\n\t\t\t`SELECT call_id, trace_id, span_id, service_name, model_name, provider,\n\t\t\t\t\tcall_type, prompt_tokens, completion_tokens, total_cost_usd,\n\t\t\t\t\tlatency_ms, is_error, error_message, occurred_at, received_at,\n\t\t\t\t\texpires_at, interaction_id, session_id\n\t\t\t FROM ai_calls\n\t\t\t WHERE project_id = ? AND call_id = ?\n\t\t\t LIMIT 1`,\n\t\t)\n\t\t.bind(projectId, callId)\n\t\t.first<AICallEvidenceRow>();\n\nconst toolCallById = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\ttoolCallId: string,\n): Promise<ToolCallRef | null> => {\n\tconst row = await db\n\t\t.prepare(\n\t\t\t`SELECT * FROM tool_calls\n\t\t\t WHERE project_id = ? AND id = ?\n\t\t\t LIMIT 1`,\n\t\t)\n\t\t.bind(projectId, toolCallId)\n\t\t.first<{\n\t\t\tid: string;\n\t\t\taction_id: string;\n\t\t\tproject_id: string;\n\t\t\ttool_name: string;\n\t\t\targs_hash: string;\n\t\t\tresult_hash: string;\n\t\t\terror_type: string | null;\n\t\t\tside_effect: number;\n\t\t\tapproval_state: string | null;\n\t\t\targs_redacted: string | null;\n\t\t\tresult_redacted: string | null;\n\t\t\tmcp_audit_json: string | null;\n\t\t\tmutation_before_json: string | null;\n\t\t\tmutation_after_json: string | null;\n\t\t\tmutation_diff_json: string | null;\n\t\t\tmutation_artifact_id: string | null;\n\t\t}>();\n\tif (!row) return null;\n\treturn {\n\t\tid: row.id,\n\t\tactionId: row.action_id,\n\t\tprojectId: row.project_id,\n\t\ttoolName: row.tool_name,\n\t\targsHash: row.args_hash,\n\t\tresultHash: row.result_hash,\n\t\terrorType: row.error_type,\n\t\tsideEffect: row.side_effect,\n\t\tapprovalState: row.approval_state,\n\t\targsRedacted: row.args_redacted,\n\t\tresultRedacted: row.result_redacted,\n\t\tmcpAuditJson: row.mcp_audit_json,\n\t\tmutationBeforeJson: row.mutation_before_json,\n\t\tmutationAfterJson: row.mutation_after_json,\n\t\tmutationDiffJson: row.mutation_diff_json,\n\t\tmutationArtifactId: row.mutation_artifact_id,\n\t};\n};\n\nconst traceEvidenceReferences = (\n\tdetail: TelemetryTraceDetailResponse,\n\tlogExemplars: LogRecord[],\n\tprofiles: ProfileEvidenceRow[],\n): EvidenceReference[] => {\n\tconst traceId = detail.trace.traceId;\n\tconst refs: EvidenceReference[] = [\n\t\tevidenceRef(\n\t\t\t`trace:${traceId}`,\n\t\t\t\"trace\",\n\t\t\ttraceId,\n\t\t\ttraceRoute(traceId),\n\t\t\t\"evidence.bundle.trace\",\n\t\t\t1,\n\t\t\t`Trace ${traceId} contains ${detail.spans.length} span(s), with ${detail.trace.errorSpanCount} error span(s).`,\n\t\t\t[],\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Open trace\",\n\t\t\t\t\tentityKind: \"trace\",\n\t\t\t\t\tentityId: traceId,\n\t\t\t\t\troute: traceRoute(traceId),\n\t\t\t\t\treason: \"Inspect the full span tree.\",\n\t\t\t\t},\n\t\t\t],\n\t\t),\n\t];\n\n\tfor (const span of failedSpans(detail.spans).slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`span:${traceId}:${span.spanId}`,\n\t\t\t\t\"span\",\n\t\t\t\t`${traceId}:${span.spanId}`,\n\t\t\t\tspanRoute(traceId, span.spanId),\n\t\t\t\t\"evidence.bundle.failed_spans\",\n\t\t\t\t0.95,\n\t\t\t\t`Span ${spanLabel(span)} is marked as failed or has a status message.`,\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: `trace ${traceId}`,\n\t\t\t\t\t\tentityKind: \"trace\",\n\t\t\t\t\t\tentityId: traceId,\n\t\t\t\t\t\troute: traceRoute(traceId),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t),\n\t\t);\n\t}\n\n\tfor (const log of logExemplars.slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`log:${log.logId}`,\n\t\t\t\t\"log\",\n\t\t\t\tlog.logId,\n\t\t\t\tlogRoute(log.logId),\n\t\t\t\t\"evidence.bundle.log_exemplars\",\n\t\t\t\tlog.severity === \"ERROR\" || log.severity === \"FATAL\" ? 0.9 : 0.7,\n\t\t\t\t`${log.severity} log exemplar: ${log.message}`,\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: `trace ${traceId}`,\n\t\t\t\t\t\tentityKind: \"trace\",\n\t\t\t\t\t\tentityId: traceId,\n\t\t\t\t\t\troute: traceRoute(traceId),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t),\n\t\t);\n\t}\n\n\tfor (const profile of profiles.slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`profile:${profile.id}`,\n\t\t\t\t\"profile\",\n\t\t\t\tprofile.id,\n\t\t\t\tprofileRoute(profile.id, traceId),\n\t\t\t\t\"evidence.bundle.connected_profiles\",\n\t\t\t\t0.85,\n\t\t\t\t`${profile.profile_type} profile covers trace ${traceId} for ${profile.duration_ms}ms.`,\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: `trace ${traceId}`,\n\t\t\t\t\t\tentityKind: \"trace\",\n\t\t\t\t\t\tentityId: traceId,\n\t\t\t\t\t\troute: traceRoute(traceId),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t),\n\t\t);\n\t}\n\n\treturn refs;\n};\n\nconst buildTraceBundle = async (\n\tprojectId: string,\n\tdetail: TelemetryTraceDetailResponse,\n\tlogs: LogRecord[],\n\tprofiles: ProfileEvidenceRow[],\n\tintent: EvidenceBundleIntent,\n\ttargetTokens: number,\n\tdetailLevel: EvidenceBundleDetailLevel,\n\thours: number,\n): Promise<EvidenceBundle> => {\n\tconst traceId = detail.trace.traceId;\n\tconst traceRefId = encodeRef({ kind: \"trace\", projectId, traceId });\n\tconst logsRefId = encodeRef({\n\t\tkind: \"logs\",\n\t\tprojectId,\n\t\ttraceId,\n\t\thours,\n\t\tlimit: MAX_LOGS_FOR_RETRIEVAL,\n\t});\n\tconst { compactions, exemplars } = clusterLogs(traceId, logs, logsRefId);\n\tconst failed = failedSpans(detail.spans);\n\tconst critical = criticalPath(detail.spans);\n\tconst evidenceReferences = traceEvidenceReferences(\n\t\tdetail,\n\t\texemplars,\n\t\tprofiles,\n\t);\n\tconst retrievalRefs: EvidenceRetrievalRef[] = [\n\t\t{\n\t\t\trefId: traceRefId,\n\t\t\tkind: \"trace\",\n\t\t\tanchor: { entityKind: \"trace\", entityId: traceId },\n\t\t\tsource: \"evidence.bundle.trace_detail\",\n\t\t\tquery: { traceId },\n\t\t\tcompactedFrom: {\n\t\t\t\trecordCount: detail.spans.length,\n\t\t\t\ttokenEstimate: estimateTokens(detail),\n\t\t\t},\n\t\t\treturned: {\n\t\t\t\trecordCount: critical.length,\n\t\t\t\ttokenEstimate: estimateTokens(critical),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\trefId: logsRefId,\n\t\t\tkind: \"logs\",\n\t\t\tanchor: { entityKind: \"trace\", entityId: traceId },\n\t\t\tsource: \"evidence.bundle.correlated_logs\",\n\t\t\tquery: { traceId, hours, limit: MAX_LOGS_FOR_RETRIEVAL },\n\t\t\tcompactedFrom: {\n\t\t\t\trecordCount: logs.length,\n\t\t\t\ttokenEstimate: estimateTokens(logs),\n\t\t\t},\n\t\t\treturned: {\n\t\t\t\trecordCount: exemplars.length,\n\t\t\t\ttokenEstimate: estimateTokens(exemplars),\n\t\t\t},\n\t\t},\n\t\t...profiles.map(\n\t\t\t(profile): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({\n\t\t\t\t\tkind: \"profile\",\n\t\t\t\t\tprojectId,\n\t\t\t\t\ttraceId,\n\t\t\t\t\tprofileId: profile.id,\n\t\t\t\t\tprofileMode: \"metadata\",\n\t\t\t\t}),\n\t\t\t\tkind: \"profile\",\n\t\t\t\tanchor: { entityKind: \"trace\", entityId: traceId },\n\t\t\t\tsource: \"evidence.bundle.connected_profiles\",\n\t\t\t\tquery: { profileId: profile.id, traceId },\n\t\t\t\tcompactedFrom: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\tbyteEstimate: profile.blob_size_bytes,\n\t\t\t\t},\n\t\t\t\treturned: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\ttokenEstimate: estimateTokens(profile),\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t\t...profiles.map(\n\t\t\t(profile): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({\n\t\t\t\t\tkind: \"profile\",\n\t\t\t\t\tprojectId,\n\t\t\t\t\ttraceId,\n\t\t\t\t\tprofileId: profile.id,\n\t\t\t\t\tprofileMode: \"frames\",\n\t\t\t\t\tlimit: DEFAULT_PROFILE_FRAME_LIMIT,\n\t\t\t\t}),\n\t\t\t\tkind: \"profile\",\n\t\t\t\tanchor: { entityKind: \"trace\", entityId: traceId },\n\t\t\t\tsource: \"evidence.bundle.profile_frames\",\n\t\t\t\tquery: {\n\t\t\t\t\tprofileId: profile.id,\n\t\t\t\t\ttraceId,\n\t\t\t\t\tframeLimit: DEFAULT_PROFILE_FRAME_LIMIT,\n\t\t\t\t},\n\t\t\t\tcompactedFrom: {\n\t\t\t\t\trecordCount: profile.sample_count ?? undefined,\n\t\t\t\t\tbyteEstimate: profile.blob_size_bytes,\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t];\n\n\tconst suggestedNextPivots: EvidenceNextPivot[] = [\n\t\t{\n\t\t\tlabel: \"Inspect full trace\",\n\t\t\tentityKind: \"trace\",\n\t\t\tentityId: traceId,\n\t\t\troute: traceRoute(traceId),\n\t\t\treason:\n\t\t\t\t\"Retrieve the complete span tree if the critical path is insufficient.\",\n\t\t},\n\t];\n\n\tif (failed[0]) {\n\t\tsuggestedNextPivots.push({\n\t\t\tlabel: \"Inspect failed span\",\n\t\t\tentityKind: \"span\",\n\t\t\tentityId: `${traceId}:${failed[0].spanId}`,\n\t\t\troute: spanRoute(traceId, failed[0].spanId),\n\t\t\treason: \"Start with the failed span before expanding unrelated spans.\",\n\t\t});\n\t}\n\n\tif (profiles[0]) {\n\t\tsuggestedNextPivots.push({\n\t\t\tlabel: \"Inspect connected profile\",\n\t\t\tentityKind: \"profile\",\n\t\t\tentityId: profiles[0].id,\n\t\t\troute: profileRoute(profiles[0].id, traceId),\n\t\t\treason:\n\t\t\t\t\"Use the sampled profile to inspect code-level CPU or runtime hotspots.\",\n\t\t});\n\t}\n\n\tconst derivedSummaries = [\n\t\t{\n\t\t\ttitle: \"Trace critical path\",\n\t\t\treason:\n\t\t\t\tcritical.length > 0\n\t\t\t\t\t? `Top span by duration is ${spanLabel(critical[0])} at ${critical[0].durationMs}ms.`\n\t\t\t\t\t: \"Trace has no spans available for critical path computation.\",\n\t\t\tconfidence: critical.length > 0 ? 0.9 : 0.2,\n\t\t\tevidenceIds: critical.map((span) => `span:${traceId}:${span.spanId}`),\n\t\t\tretrievalRefIds: [traceRefId],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Correlated logs\",\n\t\t\treason:\n\t\t\t\tlogs.length > exemplars.length\n\t\t\t\t\t? `${logs.length} correlated log(s) were reduced to ${exemplars.length} exemplar(s).`\n\t\t\t\t\t: `${logs.length} correlated log(s) were included without lossy compaction.`,\n\t\t\tconfidence: 0.85,\n\t\t\tevidenceIds: exemplars.map((log) => `log:${log.logId}`),\n\t\t\tretrievalRefIds: [logsRefId],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Connected profiles\",\n\t\t\treason:\n\t\t\t\tprofiles.length > 0\n\t\t\t\t\t? `${profiles.length} profile(s) are indexed to this trace.`\n\t\t\t\t\t: \"No profile metadata is indexed to this trace.\",\n\t\t\tconfidence: profiles.length > 0 ? 0.85 : 0.5,\n\t\t\tevidenceIds: profiles.map((profile) => `profile:${profile.id}`),\n\t\t\tretrievalRefIds: retrievalRefs\n\t\t\t\t.filter((ref) => ref.kind === \"profile\")\n\t\t\t\t.map((ref) => ref.refId),\n\t\t},\n\t];\n\n\tconst findings =\n\t\tfailed.length > 0\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\ttitle: \"Failed span present\",\n\t\t\t\t\t\treason: `Trace contains ${failed.length} failed or status-message span(s).`,\n\t\t\t\t\t\tconfidence: 0.9,\n\t\t\t\t\t\tevidenceIds: failed\n\t\t\t\t\t\t\t.slice(0, 5)\n\t\t\t\t\t\t\t.map((span) => `span:${traceId}:${span.spanId}`),\n\t\t\t\t\t\tretrievalRefIds: [traceRefId],\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: [];\n\n\tconst bundle: EvidenceBundle = {\n\t\tschemaVersion: BUNDLE_SCHEMA_VERSION,\n\t\tintent,\n\t\tanchor: { entityKind: \"trace\", entityId: traceId },\n\t\tbudget: {\n\t\t\ttargetTokens,\n\t\t\tdetailLevel,\n\t\t},\n\t\tsummary:\n\t\t\tfailed.length > 0\n\t\t\t\t? `Trace ${traceId} has ${failed.length} failed/status span(s), ${detail.spans.length} total span(s), ${logs.length} correlated log(s), and ${profiles.length} connected profile(s).`\n\t\t\t\t: `Trace ${traceId} has ${detail.spans.length} span(s), ${logs.length} correlated log(s), and ${profiles.length} connected profile(s); no failed spans were detected.`,\n\t\tderivedSummaries,\n\t\tfindings,\n\t\tcompactions,\n\t\tevidenceReferences,\n\t\tretrievalRefs,\n\t\tsuggestedNextPivots,\n\t};\n\tbundle.budget = {\n\t\ttargetTokens,\n\t\tdetailLevel,\n\t\testimatedTokens: estimateTokens(bundle),\n\t};\n\treturn bundle;\n};\n\nconst actionGraphRouteFor = (\n\tkind: \"action\" | \"agent_run\" | \"tool_call\",\n\tid: string,\n) => {\n\tswitch (kind) {\n\t\tcase \"action\":\n\t\t\treturn actionRoute(id);\n\t\tcase \"agent_run\":\n\t\t\treturn agentRunRoute(id);\n\t\tcase \"tool_call\":\n\t\t\treturn toolCallRoute(id);\n\t}\n};\n\nconst loadManifestForAnchor = async (\n\tdb: SqlDb,\n\tprojectId: string,\n\tkind: \"action\" | \"agent_run\" | \"tool_call\",\n\tid: string,\n): Promise<{ manifest: EntityManifestExtended; found: boolean }> => {\n\tconst index = new IdentityIndex(db);\n\tif (kind === \"action\") {\n\t\tconst manifest = await index.byAction(projectId, id);\n\t\treturn {\n\t\t\tmanifest,\n\t\t\tfound: manifest.actions.some((action) => action.id === id),\n\t\t};\n\t}\n\tif (kind === \"agent_run\") {\n\t\tconst manifest = await index.byAgentRun(projectId, id);\n\t\treturn {\n\t\t\tmanifest,\n\t\t\tfound: manifest.agentRuns.some((run) => run.id === id),\n\t\t};\n\t}\n\n\tconst toolCallRow = await db\n\t\t.prepare(\n\t\t\t`SELECT action_id FROM tool_calls\n\t\t\t WHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t)\n\t\t.bind(projectId, id)\n\t\t.first<{ action_id: string }>();\n\tif (!toolCallRow) {\n\t\treturn {\n\t\t\tmanifest: await index.byAction(projectId, \"__missing__\"),\n\t\t\tfound: false,\n\t\t};\n\t}\n\tconst manifest = await index.byAction(projectId, toolCallRow.action_id);\n\treturn {\n\t\tmanifest,\n\t\tfound: manifest.toolCalls.some((tool) => tool.id === id),\n\t};\n};\n\nconst causalPath = (manifest: EntityManifestExtended): ActionRef[] => {\n\tconst byId = new Map(manifest.actions.map((action) => [action.id, action]));\n\tconst roots = manifest.actions.filter(\n\t\t(action) => !action.causedByActionId || !byId.has(action.causedByActionId),\n\t);\n\tconst root = roots[0] ?? manifest.actions[0];\n\tif (!root) return [];\n\n\tconst children = new Map<string, ActionRef[]>();\n\tfor (const action of manifest.actions) {\n\t\tif (!action.causedByActionId) continue;\n\t\tconst list = children.get(action.causedByActionId) ?? [];\n\t\tlist.push(action);\n\t\tchildren.set(action.causedByActionId, list);\n\t}\n\n\tconst path: ActionRef[] = [];\n\tlet current: ActionRef | undefined = root;\n\twhile (current) {\n\t\tpath.push(current);\n\t\tconst nextChildren: ActionRef[] | undefined = children\n\t\t\t.get(current.id)\n\t\t\t?.sort((a, b) => {\n\t\t\t\tconst status = Number(b.status !== \"ok\") - Number(a.status !== \"ok\");\n\t\t\t\tif (status !== 0) return status;\n\t\t\t\treturn (b.durationMs ?? 0) - (a.durationMs ?? 0);\n\t\t\t});\n\t\tcurrent = nextChildren?.[0];\n\t}\n\treturn path;\n};\n\nconst actionEvidenceReferences = (\n\tanchorKind: \"action\" | \"agent_run\" | \"tool_call\",\n\tanchorId: string,\n\tmanifest: EntityManifestExtended,\n\tprofiles: ProfileEvidenceRow[],\n): EvidenceReference[] => {\n\tconst refs: EvidenceReference[] = [\n\t\tevidenceRef(\n\t\t\t`${anchorKind}:${anchorId}`,\n\t\t\tanchorKind,\n\t\t\tanchorId,\n\t\t\tactionGraphRouteFor(anchorKind, anchorId),\n\t\t\t\"evidence.bundle.action_graph\",\n\t\t\t1,\n\t\t\t`Action graph bundle for ${anchorKind} ${anchorId} includes ${manifest.actions.length} action(s), ${manifest.toolCalls.length} tool call(s), and ${manifest.evalResults.length} eval result(s).`,\n\t\t),\n\t];\n\n\tfor (const tool of manifest.toolCalls.slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`tool_call:${tool.id}`,\n\t\t\t\t\"tool_call\",\n\t\t\t\ttool.id,\n\t\t\t\ttoolCallRoute(tool.id),\n\t\t\t\t\"evidence.bundle.tool_calls\",\n\t\t\t\ttool.sideEffect ? 0.95 : 0.8,\n\t\t\t\t`Tool ${tool.toolName} sideEffect=${Boolean(tool.sideEffect)} approvalState=${tool.approvalState ?? \"unknown\"}.`,\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: `action ${tool.actionId}`,\n\t\t\t\t\t\tentityKind: \"action\",\n\t\t\t\t\t\tentityId: tool.actionId,\n\t\t\t\t\t\troute: actionRoute(tool.actionId),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t),\n\t\t);\n\t}\n\n\tfor (const aiCall of manifest.aiCalls.slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`ai_call:${aiCall.callId}`,\n\t\t\t\t\"ai_call\",\n\t\t\t\taiCall.callId,\n\t\t\t\taiCallRoute(aiCall.callId),\n\t\t\t\t\"evidence.bundle.ai_calls\",\n\t\t\t\t0.85,\n\t\t\t\t`AI call ${aiCall.provider}/${aiCall.modelName} cost=${(aiCall.totalCostUsd ?? 0).toFixed(6)} USD.`,\n\t\t\t\taiCall.traceId\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: `trace ${aiCall.traceId}`,\n\t\t\t\t\t\t\t\tentityKind: \"trace\",\n\t\t\t\t\t\t\t\tentityId: aiCall.traceId,\n\t\t\t\t\t\t\t\troute: traceRoute(aiCall.traceId),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [],\n\t\t\t),\n\t\t);\n\t}\n\n\tif (manifest.replay) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`replay:${manifest.replay.sessionId}`,\n\t\t\t\t\"replay\",\n\t\t\t\tmanifest.replay.sessionId,\n\t\t\t\treplayRoute(manifest.replay.sessionId),\n\t\t\t\t\"evidence.bundle.session_replay\",\n\t\t\t\t0.8,\n\t\t\t\t`Session replay has ${manifest.replay.eventsCount} event(s) across ${manifest.replay.chunkCount} chunk(s).`,\n\t\t\t),\n\t\t);\n\t}\n\n\tfor (const profile of profiles.slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`profile:${profile.id}`,\n\t\t\t\t\"profile\",\n\t\t\t\tprofile.id,\n\t\t\t\tprofileRoute(profile.id),\n\t\t\t\t\"evidence.bundle.connected_profiles\",\n\t\t\t\t0.8,\n\t\t\t\t`${profile.profile_type} profile is connected through this action graph's traces.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tfor (const evalResult of manifest.evalResults.slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`eval:${evalResult.id}`,\n\t\t\t\t\"eval\",\n\t\t\t\tevalResult.id,\n\t\t\t\t`#/evals/${encodeURIComponent(evalResult.id)}`,\n\t\t\t\t\"evidence.bundle.eval_results\",\n\t\t\t\tevalResult.passed ? 0.75 : 0.9,\n\t\t\t\t`Eval ${evalResult.evaluatorName} ${evalResult.passed ? \"passed\" : \"failed\"}${evalResult.score === null ? \"\" : ` with score ${evalResult.score}`}.`,\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: `action ${evalResult.actionId}`,\n\t\t\t\t\t\tentityKind: \"action\",\n\t\t\t\t\t\tentityId: evalResult.actionId,\n\t\t\t\t\t\troute: actionRoute(evalResult.actionId),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t),\n\t\t);\n\t}\n\n\tfor (const span of manifest.spans.slice(0, 5)) {\n\t\trefs.push(\n\t\t\tevidenceRef(\n\t\t\t\t`span:${span.traceId}:${span.spanId}`,\n\t\t\t\t\"span\",\n\t\t\t\t`${span.traceId}:${span.spanId}`,\n\t\t\t\tspanRoute(span.traceId, span.spanId),\n\t\t\t\t\"evidence.bundle.connected_spans\",\n\t\t\t\tspan.statusCode > 1 ? 0.9 : 0.7,\n\t\t\t\t`Connected span ${span.serviceName ?? \"unknown\"}:${span.spanName} status=${span.statusCode}.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn refs;\n};\n\nconst buildActionGraphBundle = (\n\tprojectId: string,\n\tanchorKind: \"action\" | \"agent_run\" | \"tool_call\",\n\tanchorId: string,\n\tmanifest: EntityManifestExtended,\n\tprofiles: ProfileEvidenceRow[],\n\tintent: EvidenceBundleIntent,\n\ttargetTokens: number,\n\tdetailLevel: EvidenceBundleDetailLevel,\n): EvidenceBundle => {\n\tconst graphRefId = encodeRef({\n\t\tkind: \"action_graph\",\n\t\tprojectId,\n\t\ttraceId: manifest.spans[0]?.traceId,\n\t\tanchorKind,\n\t\tanchorId,\n\t});\n\tconst traceIds = Array.from(\n\t\tnew Set(\n\t\t\t[\n\t\t\t\t...manifest.spans.map((span) => span.traceId),\n\t\t\t\t...manifest.logs.map((log) => log.traceId),\n\t\t\t\t...manifest.actions.map((action) => action.traceId),\n\t\t\t].filter((id): id is string => Boolean(id)),\n\t\t),\n\t).slice(0, 5);\n\tconst retrievalRefs: EvidenceRetrievalRef[] = [\n\t\t{\n\t\t\trefId: graphRefId,\n\t\t\tkind: anchorKind,\n\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\tsource: \"evidence.bundle.action_graph_manifest\",\n\t\t\tquery: { anchorKind, anchorId },\n\t\t\tcompactedFrom: {\n\t\t\t\trecordCount:\n\t\t\t\t\tmanifest.actions.length +\n\t\t\t\t\tmanifest.toolCalls.length +\n\t\t\t\t\tmanifest.evalResults.length +\n\t\t\t\t\tmanifest.logs.length +\n\t\t\t\t\tmanifest.spans.length +\n\t\t\t\t\tmanifest.aiCalls.length +\n\t\t\t\t\t(manifest.replay ? 1 : 0) +\n\t\t\t\t\tprofiles.length,\n\t\t\t\ttokenEstimate: estimateTokens(manifest),\n\t\t\t},\n\t\t\treturned: {\n\t\t\t\trecordCount: causalPath(manifest).length,\n\t\t\t\ttokenEstimate: estimateTokens(causalPath(manifest)),\n\t\t\t},\n\t\t},\n\t\t...traceIds.map(\n\t\t\t(traceId): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({ kind: \"trace\", projectId, traceId }),\n\t\t\t\tkind: \"trace\",\n\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\tsource: \"evidence.bundle.connected_traces\",\n\t\t\t\tquery: { traceId },\n\t\t\t}),\n\t\t),\n\t\t...traceIds.map(\n\t\t\t(traceId): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({\n\t\t\t\t\tkind: \"logs\",\n\t\t\t\t\tprojectId,\n\t\t\t\t\ttraceId,\n\t\t\t\t\thours: DEFAULT_HOURS,\n\t\t\t\t\tlimit: MAX_LOGS_FOR_RETRIEVAL,\n\t\t\t\t}),\n\t\t\t\tkind: \"logs\",\n\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\tsource: \"evidence.bundle.connected_logs\",\n\t\t\t\tquery: { traceId, hours: DEFAULT_HOURS, limit: MAX_LOGS_FOR_RETRIEVAL },\n\t\t\t}),\n\t\t),\n\t\t...manifest.toolCalls.map(\n\t\t\t(tool): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({ kind: \"tool_call\", projectId, toolCallId: tool.id }),\n\t\t\t\tkind: \"tool_call\",\n\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\tsource: \"evidence.bundle.tool_call_payloads\",\n\t\t\t\tquery: { toolCallId: tool.id },\n\t\t\t\tcompactedFrom: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\ttokenEstimate: estimateTokens(tool),\n\t\t\t\t},\n\t\t\t\treturned: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\ttokenEstimate: estimateTokens({\n\t\t\t\t\t\tid: tool.id,\n\t\t\t\t\t\ttoolName: tool.toolName,\n\t\t\t\t\t\targsHash: tool.argsHash,\n\t\t\t\t\t\tresultHash: tool.resultHash,\n\t\t\t\t\t\targsRedacted: tool.argsRedacted,\n\t\t\t\t\t\tresultRedacted: tool.resultRedacted,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t\t...manifest.aiCalls.map(\n\t\t\t(aiCall): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({ kind: \"ai_call\", projectId, callId: aiCall.callId }),\n\t\t\t\tkind: \"ai_call\",\n\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\tsource: \"evidence.bundle.ai_calls\",\n\t\t\t\tquery: { callId: aiCall.callId },\n\t\t\t\tcompactedFrom: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\ttokenEstimate: estimateTokens(aiCall),\n\t\t\t\t},\n\t\t\t\treturned: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\ttokenEstimate: estimateTokens(aiCall),\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t\t...(manifest.replay\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\trefId: encodeRef({\n\t\t\t\t\t\t\tkind: \"replay\" as const,\n\t\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\t\tsessionId: manifest.replay.sessionId,\n\t\t\t\t\t\t\treplayMode: \"metadata\" as const,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tkind: \"replay\" as const,\n\t\t\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\t\t\tsource: \"evidence.bundle.session_replay\",\n\t\t\t\t\t\tquery: { sessionId: manifest.replay.sessionId },\n\t\t\t\t\t\tcompactedFrom: {\n\t\t\t\t\t\t\trecordCount: manifest.replay.eventsCount,\n\t\t\t\t\t\t},\n\t\t\t\t\t\treturned: {\n\t\t\t\t\t\t\trecordCount: 1,\n\t\t\t\t\t\t\ttokenEstimate: estimateTokens(manifest.replay),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: []),\n\t\t...(manifest.replay\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\trefId: encodeRef({\n\t\t\t\t\t\t\tkind: \"replay\" as const,\n\t\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\t\tsessionId: manifest.replay.sessionId,\n\t\t\t\t\t\t\treplayMode: \"events\" as const,\n\t\t\t\t\t\t\tchunkOffset: 0,\n\t\t\t\t\t\t\tlimit: DEFAULT_REPLAY_EVENT_CHUNKS,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tkind: \"replay\" as const,\n\t\t\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\t\t\tsource: \"evidence.bundle.replay_event_window\",\n\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\tsessionId: manifest.replay.sessionId,\n\t\t\t\t\t\t\tchunkOffset: 0,\n\t\t\t\t\t\t\tchunkLimit: DEFAULT_REPLAY_EVENT_CHUNKS,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcompactedFrom: {\n\t\t\t\t\t\t\trecordCount: manifest.replay.eventsCount,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: []),\n\t\t...profiles.map(\n\t\t\t(profile): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({\n\t\t\t\t\tkind: \"profile\",\n\t\t\t\t\tprojectId,\n\t\t\t\t\tprofileId: profile.id,\n\t\t\t\t\tprofileMode: \"metadata\",\n\t\t\t\t}),\n\t\t\t\tkind: \"profile\",\n\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\tsource: \"evidence.bundle.connected_profiles\",\n\t\t\t\tquery: { profileId: profile.id },\n\t\t\t\tcompactedFrom: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\tbyteEstimate: profile.blob_size_bytes,\n\t\t\t\t},\n\t\t\t\treturned: {\n\t\t\t\t\trecordCount: 1,\n\t\t\t\t\ttokenEstimate: estimateTokens(profile),\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t\t...profiles.map(\n\t\t\t(profile): EvidenceRetrievalRef => ({\n\t\t\t\trefId: encodeRef({\n\t\t\t\t\tkind: \"profile\",\n\t\t\t\t\tprojectId,\n\t\t\t\t\tprofileId: profile.id,\n\t\t\t\t\tprofileMode: \"frames\",\n\t\t\t\t\tlimit: DEFAULT_PROFILE_FRAME_LIMIT,\n\t\t\t\t}),\n\t\t\t\tkind: \"profile\",\n\t\t\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\t\t\tsource: \"evidence.bundle.profile_frames\",\n\t\t\t\tquery: {\n\t\t\t\t\tprofileId: profile.id,\n\t\t\t\t\tframeLimit: DEFAULT_PROFILE_FRAME_LIMIT,\n\t\t\t\t},\n\t\t\t\tcompactedFrom: {\n\t\t\t\t\trecordCount: profile.sample_count ?? undefined,\n\t\t\t\t\tbyteEstimate: profile.blob_size_bytes,\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t];\n\n\tconst path = causalPath(manifest);\n\tconst sideEffectTools = manifest.toolCalls.filter((tool) => tool.sideEffect);\n\tconst failedEvals = manifest.evalResults.filter(\n\t\t(evalResult) => !evalResult.passed,\n\t);\n\tconst failedActions = manifest.actions.filter(\n\t\t(action) => action.status !== \"ok\",\n\t);\n\tconst totalCost = manifest.aiCalls.reduce(\n\t\t(sum, call) => sum + (call.totalCostUsd ?? 0),\n\t\tmanifest.agentRuns.reduce(\n\t\t\t(sum, run) => sum + (run.totalCostUsd ?? 0),\n\t\t\tmanifest.actions.reduce(\n\t\t\t\t(sum, action) => sum + (action.totalCostUsd ?? 0),\n\t\t\t\t0,\n\t\t\t),\n\t\t),\n\t);\n\tconst evidenceReferences = actionEvidenceReferences(\n\t\tanchorKind,\n\t\tanchorId,\n\t\tmanifest,\n\t\tprofiles,\n\t);\n\tconst suggestedNextPivots: EvidenceNextPivot[] = [\n\t\t{\n\t\t\tlabel: \"Inspect action graph\",\n\t\t\tentityKind: anchorKind,\n\t\t\tentityId: anchorId,\n\t\t\troute: actionGraphRouteFor(anchorKind, anchorId),\n\t\t\treason: \"Expand the full causal action graph and connected signals.\",\n\t\t},\n\t\t...traceIds.slice(0, 3).map(\n\t\t\t(traceId): EvidenceNextPivot => ({\n\t\t\t\tlabel: \"Inspect connected trace\",\n\t\t\t\tentityKind: \"trace\",\n\t\t\t\tentityId: traceId,\n\t\t\t\troute: traceRoute(traceId),\n\t\t\t\treason:\n\t\t\t\t\t\"Inspect backend spans and logs connected to this action graph.\",\n\t\t\t}),\n\t\t),\n\t];\n\n\tif (manifest.replay) {\n\t\tsuggestedNextPivots.push({\n\t\t\tlabel: \"Inspect session replay\",\n\t\t\tentityKind: \"replay\",\n\t\t\tentityId: manifest.replay.sessionId,\n\t\t\troute: replayRoute(manifest.replay.sessionId),\n\t\t\treason: \"Inspect the user-visible path that led into the action graph.\",\n\t\t});\n\t}\n\n\tif (profiles[0]) {\n\t\tsuggestedNextPivots.push({\n\t\t\tlabel: \"Inspect connected profile\",\n\t\t\tentityKind: \"profile\",\n\t\t\tentityId: profiles[0].id,\n\t\t\troute: profileRoute(profiles[0].id),\n\t\t\treason: \"Inspect runtime hotspots connected through the graph traces.\",\n\t\t});\n\t}\n\n\tconst derivedSummaries = [\n\t\t{\n\t\t\ttitle: \"Causal action path\",\n\t\t\treason:\n\t\t\t\tpath.length > 0\n\t\t\t\t\t? `Representative causal path has ${path.length} action(s): ${path.map((action) => action.actionKind).join(\" -> \")}.`\n\t\t\t\t\t: \"No actions were available for causal path extraction.\",\n\t\t\tconfidence: path.length > 0 ? 0.9 : 0.2,\n\t\t\tevidenceIds: path.map((action) => `action:${action.id}`),\n\t\t\tretrievalRefIds: [graphRefId],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Tool side effects\",\n\t\t\treason:\n\t\t\t\tsideEffectTools.length > 0\n\t\t\t\t\t? `${sideEffectTools.length} side-effecting tool call(s) are connected to this graph.`\n\t\t\t\t\t: \"No side-effecting tool calls are connected to this graph.\",\n\t\t\tconfidence: manifest.toolCalls.length > 0 ? 0.9 : 0.6,\n\t\t\tevidenceIds: sideEffectTools.map((tool) => `tool_call:${tool.id}`),\n\t\t\tretrievalRefIds: [graphRefId],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Cost and model context\",\n\t\t\treason: `Connected agent/action/AI records report total cost ${totalCost.toFixed(6)} USD across ${manifest.agentRuns.length} agent run(s) and ${manifest.aiCalls.length} AI call(s).`,\n\t\t\tconfidence:\n\t\t\t\tmanifest.agentRuns.length > 0 || manifest.actions.length > 0\n\t\t\t\t\t? 0.8\n\t\t\t\t\t: 0.3,\n\t\t\tevidenceIds: [\n\t\t\t\t...manifest.agentRuns.map((run) => `agent_run:${run.id}`),\n\t\t\t\t...manifest.aiCalls.map((call) => `ai_call:${call.callId}`),\n\t\t\t],\n\t\t\tretrievalRefIds: [graphRefId],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Replay and profile pivots\",\n\t\t\treason: `${manifest.replay ? \"One session replay\" : \"No session replay\"} and ${profiles.length} connected profile(s) are available for this graph.`,\n\t\t\tconfidence: manifest.replay || profiles.length > 0 ? 0.8 : 0.45,\n\t\t\tevidenceIds: [\n\t\t\t\t...(manifest.replay ? [`replay:${manifest.replay.sessionId}`] : []),\n\t\t\t\t...profiles.map((profile) => `profile:${profile.id}`),\n\t\t\t],\n\t\t\tretrievalRefIds: retrievalRefs\n\t\t\t\t.filter((ref) => ref.kind === \"replay\" || ref.kind === \"profile\")\n\t\t\t\t.map((ref) => ref.refId),\n\t\t},\n\t];\n\n\tconst findings = [\n\t\t...sideEffectTools.map((tool) => ({\n\t\t\ttitle: \"Side-effecting tool call present\",\n\t\t\treason: `Tool ${tool.toolName} can mutate state and has approvalState=${tool.approvalState ?? \"unknown\"}.`,\n\t\t\tconfidence: 0.9,\n\t\t\tevidenceIds: [`tool_call:${tool.id}`],\n\t\t\tretrievalRefIds: [graphRefId],\n\t\t})),\n\t\t...failedEvals.map((evalResult) => ({\n\t\t\ttitle: \"Failed eval present\",\n\t\t\treason: `Eval ${evalResult.evaluatorName} failed${evalResult.reasoning ? `: ${evalResult.reasoning}` : \".\"}`,\n\t\t\tconfidence: 0.9,\n\t\t\tevidenceIds: [`eval:${evalResult.id}`],\n\t\t\tretrievalRefIds: [graphRefId],\n\t\t})),\n\t\t...failedActions.slice(0, 3).map((action) => ({\n\t\t\ttitle: \"Non-ok action present\",\n\t\t\treason: `Action ${action.id} has status ${action.status}.`,\n\t\t\tconfidence: 0.85,\n\t\t\tevidenceIds: [`action:${action.id}`],\n\t\t\tretrievalRefIds: [graphRefId],\n\t\t})),\n\t\t...manifest.aiCalls\n\t\t\t.filter((call) => (call.totalCostUsd ?? 0) > 0)\n\t\t\t.slice(0, 3)\n\t\t\t.map((call) => ({\n\t\t\t\ttitle: \"AI call cost present\",\n\t\t\t\treason: `AI call ${call.callId} reports cost ${(call.totalCostUsd ?? 0).toFixed(6)} USD.`,\n\t\t\t\tconfidence: 0.75,\n\t\t\t\tevidenceIds: [`ai_call:${call.callId}`],\n\t\t\t\tretrievalRefIds: retrievalRefs\n\t\t\t\t\t.filter((ref) => ref.kind === \"ai_call\")\n\t\t\t\t\t.map((ref) => ref.refId),\n\t\t\t})),\n\t];\n\n\tconst bundle: EvidenceBundle = {\n\t\tschemaVersion: BUNDLE_SCHEMA_VERSION,\n\t\tintent,\n\t\tanchor: { entityKind: anchorKind, entityId: anchorId },\n\t\tbudget: { targetTokens, detailLevel },\n\t\tsummary: `${anchorKind} ${anchorId} bundle includes ${manifest.actions.length} action(s), ${manifest.toolCalls.length} tool call(s), ${manifest.evalResults.length} eval result(s), ${manifest.spans.length} span(s), ${manifest.logs.length} log(s), ${manifest.aiCalls.length} AI call(s), ${profiles.length} profile(s), and ${manifest.replay ? 1 : 0} replay(s).`,\n\t\tderivedSummaries,\n\t\tfindings,\n\t\tcompactions: [],\n\t\tevidenceReferences,\n\t\tretrievalRefs,\n\t\tsuggestedNextPivots,\n\t};\n\tbundle.budget = {\n\t\ttargetTokens,\n\t\tdetailLevel,\n\t\testimatedTokens: estimateTokens(bundle),\n\t};\n\treturn bundle;\n};\n\nconst parseBundleRequest = async (request: Request) => {\n\ttry {\n\t\tconst body = await request.json();\n\t\treturn body && typeof body === \"object\"\n\t\t\t? (body as Record<string, unknown>)\n\t\t\t: {};\n\t} catch {\n\t\treturn {};\n\t}\n};\n\nexport const evidenceRetrievalRoutesPlugin: CollectorPlugin = {\n\tname: \"evidence-retrieval-routes\",\n\tregister(app, runtime) {\n\t\tapp.post(\"/internal/evidence/bundle\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst body = await parseBundleRequest(c.req.raw);\n\t\t\tconst anchor = body.anchor as\n\t\t\t\t| { entityKind?: unknown; entityId?: unknown }\n\t\t\t\t| undefined;\n\t\t\tif (!anchor || typeof anchor.entityId !== \"string\" || !anchor.entityId) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: \"Bad Request\",\n\t\t\t\t\t\tmessage: \"anchor.entityKind and anchor.entityId are required.\",\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst intent =\n\t\t\t\ttypeof body.intent === \"string\" &&\n\t\t\t\tEVIDENCE_INTENTS.has(body.intent as EvidenceBundleIntent)\n\t\t\t\t\t? (body.intent as EvidenceBundleIntent)\n\t\t\t\t\t: \"debug_failure\";\n\t\t\tconst budget = body.budget as Record<string, unknown> | undefined;\n\t\t\tconst targetTokens = clampInt(\n\t\t\t\tbudget?.targetTokens,\n\t\t\t\t500,\n\t\t\t\t30000,\n\t\t\t\tDEFAULT_TARGET_TOKENS,\n\t\t\t);\n\t\t\tconst detailLevel =\n\t\t\t\tbudget?.detailLevel === \"brief\" ||\n\t\t\t\tbudget?.detailLevel === \"standard\" ||\n\t\t\t\tbudget?.detailLevel === \"deep\"\n\t\t\t\t\t? budget.detailLevel\n\t\t\t\t\t: \"standard\";\n\t\t\tconst hours = clampInt(body.hours, 1, 720, DEFAULT_HOURS);\n\t\t\tconst db = runtime.getSqlDb(c.env);\n\t\t\tif (\n\t\t\t\tanchor.entityKind === \"action\" ||\n\t\t\t\tanchor.entityKind === \"agent_run\" ||\n\t\t\t\tanchor.entityKind === \"tool_call\"\n\t\t\t) {\n\t\t\t\tconst { manifest, found } = await loadManifestForAnchor(\n\t\t\t\t\tdb,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tanchor.entityKind,\n\t\t\t\t\tanchor.entityId,\n\t\t\t\t);\n\t\t\t\tif (!found) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror: \"Not Found\",\n\t\t\t\t\t\t\tmessage: `${anchor.entityKind} not found`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst traceIds = Array.from(\n\t\t\t\t\tnew Set(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t...manifest.spans.map((span) => span.traceId),\n\t\t\t\t\t\t\t...manifest.logs.map((log) => log.traceId),\n\t\t\t\t\t\t\t...manifest.actions.map((action) => action.traceId),\n\t\t\t\t\t\t].filter((id): id is string => Boolean(id)),\n\t\t\t\t\t),\n\t\t\t\t).slice(0, 5);\n\t\t\t\tconst profiles = (\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\ttraceIds.map((traceId) => profilesForTrace(db, projectId, traceId)),\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t\t\t.flat()\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(profile, index, all) =>\n\t\t\t\t\t\t\tall.findIndex((candidate) => candidate.id === profile.id) ===\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t);\n\t\t\t\tconst bundle = buildActionGraphBundle(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tanchor.entityKind,\n\t\t\t\t\tanchor.entityId,\n\t\t\t\t\tmanifest,\n\t\t\t\t\tprofiles,\n\t\t\t\t\tintent,\n\t\t\t\t\ttargetTokens,\n\t\t\t\t\tdetailLevel,\n\t\t\t\t);\n\t\t\t\treturn c.json(await materializeBundle(db, projectId, bundle));\n\t\t\t}\n\n\t\t\tif (anchor.entityKind !== \"trace\") {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: \"Bad Request\",\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\"Supported evidence bundle anchors are trace, action, agent_run, and tool_call.\",\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst traceId = anchor.entityId;\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\tconst detail = await store.getTraceDetail(traceId, projectId);\n\t\t\tif (!detail) {\n\t\t\t\treturn c.json({ error: \"Not Found\", message: \"Trace not found\" }, 404);\n\t\t\t}\n\n\t\t\tconst logs = await new LogsStore(db).getLogs({\n\t\t\t\tprojectId,\n\t\t\t\ttraceId,\n\t\t\t\thours,\n\t\t\t\tlimit: MAX_LOGS_FOR_BUNDLE,\n\t\t\t});\n\t\t\tconst profiles = await profilesForTrace(db, projectId, traceId);\n\t\t\tconst bundle = await buildTraceBundle(\n\t\t\t\tprojectId,\n\t\t\t\tdetail,\n\t\t\t\tlogs.logs,\n\t\t\t\tprofiles,\n\t\t\t\tintent,\n\t\t\t\ttargetTokens,\n\t\t\t\tdetailLevel,\n\t\t\t\thours,\n\t\t\t);\n\t\t\treturn c.json(await materializeBundle(db, projectId, bundle));\n\t\t});\n\n\t\tapp.get(\"/internal/evidence/stats\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst db = runtime.getSqlDb(c.env);\n\t\t\tconst limit = clampInt(c.req.query(\"limit\"), 1, 100, 20);\n\t\t\ttry {\n\t\t\t\tconst [byKind, bySource, recentRefs, recentExpansions] =\n\t\t\t\t\tawait Promise.all([\n\t\t\t\t\t\tdb\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT\n\t\t\t\t\t\t\t\tr.kind AS kind,\n\t\t\t\t\t\t\t\tCOUNT(DISTINCT r.ref_id) AS issuedCount,\n\t\t\t\t\t\t\t\tCOUNT(e.id) AS expansionCount\n\t\t\t\t\t\t\t FROM evidence_retrieval_refs r\n\t\t\t\t\t\t\t LEFT JOIN evidence_ref_expansions e\n\t\t\t\t\t\t\t\tON e.project_id = r.project_id AND e.ref_id = r.ref_id\n\t\t\t\t\t\t\t WHERE r.project_id = ?\n\t\t\t\t\t\t\t GROUP BY r.kind\n\t\t\t\t\t\t\t ORDER BY expansionCount DESC, issuedCount DESC`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(projectId)\n\t\t\t\t\t\t\t.all<{\n\t\t\t\t\t\t\t\tkind: string;\n\t\t\t\t\t\t\t\tissuedCount: number;\n\t\t\t\t\t\t\t\texpansionCount: number;\n\t\t\t\t\t\t\t}>(),\n\t\t\t\t\t\tdb\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT\n\t\t\t\t\t\t\t\tr.source AS source,\n\t\t\t\t\t\t\t\tr.kind AS kind,\n\t\t\t\t\t\t\t\tCOUNT(DISTINCT r.ref_id) AS issuedCount,\n\t\t\t\t\t\t\t\tCOUNT(e.id) AS expansionCount\n\t\t\t\t\t\t\t FROM evidence_retrieval_refs r\n\t\t\t\t\t\t\t LEFT JOIN evidence_ref_expansions e\n\t\t\t\t\t\t\t\tON e.project_id = r.project_id AND e.ref_id = r.ref_id\n\t\t\t\t\t\t\t WHERE r.project_id = ?\n\t\t\t\t\t\t\t GROUP BY r.source, r.kind\n\t\t\t\t\t\t\t ORDER BY expansionCount DESC, issuedCount DESC\n\t\t\t\t\t\t\t LIMIT ?`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(projectId, limit)\n\t\t\t\t\t\t\t.all<{\n\t\t\t\t\t\t\t\tsource: string;\n\t\t\t\t\t\t\t\tkind: string;\n\t\t\t\t\t\t\t\tissuedCount: number;\n\t\t\t\t\t\t\t\texpansionCount: number;\n\t\t\t\t\t\t\t}>(),\n\t\t\t\t\t\tdb\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT ref_id, kind, anchor_kind, anchor_id, source,\n\t\t\t\t\t\t\t\t\tlast_seen_at, issued_at\n\t\t\t\t\t\t\t FROM evidence_retrieval_refs\n\t\t\t\t\t\t\t WHERE project_id = ?\n\t\t\t\t\t\t\t ORDER BY last_seen_at DESC\n\t\t\t\t\t\t\t LIMIT ?`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(projectId, limit)\n\t\t\t\t\t\t\t.all<{\n\t\t\t\t\t\t\t\tref_id: string;\n\t\t\t\t\t\t\t\tkind: string;\n\t\t\t\t\t\t\t\tanchor_kind: string;\n\t\t\t\t\t\t\t\tanchor_id: string;\n\t\t\t\t\t\t\t\tsource: string;\n\t\t\t\t\t\t\t\tlast_seen_at: string;\n\t\t\t\t\t\t\t\tissued_at: string;\n\t\t\t\t\t\t\t}>(),\n\t\t\t\t\t\tdb\n\t\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t\t`SELECT id, ref_id, kind, source, operation, result_status,\n\t\t\t\t\t\t\t\t\tlimit_value, query_text, expanded_at\n\t\t\t\t\t\t\t FROM evidence_ref_expansions\n\t\t\t\t\t\t\t WHERE project_id = ?\n\t\t\t\t\t\t\t ORDER BY expanded_at DESC\n\t\t\t\t\t\t\t LIMIT ?`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.bind(projectId, limit)\n\t\t\t\t\t\t\t.all<{\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\tref_id: string;\n\t\t\t\t\t\t\t\tkind: string;\n\t\t\t\t\t\t\t\tsource: string | null;\n\t\t\t\t\t\t\t\toperation: string;\n\t\t\t\t\t\t\t\tresult_status: string;\n\t\t\t\t\t\t\t\tlimit_value: number | null;\n\t\t\t\t\t\t\t\tquery_text: string | null;\n\t\t\t\t\t\t\t\texpanded_at: string;\n\t\t\t\t\t\t\t}>(),\n\t\t\t\t\t]);\n\t\t\t\treturn c.json({\n\t\t\t\t\tprojectId,\n\t\t\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t\t\t\tbyKind: byKind.results.map((row) => ({\n\t\t\t\t\t\tkind: row.kind,\n\t\t\t\t\t\tissuedCount: row.issuedCount,\n\t\t\t\t\t\texpansionCount: row.expansionCount,\n\t\t\t\t\t})),\n\t\t\t\t\tbySource: bySource.results.map((row) => ({\n\t\t\t\t\t\tsource: row.source,\n\t\t\t\t\t\tkind: row.kind,\n\t\t\t\t\t\tissuedCount: row.issuedCount,\n\t\t\t\t\t\texpansionCount: row.expansionCount,\n\t\t\t\t\t})),\n\t\t\t\t\trecentRefs: recentRefs.results.map((row) => ({\n\t\t\t\t\t\trefId: row.ref_id,\n\t\t\t\t\t\tkind: row.kind,\n\t\t\t\t\t\tanchor: {\n\t\t\t\t\t\t\tentityKind: row.anchor_kind,\n\t\t\t\t\t\t\tentityId: row.anchor_id,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsource: row.source,\n\t\t\t\t\t\tissuedAt: row.issued_at,\n\t\t\t\t\t\tlastSeenAt: row.last_seen_at,\n\t\t\t\t\t})),\n\t\t\t\t\trecentExpansions: recentExpansions.results.map((row) => ({\n\t\t\t\t\t\tid: row.id,\n\t\t\t\t\t\trefId: row.ref_id,\n\t\t\t\t\t\tkind: row.kind,\n\t\t\t\t\t\tsource: row.source,\n\t\t\t\t\t\toperation: row.operation,\n\t\t\t\t\t\tresultStatus: row.result_status,\n\t\t\t\t\t\tlimit: row.limit_value,\n\t\t\t\t\t\tquery: row.query_text,\n\t\t\t\t\t\texpandedAt: row.expanded_at,\n\t\t\t\t\t})),\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\treturn c.json({\n\t\t\t\t\tprojectId,\n\t\t\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t\t\t\tbyKind: [],\n\t\t\t\t\tbySource: [],\n\t\t\t\t\trecentRefs: [],\n\t\t\t\t\trecentExpansions: [],\n\t\t\t\t\twarning: \"Evidence materialization tables are not available.\",\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tapp.get(\"/internal/evidence/refs/:refId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst refId = c.req.param(\"refId\");\n\t\t\tconst db = runtime.getSqlDb(c.env);\n\t\t\tconst payload = decodeRef(refId);\n\t\t\tif (\n\t\t\t\t!isProjectScopedRefPayload(payload) ||\n\t\t\t\tpayload.projectId !== projectId\n\t\t\t) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Evidence ref not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst recordOk = (limit?: number) =>\n\t\t\t\trecordRefExpansion(db, {\n\t\t\t\t\tprojectId,\n\t\t\t\t\trefId,\n\t\t\t\t\tkind: payload.kind,\n\t\t\t\t\toperation: \"retrieve\",\n\t\t\t\t\tresultStatus: \"ok\",\n\t\t\t\t\tlimit,\n\t\t\t\t});\n\t\t\tif (payload.kind === \"action_graph\") {\n\t\t\t\tif (!payload.anchorKind || !payload.anchorId) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Bad Request\", message: \"Action graph ref is malformed\" },\n\t\t\t\t\t\t400,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst { manifest, found } = await loadManifestForAnchor(\n\t\t\t\t\truntime.getSqlDb(c.env),\n\t\t\t\t\tprojectId,\n\t\t\t\t\tpayload.anchorKind,\n\t\t\t\t\tpayload.anchorId,\n\t\t\t\t);\n\t\t\t\tif (!found) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Not Found\", message: \"Action graph not found\" },\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait recordOk();\n\t\t\t\treturn c.json({\n\t\t\t\t\trefId,\n\t\t\t\t\tkind: payload.anchorKind,\n\t\t\t\t\tdata: manifest,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (payload.kind === \"trace\") {\n\t\t\t\tif (!hasTraceId(payload)) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Not Found\", message: \"Evidence ref not found\" },\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst detail = await runtime\n\t\t\t\t\t.createStore(c.env)\n\t\t\t\t\t.getTraceDetail(payload.traceId, projectId);\n\t\t\t\tif (!detail) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Not Found\", message: \"Trace not found\" },\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait recordOk();\n\t\t\t\treturn c.json({ refId, kind: \"trace\", data: detail });\n\t\t\t}\n\t\t\tif (payload.kind === \"profile\") {\n\t\t\t\tif (!payload.profileId) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Bad Request\", message: \"Profile ref is malformed\" },\n\t\t\t\t\t\t400,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst profile = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT id, service_name, profile_type, start_ts, end_ts,\n\t\t\t\t\t\t\t\tduration_ms, blob_size_bytes, blob_url, sample_count,\n\t\t\t\t\t\t\t\tagent, received_at, expires_at\n\t\t\t\t\t\t FROM profile_blobs\n\t\t\t\t\t\t WHERE project_id = ? AND id = ?\n\t\t\t\t\t\t LIMIT 1`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, payload.profileId)\n\t\t\t\t\t.first<ProfileEvidenceRow>();\n\t\t\t\tif (!profile) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Not Found\", message: \"Profile not found\" },\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (payload.profileMode === \"frames\") {\n\t\t\t\t\tif (!c.env.PROFILES_BUCKET) {\n\t\t\t\t\t\treturn c.json({ error: \"Profile storage not configured\" }, 500);\n\t\t\t\t\t}\n\t\t\t\t\tif (!profile.blob_url) {\n\t\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t\t{ error: \"Not Found\", message: \"Profile blob not found\" },\n\t\t\t\t\t\t\t404,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst obj = await c.env.PROFILES_BUCKET.get(profile.blob_url);\n\t\t\t\t\tif (!obj) {\n\t\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t\t{ error: \"Not Found\", message: \"Profile blob not found\" },\n\t\t\t\t\t\t\t404,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = new Uint8Array(await obj.arrayBuffer());\n\t\t\t\t\t\tconst decoded = await decodePprofBlob(raw);\n\t\t\t\t\t\tconst frameLimit = clampInt(\n\t\t\t\t\t\t\tc.req.query(\"limit\") ?? payload.limit,\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\tMAX_PROFILE_FRAME_LIMIT,\n\t\t\t\t\t\t\tDEFAULT_PROFILE_FRAME_LIMIT,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait recordOk(frameLimit);\n\t\t\t\t\t\treturn c.json({\n\t\t\t\t\t\t\trefId,\n\t\t\t\t\t\t\tkind: \"profile\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tprofile: {\n\t\t\t\t\t\t\t\t\tid: profile.id,\n\t\t\t\t\t\t\t\t\tserviceName: profile.service_name,\n\t\t\t\t\t\t\t\t\tprofileType: profile.profile_type,\n\t\t\t\t\t\t\t\t\tdurationMs: profile.duration_ms,\n\t\t\t\t\t\t\t\t\tblobSizeBytes: profile.blob_size_bytes,\n\t\t\t\t\t\t\t\t\tsampleCount: profile.sample_count,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttraceIdRequested: payload.traceId ?? null,\n\t\t\t\t\t\t\t\tframes: summarizeProfileFrames(decoded, {\n\t\t\t\t\t\t\t\t\tlimit: frameLimit,\n\t\t\t\t\t\t\t\t\ttraceIdFilter: payload.traceId ?? null,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tframeLimit,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\truntime.logger.warn(\n\t\t\t\t\t\t\t\"[evidence-retrieval] profile frame decode failed\",\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tprofile_id: profile.id,\n\t\t\t\t\t\t\t\ttrace_id: payload.traceId ?? null,\n\t\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror: \"Profile decode failed\",\n\t\t\t\t\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t422,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tawait recordOk();\n\t\t\t\treturn c.json({\n\t\t\t\t\trefId,\n\t\t\t\t\tkind: \"profile\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tprofile: {\n\t\t\t\t\t\t\tid: profile.id,\n\t\t\t\t\t\t\tserviceName: profile.service_name,\n\t\t\t\t\t\t\tprofileType: profile.profile_type,\n\t\t\t\t\t\t\tstartTs: profile.start_ts,\n\t\t\t\t\t\t\tendTs: profile.end_ts,\n\t\t\t\t\t\t\tdurationMs: profile.duration_ms,\n\t\t\t\t\t\t\tblobSizeBytes: profile.blob_size_bytes,\n\t\t\t\t\t\t\tsampleCount: profile.sample_count,\n\t\t\t\t\t\t\tagent: profile.agent,\n\t\t\t\t\t\t\treceivedAt: profile.received_at,\n\t\t\t\t\t\t\texpiresAt: profile.expires_at,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttraceIds: await profileTraceIds(db, projectId, profile.id),\n\t\t\t\t\t\ttraceIdRequested: payload.traceId ?? null,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (payload.kind === \"replay\") {\n\t\t\t\tif (!payload.sessionId) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Bad Request\", message: \"Replay ref is malformed\" },\n\t\t\t\t\t\t400,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst replay = await replayBySession(db, projectId, payload.sessionId);\n\t\t\t\tif (!replay) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Not Found\", message: \"Replay not found\" },\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (payload.replayMode === \"events\") {\n\t\t\t\t\tif (!c.env.REPLAYS_BUCKET) {\n\t\t\t\t\t\treturn c.json({ error: \"Replay storage not configured\" }, 500);\n\t\t\t\t\t}\n\t\t\t\t\tconst chunkOffset = clampInt(\n\t\t\t\t\t\tc.req.query(\"chunkOffset\") ?? payload.chunkOffset,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tNumber.MAX_SAFE_INTEGER,\n\t\t\t\t\t\t0,\n\t\t\t\t\t);\n\t\t\t\t\tconst chunkLimit = clampInt(\n\t\t\t\t\t\tc.req.query(\"limit\") ?? payload.limit,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\tMAX_REPLAY_EVENT_CHUNKS,\n\t\t\t\t\t\tDEFAULT_REPLAY_EVENT_CHUNKS,\n\t\t\t\t\t);\n\t\t\t\t\tconst window = await replayEventWindow(\n\t\t\t\t\t\tc.env.REPLAYS_BUCKET,\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tpayload.sessionId,\n\t\t\t\t\t\tchunkOffset,\n\t\t\t\t\t\tchunkLimit,\n\t\t\t\t\t);\n\t\t\t\t\tif (window.chunks.total === 0) {\n\t\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t\t{ error: \"Not Found\", message: \"Replay chunks missing\" },\n\t\t\t\t\t\t\t404,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait recordOk(chunkLimit);\n\t\t\t\t\treturn c.json({\n\t\t\t\t\t\trefId,\n\t\t\t\t\t\tkind: \"replay\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\tsessionId: replay.session_id,\n\t\t\t\t\t\t\t\tvisitorId: replay.visitor_id,\n\t\t\t\t\t\t\t\tfirstChunkAt: replay.first_chunk_at,\n\t\t\t\t\t\t\t\tlastChunkAt: replay.last_chunk_at,\n\t\t\t\t\t\t\t\tchunkCount: replay.chunk_count,\n\t\t\t\t\t\t\t\teventsCount: replay.events_count,\n\t\t\t\t\t\t\t\tstorageBytes: replay.storage_bytes,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tevents: window.events,\n\t\t\t\t\t\t\tchunks: window.chunks,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait recordOk();\n\t\t\t\treturn c.json({\n\t\t\t\t\trefId,\n\t\t\t\t\tkind: \"replay\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tsessionId: replay.session_id,\n\t\t\t\t\t\tvisitorId: replay.visitor_id,\n\t\t\t\t\t\tfirstChunkAt: replay.first_chunk_at,\n\t\t\t\t\t\tlastChunkAt: replay.last_chunk_at,\n\t\t\t\t\t\tchunkCount: replay.chunk_count,\n\t\t\t\t\t\teventsCount: replay.events_count,\n\t\t\t\t\t\tstorageBytes: replay.storage_bytes,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (payload.kind === \"ai_call\") {\n\t\t\t\tif (!payload.callId) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Bad Request\", message: \"AI call ref is malformed\" },\n\t\t\t\t\t\t400,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst aiCall = await aiCallById(db, projectId, payload.callId);\n\t\t\t\tif (!aiCall) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Not Found\", message: \"AI call not found\" },\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait recordOk();\n\t\t\t\treturn c.json({\n\t\t\t\t\trefId,\n\t\t\t\t\tkind: \"ai_call\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcallId: aiCall.call_id,\n\t\t\t\t\t\ttraceId: aiCall.trace_id,\n\t\t\t\t\t\tspanId: aiCall.span_id,\n\t\t\t\t\t\tserviceName: aiCall.service_name,\n\t\t\t\t\t\tmodelName: aiCall.model_name,\n\t\t\t\t\t\tprovider: aiCall.provider,\n\t\t\t\t\t\tcallType: aiCall.call_type,\n\t\t\t\t\t\tpromptTokens: aiCall.prompt_tokens,\n\t\t\t\t\t\tcompletionTokens: aiCall.completion_tokens,\n\t\t\t\t\t\ttotalCostUsd: aiCall.total_cost_usd,\n\t\t\t\t\t\tlatencyMs: aiCall.latency_ms,\n\t\t\t\t\t\tisError: Boolean(aiCall.is_error),\n\t\t\t\t\t\terrorMessage: aiCall.error_message,\n\t\t\t\t\t\toccurredAt: aiCall.occurred_at,\n\t\t\t\t\t\treceivedAt: aiCall.received_at,\n\t\t\t\t\t\texpiresAt: aiCall.expires_at,\n\t\t\t\t\t\tinteractionId: aiCall.interaction_id,\n\t\t\t\t\t\tsessionId: aiCall.session_id,\n\t\t\t\t\t\trequestJson: \"[redacted]\",\n\t\t\t\t\t\tresponseJson: \"[redacted]\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (payload.kind === \"tool_call\") {\n\t\t\t\tif (!payload.toolCallId) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Bad Request\", message: \"Tool call ref is malformed\" },\n\t\t\t\t\t\t400,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst tool = await toolCallById(db, projectId, payload.toolCallId);\n\t\t\t\tif (!tool) {\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{ error: \"Not Found\", message: \"Tool call not found\" },\n\t\t\t\t\t\t404,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait recordOk();\n\t\t\t\treturn c.json({\n\t\t\t\t\trefId,\n\t\t\t\t\tkind: \"tool_call\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tid: tool.id,\n\t\t\t\t\t\tactionId: tool.actionId,\n\t\t\t\t\t\ttoolName: tool.toolName,\n\t\t\t\t\t\targsHash: tool.argsHash,\n\t\t\t\t\t\tresultHash: tool.resultHash,\n\t\t\t\t\t\terrorType: tool.errorType,\n\t\t\t\t\t\tsideEffect: Boolean(tool.sideEffect),\n\t\t\t\t\t\tapprovalState: tool.approvalState,\n\t\t\t\t\t\targsRedacted: tool.argsRedacted,\n\t\t\t\t\t\tresultRedacted: tool.resultRedacted,\n\t\t\t\t\t\tmcpAuditJson: tool.mcpAuditJson,\n\t\t\t\t\t\tmutationBeforeJson: tool.mutationBeforeJson,\n\t\t\t\t\t\tmutationAfterJson: tool.mutationAfterJson,\n\t\t\t\t\t\tmutationDiffJson: tool.mutationDiffJson,\n\t\t\t\t\t\tmutationArtifactId: tool.mutationArtifactId,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (payload.kind === \"logs\" && !hasTraceId(payload)) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Evidence ref not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (payload.kind !== \"logs\") {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Bad Request\", message: \"Evidence ref kind is unsupported\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst limit = clampInt(\n\t\t\t\tc.req.query(\"limit\"),\n\t\t\t\t1,\n\t\t\t\tMAX_LOGS_FOR_RETRIEVAL,\n\t\t\t\tpayload.limit ?? 100,\n\t\t\t);\n\t\t\tconst severity = c.req.query(\"severity\");\n\t\t\tif (severity && !LOG_SEVERITIES.has(severity as LogRecord[\"severity\"])) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Bad Request\", message: \"severity is invalid\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst logs = await new LogsStore(db).getLogs({\n\t\t\t\tprojectId,\n\t\t\t\ttraceId: payload.traceId,\n\t\t\t\thours: payload.hours ?? DEFAULT_HOURS,\n\t\t\t\tlimit,\n\t\t\t\tseverity: severity as LogRecord[\"severity\"] | undefined,\n\t\t\t\tsearch: c.req.query(\"search\"),\n\t\t\t});\n\t\t\tawait recordOk(limit);\n\t\t\treturn c.json({ refId, kind: \"logs\", data: logs });\n\t\t});\n\n\t\tapp.post(\"/internal/evidence/refs/:refId/search\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst refId = c.req.param(\"refId\");\n\t\t\tconst db = runtime.getSqlDb(c.env);\n\t\t\tconst payload = decodeRef(refId);\n\t\t\tif (\n\t\t\t\t!isProjectScopedRefPayload(payload) ||\n\t\t\t\tpayload.projectId !== projectId\n\t\t\t) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Evidence ref not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (payload.kind !== \"logs\") {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: \"Bad Request\",\n\t\t\t\t\t\tmessage: \"Search is currently supported for log refs only.\",\n\t\t\t\t\t},\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!hasTraceId(payload)) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Evidence ref not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst body = await parseBundleRequest(c.req.raw);\n\t\t\tconst query = typeof body.query === \"string\" ? body.query.trim() : \"\";\n\t\t\tif (!query) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Bad Request\", message: \"query is required\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst limit = clampInt(body.limit, 1, 100, 20);\n\t\t\tconst logs = await new LogsStore(db).getLogs({\n\t\t\t\tprojectId,\n\t\t\t\ttraceId: payload.traceId,\n\t\t\t\thours: payload.hours ?? DEFAULT_HOURS,\n\t\t\t\tlimit,\n\t\t\t\tsearch: query,\n\t\t\t});\n\t\t\tawait recordRefExpansion(db, {\n\t\t\t\tprojectId,\n\t\t\t\trefId,\n\t\t\t\tkind: payload.kind,\n\t\t\t\toperation: \"search\",\n\t\t\t\tresultStatus: \"ok\",\n\t\t\t\tlimit,\n\t\t\t\tquery,\n\t\t\t});\n\t\t\treturn c.json({\n\t\t\t\trefId,\n\t\t\t\tkind: \"logs\",\n\t\t\t\tquery,\n\t\t\t\tdata: logs,\n\t\t\t});\n\t\t});\n\t},\n};\n","/**\n * Normalize OpenTelemetry `gen_ai.*` semantic-convention attributes, OTel MCP attributes,\n * and OpenInference span kinds into the canonical obs-unified Agent Action Graph schema.\n *\n * References:\n * https://opentelemetry.io/docs/specs/semconv/gen-ai/\n * https://github.com/Arize-ai/openinference/blob/main/spec/\n *\n * Must run BEFORE ai-span-payloads-processor — that processor assumes\n * `openinference.span.kind` and `ai.payload.*` are already set.\n */\n\nimport type { JsonValue, StoredSpan } from \"@obsunified/types\";\nimport {\n\tACTION_CAUSED_BY_ID_KEY,\n\tACTION_CONFIDENCE_KEY,\n\tACTION_ID_KEY,\n\tACTION_KIND_KEY,\n\tACTION_ROOT_ID_KEY,\n\tACTOR_TYPE_KEY,\n\tActionKind,\n\tAGENT_RUN_ID_KEY,\n\tAI_PAYLOAD_INPUT_KEY,\n\tAI_PAYLOAD_OUTPUT_KEY,\n\tOPENINFERENCE_SPAN_KIND_KEY,\n\tOpenInferenceSpanKind,\n\tTOOL_ARGS_KEY,\n\tTOOL_CALL_ID_KEY,\n\tTOOL_NAME_KEY,\n\tTOOL_SIDE_EFFECT_KEY,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { deriveActionId, resolveActionIdentity } from \"../lib/action-identity\";\nimport { parseJsonRecord } from \"../lib/json\";\n\nconst GEN_AI_PREFIX = \"gen_ai.\";\nconst MCP_PREFIX = \"mcp.\";\n\nexport { deriveActionId };\n\n// Map gen_ai operation.name → OpenInference span kind.\nconst operationToKind = (op: unknown): string => {\n\tif (typeof op !== \"string\") return OpenInferenceSpanKind.LLM;\n\tconst lower = op.toLowerCase();\n\tif (lower.includes(\"embed\")) return OpenInferenceSpanKind.EMBEDDING;\n\tif (lower.includes(\"tool\")) return OpenInferenceSpanKind.TOOL;\n\tif (lower.includes(\"agent\")) return OpenInferenceSpanKind.AGENT;\n\treturn OpenInferenceSpanKind.LLM;\n};\n\nconst asNumber = (value: unknown): number | undefined => {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\") {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n};\n\nconst toJsonString = (value: unknown): string | null => {\n\tif (value === undefined || value === null) return null;\n\tif (typeof value === \"string\") return value;\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn String(value);\n\t}\n};\n\nconst SIDE_EFFECT_VERBS = new Set([\n\t\"create\",\n\t\"delete\",\n\t\"insert\",\n\t\"mutate\",\n\t\"patch\",\n\t\"remove\",\n\t\"set\",\n\t\"update\",\n\t\"upsert\",\n\t\"write\",\n]);\n\nconst inferToolSideEffect = (toolName: unknown): 0 | 1 => {\n\tif (typeof toolName !== \"string\") return 0;\n\tconst [firstToken] = toolName\n\t\t.trim()\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter(Boolean);\n\treturn firstToken && SIDE_EFFECT_VERBS.has(firstToken) ? 1 : 0;\n};\n\nconst collectIndexed = (\n\tattrs: Record<string, JsonValue>,\n\tprefix: string,\n): unknown | undefined => {\n\tconst scalar = attrs[prefix];\n\tif (scalar !== undefined) return scalar;\n\n\tconst messages: Array<Record<string, JsonValue>> = [];\n\tconst indexed = Object.keys(attrs).filter((k) => k.startsWith(`${prefix}.`));\n\tif (indexed.length === 0) return undefined;\n\n\tfor (const key of indexed) {\n\t\tconst rest = key.slice(prefix.length + 1);\n\t\tconst dot = rest.indexOf(\".\");\n\t\tconst idx = Number.parseInt(rest.slice(0, dot), 10);\n\t\tif (!Number.isFinite(idx)) continue;\n\t\tconst field = rest.slice(dot + 1);\n\t\tmessages[idx] = messages[idx] ?? {};\n\t\tmessages[idx][field] = attrs[key];\n\t}\n\n\tconst compact = messages.filter(\n\t\t(m): m is Record<string, JsonValue> => m !== undefined,\n\t);\n\treturn compact.length > 0 ? compact : undefined;\n};\n\nexport const genAiNormalizerPlugin: CollectorPlugin = {\n\tname: \"gen-ai-normalizer\",\n\tregister(_app, runtime) {\n\t\truntime.addSpanProcessor({\n\t\t\tname: \"gen-ai-normalizer\",\n\t\t\tasync process(spans) {\n\t\t\t\treturn Promise.all(\n\t\t\t\t\tspans.map(async (span): Promise<StoredSpan> => {\n\t\t\t\t\t\tconst attrs = parseJsonRecord(span.attributesJson);\n\n\t\t\t\t\t\tconst mcpMethod = attrs[\"mcp.method.name\"] || attrs[\"mcp.method\"];\n\t\t\t\t\t\tconst jsonRpcId =\n\t\t\t\t\t\t\tattrs[\"jsonrpc.request.id\"] || attrs[\"jsonrpc.id\"];\n\t\t\t\t\t\tconst hasMcp =\n\t\t\t\t\t\t\tmcpMethod !== undefined ||\n\t\t\t\t\t\t\tjsonRpcId !== undefined ||\n\t\t\t\t\t\t\tObject.keys(attrs).some((k) => k.startsWith(MCP_PREFIX));\n\n\t\t\t\t\t\tconst hasGenAi = Object.keys(attrs).some((k) =>\n\t\t\t\t\t\t\tk.startsWith(GEN_AI_PREFIX),\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconst openInferenceKind = attrs[OPENINFERENCE_SPAN_KIND_KEY];\n\t\t\t\t\t\tconst hasOpenInference = openInferenceKind !== undefined;\n\n\t\t\t\t\t\t// If it's not a GenAI, MCP, or OpenInference span, keep it as is.\n\t\t\t\t\t\tif (!hasGenAi && !hasMcp && !hasOpenInference) {\n\t\t\t\t\t\t\treturn span;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst normalized: Record<string, JsonValue> = { ...attrs };\n\n\t\t\t\t\t\t// 1. Determine OpenInference Span Kind\n\t\t\t\t\t\tlet kind = openInferenceKind as string | undefined;\n\t\t\t\t\t\tif (hasMcp && !kind) {\n\t\t\t\t\t\t\tif (mcpMethod === \"tools/call\") {\n\t\t\t\t\t\t\t\tkind = OpenInferenceSpanKind.TOOL;\n\t\t\t\t\t\t\t} else if (mcpMethod === \"resources/read\") {\n\t\t\t\t\t\t\t\tkind = OpenInferenceSpanKind.RETRIEVER;\n\t\t\t\t\t\t\t} else if (mcpMethod === \"prompts/get\") {\n\t\t\t\t\t\t\t\tkind = OpenInferenceSpanKind.PROMPT;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tkind = OpenInferenceSpanKind.CHAIN;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (hasGenAi && !kind) {\n\t\t\t\t\t\t\tkind = operationToKind(attrs[\"gen_ai.operation.name\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (kind) {\n\t\t\t\t\t\t\tnormalized[OPENINFERENCE_SPAN_KIND_KEY] = kind;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 2. Set Action Graph Schema Attributes\n\t\t\t\t\t\tconst identity = await resolveActionIdentity(span, attrs);\n\t\t\t\t\t\tconst actionId = identity.actionId;\n\n\t\t\t\t\t\tnormalized[ACTION_ID_KEY] = actionId;\n\t\t\t\t\t\tnormalized[ACTION_CONFIDENCE_KEY] = identity.confidence;\n\t\t\t\t\t\tnormalized[ACTION_ROOT_ID_KEY] = identity.rootActionId;\n\t\t\t\t\t\tnormalized[ACTION_CAUSED_BY_ID_KEY] = identity.causedByActionId;\n\n\t\t\t\t\t\tif (normalized[ACTOR_TYPE_KEY] === undefined) {\n\t\t\t\t\t\t\tnormalized[ACTOR_TYPE_KEY] = \"agent\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (normalized[AGENT_RUN_ID_KEY] === undefined) {\n\t\t\t\t\t\t\tnormalized[AGENT_RUN_ID_KEY] =\n\t\t\t\t\t\t\t\tidentity.agentRunId ?? identity.rootActionId;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Determine Action Kind\n\t\t\t\t\t\tlet actionKind = attrs[ACTION_KIND_KEY] as string | undefined;\n\t\t\t\t\t\tif (!actionKind && kind) {\n\t\t\t\t\t\t\tif (kind === OpenInferenceSpanKind.AGENT) {\n\t\t\t\t\t\t\t\tactionKind = ActionKind.AgentStep;\n\t\t\t\t\t\t\t} else if (kind === OpenInferenceSpanKind.LLM) {\n\t\t\t\t\t\t\t\tactionKind = ActionKind.LlmCall;\n\t\t\t\t\t\t\t} else if (kind === OpenInferenceSpanKind.TOOL) {\n\t\t\t\t\t\t\t\tactionKind = ActionKind.ToolCall;\n\t\t\t\t\t\t\t} else if (kind === OpenInferenceSpanKind.RETRIEVER) {\n\t\t\t\t\t\t\t\tactionKind = ActionKind.Retrieval;\n\t\t\t\t\t\t\t} else if (kind === OpenInferenceSpanKind.EVALUATOR) {\n\t\t\t\t\t\t\t\tactionKind = ActionKind.Eval;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tactionKind = ActionKind.AgentStep;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (actionKind) {\n\t\t\t\t\t\t\tnormalized[ACTION_KIND_KEY] = actionKind;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 3. MCP Specific Mapping Details\n\t\t\t\t\t\tif (hasMcp) {\n\t\t\t\t\t\t\tif (kind === OpenInferenceSpanKind.TOOL) {\n\t\t\t\t\t\t\t\tif (normalized[TOOL_CALL_ID_KEY] === undefined) {\n\t\t\t\t\t\t\t\t\tnormalized[TOOL_CALL_ID_KEY] = actionId;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (normalized[TOOL_NAME_KEY] === undefined) {\n\t\t\t\t\t\t\t\t\tconst tName =\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.tool.name\"] ??\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.operation.name\"] ??\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.name\"] ??\n\t\t\t\t\t\t\t\t\t\tspan.spanName;\n\t\t\t\t\t\t\t\t\tnormalized[TOOL_NAME_KEY] = tName;\n\t\t\t\t\t\t\t\t\tnormalized[\"obs.tool_call.tool_name\"] = tName;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (normalized[TOOL_ARGS_KEY] === undefined) {\n\t\t\t\t\t\t\t\t\tconst rawArgs =\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.tool.arguments\"] ??\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.operation.arguments\"] ??\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.arguments\"];\n\t\t\t\t\t\t\t\t\tconst tArgs = toJsonString(rawArgs) ?? \"{}\";\n\t\t\t\t\t\t\t\t\tnormalized[TOOL_ARGS_KEY] = tArgs;\n\t\t\t\t\t\t\t\t\tnormalized[\"obs.tool_call.args\"] = tArgs;\n\t\t\t\t\t\t\t\t\tnormalized[AI_PAYLOAD_INPUT_KEY] = tArgs;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (normalized[TOOL_SIDE_EFFECT_KEY] === undefined) {\n\t\t\t\t\t\t\t\t\tconst sideEffect =\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.tool.side_effect\"] ??\n\t\t\t\t\t\t\t\t\t\tattrs[\"mcp.side_effect\"] ??\n\t\t\t\t\t\t\t\t\t\tinferToolSideEffect(attrs[\"mcp.tool.name\"]);\n\t\t\t\t\t\t\t\t\tnormalized[TOOL_SIDE_EFFECT_KEY] = sideEffect;\n\t\t\t\t\t\t\t\t\tnormalized[\"obs.tool_call.side_effect\"] = sideEffect;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 4. GenAI Model + provider normalization\n\t\t\t\t\t\tconst model =\n\t\t\t\t\t\t\t(attrs[\"gen_ai.response.model\"] as string | undefined) ||\n\t\t\t\t\t\t\t(attrs[\"gen_ai.request.model\"] as string | undefined);\n\t\t\t\t\t\tconst provider = attrs[\"gen_ai.system\"];\n\t\t\t\t\t\tif (kind === OpenInferenceSpanKind.LLM) {\n\t\t\t\t\t\t\tif (typeof model === \"string\")\n\t\t\t\t\t\t\t\tnormalized[\"llm.model_name\"] = model;\n\t\t\t\t\t\t\tif (typeof provider === \"string\")\n\t\t\t\t\t\t\t\tnormalized[\"llm.provider\"] = provider;\n\t\t\t\t\t\t} else if (kind === OpenInferenceSpanKind.EMBEDDING) {\n\t\t\t\t\t\t\tif (typeof model === \"string\")\n\t\t\t\t\t\t\t\tnormalized[\"embedding.model_name\"] = model;\n\t\t\t\t\t\t\tif (typeof provider === \"string\")\n\t\t\t\t\t\t\t\tnormalized[\"embedding.provider\"] = provider;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// GenAI Token Usage\n\t\t\t\t\t\tconst promptTokens =\n\t\t\t\t\t\t\tasNumber(attrs[\"gen_ai.usage.input_tokens\"]) ??\n\t\t\t\t\t\t\tasNumber(attrs[\"gen_ai.usage.prompt_tokens\"]);\n\t\t\t\t\t\tconst completionTokens =\n\t\t\t\t\t\t\tasNumber(attrs[\"gen_ai.usage.output_tokens\"]) ??\n\t\t\t\t\t\t\tasNumber(attrs[\"gen_ai.usage.completion_tokens\"]);\n\t\t\t\t\t\tif (promptTokens !== undefined)\n\t\t\t\t\t\t\tnormalized[\"llm.token_count.prompt\"] = promptTokens;\n\t\t\t\t\t\tif (completionTokens !== undefined)\n\t\t\t\t\t\t\tnormalized[\"llm.token_count.completion\"] = completionTokens;\n\t\t\t\t\t\tif (promptTokens !== undefined && completionTokens !== undefined) {\n\t\t\t\t\t\t\tnormalized[\"llm.token_count.total\"] =\n\t\t\t\t\t\t\t\tpromptTokens + completionTokens;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// GenAI Inputs/Outputs\n\t\t\t\t\t\tif (normalized[AI_PAYLOAD_INPUT_KEY] === undefined) {\n\t\t\t\t\t\t\tconst input = collectIndexed(attrs, \"gen_ai.prompt\");\n\t\t\t\t\t\t\tif (input !== undefined) {\n\t\t\t\t\t\t\t\tnormalized[AI_PAYLOAD_INPUT_KEY] = toJsonString(input) ?? \"\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (normalized[AI_PAYLOAD_OUTPUT_KEY] === undefined) {\n\t\t\t\t\t\t\tconst output = collectIndexed(attrs, \"gen_ai.completion\");\n\t\t\t\t\t\t\tif (output !== undefined) {\n\t\t\t\t\t\t\t\tnormalized[AI_PAYLOAD_OUTPUT_KEY] = toJsonString(output) ?? \"\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...span,\n\t\t\t\t\t\t\tattributesJson: JSON.stringify(normalized),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t},\n};\n","import type { IdentifyInput } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { dialectFor, sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport const identityReceiverPlugin: CollectorPlugin = {\n\tname: \"identity-receiver\",\n\tregister(app) {\n\t\tapp.post(\"/v1/identify\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tlet payload: IdentifyInput;\n\t\t\ttry {\n\t\t\t\tpayload = await c.req.json<IdentifyInput>();\n\t\t\t} catch {\n\t\t\t\treturn c.json({ error: \"Invalid JSON body\" }, 400);\n\t\t\t}\n\t\t\tif (!payload.userId || typeof payload.userId !== \"string\") {\n\t\t\t\treturn c.json({ error: \"userId is required\" }, 400);\n\t\t\t}\n\t\t\tif (payload.userId.length > 256) {\n\t\t\t\treturn c.json({ error: \"userId too long (max 256)\" }, 400);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tpayload.email &&\n\t\t\t\t(typeof payload.email !== \"string\" || payload.email.length > 320)\n\t\t\t) {\n\t\t\t\treturn c.json({ error: \"Invalid email\" }, 400);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tpayload.name &&\n\t\t\t\t(typeof payload.name !== \"string\" || payload.name.length > 256)\n\t\t\t) {\n\t\t\t\treturn c.json({ error: \"Invalid name\" }, 400);\n\t\t\t}\n\t\t\tconst now = new Date().toISOString();\n\n\t\t\t// Backfill window: callers (synthetic seeds, historical imports)\n\t\t\t// can pass firstSeenAt to set the user's earliest observed\n\t\t\t// activity. We accept anything in the past; future timestamps\n\t\t\t// fall back to `now` so a clock-skew client can't poison the\n\t\t\t// table.\n\t\t\tlet firstSeenAt = now;\n\t\t\tif (payload.firstSeenAt) {\n\t\t\t\tconst parsed = new Date(payload.firstSeenAt);\n\t\t\t\tif (!Number.isNaN(parsed.getTime()) && parsed.getTime() <= Date.now()) {\n\t\t\t\t\tfirstSeenAt = parsed.toISOString();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst propertiesJson = payload.properties\n\t\t\t\t? JSON.stringify(payload.properties)\n\t\t\t\t: null;\n\n\t\t\t// user_id is the PK today (single-tenant legacy). For MVP, we keep\n\t\t\t// that contract — user_id is treated as globally unique and the\n\t\t\t// first project to identify them \"owns\" the profile. project_id on\n\t\t\t// the row reflects where the user was first seen.\n\t\t\t//\n\t\t\t// On conflict we keep the EARLIEST first_seen_at via MIN() — once\n\t\t\t// observed, a user's first-seen is monotonic; an identify() call\n\t\t\t// that runs at \"now\" must not overwrite a true historical value.\n\t\t\tconst db = sqlDbFor(c.env);\n\t\t\tconst firstSeenExpr =\n\t\t\t\tdialectFor(db).name === \"postgres\"\n\t\t\t\t\t? \"LEAST(user_profiles.first_seen_at, excluded.first_seen_at)\"\n\t\t\t\t\t: \"MIN(user_profiles.first_seen_at, excluded.first_seen_at)\";\n\n\t\t\tawait db\n\t\t\t\t.prepare(\n\t\t\t\t\t`INSERT INTO user_profiles (project_id, user_id, visitor_id, email, name, properties_json, first_seen_at, last_seen_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(user_id) DO UPDATE SET\n visitor_id = excluded.visitor_id,\n email = COALESCE(excluded.email, user_profiles.email),\n name = COALESCE(excluded.name, user_profiles.name),\n properties_json = COALESCE(excluded.properties_json, user_profiles.properties_json),\n first_seen_at = ${firstSeenExpr},\n last_seen_at = excluded.last_seen_at\n `,\n\t\t\t\t)\n\t\t\t\t.bind(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tpayload.userId,\n\t\t\t\t\tpayload.visitorId,\n\t\t\t\t\tpayload.email ?? null,\n\t\t\t\t\tpayload.name ?? null,\n\t\t\t\t\tpropertiesJson,\n\t\t\t\t\tfirstSeenAt,\n\t\t\t\t\tnow,\n\t\t\t\t)\n\t\t\t\t.run();\n\n\t\t\treturn c.json({ success: true, userId: payload.userId });\n\t\t});\n\t},\n};\n","import type { JsonValue, StoredSpan } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { parseJsonRecord } from \"../lib/json\";\n\nconst INTERNAL_PATH_PREFIXES = [\n\t\"/api/admin\",\n\t\"/api/internal\",\n\t\"/internal/telemetry\",\n\t\"/v1/traces\",\n\t\"/health\",\n];\n\nconst getStringValue = (\n\trecord: Record<string, JsonValue>,\n\tkeys: string[],\n): string | null => {\n\tfor (const key of keys) {\n\t\tconst value = record[key];\n\t\tif (typeof value === \"string\" && value.trim()) return value.trim();\n\t}\n\treturn null;\n};\n\nconst normalizePathSegment = (segment: string): string => {\n\tif (!segment) return segment;\n\tif (/^\\d+$/.test(segment)) return \":id\";\n\tif (/^[0-9a-f]{16,}$/i.test(segment)) return \":id\";\n\tif (\n\t\t/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n\t\t\tsegment,\n\t\t)\n\t)\n\t\treturn \":uuid\";\n\treturn segment;\n};\n\nconst normalizePath = (path: string): string => {\n\tconst [pathname] = path.split(\"?\");\n\tconst segments = pathname\n\t\t.split(\"/\")\n\t\t.map(normalizePathSegment)\n\t\t.filter((segment, index) => !(index === 0 && segment === \"\"));\n\treturn `/${segments.join(\"/\")}`.replace(/\\/{2,}/g, \"/\");\n};\n\nconst isInternalPath = (path: string): boolean =>\n\tINTERNAL_PATH_PREFIXES.some(\n\t\t(prefix) => path === prefix || path.startsWith(`${prefix}/`),\n\t);\n\nconst deriveDependencyTarget = (\n\tattributes: Record<string, JsonValue>,\n\tresourceAttributes: Record<string, JsonValue>,\n): string | null => {\n\tconst dbSystem = getStringValue(attributes, [\"db.system\"]);\n\tif (dbSystem) return dbSystem;\n\tconst peerService = getStringValue(attributes, [\n\t\t\"peer.service\",\n\t\t\"server.address\",\n\t\t\"http.host\",\n\t]);\n\tif (peerService) return peerService;\n\tconst urlValue = getStringValue(attributes, [\"url.full\", \"http.url\"]);\n\tif (urlValue) {\n\t\ttry {\n\t\t\treturn new URL(urlValue).host;\n\t\t} catch {\n\t\t\treturn urlValue;\n\t\t}\n\t}\n\treturn getStringValue(resourceAttributes, [\"host.name\"]);\n};\n\nexport const issueEnrichmentPlugin: CollectorPlugin = {\n\tname: \"issue-enrichment\",\n\tregister(_app, runtime) {\n\t\truntime.addSpanProcessor({\n\t\t\tname: \"issue-enrichment\",\n\t\t\tprocess(spans) {\n\t\t\t\treturn spans.map((span): StoredSpan => {\n\t\t\t\t\tconst attributes = parseJsonRecord(span.attributesJson);\n\t\t\t\t\tconst resourceAttributes = parseJsonRecord(\n\t\t\t\t\t\tspan.resourceAttributesJson,\n\t\t\t\t\t);\n\t\t\t\t\tconst method = getStringValue(attributes, [\n\t\t\t\t\t\t\"http.request.method\",\n\t\t\t\t\t\t\"http.method\",\n\t\t\t\t\t]);\n\t\t\t\t\tconst path = getStringValue(attributes, [\n\t\t\t\t\t\t\"url.path\",\n\t\t\t\t\t\t\"http.target\",\n\t\t\t\t\t\t\"http.route\",\n\t\t\t\t\t]);\n\t\t\t\t\tconst routePath = path ? normalizePath(path) : null;\n\t\t\t\t\tconst existingRouteLabel = getStringValue(attributes, [\n\t\t\t\t\t\t\"collector.route_label\",\n\t\t\t\t\t]);\n\t\t\t\t\tconst dependencyTarget = deriveDependencyTarget(\n\t\t\t\t\t\tattributes,\n\t\t\t\t\t\tresourceAttributes,\n\t\t\t\t\t);\n\t\t\t\t\tconst isDependencySpan = Boolean(\n\t\t\t\t\t\tdependencyTarget ||\n\t\t\t\t\t\t\tspan.spanKind === 3 ||\n\t\t\t\t\t\t\tspan.spanKind === 4 ||\n\t\t\t\t\t\t\tspan.spanKind === 5,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst nextAttributes: Record<string, JsonValue> = { ...attributes };\n\n\t\t\t\t\tif (routePath) {\n\t\t\t\t\t\tnextAttributes[\"collector.route_key\"] = routePath;\n\t\t\t\t\t\tif (!existingRouteLabel) {\n\t\t\t\t\t\t\tnextAttributes[\"collector.route_label\"] = method\n\t\t\t\t\t\t\t\t? `${method} ${routePath}`\n\t\t\t\t\t\t\t\t: routePath;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnextAttributes[\"collector.is_internal\"] = isInternalPath(routePath);\n\t\t\t\t\t}\n\t\t\t\t\tif (dependencyTarget && isDependencySpan) {\n\t\t\t\t\t\tnextAttributes[\"collector.dependency_target\"] = dependencyTarget;\n\t\t\t\t\t}\n\t\t\t\t\tif (isDependencySpan) {\n\t\t\t\t\t\tnextAttributes[\"collector.span_role\"] = \"dependency\";\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { ...span, attributesJson: JSON.stringify(nextAttributes) };\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t},\n};\n","import {\n\tDEFAULT_WINDOW_HOURS,\n\tMAX_ISSUE_ROWS,\n\tRETENTION_HOURS,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { getProjectId } from \"./_context\";\n\nconst parseHours = (rawValue?: string): number =>\n\tMath.min(\n\t\tRETENTION_HOURS,\n\t\tMath.max(\n\t\t\t1,\n\t\t\tNumber.parseInt(rawValue || String(DEFAULT_WINDOW_HOURS), 10) ||\n\t\t\t\tDEFAULT_WINDOW_HOURS,\n\t\t),\n\t);\n\nconst parseLimit = (rawValue?: string): number =>\n\tMath.min(\n\t\tMAX_ISSUE_ROWS,\n\t\tMath.max(\n\t\t\t1,\n\t\t\tNumber.parseInt(rawValue || String(MAX_ISSUE_ROWS), 10) || MAX_ISSUE_ROWS,\n\t\t),\n\t);\n\nexport const issueInsightsPlugin: CollectorPlugin = {\n\tname: \"issue-insights\",\n\tregister(app, runtime) {\n\t\tapp.get(\"/internal/telemetry/issues\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\tconst overview = await store.getIssueOverview({\n\t\t\t\tprojectId,\n\t\t\t\thours: parseHours(c.req.query(\"hours\")),\n\t\t\t\tservice: c.req.query(\"service\") || undefined,\n\t\t\t\tcategory:\n\t\t\t\t\tc.req.query(\"category\") === \"error\" ||\n\t\t\t\t\tc.req.query(\"category\") === \"latency\" ||\n\t\t\t\t\tc.req.query(\"category\") === \"dependency\"\n\t\t\t\t\t\t? (c.req.query(\"category\") as \"error\" | \"latency\" | \"dependency\")\n\t\t\t\t\t\t: \"all\",\n\t\t\t\tincludeInternal: c.req.query(\"includeInternal\") === \"true\",\n\t\t\t\tlimit: parseLimit(c.req.query(\"limit\")),\n\t\t\t});\n\t\t\treturn c.json({\n\t\t\t\t...overview,\n\t\t\t\tplugins: runtime.getRegisteredPluginNames(),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/telemetry/issues/detail\", async (c) => {\n\t\t\tconst issueId = c.req.query(\"issueId\");\n\t\t\tif (!issueId)\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Bad Request\", message: \"issueId is required\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\tconst detail = await store.getIssueDetail(issueId, {\n\t\t\t\tprojectId,\n\t\t\t\thours: parseHours(c.req.query(\"hours\")),\n\t\t\t\tservice: c.req.query(\"service\") || undefined,\n\t\t\t\tcategory:\n\t\t\t\t\tc.req.query(\"category\") === \"error\" ||\n\t\t\t\t\tc.req.query(\"category\") === \"latency\" ||\n\t\t\t\t\tc.req.query(\"category\") === \"dependency\"\n\t\t\t\t\t\t? (c.req.query(\"category\") as \"error\" | \"latency\" | \"dependency\")\n\t\t\t\t\t\t: \"all\",\n\t\t\t\tincludeInternal: c.req.query(\"includeInternal\") === \"true\",\n\t\t\t});\n\n\t\t\tif (!detail)\n\t\t\t\treturn c.json({ error: \"Not Found\", message: \"Issue not found\" }, 404);\n\t\t\treturn c.json({ ...detail, plugins: runtime.getRegisteredPluginNames() });\n\t\t});\n\t},\n};\n","import type { LogRecord, LogSeverity } from \"@obsunified/types\";\nimport { getConfiguredRetentionHours } from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { LogsStore } from \"../lib/logs-store\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { logToTailEvent, publishTail } from \"../lib/tail-publisher\";\nimport {\n\ttype DecodedLogRecord,\n\tdecodeLogsRequest,\n\tOtlpDecodeError,\n\ttype ReadBodyResult,\n\treadOtlpBody,\n} from \"../otlp/decode\";\nimport { logsResponse, otlpRetryableError } from \"../otlp/response\";\nimport { getProjectId } from \"./_context\";\n\nconst MAX_LOGS_PER_REQUEST = 1000;\n\nexport const logsReceiverPlugin: CollectorPlugin = {\n\tname: \"logs-receiver\",\n\tregister(app, runtime) {\n\t\tapp.post(\"/v1/logs\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\n\t\t\tlet body: ReadBodyResult;\n\t\t\ttry {\n\t\t\t\tbody = await readOtlpBody(c);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof OtlpDecodeError) {\n\t\t\t\t\treturn c.json({ error: err.message }, err.status);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\tlet decoded: DecodedLogRecord[];\n\t\t\ttry {\n\t\t\t\tdecoded = decodeLogsRequest(body);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof OtlpDecodeError) {\n\t\t\t\t\treturn c.json({ error: err.message }, err.status);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\tlet rejected = 0;\n\t\t\tif (decoded.length > MAX_LOGS_PER_REQUEST) {\n\t\t\t\trejected = decoded.length - MAX_LOGS_PER_REQUEST;\n\t\t\t\tdecoded = decoded.slice(0, MAX_LOGS_PER_REQUEST);\n\t\t\t}\n\n\t\t\tconst store = new LogsStore(sqlDbFor(c.env));\n\t\t\tconst retentionHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst now = new Date();\n\t\t\tconst nowStr = now.toISOString();\n\t\t\tconst expires = new Date(\n\t\t\t\tnow.getTime() + retentionHours * 60 * 60 * 1000,\n\t\t\t).toISOString();\n\n\t\t\tconst records: LogRecord[] = decoded.map((d) => {\n\t\t\t\tconst sessionId =\n\t\t\t\t\td.attributes &&\n\t\t\t\t\ttypeof d.attributes[\"session.id\"] === \"string\" &&\n\t\t\t\t\t(d.attributes[\"session.id\"] as string).length > 0\n\t\t\t\t\t\t? (d.attributes[\"session.id\"] as string)\n\t\t\t\t\t\t: null;\n\t\t\t\t// RFC 0004 — denormalize obs.interaction.id from log\n\t\t\t\t// attributes when the producer stamped it (telemetry-sdk's\n\t\t\t\t// logger inherits the active span's attribute).\n\t\t\t\tconst interactionId =\n\t\t\t\t\td.attributes &&\n\t\t\t\t\ttypeof d.attributes[\"obs.interaction.id\"] === \"string\" &&\n\t\t\t\t\t(d.attributes[\"obs.interaction.id\"] as string).length > 0\n\t\t\t\t\t\t? (d.attributes[\"obs.interaction.id\"] as string)\n\t\t\t\t\t\t: null;\n\t\t\t\treturn {\n\t\t\t\t\tprojectId,\n\t\t\t\t\tlogId: crypto.randomUUID(),\n\t\t\t\t\ttraceId: d.traceId,\n\t\t\t\t\tspanId: d.spanId,\n\t\t\t\t\tserviceName: d.serviceName,\n\t\t\t\t\tseverity: d.severity,\n\t\t\t\t\tseverityNumber: d.severityNumber || severityToNumber(d.severity),\n\t\t\t\t\tloggerName: d.loggerName,\n\t\t\t\t\tmessage: d.message,\n\t\t\t\t\tattributesJson: d.attributes ? JSON.stringify(d.attributes) : null,\n\t\t\t\t\tflags: d.flags,\n\t\t\t\t\tdroppedAttributesCount: d.droppedAttributesCount,\n\t\t\t\t\toccurredAt: d.occurredAt,\n\t\t\t\t\treceivedAt: nowStr,\n\t\t\t\t\texpiresAt: expires,\n\t\t\t\t\tsessionId,\n\t\t\t\t\tinteractionId,\n\t\t\t\t};\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait runtime.withChildSpan(\"logs.ingest\", async (span) => {\n\t\t\t\t\tspan.setAttribute(\"logs.records_received\", decoded.length + rejected);\n\t\t\t\t\tspan.setAttribute(\"logs.records_rejected\", rejected);\n\t\t\t\t\tspan.setAttribute(\"logs.records_inserted\", records.length);\n\t\t\t\t\tspan.setAttribute(\"project.id\", projectId);\n\t\t\t\t\tawait store.ingestBatch(records);\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\truntime.logger.error(\"[/v1/logs] storage error\", {\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t});\n\t\t\t\treturn otlpRetryableError(c, 503, \"Storage temporarily unavailable\");\n\t\t\t}\n\n\t\t\tif (records.length > 0 && c.env.TAIL_HUB) {\n\t\t\t\tconst events = records.map(logToTailEvent);\n\t\t\t\tc.executionCtx.waitUntil(publishTail(c.env, events));\n\t\t\t}\n\n\t\t\tif (rejected > 0) {\n\t\t\t\treturn logsResponse(c, body.wireFormat, {\n\t\t\t\t\trejected,\n\t\t\t\t\terrorMessage: `Batch exceeded ${MAX_LOGS_PER_REQUEST}-record cap; ${rejected} record(s) dropped`,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn logsResponse(c, body.wireFormat);\n\t\t});\n\n\t\tapp.get(\"/internal/logs/overview\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = new LogsStore(sqlDbFor(c.env));\n\t\t\tconst query = c.req.query();\n\t\t\tconst hours = parseInt(query.hours || \"24\", 10);\n\n\t\t\tconst response = await store.getLogs({\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tservice: query.service,\n\t\t\t\tseverity: query.severity as LogSeverity | undefined,\n\t\t\t\ttraceId: query.traceId,\n\t\t\t\tlimit: parseInt(query.limit || \"100\", 10),\n\t\t\t\tsearch: query.search,\n\t\t\t});\n\n\t\t\treturn c.json(response);\n\t\t});\n\t},\n};\n\nconst severityToNumber = (s: LogSeverity): number => {\n\tswitch (s) {\n\t\tcase \"DEBUG\":\n\t\t\treturn 5;\n\t\tcase \"INFO\":\n\t\t\treturn 9;\n\t\tcase \"WARN\":\n\t\t\treturn 13;\n\t\tcase \"ERROR\":\n\t\t\treturn 17;\n\t\tcase \"FATAL\":\n\t\t\treturn 21;\n\t}\n};\n","import type { LogRecord, StoredSpan } from \"@obsunified/types\";\nimport type { TailEvent } from \"../durable-objects/tail-hub\";\nimport type { CollectorEnv } from \"../framework/env\";\n\n/**\n * Fire-and-forget publish to the TailHub DO. Swallows errors — tail is a\n * best-effort UX feature; a broadcast failure must never break ingest.\n */\nexport async function publishTail(\n\tenv: CollectorEnv,\n\tevents: TailEvent[],\n): Promise<void> {\n\tif (!env.TAIL_HUB || events.length === 0) return;\n\ttry {\n\t\tconst id = env.TAIL_HUB.idFromName(\"singleton\");\n\t\tconst stub = env.TAIL_HUB.get(id);\n\t\tawait stub.fetch(\"https://hub/publish\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(events),\n\t\t});\n\t} catch (err) {\n\t\tconsole.error(\"[tail-publisher] publish failed:\", err);\n\t}\n}\n\nexport function spanToTailEvent(span: StoredSpan): TailEvent {\n\treturn {\n\t\tkind: \"span\",\n\t\tprojectId: span.projectId,\n\t\trow: {\n\t\t\ttraceId: span.traceId,\n\t\t\tspanId: span.spanId,\n\t\t\tparentSpanId: span.parentSpanId,\n\t\t\tserviceName: span.serviceName,\n\t\t\tspanName: span.spanName,\n\t\t\tspanKind: span.spanKind,\n\t\t\tstatusCode: span.statusCode,\n\t\t\tstatusMessage: span.statusMessage,\n\t\t\tstartTime: span.startTime,\n\t\t\tendTime: span.endTime,\n\t\t\tdurationMs: span.durationMs,\n\t\t},\n\t\tt: span.receivedAt,\n\t};\n}\n\nexport function logToTailEvent(log: LogRecord): TailEvent {\n\treturn {\n\t\tkind: \"log\",\n\t\tprojectId: log.projectId,\n\t\trow: {\n\t\t\tlogId: log.logId,\n\t\t\ttraceId: log.traceId,\n\t\t\tspanId: log.spanId,\n\t\t\tserviceName: log.serviceName,\n\t\t\tseverity: log.severity,\n\t\t\tloggerName: log.loggerName,\n\t\t\tmessage: log.message,\n\t\t\toccurredAt: log.occurredAt,\n\t\t},\n\t\tt: log.receivedAt,\n\t};\n}\n","import type { JsonValue } from \"@bufbuild/protobuf\";\nimport type { Context } from \"hono\";\n\nexport type OtlpWireFormat = \"json\" | \"protobuf\";\n\nexport interface ReadBodyResult {\n\tbytes: Uint8Array;\n\twireFormat: OtlpWireFormat;\n}\n\nexport class OtlpDecodeError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly status: 400 | 415,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\n/**\n * Reads and decompresses an OTLP request body, returning the raw bytes plus\n * the inferred wire format. Throws `OtlpDecodeError` for unsupported content-\n * types or malformed gzip.\n */\nexport const readOtlpBody = async (c: Context): Promise<ReadBodyResult> => {\n\tconst contentType = (c.req.header(\"content-type\") ?? \"\").toLowerCase();\n\tconst wireFormat = detectWireFormat(contentType);\n\n\tlet body = await c.req.arrayBuffer();\n\tconst encoding = (c.req.header(\"content-encoding\") ?? \"\").toLowerCase();\n\tif (encoding === \"gzip\") {\n\t\tbody = await gunzip(body);\n\t} else if (encoding && encoding !== \"identity\") {\n\t\tthrow new OtlpDecodeError(`Unsupported content-encoding: ${encoding}`, 415);\n\t}\n\n\treturn { bytes: new Uint8Array(body), wireFormat };\n};\n\nconst detectWireFormat = (contentType: string): OtlpWireFormat => {\n\tif (contentType.includes(\"application/x-protobuf\")) return \"protobuf\";\n\tif (contentType.includes(\"application/json\")) return \"json\";\n\tthrow new OtlpDecodeError(\n\t\t`Unsupported content-type: ${contentType || \"(missing)\"}`,\n\t\t415,\n\t);\n};\n\nconst gunzip = async (input: ArrayBuffer): Promise<ArrayBuffer> => {\n\tconst stream = new Response(input).body?.pipeThrough(\n\t\tnew DecompressionStream(\"gzip\"),\n\t);\n\tif (!stream) throw new OtlpDecodeError(\"Empty gzip body\", 400);\n\treturn new Response(stream).arrayBuffer();\n};\n\nexport const decodeJsonBody = (bytes: Uint8Array): JsonValue => {\n\tconst text = new TextDecoder().decode(bytes);\n\tif (!text.length) return {};\n\tconst parsed = JSON.parse(text) as JsonValue;\n\trewriteHexIdsToBase64(parsed);\n\treturn parsed;\n};\n\n/**\n * The OTLP JSON encoding spec requires `trace_id` (16 bytes) and `span_id`\n * (8 bytes) to be lowercase hex strings — but proto-JSON's default encoding\n * for `bytes` fields is base64, which is what protobuf-es's `fromJson`\n * expects. The Go reference receiver accepts both; we do too, by walking\n * the parsed JSON and converting any hex-shaped ID field to base64 before\n * handing it to the schema decoder.\n *\n * Mutates the input in-place. Recognized field names cover every place a\n * trace/span ID appears in OTLP: span, link, log record, exemplar.\n */\nconst rewriteHexIdsToBase64 = (node: JsonValue): void => {\n\tif (Array.isArray(node)) {\n\t\tfor (const item of node) rewriteHexIdsToBase64(item);\n\t\treturn;\n\t}\n\tif (!node || typeof node !== \"object\") return;\n\tconst obj = node as Record<string, JsonValue>;\n\tfor (const key of Object.keys(obj)) {\n\t\tconst value = obj[key];\n\t\tif (typeof value === \"string\") {\n\t\t\tif ((key === \"traceId\" || key === \"trace_id\") && isHex(value, 32)) {\n\t\t\t\tobj[key] = hexToBase64(value);\n\t\t\t} else if (\n\t\t\t\t(key === \"spanId\" ||\n\t\t\t\t\tkey === \"span_id\" ||\n\t\t\t\t\tkey === \"parentSpanId\" ||\n\t\t\t\t\tkey === \"parent_span_id\") &&\n\t\t\t\tisHex(value, 16)\n\t\t\t) {\n\t\t\t\tobj[key] = hexToBase64(value);\n\t\t\t} else if (isTimestampKey(key) && !isUint64String(value)) {\n\t\t\t\tdelete obj[key];\n\t\t\t}\n\t\t} else if (isTimestampKey(key) && typeof value !== \"number\") {\n\t\t\tdelete obj[key];\n\t\t} else {\n\t\t\trewriteHexIdsToBase64(value);\n\t\t}\n\t}\n};\n\nconst isHex = (s: string, length: number): boolean =>\n\ts.length === length && /^[0-9a-f]+$/i.test(s);\n\nconst isTimestampKey = (key: string): boolean =>\n\tkey === \"timeUnixNano\" ||\n\tkey === \"observedTimeUnixNano\" ||\n\tkey === \"startTimeUnixNano\" ||\n\tkey === \"endTimeUnixNano\";\n\nconst isUint64String = (s: string): boolean => /^\\d+$/.test(s);\n\nconst hexToBase64 = (hex: string): string => {\n\tconst bytes = new Uint8Array(hex.length / 2);\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);\n\t}\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++)\n\t\tbinary += String.fromCharCode(bytes[i] ?? 0);\n\treturn btoa(binary);\n};\n","import { fromBinary, fromJson } from \"@bufbuild/protobuf\";\nimport type { LogSeverity, JsonValue as ObsJsonValue } from \"@obsunified/types\";\nimport {\n\ttype ExportLogsServiceRequest,\n\tExportLogsServiceRequestSchema,\n} from \"../gen/opentelemetry/proto/collector/logs/v1/logs_service_pb.js\";\nimport type { LogRecord as OtlpLogRecord } from \"../gen/opentelemetry/proto/logs/v1/logs_pb.js\";\nimport { decodeJsonBody, OtlpDecodeError, type ReadBodyResult } from \"./body\";\nimport {\n\tanyValueToString,\n\tbytesToHex,\n\textractServiceName,\n\tkeyValuesToRecord,\n\tseverityFromNumber,\n} from \"./values\";\n\n// ── Logs ─────────────────────────────────────────────────────────────\n\n/**\n * A log record normalized for storage. One per emitted OTLP `LogRecord`,\n * with resource / scope context flattened into the fields the `LogsStore`\n * expects. Receiver adds storage-level fields (projectId, logId, receivedAt,\n * expiresAt) at ingest time.\n */\nexport interface DecodedLogRecord {\n\tserviceName: string | null;\n\tloggerName: string | null;\n\ttraceId: string | null;\n\tspanId: string | null;\n\tseverity: LogSeverity;\n\tseverityNumber: number;\n\tmessage: string;\n\tattributes: Record<string, ObsJsonValue> | null;\n\tflags: number;\n\tdroppedAttributesCount: number;\n\toccurredAt: string;\n}\n\n/**\n * Decode an OTLP logs export request into a flat list of records ready for\n * storage. Resource `service.name` and scope name are denormalized onto each\n * record so downstream code doesn't need to traverse the hierarchy.\n */\nexport const decodeLogsRequest = (body: ReadBodyResult): DecodedLogRecord[] => {\n\tlet msg: ExportLogsServiceRequest;\n\ttry {\n\t\tmsg =\n\t\t\tbody.wireFormat === \"protobuf\"\n\t\t\t\t? fromBinary(ExportLogsServiceRequestSchema, body.bytes)\n\t\t\t\t: fromJson(ExportLogsServiceRequestSchema, decodeJsonBody(body.bytes));\n\t} catch (err) {\n\t\tthrow new OtlpDecodeError(\n\t\t\t`Malformed OTLP body: ${(err as Error).message}`,\n\t\t\t400,\n\t\t);\n\t}\n\n\tconst out: DecodedLogRecord[] = [];\n\tfor (const rl of msg.resourceLogs) {\n\t\tconst serviceName = extractServiceName(rl.resource?.attributes);\n\t\tfor (const sl of rl.scopeLogs) {\n\t\t\tconst loggerName = sl.scope?.name || null;\n\t\t\tfor (const log of sl.logRecords) {\n\t\t\t\tout.push(adaptLogRecord(log, serviceName, loggerName));\n\t\t\t}\n\t\t}\n\t}\n\treturn out;\n};\n\nconst adaptLogRecord = (\n\tlog: OtlpLogRecord,\n\tserviceName: string | null,\n\tloggerName: string | null,\n): DecodedLogRecord => {\n\tconst ts = log.timeUnixNano || log.observedTimeUnixNano;\n\tconst occurredAt =\n\t\tts > 0n\n\t\t\t? new Date(Number(ts / 1_000_000n)).toISOString()\n\t\t\t: new Date().toISOString();\n\treturn {\n\t\tserviceName,\n\t\tloggerName,\n\t\ttraceId: log.traceId.length === 16 ? bytesToHex(log.traceId) : null,\n\t\tspanId: log.spanId.length === 8 ? bytesToHex(log.spanId) : null,\n\t\tseverity: severityFromNumber(log.severityNumber, log.severityText),\n\t\tseverityNumber: log.severityNumber || 0,\n\t\tmessage: anyValueToString(log.body),\n\t\tattributes: log.attributes.length\n\t\t\t? keyValuesToRecord(log.attributes)\n\t\t\t: null,\n\t\tflags: log.flags || 0,\n\t\tdroppedAttributesCount: log.droppedAttributesCount || 0,\n\t\toccurredAt,\n\t};\n};\n","// Copyright 2020, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/collector/logs/v1/logs_service.proto (package opentelemetry.proto.collector.logs.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type {\n\tGenFile,\n\tGenMessage,\n\tGenService,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport {\n\tfileDesc,\n\tmessageDesc,\n\tserviceDesc,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport type { ResourceLogs } from \"../../../logs/v1/logs_pb.js\";\nimport { file_opentelemetry_proto_logs_v1_logs } from \"../../../logs/v1/logs_pb.js\";\n\n/**\n * Describes the file opentelemetry/proto/collector/logs/v1/logs_service.proto.\n */\nexport const file_opentelemetry_proto_collector_logs_v1_logs_service: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"CjhvcGVudGVsZW1ldHJ5L3Byb3RvL2NvbGxlY3Rvci9sb2dzL3YxL2xvZ3Nfc2VydmljZS5wcm90bxIlb3BlbnRlbGVtZXRyeS5wcm90by5jb2xsZWN0b3IubG9ncy52MSJcChhFeHBvcnRMb2dzU2VydmljZVJlcXVlc3QSQAoNcmVzb3VyY2VfbG9ncxgBIAMoCzIpLm9wZW50ZWxlbWV0cnkucHJvdG8ubG9ncy52MS5SZXNvdXJjZUxvZ3MidQoZRXhwb3J0TG9nc1NlcnZpY2VSZXNwb25zZRJYCg9wYXJ0aWFsX3N1Y2Nlc3MYASABKAsyPy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbGxlY3Rvci5sb2dzLnYxLkV4cG9ydExvZ3NQYXJ0aWFsU3VjY2VzcyJPChhFeHBvcnRMb2dzUGFydGlhbFN1Y2Nlc3MSHAoUcmVqZWN0ZWRfbG9nX3JlY29yZHMYASABKAMSFQoNZXJyb3JfbWVzc2FnZRgCIAEoCTKdAQoLTG9nc1NlcnZpY2USjQEKBkV4cG9ydBI/Lm9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLmxvZ3MudjEuRXhwb3J0TG9nc1NlcnZpY2VSZXF1ZXN0GkAub3BlbnRlbGVtZXRyeS5wcm90by5jb2xsZWN0b3IubG9ncy52MS5FeHBvcnRMb2dzU2VydmljZVJlc3BvbnNlIgBCmAEKKGlvLm9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLmxvZ3MudjFCEExvZ3NTZXJ2aWNlUHJvdG9QAVowZ28ub3BlbnRlbGVtZXRyeS5pby9wcm90by9vdGxwL2NvbGxlY3Rvci9sb2dzL3YxqgIlT3BlblRlbGVtZXRyeS5Qcm90by5Db2xsZWN0b3IuTG9ncy5WMWIGcHJvdG8z\",\n\t\t[file_opentelemetry_proto_logs_v1_logs],\n\t);\n\n/**\n * @generated from message opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest\n */\nexport type ExportLogsServiceRequest =\n\tMessage<\"opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest\"> & {\n\t\t/**\n\t\t * An array of ResourceLogs.\n\t\t * For data coming from a single resource this array will typically\n\t\t * contain one element. Intermediary nodes (such as OpenTelemetry\n\t\t * Collector) that receive data from multiple origins typically batch\n\t\t * the data before forwarding further.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.logs.v1.ResourceLogs resource_logs = 1;\n\t\t */\n\t\tresourceLogs: ResourceLogs[];\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest.\n * Use `create(ExportLogsServiceRequestSchema)` to create a new message.\n */\nexport const ExportLogsServiceRequestSchema: GenMessage<ExportLogsServiceRequest> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_logs_v1_logs_service, 0);\n\n/**\n * @generated from message opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse\n */\nexport type ExportLogsServiceResponse =\n\tMessage<\"opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse\"> & {\n\t\t/**\n\t\t * The details of a partially successful export request.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess partial_success = 1;\n\t\t */\n\t\tpartialSuccess?: ExportLogsPartialSuccess;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse.\n * Use `create(ExportLogsServiceResponseSchema)` to create a new message.\n */\nexport const ExportLogsServiceResponseSchema: GenMessage<ExportLogsServiceResponse> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_logs_v1_logs_service, 1);\n\n/**\n * @generated from message opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess\n */\nexport type ExportLogsPartialSuccess =\n\tMessage<\"opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess\"> & {\n\t\t/**\n\t\t * The number of rejected log records.\n\t\t *\n\t\t * A `rejected_<signal>` field holding a `0` value indicates that the\n\t\t * request was fully accepted.\n\t\t *\n\t\t * @generated from field: int64 rejected_log_records = 1;\n\t\t */\n\t\trejectedLogRecords: bigint;\n\n\t\t/**\n\t\t * A developer-facing human-readable message in English.\n\t\t *\n\t\t * @generated from field: string error_message = 2;\n\t\t */\n\t\terrorMessage: string;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess.\n * Use `create(ExportLogsPartialSuccessSchema)` to create a new message.\n */\nexport const ExportLogsPartialSuccessSchema: GenMessage<ExportLogsPartialSuccess> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_logs_v1_logs_service, 2);\n\n/**\n * Service that can be used to push logs between one Application\n * instrumented with OpenTelemetry and a collector, or between a\n * collector and a central collector.\n *\n * @generated from service opentelemetry.proto.collector.logs.v1.LogsService\n */\nexport const LogsService: GenService<{\n\t/**\n\t * @generated from rpc opentelemetry.proto.collector.logs.v1.LogsService.Export\n\t */\n\texport: {\n\t\tmethodKind: \"unary\";\n\t\tinput: typeof ExportLogsServiceRequestSchema;\n\t\toutput: typeof ExportLogsServiceResponseSchema;\n\t};\n}> =\n\t/*@__PURE__*/\n\tserviceDesc(file_opentelemetry_proto_collector_logs_v1_logs_service, 0);\n","// Copyright 2020, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/logs/v1/logs.proto (package opentelemetry.proto.logs.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type {\n\tGenEnum,\n\tGenFile,\n\tGenMessage,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport { enumDesc, fileDesc, messageDesc } from \"@bufbuild/protobuf/codegenv2\";\nimport type {\n\tAnyValue,\n\tInstrumentationScope,\n\tKeyValue,\n} from \"../../common/v1/common_pb.js\";\nimport { file_opentelemetry_proto_common_v1_common } from \"../../common/v1/common_pb.js\";\nimport type { Resource } from \"../../resource/v1/resource_pb.js\";\nimport { file_opentelemetry_proto_resource_v1_resource } from \"../../resource/v1/resource_pb.js\";\n\n/**\n * Describes the file opentelemetry/proto/logs/v1/logs.proto.\n */\nexport const file_opentelemetry_proto_logs_v1_logs: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"CiZvcGVudGVsZW1ldHJ5L3Byb3RvL2xvZ3MvdjEvbG9ncy5wcm90bxIbb3BlbnRlbGVtZXRyeS5wcm90by5sb2dzLnYxIkwKCExvZ3NEYXRhEkAKDXJlc291cmNlX2xvZ3MYASADKAsyKS5vcGVudGVsZW1ldHJ5LnByb3RvLmxvZ3MudjEuUmVzb3VyY2VMb2dzIqMBCgxSZXNvdXJjZUxvZ3MSOwoIcmVzb3VyY2UYASABKAsyKS5vcGVudGVsZW1ldHJ5LnByb3RvLnJlc291cmNlLnYxLlJlc291cmNlEjoKCnNjb3BlX2xvZ3MYAiADKAsyJi5vcGVudGVsZW1ldHJ5LnByb3RvLmxvZ3MudjEuU2NvcGVMb2dzEhIKCnNjaGVtYV91cmwYAyABKAlKBgjoBxDpByKgAQoJU2NvcGVMb2dzEkIKBXNjb3BlGAEgASgLMjMub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuSW5zdHJ1bWVudGF0aW9uU2NvcGUSOwoLbG9nX3JlY29yZHMYAiADKAsyJi5vcGVudGVsZW1ldHJ5LnByb3RvLmxvZ3MudjEuTG9nUmVjb3JkEhIKCnNjaGVtYV91cmwYAyABKAkigwMKCUxvZ1JlY29yZBIWCg50aW1lX3VuaXhfbmFubxgBIAEoBhIfChdvYnNlcnZlZF90aW1lX3VuaXhfbmFubxgLIAEoBhJECg9zZXZlcml0eV9udW1iZXIYAiABKA4yKy5vcGVudGVsZW1ldHJ5LnByb3RvLmxvZ3MudjEuU2V2ZXJpdHlOdW1iZXISFQoNc2V2ZXJpdHlfdGV4dBgDIAEoCRI1CgRib2R5GAUgASgLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuQW55VmFsdWUSOwoKYXR0cmlidXRlcxgGIAMoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxLktleVZhbHVlEiAKGGRyb3BwZWRfYXR0cmlidXRlc19jb3VudBgHIAEoDRINCgVmbGFncxgIIAEoBxIQCgh0cmFjZV9pZBgJIAEoDBIPCgdzcGFuX2lkGAogASgMEhIKCmV2ZW50X25hbWUYDCABKAlKBAgEEAUqwwUKDlNldmVyaXR5TnVtYmVyEh8KG1NFVkVSSVRZX05VTUJFUl9VTlNQRUNJRklFRBAAEhkKFVNFVkVSSVRZX05VTUJFUl9UUkFDRRABEhoKFlNFVkVSSVRZX05VTUJFUl9UUkFDRTIQAhIaChZTRVZFUklUWV9OVU1CRVJfVFJBQ0UzEAMSGgoWU0VWRVJJVFlfTlVNQkVSX1RSQUNFNBAEEhkKFVNFVkVSSVRZX05VTUJFUl9ERUJVRxAFEhoKFlNFVkVSSVRZX05VTUJFUl9ERUJVRzIQBhIaChZTRVZFUklUWV9OVU1CRVJfREVCVUczEAcSGgoWU0VWRVJJVFlfTlVNQkVSX0RFQlVHNBAIEhgKFFNFVkVSSVRZX05VTUJFUl9JTkZPEAkSGQoVU0VWRVJJVFlfTlVNQkVSX0lORk8yEAoSGQoVU0VWRVJJVFlfTlVNQkVSX0lORk8zEAsSGQoVU0VWRVJJVFlfTlVNQkVSX0lORk80EAwSGAoUU0VWRVJJVFlfTlVNQkVSX1dBUk4QDRIZChVTRVZFUklUWV9OVU1CRVJfV0FSTjIQDhIZChVTRVZFUklUWV9OVU1CRVJfV0FSTjMQDxIZChVTRVZFUklUWV9OVU1CRVJfV0FSTjQQEBIZChVTRVZFUklUWV9OVU1CRVJfRVJST1IQERIaChZTRVZFUklUWV9OVU1CRVJfRVJST1IyEBISGgoWU0VWRVJJVFlfTlVNQkVSX0VSUk9SMxATEhoKFlNFVkVSSVRZX05VTUJFUl9FUlJPUjQQFBIZChVTRVZFUklUWV9OVU1CRVJfRkFUQUwQFRIaChZTRVZFUklUWV9OVU1CRVJfRkFUQUwyEBYSGgoWU0VWRVJJVFlfTlVNQkVSX0ZBVEFMMxAXEhoKFlNFVkVSSVRZX05VTUJFUl9GQVRBTDQQGCpZCg5Mb2dSZWNvcmRGbGFncxIfChtMT0dfUkVDT1JEX0ZMQUdTX0RPX05PVF9VU0UQABImCiFMT0dfUkVDT1JEX0ZMQUdTX1RSQUNFX0ZMQUdTX01BU0sQ/wFCcwoeaW8ub3BlbnRlbGVtZXRyeS5wcm90by5sb2dzLnYxQglMb2dzUHJvdG9QAVomZ28ub3BlbnRlbGVtZXRyeS5pby9wcm90by9vdGxwL2xvZ3MvdjGqAhtPcGVuVGVsZW1ldHJ5LlByb3RvLkxvZ3MuVjFiBnByb3RvMw\",\n\t\t[\n\t\t\tfile_opentelemetry_proto_common_v1_common,\n\t\t\tfile_opentelemetry_proto_resource_v1_resource,\n\t\t],\n\t);\n\n/**\n * LogsData represents the logs data that can be stored in persistent\n * storage, OR can be embedded by other protocols that transfer OTLP logs\n * data but do not implement the OTLP protocol.\n *\n * @generated from message opentelemetry.proto.logs.v1.LogsData\n */\nexport type LogsData = Message<\"opentelemetry.proto.logs.v1.LogsData\"> & {\n\t/**\n\t * @generated from field: repeated opentelemetry.proto.logs.v1.ResourceLogs resource_logs = 1;\n\t */\n\tresourceLogs: ResourceLogs[];\n};\n\n/**\n * Describes the message opentelemetry.proto.logs.v1.LogsData.\n * Use `create(LogsDataSchema)` to create a new message.\n */\nexport const LogsDataSchema: GenMessage<LogsData> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_logs_v1_logs, 0);\n\n/**\n * A collection of ScopeLogs from a Resource.\n *\n * @generated from message opentelemetry.proto.logs.v1.ResourceLogs\n */\nexport type ResourceLogs =\n\tMessage<\"opentelemetry.proto.logs.v1.ResourceLogs\"> & {\n\t\t/**\n\t\t * The resource for the logs in this message.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.resource.v1.Resource resource = 1;\n\t\t */\n\t\tresource?: Resource;\n\n\t\t/**\n\t\t * A list of ScopeLogs that originate from a resource.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.logs.v1.ScopeLogs scope_logs = 2;\n\t\t */\n\t\tscopeLogs: ScopeLogs[];\n\n\t\t/**\n\t\t * The Schema URL, if known. This is the identifier of the Schema that the\n\t\t * resource data is recorded in. Notably, the last part of the URL path is\n\t\t * the version number of the schema.\n\t\t *\n\t\t * @generated from field: string schema_url = 3;\n\t\t */\n\t\tschemaUrl: string;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.logs.v1.ResourceLogs.\n * Use `create(ResourceLogsSchema)` to create a new message.\n */\nexport const ResourceLogsSchema: GenMessage<ResourceLogs> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_logs_v1_logs, 1);\n\n/**\n * A collection of Logs produced by a Scope.\n *\n * @generated from message opentelemetry.proto.logs.v1.ScopeLogs\n */\nexport type ScopeLogs = Message<\"opentelemetry.proto.logs.v1.ScopeLogs\"> & {\n\t/**\n\t * The instrumentation scope information for the logs in this message.\n\t *\n\t * @generated from field: opentelemetry.proto.common.v1.InstrumentationScope scope = 1;\n\t */\n\tscope?: InstrumentationScope;\n\n\t/**\n\t * A list of log records.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.logs.v1.LogRecord log_records = 2;\n\t */\n\tlogRecords: LogRecord[];\n\n\t/**\n\t * The Schema URL, if known.\n\t *\n\t * @generated from field: string schema_url = 3;\n\t */\n\tschemaUrl: string;\n};\n\n/**\n * Describes the message opentelemetry.proto.logs.v1.ScopeLogs.\n * Use `create(ScopeLogsSchema)` to create a new message.\n */\nexport const ScopeLogsSchema: GenMessage<ScopeLogs> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_logs_v1_logs, 2);\n\n/**\n * A log record according to OpenTelemetry Log Data Model.\n *\n * @generated from message opentelemetry.proto.logs.v1.LogRecord\n */\nexport type LogRecord = Message<\"opentelemetry.proto.logs.v1.LogRecord\"> & {\n\t/**\n\t * time_unix_nano is the time when the event occurred, measured as the\n\t * number of nanoseconds since Unix epoch.\n\t *\n\t * @generated from field: fixed64 time_unix_nano = 1;\n\t */\n\ttimeUnixNano: bigint;\n\n\t/**\n\t * Time when the event was observed by the collection system.\n\t *\n\t * @generated from field: fixed64 observed_time_unix_nano = 11;\n\t */\n\tobservedTimeUnixNano: bigint;\n\n\t/**\n\t * Numerical value of the severity, normalized to values described in\n\t * Log Data Model.\n\t *\n\t * @generated from field: opentelemetry.proto.logs.v1.SeverityNumber severity_number = 2;\n\t */\n\tseverityNumber: SeverityNumber;\n\n\t/**\n\t * The severity text (also known as log level).\n\t *\n\t * @generated from field: string severity_text = 3;\n\t */\n\tseverityText: string;\n\n\t/**\n\t * A value containing the body of the log record.\n\t *\n\t * @generated from field: opentelemetry.proto.common.v1.AnyValue body = 5;\n\t */\n\tbody?: AnyValue;\n\n\t/**\n\t * Additional attributes that describe the specific event occurrence.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 6;\n\t */\n\tattributes: KeyValue[];\n\n\t/**\n\t * @generated from field: uint32 dropped_attributes_count = 7;\n\t */\n\tdroppedAttributesCount: number;\n\n\t/**\n\t * Flags, a bit field. 8 least significant bits are the trace flags\n\t * as defined in W3C Trace Context specification.\n\t *\n\t * @generated from field: fixed32 flags = 8;\n\t */\n\tflags: number;\n\n\t/**\n\t * A unique identifier for a trace. All logs from the same trace\n\t * share the same `trace_id`.\n\t *\n\t * @generated from field: bytes trace_id = 9;\n\t */\n\ttraceId: Uint8Array;\n\n\t/**\n\t * A unique identifier for a span within a trace, assigned when the\n\t * span is created.\n\t *\n\t * @generated from field: bytes span_id = 10;\n\t */\n\tspanId: Uint8Array;\n\n\t/**\n\t * A unique identifier of event category/type.\n\t *\n\t * @generated from field: string event_name = 12;\n\t */\n\teventName: string;\n};\n\n/**\n * Describes the message opentelemetry.proto.logs.v1.LogRecord.\n * Use `create(LogRecordSchema)` to create a new message.\n */\nexport const LogRecordSchema: GenMessage<LogRecord> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_logs_v1_logs, 3);\n\n/**\n * Possible values for LogRecord.SeverityNumber.\n *\n * @generated from enum opentelemetry.proto.logs.v1.SeverityNumber\n */\nexport enum SeverityNumber {\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_UNSPECIFIED = 0;\n\t */\n\tUNSPECIFIED = 0,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_TRACE = 1;\n\t */\n\tTRACE = 1,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_TRACE2 = 2;\n\t */\n\tTRACE2 = 2,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_TRACE3 = 3;\n\t */\n\tTRACE3 = 3,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_TRACE4 = 4;\n\t */\n\tTRACE4 = 4,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_DEBUG = 5;\n\t */\n\tDEBUG = 5,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_DEBUG2 = 6;\n\t */\n\tDEBUG2 = 6,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_DEBUG3 = 7;\n\t */\n\tDEBUG3 = 7,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_DEBUG4 = 8;\n\t */\n\tDEBUG4 = 8,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_INFO = 9;\n\t */\n\tINFO = 9,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_INFO2 = 10;\n\t */\n\tINFO2 = 10,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_INFO3 = 11;\n\t */\n\tINFO3 = 11,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_INFO4 = 12;\n\t */\n\tINFO4 = 12,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_WARN = 13;\n\t */\n\tWARN = 13,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_WARN2 = 14;\n\t */\n\tWARN2 = 14,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_WARN3 = 15;\n\t */\n\tWARN3 = 15,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_WARN4 = 16;\n\t */\n\tWARN4 = 16,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_ERROR = 17;\n\t */\n\tERROR = 17,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_ERROR2 = 18;\n\t */\n\tERROR2 = 18,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_ERROR3 = 19;\n\t */\n\tERROR3 = 19,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_ERROR4 = 20;\n\t */\n\tERROR4 = 20,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_FATAL = 21;\n\t */\n\tFATAL = 21,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_FATAL2 = 22;\n\t */\n\tFATAL2 = 22,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_FATAL3 = 23;\n\t */\n\tFATAL3 = 23,\n\n\t/**\n\t * @generated from enum value: SEVERITY_NUMBER_FATAL4 = 24;\n\t */\n\tFATAL4 = 24,\n}\n\n/**\n * Describes the enum opentelemetry.proto.logs.v1.SeverityNumber.\n */\nexport const SeverityNumberSchema: GenEnum<SeverityNumber> =\n\t/*@__PURE__*/\n\tenumDesc(file_opentelemetry_proto_logs_v1_logs, 0);\n\n/**\n * LogRecordFlags represents constants used to interpret the\n * LogRecord.flags field, which is protobuf 'fixed32' type and is to\n * be used as bit-fields.\n *\n * @generated from enum opentelemetry.proto.logs.v1.LogRecordFlags\n */\nexport enum LogRecordFlags {\n\t/**\n\t * @generated from enum value: LOG_RECORD_FLAGS_DO_NOT_USE = 0;\n\t */\n\tDO_NOT_USE = 0,\n\n\t/**\n\t * @generated from enum value: LOG_RECORD_FLAGS_TRACE_FLAGS_MASK = 255;\n\t */\n\tTRACE_FLAGS_MASK = 255,\n}\n\n/**\n * Describes the enum opentelemetry.proto.logs.v1.LogRecordFlags.\n */\nexport const LogRecordFlagsSchema: GenEnum<LogRecordFlags> =\n\t/*@__PURE__*/\n\tenumDesc(file_opentelemetry_proto_logs_v1_logs, 1);\n","// Copyright 2019, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/common/v1/common.proto (package opentelemetry.proto.common.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type { GenFile, GenMessage } from \"@bufbuild/protobuf/codegenv2\";\nimport { fileDesc, messageDesc } from \"@bufbuild/protobuf/codegenv2\";\n\n/**\n * Describes the file opentelemetry/proto/common/v1/common.proto.\n */\nexport const file_opentelemetry_proto_common_v1_common: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"CipvcGVudGVsZW1ldHJ5L3Byb3RvL2NvbW1vbi92MS9jb21tb24ucHJvdG8SHW9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxIowCCghBbnlWYWx1ZRIWCgxzdHJpbmdfdmFsdWUYASABKAlIABIUCgpib29sX3ZhbHVlGAIgASgISAASEwoJaW50X3ZhbHVlGAMgASgDSAASFgoMZG91YmxlX3ZhbHVlGAQgASgBSAASQAoLYXJyYXlfdmFsdWUYBSABKAsyKS5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi52MS5BcnJheVZhbHVlSAASQwoMa3ZsaXN0X3ZhbHVlGAYgASgLMisub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuS2V5VmFsdWVMaXN0SAASFQoLYnl0ZXNfdmFsdWUYByABKAxIAEIHCgV2YWx1ZSJFCgpBcnJheVZhbHVlEjcKBnZhbHVlcxgBIAMoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxLkFueVZhbHVlIkcKDEtleVZhbHVlTGlzdBI3CgZ2YWx1ZXMYASADKAsyJy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi52MS5LZXlWYWx1ZSJPCghLZXlWYWx1ZRILCgNrZXkYASABKAkSNgoFdmFsdWUYAiABKAsyJy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi52MS5BbnlWYWx1ZSKUAQoUSW5zdHJ1bWVudGF0aW9uU2NvcGUSDAoEbmFtZRgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEjsKCmF0dHJpYnV0ZXMYAyADKAsyJy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi52MS5LZXlWYWx1ZRIgChhkcm9wcGVkX2F0dHJpYnV0ZXNfY291bnQYBCABKA0iWAoJRW50aXR5UmVmEhIKCnNjaGVtYV91cmwYASABKAkSDAoEdHlwZRgCIAEoCRIPCgdpZF9rZXlzGAMgAygJEhgKEGRlc2NyaXB0aW9uX2tleXMYBCADKAlCewogaW8ub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjFCC0NvbW1vblByb3RvUAFaKGdvLm9wZW50ZWxlbWV0cnkuaW8vcHJvdG8vb3RscC9jb21tb24vdjGqAh1PcGVuVGVsZW1ldHJ5LlByb3RvLkNvbW1vbi5WMWIGcHJvdG8z\",\n\t);\n\n/**\n * AnyValue is used to represent any type of attribute value. AnyValue may contain a\n * primitive value such as a string or integer or it may contain an arbitrary nested\n * object containing arrays, key-value lists and primitives.\n *\n * @generated from message opentelemetry.proto.common.v1.AnyValue\n */\nexport type AnyValue = Message<\"opentelemetry.proto.common.v1.AnyValue\"> & {\n\t/**\n\t * The value is one of the listed fields. It is valid for all values to be unspecified\n\t * in which case this AnyValue is considered to be \"empty\".\n\t *\n\t * @generated from oneof opentelemetry.proto.common.v1.AnyValue.value\n\t */\n\tvalue:\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: string string_value = 1;\n\t\t\t\t */\n\t\t\t\tvalue: string;\n\t\t\t\tcase: \"stringValue\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: bool bool_value = 2;\n\t\t\t\t */\n\t\t\t\tvalue: boolean;\n\t\t\t\tcase: \"boolValue\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: int64 int_value = 3;\n\t\t\t\t */\n\t\t\t\tvalue: bigint;\n\t\t\t\tcase: \"intValue\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: double double_value = 4;\n\t\t\t\t */\n\t\t\t\tvalue: number;\n\t\t\t\tcase: \"doubleValue\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: opentelemetry.proto.common.v1.ArrayValue array_value = 5;\n\t\t\t\t */\n\t\t\t\tvalue: ArrayValue;\n\t\t\t\tcase: \"arrayValue\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: opentelemetry.proto.common.v1.KeyValueList kvlist_value = 6;\n\t\t\t\t */\n\t\t\t\tvalue: KeyValueList;\n\t\t\t\tcase: \"kvlistValue\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: bytes bytes_value = 7;\n\t\t\t\t */\n\t\t\t\tvalue: Uint8Array;\n\t\t\t\tcase: \"bytesValue\";\n\t\t }\n\t\t| { case: undefined; value?: undefined };\n};\n\n/**\n * Describes the message opentelemetry.proto.common.v1.AnyValue.\n * Use `create(AnyValueSchema)` to create a new message.\n */\nexport const AnyValueSchema: GenMessage<AnyValue> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_common_v1_common, 0);\n\n/**\n * ArrayValue is a list of AnyValue messages. We need ArrayValue as a message\n * since oneof in AnyValue does not allow repeated fields.\n *\n * @generated from message opentelemetry.proto.common.v1.ArrayValue\n */\nexport type ArrayValue = Message<\"opentelemetry.proto.common.v1.ArrayValue\"> & {\n\t/**\n\t * Array of values. The array may be empty (contain 0 elements).\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.AnyValue values = 1;\n\t */\n\tvalues: AnyValue[];\n};\n\n/**\n * Describes the message opentelemetry.proto.common.v1.ArrayValue.\n * Use `create(ArrayValueSchema)` to create a new message.\n */\nexport const ArrayValueSchema: GenMessage<ArrayValue> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_common_v1_common, 1);\n\n/**\n * KeyValueList is a list of KeyValue messages. We need KeyValueList as a message\n * since `oneof` in AnyValue does not allow repeated fields. Everywhere else where we need\n * a list of KeyValue messages (e.g. in Span) we use `repeated KeyValue` directly to\n * avoid unnecessary extra wrapping (which slows down the protocol). The 2 approaches\n * are semantically equivalent.\n *\n * @generated from message opentelemetry.proto.common.v1.KeyValueList\n */\nexport type KeyValueList =\n\tMessage<\"opentelemetry.proto.common.v1.KeyValueList\"> & {\n\t\t/**\n\t\t * A collection of key/value pairs of key-value pairs. The list may be empty (may\n\t\t * contain 0 elements).\n\t\t * The keys MUST be unique (it is not allowed to have more than one\n\t\t * value with the same key).\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue values = 1;\n\t\t */\n\t\tvalues: KeyValue[];\n\t};\n\n/**\n * Describes the message opentelemetry.proto.common.v1.KeyValueList.\n * Use `create(KeyValueListSchema)` to create a new message.\n */\nexport const KeyValueListSchema: GenMessage<KeyValueList> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_common_v1_common, 2);\n\n/**\n * KeyValue is a key-value pair that is used to store Span attributes, Link\n * attributes, etc.\n *\n * @generated from message opentelemetry.proto.common.v1.KeyValue\n */\nexport type KeyValue = Message<\"opentelemetry.proto.common.v1.KeyValue\"> & {\n\t/**\n\t * @generated from field: string key = 1;\n\t */\n\tkey: string;\n\n\t/**\n\t * @generated from field: opentelemetry.proto.common.v1.AnyValue value = 2;\n\t */\n\tvalue?: AnyValue;\n};\n\n/**\n * Describes the message opentelemetry.proto.common.v1.KeyValue.\n * Use `create(KeyValueSchema)` to create a new message.\n */\nexport const KeyValueSchema: GenMessage<KeyValue> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_common_v1_common, 3);\n\n/**\n * InstrumentationScope is a message representing the instrumentation scope information\n * such as the fully qualified name and version.\n *\n * @generated from message opentelemetry.proto.common.v1.InstrumentationScope\n */\nexport type InstrumentationScope =\n\tMessage<\"opentelemetry.proto.common.v1.InstrumentationScope\"> & {\n\t\t/**\n\t\t * An empty instrumentation scope name means the name is unknown.\n\t\t *\n\t\t * @generated from field: string name = 1;\n\t\t */\n\t\tname: string;\n\n\t\t/**\n\t\t * @generated from field: string version = 2;\n\t\t */\n\t\tversion: string;\n\n\t\t/**\n\t\t * Additional attributes that describe the scope. [Optional].\n\t\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t\t * attribute with the same key).\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 3;\n\t\t */\n\t\tattributes: KeyValue[];\n\n\t\t/**\n\t\t * @generated from field: uint32 dropped_attributes_count = 4;\n\t\t */\n\t\tdroppedAttributesCount: number;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.common.v1.InstrumentationScope.\n * Use `create(InstrumentationScopeSchema)` to create a new message.\n */\nexport const InstrumentationScopeSchema: GenMessage<InstrumentationScope> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_common_v1_common, 4);\n\n/**\n * A reference to an Entity.\n * Entity represents an object of interest associated with produced telemetry: e.g spans, metrics, profiles, or logs.\n *\n * Status: [Development]\n *\n * @generated from message opentelemetry.proto.common.v1.EntityRef\n */\nexport type EntityRef = Message<\"opentelemetry.proto.common.v1.EntityRef\"> & {\n\t/**\n\t * The Schema URL, if known. This is the identifier of the Schema that the entity data\n\t * is recorded in. To learn more about Schema URL see\n\t * https://opentelemetry.io/docs/specs/otel/schemas/#schema-url\n\t *\n\t * This schema_url applies to the data in this message and to the Resource attributes\n\t * referenced by id_keys and description_keys.\n\t * TODO: discuss if we are happy with this somewhat complicated definition of what\n\t * the schema_url applies to.\n\t *\n\t * This field obsoletes the schema_url field in ResourceMetrics/ResourceSpans/ResourceLogs.\n\t *\n\t * @generated from field: string schema_url = 1;\n\t */\n\tschemaUrl: string;\n\n\t/**\n\t * Defines the type of the entity. MUST not change during the lifetime of the entity.\n\t * For example: \"service\" or \"host\". This field is required and MUST not be empty\n\t * for valid entities.\n\t *\n\t * @generated from field: string type = 2;\n\t */\n\ttype: string;\n\n\t/**\n\t * Attribute Keys that identify the entity.\n\t * MUST not change during the lifetime of the entity. The Id must contain at least one attribute.\n\t * These keys MUST exist in the containing {message}.attributes.\n\t *\n\t * @generated from field: repeated string id_keys = 3;\n\t */\n\tidKeys: string[];\n\n\t/**\n\t * Descriptive (non-identifying) attribute keys of the entity.\n\t * MAY change over the lifetime of the entity. MAY be empty.\n\t * These attribute keys are not part of entity's identity.\n\t * These keys MUST exist in the containing {message}.attributes.\n\t *\n\t * @generated from field: repeated string description_keys = 4;\n\t */\n\tdescriptionKeys: string[];\n};\n\n/**\n * Describes the message opentelemetry.proto.common.v1.EntityRef.\n * Use `create(EntityRefSchema)` to create a new message.\n */\nexport const EntityRefSchema: GenMessage<EntityRef> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_common_v1_common, 5);\n","// Copyright 2019, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/resource/v1/resource.proto (package opentelemetry.proto.resource.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type { GenFile, GenMessage } from \"@bufbuild/protobuf/codegenv2\";\nimport { fileDesc, messageDesc } from \"@bufbuild/protobuf/codegenv2\";\nimport type { EntityRef, KeyValue } from \"../../common/v1/common_pb.js\";\nimport { file_opentelemetry_proto_common_v1_common } from \"../../common/v1/common_pb.js\";\n\n/**\n * Describes the file opentelemetry/proto/resource/v1/resource.proto.\n */\nexport const file_opentelemetry_proto_resource_v1_resource: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"Ci5vcGVudGVsZW1ldHJ5L3Byb3RvL3Jlc291cmNlL3YxL3Jlc291cmNlLnByb3RvEh9vcGVudGVsZW1ldHJ5LnByb3RvLnJlc291cmNlLnYxIqgBCghSZXNvdXJjZRI7CgphdHRyaWJ1dGVzGAEgAygLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuS2V5VmFsdWUSIAoYZHJvcHBlZF9hdHRyaWJ1dGVzX2NvdW50GAIgASgNEj0KC2VudGl0eV9yZWZzGAMgAygLMigub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuRW50aXR5UmVmQoMBCiJpby5vcGVudGVsZW1ldHJ5LnByb3RvLnJlc291cmNlLnYxQg1SZXNvdXJjZVByb3RvUAFaKmdvLm9wZW50ZWxlbWV0cnkuaW8vcHJvdG8vb3RscC9yZXNvdXJjZS92MaoCH09wZW5UZWxlbWV0cnkuUHJvdG8uUmVzb3VyY2UuVjFiBnByb3RvMw\",\n\t\t[file_opentelemetry_proto_common_v1_common],\n\t);\n\n/**\n * Resource information.\n *\n * @generated from message opentelemetry.proto.resource.v1.Resource\n */\nexport type Resource = Message<\"opentelemetry.proto.resource.v1.Resource\"> & {\n\t/**\n\t * Set of attributes that describe the resource.\n\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t * attribute with the same key).\n\t *\n\t * The attribute values SHOULD NOT contain empty values.\n\t * The attribute values SHOULD NOT contain bytes values.\n\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t * double values.\n\t * The attribute values SHOULD NOT contain kvlist values.\n\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t * These restrictions can change in a minor release.\n\t * The restrictions take origin from the OpenTelemetry specification:\n\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 1;\n\t */\n\tattributes: KeyValue[];\n\n\t/**\n\t * dropped_attributes_count is the number of dropped attributes. If the value is 0, then\n\t * no attributes were dropped.\n\t *\n\t * @generated from field: uint32 dropped_attributes_count = 2;\n\t */\n\tdroppedAttributesCount: number;\n\n\t/**\n\t * Set of entities that participate in this Resource.\n\t *\n\t * Note: keys in the references MUST exist in attributes of this message.\n\t *\n\t * Status: [Development]\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.EntityRef entity_refs = 3;\n\t */\n\tentityRefs: EntityRef[];\n};\n\n/**\n * Describes the message opentelemetry.proto.resource.v1.Resource.\n * Use `create(ResourceSchema)` to create a new message.\n */\nexport const ResourceSchema: GenMessage<Resource> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_resource_v1_resource, 0);\n","import type {\n\tLogSeverity,\n\tJsonValue as ObsJsonValue,\n\tOtlpAnyValue,\n\tOtlpKeyValue,\n} from \"@obsunified/types\";\nimport type {\n\tAnyValue,\n\tKeyValue,\n} from \"../gen/opentelemetry/proto/common/v1/common_pb.js\";\n\nexport const extractServiceName = (\n\tattrs: KeyValue[] | undefined,\n): string | null => {\n\tif (!attrs) return null;\n\tconst match = attrs.find((a) => a.key === \"service.name\");\n\tif (!match?.value) return null;\n\treturn match.value.value.case === \"stringValue\"\n\t\t? match.value.value.value\n\t\t: null;\n};\n\nexport const severityFromNumber = (n: number, text: string): LogSeverity => {\n\tif (n >= 21) return \"FATAL\";\n\tif (n >= 17) return \"ERROR\";\n\tif (n >= 13) return \"WARN\";\n\tif (n >= 9) return \"INFO\";\n\tif (n >= 5) return \"DEBUG\";\n\tif (n >= 1) return \"DEBUG\"; // TRACE collapsed to DEBUG\n\t// severityNumber unset — fall back to text, then INFO default.\n\tconst upper = text.toUpperCase();\n\tif (\n\t\tupper === \"FATAL\" ||\n\t\tupper === \"ERROR\" ||\n\t\tupper === \"WARN\" ||\n\t\tupper === \"INFO\" ||\n\t\tupper === \"DEBUG\"\n\t)\n\t\treturn upper;\n\treturn \"INFO\";\n};\n\nexport const anyValueToString = (v: AnyValue | undefined): string => {\n\tif (!v) return \"\";\n\tswitch (v.value.case) {\n\t\tcase \"stringValue\":\n\t\t\treturn v.value.value;\n\t\tcase \"boolValue\":\n\t\t\treturn String(v.value.value);\n\t\tcase \"intValue\":\n\t\t\treturn v.value.value.toString();\n\t\tcase \"doubleValue\":\n\t\t\treturn String(v.value.value);\n\t\tcase \"bytesValue\":\n\t\t\treturn bytesToBase64(v.value.value);\n\t\tcase \"arrayValue\":\n\t\tcase \"kvlistValue\":\n\t\t\treturn JSON.stringify(adaptAnyValue(v));\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n};\n\nexport const keyValuesToRecord = (\n\tkvs: KeyValue[],\n): Record<string, ObsJsonValue> => {\n\tconst out: Record<string, ObsJsonValue> = {};\n\tfor (const kv of kvs) {\n\t\tout[kv.key] = anyValueToJson(kv.value);\n\t}\n\treturn out;\n};\n\nconst anyValueToJson = (v: AnyValue | undefined): ObsJsonValue => {\n\tif (!v) return null;\n\tswitch (v.value.case) {\n\t\tcase \"stringValue\":\n\t\t\treturn v.value.value;\n\t\tcase \"boolValue\":\n\t\t\treturn v.value.value;\n\t\tcase \"intValue\":\n\t\t\t// OTel int is int64. Downgrade safely; lossy above 2^53 but rare for attrs.\n\t\t\treturn Number(v.value.value);\n\t\tcase \"doubleValue\":\n\t\t\treturn v.value.value;\n\t\tcase \"bytesValue\":\n\t\t\treturn bytesToBase64(v.value.value);\n\t\tcase \"arrayValue\":\n\t\t\treturn v.value.value.values.map((x) => anyValueToJson(x));\n\t\tcase \"kvlistValue\":\n\t\t\treturn keyValuesToRecord(v.value.value.values);\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n\nexport const adaptKeyValue = (kv: KeyValue): OtlpKeyValue => ({\n\tkey: kv.key,\n\tvalue: kv.value ? adaptAnyValue(kv.value) : undefined,\n});\n\nexport const adaptAnyValue = (v: AnyValue): OtlpAnyValue => {\n\tswitch (v.value.case) {\n\t\tcase \"stringValue\":\n\t\t\treturn { stringValue: v.value.value };\n\t\tcase \"boolValue\":\n\t\t\treturn { boolValue: v.value.value };\n\t\tcase \"intValue\":\n\t\t\treturn { intValue: v.value.value.toString() };\n\t\tcase \"doubleValue\":\n\t\t\treturn { doubleValue: v.value.value };\n\t\tcase \"arrayValue\":\n\t\t\treturn {\n\t\t\t\tarrayValue: {\n\t\t\t\t\tvalues: v.value.value.values.map((x) => adaptAnyValue(x)),\n\t\t\t\t},\n\t\t\t};\n\t\tcase \"kvlistValue\":\n\t\t\treturn {\n\t\t\t\tkvlistValue: {\n\t\t\t\t\tvalues: v.value.value.values.map(adaptKeyValue),\n\t\t\t\t},\n\t\t\t};\n\t\tcase \"bytesValue\":\n\t\t\t// Surface bytes as base64 string — matches proto-JSON mapping spec.\n\t\t\treturn { stringValue: bytesToBase64(v.value.value) };\n\t\tdefault:\n\t\t\treturn {};\n\t}\n};\n\nconst HEX_CHARS = \"0123456789abcdef\";\nexport const bytesToHex = (bytes: Uint8Array): string => {\n\tlet out = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tconst b = bytes[i] ?? 0;\n\t\tout += HEX_CHARS[b >> 4];\n\t\tout += HEX_CHARS[b & 0xf];\n\t}\n\treturn out;\n};\n\nexport const bigintToString = (n: bigint): string => n.toString();\n\nexport const bytesToBase64 = (bytes: Uint8Array): string => {\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++)\n\t\tbinary += String.fromCharCode(bytes[i] ?? 0);\n\treturn btoa(binary);\n};\n","import { fromBinary, fromJson } from \"@bufbuild/protobuf\";\nimport {\n\ttype ExportMetricsServiceRequest,\n\tExportMetricsServiceRequestSchema,\n} from \"../gen/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.js\";\nimport type { KeyValue } from \"../gen/opentelemetry/proto/common/v1/common_pb.js\";\nimport type {\n\tExemplar,\n\tExponentialHistogramDataPoint,\n\tHistogramDataPoint,\n\tMetric,\n\tNumberDataPoint,\n\tResourceMetrics,\n\tScopeMetrics,\n\tSummaryDataPoint,\n} from \"../gen/opentelemetry/proto/metrics/v1/metrics_pb.js\";\nimport { decodeJsonBody, OtlpDecodeError, type ReadBodyResult } from \"./body\";\nimport { bytesToHex, extractServiceName, keyValuesToRecord } from \"./values\";\n\n// ── Metrics ───────────────────────────────────────────────────────────\n\nexport type MetricType =\n\t| \"gauge\"\n\t| \"sum\"\n\t| \"histogram\"\n\t| \"exp_histogram\"\n\t| \"summary\";\n\nexport interface DecodedExemplar {\n\tvalue: number;\n\ttraceId: string | null;\n\tspanId: string | null;\n\ttsNs: string;\n}\n\n/**\n * A metric data point normalized for storage. Series-identifying fields\n * (name, resource/scope context, attributes) are repeated on each point so\n * the store can do series upsert in a single pass.\n */\nexport interface DecodedMetricPoint {\n\t// Series identity\n\tname: string;\n\tdescription: string | null;\n\tunit: string | null;\n\ttype: MetricType;\n\tisMonotonic: boolean | null;\n\ttemporality: number | null;\n\tscopeName: string | null;\n\tscopeVersion: string | null;\n\tserviceName: string | null;\n\tresourceAttrsJson: string | null;\n\tattributesJson: string | null;\n\tidentity: string;\n\n\t// Point\n\ttsNs: string;\n\tstartTsNs: string | null;\n\tvalue: number | null;\n\n\t// Histogram-only\n\tcount: number | null;\n\tsum: number | null;\n\tmin: number | null;\n\tmax: number | null;\n\tboundsJson: string | null;\n\tbucketCountsJson: string | null;\n\n\t/**\n\t * Type-specific fields that don't fit the column schema:\n\t * - exp_histogram: { scale, zeroCount, zeroThreshold, positive: {offset, bucketCounts}, negative: {offset, bucketCounts} }\n\t * - summary: { quantileValues: [{quantile, value}, ...] }\n\t */\n\textraJson: string | null;\n\n\texemplarsJson: string | null;\n}\n\nexport const decodeMetricsRequest = (\n\tbody: ReadBodyResult,\n): DecodedMetricPoint[] => {\n\tlet msg: ExportMetricsServiceRequest;\n\ttry {\n\t\tmsg =\n\t\t\tbody.wireFormat === \"protobuf\"\n\t\t\t\t? fromBinary(ExportMetricsServiceRequestSchema, body.bytes)\n\t\t\t\t: fromJson(\n\t\t\t\t\t\tExportMetricsServiceRequestSchema,\n\t\t\t\t\t\tdecodeJsonBody(body.bytes),\n\t\t\t\t\t);\n\t} catch (err) {\n\t\tthrow new OtlpDecodeError(\n\t\t\t`Malformed OTLP body: ${(err as Error).message}`,\n\t\t\t400,\n\t\t);\n\t}\n\n\tconst out: DecodedMetricPoint[] = [];\n\tfor (const rm of msg.resourceMetrics) {\n\t\tconst resourceAttrs = rm.resource?.attributes ?? [];\n\t\tconst resourceAttrsJson = resourceAttrs.length\n\t\t\t? JSON.stringify(keyValuesToRecord(resourceAttrs))\n\t\t\t: null;\n\t\tconst serviceName = extractServiceName(resourceAttrs);\n\t\tfor (const sm of rm.scopeMetrics) {\n\t\t\taddMetrics(out, rm, sm, serviceName, resourceAttrsJson);\n\t\t}\n\t}\n\treturn out;\n};\n\nconst addMetrics = (\n\tout: DecodedMetricPoint[],\n\trm: ResourceMetrics,\n\tsm: ScopeMetrics,\n\tserviceName: string | null,\n\tresourceAttrsJson: string | null,\n) => {\n\tconst scopeName = sm.scope?.name || null;\n\tconst scopeVersion = sm.scope?.version || null;\n\tconst resourceIdentityFragment = canonicalKeyValues(\n\t\trm.resource?.attributes ?? [],\n\t);\n\n\tfor (const metric of sm.metrics) {\n\t\tconst common = {\n\t\t\tname: metric.name,\n\t\t\tdescription: metric.description || null,\n\t\t\tunit: metric.unit || null,\n\t\t\tscopeName,\n\t\t\tscopeVersion,\n\t\t\tserviceName,\n\t\t\tresourceAttrsJson,\n\t\t};\n\t\tswitch (metric.data.case) {\n\t\t\tcase \"gauge\":\n\t\t\t\tfor (const p of metric.data.value.dataPoints) {\n\t\t\t\t\tout.push(\n\t\t\t\t\t\tnumberPoint(metric, p, \"gauge\", common, resourceIdentityFragment),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"sum\":\n\t\t\t\tfor (const p of metric.data.value.dataPoints) {\n\t\t\t\t\tout.push({\n\t\t\t\t\t\t...numberPoint(metric, p, \"sum\", common, resourceIdentityFragment),\n\t\t\t\t\t\tisMonotonic: metric.data.value.isMonotonic,\n\t\t\t\t\t\ttemporality: metric.data.value.aggregationTemporality,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"histogram\":\n\t\t\t\tfor (const p of metric.data.value.dataPoints) {\n\t\t\t\t\tout.push({\n\t\t\t\t\t\t...histogramPoint(metric, p, common, resourceIdentityFragment),\n\t\t\t\t\t\ttemporality: metric.data.value.aggregationTemporality,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"exponentialHistogram\":\n\t\t\t\tfor (const p of metric.data.value.dataPoints) {\n\t\t\t\t\tout.push({\n\t\t\t\t\t\t...expHistogramPoint(metric, p, common, resourceIdentityFragment),\n\t\t\t\t\t\ttemporality: metric.data.value.aggregationTemporality,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"summary\":\n\t\t\t\tfor (const p of metric.data.value.dataPoints) {\n\t\t\t\t\tout.push(summaryPoint(metric, p, common, resourceIdentityFragment));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n};\n\ntype SeriesCommon = {\n\tname: string;\n\tdescription: string | null;\n\tunit: string | null;\n\tscopeName: string | null;\n\tscopeVersion: string | null;\n\tserviceName: string | null;\n\tresourceAttrsJson: string | null;\n};\n\nconst numberPoint = (\n\tmetric: Metric,\n\tp: NumberDataPoint,\n\ttype: MetricType,\n\tcommon: SeriesCommon,\n\tresourceIdentityFragment: string,\n): DecodedMetricPoint => {\n\tconst value =\n\t\tp.value.case === \"asDouble\"\n\t\t\t? p.value.value\n\t\t\t: p.value.case === \"asInt\"\n\t\t\t\t? Number(p.value.value)\n\t\t\t\t: null;\n\tconst attrsRecord = p.attributes.length\n\t\t? keyValuesToRecord(p.attributes)\n\t\t: null;\n\treturn {\n\t\t...common,\n\t\ttype,\n\t\tisMonotonic: null,\n\t\ttemporality: null,\n\t\tattributesJson: attrsRecord ? JSON.stringify(attrsRecord) : null,\n\t\tidentity: buildIdentity(\n\t\t\tresourceIdentityFragment,\n\t\t\tcommon.scopeName,\n\t\t\tmetric.name,\n\t\t\tp.attributes,\n\t\t),\n\t\ttsNs: p.timeUnixNano.toString(),\n\t\tstartTsNs: p.startTimeUnixNano > 0n ? p.startTimeUnixNano.toString() : null,\n\t\tvalue,\n\t\tcount: null,\n\t\tsum: null,\n\t\tmin: null,\n\t\tmax: null,\n\t\tboundsJson: null,\n\t\tbucketCountsJson: null,\n\t\textraJson: null,\n\t\texemplarsJson: encodeExemplars(p.exemplars),\n\t};\n};\n\nconst histogramPoint = (\n\tmetric: Metric,\n\tp: HistogramDataPoint,\n\tcommon: SeriesCommon,\n\tresourceIdentityFragment: string,\n): DecodedMetricPoint => {\n\tconst attrsRecord = p.attributes.length\n\t\t? keyValuesToRecord(p.attributes)\n\t\t: null;\n\treturn {\n\t\t...common,\n\t\ttype: \"histogram\",\n\t\tisMonotonic: null,\n\t\ttemporality: null,\n\t\tattributesJson: attrsRecord ? JSON.stringify(attrsRecord) : null,\n\t\tidentity: buildIdentity(\n\t\t\tresourceIdentityFragment,\n\t\t\tcommon.scopeName,\n\t\t\tmetric.name,\n\t\t\tp.attributes,\n\t\t),\n\t\ttsNs: p.timeUnixNano.toString(),\n\t\tstartTsNs: p.startTimeUnixNano > 0n ? p.startTimeUnixNano.toString() : null,\n\t\tvalue: null,\n\t\tcount: Number(p.count),\n\t\tsum: p.sum ?? null,\n\t\tmin: p.min ?? null,\n\t\tmax: p.max ?? null,\n\t\tboundsJson: p.explicitBounds.length\n\t\t\t? JSON.stringify(p.explicitBounds)\n\t\t\t: null,\n\t\tbucketCountsJson: p.bucketCounts.length\n\t\t\t? JSON.stringify(p.bucketCounts.map((b) => Number(b)))\n\t\t\t: null,\n\t\textraJson: null,\n\t\texemplarsJson: encodeExemplars(p.exemplars),\n\t};\n};\n\nconst expHistogramPoint = (\n\tmetric: Metric,\n\tp: ExponentialHistogramDataPoint,\n\tcommon: SeriesCommon,\n\tresourceIdentityFragment: string,\n): DecodedMetricPoint => {\n\tconst attrsRecord = p.attributes.length\n\t\t? keyValuesToRecord(p.attributes)\n\t\t: null;\n\tconst extra = {\n\t\tscale: p.scale,\n\t\tzeroCount: Number(p.zeroCount),\n\t\tzeroThreshold: p.zeroThreshold,\n\t\tpositive: p.positive\n\t\t\t? {\n\t\t\t\t\toffset: p.positive.offset,\n\t\t\t\t\tbucketCounts: p.positive.bucketCounts.map((b) => Number(b)),\n\t\t\t\t}\n\t\t\t: null,\n\t\tnegative: p.negative\n\t\t\t? {\n\t\t\t\t\toffset: p.negative.offset,\n\t\t\t\t\tbucketCounts: p.negative.bucketCounts.map((b) => Number(b)),\n\t\t\t\t}\n\t\t\t: null,\n\t};\n\treturn {\n\t\t...common,\n\t\ttype: \"exp_histogram\",\n\t\tisMonotonic: null,\n\t\ttemporality: null,\n\t\tattributesJson: attrsRecord ? JSON.stringify(attrsRecord) : null,\n\t\tidentity: buildIdentity(\n\t\t\tresourceIdentityFragment,\n\t\t\tcommon.scopeName,\n\t\t\tmetric.name,\n\t\t\tp.attributes,\n\t\t),\n\t\ttsNs: p.timeUnixNano.toString(),\n\t\tstartTsNs: p.startTimeUnixNano > 0n ? p.startTimeUnixNano.toString() : null,\n\t\tvalue: null,\n\t\tcount: Number(p.count),\n\t\tsum: p.sum ?? null,\n\t\tmin: p.min ?? null,\n\t\tmax: p.max ?? null,\n\t\tboundsJson: null,\n\t\tbucketCountsJson: null,\n\t\textraJson: JSON.stringify(extra),\n\t\texemplarsJson: encodeExemplars(p.exemplars),\n\t};\n};\n\nconst summaryPoint = (\n\tmetric: Metric,\n\tp: SummaryDataPoint,\n\tcommon: SeriesCommon,\n\tresourceIdentityFragment: string,\n): DecodedMetricPoint => {\n\tconst attrsRecord = p.attributes.length\n\t\t? keyValuesToRecord(p.attributes)\n\t\t: null;\n\tconst extra = {\n\t\tquantileValues: p.quantileValues.map((q) => ({\n\t\t\tquantile: q.quantile,\n\t\t\tvalue: q.value,\n\t\t})),\n\t};\n\treturn {\n\t\t...common,\n\t\ttype: \"summary\",\n\t\tisMonotonic: null,\n\t\ttemporality: null,\n\t\tattributesJson: attrsRecord ? JSON.stringify(attrsRecord) : null,\n\t\tidentity: buildIdentity(\n\t\t\tresourceIdentityFragment,\n\t\t\tcommon.scopeName,\n\t\t\tmetric.name,\n\t\t\tp.attributes,\n\t\t),\n\t\ttsNs: p.timeUnixNano.toString(),\n\t\tstartTsNs: p.startTimeUnixNano > 0n ? p.startTimeUnixNano.toString() : null,\n\t\tvalue: null,\n\t\tcount: Number(p.count),\n\t\tsum: p.sum,\n\t\tmin: null,\n\t\tmax: null,\n\t\tboundsJson: null,\n\t\tbucketCountsJson: null,\n\t\textraJson: JSON.stringify(extra),\n\t\texemplarsJson: null, // Summary has no exemplars in the spec.\n\t};\n};\n\nconst encodeExemplars = (exemplars: Exemplar[]): string | null => {\n\tif (!exemplars.length) return null;\n\treturn JSON.stringify(\n\t\texemplars.map<DecodedExemplar>((e) => ({\n\t\t\tvalue:\n\t\t\t\te.value.case === \"asDouble\"\n\t\t\t\t\t? e.value.value\n\t\t\t\t\t: e.value.case === \"asInt\"\n\t\t\t\t\t\t? Number(e.value.value)\n\t\t\t\t\t\t: 0,\n\t\t\ttraceId: e.traceId.length === 16 ? bytesToHex(e.traceId) : null,\n\t\t\tspanId: e.spanId.length === 8 ? bytesToHex(e.spanId) : null,\n\t\t\ttsNs: e.timeUnixNano.toString(),\n\t\t})),\n\t);\n};\n\n/**\n * Canonical series identity. Stable across encodings (JSON/proto) because\n * attributes are sorted and values normalized. Short enough to index.\n */\nconst buildIdentity = (\n\tresourceFragment: string,\n\tscopeName: string | null,\n\tmetricName: string,\n\tattrs: KeyValue[],\n): string =>\n\tJSON.stringify([\n\t\tresourceFragment,\n\t\tscopeName ?? \"\",\n\t\tmetricName,\n\t\tcanonicalKeyValues(attrs),\n\t]);\n\nconst canonicalKeyValues = (attrs: KeyValue[]): string => {\n\tif (!attrs.length) return \"\";\n\tconst rec = keyValuesToRecord(attrs);\n\tconst keys = Object.keys(rec).sort();\n\treturn JSON.stringify(keys.map((k) => [k, rec[k]]));\n};\n","// Copyright 2019, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/collector/metrics/v1/metrics_service.proto (package opentelemetry.proto.collector.metrics.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type {\n\tGenFile,\n\tGenMessage,\n\tGenService,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport {\n\tfileDesc,\n\tmessageDesc,\n\tserviceDesc,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport type { ResourceMetrics } from \"../../../metrics/v1/metrics_pb.js\";\nimport { file_opentelemetry_proto_metrics_v1_metrics } from \"../../../metrics/v1/metrics_pb.js\";\n\n/**\n * Describes the file opentelemetry/proto/collector/metrics/v1/metrics_service.proto.\n */\nexport const file_opentelemetry_proto_collector_metrics_v1_metrics_service: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"Cj5vcGVudGVsZW1ldHJ5L3Byb3RvL2NvbGxlY3Rvci9tZXRyaWNzL3YxL21ldHJpY3Nfc2VydmljZS5wcm90bxIob3BlbnRlbGVtZXRyeS5wcm90by5jb2xsZWN0b3IubWV0cmljcy52MSJoChtFeHBvcnRNZXRyaWNzU2VydmljZVJlcXVlc3QSSQoQcmVzb3VyY2VfbWV0cmljcxgBIAMoCzIvLm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5SZXNvdXJjZU1ldHJpY3MifgocRXhwb3J0TWV0cmljc1NlcnZpY2VSZXNwb25zZRJeCg9wYXJ0aWFsX3N1Y2Nlc3MYASABKAsyRS5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbGxlY3Rvci5tZXRyaWNzLnYxLkV4cG9ydE1ldHJpY3NQYXJ0aWFsU3VjY2VzcyJSChtFeHBvcnRNZXRyaWNzUGFydGlhbFN1Y2Nlc3MSHAoUcmVqZWN0ZWRfZGF0YV9wb2ludHMYASABKAMSFQoNZXJyb3JfbWVzc2FnZRgCIAEoCTKsAQoOTWV0cmljc1NlcnZpY2USmQEKBkV4cG9ydBJFLm9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLm1ldHJpY3MudjEuRXhwb3J0TWV0cmljc1NlcnZpY2VSZXF1ZXN0GkYub3BlbnRlbGVtZXRyeS5wcm90by5jb2xsZWN0b3IubWV0cmljcy52MS5FeHBvcnRNZXRyaWNzU2VydmljZVJlc3BvbnNlIgBCpAEKK2lvLm9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLm1ldHJpY3MudjFCE01ldHJpY3NTZXJ2aWNlUHJvdG9QAVozZ28ub3BlbnRlbGVtZXRyeS5pby9wcm90by9vdGxwL2NvbGxlY3Rvci9tZXRyaWNzL3YxqgIoT3BlblRlbGVtZXRyeS5Qcm90by5Db2xsZWN0b3IuTWV0cmljcy5WMWIGcHJvdG8z\",\n\t\t[file_opentelemetry_proto_metrics_v1_metrics],\n\t);\n\n/**\n * @generated from message opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest\n */\nexport type ExportMetricsServiceRequest =\n\tMessage<\"opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest\"> & {\n\t\t/**\n\t\t * An array of ResourceMetrics.\n\t\t * For data coming from a single resource this array will typically contain one\n\t\t * element. Intermediary nodes (such as OpenTelemetry Collector) that receive\n\t\t * data from multiple origins typically batch the data before forwarding further and\n\t\t * in that case this array will contain multiple elements.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.ResourceMetrics resource_metrics = 1;\n\t\t */\n\t\tresourceMetrics: ResourceMetrics[];\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest.\n * Use `create(ExportMetricsServiceRequestSchema)` to create a new message.\n */\nexport const ExportMetricsServiceRequestSchema: GenMessage<ExportMetricsServiceRequest> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_metrics_v1_metrics_service, 0);\n\n/**\n * @generated from message opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse\n */\nexport type ExportMetricsServiceResponse =\n\tMessage<\"opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse\"> & {\n\t\t/**\n\t\t * The details of a partially successful export request.\n\t\t *\n\t\t * If the request is only partially accepted\n\t\t * (i.e. when the server accepts only parts of the data and rejects the rest)\n\t\t * the server MUST initialize the `partial_success` field and MUST\n\t\t * set the `rejected_<signal>` with the number of items it rejected.\n\t\t *\n\t\t * Servers MAY also make use of the `partial_success` field to convey\n\t\t * warnings/suggestions to senders even when the request was fully accepted.\n\t\t * In such cases, the `rejected_<signal>` MUST have a value of `0` and\n\t\t * the `error_message` MUST be non-empty.\n\t\t *\n\t\t * A `partial_success` message with an empty value (rejected_<signal> = 0 and\n\t\t * `error_message` = \"\") is equivalent to it not being set/present. Senders\n\t\t * SHOULD interpret it the same way as in the full success case.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.collector.metrics.v1.ExportMetricsPartialSuccess partial_success = 1;\n\t\t */\n\t\tpartialSuccess?: ExportMetricsPartialSuccess;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse.\n * Use `create(ExportMetricsServiceResponseSchema)` to create a new message.\n */\nexport const ExportMetricsServiceResponseSchema: GenMessage<ExportMetricsServiceResponse> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_metrics_v1_metrics_service, 1);\n\n/**\n * @generated from message opentelemetry.proto.collector.metrics.v1.ExportMetricsPartialSuccess\n */\nexport type ExportMetricsPartialSuccess =\n\tMessage<\"opentelemetry.proto.collector.metrics.v1.ExportMetricsPartialSuccess\"> & {\n\t\t/**\n\t\t * The number of rejected data points.\n\t\t *\n\t\t * A `rejected_<signal>` field holding a `0` value indicates that the\n\t\t * request was fully accepted.\n\t\t *\n\t\t * @generated from field: int64 rejected_data_points = 1;\n\t\t */\n\t\trejectedDataPoints: bigint;\n\n\t\t/**\n\t\t * A developer-facing human-readable message in English. It should be used\n\t\t * either to explain why the server rejected parts of the data during a partial\n\t\t * success or to convey warnings/suggestions during a full success. The message\n\t\t * should offer guidance on how users can address such issues.\n\t\t *\n\t\t * error_message is an optional field. An error_message with an empty value\n\t\t * is equivalent to it not being set.\n\t\t *\n\t\t * @generated from field: string error_message = 2;\n\t\t */\n\t\terrorMessage: string;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.metrics.v1.ExportMetricsPartialSuccess.\n * Use `create(ExportMetricsPartialSuccessSchema)` to create a new message.\n */\nexport const ExportMetricsPartialSuccessSchema: GenMessage<ExportMetricsPartialSuccess> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_metrics_v1_metrics_service, 2);\n\n/**\n * Service that can be used to push metrics between one Application\n * instrumented with OpenTelemetry and a collector, or between a collector and a\n * central collector.\n *\n * @generated from service opentelemetry.proto.collector.metrics.v1.MetricsService\n */\nexport const MetricsService: GenService<{\n\t/**\n\t * @generated from rpc opentelemetry.proto.collector.metrics.v1.MetricsService.Export\n\t */\n\texport: {\n\t\tmethodKind: \"unary\";\n\t\tinput: typeof ExportMetricsServiceRequestSchema;\n\t\toutput: typeof ExportMetricsServiceResponseSchema;\n\t};\n}> =\n\t/*@__PURE__*/\n\tserviceDesc(file_opentelemetry_proto_collector_metrics_v1_metrics_service, 0);\n","// Copyright 2019, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/metrics/v1/metrics.proto (package opentelemetry.proto.metrics.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type {\n\tGenEnum,\n\tGenFile,\n\tGenMessage,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport { enumDesc, fileDesc, messageDesc } from \"@bufbuild/protobuf/codegenv2\";\nimport type {\n\tInstrumentationScope,\n\tKeyValue,\n} from \"../../common/v1/common_pb.js\";\nimport { file_opentelemetry_proto_common_v1_common } from \"../../common/v1/common_pb.js\";\nimport type { Resource } from \"../../resource/v1/resource_pb.js\";\nimport { file_opentelemetry_proto_resource_v1_resource } from \"../../resource/v1/resource_pb.js\";\n\n/**\n * Describes the file opentelemetry/proto/metrics/v1/metrics.proto.\n */\nexport const file_opentelemetry_proto_metrics_v1_metrics: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"CixvcGVudGVsZW1ldHJ5L3Byb3RvL21ldHJpY3MvdjEvbWV0cmljcy5wcm90bxIeb3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxIlgKC01ldHJpY3NEYXRhEkkKEHJlc291cmNlX21ldHJpY3MYASADKAsyLy5vcGVudGVsZW1ldHJ5LnByb3RvLm1ldHJpY3MudjEuUmVzb3VyY2VNZXRyaWNzIq8BCg9SZXNvdXJjZU1ldHJpY3MSOwoIcmVzb3VyY2UYASABKAsyKS5vcGVudGVsZW1ldHJ5LnByb3RvLnJlc291cmNlLnYxLlJlc291cmNlEkMKDXNjb3BlX21ldHJpY3MYAiADKAsyLC5vcGVudGVsZW1ldHJ5LnByb3RvLm1ldHJpY3MudjEuU2NvcGVNZXRyaWNzEhIKCnNjaGVtYV91cmwYAyABKAlKBgjoBxDpByKfAQoMU2NvcGVNZXRyaWNzEkIKBXNjb3BlGAEgASgLMjMub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuSW5zdHJ1bWVudGF0aW9uU2NvcGUSNwoHbWV0cmljcxgCIAMoCzImLm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5NZXRyaWMSEgoKc2NoZW1hX3VybBgDIAEoCSLNAwoGTWV0cmljEgwKBG5hbWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDAoEdW5pdBgDIAEoCRI2CgVnYXVnZRgFIAEoCzIlLm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5HYXVnZUgAEjIKA3N1bRgHIAEoCzIjLm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5TdW1IABI+CgloaXN0b2dyYW0YCSABKAsyKS5vcGVudGVsZW1ldHJ5LnByb3RvLm1ldHJpY3MudjEuSGlzdG9ncmFtSAASVQoVZXhwb25lbnRpYWxfaGlzdG9ncmFtGAogASgLMjQub3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxLkV4cG9uZW50aWFsSGlzdG9ncmFtSAASOgoHc3VtbWFyeRgLIAEoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5TdW1tYXJ5SAASOQoIbWV0YWRhdGEYDCADKAsyJy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi52MS5LZXlWYWx1ZUIGCgRkYXRhSgQIBBAFSgQIBhAHSgQICBAJIk0KBUdhdWdlEkQKC2RhdGFfcG9pbnRzGAEgAygLMi8ub3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxLk51bWJlckRhdGFQb2ludCK6AQoDU3VtEkQKC2RhdGFfcG9pbnRzGAEgAygLMi8ub3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxLk51bWJlckRhdGFQb2ludBJXChdhZ2dyZWdhdGlvbl90ZW1wb3JhbGl0eRgCIAEoDjI2Lm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5BZ2dyZWdhdGlvblRlbXBvcmFsaXR5EhQKDGlzX21vbm90b25pYxgDIAEoCCKtAQoJSGlzdG9ncmFtEkcKC2RhdGFfcG9pbnRzGAEgAygLMjIub3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxLkhpc3RvZ3JhbURhdGFQb2ludBJXChdhZ2dyZWdhdGlvbl90ZW1wb3JhbGl0eRgCIAEoDjI2Lm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5BZ2dyZWdhdGlvblRlbXBvcmFsaXR5IsMBChRFeHBvbmVudGlhbEhpc3RvZ3JhbRJSCgtkYXRhX3BvaW50cxgBIAMoCzI9Lm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5FeHBvbmVudGlhbEhpc3RvZ3JhbURhdGFQb2ludBJXChdhZ2dyZWdhdGlvbl90ZW1wb3JhbGl0eRgCIAEoDjI2Lm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5BZ2dyZWdhdGlvblRlbXBvcmFsaXR5IlAKB1N1bW1hcnkSRQoLZGF0YV9wb2ludHMYASADKAsyMC5vcGVudGVsZW1ldHJ5LnByb3RvLm1ldHJpY3MudjEuU3VtbWFyeURhdGFQb2ludCKGAgoPTnVtYmVyRGF0YVBvaW50EjsKCmF0dHJpYnV0ZXMYByADKAsyJy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi52MS5LZXlWYWx1ZRIcChRzdGFydF90aW1lX3VuaXhfbmFubxgCIAEoBhIWCg50aW1lX3VuaXhfbmFubxgDIAEoBhITCglhc19kb3VibGUYBCABKAFIABIQCgZhc19pbnQYBiABKBBIABI7CglleGVtcGxhcnMYBSADKAsyKC5vcGVudGVsZW1ldHJ5LnByb3RvLm1ldHJpY3MudjEuRXhlbXBsYXISDQoFZmxhZ3MYCCABKA1CBwoFdmFsdWVKBAgBEAIi5gIKEkhpc3RvZ3JhbURhdGFQb2ludBI7CgphdHRyaWJ1dGVzGAkgAygLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuS2V5VmFsdWUSHAoUc3RhcnRfdGltZV91bml4X25hbm8YAiABKAYSFgoOdGltZV91bml4X25hbm8YAyABKAYSDQoFY291bnQYBCABKAYSEAoDc3VtGAUgASgBSACIAQESFQoNYnVja2V0X2NvdW50cxgGIAMoBhIXCg9leHBsaWNpdF9ib3VuZHMYByADKAESOwoJZXhlbXBsYXJzGAggAygLMigub3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxLkV4ZW1wbGFyEg0KBWZsYWdzGAogASgNEhAKA21pbhgLIAEoAUgBiAEBEhAKA21heBgMIAEoAUgCiAEBQgYKBF9zdW1CBgoEX21pbkIGCgRfbWF4SgQIARACItoECh1FeHBvbmVudGlhbEhpc3RvZ3JhbURhdGFQb2ludBI7CgphdHRyaWJ1dGVzGAEgAygLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuS2V5VmFsdWUSHAoUc3RhcnRfdGltZV91bml4X25hbm8YAiABKAYSFgoOdGltZV91bml4X25hbm8YAyABKAYSDQoFY291bnQYBCABKAYSEAoDc3VtGAUgASgBSACIAQESDQoFc2NhbGUYBiABKBESEgoKemVyb19jb3VudBgHIAEoBhJXCghwb3NpdGl2ZRgIIAEoCzJFLm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MS5FeHBvbmVudGlhbEhpc3RvZ3JhbURhdGFQb2ludC5CdWNrZXRzElcKCG5lZ2F0aXZlGAkgASgLMkUub3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxLkV4cG9uZW50aWFsSGlzdG9ncmFtRGF0YVBvaW50LkJ1Y2tldHMSDQoFZmxhZ3MYCiABKA0SOwoJZXhlbXBsYXJzGAsgAygLMigub3BlbnRlbGVtZXRyeS5wcm90by5tZXRyaWNzLnYxLkV4ZW1wbGFyEhAKA21pbhgMIAEoAUgBiAEBEhAKA21heBgNIAEoAUgCiAEBEhYKDnplcm9fdGhyZXNob2xkGA4gASgBGjAKB0J1Y2tldHMSDgoGb2Zmc2V0GAEgASgREhUKDWJ1Y2tldF9jb3VudHMYAiADKARCBgoEX3N1bUIGCgRfbWluQgYKBF9tYXgixQIKEFN1bW1hcnlEYXRhUG9pbnQSOwoKYXR0cmlidXRlcxgHIAMoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxLktleVZhbHVlEhwKFHN0YXJ0X3RpbWVfdW5peF9uYW5vGAIgASgGEhYKDnRpbWVfdW5peF9uYW5vGAMgASgGEg0KBWNvdW50GAQgASgGEgsKA3N1bRgFIAEoARJZCg9xdWFudGlsZV92YWx1ZXMYBiADKAsyQC5vcGVudGVsZW1ldHJ5LnByb3RvLm1ldHJpY3MudjEuU3VtbWFyeURhdGFQb2ludC5WYWx1ZUF0UXVhbnRpbGUSDQoFZmxhZ3MYCCABKA0aMgoPVmFsdWVBdFF1YW50aWxlEhAKCHF1YW50aWxlGAEgASgBEg0KBXZhbHVlGAIgASgBSgQIARACIsEBCghFeGVtcGxhchJEChNmaWx0ZXJlZF9hdHRyaWJ1dGVzGAcgAygLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuS2V5VmFsdWUSFgoOdGltZV91bml4X25hbm8YAiABKAYSEwoJYXNfZG91YmxlGAMgASgBSAASEAoGYXNfaW50GAYgASgQSAASDwoHc3Bhbl9pZBgEIAEoDBIQCgh0cmFjZV9pZBgFIAEoDEIHCgV2YWx1ZUoECAEQAiqMAQoWQWdncmVnYXRpb25UZW1wb3JhbGl0eRInCiNBR0dSRUdBVElPTl9URU1QT1JBTElUWV9VTlNQRUNJRklFRBAAEiEKHUFHR1JFR0FUSU9OX1RFTVBPUkFMSVRZX0RFTFRBEAESJgoiQUdHUkVHQVRJT05fVEVNUE9SQUxJVFlfQ1VNVUxBVElWRRACKl4KDkRhdGFQb2ludEZsYWdzEh8KG0RBVEFfUE9JTlRfRkxBR1NfRE9fTk9UX1VTRRAAEisKJ0RBVEFfUE9JTlRfRkxBR1NfTk9fUkVDT1JERURfVkFMVUVfTUFTSxABQn8KIWlvLm9wZW50ZWxlbWV0cnkucHJvdG8ubWV0cmljcy52MUIMTWV0cmljc1Byb3RvUAFaKWdvLm9wZW50ZWxlbWV0cnkuaW8vcHJvdG8vb3RscC9tZXRyaWNzL3YxqgIeT3BlblRlbGVtZXRyeS5Qcm90by5NZXRyaWNzLlYxYgZwcm90bzM\",\n\t\t[\n\t\t\tfile_opentelemetry_proto_common_v1_common,\n\t\t\tfile_opentelemetry_proto_resource_v1_resource,\n\t\t],\n\t);\n\n/**\n * MetricsData represents the metrics data that can be stored in a persistent\n * storage, OR can be embedded by other protocols that transfer OTLP metrics\n * data but do not implement the OTLP protocol.\n *\n * MetricsData\n * └─── ResourceMetrics\n * ├── Resource\n * ├── SchemaURL\n * └── ScopeMetrics\n * ├── Scope\n * ├── SchemaURL\n * └── Metric\n * ├── Name\n * ├── Description\n * ├── Unit\n * └── data\n * ├── Gauge\n * ├── Sum\n * ├── Histogram\n * ├── ExponentialHistogram\n * └── Summary\n *\n * The main difference between this message and collector protocol is that\n * in this message there will not be any \"control\" or \"metadata\" specific to\n * OTLP protocol.\n *\n * When new fields are added into this message, the OTLP request MUST be updated\n * as well.\n *\n * @generated from message opentelemetry.proto.metrics.v1.MetricsData\n */\nexport type MetricsData =\n\tMessage<\"opentelemetry.proto.metrics.v1.MetricsData\"> & {\n\t\t/**\n\t\t * An array of ResourceMetrics.\n\t\t * For data coming from a single resource this array will typically contain\n\t\t * one element. Intermediary nodes that receive data from multiple origins\n\t\t * typically batch the data before forwarding further and in that case this\n\t\t * array will contain multiple elements.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.ResourceMetrics resource_metrics = 1;\n\t\t */\n\t\tresourceMetrics: ResourceMetrics[];\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.MetricsData.\n * Use `create(MetricsDataSchema)` to create a new message.\n */\nexport const MetricsDataSchema: GenMessage<MetricsData> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 0);\n\n/**\n * A collection of ScopeMetrics from a Resource.\n *\n * @generated from message opentelemetry.proto.metrics.v1.ResourceMetrics\n */\nexport type ResourceMetrics =\n\tMessage<\"opentelemetry.proto.metrics.v1.ResourceMetrics\"> & {\n\t\t/**\n\t\t * The resource for the metrics in this message.\n\t\t * If this field is not set then no resource info is known.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.resource.v1.Resource resource = 1;\n\t\t */\n\t\tresource?: Resource;\n\n\t\t/**\n\t\t * A list of metrics that originate from a resource.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.ScopeMetrics scope_metrics = 2;\n\t\t */\n\t\tscopeMetrics: ScopeMetrics[];\n\n\t\t/**\n\t\t * The Schema URL, if known. This is the identifier of the Schema that the resource data\n\t\t * is recorded in. Notably, the last part of the URL path is the version number of the\n\t\t * schema: http[s]://server[:port]/path/<version>. To learn more about Schema URL see\n\t\t * https://opentelemetry.io/docs/specs/otel/schemas/#schema-url\n\t\t * This schema_url applies to the data in the \"resource\" field. It does not apply\n\t\t * to the data in the \"scope_metrics\" field which have their own schema_url field.\n\t\t *\n\t\t * @generated from field: string schema_url = 3;\n\t\t */\n\t\tschemaUrl: string;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.ResourceMetrics.\n * Use `create(ResourceMetricsSchema)` to create a new message.\n */\nexport const ResourceMetricsSchema: GenMessage<ResourceMetrics> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 1);\n\n/**\n * A collection of Metrics produced by an Scope.\n *\n * @generated from message opentelemetry.proto.metrics.v1.ScopeMetrics\n */\nexport type ScopeMetrics =\n\tMessage<\"opentelemetry.proto.metrics.v1.ScopeMetrics\"> & {\n\t\t/**\n\t\t * The instrumentation scope information for the metrics in this message.\n\t\t * Semantically when InstrumentationScope isn't set, it is equivalent with\n\t\t * an empty instrumentation scope name (unknown).\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.common.v1.InstrumentationScope scope = 1;\n\t\t */\n\t\tscope?: InstrumentationScope;\n\n\t\t/**\n\t\t * A list of metrics that originate from an instrumentation library.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.Metric metrics = 2;\n\t\t */\n\t\tmetrics: Metric[];\n\n\t\t/**\n\t\t * The Schema URL, if known. This is the identifier of the Schema that the metric data\n\t\t * is recorded in. Notably, the last part of the URL path is the version number of the\n\t\t * schema: http[s]://server[:port]/path/<version>. To learn more about Schema URL see\n\t\t * https://opentelemetry.io/docs/specs/otel/schemas/#schema-url\n\t\t * This schema_url applies to all metrics in the \"metrics\" field.\n\t\t *\n\t\t * @generated from field: string schema_url = 3;\n\t\t */\n\t\tschemaUrl: string;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.ScopeMetrics.\n * Use `create(ScopeMetricsSchema)` to create a new message.\n */\nexport const ScopeMetricsSchema: GenMessage<ScopeMetrics> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 2);\n\n/**\n * Defines a Metric which has one or more timeseries. The following is a\n * brief summary of the Metric data model. For more details, see:\n *\n * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md\n *\n * The data model and relation between entities is shown in the\n * diagram below. Here, \"DataPoint\" is the term used to refer to any\n * one of the specific data point value types, and \"points\" is the term used\n * to refer to any one of the lists of points contained in the Metric.\n *\n * - Metric is composed of a metadata and data.\n * - Metadata part contains a name, description, unit.\n * - Data is one of the possible types (Sum, Gauge, Histogram, Summary).\n * - DataPoint contains timestamps, attributes, and one of the possible value type\n * fields.\n *\n * Metric\n * +------------+\n * |name |\n * |description |\n * |unit | +------------------------------------+\n * |data |---> |Gauge, Sum, Histogram, Summary, ... |\n * +------------+ +------------------------------------+\n *\n * Data [One of Gauge, Sum, Histogram, Summary, ...]\n * +-----------+\n * |... | // Metadata about the Data.\n * |points |--+\n * +-----------+ |\n * | +---------------------------+\n * | |DataPoint 1 |\n * v |+------+------+ +------+ |\n * +-----+ ||label |label |...|label | |\n * | 1 |-->||value1|value2|...|valueN| |\n * +-----+ |+------+------+ +------+ |\n * | . | |+-----+ |\n * | . | ||value| |\n * | . | |+-----+ |\n * | . | +---------------------------+\n * | . | .\n * | . | .\n * | . | .\n * | . | +---------------------------+\n * | . | |DataPoint M |\n * +-----+ |+------+------+ +------+ |\n * | M |-->||label |label |...|label | |\n * +-----+ ||value1|value2|...|valueN| |\n * |+------+------+ +------+ |\n * |+-----+ |\n * ||value| |\n * |+-----+ |\n * +---------------------------+\n *\n * Each distinct type of DataPoint represents the output of a specific\n * aggregation function, the result of applying the DataPoint's\n * associated function of to one or more measurements.\n *\n * All DataPoint types have three common fields:\n * - Attributes includes key-value pairs associated with the data point\n * - TimeUnixNano is required, set to the end time of the aggregation\n * - StartTimeUnixNano is optional, but strongly encouraged for DataPoints\n * having an AggregationTemporality field, as discussed below.\n *\n * Both TimeUnixNano and StartTimeUnixNano values are expressed as\n * UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970.\n *\n * # TimeUnixNano\n *\n * This field is required, having consistent interpretation across\n * DataPoint types. TimeUnixNano is the moment corresponding to when\n * the data point's aggregate value was captured.\n *\n * Data points with the 0 value for TimeUnixNano SHOULD be rejected\n * by consumers.\n *\n * # StartTimeUnixNano\n *\n * StartTimeUnixNano in general allows detecting when a sequence of\n * observations is unbroken. This field indicates to consumers the\n * start time for points with cumulative and delta\n * AggregationTemporality, and it should be included whenever possible\n * to support correct rate calculation. Although it may be omitted\n * when the start time is truly unknown, setting StartTimeUnixNano is\n * strongly encouraged.\n *\n * @generated from message opentelemetry.proto.metrics.v1.Metric\n */\nexport type Metric = Message<\"opentelemetry.proto.metrics.v1.Metric\"> & {\n\t/**\n\t * name of the metric.\n\t *\n\t * @generated from field: string name = 1;\n\t */\n\tname: string;\n\n\t/**\n\t * description of the metric, which can be used in documentation.\n\t *\n\t * @generated from field: string description = 2;\n\t */\n\tdescription: string;\n\n\t/**\n\t * unit in which the metric value is reported. Follows the format\n\t * described by https://unitsofmeasure.org/ucum.html.\n\t *\n\t * @generated from field: string unit = 3;\n\t */\n\tunit: string;\n\n\t/**\n\t * Data determines the aggregation type (if any) of the metric, what is the\n\t * reported value type for the data points, as well as the relatationship to\n\t * the time interval over which they are reported.\n\t *\n\t * @generated from oneof opentelemetry.proto.metrics.v1.Metric.data\n\t */\n\tdata:\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: opentelemetry.proto.metrics.v1.Gauge gauge = 5;\n\t\t\t\t */\n\t\t\t\tvalue: Gauge;\n\t\t\t\tcase: \"gauge\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: opentelemetry.proto.metrics.v1.Sum sum = 7;\n\t\t\t\t */\n\t\t\t\tvalue: Sum;\n\t\t\t\tcase: \"sum\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: opentelemetry.proto.metrics.v1.Histogram histogram = 9;\n\t\t\t\t */\n\t\t\t\tvalue: Histogram;\n\t\t\t\tcase: \"histogram\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: opentelemetry.proto.metrics.v1.ExponentialHistogram exponential_histogram = 10;\n\t\t\t\t */\n\t\t\t\tvalue: ExponentialHistogram;\n\t\t\t\tcase: \"exponentialHistogram\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: opentelemetry.proto.metrics.v1.Summary summary = 11;\n\t\t\t\t */\n\t\t\t\tvalue: Summary;\n\t\t\t\tcase: \"summary\";\n\t\t }\n\t\t| { case: undefined; value?: undefined };\n\n\t/**\n\t * Additional metadata attributes that describe the metric. [Optional].\n\t * Attributes are non-identifying.\n\t * Consumers SHOULD NOT need to be aware of these attributes.\n\t * These attributes MAY be used to encode information allowing\n\t * for lossless roundtrip translation to / from another data model.\n\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t * attribute with the same key).\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue metadata = 12;\n\t */\n\tmetadata: KeyValue[];\n};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.Metric.\n * Use `create(MetricSchema)` to create a new message.\n */\nexport const MetricSchema: GenMessage<Metric> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 3);\n\n/**\n * Gauge represents the type of a scalar metric that always exports the\n * \"current value\" for every data point. It should be used for an \"unknown\"\n * aggregation.\n *\n * A Gauge does not support different aggregation temporalities. Given the\n * aggregation is unknown, points cannot be combined using the same\n * aggregation, regardless of aggregation temporalities. Therefore,\n * AggregationTemporality is not included. Consequently, this also means\n * \"StartTimeUnixNano\" is ignored for all data points.\n *\n * @generated from message opentelemetry.proto.metrics.v1.Gauge\n */\nexport type Gauge = Message<\"opentelemetry.proto.metrics.v1.Gauge\"> & {\n\t/**\n\t * @generated from field: repeated opentelemetry.proto.metrics.v1.NumberDataPoint data_points = 1;\n\t */\n\tdataPoints: NumberDataPoint[];\n};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.Gauge.\n * Use `create(GaugeSchema)` to create a new message.\n */\nexport const GaugeSchema: GenMessage<Gauge> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 4);\n\n/**\n * Sum represents the type of a scalar metric that is calculated as a sum of all\n * reported measurements over a time interval.\n *\n * @generated from message opentelemetry.proto.metrics.v1.Sum\n */\nexport type Sum = Message<\"opentelemetry.proto.metrics.v1.Sum\"> & {\n\t/**\n\t * @generated from field: repeated opentelemetry.proto.metrics.v1.NumberDataPoint data_points = 1;\n\t */\n\tdataPoints: NumberDataPoint[];\n\n\t/**\n\t * aggregation_temporality describes if the aggregator reports delta changes\n\t * since last report time, or cumulative changes since a fixed start time.\n\t *\n\t * @generated from field: opentelemetry.proto.metrics.v1.AggregationTemporality aggregation_temporality = 2;\n\t */\n\taggregationTemporality: AggregationTemporality;\n\n\t/**\n\t * If \"true\" means that the sum is monotonic.\n\t *\n\t * @generated from field: bool is_monotonic = 3;\n\t */\n\tisMonotonic: boolean;\n};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.Sum.\n * Use `create(SumSchema)` to create a new message.\n */\nexport const SumSchema: GenMessage<Sum> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 5);\n\n/**\n * Histogram represents the type of a metric that is calculated by aggregating\n * as a Histogram of all reported measurements over a time interval.\n *\n * @generated from message opentelemetry.proto.metrics.v1.Histogram\n */\nexport type Histogram = Message<\"opentelemetry.proto.metrics.v1.Histogram\"> & {\n\t/**\n\t * @generated from field: repeated opentelemetry.proto.metrics.v1.HistogramDataPoint data_points = 1;\n\t */\n\tdataPoints: HistogramDataPoint[];\n\n\t/**\n\t * aggregation_temporality describes if the aggregator reports delta changes\n\t * since last report time, or cumulative changes since a fixed start time.\n\t *\n\t * @generated from field: opentelemetry.proto.metrics.v1.AggregationTemporality aggregation_temporality = 2;\n\t */\n\taggregationTemporality: AggregationTemporality;\n};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.Histogram.\n * Use `create(HistogramSchema)` to create a new message.\n */\nexport const HistogramSchema: GenMessage<Histogram> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 6);\n\n/**\n * ExponentialHistogram represents the type of a metric that is calculated by aggregating\n * as a ExponentialHistogram of all reported double measurements over a time interval.\n *\n * @generated from message opentelemetry.proto.metrics.v1.ExponentialHistogram\n */\nexport type ExponentialHistogram =\n\tMessage<\"opentelemetry.proto.metrics.v1.ExponentialHistogram\"> & {\n\t\t/**\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint data_points = 1;\n\t\t */\n\t\tdataPoints: ExponentialHistogramDataPoint[];\n\n\t\t/**\n\t\t * aggregation_temporality describes if the aggregator reports delta changes\n\t\t * since last report time, or cumulative changes since a fixed start time.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.metrics.v1.AggregationTemporality aggregation_temporality = 2;\n\t\t */\n\t\taggregationTemporality: AggregationTemporality;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.ExponentialHistogram.\n * Use `create(ExponentialHistogramSchema)` to create a new message.\n */\nexport const ExponentialHistogramSchema: GenMessage<ExponentialHistogram> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 7);\n\n/**\n * Summary metric data are used to convey quantile summaries,\n * a Prometheus (see: https://prometheus.io/docs/concepts/metric_types/#summary)\n * and OpenMetrics (see: https://github.com/prometheus/OpenMetrics/blob/4dbf6075567ab43296eed941037c12951faafb92/protos/prometheus.proto#L45)\n * data type. These data points cannot always be merged in a meaningful way.\n * While they can be useful in some applications, histogram data points are\n * recommended for new applications.\n * Summary metrics do not have an aggregation temporality field. This is\n * because the count and sum fields of a SummaryDataPoint are assumed to be\n * cumulative values.\n *\n * @generated from message opentelemetry.proto.metrics.v1.Summary\n */\nexport type Summary = Message<\"opentelemetry.proto.metrics.v1.Summary\"> & {\n\t/**\n\t * @generated from field: repeated opentelemetry.proto.metrics.v1.SummaryDataPoint data_points = 1;\n\t */\n\tdataPoints: SummaryDataPoint[];\n};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.Summary.\n * Use `create(SummarySchema)` to create a new message.\n */\nexport const SummarySchema: GenMessage<Summary> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 8);\n\n/**\n * NumberDataPoint is a single data point in a timeseries that describes the\n * time-varying scalar value of a metric.\n *\n * @generated from message opentelemetry.proto.metrics.v1.NumberDataPoint\n */\nexport type NumberDataPoint =\n\tMessage<\"opentelemetry.proto.metrics.v1.NumberDataPoint\"> & {\n\t\t/**\n\t\t * The set of key/value pairs that uniquely identify the timeseries from\n\t\t * where this point belongs. The list may be empty (may contain 0 elements).\n\t\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t\t * attribute with the same key).\n\t\t *\n\t\t * The attribute values SHOULD NOT contain empty values.\n\t\t * The attribute values SHOULD NOT contain bytes values.\n\t\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t\t * double values.\n\t\t * The attribute values SHOULD NOT contain kvlist values.\n\t\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t\t * These restrictions can change in a minor release.\n\t\t * The restrictions take origin from the OpenTelemetry specification:\n\t\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 7;\n\t\t */\n\t\tattributes: KeyValue[];\n\n\t\t/**\n\t\t * StartTimeUnixNano is optional but strongly encouraged, see the\n\t\t * the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 start_time_unix_nano = 2;\n\t\t */\n\t\tstartTimeUnixNano: bigint;\n\n\t\t/**\n\t\t * TimeUnixNano is required, see the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 time_unix_nano = 3;\n\t\t */\n\t\ttimeUnixNano: bigint;\n\n\t\t/**\n\t\t * The value itself. A point is considered invalid when one of the recognized\n\t\t * value fields is not present inside this oneof.\n\t\t *\n\t\t * @generated from oneof opentelemetry.proto.metrics.v1.NumberDataPoint.value\n\t\t */\n\t\tvalue:\n\t\t\t| {\n\t\t\t\t\t/**\n\t\t\t\t\t * @generated from field: double as_double = 4;\n\t\t\t\t\t */\n\t\t\t\t\tvalue: number;\n\t\t\t\t\tcase: \"asDouble\";\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\t/**\n\t\t\t\t\t * @generated from field: sfixed64 as_int = 6;\n\t\t\t\t\t */\n\t\t\t\t\tvalue: bigint;\n\t\t\t\t\tcase: \"asInt\";\n\t\t\t }\n\t\t\t| { case: undefined; value?: undefined };\n\n\t\t/**\n\t\t * (Optional) List of exemplars collected from\n\t\t * measurements that were used to form the data point\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.Exemplar exemplars = 5;\n\t\t */\n\t\texemplars: Exemplar[];\n\n\t\t/**\n\t\t * Flags that apply to this specific data point. See DataPointFlags\n\t\t * for the available flags and their meaning.\n\t\t *\n\t\t * @generated from field: uint32 flags = 8;\n\t\t */\n\t\tflags: number;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.NumberDataPoint.\n * Use `create(NumberDataPointSchema)` to create a new message.\n */\nexport const NumberDataPointSchema: GenMessage<NumberDataPoint> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 9);\n\n/**\n * HistogramDataPoint is a single data point in a timeseries that describes the\n * time-varying values of a Histogram. A Histogram contains summary statistics\n * for a population of values, it may optionally contain the distribution of\n * those values across a set of buckets.\n *\n * If the histogram contains the distribution of values, then both\n * \"explicit_bounds\" and \"bucket counts\" fields must be defined.\n * If the histogram does not contain the distribution of values, then both\n * \"explicit_bounds\" and \"bucket_counts\" must be omitted and only \"count\" and\n * \"sum\" are known.\n *\n * @generated from message opentelemetry.proto.metrics.v1.HistogramDataPoint\n */\nexport type HistogramDataPoint =\n\tMessage<\"opentelemetry.proto.metrics.v1.HistogramDataPoint\"> & {\n\t\t/**\n\t\t * The set of key/value pairs that uniquely identify the timeseries from\n\t\t * where this point belongs. The list may be empty (may contain 0 elements).\n\t\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t\t * attribute with the same key).\n\t\t *\n\t\t * The attribute values SHOULD NOT contain empty values.\n\t\t * The attribute values SHOULD NOT contain bytes values.\n\t\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t\t * double values.\n\t\t * The attribute values SHOULD NOT contain kvlist values.\n\t\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t\t * These restrictions can change in a minor release.\n\t\t * The restrictions take origin from the OpenTelemetry specification:\n\t\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 9;\n\t\t */\n\t\tattributes: KeyValue[];\n\n\t\t/**\n\t\t * StartTimeUnixNano is optional but strongly encouraged, see the\n\t\t * the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 start_time_unix_nano = 2;\n\t\t */\n\t\tstartTimeUnixNano: bigint;\n\n\t\t/**\n\t\t * TimeUnixNano is required, see the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 time_unix_nano = 3;\n\t\t */\n\t\ttimeUnixNano: bigint;\n\n\t\t/**\n\t\t * count is the number of values in the population. Must be non-negative. This\n\t\t * value must be equal to the sum of the \"count\" fields in buckets if a\n\t\t * histogram is provided.\n\t\t *\n\t\t * @generated from field: fixed64 count = 4;\n\t\t */\n\t\tcount: bigint;\n\n\t\t/**\n\t\t * sum of the values in the population. If count is zero then this field\n\t\t * must be zero.\n\t\t *\n\t\t * Note: Sum should only be filled out when measuring non-negative discrete\n\t\t * events, and is assumed to be monotonic over the values of these events.\n\t\t * Negative events *can* be recorded, but sum should not be filled out when\n\t\t * doing so. This is specifically to enforce compatibility w/ OpenMetrics,\n\t\t * see: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#histogram\n\t\t *\n\t\t * @generated from field: optional double sum = 5;\n\t\t */\n\t\tsum?: number;\n\n\t\t/**\n\t\t * bucket_counts is an optional field contains the count values of histogram\n\t\t * for each bucket.\n\t\t *\n\t\t * The sum of the bucket_counts must equal the value in the count field.\n\t\t *\n\t\t * The number of elements in bucket_counts array must be by one greater than\n\t\t * the number of elements in explicit_bounds array. The exception to this rule\n\t\t * is when the length of bucket_counts is 0, then the length of explicit_bounds\n\t\t * must also be 0.\n\t\t *\n\t\t * @generated from field: repeated fixed64 bucket_counts = 6;\n\t\t */\n\t\tbucketCounts: bigint[];\n\n\t\t/**\n\t\t * explicit_bounds specifies buckets with explicitly defined bounds for values.\n\t\t *\n\t\t * The boundaries for bucket at index i are:\n\t\t *\n\t\t * (-infinity, explicit_bounds[i]] for i == 0\n\t\t * (explicit_bounds[i-1], explicit_bounds[i]] for 0 < i < size(explicit_bounds)\n\t\t * (explicit_bounds[i-1], +infinity) for i == size(explicit_bounds)\n\t\t *\n\t\t * The values in the explicit_bounds array must be strictly increasing.\n\t\t *\n\t\t * Histogram buckets are inclusive of their upper boundary, except the last\n\t\t * bucket where the boundary is at infinity. This format is intentionally\n\t\t * compatible with the OpenMetrics histogram definition.\n\t\t *\n\t\t * If bucket_counts length is 0 then explicit_bounds length must also be 0,\n\t\t * otherwise the data point is invalid.\n\t\t *\n\t\t * @generated from field: repeated double explicit_bounds = 7;\n\t\t */\n\t\texplicitBounds: number[];\n\n\t\t/**\n\t\t * (Optional) List of exemplars collected from\n\t\t * measurements that were used to form the data point\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.Exemplar exemplars = 8;\n\t\t */\n\t\texemplars: Exemplar[];\n\n\t\t/**\n\t\t * Flags that apply to this specific data point. See DataPointFlags\n\t\t * for the available flags and their meaning.\n\t\t *\n\t\t * @generated from field: uint32 flags = 10;\n\t\t */\n\t\tflags: number;\n\n\t\t/**\n\t\t * min is the minimum value over (start_time, end_time].\n\t\t *\n\t\t * @generated from field: optional double min = 11;\n\t\t */\n\t\tmin?: number;\n\n\t\t/**\n\t\t * max is the maximum value over (start_time, end_time].\n\t\t *\n\t\t * @generated from field: optional double max = 12;\n\t\t */\n\t\tmax?: number;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.HistogramDataPoint.\n * Use `create(HistogramDataPointSchema)` to create a new message.\n */\nexport const HistogramDataPointSchema: GenMessage<HistogramDataPoint> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 10);\n\n/**\n * ExponentialHistogramDataPoint is a single data point in a timeseries that describes the\n * time-varying values of a ExponentialHistogram of double values. A ExponentialHistogram contains\n * summary statistics for a population of values, it may optionally contain the\n * distribution of those values across a set of buckets.\n *\n *\n * @generated from message opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint\n */\nexport type ExponentialHistogramDataPoint =\n\tMessage<\"opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint\"> & {\n\t\t/**\n\t\t * The set of key/value pairs that uniquely identify the timeseries from\n\t\t * where this point belongs. The list may be empty (may contain 0 elements).\n\t\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t\t * attribute with the same key).\n\t\t *\n\t\t * The attribute values SHOULD NOT contain empty values.\n\t\t * The attribute values SHOULD NOT contain bytes values.\n\t\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t\t * double values.\n\t\t * The attribute values SHOULD NOT contain kvlist values.\n\t\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t\t * These restrictions can change in a minor release.\n\t\t * The restrictions take origin from the OpenTelemetry specification:\n\t\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 1;\n\t\t */\n\t\tattributes: KeyValue[];\n\n\t\t/**\n\t\t * StartTimeUnixNano is optional but strongly encouraged, see the\n\t\t * the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 start_time_unix_nano = 2;\n\t\t */\n\t\tstartTimeUnixNano: bigint;\n\n\t\t/**\n\t\t * TimeUnixNano is required, see the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 time_unix_nano = 3;\n\t\t */\n\t\ttimeUnixNano: bigint;\n\n\t\t/**\n\t\t * count is the number of values in the population. Must be\n\t\t * non-negative. This value must be equal to the sum of the \"bucket_counts\"\n\t\t * values in the positive and negative Buckets plus the \"zero_count\" field.\n\t\t *\n\t\t * @generated from field: fixed64 count = 4;\n\t\t */\n\t\tcount: bigint;\n\n\t\t/**\n\t\t * sum of the values in the population. If count is zero then this field\n\t\t * must be zero.\n\t\t *\n\t\t * Note: Sum should only be filled out when measuring non-negative discrete\n\t\t * events, and is assumed to be monotonic over the values of these events.\n\t\t * Negative events *can* be recorded, but sum should not be filled out when\n\t\t * doing so. This is specifically to enforce compatibility w/ OpenMetrics,\n\t\t * see: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#histogram\n\t\t *\n\t\t * @generated from field: optional double sum = 5;\n\t\t */\n\t\tsum?: number;\n\n\t\t/**\n\t\t * scale describes the resolution of the histogram. Boundaries are\n\t\t * located at powers of the base, where:\n\t\t *\n\t\t * base = (2^(2^-scale))\n\t\t *\n\t\t * The histogram bucket identified by `index`, a signed integer,\n\t\t * contains values that are greater than (base^index) and\n\t\t * less than or equal to (base^(index+1)).\n\t\t *\n\t\t * The positive and negative ranges of the histogram are expressed\n\t\t * separately. Negative values are mapped by their absolute value\n\t\t * into the negative range using the same scale as the positive range.\n\t\t *\n\t\t * scale is not restricted by the protocol, as the permissible\n\t\t * values depend on the range of the data.\n\t\t *\n\t\t * @generated from field: sint32 scale = 6;\n\t\t */\n\t\tscale: number;\n\n\t\t/**\n\t\t * zero_count is the count of values that are either exactly zero or\n\t\t * within the region considered zero by the instrumentation at the\n\t\t * tolerated degree of precision. This bucket stores values that\n\t\t * cannot be expressed using the standard exponential formula as\n\t\t * well as values that have been rounded to zero.\n\t\t *\n\t\t * Implementations MAY consider the zero bucket to have probability\n\t\t * mass equal to (zero_count / count).\n\t\t *\n\t\t * @generated from field: fixed64 zero_count = 7;\n\t\t */\n\t\tzeroCount: bigint;\n\n\t\t/**\n\t\t * positive carries the positive range of exponential bucket counts.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint.Buckets positive = 8;\n\t\t */\n\t\tpositive?: ExponentialHistogramDataPoint_Buckets;\n\n\t\t/**\n\t\t * negative carries the negative range of exponential bucket counts.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint.Buckets negative = 9;\n\t\t */\n\t\tnegative?: ExponentialHistogramDataPoint_Buckets;\n\n\t\t/**\n\t\t * Flags that apply to this specific data point. See DataPointFlags\n\t\t * for the available flags and their meaning.\n\t\t *\n\t\t * @generated from field: uint32 flags = 10;\n\t\t */\n\t\tflags: number;\n\n\t\t/**\n\t\t * (Optional) List of exemplars collected from\n\t\t * measurements that were used to form the data point\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.Exemplar exemplars = 11;\n\t\t */\n\t\texemplars: Exemplar[];\n\n\t\t/**\n\t\t * min is the minimum value over (start_time, end_time].\n\t\t *\n\t\t * @generated from field: optional double min = 12;\n\t\t */\n\t\tmin?: number;\n\n\t\t/**\n\t\t * max is the maximum value over (start_time, end_time].\n\t\t *\n\t\t * @generated from field: optional double max = 13;\n\t\t */\n\t\tmax?: number;\n\n\t\t/**\n\t\t * ZeroThreshold may be optionally set to convey the width of the zero\n\t\t * region. Where the zero region is defined as the closed interval\n\t\t * [-ZeroThreshold, ZeroThreshold].\n\t\t * When ZeroThreshold is 0, zero count bucket stores values that cannot be\n\t\t * expressed using the standard exponential formula as well as values that\n\t\t * have been rounded to zero.\n\t\t *\n\t\t * @generated from field: double zero_threshold = 14;\n\t\t */\n\t\tzeroThreshold: number;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint.\n * Use `create(ExponentialHistogramDataPointSchema)` to create a new message.\n */\nexport const ExponentialHistogramDataPointSchema: GenMessage<ExponentialHistogramDataPoint> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 11);\n\n/**\n * Buckets are a set of bucket counts, encoded in a contiguous array\n * of counts.\n *\n * @generated from message opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint.Buckets\n */\nexport type ExponentialHistogramDataPoint_Buckets =\n\tMessage<\"opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint.Buckets\"> & {\n\t\t/**\n\t\t * Offset is the bucket index of the first entry in the bucket_counts array.\n\t\t *\n\t\t * Note: This uses a varint encoding as a simple form of compression.\n\t\t *\n\t\t * @generated from field: sint32 offset = 1;\n\t\t */\n\t\toffset: number;\n\n\t\t/**\n\t\t * bucket_counts is an array of count values, where bucket_counts[i] carries\n\t\t * the count of the bucket at index (offset+i). bucket_counts[i] is the count\n\t\t * of values greater than base^(offset+i) and less than or equal to\n\t\t * base^(offset+i+1).\n\t\t *\n\t\t * Note: By contrast, the explicit HistogramDataPoint uses\n\t\t * fixed64. This field is expected to have many buckets,\n\t\t * especially zeros, so uint64 has been selected to ensure\n\t\t * varint encoding.\n\t\t *\n\t\t * @generated from field: repeated uint64 bucket_counts = 2;\n\t\t */\n\t\tbucketCounts: bigint[];\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint.Buckets.\n * Use `create(ExponentialHistogramDataPoint_BucketsSchema)` to create a new message.\n */\nexport const ExponentialHistogramDataPoint_BucketsSchema: GenMessage<ExponentialHistogramDataPoint_Buckets> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 11, 0);\n\n/**\n * SummaryDataPoint is a single data point in a timeseries that describes the\n * time-varying values of a Summary metric. The count and sum fields represent\n * cumulative values.\n *\n * @generated from message opentelemetry.proto.metrics.v1.SummaryDataPoint\n */\nexport type SummaryDataPoint =\n\tMessage<\"opentelemetry.proto.metrics.v1.SummaryDataPoint\"> & {\n\t\t/**\n\t\t * The set of key/value pairs that uniquely identify the timeseries from\n\t\t * where this point belongs. The list may be empty (may contain 0 elements).\n\t\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t\t * attribute with the same key).\n\t\t *\n\t\t * The attribute values SHOULD NOT contain empty values.\n\t\t * The attribute values SHOULD NOT contain bytes values.\n\t\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t\t * double values.\n\t\t * The attribute values SHOULD NOT contain kvlist values.\n\t\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t\t * These restrictions can change in a minor release.\n\t\t * The restrictions take origin from the OpenTelemetry specification:\n\t\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 7;\n\t\t */\n\t\tattributes: KeyValue[];\n\n\t\t/**\n\t\t * StartTimeUnixNano is optional but strongly encouraged, see the\n\t\t * the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 start_time_unix_nano = 2;\n\t\t */\n\t\tstartTimeUnixNano: bigint;\n\n\t\t/**\n\t\t * TimeUnixNano is required, see the detailed comments above Metric.\n\t\t *\n\t\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t\t * 1970.\n\t\t *\n\t\t * @generated from field: fixed64 time_unix_nano = 3;\n\t\t */\n\t\ttimeUnixNano: bigint;\n\n\t\t/**\n\t\t * count is the number of values in the population. Must be non-negative.\n\t\t *\n\t\t * @generated from field: fixed64 count = 4;\n\t\t */\n\t\tcount: bigint;\n\n\t\t/**\n\t\t * sum of the values in the population. If count is zero then this field\n\t\t * must be zero.\n\t\t *\n\t\t * Note: Sum should only be filled out when measuring non-negative discrete\n\t\t * events, and is assumed to be monotonic over the values of these events.\n\t\t * Negative events *can* be recorded, but sum should not be filled out when\n\t\t * doing so. This is specifically to enforce compatibility w/ OpenMetrics,\n\t\t * see: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#summary\n\t\t *\n\t\t * @generated from field: double sum = 5;\n\t\t */\n\t\tsum: number;\n\n\t\t/**\n\t\t * (Optional) list of values at different quantiles of the distribution calculated\n\t\t * from the current snapshot. The quantiles must be strictly increasing.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.metrics.v1.SummaryDataPoint.ValueAtQuantile quantile_values = 6;\n\t\t */\n\t\tquantileValues: SummaryDataPoint_ValueAtQuantile[];\n\n\t\t/**\n\t\t * Flags that apply to this specific data point. See DataPointFlags\n\t\t * for the available flags and their meaning.\n\t\t *\n\t\t * @generated from field: uint32 flags = 8;\n\t\t */\n\t\tflags: number;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.SummaryDataPoint.\n * Use `create(SummaryDataPointSchema)` to create a new message.\n */\nexport const SummaryDataPointSchema: GenMessage<SummaryDataPoint> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 12);\n\n/**\n * Represents the value at a given quantile of a distribution.\n *\n * To record Min and Max values following conventions are used:\n * - The 1.0 quantile is equivalent to the maximum value observed.\n * - The 0.0 quantile is equivalent to the minimum value observed.\n *\n * See the following issue for more context:\n * https://github.com/open-telemetry/opentelemetry-proto/issues/125\n *\n * @generated from message opentelemetry.proto.metrics.v1.SummaryDataPoint.ValueAtQuantile\n */\nexport type SummaryDataPoint_ValueAtQuantile =\n\tMessage<\"opentelemetry.proto.metrics.v1.SummaryDataPoint.ValueAtQuantile\"> & {\n\t\t/**\n\t\t * The quantile of a distribution. Must be in the interval\n\t\t * [0.0, 1.0].\n\t\t *\n\t\t * @generated from field: double quantile = 1;\n\t\t */\n\t\tquantile: number;\n\n\t\t/**\n\t\t * The value at the given quantile of a distribution.\n\t\t *\n\t\t * Quantile values must NOT be negative.\n\t\t *\n\t\t * @generated from field: double value = 2;\n\t\t */\n\t\tvalue: number;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.SummaryDataPoint.ValueAtQuantile.\n * Use `create(SummaryDataPoint_ValueAtQuantileSchema)` to create a new message.\n */\nexport const SummaryDataPoint_ValueAtQuantileSchema: GenMessage<SummaryDataPoint_ValueAtQuantile> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 12, 0);\n\n/**\n * A representation of an exemplar, which is a sample input measurement.\n * Exemplars also hold information about the environment when the measurement\n * was recorded, for example the span and trace ID of the active span when the\n * exemplar was recorded.\n *\n * @generated from message opentelemetry.proto.metrics.v1.Exemplar\n */\nexport type Exemplar = Message<\"opentelemetry.proto.metrics.v1.Exemplar\"> & {\n\t/**\n\t * The set of key/value pairs that were filtered out by the aggregator, but\n\t * recorded alongside the original measurement. Only key/value pairs that were\n\t * filtered out by the aggregator should be included\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue filtered_attributes = 7;\n\t */\n\tfilteredAttributes: KeyValue[];\n\n\t/**\n\t * time_unix_nano is the exact time when this exemplar was recorded\n\t *\n\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January\n\t * 1970.\n\t *\n\t * @generated from field: fixed64 time_unix_nano = 2;\n\t */\n\ttimeUnixNano: bigint;\n\n\t/**\n\t * The value of the measurement that was recorded. An exemplar is\n\t * considered invalid when one of the recognized value fields is not present\n\t * inside this oneof.\n\t *\n\t * @generated from oneof opentelemetry.proto.metrics.v1.Exemplar.value\n\t */\n\tvalue:\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: double as_double = 3;\n\t\t\t\t */\n\t\t\t\tvalue: number;\n\t\t\t\tcase: \"asDouble\";\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * @generated from field: sfixed64 as_int = 6;\n\t\t\t\t */\n\t\t\t\tvalue: bigint;\n\t\t\t\tcase: \"asInt\";\n\t\t }\n\t\t| { case: undefined; value?: undefined };\n\n\t/**\n\t * (Optional) Span ID of the exemplar trace.\n\t * span_id may be missing if the measurement is not recorded inside a trace\n\t * or if the trace is not sampled.\n\t *\n\t * @generated from field: bytes span_id = 4;\n\t */\n\tspanId: Uint8Array;\n\n\t/**\n\t * (Optional) Trace ID of the exemplar trace.\n\t * trace_id may be missing if the measurement is not recorded inside a trace\n\t * or if the trace is not sampled.\n\t *\n\t * @generated from field: bytes trace_id = 5;\n\t */\n\ttraceId: Uint8Array;\n};\n\n/**\n * Describes the message opentelemetry.proto.metrics.v1.Exemplar.\n * Use `create(ExemplarSchema)` to create a new message.\n */\nexport const ExemplarSchema: GenMessage<Exemplar> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_metrics_v1_metrics, 13);\n\n/**\n * AggregationTemporality defines how a metric aggregator reports aggregated\n * values. It describes how those values relate to the time interval over\n * which they are aggregated.\n *\n * @generated from enum opentelemetry.proto.metrics.v1.AggregationTemporality\n */\nexport enum AggregationTemporality {\n\t/**\n\t * UNSPECIFIED is the default AggregationTemporality, it MUST not be used.\n\t *\n\t * @generated from enum value: AGGREGATION_TEMPORALITY_UNSPECIFIED = 0;\n\t */\n\tUNSPECIFIED = 0,\n\n\t/**\n\t * DELTA is an AggregationTemporality for a metric aggregator which reports\n\t * changes since last report time. Successive metrics contain aggregation of\n\t * values from continuous and non-overlapping intervals.\n\t *\n\t * The values for a DELTA metric are based only on the time interval\n\t * associated with one measurement cycle. There is no dependency on\n\t * previous measurements like is the case for CUMULATIVE metrics.\n\t *\n\t * For example, consider a system measuring the number of requests that\n\t * it receives and reports the sum of these requests every second as a\n\t * DELTA metric:\n\t *\n\t * 1. The system starts receiving at time=t_0.\n\t * 2. A request is received, the system measures 1 request.\n\t * 3. A request is received, the system measures 1 request.\n\t * 4. A request is received, the system measures 1 request.\n\t * 5. The 1 second collection cycle ends. A metric is exported for the\n\t * number of requests received over the interval of time t_0 to\n\t * t_0+1 with a value of 3.\n\t * 6. A request is received, the system measures 1 request.\n\t * 7. A request is received, the system measures 1 request.\n\t * 8. The 1 second collection cycle ends. A metric is exported for the\n\t * number of requests received over the interval of time t_0+1 to\n\t * t_0+2 with a value of 2.\n\t *\n\t * @generated from enum value: AGGREGATION_TEMPORALITY_DELTA = 1;\n\t */\n\tDELTA = 1,\n\n\t/**\n\t * CUMULATIVE is an AggregationTemporality for a metric aggregator which\n\t * reports changes since a fixed start time. This means that current values\n\t * of a CUMULATIVE metric depend on all previous measurements since the\n\t * start time. Because of this, the sender is required to retain this state\n\t * in some form. If this state is lost or invalidated, the CUMULATIVE metric\n\t * values MUST be reset and a new fixed start time following the last\n\t * reported measurement time sent MUST be used.\n\t *\n\t * For example, consider a system measuring the number of requests that\n\t * it receives and reports the sum of these requests every second as a\n\t * CUMULATIVE metric:\n\t *\n\t * 1. The system starts receiving at time=t_0.\n\t * 2. A request is received, the system measures 1 request.\n\t * 3. A request is received, the system measures 1 request.\n\t * 4. A request is received, the system measures 1 request.\n\t * 5. The 1 second collection cycle ends. A metric is exported for the\n\t * number of requests received over the interval of time t_0 to\n\t * t_0+1 with a value of 3.\n\t * 6. A request is received, the system measures 1 request.\n\t * 7. A request is received, the system measures 1 request.\n\t * 8. The 1 second collection cycle ends. A metric is exported for the\n\t * number of requests received over the interval of time t_0 to\n\t * t_0+2 with a value of 5.\n\t * 9. The system experiences a fault and loses state.\n\t * 10. The system recovers and resumes receiving at time=t_1.\n\t * 11. A request is received, the system measures 1 request.\n\t * 12. The 1 second collection cycle ends. A metric is exported for the\n\t * number of requests received over the interval of time t_1 to\n\t * t_0+1 with a value of 1.\n\t *\n\t * Note: Even though, when reporting changes since last report time, using\n\t * CUMULATIVE is valid, it is not recommended. This may cause problems for\n\t * systems that do not use start_time to determine when the aggregation\n\t * value was reset (e.g. Prometheus).\n\t *\n\t * @generated from enum value: AGGREGATION_TEMPORALITY_CUMULATIVE = 2;\n\t */\n\tCUMULATIVE = 2,\n}\n\n/**\n * Describes the enum opentelemetry.proto.metrics.v1.AggregationTemporality.\n */\nexport const AggregationTemporalitySchema: GenEnum<AggregationTemporality> =\n\t/*@__PURE__*/\n\tenumDesc(file_opentelemetry_proto_metrics_v1_metrics, 0);\n\n/**\n * DataPointFlags is defined as a protobuf 'uint32' type and is to be used as a\n * bit-field representing 32 distinct boolean flags. Each flag defined in this\n * enum is a bit-mask. To test the presence of a single flag in the flags of\n * a data point, for example, use an expression like:\n *\n * (point.flags & DATA_POINT_FLAGS_NO_RECORDED_VALUE_MASK) == DATA_POINT_FLAGS_NO_RECORDED_VALUE_MASK\n *\n *\n * @generated from enum opentelemetry.proto.metrics.v1.DataPointFlags\n */\nexport enum DataPointFlags {\n\t/**\n\t * The zero value for the enum. Should not be used for comparisons.\n\t * Instead use bitwise \"and\" with the appropriate mask as shown above.\n\t *\n\t * @generated from enum value: DATA_POINT_FLAGS_DO_NOT_USE = 0;\n\t */\n\tDO_NOT_USE = 0,\n\n\t/**\n\t * This DataPoint is valid but has no recorded value. This value\n\t * SHOULD be used to reflect explicitly missing data in a series, as\n\t * for an equivalent to the Prometheus \"staleness marker\".\n\t *\n\t * @generated from enum value: DATA_POINT_FLAGS_NO_RECORDED_VALUE_MASK = 1;\n\t */\n\tNO_RECORDED_VALUE_MASK = 1,\n}\n\n/**\n * Describes the enum opentelemetry.proto.metrics.v1.DataPointFlags.\n */\nexport const DataPointFlagsSchema: GenEnum<DataPointFlags> =\n\t/*@__PURE__*/\n\tenumDesc(file_opentelemetry_proto_metrics_v1_metrics, 1);\n","import { fromBinary, fromJson } from \"@bufbuild/protobuf\";\nimport type {\n\tOtlpResourceSpans,\n\tOtlpTraceExportRequest,\n} from \"@obsunified/types\";\nimport {\n\ttype ExportTraceServiceRequest,\n\tExportTraceServiceRequestSchema,\n} from \"../gen/opentelemetry/proto/collector/trace/v1/trace_service_pb.js\";\nimport type { ResourceSpans } from \"../gen/opentelemetry/proto/trace/v1/trace_pb.js\";\nimport { decodeJsonBody, OtlpDecodeError, type ReadBodyResult } from \"./body\";\nimport { adaptKeyValue, bigintToString, bytesToHex } from \"./values\";\n\n/**\n * Decode an OTLP trace export request from wire bytes into the legacy\n * `@obsunified/types` shape consumed by `toStoredSpans`.\n */\nexport const decodeTraceRequest = (\n\tbody: ReadBodyResult,\n): OtlpTraceExportRequest => {\n\tlet msg: ExportTraceServiceRequest;\n\ttry {\n\t\tmsg =\n\t\t\tbody.wireFormat === \"protobuf\"\n\t\t\t\t? fromBinary(ExportTraceServiceRequestSchema, body.bytes)\n\t\t\t\t: fromJson(ExportTraceServiceRequestSchema, decodeJsonBody(body.bytes));\n\t} catch (err) {\n\t\tthrow new OtlpDecodeError(\n\t\t\t`Malformed OTLP body: ${(err as Error).message}`,\n\t\t\t400,\n\t\t);\n\t}\n\treturn { resourceSpans: msg.resourceSpans.map(adaptResourceSpans) };\n};\n\n// ── proto-native → legacy shape adapters ─────────────────────────────\n\nconst adaptResourceSpans = (rs: ResourceSpans): OtlpResourceSpans => ({\n\tresource: rs.resource\n\t\t? { attributes: rs.resource.attributes.map(adaptKeyValue) }\n\t\t: undefined,\n\tscopeSpans: rs.scopeSpans.map((ss) => ({\n\t\tscope: ss.scope\n\t\t\t? { name: ss.scope.name, version: ss.scope.version }\n\t\t\t: undefined,\n\t\tspans: ss.spans.flatMap((s) => {\n\t\t\tif (s.traceId.length !== 16 || s.spanId.length !== 8) return [];\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttraceId: bytesToHex(s.traceId),\n\t\t\t\t\tspanId: bytesToHex(s.spanId),\n\t\t\t\t\tparentSpanId:\n\t\t\t\t\t\ts.parentSpanId.length === 8\n\t\t\t\t\t\t\t? bytesToHex(s.parentSpanId)\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\ttraceState: s.traceState || undefined,\n\t\t\t\t\tname: s.name,\n\t\t\t\t\tkind: s.kind,\n\t\t\t\t\tstartTimeUnixNano: bigintToString(s.startTimeUnixNano),\n\t\t\t\t\tendTimeUnixNano: bigintToString(s.endTimeUnixNano),\n\t\t\t\t\tattributes: s.attributes.map(adaptKeyValue),\n\t\t\t\t\tdroppedAttributesCount: s.droppedAttributesCount || undefined,\n\t\t\t\t\tevents: s.events.map((e) => ({\n\t\t\t\t\t\tname: e.name,\n\t\t\t\t\t\ttimeUnixNano: bigintToString(e.timeUnixNano),\n\t\t\t\t\t\tattributes: e.attributes.map(adaptKeyValue),\n\t\t\t\t\t\tdroppedAttributesCount: e.droppedAttributesCount || undefined,\n\t\t\t\t\t})),\n\t\t\t\t\tdroppedEventsCount: s.droppedEventsCount || undefined,\n\t\t\t\t\tlinks: s.links.flatMap((l) =>\n\t\t\t\t\t\tl.traceId.length === 16 && l.spanId.length === 8\n\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttraceId: bytesToHex(l.traceId),\n\t\t\t\t\t\t\t\t\t\tspanId: bytesToHex(l.spanId),\n\t\t\t\t\t\t\t\t\t\ttraceState: l.traceState || undefined,\n\t\t\t\t\t\t\t\t\t\tattributes: l.attributes.map(adaptKeyValue),\n\t\t\t\t\t\t\t\t\t\tdroppedAttributesCount:\n\t\t\t\t\t\t\t\t\t\t\tl.droppedAttributesCount || undefined,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t: [],\n\t\t\t\t\t),\n\t\t\t\t\tdroppedLinksCount: s.droppedLinksCount || undefined,\n\t\t\t\t\tstatus: s.status\n\t\t\t\t\t\t? { code: s.status.code, message: s.status.message }\n\t\t\t\t\t\t: undefined,\n\t\t\t\t},\n\t\t\t];\n\t\t}),\n\t})),\n});\n","// Copyright 2019, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/collector/trace/v1/trace_service.proto (package opentelemetry.proto.collector.trace.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type {\n\tGenFile,\n\tGenMessage,\n\tGenService,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport {\n\tfileDesc,\n\tmessageDesc,\n\tserviceDesc,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport type { ResourceSpans } from \"../../../trace/v1/trace_pb.js\";\nimport { file_opentelemetry_proto_trace_v1_trace } from \"../../../trace/v1/trace_pb.js\";\n\n/**\n * Describes the file opentelemetry/proto/collector/trace/v1/trace_service.proto.\n */\nexport const file_opentelemetry_proto_collector_trace_v1_trace_service: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"CjpvcGVudGVsZW1ldHJ5L3Byb3RvL2NvbGxlY3Rvci90cmFjZS92MS90cmFjZV9zZXJ2aWNlLnByb3RvEiZvcGVudGVsZW1ldHJ5LnByb3RvLmNvbGxlY3Rvci50cmFjZS52MSJgChlFeHBvcnRUcmFjZVNlcnZpY2VSZXF1ZXN0EkMKDnJlc291cmNlX3NwYW5zGAEgAygLMisub3BlbnRlbGVtZXRyeS5wcm90by50cmFjZS52MS5SZXNvdXJjZVNwYW5zIngKGkV4cG9ydFRyYWNlU2VydmljZVJlc3BvbnNlEloKD3BhcnRpYWxfc3VjY2VzcxgBIAEoCzJBLm9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLnRyYWNlLnYxLkV4cG9ydFRyYWNlUGFydGlhbFN1Y2Nlc3MiSgoZRXhwb3J0VHJhY2VQYXJ0aWFsU3VjY2VzcxIWCg5yZWplY3RlZF9zcGFucxgBIAEoAxIVCg1lcnJvcl9tZXNzYWdlGAIgASgJMqIBCgxUcmFjZVNlcnZpY2USkQEKBkV4cG9ydBJBLm9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLnRyYWNlLnYxLkV4cG9ydFRyYWNlU2VydmljZVJlcXVlc3QaQi5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbGxlY3Rvci50cmFjZS52MS5FeHBvcnRUcmFjZVNlcnZpY2VSZXNwb25zZSIAQpwBCilpby5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbGxlY3Rvci50cmFjZS52MUIRVHJhY2VTZXJ2aWNlUHJvdG9QAVoxZ28ub3BlbnRlbGVtZXRyeS5pby9wcm90by9vdGxwL2NvbGxlY3Rvci90cmFjZS92MaoCJk9wZW5UZWxlbWV0cnkuUHJvdG8uQ29sbGVjdG9yLlRyYWNlLlYxYgZwcm90bzM\",\n\t\t[file_opentelemetry_proto_trace_v1_trace],\n\t);\n\n/**\n * @generated from message opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest\n */\nexport type ExportTraceServiceRequest =\n\tMessage<\"opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest\"> & {\n\t\t/**\n\t\t * An array of ResourceSpans.\n\t\t * For data coming from a single resource this array will typically contain one\n\t\t * element. Intermediary nodes (such as OpenTelemetry Collector) that receive\n\t\t * data from multiple origins typically batch the data before forwarding further and\n\t\t * in that case this array will contain multiple elements.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.trace.v1.ResourceSpans resource_spans = 1;\n\t\t */\n\t\tresourceSpans: ResourceSpans[];\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.\n * Use `create(ExportTraceServiceRequestSchema)` to create a new message.\n */\nexport const ExportTraceServiceRequestSchema: GenMessage<ExportTraceServiceRequest> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_trace_v1_trace_service, 0);\n\n/**\n * @generated from message opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse\n */\nexport type ExportTraceServiceResponse =\n\tMessage<\"opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse\"> & {\n\t\t/**\n\t\t * The details of a partially successful export request.\n\t\t *\n\t\t * If the request is only partially accepted\n\t\t * (i.e. when the server accepts only parts of the data and rejects the rest)\n\t\t * the server MUST initialize the `partial_success` field and MUST\n\t\t * set the `rejected_<signal>` with the number of items it rejected.\n\t\t *\n\t\t * Servers MAY also make use of the `partial_success` field to convey\n\t\t * warnings/suggestions to senders even when the request was fully accepted.\n\t\t * In such cases, the `rejected_<signal>` MUST have a value of `0` and\n\t\t * the `error_message` MUST be non-empty.\n\t\t *\n\t\t * A `partial_success` message with an empty value (rejected_<signal> = 0 and\n\t\t * `error_message` = \"\") is equivalent to it not being set/present. Senders\n\t\t * SHOULD interpret it the same way as in the full success case.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.collector.trace.v1.ExportTracePartialSuccess partial_success = 1;\n\t\t */\n\t\tpartialSuccess?: ExportTracePartialSuccess;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.\n * Use `create(ExportTraceServiceResponseSchema)` to create a new message.\n */\nexport const ExportTraceServiceResponseSchema: GenMessage<ExportTraceServiceResponse> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_trace_v1_trace_service, 1);\n\n/**\n * @generated from message opentelemetry.proto.collector.trace.v1.ExportTracePartialSuccess\n */\nexport type ExportTracePartialSuccess =\n\tMessage<\"opentelemetry.proto.collector.trace.v1.ExportTracePartialSuccess\"> & {\n\t\t/**\n\t\t * The number of rejected spans.\n\t\t *\n\t\t * A `rejected_<signal>` field holding a `0` value indicates that the\n\t\t * request was fully accepted.\n\t\t *\n\t\t * @generated from field: int64 rejected_spans = 1;\n\t\t */\n\t\trejectedSpans: bigint;\n\n\t\t/**\n\t\t * A developer-facing human-readable message in English. It should be used\n\t\t * either to explain why the server rejected parts of the data during a partial\n\t\t * success or to convey warnings/suggestions during a full success. The message\n\t\t * should offer guidance on how users can address such issues.\n\t\t *\n\t\t * error_message is an optional field. An error_message with an empty value\n\t\t * is equivalent to it not being set.\n\t\t *\n\t\t * @generated from field: string error_message = 2;\n\t\t */\n\t\terrorMessage: string;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.collector.trace.v1.ExportTracePartialSuccess.\n * Use `create(ExportTracePartialSuccessSchema)` to create a new message.\n */\nexport const ExportTracePartialSuccessSchema: GenMessage<ExportTracePartialSuccess> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_collector_trace_v1_trace_service, 2);\n\n/**\n * Service that can be used to push spans between one Application instrumented with\n * OpenTelemetry and a collector, or between a collector and a central collector (in this\n * case spans are sent/received to/from multiple Applications).\n *\n * @generated from service opentelemetry.proto.collector.trace.v1.TraceService\n */\nexport const TraceService: GenService<{\n\t/**\n\t * @generated from rpc opentelemetry.proto.collector.trace.v1.TraceService.Export\n\t */\n\texport: {\n\t\tmethodKind: \"unary\";\n\t\tinput: typeof ExportTraceServiceRequestSchema;\n\t\toutput: typeof ExportTraceServiceResponseSchema;\n\t};\n}> =\n\t/*@__PURE__*/\n\tserviceDesc(file_opentelemetry_proto_collector_trace_v1_trace_service, 0);\n","// Copyright 2019, OpenTelemetry Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// @generated by protoc-gen-es v2.11.0 with parameter \"target=ts,import_extension=js\"\n// @generated from file opentelemetry/proto/trace/v1/trace.proto (package opentelemetry.proto.trace.v1, syntax proto3)\n/* eslint-disable */\n\nimport type { Message } from \"@bufbuild/protobuf\";\nimport type {\n\tGenEnum,\n\tGenFile,\n\tGenMessage,\n} from \"@bufbuild/protobuf/codegenv2\";\nimport { enumDesc, fileDesc, messageDesc } from \"@bufbuild/protobuf/codegenv2\";\nimport type {\n\tInstrumentationScope,\n\tKeyValue,\n} from \"../../common/v1/common_pb.js\";\nimport { file_opentelemetry_proto_common_v1_common } from \"../../common/v1/common_pb.js\";\nimport type { Resource } from \"../../resource/v1/resource_pb.js\";\nimport { file_opentelemetry_proto_resource_v1_resource } from \"../../resource/v1/resource_pb.js\";\n\n/**\n * Describes the file opentelemetry/proto/trace/v1/trace.proto.\n */\nexport const file_opentelemetry_proto_trace_v1_trace: GenFile =\n\t/*@__PURE__*/\n\tfileDesc(\n\t\t\"CihvcGVudGVsZW1ldHJ5L3Byb3RvL3RyYWNlL3YxL3RyYWNlLnByb3RvEhxvcGVudGVsZW1ldHJ5LnByb3RvLnRyYWNlLnYxIlEKClRyYWNlc0RhdGESQwoOcmVzb3VyY2Vfc3BhbnMYASADKAsyKy5vcGVudGVsZW1ldHJ5LnByb3RvLnRyYWNlLnYxLlJlc291cmNlU3BhbnMipwEKDVJlc291cmNlU3BhbnMSOwoIcmVzb3VyY2UYASABKAsyKS5vcGVudGVsZW1ldHJ5LnByb3RvLnJlc291cmNlLnYxLlJlc291cmNlEj0KC3Njb3BlX3NwYW5zGAIgAygLMigub3BlbnRlbGVtZXRyeS5wcm90by50cmFjZS52MS5TY29wZVNwYW5zEhIKCnNjaGVtYV91cmwYAyABKAlKBgjoBxDpByKXAQoKU2NvcGVTcGFucxJCCgVzY29wZRgBIAEoCzIzLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxLkluc3RydW1lbnRhdGlvblNjb3BlEjEKBXNwYW5zGAIgAygLMiIub3BlbnRlbGVtZXRyeS5wcm90by50cmFjZS52MS5TcGFuEhIKCnNjaGVtYV91cmwYAyABKAkihAgKBFNwYW4SEAoIdHJhY2VfaWQYASABKAwSDwoHc3Bhbl9pZBgCIAEoDBITCgt0cmFjZV9zdGF0ZRgDIAEoCRIWCg5wYXJlbnRfc3Bhbl9pZBgEIAEoDBINCgVmbGFncxgQIAEoBxIMCgRuYW1lGAUgASgJEjkKBGtpbmQYBiABKA4yKy5vcGVudGVsZW1ldHJ5LnByb3RvLnRyYWNlLnYxLlNwYW4uU3BhbktpbmQSHAoUc3RhcnRfdGltZV91bml4X25hbm8YByABKAYSGgoSZW5kX3RpbWVfdW5peF9uYW5vGAggASgGEjsKCmF0dHJpYnV0ZXMYCSADKAsyJy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi52MS5LZXlWYWx1ZRIgChhkcm9wcGVkX2F0dHJpYnV0ZXNfY291bnQYCiABKA0SOAoGZXZlbnRzGAsgAygLMigub3BlbnRlbGVtZXRyeS5wcm90by50cmFjZS52MS5TcGFuLkV2ZW50EhwKFGRyb3BwZWRfZXZlbnRzX2NvdW50GAwgASgNEjYKBWxpbmtzGA0gAygLMicub3BlbnRlbGVtZXRyeS5wcm90by50cmFjZS52MS5TcGFuLkxpbmsSGwoTZHJvcHBlZF9saW5rc19jb3VudBgOIAEoDRI0CgZzdGF0dXMYDyABKAsyJC5vcGVudGVsZW1ldHJ5LnByb3RvLnRyYWNlLnYxLlN0YXR1cxqMAQoFRXZlbnQSFgoOdGltZV91bml4X25hbm8YASABKAYSDAoEbmFtZRgCIAEoCRI7CgphdHRyaWJ1dGVzGAMgAygLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb21tb24udjEuS2V5VmFsdWUSIAoYZHJvcHBlZF9hdHRyaWJ1dGVzX2NvdW50GAQgASgNGqwBCgRMaW5rEhAKCHRyYWNlX2lkGAEgASgMEg8KB3NwYW5faWQYAiABKAwSEwoLdHJhY2Vfc3RhdGUYAyABKAkSOwoKYXR0cmlidXRlcxgEIAMoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxLktleVZhbHVlEiAKGGRyb3BwZWRfYXR0cmlidXRlc19jb3VudBgFIAEoDRINCgVmbGFncxgGIAEoByKZAQoIU3BhbktpbmQSGQoVU1BBTl9LSU5EX1VOU1BFQ0lGSUVEEAASFgoSU1BBTl9LSU5EX0lOVEVSTkFMEAESFAoQU1BBTl9LSU5EX1NFUlZFUhACEhQKEFNQQU5fS0lORF9DTElFTlQQAxIWChJTUEFOX0tJTkRfUFJPRFVDRVIQBBIWChJTUEFOX0tJTkRfQ09OU1VNRVIQBSKuAQoGU3RhdHVzEg8KB21lc3NhZ2UYAiABKAkSPQoEY29kZRgDIAEoDjIvLm9wZW50ZWxlbWV0cnkucHJvdG8udHJhY2UudjEuU3RhdHVzLlN0YXR1c0NvZGUiTgoKU3RhdHVzQ29kZRIVChFTVEFUVVNfQ09ERV9VTlNFVBAAEhIKDlNUQVRVU19DT0RFX09LEAESFQoRU1RBVFVTX0NPREVfRVJST1IQAkoECAEQAiqcAQoJU3BhbkZsYWdzEhkKFVNQQU5fRkxBR1NfRE9fTk9UX1VTRRAAEiAKG1NQQU5fRkxBR1NfVFJBQ0VfRkxBR1NfTUFTSxD/ARIqCiVTUEFOX0ZMQUdTX0NPTlRFWFRfSEFTX0lTX1JFTU9URV9NQVNLEIACEiYKIVNQQU5fRkxBR1NfQ09OVEVYVF9JU19SRU1PVEVfTUFTSxCABEJ3Ch9pby5vcGVudGVsZW1ldHJ5LnByb3RvLnRyYWNlLnYxQgpUcmFjZVByb3RvUAFaJ2dvLm9wZW50ZWxlbWV0cnkuaW8vcHJvdG8vb3RscC90cmFjZS92MaoCHE9wZW5UZWxlbWV0cnkuUHJvdG8uVHJhY2UuVjFiBnByb3RvMw\",\n\t\t[\n\t\t\tfile_opentelemetry_proto_common_v1_common,\n\t\t\tfile_opentelemetry_proto_resource_v1_resource,\n\t\t],\n\t);\n\n/**\n * TracesData represents the traces data that can be stored in a persistent storage,\n * OR can be embedded by other protocols that transfer OTLP traces data but do\n * not implement the OTLP protocol.\n *\n * The main difference between this message and collector protocol is that\n * in this message there will not be any \"control\" or \"metadata\" specific to\n * OTLP protocol.\n *\n * When new fields are added into this message, the OTLP request MUST be updated\n * as well.\n *\n * @generated from message opentelemetry.proto.trace.v1.TracesData\n */\nexport type TracesData = Message<\"opentelemetry.proto.trace.v1.TracesData\"> & {\n\t/**\n\t * An array of ResourceSpans.\n\t * For data coming from a single resource this array will typically contain\n\t * one element. Intermediary nodes that receive data from multiple origins\n\t * typically batch the data before forwarding further and in that case this\n\t * array will contain multiple elements.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.trace.v1.ResourceSpans resource_spans = 1;\n\t */\n\tresourceSpans: ResourceSpans[];\n};\n\n/**\n * Describes the message opentelemetry.proto.trace.v1.TracesData.\n * Use `create(TracesDataSchema)` to create a new message.\n */\nexport const TracesDataSchema: GenMessage<TracesData> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_trace_v1_trace, 0);\n\n/**\n * A collection of ScopeSpans from a Resource.\n *\n * @generated from message opentelemetry.proto.trace.v1.ResourceSpans\n */\nexport type ResourceSpans =\n\tMessage<\"opentelemetry.proto.trace.v1.ResourceSpans\"> & {\n\t\t/**\n\t\t * The resource for the spans in this message.\n\t\t * If this field is not set then no resource info is known.\n\t\t *\n\t\t * @generated from field: opentelemetry.proto.resource.v1.Resource resource = 1;\n\t\t */\n\t\tresource?: Resource;\n\n\t\t/**\n\t\t * A list of ScopeSpans that originate from a resource.\n\t\t *\n\t\t * @generated from field: repeated opentelemetry.proto.trace.v1.ScopeSpans scope_spans = 2;\n\t\t */\n\t\tscopeSpans: ScopeSpans[];\n\n\t\t/**\n\t\t * The Schema URL, if known. This is the identifier of the Schema that the resource data\n\t\t * is recorded in. Notably, the last part of the URL path is the version number of the\n\t\t * schema: http[s]://server[:port]/path/<version>. To learn more about Schema URL see\n\t\t * https://opentelemetry.io/docs/specs/otel/schemas/#schema-url\n\t\t * This schema_url applies to the data in the \"resource\" field. It does not apply\n\t\t * to the data in the \"scope_spans\" field which have their own schema_url field.\n\t\t *\n\t\t * @generated from field: string schema_url = 3;\n\t\t */\n\t\tschemaUrl: string;\n\t};\n\n/**\n * Describes the message opentelemetry.proto.trace.v1.ResourceSpans.\n * Use `create(ResourceSpansSchema)` to create a new message.\n */\nexport const ResourceSpansSchema: GenMessage<ResourceSpans> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_trace_v1_trace, 1);\n\n/**\n * A collection of Spans produced by an InstrumentationScope.\n *\n * @generated from message opentelemetry.proto.trace.v1.ScopeSpans\n */\nexport type ScopeSpans = Message<\"opentelemetry.proto.trace.v1.ScopeSpans\"> & {\n\t/**\n\t * The instrumentation scope information for the spans in this message.\n\t * Semantically when InstrumentationScope isn't set, it is equivalent with\n\t * an empty instrumentation scope name (unknown).\n\t *\n\t * @generated from field: opentelemetry.proto.common.v1.InstrumentationScope scope = 1;\n\t */\n\tscope?: InstrumentationScope;\n\n\t/**\n\t * A list of Spans that originate from an instrumentation scope.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.trace.v1.Span spans = 2;\n\t */\n\tspans: Span[];\n\n\t/**\n\t * The Schema URL, if known. This is the identifier of the Schema that the span data\n\t * is recorded in. Notably, the last part of the URL path is the version number of the\n\t * schema: http[s]://server[:port]/path/<version>. To learn more about Schema URL see\n\t * https://opentelemetry.io/docs/specs/otel/schemas/#schema-url\n\t * This schema_url applies to all spans and span events in the \"spans\" field.\n\t *\n\t * @generated from field: string schema_url = 3;\n\t */\n\tschemaUrl: string;\n};\n\n/**\n * Describes the message opentelemetry.proto.trace.v1.ScopeSpans.\n * Use `create(ScopeSpansSchema)` to create a new message.\n */\nexport const ScopeSpansSchema: GenMessage<ScopeSpans> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_trace_v1_trace, 2);\n\n/**\n * A Span represents a single operation performed by a single component of the system.\n *\n * The next available field id is 17.\n *\n * @generated from message opentelemetry.proto.trace.v1.Span\n */\nexport type Span = Message<\"opentelemetry.proto.trace.v1.Span\"> & {\n\t/**\n\t * A unique identifier for a trace. All spans from the same trace share\n\t * the same `trace_id`. The ID is a 16-byte array. An ID with all zeroes OR\n\t * of length other than 16 bytes is considered invalid (empty string in OTLP/JSON\n\t * is zero-length and thus is also invalid).\n\t *\n\t * This field is required.\n\t *\n\t * @generated from field: bytes trace_id = 1;\n\t */\n\ttraceId: Uint8Array;\n\n\t/**\n\t * A unique identifier for a span within a trace, assigned when the span\n\t * is created. The ID is an 8-byte array. An ID with all zeroes OR of length\n\t * other than 8 bytes is considered invalid (empty string in OTLP/JSON\n\t * is zero-length and thus is also invalid).\n\t *\n\t * This field is required.\n\t *\n\t * @generated from field: bytes span_id = 2;\n\t */\n\tspanId: Uint8Array;\n\n\t/**\n\t * trace_state conveys information about request position in multiple distributed tracing graphs.\n\t * It is a trace_state in w3c-trace-context format: https://www.w3.org/TR/trace-context/#tracestate-header\n\t * See also https://github.com/w3c/distributed-tracing for more details about this field.\n\t *\n\t * @generated from field: string trace_state = 3;\n\t */\n\ttraceState: string;\n\n\t/**\n\t * The `span_id` of this span's parent span. If this is a root span, then this\n\t * field must be empty. The ID is an 8-byte array.\n\t *\n\t * @generated from field: bytes parent_span_id = 4;\n\t */\n\tparentSpanId: Uint8Array;\n\n\t/**\n\t * Flags, a bit field.\n\t *\n\t * Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace\n\t * Context specification. To read the 8-bit W3C trace flag, use\n\t * `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`.\n\t *\n\t * See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions.\n\t *\n\t * Bits 8 and 9 represent the 3 states of whether a span's parent\n\t * is remote. The states are (unknown, is not remote, is remote).\n\t * To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`.\n\t * To read whether the span is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`.\n\t *\n\t * When creating span messages, if the message is logically forwarded from another source\n\t * with an equivalent flags fields (i.e., usually another OTLP span message), the field SHOULD\n\t * be copied as-is. If creating from a source that does not have an equivalent flags field\n\t * (such as a runtime representation of an OpenTelemetry span), the high 22 bits MUST\n\t * be set to zero.\n\t * Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be zero.\n\t *\n\t * [Optional].\n\t *\n\t * @generated from field: fixed32 flags = 16;\n\t */\n\tflags: number;\n\n\t/**\n\t * A description of the span's operation.\n\t *\n\t * For example, the name can be a qualified method name or a file name\n\t * and a line number where the operation is called. A best practice is to use\n\t * the same display name at the same call point in an application.\n\t * This makes it easier to correlate spans in different traces.\n\t *\n\t * This field is semantically required to be set to non-empty string.\n\t * Empty value is equivalent to an unknown span name.\n\t *\n\t * This field is required.\n\t *\n\t * @generated from field: string name = 5;\n\t */\n\tname: string;\n\n\t/**\n\t * Distinguishes between spans generated in a particular context. For example,\n\t * two spans with the same name may be distinguished using `CLIENT` (caller)\n\t * and `SERVER` (callee) to identify queueing latency associated with the span.\n\t *\n\t * @generated from field: opentelemetry.proto.trace.v1.Span.SpanKind kind = 6;\n\t */\n\tkind: Span_SpanKind;\n\n\t/**\n\t * start_time_unix_nano is the start time of the span. On the client side, this is the time\n\t * kept by the local machine where the span execution starts. On the server side, this\n\t * is the time when the server's application handler starts running.\n\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970.\n\t *\n\t * This field is semantically required and it is expected that end_time >= start_time.\n\t *\n\t * @generated from field: fixed64 start_time_unix_nano = 7;\n\t */\n\tstartTimeUnixNano: bigint;\n\n\t/**\n\t * end_time_unix_nano is the end time of the span. On the client side, this is the time\n\t * kept by the local machine where the span execution ends. On the server side, this\n\t * is the time when the server application handler stops running.\n\t * Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970.\n\t *\n\t * This field is semantically required and it is expected that end_time >= start_time.\n\t *\n\t * @generated from field: fixed64 end_time_unix_nano = 8;\n\t */\n\tendTimeUnixNano: bigint;\n\n\t/**\n\t * attributes is a collection of key/value pairs. Note, global attributes\n\t * like server name can be set using the resource API. Examples of attributes:\n\t *\n\t * \"/http/user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36\"\n\t * \"/http/server_latency\": 300\n\t * \"example.com/myattribute\": true\n\t * \"example.com/score\": 10.239\n\t *\n\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t * attribute with the same key).\n\t *\n\t * The attribute values SHOULD NOT contain empty values.\n\t * The attribute values SHOULD NOT contain bytes values.\n\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t * double values.\n\t * The attribute values SHOULD NOT contain kvlist values.\n\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t * These restrictions can change in a minor release.\n\t * The restrictions take origin from the OpenTelemetry specification:\n\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 9;\n\t */\n\tattributes: KeyValue[];\n\n\t/**\n\t * dropped_attributes_count is the number of attributes that were discarded. Attributes\n\t * can be discarded because their keys are too long or because there are too many\n\t * attributes. If this value is 0, then no attributes were dropped.\n\t *\n\t * @generated from field: uint32 dropped_attributes_count = 10;\n\t */\n\tdroppedAttributesCount: number;\n\n\t/**\n\t * events is a collection of Event items.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.trace.v1.Span.Event events = 11;\n\t */\n\tevents: Span_Event[];\n\n\t/**\n\t * dropped_events_count is the number of dropped events. If the value is 0, then no\n\t * events were dropped.\n\t *\n\t * @generated from field: uint32 dropped_events_count = 12;\n\t */\n\tdroppedEventsCount: number;\n\n\t/**\n\t * links is a collection of Links, which are references from this span to a span\n\t * in the same or different trace.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.trace.v1.Span.Link links = 13;\n\t */\n\tlinks: Span_Link[];\n\n\t/**\n\t * dropped_links_count is the number of dropped links after the maximum size was\n\t * enforced. If this value is 0, then no links were dropped.\n\t *\n\t * @generated from field: uint32 dropped_links_count = 14;\n\t */\n\tdroppedLinksCount: number;\n\n\t/**\n\t * An optional final status for this span. Semantically when Status isn't set, it means\n\t * span's status code is unset, i.e. assume STATUS_CODE_UNSET (code = 0).\n\t *\n\t * @generated from field: opentelemetry.proto.trace.v1.Status status = 15;\n\t */\n\tstatus?: Status;\n};\n\n/**\n * Describes the message opentelemetry.proto.trace.v1.Span.\n * Use `create(SpanSchema)` to create a new message.\n */\nexport const SpanSchema: GenMessage<Span> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_trace_v1_trace, 3);\n\n/**\n * Event is a time-stamped annotation of the span, consisting of user-supplied\n * text description and key-value pairs.\n *\n * @generated from message opentelemetry.proto.trace.v1.Span.Event\n */\nexport type Span_Event = Message<\"opentelemetry.proto.trace.v1.Span.Event\"> & {\n\t/**\n\t * time_unix_nano is the time the event occurred.\n\t *\n\t * @generated from field: fixed64 time_unix_nano = 1;\n\t */\n\ttimeUnixNano: bigint;\n\n\t/**\n\t * name of the event.\n\t * This field is semantically required to be set to non-empty string.\n\t *\n\t * @generated from field: string name = 2;\n\t */\n\tname: string;\n\n\t/**\n\t * attributes is a collection of attribute key/value pairs on the event.\n\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t * attribute with the same key).\n\t *\n\t * The attribute values SHOULD NOT contain empty values.\n\t * The attribute values SHOULD NOT contain bytes values.\n\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t * double values.\n\t * The attribute values SHOULD NOT contain kvlist values.\n\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t * These restrictions can change in a minor release.\n\t * The restrictions take origin from the OpenTelemetry specification:\n\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 3;\n\t */\n\tattributes: KeyValue[];\n\n\t/**\n\t * dropped_attributes_count is the number of dropped attributes. If the value is 0,\n\t * then no attributes were dropped.\n\t *\n\t * @generated from field: uint32 dropped_attributes_count = 4;\n\t */\n\tdroppedAttributesCount: number;\n};\n\n/**\n * Describes the message opentelemetry.proto.trace.v1.Span.Event.\n * Use `create(Span_EventSchema)` to create a new message.\n */\nexport const Span_EventSchema: GenMessage<Span_Event> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_trace_v1_trace, 3, 0);\n\n/**\n * A pointer from the current span to another span in the same trace or in a\n * different trace. For example, this can be used in batching operations,\n * where a single batch handler processes multiple requests from different\n * traces or when the handler receives a request from a different project.\n *\n * @generated from message opentelemetry.proto.trace.v1.Span.Link\n */\nexport type Span_Link = Message<\"opentelemetry.proto.trace.v1.Span.Link\"> & {\n\t/**\n\t * A unique identifier of a trace that this linked span is part of. The ID is a\n\t * 16-byte array.\n\t *\n\t * @generated from field: bytes trace_id = 1;\n\t */\n\ttraceId: Uint8Array;\n\n\t/**\n\t * A unique identifier for the linked span. The ID is an 8-byte array.\n\t *\n\t * @generated from field: bytes span_id = 2;\n\t */\n\tspanId: Uint8Array;\n\n\t/**\n\t * The trace_state associated with the link.\n\t *\n\t * @generated from field: string trace_state = 3;\n\t */\n\ttraceState: string;\n\n\t/**\n\t * attributes is a collection of attribute key/value pairs on the link.\n\t * Attribute keys MUST be unique (it is not allowed to have more than one\n\t * attribute with the same key).\n\t *\n\t * The attribute values SHOULD NOT contain empty values.\n\t * The attribute values SHOULD NOT contain bytes values.\n\t * The attribute values SHOULD NOT contain array values different than array of string values, bool values, int values,\n\t * double values.\n\t * The attribute values SHOULD NOT contain kvlist values.\n\t * The behavior of software that receives attributes containing such values can be unpredictable.\n\t * These restrictions can change in a minor release.\n\t * The restrictions take origin from the OpenTelemetry specification:\n\t * https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.\n\t *\n\t * @generated from field: repeated opentelemetry.proto.common.v1.KeyValue attributes = 4;\n\t */\n\tattributes: KeyValue[];\n\n\t/**\n\t * dropped_attributes_count is the number of dropped attributes. If the value is 0,\n\t * then no attributes were dropped.\n\t *\n\t * @generated from field: uint32 dropped_attributes_count = 5;\n\t */\n\tdroppedAttributesCount: number;\n\n\t/**\n\t * Flags, a bit field.\n\t *\n\t * Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace\n\t * Context specification. To read the 8-bit W3C trace flag, use\n\t * `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`.\n\t *\n\t * See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions.\n\t *\n\t * Bits 8 and 9 represent the 3 states of whether the link is remote.\n\t * The states are (unknown, is not remote, is remote).\n\t * To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`.\n\t * To read whether the link is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`.\n\t *\n\t * Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be zero.\n\t * When creating new spans, bits 10-31 (most-significant 22-bits) MUST be zero.\n\t *\n\t * [Optional].\n\t *\n\t * @generated from field: fixed32 flags = 6;\n\t */\n\tflags: number;\n};\n\n/**\n * Describes the message opentelemetry.proto.trace.v1.Span.Link.\n * Use `create(Span_LinkSchema)` to create a new message.\n */\nexport const Span_LinkSchema: GenMessage<Span_Link> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_trace_v1_trace, 3, 1);\n\n/**\n * SpanKind is the type of span. Can be used to specify additional relationships between spans\n * in addition to a parent/child relationship.\n *\n * @generated from enum opentelemetry.proto.trace.v1.Span.SpanKind\n */\nexport enum Span_SpanKind {\n\t/**\n\t * Unspecified. Do NOT use as default.\n\t * Implementations MAY assume SpanKind to be INTERNAL when receiving UNSPECIFIED.\n\t *\n\t * @generated from enum value: SPAN_KIND_UNSPECIFIED = 0;\n\t */\n\tUNSPECIFIED = 0,\n\n\t/**\n\t * Indicates that the span represents an internal operation within an application,\n\t * as opposed to an operation happening at the boundaries. Default value.\n\t *\n\t * @generated from enum value: SPAN_KIND_INTERNAL = 1;\n\t */\n\tINTERNAL = 1,\n\n\t/**\n\t * Indicates that the span covers server-side handling of an RPC or other\n\t * remote network request.\n\t *\n\t * @generated from enum value: SPAN_KIND_SERVER = 2;\n\t */\n\tSERVER = 2,\n\n\t/**\n\t * Indicates that the span describes a request to some remote service.\n\t *\n\t * @generated from enum value: SPAN_KIND_CLIENT = 3;\n\t */\n\tCLIENT = 3,\n\n\t/**\n\t * Indicates that the span describes a producer sending a message to a broker.\n\t * Unlike CLIENT and SERVER, there is often no direct critical path latency relationship\n\t * between producer and consumer spans. A PRODUCER span ends when the message was accepted\n\t * by the broker while the logical processing of the message might span a much longer time.\n\t *\n\t * @generated from enum value: SPAN_KIND_PRODUCER = 4;\n\t */\n\tPRODUCER = 4,\n\n\t/**\n\t * Indicates that the span describes consumer receiving a message from a broker.\n\t * Like the PRODUCER kind, there is often no direct critical path latency relationship\n\t * between producer and consumer spans.\n\t *\n\t * @generated from enum value: SPAN_KIND_CONSUMER = 5;\n\t */\n\tCONSUMER = 5,\n}\n\n/**\n * Describes the enum opentelemetry.proto.trace.v1.Span.SpanKind.\n */\nexport const Span_SpanKindSchema: GenEnum<Span_SpanKind> =\n\t/*@__PURE__*/\n\tenumDesc(file_opentelemetry_proto_trace_v1_trace, 3, 0);\n\n/**\n * The Status type defines a logical error model that is suitable for different\n * programming environments, including REST APIs and RPC APIs.\n *\n * @generated from message opentelemetry.proto.trace.v1.Status\n */\nexport type Status = Message<\"opentelemetry.proto.trace.v1.Status\"> & {\n\t/**\n\t * A developer-facing human readable error message.\n\t *\n\t * @generated from field: string message = 2;\n\t */\n\tmessage: string;\n\n\t/**\n\t * The status code.\n\t *\n\t * @generated from field: opentelemetry.proto.trace.v1.Status.StatusCode code = 3;\n\t */\n\tcode: Status_StatusCode;\n};\n\n/**\n * Describes the message opentelemetry.proto.trace.v1.Status.\n * Use `create(StatusSchema)` to create a new message.\n */\nexport const StatusSchema: GenMessage<Status> =\n\t/*@__PURE__*/\n\tmessageDesc(file_opentelemetry_proto_trace_v1_trace, 4);\n\n/**\n * For the semantics of status codes see\n * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#set-status\n *\n * @generated from enum opentelemetry.proto.trace.v1.Status.StatusCode\n */\nexport enum Status_StatusCode {\n\t/**\n\t * The default status.\n\t *\n\t * @generated from enum value: STATUS_CODE_UNSET = 0;\n\t */\n\tUNSET = 0,\n\n\t/**\n\t * The Span has been validated by an Application developer or Operator to\n\t * have completed successfully.\n\t *\n\t * @generated from enum value: STATUS_CODE_OK = 1;\n\t */\n\tOK = 1,\n\n\t/**\n\t * The Span contains an error.\n\t *\n\t * @generated from enum value: STATUS_CODE_ERROR = 2;\n\t */\n\tERROR = 2,\n}\n\n/**\n * Describes the enum opentelemetry.proto.trace.v1.Status.StatusCode.\n */\nexport const Status_StatusCodeSchema: GenEnum<Status_StatusCode> =\n\t/*@__PURE__*/\n\tenumDesc(file_opentelemetry_proto_trace_v1_trace, 4, 0);\n\n/**\n * SpanFlags represents constants used to interpret the\n * Span.flags field, which is protobuf 'fixed32' type and is to\n * be used as bit-fields. Each non-zero value defined in this enum is\n * a bit-mask. To extract the bit-field, for example, use an\n * expression like:\n *\n * (span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK)\n *\n * See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions.\n *\n * Note that Span flags were introduced in version 1.1 of the\n * OpenTelemetry protocol. Older Span producers do not set this\n * field, consequently consumers should not rely on the absence of a\n * particular flag bit to indicate the presence of a particular feature.\n *\n * @generated from enum opentelemetry.proto.trace.v1.SpanFlags\n */\nexport enum SpanFlags {\n\t/**\n\t * The zero value for the enum. Should not be used for comparisons.\n\t * Instead use bitwise \"and\" with the appropriate mask as shown above.\n\t *\n\t * @generated from enum value: SPAN_FLAGS_DO_NOT_USE = 0;\n\t */\n\tDO_NOT_USE = 0,\n\n\t/**\n\t * Bits 0-7 are used for trace flags.\n\t *\n\t * @generated from enum value: SPAN_FLAGS_TRACE_FLAGS_MASK = 255;\n\t */\n\tTRACE_FLAGS_MASK = 255,\n\n\t/**\n\t * Bits 8 and 9 are used to indicate that the parent span or link span is remote.\n\t * Bit 8 (`HAS_IS_REMOTE`) indicates whether the value is known.\n\t * Bit 9 (`IS_REMOTE`) indicates whether the span or link is remote.\n\t *\n\t * @generated from enum value: SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK = 256;\n\t */\n\tCONTEXT_HAS_IS_REMOTE_MASK = 256,\n\n\t/**\n\t * @generated from enum value: SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK = 512;\n\t */\n\tCONTEXT_IS_REMOTE_MASK = 512,\n}\n\n/**\n * Describes the enum opentelemetry.proto.trace.v1.SpanFlags.\n */\nexport const SpanFlagsSchema: GenEnum<SpanFlags> =\n\t/*@__PURE__*/\n\tenumDesc(file_opentelemetry_proto_trace_v1_trace, 0);\n","/**\n * OTLP response envelope encoders.\n *\n * Per the OTLP/HTTP spec, successful responses are always `200 OK` — whether\n * fully accepted or partial — with a serialized `Export{Signal}ServiceResponse`\n * body. Wire format mirrors the request (JSON in → JSON out; protobuf in →\n * protobuf out). `partial_success` is set only when records were actually\n * rejected; an empty partial_success block is semantically identical to a\n * fully-accepted response and wastes bytes.\n *\n * See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md#failures\n */\n\nimport { create, type DescMessage, toBinary, toJson } from \"@bufbuild/protobuf\";\nimport type { Context } from \"hono\";\nimport type { OtlpWireFormat } from \"./decode\";\nimport {\n\tExportLogsPartialSuccessSchema,\n\tExportLogsServiceResponseSchema,\n} from \"./gen/opentelemetry/proto/collector/logs/v1/logs_service_pb.js\";\nimport {\n\tExportMetricsPartialSuccessSchema,\n\tExportMetricsServiceResponseSchema,\n} from \"./gen/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.js\";\nimport {\n\tExportTracePartialSuccessSchema,\n\tExportTraceServiceResponseSchema,\n} from \"./gen/opentelemetry/proto/collector/trace/v1/trace_service_pb.js\";\n\nexport interface PartialSuccess {\n\trejected: number;\n\terrorMessage: string;\n}\n\n/**\n * Return a retryable error response per the OTLP/HTTP spec. Sets the\n * `Retry-After` header which OTel SDKs respect for exponential backoff.\n *\n * 429 Too Many Requests — per-client throttling\n * 503 Service Unavailable — server-side overload or transient failure\n *\n * The body is a plain JSON error, not an OTLP envelope — the spec permits\n * any body (or empty) for failure cases. `Retry-After` uses integer seconds.\n */\nexport const otlpRetryableError = (\n\tc: Context,\n\tstatus: 429 | 503,\n\tmessage: string,\n\tretryAfterSec = 5,\n) =>\n\tc.body(JSON.stringify({ error: message }), status, {\n\t\t\"Content-Type\": \"application/json\",\n\t\t\"Retry-After\": String(retryAfterSec),\n\t});\n\nexport const traceResponse = (\n\tc: Context,\n\twireFormat: OtlpWireFormat,\n\tpartial?: PartialSuccess,\n) => {\n\tconst msg = create(\n\t\tExportTraceServiceResponseSchema,\n\t\tpartial\n\t\t\t? {\n\t\t\t\t\tpartialSuccess: create(ExportTracePartialSuccessSchema, {\n\t\t\t\t\t\trejectedSpans: BigInt(partial.rejected),\n\t\t\t\t\t\terrorMessage: partial.errorMessage,\n\t\t\t\t\t}),\n\t\t\t\t}\n\t\t\t: {},\n\t);\n\treturn encode(c, wireFormat, ExportTraceServiceResponseSchema, msg);\n};\n\nexport const logsResponse = (\n\tc: Context,\n\twireFormat: OtlpWireFormat,\n\tpartial?: PartialSuccess,\n) => {\n\tconst msg = create(\n\t\tExportLogsServiceResponseSchema,\n\t\tpartial\n\t\t\t? {\n\t\t\t\t\tpartialSuccess: create(ExportLogsPartialSuccessSchema, {\n\t\t\t\t\t\trejectedLogRecords: BigInt(partial.rejected),\n\t\t\t\t\t\terrorMessage: partial.errorMessage,\n\t\t\t\t\t}),\n\t\t\t\t}\n\t\t\t: {},\n\t);\n\treturn encode(c, wireFormat, ExportLogsServiceResponseSchema, msg);\n};\n\nexport const metricsResponse = (\n\tc: Context,\n\twireFormat: OtlpWireFormat,\n\tpartial?: PartialSuccess,\n) => {\n\tconst msg = create(\n\t\tExportMetricsServiceResponseSchema,\n\t\tpartial\n\t\t\t? {\n\t\t\t\t\tpartialSuccess: create(ExportMetricsPartialSuccessSchema, {\n\t\t\t\t\t\trejectedDataPoints: BigInt(partial.rejected),\n\t\t\t\t\t\terrorMessage: partial.errorMessage,\n\t\t\t\t\t}),\n\t\t\t\t}\n\t\t\t: {},\n\t);\n\treturn encode(c, wireFormat, ExportMetricsServiceResponseSchema, msg);\n};\n\nconst encode = <T extends DescMessage>(\n\tc: Context,\n\twireFormat: OtlpWireFormat,\n\tschema: T,\n\tmsg: Parameters<typeof toBinary<T>>[1],\n) => {\n\tif (wireFormat === \"protobuf\") {\n\t\tconst bytes = toBinary(schema, msg);\n\t\treturn c.body(bytes, 200, {\n\t\t\t\"Content-Type\": \"application/x-protobuf\",\n\t\t});\n\t}\n\tconst json = toJson(schema, msg);\n\treturn c.body(JSON.stringify(json), 200, {\n\t\t\"Content-Type\": \"application/json\",\n\t});\n};\n","/** OTLP/HTTP metrics receiver. Accepts JSON or protobuf, with gzip. */\n\nimport { getConfiguredRetentionHours } from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { MetricsStore } from \"../lib/metrics-store\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport {\n\tdecodeMetricsRequest,\n\tOtlpDecodeError,\n\ttype ReadBodyResult,\n\treadOtlpBody,\n} from \"../otlp/decode\";\nimport { metricsResponse, otlpRetryableError } from \"../otlp/response\";\nimport { getProjectId } from \"./_context\";\n\nconst MAX_POINTS_PER_REQUEST = 2000;\n\nexport const metricsReceiverPlugin: CollectorPlugin = {\n\tname: \"metrics-http-receiver\",\n\tregister(app, runtime) {\n\t\tapp.post(\"/v1/metrics\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\n\t\t\tlet body: ReadBodyResult;\n\t\t\ttry {\n\t\t\t\tbody = await readOtlpBody(c);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof OtlpDecodeError) {\n\t\t\t\t\treturn c.json({ error: err.message }, err.status);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\tlet points: ReturnType<typeof decodeMetricsRequest>;\n\t\t\ttry {\n\t\t\t\tpoints = decodeMetricsRequest(body);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof OtlpDecodeError) {\n\t\t\t\t\treturn c.json({ error: err.message }, err.status);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\tlet rejected = 0;\n\t\t\tif (points.length > MAX_POINTS_PER_REQUEST) {\n\t\t\t\trejected = points.length - MAX_POINTS_PER_REQUEST;\n\t\t\t\tpoints = points.slice(0, MAX_POINTS_PER_REQUEST);\n\t\t\t}\n\n\t\t\tconst retentionHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst now = new Date();\n\t\t\tconst receivedAt = now.toISOString();\n\t\t\tconst expiresAt = new Date(\n\t\t\t\tnow.getTime() + retentionHours * 60 * 60 * 1000,\n\t\t\t).toISOString();\n\n\t\t\tconst store = new MetricsStore(sqlDbFor(c.env));\n\t\t\ttry {\n\t\t\t\tawait runtime.withChildSpan(\"metrics.ingest\", async (span) => {\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"metrics.points_received\",\n\t\t\t\t\t\tpoints.length + rejected,\n\t\t\t\t\t);\n\t\t\t\t\tspan.setAttribute(\"metrics.points_rejected\", rejected);\n\t\t\t\t\tspan.setAttribute(\"metrics.points_inserted\", points.length);\n\t\t\t\t\tspan.setAttribute(\"project.id\", projectId);\n\t\t\t\t\tawait store.ingestBatch({\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tpoints,\n\t\t\t\t\t\treceivedAt,\n\t\t\t\t\t\texpiresAt,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\truntime.logger.error(\"[/v1/metrics] storage error\", {\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t});\n\t\t\t\treturn otlpRetryableError(c, 503, \"Storage temporarily unavailable\");\n\t\t\t}\n\n\t\t\tif (rejected > 0) {\n\t\t\t\treturn metricsResponse(c, body.wireFormat, {\n\t\t\t\t\trejected,\n\t\t\t\t\terrorMessage: `Batch exceeded ${MAX_POINTS_PER_REQUEST}-point cap; ${rejected} point(s) dropped`,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn metricsResponse(c, body.wireFormat);\n\t\t});\n\t},\n};\n","import type { CollectorPlugin } from \"../framework/collector\";\nimport { sqlDbFor } from \"../lib/sql-db\";\n\n/**\n * Drives the in-dashboard Onboarding tab — returns counts of signal\n * types, used to decide which \"you need to wire X\" snippets to show\n * the user.\n *\n * Returns zeros for tables that don't yet exist (e.g. fresh DB) rather\n * than 500ing — onboarding has to work on day zero.\n */\nexport const onboardingRoutesPlugin: CollectorPlugin = {\n\tname: \"onboarding-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/onboarding/counts\", async (c) => {\n\t\t\tconst db = sqlDbFor(c.env);\n\t\t\tconst counts = await Promise.all([\n\t\t\t\tsafeCount(db, \"SELECT COUNT(*) AS n FROM telemetry_spans\"),\n\t\t\t\tsafeCount(db, \"SELECT COUNT(*) AS n FROM logs\"),\n\t\t\t\tsafeCount(db, \"SELECT COUNT(*) AS n FROM usage_events\"),\n\t\t\t\tsafeCount(db, \"SELECT COUNT(*) AS n FROM user_profiles\"),\n\t\t\t\tsafeCount(db, \"SELECT COUNT(*) AS n FROM ai_calls\"),\n\t\t\t\tsafeCount(db, \"SELECT COUNT(*) AS n FROM session_replay_metadata\"),\n\t\t\t\tsafeCount(\n\t\t\t\t\tdb,\n\t\t\t\t\t\"SELECT COUNT(*) AS n FROM telemetry_spans WHERE interaction_id IS NOT NULL\",\n\t\t\t\t),\n\t\t\t]);\n\n\t\t\treturn c.json({\n\t\t\t\tspans: counts[0],\n\t\t\t\tlogs: counts[1],\n\t\t\t\tusageEvents: counts[2],\n\t\t\t\tidentifiedUsers: counts[3],\n\t\t\t\taiCalls: counts[4],\n\t\t\t\treplayChunks: counts[5],\n\t\t\t\tspansWithInteraction: counts[6],\n\t\t\t});\n\t\t});\n\t},\n};\n\nasync function safeCount(\n\tdb: { prepare: (sql: string) => { first: <T>() => Promise<T | null> } },\n\tsql: string,\n): Promise<number> {\n\ttry {\n\t\tconst row = await db.prepare(sql).first<{ n: number }>();\n\t\treturn Number(row?.n ?? 0);\n\t} catch {\n\t\t// Table doesn't exist yet — fresh DB, no signals of this type.\n\t\treturn 0;\n\t}\n}\n","/** OTLP/HTTP trace receiver. Accepts JSON or protobuf, with gzip. */\n\nimport { getConfiguredRetentionHours } from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { toStoredSpans } from \"../lib/otlp\";\nimport { publishTail, spanToTailEvent } from \"../lib/tail-publisher\";\nimport {\n\tdecodeTraceRequest,\n\tOtlpDecodeError,\n\ttype ReadBodyResult,\n\treadOtlpBody,\n} from \"../otlp/decode\";\nimport { otlpRetryableError, traceResponse } from \"../otlp/response\";\nimport { getProjectId } from \"./_context\";\n\nconst MAX_SPANS_PER_REQUEST = 500;\n\nexport const otlpReceiverPlugin: CollectorPlugin = {\n\tname: \"otlp-http-receiver\",\n\tregister(app, runtime) {\n\t\tapp.post(\"/v1/traces\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst routeContext = runtime.createRouteContext(c.env, c);\n\n\t\t\tlet body: ReadBodyResult;\n\t\t\ttry {\n\t\t\t\tbody = await readOtlpBody(c);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof OtlpDecodeError) {\n\t\t\t\t\treturn c.json({ error: err.message }, err.status);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\tlet payload: ReturnType<typeof decodeTraceRequest>;\n\t\t\ttry {\n\t\t\t\tpayload = decodeTraceRequest(body);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof OtlpDecodeError) {\n\t\t\t\t\treturn c.json({ error: err.message }, err.status);\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\t// Count spans and truncate to cap, tracking rejected excess for the\n\t\t\t// partial_success envelope. We rebuild a trimmed payload rather than\n\t\t\t// touching the rest of the pipeline.\n\t\t\tlet total = 0;\n\t\t\tlet rejected = 0;\n\t\t\tconst trimmedResourceSpans = [];\n\t\t\tfor (const rs of payload.resourceSpans ?? []) {\n\t\t\t\tconst scopeSpans = [];\n\t\t\t\tfor (const ss of rs.scopeSpans ?? []) {\n\t\t\t\t\tconst spans = [];\n\t\t\t\t\tfor (const s of ss.spans ?? []) {\n\t\t\t\t\t\tif (total >= MAX_SPANS_PER_REQUEST) {\n\t\t\t\t\t\t\trejected++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tspans.push(s);\n\t\t\t\t\t\t\ttotal++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tscopeSpans.push({ ...ss, spans });\n\t\t\t\t}\n\t\t\t\ttrimmedResourceSpans.push({ ...rs, scopeSpans });\n\t\t\t}\n\n\t\t\tconst parsedSpans = toStoredSpans(\n\t\t\t\t{ resourceSpans: trimmedResourceSpans },\n\t\t\t\tprojectId,\n\t\t\t\trouteContext.now,\n\t\t\t\tgetConfiguredRetentionHours(c.env.RETENTION_HOURS),\n\t\t\t);\n\t\t\t// `toStoredSpans` silently drops spans with invalid trace/span IDs\n\t\t\t// (length mismatch, non-hex). Surface those to the caller via\n\t\t\t// partial_success rather than making them disappear.\n\t\t\tconst malformed = total - parsedSpans.length;\n\t\t\tconst totalRejected = rejected + malformed;\n\n\t\t\tconst spans = await runtime.runSpanProcessors(parsedSpans, routeContext);\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\ttry {\n\t\t\t\tawait runtime.withChildSpan(\"traces.ingest\", async (span) => {\n\t\t\t\t\tspan.setAttribute(\"traces.spans_received\", total);\n\t\t\t\t\tspan.setAttribute(\"traces.spans_rejected\", totalRejected);\n\t\t\t\t\tspan.setAttribute(\"traces.spans_inserted\", spans.length);\n\t\t\t\t\tspan.setAttribute(\"project.id\", projectId);\n\t\t\t\t\tconst result = await store.ingest(spans);\n\t\t\t\t\t// Distinct traces touched by this batch — the write-side\n\t\t\t\t\t// denominator for the gap/trace-detail read-rate ratio (Q3).\n\t\t\t\t\tspan.setAttribute(\"traces.trace_count\", result.traceCount);\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\truntime.logger.error(\"[/v1/traces] storage error\", {\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t});\n\t\t\t\treturn otlpRetryableError(c, 503, \"Storage temporarily unavailable\");\n\t\t\t}\n\n\t\t\tif (spans.length > 0 && c.env.TAIL_HUB) {\n\t\t\t\tconst events = spans.map(spanToTailEvent);\n\t\t\t\tc.executionCtx.waitUntil(publishTail(c.env, events));\n\t\t\t}\n\n\t\t\tif (totalRejected > 0) {\n\t\t\t\tconst parts: string[] = [];\n\t\t\t\tif (rejected > 0)\n\t\t\t\t\tparts.push(\n\t\t\t\t\t\t`${rejected} span(s) dropped over ${MAX_SPANS_PER_REQUEST}-span cap`,\n\t\t\t\t\t);\n\t\t\t\tif (malformed > 0)\n\t\t\t\t\tparts.push(\n\t\t\t\t\t\t`${malformed} span(s) rejected (invalid trace_id or span_id)`,\n\t\t\t\t\t);\n\t\t\t\treturn traceResponse(c, body.wireFormat, {\n\t\t\t\t\trejected: totalRejected,\n\t\t\t\t\terrorMessage: parts.join(\"; \"),\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn traceResponse(c, body.wireFormat);\n\t\t});\n\t},\n};\n","/**\n * OTLP wire format → StoredSpan conversion.\n * Union of all repos: A's advanced value conversion, hex validation,\n * service name fallback, safe BigInt handling.\n */\n\nimport type {\n\tJsonValue,\n\tOtlpAnyValue,\n\tOtlpKeyValue,\n\tOtlpResourceSpans,\n\tOtlpScopeSpans,\n\tOtlpSpan,\n\tOtlpTraceExportRequest,\n\tStoredSpan,\n} from \"@obsunified/types\";\nimport {\n\tDEFAULT_WINDOW_HOURS,\n\tgetConfiguredRetentionHours,\n} from \"@obsunified/types/constants\";\n\nconst EMPTY_ARRAY_JSON = \"[]\";\nconst EMPTY_OBJECT_JSON = \"{}\";\n\n/** Recursive OTLP value → JSON (from A: handles arrayValue, kvlistValue) */\nconst anyValueToJson = (value?: OtlpAnyValue): JsonValue => {\n\tif (!value) return null;\n\tif (typeof value.stringValue === \"string\") return value.stringValue;\n\tif (typeof value.boolValue === \"boolean\") return value.boolValue;\n\tif (typeof value.doubleValue === \"number\") return value.doubleValue;\n\tif (\n\t\ttypeof value.intValue === \"string\" ||\n\t\ttypeof value.intValue === \"number\"\n\t) {\n\t\tconst parsed = Number(value.intValue);\n\t\treturn Number.isFinite(parsed) ? parsed : String(value.intValue);\n\t}\n\tif (value.arrayValue?.values) {\n\t\treturn value.arrayValue.values.map((item) => anyValueToJson(item));\n\t}\n\tif (value.kvlistValue?.values) {\n\t\treturn keyValuesToRecord(value.kvlistValue.values);\n\t}\n\treturn null;\n};\n\nconst keyValuesToRecord = (\n\tvalues?: OtlpKeyValue[],\n): Record<string, JsonValue> => {\n\tif (!values?.length) return {};\n\treturn Object.fromEntries(\n\t\tvalues.map((entry) => [entry.key, anyValueToJson(entry.value)]),\n\t);\n};\n\n/** Validates hex string length (from A) */\nconst normalizeHex = (\n\tvalue: string | undefined,\n\tlength: number,\n): string | null => {\n\tif (!value) return null;\n\tconst normalized = value.trim().toLowerCase();\n\tif (!/^[0-9a-f]+$/i.test(normalized) || normalized.length !== length)\n\t\treturn null;\n\treturn normalized;\n};\n\n/** Safe BigInt nanosecond → millisecond duration (from A) */\nconst nanosToMs = (start?: string, end?: string): number => {\n\ttry {\n\t\tconst startNs = BigInt(start ?? 0);\n\t\tconst endNs = BigInt(end ?? 0);\n\t\tif (endNs < startNs) return 0;\n\t\treturn Number((endNs - startNs) / 1_000_000n);\n\t} catch {\n\t\treturn 0;\n\t}\n};\n\n/** Safe BigInt nanosecond → ISO string (from A) */\nconst nanosToIso = (value?: string, fallback?: Date): string => {\n\tif (!value) return fallback?.toISOString() ?? new Date().toISOString();\n\ttry {\n\t\tconst ns = BigInt(value);\n\t\tif (ns <= 0n) return fallback?.toISOString() ?? new Date().toISOString();\n\t\treturn new Date(Number(ns / 1_000_000n)).toISOString();\n\t} catch {\n\t\treturn fallback?.toISOString() ?? new Date().toISOString();\n\t}\n};\n\nconst serializeJson = (value: unknown, fallback: string): string => {\n\ttry {\n\t\treturn JSON.stringify(value ?? JSON.parse(fallback));\n\t} catch {\n\t\treturn fallback;\n\t}\n};\n\n/** Service name with fallback to server.address (from A) */\nconst getServiceName = (\n\tresourceAttributes: Record<string, JsonValue>,\n\tspanAttributes: Record<string, JsonValue>,\n): string | null => {\n\tconst resourceName = resourceAttributes[\"service.name\"];\n\tif (typeof resourceName === \"string\" && resourceName.trim())\n\t\treturn resourceName.trim();\n\tconst serverAddress = spanAttributes[\"server.address\"];\n\tif (typeof serverAddress === \"string\" && serverAddress.trim())\n\t\treturn serverAddress.trim();\n\treturn null;\n};\n\nconst scopeToStoredSpans = (\n\tresourceSpans: OtlpResourceSpans,\n\tscopeSpans: OtlpScopeSpans,\n\treceivedAt: Date,\n\tretentionHours: number,\n\tprojectId: string,\n): StoredSpan[] => {\n\tconst resourceAttributes = keyValuesToRecord(\n\t\tresourceSpans.resource?.attributes,\n\t);\n\tconst scopeName = scopeSpans.scope?.name ?? null;\n\tconst scopeVersion = scopeSpans.scope?.version ?? null;\n\n\treturn (scopeSpans.spans ?? []).flatMap((span: OtlpSpan): StoredSpan[] => {\n\t\tconst traceId = normalizeHex(span.traceId, 32);\n\t\tconst spanId = normalizeHex(span.spanId, 16);\n\t\tif (!traceId || !spanId) return [];\n\n\t\tconst attributes = keyValuesToRecord(span.attributes);\n\t\tconst serviceName = getServiceName(resourceAttributes, attributes);\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tprojectId,\n\t\t\t\ttraceId,\n\t\t\t\tspanId,\n\t\t\t\tparentSpanId: normalizeHex(span.parentSpanId, 16),\n\t\t\t\ttraceState: span.traceState ?? null,\n\t\t\t\tserviceName,\n\t\t\t\tscopeName,\n\t\t\t\tscopeVersion,\n\t\t\t\tspanName: span.name || \"unnamed-span\",\n\t\t\t\tspanKind: span.kind ?? 0,\n\t\t\t\tstatusCode: span.status?.code ?? 0,\n\t\t\t\tstatusMessage: span.status?.message ?? null,\n\t\t\t\tstartTime: nanosToIso(span.startTimeUnixNano, receivedAt),\n\t\t\t\tendTime: nanosToIso(span.endTimeUnixNano, receivedAt),\n\t\t\t\tdurationMs: nanosToMs(span.startTimeUnixNano, span.endTimeUnixNano),\n\t\t\t\tattributesJson: serializeJson(attributes, EMPTY_OBJECT_JSON),\n\t\t\t\tdroppedAttributesCount: span.droppedAttributesCount ?? 0,\n\t\t\t\tresourceAttributesJson: serializeJson(\n\t\t\t\t\tresourceAttributes,\n\t\t\t\t\tEMPTY_OBJECT_JSON,\n\t\t\t\t),\n\t\t\t\teventsJson: serializeJson(\n\t\t\t\t\t(span.events ?? []).map((event) => ({\n\t\t\t\t\t\tname: event.name,\n\t\t\t\t\t\ttimeUnixNano: event.timeUnixNano ?? null,\n\t\t\t\t\t\tattributes: keyValuesToRecord(event.attributes),\n\t\t\t\t\t\tdroppedAttributesCount: event.droppedAttributesCount ?? 0,\n\t\t\t\t\t})),\n\t\t\t\t\tEMPTY_ARRAY_JSON,\n\t\t\t\t),\n\t\t\t\tdroppedEventsCount: span.droppedEventsCount ?? 0,\n\t\t\t\tlinksJson: serializeJson(\n\t\t\t\t\t(span.links ?? []).map((link) => ({\n\t\t\t\t\t\ttraceId: normalizeHex(link.traceId, 32),\n\t\t\t\t\t\tspanId: normalizeHex(link.spanId, 16),\n\t\t\t\t\t\ttraceState: link.traceState ?? null,\n\t\t\t\t\t\tattributes: keyValuesToRecord(link.attributes),\n\t\t\t\t\t\tdroppedAttributesCount: link.droppedAttributesCount ?? 0,\n\t\t\t\t\t})),\n\t\t\t\t\tEMPTY_ARRAY_JSON,\n\t\t\t\t),\n\t\t\t\tdroppedLinksCount: span.droppedLinksCount ?? 0,\n\t\t\t\treceivedAt: receivedAt.toISOString(),\n\t\t\t\texpiresAt: retentionExpiry(receivedAt, retentionHours),\n\t\t\t},\n\t\t];\n\t});\n};\n\nexport const retentionExpiry = (\n\treceivedAt: Date,\n\tretentionHours = DEFAULT_WINDOW_HOURS,\n): string => {\n\tconst expiry = new Date(\n\t\treceivedAt.getTime() + retentionHours * 60 * 60 * 1000,\n\t);\n\treturn expiry.toISOString();\n};\n\nexport const toStoredSpans = (\n\tpayload: OtlpTraceExportRequest,\n\tprojectId: string,\n\treceivedAt = new Date(),\n\tretentionHours = getConfiguredRetentionHours(undefined),\n): StoredSpan[] =>\n\t(payload.resourceSpans ?? []).flatMap((resourceSpans) =>\n\t\t(resourceSpans.scopeSpans ?? []).flatMap((scopeSpans) =>\n\t\t\tscopeToStoredSpans(\n\t\t\t\tresourceSpans,\n\t\t\t\tscopeSpans,\n\t\t\t\treceivedAt,\n\t\t\t\tretentionHours,\n\t\t\t\tprojectId,\n\t\t\t),\n\t\t),\n\t);\n","import type { CollectorPlugin } from \"../framework/collector\";\nimport { MetricsStore } from \"../lib/metrics-store\";\nimport { dialectFor, sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport const platformRoutesPlugin: CollectorPlugin = {\n\tname: \"platform-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/platform/resources\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst db = sqlDbFor(c.env);\n\n\t\t\tconst countFor = async (table: string) => {\n\t\t\t\tconst row = await db\n\t\t\t\t\t.prepare(`SELECT COUNT(*) as c FROM ${table} WHERE project_id = ?`)\n\t\t\t\t\t.bind(projectId)\n\t\t\t\t\t.first<{ c: number }>();\n\t\t\t\treturn row?.c ?? 0;\n\t\t\t};\n\n\t\t\tconst eventsCount = await countFor(\"usage_events\");\n\t\t\tconst tracesCount = await countFor(\"telemetry_spans\");\n\t\t\tconst logsCount = await countFor(\"logs\");\n\t\t\tconst aiCallsCount = await countFor(\"ai_calls\");\n\n\t\t\tconst d1RowDensity = eventsCount + tracesCount + logsCount + aiCallsCount;\n\n\t\t\tlet r2StorageBytes = 0;\n\t\t\ttry {\n\t\t\t\tconst r2Info = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\"SELECT SUM(storage_bytes) as s FROM session_replay_metadata WHERE project_id = ?\",\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId)\n\t\t\t\t\t.first<{ s: number }>();\n\t\t\t\tr2StorageBytes = r2Info?.s ?? 0;\n\t\t\t} catch {\n\t\t\t\tr2StorageBytes = 0;\n\t\t\t}\n\n\t\t\treturn c.json({\n\t\t\t\tsuccess: true,\n\t\t\t\tresources: {\n\t\t\t\t\td1: {\n\t\t\t\t\t\trowDensity: d1RowDensity,\n\t\t\t\t\t\teventsCount,\n\t\t\t\t\t\ttracesCount,\n\t\t\t\t\t\tlogsCount,\n\t\t\t\t\t\taiCallsCount,\n\t\t\t\t\t},\n\t\t\t\t\tr2: {\n\t\t\t\t\t\tstorageBytes: r2StorageBytes,\n\t\t\t\t\t},\n\t\t\t\t\tworker: {\n\t\t\t\t\t\tcpuMs: 0,\n\t\t\t\t\t\tmemoryBytes: 0,\n\t\t\t\t\t\trequestsCount: 0,\n\t\t\t\t\t\tstatus: \"Needs Cloudflare Auth Token for live metrics\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t});\n\n\t\t// RFC 0009 Phase 5.2 — Linux hosts mode. Queries the latest\n\t\t// gauge points for the standard OTel host-metrics semconv\n\t\t// (system.cpu.utilization, system.memory.usage, etc.) grouped\n\t\t// by host.name. Returns an empty array if no `system.*` series\n\t\t// exist; the dashboard renders Cloudflare-only mode in that case.\n\t\tapp.get(\"/internal/platform/hosts\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst db = sqlDbFor(c.env);\n\t\t\tconst dialect = dialectFor(db);\n\n\t\t\tconst rows = await db\n\t\t\t\t.prepare(\n\t\t\t\t\t`WITH host_series AS (\n\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\ts.id AS series_id,\n\t\t\t\t\t\t\ts.name AS metric_name,\n\t\t\t\t\t\t\t${dialect.jsonText(\"s.resource_attrs_json\", \"$.host\\\\u002Ename\")} AS host_name,\n\t\t\t\t\t\t\ts.attributes_json\n\t\t\t\t\t\tFROM metric_series s\n\t\t\t\t\t\tWHERE s.project_id = ?\n\t\t\t\t\t\t\tAND s.name LIKE 'system.%'\n\t\t\t\t\t),\n\t\t\t\t\tlatest_points AS (\n\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\tp.series_id,\n\t\t\t\t\t\t\tp.value,\n\t\t\t\t\t\t\tp.received_at,\n\t\t\t\t\t\t\tROW_NUMBER() OVER (PARTITION BY p.series_id ORDER BY p.received_at DESC) AS rn\n\t\t\t\t\t\tFROM metric_point p\n\t\t\t\t\t\tWHERE p.project_id = ?\n\t\t\t\t\t\t\tAND p.received_at >= ${dialect.sinceMinutes(\"15\")}\n\t\t\t\t\t\t\tAND p.series_id IN (SELECT series_id FROM host_series)\n\t\t\t\t\t)\n\t\t\t\t\tSELECT\n\t\t\t\t\t\ths.host_name,\n\t\t\t\t\t\ths.metric_name,\n\t\t\t\t\t\tlp.value,\n\t\t\t\t\t\tlp.received_at\n\t\t\t\t\tFROM latest_points lp\n\t\t\t\t\tJOIN host_series hs ON hs.series_id = lp.series_id\n\t\t\t\t\tWHERE lp.rn = 1\n\t\t\t\t\tORDER BY hs.host_name, hs.metric_name`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, projectId)\n\t\t\t\t.all<{\n\t\t\t\t\thost_name: string | null;\n\t\t\t\t\tmetric_name: string;\n\t\t\t\t\tvalue: number | null;\n\t\t\t\t\treceived_at: string;\n\t\t\t\t}>();\n\n\t\t\t// Bucket per host — null host_name means resource_attrs_json\n\t\t\t// didn't carry host.name, group as <unknown>.\n\t\t\tconst byHost = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ host: string; metrics: Record<string, number>; updatedAt: string }\n\t\t\t>();\n\t\t\tfor (const row of rows.results) {\n\t\t\t\tconst host = row.host_name ?? \"<unknown>\";\n\t\t\t\tif (!byHost.has(host)) {\n\t\t\t\t\tbyHost.set(host, {\n\t\t\t\t\t\thost,\n\t\t\t\t\t\tmetrics: {},\n\t\t\t\t\t\tupdatedAt: row.received_at,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst entry = byHost.get(host);\n\t\t\t\tif (!entry) continue;\n\t\t\t\tif (row.value !== null) entry.metrics[row.metric_name] = row.value;\n\t\t\t\tif (row.received_at > entry.updatedAt)\n\t\t\t\t\tentry.updatedAt = row.received_at;\n\t\t\t}\n\n\t\t\treturn c.json({\n\t\t\t\tsuccess: true,\n\t\t\t\thosts: Array.from(byHost.values()),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/platform/metric-exemplars\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst limit = Math.max(\n\t\t\t\t1,\n\t\t\t\tMath.min(Number.parseInt(c.req.query(\"limit\") ?? \"20\", 10) || 20, 100),\n\t\t\t);\n\t\t\tconst metricPrefix = c.req.query(\"metric_prefix\") ?? \"system.\";\n\t\t\tconst serviceName = c.req.query(\"service\") ?? null;\n\t\t\tconst store = new MetricsStore(sqlDbFor(c.env));\n\t\t\tconst exemplars = await store.recentExemplars({\n\t\t\t\tprojectId,\n\t\t\t\tserviceName,\n\t\t\t\tmetricPrefix,\n\t\t\t\tlimit,\n\t\t\t});\n\t\t\treturn c.json({\n\t\t\t\tsuccess: true,\n\t\t\t\texemplars,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t});\n\t\t});\n\t},\n};\n","/**\n * RFC 0007 — pprof profiling receiver + read endpoints.\n *\n * POST /v1/profiles/pprof — accepts gzipped pprof blob\n * GET /internal/profiles/:id — proxies the blob back\n * GET /internal/profiles/:id?trace_id=… — Phase 4.5 server-side filter\n *\n * Phase 4 minimal scope: ingest-time pprof parsing is deferred. The\n * receiver writes the blob verbatim to R2 / filesystem and reads\n * trace_ids from an `x-obs-trace-ids` header (comma-separated). The\n * @obsunified/telemetry-sdk profile helper will stamp this; eBPF agents that\n * don't emit the header just don't populate `profile_trace_index`,\n * which means the trace waterfall's 🔥 badge won't fire for those\n * profiles. Aggregate views still work.\n *\n * A follow-on commit can add server-side pprof parsing using a Buf-\n * generated schema or pprof-format. The endpoint shape doesn't change\n * when that lands.\n */\n\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport {\n\tdecodePprofBlob,\n\textractTraceIdsFromProfile,\n\tfilterPprofByTraceId,\n\tsummarizeProfileFrames,\n} from \"../lib/parse-pprof\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nconst PROFILE_TYPES = new Set([\n\t\"cpu\",\n\t\"heap\",\n\t\"wall\",\n\t\"block\",\n\t\"mutex\",\n\t\"goroutine\",\n\t\"offcpu\",\n]);\n\n// Time-sortable random id for profile blob keys. Not a real ULID — no\n// monotonic clock and we use modulo over crypto bytes for the random\n// suffix — but the format (10-char time prefix + 16-char random) gives\n// us lexicographic ordering by ingest time, which is what the R2 path\n// layout assumes. The \"ULID\" name was misleading.\nconst profileId = (): string => {\n\tconst ENCODING = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\tlet timeStr = \"\";\n\tlet n = Date.now();\n\tfor (let i = 0; i < 10; i++) {\n\t\ttimeStr = ENCODING[n % 32] + timeStr;\n\t\tn = Math.floor(n / 32);\n\t}\n\tconst bytes = new Uint8Array(16);\n\tcrypto.getRandomValues(bytes);\n\tlet randStr = \"\";\n\tfor (let i = 0; i < 16; i++) randStr += ENCODING[bytes[i] % 32];\n\treturn timeStr + randStr;\n};\n\n// Parse a non-negative integer from an untrusted source. Returns the\n// fallback when the input is missing, malformed, NaN, negative, or\n// non-finite. parseInt happily returns NaN for \"foo\" and that NaN was\n// being written verbatim to D1 as \"Invalid Date\" / NaN before this\n// landed.\nconst parseNonNegInt = (\n\tvalue: string | null | undefined,\n\tfallback: number,\n): number => {\n\tif (value == null) return fallback;\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed < 0) return fallback;\n\treturn parsed;\n};\n\nconst TRACE_ID_RE = /^[0-9a-f]{16,32}$/i;\n\nconst parseTraceIdsHeader = (header: string | null | undefined): string[] => {\n\tif (!header) return [];\n\treturn header\n\t\t.split(\",\")\n\t\t.map((s) => s.trim().toLowerCase())\n\t\t.filter((s) => TRACE_ID_RE.test(s));\n};\n\nexport const profileRoutesPlugin: CollectorPlugin = {\n\tname: \"profile-routes\",\n\tregister(app, runtime) {\n\t\t// ── POST /v1/profiles/pprof ─────────────────────────────────────\n\t\tapp.post(\"/v1/profiles/pprof\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\n\t\t\tconst profileType = (\n\t\t\t\tc.req.header(\"x-obs-profile-type\") || \"cpu\"\n\t\t\t).toLowerCase();\n\t\t\tif (!PROFILE_TYPES.has(profileType)) {\n\t\t\t\treturn c.json({ error: `unknown profile type: ${profileType}` }, 400);\n\t\t\t}\n\t\t\tconst serviceName = c.req.header(\"x-obs-service\") || null;\n\t\t\t// RFC 0007 acceptance #2 — ingest-time pprof parsing.\n\t\t\t// The x-obs-trace-ids header is honored as a pre-extraction\n\t\t\t// fast path (clients that already iterated the profile\n\t\t\t// avoid us re-parsing on the worker), but we no longer\n\t\t\t// require it: when absent, parse the blob and read sample\n\t\t\t// labels directly. Closes the Phase 4 header-driven\n\t\t\t// shortcut.\n\t\t\tconst headerTraceIds = parseTraceIdsHeader(\n\t\t\t\tc.req.header(\"x-obs-trace-ids\"),\n\t\t\t);\n\n\t\t\tconst body = await c.req.arrayBuffer();\n\t\t\tif (body.byteLength === 0) {\n\t\t\t\treturn c.json({ error: \"empty body\" }, 400);\n\t\t\t}\n\t\t\tif (body.byteLength > 4 * 1024 * 1024) {\n\t\t\t\treturn c.json({ error: \"blob too large (max 4 MB)\" }, 413);\n\t\t\t}\n\n\t\t\tlet traceIds: string[];\n\t\t\tlet parsedSampleCount: number | null = null;\n\t\t\tif (headerTraceIds.length > 0) {\n\t\t\t\t// Client pre-extracted trace ids — accept verbatim without\n\t\t\t\t// re-parsing. Decode failures on the blob itself are reported\n\t\t\t\t// at read time.\n\t\t\t\ttraceIds = headerTraceIds;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst profile = await decodePprofBlob(body);\n\t\t\t\t\ttraceIds = extractTraceIdsFromProfile(profile);\n\t\t\t\t\tparsedSampleCount = profile.samples.length;\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// No client-side trace_id header and the blob doesn't\n\t\t\t\t\t// decode. Return 422 so the agent learns its emit path\n\t\t\t\t\t// is broken — silently accepting corrupt blobs into R2\n\t\t\t\t\t// makes ingest debugging impossible.\n\t\t\t\t\truntime.logger.warn(\n\t\t\t\t\t\t\"[profile-receiver] pprof parse failed (no header fallback)\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\t\t\tsize: body.byteLength,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror: \"pprof decode failed\",\n\t\t\t\t\t\t\thint: \"Set x-obs-trace-ids header to bypass server-side parsing.\",\n\t\t\t\t\t\t\tdetails: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t422,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst id = profileId();\n\t\t\tconst now = new Date();\n\t\t\tconst nowStr = now.toISOString();\n\t\t\tconst dateKey = nowStr.slice(0, 10);\n\t\t\tconst objectKey = `profiles/${projectId}/${dateKey}/${id}.pprof.gz`;\n\n\t\t\t// Storage dispatch — R2 first, no fallback yet (Workers-only).\n\t\t\tif (!c.env.PROFILES_BUCKET) {\n\t\t\t\truntime.logger.error(\"PROFILES_BUCKET binding is missing\", {\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t});\n\t\t\t\treturn c.json({ error: \"Profile storage not configured\" }, 500);\n\t\t\t}\n\t\t\tawait c.env.PROFILES_BUCKET.put(objectKey, body, {\n\t\t\t\thttpMetadata: { contentType: \"application/octet-stream\" },\n\t\t\t});\n\n\t\t\t// 72-hour default, clamped to a sane upper bound so a misconfigured\n\t\t\t// env var can't push expires_at thousands of years out.\n\t\t\tconst RETENTION_MAX_HOURS = 24 * 90;\n\t\t\tconst retentionHours = Math.min(\n\t\t\t\tparseNonNegInt(c.env.RETENTION_HOURS, 72),\n\t\t\t\tRETENTION_MAX_HOURS,\n\t\t\t);\n\t\t\tconst expiresAt = new Date(\n\t\t\t\tnow.getTime() + retentionHours * 60 * 60 * 1000,\n\t\t\t).toISOString();\n\n\t\t\t// Duration / window are optional headers; default to \"now\".\n\t\t\t// Untrusted client input — parseNonNegInt drops NaN / negative.\n\t\t\tconst durationMs = parseNonNegInt(c.req.header(\"x-obs-duration-ms\"), 0);\n\t\t\tconst startTs = c.req.header(\"x-obs-start-ts\") || nowStr;\n\n\t\t\tconst db = sqlDbFor(c.env);\n\t\t\tawait db\n\t\t\t\t.prepare(\n\t\t\t\t\t`INSERT INTO profile_blobs (\n\t\t\t\t\t\tid, project_id, service_name, profile_type,\n\t\t\t\t\t\tstart_ts, end_ts, duration_ms, blob_size_bytes, blob_url,\n\t\t\t\t\t\tsample_count, agent, resource_attrs_json,\n\t\t\t\t\t\treceived_at, expires_at\n\t\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t\t)\n\t\t\t\t.bind(\n\t\t\t\t\tid,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tserviceName,\n\t\t\t\t\tprofileType,\n\t\t\t\t\tstartTs,\n\t\t\t\t\tnowStr,\n\t\t\t\t\tdurationMs,\n\t\t\t\t\tbody.byteLength,\n\t\t\t\t\tobjectKey,\n\t\t\t\t\tparsedSampleCount,\n\t\t\t\t\tc.req.header(\"x-obs-agent\") || \"unknown\",\n\t\t\t\t\tnull,\n\t\t\t\t\tnowStr,\n\t\t\t\t\texpiresAt,\n\t\t\t\t)\n\t\t\t\t.run();\n\n\t\t\tif (traceIds.length > 0) {\n\t\t\t\tconst stmt = db.prepare(\n\t\t\t\t\t`INSERT OR IGNORE INTO profile_trace_index (profile_id, trace_id, project_id) VALUES (?, ?, ?)`,\n\t\t\t\t);\n\t\t\t\tconst batch = traceIds.map((tid) => stmt.bind(id, tid, projectId));\n\t\t\t\tawait db.batch(batch);\n\t\t\t}\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\taccepted: true,\n\t\t\t\t\tprofileId: id,\n\t\t\t\t\ttraceIdsIndexed: traceIds.length,\n\t\t\t\t},\n\t\t\t\t202,\n\t\t\t);\n\t\t});\n\n\t\t// ── GET /internal/profiles/:id ─────────────────────────────────\n\t\tapp.get(\"/internal/profiles/:id\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tconst db = sqlDbFor(c.env);\n\n\t\t\tconst meta = await db\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT id, service_name, profile_type, start_ts, end_ts,\n\t\t\t\t\t\t\tduration_ms, blob_size_bytes, blob_url, sample_count,\n\t\t\t\t\t\t\tagent, received_at, expires_at\n\t\t\t\t\t FROM profile_blobs\n\t\t\t\t\t WHERE project_id = ? AND id = ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, id)\n\t\t\t\t.first<{\n\t\t\t\t\tid: string;\n\t\t\t\t\tservice_name: string | null;\n\t\t\t\t\tprofile_type: string;\n\t\t\t\t\tstart_ts: string;\n\t\t\t\t\tend_ts: string;\n\t\t\t\t\tduration_ms: number;\n\t\t\t\t\tblob_size_bytes: number;\n\t\t\t\t\tblob_url: string;\n\t\t\t\t\tsample_count: number | null;\n\t\t\t\t\tagent: string | null;\n\t\t\t\t\treceived_at: string;\n\t\t\t\t\texpires_at: string;\n\t\t\t\t}>();\n\n\t\t\tif (!meta) {\n\t\t\t\treturn c.json({ error: \"Not found\" }, 404);\n\t\t\t}\n\n\t\t\t// Optional: download the blob inline. Default returns metadata\n\t\t\t// only; the dashboard's flame graph viewer will fetch the blob\n\t\t\t// separately via ?blob=true.\n\t\t\tif (c.req.query(\"blob\") === \"true\") {\n\t\t\t\tif (!c.env.PROFILES_BUCKET) {\n\t\t\t\t\treturn c.json({ error: \"Profile storage not configured\" }, 500);\n\t\t\t\t}\n\t\t\t\tconst obj = await c.env.PROFILES_BUCKET.get(meta.blob_url);\n\t\t\t\tif (!obj) {\n\t\t\t\t\treturn c.json({ error: \"Blob not found in storage\" }, 404);\n\t\t\t\t}\n\t\t\t\t// RFC 0007 acceptance #6 — server-side pre-filter.\n\t\t\t\t// When `?trace_id=X` is set alongside `?blob=true`, parse\n\t\t\t\t// the pprof, retain only samples with the matching label,\n\t\t\t\t// and re-emit a smaller blob. Saves bandwidth on large\n\t\t\t\t// JVM profiles where 99% of samples don't belong to the\n\t\t\t\t// trace the user is drilling into.\n\t\t\t\tconst filterTraceId = c.req.query(\"trace_id\");\n\t\t\t\tif (filterTraceId) {\n\t\t\t\t\tconst raw = new Uint8Array(await obj.arrayBuffer());\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst profile = await decodePprofBlob(raw);\n\t\t\t\t\t\tconst filtered = await filterPprofByTraceId(profile, filterTraceId);\n\t\t\t\t\t\treturn new Response(filtered as unknown as BodyInit, {\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/octet-stream\",\n\t\t\t\t\t\t\t\t\"Content-Encoding\": \"gzip\",\n\t\t\t\t\t\t\t\t\"Content-Disposition\": `attachment; filename=\"${id}-trace-${filterTraceId.slice(0, 8)}.pprof.gz\"`,\n\t\t\t\t\t\t\t\t// Surface the size shrink so the UI can show savings.\n\t\t\t\t\t\t\t\t\"X-Obs-Filter-Original-Bytes\": String(raw.byteLength),\n\t\t\t\t\t\t\t\t\"X-Obs-Filter-Filtered-Bytes\": String(filtered.byteLength),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\truntime.logger.warn(\n\t\t\t\t\t\t\t\"[profile-routes] filter failed; returning unfiltered blob\",\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tprofile_id: id,\n\t\t\t\t\t\t\t\ttrace_id: filterTraceId,\n\t\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// Fall through to unfiltered.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn new Response(obj.body, {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"application/octet-stream\",\n\t\t\t\t\t\t\"Content-Disposition\": `attachment; filename=\"${id}.pprof.gz\"`,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Metadata + trace_id list (no blob). The full server-side\n\t\t\t// pprof filter runs above when `?blob=true&trace_id=…`.\n\t\t\tconst trace_id = c.req.query(\"trace_id\");\n\t\t\tconst traces = await db\n\t\t\t\t.prepare(\n\t\t\t\t\ttrace_id\n\t\t\t\t\t\t? `SELECT trace_id FROM profile_trace_index WHERE profile_id = ? AND project_id = ? AND trace_id = ?`\n\t\t\t\t\t\t: `SELECT trace_id FROM profile_trace_index WHERE profile_id = ? AND project_id = ? LIMIT 1000`,\n\t\t\t\t)\n\t\t\t\t.bind(\n\t\t\t\t\t...(trace_id ? [meta.id, projectId, trace_id] : [meta.id, projectId]),\n\t\t\t\t)\n\t\t\t\t.all<{ trace_id: string }>();\n\t\t\tconst includeFrames = c.req.query(\"frames\") === \"true\";\n\t\t\tlet frames: ReturnType<typeof summarizeProfileFrames> | undefined;\n\t\t\tlet framesError: string | null = null;\n\t\t\tif (includeFrames) {\n\t\t\t\tif (!c.env.PROFILES_BUCKET) {\n\t\t\t\t\tframesError = \"Profile storage not configured\";\n\t\t\t\t} else {\n\t\t\t\t\tconst obj = await c.env.PROFILES_BUCKET.get(meta.blob_url);\n\t\t\t\t\tif (!obj) {\n\t\t\t\t\t\tframesError = \"Blob not found in storage\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst raw = new Uint8Array(await obj.arrayBuffer());\n\t\t\t\t\t\t\tconst profile = await decodePprofBlob(raw);\n\t\t\t\t\t\t\tframes = summarizeProfileFrames(profile, {\n\t\t\t\t\t\t\t\tlimit: parseNonNegInt(c.req.query(\"frame_limit\"), 50),\n\t\t\t\t\t\t\t\ttraceIdFilter: trace_id ?? null,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tframesError = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\t\truntime.logger.warn(\"[profile-routes] frame summary failed\", {\n\t\t\t\t\t\t\t\tprofile_id: id,\n\t\t\t\t\t\t\t\ttrace_id: trace_id ?? null,\n\t\t\t\t\t\t\t\terror: framesError,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn c.json({\n\t\t\t\tprofile: {\n\t\t\t\t\tid: meta.id,\n\t\t\t\t\tserviceName: meta.service_name,\n\t\t\t\t\tprofileType: meta.profile_type,\n\t\t\t\t\tstartTs: meta.start_ts,\n\t\t\t\t\tendTs: meta.end_ts,\n\t\t\t\t\tdurationMs: meta.duration_ms,\n\t\t\t\t\tblobSizeBytes: meta.blob_size_bytes,\n\t\t\t\t\tsampleCount: meta.sample_count,\n\t\t\t\t\tagent: meta.agent,\n\t\t\t\t\treceivedAt: meta.received_at,\n\t\t\t\t\texpiresAt: meta.expires_at,\n\t\t\t\t},\n\t\t\t\ttraceIds: traces.results.map((r) => r.trace_id),\n\t\t\t\ttraceIdRequested: trace_id ?? null,\n\t\t\t\tframes: frames ?? [],\n\t\t\t\tframesError,\n\t\t\t});\n\t\t});\n\n\t\t// ── GET /internal/profiles ─────────────────────────────────────\n\t\t// Recent profiles, optionally scoped by trace_id (powers the\n\t\t// 🔥 badge on the trace waterfall).\n\t\tapp.get(\"/internal/profiles\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst traceId = c.req.query(\"trace_id\");\n\t\t\tconst serviceName = c.req.query(\"service\");\n\t\t\tconst db = sqlDbFor(c.env);\n\n\t\t\tif (traceId) {\n\t\t\t\tconst rows = await db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT b.id, b.service_name, b.profile_type, b.start_ts, b.end_ts,\n\t\t\t\t\t\t\t\tb.duration_ms, b.blob_size_bytes, b.agent\n\t\t\t\t\t\t FROM profile_trace_index i\n\t\t\t\t\t\t JOIN profile_blobs b ON b.id = i.profile_id\n\t\t\t\t\t\t WHERE i.project_id = ? AND i.trace_id = ?\n\t\t\t\t\t\t ORDER BY b.end_ts DESC\n\t\t\t\t\t\t LIMIT 50`,\n\t\t\t\t\t)\n\t\t\t\t\t.bind(projectId, traceId)\n\t\t\t\t\t.all<{\n\t\t\t\t\t\tid: string;\n\t\t\t\t\t\tservice_name: string | null;\n\t\t\t\t\t\tprofile_type: string;\n\t\t\t\t\t\tstart_ts: string;\n\t\t\t\t\t\tend_ts: string;\n\t\t\t\t\t\tduration_ms: number;\n\t\t\t\t\t\tblob_size_bytes: number;\n\t\t\t\t\t\tagent: string | null;\n\t\t\t\t\t}>();\n\t\t\t\treturn c.json({\n\t\t\t\t\tprofiles: rows.results.map((r) => ({\n\t\t\t\t\t\tid: r.id,\n\t\t\t\t\t\tserviceName: r.service_name,\n\t\t\t\t\t\tprofileType: r.profile_type,\n\t\t\t\t\t\tstartTs: r.start_ts,\n\t\t\t\t\t\tendTs: r.end_ts,\n\t\t\t\t\t\tdurationMs: r.duration_ms,\n\t\t\t\t\t\tblobSizeBytes: r.blob_size_bytes,\n\t\t\t\t\t\tagent: r.agent,\n\t\t\t\t\t})),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet sql = `SELECT id, service_name, profile_type, start_ts, end_ts,\n\t\t\t\t\t\t duration_ms, blob_size_bytes, agent\n\t\t\t\tFROM profile_blobs WHERE project_id = ?`;\n\t\t\tconst binds: unknown[] = [projectId];\n\t\t\tif (serviceName) {\n\t\t\t\tsql += ` AND service_name = ?`;\n\t\t\t\tbinds.push(serviceName);\n\t\t\t}\n\t\t\tsql += ` ORDER BY end_ts DESC LIMIT 50`;\n\n\t\t\tconst rows = await db\n\t\t\t\t.prepare(sql)\n\t\t\t\t.bind(...binds)\n\t\t\t\t.all<{\n\t\t\t\t\tid: string;\n\t\t\t\t\tservice_name: string | null;\n\t\t\t\t\tprofile_type: string;\n\t\t\t\t\tstart_ts: string;\n\t\t\t\t\tend_ts: string;\n\t\t\t\t\tduration_ms: number;\n\t\t\t\t\tblob_size_bytes: number;\n\t\t\t\t\tagent: string | null;\n\t\t\t\t}>();\n\n\t\t\treturn c.json({\n\t\t\t\tprofiles: rows.results.map((r) => ({\n\t\t\t\t\tid: r.id,\n\t\t\t\t\tserviceName: r.service_name,\n\t\t\t\t\tprofileType: r.profile_type,\n\t\t\t\t\tstartTs: r.start_ts,\n\t\t\t\t\tendTs: r.end_ts,\n\t\t\t\t\tdurationMs: r.duration_ms,\n\t\t\t\t\tblobSizeBytes: r.blob_size_bytes,\n\t\t\t\t\tagent: r.agent,\n\t\t\t\t})),\n\t\t\t});\n\t\t});\n\t},\n};\n","import type { CollectorPlugin } from \"../framework/collector\";\nimport { ProjectsStore } from \"../lib/projects-store\";\nimport { sqlDbFor } from \"../lib/sql-db\";\n\nexport const projectsRoutesPlugin: CollectorPlugin = {\n\tname: \"projects-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/projects\", async (c) => {\n\t\t\tconst store = new ProjectsStore(sqlDbFor(c.env));\n\t\t\tawait store.ensureDefaultProject();\n\t\t\tconst projects = await store.listProjects();\n\t\t\treturn c.json({ projects });\n\t\t});\n\n\t\tapp.post(\"/internal/projects\", async (c) => {\n\t\t\tconst body = await c.req\n\t\t\t\t.json<{ name?: string; slug?: string }>()\n\t\t\t\t.catch(() => ({ name: undefined, slug: undefined }));\n\t\t\tif (!body.name || !body.slug) {\n\t\t\t\treturn c.json({ error: \"name and slug are required\" }, 400);\n\t\t\t}\n\t\t\tconst store = new ProjectsStore(sqlDbFor(c.env));\n\t\t\ttry {\n\t\t\t\tconst project = await store.createProject({\n\t\t\t\t\tname: body.name,\n\t\t\t\t\tslug: body.slug,\n\t\t\t\t});\n\t\t\t\treturn c.json({ project }, 201);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\t// UNIQUE constraint failures from D1 surface as \"D1_ERROR\" with a cause.\n\t\t\t\tif (\n\t\t\t\t\tmessage.includes(\"UNIQUE\") ||\n\t\t\t\t\tmessage.toLowerCase().includes(\"slug\")\n\t\t\t\t) {\n\t\t\t\t\treturn c.json({ error: \"Slug already in use or invalid\" }, 409);\n\t\t\t\t}\n\t\t\t\treturn c.json({ error: message }, 400);\n\t\t\t}\n\t\t});\n\n\t\tapp.patch(\"/internal/projects/:id\", async (c) => {\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tconst body = await c.req\n\t\t\t\t.json<{ name?: string; payloadCaptureEnabled?: boolean }>()\n\t\t\t\t.catch(() => ({\n\t\t\t\t\tname: undefined,\n\t\t\t\t\tpayloadCaptureEnabled: undefined,\n\t\t\t\t}));\n\t\t\tconst store = new ProjectsStore(sqlDbFor(c.env));\n\t\t\tconst project = await store.updateProject(id, {\n\t\t\t\tname: body.name,\n\t\t\t\tpayloadCaptureEnabled: body.payloadCaptureEnabled,\n\t\t\t});\n\t\t\tif (!project) return c.json({ error: \"Project not found\" }, 404);\n\t\t\treturn c.json({ project });\n\t\t});\n\n\t\tapp.get(\"/internal/projects/:id/keys\", async (c) => {\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tconst store = new ProjectsStore(sqlDbFor(c.env));\n\t\t\tconst project = await store.getProject(id);\n\t\t\tif (!project) return c.json({ error: \"Project not found\" }, 404);\n\t\t\tconst keys = await store.listKeys(id);\n\t\t\treturn c.json({ keys });\n\t\t});\n\n\t\tapp.post(\"/internal/projects/:id/keys\", async (c) => {\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tconst body = await c.req\n\t\t\t\t.json<{ name?: string }>()\n\t\t\t\t.catch(() => ({ name: undefined }));\n\t\t\tconst store = new ProjectsStore(sqlDbFor(c.env));\n\t\t\ttry {\n\t\t\t\tconst result = await store.createKey(id, body.name ?? \"unnamed\");\n\t\t\t\treturn c.json(result, 201);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\treturn c.json({ error: message }, 400);\n\t\t\t}\n\t\t});\n\n\t\tapp.delete(\"/internal/projects/:id/keys/:keyId\", async (c) => {\n\t\t\tconst keyId = c.req.param(\"keyId\");\n\t\t\tconst store = new ProjectsStore(sqlDbFor(c.env));\n\t\t\tconst revoked = await store.revokeKey(keyId);\n\t\t\tif (!revoked)\n\t\t\t\treturn c.json({ error: \"Key not found or already revoked\" }, 404);\n\t\t\treturn c.json({ success: true });\n\t\t});\n\t},\n};\n","/** Union: A's env-based retention + D's search param + D's export endpoint */\nimport {\n\tDEFAULT_WINDOW_HOURS,\n\tgetConfiguredRetentionHours,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { getProjectId } from \"./_context\";\n\nexport const queryRoutesPlugin: CollectorPlugin = {\n\tname: \"query-routes\",\n\tregister(app, runtime) {\n\t\tapp.get(\"/internal/telemetry/overview\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst maxHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst hours = Math.min(\n\t\t\t\tmaxHours,\n\t\t\t\tMath.max(\n\t\t\t\t\t1,\n\t\t\t\t\tNumber.parseInt(\n\t\t\t\t\t\tc.req.query(\"hours\") || String(DEFAULT_WINDOW_HOURS),\n\t\t\t\t\t\t10,\n\t\t\t\t\t) || DEFAULT_WINDOW_HOURS,\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst service = c.req.query(\"service\") || undefined;\n\t\t\tconst statusParam = c.req.query(\"status\");\n\t\t\tconst status =\n\t\t\t\tstatusParam === \"ok\" || statusParam === \"error\" ? statusParam : \"all\";\n\t\t\tconst limit = Number.parseInt(c.req.query(\"limit\") || \"30\", 10) || 30;\n\t\t\tconst search = c.req.query(\"q\")?.trim() || undefined;\n\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\tconst overview = await store.getOverview({\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tservice,\n\t\t\t\tstatus,\n\t\t\t\tlimit,\n\t\t\t\tsearch,\n\t\t\t});\n\t\t\treturn c.json({\n\t\t\t\t...overview,\n\t\t\t\tplugins: runtime.getRegisteredPluginNames(),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/telemetry/service-map\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst maxHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst hours = Math.min(\n\t\t\t\tmaxHours,\n\t\t\t\tMath.max(\n\t\t\t\t\t1,\n\t\t\t\t\tNumber.parseInt(\n\t\t\t\t\t\tc.req.query(\"hours\") || String(DEFAULT_WINDOW_HOURS),\n\t\t\t\t\t\t10,\n\t\t\t\t\t) || DEFAULT_WINDOW_HOURS,\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\t// RFC 0009 — `?source=sdk|ebpf|all` toggles which spans\n\t\t\t// contribute. Default is `all` so existing dashboards see\n\t\t\t// every edge. The dashboard's service-map view exposes the\n\t\t\t// filter as a UI toggle.\n\t\t\tconst sourceParam = c.req.query(\"source\");\n\t\t\tconst source: \"all\" | \"sdk\" | \"ebpf\" =\n\t\t\t\tsourceParam === \"sdk\" || sourceParam === \"ebpf\" ? sourceParam : \"all\";\n\t\t\tconst map = await store.getServiceMap({ projectId, hours, source });\n\t\t\treturn c.json({\n\t\t\t\t...map,\n\t\t\t\twindowHours: hours,\n\t\t\t\tsource,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/telemetry/services/:service/operations\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst maxHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst hours = Math.min(\n\t\t\t\tmaxHours,\n\t\t\t\tMath.max(\n\t\t\t\t\t1,\n\t\t\t\t\tNumber.parseInt(\n\t\t\t\t\t\tc.req.query(\"hours\") || String(DEFAULT_WINDOW_HOURS),\n\t\t\t\t\t\t10,\n\t\t\t\t\t) || DEFAULT_WINDOW_HOURS,\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst service = c.req.param(\"service\");\n\t\t\tif (!service) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Bad Request\", message: \"service is required\" },\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\tconst result = await store.getServiceOperations({\n\t\t\t\tprojectId,\n\t\t\t\tservice,\n\t\t\t\thours,\n\t\t\t});\n\t\t\treturn c.json({\n\t\t\t\t...result,\n\t\t\t\twindowHours: hours,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/telemetry/traces/:traceId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst traceId = c.req.param(\"traceId\");\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\t// A `query.trace_detail` span = a trace was viewed. Counting these\n\t\t\t// against `traces.ingest`'s trace_count gives the read/write ratio\n\t\t\t// (Q3); span duration captures end-to-end read latency (Q1).\n\t\t\tconst detail = await runtime.withChildSpan(\n\t\t\t\t\"query.trace_detail\",\n\t\t\t\tasync (span) => {\n\t\t\t\t\tspan.setAttribute(\"project.id\", projectId);\n\t\t\t\t\tspan.setAttribute(\"trace.id\", traceId);\n\t\t\t\t\tconst result = await store.getTraceDetail(traceId, projectId);\n\t\t\t\t\tspan.setAttribute(\"query.found\", result !== null);\n\t\t\t\t\tspan.setAttribute(\"query.span_count\", result?.spans.length ?? 0);\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!detail)\n\t\t\t\treturn c.json({ error: \"Not Found\", message: \"Trace not found\" }, 404);\n\t\t\treturn c.json({ ...detail, plugins: runtime.getRegisteredPluginNames() });\n\t\t});\n\n\t\tapp.get(\"/internal/telemetry/traces/:traceId/gaps\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst traceId = c.req.param(\"traceId\");\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\t// `query.trace_gaps` span duration is the read-time gap computation\n\t\t\t// cost end-to-end (project-scoped span SELECT + compute) — the\n\t\t\t// DB-inclusive half of Q1 that the pure-compute benchmark omits.\n\t\t\tconst gaps = await runtime.withChildSpan(\n\t\t\t\t\"query.trace_gaps\",\n\t\t\t\tasync (span) => {\n\t\t\t\t\tspan.setAttribute(\"project.id\", projectId);\n\t\t\t\t\tspan.setAttribute(\"trace.id\", traceId);\n\t\t\t\t\tconst result = await store.getTraceGaps(traceId, projectId);\n\t\t\t\t\tspan.setAttribute(\"query.found\", result !== null);\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"query.blindspot_count\",\n\t\t\t\t\t\tresult?.blindspots.length ?? 0,\n\t\t\t\t\t);\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!gaps)\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Trace gaps not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\treturn c.json(gaps);\n\t\t});\n\n\t\tapp.get(\n\t\t\t\"/internal/telemetry/instrumentation-gaps/calibration\",\n\t\t\tasync (c) => {\n\t\t\t\tconst projectId = getProjectId(c);\n\t\t\t\tconst maxHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\t\tconst hours = Math.min(\n\t\t\t\t\tmaxHours,\n\t\t\t\t\tMath.max(1, Number.parseInt(c.req.query(\"hours\") || \"72\", 10) || 72),\n\t\t\t\t);\n\t\t\t\tconst limit =\n\t\t\t\t\tNumber.parseInt(c.req.query(\"limit\") || \"5000\", 10) || 5000;\n\t\t\t\tconst store = runtime.createStore(c.env);\n\t\t\t\tconst calibration = await store.calibrateTraceGaps({\n\t\t\t\t\tprojectId,\n\t\t\t\t\thours,\n\t\t\t\t\tlimit,\n\t\t\t\t});\n\t\t\t\treturn c.json(calibration);\n\t\t\t},\n\t\t);\n\n\t\t// NDJSON export (from D)\n\t\tapp.get(\"/internal/telemetry/export\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst maxHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst hours = Math.min(\n\t\t\t\tmaxHours,\n\t\t\t\tMath.max(\n\t\t\t\t\t1,\n\t\t\t\t\tNumber.parseInt(\n\t\t\t\t\t\tc.req.query(\"hours\") || String(DEFAULT_WINDOW_HOURS),\n\t\t\t\t\t\t10,\n\t\t\t\t\t) || DEFAULT_WINDOW_HOURS,\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst service = c.req.query(\"service\") || undefined;\n\t\t\tconst statusParam = c.req.query(\"status\");\n\t\t\tconst status =\n\t\t\t\tstatusParam === \"ok\" || statusParam === \"error\" ? statusParam : \"all\";\n\t\t\tconst search = c.req.query(\"q\")?.trim() || undefined;\n\n\t\t\tconst store = runtime.createStore(c.env);\n\t\t\tconst ndjson = await store.getExportRows({\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tservice,\n\t\t\t\tstatus,\n\t\t\t\tsearch,\n\t\t\t});\n\n\t\t\treturn new Response(ndjson, {\n\t\t\t\theaders: {\n\t\t\t\t\t\"content-type\": \"application/x-ndjson; charset=utf-8\",\n\t\t\t\t\t\"content-disposition\": `attachment; filename=\"telemetry-export-${new Date().toISOString().slice(0, 19).replace(/:/g, \"-\")}.jsonl\"`,\n\t\t\t\t},\n\t\t\t});\n\t\t});\n\t},\n};\n","import type { JsonValue, StoredSpan } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { parseJsonValue } from \"../lib/json\";\n\nconst DEFAULT_REDACT_FIELDS = [\n\t\"authorization\",\n\t\"cookie\",\n\t\"set-cookie\",\n\t\"password\",\n\t\"passwd\",\n\t\"secret\",\n\t\"token\",\n\t\"api-key\",\n\t\"x-api-key\",\n\t\"email\",\n\t\"enduser.id\",\n];\n\nconst REDACTED_VALUE = \"[REDACTED]\";\n\nconst toRedactionFieldSet = (extraFields?: string): Set<string> => {\n\tconst customFields = extraFields\n\t\t? extraFields\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((field) => field.trim().toLowerCase())\n\t\t\t\t.filter(Boolean)\n\t\t: [];\n\treturn new Set([...DEFAULT_REDACT_FIELDS, ...customFields]);\n};\n\nconst shouldRedactKey = (key: string, fields: Set<string>): boolean => {\n\tconst normalizedKey = key.toLowerCase();\n\tif (fields.has(normalizedKey)) return true;\n\tfor (const field of fields) {\n\t\tif (normalizedKey.endsWith(field)) return true;\n\t}\n\treturn false;\n};\n\nconst redactJsonValue = (\n\tvalue: JsonValue,\n\tfields: Set<string>,\n): { nextValue: JsonValue; redactionCount: number } => {\n\tif (Array.isArray(value)) {\n\t\tlet redactionCount = 0;\n\t\tconst nextValue = value.map((item) => {\n\t\t\tconst result = redactJsonValue(item, fields);\n\t\t\tredactionCount += result.redactionCount;\n\t\t\treturn result.nextValue;\n\t\t});\n\t\treturn { nextValue, redactionCount };\n\t}\n\n\tif (value && typeof value === \"object\") {\n\t\tlet redactionCount = 0;\n\t\tconst nextEntries = Object.entries(value).map(([key, nestedValue]) => {\n\t\t\tif (shouldRedactKey(key, fields)) {\n\t\t\t\tredactionCount += 1;\n\t\t\t\treturn [key, REDACTED_VALUE] as const;\n\t\t\t}\n\t\t\tconst result = redactJsonValue(nestedValue, fields);\n\t\t\tredactionCount += result.redactionCount;\n\t\t\treturn [key, result.nextValue] as const;\n\t\t});\n\t\treturn { nextValue: Object.fromEntries(nextEntries), redactionCount };\n\t}\n\n\treturn { nextValue: value, redactionCount: 0 };\n};\n\nconst redactJsonString = (\n\tvalue: string,\n\tfields: Set<string>,\n): { serialized: string; redactionCount: number } => {\n\tconst parsed = parseJsonValue(value);\n\tconst redacted = redactJsonValue(parsed, fields);\n\treturn {\n\t\tserialized: JSON.stringify(redacted.nextValue),\n\t\tredactionCount: redacted.redactionCount,\n\t};\n};\n\nexport const redactionProcessorPlugin: CollectorPlugin = {\n\tname: \"redaction-processor\",\n\tregister(_app, runtime) {\n\t\truntime.addSpanProcessor({\n\t\t\tname: \"redaction-processor\",\n\t\t\tprocess(spans, context) {\n\t\t\t\tconst redactFields = toRedactionFieldSet(\n\t\t\t\t\tcontext.env.TELEMETRY_REDACT_FIELDS,\n\t\t\t\t);\n\t\t\t\treturn spans.map((span): StoredSpan => {\n\t\t\t\t\tconst attributes = redactJsonString(\n\t\t\t\t\t\tspan.attributesJson,\n\t\t\t\t\t\tredactFields,\n\t\t\t\t\t);\n\t\t\t\t\tconst resourceAttributes = redactJsonString(\n\t\t\t\t\t\tspan.resourceAttributesJson,\n\t\t\t\t\t\tredactFields,\n\t\t\t\t\t);\n\t\t\t\t\tconst events = redactJsonString(span.eventsJson, redactFields);\n\t\t\t\t\tconst links = redactJsonString(span.linksJson, redactFields);\n\n\t\t\t\t\tconst totalRedactions =\n\t\t\t\t\t\tattributes.redactionCount +\n\t\t\t\t\t\tresourceAttributes.redactionCount +\n\t\t\t\t\t\tevents.redactionCount +\n\t\t\t\t\t\tlinks.redactionCount;\n\n\t\t\t\t\tconst normalizedAttributes = parseJsonValue(attributes.serialized);\n\t\t\t\t\tconst nextAttributes =\n\t\t\t\t\t\tnormalizedAttributes &&\n\t\t\t\t\t\ttypeof normalizedAttributes === \"object\" &&\n\t\t\t\t\t\t!Array.isArray(normalizedAttributes)\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...normalizedAttributes,\n\t\t\t\t\t\t\t\t\t\"collector.redaction.count\": totalRedactions,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: normalizedAttributes;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...span,\n\t\t\t\t\t\tattributesJson: JSON.stringify(nextAttributes),\n\t\t\t\t\t\tresourceAttributesJson: resourceAttributes.serialized,\n\t\t\t\t\t\teventsJson: events.serialized,\n\t\t\t\t\t\tlinksJson: links.serialized,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t},\n};\n","import type { ReplayChunkInput } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport const replayReceiverPlugin: CollectorPlugin = {\n\tname: \"replay-receiver\",\n\tregister(app, runtime) {\n\t\tapp.post(\"/v1/replays\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tlet payload: ReplayChunkInput;\n\t\t\ttry {\n\t\t\t\tpayload = await c.req.json<ReplayChunkInput>();\n\t\t\t} catch {\n\t\t\t\treturn c.json({ error: \"Invalid JSON body\" }, 400);\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!isSafeId(payload.sessionId) ||\n\t\t\t\t(payload.visitorId !== undefined && !isSafeId(payload.visitorId)) ||\n\t\t\t\t!Number.isInteger(payload.sequenceNumber) ||\n\t\t\t\tpayload.sequenceNumber < 0 ||\n\t\t\t\t!Array.isArray(payload.events)\n\t\t\t) {\n\t\t\t\treturn c.json({ error: \"Invalid replay payload\" }, 400);\n\t\t\t}\n\t\t\tconst now = new Date().toISOString();\n\n\t\t\tconst timestamp = Date.now();\n\t\t\tconst objectKey = `replays/${projectId}/${payload.sessionId}/${timestamp}-${payload.sequenceNumber}.json`;\n\n\t\t\tif (!c.env.REPLAYS_BUCKET) {\n\t\t\t\truntime.logger.error(\"REPLAYS_BUCKET binding is missing\", {\n\t\t\t\t\tproject_id: projectId,\n\t\t\t\t});\n\t\t\t\treturn c.json({ error: \"Replay storage not configured\" }, 500);\n\t\t\t}\n\n\t\t\tconst payloadString = JSON.stringify(payload.events);\n\t\t\tconst chunkBytes = new TextEncoder().encode(payloadString).length;\n\n\t\t\tawait c.env.REPLAYS_BUCKET.put(objectKey, payloadString, {\n\t\t\t\thttpMetadata: { contentType: \"application/json\" },\n\t\t\t});\n\n\t\t\tawait sqlDbFor(c.env)\n\t\t\t\t.prepare(\n\t\t\t\t\t`INSERT INTO session_replay_metadata (project_id, session_id, visitor_id, first_chunk_at, last_chunk_at, chunk_count, events_count, storage_bytes)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(session_id) DO UPDATE SET\n last_chunk_at = excluded.last_chunk_at,\n chunk_count = session_replay_metadata.chunk_count + 1,\n events_count = session_replay_metadata.events_count + excluded.events_count,\n storage_bytes = session_replay_metadata.storage_bytes + excluded.storage_bytes\n `,\n\t\t\t\t)\n\t\t\t\t.bind(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tpayload.sessionId,\n\t\t\t\t\tpayload.visitorId,\n\t\t\t\t\tnow,\n\t\t\t\t\tnow,\n\t\t\t\t\t1,\n\t\t\t\t\tpayload.events.length,\n\t\t\t\t\tchunkBytes,\n\t\t\t\t)\n\t\t\t\t.run();\n\n\t\t\treturn c.json({ success: true, chunkKey: objectKey });\n\t\t});\n\t},\n};\n\nfunction isSafeId(value: unknown): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= 160 &&\n\t\t/^[A-Za-z0-9._:-]+$/.test(value) &&\n\t\t!value.includes(\"..\")\n\t);\n}\n","import type { CollectorPlugin } from \"../framework/collector\";\nimport { getProjectId } from \"./_context\";\n\n/**\n * Live tail SSE endpoint. The dashboard opens an EventSource here; the\n * collector proxies to the TailHub Durable Object which holds the open\n * stream and fans out broadcasts from ingest.\n */\nexport const tailRoutesPlugin: CollectorPlugin = {\n\tname: \"tail-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/telemetry/tail\", (c) => {\n\t\t\tconst hub = c.env.TAIL_HUB;\n\t\t\tif (!hub) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Live tail not configured (TAIL_HUB binding missing)\" },\n\t\t\t\t\t503,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Project scope must come from auth middleware, never from the client\n\t\t\t// URL. The dashboard live-tail client uses a fetch stream so it can\n\t\t\t// send the same X-Project-Id header as the rest of the API.\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tif (!/^[A-Za-z0-9_-]{1,128}$/.test(projectId)) {\n\t\t\t\treturn c.json({ error: \"invalid projectId\" }, 400);\n\t\t\t}\n\t\t\tconst kinds = c.req.query(\"kinds\") || \"span,log\";\n\n\t\t\tconst id = hub.idFromName(\"singleton\");\n\t\t\tconst stub = hub.get(id);\n\n\t\t\tconst subscribeUrl = new URL(\"https://hub/subscribe\");\n\t\t\tsubscribeUrl.searchParams.set(\"projectId\", projectId);\n\t\t\tsubscribeUrl.searchParams.set(\"kinds\", kinds);\n\n\t\t\treturn stub.fetch(subscribeUrl.toString(), {\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tsignal: c.req.raw.signal,\n\t\t\t});\n\t\t});\n\t},\n};\n","import type { CollectorPlugin } from \"../framework/collector\";\nimport { IdentityIndex } from \"../lib/identity-index\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport interface TimelineEvent {\n\tt: string;\n\tkind: \"span\" | \"log\" | \"usage\";\n\tid: string;\n\ttitle: string;\n\tsubtitle?: string;\n\tseverity?: \"info\" | \"warn\" | \"error\";\n\tdurationMs?: number;\n\t/**\n\t * RFC 0004 — click-scoped correlation key. Present on every event that\n\t * was emitted while an interaction was active. The {@link TimelineResponse.groups}\n\t * field groups events by this id so the dashboard can render\n\t * \"click → traces it caused\" without a second round-trip.\n\t */\n\tinteractionId?: string;\n\tpayload: Record<string, unknown>;\n}\n\nexport interface TimelineReplayMetadata {\n\tfirstChunkAt: string;\n\tlastChunkAt: string;\n\tchunkCount: number;\n\teventsCount: number;\n}\n\n/**\n * RFC 0004 — a click and the traces it caused, bundled. The dashboard's\n * session timeline collapses an interaction's events under its\n * originating click; this is the precomputed shape the dashboard reads.\n */\nexport interface TimelineGroup {\n\tinteractionId: string;\n\t/** The originating user-originated event (usage event, kind=\"interaction\" or \"page_view\"). */\n\tclickEvent: TimelineEvent | null;\n\t/** Root spans (parent_span_id IS NULL) carrying this interaction_id. */\n\tcausedTraces: Array<{\n\t\ttraceId: string;\n\t\trootSpanId: string;\n\t\trootSpanName: string;\n\t\tserviceName: string | null;\n\t\tdurationMs: number;\n\t\tstatus: \"ok\" | \"error\";\n\t}>;\n\t/** Logs + non-click usage events sharing this interaction_id. */\n\trelatedEvents: TimelineEvent[];\n}\n\nexport interface TimelineResponse {\n\tsessionId: string;\n\tfirstSeen: string | null;\n\tlastSeen: string | null;\n\tcounts: {\n\t\tspans: number;\n\t\tlogs: number;\n\t\tusage: number;\n\t};\n\treplay: TimelineReplayMetadata | null;\n\tevents: TimelineEvent[];\n\t/**\n\t * RFC 0004 — derived view keyed by interaction_id. Empty object when\n\t * no events in the session carry one (sessions ingested before\n\t * @obsunified/analytics-sdk's autoCorrelate landed). Events without an\n\t * interaction_id appear in `events` but never under `groups`.\n\t */\n\tgroups: Record<string, TimelineGroup>;\n\ttimestamp: string;\n}\n\nconst severityFromStatus = (code: number): \"info\" | \"warn\" | \"error\" =>\n\tcode === 2 ? \"error\" : \"info\";\n\nconst severityFromLog = (\n\tseverity: string | null,\n): \"info\" | \"warn\" | \"error\" => {\n\tif (severity === \"ERROR\" || severity === \"FATAL\") return \"error\";\n\tif (severity === \"WARN\") return \"warn\";\n\treturn \"info\";\n};\n\nconst severityFromUsage = (\n\ttype: string,\n\tseverity: string | null,\n): \"info\" | \"warn\" | \"error\" => {\n\tif (type === \"frontend_error\" || severity === \"error\") return \"error\";\n\tif (severity === \"warning\") return \"warn\";\n\treturn \"info\";\n};\n\nexport const timelineRoutesPlugin: CollectorPlugin = {\n\tname: \"timeline-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/timeline/:sessionId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst sessionId = c.req.param(\"sessionId\");\n\t\t\tif (!sessionId) {\n\t\t\t\treturn c.json({ error: \"sessionId required\" }, 400);\n\t\t\t}\n\n\t\t\t// RFC 0008 — go through the IdentityIndex helper rather than\n\t\t\t// duplicating per-signal SQL. Same indexed lookup, single\n\t\t\t// ownership of the cross-signal join shape.\n\t\t\tconst index = new IdentityIndex(sqlDbFor(c.env));\n\t\t\tconst manifest = await index.bySession(projectId, sessionId);\n\n\t\t\tconst events: TimelineEvent[] = [];\n\t\t\t// Stash root-span shapes for grouping. Indexed by trace_id since a\n\t\t\t// single click can fan out into multiple service-level traces (rare\n\t\t\t// for a normal browser → single backend, but defensible).\n\t\t\tconst rootSpansByInteraction = new Map<\n\t\t\t\tstring,\n\t\t\t\tTimelineGroup[\"causedTraces\"]\n\t\t\t>();\n\n\t\t\tfor (const s of manifest.spans) {\n\t\t\t\tconst interactionId = s.interactionId ?? undefined;\n\t\t\t\tevents.push({\n\t\t\t\t\tt: s.startTime,\n\t\t\t\t\tkind: \"span\",\n\t\t\t\t\tid: `${s.traceId}:${s.spanId}`,\n\t\t\t\t\ttitle: `${s.serviceName ?? \"unknown\"} · ${s.spanName}`,\n\t\t\t\t\tsubtitle: s.statusMessage ?? undefined,\n\t\t\t\t\tseverity: severityFromStatus(s.statusCode),\n\t\t\t\t\tdurationMs: s.durationMs,\n\t\t\t\t\tinteractionId,\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\ttraceId: s.traceId,\n\t\t\t\t\t\tspanId: s.spanId,\n\t\t\t\t\t\tparentSpanId: s.parentSpanId,\n\t\t\t\t\t\tstatusCode: s.statusCode,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\t// Only root spans count as \"the trace this click caused\" — child\n\t\t\t\t// spans are part of the same trace tree, so collecting them\n\t\t\t\t// would double-count.\n\t\t\t\tif (interactionId && s.parentSpanId === null) {\n\t\t\t\t\tconst list = rootSpansByInteraction.get(interactionId) ?? [];\n\t\t\t\t\tlist.push({\n\t\t\t\t\t\ttraceId: s.traceId,\n\t\t\t\t\t\trootSpanId: s.spanId,\n\t\t\t\t\t\trootSpanName: s.spanName,\n\t\t\t\t\t\tserviceName: s.serviceName,\n\t\t\t\t\t\tdurationMs: s.durationMs,\n\t\t\t\t\t\tstatus: s.statusCode === 2 ? \"error\" : \"ok\",\n\t\t\t\t\t});\n\t\t\t\t\trootSpansByInteraction.set(interactionId, list);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const l of manifest.logs) {\n\t\t\t\tevents.push({\n\t\t\t\t\tt: l.occurredAt,\n\t\t\t\t\tkind: \"log\",\n\t\t\t\t\tid: l.logId,\n\t\t\t\t\ttitle: l.message.slice(0, 160),\n\t\t\t\t\tsubtitle:\n\t\t\t\t\t\t`${l.serviceName ?? \"\"}${l.loggerName ? ` · ${l.loggerName}` : \"\"}`.trim(),\n\t\t\t\t\tseverity: severityFromLog(l.severity),\n\t\t\t\t\tinteractionId: l.interactionId ?? undefined,\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\tseverity: l.severity,\n\t\t\t\t\t\ttraceId: l.traceId,\n\t\t\t\t\t\tspanId: l.spanId,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (const u of manifest.usageEvents) {\n\t\t\t\tevents.push({\n\t\t\t\t\tt: u.occurredAt,\n\t\t\t\t\tkind: \"usage\",\n\t\t\t\t\tid: u.eventId,\n\t\t\t\t\ttitle: `${u.eventType}${u.eventName && u.eventName !== u.eventType ? ` · ${u.eventName}` : \"\"}`,\n\t\t\t\t\tsubtitle: u.pagePath ?? undefined,\n\t\t\t\t\tseverity: severityFromUsage(u.eventType, u.severity),\n\t\t\t\t\tinteractionId: u.interactionId ?? undefined,\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\teventType: u.eventType,\n\t\t\t\t\t\teventName: u.eventName,\n\t\t\t\t\t\tpagePath: u.pagePath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tevents.sort((a, b) => a.t.localeCompare(b.t));\n\n\t\t\t// RFC 0004 — derive groups keyed by interaction_id.\n\t\t\tconst groups: Record<string, TimelineGroup> = {};\n\t\t\tfor (const event of events) {\n\t\t\t\tif (!event.interactionId) continue;\n\t\t\t\tlet group = groups[event.interactionId];\n\t\t\t\tif (!group) {\n\t\t\t\t\tgroup = {\n\t\t\t\t\t\tinteractionId: event.interactionId,\n\t\t\t\t\t\tclickEvent: null,\n\t\t\t\t\t\tcausedTraces: rootSpansByInteraction.get(event.interactionId) ?? [],\n\t\t\t\t\t\trelatedEvents: [],\n\t\t\t\t\t};\n\t\t\t\t\tgroups[event.interactionId] = group;\n\t\t\t\t}\n\t\t\t\t// Treat the first usage event with this id as the click that\n\t\t\t\t// originated it. Usage events are minted at addEventListener\n\t\t\t\t// fire time so they're timestamp-prior to any fetch the\n\t\t\t\t// handler kicks off.\n\t\t\t\tif (event.kind === \"usage\" && group.clickEvent === null) {\n\t\t\t\t\tgroup.clickEvent = event;\n\t\t\t\t} else {\n\t\t\t\t\tgroup.relatedEvents.push(event);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst firstSeen = events[0]?.t ?? null;\n\t\t\tconst lastSeen = events[events.length - 1]?.t ?? null;\n\n\t\t\tconst response: TimelineResponse = {\n\t\t\t\tsessionId,\n\t\t\t\tfirstSeen,\n\t\t\t\tlastSeen,\n\t\t\t\tcounts: {\n\t\t\t\t\tspans: manifest.spans.length,\n\t\t\t\t\tlogs: manifest.logs.length,\n\t\t\t\t\tusage: manifest.usageEvents.length,\n\t\t\t\t},\n\t\t\t\treplay: manifest.replay\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tfirstChunkAt: manifest.replay.firstChunkAt,\n\t\t\t\t\t\t\tlastChunkAt: manifest.replay.lastChunkAt,\n\t\t\t\t\t\t\tchunkCount: manifest.replay.chunkCount,\n\t\t\t\t\t\t\teventsCount: manifest.replay.eventsCount,\n\t\t\t\t\t\t}\n\t\t\t\t\t: null,\n\t\t\t\tevents,\n\t\t\t\tgroups,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t};\n\n\t\t\treturn c.json(response);\n\t\t});\n\t},\n};\n","import type {\n\tCollectorPlugin,\n\tUsageEventProcessorPlugin,\n} from \"../framework/collector\";\nimport { parseUserAgent } from \"../lib/ua-parser\";\n\nconst processor: UsageEventProcessorPlugin = {\n\tname: \"ua-enrichment\",\n\tprocess(events) {\n\t\treturn events.map((event) => {\n\t\t\tconst parsed = parseUserAgent(event.userAgent);\n\t\t\treturn {\n\t\t\t\t...event,\n\t\t\t\tbrowser: parsed.browser,\n\t\t\t\tos: parsed.os,\n\t\t\t\tdeviceType: parsed.deviceType,\n\t\t\t};\n\t\t});\n\t},\n};\n\nexport const uaEnrichmentPlugin: CollectorPlugin = {\n\tname: \"ua-enrichment\",\n\tregister(_app, runtime) {\n\t\truntime.addUsageEventProcessor(processor);\n\t},\n};\n","import type { JsonValue, UsageEventRecord } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { parseJsonRecord } from \"../lib/json\";\n\nconst normalizePathSegment = (segment: string): string => {\n\tif (!segment) return segment;\n\tif (/^\\d+$/.test(segment)) return \":id\";\n\tif (/^[0-9a-f]{16,}$/i.test(segment)) return \":id\";\n\treturn segment;\n};\n\nconst normalizePath = (path: string | null): string | null => {\n\tif (!path) return null;\n\tconst [pathname] = path.split(\"?\");\n\tconst segments = pathname\n\t\t.split(\"/\")\n\t\t.map(normalizePathSegment)\n\t\t.filter((segment, index) => !(index === 0 && segment === \"\"));\n\treturn `/${segments.join(\"/\")}`.replace(/\\/{2,}/g, \"/\");\n};\n\nexport const usageNormalizationPlugin: CollectorPlugin = {\n\tname: \"usage-normalization\",\n\tregister(_app, runtime) {\n\t\truntime.addUsageEventProcessor({\n\t\t\tname: \"usage-normalization\",\n\t\t\tprocess(events) {\n\t\t\t\treturn events.map((event): UsageEventRecord => {\n\t\t\t\t\tconst context = parseJsonRecord(event.contextJson);\n\t\t\t\t\tconst normalizedPath = normalizePath(event.pagePath);\n\t\t\t\t\tconst nextContext: Record<string, JsonValue> = {\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\"collector.is_admin_path\": Boolean(\n\t\t\t\t\t\t\tnormalizedPath?.startsWith(\"/admin\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t};\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...event,\n\t\t\t\t\t\tpagePath: normalizedPath,\n\t\t\t\t\t\tcontextJson: JSON.stringify(nextContext),\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t},\n};\n","import type { JsonValue, UsageEventRecord } from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { parseJsonValue } from \"../lib/json\";\n\nconst REDACTED_VALUE = \"[REDACTED]\";\nconst DEFAULT_REDACT_FIELDS = [\n\t\"email\",\n\t\"token\",\n\t\"password\",\n\t\"authorization\",\n\t\"cookie\",\n];\n\nconst shouldRedactKey = (key: string): boolean => {\n\tconst normalized = key.toLowerCase();\n\treturn DEFAULT_REDACT_FIELDS.some(\n\t\t(field) => normalized === field || normalized.endsWith(field),\n\t);\n};\n\nconst redactJson = (value: JsonValue): JsonValue => {\n\tif (Array.isArray(value)) return value.map(redactJson);\n\tif (value && typeof value === \"object\") {\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(value).map(([key, nestedValue]) =>\n\t\t\t\tshouldRedactKey(key)\n\t\t\t\t\t? [key, REDACTED_VALUE]\n\t\t\t\t\t: [key, redactJson(nestedValue)],\n\t\t\t),\n\t\t);\n\t}\n\treturn value;\n};\n\nexport const usagePrivacyPlugin: CollectorPlugin = {\n\tname: \"usage-privacy\",\n\tregister(_app, runtime) {\n\t\truntime.addUsageEventProcessor({\n\t\t\tname: \"usage-privacy\",\n\t\t\tprocess(events) {\n\t\t\t\treturn events.map(\n\t\t\t\t\t(event): UsageEventRecord => ({\n\t\t\t\t\t\t...event,\n\t\t\t\t\t\tcontextJson: JSON.stringify(\n\t\t\t\t\t\t\tredactJson(parseJsonValue(event.contextJson)),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tpropertiesJson: JSON.stringify(\n\t\t\t\t\t\t\tredactJson(parseJsonValue(event.propertiesJson)),\n\t\t\t\t\t\t),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t},\n};\n","import {\n\tDEFAULT_WINDOW_HOURS,\n\tgetConfiguredRetentionHours,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { getProjectId } from \"./_context\";\n\nexport const usageQueryRoutesPlugin: CollectorPlugin = {\n\tname: \"usage-query-routes\",\n\tregister(app, runtime) {\n\t\tapp.get(\"/internal/usage/overview\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst maxHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst hours = Math.min(\n\t\t\t\tmaxHours,\n\t\t\t\tMath.max(\n\t\t\t\t\t1,\n\t\t\t\t\tNumber.parseInt(\n\t\t\t\t\t\tc.req.query(\"hours\") || String(DEFAULT_WINDOW_HOURS),\n\t\t\t\t\t\t10,\n\t\t\t\t\t) || DEFAULT_WINDOW_HOURS,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tconst store = runtime.createUsageStore(c.env);\n\t\t\tconst overview = await store.getOverview({\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tpath: c.req.query(\"path\") || undefined,\n\t\t\t\tincludeAdmin: c.req.query(\"includeAdmin\") === \"true\",\n\t\t\t});\n\t\t\treturn c.json({\n\t\t\t\t...overview,\n\t\t\t\tplugins: runtime.getRegisteredPluginNames(),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/usage/sessions\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst maxHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst hours = Math.min(\n\t\t\t\tmaxHours,\n\t\t\t\tMath.max(\n\t\t\t\t\t1,\n\t\t\t\t\tNumber.parseInt(\n\t\t\t\t\t\tc.req.query(\"hours\") || String(DEFAULT_WINDOW_HOURS),\n\t\t\t\t\t\t10,\n\t\t\t\t\t) || DEFAULT_WINDOW_HOURS,\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst filterParam = c.req.query(\"filter\");\n\t\t\tconst filter: \"all\" | \"ended_in_error\" | \"dropoff\" | \"slow\" =\n\t\t\t\tfilterParam === \"ended_in_error\" ||\n\t\t\t\tfilterParam === \"dropoff\" ||\n\t\t\t\tfilterParam === \"slow\"\n\t\t\t\t\t? filterParam\n\t\t\t\t\t: \"all\";\n\t\t\tconst slowMs = Math.max(\n\t\t\t\t100,\n\t\t\t\tNumber.parseInt(c.req.query(\"slowMs\") || \"3000\", 10) || 3000,\n\t\t\t);\n\t\t\tconst limit = Math.max(\n\t\t\t\t1,\n\t\t\t\tMath.min(\n\t\t\t\t\t500,\n\t\t\t\t\tNumber.parseInt(c.req.query(\"limit\") || \"100\", 10) || 100,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tconst store = runtime.createUsageStore(c.env);\n\t\t\tconst result = await store.listSessions({\n\t\t\t\tprojectId,\n\t\t\t\thours,\n\t\t\t\tfilter,\n\t\t\t\tslowMs,\n\t\t\t\tlimit,\n\t\t\t});\n\t\t\treturn c.json({\n\t\t\t\t...result,\n\t\t\t\tfilter,\n\t\t\t\thours,\n\t\t\t\tslowMs,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t});\n\t\t});\n\n\t\tapp.get(\"/internal/usage/sessions/:sessionId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst store = runtime.createUsageStore(c.env);\n\t\t\tconst detail = await store.getSessionDetail(\n\t\t\t\tc.req.param(\"sessionId\"),\n\t\t\t\tprojectId,\n\t\t\t);\n\t\t\tif (!detail)\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: \"Not Found\", message: \"Session not found\" },\n\t\t\t\t\t404,\n\t\t\t\t);\n\t\t\treturn c.json({ ...detail, plugins: runtime.getRegisteredPluginNames() });\n\t\t});\n\t},\n};\n","/** Union: A's JSON error handling, event limit, env-based retention. P/D's dynamic CORS. */\n\nimport type {\n\tUsageEventInput,\n\tUsageEventPayload,\n\tUsageEventRecord,\n} from \"@obsunified/types\";\nimport {\n\tDEFAULT_WINDOW_HOURS,\n\tgetConfiguredRetentionHours,\n} from \"@obsunified/types/constants\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { retentionExpiry } from \"../lib/otlp\";\nimport { getProjectId } from \"./_context\";\n\nconst sanitizeIsoTimestamp = (value?: string): string => {\n\tif (!value) return new Date().toISOString();\n\tconst parsed = new Date(value);\n\treturn Number.isNaN(parsed.getTime())\n\t\t? new Date().toISOString()\n\t\t: parsed.toISOString();\n};\n\nconst toUsageRecord = (\n\tinput: UsageEventInput,\n\tuserAgent: string | null,\n\tcountry: string | null,\n\treceivedAt: Date,\n\tprojectId: string,\n\tretentionHours?: number,\n): UsageEventRecord => ({\n\tprojectId,\n\teventId: crypto.randomUUID(),\n\tsessionId: input.sessionId,\n\tvisitorId: input.visitorId,\n\teventType: input.type,\n\teventName: input.name,\n\tpagePath: input.path || null,\n\tpageTitle: input.title || null,\n\treferrer: input.referrer || null,\n\tseverity: input.severity || \"info\",\n\tsource: \"web\",\n\tcontextJson: JSON.stringify(input.context || {}),\n\tpropertiesJson: JSON.stringify(input.properties || {}),\n\tuserAgent,\n\toccurredAt: sanitizeIsoTimestamp(input.occurredAt),\n\treceivedAt: receivedAt.toISOString(),\n\texpiresAt: retentionExpiry(receivedAt, retentionHours),\n\tcountry,\n\tbrowser: null,\n\tos: null,\n\tdeviceType: null,\n\tisBot: false,\n\tutmSource: null,\n\tutmMedium: null,\n\tutmCampaign: null,\n\t// RFC 0004 — opaque correlation id from the analytics SDK; null when\n\t// the event was emitted outside any user interaction.\n\tinteractionId: input.interactionId || null,\n});\n\nexport const usageReceiverPlugin: CollectorPlugin = {\n\tname: \"usage-receiver\",\n\tregister(app, runtime) {\n\t\t// CORS is handled by the framework-level /v1/* middleware.\n\t\t// No per-route CORS needed here.\n\n\t\tapp.post(\"/v1/usage\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tlet payload: UsageEventPayload;\n\t\t\ttry {\n\t\t\t\tpayload = await c.req.json<UsageEventPayload>();\n\t\t\t} catch {\n\t\t\t\treturn c.json({ error: \"Invalid JSON body\" }, 400);\n\t\t\t}\n\t\t\tconst rawEvents = payload.events || [];\n\t\t\tif (rawEvents.length > 200) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: `Too many events: ${rawEvents.length} (max 200)` },\n\t\t\t\t\t413,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst validInputs = rawEvents.filter((event): event is UsageEventInput =>\n\t\t\t\tBoolean(\n\t\t\t\t\tevent?.type && event?.name && event?.sessionId && event?.visitorId,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tconst receivedAt = new Date();\n\t\t\tconst retentionHours = getConfiguredRetentionHours(c.env.RETENTION_HOURS);\n\t\t\tconst country = c.req.header(\"X-Client-Country\") || null;\n\t\t\tconst records = validInputs.map((event) =>\n\t\t\t\ttoUsageRecord(\n\t\t\t\t\tevent,\n\t\t\t\t\tc.req.header(\"User-Agent\") || null,\n\t\t\t\t\tcountry,\n\t\t\t\t\treceivedAt,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tretentionHours,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tconst processed = await runtime.runUsageEventProcessors(\n\t\t\t\trecords,\n\t\t\t\truntime.createRouteContext(c.env, c),\n\t\t\t);\n\t\t\tconst store = runtime.createUsageStore(c.env);\n\t\t\tconst result = await runtime.withChildSpan(\n\t\t\t\t\"usage.ingest\",\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst r = await store.ingest(processed);\n\t\t\t\t\tspan.setAttribute(\"usage.events_received\", rawEvents.length);\n\t\t\t\t\tspan.setAttribute(\"usage.events_valid\", validInputs.length);\n\t\t\t\t\tspan.setAttribute(\"usage.events_inserted\", r.inserted);\n\t\t\t\t\tspan.setAttribute(\"usage.session_count\", r.sessionCount);\n\t\t\t\t\tspan.setAttribute(\"project.id\", projectId);\n\t\t\t\t\treturn r;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn c.json({\n\t\t\t\tsuccess: true,\n\t\t\t\tinserted: result.inserted,\n\t\t\t\tsessionCount: result.sessionCount,\n\t\t\t\tacceptedWindowHours: DEFAULT_WINDOW_HOURS,\n\t\t\t});\n\t\t});\n\t},\n};\n","import type {\n\tJsonValue,\n\tUserProfileDetail,\n\tUserProfileRow,\n} from \"@obsunified/types\";\nimport type { CollectorPlugin } from \"../framework/collector\";\nimport { sqlDbFor } from \"../lib/sql-db\";\nimport { getProjectId } from \"./_context\";\n\nexport const usersQueryRoutesPlugin: CollectorPlugin = {\n\tname: \"users-query-routes\",\n\tregister(app) {\n\t\tapp.get(\"/internal/users\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst limit = Math.max(\n\t\t\t\t1,\n\t\t\t\tMath.min(1000, parseInt(c.req.query(\"limit\") ?? \"50\", 10) || 50),\n\t\t\t);\n\t\t\tconst { results } = await sqlDbFor(c.env)\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM user_profiles WHERE project_id = ? ORDER BY last_seen_at DESC LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, limit)\n\t\t\t\t.all<UserProfileRow>();\n\n\t\t\tconst users: UserProfileDetail[] = results.map((row) => ({\n\t\t\t\tuserId: row.user_id,\n\t\t\t\tvisitorId: row.visitor_id,\n\t\t\t\temail: row.email,\n\t\t\t\tname: row.name,\n\t\t\t\tproperties: parseProperties(row.properties_json),\n\t\t\t\tfirstSeenAt: row.first_seen_at,\n\t\t\t\tlastSeenAt: row.last_seen_at,\n\t\t\t}));\n\n\t\t\treturn c.json({ users });\n\t\t});\n\n\t\tapp.get(\"/internal/users/:userId\", async (c) => {\n\t\t\tconst projectId = getProjectId(c);\n\t\t\tconst userId = c.req.param(\"userId\");\n\t\t\tconst user = await sqlDbFor(c.env)\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM user_profiles WHERE project_id = ? AND user_id = ?`,\n\t\t\t\t)\n\t\t\t\t.bind(projectId, userId)\n\t\t\t\t.first<UserProfileRow>();\n\n\t\t\tif (!user) {\n\t\t\t\treturn c.json({ error: \"User not found\" }, 404);\n\t\t\t}\n\n\t\t\tconst detail: UserProfileDetail = {\n\t\t\t\tuserId: user.user_id,\n\t\t\t\tvisitorId: user.visitor_id,\n\t\t\t\temail: user.email,\n\t\t\t\tname: user.name,\n\t\t\t\tproperties: parseProperties(user.properties_json),\n\t\t\t\tfirstSeenAt: user.first_seen_at,\n\t\t\t\tlastSeenAt: user.last_seen_at,\n\t\t\t};\n\n\t\t\treturn c.json({ user: detail });\n\t\t});\n\t},\n};\n\nfunction parseProperties(value: string | null): Record<string, JsonValue> {\n\tif (!value) return {};\n\ttry {\n\t\tconst parsed = JSON.parse(value) as JsonValue;\n\t\treturn parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n\t\t\t? (parsed as Record<string, JsonValue>)\n\t\t\t: {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n","import type {\n\tCollectorPlugin,\n\tUsageEventProcessorPlugin,\n} from \"../framework/collector\";\nimport { parseJsonRecord } from \"../lib/json\";\n\nconst processor: UsageEventProcessorPlugin = {\n\tname: \"utm-enrichment\",\n\tprocess(events) {\n\t\treturn events.map((event) => {\n\t\t\tconst properties = parseJsonRecord(event.propertiesJson);\n\t\t\treturn {\n\t\t\t\t...event,\n\t\t\t\tutmSource:\n\t\t\t\t\t(typeof properties.utmSource === \"string\"\n\t\t\t\t\t\t? properties.utmSource\n\t\t\t\t\t\t: null) || event.utmSource,\n\t\t\t\tutmMedium:\n\t\t\t\t\t(typeof properties.utmMedium === \"string\"\n\t\t\t\t\t\t? properties.utmMedium\n\t\t\t\t\t\t: null) || event.utmMedium,\n\t\t\t\tutmCampaign:\n\t\t\t\t\t(typeof properties.utmCampaign === \"string\"\n\t\t\t\t\t\t? properties.utmCampaign\n\t\t\t\t\t\t: null) || event.utmCampaign,\n\t\t\t};\n\t\t});\n\t},\n};\n\nexport const utmEnrichmentPlugin: CollectorPlugin = {\n\tname: \"utm-enrichment\",\n\tregister(_app, runtime) {\n\t\truntime.addUsageEventProcessor(processor);\n\t},\n};\n","import type { MiddlewareHandler } from \"hono\";\nimport type { CollectorEnv } from \"../framework/env\";\nimport { ProjectsStore } from \"../lib/projects-store\";\nimport { type SqlDb, sqlDbFor } from \"../lib/sql-db\";\n\nconst SESSION_COOKIE = \"obs_session\";\nconst SESSION_MAX_AGE = 7 * 24 * 60 * 60; // 7 days in seconds\nconst PROJECT_CACHE_TTL_MS = 30_000;\n\ninterface ProjectCacheEntry {\n\tids: Set<string>;\n\texpiresAt: number;\n}\n\nlet projectCache = new WeakMap<object, ProjectCacheEntry>();\n\nasync function knownProjectIds(\n\tdbKey: object,\n\tdb: SqlDb,\n\tnow: number,\n): Promise<Set<string>> {\n\tconst cached = projectCache.get(dbKey);\n\tif (cached && cached.expiresAt > now) {\n\t\treturn cached.ids;\n\t}\n\tconst store = new ProjectsStore(db);\n\tconst projects = await store.listProjects();\n\tconst ids = new Set(projects.map((p) => p.id));\n\tprojectCache.set(dbKey, { ids, expiresAt: now + PROJECT_CACHE_TTL_MS });\n\treturn ids;\n}\n\n/** Test helper — clears the project list cache. */\nexport function resetDashboardProjectCache(): void {\n\tprojectCache = new WeakMap();\n}\n\n/**\n * Sign a payload using HMAC-SHA256.\n * Works across all runtimes that support Web Crypto API (CF Workers, Node 20+, Deno, Bun).\n */\nasync function sign(payload: string, secret: string): Promise<string> {\n\tconst encoder = new TextEncoder();\n\tconst key = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tencoder.encode(secret),\n\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\tfalse,\n\t\t[\"sign\"],\n\t);\n\tconst signature = await crypto.subtle.sign(\n\t\t\"HMAC\",\n\t\tkey,\n\t\tencoder.encode(payload),\n\t);\n\treturn btoa(String.fromCharCode(...new Uint8Array(signature)));\n}\n\nasync function verify(\n\tpayload: string,\n\tsignature: string,\n\tsecret: string,\n): Promise<boolean> {\n\tconst expected = await sign(payload, secret);\n\treturn timingSafeEqualStr(expected, signature);\n}\n\n// Constant-time comparison. Both inputs are SHA-256-digested first so the\n// XOR loop runs over fixed-length (32-byte) buffers — this removes the\n// early-exit timing oracle of `===` and any length-based side channel.\nasync function timingSafeEqualStr(a: string, b: string): Promise<boolean> {\n\tconst enc = new TextEncoder();\n\tconst [da, db] = await Promise.all([\n\t\tcrypto.subtle.digest(\"SHA-256\", enc.encode(a)),\n\t\tcrypto.subtle.digest(\"SHA-256\", enc.encode(b)),\n\t]);\n\tconst ha = new Uint8Array(da);\n\tconst hb = new Uint8Array(db);\n\tlet diff = 0;\n\tfor (let i = 0; i < ha.length; i++) diff |= ha[i] ^ hb[i];\n\treturn diff === 0;\n}\n\nfunction createSessionToken(expiresAt: number): string {\n\treturn JSON.stringify({ exp: expiresAt });\n}\n\nfunction parseSessionToken(token: string): { exp: number } | null {\n\ttry {\n\t\tconst parsed = JSON.parse(token);\n\t\tif (typeof parsed.exp === \"number\") return parsed;\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getCookie(\n\tcookieHeader: string | undefined,\n\tname: string,\n): string | undefined {\n\tif (!cookieHeader) return undefined;\n\tconst match = cookieHeader.match(new RegExp(`(?:^|;\\\\s*)${name}=([^;]*)`));\n\treturn match ? decodeURIComponent(match[1]) : undefined;\n}\n\n/**\n * Creates auth routes and middleware for dashboard password login.\n *\n * Routes added:\n * POST /auth/login — accepts { password }, sets session cookie\n * GET /auth/check — returns { authenticated: true/false }\n * POST /auth/logout — clears session cookie\n *\n * The returned middleware validates the session cookie on protected routes.\n */\nexport function createDashboardAuth(config: { password: string }): {\n\tmiddleware: MiddlewareHandler<{\n\t\tBindings: CollectorEnv;\n\t\tVariables: { projectId: string };\n\t}>;\n\tregisterRoutes: (\n\t\tapp: import(\"hono\").Hono<{ Bindings: CollectorEnv }>,\n\t) => void;\n} {\n\tconst middleware: MiddlewareHandler<{\n\t\tBindings: CollectorEnv;\n\t\tVariables: { projectId: string };\n\t}> = async (c, next) => {\n\t\tif (!config.password) {\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\terror:\n\t\t\t\t\t\t\"DASHBOARD_PASSWORD is not configured. Set the DASHBOARD_PASSWORD environment variable.\",\n\t\t\t\t},\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\n\t\tconst cookieHeader = c.req.header(\"Cookie\");\n\t\tconst sessionValue = getCookie(cookieHeader, SESSION_COOKIE);\n\n\t\tif (!sessionValue) {\n\t\t\t// For API requests, return 401. For page requests, redirect to login.\n\t\t\tconst accept = c.req.header(\"Accept\") || \"\";\n\t\t\tif (accept.includes(\"text/html\")) {\n\t\t\t\treturn c.redirect(\"/dashboard/login\");\n\t\t\t}\n\t\t\treturn c.json({ error: \"Unauthorized\" }, 401);\n\t\t}\n\n\t\t// Session cookie format: payload.signature\n\t\tconst dotIndex = sessionValue.lastIndexOf(\".\");\n\t\tif (dotIndex === -1) {\n\t\t\treturn c.json({ error: \"Invalid session\" }, 401);\n\t\t}\n\n\t\tconst payload = sessionValue.substring(0, dotIndex);\n\t\tconst sig = sessionValue.substring(dotIndex + 1);\n\n\t\tconst valid = await verify(payload, sig, config.password);\n\t\tif (!valid) {\n\t\t\treturn c.json({ error: \"Invalid session\" }, 401);\n\t\t}\n\n\t\tconst token = parseSessionToken(payload);\n\t\tif (!token || token.exp < Math.floor(Date.now() / 1000)) {\n\t\t\treturn c.json({ error: \"Session expired\" }, 401);\n\t\t}\n\n\t\t// Resolve project for data-scoped routes. /internal/projects/* is exempt\n\t\t// because that's where projects are managed (and where the first\n\t\t// project is created before the user has selected anything).\n\t\tconst path = c.req.path;\n\t\tconst needsProject =\n\t\t\tpath.startsWith(\"/internal/\") && !path.startsWith(\"/internal/projects\");\n\n\t\tif (needsProject) {\n\t\t\tconst headerProject = c.req.header(\"X-Project-Id\");\n\t\t\tconst projectId = headerProject?.trim() || \"default\";\n\t\t\tconst known = await knownProjectIds(\n\t\t\t\tc.env.DB,\n\t\t\t\tsqlDbFor(c.env),\n\t\t\t\tDate.now(),\n\t\t\t);\n\t\t\t// Always allow 'default' so fresh installs don't 400 before any\n\t\t\t// project is seeded (ensure_default_project runs via migration).\n\t\t\tif (projectId !== \"default\" && !known.has(projectId)) {\n\t\t\t\treturn c.json({ error: `Unknown project: ${projectId}` }, 400);\n\t\t\t}\n\t\t\tc.set(\"projectId\", projectId);\n\t\t}\n\n\t\tawait next();\n\t};\n\n\tconst registerRoutes = (\n\t\tapp: import(\"hono\").Hono<{ Bindings: CollectorEnv }>,\n\t) => {\n\t\tapp.post(\"/auth/login\", async (c) => {\n\t\t\tif (!config.password) {\n\t\t\t\treturn c.json({ error: \"Dashboard password not configured\" }, 500);\n\t\t\t}\n\n\t\t\tconst body = await c.req\n\t\t\t\t.json<{ password?: string }>()\n\t\t\t\t.catch(() => ({ password: undefined }));\n\t\t\tif (\n\t\t\t\t!body.password ||\n\t\t\t\t!(await timingSafeEqualStr(body.password, config.password))\n\t\t\t) {\n\t\t\t\treturn c.json({ error: \"Invalid password\" }, 401);\n\t\t\t}\n\n\t\t\tconst expiresAt = Math.floor(Date.now() / 1000) + SESSION_MAX_AGE;\n\t\t\tconst payload = createSessionToken(expiresAt);\n\t\t\tconst sig = await sign(payload, config.password);\n\t\t\tconst cookieValue = `${payload}.${sig}`;\n\n\t\t\tconst isSecure = c.req.url.startsWith(\"https:\");\n\t\t\tc.header(\n\t\t\t\t\"Set-Cookie\",\n\t\t\t\t`${SESSION_COOKIE}=${encodeURIComponent(cookieValue)}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${SESSION_MAX_AGE}${isSecure ? \"; Secure\" : \"\"}`,\n\t\t\t);\n\n\t\t\treturn c.json({ success: true });\n\t\t});\n\n\t\tapp.get(\"/auth/check\", async (c) => {\n\t\t\tconst cookieHeader = c.req.header(\"Cookie\");\n\t\t\tconst sessionValue = getCookie(cookieHeader, SESSION_COOKIE);\n\n\t\t\tif (!sessionValue) {\n\t\t\t\treturn c.json({ authenticated: false });\n\t\t\t}\n\n\t\t\tconst dotIndex = sessionValue.lastIndexOf(\".\");\n\t\t\tif (dotIndex === -1) {\n\t\t\t\treturn c.json({ authenticated: false });\n\t\t\t}\n\n\t\t\tconst payload = sessionValue.substring(0, dotIndex);\n\t\t\tconst sig = sessionValue.substring(dotIndex + 1);\n\n\t\t\tconst valid = await verify(payload, sig, config.password);\n\t\t\tif (!valid) {\n\t\t\t\treturn c.json({ authenticated: false });\n\t\t\t}\n\n\t\t\tconst token = parseSessionToken(payload);\n\t\t\tif (!token || token.exp < Math.floor(Date.now() / 1000)) {\n\t\t\t\treturn c.json({ authenticated: false });\n\t\t\t}\n\n\t\t\treturn c.json({ authenticated: true });\n\t\t});\n\n\t\tapp.post(\"/auth/logout\", (c) => {\n\t\t\tconst isSecure = c.req.url.startsWith(\"https:\");\n\t\t\tc.header(\n\t\t\t\t\"Set-Cookie\",\n\t\t\t\t`${SESSION_COOKIE}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0${isSecure ? \"; Secure\" : \"\"}`,\n\t\t\t);\n\t\t\treturn c.json({ success: true });\n\t\t});\n\t};\n\n\treturn { middleware, registerRoutes };\n}\n","/**\n * In-memory SSE pub/sub hub for live-tailing spans and logs.\n *\n * Ingest plugins call `/publish` after writing to D1; the dashboard opens an\n * EventSource on `/internal/telemetry/tail` which proxies here via `/subscribe`.\n *\n * One singleton DO instance is used (idFromName(\"singleton\")); it fans out to\n * every connected subscriber, filtering by projectId and kind server-side so\n * clients don't see other tenants' data.\n *\n * Heartbeat frames keep the connection alive through proxies with idle\n * timeouts (Vite dev proxy, Cloudflare edge).\n */\n\nexport type TailKind = \"span\" | \"log\";\n\nexport interface TailEvent {\n\tkind: TailKind;\n\tprojectId: string;\n\trow: Record<string, unknown>;\n\tt: string;\n}\n\ninterface Subscriber {\n\tid: string;\n\tprojectId: string;\n\tkinds: Set<TailKind>;\n\twriter: WritableStreamDefaultWriter<Uint8Array>;\n\theartbeat: ReturnType<typeof setInterval>;\n}\n\nconst HEARTBEAT_MS = 20_000;\nconst MAX_SUBSCRIBERS = 200;\nconst PROJECT_ID_RE = /^[A-Za-z0-9_-]{1,128}$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isTailEvent(value: unknown): value is TailEvent {\n\tif (!isRecord(value)) return false;\n\tconst { kind, projectId, row, t } = value;\n\treturn (\n\t\t(kind === \"span\" || kind === \"log\") &&\n\t\ttypeof projectId === \"string\" &&\n\t\tPROJECT_ID_RE.test(projectId) &&\n\t\tisRecord(row) &&\n\t\ttypeof t === \"string\" &&\n\t\tt.length > 0\n\t);\n}\n\nexport class TailHub {\n\tprivate readonly subscribers = new Map<string, Subscriber>();\n\tprivate readonly encoder = new TextEncoder();\n\n\tasync fetch(req: Request): Promise<Response> {\n\t\tconst url = new URL(req.url);\n\t\tif (req.method === \"POST\" && url.pathname === \"/publish\") {\n\t\t\tlet events: TailEvent[];\n\t\t\ttry {\n\t\t\t\tevents = (await req.json()) as TailEvent[];\n\t\t\t} catch {\n\t\t\t\treturn new Response(null, { status: 400 });\n\t\t\t}\n\t\t\tif (!Array.isArray(events)) {\n\t\t\t\treturn new Response(null, { status: 400 });\n\t\t\t}\n\t\t\tif (!events.every(isTailEvent)) {\n\t\t\t\treturn new Response(null, { status: 400 });\n\t\t\t}\n\t\t\tawait this.broadcast(events);\n\t\t\treturn new Response(null, { status: 204 });\n\t\t}\n\t\tif (req.method === \"GET\" && url.pathname === \"/subscribe\") {\n\t\t\tconst projectId = url.searchParams.get(\"projectId\") ?? \"default\";\n\t\t\tif (!PROJECT_ID_RE.test(projectId)) {\n\t\t\t\treturn new Response(\"bad projectId\", { status: 400 });\n\t\t\t}\n\t\t\tconst kindsParam = url.searchParams.get(\"kinds\") ?? \"span,log\";\n\t\t\tconst kinds = new Set(\n\t\t\t\tkindsParam\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t) as Set<TailKind>;\n\t\t\tif (![...kinds].every((kind) => kind === \"span\" || kind === \"log\")) {\n\t\t\t\treturn new Response(\"bad kinds\", { status: 400 });\n\t\t\t}\n\t\t\treturn this.subscribe(projectId, kinds, req);\n\t\t}\n\t\treturn new Response(\"not found\", { status: 404 });\n\t}\n\n\tprivate subscribe(\n\t\tprojectId: string,\n\t\tkinds: Set<TailKind>,\n\t\treq: Request,\n\t): Response {\n\t\tif (req.signal.aborted) {\n\t\t\treturn new Response(null, { status: 499 });\n\t\t}\n\t\tif (this.subscribers.size >= MAX_SUBSCRIBERS) {\n\t\t\treturn new Response(\"too many subscribers\", { status: 429 });\n\t\t}\n\t\tconst { readable, writable } = new TransformStream<\n\t\t\tUint8Array,\n\t\t\tUint8Array\n\t\t>();\n\t\tconst writer = writable.getWriter();\n\t\tconst id = crypto.randomUUID();\n\n\t\twriter.write(this.encoder.encode(`: connected\\n\\n`)).catch(() => {});\n\n\t\tconst heartbeat = setInterval(() => {\n\t\t\twriter\n\t\t\t\t.write(this.encoder.encode(`: heartbeat\\n\\n`))\n\t\t\t\t.catch(() => this.drop(id));\n\t\t}, HEARTBEAT_MS);\n\n\t\treq.signal.addEventListener(\"abort\", () => this.drop(id));\n\t\tthis.subscribers.set(id, { id, projectId, kinds, writer, heartbeat });\n\n\t\treturn new Response(readable, {\n\t\t\theaders: {\n\t\t\t\t\"content-type\": \"text/event-stream\",\n\t\t\t\t\"cache-control\": \"no-cache\",\n\t\t\t\t\"x-accel-buffering\": \"no\",\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate drop(id: string): void {\n\t\tconst sub = this.subscribers.get(id);\n\t\tif (!sub) return;\n\t\tclearInterval(sub.heartbeat);\n\t\tsub.writer.close().catch(() => {});\n\t\tthis.subscribers.delete(id);\n\t}\n\n\tprivate async broadcast(events: TailEvent[]): Promise<void> {\n\t\tif (events.length === 0 || this.subscribers.size === 0) return;\n\t\tfor (const sub of this.subscribers.values()) {\n\t\t\tconst payload = events.filter(\n\t\t\t\t(e) => e.projectId === sub.projectId && sub.kinds.has(e.kind),\n\t\t\t);\n\t\t\tif (payload.length === 0) continue;\n\t\t\tconst frame = this.encoder.encode(\n\t\t\t\t`event: tail\\ndata: ${JSON.stringify(payload)}\\n\\n`,\n\t\t\t);\n\t\t\ttry {\n\t\t\t\tawait sub.writer.write(frame);\n\t\t\t} catch {\n\t\t\t\tthis.drop(sub.id);\n\t\t\t}\n\t\t}\n\t}\n}\n","import type {\n\tActionRef,\n\tAgentRunRef,\n\tArtifactRef,\n\tEvalResultRef,\n\tRetrievalEventRef,\n\tToolCallRef,\n} from \"./identity-index\";\nimport {\n\tmapAction,\n\tmapAgentRun,\n\tmapArtifact,\n\tmapEvalResult,\n\tmapRetrievalEvent,\n\tmapToolCall,\n} from \"./identity-index/mappers\";\nimport type { SqlDb } from \"./sql-db\";\n\nexport type ActionRecord = Omit<ActionRef, \"projectId\"> & {\n\tprojectId: string;\n};\n\nexport type AgentRunRecord = Omit<AgentRunRef, \"projectId\"> & {\n\tprojectId: string;\n};\n\nexport type ToolCallRecord = Omit<ToolCallRef, \"projectId\" | \"sideEffect\"> & {\n\tprojectId: string;\n\tsideEffect: boolean | number;\n};\n\nexport type RetrievalEventRecord = Omit<RetrievalEventRef, \"projectId\"> & {\n\tprojectId: string;\n};\n\nexport type EvalResultRecord = Omit<EvalResultRef, \"projectId\" | \"passed\"> & {\n\tprojectId: string;\n\tpassed: boolean | number;\n};\n\nexport type ArtifactRecord = Omit<ArtifactRef, \"projectId\"> & {\n\tprojectId: string;\n};\n\nexport class ActionStore {\n\tconstructor(private readonly db: SqlDb) {}\n\n\tasync upsertAction(action: ActionRecord): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(`\n\t\t\t\tINSERT INTO actions (\n\t\t\t\t\tid, project_id, root_action_id, caused_by_action_id, actor_type, actor_id,\n\t\t\t\t\taction_kind, name, status, started_at, ended_at, duration_ms, trace_id,\n\t\t\t\t\tspan_id, session_id, interaction_id, user_id, agent_run_id, step_id,\n\t\t\t\t\ttool_call_id, prompt_version, model_name, provider, total_cost_usd,\n\t\t\t\t\tattrs_json\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\troot_action_id = excluded.root_action_id,\n\t\t\t\t\tcaused_by_action_id = excluded.caused_by_action_id,\n\t\t\t\t\tactor_type = excluded.actor_type,\n\t\t\t\t\tactor_id = excluded.actor_id,\n\t\t\t\t\taction_kind = excluded.action_kind,\n\t\t\t\t\tname = excluded.name,\n\t\t\t\t\tstatus = excluded.status,\n\t\t\t\t\tstarted_at = excluded.started_at,\n\t\t\t\t\tended_at = excluded.ended_at,\n\t\t\t\t\tduration_ms = excluded.duration_ms,\n\t\t\t\t\ttrace_id = excluded.trace_id,\n\t\t\t\t\tspan_id = excluded.span_id,\n\t\t\t\t\tsession_id = excluded.session_id,\n\t\t\t\t\tinteraction_id = excluded.interaction_id,\n\t\t\t\t\tuser_id = excluded.user_id,\n\t\t\t\t\tagent_run_id = excluded.agent_run_id,\n\t\t\t\t\tstep_id = excluded.step_id,\n\t\t\t\t\ttool_call_id = excluded.tool_call_id,\n\t\t\t\t\tprompt_version = excluded.prompt_version,\n\t\t\t\t\tmodel_name = excluded.model_name,\n\t\t\t\t\tprovider = excluded.provider,\n\t\t\t\t\ttotal_cost_usd = excluded.total_cost_usd,\n\t\t\t\t\tattrs_json = excluded.attrs_json\n\t\t\t`)\n\t\t\t.bind(\n\t\t\t\taction.id,\n\t\t\t\taction.projectId,\n\t\t\t\taction.rootActionId,\n\t\t\t\taction.causedByActionId,\n\t\t\t\taction.actorType,\n\t\t\t\taction.actorId,\n\t\t\t\taction.actionKind,\n\t\t\t\taction.name,\n\t\t\t\taction.status,\n\t\t\t\taction.startedAt,\n\t\t\t\taction.endedAt,\n\t\t\t\taction.durationMs,\n\t\t\t\taction.traceId,\n\t\t\t\taction.spanId,\n\t\t\t\taction.sessionId,\n\t\t\t\taction.interactionId,\n\t\t\t\taction.userId,\n\t\t\t\taction.agentRunId,\n\t\t\t\taction.stepId,\n\t\t\t\taction.toolCallId,\n\t\t\t\taction.promptVersion,\n\t\t\t\taction.modelName,\n\t\t\t\taction.provider,\n\t\t\t\taction.totalCostUsd,\n\t\t\t\taction.attrsJson,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync upsertAgentRun(run: AgentRunRecord): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(`\n\t\t\t\tINSERT INTO agent_runs (\n\t\t\t\t\tid, project_id, agent_id, agent_name, agent_version, goal, outcome,\n\t\t\t\t\tautonomy_level, status, error_message, total_cost_usd,\n\t\t\t\t\ttotal_duration_ms, metadata_json\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\tagent_id = excluded.agent_id,\n\t\t\t\t\tagent_name = excluded.agent_name,\n\t\t\t\t\tagent_version = excluded.agent_version,\n\t\t\t\t\tgoal = excluded.goal,\n\t\t\t\t\toutcome = excluded.outcome,\n\t\t\t\t\tautonomy_level = excluded.autonomy_level,\n\t\t\t\t\tstatus = excluded.status,\n\t\t\t\t\terror_message = excluded.error_message,\n\t\t\t\t\ttotal_cost_usd = excluded.total_cost_usd,\n\t\t\t\t\ttotal_duration_ms = excluded.total_duration_ms,\n\t\t\t\t\tmetadata_json = excluded.metadata_json\n\t\t\t`)\n\t\t\t.bind(\n\t\t\t\trun.id,\n\t\t\t\trun.projectId,\n\t\t\t\trun.agentId,\n\t\t\t\trun.agentName,\n\t\t\t\trun.agentVersion,\n\t\t\t\trun.goal,\n\t\t\t\trun.outcome,\n\t\t\t\trun.autonomyLevel,\n\t\t\t\trun.status,\n\t\t\t\trun.errorMessage,\n\t\t\t\trun.totalCostUsd,\n\t\t\t\trun.totalDurationMs,\n\t\t\t\trun.metadataJson,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync upsertToolCall(toolCall: ToolCallRecord): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(`\n\t\t\t\tINSERT INTO tool_calls (\n\t\t\t\t\tid, action_id, project_id, tool_name, args_hash, result_hash,\n\t\t\t\t\terror_type, side_effect, approval_state, args_redacted, result_redacted,\n\t\t\t\t\tmcp_audit_json, mutation_before_json, mutation_after_json,\n\t\t\t\t\tmutation_diff_json, mutation_artifact_id\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\ttool_name = excluded.tool_name,\n\t\t\t\t\targs_hash = excluded.args_hash,\n\t\t\t\t\tresult_hash = excluded.result_hash,\n\t\t\t\t\terror_type = excluded.error_type,\n\t\t\t\t\tside_effect = excluded.side_effect,\n\t\t\t\t\tapproval_state = excluded.approval_state,\n\t\t\t\t\targs_redacted = excluded.args_redacted,\n\t\t\t\t\tresult_redacted = excluded.result_redacted,\n\t\t\t\t\tmcp_audit_json = excluded.mcp_audit_json,\n\t\t\t\t\tmutation_before_json = excluded.mutation_before_json,\n\t\t\t\t\tmutation_after_json = excluded.mutation_after_json,\n\t\t\t\t\tmutation_diff_json = excluded.mutation_diff_json,\n\t\t\t\t\tmutation_artifact_id = excluded.mutation_artifact_id\n\t\t\t`)\n\t\t\t.bind(\n\t\t\t\ttoolCall.id,\n\t\t\t\ttoolCall.actionId,\n\t\t\t\ttoolCall.projectId,\n\t\t\t\ttoolCall.toolName,\n\t\t\t\ttoolCall.argsHash,\n\t\t\t\ttoolCall.resultHash,\n\t\t\t\ttoolCall.errorType,\n\t\t\t\ttoolCall.sideEffect ? 1 : 0,\n\t\t\t\ttoolCall.approvalState,\n\t\t\t\ttoolCall.argsRedacted,\n\t\t\t\ttoolCall.resultRedacted,\n\t\t\t\ttoolCall.mcpAuditJson,\n\t\t\t\ttoolCall.mutationBeforeJson,\n\t\t\t\ttoolCall.mutationAfterJson,\n\t\t\t\ttoolCall.mutationDiffJson,\n\t\t\t\ttoolCall.mutationArtifactId,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync upsertRetrievalEvent(event: RetrievalEventRecord): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(`\n\t\t\t\tINSERT INTO retrieval_events (\n\t\t\t\t\tid, action_id, project_id, retriever_name, query_hash, documents_json,\n\t\t\t\t\ttotal_results, max_relevance_score, duration_ms\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\tretriever_name = excluded.retriever_name,\n\t\t\t\t\tquery_hash = excluded.query_hash,\n\t\t\t\t\tdocuments_json = excluded.documents_json,\n\t\t\t\t\ttotal_results = excluded.total_results,\n\t\t\t\t\tmax_relevance_score = excluded.max_relevance_score,\n\t\t\t\t\tduration_ms = excluded.duration_ms\n\t\t\t`)\n\t\t\t.bind(\n\t\t\t\tevent.id,\n\t\t\t\tevent.actionId,\n\t\t\t\tevent.projectId,\n\t\t\t\tevent.retrieverName,\n\t\t\t\tevent.queryHash,\n\t\t\t\tevent.documentsJson,\n\t\t\t\tevent.totalResults,\n\t\t\t\tevent.maxRelevanceScore,\n\t\t\t\tevent.durationMs,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync upsertEvalResult(result: EvalResultRecord): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(`\n\t\t\t\tINSERT INTO eval_results (\n\t\t\t\t\tid, action_id, project_id, evaluator_name, evaluator_version, score,\n\t\t\t\t\tpassed, reasoning, rubric_json\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\tevaluator_name = excluded.evaluator_name,\n\t\t\t\t\tevaluator_version = excluded.evaluator_version,\n\t\t\t\t\tscore = excluded.score,\n\t\t\t\t\tpassed = excluded.passed,\n\t\t\t\t\treasoning = excluded.reasoning,\n\t\t\t\t\trubric_json = excluded.rubric_json\n\t\t\t`)\n\t\t\t.bind(\n\t\t\t\tresult.id,\n\t\t\t\tresult.actionId,\n\t\t\t\tresult.projectId,\n\t\t\t\tresult.evaluatorName,\n\t\t\t\tresult.evaluatorVersion,\n\t\t\t\tresult.score,\n\t\t\t\tresult.passed ? 1 : 0,\n\t\t\t\tresult.reasoning,\n\t\t\t\tresult.rubricJson,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync upsertArtifact(artifact: ArtifactRecord): Promise<void> {\n\t\tawait this.db\n\t\t\t.prepare(`\n\t\t\t\tINSERT INTO artifacts (\n\t\t\t\t\tid, action_id, project_id, artifact_name, artifact_type, storage_ref,\n\t\t\t\t\tsize_bytes, sha256_hash, content_preview\n\t\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\t\taction_id = excluded.action_id,\n\t\t\t\t\tproject_id = excluded.project_id,\n\t\t\t\t\tartifact_name = excluded.artifact_name,\n\t\t\t\t\tartifact_type = excluded.artifact_type,\n\t\t\t\t\tstorage_ref = excluded.storage_ref,\n\t\t\t\t\tsize_bytes = excluded.size_bytes,\n\t\t\t\t\tsha256_hash = excluded.sha256_hash,\n\t\t\t\t\tcontent_preview = excluded.content_preview\n\t\t\t`)\n\t\t\t.bind(\n\t\t\t\tartifact.id,\n\t\t\t\tartifact.actionId,\n\t\t\t\tartifact.projectId,\n\t\t\t\tartifact.artifactName,\n\t\t\t\tartifact.artifactType,\n\t\t\t\tartifact.storageRef,\n\t\t\t\tartifact.sizeBytes,\n\t\t\t\tartifact.sha256Hash,\n\t\t\t\tartifact.contentPreview,\n\t\t\t)\n\t\t\t.run();\n\t}\n\n\tasync getAction(\n\t\tprojectId: string,\n\t\tactionId: string,\n\t): Promise<ActionRef | null> {\n\t\tconst row = await this.db\n\t\t\t.prepare(`SELECT * FROM actions WHERE project_id = ? AND id = ? LIMIT 1`)\n\t\t\t.bind(projectId, actionId)\n\t\t\t.first<Parameters<typeof mapAction>[0]>();\n\t\treturn row ? mapAction(row) : null;\n\t}\n\n\tasync listActionsByRoot(\n\t\tprojectId: string,\n\t\trootActionId: string,\n\t\tlimit = 100,\n\t): Promise<ActionRef[]> {\n\t\tconst rows = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM actions\n\t\t\t\t\tWHERE project_id = ? AND root_action_id = ?\n\t\t\t\t\tORDER BY started_at ASC LIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, rootActionId, limit)\n\t\t\t.all<Parameters<typeof mapAction>[0]>();\n\t\treturn rows.results.map(mapAction);\n\t}\n\n\tasync getAgentRun(\n\t\tprojectId: string,\n\t\tagentRunId: string,\n\t): Promise<AgentRunRef | null> {\n\t\tconst row = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM agent_runs WHERE project_id = ? AND id = ? LIMIT 1`,\n\t\t\t)\n\t\t\t.bind(projectId, agentRunId)\n\t\t\t.first<Parameters<typeof mapAgentRun>[0]>();\n\t\treturn row ? mapAgentRun(row) : null;\n\t}\n\n\tasync listToolCallsByAction(\n\t\tprojectId: string,\n\t\tactionId: string,\n\t\tlimit = 100,\n\t): Promise<ToolCallRef[]> {\n\t\tconst rows = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM tool_calls\n\t\t\t\t\tWHERE project_id = ? AND action_id = ?\n\t\t\t\t\tLIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, actionId, limit)\n\t\t\t.all<Parameters<typeof mapToolCall>[0]>();\n\t\treturn rows.results.map(mapToolCall);\n\t}\n\n\tasync listRetrievalEventsByAction(\n\t\tprojectId: string,\n\t\tactionId: string,\n\t\tlimit = 100,\n\t): Promise<RetrievalEventRef[]> {\n\t\tconst rows = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM retrieval_events\n\t\t\t\t\tWHERE project_id = ? AND action_id = ?\n\t\t\t\t\tLIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, actionId, limit)\n\t\t\t.all<Parameters<typeof mapRetrievalEvent>[0]>();\n\t\treturn rows.results.map(mapRetrievalEvent);\n\t}\n\n\tasync listEvalResultsByAction(\n\t\tprojectId: string,\n\t\tactionId: string,\n\t\tlimit = 100,\n\t): Promise<EvalResultRef[]> {\n\t\tconst rows = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM eval_results\n\t\t\t\t\tWHERE project_id = ? AND action_id = ?\n\t\t\t\t\tLIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, actionId, limit)\n\t\t\t.all<Parameters<typeof mapEvalResult>[0]>();\n\t\treturn rows.results.map(mapEvalResult);\n\t}\n\n\tasync listArtifactsByAction(\n\t\tprojectId: string,\n\t\tactionId: string,\n\t\tlimit = 100,\n\t): Promise<ArtifactRef[]> {\n\t\tconst rows = await this.db\n\t\t\t.prepare(\n\t\t\t\t`SELECT * FROM artifacts\n\t\t\t\t\tWHERE project_id = ? AND action_id = ?\n\t\t\t\t\tLIMIT ?`,\n\t\t\t)\n\t\t\t.bind(projectId, actionId, limit)\n\t\t\t.all<Parameters<typeof mapArtifact>[0]>();\n\t\treturn rows.results.map(mapArtifact);\n\t}\n}\n","/**\n * Storage seam for opaque blob payloads — replay rrweb chunks and\n * pprof profiles.\n *\n * Two implementations:\n * - `R2BlobStore` — Cloudflare R2 binding (default on Workers).\n * - `S3BlobStore` (sibling file) — AWS S3 / MinIO / any S3-compatible.\n *\n * Replay chunks live under `replays/<session_id>/<chunk_id>`; pprof\n * profiles live under `profiles/<service>/<trace_id>/<span_id>`. The\n * adapter never sees these paths — they're constructed by the callers\n * (`replay-receiver`, `profile-routes`).\n */\n\nexport interface BlobStore {\n\tput(\n\t\tkey: string,\n\t\tbody: ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>,\n\t\toptions?: BlobPutOptions,\n\t): Promise<void>;\n\tget(key: string): Promise<BlobObject | null>;\n\tdelete(key: string): Promise<void>;\n\tlist(prefix: string, options?: BlobListOptions): Promise<BlobListResult>;\n}\n\nexport interface BlobPutOptions {\n\thttpMetadata?: { contentType?: string; contentEncoding?: string };\n\tcustomMetadata?: Record<string, string>;\n}\n\nexport interface BlobListOptions {\n\tlimit?: number;\n\tcursor?: string;\n}\n\nexport interface BlobObject {\n\tbody: ReadableStream<Uint8Array>;\n\tbytes(): Promise<Uint8Array>;\n\t/**\n\t * Object size in bytes when the store knows it cheaply (S3 `ContentLength`,\n\t * R2 `size`). Undefined when it can't be determined without reading the body.\n\t */\n\tsize?: number;\n\thttpMetadata?: { contentType?: string; contentEncoding?: string };\n\tcustomMetadata?: Record<string, string>;\n}\n\nexport interface BlobListResult {\n\tobjects: Array<{ key: string; size: number; uploaded: Date }>;\n\tcursor?: string;\n\ttruncated: boolean;\n}\n\nconst toExactArrayBuffer = (bytes: Uint8Array): ArrayBuffer => {\n\tconst copy = new Uint8Array(bytes.byteLength);\n\tcopy.set(bytes);\n\treturn copy.buffer;\n};\n\nconst emptyChecksums: R2Checksums = {\n\ttoJSON: () => ({}),\n};\n\nconst writeMetadata = (\n\tmetadata: R2HTTPMetadata | undefined,\n\theaders: Headers,\n): void => {\n\tif (!metadata) return;\n\tif (metadata.contentType) headers.set(\"content-type\", metadata.contentType);\n\tif (metadata.contentLanguage)\n\t\theaders.set(\"content-language\", metadata.contentLanguage);\n\tif (metadata.contentDisposition)\n\t\theaders.set(\"content-disposition\", metadata.contentDisposition);\n\tif (metadata.contentEncoding)\n\t\theaders.set(\"content-encoding\", metadata.contentEncoding);\n\tif (metadata.cacheControl)\n\t\theaders.set(\"cache-control\", metadata.cacheControl);\n\tif (metadata.cacheExpiry)\n\t\theaders.set(\"expires\", metadata.cacheExpiry.toUTCString());\n};\n\nconst metadataFrom = (\n\tmetadata: R2HTTPMetadata | Headers | undefined,\n): R2HTTPMetadata | undefined => {\n\tif (!metadata) return undefined;\n\tif (metadata instanceof Headers) {\n\t\treturn {\n\t\t\tcontentType: metadata.get(\"content-type\") ?? undefined,\n\t\t\tcontentLanguage: metadata.get(\"content-language\") ?? undefined,\n\t\t\tcontentDisposition: metadata.get(\"content-disposition\") ?? undefined,\n\t\t\tcontentEncoding: metadata.get(\"content-encoding\") ?? undefined,\n\t\t\tcacheControl: metadata.get(\"cache-control\") ?? undefined,\n\t\t\tcacheExpiry: metadata.get(\"expires\")\n\t\t\t\t? new Date(metadata.get(\"expires\") as string)\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\treturn metadata;\n};\n\n/**\n * R2 adapter. R2's binding shape is already very close to this\n * interface; the adapter normalizes the differences (cursor type,\n * list pagination shape).\n */\nexport class R2BlobStore implements BlobStore {\n\tconstructor(private readonly bucket: R2Bucket) {}\n\n\tasync put(\n\t\tkey: string,\n\t\tbody: ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>,\n\t\toptions?: BlobPutOptions,\n\t): Promise<void> {\n\t\tawait this.bucket.put(key, body as ArrayBuffer | ReadableStream, {\n\t\t\thttpMetadata: options?.httpMetadata,\n\t\t\tcustomMetadata: options?.customMetadata,\n\t\t});\n\t}\n\n\tasync get(key: string): Promise<BlobObject | null> {\n\t\tconst obj = await this.bucket.get(key);\n\t\tif (!obj) return null;\n\t\treturn {\n\t\t\tbody: obj.body,\n\t\t\tbytes: () => obj.arrayBuffer().then((b) => new Uint8Array(b)),\n\t\t\tsize: obj.size,\n\t\t\thttpMetadata: obj.httpMetadata,\n\t\t\tcustomMetadata: obj.customMetadata,\n\t\t};\n\t}\n\n\tasync delete(key: string): Promise<void> {\n\t\tawait this.bucket.delete(key);\n\t}\n\n\tasync list(\n\t\tprefix: string,\n\t\toptions?: BlobListOptions,\n\t): Promise<BlobListResult> {\n\t\tconst r = await this.bucket.list({\n\t\t\tprefix,\n\t\t\tlimit: options?.limit,\n\t\t\tcursor: options?.cursor,\n\t\t});\n\t\treturn {\n\t\t\tobjects: r.objects.map((o) => ({\n\t\t\t\tkey: o.key,\n\t\t\t\tsize: o.size,\n\t\t\t\tuploaded: o.uploaded,\n\t\t\t})),\n\t\t\tcursor: r.truncated ? r.cursor : undefined,\n\t\t\ttruncated: r.truncated,\n\t\t};\n\t}\n}\n\nexport class BlobStoreToR2Adapter implements R2Bucket {\n\tconstructor(private readonly store: BlobStore) {}\n\n\tasync put(\n\t\tkey: string,\n\t\tvalue:\n\t\t\t| ReadableStream\n\t\t\t| ArrayBuffer\n\t\t\t| ArrayBufferView\n\t\t\t| string\n\t\t\t| Blob\n\t\t\t| null,\n\t\toptions?: R2PutOptions,\n\t): Promise<R2Object> {\n\t\tlet body: ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>;\n\t\tif (value === null) {\n\t\t\tbody = new Uint8Array(0);\n\t\t} else if (typeof value === \"string\") {\n\t\t\tbody = new TextEncoder().encode(value);\n\t\t} else if (value instanceof ReadableStream) {\n\t\t\tbody = value as ReadableStream<Uint8Array>;\n\t\t} else if (value instanceof ArrayBuffer) {\n\t\t\tbody = value;\n\t\t} else if (ArrayBuffer.isView(value)) {\n\t\t\tbody = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n\t\t} else if (value instanceof Blob) {\n\t\t\tbody = new Uint8Array(await value.arrayBuffer());\n\t\t} else {\n\t\t\tthrow new Error(\"Unsupported value type for S3 put\");\n\t\t}\n\n\t\tconst size =\n\t\t\tbody instanceof ReadableStream\n\t\t\t\t? 0\n\t\t\t\t: body instanceof ArrayBuffer\n\t\t\t\t\t? body.byteLength\n\t\t\t\t\t: body.byteLength;\n\t\tconst httpMetadata = metadataFrom(options?.httpMetadata);\n\t\tawait this.store.put(key, body, {\n\t\t\thttpMetadata,\n\t\t\tcustomMetadata: options?.customMetadata,\n\t\t});\n\n\t\treturn {\n\t\t\tkey,\n\t\t\tversion: \"\",\n\t\t\tsize,\n\t\t\tetag: \"\",\n\t\t\thttpEtag: \"\",\n\t\t\tchecksums: emptyChecksums,\n\t\t\tuploaded: new Date(),\n\t\t\thttpMetadata,\n\t\t\tcustomMetadata: options?.customMetadata,\n\t\t\tstorageClass: options?.storageClass ?? \"Standard\",\n\t\t\twriteHttpMetadata: (headers: Headers) =>\n\t\t\t\twriteMetadata(httpMetadata, headers),\n\t\t} as unknown as R2Object;\n\t}\n\n\tasync get(\n\t\tkey: string,\n\t\t_options?: R2GetOptions,\n\t): Promise<R2ObjectBody | null> {\n\t\tconst obj = await this.store.get(key);\n\t\tif (!obj) return null;\n\n\t\t// One underlying stream backs both `body` and the buffered accessors.\n\t\t// Callers consume exactly one of them — the profile download streams\n\t\t// `body` via `new Response(obj.body)`, while replay/profile-filter read\n\t\t// `json()`/`arrayBuffer()`. Teeing would force the unread branch to\n\t\t// buffer the entire blob in memory (defeating the streaming download for\n\t\t// large pprof profiles), so we share a single stream instead. This also\n\t\t// keeps `bodyUsed` honest: the buffered accessors lock `body` directly.\n\t\tconst body = obj.body;\n\t\tlet bytesPromise: Promise<Uint8Array> | null = null;\n\t\tconst bytes = async (): Promise<Uint8Array> => {\n\t\t\tif (!bytesPromise) bytesPromise = streamToBytes(body);\n\t\t\treturn bytesPromise;\n\t\t};\n\t\tconst httpMetadata = obj.httpMetadata;\n\n\t\treturn {\n\t\t\tkey,\n\t\t\tversion: \"\",\n\t\t\tsize: obj.size ?? 0,\n\t\t\tetag: \"\",\n\t\t\thttpEtag: \"\",\n\t\t\tchecksums: emptyChecksums,\n\t\t\tuploaded: new Date(),\n\t\t\thttpMetadata,\n\t\t\tcustomMetadata: obj.customMetadata,\n\t\t\tstorageClass: \"Standard\",\n\t\t\tbody,\n\t\t\tget bodyUsed() {\n\t\t\t\treturn body.locked;\n\t\t\t},\n\t\t\tarrayBuffer: async () => {\n\t\t\t\tconst data = await bytes();\n\t\t\t\treturn toExactArrayBuffer(data);\n\t\t\t},\n\t\t\tbytes: async () => {\n\t\t\t\tconst data = await bytes();\n\t\t\t\treturn new Uint8Array(data);\n\t\t\t},\n\t\t\tjson: async <T>() => {\n\t\t\t\tconst data = await bytes();\n\t\t\t\tconst text = new TextDecoder().decode(data);\n\t\t\t\treturn JSON.parse(text) as T;\n\t\t\t},\n\t\t\ttext: async () => {\n\t\t\t\tconst data = await bytes();\n\t\t\t\treturn new TextDecoder().decode(data);\n\t\t\t},\n\t\t\tblob: async () => {\n\t\t\t\tconst data = await bytes();\n\t\t\t\treturn new Blob([toExactArrayBuffer(data)], {\n\t\t\t\t\ttype: obj.httpMetadata?.contentType,\n\t\t\t\t});\n\t\t\t},\n\t\t\twriteHttpMetadata: (headers: Headers) =>\n\t\t\t\twriteMetadata(httpMetadata, headers),\n\t\t} as unknown as R2ObjectBody;\n\t}\n\n\tasync delete(keys: string | string[]): Promise<void> {\n\t\tconst keysArr = Array.isArray(keys) ? keys : [keys];\n\t\tawait Promise.all(keysArr.map((k) => this.store.delete(k)));\n\t}\n\n\tasync list(options?: R2ListOptions): Promise<R2Objects> {\n\t\tconst res = await this.store.list(options?.prefix ?? \"\", {\n\t\t\tlimit: options?.limit,\n\t\t\tcursor: options?.cursor,\n\t\t});\n\n\t\tconst objects = res.objects.map((o) => ({\n\t\t\tkey: o.key,\n\t\t\tsize: o.size,\n\t\t\tuploaded: o.uploaded,\n\t\t\tetag: \"\",\n\t\t\thttpEtag: \"\",\n\t\t\tchecksums: emptyChecksums,\n\t\t\tversion: \"\",\n\t\t\tstorageClass: \"Standard\",\n\t\t\twriteHttpMetadata: () => {},\n\t\t})) as unknown as R2Object[];\n\n\t\treturn res.truncated\n\t\t\t? ({\n\t\t\t\t\tobjects,\n\t\t\t\t\ttruncated: true,\n\t\t\t\t\tcursor: res.cursor ?? \"\",\n\t\t\t\t\tdelimitedPrefixes: [],\n\t\t\t\t} as R2Objects)\n\t\t\t: ({ objects, truncated: false, delimitedPrefixes: [] } as R2Objects);\n\t}\n\n\tasync head(key: string): Promise<R2Object | null> {\n\t\tconst obj = await this.store.get(key);\n\t\tif (!obj) return null;\n\t\t// BlobStore has no metadata-only HEAD, so this issues a GET under the\n\t\t// hood. Release the response body immediately so S3 can reuse the socket.\n\t\tawait obj.body.cancel().catch(() => {});\n\t\treturn {\n\t\t\tkey,\n\t\t\tversion: \"\",\n\t\t\tsize: obj.size ?? 0,\n\t\t\tetag: \"\",\n\t\t\thttpEtag: \"\",\n\t\t\tchecksums: emptyChecksums,\n\t\t\tuploaded: new Date(),\n\t\t\thttpMetadata: obj.httpMetadata,\n\t\t\tcustomMetadata: obj.customMetadata,\n\t\t\tstorageClass: \"Standard\",\n\t\t\twriteHttpMetadata: (headers: Headers) =>\n\t\t\t\twriteMetadata(obj.httpMetadata, headers),\n\t\t} as unknown as R2Object;\n\t}\n\n\tasync createMultipartUpload(\n\t\t_key: string,\n\t\t_options?: R2MultipartOptions,\n\t): Promise<R2MultipartUpload> {\n\t\tthrow new Error(\"Multipart upload not implemented for S3 wrapper\");\n\t}\n\n\tresumeMultipartUpload(_key: string, _uploadId: string): R2MultipartUpload {\n\t\tthrow new Error(\"Multipart upload not implemented for S3 wrapper\");\n\t}\n}\n\nconst streamToBytes = async (\n\tstream: ReadableStream<Uint8Array>,\n): Promise<Uint8Array> => {\n\tconst reader = stream.getReader();\n\tconst chunks: Uint8Array[] = [];\n\twhile (true) {\n\t\tconst { value, done } = await reader.read();\n\t\tif (done) break;\n\t\tif (value) chunks.push(value);\n\t}\n\tconst total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n\tconst out = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tout.set(chunk, offset);\n\t\toffset += chunk.byteLength;\n\t}\n\treturn out;\n};\n","/**\n * S3-compatible adapter for `BlobStore`. Works against AWS S3, MinIO,\n * Cloudflare R2's S3 API, Backblaze B2, etc.\n *\n * Uses `@aws-sdk/client-s3` v3. The adapter is intentionally thin —\n * just enough to satisfy `BlobStore` for replay + pprof payloads. We\n * deliberately do NOT expose pre-signed URLs, ACLs, or storage-class\n * tuning — those belong in a richer storage adapter for users that\n * outgrow the default.\n */\n\nimport type {\n\tBlobListOptions,\n\tBlobListResult,\n\tBlobObject,\n\tBlobPutOptions,\n\tBlobStore,\n} from \"./blob-store\";\n\ntype S3Body = Uint8Array | ArrayBuffer | ReadableStream<Uint8Array>;\ntype S3CommandBody = Exclude<S3Body, ArrayBuffer>;\ntype S3ResponseBody =\n\t| ReadableStream<Uint8Array>\n\t| AsyncIterable<Uint8Array | ArrayBuffer | ArrayBufferView | string>\n\t| {\n\t\t\ttransformToWebStream(): ReadableStream<Uint8Array>;\n\t };\n\ninterface S3ClientShape {\n\tsend(command: unknown): Promise<unknown>;\n}\n\ninterface S3SdkConstructors {\n\t// Loose typing so the consumer can pass the AWS SDK's CommandInput types\n\t// without the BlobStore adapter dragging in a hard dep on\n\t// @aws-sdk/client-s3. The runtime contract is just \"construct with an\n\t// object literal of S3 params.\"\n\tPutObjectCommand: new (input: {\n\t\tBucket: string;\n\t\tKey: string;\n\t\tBody?: S3CommandBody;\n\t\tContentType?: string;\n\t\tContentEncoding?: string;\n\t\tMetadata?: Record<string, string>;\n\t}) => unknown;\n\tGetObjectCommand: new (input: { Bucket: string; Key: string }) => unknown;\n\tDeleteObjectCommand: new (input: { Bucket: string; Key: string }) => unknown;\n\tListObjectsV2Command: new (input: {\n\t\tBucket: string;\n\t\tPrefix: string;\n\t\tMaxKeys?: number;\n\t\tContinuationToken?: string;\n\t}) => unknown;\n}\n\nexport interface S3BlobStoreOptions {\n\tclient: S3ClientShape;\n\tcommands: S3SdkConstructors;\n\tbucket: string;\n}\n\nexport class S3BlobStore implements BlobStore {\n\tconstructor(private readonly opts: S3BlobStoreOptions) {}\n\n\tasync put(\n\t\tkey: string,\n\t\tbody: S3Body,\n\t\toptions?: BlobPutOptions,\n\t): Promise<void> {\n\t\tconst commandBody: S3CommandBody =\n\t\t\tbody instanceof ArrayBuffer ? new Uint8Array(body) : body;\n\t\tconst cmd = new this.opts.commands.PutObjectCommand({\n\t\t\tBucket: this.opts.bucket,\n\t\t\tKey: key,\n\t\t\tBody: commandBody,\n\t\t\tContentType: options?.httpMetadata?.contentType,\n\t\t\tContentEncoding: options?.httpMetadata?.contentEncoding,\n\t\t\tMetadata: options?.customMetadata,\n\t\t});\n\t\tawait this.opts.client.send(cmd);\n\t}\n\n\tasync get(key: string): Promise<BlobObject | null> {\n\t\tconst cmd = new this.opts.commands.GetObjectCommand({\n\t\t\tBucket: this.opts.bucket,\n\t\t\tKey: key,\n\t\t});\n\t\ttry {\n\t\t\tconst r = (await this.opts.client.send(cmd)) as {\n\t\t\t\tBody: S3ResponseBody;\n\t\t\t\tContentLength?: number;\n\t\t\t\tContentType?: string;\n\t\t\t\tContentEncoding?: string;\n\t\t\t\tMetadata?: Record<string, string>;\n\t\t\t};\n\t\t\tconst body = toWebReadableStream(r.Body);\n\t\t\treturn {\n\t\t\t\tbody,\n\t\t\t\tsize: r.ContentLength,\n\t\t\t\tbytes: () => streamToBytes(body),\n\t\t\t\thttpMetadata: {\n\t\t\t\t\tcontentType: r.ContentType,\n\t\t\t\t\tcontentEncoding: r.ContentEncoding,\n\t\t\t\t},\n\t\t\t\tcustomMetadata: r.Metadata,\n\t\t\t};\n\t\t} catch (err: unknown) {\n\t\t\tif (isNotFound(err)) return null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync delete(key: string): Promise<void> {\n\t\tconst cmd = new this.opts.commands.DeleteObjectCommand({\n\t\t\tBucket: this.opts.bucket,\n\t\t\tKey: key,\n\t\t});\n\t\tawait this.opts.client.send(cmd);\n\t}\n\n\tasync list(\n\t\tprefix: string,\n\t\toptions?: BlobListOptions,\n\t): Promise<BlobListResult> {\n\t\tconst cmd = new this.opts.commands.ListObjectsV2Command({\n\t\t\tBucket: this.opts.bucket,\n\t\t\tPrefix: prefix,\n\t\t\tMaxKeys: options?.limit,\n\t\t\tContinuationToken: options?.cursor,\n\t\t});\n\t\tconst r = (await this.opts.client.send(cmd)) as {\n\t\t\tContents?: Array<{ Key?: string; Size?: number; LastModified?: Date }>;\n\t\t\tNextContinuationToken?: string;\n\t\t\tIsTruncated?: boolean;\n\t\t};\n\t\treturn {\n\t\t\tobjects: (r.Contents ?? [])\n\t\t\t\t.filter((o): o is { Key: string; Size: number; LastModified: Date } =>\n\t\t\t\t\tBoolean(o.Key && o.Size !== undefined && o.LastModified),\n\t\t\t\t)\n\t\t\t\t.map((o) => ({\n\t\t\t\t\tkey: o.Key,\n\t\t\t\t\tsize: o.Size,\n\t\t\t\t\tuploaded: o.LastModified,\n\t\t\t\t})),\n\t\t\tcursor: r.NextContinuationToken,\n\t\t\ttruncated: Boolean(r.IsTruncated),\n\t\t};\n\t}\n}\n\nconst isNotFound = (err: unknown): boolean => {\n\tif (!err || typeof err !== \"object\") return false;\n\tconst e = err as { name?: string; $metadata?: { httpStatusCode?: number } };\n\treturn e.name === \"NoSuchKey\" || e.$metadata?.httpStatusCode === 404;\n};\n\nconst toWebReadableStream = (\n\tbody: S3ResponseBody,\n): ReadableStream<Uint8Array> => {\n\tif (body instanceof ReadableStream) return body;\n\tif (\"transformToWebStream\" in body) return body.transformToWebStream();\n\tif (Symbol.asyncIterator in body) return asyncIterableToStream(body);\n\tthrow new Error(\"Unsupported S3 response body type\");\n};\n\nconst asyncIterableToStream = (\n\titerable: AsyncIterable<Uint8Array | ArrayBuffer | ArrayBufferView | string>,\n): ReadableStream<Uint8Array> => {\n\tconst iterator = iterable[Symbol.asyncIterator]();\n\treturn new ReadableStream<Uint8Array>({\n\t\tasync pull(controller) {\n\t\t\tconst { value, done } = await iterator.next();\n\t\t\tif (done) {\n\t\t\t\tcontroller.close();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcontroller.enqueue(toUint8Array(value));\n\t\t},\n\t\tasync cancel(reason) {\n\t\t\tawait iterator.return?.(reason);\n\t\t},\n\t});\n};\n\nconst toUint8Array = (\n\tvalue: Uint8Array | ArrayBuffer | ArrayBufferView | string,\n): Uint8Array => {\n\tif (typeof value === \"string\") return new TextEncoder().encode(value);\n\tif (value instanceof Uint8Array) return value;\n\tif (value instanceof ArrayBuffer) return new Uint8Array(value);\n\treturn new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n};\n\nconst streamToBytes = async (\n\tstream: ReadableStream<Uint8Array>,\n): Promise<Uint8Array> => {\n\tconst reader = stream.getReader();\n\tconst chunks: Uint8Array[] = [];\n\twhile (true) {\n\t\tconst { value, done } = await reader.read();\n\t\tif (done) break;\n\t\tif (value) chunks.push(value);\n\t}\n\tconst total = chunks.reduce((n, c) => n + c.byteLength, 0);\n\tconst out = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const c of chunks) {\n\t\tout.set(c, offset);\n\t\toffset += c.byteLength;\n\t}\n\treturn out;\n};\n","/**\n * Postgres adapter for the SqlDb seam (RFC 0008).\n *\n * Wraps `pg` (node-postgres) to expose the same `prepare → bind → first |\n * all | run` chain as `D1Adapter`. Used by the Docker / standalone Node\n * deployment of `apps/collector`; the Workers deployment continues to\n * use `D1Adapter`.\n *\n * Notable differences from D1 handled here:\n * - Placeholders: D1 uses `?`; Postgres uses `$1`, `$2`. We rewrite\n * `?` to `$N` in `prepare`. Statements MUST use `?` for portability.\n * - `INSERT … RETURNING`: D1 doesn't support RETURNING; Postgres does.\n * Code that targets both MUST NOT rely on RETURNING.\n * - `TEXT vs VARCHAR`: D1 is permissive; we use TEXT exclusively in\n * the postgres migrations.\n * - `meta.changes`: D1 reports affected row count via meta.changes;\n * Postgres reports it via `result.rowCount`. We normalize.\n *\n * Connection pooling is the caller's job — pass a `pg.Pool`, not a\n * one-shot Client. Each `prepare` checks out, runs the statement, and\n * releases. Long-lived transactions need a different surface (not yet\n * exposed; collector code today does not require them).\n */\n\nimport type { Pool, QueryResultRow } from \"pg\";\nimport { postgresDialect, type SqlDb, type SqlStatement } from \"./sql-db\";\n\nexport interface PostgresAdapterOptions {\n\t/**\n\t * Statement-level timeout in milliseconds. Defaults to 30s. Issued\n\t * via `SET statement_timeout` at the start of each query (session-level;\n\t * `SET LOCAL` outside a transaction would be a no-op).\n\t */\n\tstatementTimeoutMs?: number;\n}\n\nexport class PostgresAdapter implements SqlDb {\n\treadonly dialect = postgresDialect;\n\tprivate readonly statementTimeoutMs: number;\n\n\tconstructor(\n\t\tprivate readonly pool: Pool,\n\t\toptions: PostgresAdapterOptions = {},\n\t) {\n\t\tconst rawTimeout = options.statementTimeoutMs ?? 30_000;\n\t\tthis.statementTimeoutMs =\n\t\t\tNumber.isFinite(rawTimeout) && rawTimeout >= 0\n\t\t\t\t? Math.trunc(rawTimeout)\n\t\t\t\t: 30_000;\n\n\t\t// Configure statement timeout once upon connection establishment\n\t\tthis.pool.on(\"connect\", (client) => {\n\t\t\tclient\n\t\t\t\t.query(`SET statement_timeout = ${this.statementTimeoutMs}`)\n\t\t\t\t.catch(() => {});\n\t\t});\n\t}\n\n\tprepare(sql: string): SqlStatement {\n\t\treturn new PostgresStatement(\n\t\t\tthis.pool,\n\t\t\ttranslateD1Sql(rewriteQuestionMarks(sql)),\n\t\t);\n\t}\n\n\tasync batch(\n\t\tstatements: SqlStatement[],\n\t): Promise<Array<{ meta: { changes: number } }>> {\n\t\tconst client = await this.pool.connect();\n\t\ttry {\n\t\t\tawait client.query(\"BEGIN\");\n\t\t\t// SET LOCAL works here because it is inside the transaction.\n\t\t\tawait client.query(\n\t\t\t\t`SET LOCAL statement_timeout = ${this.statementTimeoutMs}`,\n\t\t\t);\n\t\t\tconst out: Array<{ meta: { changes: number } }> = [];\n\t\t\tfor (const s of statements) {\n\t\t\t\tif (!(s instanceof PostgresStatement)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"PostgresAdapter.batch: statement was not produced by PostgresAdapter\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst r = await s.runOnClient(client);\n\t\t\t\tout.push(r);\n\t\t\t}\n\t\t\tawait client.query(\"COMMIT\");\n\t\t\treturn out;\n\t\t} catch (err) {\n\t\t\tawait client.query(\"ROLLBACK\").catch(() => {});\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\tclient.release();\n\t\t}\n\t}\n}\n\nclass PostgresStatement implements SqlStatement {\n\tprivate bound: unknown[] = [];\n\n\tconstructor(\n\t\tprivate readonly pool: Pool,\n\t\tprivate readonly sql: string,\n\t) {}\n\n\tbind(...args: unknown[]): SqlStatement {\n\t\tthis.bound = args;\n\t\treturn this;\n\t}\n\n\tasync first<T = Record<string, unknown>>(): Promise<T | null> {\n\t\tconst result = await this.exec<T & QueryResultRow>();\n\t\treturn (result.rows[0] as T | undefined) ?? null;\n\t}\n\n\tasync all<T = Record<string, unknown>>(): Promise<{ results: T[] }> {\n\t\tconst result = await this.exec<T & QueryResultRow>();\n\t\treturn { results: result.rows as unknown as T[] };\n\t}\n\n\tasync run(): Promise<{ meta: { changes: number } }> {\n\t\tconst result = await this.exec();\n\t\treturn { meta: { changes: result.rowCount ?? 0 } };\n\t}\n\n\t// Internal — used by batch() to run inside an already-checked-out\n\t// client (so the BEGIN/COMMIT span the whole batch).\n\tasync runOnClient(client: {\n\t\tquery: (\n\t\t\ttext: string,\n\t\t\tvalues?: unknown[],\n\t\t) => Promise<{ rowCount: number | null }>;\n\t}): Promise<{ meta: { changes: number } }> {\n\t\tconst r = await client.query(this.sql, this.bound);\n\t\treturn { meta: { changes: r.rowCount ?? 0 } };\n\t}\n\n\tprivate async exec<T extends QueryResultRow = QueryResultRow>(): Promise<{\n\t\trows: T[];\n\t\trowCount: number | null;\n\t}> {\n\t\tconst client = await this.pool.connect();\n\t\ttry {\n\t\t\tconst r = await client.query<T>(this.sql, this.bound);\n\t\t\treturn { rows: r.rows, rowCount: r.rowCount };\n\t\t} finally {\n\t\t\tclient.release();\n\t\t}\n\t}\n}\n\n// D1 → Postgres placeholder rewrite. Walks the string once; tracks\n// whether we're inside a single-quoted string literal so that '?' inside\n// strings isn't rewritten. Doesn't handle dollar-quoted strings — none\n// of the collector's SQL uses them.\nconst rewriteQuestionMarks = (sql: string): string => {\n\tlet out = \"\";\n\tlet inString = false;\n\tlet n = 0;\n\tfor (let i = 0; i < sql.length; i++) {\n\t\tconst ch = sql[i];\n\t\tif (ch === \"'\") {\n\t\t\tinString = !inString;\n\t\t\tout += ch;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === \"?\" && !inString) {\n\t\t\tn += 1;\n\t\t\tout += `$${n}`;\n\t\t\tcontinue;\n\t\t}\n\t\tout += ch;\n\t}\n\treturn out;\n};\n\nconst translateD1Sql = (sql: string): string => {\n\tlet out = sql;\n\tconst hadInsertOrIgnore = /\\bINSERT\\s+OR\\s+IGNORE\\s+INTO\\b/i.test(out);\n\n\tout = out.replace(/\\bINSERT\\s+OR\\s+IGNORE\\s+INTO\\b/gi, \"INSERT INTO\");\n\n\tout = out.replace(\n\t\t/datetime\\('now',\\s*'-'\\s*\\|\\|\\s*(\\$\\d+)\\s*\\|\\|\\s*'\\s*hours'\\)/gi,\n\t\t\"(CURRENT_TIMESTAMP - ($1::text || ' hours')::interval)\",\n\t);\n\tout = out.replace(\n\t\t/datetime\\('now',\\s*'-'\\s*\\|\\|\\s*(\\$\\d+)\\s*\\|\\|\\s*'\\s*minutes'\\)/gi,\n\t\t\"(CURRENT_TIMESTAMP - ($1::text || ' minutes')::interval)\",\n\t);\n\tout = out.replace(\n\t\t/datetime\\('now',\\s*'-(\\d+)\\s+(hour|hours|minute|minutes|day|days)'\\)/gi,\n\t\t\"CURRENT_TIMESTAMP - INTERVAL '$1 $2'\",\n\t);\n\tout = out.replace(/datetime\\('now'\\)/gi, \"CURRENT_TIMESTAMP\");\n\n\tout = out.replace(\n\t\t/json_extract\\(([^,()]+),\\s*'\\$\\.(?:\"([^\"]+)\"|([A-Za-z0-9_\\\\.\\\\\\\\]+))'\\)/gi,\n\t\t(\n\t\t\t_match,\n\t\t\texpr: string,\n\t\t\tquotedKey: string | undefined,\n\t\t\tbareKey: string | undefined,\n\t\t) => {\n\t\t\tconst key = (quotedKey ?? bareKey ?? \"\").replace(\n\t\t\t\t/\\\\\\\\u002E|\\\\u002E/g,\n\t\t\t\t\".\",\n\t\t\t);\n\t\t\treturn `(${expr.trim()}::jsonb ->> '${key.replace(/'/g, \"''\")}')`;\n\t\t},\n\t);\n\n\tout = out.replace(\n\t\t/strftime\\('%Y-%m-%dT%H:%M:00Z',\\s*([^)]+)\\)/gi,\n\t\t\"to_char(date_trunc('minute', $1::timestamp), 'YYYY-MM-DD\\\"T\\\"HH24:MI:00\\\"Z\\\"')\",\n\t);\n\tout = out.replace(\n\t\t/strftime\\('%Y-%m-%dT%H:00:00Z',\\s*([^)]+)\\)/gi,\n\t\t\"to_char(date_trunc('hour', $1::timestamp), 'YYYY-MM-DD\\\"T\\\"HH24:00:00\\\"Z\\\"')\",\n\t);\n\tout = out.replace(\n\t\t/strftime\\('%s',\\s*([^)]+)\\)/gi,\n\t\t\"EXTRACT(EPOCH FROM $1::timestamp)\",\n\t);\n\tif (hadInsertOrIgnore && /\\bON\\s+CONFLICT\\b/i.test(out) === false) {\n\t\tout = out.replace(/(;?\\s*)$/, \" ON CONFLICT DO NOTHING$1\");\n\t}\n\n\treturn out;\n};\n","import {\n\ttype CollectorConfig,\n\tcreateTelemetryCollectorApp,\n} from \"./framework/collector\";\nimport { actionGraphProcessorPlugin } from \"./plugins/action-graph-processor\";\nimport { actionRoutesPlugin } from \"./plugins/action-routes\";\nimport { aiReceiverPlugin } from \"./plugins/ai-receiver\";\nimport { aiSpanPayloadsProcessorPlugin } from \"./plugins/ai-span-payloads-processor\";\nimport {\n\tcreateAlertEvaluatorHandler,\n\tevaluateAllRules,\n} from \"./plugins/alerts-evaluator\";\nimport { alertsRoutesPlugin } from \"./plugins/alerts-routes\";\nimport { analysesRoutesPlugin } from \"./plugins/analyses-routes\";\nimport { askRoutesPlugin } from \"./plugins/ask-routes\";\nimport { botFilterPlugin } from \"./plugins/bot-filter\";\nimport { connectedRoutesPlugin } from \"./plugins/connected-routes\";\nimport { dashboardRoutesPlugin } from \"./plugins/dashboard-routes\";\nimport { defaultSpanEnrichmentPlugin } from \"./plugins/default-span-enrichment\";\nimport { evalCasesRoutesPlugin } from \"./plugins/eval-cases-routes\";\nimport { evidenceRetrievalRoutesPlugin } from \"./plugins/evidence-retrieval-routes\";\nimport { genAiNormalizerPlugin } from \"./plugins/gen-ai-normalizer\";\nimport { identityReceiverPlugin } from \"./plugins/identity-receiver\";\nimport { issueEnrichmentPlugin } from \"./plugins/issue-enrichment\";\nimport { issueInsightsPlugin } from \"./plugins/issue-insights\";\nimport { logsReceiverPlugin } from \"./plugins/logs-receiver\";\nimport { metricsReceiverPlugin } from \"./plugins/metrics-receiver\";\nimport { onboardingRoutesPlugin } from \"./plugins/onboarding-routes\";\nimport { otlpReceiverPlugin } from \"./plugins/otlp-receiver\";\nimport { platformRoutesPlugin } from \"./plugins/platform-routes\";\nimport { profileRoutesPlugin } from \"./plugins/profile-routes\";\nimport { projectsRoutesPlugin } from \"./plugins/projects-routes\";\nimport { queryRoutesPlugin } from \"./plugins/query-routes\";\nimport { redactionProcessorPlugin } from \"./plugins/redaction-processor\";\nimport { replayQueryRoutesPlugin } from \"./plugins/replay-query-routes\";\nimport { replayReceiverPlugin } from \"./plugins/replay-receiver\";\nimport { tailRoutesPlugin } from \"./plugins/tail-routes\";\nimport { timelineRoutesPlugin } from \"./plugins/timeline-routes\";\nimport { uaEnrichmentPlugin } from \"./plugins/ua-enrichment\";\nimport { usageNormalizationPlugin } from \"./plugins/usage-normalization\";\nimport { usagePrivacyPlugin } from \"./plugins/usage-privacy\";\nimport { usageQueryRoutesPlugin } from \"./plugins/usage-query-routes\";\nimport { usageReceiverPlugin } from \"./plugins/usage-receiver\";\nimport { usersQueryRoutesPlugin } from \"./plugins/users-query-routes\";\nimport { utmEnrichmentPlugin } from \"./plugins/utm-enrichment\";\n\nexport { createDashboardAuth } from \"./auth/dashboard-auth\";\nexport { createIngestAuth } from \"./auth/ingest-auth\";\nexport type { TailEvent, TailKind } from \"./durable-objects/tail-hub\";\nexport { TailHub } from \"./durable-objects/tail-hub\";\nexport {\n\ttype CollectorAuthConfig,\n\ttype CollectorConfig,\n\ttype CollectorPlugin,\n\ttype CollectorRuntime,\n\tcreateAnalysesRunHandler,\n\tcreateRetentionCleanupHandler,\n\tcreateTelemetryCollectorApp,\n\ttype SpanProcessorPlugin,\n\ttype SqlDbFactory,\n\ttype UsageEventProcessorPlugin,\n} from \"./framework/collector\";\n\nexport type {\n\tCollectorApp,\n\tCollectorEnv,\n\tCollectorRouteContext,\n} from \"./framework/env\";\n\nexport type { Logger } from \"./framework/logger\";\nexport { consoleLogger } from \"./framework/logger\";\nexport {\n\ttype ActionRecord,\n\tActionStore,\n\ttype AgentRunRecord,\n\ttype ArtifactRecord,\n\ttype EvalResultRecord,\n\ttype RetrievalEventRecord,\n\ttype ToolCallRecord,\n} from \"./lib/actions-store\";\nexport { AlertsStore, compareValue } from \"./lib/alerts-store\";\nexport {\n\ttype BlobListOptions,\n\ttype BlobListResult,\n\ttype BlobObject,\n\ttype BlobPutOptions,\n\ttype BlobStore,\n\tBlobStoreToR2Adapter,\n\tR2BlobStore,\n} from \"./lib/blob-store\";\nexport { S3BlobStore, type S3BlobStoreOptions } from \"./lib/blob-store-s3\";\nexport {\n\ttype EvalCase,\n\ttype EvalCaseInput,\n\ttype EvalCaseListOptions,\n\ttype EvalCaseSourceLinks,\n\tEvalCaseSourceNotFoundError,\n\ttype EvalCaseSourceType,\n\tEvalCasesStore,\n\ttype EvalRun,\n\ttype EvalRunCandidate,\n\ttype EvalRunInput,\n\ttype EvalRunSourceCase,\n\ttype EvalRunStatus,\n\ttype EvalRunsListOptions,\n\tisEvalCaseSourceType,\n\tisEvalRunStatus,\n} from \"./lib/eval-cases-store\";\nexport { MetricsStore } from \"./lib/metrics-store\";\nexport { ProjectsStore } from \"./lib/projects-store\";\nexport { D1Adapter, type SqlDb, type SqlStatement } from \"./lib/sql-db\";\nexport {\n\tPostgresAdapter,\n\ttype PostgresAdapterOptions,\n} from \"./lib/sql-db-postgres\";\nexport {\n\tactionRoutesPlugin,\n\taiReceiverPlugin,\n\taiSpanPayloadsProcessorPlugin,\n\talertsRoutesPlugin,\n\tanalysesRoutesPlugin,\n\taskRoutesPlugin,\n\tbotFilterPlugin,\n\tconnectedRoutesPlugin,\n\tcreateAlertEvaluatorHandler,\n\tdashboardRoutesPlugin,\n\tdefaultSpanEnrichmentPlugin,\n\tevalCasesRoutesPlugin,\n\tevaluateAllRules,\n\tevidenceRetrievalRoutesPlugin,\n\tgenAiNormalizerPlugin,\n\tidentityReceiverPlugin,\n\tissueEnrichmentPlugin,\n\tissueInsightsPlugin,\n\tlogsReceiverPlugin,\n\tmetricsReceiverPlugin,\n\tonboardingRoutesPlugin,\n\totlpReceiverPlugin,\n\tplatformRoutesPlugin,\n\tprofileRoutesPlugin,\n\tprojectsRoutesPlugin,\n\tqueryRoutesPlugin,\n\tredactionProcessorPlugin,\n\treplayQueryRoutesPlugin,\n\treplayReceiverPlugin,\n\ttailRoutesPlugin,\n\ttimelineRoutesPlugin,\n\tuaEnrichmentPlugin,\n\tusageNormalizationPlugin,\n\tusagePrivacyPlugin,\n\tusageQueryRoutesPlugin,\n\tusageReceiverPlugin,\n\tusersQueryRoutesPlugin,\n\tutmEnrichmentPlugin,\n};\n\n/** All built-in plugins in recommended registration order */\nexport const allPlugins = [\n\tdefaultSpanEnrichmentPlugin,\n\tissueEnrichmentPlugin,\n\tredactionProcessorPlugin,\n\t// Normalize vendor gen_ai.* attrs → OpenInference before payload routing.\n\tgenAiNormalizerPlugin,\n\tactionGraphProcessorPlugin,\n\t// Must run after redaction + normalization so stored payloads reflect the\n\t// redacted form and cover both native-SDK and gen_ai spans.\n\taiSpanPayloadsProcessorPlugin,\n\tusageNormalizationPlugin,\n\tusagePrivacyPlugin,\n\tuaEnrichmentPlugin,\n\tbotFilterPlugin,\n\tutmEnrichmentPlugin,\n\totlpReceiverPlugin,\n\tusageReceiverPlugin,\n\tlogsReceiverPlugin,\n\tmetricsReceiverPlugin,\n\taiReceiverPlugin,\n\tidentityReceiverPlugin,\n\treplayReceiverPlugin,\n\tissueInsightsPlugin,\n\tonboardingRoutesPlugin,\n\tprojectsRoutesPlugin,\n\tqueryRoutesPlugin,\n\tusageQueryRoutesPlugin,\n\tusersQueryRoutesPlugin,\n\treplayQueryRoutesPlugin,\n\talertsRoutesPlugin,\n\tanalysesRoutesPlugin,\n\tactionRoutesPlugin,\n\tevalCasesRoutesPlugin,\n\tevidenceRetrievalRoutesPlugin,\n\taskRoutesPlugin,\n\ttailRoutesPlugin,\n\ttimelineRoutesPlugin,\n\tconnectedRoutesPlugin,\n\tprofileRoutesPlugin,\n\tdashboardRoutesPlugin,\n];\n\nexport const createDefaultCollectorApp = (config?: Partial<CollectorConfig>) =>\n\tcreateTelemetryCollectorApp({\n\t\tplugins: config?.plugins ?? [...allPlugins, platformRoutesPlugin],\n\t\tauth: config?.auth,\n\t\tallowedOrigins: config?.allowedOrigins,\n\t\tdashboardAuth: config?.dashboardAuth,\n\t\tlogger: config?.logger,\n\t\twithChildSpan: config?.withChildSpan,\n\t\tsqlDb: config?.sqlDb,\n\t});\n\nexport default createTelemetryCollectorApp(allPlugins);\n"],"mappings":"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","names":["placeholders","EVIDENCE_REFERENCE_CONTRACT","EVIDENCE_REFERENCE_CONTRACT","placeholders","latest","clampInt","placeholders","durationMs","latest","cutoffIso","processor","ACTION_CAUSED_BY_ID_KEY","ACTION_CONFIDENCE_KEY","ACTION_ID_KEY","ACTION_KIND_KEY","ACTION_ROOT_ID_KEY","AGENT_RUN_ID_KEY","ACTION_ID_KEY","ACTION_KIND_KEY","ACTION_ROOT_ID_KEY","ACTION_CONFIDENCE_KEY","ACTION_CAUSED_BY_ID_KEY","durationMs","AGENT_RUN_ID_KEY","getConfiguredRetentionHours","percentile","ActionConfidence","ACTION_CONFIDENCE_KEY","ACTION_ID_KEY","ACTION_ID_RE","ActionConfidence","ActionConfidence","placeholders","placeholders","getConfiguredRetentionHours","EVIDENCE_REFERENCE_CONTRACT","getConfiguredRetentionHours","getConfiguredRetentionHours","EVIDENCE_REFERENCE_CONTRACT","ACTION_ID_KEY","AI_PAYLOAD_INPUT_KEY","AI_PAYLOAD_OUTPUT_KEY","OPENINFERENCE_SPAN_KIND_KEY","OPENINFERENCE_SPAN_KIND_KEY","AI_PAYLOAD_INPUT_KEY","AI_PAYLOAD_OUTPUT_KEY","ACTION_ID_KEY","EVIDENCE_REFERENCE_CONTRACT","SIGNALS","EVIDENCE_REFERENCE_CONTRACT","EVIDENCE_REFERENCE_CONTRACT","EVIDENCE_REFERENCE_CONTRACT","getConfiguredRetentionHours","latest","getConfiguredRetentionHours","EVIDENCE_REFERENCE_CONTRACT","EVIDENCE_REFERENCE_CONTRACT","ActionConfidence","ActionConfidence","placeholders","INTERACTION_ID_KEY","SESSION_ID_KEY","SESSION_ID_KEY","INTERACTION_ID_KEY","EVIDENCE_REFERENCE_CONTRACT","EVIDENCE_REFERENCE_CONTRACT","parseJsonField","EVIDENCE_REFERENCE_CONTRACT","EVIDENCE_REFERENCE_CONTRACT","mapWithConcurrency","LOG_SEVERITIES","clampInt","profileId","manifest","profiles","traceId","bundle","limit","ACTION_CAUSED_BY_ID_KEY","ACTION_CONFIDENCE_KEY","ACTION_ID_KEY","ACTION_KIND_KEY","ACTION_ROOT_ID_KEY","ACTOR_TYPE_KEY","AGENT_RUN_ID_KEY","AI_PAYLOAD_INPUT_KEY","AI_PAYLOAD_OUTPUT_KEY","OPENINFERENCE_SPAN_KIND_KEY","TOOL_ARGS_KEY","TOOL_CALL_ID_KEY","TOOL_NAME_KEY","TOOL_SIDE_EFFECT_KEY","toJsonString","OPENINFERENCE_SPAN_KIND_KEY","ACTION_ID_KEY","ACTION_CONFIDENCE_KEY","ACTION_ROOT_ID_KEY","ACTION_CAUSED_BY_ID_KEY","ACTOR_TYPE_KEY","AGENT_RUN_ID_KEY","ACTION_KIND_KEY","TOOL_CALL_ID_KEY","TOOL_NAME_KEY","TOOL_ARGS_KEY","AI_PAYLOAD_INPUT_KEY","TOOL_SIDE_EFFECT_KEY","AI_PAYLOAD_OUTPUT_KEY","DEFAULT_WINDOW_HOURS","DEFAULT_WINDOW_HOURS","parseLimit","getConfiguredRetentionHours","fileDesc","messageDesc","fileDesc","messageDesc","fileDesc","messageDesc","fileDesc","fileDesc","fileDesc","messageDesc","fromBinary","fromJson","fileDesc","messageDesc","serviceDesc","enumDesc","fileDesc","messageDesc","fileDesc","fileDesc","messageDesc","fromBinary","fromJson","fromBinary","fromJson","fileDesc","messageDesc","serviceDesc","enumDesc","fileDesc","messageDesc","fileDesc","fileDesc","messageDesc","fromBinary","fromJson","getConfiguredRetentionHours","getConfiguredRetentionHours","getConfiguredRetentionHours","getConfiguredRetentionHours","DEFAULT_WINDOW_HOURS","getConfiguredRetentionHours","anyValueToJson","keyValuesToRecord","spans","getConfiguredRetentionHours","TRACE_ID_RE","durationMs","rows","DEFAULT_WINDOW_HOURS","getConfiguredRetentionHours","getConfiguredRetentionHours","DEFAULT_WINDOW_HOURS","shouldRedactKey","processor","normalizePathSegment","normalizePath","REDACTED_VALUE","DEFAULT_REDACT_FIELDS","shouldRedactKey","DEFAULT_WINDOW_HOURS","getConfiguredRetentionHours","getConfiguredRetentionHours","DEFAULT_WINDOW_HOURS","DEFAULT_WINDOW_HOURS","getConfiguredRetentionHours","getConfiguredRetentionHours","DEFAULT_WINDOW_HOURS","processor","streamToBytes"]}
|