@fml-inc/panopticon 0.1.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 (124) hide show
  1. package/.claude-plugin/plugin.json +10 -0
  2. package/LICENSE +5 -0
  3. package/README.md +363 -0
  4. package/bin/hook-handler +3 -0
  5. package/bin/mcp-server +3 -0
  6. package/bin/panopticon +3 -0
  7. package/bin/proxy +3 -0
  8. package/bin/server +3 -0
  9. package/dist/api/client.d.ts +67 -0
  10. package/dist/api/client.js +48 -0
  11. package/dist/api/client.js.map +1 -0
  12. package/dist/chunk-3BUJ7URA.js +387 -0
  13. package/dist/chunk-3BUJ7URA.js.map +1 -0
  14. package/dist/chunk-3TZAKV3M.js +158 -0
  15. package/dist/chunk-3TZAKV3M.js.map +1 -0
  16. package/dist/chunk-4SM2H22C.js +169 -0
  17. package/dist/chunk-4SM2H22C.js.map +1 -0
  18. package/dist/chunk-7Q3BJMLG.js +62 -0
  19. package/dist/chunk-7Q3BJMLG.js.map +1 -0
  20. package/dist/chunk-BVOE7A2Z.js +412 -0
  21. package/dist/chunk-BVOE7A2Z.js.map +1 -0
  22. package/dist/chunk-CF4GPWLI.js +170 -0
  23. package/dist/chunk-CF4GPWLI.js.map +1 -0
  24. package/dist/chunk-DZ5HJFB4.js +467 -0
  25. package/dist/chunk-DZ5HJFB4.js.map +1 -0
  26. package/dist/chunk-HQCY722C.js +428 -0
  27. package/dist/chunk-HQCY722C.js.map +1 -0
  28. package/dist/chunk-HRCEIYKU.js +134 -0
  29. package/dist/chunk-HRCEIYKU.js.map +1 -0
  30. package/dist/chunk-K7YUPLES.js +76 -0
  31. package/dist/chunk-K7YUPLES.js.map +1 -0
  32. package/dist/chunk-L7G27XWF.js +130 -0
  33. package/dist/chunk-L7G27XWF.js.map +1 -0
  34. package/dist/chunk-LWXF7YRG.js +626 -0
  35. package/dist/chunk-LWXF7YRG.js.map +1 -0
  36. package/dist/chunk-NXH7AONS.js +1120 -0
  37. package/dist/chunk-NXH7AONS.js.map +1 -0
  38. package/dist/chunk-QK5442ZP.js +55 -0
  39. package/dist/chunk-QK5442ZP.js.map +1 -0
  40. package/dist/chunk-QVK6VGCV.js +1703 -0
  41. package/dist/chunk-QVK6VGCV.js.map +1 -0
  42. package/dist/chunk-RX2RXHBH.js +1699 -0
  43. package/dist/chunk-RX2RXHBH.js.map +1 -0
  44. package/dist/chunk-SEXU2WYG.js +788 -0
  45. package/dist/chunk-SEXU2WYG.js.map +1 -0
  46. package/dist/chunk-SUGSQ4YI.js +264 -0
  47. package/dist/chunk-SUGSQ4YI.js.map +1 -0
  48. package/dist/chunk-TGXFVAID.js +138 -0
  49. package/dist/chunk-TGXFVAID.js.map +1 -0
  50. package/dist/chunk-WLBNFVIG.js +447 -0
  51. package/dist/chunk-WLBNFVIG.js.map +1 -0
  52. package/dist/chunk-XLTCUH5A.js +1072 -0
  53. package/dist/chunk-XLTCUH5A.js.map +1 -0
  54. package/dist/chunk-YVRWVDIA.js +146 -0
  55. package/dist/chunk-YVRWVDIA.js.map +1 -0
  56. package/dist/chunk-ZEC4LRKS.js +176 -0
  57. package/dist/chunk-ZEC4LRKS.js.map +1 -0
  58. package/dist/cli.d.ts +1 -0
  59. package/dist/cli.js +1084 -0
  60. package/dist/cli.js.map +1 -0
  61. package/dist/config-NwoZC-GM.d.ts +20 -0
  62. package/dist/db.d.ts +46 -0
  63. package/dist/db.js +15 -0
  64. package/dist/db.js.map +1 -0
  65. package/dist/doctor.d.ts +37 -0
  66. package/dist/doctor.js +14 -0
  67. package/dist/doctor.js.map +1 -0
  68. package/dist/hooks/handler.d.ts +23 -0
  69. package/dist/hooks/handler.js +295 -0
  70. package/dist/hooks/handler.js.map +1 -0
  71. package/dist/index.d.ts +57 -0
  72. package/dist/index.js +101 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/mcp/server.d.ts +1 -0
  75. package/dist/mcp/server.js +243 -0
  76. package/dist/mcp/server.js.map +1 -0
  77. package/dist/otlp/server.d.ts +7 -0
  78. package/dist/otlp/server.js +17 -0
  79. package/dist/otlp/server.js.map +1 -0
  80. package/dist/permissions.d.ts +33 -0
  81. package/dist/permissions.js +14 -0
  82. package/dist/permissions.js.map +1 -0
  83. package/dist/pricing.d.ts +29 -0
  84. package/dist/pricing.js +13 -0
  85. package/dist/pricing.js.map +1 -0
  86. package/dist/proxy/server.d.ts +10 -0
  87. package/dist/proxy/server.js +20 -0
  88. package/dist/proxy/server.js.map +1 -0
  89. package/dist/prune.d.ts +18 -0
  90. package/dist/prune.js +13 -0
  91. package/dist/prune.js.map +1 -0
  92. package/dist/query.d.ts +56 -0
  93. package/dist/query.js +27 -0
  94. package/dist/query.js.map +1 -0
  95. package/dist/reparse-636YZCE3.js +14 -0
  96. package/dist/reparse-636YZCE3.js.map +1 -0
  97. package/dist/repo.d.ts +17 -0
  98. package/dist/repo.js +9 -0
  99. package/dist/repo.js.map +1 -0
  100. package/dist/scanner.d.ts +73 -0
  101. package/dist/scanner.js +15 -0
  102. package/dist/scanner.js.map +1 -0
  103. package/dist/sdk.d.ts +82 -0
  104. package/dist/sdk.js +208 -0
  105. package/dist/sdk.js.map +1 -0
  106. package/dist/server.d.ts +5 -0
  107. package/dist/server.js +25 -0
  108. package/dist/server.js.map +1 -0
  109. package/dist/setup.d.ts +35 -0
  110. package/dist/setup.js +19 -0
  111. package/dist/setup.js.map +1 -0
  112. package/dist/sync/index.d.ts +29 -0
  113. package/dist/sync/index.js +32 -0
  114. package/dist/sync/index.js.map +1 -0
  115. package/dist/targets.d.ts +279 -0
  116. package/dist/targets.js +20 -0
  117. package/dist/targets.js.map +1 -0
  118. package/dist/types-D-MYCBol.d.ts +128 -0
  119. package/dist/types.d.ts +164 -0
  120. package/dist/types.js +1 -0
  121. package/dist/types.js.map +1 -0
  122. package/hooks/hooks.json +274 -0
  123. package/package.json +124 -0
  124. package/skills/panopticon-optimize/SKILL.md +222 -0
