@prefactor/core 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +35 -2
  2. package/dist/agent/instance-manager.d.ts +16 -0
  3. package/dist/agent/instance-manager.d.ts.map +1 -0
  4. package/dist/agent/instance-manager.js +50 -0
  5. package/dist/agent/instance-manager.js.map +1 -0
  6. package/dist/config.d.ts +28 -52
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +33 -18
  9. package/dist/config.js.map +1 -1
  10. package/dist/create-core.d.ts +10 -0
  11. package/dist/create-core.d.ts.map +1 -0
  12. package/dist/create-core.js +31 -0
  13. package/dist/create-core.js.map +1 -0
  14. package/dist/index.cjs +632 -256
  15. package/dist/index.cjs.map +18 -11
  16. package/dist/index.d.ts +3 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +633 -257
  19. package/dist/index.js.map +18 -11
  20. package/dist/queue/actions.d.ts +24 -0
  21. package/dist/queue/actions.d.ts.map +1 -0
  22. package/dist/queue/actions.js +2 -0
  23. package/dist/queue/actions.js.map +1 -0
  24. package/dist/queue/base.d.ts +19 -0
  25. package/dist/queue/base.d.ts.map +1 -0
  26. package/dist/{transport → queue}/base.js.map +1 -1
  27. package/dist/queue/in-memory-queue.d.ts +11 -0
  28. package/dist/queue/in-memory-queue.d.ts.map +1 -0
  29. package/dist/queue/in-memory-queue.js +46 -0
  30. package/dist/queue/in-memory-queue.js.map +1 -0
  31. package/dist/queue/task-executor.d.ts +18 -0
  32. package/dist/queue/task-executor.d.ts.map +1 -0
  33. package/dist/queue/task-executor.js +77 -0
  34. package/dist/queue/task-executor.js.map +1 -0
  35. package/dist/tracing/context.d.ts +12 -0
  36. package/dist/tracing/context.d.ts.map +1 -1
  37. package/dist/tracing/context.js +41 -5
  38. package/dist/tracing/context.js.map +1 -1
  39. package/dist/tracing/span.d.ts +7 -9
  40. package/dist/tracing/span.d.ts.map +1 -1
  41. package/dist/tracing/span.js +6 -8
  42. package/dist/tracing/span.js.map +1 -1
  43. package/dist/tracing/tracer.d.ts +5 -16
  44. package/dist/tracing/tracer.d.ts.map +1 -1
  45. package/dist/tracing/tracer.js +22 -26
  46. package/dist/tracing/tracer.js.map +1 -1
  47. package/dist/transport/http/agent-instance-client.d.ts +23 -0
  48. package/dist/transport/http/agent-instance-client.d.ts.map +1 -0
  49. package/dist/transport/http/agent-instance-client.js +25 -0
  50. package/dist/transport/http/agent-instance-client.js.map +1 -0
  51. package/dist/transport/http/agent-span-client.d.ts +25 -0
  52. package/dist/transport/http/agent-span-client.d.ts.map +1 -0
  53. package/dist/transport/http/agent-span-client.js +37 -0
  54. package/dist/transport/http/agent-span-client.js.map +1 -0
  55. package/dist/transport/http/http-client.d.ts +43 -0
  56. package/dist/transport/http/http-client.d.ts.map +1 -0
  57. package/dist/transport/http/http-client.js +127 -0
  58. package/dist/transport/http/http-client.js.map +1 -0
  59. package/dist/transport/http/retry-policy.d.ts +4 -0
  60. package/dist/transport/http/retry-policy.d.ts.map +1 -0
  61. package/dist/transport/http/retry-policy.js +10 -0
  62. package/dist/transport/http/retry-policy.js.map +1 -0
  63. package/dist/transport/http.d.ts +30 -72
  64. package/dist/transport/http.d.ts.map +1 -1
  65. package/dist/transport/http.js +146 -269
  66. package/dist/transport/http.js.map +1 -1
  67. package/dist/utils/logging.d.ts.map +1 -1
  68. package/dist/utils/logging.js +7 -1
  69. package/dist/utils/logging.js.map +1 -1
  70. package/package.json +1 -1
  71. package/dist/transport/base.d.ts +0 -38
  72. package/dist/transport/base.d.ts.map +0 -1
  73. package/dist/transport/stdio.d.ts +0 -48
  74. package/dist/transport/stdio.d.ts.map +0 -1
  75. package/dist/transport/stdio.js +0 -71
  76. package/dist/transport/stdio.js.map +0 -1
  77. /package/dist/{transport → queue}/base.js +0 -0
package/dist/index.cjs CHANGED
@@ -32,58 +32,110 @@ __export(exports_src, {
32
32
  truncateString: () => truncateString,
33
33
  serializeValue: () => serializeValue,
34
34
  getLogger: () => getLogger,
35
+ createCore: () => createCore,
35
36
  createConfig: () => createConfig,
36
37
  configureLogging: () => configureLogging,
37
38
  Tracer: () => Tracer,
38
- StdioTransport: () => StdioTransport,
39
39
  SpanType: () => SpanType,
40
40
  SpanStatus: () => SpanStatus,
41
41
  SpanContext: () => SpanContext,
42
42
  PartialHttpConfigSchema: () => PartialHttpConfigSchema,
43
43
  HttpTransportConfigSchema: () => HttpTransportConfigSchema,
44
44
  HttpTransport: () => HttpTransport,
45
- ConfigSchema: () => ConfigSchema
45
+ ConfigSchema: () => ConfigSchema,
46
+ AgentInstanceManager: () => AgentInstanceManager
46
47
  });
47
48
  module.exports = __toCommonJS(exports_src);
48
49
 
