@agent-inspect/langchain 1.1.0 → 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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
2
- import { Redactor, hasActiveContext, getTraceDirFromContext, resolveTraceDir, getCurrentRunId, createRunId, resolveTraceSafetyOptions, createStepId, initializeTraceFile, prepareTraceEventForDisk, writeTraceEvent } from 'agent-inspect';
2
+ import { Redactor, getCurrentCorrelationMetadata, hasActiveContext, getTraceDirFromContext, resolveTraceDir, getCurrentRunId, createRunId, resolveTraceSafetyOptions, createStepId, initializeTraceFile, prepareTraceEventForDisk, writeTraceEvent } from 'agent-inspect';
3
3
 
4
4
  // packages/langchain/src/agent-inspect-callback.ts
5
5
 
@@ -145,6 +145,68 @@ function toPlainMetadata(value) {
145
145
  return {};
146
146
  }
147
147
  }
148
+
149
+ // packages/langchain/src/streaming-metadata.ts
150
+ function createLlmStreamState() {
151
+ return {
152
+ chunkCount: 0,
153
+ streamedCharCount: 0,
154
+ previewChars: "",
155
+ previewTruncated: false
156
+ };
157
+ }
158
+ function recordLlmStreamToken(state, token, now, maxPreviewChars) {
159
+ state.chunkCount += 1;
160
+ if (state.firstChunkAt === void 0) {
161
+ state.firstChunkAt = now;
162
+ }
163
+ state.lastChunkAt = now;
164
+ if (typeof token === "string" && token.length > 0) {
165
+ state.streamedCharCount += token.length;
166
+ if (maxPreviewChars > 0) {
167
+ const remaining = maxPreviewChars - state.previewChars.length;
168
+ if (remaining > 0) {
169
+ const slice = token.slice(0, remaining);
170
+ state.previewChars += slice;
171
+ if (token.length > remaining) {
172
+ state.previewTruncated = true;
173
+ }
174
+ } else {
175
+ state.previewTruncated = true;
176
+ }
177
+ }
178
+ }
179
+ }
180
+ function streamMetadataFromState(state, options) {
181
+ if (!state || state.chunkCount === 0) {
182
+ return void 0;
183
+ }
184
+ const out = {
185
+ stream: true,
186
+ chunkCount: state.chunkCount,
187
+ streamedCharCount: state.streamedCharCount
188
+ };
189
+ if (state.firstChunkAt !== void 0) {
190
+ out.firstChunkAt = state.firstChunkAt;
191
+ }
192
+ if (state.lastChunkAt !== void 0) {
193
+ out.lastChunkAt = state.lastChunkAt;
194
+ }
195
+ if (state.firstChunkAt !== void 0 && state.lastChunkAt !== void 0 && state.lastChunkAt >= state.firstChunkAt) {
196
+ out.streamDurationMs = state.lastChunkAt - state.firstChunkAt;
197
+ }
198
+ if (state.previewTruncated) {
199
+ out.previewTruncated = true;
200
+ }
201
+ if (options.capturePreview && state.previewChars.length > 0) {
202
+ const preview = state.previewChars.length <= options.maxPreviewChars ? state.previewChars : `${state.previewChars.slice(0, options.maxPreviewChars)}\u2026`;
203
+ out.streamPreview = preview;
204
+ if (state.previewChars.length > options.maxPreviewChars) {
205
+ out.previewTruncated = true;
206
+ }
207
+ }
208
+ return out;
209
+ }
148
210
  function kindToStepType(kind) {
149
211
  switch (kind) {
150
212
  case "LLM":
@@ -241,7 +303,28 @@ var LangChainTracePersistence = class {
241
303
  }
242
304
  async onStepEnd(params) {
243
305
  try {
244
- const stepId = this.#lcToStepId.get(params.lcRunId);
306
+ let stepId = this.#lcToStepId.get(params.lcRunId);
307
+ if (!stepId && params.completionAttributes) {
308
+ stepId = createStepId();
309
+ this.#lcToStepId.set(params.lcRunId, stepId);
310
+ const parentId = this.resolveParentId(params.lcParentRunId);
311
+ const startTime = params.endTime - (params.durationMs ?? 0);
312
+ const started = {
313
+ schemaVersion: "0.1",
314
+ event: "step_started",
315
+ timestamp: startTime,
316
+ runId: this.#runId,
317
+ stepId,
318
+ ...parentId ? { parentId } : {},
319
+ name: String(params.completionAttributes.name ?? "llm:llm"),
320
+ type: kindToStepType(
321
+ params.completionAttributes.kind ?? "LLM"
322
+ ),
323
+ startTime,
324
+ metadata: toStepMetadata(params.completionAttributes)
325
+ };
326
+ await this.#write(started);
327
+ }
245
328
  if (!stepId) return;
246
329
  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));
247
330
  const event = {
@@ -376,6 +459,8 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
376
459
  #persistence;
377
460
  #events = [];
378
461
  #starts = /* @__PURE__ */ new Map();
462
+ #streamState = /* @__PURE__ */ new Map();
463
+ #deferredPersistStart = /* @__PURE__ */ new Map();
379
464
  #rootRunId;
380
465
  constructor(options = {}) {
381
466
  super({});
@@ -409,9 +494,71 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
409
494
  clear() {
410
495
  this.#events = [];
411
496
  this.#starts.clear();
497
+ this.#streamState.clear();
498
+ this.#deferredPersistStart.clear();
412
499
  this.#rootRunId = void 0;
413
500
  this.#persistence?.reset();
414
501
  }
502
+ #streamPreviewLimit() {
503
+ if (this.#opts.capture !== "preview") return 0;
504
+ return this.#opts.maxStreamPreviewChars ?? this.#opts.maxPreviewChars ?? 200;
505
+ }
506
+ #attachStreamMetadata(attrs, lcRunId) {
507
+ const meta = streamMetadataFromState(this.#streamState.get(lcRunId), {
508
+ capturePreview: this.#opts.capture === "preview",
509
+ maxPreviewChars: this.#streamPreviewLimit()
510
+ });
511
+ if (meta) {
512
+ Object.assign(attrs, meta);
513
+ }
514
+ }
515
+ #clearStreamState(lcRunId) {
516
+ this.#streamState.delete(lcRunId);
517
+ this.#deferredPersistStart.delete(lcRunId);
518
+ }
519
+ #mergeCorrelation(attrs) {
520
+ if (this.#opts.capture === "none") return;
521
+ try {
522
+ const corr = getCurrentCorrelationMetadata();
523
+ if (!corr) return;
524
+ for (const [key, value] of Object.entries(corr)) {
525
+ if (typeof value === "string" && value.length > 0) {
526
+ attrs[key] = value;
527
+ }
528
+ }
529
+ } catch {
530
+ }
531
+ }
532
+ async #persistLlmStepStart(lcRunId, lcParentRunId, name, kind, startTime, attributes) {
533
+ if (this.#opts.stream && this.#opts.persist) {
534
+ this.#deferredPersistStart.set(lcRunId, {
535
+ lcParentRunId,
536
+ name,
537
+ kind,
538
+ startTime,
539
+ attributes: { ...attributes }
540
+ });
541
+ return;
542
+ }
543
+ await this.#persistStepStart(lcRunId, lcParentRunId, name, kind, attributes, startTime);
544
+ }
545
+ async #flushDeferredPersistStart(lcRunId, completionAttributes) {
546
+ const pending = this.#deferredPersistStart.get(lcRunId);
547
+ if (!pending || !this.#opts.persist) return;
548
+ const merged = {
549
+ ...pending.attributes,
550
+ ...completionAttributes
551
+ };
552
+ await this.#persistStepStart(
553
+ lcRunId,
554
+ pending.lcParentRunId,
555
+ pending.name,
556
+ pending.kind,
557
+ merged,
558
+ pending.startTime
559
+ );
560
+ this.#deferredPersistStart.delete(lcRunId);
561
+ }
415
562
  #ensureRoot(lcRunId, parentRunId) {
