@agent-inspect/langchain 1.0.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -148,6 +148,300 @@ function toPlainMetadata(value) {
148
148
  }
149
149
  }
150
150
 
151
+ // packages/langchain/src/streaming-metadata.ts
152
+ function createLlmStreamState() {
153
+ return {
154
+ chunkCount: 0,
155
+ streamedCharCount: 0,
156
+ previewChars: "",
157
+ previewTruncated: false
158
+ };
159
+ }
160
+ function recordLlmStreamToken(state, token, now, maxPreviewChars) {
161
+ state.chunkCount += 1;
162
+ if (state.firstChunkAt === void 0) {
163
+ state.firstChunkAt = now;
164
+ }
165
+ state.lastChunkAt = now;
166
+ if (typeof token === "string" && token.length > 0) {
167
+ state.streamedCharCount += token.length;
168
+ if (maxPreviewChars > 0) {
169
+ const remaining = maxPreviewChars - state.previewChars.length;
170
+ if (remaining > 0) {
171
+ const slice = token.slice(0, remaining);
172
+ state.previewChars += slice;
173
+ if (token.length > remaining) {
174
+ state.previewTruncated = true;
175
+ }
176
+ } else {
177
+ state.previewTruncated = true;
178
+ }
179
+ }
180
+ }
181
+ }
182
+ function streamMetadataFromState(state, options) {
183
+ if (!state || state.chunkCount === 0) {
184
+ return void 0;
185
+ }
186
+ const out = {
187
+ stream: true,
188
+ chunkCount: state.chunkCount,
189
+ streamedCharCount: state.streamedCharCount
190
+ };
191
+ if (state.firstChunkAt !== void 0) {
192
+ out.firstChunkAt = state.firstChunkAt;
193
+ }
194
+ if (state.lastChunkAt !== void 0) {
195
+ out.lastChunkAt = state.lastChunkAt;
196
+ }
197
+ if (state.firstChunkAt !== void 0 && state.lastChunkAt !== void 0 && state.lastChunkAt >= state.firstChunkAt) {
198
+ out.streamDurationMs = state.lastChunkAt - state.firstChunkAt;
199
+ }
200
+ if (state.previewTruncated) {
201
+ out.previewTruncated = true;
202
+ }
203
+ if (options.capturePreview && state.previewChars.length > 0) {
204
+ const preview = state.previewChars.length <= options.maxPreviewChars ? state.previewChars : `${state.previewChars.slice(0, options.maxPreviewChars)}\u2026`;
205
+ out.streamPreview = preview;
206
+ if (state.previewChars.length > options.maxPreviewChars) {
207
+ out.previewTruncated = true;
208
+ }
209
+ }
210
+ return out;
211
+ }
212
+ function kindToStepType(kind) {
213
+ switch (kind) {
214
+ case "LLM":
215
+ return "llm";
216
+ case "TOOL":
217
+ return "tool";
218
+ case "DECISION":
219
+ return "decision";
220
+ default:
221
+ return "logic";
222
+ }
223
+ }
224
+ function toStepMetadata(attrs) {
225
+ const out = {
226
+ adapter: "langchain",
227
+ confidence: "explicit"
228
+ };
229
+ for (const [k, v] of Object.entries(attrs)) {
230
+ out[k] = v;
231
+ }
232
+ return out;
233
+ }
234
+ var LangChainTracePersistence = class {
235
+ #traceDir;
236
+ #runId;
237
+ #runName;
238
+ #standalone;
239
+ #silent;
240
+ #safety;
241
+ #runStarted = false;
242
+ #runCompleted = false;
243
+ #runStartTime;
244
+ #rootLcRunId;
245
+ #lcToStepId = /* @__PURE__ */ new Map();
246
+ constructor(options = {}) {
247
+ const inContext = agentInspect.hasActiveContext();
248
+ this.#standalone = !inContext;
249
+ this.#silent = options.silent ?? false;
250
+ this.#traceDir = inContext ? agentInspect.getTraceDirFromContext() ?? agentInspect.resolveTraceDir({ dir: options.traceDir }) : agentInspect.resolveTraceDir({ dir: options.traceDir });
251
+ this.#runId = (inContext ? agentInspect.getCurrentRunId() : void 0) ?? options.runId ?? agentInspect.createRunId();
252
+ this.#runName = options.runName ?? "langchain-agent";
253
+ this.#safety = agentInspect.resolveTraceSafetyOptions({
254
+ redact: options.redact ? { rules: options.redact } : true,
255
+ maxPreviewLength: options.maxPreviewChars
256
+ });
257
+ }
258
+ get runId() {
259
+ return this.#runId;
260
+ }
261
+ get traceDir() {
262
+ return this.#traceDir;
263
+ }
264
+ reset() {
265
+ this.#runStarted = false;
266
+ this.#runCompleted = false;
267
+ this.#runStartTime = void 0;
268
+ this.#rootLcRunId = void 0;
269
+ this.#lcToStepId.clear();
270
+ }
271
+ noteRoot(lcRunId, parentRunId) {
272
+ if (!parentRunId && !this.#rootLcRunId) {
273
+ this.#rootLcRunId = lcRunId;
274
+ }
275
+ }
276
+ resolveParentId(lcParentRunId) {
277
+ if (!lcParentRunId) return void 0;
278
+ return this.#lcToStepId.get(lcParentRunId);
279
+ }
280
+ async onStepStart(params) {
281
+ try {
282
+ this.noteRoot(params.lcRunId, params.lcParentRunId);
283
+ if (this.#standalone && !this.#runStarted) {
284
+ await this.#ensureRunStarted(params.startTime, params.attributes);
285
+ }
286
+ const stepId = agentInspect.createStepId();
287
+ this.#lcToStepId.set(params.lcRunId, stepId);
288
+ const parentId = this.resolveParentId(params.lcParentRunId);
289
+ const event = {
290
+ schemaVersion: "0.1",
291
+ event: "step_started",
292
+ timestamp: params.startTime,
293
+ runId: this.#runId,
294
+ stepId,
295
+ ...parentId ? { parentId } : {},
296
+ name: params.name,
297
+ type: kindToStepType(params.kind),
298
+ startTime: params.startTime,
299
+ metadata: toStepMetadata(params.attributes)
300
+ };
301
+ await this.#write(event);
302
+ } catch (err) {
303
+ this.#warn(err);
304
+ }
305
+ }
306
+ async onStepEnd(params) {
307
+ try {
308
+ let stepId = this.#lcToStepId.get(params.lcRunId);
309
+ if (!stepId && params.completionAttributes) {
310
+ stepId = agentInspect.createStepId();
311
+ this.#lcToStepId.set(params.lcRunId, stepId);
312
+ const parentId = this.resolveParentId(params.lcParentRunId);
313
+ const startTime = params.endTime - (params.durationMs ?? 0);
314
+ const started = {
315
+ schemaVersion: "0.1",
316
+ event: "step_started",
317
+ timestamp: startTime,
318
+ runId: this.#runId,
319
+ stepId,
320
+ ...parentId ? { parentId } : {},
321
+ name: String(params.completionAttributes.name ?? "llm:llm"),
322
+ type: kindToStepType(
323
+ params.completionAttributes.kind ?? "LLM"
324
+ ),
325
+ startTime,
326
+ metadata: toStepMetadata(params.completionAttributes)
327
+ };
328
+ await this.#write(started);
329
+ }
330
+ if (!stepId) return;
331
+ const durationMs = typeof params.durationMs === "number" && Number.isFinite(params.durationMs) ? Math.max(0, Math.floor(params.durationMs)) : Math.max(0, params.endTime - (this.#runStartTime ?? params.endTime));
332
+ const event = {
333
+ schemaVersion: "0.1",
334
+ event: "step_completed",
335
+ timestamp: params.endTime,
336
+ runId: this.#runId,
337
+ stepId,
338
+ status: params.status,
339
+ endTime: params.endTime,
340
+ durationMs,
341
+ ...params.status === "error" && params.errorMessage ? { error: { message: params.errorMessage } } : {}
342
+ };
343
+ await this.#write(event);
344
+ if (this.#standalone && !this.#runCompleted && this.#rootLcRunId === params.lcRunId && !params.lcParentRunId) {
345
+ await this.#ensureRunCompleted(
346
+ params.endTime,
347
+ params.status,
348
+ params.errorMessage
349
+ );
350
+ }
351
+ } catch (err) {
352
+ this.#warn(err);
353
+ }
354
+ }
355
+ /** Point-in-time adapter events (e.g. agent action) — writes start + completed pair. */
356
+ async onInstantStep(params) {
357
+ try {
358
+ this.noteRoot(params.lcRunId, params.lcParentRunId);
359
+ if (this.#standalone && !this.#runStarted) {
360
+ await this.#ensureRunStarted(params.timestamp, params.attributes);
361
+ }
362
+ const stepId = agentInspect.createStepId();
363
+ this.#lcToStepId.set(params.lcRunId, stepId);
364
+ const parentId = this.resolveParentId(params.lcParentRunId);
365
+ const started = {
366
+ schemaVersion: "0.1",
367
+ event: "step_started",
368
+ timestamp: params.timestamp,
369
+ runId: this.#runId,
370
+ stepId,
371
+ ...parentId ? { parentId } : {},
372
+ name: params.name,
373
+ type: kindToStepType(params.kind),
374
+ startTime: params.timestamp,
375
+ metadata: toStepMetadata(params.attributes)
376
+ };
377
+ await this.#write(started);
378
+ const completed = {
379
+ schemaVersion: "0.1",
380
+ event: "step_completed",
381
+ timestamp: params.timestamp,
382
+ runId: this.#runId,
383
+ stepId,
384
+ status: params.status,
385
+ endTime: params.timestamp,
386
+ durationMs: 0,
387
+ ...params.status === "error" && params.errorMessage ? { error: { message: params.errorMessage } } : {}
388
+ };
389
+ await this.#write(completed);
390
+ } catch (err) {
391
+ this.#warn(err);
392
+ }
393
+ }
394
+ async #ensureRunStarted(startTime, attrs) {
395
+ if (this.#runStarted) return;
396
+ this.#runStarted = true;
397
+ this.#runStartTime = startTime;
398
+ await agentInspect.initializeTraceFile(this.#runId, this.#traceDir);
399
+ const metadata = {
400
+ adapter: "langchain",
401
+ confidence: "explicit"
402
+ };
403
+ if (attrs.langchainRunId) metadata.langchainRunId = attrs.langchainRunId;
404
+ if (attrs.adapterRunName) metadata.adapterRunName = attrs.adapterRunName;
405
+ const event = {
406
+ schemaVersion: "0.1",
407
+ event: "run_started",
408
+ timestamp: startTime,
409
+ runId: this.#runId,
410
+ name: this.#runName,
411
+ startTime,
412
+ metadata
413
+ };
414
+ await this.#write(event);
415
+ }
416
+ async #ensureRunCompleted(endTime, stepStatus, errorMessage) {
417
+ if (this.#runCompleted || !this.#runStarted) return;
418
+ this.#runCompleted = true;
419
+ const startTime = this.#runStartTime ?? endTime;
420
+ const durationMs = Math.max(0, endTime - startTime);
421
+ const runStatus = stepStatus === "error" ? "error" : "success";
422
+ const event = {
423
+ schemaVersion: "0.1",
424
+ event: "run_completed",
425
+ timestamp: endTime,
426
+ runId: this.#runId,
427
+ status: runStatus,
428
+ endTime,
429
+ durationMs,
430
+ ...runStatus === "error" && errorMessage ? { error: { message: errorMessage } } : {}
431
+ };
432
+ await this.#write(event);
433
+ }
434
+ async #write(event) {
435
+ const safe = agentInspect.prepareTraceEventForDisk(event, this.#safety);
436
+ await agentInspect.writeTraceEvent(safe, this.#traceDir);
437
+ }
438
+ #warn(err) {
439
+ if (!this.#silent) {
440
+ console.error("[agent-inspect:langchain]", err);
441
+ }
442
+ }
443
+ };
444
+
151
445
  // packages/langchain/src/agent-inspect-callback.ts
152
446
  function serializedLabel(s) {
153
447
  if (typeof s.name === "string" && s.name.trim()) return s.name;
@@ -164,8 +458,11 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
164
458
  name = "agent-inspect";
165
459
  #opts;
166
460
  #redactor;
461
+ #persistence;
167
462
  #events = [];
168
463
  #starts = /* @__PURE__ */ new Map();
464
+ #streamState = /* @__PURE__ */ new Map();
465
+ #deferredPersistStart = /* @__PURE__ */ new Map();
169
466
  #rootRunId;
170
467
  constructor(options = {}) {
171
468
  super({});
@@ -173,9 +470,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
173
470
  capture: options.capture ?? "metadata-only",
174
471
  silent: options.silent ?? false,
175
472
  maxPreviewChars: options.maxPreviewChars ?? 200,
473
+ persist: options.persist ?? false,
474
+ runName: options.runName ?? "langchain-agent",
176
475
  ...options
177
476
  };
178
477
  this.#redactor = new agentInspect.Redactor({ rules: this.#opts.redact });
478
+ if (this.#opts.persist) {
479
+ this.#persistence = new LangChainTracePersistence({
480
+ runName: this.#opts.runName,
481
+ traceDir: this.#opts.traceDir,
482
+ runId: this.#opts.runId,
483
+ redact: this.#opts.redact,
484
+ silent: this.#opts.silent,
485
+ maxPreviewChars: this.#opts.maxPreviewChars
486
+ });
487
+ }
179
488
  }
