@visibe.ai/node 0.1.26 → 0.1.27

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.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LangChainCallback = exports.LANGGRAPH_INTERNAL_NODES = exports.activeLangChainStorage = void 0;
4
4
  exports.patchRunnableSequence = patchRunnableSequence;
5
5
  exports.patchAgentExecutor = patchAgentExecutor;
6
+ exports.serializeInput = serializeInput;
6
7
  const node_async_hooks_1 = require("node:async_hooks");
7
8
  const node_crypto_1 = require("node:crypto");
8
9
  const utils_1 = require("../utils");
@@ -79,6 +80,8 @@ class LangChainCallback {
79
80
  this.totalOutputTokens = 0;
80
81
  this.totalCost = 0;
81
82
  this.llmCallCount = 0;
83
+ // First model seen across all LLM calls in this trace — set on first handleLLMEnd.
84
+ this.firstModel = undefined;
82
85
  this.visibe = options.visibe;
83
86
  this.traceId = options.traceId;
84
87
  this.agentName = options.agentName;
@@ -144,6 +147,8 @@ class LangChainCallback {
144
147
  this.totalOutputTokens += outputTokens;
145
148
  this.totalCost += cost;
146
149
  this.llmCallCount++;
150
+ if (!this.firstModel)
151
+ this.firstModel = model;
147
152
  this._onLLMSpan?.(inputTokens, outputTokens, cost);
148
153
  }
149
154
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -250,6 +255,7 @@ function patchRunnableSequence(lcModule, visibe) {
250
255
  name: 'langchain',
251
256
  framework: 'langchain',
252
257
  started_at: startedAt,
258
+ prompt: serializeInput(input),
253
259
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
254
260
  });
255
261
  const cb = new LangChainCallback({ visibe, traceId, agentName: 'langchain' });
@@ -274,6 +280,7 @@ function patchRunnableSequence(lcModule, visibe) {
274
280
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
275
281
  total_input_tokens: cb.totalInputTokens,
276
282
  total_output_tokens: cb.totalOutputTokens,
283
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
277
284
  });
278
285
  }
279
286
  return result;
@@ -292,6 +299,7 @@ function patchRunnableSequence(lcModule, visibe) {
292
299
  name: 'langchain',
293
300
  framework: 'langchain',
294
301
  started_at: startedAt,
302
+ prompt: serializeInput(input),
295
303
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
296
304
  });
297
305
  const cb = new LangChainCallback({ visibe, traceId, agentName: 'langchain' });
@@ -315,6 +323,7 @@ function patchRunnableSequence(lcModule, visibe) {
315
323
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
316
324
  total_input_tokens: cb.totalInputTokens,
317
325
  total_output_tokens: cb.totalOutputTokens,
326
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
318
327
  });
319
328
  }
320
329
  };
@@ -352,6 +361,7 @@ function patchAgentExecutor(agentsModule, visibe) {
352
361
  name: agentName,
353
362
  framework: 'langchain',
354
363
  started_at: startedAt,
364
+ prompt: serializeInput(input),
355
365
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
356
366
  });
357
367
  const cb = new LangChainCallback({ visibe, traceId, agentName });
@@ -376,6 +386,7 @@ function patchAgentExecutor(agentsModule, visibe) {
376
386
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
377
387
  total_input_tokens: cb.totalInputTokens,
378
388
  total_output_tokens: cb.totalOutputTokens,
389
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
379
390
  });
380
391
  }
381
392
  return result;
@@ -395,6 +406,7 @@ function patchAgentExecutor(agentsModule, visibe) {
395
406
  name: agentName,
396
407
  framework: 'langchain',
397
408
  started_at: startedAt,
409
+ prompt: serializeInput(input),
398
410
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
399
411
  });
400
412
  const cb = new LangChainCallback({ visibe, traceId, agentName });
@@ -418,6 +430,7 @@ function patchAgentExecutor(agentsModule, visibe) {
418
430
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
419
431
  total_input_tokens: cb.totalInputTokens,
420
432
  total_output_tokens: cb.totalOutputTokens,
433
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
421
434
  });
422
435
  }
423
436
  };
@@ -436,3 +449,37 @@ function _mergeCallbacks(config, cb) {
436
449
  const existing = Array.isArray(config.callbacks) ? config.callbacks : [];
437
450
  return { ...config, callbacks: [...existing, cb] };
438
451
  }
