@prefactor/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/config.d.ts +259 -0
  2. package/dist/config.d.ts.map +1 -0
  3. package/dist/config.js +110 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/index.cjs +642 -0
  6. package/dist/index.cjs.map +17 -0
  7. package/dist/index.d.ts +10 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +610 -0
  10. package/dist/index.js.map +17 -0
  11. package/dist/tracing/context.d.ts +53 -0
  12. package/dist/tracing/context.d.ts.map +1 -0
  13. package/dist/tracing/context.js +66 -0
  14. package/dist/tracing/context.js.map +1 -0
  15. package/dist/tracing/span.d.ts +68 -0
  16. package/dist/tracing/span.d.ts.map +1 -0
  17. package/dist/tracing/span.js +21 -0
  18. package/dist/tracing/span.js.map +1 -0
  19. package/dist/tracing/tracer.d.ts +100 -0
  20. package/dist/tracing/tracer.d.ts.map +1 -0
  21. package/dist/tracing/tracer.js +151 -0
  22. package/dist/tracing/tracer.js.map +1 -0
  23. package/dist/transport/base.d.ts +38 -0
  24. package/dist/transport/base.d.ts.map +1 -0
  25. package/dist/transport/base.js +2 -0
  26. package/dist/transport/base.js.map +1 -0
  27. package/dist/transport/http.d.ts +90 -0
  28. package/dist/transport/http.d.ts.map +1 -0
  29. package/dist/transport/http.js +399 -0
  30. package/dist/transport/http.js.map +1 -0
  31. package/dist/transport/stdio.d.ts +48 -0
  32. package/dist/transport/stdio.d.ts.map +1 -0
  33. package/dist/transport/stdio.js +71 -0
  34. package/dist/transport/stdio.js.map +1 -0
  35. package/dist/utils/logging.d.ts +29 -0
  36. package/dist/utils/logging.d.ts.map +1 -0
  37. package/dist/utils/logging.js +71 -0
  38. package/dist/utils/logging.js.map +1 -0
  39. package/dist/utils/serialization.d.ts +24 -0
  40. package/dist/utils/serialization.d.ts.map +1 -0
  41. package/dist/utils/serialization.js +60 -0
  42. package/dist/utils/serialization.js.map +1 -0
  43. package/package.json +36 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,642 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