180
489
  getEvents() {
181
490
  return this.#events.map((e) => ({
@@ -187,7 +496,70 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
187
496
  clear() {
188
497
  this.#events = [];
189
498
  this.#starts.clear();
499
+ this.#streamState.clear();
500
+ this.#deferredPersistStart.clear();
190
501
  this.#rootRunId = void 0;
502
+ this.#persistence?.reset();
503
+ }
504
+ #streamPreviewLimit() {
505
+ if (this.#opts.capture !== "preview") return 0;
506
+ return this.#opts.maxStreamPreviewChars ?? this.#opts.maxPreviewChars ?? 200;
507
+ }
508
+ #attachStreamMetadata(attrs, lcRunId) {
509
+ const meta = streamMetadataFromState(this.#streamState.get(lcRunId), {
510
+ capturePreview: this.#opts.capture === "preview",
511
+ maxPreviewChars: this.#streamPreviewLimit()
512
+ });
513
+ if (meta) {
514
+ Object.assign(attrs, meta);
515
+ }
516
+ }
517
+ #clearStreamState(lcRunId) {
518
+ this.#streamState.delete(lcRunId);
519
+ this.#deferredPersistStart.delete(lcRunId);
520
+ }
521
+ #mergeCorrelation(attrs) {
522
+ if (this.#opts.capture === "none") return;
523
+ try {
524
+ const corr = agentInspect.getCurrentCorrelationMetadata();
525
+ if (!corr) return;
526
+ for (const [key, value] of Object.entries(corr)) {
527
+ if (typeof value === "string" && value.length > 0) {
528
+ attrs[key] = value;
529
+ }
530
+ }
531
+ } catch {
532
+ }
533
+ }
534
+ async #persistLlmStepStart(lcRunId, lcParentRunId, name, kind, startTime, attributes) {
535
+ if (this.#opts.stream && this.#opts.persist) {
536
+ this.#deferredPersistStart.set(lcRunId, {
537
+ lcParentRunId,
538
+ name,
539
+ kind,
540
+ startTime,
541
+ attributes: { ...attributes }
542
+ });
543
+ return;
544
+ }
545
+ await this.#persistStepStart(lcRunId, lcParentRunId, name, kind, attributes, startTime);
546
+ }
547
+ async #flushDeferredPersistStart(lcRunId, completionAttributes) {
548
+ const pending = this.#deferredPersistStart.get(lcRunId);
549
+ if (!pending || !this.#opts.persist) return;
550
+ const merged = {
551
+ ...pending.attributes,
552
+ ...completionAttributes
553
+ };
554
+ await this.#persistStepStart(
555
+ lcRunId,
556
+ pending.lcParentRunId,
557
+ pending.name,
558
+ pending.kind,
559
+ merged,
560
+ pending.startTime
561
+ );
562
+ this.#deferredPersistStart.delete(lcRunId);
191
563
  }