452
+ // Serialize a graph/chain input to a prompt string for the trace header.
453
+ // Handles strings, common object shapes, and falls back to JSON.
454
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
455
+ function serializeInput(input, limit = 2000) {
456
+ if (!input)
457
+ return undefined;
458
+ let s;
459
+ if (typeof input === 'string') {
460
+ s = input;
461
+ }
462
+ else if (typeof input === 'object') {
463
+ // Try common single-field patterns first.
464
+ for (const key of ['task', 'prompt', 'input', 'query', 'question', 'text', 'content']) {
465
+ if (typeof input[key] === 'string') {
466
+ s = input[key];
467
+ break;
468
+ }
469
+ }
470
+ if (!s) {
471
+ // HumanMessage / messages array — grab the last message content.
472
+ if (Array.isArray(input.messages) && input.messages.length > 0) {
473
+ const last = input.messages[input.messages.length - 1];
474
+ s = typeof last?.content === 'string' ? last.content : JSON.stringify(last?.content ?? '');
475
+ }
476
+ else {
477
+ s = JSON.stringify(input);
478
+ }
479
+ }
480
+ }
481
+ else {
482
+ s = String(input);
483
+ }
484
+ return s.length > limit ? s.slice(0, limit) + '…' : s;
485
+ }
@@ -68,6 +68,7 @@ function patchCompiledStateGraph(lgModule, visibe) {
68
68
  name: graphName,
69
69
  framework: 'langgraph',
70
70
  started_at: startedAt,
71
+ prompt: (0, langchain_1.serializeInput)(input),
71
72
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
72
73
  });
73
74
  // Collect node names from the graph's node registry.
@@ -98,6 +99,7 @@ function patchCompiledStateGraph(lgModule, visibe) {
98
99
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
99
100
  total_input_tokens: cb.totalInputTokens,
100
101
  total_output_tokens: cb.totalOutputTokens,
102
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
101
103
  });
102
104
  }
103
105
  return result;
@@ -119,6 +121,7 @@ function patchCompiledStateGraph(lgModule, visibe) {
119
121
  name: graphName,
120
122
  framework: 'langgraph',
121
123
  started_at: startedAt,
124
+ prompt: (0, langchain_1.serializeInput)(input),
122
125
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
123
126
  });
124
127
  const nodeNames = _extractNodeNames(this);
@@ -150,6 +153,7 @@ function patchCompiledStateGraph(lgModule, visibe) {
150
153
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
151
154
  total_input_tokens: cb.totalInputTokens,
152
155
  total_output_tokens: cb.totalOutputTokens,
156
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
153
157
  });
154
158
  }
155
159
  };
@@ -74,6 +74,8 @@ export class LangChainCallback {
74
74
  this.totalOutputTokens = 0;
75
75
  this.totalCost = 0;
76
76
  this.llmCallCount = 0;
77
+ // First model seen across all LLM calls in this trace — set on first handleLLMEnd.
78
+ this.firstModel = undefined;
77
79
  this.visibe = options.visibe;
78
80
  this.traceId = options.traceId;
79
81
  this.agentName = options.agentName;
@@ -139,6 +141,8 @@ export class LangChainCallback {
139
141
  this.totalOutputTokens += outputTokens;
140
142
  this.totalCost += cost;
141
143
  this.llmCallCount++;
144
+ if (!this.firstModel)
145
+ this.firstModel = model;
142
146
  this._onLLMSpan?.(inputTokens, outputTokens, cost);
143
147
  }
144
148
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -244,6 +248,7 @@ export function patchRunnableSequence(lcModule, visibe) {
244
248
  name: 'langchain',
245
249
  framework: 'langchain',
246
250
  started_at: startedAt,
251
+ prompt: serializeInput(input),
247
252
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
248
253
  });
249
254
  const cb = new LangChainCallback({ visibe, traceId, agentName: 'langchain' });
@@ -268,6 +273,7 @@ export function patchRunnableSequence(lcModule, visibe) {
268
273
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
269
274
  total_input_tokens: cb.totalInputTokens,
270
275
  total_output_tokens: cb.totalOutputTokens,
276
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
271
277
  });
272
278
  }
273
279
  return result;
@@ -286,6 +292,7 @@ export function patchRunnableSequence(lcModule, visibe) {
286
292
  name: 'langchain',
287
293
  framework: 'langchain',
288
294
  started_at: startedAt,
295
+ prompt: serializeInput(input),
289
296
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
290
297
  });
291
298
  const cb = new LangChainCallback({ visibe, traceId, agentName: 'langchain' });
@@ -309,6 +316,7 @@ export function patchRunnableSequence(lcModule, visibe) {
309
316
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
310
317
  total_input_tokens: cb.totalInputTokens,
311
318
  total_output_tokens: cb.totalOutputTokens,
319
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
312
320
  });
313
321
  }
314
322
  };
@@ -346,6 +354,7 @@ export function patchAgentExecutor(agentsModule, visibe) {
346
354
  name: agentName,
347
355
  framework: 'langchain',
348
356
  started_at: startedAt,
357
+ prompt: serializeInput(input),
349
358
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
350
359
  });
351
360
  const cb = new LangChainCallback({ visibe, traceId, agentName });
@@ -370,6 +379,7 @@ export function patchAgentExecutor(agentsModule, visibe) {
370
379
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
371
380
  total_input_tokens: cb.totalInputTokens,
372
381
  total_output_tokens: cb.totalOutputTokens,
382
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
373
383
  });
374
384
  }
375
385
  return result;