6
+ var __toCommonJS = (from) => {
7
+ var entry = __moduleCache.get(from), desc;
8
+ if (entry)
9
+ return entry;
10
+ entry = __defProp({}, "__esModule", { value: true });
11
+ if (from && typeof from === "object" || typeof from === "function")
12
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
+ get: () => from[key],
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ }));
16
+ __moduleCache.set(from, entry);
17
+ return entry;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+
29
+ // packages/core/src/index.ts
30
+ var exports_src = {};
31
+ __export(exports_src, {
32
+ truncateString: () => truncateString,
33
+ serializeValue: () => serializeValue,
34
+ getLogger: () => getLogger,
35
+ createConfig: () => createConfig,
36
+ configureLogging: () => configureLogging,
37
+ Tracer: () => Tracer,
38
+ StdioTransport: () => StdioTransport,
39
+ SpanType: () => SpanType,
40
+ SpanStatus: () => SpanStatus,
41
+ SpanContext: () => SpanContext,
42
+ PartialHttpConfigSchema: () => PartialHttpConfigSchema,
43
+ HttpTransportConfigSchema: () => HttpTransportConfigSchema,
44
+ HttpTransport: () => HttpTransport,
45
+ ConfigSchema: () => ConfigSchema
46
+ });
47
+ module.exports = __toCommonJS(exports_src);
48
+
49
+ // packages/core/src/config.ts
50
+ var import_zod = require("zod");
51
+ var HttpTransportConfigSchema = import_zod.z.object({
52
+ apiUrl: import_zod.z.string().url(),
53
+ apiToken: import_zod.z.string().min(1),
54
+ agentId: import_zod.z.string().optional(),
55
+ agentVersion: import_zod.z.string().optional(),
56
+ agentName: import_zod.z.string().optional(),
57
+ agentDescription: import_zod.z.string().optional(),
58
+ 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
+ requestTimeout: import_zod.z.number().positive().default(30000),
62
+ connectTimeout: import_zod.z.number().positive().default(1e4),
63
+ maxRetries: import_zod.z.number().int().nonnegative().default(3),
64
+ initialRetryDelay: import_zod.z.number().positive().default(1000),
65
+ maxRetryDelay: import_zod.z.number().positive().default(60000),
66
+ retryMultiplier: import_zod.z.number().positive().default(2)
67
+ });
68
+ var PartialHttpConfigSchema = import_zod.z.object({
69
+ apiUrl: import_zod.z.string().url(),
70
+ apiToken: import_zod.z.string().min(1),
71
+ agentId: import_zod.z.string().optional(),
72
+ agentVersion: import_zod.z.string().optional(),
73
+ agentName: import_zod.z.string().optional(),
74
+ agentDescription: import_zod.z.string().optional(),
75
+ 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
+ requestTimeout: import_zod.z.number().positive().optional(),
79
+ connectTimeout: import_zod.z.number().positive().optional(),
80
+ maxRetries: import_zod.z.number().int().nonnegative().optional(),
81
+ initialRetryDelay: import_zod.z.number().positive().optional(),
82
+ maxRetryDelay: import_zod.z.number().positive().optional(),
83
+ retryMultiplier: import_zod.z.number().positive().optional()
84
+ });
85
+ var ConfigSchema = import_zod.z.object({
86
+ transportType: import_zod.z.enum(["stdio", "http"]).default("stdio"),
87
+ sampleRate: import_zod.z.number().min(0).max(1).default(1),
88
+ captureInputs: import_zod.z.boolean().default(true),
89
+ captureOutputs: import_zod.z.boolean().default(true),
90
+ maxInputLength: import_zod.z.number().int().positive().default(1e4),
91
+ maxOutputLength: import_zod.z.number().int().positive().default(1e4),
92
+ httpConfig: PartialHttpConfigSchema.optional()
93
+ });
94
+ function createConfig(options) {
95
+ const config = {
96
+ transportType: options?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? "stdio",
97
+ sampleRate: options?.sampleRate ?? parseFloat(process.env.PREFACTOR_SAMPLE_RATE ?? "1.0"),
98
+ captureInputs: options?.captureInputs ?? process.env.PREFACTOR_CAPTURE_INPUTS !== "false",
99
+ captureOutputs: options?.captureOutputs ?? process.env.PREFACTOR_CAPTURE_OUTPUTS !== "false",
100
+ maxInputLength: options?.maxInputLength ?? parseInt(process.env.PREFACTOR_MAX_INPUT_LENGTH ?? "10000", 10),
101
+ maxOutputLength: options?.maxOutputLength ?? parseInt(process.env.PREFACTOR_MAX_OUTPUT_LENGTH ?? "10000", 10),
102
+ httpConfig: options?.httpConfig
103
+ };
104
+ return ConfigSchema.parse(config);
105
+ }
106
+ // packages/core/src/tracing/context.ts
107
+ var import_node_async_hooks = require("node:async_hooks");
108
+ var spanStorage = new import_node_async_hooks.AsyncLocalStorage;
109
+
110
+ class SpanContext {
111
+ static getCurrent() {
112
+ return spanStorage.getStore();
113
+ }
114
+ static run(span, fn) {
115
+ return spanStorage.run(span, fn);
116
+ }
117
+ static async runAsync(span, fn) {
118
+ return spanStorage.run(span, fn);
119
+ }
120
+ static clear() {
121
+ spanStorage.disable();
122
+ }
123
+ }
124
+ // 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 ||= {});
133
+ var SpanStatus;
134
+ ((SpanStatus2) => {
135
+ SpanStatus2["RUNNING"] = "running";
136
+ SpanStatus2["SUCCESS"] = "success";
137
+ SpanStatus2["ERROR"] = "error";
138
+ })(SpanStatus ||= {});
139
+ // packages/core/src/tracing/tracer.ts
140
+ var import_pfid = require("@prefactor/pfid");
141
+ class Tracer {
142
+ transport;
143
+ partition;
144
+ constructor(transport, partition) {
145
+ this.transport = transport;
146
+ this.partition = partition ?? import_pfid.generatePartition();
147
+ }
148
+ startSpan(options) {
149
+ const spanId = import_pfid.generate(this.partition);
150
+ const traceId = options.traceId ?? import_pfid.generate(this.partition);
151
+ const span = {
152
+ spanId,
153
+ parentSpanId: options.parentSpanId ?? null,
154
+ traceId,
155
+ name: options.name,
156
+ spanType: options.spanType,
157
+ startTime: Date.now(),
158
+ endTime: null,
159
+ status: "running" /* RUNNING */,
160
+ inputs: options.inputs,
161
+ outputs: null,
162
+ tokenUsage: null,
163
+ error: null,
164
+ metadata: options.metadata ?? {},
165
+ tags: options.tags ?? []
166
+ };
167
+ if (options.spanType === "agent") {
168
+ try {
169
+ this.transport.emit(span);
170
+ } catch (error) {
171
+ console.error("Failed to emit agent span:", error);
172
+ }
173
+ }
174
+ return span;
175
+ }
176
+ endSpan(span, options) {
177
+ span.endTime = Date.now();
178
+ span.outputs = options?.outputs ?? null;
179
+ span.tokenUsage = options?.tokenUsage ?? null;
180
+ if (options?.error) {
181
+ span.status = "error" /* ERROR */;
182
+ span.error = {
183
+ errorType: options.error.constructor.name,
184
+ message: options.error.message,
185
+ stacktrace: options.error.stack ?? ""
186
+ };
187
+ } else {
188
+ span.status = "success" /* SUCCESS */;
189
+ }
190
+ try {
191
+ if (span.spanType === "agent") {
192
+ this.transport.finishSpan(span.spanId, span.endTime);
193
+ } else {
194
+ this.transport.emit(span);
195
+ }
196
+ } catch (error) {
197
+ console.error("Failed to emit/finish span:", error);
198
+ }
199
+ }
200
+ startAgentInstance() {
201
+ try {
202
+ this.transport.startAgentInstance();
203
+ } catch (error) {
204
+ console.error("Failed to start agent instance:", error);
205
+ }
206
+ }
207
+ finishAgentInstance() {
208
+ try {
209
+ this.transport.finishAgentInstance();
210
+ } catch (error) {
211
+ console.error("Failed to finish agent instance:", error);
212
+ }
213
+ }
214
+ async close() {
215
+ try {
216
+ await this.transport.close();
217
+ } catch (error) {
218
+ console.error("Failed to close transport:", error);
219
+ }
220
+ }
221
+ }
222
+ // packages/core/src/utils/logging.ts
223
+ class Logger {
224
+ namespace;
225
+ static level = 1 /* INFO */;
226
+ constructor(namespace) {
227
+ this.namespace = namespace;
228
+ }
229
+ debug(message, ...args) {
230
+ if (Logger.level <= 0 /* DEBUG */) {
231
+ console.debug(`[prefactor:${this.namespace}] ${message}`, ...args);
232
+ }
233
+ }
234
+ info(message, ...args) {
235
+ if (Logger.level <= 1 /* INFO */) {
236
+ console.info(`[prefactor:${this.namespace}] ${message}`, ...args);
237
+ }
238
+ }
239
+ warn(message, ...args) {
240
+ if (Logger.level <= 2 /* WARN */) {
241
+ console.warn(`[prefactor:${this.namespace}] ${message}`, ...args);
242
+ }
243
+ }
244
+ error(message, ...args) {
245
+ if (Logger.level <= 3 /* ERROR */) {
246
+ console.error(`[prefactor:${this.namespace}] ${message}`, ...args);
247
+ }
248
+ }
249
+ static setLevel(level) {
250
+ const levelMap = {
251
+ debug: 0 /* DEBUG */,
252
+ info: 1 /* INFO */,
253
+ warn: 2 /* WARN */,
254
+ error: 3 /* ERROR */
255
+ };
256
+ Logger.level = levelMap[level];
257
+ }
258
+ }
259
+ function getLogger(namespace) {
260
+ return new Logger(namespace);
261
+ }
262
+ function configureLogging() {
263
+ const level = process.env.PREFACTOR_LOG_LEVEL?.toLowerCase();
264
+ if (level) {
265
+ Logger.setLevel(level);
266
+ }
267
+ }
268
+
269
+ // packages/core/src/transport/http.ts
270
+ var logger = getLogger("http-transport");
271
+
272
+ class HttpTransport {
273
+ config;
274
+ queue = [];
275
+ processing = false;
276
+ closed = false;
277
+ agentInstanceId = null;
278
+ spanIdMap = new Map;
279
+ constructor(config) {
280
+ this.config = config;
281
+ this.startProcessing();
282
+ }
283
+ emit(span) {
284
+ if (this.closed) {
285
+ return;
286
+ }
287
+ this.queue.push({ type: "span", data: span });
288
+ }
289
+ 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 } });
295
+ }
296
+ startAgentInstance() {
297
+ if (this.closed) {
298
+ return;
299
+ }
300
+ this.queue.push({ type: "start_agent", data: null });
301
+ }
302
+ finishAgentInstance() {
303
+ if (this.closed) {
304
+ return;
305
+ }
306
+ this.queue.push({ type: "finish_agent", data: null });
307
+ }
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;
314
+ }
315
+ const item = this.queue.shift();
316
+ if (!item)
317
+ continue;
318
+ try {
319
+ if (!this.agentInstanceId && item.type !== "start_agent") {
320
+ await this.ensureAgentRegistered();
321
+ }
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;
335
+ }
336
+ } catch (error) {
337
+ logger.error("Error processing queue item:", error);
338
+ }
339
+ }
340
+ this.processing = false;
341
+ }
342
+ async sendSpan(span, retry = 0) {
343
+ const url = `${this.config.apiUrl}/api/v1/agent_spans`;
344
+ const payload = this.transformSpanToApiFormat(span);
345
+ 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
+ }
361
+ return;
362
+ }
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}`);
370
+ } catch (error) {
371
+ 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
+ }
378
+ }
379
+ transformSpanToApiFormat(span) {
380
+ const startedAt = new Date(span.startTime).toISOString();
381
+ const finishedAt = span.endTime ? new Date(span.endTime).toISOString() : null;
382
+ const payload = {
383
+ span_id: span.spanId,
384
+ trace_id: span.traceId,
385
+ name: span.name,
386
+ status: span.status,
387
+ inputs: span.inputs,
388
+ outputs: span.outputs,
389
+ metadata: span.metadata,
390
+ tags: span.tags,
391
+ token_usage: null,
392
+ error: null
393
+ };
394
+ if (span.tokenUsage) {
395
+ payload.token_usage = {
396
+ prompt_tokens: span.tokenUsage.promptTokens,
397
+ completion_tokens: span.tokenUsage.completionTokens,
398
+ total_tokens: span.tokenUsage.totalTokens
399
+ };
400
+ }
401
+ if (span.error) {
402
+ payload.error = {
403
+ error_type: span.error.errorType,
404
+ message: span.error.message,
405
+ stacktrace: span.error.stacktrace
406
+ };
407
+ }
408
+ const parentSpanId = span.parentSpanId ? this.spanIdMap.get(span.parentSpanId) ?? null : null;
409
+ return {
410
+ details: {
411
+ agent_instance_id: this.agentInstanceId,
412
+ schema_name: span.spanType,
413
+ payload,
414
+ parent_span_id: parentSpanId,
415
+ started_at: startedAt,
416
+ finished_at: finishedAt
417
+ }
418
+ };
419
+ }
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
+ };
446
+ }
447
+ async ensureAgentRegistered() {
448
+ if (this.agentInstanceId) {
449
+ return;
450
+ }
451
+ const url = `${this.config.apiUrl}/api/v1/agent_instance/register`;
452
+ const payload = {};
453
+ if (this.config.agentId)
454
+ payload.agent_id = this.config.agentId;
455
+ if (this.config.agentVersion) {
456
+ payload.agent_version = {
457
+ external_identifier: this.config.agentVersion,
458
+ name: this.config.agentName || "Agent",
459
+ description: this.config.agentDescription || ""
460
+ };
461
+ }
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");
466
+ 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
+ }
476
+ 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
+ }
493
+ } catch (error) {
494
+ logger.error("Error registering agent:", error);
495
+ }
496
+ }
497
+ async startAgentInstanceHttp() {
498
+ await this.ensureAgentRegistered();
499
+ if (!this.agentInstanceId) {
500
+ logger.error("Cannot start agent instance: not registered");
501
+ return;
502
+ }
503
+ const url = `${this.config.apiUrl}/api/v1/agent_instance/${this.agentInstanceId}/start`;
504
+ 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
+ }
517
+ } catch (error) {
518
+ logger.error("Error starting agent instance:", error);
519
+ }
520
+ }
521
+ async finishAgentInstanceHttp() {
522
+ if (!this.agentInstanceId) {
523
+ logger.error("Cannot finish agent instance: not registered");
524
+ return;
525
+ }
526
+ const url = `${this.config.apiUrl}/api/v1/agent_instance/${this.agentInstanceId}/finish`;
527
+ 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
+ }
540
+ } catch (error) {
541
+ logger.error("Error finishing agent instance:", error);
542
+ }
543
+ }
544
+ async finishSpanHttp(data) {
545
+ const backendSpanId = this.spanIdMap.get(data.spanId);
546
+ if (!backendSpanId) {
547
+ logger.warn(`Cannot finish span ${data.spanId}: backend ID not found`);
548
+ return;
549
+ }
550
+ const url = `${this.config.apiUrl}/api/v1/agent_spans/${backendSpanId}/finish`;
551
+ 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
+ }
564
+ } catch (error) {
565
+ logger.error("Error finishing span:", error);
566
+ }
567
+ }
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
+ }
579
+ }
580
+ // packages/core/src/utils/serialization.ts
581
+ function truncateString(value, maxLength) {
582
+ if (value.length <= maxLength) {
583
+ return value;
584
+ }
585
+ return `${value.slice(0, maxLength)}... [truncated]`;
586
+ }
587
+ function serializeValue(value, maxLength = 1e4) {
588
+ if (value === null || value === undefined) {
589
+ return value;
590
+ }
591
+ if (typeof value === "boolean" || typeof value === "number") {
592
+ return value;
593
+ }
594
+ if (typeof value === "string") {
595
+ return maxLength !== null ? truncateString(value, maxLength) : value;
596
+ }
597
+ if (Array.isArray(value)) {
598
+ return value.map((item) => serializeValue(item, maxLength));
599
+ }
600
+ if (typeof value === "object") {
601
+ const result = {};
602
+ for (const [key, val] of Object.entries(value)) {
603
+ result[key] = serializeValue(val, maxLength);
604
+ }
605
+ return result;
606
+ }
607
+ try {
608
+ return String(value);
609
+ } catch {
610
+ return `<${typeof value} object>`;
611
+ }
612
+ }
613
+
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