192
564
  #ensureRoot(lcRunId, parentRunId) {
193
565
  if (parentRunId) return;
@@ -241,6 +613,39 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
241
613
  }
242
614
  }
243
615
  }
616
+ async #persistStepStart(lcRunId, lcParentRunId, name, kind, attrs, startTime) {
617
+ await this.#persistence?.onStepStart({
618
+ lcRunId,
619
+ lcParentRunId,
620
+ name,
621
+ kind,
622
+ startTime,
623
+ attributes: attrs
624
+ });
625
+ }
626
+ async #persistStepEnd(lcRunId, lcParentRunId, status, endTime, durationMs, errorMessage, completionAttributes) {
627
+ await this.#persistence?.onStepEnd({
628
+ lcRunId,
629
+ lcParentRunId,
630
+ endTime,
631
+ durationMs,
632
+ status,
633
+ errorMessage,
634
+ completionAttributes
635
+ });
636
+ }
637
+ async #persistInstant(lcRunId, lcParentRunId, name, kind, attrs, status, errorMessage) {
638
+ await this.#persistence?.onInstantStep({
639
+ lcRunId,
640
+ lcParentRunId,
641
+ name,
642
+ kind,
643
+ timestamp: Date.now(),
644
+ attributes: attrs,
645
+ status,
646
+ errorMessage
647
+ });
648
+ }
244
649
  async handleChainStart(chain, inputs, runId, runType, tags, metadata, runName, parentRunId, _extra) {
245
650
  this.#ensureRoot(runId, parentRunId);
246
651
  this.#rememberStart(runId, "CHAIN");
@@ -252,18 +657,20 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
252
657
  };
