@cloudbase/agent-adapter-langgraph 0.0.12 → 0.0.14

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.js CHANGED
@@ -34,7 +34,9 @@ __export(index_exports, {
34
34
  ClientStateAnnotation: () => ClientStateAnnotation,
35
35
  LanggraphAgent: () => LanggraphAgent,
36
36
  TDAISaver: () => TDAISaver,
37
- TDAIStore: () => TDAIStore
37
+ TDAIStore: () => TDAIStore,
38
+ createConsoleLogger: () => import_agent_shared2.createConsoleLogger,
39
+ noopLogger: () => import_agent_shared2.noopLogger
38
40
  });
39
41
  module.exports = __toCommonJS(index_exports);
40
42
 
@@ -91,6 +93,7 @@ function convertJsonSchemaToZodSchema(jsonSchema, required) {
91
93
  }
92
94
 
93
95
  // src/agent.ts
96
+ var import_agent_shared = require("@cloudbase/agent-shared");
94
97
  var ClientPropertiesAnnotation = import_langgraph.Annotation.Root({
95
98
  tools: import_langgraph.Annotation
96
99
  });
@@ -102,6 +105,8 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
102
105
  constructor(agentConfig) {
103
106
  super(agentConfig);
104
107
  this.compiledWorkflow = agentConfig.compiledWorkflow;
108
+ const baseLogger = agentConfig.logger ?? import_agent_shared.noopLogger;
109
+ this.logger = baseLogger.child?.({ component: "langgraph-agent" }) ?? baseLogger;
105
110
  }
