@warlock.js/ai-panoptic 4.3.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/CHANGELOG.md +47 -0
  2. package/LICENSE +21 -0
  3. package/README.md +111 -0
  4. package/cjs/index.cjs +1370 -0
  5. package/cjs/index.cjs.map +1 -0
  6. package/esm/collector/collector.d.mts +19 -0
  7. package/esm/collector/collector.d.mts.map +1 -0
  8. package/esm/collector/collector.mjs +89 -0
  9. package/esm/collector/collector.mjs.map +1 -0
  10. package/esm/collector/extract-span-attributes.d.mts +29 -0
  11. package/esm/collector/extract-span-attributes.d.mts.map +1 -0
  12. package/esm/collector/extract-span-attributes.mjs +76 -0
  13. package/esm/collector/extract-span-attributes.mjs.map +1 -0
  14. package/esm/collector/index.d.mts +5 -0
  15. package/esm/collector/normalize-error.d.mts +27 -0
  16. package/esm/collector/normalize-error.d.mts.map +1 -0
  17. package/esm/collector/normalize-error.mjs +49 -0
  18. package/esm/collector/normalize-error.mjs.map +1 -0
  19. package/esm/collector/report-to-span.d.mts +31 -0
  20. package/esm/collector/report-to-span.d.mts.map +1 -0
  21. package/esm/collector/report-to-span.mjs +53 -0
  22. package/esm/collector/report-to-span.mjs.map +1 -0
  23. package/esm/collector/report-to-trace.d.mts +35 -0
  24. package/esm/collector/report-to-trace.d.mts.map +1 -0
  25. package/esm/collector/report-to-trace.mjs +53 -0
  26. package/esm/collector/report-to-trace.mjs.map +1 -0
  27. package/esm/contracts/collector.contract.d.mts +63 -0
  28. package/esm/contracts/collector.contract.d.mts.map +1 -0
  29. package/esm/contracts/exporter.contract.d.mts +76 -0
  30. package/esm/contracts/exporter.contract.d.mts.map +1 -0
  31. package/esm/contracts/index.d.mts +3 -0
  32. package/esm/contracts/trace.type.d.mts +122 -0
  33. package/esm/contracts/trace.type.d.mts.map +1 -0
  34. package/esm/exporters/console/console-exporter.d.mts +25 -0
  35. package/esm/exporters/console/console-exporter.d.mts.map +1 -0
  36. package/esm/exporters/console/console-exporter.mjs +79 -0
  37. package/esm/exporters/console/console-exporter.mjs.map +1 -0
  38. package/esm/exporters/console/console-exporter.type.d.mts +36 -0
  39. package/esm/exporters/console/console-exporter.type.d.mts.map +1 -0
  40. package/esm/exporters/console/format-span-line.d.mts +17 -0
  41. package/esm/exporters/console/format-span-line.d.mts.map +1 -0
  42. package/esm/exporters/console/format-span-line.mjs +41 -0
  43. package/esm/exporters/console/format-span-line.mjs.map +1 -0
  44. package/esm/exporters/console/index.d.mts +3 -0
  45. package/esm/exporters/file/file-exporter.d.mts +23 -0
  46. package/esm/exporters/file/file-exporter.d.mts.map +1 -0
  47. package/esm/exporters/file/file-exporter.mjs +93 -0
  48. package/esm/exporters/file/file-exporter.mjs.map +1 -0
  49. package/esm/exporters/file/file-exporter.type.d.mts +39 -0
  50. package/esm/exporters/file/file-exporter.type.d.mts.map +1 -0
  51. package/esm/exporters/file/index.d.mts +2 -0
  52. package/esm/exporters/index.d.mts +12 -0
  53. package/esm/exporters/index.mjs +12 -0
  54. package/esm/exporters/langfuse/index.d.mts +2 -0
  55. package/esm/exporters/langfuse/index.mjs +3 -0
  56. package/esm/exporters/langfuse/langfuse-exporter.d.mts +27 -0
  57. package/esm/exporters/langfuse/langfuse-exporter.d.mts.map +1 -0
  58. package/esm/exporters/langfuse/langfuse-exporter.mjs +158 -0
  59. package/esm/exporters/langfuse/langfuse-exporter.mjs.map +1 -0
  60. package/esm/exporters/langfuse/langfuse-exporter.type.d.mts +90 -0
  61. package/esm/exporters/langfuse/langfuse-exporter.type.d.mts.map +1 -0
  62. package/esm/exporters/otel/index.d.mts +2 -0
  63. package/esm/exporters/otel/index.mjs +3 -0
  64. package/esm/exporters/otel/otel-exporter.d.mts +29 -0
  65. package/esm/exporters/otel/otel-exporter.d.mts.map +1 -0
  66. package/esm/exporters/otel/otel-exporter.mjs +142 -0
  67. package/esm/exporters/otel/otel-exporter.mjs.map +1 -0
  68. package/esm/exporters/otel/otel-exporter.type.d.mts +39 -0
  69. package/esm/exporters/otel/otel-exporter.type.d.mts.map +1 -0
  70. package/esm/exporters/utils/gen-ai-attributes.d.mts +65 -0
  71. package/esm/exporters/utils/gen-ai-attributes.d.mts.map +1 -0
  72. package/esm/exporters/utils/gen-ai-attributes.mjs +88 -0
  73. package/esm/exporters/utils/gen-ai-attributes.mjs.map +1 -0
  74. package/esm/exporters/utils/index.d.mts +3 -0
  75. package/esm/exporters/utils/total-cost.d.mts +20 -0
  76. package/esm/exporters/utils/total-cost.d.mts.map +1 -0
  77. package/esm/exporters/utils/total-cost.mjs +23 -0
  78. package/esm/exporters/utils/total-cost.mjs.map +1 -0
  79. package/esm/exporters/utils/walk-spans.d.mts +18 -0
  80. package/esm/exporters/utils/walk-spans.d.mts.map +1 -0
  81. package/esm/exporters/utils/walk-spans.mjs +21 -0
  82. package/esm/exporters/utils/walk-spans.mjs.map +1 -0
  83. package/esm/index.d.mts +31 -0
  84. package/esm/index.mjs +22 -0
  85. package/esm/panoptic/index.d.mts +4 -0
  86. package/esm/panoptic/panoptic-middleware.d.mts +38 -0
  87. package/esm/panoptic/panoptic-middleware.d.mts.map +1 -0
  88. package/esm/panoptic/panoptic-middleware.mjs +68 -0
  89. package/esm/panoptic/panoptic-middleware.mjs.map +1 -0
  90. package/esm/panoptic/panoptic-target.type.d.mts +53 -0
  91. package/esm/panoptic/panoptic-target.type.d.mts.map +1 -0
  92. package/esm/panoptic/panoptic.d.mts +37 -0
  93. package/esm/panoptic/panoptic.d.mts.map +1 -0
  94. package/esm/panoptic/panoptic.mjs +134 -0
  95. package/esm/panoptic/panoptic.mjs.map +1 -0
  96. package/esm/panoptic/panoptic.type.d.mts +100 -0
  97. package/esm/panoptic/panoptic.type.d.mts.map +1 -0
  98. package/esm/store/in-memory-trace-store.d.mts +32 -0
  99. package/esm/store/in-memory-trace-store.d.mts.map +1 -0
  100. package/esm/store/in-memory-trace-store.mjs +134 -0
  101. package/esm/store/in-memory-trace-store.mjs.map +1 -0
  102. package/esm/store/index.d.mts +6 -0
  103. package/esm/store/index.mjs +5 -0
  104. package/esm/store/match-trace.d.mts +21 -0
  105. package/esm/store/match-trace.d.mts.map +1 -0
  106. package/esm/store/match-trace.mjs +44 -0
  107. package/esm/store/match-trace.mjs.map +1 -0
  108. package/esm/store/sum-usage.d.mts +34 -0
  109. package/esm/store/sum-usage.d.mts.map +1 -0
  110. package/esm/store/sum-usage.mjs +65 -0
  111. package/esm/store/sum-usage.mjs.map +1 -0
  112. package/esm/store/trace-aggregate.type.d.mts +51 -0
  113. package/esm/store/trace-aggregate.type.d.mts.map +1 -0
  114. package/esm/store/trace-query.type.d.mts +45 -0
  115. package/esm/store/trace-query.type.d.mts.map +1 -0
  116. package/esm/store/trace-store.contract.d.mts +55 -0
  117. package/esm/store/trace-store.contract.d.mts.map +1 -0
  118. package/llms-full.txt +450 -0
  119. package/llms.txt +11 -0
  120. package/package.json +40 -0
  121. package/skills/README.md +17 -0
  122. package/skills/export-traces/SKILL.md +152 -0
  123. package/skills/observe-with-panoptic/SKILL.md +128 -0
  124. package/skills/query-traces/SKILL.md +152 -0