253
658
  this.#mergeMetadata(attrs, metadata);
254
659
  this.#applyPreview(attrs, previews);
660
+ const ts = Date.now();
255
661
  this.#pushEvent({
256
662
  eventId: `${runId}:CHAIN:start`,
257
663
  runId: this.#traceRunId(runId),
258
664
  parentId: parentRunId,
259
665
  name: `chain:${runName ?? label}`,
260
666
  kind: "CHAIN",
261
- timestamp: Date.now(),
667
+ timestamp: ts,
262
668
  status: "running",
263
669
  attributes: attrs,
264
670
  confidence: "explicit",
265
671
  source: { type: "adapter" }
266
672
  });
673
+ await this.#persistStepStart(runId, parentRunId, `chain:${runName ?? label}`, "CHAIN", attrs, ts);
267
674
  }
268
675
  async handleChainEnd(outputs, runId, parentRunId, tags, _kwargs) {
269
676
  this.#ensureRoot(runId, parentRunId);
@@ -275,19 +682,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
275
682
  ...this.#baseAttrs(runId, parentRunId, tags, void 0)
276
683
  };
277
684
  this.#applyPreview(attrs, previews);
685
+ const ts = Date.now();
278
686
  this.#pushEvent({
279
687
  eventId: `${runId}:CHAIN:end`,