106
111
  run(input) {
107
112
  return new import_rxjs.Observable((subscriber) => {
@@ -110,15 +115,48 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
110
115
  }
111
116
  async _run(subscriber, input) {
112
117
  const { messages, runId, threadId } = input;
113
- subscriber.next({
118
+ const logger = this.logger.child?.({ runId, threadId }) ?? this.logger;
119
+ logger.info?.("Run started");
120
+ const runStartedEvent = {
114
121
  type: import_client.EventType.RUN_STARTED,
115
122
  threadId,
116
123
  runId
117
- });
118
- const streamEventInput = input.forwardedProps?.resume ? new import_langgraph.Command({
124
+ };
125
+ logger.trace?.({ aguiEvent: runStartedEvent }, "Emitting AGUI event");
126
+ subscriber.next(runStartedEvent);
127
+ const isResume = !!input.forwardedProps?.resume;
128
+ const lastUserMessage = messages.filter((m) => m.role === "user").pop();
129
+ logger.debug?.(
130
+ {
131
+ isResume,
132
+ messageCount: messages.length,
133
+ toolCount: input.tools?.length ?? 0,
134
+ tools: input.tools?.map((t) => t.name),
135
+ lastUserMessage: typeof lastUserMessage?.content === "string" ? lastUserMessage.content.slice(0, 200) : void 0
136
+ },
137
+ "Preparing stream input"
138
+ );
139
+ logger.trace?.({ messages, tools: input.tools }, "Full input messages");
140
+ const langChainMessages = isResume ? void 0 : aguiMessagesToLangChain(messages);
141
+ if (langChainMessages) {
142
+ logger.trace?.(
143
+ {
144
+ langChainMessages,
145
+ messageCount: langChainMessages.length,
146
+ messageTypes: langChainMessages.map((m) => ({
147
+ type: m.type,
148
+ id: m.id,
149
+ hasToolCalls: "tool_calls" in m && Array.isArray(m.tool_calls) && m.tool_calls.length > 0,
150
+ toolCallId: "tool_call_id" in m ? m.tool_call_id : void 0
151
+ }))
152
+ },
153
+ "Converted LangGraph messages"
154
+ );
155
+ }
156
+ const streamEventInput = isResume ? new import_langgraph.Command({
119
157
  resume: JSON.stringify(input.forwardedProps?.resume?.payload)
120
158
  }) : {
121
- messages: aguiMessagesToLangChain(messages),
159
+ messages: langChainMessages,
122
160
  client: {
123
161
  tools: convertActionsToDynamicStructuredTools(
124
162
  input.tools.map((x) => ({
@@ -135,6 +173,7 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
135
173
  thread_id: threadId
136
174
  }
137
175
  });
176
+ logger.debug?.("Stream created, starting event processing");
138
177
  const chatModelRuns = [];
139
178
  const handledToolCallIds = /* @__PURE__ */ new Set();
140
179
  for (const msg of messages) {
@@ -142,14 +181,32 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
142
181
  handledToolCallIds.add(msg.toolCallId);
143
182
  }
144
183
  }
184
+ if (handledToolCallIds.size > 0) {
185
+ logger.debug?.(
186
+ { count: handledToolCallIds.size },
187
+ "Pre-populated handled tool call IDs from input messages"
188
+ );
189
+ }
145
190
  let interrupt;
146
191
  let currentToolCall = null;
192
+ let eventCount = 0;
193
+ let toolCallCount = 0;
194
+ let textChunkCount = 0;
147
195
  try {
148
196
  for await (const event of stream) {
197
+ eventCount++;
198
+ logger.trace?.(
199
+ { eventType: event.event, eventCount, langGraphEvent: event },
200
+ "Processing stream event"
201
+ );
149
202
  if (event.event.startsWith("ChannelWrite<")) {
150
203
  continue;
151
204
  }
152
205
  if (event.event === "on_chat_model_start") {
206
+ logger.debug?.(
207
+ { chatModelRunId: event.run_id },
208
+ "Chat model started"
209
+ );
153
210
  chatModelRuns.push({ runId: event.run_id });
154
211
  continue;
155
212
  }
@@ -158,8 +215,13 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
158
215
  (run) => run.runId === event.run_id
159
216
  );
160
217
  if (!chatModelRun) {
218
+ logger.warn?.(
219
+ { chatModelRunId: event.run_id },
220
+ "Received message from unknown chat model run"
221
+ );
161
222
  subscriber.next({
162
223
  type: import_client.EventType.RUN_ERROR,
224
+ code: "INTERNAL_ERROR",
163
225
  message: `Received a message from an unknown chat model run. Run Id: ${event.run_id}`
164
226
  });
165
227
  continue;
@@ -167,14 +229,29 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
167
229
  const chunkId = event.data.chunk.id;
168
230
  if (!chatModelRun.messageId) {
169
231
  chatModelRun.messageId = chunkId;
170
- subscriber.next({
232
+ const textStartEvent = {
171
233
  messageId: chunkId,
172
234
  type: import_client.EventType.TEXT_MESSAGE_START,
173
235
  role: "assistant"
174
- });
236
+ };
237
+ logger.debug?.({ messageId: chunkId }, "Text message started");
238
+ logger.trace?.(
239
+ { aguiEvent: textStartEvent },
240
+ "Emitting AGUI event"
241
+ );
242
+ subscriber.next(textStartEvent);
175
243
  } else if (chatModelRun.messageId !== chunkId) {
244
+ logger.warn?.(
245
+ {
246
+ expectedMessageId: chatModelRun.messageId,
247
+ receivedMessageId: chunkId,
248
+ chatModelRunId: event.run_id
249
+ },
250
+ "Received message with unexpected ID"
251
+ );
176
252
  subscriber.next({
177
253
  type: import_client.EventType.RUN_ERROR,
254
+ code: "INTERNAL_ERROR",
178
255
  message: `Received a message of unknown message id from current run. Run Id: ${event.run_id} Message Id from current run: ${chatModelRun.messageId} Message Id from received message: ${chunkId}`
179
256
  });
180
257
  continue;
@@ -187,29 +264,68 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
187
264
  })).forEach((toolCall) => {
188
265
  if (currentToolCall) {
189
266
  if (toolCall.id && currentToolCall.id !== toolCall.id) {
190
- subscriber.next({
267
+ const toolEndEvent = {
191
268
  toolCallId: currentToolCall.id,
192
269
  type: import_client.EventType.TOOL_CALL_END
193
- });
270
+ };
271
+ logger.debug?.(
272
+ {
273
+ toolCallId: currentToolCall.id,
274
+ toolCallName: currentToolCall.name
275
+ },
276
+ "Tool call ended"
277
+ );
278
+ logger.trace?.(
279
+ { aguiEvent: toolEndEvent },
280
+ "Emitting AGUI event"
281
+ );
282
+ subscriber.next(toolEndEvent);
194
283
  if (toolCall.name && toolCall.id) {
195
284
  currentToolCall = toolCall;
196
- subscriber.next({
285
+ toolCallCount++;
286
+ const toolStartEvent = {
197
287
  toolCallId: currentToolCall.id,
198
288
  toolCallName: currentToolCall.name,
199
289
  parentMessageId,
200
290
  type: import_client.EventType.TOOL_CALL_START
201
- });
291
+ };
292
+ logger.debug?.(
293
+ {
294
+ toolCallId: toolCall.id,
295
+ toolCallName: toolCall.name
296
+ },
297
+ "Tool call started"
298
+ );
299
+ logger.trace?.(
300
+ { aguiEvent: toolStartEvent },
301
+ "Emitting AGUI event"
302
+ );
303
+ subscriber.next(toolStartEvent);
202
304
  if (currentToolCall.args) {
203
- subscriber.next({
305
+ const toolArgsEvent = {
204
306
  toolCallId: currentToolCall.id,
205
307
  delta: currentToolCall.args,
206
308
  type: import_client.EventType.TOOL_CALL_ARGS
207
- });
309
+ };
310
+ logger.trace?.(
311
+ { aguiEvent: toolArgsEvent },
312
+ "Emitting AGUI event"
313
+ );
314
+ subscriber.next(toolArgsEvent);
208
315
  if (isValidJson(currentToolCall.args)) {
209
- subscriber.next({
316
+ const toolEndEvent2 = {
210
317
  toolCallId: currentToolCall.id,
211
318
  type: import_client.EventType.TOOL_CALL_END
212
- });
319
+ };
320
+ logger.debug?.(
321
+ { toolCallId: currentToolCall.id },
322
+ "Tool call ended (args complete)"
323
+ );
324
+ logger.trace?.(
325
+ { aguiEvent: toolEndEvent2 },
326
+ "Emitting AGUI event"
327
+ );
328
+ subscriber.next(toolEndEvent2);
213
329
  currentToolCall = null;
214
330
  }
215
331
  }
@@ -217,16 +333,30 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
217
333
  } else {
218
334
  if (toolCall.args) {
219
335
  currentToolCall.args += toolCall.args;
220
- subscriber.next({
336
+ const toolArgsEvent = {
221
337
  toolCallId: currentToolCall.id,
222
338
  delta: toolCall.args,
223
339
  type: import_client.EventType.TOOL_CALL_ARGS
224
- });
340
+ };
341
+ logger.trace?.(
342
+ { aguiEvent: toolArgsEvent },
343
+ "Emitting AGUI event"
344
+ );
345
+ subscriber.next(toolArgsEvent);
225
346
  if (isValidJson(currentToolCall.args)) {
226
- subscriber.next({
347
+ const toolEndEvent = {
227
348
  toolCallId: currentToolCall.id,
228
349
  type: import_client.EventType.TOOL_CALL_END
229
- });
350
+ };
351
+ logger.debug?.(
352
+ { toolCallId: currentToolCall.id },
353
+ "Tool call ended (args complete)"
354
+ );
355
+ logger.trace?.(
356
+ { aguiEvent: toolEndEvent },
357
+ "Emitting AGUI event"
358
+ );
359
+ subscriber.next(toolEndEvent);
230
360
  currentToolCall = null;
231
361
  }
232
362
  }
@@ -234,23 +364,47 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
234
364
  } else {
235
365
  if (toolCall.name && toolCall.id) {
236
366
  currentToolCall = toolCall;
237
- subscriber.next({
367
+ toolCallCount++;
368
+ const toolStartEvent = {
238
369
  toolCallId: toolCall.id,
239
370
  toolCallName: toolCall.name,
240
371
  parentMessageId,
241
372
  type: import_client.EventType.TOOL_CALL_START
242
- });
373
+ };
374
+ logger.debug?.(
375
+ { toolCallId: toolCall.id, toolCallName: toolCall.name },
376
+ "Tool call started"
377
+ );
378
+ logger.trace?.(
379
+ { aguiEvent: toolStartEvent },
380
+ "Emitting AGUI event"
381
+ );
382
+ subscriber.next(toolStartEvent);
243
383
  if (toolCall.args) {
244
- subscriber.next({
384
+ const toolArgsEvent = {
245
385
  toolCallId: toolCall.id,
246
386
  delta: toolCall.args,
247
387
  type: import_client.EventType.TOOL_CALL_ARGS
248
- });
388
+ };
389
+ logger.trace?.(
390
+ { aguiEvent: toolArgsEvent },
391
+ "Emitting AGUI event"
392
+ );
393
+ subscriber.next(toolArgsEvent);
249
394
  if (isValidJson(toolCall.args)) {
250
- subscriber.next({
395
+ const toolEndEvent = {
251
396
  toolCallId: toolCall.id,
252
397
  type: import_client.EventType.TOOL_CALL_END
253
- });
398
+ };
399
+ logger.debug?.(
400
+ { toolCallId: toolCall.id },
401
+ "Tool call ended (args complete)"
402
+ );
403
+ logger.trace?.(
404
+ { aguiEvent: toolEndEvent },
405
+ "Emitting AGUI event"
406
+ );
407
+ subscriber.next(toolEndEvent);
254
408
  currentToolCall = null;
255
409
  }
256
410
  }
@@ -260,11 +414,17 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
260
414
  }
261
415
  const delta = event.data.chunk.content;
262
416
  if (typeof delta === "string" && delta) {
263
- subscriber.next({
417
+ textChunkCount++;
418
+ const textContentEvent = {
264
419
  messageId: chatModelRun.messageId,
265
420
  type: import_client.EventType.TEXT_MESSAGE_CONTENT,
266
421
  delta
267
- });
422
+ };
423
+ logger.trace?.(
424
+ { aguiEvent: textContentEvent },
425
+ "Emitting AGUI event"
426
+ );
427
+ subscriber.next(textContentEvent);
268
428
  }
269
429
  continue;
270
430
  }
@@ -273,16 +433,27 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
273
433
  (run) => run.runId === event.run_id
274
434
  );
275
435
  if (!chatModelRun) {
436
+ logger.warn?.(
437
+ { chatModelRunId: event.run_id },
438
+ "Received on_chat_model_end from unknown run"
439
+ );
276
440
  subscriber.next({
277
441
  type: import_client.EventType.RUN_ERROR,
442
+ code: "INTERNAL_ERROR",
278
443
  message: `Received a on_chat_model_end event from an unknown chat model run. Run Id: ${event.run_id}`
279
444
  });
280
445
  continue;
281
446
  }
282
- subscriber.next({
447
+ const textEndEvent = {
283
448
  type: import_client.EventType.TEXT_MESSAGE_END,
284
449
  messageId: chatModelRun.messageId
285
- });
450
+ };
451
+ logger.debug?.(
452
+ { messageId: chatModelRun.messageId },
453
+ "Text message ended"
454
+ );
455
+ logger.trace?.({ aguiEvent: textEndEvent }, "Emitting AGUI event");
456
+ subscriber.next(textEndEvent);
286
457
  continue;
287
458
  }
288
459
  if (event.event === "on_tool_end") {
@@ -295,57 +466,115 @@ var LanggraphAgent = class extends import_client.AbstractAgent {
295
466
  toolMessage.lc_kwargs.id = toolMessage.id;
296
467
  }
297
468
  }
298
- subscriber.next({
469
+ const toolResultEvent = {
299
470
  toolCallId: toolMessage.tool_call_id,
300
471
  type: import_client.EventType.TOOL_CALL_RESULT,
301
472
  content: typeof toolMessage.content === "string" ? toolMessage.content : JSON.stringify(toolMessage.content),
302
473
  messageId: toolMessage.id
303
- });
474
+ };
475
+ logger.debug?.(
476
+ {
477
+ toolCallId: toolMessage.tool_call_id,
478
+ messageId: toolMessage.id
479
+ },
480
+ "Tool call result received"
481
+ );
482
+ logger.trace?.(
483
+ { aguiEvent: toolResultEvent },
484
+ "Emitting AGUI event"
485
+ );
486
+ subscriber.next(toolResultEvent);
304
487
  handledToolCallIds.add(toolMessage.tool_call_id);
488
+ } else {
489
+ logger.trace?.(
490
+ { toolCallId: toolMessage.tool_call_id },
491
+ "Skipping duplicate tool call result"
492
+ );
305
493
  }
306
494
  }
307
495
  continue;
308
496
  }
309
- if (event.event === "on_chain_stream" && event.data.chunk?.__interrupt__ && Array.isArray(event.data.chunk.__interrupt__) && event.data.chunk.__interrupt__.length > 0) {
310
- const rawInterrupt = event.data.chunk.__interrupt__[0];
311
- interrupt = {
312
- id: rawInterrupt.id,
313
- // TODO: replace with actual reason
314
- reason: "agent requested interrupt",
315
- payload: rawInterrupt.value
316
- };
497
+ if (event.event === "on_chain_stream") {
498
+ const chunk = event.data.chunk;
499
+ if (chunk?.messages && Array.isArray(chunk.messages)) {
500
+ logger.trace?.(
501
+ {
502
+ nodeName: event.name,
503
+ stateMessages: chunk.messages.map((m) => ({
504
+ type: m.type,
505
+ id: m.id,
506
+ contentPreview: typeof m.content === "string" ? m.content.slice(0, 100) : "[non-string content]",
507
+ hasToolCalls: "tool_calls" in m && Array.isArray(m.tool_calls) && m.tool_calls.length > 0,
508
+ toolCallId: "tool_call_id" in m ? m.tool_call_id : void 0
509
+ })),
510
+ messageCount: chunk.messages.length
511
+ },
512
+ "State update with messages"
513
+ );
514
+ }
515
+ if (chunk?.__interrupt__ && Array.isArray(chunk.__interrupt__) && chunk.__interrupt__.length > 0) {
516
+ const rawInterrupt = chunk.__interrupt__[0];
517
+ logger.debug?.(
518
+ { interruptId: rawInterrupt.id },
519
+ "Interrupt received"
520
+ );
521
+ interrupt = {
522
+ id: rawInterrupt.id,
523
+ // TODO: replace with actual reason
524
+ reason: "agent requested interrupt",
525
+ payload: rawInterrupt.value
526
+ };
527
+ }
317
528
  }
318
529
  }
530
+ const stats = { eventCount, toolCallCount, textChunkCount };
319
531
  if (interrupt) {
320
- subscriber.next({
532
+ const runFinishedEvent = {
321
533
  type: import_client.EventType.RUN_FINISHED,
322
534
  threadId,
323
535
  runId,
324
536
  outcome: "interrupt",
325
537
  interrupt
326
- });
538
+ };
539
+ logger.info?.(
540
+ { outcome: "interrupt", interruptId: interrupt.id, ...stats },
541
+ "Run finished with interrupt"
542
+ );
543
+ logger.trace?.({ aguiEvent: runFinishedEvent }, "Emitting AGUI event");
544
+ subscriber.next(runFinishedEvent);
327
545
  } else {
328
- subscriber.next({
546
+ const runFinishedEvent = {
329
547
  type: import_client.EventType.RUN_FINISHED,
330
548
  threadId,
331
549
  runId
332
- });
550
+ };
551
+ logger.info?.({ outcome: "complete", ...stats }, "Run finished");
552
+ logger.trace?.({ aguiEvent: runFinishedEvent }, "Emitting AGUI event");
553
+ subscriber.next(runFinishedEvent);
333
554
  }
334
555
  } catch (error) {
335
- console.error("[LanggraphAgent] Error during stream processing:", error);
556
+ logger.error?.(
557
+ { err: error, eventCount, toolCallCount, textChunkCount },
558
+ "Error during stream processing"
559
+ );
560
+ const errorCode = (0, import_agent_shared.isErrorWithCode)(error) ? error.code : "INTERNAL_ERROR";
561
+ const errorMessage = error instanceof Error ? error.message : String(error);
336
562
  subscriber.next({
337
563
  type: import_client.EventType.RUN_ERROR,
338
- message: error instanceof Error ? error.message : String(error)
564
+ code: errorCode,
565
+ message: errorMessage
339
566
  });
340
567
  }
341
568
  subscriber.complete();
342
569
  }
343
570
  clone() {
344
571
  const workflow = this.compiledWorkflow;
572
+ const logger = this.logger;
345
573
  this.compiledWorkflow = void 0;
346
574
  const cloned = super.clone();
347
575
  this.compiledWorkflow = workflow;
348
576
  cloned.compiledWorkflow = workflow;
577
+ cloned.logger = logger;
349
578
  return cloned;
350
579
  }
351
580
  };
@@ -397,8 +626,7 @@ function aguiMessagesToLangChain(messages) {
397
626
  id: message.id
398
627
  };
399
628
  default:
400
- console.error(`Message role ${message.role} is not implemented`);
401
- throw new Error("message role is not supported.");
629
+ throw new Error(`Message role ${message.role} is not supported.`);
402
630
  }
403
631
  });
404
632
  }
@@ -1086,12 +1314,17 @@ var TDAIStore = class extends import_langgraph3.BaseStore {
1086
1314
  }
1087
1315
  }
1088
1316
  };
1317
+
1318
+ // src/index.ts
1319
+ var import_agent_shared2 = require("@cloudbase/agent-shared");
1089
1320
  // Annotate the CommonJS export names for ESM import in node:
1090
1321
  0 && (module.exports = {
1091
1322
  ClientPropertiesAnnotation,
1092
1323
  ClientStateAnnotation,
1093
1324
  LanggraphAgent,
1094
1325
  TDAISaver,
1095
- TDAIStore
1326
+ TDAIStore,
1327
+ createConsoleLogger,
1328
+ noopLogger
1096
1329
  });
1097
1330
  //# sourceMappingURL=index.js.map