modelrig 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +41 -11
  3. package/data/PROVENANCE.md +19 -0
  4. package/data/pricing-manual.json +22 -0
  5. package/data/pricing-map.json +46362 -0
  6. package/data/pricing-overlay.json +419 -0
  7. package/dist/adapters/anthropic.d.ts +50 -6
  8. package/dist/adapters/anthropic.d.ts.map +1 -1
  9. package/dist/adapters/anthropic.js +123 -29
  10. package/dist/adapters/build-adapters.d.ts +11 -0
  11. package/dist/adapters/build-adapters.d.ts.map +1 -0
  12. package/dist/adapters/build-adapters.js +45 -0
  13. package/dist/adapters/deepseek.d.ts +6 -0
  14. package/dist/adapters/deepseek.d.ts.map +1 -1
  15. package/dist/adapters/deepseek.js +54 -1
  16. package/dist/adapters/gemini.d.ts.map +1 -1
  17. package/dist/adapters/gemini.js +46 -6
  18. package/dist/adapters/grok.d.ts +9 -0
  19. package/dist/adapters/grok.d.ts.map +1 -1
  20. package/dist/adapters/grok.js +67 -3
  21. package/dist/adapters/openai-compat.d.ts +6 -0
  22. package/dist/adapters/openai-compat.d.ts.map +1 -1
  23. package/dist/adapters/openai-compat.js +58 -1
  24. package/dist/adapters/openai-stream.d.ts +58 -0
  25. package/dist/adapters/openai-stream.d.ts.map +1 -0
  26. package/dist/adapters/openai-stream.js +120 -0
  27. package/dist/adapters/openai.d.ts +6 -0
  28. package/dist/adapters/openai.d.ts.map +1 -1
  29. package/dist/adapters/openai.js +60 -1
  30. package/dist/adapters/sampling.d.ts +28 -0
  31. package/dist/adapters/sampling.d.ts.map +1 -0
  32. package/dist/adapters/sampling.js +34 -0
  33. package/dist/adapters/tool-mapping.d.ts +92 -0
  34. package/dist/adapters/tool-mapping.d.ts.map +1 -0
  35. package/dist/adapters/tool-mapping.js +143 -0
  36. package/dist/artifacts/artifact.d.ts +137 -0
  37. package/dist/artifacts/artifact.d.ts.map +1 -0
  38. package/dist/artifacts/artifact.js +377 -0
  39. package/dist/artifacts/content-uploader.d.ts +87 -0
  40. package/dist/artifacts/content-uploader.d.ts.map +1 -0
  41. package/dist/artifacts/content-uploader.js +124 -0
  42. package/dist/artifacts/index.d.ts +63 -0
  43. package/dist/artifacts/index.d.ts.map +1 -0
  44. package/dist/artifacts/index.js +80 -0
  45. package/dist/artifacts/run-context.d.ts +129 -0
  46. package/dist/artifacts/run-context.d.ts.map +1 -0
  47. package/dist/artifacts/run-context.js +208 -0
  48. package/dist/artifacts/scrub.d.ts +60 -0
  49. package/dist/artifacts/scrub.d.ts.map +1 -0
  50. package/dist/artifacts/scrub.js +139 -0
  51. package/dist/artifacts/step.d.ts +26 -0
  52. package/dist/artifacts/step.d.ts.map +1 -0
  53. package/dist/artifacts/step.js +37 -0
  54. package/dist/artifacts/taint.d.ts +63 -0
  55. package/dist/artifacts/taint.d.ts.map +1 -0
  56. package/dist/artifacts/taint.js +76 -0
  57. package/dist/bakeoff/cache-sim.d.ts +99 -0
  58. package/dist/bakeoff/cache-sim.d.ts.map +1 -0
  59. package/dist/bakeoff/cache-sim.js +126 -0
  60. package/dist/bakeoff/eval-cases.d.ts +96 -0
  61. package/dist/bakeoff/eval-cases.d.ts.map +1 -0
  62. package/dist/bakeoff/eval-cases.js +105 -0
  63. package/dist/bakeoff/report.d.ts +41 -0
  64. package/dist/bakeoff/report.d.ts.map +1 -0
  65. package/dist/bakeoff/report.js +142 -0
  66. package/dist/bakeoff/samples.d.ts +15 -0
  67. package/dist/bakeoff/samples.d.ts.map +1 -1
  68. package/dist/bakeoff/samples.js +20 -0
  69. package/dist/cli.d.ts +1 -3
  70. package/dist/cli.d.ts.map +1 -1
  71. package/dist/cli.js +134 -116
  72. package/dist/config.d.ts +100 -0
  73. package/dist/config.d.ts.map +1 -1
  74. package/dist/config.js +104 -0
  75. package/dist/deprecations.d.ts +32 -0
  76. package/dist/deprecations.d.ts.map +1 -0
  77. package/dist/deprecations.js +59 -0
  78. package/dist/gateway/http-protocol.d.ts +175 -0
  79. package/dist/gateway/http-protocol.d.ts.map +1 -0
  80. package/dist/gateway/http-protocol.js +105 -0
  81. package/dist/index.d.ts +105 -18
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +266 -138
  84. package/dist/init/finder.d.ts +15 -0
  85. package/dist/init/finder.d.ts.map +1 -1
  86. package/dist/init/finder.js +46 -0
  87. package/dist/init/init-cli.d.ts +10 -0
  88. package/dist/init/init-cli.d.ts.map +1 -0
  89. package/dist/init/init-cli.js +86 -0
  90. package/dist/init/observe-cli.d.ts +19 -0
  91. package/dist/init/observe-cli.d.ts.map +1 -0
  92. package/dist/init/observe-cli.js +73 -0
  93. package/dist/init/observe.d.ts +81 -0
  94. package/dist/init/observe.d.ts.map +1 -0
  95. package/dist/init/observe.js +245 -0
  96. package/dist/registry/build.d.ts +94 -1
  97. package/dist/registry/build.d.ts.map +1 -1
  98. package/dist/registry/build.js +125 -4
  99. package/dist/registry/cache-policy.d.ts +94 -0
  100. package/dist/registry/cache-policy.d.ts.map +1 -0
  101. package/dist/registry/cache-policy.js +238 -0
  102. package/dist/registry/call-notes.d.ts.map +1 -1
  103. package/dist/registry/call-notes.js +40 -2
  104. package/dist/registry/effective-rate.d.ts +151 -0
  105. package/dist/registry/effective-rate.d.ts.map +1 -0
  106. package/dist/registry/effective-rate.js +156 -0
  107. package/dist/registry/facts.d.ts.map +1 -1
  108. package/dist/registry/facts.js +16 -0
  109. package/dist/registry/parity.d.ts +26 -0
  110. package/dist/registry/parity.d.ts.map +1 -1
  111. package/dist/registry/parity.js +43 -2
  112. package/dist/registry/pricing-shape.d.ts +113 -0
  113. package/dist/registry/pricing-shape.d.ts.map +1 -0
  114. package/dist/registry/pricing-shape.js +123 -0
  115. package/dist/registry/pricing.d.ts +25 -1
  116. package/dist/registry/pricing.d.ts.map +1 -1
  117. package/dist/registry/pricing.js +64 -6
  118. package/dist/rigindex/bootstrap.d.ts +36 -0
  119. package/dist/rigindex/bootstrap.d.ts.map +1 -0
  120. package/dist/rigindex/bootstrap.js +97 -0
  121. package/dist/rigindex/fit.d.ts +24 -0
  122. package/dist/rigindex/fit.d.ts.map +1 -0
  123. package/dist/rigindex/fit.js +76 -0
  124. package/dist/rigindex/gates.d.ts +52 -0
  125. package/dist/rigindex/gates.d.ts.map +1 -0
  126. package/dist/rigindex/gates.js +109 -0
  127. package/dist/rigindex/graph.d.ts +31 -0
  128. package/dist/rigindex/graph.d.ts.map +1 -0
  129. package/dist/rigindex/graph.js +120 -0
  130. package/dist/rigindex/index.d.ts +23 -0
  131. package/dist/rigindex/index.d.ts.map +1 -0
  132. package/dist/rigindex/index.js +112 -0
  133. package/dist/rigindex/types.d.ts +76 -0
  134. package/dist/rigindex/types.d.ts.map +1 -0
  135. package/dist/rigindex/types.js +8 -0
  136. package/dist/routes/cache-lint.d.ts +41 -0
  137. package/dist/routes/cache-lint.d.ts.map +1 -0
  138. package/dist/routes/cache-lint.js +81 -0
  139. package/dist/routes/loader.d.ts +37 -0
  140. package/dist/routes/loader.d.ts.map +1 -1
  141. package/dist/routes/loader.js +138 -0
  142. package/dist/routes/resolved-bundle.d.ts +79 -0
  143. package/dist/routes/resolved-bundle.d.ts.map +1 -0
  144. package/dist/routes/resolved-bundle.js +148 -0
  145. package/dist/routes/sampling-config.d.ts +32 -0
  146. package/dist/routes/sampling-config.d.ts.map +1 -0
  147. package/dist/routes/sampling-config.js +91 -0
  148. package/dist/run/ajv.d.ts +22 -0
  149. package/dist/run/ajv.d.ts.map +1 -0
  150. package/dist/run/ajv.js +32 -0
  151. package/dist/run/cache-handle.d.ts +58 -0
  152. package/dist/run/cache-handle.d.ts.map +1 -0
  153. package/dist/run/cache-handle.js +54 -0
  154. package/dist/run/cache-stamp.d.ts +65 -0
  155. package/dist/run/cache-stamp.d.ts.map +1 -0
  156. package/dist/run/cache-stamp.js +0 -0
  157. package/dist/run/capture-write.d.ts +33 -0
  158. package/dist/run/capture-write.d.ts.map +1 -0
  159. package/dist/run/capture-write.js +55 -0
  160. package/dist/run/cost.d.ts.map +1 -1
  161. package/dist/run/cost.js +1 -1
  162. package/dist/run/dispatch.d.ts +99 -0
  163. package/dist/run/dispatch.d.ts.map +1 -0
  164. package/dist/run/dispatch.js +191 -0
  165. package/dist/run/raw.d.ts +88 -0
  166. package/dist/run/raw.d.ts.map +1 -0
  167. package/dist/run/raw.js +286 -0
  168. package/dist/run/record-attempt.d.ts +40 -0
  169. package/dist/run/record-attempt.d.ts.map +1 -0
  170. package/dist/run/record-attempt.js +99 -0
  171. package/dist/run/resolve.d.ts +75 -2
  172. package/dist/run/resolve.d.ts.map +1 -1
  173. package/dist/run/resolve.js +126 -4
  174. package/dist/run/run.d.ts +14 -0
  175. package/dist/run/run.d.ts.map +1 -1
  176. package/dist/run/run.js +0 -0
  177. package/dist/run/stream.d.ts +49 -0
  178. package/dist/run/stream.d.ts.map +1 -0
  179. package/dist/run/stream.js +87 -0
  180. package/dist/run/validate.d.ts.map +1 -1
  181. package/dist/run/validate.js +6 -7
  182. package/dist/savings/cache-ledger.d.ts +108 -0
  183. package/dist/savings/cache-ledger.d.ts.map +1 -0
  184. package/dist/savings/cache-ledger.js +174 -0
  185. package/dist/savings/cache-reconcile.d.ts +64 -0
  186. package/dist/savings/cache-reconcile.d.ts.map +1 -0
  187. package/dist/savings/cache-reconcile.js +59 -0
  188. package/dist/savings/cache-stats.d.ts +63 -0
  189. package/dist/savings/cache-stats.d.ts.map +1 -0
  190. package/dist/savings/cache-stats.js +108 -0
  191. package/dist/savings/emit.d.ts +13 -0
  192. package/dist/savings/emit.d.ts.map +1 -1
  193. package/dist/savings/emit.js +25 -0
  194. package/dist/savings/swap-execute.d.ts +14 -0
  195. package/dist/savings/swap-execute.d.ts.map +1 -1
  196. package/dist/savings/swap-execute.js +44 -1
  197. package/dist/savings/swaps-client.d.ts +14 -0
  198. package/dist/savings/swaps-client.d.ts.map +1 -1
  199. package/dist/savings/swaps-client.js +16 -2
  200. package/dist/settings/api-fetcher.d.ts +39 -0
  201. package/dist/settings/api-fetcher.d.ts.map +1 -0
  202. package/dist/settings/api-fetcher.js +92 -0
  203. package/dist/settings/index.d.ts +10 -0
  204. package/dist/settings/index.d.ts.map +1 -0
  205. package/dist/settings/index.js +15 -0
  206. package/dist/settings/task-settings.d.ts +91 -0
  207. package/dist/settings/task-settings.d.ts.map +1 -0
  208. package/dist/settings/task-settings.js +116 -0
  209. package/dist/status.d.ts +77 -0
  210. package/dist/status.d.ts.map +1 -0
  211. package/dist/status.js +113 -0
  212. package/dist/telemetry/artifact-store.d.ts +48 -0
  213. package/dist/telemetry/artifact-store.d.ts.map +1 -0
  214. package/dist/telemetry/artifact-store.js +189 -0
  215. package/dist/telemetry/cache-miss-streak.d.ts +79 -0
  216. package/dist/telemetry/cache-miss-streak.d.ts.map +1 -0
  217. package/dist/telemetry/cache-miss-streak.js +99 -0
  218. package/dist/telemetry/capture.d.ts +3 -0
  219. package/dist/telemetry/capture.d.ts.map +1 -1
  220. package/dist/telemetry/capture.js +15 -8
  221. package/dist/telemetry/exporter-setup.d.ts +28 -0
  222. package/dist/telemetry/exporter-setup.d.ts.map +1 -0
  223. package/dist/telemetry/exporter-setup.js +34 -0
  224. package/dist/telemetry/exporter.d.ts +75 -0
  225. package/dist/telemetry/exporter.d.ts.map +1 -1
  226. package/dist/telemetry/exporter.js +324 -47
  227. package/dist/telemetry/health.d.ts +76 -0
  228. package/dist/telemetry/health.d.ts.map +1 -0
  229. package/dist/telemetry/health.js +92 -0
  230. package/dist/telemetry/ingest-protocol.d.ts +152 -3
  231. package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
  232. package/dist/telemetry/ingest-protocol.js +204 -4
  233. package/dist/telemetry/load-error-report.d.ts +24 -0
  234. package/dist/telemetry/load-error-report.d.ts.map +1 -0
  235. package/dist/telemetry/load-error-report.js +50 -0
  236. package/dist/telemetry/otel-map.d.ts +121 -0
  237. package/dist/telemetry/otel-map.d.ts.map +1 -0
  238. package/dist/telemetry/otel-map.js +224 -0
  239. package/dist/telemetry/otel-normalize.d.ts +104 -0
  240. package/dist/telemetry/otel-normalize.d.ts.map +1 -0
  241. package/dist/telemetry/otel-normalize.js +530 -0
  242. package/dist/telemetry/otlp-emitter.d.ts +52 -0
  243. package/dist/telemetry/otlp-emitter.d.ts.map +1 -0
  244. package/dist/telemetry/otlp-emitter.js +144 -0
  245. package/dist/telemetry/otlp-proto.d.ts +29 -0
  246. package/dist/telemetry/otlp-proto.d.ts.map +1 -0
  247. package/dist/telemetry/otlp-proto.js +266 -0
  248. package/dist/telemetry/sinks.d.ts +37 -1
  249. package/dist/telemetry/sinks.d.ts.map +1 -1
  250. package/dist/telemetry/sinks.js +121 -30
  251. package/dist/telemetry/store.d.ts +28 -1
  252. package/dist/telemetry/store.d.ts.map +1 -1
  253. package/dist/telemetry/store.js +218 -3
  254. package/dist/tenancy/api-key-format.d.ts +15 -5
  255. package/dist/tenancy/api-key-format.d.ts.map +1 -1
  256. package/dist/tenancy/api-key-format.js +24 -5
  257. package/dist/types/config-teaching.d.ts +62 -0
  258. package/dist/types/config-teaching.d.ts.map +1 -0
  259. package/dist/types/config-teaching.js +183 -0
  260. package/dist/types/provider.d.ts +122 -1
  261. package/dist/types/provider.d.ts.map +1 -1
  262. package/dist/types/provider.js +21 -1
  263. package/dist/types/route.d.ts +79 -1
  264. package/dist/types/route.d.ts.map +1 -1
  265. package/dist/types/telemetry.d.ts +117 -0
  266. package/dist/types/telemetry.d.ts.map +1 -1
  267. package/dist/validate-cli.d.ts +12 -0
  268. package/dist/validate-cli.d.ts.map +1 -0
  269. package/dist/validate-cli.js +57 -0
  270. package/dist/verify/capture.d.ts +66 -0
  271. package/dist/verify/capture.d.ts.map +1 -0
  272. package/dist/verify/capture.js +180 -0
  273. package/dist/verify/cli-run.d.ts +23 -0
  274. package/dist/verify/cli-run.d.ts.map +1 -0
  275. package/dist/verify/cli-run.js +57 -0
  276. package/dist/verify/diff.d.ts +48 -0
  277. package/dist/verify/diff.d.ts.map +1 -0
  278. package/dist/verify/diff.js +157 -0
  279. package/dist/verify/index.d.ts +17 -0
  280. package/dist/verify/index.d.ts.map +1 -0
  281. package/dist/verify/index.js +24 -0
  282. package/dist/verify/report.d.ts +14 -0
  283. package/dist/verify/report.d.ts.map +1 -0
  284. package/dist/verify/report.js +88 -0
  285. package/dist/verify/types.d.ts +101 -0
  286. package/dist/verify/types.d.ts.map +1 -0
  287. package/dist/verify/types.js +17 -0
  288. package/dist/verify/verify.d.ts +29 -0
  289. package/dist/verify/verify.d.ts.map +1 -0
  290. package/dist/verify/verify.js +148 -0
  291. package/dist/watch/evaluate.d.ts +162 -3
  292. package/dist/watch/evaluate.d.ts.map +1 -1
  293. package/dist/watch/evaluate.js +61 -0
  294. package/dist/watch/monitor.d.ts +116 -0
  295. package/dist/watch/monitor.d.ts.map +1 -0
  296. package/dist/watch/monitor.js +199 -0
  297. package/dist/watch/proposals.d.ts +20 -4
  298. package/dist/watch/proposals.d.ts.map +1 -1
  299. package/dist/watch/proposals.js +31 -3
  300. package/dist/watch/run.d.ts +33 -0
  301. package/dist/watch/run.d.ts.map +1 -1
  302. package/dist/watch/run.js +39 -0
  303. package/package.json +7 -1
  304. package/registry/LICENSE +20 -0
  305. package/registry/leaderboard.json +3639 -0
  306. package/registry/registry.json +7263 -0
  307. package/dist/telemetry/supabase-exporter.d.ts +0 -64
  308. package/dist/telemetry/supabase-exporter.d.ts.map +0 -1
  309. package/dist/telemetry/supabase-exporter.js +0 -211