280
688
  runId: this.#traceRunId(runId),
281
689
  parentId: parentRunId,
282
690
  name: "chain:end",
283
691
  kind: "CHAIN",
284
- timestamp: Date.now(),
692
+ timestamp: ts,
285
693
  status: "ok",
286
694
  durationMs,
287
695
  attributes: attrs,
288
696
  confidence: "explicit",
289
697
  source: { type: "adapter" }
290
698
  });
699
+ await this.#persistStepEnd(runId, parentRunId, "success", ts, durationMs);
291
700
  }
292
701
  async handleChainError(err, runId, parentRunId, tags, _kwargs) {
293
702
  this.#ensureRoot(runId, parentRunId);
@@ -299,19 +708,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
299
708
  errorName,
300
709
  errorMessage
301
710
  };
711
+ const ts = Date.now();
302
712
  this.#pushEvent({
303
713
  eventId: `${runId}:CHAIN:error`,
304
714
  runId: this.#traceRunId(runId),
305
715
  parentId: parentRunId,
306
716
  name: "chain:error",
307
717
  kind: "CHAIN",
308
- timestamp: Date.now(),
718
+ timestamp: ts,
309
719
  status: "error",
310
720
  durationMs,
311
721
  attributes: attrs,
312
722
  confidence: "explicit",
313
723
  source: { type: "adapter" }
314
724
  });
725
+ await this.#persistStepEnd(runId, parentRunId, "error", ts, durationMs, errorMessage);
315
726
  }