50
+ // packages/core/src/agent/instance-manager.ts
51
+ class AgentInstanceManager {
52
+ transport;
53
+ options;
54
+ registeredSchema = null;
55
+ constructor(transport, options) {
56
+ this.transport = transport;
57
+ this.options = options;
58
+ }
59
+ registerSchema(schema) {
60
+ if (this.registeredSchema === null) {
61
+ this.registeredSchema = schema;
62
+ this.transport.registerSchema(schema);
63
+ return;
64
+ }
65
+ const existingSchema = stableStringify(this.registeredSchema);
66
+ const incomingSchema = stableStringify(schema);
67
+ if (existingSchema !== incomingSchema) {
68
+ console.warn("A different schema was provided after registration; ignoring subsequent schema.");
69
+ }
70
+ }
71
+ startInstance(options = {}) {
72
+ if (!this.options.allowUnregisteredSchema && this.registeredSchema === null) {
73
+ console.warn("Schema must be registered before starting an agent instance.");
74
+ return;
75
+ }
76
+ this.transport.startAgentInstance(options);
77
+ }
78
+ finishInstance() {
79
+ this.transport.finishAgentInstance();
80
+ }
81
+ }
82
+ function stableStringify(value) {
83
+ return JSON.stringify(normalizeValue(value));
84
+ }
85
+ function normalizeValue(value) {
86
+ if (Array.isArray(value)) {
87
+ return value.map((entry) => normalizeValue(entry));
88
+ }
89
+ if (value && typeof value === "object") {
90
+ const normalized = {};
91
+ const objectValue = value;
92
+ const keys = Object.keys(objectValue).sort((a, b) => a.localeCompare(b));
93
+ for (const key of keys) {
94
+ normalized[key] = normalizeValue(objectValue[key]);
95
+ }
96
+ return normalized;
97
+ }
98
+ return value;
99
+ }
49
100
  // packages/core/src/config.ts
50
101
  var import_zod = require("zod");
102
+ var DEFAULT_RETRY_ON_STATUS_CODES = [
103
+ 429,
104
+ ...Array.from({ length: 100 }, (_, index) => 500 + index)
105
+ ];
106
+ var HttpStatusCodeSchema = import_zod.z.number().int().min(100).max(599);
51
107
  var HttpTransportConfigSchema = import_zod.z.object({
52
108
  apiUrl: import_zod.z.string().url(),
53
109
  apiToken: import_zod.z.string().min(1),
54
110
  agentId: import_zod.z.string().optional(),
55
- agentVersion: import_zod.z.string().optional(),
111
+ agentIdentifier: import_zod.z.string().default("v1.0.0"),
56
112
  agentName: import_zod.z.string().optional(),
57
113
  agentDescription: import_zod.z.string().optional(),
58
114
  agentSchema: import_zod.z.record(import_zod.z.unknown()).optional(),
59
- agentSchemaVersion: import_zod.z.string().optional(),
60
- skipSchema: import_zod.z.boolean().default(false),
61
115
  requestTimeout: import_zod.z.number().positive().default(30000),
62
- connectTimeout: import_zod.z.number().positive().default(1e4),
63
116
  maxRetries: import_zod.z.number().int().nonnegative().default(3),
64
117
  initialRetryDelay: import_zod.z.number().positive().default(1000),
65
118
  maxRetryDelay: import_zod.z.number().positive().default(60000),
66
- retryMultiplier: import_zod.z.number().positive().default(2)
119
+ retryMultiplier: import_zod.z.number().positive().default(2),
120
+ retryOnStatusCodes: import_zod.z.array(HttpStatusCodeSchema).default([...DEFAULT_RETRY_ON_STATUS_CODES])
67
121
  });
68
122
  var PartialHttpConfigSchema = import_zod.z.object({
69
123
  apiUrl: import_zod.z.string().url(),
70
124
  apiToken: import_zod.z.string().min(1),
71
125
  agentId: import_zod.z.string().optional(),
72
- agentVersion: import_zod.z.string().optional(),
126
+ agentIdentifier: import_zod.z.string().optional(),
73
127
  agentName: import_zod.z.string().optional(),
74
128
  agentDescription: import_zod.z.string().optional(),
75
129
  agentSchema: import_zod.z.record(import_zod.z.unknown()).optional(),
76
- agentSchemaVersion: import_zod.z.string().optional(),
77
- skipSchema: import_zod.z.boolean().optional(),
78
130
  requestTimeout: import_zod.z.number().positive().optional(),
79
- connectTimeout: import_zod.z.number().positive().optional(),
80
131
  maxRetries: import_zod.z.number().int().nonnegative().optional(),
81
132
  initialRetryDelay: import_zod.z.number().positive().optional(),
82
133
  maxRetryDelay: import_zod.z.number().positive().optional(),
83
- retryMultiplier: import_zod.z.number().positive().optional()
134
+ retryMultiplier: import_zod.z.number().positive().optional(),
135
+ retryOnStatusCodes: import_zod.z.array(HttpStatusCodeSchema).optional()
84
136
  });
