@xandout/libra-harness 0.1.8

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 (289) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +486 -0
  3. package/dist/agent.d.ts +174 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +575 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/ai-sdk-model.d.ts +26 -0
  8. package/dist/ai-sdk-model.d.ts.map +1 -0
  9. package/dist/ai-sdk-model.js +260 -0
  10. package/dist/ai-sdk-model.js.map +1 -0
  11. package/dist/context.d.ts +75 -0
  12. package/dist/context.d.ts.map +1 -0
  13. package/dist/context.js +2 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/errors.d.ts +33 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +59 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/extension.d.ts +63 -0
  20. package/dist/extension.d.ts.map +1 -0
  21. package/dist/extension.js +2 -0
  22. package/dist/extension.js.map +1 -0
  23. package/dist/extras/extension-loader.d.ts +205 -0
  24. package/dist/extras/extension-loader.d.ts.map +1 -0
  25. package/dist/extras/extension-loader.js +315 -0
  26. package/dist/extras/extension-loader.js.map +1 -0
  27. package/dist/extras/extensions/auto-steer/extension.d.ts +46 -0
  28. package/dist/extras/extensions/auto-steer/extension.d.ts.map +1 -0
  29. package/dist/extras/extensions/auto-steer/extension.js +52 -0
  30. package/dist/extras/extensions/auto-steer/extension.js.map +1 -0
  31. package/dist/extras/extensions/auto-steer/extension.json +7 -0
  32. package/dist/extras/extensions/auto-steer/index.d.ts +3 -0
  33. package/dist/extras/extensions/auto-steer/index.d.ts.map +1 -0
  34. package/dist/extras/extensions/auto-steer/index.js +2 -0
  35. package/dist/extras/extensions/auto-steer/index.js.map +1 -0
  36. package/dist/extras/extensions/disk-session/extension.d.ts +167 -0
  37. package/dist/extras/extensions/disk-session/extension.d.ts.map +1 -0
  38. package/dist/extras/extensions/disk-session/extension.js +492 -0
  39. package/dist/extras/extensions/disk-session/extension.js.map +1 -0
  40. package/dist/extras/extensions/disk-session/extension.json +6 -0
  41. package/dist/extras/extensions/disk-session/extension.test.d.ts +2 -0
  42. package/dist/extras/extensions/disk-session/extension.test.d.ts.map +1 -0
  43. package/dist/extras/extensions/disk-session/extension.test.js +672 -0
  44. package/dist/extras/extensions/disk-session/extension.test.js.map +1 -0
  45. package/dist/extras/extensions/disk-session/index.d.ts +3 -0
  46. package/dist/extras/extensions/disk-session/index.d.ts.map +1 -0
  47. package/dist/extras/extensions/disk-session/index.js +2 -0
  48. package/dist/extras/extensions/disk-session/index.js.map +1 -0
  49. package/dist/extras/extensions/emoji/extension.d.ts +20 -0
  50. package/dist/extras/extensions/emoji/extension.d.ts.map +1 -0
  51. package/dist/extras/extensions/emoji/extension.js +22 -0
  52. package/dist/extras/extensions/emoji/extension.js.map +1 -0
  53. package/dist/extras/extensions/emoji/extension.json +7 -0
  54. package/dist/extras/extensions/emoji/index.d.ts +3 -0
  55. package/dist/extras/extensions/emoji/index.d.ts.map +1 -0
  56. package/dist/extras/extensions/emoji/index.js +2 -0
  57. package/dist/extras/extensions/emoji/index.js.map +1 -0
  58. package/dist/extras/extensions/filesystem/extension.d.ts +53 -0
  59. package/dist/extras/extensions/filesystem/extension.d.ts.map +1 -0
  60. package/dist/extras/extensions/filesystem/extension.js +350 -0
  61. package/dist/extras/extensions/filesystem/extension.js.map +1 -0
  62. package/dist/extras/extensions/filesystem/extension.json +6 -0
  63. package/dist/extras/extensions/filesystem/extension.test.d.ts +2 -0
  64. package/dist/extras/extensions/filesystem/extension.test.d.ts.map +1 -0
  65. package/dist/extras/extensions/filesystem/extension.test.js +387 -0
  66. package/dist/extras/extensions/filesystem/extension.test.js.map +1 -0
  67. package/dist/extras/extensions/filesystem/index.d.ts +2 -0
  68. package/dist/extras/extensions/filesystem/index.d.ts.map +1 -0
  69. package/dist/extras/extensions/filesystem/index.js +2 -0
  70. package/dist/extras/extensions/filesystem/index.js.map +1 -0
  71. package/dist/extras/extensions/keyword-extractor/extension.d.ts +53 -0
  72. package/dist/extras/extensions/keyword-extractor/extension.d.ts.map +1 -0
  73. package/dist/extras/extensions/keyword-extractor/extension.js +61 -0
  74. package/dist/extras/extensions/keyword-extractor/extension.js.map +1 -0
  75. package/dist/extras/extensions/keyword-extractor/extension.json +6 -0
  76. package/dist/extras/extensions/keyword-extractor/extension.test.d.ts +2 -0
  77. package/dist/extras/extensions/keyword-extractor/extension.test.d.ts.map +1 -0
  78. package/dist/extras/extensions/keyword-extractor/extension.test.js +105 -0
  79. package/dist/extras/extensions/keyword-extractor/extension.test.js.map +1 -0
  80. package/dist/extras/extensions/keyword-extractor/index.d.ts +5 -0
  81. package/dist/extras/extensions/keyword-extractor/index.d.ts.map +1 -0
  82. package/dist/extras/extensions/keyword-extractor/index.js +3 -0
  83. package/dist/extras/extensions/keyword-extractor/index.js.map +1 -0
  84. package/dist/extras/extensions/keyword-extractor/nlp.d.ts +68 -0
  85. package/dist/extras/extensions/keyword-extractor/nlp.d.ts.map +1 -0
  86. package/dist/extras/extensions/keyword-extractor/nlp.js +156 -0
  87. package/dist/extras/extensions/keyword-extractor/nlp.js.map +1 -0
  88. package/dist/extras/extensions/keyword-extractor/nlp.test.d.ts +2 -0
  89. package/dist/extras/extensions/keyword-extractor/nlp.test.d.ts.map +1 -0
  90. package/dist/extras/extensions/keyword-extractor/nlp.test.js +176 -0
  91. package/dist/extras/extensions/keyword-extractor/nlp.test.js.map +1 -0
  92. package/dist/extras/extensions/logger/extension.d.ts +52 -0
  93. package/dist/extras/extensions/logger/extension.d.ts.map +1 -0
  94. package/dist/extras/extensions/logger/extension.js +68 -0
  95. package/dist/extras/extensions/logger/extension.js.map +1 -0
  96. package/dist/extras/extensions/logger/extension.json +7 -0
  97. package/dist/extras/extensions/logger/index.d.ts +3 -0
  98. package/dist/extras/extensions/logger/index.d.ts.map +1 -0
  99. package/dist/extras/extensions/logger/index.js +2 -0
  100. package/dist/extras/extensions/logger/index.js.map +1 -0
  101. package/dist/extras/extensions/mcp/extension.d.ts +63 -0
  102. package/dist/extras/extensions/mcp/extension.d.ts.map +1 -0
  103. package/dist/extras/extensions/mcp/extension.js +437 -0
  104. package/dist/extras/extensions/mcp/extension.js.map +1 -0
  105. package/dist/extras/extensions/mcp/extension.json +7 -0
  106. package/dist/extras/extensions/mcp/extension.test.d.ts +2 -0
  107. package/dist/extras/extensions/mcp/extension.test.d.ts.map +1 -0
  108. package/dist/extras/extensions/mcp/extension.test.js +286 -0
  109. package/dist/extras/extensions/mcp/extension.test.js.map +1 -0
  110. package/dist/extras/extensions/mcp/index.d.ts +3 -0
  111. package/dist/extras/extensions/mcp/index.d.ts.map +1 -0
  112. package/dist/extras/extensions/mcp/index.js +2 -0
  113. package/dist/extras/extensions/mcp/index.js.map +1 -0
  114. package/dist/extras/extensions/mem-session/extension.d.ts +24 -0
  115. package/dist/extras/extensions/mem-session/extension.d.ts.map +1 -0
  116. package/dist/extras/extensions/mem-session/extension.js +49 -0
  117. package/dist/extras/extensions/mem-session/extension.js.map +1 -0
  118. package/dist/extras/extensions/mem-session/extension.json +6 -0
  119. package/dist/extras/extensions/mem-session/index.d.ts +2 -0
  120. package/dist/extras/extensions/mem-session/index.d.ts.map +1 -0
  121. package/dist/extras/extensions/mem-session/index.js +2 -0
  122. package/dist/extras/extensions/mem-session/index.js.map +1 -0
  123. package/dist/extras/extensions/memory/extension.d.ts +54 -0
  124. package/dist/extras/extensions/memory/extension.d.ts.map +1 -0
  125. package/dist/extras/extensions/memory/extension.js +143 -0
  126. package/dist/extras/extensions/memory/extension.js.map +1 -0
  127. package/dist/extras/extensions/memory/extension.json +7 -0
  128. package/dist/extras/extensions/memory/index.d.ts +5 -0
  129. package/dist/extras/extensions/memory/index.d.ts.map +1 -0
  130. package/dist/extras/extensions/memory/index.js +3 -0
  131. package/dist/extras/extensions/memory/index.js.map +1 -0
  132. package/dist/extras/extensions/memory/llm-extractor.d.ts +42 -0
  133. package/dist/extras/extensions/memory/llm-extractor.d.ts.map +1 -0
  134. package/dist/extras/extensions/memory/llm-extractor.js +89 -0
  135. package/dist/extras/extensions/memory/llm-extractor.js.map +1 -0
  136. package/dist/extras/extensions/memory/types.d.ts +142 -0
  137. package/dist/extras/extensions/memory/types.d.ts.map +1 -0
  138. package/dist/extras/extensions/memory/types.js +2 -0
  139. package/dist/extras/extensions/memory/types.js.map +1 -0
  140. package/dist/extras/extensions/otel/extension.d.ts +57 -0
  141. package/dist/extras/extensions/otel/extension.d.ts.map +1 -0
  142. package/dist/extras/extensions/otel/extension.js +253 -0
  143. package/dist/extras/extensions/otel/extension.js.map +1 -0
  144. package/dist/extras/extensions/otel/extension.json +7 -0
  145. package/dist/extras/extensions/otel/extension.test.d.ts +2 -0
  146. package/dist/extras/extensions/otel/extension.test.d.ts.map +1 -0
  147. package/dist/extras/extensions/otel/extension.test.js +399 -0
  148. package/dist/extras/extensions/otel/extension.test.js.map +1 -0
  149. package/dist/extras/extensions/otel/index.d.ts +4 -0
  150. package/dist/extras/extensions/otel/index.d.ts.map +1 -0
  151. package/dist/extras/extensions/otel/index.js +3 -0
  152. package/dist/extras/extensions/otel/index.js.map +1 -0
  153. package/dist/extras/extensions/otel/jsonl-span-exporter.d.ts +60 -0
  154. package/dist/extras/extensions/otel/jsonl-span-exporter.d.ts.map +1 -0
  155. package/dist/extras/extensions/otel/jsonl-span-exporter.js +134 -0
  156. package/dist/extras/extensions/otel/jsonl-span-exporter.js.map +1 -0
  157. package/dist/extras/extensions/scripts/extension.d.ts +180 -0
  158. package/dist/extras/extensions/scripts/extension.d.ts.map +1 -0
  159. package/dist/extras/extensions/scripts/extension.js +618 -0
  160. package/dist/extras/extensions/scripts/extension.js.map +1 -0
  161. package/dist/extras/extensions/scripts/extension.json +7 -0
  162. package/dist/extras/extensions/scripts/extension.test.d.ts +2 -0
  163. package/dist/extras/extensions/scripts/extension.test.d.ts.map +1 -0
  164. package/dist/extras/extensions/scripts/extension.test.js +552 -0
  165. package/dist/extras/extensions/scripts/extension.test.js.map +1 -0
  166. package/dist/extras/extensions/scripts/index.d.ts +3 -0
  167. package/dist/extras/extensions/scripts/index.d.ts.map +1 -0
  168. package/dist/extras/extensions/scripts/index.js +2 -0
  169. package/dist/extras/extensions/scripts/index.js.map +1 -0
  170. package/dist/extras/extensions/skills/extension.d.ts +105 -0
  171. package/dist/extras/extensions/skills/extension.d.ts.map +1 -0
  172. package/dist/extras/extensions/skills/extension.js +419 -0
  173. package/dist/extras/extensions/skills/extension.js.map +1 -0
  174. package/dist/extras/extensions/skills/extension.json +7 -0
  175. package/dist/extras/extensions/skills/extension.test.d.ts +2 -0
  176. package/dist/extras/extensions/skills/extension.test.d.ts.map +1 -0
  177. package/dist/extras/extensions/skills/extension.test.js +184 -0
  178. package/dist/extras/extensions/skills/extension.test.js.map +1 -0
  179. package/dist/extras/extensions/skills/index.d.ts +4 -0
  180. package/dist/extras/extensions/skills/index.d.ts.map +1 -0
  181. package/dist/extras/extensions/skills/index.js +3 -0
  182. package/dist/extras/extensions/skills/index.js.map +1 -0
  183. package/dist/extras/extensions/streaming/extension.d.ts +15 -0
  184. package/dist/extras/extensions/streaming/extension.d.ts.map +1 -0
  185. package/dist/extras/extensions/streaming/extension.js +41 -0
  186. package/dist/extras/extensions/streaming/extension.js.map +1 -0
  187. package/dist/extras/extensions/streaming/extension.json +6 -0
  188. package/dist/extras/extensions/streaming/index.d.ts +2 -0
  189. package/dist/extras/extensions/streaming/index.d.ts.map +1 -0
  190. package/dist/extras/extensions/streaming/index.js +2 -0
  191. package/dist/extras/extensions/streaming/index.js.map +1 -0
  192. package/dist/extras/extensions/structured-output/extension.d.ts +11 -0
  193. package/dist/extras/extensions/structured-output/extension.d.ts.map +1 -0
  194. package/dist/extras/extensions/structured-output/extension.js +102 -0
  195. package/dist/extras/extensions/structured-output/extension.js.map +1 -0
  196. package/dist/extras/extensions/structured-output/extension.json +7 -0
  197. package/dist/extras/extensions/structured-output/index.d.ts +3 -0
  198. package/dist/extras/extensions/structured-output/index.d.ts.map +1 -0
  199. package/dist/extras/extensions/structured-output/index.js +2 -0
  200. package/dist/extras/extensions/structured-output/index.js.map +1 -0
  201. package/dist/extras/extensions/timestamp/extension.d.ts +11 -0
  202. package/dist/extras/extensions/timestamp/extension.d.ts.map +1 -0
  203. package/dist/extras/extensions/timestamp/extension.js +21 -0
  204. package/dist/extras/extensions/timestamp/extension.js.map +1 -0
  205. package/dist/extras/extensions/timestamp/extension.json +6 -0
  206. package/dist/extras/extensions/timestamp/index.d.ts +2 -0
  207. package/dist/extras/extensions/timestamp/index.d.ts.map +1 -0
  208. package/dist/extras/extensions/timestamp/index.js +2 -0
  209. package/dist/extras/extensions/timestamp/index.js.map +1 -0
  210. package/dist/extras/extensions/token-stats/extension.d.ts +50 -0
  211. package/dist/extras/extensions/token-stats/extension.d.ts.map +1 -0
  212. package/dist/extras/extensions/token-stats/extension.js +99 -0
  213. package/dist/extras/extensions/token-stats/extension.js.map +1 -0
  214. package/dist/extras/extensions/token-stats/extension.json +7 -0
  215. package/dist/extras/extensions/token-stats/extension.test.d.ts +2 -0
  216. package/dist/extras/extensions/token-stats/extension.test.d.ts.map +1 -0
  217. package/dist/extras/extensions/token-stats/extension.test.js +197 -0
  218. package/dist/extras/extensions/token-stats/extension.test.js.map +1 -0
  219. package/dist/extras/extensions/token-stats/index.d.ts +3 -0
  220. package/dist/extras/extensions/token-stats/index.d.ts.map +1 -0
  221. package/dist/extras/extensions/token-stats/index.js +2 -0
  222. package/dist/extras/extensions/token-stats/index.js.map +1 -0
  223. package/dist/extras/extensions/tool-buffer/extension.d.ts +89 -0
  224. package/dist/extras/extensions/tool-buffer/extension.d.ts.map +1 -0
  225. package/dist/extras/extensions/tool-buffer/extension.js +182 -0
  226. package/dist/extras/extensions/tool-buffer/extension.js.map +1 -0
  227. package/dist/extras/extensions/tool-buffer/extension.json +7 -0
  228. package/dist/extras/extensions/tool-buffer/extension.test.d.ts +2 -0
  229. package/dist/extras/extensions/tool-buffer/extension.test.d.ts.map +1 -0
  230. package/dist/extras/extensions/tool-buffer/extension.test.js +549 -0
  231. package/dist/extras/extensions/tool-buffer/extension.test.js.map +1 -0
  232. package/dist/extras/extensions/tool-buffer/index.d.ts +3 -0
  233. package/dist/extras/extensions/tool-buffer/index.d.ts.map +1 -0
  234. package/dist/extras/extensions/tool-buffer/index.js +2 -0
  235. package/dist/extras/extensions/tool-buffer/index.js.map +1 -0
  236. package/dist/extras/extensions/weather-tool/extension.d.ts +22 -0
  237. package/dist/extras/extensions/weather-tool/extension.d.ts.map +1 -0
  238. package/dist/extras/extensions/weather-tool/extension.js +33 -0
  239. package/dist/extras/extensions/weather-tool/extension.js.map +1 -0
  240. package/dist/extras/extensions/weather-tool/extension.json +7 -0
  241. package/dist/extras/extensions/weather-tool/index.d.ts +3 -0
  242. package/dist/extras/extensions/weather-tool/index.d.ts.map +1 -0
  243. package/dist/extras/extensions/weather-tool/index.js +2 -0
  244. package/dist/extras/extensions/weather-tool/index.js.map +1 -0
  245. package/dist/extras/models/ai-sdk-resolver.d.ts +15 -0
  246. package/dist/extras/models/ai-sdk-resolver.d.ts.map +1 -0
  247. package/dist/extras/models/ai-sdk-resolver.js +57 -0
  248. package/dist/extras/models/ai-sdk-resolver.js.map +1 -0
  249. package/dist/extras/models/index.d.ts +5 -0
  250. package/dist/extras/models/index.d.ts.map +1 -0
  251. package/dist/extras/models/index.js +3 -0
  252. package/dist/extras/models/index.js.map +1 -0
  253. package/dist/extras/models/routing-model.d.ts +18 -0
  254. package/dist/extras/models/routing-model.d.ts.map +1 -0
  255. package/dist/extras/models/routing-model.js +24 -0
  256. package/dist/extras/models/routing-model.js.map +1 -0
  257. package/dist/extras/openai-provider/index.d.ts +3 -0
  258. package/dist/extras/openai-provider/index.d.ts.map +1 -0
  259. package/dist/extras/openai-provider/index.js +2 -0
  260. package/dist/extras/openai-provider/index.js.map +1 -0
  261. package/dist/extras/openai-provider/server.d.ts +34 -0
  262. package/dist/extras/openai-provider/server.d.ts.map +1 -0
  263. package/dist/extras/openai-provider/server.js +335 -0
  264. package/dist/extras/openai-provider/server.js.map +1 -0
  265. package/dist/handle.d.ts +56 -0
  266. package/dist/handle.d.ts.map +1 -0
  267. package/dist/handle.js +2 -0
  268. package/dist/handle.js.map +1 -0
  269. package/dist/hooks.d.ts +98 -0
  270. package/dist/hooks.d.ts.map +1 -0
  271. package/dist/hooks.js +53 -0
  272. package/dist/hooks.js.map +1 -0
  273. package/dist/index.d.ts +16 -0
  274. package/dist/index.d.ts.map +1 -0
  275. package/dist/index.js +9 -0
  276. package/dist/index.js.map +1 -0
  277. package/dist/model.d.ts +75 -0
  278. package/dist/model.d.ts.map +1 -0
  279. package/dist/model.js +2 -0
  280. package/dist/model.js.map +1 -0
  281. package/dist/tool.d.ts +78 -0
  282. package/dist/tool.d.ts.map +1 -0
  283. package/dist/tool.js +78 -0
  284. package/dist/tool.js.map +1 -0
  285. package/dist/types.d.ts +83 -0
  286. package/dist/types.d.ts.map +1 -0
  287. package/dist/types.js +21 -0
  288. package/dist/types.js.map +1 -0
  289. package/package.json +178 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "otel",