316
727
  async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata, runName) {
317
728
  this.#ensureRoot(runId, parentRunId);
@@ -326,19 +737,23 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
326
737
  };
327
738
  if (model && this.#opts.capture !== "none") attrs.model = model;
328
739
  this.#mergeMetadata(attrs, metadata);
740
+ this.#mergeCorrelation(attrs);
329
741
  this.#applyPreview(attrs, previews);
742
+ const ts = Date.now();
743
+ const stepName = `llm:${model ?? "llm"}`;
330
744
  this.#pushEvent({
331
745
  eventId: `${runId}:LLM:start`,
332
746
  runId: this.#traceRunId(runId),
333
747
  parentId: parentRunId,
334
- name: `llm:${model ?? "llm"}`,
748
+ name: stepName,
335
749
  kind: "LLM",
336
- timestamp: Date.now(),
750
+ timestamp: ts,
337
751
  status: "running",
338
752
  attributes: attrs,
339
753
  confidence: "explicit",
340
754
  source: { type: "adapter" }
341
755
  });
756
+ await this.#persistLlmStepStart(runId, parentRunId, stepName, "LLM", ts, attrs);
342
757
  }
343
758
  async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata, runName) {
344
759
  this.#ensureRoot(runId, parentRunId);
@@ -351,19 +766,38 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
351
766
  };
352
767
  if (model && this.#opts.capture !== "none") attrs.model = model;
353
768
  this.#mergeMetadata(attrs, metadata);
769
+ this.#mergeCorrelation(attrs);
354
770
  this.#applyPreview(attrs, previews);
771
+ const ts = Date.now();
772
+ const stepName = `llm:${model ?? "llm"}`;
355
773
  this.#pushEvent({
356
774
  eventId: `${runId}:CHAT:start`,
357
775
  runId: this.#traceRunId(runId),
358
776
  parentId: parentRunId,
359
- name: `llm:${model ?? "llm"}`,
777
+ name: stepName,
360
778
  kind: "LLM",
361
- timestamp: Date.now(),
779
+ timestamp: ts,
362
780
  status: "running",
363
781
  attributes: attrs,
364
782
  confidence: "explicit",
365
783
  source: { type: "adapter" }
366
784
  });
785
+ await this.#persistLlmStepStart(runId, parentRunId, stepName, "LLM", ts, attrs);
786
+ }
787
+ handleLLMNewToken(token, _idx, runId, _parentRunId, _tags, _fields) {
788
+ try {
789
+ if (!this.#opts.stream) return;
790
+ let state = this.#streamState.get(runId);
791
+ if (!state) {
792
+ state = createLlmStreamState();
793
+ this.#streamState.set(runId, state);
794
+ }
795
+ recordLlmStreamToken(state, token, Date.now(), this.#streamPreviewLimit());
796
+ } catch (err) {
797
+ if (!this.#opts.silent) {
798
+ console.error("[agent-inspect:langchain]", err);
799
+ }
800
+ }
367
801
  }
368
802
  async handleLLMEnd(output, runId, parentRunId, tags, _extraParams) {
369
803
  this.#ensureRoot(runId, parentRunId);
@@ -378,20 +812,30 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
378
812
  };
379
813
  if (model && this.#opts.capture !== "none") attrs.model = model;
380
814
  if (tokens && this.#opts.capture !== "none") attrs.tokens = tokens;
815
+ this.#attachStreamMetadata(attrs, runId);
816
+ this.#mergeCorrelation(attrs);
381
817
  this.#applyPreview(attrs, previews);
818
+ const ts = Date.now();
382
819
  this.#pushEvent({
383
820
  eventId: `${runId}:LLM:end`,
384
821
  runId: this.#traceRunId(runId),
385
822
  parentId: parentRunId,
386
823
  name: `llm:${model ?? "llm"}`,
387
824
  kind: "LLM",
388
- timestamp: Date.now(),
825
+ timestamp: ts,
389
826
  status: "ok",
390
827
  durationMs,
391
828
  attributes: attrs,
392
829
  confidence: "explicit",
393
830
  source: { type: "adapter" }
394
831
  });
832
+ await this.#flushDeferredPersistStart(runId, attrs);
833
+ await this.#persistStepEnd(runId, parentRunId, "success", ts, durationMs, void 0, {
834
+ ...attrs,
835
+ name: `llm:${model ?? "llm"}`,
836
+ kind: "LLM"
837
+ });
838
+ this.#clearStreamState(runId);
395
839
  }