@@ -0,0 +1,530 @@
1
+ "use strict";
2
+ /**
3
+ * OTLP-in v0 normalizer — Expansion E3-Harvest (spec §3). PURE: no I/O, no env,
4
+ * no imports from the exporter/sinks/server. The INBOUND sibling of `otel-map.ts`
5
+ * (which is the OUTBOUND our-rows → OTLP mapper). Foreign OTLP spans in →
6
+ * `runs` + attested `steps` out.
7
+ *
8
+ * ── SCOPE (spec §3.1): identity, structure, timing, status, model/provider,
9
+ * usage ONLY. ZERO content extraction — prompts/completions/messages in foreign
10
+ * spans are never read, never stored, never passed to the envelope. Retention-
11
+ * free default; content custody arrives with E2-C. This deletes ~60% of
12
+ * Langfuse's problem surface deliberately.
13
+ *
14
+ * ── VINTAGE HANDLING is pure NAME-UNION, not versioned dispatch (learnings
15
+ * §1.1, their proven approach), with our two divergences (spec §3.3):
16
+ * (1) namespaced attributes outrank bare ones — `gen_ai.*`/`llm.*` are checked
17
+ * BEFORE a bare `model`;
18
+ * (2) provider IS normalized (Langfuse never reads provider on ingest), because
19
+ * `model_key = provider/model` feeds our registry/priors/leaderboard —
20
+ * recorded honestly, ending at "unknown", never guessed.
21
+ *
22
+ * The usage de-double-counting and the agent-span aggregate skip are adopted
23
+ * from OtelIngestionProcessor's generic extractor (learnings §1.2, read for
24
+ * pattern per §5.3 — implemented fresh here, no bodies copied).
25
+ */
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.normalizeOtlpTraces = normalizeOtlpTraces;
28
+ exports.looksLikeLogsPayload = looksLikeLogsPayload;
29
+ const node_crypto_1 = require("node:crypto");
30
+ // ── value coercion (learnings §1.2, ported fresh) ────────────────────────────
31
+ /** OTLP AnyValue → plain JS. Numeric strings coerce EXCEPT NaN/±Infinity which
32
+ * stay as their string form (invalid JSON must never enter the envelope). int64
33
+ * arrives as number | decimal-string | protobuf Long `{high,low}`. Unparseable
34
+ * → undefined, never NaN. */
35
+ function coerceAnyValue(v) {
36
+ if (v === undefined || v === null)
37
+ return undefined;
38
+ if (typeof v.stringValue === "string")
39
+ return v.stringValue;
40
+ if (v.boolValue !== undefined)
41
+ return v.boolValue;
42
+ if (v.doubleValue !== undefined) {
43
+ if (typeof v.doubleValue === "string") {
44
+ const parsed = Number(v.doubleValue);
45
+ return Number.isFinite(parsed) ? parsed : v.doubleValue;
46
+ }
47
+ return v.doubleValue;
48
+ }
49
+ if (v.intValue !== undefined)
50
+ return coerceIntValue(v.intValue);
51
+ if (isRecord(v.arrayValue) && Array.isArray(v.arrayValue.values)) {
52
+ return v.arrayValue.values.map(coerceAnyValue);
53
+ }
54
+ // kvlistValue / bytesValue are content-adjacent shapes — not read in v0.
55
+ return undefined;
56
+ }
57
+ function coerceIntValue(intValue) {
58
+ if (typeof intValue === "number")
59
+ return intValue;
60
+ if (typeof intValue === "string") {
61
+ const parsed = Number(intValue);
62
+ return Number.isNaN(parsed) ? undefined : parsed;
63
+ }
64
+ if (isRecord(intValue)) {
65
+ const high = intValue.high;
66
+ const low = intValue.low;
67
+ if (high === 0)
68
+ return typeof low === "number" ? low : undefined;
69
+ if (high === -1 && low === -1)
70
+ return -1;
71
+ if (typeof high === "number" && typeof low === "number") {
72
+ return high * 2 ** 32 + low;
73
+ }
74
+ }
75
+ return undefined;
76
+ }
77
+ function isRecord(v) {
78
+ return typeof v === "object" && v !== null && !Array.isArray(v);
79
+ }
80
+ /** Prototype-safe own-property check (the modelrig package targets < es2022, so
81
+ * `Object.hasOwn` is unavailable). Same contract: a key literally named
82
+ * "__proto__"/"toString" is NOT matched via the prototype chain. */
83
+ function hasOwn(obj, key) {
84
+ return Object.prototype.hasOwnProperty.call(obj, key);
85
+ }
86
+ /** Flatten a span's KeyValue attributes into a `name → value` map. Content-only
87
+ * shapes (kvlist/bytes) yield undefined and are dropped. */
88
+ function attrMap(attributes) {
89
+ // null-proto object (langfuse's flattened-key discipline): a key literally
90
+ // named "__proto__"/"constructor" becomes a normal own property instead of
91
+ // touching the prototype — no pollution, and hasOwn stays total.
92
+ const map = Object.create(null);
93
+ const keys = [];
94
+ for (const kv of attributes ?? []) {
95
+ if (typeof kv?.key !== "string")
96
+ continue;
97
+ const value = coerceAnyValue(kv.value);
98
+ if (value === undefined)
99
+ continue;
100
+ map[kv.key] = value;
101
+ keys.push(kv.key);
102
+ }
103
+ return { map, keys };
104
+ }
105
+ /** First present + string-coercible attribute across a priority chain. */
106
+ function firstAttr(map, chain) {
107
+ for (const key of chain) {
108
+ if (hasOwn(map, key)) {
109
+ const v = map[key];
110
+ if (typeof v === "string" && v !== "")
111
+ return v;
112
+ if (typeof v === "number" || typeof v === "boolean")
113
+ return String(v);
114
+ }
115
+ }
116
+ return undefined;
117
+ }
118
+ // ── id coercion (spec §3.2: hex string | base64 | byte array | {high,low}) ───
119
+ const HEX_RE = /^[0-9a-fA-F]+$/;
120
+ /** Coerce an OTLP trace/span id to lowercase hex of `byteLen` bytes, or null. */
121
+ function toHexId(v, byteLen) {
122
+ const hexLen = byteLen * 2;
123
+ if (typeof v === "string") {
124
+ if (v === "")
125
+ return null;
126
+ if (HEX_RE.test(v) && v.length === hexLen)
127
+ return v.toLowerCase();
128
+ // OTLP/JSON uses hex, but a protobuf-shaped emitter may base64 the bytes.
129
+ if (/^[A-Za-z0-9+/]+={0,2}$/.test(v)) {
130
+ try {
131
+ const hex = Buffer.from(v, "base64").toString("hex");
132
+ if (hex.length === hexLen && !/^0+$/.test(hex))
133
+ return hex;
134
+ }
135
+ catch {
136
+ /* fallthrough */
137
+ }
138
+ }
139
+ // A hex string of the wrong length is not a valid id.
140
+ return null;
141
+ }
142
+ if (Array.isArray(v)) {
143
+ if (v.length !== byteLen || v.some((b) => typeof b !== "number"))
144
+ return null;
145
+ const hex = v.map((b) => (b & 0xff).toString(16).padStart(2, "0")).join("");
146
+ return /^0+$/.test(hex) ? null : hex;
147
+ }
148
+ return null;
149
+ }
150
+ // ── timestamp coercion (learnings §1.2 / spec §3.3) ──────────────────────────
151
+ /** nanos (decimal string | number | protobuf {high,low}) → epoch ms, or null. */
152
+ function nanoToMs(v) {
153
+ if (typeof v === "number")
154
+ return Number.isFinite(v) ? v / 1e6 : null;
155
+ if (typeof v === "string") {
156
+ if (!/^\d+$/.test(v))
157
+ return null;
158
+ try {
159
+ return Number(BigInt(v) / 1000000n);
160
+ }
161
+ catch {
162
+ return null;
163
+ }
164
+ }
165
+ if (isRecord(v) && typeof v.high === "number" && typeof v.low === "number") {
166
+ const nanos = BigInt(v.high) * 2n ** 32n + BigInt(v.low >>> 0);
167
+ return Number(nanos / 1000000n);
168
+ }
169
+ return null;
170
+ }
171
+ // ── priority chains (spec §3.3, learnings §1.3) ──────────────────────────────
172
+ // Namespaced FIRST (our divergence), bare `model` LAST. Langfuse's own
173
+ // langfuse.observation.* keys are their namespace — dropped here.
174
+ const MODEL_CHAIN = [
175
+ "gen_ai.response.model",
176
+ "ai.model.id",
177
+ "gen_ai.request.model",
178
+ "llm.response.model",
179
+ "llm.model_name",
180
+ "model",
181
+ ];
182
+ /** Provider chain (spec §3.3): honest, ending at "unknown", NEVER guessed. Note
183
+ * scope names (Vercel "ai", OpenLLMetry) imply nothing about the provider, so
184
+ * there is deliberately no scope→provider guess. */
185
+ const PROVIDER_CHAIN = [
186
+ "gen_ai.provider.name",
187
+ "gen_ai.system", // deprecated
188
+ "ai.model.provider",
189
+ ];
190
+ // Episode chain (spec §3.3). ⚠ ARCHITECT FLAG (P2 — do not silently change the
191
+ // frozen spec): `runs` has an index on (org_id, episode_key). The LIVE ModelRig
192
+ // DB has it NON-unique (`idx_runs_org_episode`), so mapping a trace-spanning
193
+ // `gen_ai.conversation.id` to episode_key is safe there. But the migration 00029
194
+ // FILE declares it UNIQUE (`uq_runs_org_episode`); a fresh env built from files
195
+ // would then 23505 when two attested traces (each its own run) share one
196
+ // conversation id — breaking the whole batch. Either the file must drop UNIQUE,
197
+ // or attested runs must not populate episode_key. Left spec-compliant pending
198
+ // the architect's ruling; flagged in verification.md.
199
+ const EPISODE_CHAIN = ["modelrig.run.id", "gen_ai.conversation.id"];
200
+ const ENVIRONMENT_CHAIN = ["deployment.environment.name", "deployment.environment"];
201
+ const PIPELINE_RESOURCE_CHAIN = ["service.name"];
202
+ /** AI-SDK agent spans whose aggregate usage duplicates their child model span
203
+ * (learnings §1.2 — skip model/usage/cost entirely). */
204
+ const AGENT_OPERATIONS = new Set(["invoke_agent", "agent_step"]);
205
+ // ── usage extraction + de-double-counting (learnings §1.2, ported fresh) ─────
206
+ function extractUsage(map) {
207
+ const raw = {};
208
+ for (const key of Object.keys(map)) {
209
+ if ((key.startsWith("gen_ai.usage.") && key !== "gen_ai.usage.cost") ||
210
+ key.startsWith("llm.token_count.")) {
211
+ const stripped = key.replace("gen_ai.usage.", "").replace("llm.token_count.", "");
212
+ const value = Number(map[key]);
213
+ if (!Number.isNaN(value))
214
+ raw[stripped] = value;
215
+ }
216
+ }
217
+ if (Object.keys(raw).length === 0)
218
+ return undefined;
219
+ const inputTokens = raw["prompt_tokens"] ?? raw["input_tokens"] ?? raw["prompt"];
220
+ const outputTokens = raw["completion_tokens"] ?? raw["output_tokens"] ?? raw["completion"];
221
+ const totalTokens = raw["total_tokens"] ?? raw["total"];
222
+ const cacheReadTokens = raw["cache_read.input_tokens"] ??
223
+ raw["cache_read_input_tokens"] ??
224
+ raw["cache_read_tokens"] ??
225
+ raw["details.cache_read_tokens"] ??
226
+ raw["details.cache_read_input_tokens"] ??
227
+ raw["prompt_details.cache_read"] ??
228
+ raw["input_cached_tokens"];
229
+ const cacheCreationTokens = raw["cache_creation.input_tokens"] ??
230
+ raw["cache_creation_input_tokens"] ??
231
+ raw["cache_write_tokens"] ??
232
+ raw["details.cache_write_tokens"] ??
233
+ raw["details.cache_creation_input_tokens"] ??
234
+ raw["prompt_details.cache_write"] ??
235
+ raw["input_cache_creation"];
236
+ const outputReasoningTokens = raw["reasoning.output_tokens"] ?? raw["completion_details.reasoning"];
237
+ const outputAudioTokens = raw["completion_details.audio"];
238
+ // Buckets that were consumed by the alias resolution above are not re-emitted
239
+ // under their raw names; everything else passes through (details.* flattened).
240
+ const consumed = new Set([
241
+ "prompt_tokens", "input_tokens", "prompt",
242
+ "completion_tokens", "output_tokens", "completion",
243
+ "total_tokens", "total",
244
+ "cache_read.input_tokens", "cache_read_input_tokens", "cache_read_tokens",
245
+ "details.cache_read_tokens", "details.cache_read_input_tokens",
246
+ "prompt_details.cache_read", "input_cached_tokens",
247
+ "cache_creation.input_tokens", "cache_creation_input_tokens", "cache_write_tokens",
248
+ "details.cache_write_tokens", "details.cache_creation_input_tokens",
249
+ "prompt_details.cache_write", "input_cache_creation",
250
+ "reasoning.output_tokens", "completion_details.reasoning", "completion_details.audio",
251
+ ]);
252
+ const usage = {};
253
+ for (const [key, value] of Object.entries(raw)) {
254
+ if (consumed.has(key))
255
+ continue;
256
+ usage[key.startsWith("details.") ? key.replace("details.", "") : key] = value;
257
+ }
258
+ // De-double-counting (adopted verbatim): input −= cache buckets; output −=
259
+ // reasoning + audio; floored at 0. Cached/reasoning tokens are INCLUDED in the
260
+ // provider's prompt/completion totals, so subtracting yields the billable net.
261
+ if (inputTokens !== undefined) {
262
+ usage.input = Math.max(inputTokens - (cacheReadTokens ?? 0) - (cacheCreationTokens ?? 0), 0);
263
+ }
264
+ if (outputTokens !== undefined) {
265
+ usage.output = Math.max(outputTokens - (outputReasoningTokens ?? 0) - (outputAudioTokens ?? 0), 0);
266
+ }
267
+ if (totalTokens !== undefined)
268
+ usage.total = totalTokens;
269
+ if (cacheReadTokens !== undefined)
270
+ usage.input_cached_tokens = cacheReadTokens;
271
+ if (cacheCreationTokens !== undefined)
272
+ usage.input_cache_creation = cacheCreationTokens;
273
+ if (outputReasoningTokens !== undefined)
274
+ usage.output_reasoning_tokens = outputReasoningTokens;
275
+ if (outputAudioTokens !== undefined)
276
+ usage.output_audio_tokens = outputAudioTokens;
277
+ return usage;
278
+ }
279
+ // ── classification registry (spec §3.3: priority-ordered) ────────────────────
280
+ // openinference.span.kind → gen_ai.operation.name → tool-attr presence →
281
+ // model-presence fallback → "span".
282
+ function classify(map) {
283
+ const openinference = firstAttr(map, ["openinference.span.kind"]);
284
+ if (openinference !== undefined)
285
+ return openinference.toLowerCase();
286
+ const operation = firstAttr(map, ["gen_ai.operation.name"]);
287
+ if (operation !== undefined)
288
+ return operation;
289
+ // Genuine tool signals only. `traceloop.entity.name` is NOT one — OpenLLMetry
290
+ // stamps it on every span (workflow/task/tool/llm alike), so treating it as a
291
+ // tool marker would misclassify chat spans.
292
+ if (hasOwn(map, "gen_ai.tool.name") || hasOwn(map, "tool.name")) {
293
+ return "execute_tool";
294
+ }
295
+ if (firstAttr(map, MODEL_CHAIN) !== undefined)
296
+ return "chat";
297
+ return "span";
298
+ }
299
+ // ── structure helpers ────────────────────────────────────────────────────────
300
+ const WS_RE = /\s+/g;
301
+ /** span name → step_key: trimmed, whitespace-collapsed, length-capped, never
302
+ * empty (the step PK forbids it). */
303
+ function toStepKey(name) {
304
+ const raw = typeof name === "string" ? name.trim().replace(WS_RE, " ") : "";
305
+ if (raw === "")
306
+ return "span";
307
+ return raw.slice(0, 200);
308
+ }
309
+ /** 32-hex trace id → canonical UUID string (runs.id is uuid; 16 bytes ≡ a UUID).
310
+ * A trace id that is not 16 bytes gets a deterministic UUID derived from it. */
311
+ function traceIdToRunUuid(traceHex) {
312
+ const hex = traceHex.length === 32 ? traceHex : (0, node_crypto_1.createHash)("sha256").update(traceHex).digest("hex").slice(0, 32);
313
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
314
+ }
315
+ function bump(drops, reason, by = 1) {
316
+ drops[reason] = (drops[reason] ?? 0) + by;
317
+ }
318
+ /** Resolve a span's start/end. One edge missing → copy the other; both missing
319
+ * → `now`. Each fallback counted (spec §3.3). */
320
+ function resolveTiming(span, nowMs, drops) {
321
+ const startNano = span.startTimeUnixNano ?? span.start_time_unix_nano;
322
+ const endNano = span.endTimeUnixNano ?? span.end_time_unix_nano;
323
+ let startMs = nanoToMs(startNano);
324
+ let endMs = nanoToMs(endNano);
325
+ if (startMs === null && endMs === null) {
326
+ bump(drops, "ts_both_missing");
327
+ startMs = nowMs;
328
+ endMs = nowMs;
329
+ }
330
+ else if (startMs === null) {
331
+ bump(drops, "ts_copied_edge");
332
+ startMs = endMs;
333
+ }
334
+ else if (endMs === null) {
335
+ bump(drops, "ts_copied_edge");
336
+ endMs = startMs;
337
+ }
338
+ return {
339
+ startedAt: new Date(startMs).toISOString(),
340
+ endedAt: endMs === null ? null : new Date(endMs).toISOString(),
341
+ startMs,
342
+ };
343
+ }
344
+ // ── the normalizer ───────────────────────────────────────────────────────────
345
+ /**
346
+ * Normalize a decoded OTLP `TracesData` structure into runs + attested steps.
347
+ * Total and defensive: a malformed span is dropped-and-counted, never thrown.
348
+ * `nowMs` is injected so callers/tests are deterministic (default Date.now()).
349
+ */
350
+ function normalizeOtlpTraces(data, nowMs = Date.now()) {
351
+ const drops = {};
352
+ const scopeNames = new Set();
353
+ const steps = [];
354
+ let spanCount = 0;
355
+ const resourceSpans = readResourceSpans(data);
356
+ const runs = new Map();
357
+ for (const rs of resourceSpans) {
358
+ const resourceAttrs = attrMap(rs.resource?.attributes).map;
359
+ const scopeSpansList = rs.scopeSpans ?? rs.scope_spans ?? [];
360
+ for (const ss of scopeSpansList) {
361
+ const scopeName = typeof ss.scope?.name === "string" ? ss.scope.name : "";
362
+ const scopeVersion = typeof ss.scope?.version === "string" ? ss.scope.version : null;
363
+ if (scopeName !== "")
364
+ scopeNames.add(scopeName);
365
+ for (const span of ss.spans ?? []) {
366
+ spanCount += 1;
367
+ const traceHex = toHexId(span.traceId ?? span.trace_id, 16);
368
+ const spanHex = toHexId(span.spanId ?? span.span_id, 8);
369
+ // A span with no usable identity is exactly the logs-exporter symptom;
370
+ // it cannot become an attested step (the steps CHECK needs span_id).
371
+ if (traceHex === null || spanHex === null) {
372
+ bump(drops, "bad_otlp_span");
373
+ continue;
374
+ }
375
+ const { map, keys } = attrMap(span.attributes);
376
+ const timing = resolveTiming(span, nowMs, drops);
377
+ const runId = traceIdToRunUuid(traceHex);
378
+ // ── envelope (identity/structure/usage ONLY; NO content) ──
379
+ const operation = classify(map);
380
+ const isAgentAggregate = AGENT_OPERATIONS.has(operation);
381
+ const model = isAgentAggregate ? null : (firstAttr(map, MODEL_CHAIN) ?? null);
382
+ const provider = isAgentAggregate
383
+ ? "unknown"
384
+ : (firstAttr(map, PROVIDER_CHAIN) ?? "unknown");
385
+ const usage = isAgentAggregate ? undefined : extractUsage(map);
386
+ const envelope = {
387
+ model,
388
+ provider,
389
+ operation,
390
+ ...(usage !== undefined ? { usage } : {}),
391
+ scope: { name: scopeName, version: scopeVersion },
392
+ };
393
+ // Count attributes we did not map into structure/identity/usage — honest
394
+ // in v0 where there is no metadata store to pass them into (spec §3.3).
395
+ countUnmapped(keys, map, drops);
396
+ const statusCode = coerceIntValue(span.status?.code);
397
+ const failureClass = statusCode === 2 ? "attested_error" : null;
398
+ const step = {
399
+ run_id: runId,
400
+ step_key: toStepKey(span.name),
401
+ attempt_no: 1, // assigned per (trace, step_key) below
402
+ task: null,
403
+ provenance: "attested",
404
+ inference_id: null,
405
+ span_trace_id: traceHex,
406
+ span_id: spanHex,
407
+ started_at: timing.startedAt,
408
+ ended_at: timing.endedAt,
409
+ failure_class: failureClass,
410
+ attested: envelope,
411
+ };
412
+ // ── run correlate (upserted shallow, merge=true — idempotent) ──
413
+ const acc = runs.get(runId);
414
+ const endMs = timing.endedAt !== null ? Date.parse(timing.endedAt) : timing.startMs;
415
+ const episodeKey = firstAttr(map, EPISODE_CHAIN) ?? null;
416
+ if (acc === undefined) {
417
+ runs.set(runId, {
418
+ runId,
419
+ traceHex,
420
+ pipeline: firstAttr(resourceAttrs, PIPELINE_RESOURCE_CHAIN) ?? (scopeName !== "" ? scopeName : "otlp"),
421
+ environment: firstAttr(resourceAttrs, ENVIRONMENT_CHAIN) ?? null,
422
+ episodeKey,
423
+ minStartMs: timing.startMs,
424
+ maxEndMs: endMs,
425
+ anyError: failureClass !== null,
426
+ pending: [{ step, stepKey: step.step_key, startMs: timing.startMs }],
427
+ });
428
+ }
429
+ else {
430
+ acc.minStartMs = Math.min(acc.minStartMs, timing.startMs);
431
+ acc.maxEndMs = Math.max(acc.maxEndMs, endMs);
432
+ acc.anyError = acc.anyError || failureClass !== null;
433
+ if (acc.episodeKey === null && episodeKey !== null)
434
+ acc.episodeKey = episodeKey;
435
+ acc.pending.push({ step, stepKey: step.step_key, startMs: timing.startMs });
436
+ }
437
+ }
438
+ }
439
+ }
440
+ const runRows = [];
441
+ for (const acc of runs.values()) {
442
+ runRows.push({
443
+ id: acc.runId,
444
+ pipeline: acc.pipeline,
445
+ pipeline_version: null,
446
+ environment: acc.environment,
447
+ episode_key: acc.episodeKey,
448
+ started_at: new Date(acc.minStartMs).toISOString(),
449
+ ended_at: new Date(acc.maxEndMs).toISOString(),
450
+ // The trace has completed (we only see finished spans); status is honest.
451
+ status: acc.anyError ? "failed" : "succeeded",
452
+ });
453
+ // Assign attempt_no per (run, step_key): repeated same-named spans become
454
+ // attempts in start-time (then span-id) order — deterministic within a
455
+ // trace. v0 limitation: a trace split across batches is not deduped (no
456
+ // seen-store); one trace = one batch is the common, correct case.
457
+ const perKey = new Map();
458
+ for (const p of acc.pending) {
459
+ const list = perKey.get(p.stepKey) ?? [];
460
+ list.push({ step: p.step, startMs: p.startMs });
461
+ perKey.set(p.stepKey, list);
462
+ }
463
+ for (const list of perKey.values()) {
464
+ list.sort((a, b) => a.startMs !== b.startMs
465
+ ? a.startMs - b.startMs
466
+ : (a.step.span_id ?? "") < (b.step.span_id ?? "")
467
+ ? -1
468
+ : 1);
469
+ list.forEach(({ step }, i) => steps.push({ ...step, attempt_no: i + 1 }));
470
+ }
471
+ }
472
+ return { runs: runRows, steps, drops, spanCount, scopeNames: [...scopeNames] };
473
+ }
474
+ /** The keys the envelope consumes structurally — everything else on a span is an
475
+ * "unmapped attribute" in v0 (counted, not stored). */
476
+ function countUnmapped(keys, map, drops) {
477
+ let unmapped = 0;
478
+ for (const key of keys) {
479
+ if (key.startsWith("gen_ai.usage.") ||
480
+ key.startsWith("llm.token_count.") ||
481
+ MODEL_CHAIN.includes(key) ||
482
+ PROVIDER_CHAIN.includes(key) ||
483
+ EPISODE_CHAIN.includes(key) ||
484
+ key === "gen_ai.operation.name" ||
485
+ key === "openinference.span.kind") {
486
+ continue;
487
+ }
488
+ unmapped += 1;
489
+ }
490
+ void map;
491
+ if (unmapped > 0)
492
+ bump(drops, "unmapped_attribute", unmapped);
493
+ }
494
+ /** Read `resourceSpans` (camel or snake) from a decoded body, tolerating shape. */
495
+ function readResourceSpans(data) {
496
+ if (!isRecord(data))
497
+ return [];
498
+ const rs = data.resourceSpans ?? data.resource_spans;
499
+ return Array.isArray(rs) ? rs : [];
500
+ }
501
+ /**
502
+ * Logs-exporter detection (learnings §1.2). ResourceLogs and ResourceSpans share
503
+ * protobuf field numbers, so a logs exporter pointed at the traces endpoint
504
+ * decodes as id-less "spans". A JSON logs body carries `resourceLogs` outright.
505
+ * Returns true when the body is a logs payload that must be rejected 400.
506
+ */
507
+ function looksLikeLogsPayload(data) {
508
+ if (!isRecord(data))
509
+ return false;
510
+ if (Array.isArray(data.resourceLogs) || Array.isArray(data.resource_logs)) {
511
+ return true;
512
+ }
513
+ const resourceSpans = readResourceSpans(data);
514
+ if (resourceSpans.length === 0)
515
+ return false;
516
+ // Every span across the payload lacking BOTH ids is the decoded-logs symptom.
517
+ let sawSpan = false;
518
+ for (const rs of resourceSpans) {
519
+ for (const ss of rs.scopeSpans ?? rs.scope_spans ?? []) {
520
+ for (const span of ss.spans ?? []) {
521
+ sawSpan = true;
522
+ const hasTrace = toHexId(span.traceId ?? span.trace_id, 16) !== null;
523
+ const hasSpan = toHexId(span.spanId ?? span.span_id, 8) !== null;
524
+ if (hasTrace || hasSpan)
525
+ return false;
526
+ }
527
+ }
528
+ }
529
+ return sawSpan;
530
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * OTLP span emitter — E1 (spec §2.3, §4). A SIBLING of the control-plane
3
+ * exporter, not a sink inside it: it reads the same `inferences` table behind
4
+ * its OWN watermark (`${sourceId}:otlp`), so the OTLP stream and the
5
+ * control-plane export never block or drain each other — exactly the pattern
6
+ * the feedback stream already uses (`:feedback`).
7
+ *
8
+ * ── DOCTRINE CLONED FROM exporter.ts (verbatim, on purpose) ───────────────
9
+ * Fire-and-forget from the run loop; at-least-once with idempotent span ids
10
+ * (otel-map derives them deterministically, so a re-emit after a crash is a
11
+ * no-op at the sink); the watermark advances ONLY after a confirmed 2xx;
12
+ * sink errors are swallowed-and-logged with exponential skip backoff; the
13
+ * interval timer is `unref()`ed so telemetry never keeps a process alive.
14
+ *
15
+ * ── OFF BY DEFAULT ────────────────────────────────────────────────────────
16
+ * This module is only constructed when `MODELRIG_OTLP_ENDPOINT` is set
17
+ * (config.ts). No endpoint ⇒ no emitter ⇒ zero behaviour change (spec §6a).
18
+ *
19
+ * ── C2 (never leak credentials) ───────────────────────────────────────────
20
+ * `cfg.headers` may carry sink auth (e.g. Langfuse Basic auth) and `endpoint`
21
+ * itself may embed a token. NEITHER is ever logged or put in an error. Failure
22
+ * text is run through the shared secret scrubber before it reaches a warning.
23
+ */
24
+ import type { OtlpConfig } from "../config";
25
+ import type { ExportableTelemetryStore } from "./store";
26
+ export interface OtlpEmitterConfig {
27
+ /** OTLP/HTTP traces endpoint, e.g. `https://cloud.langfuse.com/api/public/otel/v1/traces`. */
28
+ readonly endpoint: string;
29
+ /** Sink auth headers (`k=v` pairs from MODELRIG_OTLP_HEADERS). May be empty. */
30
+ readonly headers: Record<string, string>;
31
+ /** Watermark namespace — the rig's source instance. Key is `${sourceId}:otlp`. */
32
+ readonly sourceId: string;
33
+ readonly batchSize?: number;
34
+ readonly intervalMs?: number;
35
+ /** Injectable for tests; defaults to global fetch. */
36
+ readonly fetchFn?: typeof fetch;
37
+ }
38
+ export interface OtlpEmitter {
39
+ start(): void;
40
+ /** Flush pending rows now (tests + process-exit hooks). */
41
+ flushNow(): Promise<void>;
42
+ stop(): Promise<void>;
43
+ }
44
+ export declare function createOtlpEmitter(store: ExportableTelemetryStore, config: OtlpEmitterConfig): OtlpEmitter;
45
+ /**
46
+ * Construct + start the OTLP emitter iff an endpoint is configured, else null
47
+ * (spec §6a). Lives here rather than index.ts so createRig's wiring stays one
48
+ * line and this file keeps the LOC cap on index.ts — the same reason
49
+ * `buildTelemetrySink` moved to sinks.ts.
50
+ */
51
+ export declare function startOtlpEmitterIfConfigured(store: ExportableTelemetryStore, otlp: OtlpConfig | null | undefined, sourceId: string): OtlpEmitter | null;
52
+ //# sourceMappingURL=otlp-emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otlp-emitter.d.ts","sourceRoot":"","sources":["../../src/telemetry/otlp-emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAKxD,MAAM,WAAW,iBAAiB;IAChC,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,IAAI,IAAI,CAAC;IACd,2DAA2D;IAC3D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAQD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,wBAAwB,EAC/B,MAAM,EAAE,iBAAiB,GACxB,WAAW,CAgGb;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,wBAAwB,EAC/B,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACnC,QAAQ,EAAE,MAAM,GACf,WAAW,GAAG,IAAI,CASpB"}