@@ -0,0 +1,1072 @@
1
+ import {
2
+ insertOtelLogs,
3
+ insertOtelMetrics,
4
+ insertOtelSpans,
5
+ upsertSession
6
+ } from "./chunk-BVOE7A2Z.js";
7
+ import {
8
+ captureException
9
+ } from "./chunk-CF4GPWLI.js";
10
+ import {
11
+ log
12
+ } from "./chunk-7Q3BJMLG.js";
13
+ import {
14
+ refreshIfStale
15
+ } from "./chunk-3TZAKV3M.js";
16
+ import {
17
+ allTargets
18
+ } from "./chunk-QVK6VGCV.js";
19
+ import {
20
+ config
21
+ } from "./chunk-K7YUPLES.js";
22
+
23
+ // src/otlp/server.ts
24
+ import http from "http";
25
+
26
+ // src/otlp/proto.ts
27
+ import protobuf from "protobufjs";
28
+ var root = protobuf.Root.fromJSON({
29
+ nested: {
30
+ opentelemetry: {
31
+ nested: {
32
+ proto: {
33
+ nested: {
34
+ common: {
35
+ nested: {
36
+ v1: {
37
+ nested: {
38
+ AnyValue: {
39
+ oneofs: {
40
+ value: {
41
+ oneof: [
42
+ "stringValue",
43
+ "boolValue",
44
+ "intValue",
45
+ "doubleValue",
46
+ "arrayValue",
47
+ "kvlistValue",
48
+ "bytesValue"
49
+ ]
50
+ }
51
+ },
52
+ fields: {
53
+ stringValue: { type: "string", id: 1 },
54
+ boolValue: { type: "bool", id: 2 },
55
+ intValue: { type: "int64", id: 3 },
56
+ doubleValue: { type: "double", id: 4 },
57
+ arrayValue: {
58
+ type: "ArrayValue",
59
+ id: 5
60
+ },
61
+ kvlistValue: {
62
+ type: "KeyValueList",
63
+ id: 6
64
+ },
65
+ bytesValue: { type: "bytes", id: 7 }
66
+ }
67
+ },
68
+ ArrayValue: {
69
+ fields: {
70
+ values: {
71
+ rule: "repeated",
72
+ type: "AnyValue",
73
+ id: 1
74
+ }
75
+ }
76
+ },
77
+ KeyValueList: {
78
+ fields: {
79
+ values: {
80
+ rule: "repeated",
81
+ type: "KeyValue",
82
+ id: 1
83
+ }
84
+ }
85
+ },
86
+ KeyValue: {
87
+ fields: {
88
+ key: { type: "string", id: 1 },
89
+ value: { type: "AnyValue", id: 2 }
90
+ }
91
+ },
92
+ InstrumentationScope: {
93
+ fields: {
94
+ name: { type: "string", id: 1 },
95
+ version: { type: "string", id: 2 },
96
+ attributes: {
97
+ rule: "repeated",
98
+ type: "KeyValue",
99
+ id: 3
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ },
107
+ resource: {
108
+ nested: {
109
+ v1: {
110
+ nested: {
111
+ Resource: {
112
+ fields: {
113
+ attributes: {
114
+ rule: "repeated",
115
+ type: "opentelemetry.proto.common.v1.KeyValue",
116
+ id: 1
117
+ },
118
+ droppedAttributesCount: {
119
+ type: "uint32",
120
+ id: 2
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ },
128
+ logs: {
129
+ nested: {
130
+ v1: {
131
+ nested: {
132
+ ExportLogsServiceRequest: {
133
+ fields: {
134
+ resourceLogs: {
135
+ rule: "repeated",
136
+ type: "ResourceLogs",
137
+ id: 1
138
+ }
139
+ }
140
+ },
141
+ ResourceLogs: {
142
+ fields: {
143
+ resource: {
144
+ type: "opentelemetry.proto.resource.v1.Resource",
145
+ id: 1
146
+ },
147
+ scopeLogs: {
148
+ rule: "repeated",
149
+ type: "ScopeLogs",
150
+ id: 2
151
+ },
152
+ schemaUrl: { type: "string", id: 3 }
153
+ }
154
+ },
155
+ ScopeLogs: {
156
+ fields: {
157
+ scope: {
158
+ type: "opentelemetry.proto.common.v1.InstrumentationScope",
159
+ id: 1
160
+ },
161
+ logRecords: {
162
+ rule: "repeated",
163
+ type: "LogRecord",
164
+ id: 2
165
+ },
166
+ schemaUrl: { type: "string", id: 3 }
167
+ }
168
+ },
169
+ LogRecord: {
170
+ fields: {
171
+ timeUnixNano: {
172
+ type: "fixed64",
173
+ id: 1
174
+ },
175
+ severityNumber: { type: "int32", id: 2 },
176
+ severityText: { type: "string", id: 3 },
177
+ body: {
178
+ type: "opentelemetry.proto.common.v1.AnyValue",
179
+ id: 5
180
+ },
181
+ attributes: {
182
+ rule: "repeated",
183
+ type: "opentelemetry.proto.common.v1.KeyValue",
184
+ id: 6
185
+ },
186
+ droppedAttributesCount: {
187
+ type: "uint32",
188
+ id: 7
189
+ },
190
+ flags: { type: "fixed32", id: 8 },
191
+ traceId: { type: "bytes", id: 9 },
192
+ spanId: { type: "bytes", id: 10 },
193
+ observedTimeUnixNano: {
194
+ type: "fixed64",
195
+ id: 11
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+ },
203
+ metrics: {
204
+ nested: {
205
+ v1: {
206
+ nested: {
207
+ ExportMetricsServiceRequest: {
208
+ fields: {
209
+ resourceMetrics: {
210
+ rule: "repeated",
211
+ type: "ResourceMetrics",
212
+ id: 1
213
+ }
214
+ }
215
+ },
216
+ ResourceMetrics: {
217
+ fields: {
218
+ resource: {
219
+ type: "opentelemetry.proto.resource.v1.Resource",
220
+ id: 1
221
+ },
222
+ scopeMetrics: {
223
+ rule: "repeated",
224
+ type: "ScopeMetrics",
225
+ id: 2
226
+ },
227
+ schemaUrl: { type: "string", id: 3 }
228
+ }
229
+ },
230
+ ScopeMetrics: {
231
+ fields: {
232
+ scope: {
233
+ type: "opentelemetry.proto.common.v1.InstrumentationScope",
234
+ id: 1
235
+ },
236
+ metrics: {
237
+ rule: "repeated",
238
+ type: "Metric",
239
+ id: 2
240
+ },
241
+ schemaUrl: { type: "string", id: 3 }
242
+ }
243
+ },
244
+ Metric: {
245
+ oneofs: {
246
+ data: {
247
+ oneof: ["gauge", "sum", "histogram"]
248
+ }
249
+ },
250
+ fields: {
251
+ name: { type: "string", id: 1 },
252
+ description: { type: "string", id: 2 },
253
+ unit: { type: "string", id: 3 },
254
+ gauge: { type: "Gauge", id: 5 },
255
+ sum: { type: "Sum", id: 7 },
256
+ histogram: { type: "Histogram", id: 9 }
257
+ }
258
+ },
259
+ Gauge: {
260
+ fields: {
261
+ dataPoints: {
262
+ rule: "repeated",
263
+ type: "NumberDataPoint",
264
+ id: 1
265
+ }
266
+ }
267
+ },
268
+ Sum: {
269
+ fields: {
270
+ dataPoints: {
271
+ rule: "repeated",
272
+ type: "NumberDataPoint",
273
+ id: 1
274
+ },
275
+ aggregationTemporality: {
276
+ type: "int32",
277
+ id: 2
278
+ },
279
+ isMonotonic: { type: "bool", id: 3 }
280
+ }
281
+ },
282
+ Histogram: {
283
+ fields: {
284
+ dataPoints: {
285
+ rule: "repeated",
286
+ type: "HistogramDataPoint",
287
+ id: 1
288
+ },
289
+ aggregationTemporality: {
290
+ type: "int32",
291
+ id: 2
292
+ }
293
+ }
294
+ },
295
+ NumberDataPoint: {
296
+ oneofs: {
297
+ value: {
298
+ oneof: ["asDouble", "asInt"]
299
+ }
300
+ },
301
+ fields: {
302
+ attributes: {
303
+ rule: "repeated",
304
+ type: "opentelemetry.proto.common.v1.KeyValue",
305
+ id: 7
306
+ },
307
+ startTimeUnixNano: {
308
+ type: "fixed64",
309
+ id: 2
310
+ },
311
+ timeUnixNano: {
312
+ type: "fixed64",
313
+ id: 3
314
+ },
315
+ asDouble: { type: "double", id: 4 },
316
+ asInt: { type: "sfixed64", id: 6 }
317
+ }
318
+ },
319
+ HistogramDataPoint: {
320
+ fields: {
321
+ attributes: {
322
+ rule: "repeated",
323
+ type: "opentelemetry.proto.common.v1.KeyValue",
324
+ id: 9
325
+ },
326
+ startTimeUnixNano: {
327
+ type: "fixed64",
328
+ id: 2
329
+ },
330
+ timeUnixNano: {
331
+ type: "fixed64",
332
+ id: 3
333
+ },
334
+ count: { type: "fixed64", id: 4 },
335
+ sum: { type: "double", id: 5 },
336
+ bucketCounts: {
337
+ rule: "repeated",
338
+ type: "fixed64",
339
+ id: 6,
340
+ options: { packed: true }
341
+ },
342
+ explicitBounds: {
343
+ rule: "repeated",
344
+ type: "double",
345
+ id: 7,
346
+ options: { packed: true }
347
+ },
348
+ min: { type: "double", id: 11 },
349
+ max: { type: "double", id: 12 }
350
+ }
351
+ }
352
+ }
353
+ }
354
+ }
355
+ },
356
+ trace: {
357
+ nested: {
358
+ v1: {
359
+ nested: {
360
+ Span: {
361
+ fields: {
362
+ traceId: { type: "bytes", id: 1 },
363
+ spanId: { type: "bytes", id: 2 },
364
+ traceState: { type: "string", id: 3 },
365
+ parentSpanId: { type: "bytes", id: 4 },
366
+ name: { type: "string", id: 5 },
367
+ kind: { type: "int32", id: 6 },
368
+ startTimeUnixNano: {
369
+ type: "fixed64",
370
+ id: 7
371
+ },
372
+ endTimeUnixNano: {
373
+ type: "fixed64",
374
+ id: 8
375
+ },
376
+ attributes: {
377
+ rule: "repeated",
378
+ type: "opentelemetry.proto.common.v1.KeyValue",
379
+ id: 9
380
+ },
381
+ status: { type: "Status", id: 15 }
382
+ }
383
+ },
384
+ Status: {
385
+ fields: {
386
+ message: { type: "string", id: 2 },
387
+ code: { type: "int32", id: 3 }
388
+ }
389
+ },
390
+ ResourceSpans: {
391
+ fields: {
392
+ resource: {
393
+ type: "opentelemetry.proto.resource.v1.Resource",
394
+ id: 1
395
+ },
396
+ scopeSpans: {
397
+ rule: "repeated",
398
+ type: "ScopeSpans",
399
+ id: 2
400
+ },
401
+ schemaUrl: { type: "string", id: 3 }
402
+ }
403
+ },
404
+ ScopeSpans: {
405
+ fields: {
406
+ scope: {
407
+ type: "opentelemetry.proto.common.v1.InstrumentationScope",
408
+ id: 1
409
+ },
410
+ spans: {
411
+ rule: "repeated",
412
+ type: "Span",
413
+ id: 2
414
+ },
415
+ schemaUrl: { type: "string", id: 3 }
416
+ }
417
+ }
418
+ }
419
+ }
420
+ }
421
+ },
422
+ collector: {
423
+ nested: {
424
+ logs: {
425
+ nested: {
426
+ v1: {
427
+ nested: {
428
+ ExportLogsServiceRequest: {
429
+ fields: {
430
+ resourceLogs: {
431
+ rule: "repeated",
432
+ type: "opentelemetry.proto.logs.v1.ResourceLogs",
433
+ id: 1
434
+ }
435
+ }
436
+ },
437
+ ExportLogsServiceResponse: {
438
+ fields: {}
439
+ }
440
+ }
441
+ }
442
+ }
443
+ },
444
+ metrics: {
445
+ nested: {
446
+ v1: {
447
+ nested: {
448
+ ExportMetricsServiceRequest: {
449
+ fields: {
450
+ resourceMetrics: {
451
+ rule: "repeated",
452
+ type: "opentelemetry.proto.metrics.v1.ResourceMetrics",
453
+ id: 1
454
+ }
455
+ }
456
+ },
457
+ ExportMetricsServiceResponse: {
458
+ fields: {}
459
+ }
460
+ }
461
+ }
462
+ }
463
+ },
464
+ trace: {
465
+ nested: {
466
+ v1: {
467
+ nested: {
468
+ ExportTracesServiceRequest: {
469
+ fields: {
470
+ resourceSpans: {
471
+ rule: "repeated",
472
+ type: "opentelemetry.proto.trace.v1.ResourceSpans",
473
+ id: 1
474
+ }
475
+ }
476
+ },
477
+ ExportTracesServiceResponse: {
478
+ fields: {}
479
+ }
480
+ }
481
+ }
482
+ }
483
+ }
484
+ }
485
+ }
486
+ }
487
+ }
488
+ }
489
+ }
490
+ }
491
+ });
492
+ var ExportLogsServiceRequest = root.lookupType(
493
+ "opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest"
494
+ );
495
+ var ExportMetricsServiceRequest = root.lookupType(
496
+ "opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest"
497
+ );
498
+ var ExportLogsServiceResponse = root.lookupType(
499
+ "opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse"
500
+ );
501
+ var ExportMetricsServiceResponse = root.lookupType(
502
+ "opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse"
503
+ );
504
+ var ExportTracesServiceRequest = root.lookupType(
505
+ "opentelemetry.proto.collector.trace.v1.ExportTracesServiceRequest"
506
+ );
507
+ var ExportTracesServiceResponse = root.lookupType(
508
+ "opentelemetry.proto.collector.trace.v1.ExportTracesServiceResponse"
509
+ );
510
+ function extractAnyValue(v) {
511
+ if (!v) return null;
512
+ if (v.stringValue != null) return v.stringValue;
513
+ if (v.intValue != null) {
514
+ return typeof v.intValue === "object" && v.intValue.toNumber ? v.intValue.toNumber() : Number(v.intValue);
515
+ }
516
+ if (v.doubleValue != null) return v.doubleValue;
517
+ if (v.boolValue != null) return v.boolValue;
518
+ if (v.bytesValue != null) return Buffer.from(v.bytesValue).toString("hex");
519
+ if (v.arrayValue?.values)
520
+ return v.arrayValue.values.map(extractAnyValue);
521
+ if (v.kvlistValue?.values) return attrsToMap(v.kvlistValue.values);
522
+ return null;
523
+ }
524
+ function attrsToMap(kvs) {
525
+ const out = {};
526
+ if (!kvs) return out;
527
+ for (const kv of kvs) {
528
+ if (kv.key) {
529
+ out[kv.key] = extractAnyValue(kv.value);
530
+ }
531
+ }
532
+ return out;
533
+ }
534
+ function longToNumber(val) {
535
+ if (val == null) return 0;
536
+ if (typeof val === "number") return val;
537
+ if (typeof val === "bigint") return Number(val);
538
+ if (typeof val.toNumber === "function") return val.toNumber();
539
+ return Number(val);
540
+ }
541
+ function bytesToHex(val) {
542
+ if (!val || val.length === 0) return "";
543
+ return Buffer.from(val).toString("hex");
544
+ }
545
+
546
+ // src/otlp/decode-logs.ts
547
+ function decodeLogs(buf) {
548
+ const message = ExportLogsServiceRequest.decode(buf);
549
+ const rows = [];
550
+ for (const resourceLog of message.resourceLogs ?? []) {
551
+ const resourceAttrs = attrsToMap(resourceLog.resource?.attributes);
552
+ const resourceSessionId = resourceAttrs["session.id"] ?? resourceAttrs["conversation.id"] ?? resourceAttrs["service.instance.id"] ?? void 0;
553
+ for (const scopeLog of resourceLog.scopeLogs ?? []) {
554
+ for (const record of scopeLog.logRecords ?? []) {
555
+ const attrs = attrsToMap(record.attributes);
556
+ const rawBody = extractAnyValue(record.body);
557
+ const body = typeof rawBody === "string" ? rawBody : rawBody != null ? JSON.stringify(rawBody) : attrs["event.name"] ?? void 0;
558
+ let timestamp_ns = longToNumber(record.timeUnixNano);
559
+ if (!timestamp_ns && typeof attrs["event.timestamp"] === "string") {
560
+ timestamp_ns = new Date(attrs["event.timestamp"]).getTime() * 1e6;
561
+ }
562
+ rows.push({
563
+ timestamp_ns,
564
+ observed_timestamp_ns: longToNumber(record.observedTimeUnixNano) || void 0,
565
+ severity_number: record.severityNumber ?? void 0,
566
+ severity_text: record.severityText || void 0,
567
+ body,
568
+ attributes: Object.keys(attrs).length > 0 ? attrs : void 0,
569
+ resource_attributes: Object.keys(resourceAttrs).length > 0 ? resourceAttrs : void 0,
570
+ session_id: attrs["session.id"] ?? attrs["conversation.id"] ?? resourceSessionId,
571
+ prompt_id: attrs["prompt.id"] ?? attrs.prompt_id,
572
+ trace_id: bytesToHex(record.traceId) || void 0,
573
+ span_id: bytesToHex(record.spanId) || void 0
574
+ });
575
+ }
576
+ }
577
+ }
578
+ return rows;
579
+ }
580
+
581
+ // src/otlp/decode-metrics.ts
582
+ function decodeMetrics(buf) {
583
+ const message = ExportMetricsServiceRequest.decode(buf);
584
+ const rows = [];
585
+ for (const resourceMetric of message.resourceMetrics ?? []) {
586
+ const resourceAttrs = attrsToMap(resourceMetric.resource?.attributes);
587
+ const resourceSessionId = resourceAttrs["session.id"] ?? resourceAttrs["conversation.id"] ?? resourceAttrs["service.instance.id"] ?? void 0;
588
+ for (const scopeMetric of resourceMetric.scopeMetrics ?? []) {
589
+ for (const metric of scopeMetric.metrics ?? []) {
590
+ const name = metric.name;
591
+ const unit = metric.unit || void 0;
592
+ let metricType;
593
+ let dataPoints = [];
594
+ if (metric.gauge) {
595
+ metricType = "gauge";
596
+ dataPoints = metric.gauge.dataPoints ?? [];
597
+ } else if (metric.sum) {
598
+ metricType = "sum";
599
+ dataPoints = metric.sum.dataPoints ?? [];
600
+ } else if (metric.histogram) {
601
+ metricType = "histogram";
602
+ for (const dp of metric.histogram.dataPoints ?? []) {
603
+ const attrs = attrsToMap(dp.attributes);
604
+ rows.push({
605
+ timestamp_ns: longToNumber(dp.timeUnixNano),
606
+ name,
607
+ value: dp.sum ?? 0,
608
+ metric_type: "histogram",
609
+ unit,
610
+ attributes: Object.keys(attrs).length > 0 ? attrs : void 0,
611
+ resource_attributes: Object.keys(resourceAttrs).length > 0 ? resourceAttrs : void 0,
612
+ session_id: attrs["session.id"] ?? attrs["conversation.id"] ?? resourceSessionId
613
+ });
614
+ }
615
+ continue;
616
+ }
617
+ for (const dp of dataPoints) {
618
+ const attrs = attrsToMap(dp.attributes);
619
+ const value = dp.asDouble != null ? dp.asDouble : dp.asInt != null ? longToNumber(dp.asInt) : 0;
620
+ rows.push({
621
+ timestamp_ns: longToNumber(dp.timeUnixNano),
622
+ name,
623
+ value,
624
+ metric_type: metricType,
625
+ unit,
626
+ attributes: Object.keys(attrs).length > 0 ? attrs : void 0,
627
+ resource_attributes: Object.keys(resourceAttrs).length > 0 ? resourceAttrs : void 0,
628
+ session_id: attrs["session.id"] ?? resourceSessionId
629
+ });
630
+ }
631
+ }
632
+ }
633
+ }
634
+ return rows;
635
+ }
636
+
637
+ // src/otlp/decode-traces.ts
638
+ function extractConversationId(promptName) {
639
+ if (typeof promptName !== "string") return void 0;
640
+ const sep = promptName.indexOf("########");
641
+ if (sep === -1) return void 0;
642
+ const uuid = promptName.slice(0, sep);
643
+ if (uuid.length === 36 && uuid[8] === "-") return uuid;
644
+ return void 0;
645
+ }
646
+ function decodeTraces(buf) {
647
+ const message = ExportTracesServiceRequest.decode(buf);
648
+ const rows = [];
649
+ for (const resourceSpan of message.resourceSpans ?? []) {
650
+ const resourceAttrs = attrsToMap(resourceSpan.resource?.attributes);
651
+ const resourceSessionId = resourceAttrs["session.id"] ?? resourceAttrs["conversation.id"] ?? resourceAttrs["service.instance.id"] ?? void 0;
652
+ const traceConversation = /* @__PURE__ */ new Map();
653
+ for (const scopeSpan of resourceSpan.scopeSpans ?? []) {
654
+ for (const span of scopeSpan.spans ?? []) {
655
+ const attrs = attrsToMap(span.attributes);
656
+ const convId = extractConversationId(attrs["gen_ai.prompt.name"]);
657
+ if (convId) {
658
+ traceConversation.set(bytesToHex(span.traceId), convId);
659
+ }
660
+ }
661
+ }
662
+ for (const scopeSpan of resourceSpan.scopeSpans ?? []) {
663
+ for (const span of scopeSpan.spans ?? []) {
664
+ const attrs = attrsToMap(span.attributes);
665
+ const traceId = bytesToHex(span.traceId);
666
+ const conversationId = traceConversation.get(traceId);
667
+ rows.push({
668
+ trace_id: traceId,
669
+ span_id: bytesToHex(span.spanId),
670
+ parent_span_id: bytesToHex(span.parentSpanId) || void 0,
671
+ name: span.name ?? "",
672
+ kind: span.kind ?? void 0,
673
+ start_time_ns: longToNumber(span.startTimeUnixNano),
674
+ end_time_ns: longToNumber(span.endTimeUnixNano),
675
+ status_code: span.status?.code ?? void 0,
676
+ status_message: span.status?.message || void 0,
677
+ attributes: Object.keys(attrs).length > 0 ? attrs : void 0,
678
+ resource_attributes: Object.keys(resourceAttrs).length > 0 ? resourceAttrs : void 0,
679
+ session_id: conversationId ?? attrs["session.id"] ?? attrs["conversation.id"] ?? resourceSessionId
680
+ });
681
+ }
682
+ }
683
+ }
684
+ return rows;
685
+ }
686
+
687
+ // src/otlp/server.ts
688
+ function collectBody(req) {
689
+ return new Promise((resolve, reject) => {
690
+ const chunks = [];
691
+ req.on("data", (chunk) => chunks.push(chunk));
692
+ req.on("end", () => resolve(Buffer.concat(chunks)));
693
+ req.on("error", reject);
694
+ });
695
+ }
696
+ var _serviceNameMap = null;
697
+ function serviceNameMap() {
698
+ if (!_serviceNameMap) {
699
+ _serviceNameMap = /* @__PURE__ */ new Map();
700
+ for (const t of allTargets()) {
701
+ if (t.otel?.serviceName) {
702
+ _serviceNameMap.set(t.otel.serviceName, t.id);
703
+ }
704
+ }
705
+ }
706
+ return _serviceNameMap;
707
+ }
708
+ function ensureSessionsFromOtel(rows) {
709
+ const sessions = /* @__PURE__ */ new Map();
710
+ for (const row of rows) {
711
+ const sid = row.session_id;
712
+ if (!sid) continue;
713
+ if (!sessions.has(sid)) {
714
+ const serviceName = row.resource_attributes?.["service.name"];
715
+ const target = typeof serviceName === "string" ? serviceNameMap().get(serviceName) : void 0;
716
+ sessions.set(sid, {
717
+ target,
718
+ otelInput: 0,
719
+ otelOutput: 0,
720
+ otelCacheRead: 0,
721
+ otelCacheCreation: 0
722
+ });
723
+ }
724
+ const sess = sessions.get(sid);
725
+ if (row.timestamp_ns && row.timestamp_ns > 0) {
726
+ const ms = Math.floor(row.timestamp_ns / 1e6);
727
+ if (!sess.minTimestampMs || ms < sess.minTimestampMs) {
728
+ sess.minTimestampMs = ms;
729
+ }
730
+ }
731
+ if (!sess.model && row.attributes) {
732
+ const m = row.attributes.model ?? row.attributes["gen_ai.response.model"];
733
+ if (typeof m === "string") sess.model = m;
734
+ }
735
+ if (row.name && typeof row.value === "number" && row.name.includes("token")) {
736
+ const tokenType = row.attributes?.type ?? row.attributes?.["gen_ai.token.type"] ?? row.attributes?.token_type;
737
+ if (tokenType === "input") sess.otelInput += row.value;
738
+ else if (tokenType === "output") sess.otelOutput += row.value;
739
+ else if (tokenType === "cacheRead" || tokenType === "cache_read")
740
+ sess.otelCacheRead += row.value;
741
+ else if (tokenType === "cacheCreation" || tokenType === "cache_write")
742
+ sess.otelCacheCreation += row.value;
743
+ }
744
+ }
745
+ for (const [sessionId, sess] of sessions) {
746
+ if (!sess.target) continue;
747
+ upsertSession({
748
+ session_id: sessionId,
749
+ target: sess.target,
750
+ started_at_ms: sess.minTimestampMs,
751
+ model: sess.model,
752
+ otel_input_tokens: sess.otelInput || void 0,
753
+ otel_output_tokens: sess.otelOutput || void 0,
754
+ otel_cache_read_tokens: sess.otelCacheRead || void 0,
755
+ otel_cache_creation_tokens: sess.otelCacheCreation || void 0,
756
+ has_otel: 1
757
+ });
758
+ }
759
+ }
760
+ function isProtobuf(req) {
761
+ const ct = req.headers["content-type"] ?? "";
762
+ return ct.includes("application/x-protobuf") || ct.includes("application/protobuf");
763
+ }
764
+ function isJson(req) {
765
+ const ct = req.headers["content-type"] ?? "";
766
+ return ct.includes("application/json");
767
+ }
768
+ function detectSignal(url) {
769
+ if (url.includes("/logs")) return "logs";
770
+ if (url.includes("/metrics")) return "metrics";
771
+ if (url.includes("/traces")) return "traces";
772
+ return null;
773
+ }
774
+ function sniffSignalFromBody(body, protobuf2) {
775
+ if (protobuf2) {
776
+ try {
777
+ const rows = decodeLogs(body);
778
+ if (rows.length > 0) return "logs";
779
+ } catch {
780
+ }
781
+ try {
782
+ const rows = decodeMetrics(body);
783
+ if (rows.length > 0) return "metrics";
784
+ } catch {
785
+ }
786
+ try {
787
+ const rows = decodeTraces(body);
788
+ if (rows.length > 0) return "traces";
789
+ } catch {
790
+ }
791
+ return null;
792
+ }
793
+ try {
794
+ const data = JSON.parse(body.toString("utf-8"));
795
+ if (data.resourceLogs) return "logs";
796
+ if (data.resourceMetrics) return "metrics";
797
+ if (data.resourceSpans) return "traces";
798
+ } catch {
799
+ }
800
+ return null;
801
+ }
802
+ async function handleOtlpRequest(req, res) {
803
+ const url = req.url ?? "";
804
+ try {
805
+ const body = await collectBody(req);
806
+ let signal = detectSignal(url);
807
+ if (!signal && (url === "/" || url === "")) {
808
+ signal = sniffSignalFromBody(body, isProtobuf(req));
809
+ }
810
+ if (signal === "logs") {
811
+ if (isProtobuf(req)) {
812
+ const rows = decodeLogs(body);
813
+ if (rows.length > 0) {
814
+ insertOtelLogs(rows);
815
+ ensureSessionsFromOtel(rows);
816
+ }
817
+ const respBytes = ExportLogsServiceResponse.encode(
818
+ ExportLogsServiceResponse.create({})
819
+ ).finish();
820
+ res.writeHead(200, { "Content-Type": "application/x-protobuf" });
821
+ res.end(Buffer.from(respBytes));
822
+ } else if (isJson(req)) {
823
+ const data = JSON.parse(body.toString("utf-8"));
824
+ const rows = jsonLogsToRows(data);
825
+ if (rows.length > 0) {
826
+ insertOtelLogs(rows);
827
+ ensureSessionsFromOtel(rows);
828
+ }
829
+ res.writeHead(200, { "Content-Type": "application/json" });
830
+ res.end("{}");
831
+ } else {
832
+ res.writeHead(415);
833
+ res.end();
834
+ }
835
+ } else if (signal === "metrics") {
836
+ refreshIfStale().catch(() => {
837
+ });
838
+ if (isProtobuf(req)) {
839
+ const rows = decodeMetrics(body);
840
+ if (rows.length > 0) {
841
+ insertOtelMetrics(rows);
842
+ ensureSessionsFromOtel(rows);
843
+ }
844
+ const respBytes = ExportMetricsServiceResponse.encode(
845
+ ExportMetricsServiceResponse.create({})
846
+ ).finish();
847
+ res.writeHead(200, { "Content-Type": "application/x-protobuf" });
848
+ res.end(Buffer.from(respBytes));
849
+ } else if (isJson(req)) {
850
+ const data = JSON.parse(body.toString("utf-8"));
851
+ const rows = jsonMetricsToRows(data);
852
+ if (rows.length > 0) {
853
+ insertOtelMetrics(rows);
854
+ ensureSessionsFromOtel(rows);
855
+ }
856
+ res.writeHead(200, { "Content-Type": "application/json" });
857
+ res.end("{}");
858
+ } else {
859
+ res.writeHead(415);
860
+ res.end();
861
+ }
862
+ } else if (signal === "traces") {
863
+ if (isProtobuf(req)) {
864
+ const rows = decodeTraces(body);
865
+ if (rows.length > 0) {
866
+ insertOtelSpans(rows);
867
+ ensureSessionsFromOtel(
868
+ rows.map((r) => ({
869
+ session_id: r.session_id,
870
+ timestamp_ns: r.start_time_ns,
871
+ resource_attributes: r.resource_attributes,
872
+ attributes: r.attributes
873
+ }))
874
+ );
875
+ }
876
+ const respBytes = ExportTracesServiceResponse.encode(
877
+ ExportTracesServiceResponse.create({})
878
+ ).finish();
879
+ res.writeHead(200, { "Content-Type": "application/x-protobuf" });
880
+ res.end(Buffer.from(respBytes));
881
+ } else if (isJson(req)) {
882
+ const data = JSON.parse(body.toString("utf-8"));
883
+ const rows = jsonTracesToRows(data);
884
+ if (rows.length > 0) {
885
+ insertOtelSpans(rows);
886
+ ensureSessionsFromOtel(
887
+ rows.map((r) => ({
888
+ session_id: r.session_id,
889
+ timestamp_ns: r.start_time_ns,
890
+ resource_attributes: r.resource_attributes,
891
+ attributes: r.attributes
892
+ }))
893
+ );
894
+ }
895
+ res.writeHead(200, { "Content-Type": "application/json" });
896
+ res.end("{}");
897
+ } else {
898
+ res.writeHead(415);
899
+ res.end();
900
+ }
901
+ } else {
902
+ res.writeHead(404);
903
+ res.end();
904
+ }
905
+ } catch (err) {
906
+ log.otlp.error("OTLP handler error:", err);
907
+ captureException(err, { component: "otlp", url });
908
+ if (!res.headersSent) {
909
+ res.writeHead(500);
910
+ res.end();
911
+ }
912
+ }
913
+ }
914
+ function createOtlpServer() {
915
+ return http.createServer(async (req, res) => {
916
+ const url = req.url ?? "";
917
+ const method = req.method ?? "";
918
+ if (url === "/health" && method === "GET") {
919
+ res.writeHead(200, { "Content-Type": "application/json" });
920
+ res.end(JSON.stringify({ status: "ok" }));
921
+ return;
922
+ }
923
+ if (method !== "POST") {
924
+ res.writeHead(405);
925
+ res.end();
926
+ return;
927
+ }
928
+ await handleOtlpRequest(req, res);
929
+ });
930
+ }
931
+ function jsonLogsToRows(data) {
932
+ const rows = [];
933
+ for (const rl of data.resourceLogs ?? []) {
934
+ const resourceAttrs = kvListToMap(rl.resource?.attributes);
935
+ const resourceSessionId = resourceAttrs["session.id"] ?? resourceAttrs["conversation.id"] ?? resourceAttrs["service.instance.id"];
936
+ for (const sl of rl.scopeLogs ?? []) {
937
+ for (const lr of sl.logRecords ?? []) {
938
+ const attrs = kvListToMap(lr.attributes);
939
+ const rawBody = extractJsonAnyValue(lr.body);
940
+ const body = rawBody ?? attrs["event.name"] ?? void 0;
941
+ let timestamp_ns = parseInt(lr.timeUnixNano ?? "0", 10);
942
+ if (!timestamp_ns && typeof attrs["event.timestamp"] === "string") {
943
+ timestamp_ns = new Date(attrs["event.timestamp"]).getTime() * 1e6;
944
+ }
945
+ rows.push({
946
+ timestamp_ns,
947
+ observed_timestamp_ns: lr.observedTimeUnixNano ? parseInt(lr.observedTimeUnixNano, 10) : void 0,
948
+ severity_number: lr.severityNumber,
949
+ severity_text: lr.severityText,
950
+ body,
951
+ attributes: Object.keys(attrs).length > 0 ? attrs : void 0,
952
+ resource_attributes: Object.keys(resourceAttrs).length > 0 ? resourceAttrs : void 0,
953
+ session_id: attrs["session.id"] ?? attrs["conversation.id"] ?? resourceSessionId,
954
+ prompt_id: attrs["prompt.id"] ?? attrs.prompt_id,
955
+ trace_id: lr.traceId,
956
+ span_id: lr.spanId
957
+ });
958
+ }
959
+ }
960
+ }
961
+ return rows;
962
+ }
963
+ function jsonMetricsToRows(data) {
964
+ const rows = [];
965
+ for (const rm of data.resourceMetrics ?? []) {
966
+ const resourceAttrs = kvListToMap(rm.resource?.attributes);
967
+ const resourceSessionId = resourceAttrs["session.id"] ?? resourceAttrs["conversation.id"] ?? resourceAttrs["service.instance.id"];
968
+ for (const sm of rm.scopeMetrics ?? []) {
969
+ for (const m of sm.metrics ?? []) {
970
+ const dps = m.gauge?.dataPoints ?? m.sum?.dataPoints ?? m.histogram?.dataPoints ?? [];
971
+ const metricType = m.gauge ? "gauge" : m.sum ? "sum" : m.histogram ? "histogram" : void 0;
972
+ for (const dp of dps) {
973
+ const attrs = kvListToMap(dp.attributes);
974
+ const value = dp.asDouble ?? dp.asInt ?? dp.sum ?? dp.count ?? 0;
975
+ rows.push({
976
+ timestamp_ns: parseInt(dp.timeUnixNano ?? "0", 10),
977
+ name: m.name,
978
+ value: Number(value),
979
+ metric_type: metricType,
980
+ unit: m.unit || void 0,
981
+ attributes: Object.keys(attrs).length > 0 ? attrs : void 0,
982
+ resource_attributes: Object.keys(resourceAttrs).length > 0 ? resourceAttrs : void 0,
983
+ session_id: attrs["session.id"] ?? attrs["conversation.id"] ?? resourceSessionId
984
+ });
985
+ }
986
+ }
987
+ }
988
+ }
989
+ return rows;
990
+ }
991
+ function extractJsonConversationId(promptName) {
992
+ if (typeof promptName !== "string") return void 0;
993
+ const sep = promptName.indexOf("########");
994
+ if (sep === -1) return void 0;
995
+ const uuid = promptName.slice(0, sep);
996
+ if (uuid.length === 36 && uuid[8] === "-") return uuid;
997
+ return void 0;
998
+ }
999
+ function jsonTracesToRows(data) {
1000
+ const rows = [];
1001
+ for (const rs of data.resourceSpans ?? []) {
1002
+ const resourceAttrs = kvListToMap(rs.resource?.attributes);
1003
+ const resourceSessionId = resourceAttrs["session.id"] ?? resourceAttrs["conversation.id"] ?? resourceAttrs["service.instance.id"];
1004
+ const traceConversation = /* @__PURE__ */ new Map();
1005
+ for (const ss of rs.scopeSpans ?? []) {
1006
+ for (const span of ss.spans ?? []) {
1007
+ const attrs = kvListToMap(span.attributes);
1008
+ const convId = extractJsonConversationId(attrs["gen_ai.prompt.name"]);
1009
+ if (convId && span.traceId) {
1010
+ traceConversation.set(span.traceId, convId);
1011
+ }
1012
+ }
1013
+ }
1014
+ for (const ss of rs.scopeSpans ?? []) {
1015
+ for (const span of ss.spans ?? []) {
1016
+ const attrs = kvListToMap(span.attributes);
1017
+ const conversationId = traceConversation.get(span.traceId ?? "");
1018
+ rows.push({
1019
+ trace_id: span.traceId ?? "",
1020
+ span_id: span.spanId ?? "",
1021
+ parent_span_id: span.parentSpanId || void 0,
1022
+ name: span.name ?? "",
1023
+ kind: span.kind ?? void 0,
1024
+ start_time_ns: parseInt(span.startTimeUnixNano ?? "0", 10),
1025
+ end_time_ns: parseInt(span.endTimeUnixNano ?? "0", 10),
1026
+ status_code: span.status?.code ?? void 0,
1027
+ status_message: span.status?.message || void 0,
1028
+ attributes: Object.keys(attrs).length > 0 ? attrs : void 0,
1029
+ resource_attributes: Object.keys(resourceAttrs).length > 0 ? resourceAttrs : void 0,
1030
+ session_id: conversationId ?? attrs["session.id"] ?? attrs["conversation.id"] ?? resourceSessionId
1031
+ });
1032
+ }
1033
+ }
1034
+ }
1035
+ return rows;
1036
+ }
1037
+ function kvListToMap(kvs) {
1038
+ const out = {};
1039
+ if (!kvs) return out;
1040
+ for (const kv of kvs) {
1041
+ out[kv.key] = extractJsonAnyValue(kv.value);
1042
+ }
1043
+ return out;
1044
+ }
1045
+ function extractJsonAnyValue(v) {
1046
+ if (!v) return null;
1047
+ if (v.stringValue !== void 0) return v.stringValue;
1048
+ if (v.intValue !== void 0) return Number(v.intValue);
1049
+ if (v.doubleValue !== void 0) return v.doubleValue;
1050
+ if (v.boolValue !== void 0) return v.boolValue;
1051
+ return JSON.stringify(v);
1052
+ }
1053
+ var entryScript = process.argv[1]?.replaceAll("\\", "/") ?? "";
1054
+ if (entryScript.endsWith("/otlp/server.js") || entryScript.endsWith("/otlp/server.ts")) {
1055
+ const server = createOtlpServer();
1056
+ server.listen(config.otlpPort, config.otlpHost, () => {
1057
+ log.otlp.info(`Listening on ${config.otlpHost}:${config.otlpPort}`);
1058
+ });
1059
+ const shutdown = () => {
1060
+ server.close();
1061
+ process.exit(0);
1062
+ };
1063
+ process.on("SIGTERM", shutdown);
1064
+ process.on("SIGINT", shutdown);
1065
+ process.on("SIGHUP", shutdown);
1066
+ }
1067
+
1068
+ export {
1069
+ handleOtlpRequest,
1070
+ createOtlpServer
1071
+ };
1072
+ //# sourceMappingURL=chunk-XLTCUH5A.js.map