396
840
  async handleLLMError(err, runId, parentRunId, tags, _extraParams) {
397
841
  this.#ensureRoot(runId, parentRunId);
@@ -403,19 +847,29 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
403
847
  errorName,
404
848
  errorMessage
405
849
  };
850
+ this.#attachStreamMetadata(attrs, runId);
851
+ this.#mergeCorrelation(attrs);
852
+ const ts = Date.now();
406
853
  this.#pushEvent({
407
854
  eventId: `${runId}:LLM:error`,
408
855
  runId: this.#traceRunId(runId),
409
856
  parentId: parentRunId,
410
857
  name: "llm:error",
411
858
  kind: "LLM",
412
- timestamp: Date.now(),
859
+ timestamp: ts,
413
860
  status: "error",
414
861
  durationMs,
415
862
  attributes: attrs,
416
863
  confidence: "explicit",
417
864
  source: { type: "adapter" }
418
865
  });
866
+ await this.#flushDeferredPersistStart(runId, attrs);
867
+ await this.#persistStepEnd(runId, parentRunId, "error", ts, durationMs, errorMessage, {
868
+ ...attrs,
869
+ name: "llm:error",
870
+ kind: "LLM"
871
+ });
872
+ this.#clearStreamState(runId);
419
873
  }
420
874
  async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName, _toolCallId) {
421
875
  this.#ensureRoot(runId, parentRunId);
@@ -429,18 +883,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
429
883
  };
430
884
  this.#mergeMetadata(attrs, metadata);
431
885
  this.#applyPreview(attrs, previews);
886
+ const ts = Date.now();
887
+ const stepName = `tool:${toolName}`;
432
888
  this.#pushEvent({
433
889
  eventId: `${runId}:TOOL:start`,
434
890
  runId: this.#traceRunId(runId),
435
891
  parentId: parentRunId,
436
- name: `tool:${toolName}`,
892
+ name: stepName,
437
893
  kind: "TOOL",
438
- timestamp: Date.now(),
894
+ timestamp: ts,
439
895
  status: "running",
440
896
  attributes: attrs,
441
897
  confidence: "explicit",
442
898
  source: { type: "adapter" }
443
899
  });
900
+ await this.#persistStepStart(runId, parentRunId, stepName, "TOOL", attrs, ts);
444
901
  }
445
902
  async handleToolEnd(output, runId, parentRunId, tags) {
446
903
  this.#ensureRoot(runId, parentRunId);
@@ -452,19 +909,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
452
909
  ...this.#baseAttrs(runId, parentRunId, tags, void 0)
453
910
  };
454
911
  this.#applyPreview(attrs, previews);
912
+ const ts = Date.now();
455
913
  this.#pushEvent({
456
914
  eventId: `${runId}:TOOL:end`,
457
915
  runId: this.#traceRunId(runId),
458
916
  parentId: parentRunId,
459
917
  name: "tool:end",
460
918
  kind: "TOOL",
461
- timestamp: Date.now(),
919
+ timestamp: ts,
462
920
  status: "ok",
463
921
  durationMs,
464
922
  attributes: attrs,
465
923
  confidence: "explicit",
466
924
  source: { type: "adapter" }
467
925
  });
926
+ await this.#persistStepEnd(runId, parentRunId, "success", ts, durationMs);
468
927
  }
469
928
  async handleToolError(err, runId, parentRunId, tags) {
470
929
  this.#ensureRoot(runId, parentRunId);
@@ -476,19 +935,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
476
935
  errorName,
477
936
  errorMessage
478
937
  };
938
+ const ts = Date.now();
479
939
  this.#pushEvent({
480
940
  eventId: `${runId}:TOOL:error`,
481
941
  runId: this.#traceRunId(runId),
482
942
  parentId: parentRunId,
483
943
  name: "tool:error",
484
944
  kind: "TOOL",
485
- timestamp: Date.now(),
945
+ timestamp: ts,
486
946
  status: "error",
487
947
  durationMs,
488
948
  attributes: attrs,
489
949
  confidence: "explicit",