@@ -389,6 +399,7 @@ export function patchAgentExecutor(agentsModule, visibe) {
389
399
  name: agentName,
390
400
  framework: 'langchain',
391
401
  started_at: startedAt,
402
+ prompt: serializeInput(input),
392
403
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
393
404
  });
394
405
  const cb = new LangChainCallback({ visibe, traceId, agentName });
@@ -412,6 +423,7 @@ export function patchAgentExecutor(agentsModule, visibe) {
412
423
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
413
424
  total_input_tokens: cb.totalInputTokens,
414
425
  total_output_tokens: cb.totalOutputTokens,
426
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
415
427
  });
416
428
  }
417
429
  };
@@ -430,3 +442,37 @@ function _mergeCallbacks(config, cb) {
430
442
  const existing = Array.isArray(config.callbacks) ? config.callbacks : [];
431
443
  return { ...config, callbacks: [...existing, cb] };
432
444
  }
445
+ // Serialize a graph/chain input to a prompt string for the trace header.
446
+ // Handles strings, common object shapes, and falls back to JSON.
447
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
448
+ export function serializeInput(input, limit = 2000) {
449
+ if (!input)
450
+ return undefined;
451
+ let s;
452
+ if (typeof input === 'string') {
453
+ s = input;
454
+ }
455
+ else if (typeof input === 'object') {
456
+ // Try common single-field patterns first.
457
+ for (const key of ['task', 'prompt', 'input', 'query', 'question', 'text', 'content']) {
458
+ if (typeof input[key] === 'string') {
459
+ s = input[key];
460
+ break;
461
+ }
462
+ }
463
+ if (!s) {
464
+ // HumanMessage / messages array — grab the last message content.
465
+ if (Array.isArray(input.messages) && input.messages.length > 0) {
466
+ const last = input.messages[input.messages.length - 1];
467
+ s = typeof last?.content === 'string' ? last.content : JSON.stringify(last?.content ?? '');
468
+ }
469
+ else {
470
+ s = JSON.stringify(input);
471
+ }
472
+ }
473
+ }
474
+ else {
475
+ s = String(input);
476
+ }
477
+ return s.length > limit ? s.slice(0, limit) + '…' : s;
478
+ }
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { LangChainCallback, activeLangChainStorage, LANGGRAPH_INTERNAL_NODES } from './langchain.js';
2
+ import { LangChainCallback, activeLangChainStorage, LANGGRAPH_INTERNAL_NODES, serializeInput } from './langchain.js';
3
3
  // ---------------------------------------------------------------------------
4
4
  // LangGraphCallback
5
5
  // Extends LangChainCallback and adds node-level agent_start spans.
@@ -63,6 +63,7 @@ export function patchCompiledStateGraph(lgModule, visibe) {
63
63
  name: graphName,
64
64
  framework: 'langgraph',
65
65
  started_at: startedAt,
66
+ prompt: serializeInput(input),
66
67
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
67
68
  });
68
69
  // Collect node names from the graph's node registry.
@@ -93,6 +94,7 @@ export function patchCompiledStateGraph(lgModule, visibe) {
93
94
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
94
95
  total_input_tokens: cb.totalInputTokens,
95
96
  total_output_tokens: cb.totalOutputTokens,
97
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
96
98
  });
97
99
  }
98
100
  return result;
@@ -114,6 +116,7 @@ export function patchCompiledStateGraph(lgModule, visibe) {
114
116
  name: graphName,
115
117
  framework: 'langgraph',
116
118
  started_at: startedAt,
119
+ prompt: serializeInput(input),
117
120
  ...(visibe.sessionId ? { session_id: visibe.sessionId } : {}),
118
121
  });
119
122
  const nodeNames = _extractNodeNames(this);
@@ -145,6 +148,7 @@ export function patchCompiledStateGraph(lgModule, visibe) {
145
148
  total_tokens: cb.totalInputTokens + cb.totalOutputTokens,
146
149
  total_input_tokens: cb.totalInputTokens,
147
150
  total_output_tokens: cb.totalOutputTokens,
151
+ ...(cb.firstModel ? { model: cb.firstModel } : {}),
148
152
  });
149
153
  }
150
154
  };
@@ -30,6 +30,7 @@ export declare class LangChainCallback {
30
30
  totalOutputTokens: number;
31
31
  totalCost: number;
32
32
  llmCallCount: number;
33
+ firstModel: string | undefined;
33
34
  constructor(options: {
34
35
  visibe: Visibe;
35
36
  traceId: string;
@@ -50,3 +51,4 @@ export declare class LangChainCallback {
50
51
  }
51
52
  export declare function patchRunnableSequence(lcModule: any, visibe: Visibe): () => void;
52
53
  export declare function patchAgentExecutor(agentsModule: any, visibe: Visibe): () => void;
54
+ export declare function serializeInput(input: any, limit?: number): string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visibe.ai/node",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "AI Agent Observability — Track OpenAI, LangChain, LangGraph, Bedrock, Vercel AI, Anthropic",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",