416
563
  if (parentRunId) return;
417
564
  if (!this.#rootRunId) this.#rootRunId = lcRunId;
@@ -474,14 +621,15 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
474
621
  attributes: attrs
475
622
  });
476
623
  }
477
- async #persistStepEnd(lcRunId, lcParentRunId, status, endTime, durationMs, errorMessage) {
624
+ async #persistStepEnd(lcRunId, lcParentRunId, status, endTime, durationMs, errorMessage, completionAttributes) {
478
625
  await this.#persistence?.onStepEnd({
479
626
  lcRunId,
480
627
  lcParentRunId,
481
628
  endTime,
482
629
  durationMs,
483
630
  status,
484
- errorMessage
631
+ errorMessage,
632
+ completionAttributes
485
633
  });
486
634
  }
487
635
  async #persistInstant(lcRunId, lcParentRunId, name, kind, attrs, status, errorMessage) {
@@ -587,6 +735,7 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
587
735
  };
588
736
  if (model && this.#opts.capture !== "none") attrs.model = model;
589
737
  this.#mergeMetadata(attrs, metadata);
738
+ this.#mergeCorrelation(attrs);
590
739
  this.#applyPreview(attrs, previews);
591
740
  const ts = Date.now();
592
741
  const stepName = `llm:${model ?? "llm"}`;
@@ -602,7 +751,7 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
602
751
  confidence: "explicit",
603
752
  source: { type: "adapter" }
604
753
  });