490
950
  source: { type: "adapter" }
491
951
  });
952
+ await this.#persistStepEnd(runId, parentRunId, "error", ts, durationMs, errorMessage);
492
953
  }
493
954
  async handleRetrieverStart(retriever, _query, runId, parentRunId, tags, metadata, name) {
494
955
  this.#ensureRoot(runId, parentRunId);
@@ -499,18 +960,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
499
960
  retriever: rname
500
961
  };
501
962
  this.#mergeMetadata(attrs, metadata);
963
+ const ts = Date.now();
964
+ const stepName = `retriever:${rname}`;
502
965
  this.#pushEvent({
503
966
  eventId: `${runId}:RETRIEVER:start`,
504
967
  runId: this.#traceRunId(runId),
505
968
  parentId: parentRunId,
506
- name: `retriever:${rname}`,
969
+ name: stepName,
507
970
  kind: "RETRIEVER",
508
- timestamp: Date.now(),
971
+ timestamp: ts,
509
972
  status: "running",
510
973
  attributes: attrs,
511
974
  confidence: "explicit",
512
975
  source: { type: "adapter" }
513
976
  });
977
+ await this.#persistStepStart(runId, parentRunId, stepName, "RETRIEVER", attrs, ts);
514
978
  }
515
979
  async handleRetrieverEnd(documents, runId, parentRunId, tags) {
516
980
  this.#ensureRoot(runId, parentRunId);
@@ -525,19 +989,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
525
989
  documentCount: documents.length
526
990
  };
527
991
  this.#applyPreview(attrs, previews);
992
+ const ts = Date.now();
528
993
  this.#pushEvent({
529
994
  eventId: `${runId}:RETRIEVER:end`,
530
995
  runId: this.#traceRunId(runId),
531
996
  parentId: parentRunId,
532
997
  name: "retriever:end",
533
998
  kind: "RETRIEVER",
534
- timestamp: Date.now(),
999
+ timestamp: ts,
535
1000
  status: "ok",
536
1001
  durationMs,
537
1002
  attributes: attrs,
538
1003
  confidence: "explicit",
539
1004
  source: { type: "adapter" }
540
1005
  });
1006
+ await this.#persistStepEnd(runId, parentRunId, "success", ts, durationMs);
541
1007
  }
542
1008
  async handleRetrieverError(err, runId, parentRunId, tags) {
543
1009
  this.#ensureRoot(runId, parentRunId);
@@ -549,19 +1015,21 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
549
1015
  errorName,
550
1016
  errorMessage
551
1017
  };
1018
+ const ts = Date.now();
552
1019
  this.#pushEvent({
553
1020
  eventId: `${runId}:RETRIEVER:error`,
554
1021
  runId: this.#traceRunId(runId),
555
1022
  parentId: parentRunId,
556
1023
  name: "retriever:error",
557
1024
  kind: "RETRIEVER",
558
- timestamp: Date.now(),
1025
+ timestamp: ts,
559
1026
  status: "error",
560
1027
  durationMs,
561
1028
  attributes: attrs,
562
1029
  confidence: "explicit",
563
1030
  source: { type: "adapter" }
564
1031
  });
1032
+ await this.#persistStepEnd(runId, parentRunId, "error", ts, durationMs, errorMessage);
565
1033
  }
566
1034
  async handleAgentAction(action, runId, parentRunId, tags) {
567
1035
  this.#ensureRoot(runId, parentRunId);
@@ -587,6 +1055,7 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
587
1055
  confidence: "explicit",
588
1056
  source: { type: "adapter" }
589
1057
  });
1058
+ await this.#persistInstant(runId, parentRunId, "agent:action", "DECISION", attrs, "success");
590
1059
  }
591
1060
  async handleAgentEnd(finish, runId, parentRunId, tags) {
592
1061
  this.#ensureRoot(runId, parentRunId);
@@ -611,6 +1080,7 @@ var AgentInspectCallback = class extends base.BaseCallbackHandler {
611
1080
  confidence: "explicit",
612
1081
  source: { type: "adapter" }
613
1082
  });
1083
+ await this.#persistInstant(runId, parentRunId, "agent:end", "AGENT", attrs, "success");
614
1084
  }
615
1085
  };
616
1086