3
+ "description": "OpenTelemetry observability — creates spans across the agent turn lifecycle (agent.turn → llm.request → tool.<name>). Uses @opentelemetry/api; host must register a tracer provider.",
4
+ "enabled": true,
5
+ "priority": 200,
6
+ "configKeys": ["tracer", "tracerName", "serviceName", "recordToolArgs", "maxResultLength"]
7
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=extension.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.test.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/otel/extension.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,399 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { SpanStatusCode } from '@opentelemetry/api';
3
+ import { Agent } from '../../../agent.js';
4
+ import { createOtelExtension } from './index.js';
5
+ function createInMemoryTracer() {
6
+ const spans = [];
7
+ let counter = 0;
8
+ function makeSpan(name, parentSpanId) {
9
+ const span = {
10
+ name,
11
+ attributes: {},
12
+ status: { code: SpanStatusCode.UNSET },
13
+ events: [],
14
+ parentSpanId,
15
+ spanId: `span_${counter++}`,
16
+ ended: false,
17
+ startTime: performance.now(),
18
+ endTime: 0,
19
+ };
20
+ spans.push(span);
21
+ const spanApi = {
22
+ spanContext: () => ({
23
+ traceId: 'test-trace',
24
+ spanId: span.spanId,
25
+ traceFlags: 1,
26
+ isRemote: false,
27
+ }),
28
+ setAttribute(key, value) {
29
+ span.attributes[key] = value;
30
+ return spanApi;
31
+ },
32
+ setAttributes(attrs) {
33
+ Object.assign(span.attributes, attrs);
34
+ return spanApi;
35
+ },
36
+ addEvent(name, attributes) {
37
+ span.events.push({ name, attributes });
38
+ return spanApi;
39
+ },
40
+ setStatus(status) {
41
+ span.status = status;
42
+ return spanApi;
43
+ },
44
+ end() {
45
+ span.ended = true;
46
+ span.endTime = performance.now();
47
+ },
48
+ isRecording() {
49
+ return !span.ended;
50
+ },
51
+ recordException(exception) {
52
+ const msg = typeof exception === 'string' ? exception : exception.message;
53
+ span.events.push({ name: 'exception', attributes: { 'exception.message': msg } });
54
+ },
55
+ updateName(name) {
56
+ span.name = name;
57
+ return spanApi;
58
+ },
59
+ addLink: () => spanApi,
60
+ addLinks: () => spanApi,
61
+ };
62
+ // Store the spanId on the Span object so the tracer can find the
63
+ // parent when creating child spans.
64
+ spanApi._spanId = span.spanId;
65
+ return spanApi;
66
+ }
67
+ const tracer = {
68
+ spans,
69
+ startSpan(name, _options, ctx) {
70
+ // Extract parent spanId from context.
71
+ const parentSpan = ctx ? ctx._activeSpan : undefined;
72
+ const parentSpanId = parentSpan?._spanId;
73
+ const span = makeSpan(name, parentSpanId);
74
+ // Store on context for child spans — but since we're using a
75
+ // simplified context, we stash it on the returned span.
76
+ span._activeSpan = span;
77
+ return span;
78
+ },
79
+ startActiveSpan(name, fn) {
80
+ const span = makeSpan(name);
81
+ return fn(span);
82
+ },
83
+ };
84
+ return tracer;
85
+ }
86
+ // ── Mock model ─────────────────────────────────────────────────────
87
+ function mockModel(responses = [{ message: { role: 'assistant', content: 'ok' }, finishReason: 'stop' }]) {
88
+ let callCount = 0;
89
+ return {
90
+ async generate(req) {
91
+ const resp = responses[Math.min(callCount, responses.length - 1)];
92
+ callCount++;
93
+ if (typeof resp === 'function')
94
+ return resp(req);
95
+ return resp;
96
+ },
97
+ };
98
+ }
99
+ // ── Test setup ─────────────────────────────────────────────────────
100
+ let tracer;
101
+ beforeEach(() => {
102
+ tracer = createInMemoryTracer();
103
+ });
104
+ // Helper to find spans by name.
105
+ function findSpans(name) {
106
+ return tracer.spans.filter((s) => s.name === name);
107
+ }
108
+ function findSpan(name) {
109
+ const spans = findSpans(name);
110
+ if (spans.length === 0)
111
+ throw new Error(`No span named "${name}" found`);
112
+ if (spans.length > 1)
113
+ throw new Error(`Multiple spans named "${name}" found`);
114
+ return spans[0];
115
+ }
116
+ // ── Tests ──────────────────────────────────────────────────────────
117
+ describe('otel extension', () => {
118
+ it('creates a root span for each turn', async () => {
119
+ const ext = createOtelExtension({ tracer });
120
+ const agent = new Agent({ model: mockModel() });
121
+ agent.use(ext);
122
+ await agent.run({ message: 'hello' });
123
+ const rootSpan = findSpan('agent.turn');
124
+ expect(rootSpan.ended).toBe(true);
125
+ expect(rootSpan.attributes['libra.turn.finish_reason']).toBe('stop');
126
+ expect(rootSpan.attributes['libra.turn.iterations']).toBe(1);
127
+ });
128
+ it('records turn duration and message length', async () => {
129
+ const ext = createOtelExtension({ tracer });
130
+ const agent = new Agent({ model: mockModel() });
131
+ agent.use(ext);
132
+ await agent.run({ message: 'hello world' });
133
+ const span = findSpan('agent.turn');
134
+ expect(span.attributes['libra.turn.message_length']).toBe(11);
135
+ expect(span.attributes['libra.turn.duration_ms']).toBeDefined();
136
+ expect(typeof span.attributes['libra.turn.duration_ms']).toBe('number');
137
+ });
138
+ it('creates LLM child spans', async () => {
139
+ const ext = createOtelExtension({ tracer });
140
+ const agent = new Agent({ model: mockModel() });
141
+ agent.use(ext);
142
+ await agent.run({ message: 'hi' });
143
+ const llmSpan = findSpan('llm.request');
144
+ expect(llmSpan.ended).toBe(true);
145
+ expect(llmSpan.attributes['libra.llm.message_count']).toBe(1);
146
+ expect(llmSpan.attributes['libra.llm.has_tool_calls']).toBe(false);
147
+ });
148
+ it('records token usage on LLM spans', async () => {
149
+ const model = mockModel([{
150
+ message: { role: 'assistant', content: 'reply' },
151
+ finishReason: 'stop',
152
+ usage: {
153
+ promptTokens: 100,
154
+ completionTokens: 20,
155
+ cachedPromptTokens: 50,
156
+ reasoningTokens: 5,
157
+ },
158
+ }]);
159
+ const ext = createOtelExtension({ tracer });
160
+ const agent = new Agent({ model: model });
161
+ agent.use(ext);
162
+ await agent.run({ message: 'hi' });
163
+ const llmSpan = findSpan('llm.request');
164
+ expect(llmSpan.attributes['libra.llm.prompt_tokens']).toBe(100);
165
+ expect(llmSpan.attributes['libra.llm.completion_tokens']).toBe(20);
166
+ expect(llmSpan.attributes['libra.llm.cached_prompt_tokens']).toBe(50);
167
+ expect(llmSpan.attributes['libra.llm.reasoning_tokens']).toBe(5);
168
+ });
169
+ it('creates tool child spans for tool calls', async () => {
170
+ const tool = {
171
+ name: 'echo',
172
+ description: 'Echo tool',
173
+ parameters: { type: 'object', properties: {} },
174
+ async execute() {
175
+ return { toolCallId: '', content: 'echoed' };
176
+ },
177
+ };
178
+ const model = mockModel([
179
+ {
180
+ message: {
181
+ role: 'assistant',
182
+ content: '',
183
+ toolCalls: [{ id: 'tc1', name: 'echo', arguments: '{}' }],
184
+ },
185
+ finishReason: 'tool_calls',
186
+ },
187
+ { message: { role: 'assistant', content: 'done' }, finishReason: 'stop' },
188
+ ]);
189
+ const ext = createOtelExtension({ tracer });
190
+ const agent = new Agent({ model: model, tools: [tool] });
191
+ agent.use(ext);
192
+ await agent.run({ message: 'call echo' });
193
+ const toolSpan = findSpan('tool.echo');
194
+ expect(toolSpan.ended).toBe(true);
195
+ expect(toolSpan.attributes['libra.tool.name']).toBe('echo');
196
+ expect(toolSpan.attributes['libra.tool.is_error']).toBe(false);
197
+ });
198
+ it('marks error tool calls with ERROR status', async () => {
199
+ const tool = {
200
+ name: 'fail',
201
+ description: 'Always fails',
202
+ parameters: { type: 'object', properties: {} },
203
+ async execute() {
204
+ return { toolCallId: '', content: 'Something went wrong', isError: true };
205
+ },
206
+ };
207
+ const model = mockModel([
208
+ {
209
+ message: {
210
+ role: 'assistant',
211
+ content: '',
212
+ toolCalls: [{ id: 'tc1', name: 'fail', arguments: '{}' }],
213
+ },
214
+ finishReason: 'tool_calls',
215
+ },
216
+ { message: { role: 'assistant', content: 'sorry' }, finishReason: 'stop' },
217
+ ]);
218
+ const ext = createOtelExtension({ tracer });
219
+ const agent = new Agent({ model: model, tools: [tool] });
220
+ agent.use(ext);
221
+ await agent.run({ message: 'call fail' });
222
+ const toolSpan = findSpan('tool.fail');
223
+ expect(toolSpan.attributes['libra.tool.is_error']).toBe(true);
224
+ expect(toolSpan.status.code).toBe(SpanStatusCode.ERROR);
225
+ });
226
+ it('records tool result as a span event', async () => {
227
+ const tool = {
228
+ name: 'echo',
229
+ description: 'Echo',
230
+ parameters: { type: 'object', properties: {} },
231
+ async execute() {
232
+ return { toolCallId: '', content: 'hello result' };
233
+ },
234
+ };
235
+ const model = mockModel([
236
+ {
237
+ message: {
238
+ role: 'assistant',
239
+ content: '',
240
+ toolCalls: [{ id: 'tc1', name: 'echo', arguments: '{}' }],
241
+ },
242
+ finishReason: 'tool_calls',
243
+ },
244
+ { message: { role: 'assistant', content: 'done' }, finishReason: 'stop' },
245
+ ]);
246
+ const ext = createOtelExtension({ tracer, maxResultLength: 100 });
247
+ const agent = new Agent({ model: model, tools: [tool] });
248
+ agent.use(ext);
249
+ await agent.run({ message: 'call echo' });
250
+ const toolSpan = findSpan('tool.echo');
251
+ const resultEvent = toolSpan.events.find((e) => e.name === 'tool.result');
252
+ expect(resultEvent).toBeDefined();
253
+ expect(resultEvent.attributes?.['libra.tool.result']).toBe('hello result');
254
+ });
255
+ it('records exceptions on error', async () => {
256
+ const model = {
257
+ async generate() {
258
+ throw new Error('model exploded');
259
+ },
260
+ };
261
+ const ext = createOtelExtension({ tracer });
262
+ const agent = new Agent({ model: model, errorPolicy: 'fallback' });
263
+ agent.use(ext);
264
+ await agent.run({ message: 'hi' });
265
+ const rootSpan = findSpan('agent.turn');
266
+ const exceptionEvent = rootSpan.events.find((e) => e.name === 'exception');
267
+ expect(exceptionEvent).toBeDefined();
268
+ expect(exceptionEvent.attributes?.['exception.message']).toBe('model exploded');
269
+ expect(rootSpan.status.code).toBe(SpanStatusCode.ERROR);
270
+ });
271
+ it('sets serviceName attribute when configured', async () => {
272
+ const ext = createOtelExtension({ tracer, serviceName: 'slack-bot' });
273
+ const agent = new Agent({ model: mockModel() });
274
+ agent.use(ext);
275
+ await agent.run({ message: 'hi' });
276
+ const rootSpan = findSpan('agent.turn');
277
+ expect(rootSpan.attributes['libra.service']).toBe('slack-bot');
278
+ });
279
+ it('records tool args when recordToolArgs is enabled', async () => {
280
+ const tool = {
281
+ name: 'echo',
282
+ description: 'Echo',
283
+ parameters: { type: 'object', properties: { text: { type: 'string' } } },
284
+ async execute(args) {
285
+ return { toolCallId: '', content: args.text };
286
+ },
287
+ };
288
+ const model = mockModel([
289
+ {
290
+ message: {
291
+ role: 'assistant',
292
+ content: '',
293
+ toolCalls: [{ id: 'tc1', name: 'echo', arguments: '{"text":"hello"}' }],
294
+ },
295
+ finishReason: 'tool_calls',
296
+ },
297
+ { message: { role: 'assistant', content: 'done' }, finishReason: 'stop' },
298
+ ]);
299
+ const ext = createOtelExtension({ tracer, recordToolArgs: true });
300
+ const agent = new Agent({ model: model, tools: [tool] });
301
+ agent.use(ext);
302
+ await agent.run({ message: 'call echo' });
303
+ const toolSpan = findSpan('tool.echo');
304
+ expect(toolSpan.attributes['libra.tool.args']).toBe('{"text":"hello"}');
305
+ });
306
+ it('creates multiple LLM spans for multi-iteration turns', async () => {
307
+ const tool = {
308
+ name: 'echo',
309
+ description: 'Echo',
310
+ parameters: { type: 'object', properties: {} },
311
+ async execute() {
312
+ return { toolCallId: '', content: 'echoed' };
313
+ },
314
+ };
315
+ const model = mockModel([
316
+ {
317
+ message: {
318
+ role: 'assistant',
319
+ content: '',
320
+ toolCalls: [{ id: 'tc1', name: 'echo', arguments: '{}' }],
321
+ },
322
+ finishReason: 'tool_calls',
323
+ },
324
+ { message: { role: 'assistant', content: 'final' }, finishReason: 'stop' },
325
+ ]);
326
+ const ext = createOtelExtension({ tracer });
327
+ const agent = new Agent({ model: model, tools: [tool] });
328
+ agent.use(ext);
329
+ await agent.run({ message: 'call echo then respond' });
330
+ const llmSpans = findSpans('llm.request');
331
+ expect(llmSpans).toHaveLength(2);
332
+ const rootSpan = findSpan('agent.turn');
333
+ expect(rootSpan.attributes['libra.turn.iterations']).toBe(2);
334
+ expect(rootSpan.attributes['libra.turn.tool_calls']).toBe(1);
335
+ });
336
+ it('is a no-op when no tracer provider is registered', async () => {
337
+ // Don't pass a tracer — use the global (which has no provider registered).
338
+ // Should not throw.
339
+ const ext = createOtelExtension();
340
+ const agent = new Agent({ model: mockModel() });
341
+ agent.use(ext);
342
+ const result = await agent.run({ message: 'hi' });
343
+ expect(result.finishReason).toBe('stop');
344
+ });
345
+ it('uses high priority so spans start before other extensions', () => {
346
+ const ext = createOtelExtension({ tracer });
347
+ expect(ext.priority).toBe(200);
348
+ });
349
+ it('records sessionId from metadata by default', async () => {
350
+ const ext = createOtelExtension({ tracer });
351
+ const agent = new Agent({ model: mockModel() });
352
+ agent.use(ext);
353
+ await agent.run({ message: 'hi', metadata: { sessionId: 'slack_C123' } });
354
+ const rootSpan = findSpan('agent.turn');
355
+ expect(rootSpan.attributes['libra.turn.sessionId']).toBe('slack_C123');
356
+ });
357
+ it('records nested metadata keys via dot notation', async () => {
358
+ const ext = createOtelExtension({
359
+ tracer,
360
+ metadataKeys: ['sessionId', 'slack.channelId', 'slack.userId'],
361
+ });
362
+ const agent = new Agent({ model: mockModel() });
363
+ agent.use(ext);
364
+ await agent.run({
365
+ message: 'hi',
366
+ metadata: {
367
+ sessionId: 'slack_C123',
368
+ slack: {
369
+ channelId: 'C12345678',
370
+ userId: 'U87654321',
371
+ },
372
+ },
373
+ });
374
+ const rootSpan = findSpan('agent.turn');
375
+ expect(rootSpan.attributes['libra.turn.sessionId']).toBe('slack_C123');
376
+ expect(rootSpan.attributes['libra.turn.slack.channelId']).toBe('C12345678');
377
+ expect(rootSpan.attributes['libra.turn.slack.userId']).toBe('U87654321');
378
+ });
379
+ it('skips metadata keys that are objects or missing', async () => {
380
+ const ext = createOtelExtension({
381
+ tracer,
382
+ metadataKeys: ['sessionId', 'slack', 'missing.key'],
383
+ });
384
+ const agent = new Agent({ model: mockModel() });
385
+ agent.use(ext);
386
+ await agent.run({
387
+ message: 'hi',
388
+ metadata: {
389
+ sessionId: 's1',
390
+ slack: { channelId: 'C1' }, // object — should be skipped
391
+ },
392
+ });
393
+ const rootSpan = findSpan('agent.turn');
394
+ expect(rootSpan.attributes['libra.turn.sessionId']).toBe('s1');
395
+ expect(rootSpan.attributes['libra.turn.slack']).toBeUndefined();
396
+ expect(rootSpan.attributes['libra.turn.missing.key']).toBeUndefined();
397
+ });
398
+ });
399
+ //# sourceMappingURL=extension.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.test.js","sourceRoot":"","sources":["../../../../src/extras/extensions/otel/extension.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { default as createOtelExtension } from './extension.js';
2
+ export type { OtelExtensionConfig } from './extension.js';
3
+ export { JsonlSpanExporter } from './jsonl-span-exporter.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/otel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAChE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { default as createOtelExtension } from './extension.js';
2
+ export { JsonlSpanExporter } from './jsonl-span-exporter.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/extras/extensions/otel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,60 @@
1
+ import type { SpanExporter, ReadableSpan } from '@opentelemetry/sdk-trace-base';
2
+ /**
3
+ * A JSONL span exporter for OpenTelemetry.
4
+ *
5
+ * Appends each ended span as one JSON line to a `.jsonl` file — same
6
+ * append-only pattern as disk-session. Each line is a self-contained
7
+ * record with the span name, attributes, timing, status, and events.
8
+ *
9
+ * The file is structured so it can be read line-by-line for analytics
10
+ * (no need to parse the whole file into memory).
11
+ *
12
+ * ## Record format
13
+ *
14
+ * ```json
15
+ * {
16
+ * "traceId": "abc123...",
17
+ * "spanId": "span_0",
18
+ * "parentSpanId": "span_1",
19
+ * "name": "agent.turn",
20
+ * "kind": 0,
21
+ * "startTime": 1234567890.123,
22
+ * "endTime": 1234567890.456,
23
+ * "durationMs": 333,
24
+ * "attributes": { "libra.turn.finish_reason": "stop", ... },
25
+ * "status": { "code": 1 },
26
+ * "events": [{ "name": "tool.result", "attributes": {...}, "time": ... }],
27
+ * "resource": { "service.name": "my-agent" },
28
+ * "scope": "libra"
29
+ * }
30
+ * ```
31
+ *
32
+ * ## Usage
33
+ *
34
+ * ```typescript
35
+ * import { JsonlSpanExporter } from '@xandout/libra-harness/extras/otel';
36
+ * import { NodeSDK } from '@opentelemetry/sdk-node';
37
+ *
38
+ * const sdk = new NodeSDK({
39
+ * serviceName: 'my-agent',
40
+ * traceExporter: new JsonlSpanExporter('./traces/traces.jsonl'),
41
+ * });
42
+ * sdk.start();
43
+ * ```
44
+ *
45
+ * No external infrastructure required — just a file path. Good for
46
+ * local development and single-process deployments. For multi-process
47
+ * or dashboard scenarios, use the OTLP exporter instead.
48
+ */
49
+ export declare class JsonlSpanExporter implements SpanExporter {
50
+ private readonly filePath;
51
+ private isShutdown;
52
+ constructor(filePath: string);
53
+ export(spans: ReadableSpan[], resultCallback: (result: {
54
+ code: number;
55
+ }) => void): void;
56
+ shutdown(): Promise<void>;
57
+ forceFlush(): Promise<void>;
58
+ private serialize;
59
+ }
60
+ //# sourceMappingURL=jsonl-span-exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-span-exporter.d.ts","sourceRoot":"","sources":["../../../../src/extras/extensions/otel/jsonl-span-exporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,UAAU,CAAS;IAE3B,YAAY,QAAQ,EAAE,MAAM,EAM3B;IAED,MAAM,CACJ,KAAK,EAAE,YAAY,EAAE,EACrB,cAAc,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GACjD,IAAI,CAcN;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9B;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhC;IAED,OAAO,CAAC,SAAS;CAuDlB"}
@@ -0,0 +1,134 @@
1
+ import { appendFileSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ /**
4
+ * A JSONL span exporter for OpenTelemetry.
5
+ *
6
+ * Appends each ended span as one JSON line to a `.jsonl` file — same
7
+ * append-only pattern as disk-session. Each line is a self-contained
8
+ * record with the span name, attributes, timing, status, and events.
9
+ *
10
+ * The file is structured so it can be read line-by-line for analytics
11
+ * (no need to parse the whole file into memory).
12
+ *
13
+ * ## Record format
14
+ *
15
+ * ```json
16
+ * {
17
+ * "traceId": "abc123...",
18
+ * "spanId": "span_0",
19
+ * "parentSpanId": "span_1",
20
+ * "name": "agent.turn",
21
+ * "kind": 0,
22
+ * "startTime": 1234567890.123,
23
+ * "endTime": 1234567890.456,
24
+ * "durationMs": 333,
25
+ * "attributes": { "libra.turn.finish_reason": "stop", ... },
26
+ * "status": { "code": 1 },
27
+ * "events": [{ "name": "tool.result", "attributes": {...}, "time": ... }],
28
+ * "resource": { "service.name": "my-agent" },
29
+ * "scope": "libra"
30
+ * }
31
+ * ```
32
+ *
33
+ * ## Usage
34
+ *
35
+ * ```typescript
36
+ * import { JsonlSpanExporter } from '@xandout/libra-harness/extras/otel';
37
+ * import { NodeSDK } from '@opentelemetry/sdk-node';
38
+ *
39
+ * const sdk = new NodeSDK({
40
+ * serviceName: 'my-agent',
41
+ * traceExporter: new JsonlSpanExporter('./traces/traces.jsonl'),
42
+ * });
43
+ * sdk.start();
44
+ * ```
45
+ *
46
+ * No external infrastructure required — just a file path. Good for
47
+ * local development and single-process deployments. For multi-process
48
+ * or dashboard scenarios, use the OTLP exporter instead.
49
+ */
50
+ export class JsonlSpanExporter {
51
+ filePath;
52
+ isShutdown = false;
53
+ constructor(filePath) {
54
+ this.filePath = filePath;
55
+ const dir = dirname(filePath);
56
+ if (!existsSync(dir)) {
57
+ mkdirSync(dir, { recursive: true });
58
+ }
59
+ }
60
+ export(spans, resultCallback) {
61
+ if (this.isShutdown) {
62
+ resultCallback({ code: 1 }); // FAILURE
63
+ return;
64
+ }
65
+ try {
66
+ const lines = spans.map((span) => JSON.stringify(this.serialize(span))).join('\n') + '\n';
67
+ appendFileSync(this.filePath, lines);
68
+ resultCallback({ code: 0 }); // SUCCESS
69
+ }
70
+ catch (err) {
71
+ console.error('[otel/jsonl] export failed:', err);
72
+ resultCallback({ code: 1 }); // FAILURE
73
+ }
74
+ }
75
+ async shutdown() {
76
+ this.isShutdown = true;
77
+ }
78
+ async forceFlush() {
79
+ // Writes are synchronous — nothing to flush.
80
+ }
81
+ serialize(span) {
82
+ const ctx = span.spanContext();
83
+ const parent = span.parentSpanContext;
84
+ // Convert HrTime [seconds, nanos] to ms.
85
+ const durationMs = span.duration
86
+ ? Math.round(span.duration[0] * 1000 + span.duration[1] / 1_000_000)
87
+ : 0;
88
+ // Convert start/end HrTime to epoch seconds (float).
89
+ const startTime = span.startTime
90
+ ? span.startTime[0] + span.startTime[1] / 1_000_000_000
91
+ : 0;
92
+ const endTime = span.endTime
93
+ ? span.endTime[0] + span.endTime[1] / 1_000_000_000
94
+ : 0;
95
+ // Serialize events (TimedEvent[]).
96
+ const events = span.events?.map((e) => ({
97
+ name: e.name,
98
+ attributes: e.attributes ?? {},
99
+ time: e.time ? e.time[0] + e.time[1] / 1_000_000_000 : 0,
100
+ })) ?? [];
101
+ // Serialize resource attributes.
102
+ const resource = {};
103
+ try {
104
+ const attrs = span.resource.attributes;
105
+ if (attrs && typeof attrs.forEach === 'function') {
106
+ attrs.forEach((value, key) => {
107
+ resource[key] = value;
108
+ });
109
+ }
110
+ else if (attrs) {
111
+ Object.assign(resource, attrs);
112
+ }
113
+ }
114
+ catch {
115
+ // Resource may not have attributes — skip.
116
+ }
117
+ return {
118
+ traceId: ctx.traceId,
119
+ spanId: ctx.spanId,
120
+ parentSpanId: parent?.spanId,
121
+ name: span.name,
122
+ kind: span.kind,
123
+ startTime,
124
+ endTime,
125
+ durationMs,
126
+ attributes: span.attributes ?? {},
127
+ status: span.status,
128
+ events,
129
+ resource,
130
+ scope: span.instrumentationScope?.name ?? '',
131
+ };
132
+ }
133
+ }
134
+ //# sourceMappingURL=jsonl-span-exporter.js.map