@@ -0,0 +1,142 @@
1
+ import { GEN_AI_ATTRIBUTES, toGenAiAttributes } from "../utils/gen-ai-attributes.mjs";
2
+
3
+ //#region ../@warlock.js/ai-panoptic/src/exporters/otel/otel-exporter.ts
4
+ const EXPORTER_NAME = "otel";
5
+ const DEFAULT_TRACER_NAME = "@warlock.js/ai-panoptic";
6
+ let OtelApi;
7
+ let isModuleExists = null;
8
+ let loadingPromise;
9
+ const OTEL_INSTALL_INSTRUCTIONS = `
10
+ The Panoptic OpenTelemetry exporter requires the @opentelemetry/api package.
11
+ Install it with:
12
+
13
+ npm install @opentelemetry/api
14
+
15
+ Or with your preferred package manager:
16
+
17
+ pnpm add @opentelemetry/api
18
+ yarn add @opentelemetry/api
19
+ `.trim();
20
+ /**
21
+ * Settle the lazy import of `@opentelemetry/api` once, concurrency-safe.
22
+ * A bare `catch` flips the flag to `false`; the curated install string
23
+ * surfaces at use time so a missing SDK never throws a raw module
24
+ * resolution error.
25
+ */
26
+ function loadOtel() {
27
+ if (isModuleExists !== null) return Promise.resolve();
28
+ if (loadingPromise) return loadingPromise;
29
+ loadingPromise = (async () => {
30
+ try {
31
+ OtelApi = await import("@opentelemetry/api");
32
+ isModuleExists = true;
33
+ } catch {
34
+ isModuleExists = false;
35
+ }
36
+ })();
37
+ return loadingPromise;
38
+ }
39
+ /**
40
+ * {@link ExporterContract} that maps Panoptic traces onto OpenTelemetry
41
+ * spans following the GenAI semantic conventions (`gen_ai.*`
42
+ * attributes). Lazily imports `@opentelemetry/api` so it stays an
43
+ * OPTIONAL peer — importing this module never forces the SDK to be
44
+ * installed, and a missing SDK surfaces as a curated "install this"
45
+ * error on first `export`, not a boot-time stack trace.
46
+ *
47
+ * The exporter emits onto a `Tracer` you supply (or fetches one from the
48
+ * globally registered provider). It never configures the SDK — wiring a
49
+ * `TracerProvider`, processors, and span exporters is the host app's
50
+ * job, exactly as with any other OTel instrumentation.
51
+ *
52
+ * Each {@link TraceSpan} becomes one OTel span with the source span's
53
+ * start/end times and parent relationship reconstructed, so the emitted
54
+ * tree matches the original execution tree.
55
+ *
56
+ * @example
57
+ * // app already set up @opentelemetry/sdk-trace-base + a provider
58
+ * collector.use(otelExporter({ tracerName: "my-app", system: "openai" }));
59
+ */
60
+ function otelExporter(options = {}) {
61
+ loadOtel();
62
+ return {
63
+ name: EXPORTER_NAME,
64
+ async export(trace) {
65
+ await loadOtel();
66
+ if (!isModuleExists) throw new Error(OTEL_INSTALL_INSTRUCTIONS);
67
+ emitSpan(resolveTracer(options), trace.root, void 0, options);
68
+ }
69
+ };
70
+ }
71
+ /**
72
+ * Resolve the `Tracer` spans are emitted on — the caller-supplied one,
73
+ * or one fetched from the globally registered provider by name.
74
+ */
75
+ function resolveTracer(options) {
76
+ if (options.tracer) return options.tracer;
77
+ return OtelApi.trace.getTracer(options.tracerName ?? DEFAULT_TRACER_NAME, options.tracerVersion);
78
+ }
79
+ /**
80
+ * Recreate one {@link TraceSpan} (and its subtree) as OTel spans. The
81
+ * span is started with the source `startedAt`, parented under
82
+ * `parentContext` so the tree is preserved, annotated with GenAI
83
+ * attributes, given the mapped status, and ended at `endedAt`. Children
84
+ * recurse under this span's context.
85
+ */
86
+ function emitSpan(tracer, span, parentContext, options) {
87
+ const startTime = toEpochMillis(span.startedAt);
88
+ const baseContext = parentContext ?? OtelApi.context.active();
89
+ const otelSpan = tracer.startSpan(span.name, { startTime }, baseContext);
90
+ applyAttributes(otelSpan, span, options);
91
+ applyStatus(otelSpan, span);
92
+ const childContext = OtelApi.trace.setSpan(baseContext, otelSpan);
93
+ for (const child of span.children) emitSpan(tracer, child, childContext, options);
94
+ otelSpan.end(toEpochMillis(span.endedAt));
95
+ }
96
+ /**
97
+ * Set the GenAI + Warlock attributes on the OTel span, defaulting
98
+ * `gen_ai.system` from the exporter options when the span carried none.
99
+ */
100
+ function applyAttributes(otelSpan, span, options) {
101
+ const attributes = toGenAiAttributes(span);
102
+ if (options.system !== void 0 && attributes[GEN_AI_ATTRIBUTES.system] === void 0) attributes[GEN_AI_ATTRIBUTES.system] = options.system;
103
+ otelSpan.setAttributes(attributes);
104
+ }
105
+ /**
106
+ * Map the Panoptic span status onto the OTel span status, recording the
107
+ * normalized error as an exception event + ERROR status when present.
108
+ */
109
+ function applyStatus(otelSpan, span) {
110
+ const codes = OtelApi.SpanStatusCode;
111
+ if (span.error) otelSpan.recordException({
112
+ name: span.error.type,
113
+ message: span.error.message,
114
+ stack: span.error.stack
115
+ });
116
+ if (span.status === "failed" || span.status === "cancelled") {
117
+ otelSpan.setStatus({
118
+ code: codes.ERROR,
119
+ message: span.error?.message
120
+ });
121
+ return;
122
+ }
123
+ if (span.status === "max-iterations" || span.status === "awaiting-input") {
124
+ otelSpan.setStatus({
125
+ code: codes.UNSET,
126
+ message: span.status === "max-iterations" ? "Run hit the iteration cap without an explicit end" : "Run is awaiting the next input turn"
127
+ });
128
+ return;
129
+ }
130
+ otelSpan.setStatus({ code: codes.OK });
131
+ }
132
+ /**
133
+ * Convert an ISO-8601 timestamp to epoch milliseconds — the `TimeInput`
134
+ * form OTel's `startSpan` / `Span.end` accept directly.
135
+ */
136
+ function toEpochMillis(isoTimestamp) {
137
+ return new Date(isoTimestamp).getTime();
138
+ }
139
+
140
+ //#endregion
141
+ export { otelExporter };
142
+ //# sourceMappingURL=otel-exporter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-exporter.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/otel/otel-exporter.ts"],"sourcesContent":["import type {\n Context,\n Span,\n SpanStatusCode as SpanStatusCodeEnum,\n Tracer,\n} from \"@opentelemetry/api\";\nimport type { ExporterContract, Trace, TraceSpan } from \"../../contracts\";\nimport { toGenAiAttributes, GEN_AI_ATTRIBUTES } from \"../utils\";\nimport type { OtelExporterOptions } from \"./otel-exporter.type\";\n\nconst EXPORTER_NAME = \"otel\";\nconst DEFAULT_TRACER_NAME = \"@warlock.js/ai-panoptic\";\n\n// ============================================================\n// Lazily-loaded @opentelemetry/api (OPTIONAL peer)\n// ============================================================\n\nlet OtelApi: typeof import(\"@opentelemetry/api\");\nlet isModuleExists: boolean | null = null;\nlet loadingPromise: Promise<void> | undefined;\n\nconst OTEL_INSTALL_INSTRUCTIONS = `\nThe Panoptic OpenTelemetry exporter requires the @opentelemetry/api package.\nInstall it with:\n\n npm install @opentelemetry/api\n\nOr with your preferred package manager:\n\n pnpm add @opentelemetry/api\n yarn add @opentelemetry/api\n`.trim();\n\n/**\n * Settle the lazy import of `@opentelemetry/api` once, concurrency-safe.\n * A bare `catch` flips the flag to `false`; the curated install string\n * surfaces at use time so a missing SDK never throws a raw module\n * resolution error.\n */\nfunction loadOtel(): Promise<void> {\n if (isModuleExists !== null) {\n return Promise.resolve();\n }\n\n if (loadingPromise) {\n return loadingPromise;\n }\n\n loadingPromise = (async () => {\n try {\n OtelApi = await import(\"@opentelemetry/api\");\n isModuleExists = true;\n } catch {\n isModuleExists = false;\n }\n })();\n\n return loadingPromise;\n}\n\n/**\n * {@link ExporterContract} that maps Panoptic traces onto OpenTelemetry\n * spans following the GenAI semantic conventions (`gen_ai.*`\n * attributes). Lazily imports `@opentelemetry/api` so it stays an\n * OPTIONAL peer — importing this module never forces the SDK to be\n * installed, and a missing SDK surfaces as a curated \"install this\"\n * error on first `export`, not a boot-time stack trace.\n *\n * The exporter emits onto a `Tracer` you supply (or fetches one from the\n * globally registered provider). It never configures the SDK — wiring a\n * `TracerProvider`, processors, and span exporters is the host app's\n * job, exactly as with any other OTel instrumentation.\n *\n * Each {@link TraceSpan} becomes one OTel span with the source span's\n * start/end times and parent relationship reconstructed, so the emitted\n * tree matches the original execution tree.\n *\n * @example\n * // app already set up @opentelemetry/sdk-trace-base + a provider\n * collector.use(otelExporter({ tracerName: \"my-app\", system: \"openai\" }));\n */\nexport function otelExporter(options: OtelExporterOptions = {}): ExporterContract {\n loadOtel();\n\n return {\n name: EXPORTER_NAME,\n async export(trace: Trace): Promise<void> {\n await loadOtel();\n\n if (!isModuleExists) {\n throw new Error(OTEL_INSTALL_INSTRUCTIONS);\n }\n\n const tracer = resolveTracer(options);\n emitSpan(tracer, trace.root, undefined, options);\n },\n };\n}\n\n/**\n * Resolve the `Tracer` spans are emitted on — the caller-supplied one,\n * or one fetched from the globally registered provider by name.\n */\nfunction resolveTracer(options: OtelExporterOptions): Tracer {\n if (options.tracer) {\n return options.tracer;\n }\n\n return OtelApi.trace.getTracer(\n options.tracerName ?? DEFAULT_TRACER_NAME,\n options.tracerVersion,\n );\n}\n\n/**\n * Recreate one {@link TraceSpan} (and its subtree) as OTel spans. The\n * span is started with the source `startedAt`, parented under\n * `parentContext` so the tree is preserved, annotated with GenAI\n * attributes, given the mapped status, and ended at `endedAt`. Children\n * recurse under this span's context.\n */\nfunction emitSpan(\n tracer: Tracer,\n span: TraceSpan,\n parentContext: Context | undefined,\n options: OtelExporterOptions,\n): void {\n const startTime = toEpochMillis(span.startedAt);\n const baseContext = parentContext ?? OtelApi.context.active();\n\n const otelSpan = tracer.startSpan(span.name, { startTime }, baseContext);\n\n applyAttributes(otelSpan, span, options);\n applyStatus(otelSpan, span);\n\n const childContext = OtelApi.trace.setSpan(baseContext, otelSpan);\n\n for (const child of span.children) {\n emitSpan(tracer, child, childContext, options);\n }\n\n otelSpan.end(toEpochMillis(span.endedAt));\n}\n\n/**\n * Set the GenAI + Warlock attributes on the OTel span, defaulting\n * `gen_ai.system` from the exporter options when the span carried none.\n */\nfunction applyAttributes(\n otelSpan: Span,\n span: TraceSpan,\n options: OtelExporterOptions,\n): void {\n const attributes = toGenAiAttributes(span);\n\n if (options.system !== undefined && attributes[GEN_AI_ATTRIBUTES.system] === undefined) {\n attributes[GEN_AI_ATTRIBUTES.system] = options.system;\n }\n\n otelSpan.setAttributes(attributes);\n}\n\n/**\n * Map the Panoptic span status onto the OTel span status, recording the\n * normalized error as an exception event + ERROR status when present.\n */\nfunction applyStatus(otelSpan: Span, span: TraceSpan): void {\n const codes: typeof SpanStatusCodeEnum = OtelApi.SpanStatusCode;\n\n if (span.error) {\n otelSpan.recordException({\n name: span.error.type,\n message: span.error.message,\n stack: span.error.stack,\n });\n }\n\n if (span.status === \"failed\" || span.status === \"cancelled\") {\n otelSpan.setStatus({\n code: codes.ERROR,\n message: span.error?.message,\n });\n return;\n }\n\n // A capped / paused run is neither a failure nor a clean success.\n // Mapping it to OK would let a hit iteration cap read as a healthy\n // run; leave the OTel status UNSET with a descriptive message so the\n // outcome is visible without being miscounted as an error.\n if (span.status === \"max-iterations\" || span.status === \"awaiting-input\") {\n otelSpan.setStatus({\n code: codes.UNSET,\n message:\n span.status === \"max-iterations\"\n ? \"Run hit the iteration cap without an explicit end\"\n : \"Run is awaiting the next input turn\",\n });\n return;\n }\n\n otelSpan.setStatus({ code: codes.OK });\n}\n\n/**\n * Convert an ISO-8601 timestamp to epoch milliseconds — the `TimeInput`\n * form OTel's `startSpan` / `Span.end` accept directly.\n */\nfunction toEpochMillis(isoTimestamp: string): number {\n return new Date(isoTimestamp).getTime();\n}\n"],"mappings":";;;AAUA,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAM5B,IAAI;AACJ,IAAI,iBAAiC;AACrC,IAAI;AAEJ,MAAM,4BAA4B;;;;;;;;;;EAUhC,KAAK;;;;;;;AAQP,SAAS,WAA0B;CACjC,IAAI,mBAAmB,MACrB,OAAO,QAAQ,QAAQ;CAGzB,IAAI,gBACF,OAAO;CAGT,kBAAkB,YAAY;EAC5B,IAAI;GACF,UAAU,MAAM,OAAO;GACvB,iBAAiB;EACnB,QAAQ;GACN,iBAAiB;EACnB;CACF,EAAC,CAAE;CAEH,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,aAAa,UAA+B,CAAC,GAAqB;CAChF,SAAS;CAET,OAAO;EACL,MAAM;EACN,MAAM,OAAO,OAA6B;GACxC,MAAM,SAAS;GAEf,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,yBAAyB;GAI3C,SADe,cAAc,OACf,GAAG,MAAM,MAAM,QAAW,OAAO;EACjD;CACF;AACF;;;;;AAMA,SAAS,cAAc,SAAsC;CAC3D,IAAI,QAAQ,QACV,OAAO,QAAQ;CAGjB,OAAO,QAAQ,MAAM,UACnB,QAAQ,cAAc,qBACtB,QAAQ,aACV;AACF;;;;;;;;AASA,SAAS,SACP,QACA,MACA,eACA,SACM;CACN,MAAM,YAAY,cAAc,KAAK,SAAS;CAC9C,MAAM,cAAc,iBAAiB,QAAQ,QAAQ,OAAO;CAE5D,MAAM,WAAW,OAAO,UAAU,KAAK,MAAM,EAAE,UAAU,GAAG,WAAW;CAEvE,gBAAgB,UAAU,MAAM,OAAO;CACvC,YAAY,UAAU,IAAI;CAE1B,MAAM,eAAe,QAAQ,MAAM,QAAQ,aAAa,QAAQ;CAEhE,KAAK,MAAM,SAAS,KAAK,UACvB,SAAS,QAAQ,OAAO,cAAc,OAAO;CAG/C,SAAS,IAAI,cAAc,KAAK,OAAO,CAAC;AAC1C;;;;;AAMA,SAAS,gBACP,UACA,MACA,SACM;CACN,MAAM,aAAa,kBAAkB,IAAI;CAEzC,IAAI,QAAQ,WAAW,UAAa,WAAW,kBAAkB,YAAY,QAC3E,WAAW,kBAAkB,UAAU,QAAQ;CAGjD,SAAS,cAAc,UAAU;AACnC;;;;;AAMA,SAAS,YAAY,UAAgB,MAAuB;CAC1D,MAAM,QAAmC,QAAQ;CAEjD,IAAI,KAAK,OACP,SAAS,gBAAgB;EACvB,MAAM,KAAK,MAAM;EACjB,SAAS,KAAK,MAAM;EACpB,OAAO,KAAK,MAAM;CACpB,CAAC;CAGH,IAAI,KAAK,WAAW,YAAY,KAAK,WAAW,aAAa;EAC3D,SAAS,UAAU;GACjB,MAAM,MAAM;GACZ,SAAS,KAAK,OAAO;EACvB,CAAC;EACD;CACF;CAMA,IAAI,KAAK,WAAW,oBAAoB,KAAK,WAAW,kBAAkB;EACxE,SAAS,UAAU;GACjB,MAAM,MAAM;GACZ,SACE,KAAK,WAAW,mBACZ,sDACA;EACR,CAAC;EACD;CACF;CAEA,SAAS,UAAU,EAAE,MAAM,MAAM,GAAG,CAAC;AACvC;;;;;AAMA,SAAS,cAAc,cAA8B;CACnD,OAAO,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ;AACxC"}
@@ -0,0 +1,39 @@
1
+ import { Tracer } from "@opentelemetry/api";
2
+
3
+ //#region ../@warlock.js/ai-panoptic/src/exporters/otel/otel-exporter.type.d.ts
4
+ /**
5
+ * Options for {@link otelExporter}.
6
+ *
7
+ * The exporter never owns a `TracerProvider` — wiring the SDK
8
+ * (`@opentelemetry/sdk-trace-base`, exporters, processors) is the host
9
+ * app's job. Pass either a ready {@link Tracer} or a name and let the
10
+ * exporter fetch one from the globally registered provider via
11
+ * `trace.getTracer(name)`.
12
+ */
13
+ type OtelExporterOptions = {
14
+ /**
15
+ * A `Tracer` to emit spans on. When omitted, the exporter lazily calls
16
+ * `trace.getTracer(tracerName, tracerVersion)` against the globally
17
+ * registered provider, so it works with whatever SDK the app set up.
18
+ */
19
+ tracer?: Tracer;
20
+ /**
21
+ * Instrumentation-scope name passed to `trace.getTracer` when `tracer`
22
+ * is not supplied. Defaults to `"@warlock.js/ai-panoptic"`.
23
+ */
24
+ tracerName?: string;
25
+ /**
26
+ * Instrumentation-scope version passed alongside `tracerName`.
27
+ * Optional.
28
+ */
29
+ tracerVersion?: string;
30
+ /**
31
+ * Value of the `gen_ai.system` attribute set on every span when the
32
+ * span itself didn't carry one (e.g. `"openai"`, `"anthropic"`).
33
+ * Optional — omitted when neither this nor the span supplies it.
34
+ */
35
+ system?: string;
36
+ };
37
+ //#endregion
38
+ export { OtelExporterOptions };
39
+ //# sourceMappingURL=otel-exporter.type.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-exporter.type.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/otel/otel-exporter.type.ts"],"mappings":";;;;;AAWA;;;;;;;KAAY,mBAAA;EAsBV;;AAAM;;;EAhBN,MAAA,GAAS,MAAM;;;;;EAKf,UAAA;;;;;EAKA,aAAA;;;;;;EAMA,MAAA;AAAA"}
@@ -0,0 +1,65 @@
1
+ import { TraceSpan } from "../../contracts/trace.type.mjs";
2
+ //#region ../@warlock.js/ai-panoptic/src/exporters/utils/gen-ai-attributes.d.ts
3
+ /**
4
+ * Subset of the OpenTelemetry GenAI semantic-convention attribute keys
5
+ * Panoptic emits. Kept as a named constant map (not inline string
6
+ * literals scattered through the mapper) so the convention names live in
7
+ * one place and a convention bump is a single edit.
8
+ *
9
+ * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/
10
+ */
11
+ declare const GEN_AI_ATTRIBUTES: {
12
+ readonly operationName: "gen_ai.operation.name";
13
+ readonly system: "gen_ai.system";
14
+ readonly requestModel: "gen_ai.request.model";
15
+ readonly responseModel: "gen_ai.response.model";
16
+ readonly usageInputTokens: "gen_ai.usage.input_tokens";
17
+ readonly usageOutputTokens: "gen_ai.usage.output_tokens";
18
+ readonly conversationId: "gen_ai.conversation.id";
19
+ };
20
+ /**
21
+ * Panoptic-specific attribute keys that have no GenAI-convention
22
+ * equivalent. Namespaced under `warlock.*` so they never collide with a
23
+ * future `gen_ai.*` key the spec might add.
24
+ */
25
+ declare const WARLOCK_ATTRIBUTES: {
26
+ readonly reportType: "warlock.report.type";
27
+ readonly version: "warlock.version";
28
+ readonly durationMs: "warlock.duration_ms";
29
+ readonly totalTokens: "gen_ai.usage.total_tokens";
30
+ readonly cachedTokens: "gen_ai.usage.cached_tokens";
31
+ readonly reasoningTokens: "gen_ai.usage.reasoning_tokens";
32
+ readonly costUsd: "warlock.cost.usd";
33
+ };
34
+ /**
35
+ * Span attribute values an OpenTelemetry / Langfuse backend accepts.
36
+ * GenAI attributes are scalars; the framework's free-form
37
+ * `TraceSpan.attributes` may also carry these.
38
+ */
39
+ type AttributeValue = string | number | boolean;
40
+ /**
41
+ * Project a {@link TraceSpan} onto the OpenTelemetry GenAI
42
+ * semantic-convention attribute set.
43
+ *
44
+ * The vendor-neutral {@link TraceSpan} carries identity, timing, status,
45
+ * and rolled-up `usage` as first-class fields; model identity and other
46
+ * provider detail live in the free-form `attributes` bag the collector
47
+ * populated. This mapper folds both into a flat `gen_ai.*` /
48
+ * `warlock.*` attribute map ready to set on an OTel span or hand to a
49
+ * Langfuse generation.
50
+ *
51
+ * - `gen_ai.operation.name` / `gen_ai.system` / `gen_ai.request.model`
52
+ * are forwarded from the span's `attributes` when the collector set
53
+ * them; never invented here.
54
+ * - Token counts come from the span's typed `usage` rollup.
55
+ * - The free-form `attributes` are merged last so an explicit collector
56
+ * value wins over a derived one.
57
+ *
58
+ * @example
59
+ * const attributes = toGenAiAttributes(span);
60
+ * // { "gen_ai.usage.input_tokens": 150, "gen_ai.usage.output_tokens": 320, ... }
61
+ */
62
+ declare function toGenAiAttributes(span: TraceSpan): Record<string, AttributeValue>;
63
+ //#endregion
64
+ export { AttributeValue, GEN_AI_ATTRIBUTES, WARLOCK_ATTRIBUTES, toGenAiAttributes };
65
+ //# sourceMappingURL=gen-ai-attributes.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gen-ai-attributes.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/utils/gen-ai-attributes.ts"],"mappings":";;;;;AAWA;;;;;cAAa,iBAAA;EAAA;;;;;;;;;;;;;cAeA,kBAAA;EAAA;;;;;;;;;;AAea;AAwB1B;;KAxBY,cAAA;;;;;;;;;;;AAwBqE;;;;;;;;;;;;iBAAjE,iBAAA,CAAkB,IAAA,EAAM,SAAA,GAAY,MAAA,SAAe,cAAA"}
@@ -0,0 +1,88 @@
1
+ import { totalCostUsd } from "./total-cost.mjs";
2
+
3
+ //#region ../@warlock.js/ai-panoptic/src/exporters/utils/gen-ai-attributes.ts
4
+ /**
5
+ * Subset of the OpenTelemetry GenAI semantic-convention attribute keys
6
+ * Panoptic emits. Kept as a named constant map (not inline string
7
+ * literals scattered through the mapper) so the convention names live in
8
+ * one place and a convention bump is a single edit.
9
+ *
10
+ * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/
11
+ */
12
+ const GEN_AI_ATTRIBUTES = {
13
+ operationName: "gen_ai.operation.name",
14
+ system: "gen_ai.system",
15
+ requestModel: "gen_ai.request.model",
16
+ responseModel: "gen_ai.response.model",
17
+ usageInputTokens: "gen_ai.usage.input_tokens",
18
+ usageOutputTokens: "gen_ai.usage.output_tokens",
19
+ conversationId: "gen_ai.conversation.id"
20
+ };
21
+ /**
22
+ * Panoptic-specific attribute keys that have no GenAI-convention
23
+ * equivalent. Namespaced under `warlock.*` so they never collide with a
24
+ * future `gen_ai.*` key the spec might add.
25
+ */
26
+ const WARLOCK_ATTRIBUTES = {
27
+ reportType: "warlock.report.type",
28
+ version: "warlock.version",
29
+ durationMs: "warlock.duration_ms",
30
+ totalTokens: "gen_ai.usage.total_tokens",
31
+ cachedTokens: "gen_ai.usage.cached_tokens",
32
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
33
+ costUsd: "warlock.cost.usd"
34
+ };
35
+ /**
36
+ * Project a {@link TraceSpan} onto the OpenTelemetry GenAI
37
+ * semantic-convention attribute set.
38
+ *
39
+ * The vendor-neutral {@link TraceSpan} carries identity, timing, status,
40
+ * and rolled-up `usage` as first-class fields; model identity and other
41
+ * provider detail live in the free-form `attributes` bag the collector
42
+ * populated. This mapper folds both into a flat `gen_ai.*` /
43
+ * `warlock.*` attribute map ready to set on an OTel span or hand to a
44
+ * Langfuse generation.
45
+ *
46
+ * - `gen_ai.operation.name` / `gen_ai.system` / `gen_ai.request.model`
47
+ * are forwarded from the span's `attributes` when the collector set
48
+ * them; never invented here.
49
+ * - Token counts come from the span's typed `usage` rollup.
50
+ * - The free-form `attributes` are merged last so an explicit collector
51
+ * value wins over a derived one.
52
+ *
53
+ * @example
54
+ * const attributes = toGenAiAttributes(span);
55
+ * // { "gen_ai.usage.input_tokens": 150, "gen_ai.usage.output_tokens": 320, ... }
56
+ */
57
+ function toGenAiAttributes(span) {
58
+ const attributes = {
59
+ [WARLOCK_ATTRIBUTES.reportType]: span.type,
60
+ [WARLOCK_ATTRIBUTES.durationMs]: span.duration,
61
+ [WARLOCK_ATTRIBUTES.totalTokens]: span.usage.total,
62
+ [GEN_AI_ATTRIBUTES.usageInputTokens]: span.usage.input,
63
+ [GEN_AI_ATTRIBUTES.usageOutputTokens]: span.usage.output
64
+ };
65
+ if (span.version !== void 0) attributes[WARLOCK_ATTRIBUTES.version] = span.version;
66
+ if (span.sessionId !== void 0) attributes[GEN_AI_ATTRIBUTES.conversationId] = span.sessionId;
67
+ if (span.usage.cachedTokens !== void 0) attributes[WARLOCK_ATTRIBUTES.cachedTokens] = span.usage.cachedTokens;
68
+ if (span.usage.reasoningTokens !== void 0) attributes[WARLOCK_ATTRIBUTES.reasoningTokens] = span.usage.reasoningTokens;
69
+ const cost = totalCostUsd(span.usage);
70
+ if (cost !== void 0) attributes[WARLOCK_ATTRIBUTES.costUsd] = cost;
71
+ mergeScalarAttributes(attributes, span.attributes);
72
+ return attributes;
73
+ }
74
+ /**
75
+ * Copy the scalar entries of a free-form attribute bag onto the target
76
+ * map. Non-scalar values (objects, arrays, functions) are skipped — OTel
77
+ * and Langfuse attribute values must be primitives, and the collector's
78
+ * bag may legitimately hold nested digests that don't belong on a span
79
+ * attribute. Explicit collector values overwrite derived ones.
80
+ */
81
+ function mergeScalarAttributes(target, source) {
82
+ if (!source) return;
83
+ for (const [key, value] of Object.entries(source)) if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") target[key] = value;
84
+ }
85
+
86
+ //#endregion
87
+ export { GEN_AI_ATTRIBUTES, WARLOCK_ATTRIBUTES, toGenAiAttributes };
88
+ //# sourceMappingURL=gen-ai-attributes.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gen-ai-attributes.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/utils/gen-ai-attributes.ts"],"sourcesContent":["import type { TraceSpan } from \"../../contracts\";\nimport { totalCostUsd } from \"./total-cost\";\n\n/**\n * Subset of the OpenTelemetry GenAI semantic-convention attribute keys\n * Panoptic emits. Kept as a named constant map (not inline string\n * literals scattered through the mapper) so the convention names live in\n * one place and a convention bump is a single edit.\n *\n * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/\n */\nexport const GEN_AI_ATTRIBUTES = {\n operationName: \"gen_ai.operation.name\",\n system: \"gen_ai.system\",\n requestModel: \"gen_ai.request.model\",\n responseModel: \"gen_ai.response.model\",\n usageInputTokens: \"gen_ai.usage.input_tokens\",\n usageOutputTokens: \"gen_ai.usage.output_tokens\",\n conversationId: \"gen_ai.conversation.id\",\n} as const;\n\n/**\n * Panoptic-specific attribute keys that have no GenAI-convention\n * equivalent. Namespaced under `warlock.*` so they never collide with a\n * future `gen_ai.*` key the spec might add.\n */\nexport const WARLOCK_ATTRIBUTES = {\n reportType: \"warlock.report.type\",\n version: \"warlock.version\",\n durationMs: \"warlock.duration_ms\",\n totalTokens: \"gen_ai.usage.total_tokens\",\n cachedTokens: \"gen_ai.usage.cached_tokens\",\n reasoningTokens: \"gen_ai.usage.reasoning_tokens\",\n costUsd: \"warlock.cost.usd\",\n} as const;\n\n/**\n * Span attribute values an OpenTelemetry / Langfuse backend accepts.\n * GenAI attributes are scalars; the framework's free-form\n * `TraceSpan.attributes` may also carry these.\n */\nexport type AttributeValue = string | number | boolean;\n\n/**\n * Project a {@link TraceSpan} onto the OpenTelemetry GenAI\n * semantic-convention attribute set.\n *\n * The vendor-neutral {@link TraceSpan} carries identity, timing, status,\n * and rolled-up `usage` as first-class fields; model identity and other\n * provider detail live in the free-form `attributes` bag the collector\n * populated. This mapper folds both into a flat `gen_ai.*` /\n * `warlock.*` attribute map ready to set on an OTel span or hand to a\n * Langfuse generation.\n *\n * - `gen_ai.operation.name` / `gen_ai.system` / `gen_ai.request.model`\n * are forwarded from the span's `attributes` when the collector set\n * them; never invented here.\n * - Token counts come from the span's typed `usage` rollup.\n * - The free-form `attributes` are merged last so an explicit collector\n * value wins over a derived one.\n *\n * @example\n * const attributes = toGenAiAttributes(span);\n * // { \"gen_ai.usage.input_tokens\": 150, \"gen_ai.usage.output_tokens\": 320, ... }\n */\nexport function toGenAiAttributes(span: TraceSpan): Record<string, AttributeValue> {\n const attributes: Record<string, AttributeValue> = {\n [WARLOCK_ATTRIBUTES.reportType]: span.type,\n [WARLOCK_ATTRIBUTES.durationMs]: span.duration,\n [WARLOCK_ATTRIBUTES.totalTokens]: span.usage.total,\n [GEN_AI_ATTRIBUTES.usageInputTokens]: span.usage.input,\n [GEN_AI_ATTRIBUTES.usageOutputTokens]: span.usage.output,\n };\n\n if (span.version !== undefined) {\n attributes[WARLOCK_ATTRIBUTES.version] = span.version;\n }\n\n if (span.sessionId !== undefined) {\n attributes[GEN_AI_ATTRIBUTES.conversationId] = span.sessionId;\n }\n\n if (span.usage.cachedTokens !== undefined) {\n attributes[WARLOCK_ATTRIBUTES.cachedTokens] = span.usage.cachedTokens;\n }\n\n if (span.usage.reasoningTokens !== undefined) {\n attributes[WARLOCK_ATTRIBUTES.reasoningTokens] = span.usage.reasoningTokens;\n }\n\n const cost = totalCostUsd(span.usage);\n\n if (cost !== undefined) {\n attributes[WARLOCK_ATTRIBUTES.costUsd] = cost;\n }\n\n mergeScalarAttributes(attributes, span.attributes);\n\n return attributes;\n}\n\n/**\n * Copy the scalar entries of a free-form attribute bag onto the target\n * map. Non-scalar values (objects, arrays, functions) are skipped — OTel\n * and Langfuse attribute values must be primitives, and the collector's\n * bag may legitimately hold nested digests that don't belong on a span\n * attribute. Explicit collector values overwrite derived ones.\n */\nfunction mergeScalarAttributes(\n target: Record<string, AttributeValue>,\n source: Record<string, unknown> | undefined,\n): void {\n if (!source) {\n return;\n }\n\n for (const [key, value] of Object.entries(source)) {\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n target[key] = value;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,oBAAoB;CAC/B,eAAe;CACf,QAAQ;CACR,cAAc;CACd,eAAe;CACf,kBAAkB;CAClB,mBAAmB;CACnB,gBAAgB;AAClB;;;;;;AAOA,MAAa,qBAAqB;CAChC,YAAY;CACZ,SAAS;CACT,YAAY;CACZ,aAAa;CACb,cAAc;CACd,iBAAiB;CACjB,SAAS;AACX;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,kBAAkB,MAAiD;CACjF,MAAM,aAA6C;GAChD,mBAAmB,aAAa,KAAK;GACrC,mBAAmB,aAAa,KAAK;GACrC,mBAAmB,cAAc,KAAK,MAAM;GAC5C,kBAAkB,mBAAmB,KAAK,MAAM;GAChD,kBAAkB,oBAAoB,KAAK,MAAM;CACpD;CAEA,IAAI,KAAK,YAAY,QACnB,WAAW,mBAAmB,WAAW,KAAK;CAGhD,IAAI,KAAK,cAAc,QACrB,WAAW,kBAAkB,kBAAkB,KAAK;CAGtD,IAAI,KAAK,MAAM,iBAAiB,QAC9B,WAAW,mBAAmB,gBAAgB,KAAK,MAAM;CAG3D,IAAI,KAAK,MAAM,oBAAoB,QACjC,WAAW,mBAAmB,mBAAmB,KAAK,MAAM;CAG9D,MAAM,OAAO,aAAa,KAAK,KAAK;CAEpC,IAAI,SAAS,QACX,WAAW,mBAAmB,WAAW;CAG3C,sBAAsB,YAAY,KAAK,UAAU;CAEjD,OAAO;AACT;;;;;;;;AASA,SAAS,sBACP,QACA,QACM;CACN,IAAI,CAAC,QACH;CAGF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,WAC7E,OAAO,OAAO;AAGpB"}
@@ -0,0 +1,3 @@
1
+ import { AttributeValue, GEN_AI_ATTRIBUTES, WARLOCK_ATTRIBUTES, toGenAiAttributes } from "./gen-ai-attributes.mjs";
2
+ import { totalCostUsd } from "./total-cost.mjs";
3
+ import { walkSpans } from "./walk-spans.mjs";
@@ -0,0 +1,20 @@
1
+ import { Usage } from "@warlock.js/ai";
2
+
3
+ //#region ../@warlock.js/ai-panoptic/src/exporters/utils/total-cost.d.ts
4
+ /**
5
+ * Collapse a {@link Usage.cost} breakdown into a single USD scalar by
6
+ * summing every populated field. Mirrors the formula documented on
7
+ * `Usage.cost` (input + output + cachedInput + cachedOutput), and also
8
+ * folds in `reasoning` for forward-safety when a provider prices
9
+ * reasoning tokens as a separate channel. Returns `undefined` when no
10
+ * pricing was attached, so exporters can omit the cost attribute
11
+ * entirely rather than reporting a misleading `0`.
12
+ *
13
+ * @example
14
+ * totalCostUsd({ input: 1, output: 2, total: 3, cost: { input: 0.01, output: 0.04 } });
15
+ * // => 0.05
16
+ */
17
+ declare function totalCostUsd(usage: Usage): number | undefined;
18
+ //#endregion
19
+ export { totalCostUsd };
20
+ //# sourceMappingURL=total-cost.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"total-cost.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/utils/total-cost.ts"],"mappings":";;;;;AAeA;;;;AAAyC;;;;;;;iBAAzB,YAAA,CAAa,KAAY,EAAL,KAAK"}
@@ -0,0 +1,23 @@
1
+ //#region ../@warlock.js/ai-panoptic/src/exporters/utils/total-cost.ts
2
+ /**
3
+ * Collapse a {@link Usage.cost} breakdown into a single USD scalar by
4
+ * summing every populated field. Mirrors the formula documented on
5
+ * `Usage.cost` (input + output + cachedInput + cachedOutput), and also
6
+ * folds in `reasoning` for forward-safety when a provider prices
7
+ * reasoning tokens as a separate channel. Returns `undefined` when no
8
+ * pricing was attached, so exporters can omit the cost attribute
9
+ * entirely rather than reporting a misleading `0`.
10
+ *
11
+ * @example
12
+ * totalCostUsd({ input: 1, output: 2, total: 3, cost: { input: 0.01, output: 0.04 } });
13
+ * // => 0.05
14
+ */
15
+ function totalCostUsd(usage) {
16
+ const cost = usage.cost;
17
+ if (!cost) return;
18
+ return (cost.input ?? 0) + (cost.output ?? 0) + (cost.cachedInput ?? 0) + (cost.cachedOutput ?? 0) + (cost.reasoning ?? 0);
19
+ }
20
+
21
+ //#endregion
22
+ export { totalCostUsd };
23
+ //# sourceMappingURL=total-cost.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"total-cost.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/utils/total-cost.ts"],"sourcesContent":["import type { Usage } from \"@warlock.js/ai\";\n\n/**\n * Collapse a {@link Usage.cost} breakdown into a single USD scalar by\n * summing every populated field. Mirrors the formula documented on\n * `Usage.cost` (input + output + cachedInput + cachedOutput), and also\n * folds in `reasoning` for forward-safety when a provider prices\n * reasoning tokens as a separate channel. Returns `undefined` when no\n * pricing was attached, so exporters can omit the cost attribute\n * entirely rather than reporting a misleading `0`.\n *\n * @example\n * totalCostUsd({ input: 1, output: 2, total: 3, cost: { input: 0.01, output: 0.04 } });\n * // => 0.05\n */\nexport function totalCostUsd(usage: Usage): number | undefined {\n const cost = usage.cost;\n\n if (!cost) {\n return undefined;\n }\n\n return (\n (cost.input ?? 0) +\n (cost.output ?? 0) +\n (cost.cachedInput ?? 0) +\n (cost.cachedOutput ?? 0) +\n (cost.reasoning ?? 0)\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,SAAgB,aAAa,OAAkC;CAC7D,MAAM,OAAO,MAAM;CAEnB,IAAI,CAAC,MACH;CAGF,QACG,KAAK,SAAS,MACd,KAAK,UAAU,MACf,KAAK,eAAe,MACpB,KAAK,gBAAgB,MACrB,KAAK,aAAa;AAEvB"}
@@ -0,0 +1,18 @@
1
+ import { TraceSpan } from "../../contracts/trace.type.mjs";
2
+ //#region ../@warlock.js/ai-panoptic/src/exporters/utils/walk-spans.d.ts
3
+ /**
4
+ * Depth-first pre-order traversal of a {@link TraceSpan} tree, yielding
5
+ * the root first and then each descendant in `children` (invocation)
6
+ * order. Exporters that emit a flat span stream — OpenTelemetry, the
7
+ * console table — walk the tree once with this instead of re-writing the
8
+ * recursion in every exporter.
9
+ *
10
+ * @example
11
+ * for (const span of walkSpans(trace.root)) {
12
+ * emit(span);
13
+ * }
14
+ */
15
+ declare function walkSpans(root: TraceSpan): Generator<TraceSpan>;
16
+ //#endregion
17
+ export { walkSpans };
18
+ //# sourceMappingURL=walk-spans.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk-spans.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/utils/walk-spans.ts"],"mappings":";;;;;AAcA;;;;;;;;;iBAAiB,SAAA,CAAU,IAAA,EAAM,SAAA,GAAY,SAAA,CAAU,SAAA"}
@@ -0,0 +1,21 @@
1
+ //#region ../@warlock.js/ai-panoptic/src/exporters/utils/walk-spans.ts
2
+ /**
3
+ * Depth-first pre-order traversal of a {@link TraceSpan} tree, yielding
4
+ * the root first and then each descendant in `children` (invocation)
5
+ * order. Exporters that emit a flat span stream — OpenTelemetry, the
6
+ * console table — walk the tree once with this instead of re-writing the
7
+ * recursion in every exporter.
8
+ *
9
+ * @example
10
+ * for (const span of walkSpans(trace.root)) {
11
+ * emit(span);
12
+ * }
13
+ */
14
+ function* walkSpans(root) {
15
+ yield root;
16
+ for (const child of root.children) yield* walkSpans(child);
17
+ }
18
+
19
+ //#endregion
20
+ export { walkSpans };
21
+ //# sourceMappingURL=walk-spans.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk-spans.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai-panoptic/src/exporters/utils/walk-spans.ts"],"sourcesContent":["import type { TraceSpan } from \"../../contracts\";\n\n/**\n * Depth-first pre-order traversal of a {@link TraceSpan} tree, yielding\n * the root first and then each descendant in `children` (invocation)\n * order. Exporters that emit a flat span stream — OpenTelemetry, the\n * console table — walk the tree once with this instead of re-writing the\n * recursion in every exporter.\n *\n * @example\n * for (const span of walkSpans(trace.root)) {\n * emit(span);\n * }\n */\nexport function* walkSpans(root: TraceSpan): Generator<TraceSpan> {\n yield root;\n\n for (const child of root.children) {\n yield* walkSpans(child);\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,UAAiB,UAAU,MAAuC;CAChE,MAAM;CAEN,KAAK,MAAM,SAAS,KAAK,UACvB,OAAO,UAAU,KAAK;AAE1B"}
@@ -0,0 +1,31 @@
1
+ import { Trace, TraceSpan, TraceSpanError } from "./contracts/trace.type.mjs";
2
+ import { ExporterContract } from "./contracts/exporter.contract.mjs";
3
+ import { CollectorContract } from "./contracts/collector.contract.mjs";
4
+ import { createCollector } from "./collector/collector.mjs";
5
+ import { reportToTrace } from "./collector/report-to-trace.mjs";
6
+ import { reportToSpan } from "./collector/report-to-span.mjs";
7
+ import { extractSpanAttributes } from "./collector/extract-span-attributes.mjs";
8
+ import { normalizeError } from "./collector/normalize-error.mjs";
9
+ import { TraceAggregate } from "./store/trace-aggregate.type.mjs";
10
+ import { TraceQuery } from "./store/trace-query.type.mjs";
11
+ import { TraceStoreContract } from "./store/trace-store.contract.mjs";
12
+ import { InMemoryTraceStoreOptions, createInMemoryTraceStore } from "./store/in-memory-trace-store.mjs";
13
+ import { matchTrace } from "./store/match-trace.mjs";
14
+ import { emptyUsage, sumUsage } from "./store/sum-usage.mjs";
15
+ import { ConsoleExporterOptions, ConsoleLike } from "./exporters/console/console-exporter.type.mjs";
16
+ import { consoleExporter } from "./exporters/console/console-exporter.mjs";
17
+ import { formatSpanLine } from "./exporters/console/format-span-line.mjs";
18
+ import { FileExporterOptions, TraceRecord } from "./exporters/file/file-exporter.type.mjs";
19
+ import { fileExporter } from "./exporters/file/file-exporter.mjs";
20
+ import { LangfuseClientLike, LangfuseExporterOptions, LangfuseObservationBody, LangfuseObservationEndBody, LangfuseObservationLevel, LangfuseObservationLike, LangfuseTraceBody, LangfuseTraceLike, LangfuseUsageBody } from "./exporters/langfuse/langfuse-exporter.type.mjs";
21
+ import { langfuseExporter } from "./exporters/langfuse/langfuse-exporter.mjs";
22
+ import { OtelExporterOptions } from "./exporters/otel/otel-exporter.type.mjs";
23
+ import { otelExporter } from "./exporters/otel/otel-exporter.mjs";
24
+ import { AttributeValue, GEN_AI_ATTRIBUTES, WARLOCK_ATTRIBUTES, toGenAiAttributes } from "./exporters/utils/gen-ai-attributes.mjs";
25
+ import { totalCostUsd } from "./exporters/utils/total-cost.mjs";
26
+ import { walkSpans } from "./exporters/utils/walk-spans.mjs";
27
+ import { CompletedEventPayload, PanopticTarget } from "./panoptic/panoptic-target.type.mjs";
28
+ import { Panoptic, PanopticOptions } from "./panoptic/panoptic.type.mjs";
29
+ import { panoptic } from "./panoptic/panoptic.mjs";
30
+ import { createPanopticMiddleware } from "./panoptic/panoptic-middleware.mjs";
31
+ export { type AttributeValue, type CollectorContract, type CompletedEventPayload, type ConsoleExporterOptions, type ConsoleLike, type ExporterContract, type FileExporterOptions, GEN_AI_ATTRIBUTES, type InMemoryTraceStoreOptions, type LangfuseClientLike, type LangfuseExporterOptions, type LangfuseObservationBody, type LangfuseObservationEndBody, type LangfuseObservationLevel, type LangfuseObservationLike, type LangfuseTraceBody, type LangfuseTraceLike, type LangfuseUsageBody, type OtelExporterOptions, type Panoptic, type PanopticOptions, type PanopticTarget, type Trace, type TraceAggregate, type TraceQuery, type TraceRecord, type TraceSpan, type TraceSpanError, type TraceStoreContract, WARLOCK_ATTRIBUTES, consoleExporter, createCollector, createInMemoryTraceStore, createPanopticMiddleware, emptyUsage, extractSpanAttributes, fileExporter, formatSpanLine, langfuseExporter, matchTrace, normalizeError, otelExporter, panoptic, reportToSpan, reportToTrace, sumUsage, toGenAiAttributes, totalCostUsd, walkSpans };
package/esm/index.mjs ADDED
@@ -0,0 +1,22 @@
1
+ import { walkSpans } from "./exporters/utils/walk-spans.mjs";
2
+ import { normalizeError } from "./collector/normalize-error.mjs";
3
+ import { extractSpanAttributes } from "./collector/extract-span-attributes.mjs";
4
+ import { reportToSpan } from "./collector/report-to-span.mjs";
5
+ import { reportToTrace } from "./collector/report-to-trace.mjs";
6
+ import { createCollector } from "./collector/collector.mjs";
7
+ import { matchTrace } from "./store/match-trace.mjs";
8
+ import { emptyUsage, sumUsage } from "./store/sum-usage.mjs";
9
+ import { createInMemoryTraceStore } from "./store/in-memory-trace-store.mjs";
10
+ import "./store/index.mjs";
11
+ import { totalCostUsd } from "./exporters/utils/total-cost.mjs";
12
+ import { GEN_AI_ATTRIBUTES, WARLOCK_ATTRIBUTES, toGenAiAttributes } from "./exporters/utils/gen-ai-attributes.mjs";
13
+ import { formatSpanLine } from "./exporters/console/format-span-line.mjs";
14
+ import { consoleExporter } from "./exporters/console/console-exporter.mjs";
15
+ import { fileExporter } from "./exporters/file/file-exporter.mjs";
16
+ import { langfuseExporter } from "./exporters/langfuse/langfuse-exporter.mjs";
17
+ import { otelExporter } from "./exporters/otel/otel-exporter.mjs";
18
+ import "./exporters/index.mjs";
19
+ import { createPanopticMiddleware } from "./panoptic/panoptic-middleware.mjs";
20
+ import { panoptic } from "./panoptic/panoptic.mjs";
21
+
22
+ export { GEN_AI_ATTRIBUTES, WARLOCK_ATTRIBUTES, consoleExporter, createCollector, createInMemoryTraceStore, createPanopticMiddleware, emptyUsage, extractSpanAttributes, fileExporter, formatSpanLine, langfuseExporter, matchTrace, normalizeError, otelExporter, panoptic, reportToSpan, reportToTrace, sumUsage, toGenAiAttributes, totalCostUsd, walkSpans };
@@ -0,0 +1,4 @@
1
+ import { CompletedEventPayload, PanopticTarget } from "./panoptic-target.type.mjs";
2
+ import { Panoptic, PanopticOptions } from "./panoptic.type.mjs";
3
+ import { panoptic } from "./panoptic.mjs";
4
+ import { createPanopticMiddleware } from "./panoptic-middleware.mjs";
@@ -0,0 +1,38 @@
1
+ import { CollectorContract } from "../contracts/collector.contract.mjs";
2
+ import { AgentMiddleware } from "@warlock.js/ai";
3
+
4
+ //#region ../@warlock.js/ai-panoptic/src/panoptic/panoptic-middleware.d.ts
5
+ /**
6
+ * Build an {@link AgentMiddleware} that feeds a collector from the
7
+ * `execute`- and `supervisor`-level hooks. An alternative wiring to event
8
+ * subscription for apps that already compose cross-cutting concerns
9
+ * through the agent middleware pipeline (`[cache, budget, guardrail,
10
+ * observability]`). Declaring both hook maps lets a single middleware
11
+ * object work uniformly on agents (which fire the `execute` map) and
12
+ * supervisors (which fire the `supervisor` map) — registering it on a
13
+ * supervisor would otherwise install and collect nothing silently.
14
+ *
15
+ * Both terminal paths are covered on each surface:
16
+ * - `after` — fires on a run that produced a result. A run can complete
17
+ * with `result.error` populated (the engine still calls `after`), so
18
+ * the report AND the envelope error are collected; the error type and
19
+ * message land on the root span.
20
+ * - `onError` — fires when the run threw before assembling a result. The
21
+ * error carries the partial result's report on its envelope; when
22
+ * present it is collected, with the error itself threaded onto the
23
+ * root span so failed runs still produce a trace.
24
+ *
25
+ * The hooks never return a value, so they never mutate the agent's /
26
+ * supervisor's result. The `collect` call is fire-and-forget relative to
27
+ * the run — the collector isolates exporter failures internally, and we
28
+ * additionally swallow any rejection here so an observability fault can
29
+ * never surface on the run's hot path.
30
+ *
31
+ * @param collector - the collector traces are fed into.
32
+ * @param name - stable middleware name (kebab-case). Defaults to
33
+ * `"panoptic"`.
34
+ */
35
+ declare function createPanopticMiddleware(collector: CollectorContract, name?: string): AgentMiddleware;
36
+ //#endregion
37
+ export { createPanopticMiddleware };
38
+ //# sourceMappingURL=panoptic-middleware.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panoptic-middleware.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai-panoptic/src/panoptic/panoptic-middleware.ts"],"mappings":";;;;;;AAiCA;;;;;;;;;AAGkB;;;;;;;;;;;;;;;;;;;iBAHF,wBAAA,CACd,SAAA,EAAW,iBAAA,EACX,IAAA,YACC,eAAe"}