605
- await this.#persistStepStart(runId, parentRunId, stepName, "LLM", attrs, ts);
754
+ await this.#persistLlmStepStart(runId, parentRunId, stepName, "LLM", ts, attrs);
606
755
  }
607
756
  async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata, runName) {
608
757
  this.#ensureRoot(runId, parentRunId);
@@ -615,6 +764,7 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
615
764
  };
616
765
  if (model && this.#opts.capture !== "none") attrs.model = model;
617
766
  this.#mergeMetadata(attrs, metadata);
767
+ this.#mergeCorrelation(attrs);
618
768
  this.#applyPreview(attrs, previews);
619
769
  const ts = Date.now();
620
770
  const stepName = `llm:${model ?? "llm"}`;
@@ -630,7 +780,22 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
630
780
  confidence: "explicit",
631
781
  source: { type: "adapter" }
632
782
  });
633
- await this.#persistStepStart(runId, parentRunId, stepName, "LLM", attrs, ts);
783
+ await this.#persistLlmStepStart(runId, parentRunId, stepName, "LLM", ts, attrs);
784
+ }
785
+ handleLLMNewToken(token, _idx, runId, _parentRunId, _tags, _fields) {
786
+ try {
787
+ if (!this.#opts.stream) return;
788
+ let state = this.#streamState.get(runId);
789
+ if (!state) {
790
+ state = createLlmStreamState();
791
+ this.#streamState.set(runId, state);
792
+ }
793
+ recordLlmStreamToken(state, token, Date.now(), this.#streamPreviewLimit());
794
+ } catch (err) {
795
+ if (!this.#opts.silent) {
796
+ console.error("[agent-inspect:langchain]", err);
797
+ }
798
+ }
634
799
  }
635
800
  async handleLLMEnd(output, runId, parentRunId, tags, _extraParams) {
636
801
  this.#ensureRoot(runId, parentRunId);
@@ -645,6 +810,8 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
645
810
  };
646
811
  if (model && this.#opts.capture !== "none") attrs.model = model;
647
812
  if (tokens && this.#opts.capture !== "none") attrs.tokens = tokens;
813
+ this.#attachStreamMetadata(attrs, runId);
814
+ this.#mergeCorrelation(attrs);
648
815
  this.#applyPreview(attrs, previews);
649
816
  const ts = Date.now();
650
817
  this.#pushEvent({
@@ -660,7 +827,13 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
660
827
  confidence: "explicit",
661
828
  source: { type: "adapter" }
662
829
  });
663
- await this.#persistStepEnd(runId, parentRunId, "success", ts, durationMs);
830
+ await this.#flushDeferredPersistStart(runId, attrs);
831
+ await this.#persistStepEnd(runId, parentRunId, "success", ts, durationMs, void 0, {
832
+ ...attrs,
833
+ name: `llm:${model ?? "llm"}`,
834
+ kind: "LLM"
835
+ });
836
+ this.#clearStreamState(runId);
664
837
  }
665
838
  async handleLLMError(err, runId, parentRunId, tags, _extraParams) {
666
839
  this.#ensureRoot(runId, parentRunId);
@@ -672,6 +845,8 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
672
845
  errorName,
673
846
  errorMessage
674
847
  };
848
+ this.#attachStreamMetadata(attrs, runId);
849
+ this.#mergeCorrelation(attrs);
675
850
  const ts = Date.now();
676
851
  this.#pushEvent({
677
852
  eventId: `${runId}:LLM:error`,
@@ -686,7 +861,13 @@ var AgentInspectCallback = class extends BaseCallbackHandler {
686
861
  confidence: "explicit",
687
862
  source: { type: "adapter" }
688
863
  });
689
- await this.#persistStepEnd(runId, parentRunId, "error", ts, durationMs, errorMessage);
864
+ await this.#flushDeferredPersistStart(runId, attrs);
865
+ await this.#persistStepEnd(runId, parentRunId, "error", ts, durationMs, errorMessage, {
866
+ ...attrs,
867
+ name: "llm:error",
868
+ kind: "LLM"
869
+ });
870
+ this.#clearStreamState(runId);
690
871
  }
691
872
  async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName, _toolCallId) {
692
873
  this.#ensureRoot(runId, parentRunId);