85
137
  var ConfigSchema = import_zod.z.object({
86
- transportType: import_zod.z.enum(["stdio", "http"]).default("stdio"),
138
+ transportType: import_zod.z.enum(["http"]).default("http"),
87
139
  sampleRate: import_zod.z.number().min(0).max(1).default(1),
88
140
  captureInputs: import_zod.z.boolean().default(true),
89
141
  captureOutputs: import_zod.z.boolean().default(true),
@@ -92,52 +144,93 @@ var ConfigSchema = import_zod.z.object({
92
144
  httpConfig: PartialHttpConfigSchema.optional()
93
145
  });
94
146
  function createConfig(options) {
147
+ const retryOnStatusCodesFromEnv = parseRetryOnStatusCodesEnv(process.env.PREFACTOR_RETRY_ON_STATUS_CODES);
95
148
  const config = {
96
- transportType: options?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? "stdio",
149
+ transportType: options?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? "http",
97
150
  sampleRate: options?.sampleRate ?? parseFloat(process.env.PREFACTOR_SAMPLE_RATE ?? "1.0"),
98
151
  captureInputs: options?.captureInputs ?? process.env.PREFACTOR_CAPTURE_INPUTS !== "false",
99
152
  captureOutputs: options?.captureOutputs ?? process.env.PREFACTOR_CAPTURE_OUTPUTS !== "false",
100
153
  maxInputLength: options?.maxInputLength ?? parseInt(process.env.PREFACTOR_MAX_INPUT_LENGTH ?? "10000", 10),
101
154
  maxOutputLength: options?.maxOutputLength ?? parseInt(process.env.PREFACTOR_MAX_OUTPUT_LENGTH ?? "10000", 10),
102
- httpConfig: options?.httpConfig
155
+ httpConfig: options?.httpConfig ? {
156
+ ...options.httpConfig,
157
+ retryOnStatusCodes: options.httpConfig.retryOnStatusCodes ?? retryOnStatusCodesFromEnv
158
+ } : undefined
103
159
  };
104
160
  return ConfigSchema.parse(config);
105
161
  }
162
+ function parseRetryOnStatusCodesEnv(value) {
163
+ if (!value) {
164
+ return;
165
+ }
166
+ const parsedCodes = value.split(",").map((status) => status.trim()).filter((status) => /^\d{3}$/.test(status)).map((status) => Number(status)).filter((status) => status >= 100 && status <= 599);
167
+ return parsedCodes.length > 0 ? parsedCodes : undefined;
168
+ }
169
+ // packages/core/src/create-core.ts
170
+ var import_pfid2 = require("@prefactor/pfid");
171
+
172
+ // packages/core/src/tracing/tracer.ts
173
+ var import_pfid = require("@prefactor/pfid");
174
+
106
175
  // packages/core/src/tracing/context.ts
107
176
  var import_node_async_hooks = require("node:async_hooks");
108
177
  var spanStorage = new import_node_async_hooks.AsyncLocalStorage;
109
178
 
110
179
  class SpanContext {
111
180
  static getCurrent() {
112
- return spanStorage.getStore();
181
+ const stack = spanStorage.getStore() ?? [];
182
+ return stack[stack.length - 1];
183
+ }
184
+ static getStack() {
185
+ return [...spanStorage.getStore() ?? []];
186
+ }
187
+ static enter(span) {
188
+ const stack = [...spanStorage.getStore() ?? [], span];
189
+ spanStorage.enterWith(stack);
190
+ }
191
+ static exit() {
192
+ const stack = [...spanStorage.getStore() ?? []];
193
+ stack.pop();
194
+ spanStorage.enterWith(stack);
113
195
  }
114
196
  static run(span, fn) {
115
- return spanStorage.run(span, fn);
197
+ const stack = spanStorage.getStore() ?? [];
198
+ const resource = new import_node_async_hooks.AsyncResource("SpanContext.run");
199
+ try {
200
+ return resource.runInAsyncScope(() => spanStorage.run([...stack, span], fn));
201
+ } finally {
202
+ resource.emitDestroy();
203
+ }
116
204
  }
117
205
  static async runAsync(span, fn) {
118
- return spanStorage.run(span, fn);
206
+ const stack = spanStorage.getStore() ?? [];
207
+ const resource = new import_node_async_hooks.AsyncResource("SpanContext.runAsync");
208
+ try {
209
+ return await resource.runInAsyncScope(() => spanStorage.run([...stack, span], fn));
210
+ } finally {
211
+ resource.emitDestroy();
212
+ }
119
213
  }
120
214
  static clear() {
121
215
  spanStorage.disable();
122
216
  }
123
217
  }
218
+
124
219
  // packages/core/src/tracing/span.ts
125
- var SpanType;
126
- ((SpanType2) => {
127
- SpanType2["AGENT"] = "agent";
128
- SpanType2["LLM"] = "llm";
129
- SpanType2["TOOL"] = "tool";
130
- SpanType2["CHAIN"] = "chain";
131
- SpanType2["RETRIEVER"] = "retriever";
132
- })(SpanType ||= {});
220
+ var SpanType = {
221
+ AGENT: "agent",
222
+ LLM: "llm",
223
+ TOOL: "tool",
224
+ CHAIN: "chain"
225
+ };
133
226
  var SpanStatus;
134
227
  ((SpanStatus2) => {
135
228
  SpanStatus2["RUNNING"] = "running";
136
229
  SpanStatus2["SUCCESS"] = "success";
137
230
  SpanStatus2["ERROR"] = "error";
138
231
  })(SpanStatus ||= {});
232
+
139
233
  // packages/core/src/tracing/tracer.ts
140
- var import_pfid = require("@prefactor/pfid");
141
234
  class Tracer {
142
235
  transport;
143
236
  partition;
@@ -146,11 +239,12 @@ class Tracer {
146
239
  this.partition = partition ?? import_pfid.generatePartition();
147
240
  }
148
241
  startSpan(options) {
242
+ const parentSpan = SpanContext.getCurrent();
149
243
  const spanId = import_pfid.generate(this.partition);
150
- const traceId = options.traceId ?? import_pfid.generate(this.partition);
244
+ const traceId = parentSpan?.traceId ?? import_pfid.generate(this.partition);
151
245
  const span = {
152
246
  spanId,
153
- parentSpanId: options.parentSpanId ?? null,
247
+ parentSpanId: parentSpan?.spanId ?? null,
154
248
  traceId,
155
249
  name: options.name,
156
250
  spanType: options.spanType,
@@ -161,10 +255,9 @@ class Tracer {
161
255
  outputs: null,
162
256
  tokenUsage: null,
163
257
  error: null,
164
- metadata: options.metadata ?? {},
165
- tags: options.tags ?? []
258
+ metadata: options.metadata ?? {}
166
259
  };
167
- if (options.spanType === "agent") {
260
+ if (options.spanType === SpanType.AGENT) {
168
261
  try {
169
262
  this.transport.emit(span);
170
263
  } catch (error) {
@@ -174,7 +267,8 @@ class Tracer {
174
267
  return span;
175
268
  }
176
269
  endSpan(span, options) {
177
- span.endTime = Date.now();
270
+ const endTime = Date.now();
271
+ span.endTime = endTime;
178
272
  span.outputs = options?.outputs ?? null;
179
273
  span.tokenUsage = options?.tokenUsage ?? null;
180
274
  if (options?.error) {
@@ -188,13 +282,20 @@ class Tracer {
188
282
  span.status = "success" /* SUCCESS */;
189
283
  }
190
284
  try {
191
- if (span.spanType === "agent") {
192
- this.transport.finishSpan(span.spanId, span.endTime);
285
+ if (span.spanType === SpanType.AGENT) {
286
+ this.transport.finishSpan(span.spanId, endTime);
193
287
  } else {
194
288
  this.transport.emit(span);
195
289
  }
196
290
  } catch (error) {
197
- console.error("Failed to emit/finish span:", error);
291
+ console.error("Failed to emit span action:", error);
292
+ }
293
+ }
294
+ async close() {
295
+ try {
296
+ await this.transport.close();
297
+ } catch (error) {
298
+ console.error("Failed to close transport:", error);
198
299
  }
199
300
  }
200
301
  startAgentInstance() {
@@ -211,18 +312,150 @@ class Tracer {
211
312
  console.error("Failed to finish agent instance:", error);
212
313
  }
213
314
  }
214
- async close() {
315
+ }
316
+
317
+ // packages/core/src/queue/in-memory-queue.ts
318
+ class InMemoryQueue {
319
+ items = [];
320
+ waiters = [];
321
+ isClosed = false;
322
+ async put(item) {
323
+ if (this.isClosed) {
324
+ throw new Error("Cannot put item into a closed queue");
325
+ }
326
+ const waiter = this.waiters.shift();
327
+ if (waiter) {
328
+ waiter({ done: false, item });
329
+ return;
330
+ }
331
+ this.items.push({ item });
332
+ }
333
+ async get() {
334
+ if (this.items.length > 0) {
335
+ const entry = this.items.shift();
336
+ if (entry) {
337
+ return { done: false, item: entry.item };
338
+ }
339
+ }
340
+ if (this.isClosed) {
341
+ return { done: true };
342
+ }
343
+ return new Promise((resolve) => {
344
+ this.waiters.push(resolve);
345
+ });
346
+ }
347
+ close() {
348
+ if (this.isClosed) {
349
+ return;
350
+ }
351
+ this.isClosed = true;
352
+ while (this.waiters.length > 0) {
353
+ const waiter = this.waiters.shift();
354
+ if (waiter) {
355
+ waiter({ done: true });
356
+ }
357
+ }
358
+ }
359
+ size() {
360
+ return this.items.length;
361
+ }
362
+ }
363
+
364
+ // packages/core/src/queue/task-executor.ts
365
+ var DEFAULT_WORKER_COUNT = 1;
366
+ var DEFAULT_MAX_RETRIES = 0;
367
+ var DEFAULT_RETRY_DELAY_MS = 0;
368
+
369
+ class TaskExecutor {
370
+ queue;
371
+ handler;
372
+ isRunning = false;
373
+ workerPromises = [];
374
+ workerCount;
375
+ maxRetries;
376
+ retryDelayMs;
377
+ onError;
378
+ constructor(queue, handler, options = {}) {
379
+ this.queue = queue;
380
+ this.handler = handler;
381
+ this.workerCount = Math.max(options.workerCount ?? DEFAULT_WORKER_COUNT, 1);
382
+ this.maxRetries = Math.max(options.maxRetries ?? DEFAULT_MAX_RETRIES, 0);
383
+ this.retryDelayMs = Math.max(options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS, 0);
384
+ this.onError = options.onError;
385
+ }
386
+ start() {
387
+ if (this.isRunning) {
388
+ return;
389
+ }
390
+ this.isRunning = true;
391
+ this.workerPromises = Array.from({ length: this.workerCount }, () => this.runWorker());
392
+ }
393
+ async stop() {
394
+ if (!this.isRunning) {
395
+ return;
396
+ }
397
+ this.isRunning = false;
398
+ this.queue.close();
399
+ await Promise.all(this.workerPromises);
400
+ this.workerPromises = [];
401
+ }
402
+ async runWorker() {
403
+ while (true) {
404
+ const result = await this.queue.get();
405
+ if (result.done) {
406
+ return;
407
+ }
408
+ await this.executeWithRetry(result.item);
409
+ }
410
+ }
411
+ async executeWithRetry(item) {
412
+ let attempt = 0;
413
+ while (attempt <= this.maxRetries) {
414
+ try {
415
+ await this.handler(item);
416
+ return;
417
+ } catch (error) {
418
+ if (attempt >= this.maxRetries) {
419
+ await this.safeOnError(error, item);
420
+ return;
421
+ }
422
+ if (this.retryDelayMs > 0) {
423
+ await new Promise((resolve) => setTimeout(resolve, this.retryDelayMs));
424
+ }
425
+ }
426
+ attempt += 1;
427
+ }
428
+ }
429
+ async safeOnError(error, item) {
430
+ if (!this.onError) {
431
+ return;
432
+ }
215
433
  try {
216
- await this.transport.close();
217
- } catch (error) {
218
- console.error("Failed to close transport:", error);
434
+ await this.onError(error, item);
435
+ } catch {
436
+ return;
219
437
  }
220
438
  }
221
439
  }
440
+
222
441
  // packages/core/src/utils/logging.ts
442
+ var LogLevel;
443
+ ((LogLevel2) => {
444
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
445
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
446
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
447
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
448
+ })(LogLevel ||= {});
449
+
223
450
  class Logger {
224
451
  namespace;
225
- static level = 1 /* INFO */;
452
+ static level = (() => {
453
+ const level = process.env.PREFACTOR_LOG_LEVEL?.toUpperCase();
454
+ if (level && level in LogLevel) {
455
+ return LogLevel[level];
456
+ }
457
+ return 1 /* INFO */;
458
+ })();
226
459
  constructor(namespace) {
227
460
  this.namespace = namespace;
228
461
  }
@@ -266,128 +499,358 @@ function configureLogging() {
266
499
  }
267
500
  }
268
501
 
502
+ // packages/core/src/transport/http/agent-instance-client.ts
503
+ class AgentInstanceClient {
504
+ httpClient;
505
+ constructor(httpClient) {
506
+ this.httpClient = httpClient;
507
+ }
508
+ register(payload) {
509
+ return this.httpClient.request("/api/v1/agent_instance/register", {
510
+ method: "POST",
511
+ body: payload
512
+ });
513
+ }
514
+ async start(agentInstanceId) {
515
+ await this.httpClient.request(`/api/v1/agent_instance/${agentInstanceId}/start`, {
516
+ method: "POST",
517
+ body: {}
518
+ });
519
+ }
520
+ async finish(agentInstanceId) {
521
+ await this.httpClient.request(`/api/v1/agent_instance/${agentInstanceId}/finish`, {
522
+ method: "POST",
523
+ body: {}
524
+ });
525
+ }
526
+ }
527
+
528
+ // packages/core/src/transport/http/retry-policy.ts
529
+ var JITTER_MIN = 0.5;
530
+ function shouldRetryStatusCode(statusCode, retryOnStatusCodes) {
531
+ return retryOnStatusCodes.includes(statusCode);
532
+ }
533
+ function calculateRetryDelay(attempt, config, random = Math.random) {
534
+ const baseDelay = Math.min(config.initialRetryDelay * config.retryMultiplier ** attempt, config.maxRetryDelay);
535
+ const jitterMultiplier = JITTER_MIN + random() * JITTER_MIN;
536
+ return Math.round(baseDelay * jitterMultiplier);
537
+ }
538
+
539
+ // packages/core/src/transport/http/http-client.ts
540
+ class HttpClientError extends Error {
541
+ url;
542
+ method;
543
+ status;
544
+ statusText;
545
+ responseBody;
546
+ retryable;
547
+ constructor(message, options) {
548
+ super(message, { cause: options.cause });
549
+ this.name = "HttpClientError";
550
+ this.url = options.url;
551
+ this.method = options.method;
552
+ this.status = options.status;
553
+ this.statusText = options.statusText;
554
+ this.responseBody = options.responseBody;
555
+ this.retryable = options.retryable;
556
+ }
557
+ }
558
+
559
+ class HttpClient {
560
+ config;
561
+ fetchFn;
562
+ sleep;
563
+ random;
564
+ constructor(config, dependencies = {}) {
565
+ this.config = config;
566
+ this.fetchFn = dependencies.fetchFn ?? fetch;
567
+ this.sleep = dependencies.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
568
+ this.random = dependencies.random ?? Math.random;
569
+ }
570
+ async request(path, options = {}) {
571
+ const url = new URL(path, this.config.apiUrl).toString();
572
+ const method = options.method ?? "GET";
573
+ let attempt = 0;
574
+ while (true) {
575
+ const headers = new Headers(options.headers);
576
+ headers.set("Authorization", `Bearer ${this.config.apiToken}`);
577
+ if (options.body !== undefined && !headers.has("Content-Type")) {
578
+ headers.set("Content-Type", "application/json");
579
+ }
580
+ const requestInit = {
581
+ ...options,
582
+ method,
583
+ headers,
584
+ body: options.body === undefined ? undefined : JSON.stringify(options.body),
585
+ signal: AbortSignal.timeout(options.timeoutMs ?? this.config.requestTimeout)
586
+ };
587
+ try {
588
+ const response = await this.fetchFn(url, requestInit);
589
+ if (response.ok) {
590
+ return await parseResponseBody(response);
591
+ }
592
+ const responseBody = await parseResponseBody(response);
593
+ const canRetry = attempt < this.config.maxRetries && shouldRetryStatusCode(response.status, this.config.retryOnStatusCodes);
594
+ if (canRetry) {
595
+ const delayMs = calculateRetryDelay(attempt, this.config, this.random);
596
+ await this.sleep(delayMs);
597
+ attempt += 1;
598
+ continue;
599
+ }
600
+ throw new HttpClientError(`HTTP request failed with status ${response.status}`, {
601
+ url,
602
+ method,
603
+ status: response.status,
604
+ statusText: response.statusText,
605
+ responseBody,
606
+ retryable: shouldRetryStatusCode(response.status, this.config.retryOnStatusCodes)
607
+ });
608
+ } catch (error) {
609
+ if (error instanceof HttpClientError) {
610
+ throw error;
611
+ }
612
+ const canRetry = attempt < this.config.maxRetries && isRetryableNetworkError(error);
613
+ if (canRetry) {
614
+ const delayMs = calculateRetryDelay(attempt, this.config, this.random);
615
+ await this.sleep(delayMs);
616
+ attempt += 1;
617
+ continue;
618
+ }
619
+ throw new HttpClientError("HTTP request failed due to network error", {
620
+ url,
621
+ method,
622
+ retryable: false,
623
+ cause: error
624
+ });
625
+ }
626
+ }
627
+ }
628
+ }
629
+ function isRetryableNetworkError(error) {
630
+ if (error instanceof TypeError) {
631
+ return true;
632
+ }
633
+ if (error instanceof DOMException && (error.name === "AbortError" || error.name === "TimeoutError")) {
634
+ return true;
635
+ }
636
+ if (error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError")) {
637
+ return true;
638
+ }
639
+ return false;
640
+ }
641
+ async function parseResponseBody(response) {
642
+ const bodyText = await response.text();
643
+ if (!bodyText) {
644
+ return null;
645
+ }
646
+ const contentType = response.headers.get("content-type") ?? "";
647
+ if (contentType.includes("application/json")) {
648
+ try {
649
+ return JSON.parse(bodyText);
650
+ } catch {
651
+ return bodyText;
652
+ }
653
+ }
654
+ try {
655
+ return JSON.parse(bodyText);
656
+ } catch {
657
+ return bodyText;
658
+ }
659
+ }
660
+
661
+ // packages/core/src/transport/http/agent-span-client.ts
662
+ class AgentSpanClient {
663
+ httpClient;
664
+ constructor(httpClient) {
665
+ this.httpClient = httpClient;
666
+ }
667
+ create(payload) {
668
+ return this.httpClient.request("/api/v1/agent_spans", {
669
+ method: "POST",
670
+ body: payload
671
+ });
672
+ }
673
+ async finish(spanId, timestamp) {
674
+ try {
675
+ await this.httpClient.request(`/api/v1/agent_spans/${spanId}/finish`, {
676
+ method: "POST",
677
+ body: { timestamp }
678
+ });
679
+ } catch (error) {
680
+ if (error instanceof HttpClientError && error.status === 409 && isAlreadyFinishedError(error.responseBody)) {
681
+ return;
682
+ }
683
+ throw error;
684
+ }
685
+ }
686
+ }
687
+ function isAlreadyFinishedError(responseBody) {
688
+ if (!responseBody || typeof responseBody !== "object") {
689
+ return false;
690
+ }
691
+ const payload = responseBody;
692
+ return payload.code === "invalid_action";
693
+ }
694
+
269
695
  // packages/core/src/transport/http.ts
270
696
  var logger = getLogger("http-transport");
271
697
 
272
698
  class HttpTransport {
273
699
  config;
274
- queue = [];
275
- processing = false;
276
700
  closed = false;
701
+ actionQueue = new InMemoryQueue;
702
+ taskExecutor;
703
+ agentInstanceClient;
704
+ agentSpanClient;
705
+ previousAgentSchema = null;
706
+ requiresNewAgentIdentifier = false;
707
+ previousAgentIdentifier = null;
277
708
  agentInstanceId = null;
278
709
  spanIdMap = new Map;
710
+ pendingFinishes = new Map;
279
711
  constructor(config) {
280
712
  this.config = config;
281
- this.startProcessing();
713
+ const httpClient = new HttpClient(config);
714
+ this.agentInstanceClient = new AgentInstanceClient(httpClient);
715
+ this.agentSpanClient = new AgentSpanClient(httpClient);
716
+ this.taskExecutor = new TaskExecutor(this.actionQueue, this.processAction, {
717
+ workerCount: 1,
718
+ onError: async (error) => {
719
+ logger.error("Error processing HTTP action:", error);
720
+ }
721
+ });
722
+ this.taskExecutor.start();
723
+ }
724
+ registerSchema(schema) {
725
+ this.enqueue({ type: "schema_register", schema });
726
+ }
727
+ startAgentInstance(options) {
728
+ this.enqueue({ type: "agent_start", options });
729
+ }
730
+ finishAgentInstance() {
731
+ this.enqueue({ type: "agent_finish" });
282
732
  }
283
733
  emit(span) {
284
- if (this.closed) {
285
- return;
286
- }
287
- this.queue.push({ type: "span", data: span });
734
+ this.enqueue({ type: "span_end", span });
288
735
  }
289
736
  finishSpan(spanId, endTime) {
290
- if (this.closed) {
291
- return;
292
- }
293
- const timestamp = new Date(endTime).toISOString();
294
- this.queue.push({ type: "finish_span", data: { spanId, timestamp } });
737
+ this.enqueue({ type: "span_finish", spanId, endTime });
295
738
  }
296
- startAgentInstance() {
297
- if (this.closed) {
298
- return;
739
+ async close() {
740
+ this.closed = true;
741
+ await this.taskExecutor.stop();
742
+ if (this.pendingFinishes.size > 0) {
743
+ logger.warn(`Transport closed with ${this.pendingFinishes.size} pending span finish(es) that could not be processed`);
744
+ this.pendingFinishes.clear();
299
745
  }
300
- this.queue.push({ type: "start_agent", data: null });
301
746
  }
302
- finishAgentInstance() {
747
+ enqueue(action) {
303
748
  if (this.closed) {
304
749
  return;
305
750
  }
306
- this.queue.push({ type: "finish_agent", data: null });
751
+ this.actionQueue.put(action).catch((error) => {
752
+ logger.error("Failed to enqueue HTTP action:", error);
753
+ });
307
754
  }
308
- async startProcessing() {
309
- this.processing = true;
310
- while (!this.closed || this.queue.length > 0) {
311
- if (this.queue.length === 0) {
312
- await new Promise((resolve) => setTimeout(resolve, 100));
313
- continue;
755
+ processAction = async (action) => {
756
+ switch (action.type) {
757
+ case "schema_register": {
758
+ const incomingSchema = JSON.stringify(action.schema);
759
+ if (this.previousAgentSchema !== null && this.previousAgentSchema !== incomingSchema) {
760
+ this.requiresNewAgentIdentifier = true;
761
+ this.previousAgentIdentifier = this.config.agentIdentifier;
762
+ this.agentInstanceId = null;
763
+ }
764
+ this.previousAgentSchema = incomingSchema;
765
+ this.config.agentSchema = action.schema;
766
+ return;
314
767
  }
315
- const item = this.queue.shift();
316
- if (!item)
317
- continue;
318
- try {
319
- if (!this.agentInstanceId && item.type !== "start_agent") {
768
+ case "agent_start": {
769
+ if (this.requiresNewAgentIdentifier) {
770
+ const nextAgentIdentifier = action.options?.agentIdentifier;
771
+ if (nextAgentIdentifier === undefined || nextAgentIdentifier === this.previousAgentIdentifier) {
772
+ logger.error("Schema changed; starting an agent requires a new agentIdentifier value.");
773
+ return;
774
+ }
775
+ this.requiresNewAgentIdentifier = false;
776
+ this.previousAgentIdentifier = null;
777
+ }
778
+ if (action.options?.agentId !== undefined)
779
+ this.config.agentId = action.options.agentId;
780
+ if (action.options?.agentIdentifier !== undefined) {
781
+ this.config.agentIdentifier = action.options.agentIdentifier;
782
+ }
783
+ if (action.options?.agentName !== undefined)
784
+ this.config.agentName = action.options.agentName;
785
+ if (action.options?.agentDescription !== undefined) {
786
+ this.config.agentDescription = action.options.agentDescription;
787
+ }
788
+ await this.startAgentInstanceHttp();
789
+ return;
790
+ }
791
+ case "agent_finish":
792
+ await this.finishAgentInstanceHttp();
793
+ return;
794
+ case "span_end":
795
+ if (!this.agentInstanceId) {
320
796
  await this.ensureAgentRegistered();
321
797
  }
322
- switch (item.type) {
323
- case "span":
324
- await this.sendSpan(item.data);
325
- break;
326
- case "finish_span":
327
- await this.finishSpanHttp(item.data);
328
- break;
329
- case "start_agent":
330
- await this.startAgentInstanceHttp();
331
- break;
332
- case "finish_agent":
333
- await this.finishAgentInstanceHttp();
334
- break;
798
+ await this.sendSpan(action.span);
799
+ return;
800
+ case "span_finish": {
801
+ const backendSpanId = this.spanIdMap.get(action.spanId);
802
+ if (backendSpanId) {
803
+ const timestamp = new Date(action.endTime).toISOString();
804
+ await this.finishSpanHttp({ spanId: action.spanId, timestamp });
805
+ } else {
806
+ this.pendingFinishes.set(action.spanId, action.endTime);
335
807
  }
336
- } catch (error) {
337
- logger.error("Error processing queue item:", error);
808
+ return;
338
809
  }
339
810
  }
340
- this.processing = false;
811
+ };
812
+ async processPendingFinishes(spanId) {
813
+ if (!this.pendingFinishes.has(spanId)) {
814
+ return;
815
+ }
816
+ const pendingEndTime = this.pendingFinishes.get(spanId);
817
+ if (pendingEndTime === undefined) {
818
+ return;
819
+ }
820
+ try {
821
+ const timestamp = new Date(pendingEndTime).toISOString();
822
+ await this.finishSpanHttp({ spanId, timestamp });
823
+ this.pendingFinishes.delete(spanId);
824
+ } catch (error) {
825
+ logger.error("Error processing pending span finish:", error);
826
+ }
341
827
  }
342
- async sendSpan(span, retry = 0) {
343
- const url = `${this.config.apiUrl}/api/v1/agent_spans`;
828
+ async sendSpan(span) {
344
829
  const payload = this.transformSpanToApiFormat(span);
345
830
  try {
346
- const response = await fetch(url, {
347
- method: "POST",
348
- headers: {
349
- Authorization: `Bearer ${this.config.apiToken}`,
350
- "Content-Type": "application/json"
351
- },
352
- body: JSON.stringify(payload),
353
- signal: AbortSignal.timeout(this.config.requestTimeout)
354
- });
355
- if (response.ok) {
356
- const data = await response.json();
357
- const backendSpanId = data?.details?.id;
358
- if (backendSpanId) {
359
- this.spanIdMap.set(span.spanId, backendSpanId);
360
- }
831
+ const response = await this.agentSpanClient.create(payload);
832
+ const backendSpanId = response.details?.id;
833
+ if (!backendSpanId) {
361
834
  return;
362
835
  }
363
- if ((response.status >= 500 || response.status === 429) && retry < this.config.maxRetries) {
364
- const delay = Math.min(this.config.initialRetryDelay * this.config.retryMultiplier ** retry, this.config.maxRetryDelay);
365
- logger.debug(`Retrying span send after ${delay}ms (attempt ${retry + 1})`);
366
- await new Promise((resolve) => setTimeout(resolve, delay));
367
- return this.sendSpan(span, retry + 1);
368
- }
369
- logger.error(`Failed to send span: ${response.status} ${response.statusText}`);
836
+ this.spanIdMap.set(span.spanId, backendSpanId);
837
+ await this.processPendingFinishes(span.spanId);
370
838
  } catch (error) {
371
839
  logger.error("Error sending span:", error);
372
- if (retry < this.config.maxRetries) {
373
- const delay = Math.min(this.config.initialRetryDelay * this.config.retryMultiplier ** retry, this.config.maxRetryDelay);
374
- await new Promise((resolve) => setTimeout(resolve, delay));
375
- return this.sendSpan(span, retry + 1);
376
- }
377
840
  }
378
841
  }
379
842
  transformSpanToApiFormat(span) {
380
843
  const startedAt = new Date(span.startTime).toISOString();
381
844
  const finishedAt = span.endTime ? new Date(span.endTime).toISOString() : null;
845
+ const apiStatus = this.mapStatusForApi(span.status);
382
846
  const payload = {
383
847
  span_id: span.spanId,
384
848
  trace_id: span.traceId,
385
849
  name: span.name,
386
- status: span.status,
850
+ status: apiStatus,
387
851
  inputs: span.inputs,
388
852
  outputs: span.outputs,
389
853
  metadata: span.metadata,
390
- tags: span.tags,
391
854
  token_usage: null,
392
855
  error: null
393
856
  };
@@ -410,6 +873,7 @@ class HttpTransport {
410
873
  details: {
411
874
  agent_instance_id: this.agentInstanceId,
412
875
  schema_name: span.spanType,
876
+ status: apiStatus,
413
877
  payload,
414
878
  parent_span_id: parentSpanId,
415
879
  started_at: startedAt,
@@ -417,103 +881,51 @@ class HttpTransport {
417
881
  }
418
882
  };
419
883
  }
420
- getDefaultSchema() {
421
- return {
422
- external_identifier: "1.0.0",
423
- span_schemas: {
424
- agent: {
425
- type: "object",
426
- properties: { type: { type: "string", const: "agent" } }
427
- },
428
- llm: {
429
- type: "object",
430
- properties: { type: { type: "string", const: "llm" } }
431
- },
432
- tool: {
433
- type: "object",
434
- properties: { type: { type: "string", const: "tool" } }
435
- },
436
- chain: {
437
- type: "object",
438
- properties: { type: { type: "string", const: "chain" } }
439
- },
440
- retriever: {
441
- type: "object",
442
- properties: { type: { type: "string", const: "retriever" } }
443
- }
444
- }
445
- };
884
+ mapStatusForApi(status) {
885
+ switch (status) {
886
+ case "running":
887
+ return "active";
888
+ case "success":
889
+ return "complete";
890
+ case "error":
891
+ return "failed";
892
+ default:
893
+ return "active";
894
+ }
446
895
  }
447
896
  async ensureAgentRegistered() {
448
897
  if (this.agentInstanceId) {
449
- return;
898
+ return true;
450
899
  }
451
- const url = `${this.config.apiUrl}/api/v1/agent_instance/register`;
452
900
  const payload = {};
453
901
  if (this.config.agentId)
454
902
  payload.agent_id = this.config.agentId;
455
- if (this.config.agentVersion) {
903
+ if (this.config.agentIdentifier) {
456
904
  payload.agent_version = {
457
- external_identifier: this.config.agentVersion,
905
+ external_identifier: this.config.agentIdentifier,
458
906
  name: this.config.agentName || "Agent",
459
907
  description: this.config.agentDescription || ""
460
908
  };
461
909
  }
462
- if (this.config.skipSchema) {
463
- logger.debug("Skipping schema in registration (skipSchema=true)");
464
- } else if (this.config.agentSchema) {
465
- logger.debug("Using custom agent schema");
910
+ if (this.config.agentSchema) {
466
911
  payload.agent_schema_version = this.config.agentSchema;
467
- } else if (this.config.agentSchemaVersion) {
468
- logger.debug(`Using schema version: ${this.config.agentSchemaVersion}`);
469
- payload.agent_schema_version = {
470
- external_identifier: this.config.agentSchemaVersion
471
- };
472
- } else {
473
- logger.debug("Using default hardcoded schema (v1.0.0)");
474
- payload.agent_schema_version = this.getDefaultSchema();
475
912
  }
476
913
  try {
477
- const response = await fetch(url, {
478
- method: "POST",
479
- headers: {
480
- Authorization: `Bearer ${this.config.apiToken}`,
481
- "Content-Type": "application/json"
482
- },
483
- body: JSON.stringify(payload),
484
- signal: AbortSignal.timeout(this.config.requestTimeout)
485
- });
486
- if (response.ok) {
487
- const data = await response.json();
488
- this.agentInstanceId = data?.details?.id ?? null;
489
- logger.debug(`Registered agent instance: ${this.agentInstanceId}`);
490
- } else {
491
- logger.error(`Failed to register agent: ${response.status} ${response.statusText}`);
492
- }
914
+ const data = await this.agentInstanceClient.register(payload);
915
+ this.agentInstanceId = data.details?.id ?? null;
493
916
  } catch (error) {
494
917
  logger.error("Error registering agent:", error);
495
918
  }
919
+ return this.agentInstanceId !== null;
496
920
  }
497
921
  async startAgentInstanceHttp() {
498
- await this.ensureAgentRegistered();
499
- if (!this.agentInstanceId) {
922
+ const isRegistered = await this.ensureAgentRegistered();
923
+ if (!isRegistered || !this.agentInstanceId) {
500
924
  logger.error("Cannot start agent instance: not registered");
501
925
  return;
502
926
  }
503
- const url = `${this.config.apiUrl}/api/v1/agent_instance/${this.agentInstanceId}/start`;
504
927
  try {
505
- const response = await fetch(url, {
506
- method: "POST",
507
- headers: {
508
- Authorization: `Bearer ${this.config.apiToken}`,
509
- "Content-Type": "application/json"
510
- },
511
- body: JSON.stringify({}),
512
- signal: AbortSignal.timeout(this.config.requestTimeout)
513
- });
514
- if (!response.ok) {
515
- logger.error(`Failed to start agent instance: ${response.status} ${response.statusText}`);
516
- }
928
+ await this.agentInstanceClient.start(this.agentInstanceId);
517
929
  } catch (error) {
518
930
  logger.error("Error starting agent instance:", error);
519
931
  }
@@ -523,23 +935,12 @@ class HttpTransport {
523
935
  logger.error("Cannot finish agent instance: not registered");
524
936
  return;
525
937
  }
526
- const url = `${this.config.apiUrl}/api/v1/agent_instance/${this.agentInstanceId}/finish`;
527
938
  try {
528
- const response = await fetch(url, {
529
- method: "POST",
530
- headers: {
531
- Authorization: `Bearer ${this.config.apiToken}`,
532
- "Content-Type": "application/json"
533
- },
534
- body: JSON.stringify({}),
535
- signal: AbortSignal.timeout(this.config.requestTimeout)
536
- });
537
- if (!response.ok) {
538
- logger.error(`Failed to finish agent instance: ${response.status} ${response.statusText}`);
539
- }
939
+ await this.agentInstanceClient.finish(this.agentInstanceId);
540
940
  } catch (error) {
541
941
  logger.error("Error finishing agent instance:", error);
542
942
  }
943
+ this.agentInstanceId = null;
543
944
  }
544
945
  async finishSpanHttp(data) {
545
946
  const backendSpanId = this.spanIdMap.get(data.spanId);
@@ -547,35 +948,38 @@ class HttpTransport {
547
948
  logger.warn(`Cannot finish span ${data.spanId}: backend ID not found`);
548
949
  return;
549
950
  }
550
- const url = `${this.config.apiUrl}/api/v1/agent_spans/${backendSpanId}/finish`;
551
951
  try {
552
- const response = await fetch(url, {
553
- method: "POST",
554
- headers: {
555
- Authorization: `Bearer ${this.config.apiToken}`,
556
- "Content-Type": "application/json"
557
- },
558
- body: JSON.stringify({ timestamp: data.timestamp }),
559
- signal: AbortSignal.timeout(this.config.requestTimeout)
560
- });
561
- if (!response.ok) {
562
- logger.error(`Failed to finish span: ${response.status} ${response.statusText}`);
563
- }
952
+ await this.agentSpanClient.finish(backendSpanId, data.timestamp);
564
953
  } catch (error) {
565
954
  logger.error("Error finishing span:", error);
566
955
  }
567
956
  }
568
- async close() {
569
- this.closed = true;
570
- const timeout = 1e4;
571
- const start = Date.now();
572
- while (this.processing && Date.now() - start < timeout) {
573
- await new Promise((resolve) => setTimeout(resolve, 100));
574
- }
575
- if (this.processing) {
576
- logger.warn("Transport closed with pending queue items");
577
- }
578
- }
957
+ }
958
+
959
+ // packages/core/src/create-core.ts
960
+ function createCore(config) {
961
+ if (!config.httpConfig) {
962
+ throw new Error("HTTP transport requires httpConfig to be provided in configuration");
963
+ }
964
+ const httpConfig = HttpTransportConfigSchema.parse(config.httpConfig);
965
+ const transport = new HttpTransport(httpConfig);
966
+ let partition;
967
+ if (config.httpConfig.agentId) {
968
+ try {
969
+ partition = import_pfid2.extractPartition(config.httpConfig.agentId);
970
+ } catch {
971
+ partition = undefined;
972
+ }
973
+ }
974
+ const tracer = new Tracer(transport, partition);
975
+ const allowUnregisteredSchema = Boolean(config.httpConfig.agentSchema);
976
+ const agentManager = new AgentInstanceManager(transport, {
977
+ allowUnregisteredSchema
978
+ });
979
+ const shutdown = async () => {
980
+ await tracer.close();
981
+ };
982
+ return { tracer, agentManager, shutdown };
579
983
  }
580
984
  // packages/core/src/utils/serialization.ts
581
985
  function truncateString(value, maxLength) {
@@ -611,32 +1015,4 @@ function serializeValue(value, maxLength = 1e4) {
611
1015
  }
612
1016
  }
613
1017
 
614
- // packages/core/src/transport/stdio.ts
615
- class StdioTransport {
616
- closed = false;
617
- writeLock = Promise.resolve();
618
- emit(span) {
619
- if (this.closed) {
620
- return;
621
- }
622
- this.writeLock = this.writeLock.then(async () => {
623
- try {
624
- const serialized = serializeValue(span);
625
- const json = JSON.stringify(serialized);
626
- await Bun.write(Bun.stdout, `${json}
627
- `);
628
- } catch (error) {
629
- console.error("Failed to emit span to stdout:", error);
630
- }
631
- });
632
- }
633
- finishSpan() {}
634
- startAgentInstance() {}
635
- finishAgentInstance() {}
636
- async close() {
637
- this.closed = true;
638
- await this.writeLock;
639
- }
640
- }
641
-
642
- //# debugId=E95D2EBB45D9CCA264756E2164756E21
1018
+ //# debugId=97A3CED64412936764756E2164756E21