@voltagent/core 1.2.1 → 1.2.2

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.d.mts CHANGED
@@ -4837,6 +4837,7 @@ declare class Agent {
4837
4837
  * Common preparation for all execution methods
4838
4838
  */
4839
4839
  private prepareExecution;
4840
+ private collectToolDataFromResult;
4840
4841
  /**
4841
4842
  * Create execution context
4842
4843
  */
package/dist/index.d.ts CHANGED
@@ -4837,6 +4837,7 @@ declare class Agent {
4837
4837
  * Common preparation for all execution methods
4838
4838
  */
4839
4839
  private prepareExecution;
4840
+ private collectToolDataFromResult;
4840
4841
  /**
4841
4842
  * Create execution context
4842
4843
  */
package/dist/index.js CHANGED
@@ -8485,14 +8485,60 @@ var bytesToBase64 = /* @__PURE__ */ __name((bytes) => {
8485
8485
  }, "bytesToBase64");
8486
8486
 
8487
8487
  // src/utils/message-converter.ts
8488
+ function findExistingToolPart(parts, toolCallId) {
8489
+ for (let i = parts.length - 1; i >= 0; i--) {
8490
+ const part = parts[i];
8491
+ if (part && typeof part.type === "string" && part.type.startsWith("tool-") && part.toolCallId === toolCallId) {
8492
+ return part;
8493
+ }
8494
+ }
8495
+ return void 0;
8496
+ }
8497
+ __name(findExistingToolPart, "findExistingToolPart");
8488
8498
  function convertModelMessagesToUIMessages(messages) {
8489
8499
  const uiMessages = [];
8500
+ const toolPartsById = /* @__PURE__ */ new Map();
8501
+ const assignToolResult = /* @__PURE__ */ __name((toolCallId, output, providerExecuted, partsToSearch) => {
8502
+ const existing = toolPartsById.get(toolCallId);
8503
+ if (existing) {
8504
+ existing.state = "output-available";
8505
+ existing.output = output;
8506
+ existing.providerExecuted = providerExecuted;
8507
+ return true;
8508
+ }
8509
+ if (partsToSearch) {
8510
+ const fallback = findExistingToolPart(partsToSearch, toolCallId);
8511
+ if (fallback) {
8512
+ fallback.state = "output-available";
8513
+ fallback.output = output;
8514
+ fallback.providerExecuted = providerExecuted;
8515
+ toolPartsById.set(toolCallId, fallback);
8516
+ return true;
8517
+ }
8518
+ }
8519
+ const globalFallback = findExistingToolPart(
8520
+ uiMessages.flatMap((msg) => msg.parts),
8521
+ toolCallId
8522
+ );
8523
+ if (globalFallback) {
8524
+ globalFallback.state = "output-available";
8525
+ globalFallback.output = output;
8526
+ globalFallback.providerExecuted = providerExecuted;
8527
+ toolPartsById.set(toolCallId, globalFallback);
8528
+ return true;
8529
+ }
8530
+ return false;
8531
+ }, "assignToolResult");
8490
8532
  for (const message of messages) {
8491
8533
  if (message.role === "tool") {
8492
8534
  if (Array.isArray(message.content)) {
8493
8535
  for (const part of message.content) {
8494
8536
  if (part.type === "tool-result") {
8495
- uiMessages.push({
8537
+ const merged = assignToolResult(part.toolCallId, part.output, false);
8538
+ if (merged) {
8539
+ continue;
8540
+ }
8541
+ const toolMessage = {
8496
8542
  id: randomUUID(),
8497
8543
  role: "assistant",
8498
8544
  parts: [
@@ -8505,7 +8551,9 @@ function convertModelMessagesToUIMessages(messages) {
8505
8551
  providerExecuted: false
8506
8552
  }
8507
8553
  ]
8508
- });
8554
+ };
8555
+ uiMessages.push(toolMessage);
8556
+ toolPartsById.set(part.toolCallId, toolMessage.parts[0]);
8509
8557
  }
8510
8558
  }
8511
8559
  }
@@ -8552,26 +8600,37 @@ function convertModelMessagesToUIMessages(messages) {
8552
8600
  break;
8553
8601
  }
8554
8602
  case "tool-call": {
8555
- ui.parts.push({
8603
+ const toolPart = {
8556
8604
  type: `tool-${contentPart.toolName}`,
8557
8605
  toolCallId: contentPart.toolCallId,
8558
8606
  state: "input-available",
8559
8607
  input: contentPart.input || {},
8560
8608
  ...contentPart.providerOptions ? { callProviderMetadata: contentPart.providerOptions } : {},
8561
8609
  ...contentPart.providerExecuted != null ? { providerExecuted: contentPart.providerExecuted } : {}
8562
- });
8610
+ };
8611
+ ui.parts.push(toolPart);
8612
+ toolPartsById.set(contentPart.toolCallId, toolPart);
8563
8613
  break;
8564
8614
  }
8565
8615
  case "tool-result": {
8566
- ui.parts.push({
8567
- type: `tool-${contentPart.toolName}`,
8568
- toolCallId: contentPart.toolCallId,
8569
- state: "output-available",
8570
- input: {},
8571
- output: contentPart.output,
8572
- // tool-result in assistant message content indicates provider execution
8573
- providerExecuted: true
8574
- });
8616
+ const merged = assignToolResult(
8617
+ contentPart.toolCallId,
8618
+ contentPart.output,
8619
+ true,
8620
+ ui.parts
8621
+ );
8622
+ if (!merged) {
8623
+ const resultPart = {
8624
+ type: `tool-${contentPart.toolName}`,
8625
+ toolCallId: contentPart.toolCallId,
8626
+ state: "output-available",
8627
+ input: {},
8628
+ output: contentPart.output,
8629
+ providerExecuted: true
8630
+ };
8631
+ ui.parts.push(resultPart);
8632
+ toolPartsById.set(contentPart.toolCallId, resultPart);
8633
+ }
8575
8634
  break;
8576
8635
  }
8577
8636
  case "image": {
@@ -13278,6 +13337,8 @@ async function runOutputGuardrails({
13278
13337
  __name(runOutputGuardrails, "runOutputGuardrails");
13279
13338
 
13280
13339
  // src/agent/memory-persist-queue.ts
13340
+ var AGENT_METADATA_CONTEXT_KEY = Symbol("agentMetadata");
13341
+ var SUBAGENT_TOOL_CALL_METADATA_KEY = Symbol("subAgentToolCallMetadata");
13281
13342
  var MemoryPersistQueue = class {
13282
13343
  constructor(memoryManager, options = {}) {
13283
13344
  this.memoryManager = memoryManager;
@@ -13344,9 +13405,16 @@ var MemoryPersistQueue = class {
13344
13405
  ids: pending.map((msg) => msg.id)
13345
13406
  };
13346
13407
  this.logger?.debug?.("[MemoryPersistQueue] persisting", payload);
13408
+ const agentMetadata = oc.systemContext.get(AGENT_METADATA_CONTEXT_KEY);
13409
+ const shouldApplySubAgentMetadata = Boolean(agentMetadata && oc.parentAgentId);
13410
+ const toolCallMetadata = oc.systemContext.get(SUBAGENT_TOOL_CALL_METADATA_KEY);
13347
13411
  for (const message of pending) {
13348
13412
  try {
13349
- await this.memoryManager.saveMessage(oc, message, oc.userId, oc.conversationId);
13413
+ const messageWithMetadata = this.applySubAgentMetadata(message, {
13414
+ defaultMetadata: shouldApplySubAgentMetadata ? agentMetadata : void 0,
13415
+ toolCallMetadata
13416
+ });
13417
+ await this.memoryManager.saveMessage(oc, messageWithMetadata, oc.userId, oc.conversationId);
13350
13418
  } catch (error) {
13351
13419
  this.logger?.error?.("Failed to save message", {
13352
13420
  conversationId: oc.conversationId,
@@ -13384,6 +13452,53 @@ var MemoryPersistQueue = class {
13384
13452
  getKey(oc) {
13385
13453
  return `${oc.userId ?? "unknown"}:${oc.conversationId ?? "unknown"}`;
13386
13454
  }
13455
+ applySubAgentMetadata(message, opts) {
13456
+ let metadata = typeof message.metadata === "object" && message.metadata !== null ? { ...message.metadata } : void 0;
13457
+ const attachMetadata = /* @__PURE__ */ __name((value) => {
13458
+ if (!value) return;
13459
+ if (!metadata) metadata = {};
13460
+ if (!metadata.subAgentId) {
13461
+ metadata.subAgentId = value.agentId;
13462
+ }
13463
+ if (!metadata.subAgentName) {
13464
+ metadata.subAgentName = value.agentName;
13465
+ }
13466
+ }, "attachMetadata");
13467
+ const partMetadata = opts.toolCallMetadata && this.getMetadataFromMessageParts(message, opts.toolCallMetadata);
13468
+ if (partMetadata) {
13469
+ attachMetadata(partMetadata);
13470
+ }
13471
+ if (!metadata?.subAgentId && opts.defaultMetadata) {
13472
+ attachMetadata(opts.defaultMetadata);
13473
+ }
13474
+ if (!metadata) {
13475
+ return message;
13476
+ }
13477
+ return {
13478
+ ...message,
13479
+ metadata
13480
+ };
13481
+ }
13482
+ getMetadataFromMessageParts(message, toolCallMetadata) {
13483
+ for (const part of message.parts) {
13484
+ const type = part.type;
13485
+ if (!type) continue;
13486
+ if (type === "data-subagent-stream") {
13487
+ const data = part.data;
13488
+ if (data?.subAgentId && data?.subAgentName) {
13489
+ return { agentId: data.subAgentId, agentName: data.subAgentName };
13490
+ }
13491
+ continue;
13492
+ }
13493
+ if (type.startsWith("tool-")) {
13494
+ const toolCallId = part.toolCallId;
13495
+ if (toolCallId && toolCallMetadata.has(toolCallId)) {
13496
+ return toolCallMetadata.get(toolCallId);
13497
+ }
13498
+ }
13499
+ }
13500
+ return void 0;
13501
+ }
13387
13502
  };
13388
13503
 
13389
13504
  // src/agent/message-normalizer.ts
@@ -13498,6 +13613,22 @@ var isWorkingMemoryTool = /* @__PURE__ */ __name((part) => {
13498
13613
  if (!toolName) return false;
13499
13614
  return WORKING_MEMORY_TOOL_NAMES.has(toolName);
13500
13615
  }, "isWorkingMemoryTool");
13616
+ var normalizeToolOutputPayload = /* @__PURE__ */ __name((output) => {
13617
+ if (Array.isArray(output)) {
13618
+ return output.map((item) => normalizeToolOutputPayload(item));
13619
+ }
13620
+ if (!isObject(output)) {
13621
+ return output;
13622
+ }
13623
+ const candidate = output;
13624
+ if ("value" in candidate) {
13625
+ const type = candidate.type;
13626
+ if (typeof type === "string" && type.toLowerCase().includes("json")) {
13627
+ return normalizeToolOutputPayload(candidate.value);
13628
+ }
13629
+ }
13630
+ return output;
13631
+ }, "normalizeToolOutputPayload");
13501
13632
  var normalizeToolPart = /* @__PURE__ */ __name((part) => {
13502
13633
  if (isWorkingMemoryTool(part)) {
13503
13634
  return null;
@@ -13512,7 +13643,9 @@ var normalizeToolPart = /* @__PURE__ */ __name((part) => {
13512
13643
  if (part.toolCallId) normalized.toolCallId = part.toolCallId;
13513
13644
  if (part.state) normalized.state = part.state;
13514
13645
  if (part.input !== void 0) normalized.input = safeClone(part.input);
13515
- if (part.output !== void 0) normalized.output = safeClone(part.output);
13646
+ if (part.output !== void 0) {
13647
+ normalized.output = safeClone(normalizeToolOutputPayload(part.output));
13648
+ }
13516
13649
  if (part.providerExecuted !== void 0) normalized.providerExecuted = part.providerExecuted;
13517
13650
  if (part.isError !== void 0) normalized.isError = part.isError;
13518
13651
  if (part.errorText !== void 0) normalized.errorText = part.errorText;
@@ -14832,6 +14965,7 @@ Context: ${(0, import_utils16.safeStringify)(contextObj, { indentation: 2 })}`;
14832
14965
  subAgentId: targetAgent.id,
14833
14966
  subAgentName: targetAgent.name
14834
14967
  };
14968
+ this.registerToolCallMetadata(parentOperationContext, enrichedPart, targetAgent);
14835
14969
  await fullStreamWriter.write(enrichedPart);
14836
14970
  }
14837
14971
  } catch (error) {
@@ -14889,6 +15023,7 @@ Context: ${(0, import_utils16.safeStringify)(contextObj, { indentation: 2 })}`;
14889
15023
  subAgentId: targetAgent.id,
14890
15024
  subAgentName: targetAgent.name
14891
15025
  };
15026
+ this.registerToolCallMetadata(parentOperationContext, enrichedPart, targetAgent);
14892
15027
  await fullStreamWriter.write(enrichedPart);
14893
15028
  }
14894
15029
  } catch (error) {
@@ -15182,6 +15317,22 @@ Context: ${(0, import_utils16.safeStringify)(contextObj, { indentation: 2 })}`;
15182
15317
  return subAgentData;
15183
15318
  });
15184
15319
  }
15320
+ registerToolCallMetadata(oc, part, agent) {
15321
+ if (!oc || !part?.type || !part.type.startsWith("tool-") || !part.toolCallId) {
15322
+ return;
15323
+ }
15324
+ let metadataMap = oc.systemContext.get(SUBAGENT_TOOL_CALL_METADATA_KEY);
15325
+ if (!metadataMap) {
15326
+ metadataMap = /* @__PURE__ */ new Map();
15327
+ oc.systemContext.set(SUBAGENT_TOOL_CALL_METADATA_KEY, metadataMap);
15328
+ }
15329
+ if (!metadataMap.has(part.toolCallId)) {
15330
+ metadataMap.set(part.toolCallId, {
15331
+ agentId: agent.id,
15332
+ agentName: agent.name
15333
+ });
15334
+ }
15335
+ }
15185
15336
  };
15186
15337
 
15187
15338
  // src/agent/agent.ts
@@ -15432,6 +15583,7 @@ var Agent = class {
15432
15583
  usage: resolvedProviderUsage,
15433
15584
  finishReason: result.finishReason
15434
15585
  });
15586
+ const { toolCalls: aggregatedToolCalls, toolResults: aggregatedToolResults } = this.collectToolDataFromResult(result);
15435
15587
  await persistQueue.flush(buffer, oc);
15436
15588
  const usageInfo = convertUsage(result.usage);
15437
15589
  const finalText = await runOutputGuardrails({
@@ -15473,7 +15625,7 @@ var Agent = class {
15473
15625
  duration: Date.now() - startTime,
15474
15626
  finishReason: result.finishReason,
15475
15627
  usage: result.usage,
15476
- toolCalls: result.toolCalls?.length || 0,
15628
+ toolCalls: aggregatedToolCalls.length,
15477
15629
  text: finalText
15478
15630
  }
15479
15631
  );
@@ -15491,13 +15643,15 @@ var Agent = class {
15491
15643
  metadata: {
15492
15644
  finishReason: result.finishReason,
15493
15645
  usage: result.usage ? JSON.parse((0, import_utils17.safeStringify)(result.usage)) : void 0,
15494
- toolCalls: result.toolCalls
15646
+ toolCalls: aggregatedToolCalls
15495
15647
  }
15496
15648
  });
15497
15649
  oc.traceContext.end("completed");
15498
15650
  return cloneGenerateTextResultWithContext(result, {
15499
15651
  text: finalText,
15500
- context: oc.context
15652
+ context: oc.context,
15653
+ toolCalls: aggregatedToolCalls,
15654
+ toolResults: aggregatedToolResults
15501
15655
  });
15502
15656
  } catch (error) {
15503
15657
  if (isBailError(error)) {
@@ -16464,6 +16618,15 @@ var Agent = class {
16464
16618
  maxSteps
16465
16619
  };
16466
16620
  }
16621
+ collectToolDataFromResult(result) {
16622
+ const steps = result.steps ?? [];
16623
+ const stepToolCalls = steps.flatMap((step) => step.toolCalls ?? []);
16624
+ const stepToolResults = steps.flatMap((step) => step.toolResults ?? []);
16625
+ return {
16626
+ toolCalls: stepToolCalls.length > 0 ? stepToolCalls : result.toolCalls ?? [],
16627
+ toolResults: stepToolResults.length > 0 ? stepToolResults : result.toolResults ?? []
16628
+ };
16629
+ }
16467
16630
  /**
16468
16631
  * Create execution context
16469
16632
  */
@@ -16534,6 +16697,10 @@ var Agent = class {
16534
16697
  QUEUE_CONTEXT_KEY,
16535
16698
  new MemoryPersistQueue(this.memoryManager, { debounceMs: 200, logger })
16536
16699
  );
16700
+ systemContext.set(AGENT_METADATA_CONTEXT_KEY, {
16701
+ agentId: this.id,
16702
+ agentName: this.name
16703
+ });
16537
16704
  const elicitationHandler = options?.elicitation ?? options?.parentOperationContext?.elicitation;
16538
16705
  return {
16539
16706
  operationId,