@voltagent/core 2.3.1 → 2.3.3

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
@@ -8428,6 +8428,7 @@ declare class Agent {
8428
8428
  private resetOperationAttemptState;
8429
8429
  private getConversationBuffer;
8430
8430
  private getMemoryPersistQueue;
8431
+ private ensureStreamingResponseMessageId;
8431
8432
  private flushPendingMessagesOnError;
8432
8433
  /**
8433
8434
  * Get contextual logger with parent tracking
@@ -8469,6 +8470,7 @@ declare class Agent {
8469
8470
  * Prepare messages with system prompt and memory
8470
8471
  */
8471
8472
  private prepareMessages;
8473
+ private validateIncomingUIMessages;
8472
8474
  /**
8473
8475
  * Get system message with dynamic instructions and retriever context
8474
8476
  */
package/dist/index.d.ts CHANGED
@@ -8428,6 +8428,7 @@ declare class Agent {
8428
8428
  private resetOperationAttemptState;
8429
8429
  private getConversationBuffer;
8430
8430
  private getMemoryPersistQueue;
8431
+ private ensureStreamingResponseMessageId;
8431
8432
  private flushPendingMessagesOnError;
8432
8433
  /**
8433
8434
  * Get contextual logger with parent tracking
@@ -8469,6 +8470,7 @@ declare class Agent {
8469
8470
  * Prepare messages with system prompt and memory
8470
8471
  */
8471
8472
  private prepareMessages;
8473
+ private validateIncomingUIMessages;
8472
8474
  /**
8473
8475
  * Get system message with dynamic instructions and retriever context
8474
8476
  */
package/dist/index.js CHANGED
@@ -12788,6 +12788,34 @@ var bytesToBase64 = /* @__PURE__ */ __name((bytes) => {
12788
12788
  }, "bytesToBase64");
12789
12789
 
12790
12790
  // src/utils/message-converter.ts
12791
+ var hasOpenAIReasoningProviderOptions = /* @__PURE__ */ __name((providerOptions) => {
12792
+ if (!providerOptions || typeof providerOptions !== "object") {
12793
+ return false;
12794
+ }
12795
+ const openai = providerOptions.openai;
12796
+ if (!openai || typeof openai !== "object") {
12797
+ return false;
12798
+ }
12799
+ const itemId = typeof openai.itemId === "string" ? openai.itemId.trim() : "";
12800
+ if (itemId) {
12801
+ return true;
12802
+ }
12803
+ const reasoningTraceId = typeof openai.reasoning_trace_id === "string" ? openai.reasoning_trace_id.trim() : "";
12804
+ if (reasoningTraceId) {
12805
+ return true;
12806
+ }
12807
+ const reasoning = openai.reasoning;
12808
+ if (reasoning && typeof reasoning === "object") {
12809
+ const reasoningId = typeof reasoning.id === "string" ? reasoning.id.trim() : "";
12810
+ if (reasoningId) {
12811
+ return true;
12812
+ }
12813
+ }
12814
+ if (typeof openai.reasoningEncryptedContent === "string" && openai.reasoningEncryptedContent) {
12815
+ return true;
12816
+ }
12817
+ return false;
12818
+ }, "hasOpenAIReasoningProviderOptions");
12791
12819
  function findExistingToolPart(parts, toolCallId) {
12792
12820
  for (let i = parts.length - 1; i >= 0; i--) {
12793
12821
  const part = parts[i];
@@ -12936,10 +12964,13 @@ function convertModelMessagesToUIMessages(messages) {
12936
12964
  break;
12937
12965
  }
12938
12966
  case "reasoning": {
12939
- if (contentPart.text && contentPart.text.length > 0) {
12967
+ const reasoningText = typeof contentPart.text === "string" ? contentPart.text : "";
12968
+ const hasReasoningId = typeof contentPart.id === "string" && contentPart.id.trim().length > 0;
12969
+ const shouldKeep = reasoningText.length > 0 || hasReasoningId || hasOpenAIReasoningProviderOptions(contentPart.providerOptions);
12970
+ if (shouldKeep) {
12940
12971
  ui.parts.push({
12941
12972
  type: "reasoning",
12942
- text: contentPart.text,
12973
+ text: reasoningText,
12943
12974
  ...contentPart.providerOptions ? { providerMetadata: contentPart.providerOptions } : {},
12944
12975
  ...contentPart.id ? { reasoningId: contentPart.id } : {},
12945
12976
  ...contentPart.confidence ? { reasoningConfidence: contentPart.confidence } : {}
@@ -19153,6 +19184,32 @@ var TOOL_ROUTING_CONTEXT_KEY = Symbol("toolRoutingConfig");
19153
19184
  var TOOL_ROUTING_SEARCHED_TOOLS_CONTEXT_KEY = Symbol("toolRoutingSearchedTools");
19154
19185
 
19155
19186
  // src/agent/conversation-buffer.ts
19187
+ var extractOpenAIItemId = /* @__PURE__ */ __name((metadata) => {
19188
+ if (!metadata || typeof metadata !== "object") {
19189
+ return "";
19190
+ }
19191
+ const openai = metadata.openai;
19192
+ if (!openai || typeof openai !== "object") {
19193
+ return "";
19194
+ }
19195
+ const openaiRecord = openai;
19196
+ const itemId = typeof openaiRecord.itemId === "string" ? openaiRecord.itemId.trim() : "";
19197
+ if (itemId) {
19198
+ return itemId;
19199
+ }
19200
+ const traceId = typeof openaiRecord.reasoning_trace_id === "string" ? openaiRecord.reasoning_trace_id.trim() : "";
19201
+ if (traceId) {
19202
+ return traceId;
19203
+ }
19204
+ const reasoning = openaiRecord.reasoning;
19205
+ if (reasoning && typeof reasoning === "object") {
19206
+ const reasoningId = typeof reasoning.id === "string" ? reasoning.id.trim() : "";
19207
+ if (reasoningId) {
19208
+ return reasoningId;
19209
+ }
19210
+ }
19211
+ return "";
19212
+ }, "extractOpenAIItemId");
19156
19213
  var ConversationBuffer = class {
19157
19214
  constructor(initialMessages, logger) {
19158
19215
  this.logger = logger;
@@ -19225,13 +19282,21 @@ var ConversationBuffer = class {
19225
19282
  getAllMessages() {
19226
19283
  return this.messages.map((message) => this.cloneMessage(message));
19227
19284
  }
19228
- addMetadataToLastAssistantMessage(metadata) {
19285
+ addMetadataToLastAssistantMessage(metadata, options) {
19229
19286
  if (!metadata || Object.keys(metadata).length === 0) {
19230
- return;
19287
+ return false;
19231
19288
  }
19232
- const lastAssistantIndex = this.findLastAssistantIndex();
19289
+ let lastAssistantIndex = this.findLastAssistantIndex({
19290
+ pendingOnly: options?.requirePending
19291
+ });
19233
19292
  if (lastAssistantIndex === -1) {
19234
- return;
19293
+ if (options?.requirePending) {
19294
+ return false;
19295
+ }
19296
+ lastAssistantIndex = this.findLastAssistantIndex();
19297
+ }
19298
+ if (lastAssistantIndex === -1) {
19299
+ return false;
19235
19300
  }
19236
19301
  const target = this.messages[lastAssistantIndex];
19237
19302
  const existing = typeof target.metadata === "object" && target.metadata !== null ? target.metadata : {};
@@ -19240,6 +19305,7 @@ var ConversationBuffer = class {
19240
19305
  ...metadata
19241
19306
  };
19242
19307
  this.pendingMessageIds.add(target.id);
19308
+ return true;
19243
19309
  }
19244
19310
  appendExistingMessage(message, options = { markAsSaved: true }) {
19245
19311
  const hydrated = this.cloneMessage(message);
@@ -19380,9 +19446,12 @@ var ConversationBuffer = class {
19380
19446
  }
19381
19447
  }
19382
19448
  }
19383
- findLastAssistantIndex() {
19449
+ findLastAssistantIndex(options) {
19384
19450
  for (let i = this.messages.length - 1; i >= 0; i--) {
19385
19451
  if (this.messages[i].role === "assistant") {
19452
+ if (options?.pendingOnly && !this.pendingMessageIds.has(this.messages[i].id)) {
19453
+ continue;
19454
+ }
19386
19455
  return i;
19387
19456
  }
19388
19457
  }
@@ -19510,8 +19579,12 @@ var ConversationBuffer = class {
19510
19579
  switch (part.type) {
19511
19580
  case "text":
19512
19581
  return `text:${part.text}:${JSON.stringify(part.providerMetadata ?? null)}`;
19513
- case "reasoning":
19514
- return `reasoning:${part.text}`;
19582
+ case "reasoning": {
19583
+ const reasoningText = typeof part.text === "string" ? part.text : "";
19584
+ const reasoningId = typeof part.reasoningId === "string" ? part.reasoningId.trim() : "";
19585
+ const openaiItemId = extractOpenAIItemId(part.providerMetadata);
19586
+ return `reasoning:${reasoningText}:${reasoningId}:${openaiItemId}`;
19587
+ }
19515
19588
  case "step-start":
19516
19589
  return "step-start";
19517
19590
  default: {
@@ -19698,7 +19771,9 @@ var WORKING_MEMORY_TOOL_NAMES = /* @__PURE__ */ new Set([
19698
19771
  "get_working_memory",
19699
19772
  "clear_working_memory"
19700
19773
  ]);
19774
+ var OPENAI_REASONING_ID_PREFIX = "rs_";
19701
19775
  var isObject = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null, "isObject");
19776
+ var isOpenAIReasoningId = /* @__PURE__ */ __name((value) => value.trim().startsWith(OPENAI_REASONING_ID_PREFIX), "isOpenAIReasoningId");
19702
19777
  var safeClone = /* @__PURE__ */ __name((value) => {
19703
19778
  if (!isObject(value) && !Array.isArray(value)) {
19704
19779
  return value;
@@ -19716,6 +19791,13 @@ var safeClone = /* @__PURE__ */ __name((value) => {
19716
19791
  return { ...value };
19717
19792
  }
19718
19793
  }, "safeClone");
19794
+ var compactObject = /* @__PURE__ */ __name((value) => {
19795
+ const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0);
19796
+ if (entries.length === Object.keys(value).length) {
19797
+ return value;
19798
+ }
19799
+ return Object.fromEntries(entries);
19800
+ }, "compactObject");
19719
19801
  var normalizeText = /* @__PURE__ */ __name((part) => {
19720
19802
  const text = typeof part.text === "string" ? part.text : "";
19721
19803
  if (!text.trim()) {
@@ -19743,7 +19825,54 @@ var sanitizeReasoningProviderMetadata = /* @__PURE__ */ __name((providerMetadata
19743
19825
  }
19744
19826
  return cloned;
19745
19827
  }, "sanitizeReasoningProviderMetadata");
19828
+ var extractOpenAIReasoningId = /* @__PURE__ */ __name((metadata) => {
19829
+ const openai = metadata.openai;
19830
+ if (!isObject(openai)) {
19831
+ return void 0;
19832
+ }
19833
+ if (typeof openai.itemId === "string") {
19834
+ const itemId = openai.itemId.trim();
19835
+ if (itemId) {
19836
+ return itemId;
19837
+ }
19838
+ }
19839
+ if (typeof openai.reasoning_trace_id === "string") {
19840
+ const traceId = openai.reasoning_trace_id.trim();
19841
+ if (traceId) {
19842
+ return traceId;
19843
+ }
19844
+ }
19845
+ const reasoning = openai.reasoning;
19846
+ if (isObject(reasoning)) {
19847
+ const reasoningId = typeof reasoning.id === "string" ? reasoning.id.trim() : "";
19848
+ if (reasoningId) {
19849
+ return reasoningId;
19850
+ }
19851
+ }
19852
+ return void 0;
19853
+ }, "extractOpenAIReasoningId");
19854
+ var buildOpenAIReasoningProviderMetadata = /* @__PURE__ */ __name((providerMetadata, reasoningId) => {
19855
+ const openai = providerMetadata && isObject(providerMetadata.openai) ? providerMetadata.openai : void 0;
19856
+ const openaiMeta = isObject(openai) ? openai : void 0;
19857
+ const itemId = typeof openaiMeta?.itemId === "string" ? openaiMeta.itemId.trim() : isOpenAIReasoningId(reasoningId) ? reasoningId : "";
19858
+ const reasoningEncryptedContent = typeof openaiMeta?.reasoningEncryptedContent === "string" ? openaiMeta.reasoningEncryptedContent : void 0;
19859
+ if (!itemId && !reasoningEncryptedContent) {
19860
+ return void 0;
19861
+ }
19862
+ const openaiPayload = {};
19863
+ if (itemId) {
19864
+ openaiPayload.itemId = itemId;
19865
+ }
19866
+ if (reasoningEncryptedContent) {
19867
+ openaiPayload.reasoningEncryptedContent = reasoningEncryptedContent;
19868
+ }
19869
+ return { openai: openaiPayload };
19870
+ }, "buildOpenAIReasoningProviderMetadata");
19746
19871
  var extractReasoningIdFromMetadata = /* @__PURE__ */ __name((metadata) => {
19872
+ const openaiReasoningId = extractOpenAIReasoningId(metadata);
19873
+ if (openaiReasoningId) {
19874
+ return openaiReasoningId;
19875
+ }
19747
19876
  const visit = /* @__PURE__ */ __name((value, hasReasoningContext) => {
19748
19877
  if (Array.isArray(value)) {
19749
19878
  for (const element of value) {
@@ -19789,6 +19918,10 @@ var normalizeReasoning = /* @__PURE__ */ __name((part) => {
19789
19918
  if (reasoningId) {
19790
19919
  normalized.reasoningId = reasoningId;
19791
19920
  }
19921
+ const openaiMetadata = buildOpenAIReasoningProviderMetadata(providerMetadata, reasoningId);
19922
+ if (openaiMetadata) {
19923
+ normalized.providerMetadata = openaiMetadata;
19924
+ }
19792
19925
  if (part.reasoningConfidence !== void 0) {
19793
19926
  normalized.reasoningConfidence = part.reasoningConfidence;
19794
19927
  }
@@ -20036,9 +20169,31 @@ var removeProviderExecutedToolsWithoutReasoning = /* @__PURE__ */ __name((parts)
20036
20169
  (part) => !(typeof part.type === "string" && part.type.startsWith("tool-") && part.providerExecuted === true)
20037
20170
  );
20038
20171
  }, "removeProviderExecutedToolsWithoutReasoning");
20172
+ var hasOpenAIReasoningContext = /* @__PURE__ */ __name((parts) => {
20173
+ for (const part of parts) {
20174
+ if (part.type !== "reasoning") {
20175
+ continue;
20176
+ }
20177
+ const reasoningId = typeof part.reasoningId === "string" ? part.reasoningId.trim() : "";
20178
+ if (reasoningId && isOpenAIReasoningId(reasoningId)) {
20179
+ return true;
20180
+ }
20181
+ const providerMetadata = part.providerMetadata;
20182
+ if (isObject(providerMetadata)) {
20183
+ const openai = providerMetadata.openai;
20184
+ if (isObject(openai)) {
20185
+ const itemId = typeof openai.itemId === "string" ? openai.itemId.trim() : "";
20186
+ if (itemId) {
20187
+ return true;
20188
+ }
20189
+ }
20190
+ }
20191
+ }
20192
+ return false;
20193
+ }, "hasOpenAIReasoningContext");
20039
20194
  var stripReasoningLinkedProviderMetadata = /* @__PURE__ */ __name((parts) => {
20040
- const hasReasoning = parts.some((part) => part.type === "reasoning");
20041
- if (hasReasoning) {
20195
+ const hasOpenAIReasoning = hasOpenAIReasoningContext(parts);
20196
+ if (hasOpenAIReasoning) {
20042
20197
  return parts;
20043
20198
  }
20044
20199
  const stripMetadata = /* @__PURE__ */ __name((metadata) => {
@@ -20047,10 +20202,35 @@ var stripReasoningLinkedProviderMetadata = /* @__PURE__ */ __name((parts) => {
20047
20202
  }
20048
20203
  const cloned = { ...metadata };
20049
20204
  const openaiMetadata = cloned.openai;
20050
- if (!isObject(openaiMetadata) || !("itemId" in openaiMetadata || "reasoning_trace_id" in openaiMetadata || "reasoning" in openaiMetadata && isObject(openaiMetadata.reasoning))) {
20205
+ if (!isObject(openaiMetadata)) {
20206
+ return metadata;
20207
+ }
20208
+ const openaiClone = { ...openaiMetadata };
20209
+ let changed = false;
20210
+ if (typeof openaiClone.itemId === "string") {
20211
+ const itemId = openaiClone.itemId.trim();
20212
+ if (itemId && isOpenAIReasoningId(itemId)) {
20213
+ openaiClone.itemId = void 0;
20214
+ changed = true;
20215
+ }
20216
+ }
20217
+ if (typeof openaiClone.reasoning_trace_id === "string") {
20218
+ openaiClone.reasoning_trace_id = void 0;
20219
+ changed = true;
20220
+ }
20221
+ if ("reasoning" in openaiClone) {
20222
+ openaiClone.reasoning = void 0;
20223
+ changed = true;
20224
+ }
20225
+ if (!changed) {
20051
20226
  return metadata;
20052
20227
  }
20053
- const { openai, ...cleanedMetadata } = cloned;
20228
+ const cleanedOpenai = compactObject(openaiClone);
20229
+ const nextMetadata = {
20230
+ ...cloned,
20231
+ openai: Object.keys(cleanedOpenai).length > 0 ? cleanedOpenai : void 0
20232
+ };
20233
+ const cleanedMetadata = compactObject(nextMetadata);
20054
20234
  return Object.keys(cleanedMetadata).length > 0 ? cleanedMetadata : void 0;
20055
20235
  }, "stripMetadata");
20056
20236
  let mutated = false;
@@ -21838,6 +22018,7 @@ var QUEUE_CONTEXT_KEY = Symbol("memoryPersistQueue");
21838
22018
  var STEP_PERSIST_COUNT_KEY = Symbol("persistedStepCount");
21839
22019
  var ABORT_LISTENER_ATTACHED_KEY = Symbol("abortListenerAttached");
21840
22020
  var MIDDLEWARE_RETRY_FEEDBACK_KEY = Symbol("middlewareRetryFeedback");
22021
+ var STREAM_RESPONSE_MESSAGE_ID_KEY = Symbol("streamResponseMessageId");
21841
22022
  var DEFAULT_FEEDBACK_KEY = "satisfaction";
21842
22023
  var DEFAULT_CONVERSATION_TITLE_PROMPT = [
21843
22024
  "You generate concise titles for new conversations.",
@@ -21848,6 +22029,67 @@ var DEFAULT_CONVERSATION_TITLE_MAX_OUTPUT_TOKENS = 32;
21848
22029
  var DEFAULT_CONVERSATION_TITLE_MAX_CHARS = 80;
21849
22030
  var CONVERSATION_TITLE_INPUT_MAX_CHARS = 2e3;
21850
22031
  var DEFAULT_TOOL_SEARCH_TOP_K = 1;
22032
+ var isRecord2 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null, "isRecord");
22033
+ var hasNonEmptyString = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim().length > 0, "hasNonEmptyString");
22034
+ var isAssistantContentPart = /* @__PURE__ */ __name((value) => {
22035
+ if (!isRecord2(value)) {
22036
+ return false;
22037
+ }
22038
+ switch (value.type) {
22039
+ case "text":
22040
+ case "reasoning":
22041
+ return typeof value.text === "string";
22042
+ case "tool-call":
22043
+ case "tool-result":
22044
+ return hasNonEmptyString(value.toolCallId) && hasNonEmptyString(value.toolName);
22045
+ case "tool-approval-request":
22046
+ return hasNonEmptyString(value.toolCallId) && hasNonEmptyString(value.approvalId);
22047
+ case "image":
22048
+ return "image" in value && value.image != null;
22049
+ case "file":
22050
+ return hasNonEmptyString(value.mediaType) && "data" in value && value.data != null;
22051
+ default:
22052
+ return false;
22053
+ }
22054
+ }, "isAssistantContentPart");
22055
+ var isToolContentPart = /* @__PURE__ */ __name((value) => {
22056
+ if (!isRecord2(value)) {
22057
+ return false;
22058
+ }
22059
+ switch (value.type) {
22060
+ case "tool-result":
22061
+ return hasNonEmptyString(value.toolCallId) && hasNonEmptyString(value.toolName);
22062
+ case "tool-approval-response":
22063
+ return hasNonEmptyString(value.approvalId) && typeof value.approved === "boolean";
22064
+ default:
22065
+ return false;
22066
+ }
22067
+ }, "isToolContentPart");
22068
+ var isResponseMessage = /* @__PURE__ */ __name((value) => {
22069
+ if (!isRecord2(value)) {
22070
+ return false;
22071
+ }
22072
+ if (value.role === "assistant") {
22073
+ if (typeof value.content === "string") {
22074
+ return true;
22075
+ }
22076
+ if (Array.isArray(value.content)) {
22077
+ return value.content.every(isAssistantContentPart);
22078
+ }
22079
+ return false;
22080
+ }
22081
+ if (value.role === "tool") {
22082
+ return Array.isArray(value.content) && value.content.every(isToolContentPart);
22083
+ }
22084
+ return false;
22085
+ }, "isResponseMessage");
22086
+ var filterResponseMessages = /* @__PURE__ */ __name((messages) => {
22087
+ if (!Array.isArray(messages)) {
22088
+ return void 0;
22089
+ }
22090
+ const filtered = messages.filter(isResponseMessage);
22091
+ return filtered.length > 0 ? filtered : void 0;
22092
+ }, "filterResponseMessages");
21851
22093
  var searchToolsParameters = import_zod3.z.object({
21852
22094
  query: import_zod3.z.string().describe("User request or query to search tools for."),
21853
22095
  topK: import_zod3.z.number().int().positive().optional().describe("Maximum number of tools to return.")
@@ -22343,7 +22585,20 @@ var Agent = class {
22343
22585
  feedbackMetadata = await feedbackPromise;
22344
22586
  }
22345
22587
  if (feedbackMetadata) {
22346
- buffer.addMetadataToLastAssistantMessage({ feedback: feedbackMetadata });
22588
+ const metadataApplied = buffer.addMetadataToLastAssistantMessage(
22589
+ { feedback: feedbackMetadata },
22590
+ { requirePending: true }
22591
+ );
22592
+ if (!metadataApplied) {
22593
+ const responseMessages = filterResponseMessages(result.response?.messages);
22594
+ if (responseMessages?.length) {
22595
+ buffer.addModelMessages(responseMessages, "response");
22596
+ buffer.addMetadataToLastAssistantMessage(
22597
+ { feedback: feedbackMetadata },
22598
+ { requirePending: true }
22599
+ );
22600
+ }
22601
+ }
22347
22602
  }
22348
22603
  if (shouldDeferPersist) {
22349
22604
  await persistQueue.flush(buffer, oc);
@@ -22463,6 +22718,7 @@ var Agent = class {
22463
22718
  let feedbackResolved = false;
22464
22719
  let feedbackFinalizeRequested = false;
22465
22720
  let feedbackApplied = false;
22721
+ let latestResponseMessages;
22466
22722
  const resolveFeedbackDeferred = /* @__PURE__ */ __name((value) => {
22467
22723
  if (!feedbackDeferred || feedbackResolved) {
22468
22724
  return;
@@ -22484,7 +22740,17 @@ var Agent = class {
22484
22740
  return;
22485
22741
  }
22486
22742
  feedbackApplied = true;
22487
- buffer.addMetadataToLastAssistantMessage({ feedback: metadata });
22743
+ const metadataApplied = buffer.addMetadataToLastAssistantMessage(
22744
+ { feedback: metadata },
22745
+ { requirePending: true }
22746
+ );
22747
+ if (!metadataApplied && latestResponseMessages?.length) {
22748
+ buffer.addModelMessages(latestResponseMessages, "response");
22749
+ buffer.addMetadataToLastAssistantMessage(
22750
+ { feedback: metadata },
22751
+ { requirePending: true }
22752
+ );
22753
+ }
22488
22754
  if (shouldDeferPersist) {
22489
22755
  void persistQueue.flush(buffer, oc).catch((error) => {
22490
22756
  oc.logger?.debug?.("Failed to persist feedback metadata", { error });
@@ -22612,6 +22878,7 @@ var Agent = class {
22612
22878
  } = options || {};
22613
22879
  const forcedToolChoice = oc.systemContext.get(FORCED_TOOL_CHOICE_CONTEXT_KEY);
22614
22880
  applyForcedToolChoice(aiSDKOptions, forcedToolChoice);
22881
+ const responseMessageId = await this.ensureStreamingResponseMessageId(oc, buffer);
22615
22882
  const guardrailStreamingEnabled = guardrailSet.output.length > 0;
22616
22883
  let guardrailPipeline = null;
22617
22884
  let sanitizedTextPromise;
@@ -22736,6 +23003,7 @@ var Agent = class {
22736
23003
  );
22737
23004
  }, "onError"),
22738
23005
  onFinish: /* @__PURE__ */ __name(async (finalResult) => {
23006
+ latestResponseMessages = filterResponseMessages(finalResult.response?.messages);
22739
23007
  const providerUsage = finalResult.usage ? await Promise.resolve(finalResult.usage) : void 0;
22740
23008
  const usageForFinish = resolveFinishUsage({
22741
23009
  providerMetadata: finalResult.providerMetadata,
@@ -22895,6 +23163,15 @@ var Agent = class {
22895
23163
  );
22896
23164
  }
22897
23165
  const agent = this;
23166
+ const applyResponseMessageId = /* @__PURE__ */ __name((streamOptions) => {
23167
+ if (!responseMessageId) {
23168
+ return streamOptions;
23169
+ }
23170
+ return {
23171
+ ...streamOptions ?? {},
23172
+ generateMessageId: /* @__PURE__ */ __name(() => responseMessageId, "generateMessageId")
23173
+ };
23174
+ }, "applyResponseMessageId");
22898
23175
  const createBaseFullStream = /* @__PURE__ */ __name(() => {
22899
23176
  const wrapWithAbortHandling = /* @__PURE__ */ __name(async function* (baseStream) {
22900
23177
  const iterator = baseStream[Symbol.asyncIterator]();
@@ -23009,10 +23286,11 @@ var Agent = class {
23009
23286
  return guardrailPipeline.createUIStream(streamOptions);
23010
23287
  }, "getGuardrailAwareUIStream");
23011
23288
  const createMergedUIStream = /* @__PURE__ */ __name((streamOptions) => {
23289
+ const resolvedStreamOptions = applyResponseMessageId(streamOptions);
23012
23290
  const mergedStream = (0, import_ai7.createUIMessageStream)({
23013
23291
  execute: /* @__PURE__ */ __name(async ({ writer }) => {
23014
23292
  oc.systemContext.set("uiStreamWriter", writer);
23015
- writer.merge(getGuardrailAwareUIStream(streamOptions));
23293
+ writer.merge(getGuardrailAwareUIStream(resolvedStreamOptions));
23016
23294
  }, "execute"),
23017
23295
  onError: /* @__PURE__ */ __name((error) => String(error), "onError")
23018
23296
  });
@@ -23068,7 +23346,8 @@ var Agent = class {
23068
23346
  });
23069
23347
  }, "attachFeedbackMetadata");
23070
23348
  const toUIMessageStreamSanitized = /* @__PURE__ */ __name((streamOptions) => {
23071
- const baseStream = agent.subAgentManager.hasSubAgents() ? createMergedUIStream(streamOptions) : getGuardrailAwareUIStream(streamOptions);
23349
+ const resolvedStreamOptions = applyResponseMessageId(streamOptions);
23350
+ const baseStream = agent.subAgentManager.hasSubAgents() ? createMergedUIStream(resolvedStreamOptions) : getGuardrailAwareUIStream(resolvedStreamOptions);
23072
23351
  return attachFeedbackMetadata(baseStream);
23073
23352
  }, "toUIMessageStreamSanitized");
23074
23353
  const toUIMessageStreamResponseSanitized = /* @__PURE__ */ __name((options2) => {
@@ -23979,6 +24258,7 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
23979
24258
  oc.systemContext.delete(STEP_PERSIST_COUNT_KEY);
23980
24259
  oc.systemContext.delete("conversationSteps");
23981
24260
  oc.systemContext.delete("bailedResult");
24261
+ oc.systemContext.delete(STREAM_RESPONSE_MESSAGE_ID_KEY);
23982
24262
  oc.conversationSteps = [];
23983
24263
  oc.output = void 0;
23984
24264
  }
@@ -23998,6 +24278,21 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
23998
24278
  }
23999
24279
  return queue;
24000
24280
  }
24281
+ async ensureStreamingResponseMessageId(oc, buffer) {
24282
+ const existing = oc.systemContext.get(STREAM_RESPONSE_MESSAGE_ID_KEY);
24283
+ if (typeof existing === "string" && existing.trim().length > 0) {
24284
+ return existing;
24285
+ }
24286
+ const messageId = (0, import_ai7.generateId)();
24287
+ const placeholder = {
24288
+ id: messageId,
24289
+ role: "assistant",
24290
+ parts: []
24291
+ };
24292
+ buffer.ingestUIMessages([placeholder], false);
24293
+ oc.systemContext.set(STREAM_RESPONSE_MESSAGE_ID_KEY, messageId);
24294
+ return messageId;
24295
+ }
24001
24296
  async flushPendingMessagesOnError(oc) {
24002
24297
  const buffer = this.getConversationBuffer(oc);
24003
24298
  const queue = this.getMemoryPersistQueue(oc);
@@ -24403,8 +24698,9 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24403
24698
  */
24404
24699
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: legacy message preparation pipeline
24405
24700
  async prepareMessages(input, oc, options, buffer) {
24701
+ const resolvedInput = await this.validateIncomingUIMessages(input, oc);
24406
24702
  const messages = [];
24407
- const systemMessage = await this.getSystemMessage(input, oc, options);
24703
+ const systemMessage = await this.getSystemMessage(resolvedInput, oc, options);
24408
24704
  if (systemMessage) {
24409
24705
  const systemMessagesAsUI = (() => {
24410
24706
  if (typeof systemMessage === "string") {
@@ -24449,7 +24745,7 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24449
24745
  const canIUseMemory = options?.userId && options.conversationId;
24450
24746
  if (canIUseMemory) {
24451
24747
  const useSemanticSearch = options?.semanticMemory?.enabled ?? this.hasSemanticSearchSupport();
24452
- const currentQuery = useSemanticSearch ? this.extractUserQuery(input) : void 0;
24748
+ const currentQuery = useSemanticSearch ? this.extractUserQuery(resolvedInput) : void 0;
24453
24749
  const semanticLimit = options?.semanticMemory?.semanticLimit ?? 5;
24454
24750
  const semanticThreshold = options?.semanticMemory?.semanticThreshold ?? 0.7;
24455
24751
  const mergeStrategy = options?.semanticMemory?.mergeStrategy ?? "append";
@@ -24457,7 +24753,7 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24457
24753
  const traceContext = oc.traceContext;
24458
24754
  if (traceContext) {
24459
24755
  const spanInput = {
24460
- query: isSemanticSearch ? currentQuery : input,
24756
+ query: isSemanticSearch ? currentQuery : resolvedInput,
24461
24757
  userId: options?.userId,
24462
24758
  conversationId: options?.conversationId
24463
24759
  };
@@ -24495,7 +24791,7 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24495
24791
  buffer.ingestUIMessages(memMessages, true);
24496
24792
  return memMessages;
24497
24793
  }
24498
- const inputForMemory = typeof input === "string" ? input : Array.isArray(input) && input[0]?.parts ? input : convertModelMessagesToUIMessages(input);
24794
+ const inputForMemory = typeof resolvedInput === "string" ? resolvedInput : Array.isArray(resolvedInput) && resolvedInput[0]?.parts ? resolvedInput : convertModelMessagesToUIMessages(resolvedInput);
24499
24795
  const result = await this.memoryManager.prepareConversationContext(
24500
24796
  oc,
24501
24797
  inputForMemory,
@@ -24520,7 +24816,7 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24520
24816
  messages.push(...memoryResult);
24521
24817
  if (isSemanticSearch && oc.userId && oc.conversationId) {
24522
24818
  try {
24523
- const inputForMemory = typeof input === "string" ? input : Array.isArray(input) && input[0]?.parts ? input : convertModelMessagesToUIMessages(input);
24819
+ const inputForMemory = typeof resolvedInput === "string" ? resolvedInput : Array.isArray(resolvedInput) && resolvedInput[0]?.parts ? resolvedInput : convertModelMessagesToUIMessages(resolvedInput);
24524
24820
  this.memoryManager.queueSaveInput(oc, inputForMemory, oc.userId, oc.conversationId);
24525
24821
  } catch (_e) {
24526
24822
  }
@@ -24533,16 +24829,16 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24533
24829
  }
24534
24830
  }
24535
24831
  }
24536
- if (typeof input === "string") {
24832
+ if (typeof resolvedInput === "string") {
24537
24833
  messages.push({
24538
24834
  id: randomUUID(),
24539
24835
  role: "user",
24540
- parts: [{ type: "text", text: input }]
24836
+ parts: [{ type: "text", text: resolvedInput }]
24541
24837
  });
24542
- } else if (Array.isArray(input)) {
24543
- const first = input[0];
24838
+ } else if (Array.isArray(resolvedInput)) {
24839
+ const first = resolvedInput[0];
24544
24840
  if (first && Array.isArray(first.parts)) {
24545
- const inputMessages = input;
24841
+ const inputMessages = resolvedInput;
24546
24842
  const idsToReplace = new Set(
24547
24843
  inputMessages.map((message) => message.id).filter((id) => typeof id === "string" && id.trim().length > 0)
24548
24844
  );
@@ -24555,7 +24851,7 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24555
24851
  }
24556
24852
  messages.push(...inputMessages);
24557
24853
  } else {
24558
- messages.push(...convertModelMessagesToUIMessages(input));
24854
+ messages.push(...convertModelMessagesToUIMessages(resolvedInput));
24559
24855
  }
24560
24856
  }
24561
24857
  const sanitizedMessages = sanitizeMessagesForModel(messages);
@@ -24575,9 +24871,25 @@ Metadata: ${(0, import_utils28.safeStringify)(metadata)}`;
24575
24871
  agent: this,
24576
24872
  context: oc
24577
24873
  });
24578
- return result?.messages || summarizedMessages;
24874
+ const preparedMessages = result?.messages || summarizedMessages;
24875
+ return await (0, import_ai7.validateUIMessages)({ messages: preparedMessages });
24876
+ }
24877
+ return await (0, import_ai7.validateUIMessages)({ messages: summarizedMessages });
24878
+ }
24879
+ async validateIncomingUIMessages(input, oc) {
24880
+ if (!Array.isArray(input) || input.length === 0) {
24881
+ return input;
24882
+ }
24883
+ const first = input[0];
24884
+ if (!first || !Array.isArray(first.parts)) {
24885
+ return input;
24886
+ }
24887
+ try {
24888
+ return await (0, import_ai7.validateUIMessages)({ messages: input });
24889
+ } catch (error) {
24890
+ oc.logger?.error?.("Invalid UI messages", { error });
24891
+ throw error;
24579
24892
  }
24580
- return summarizedMessages;
24581
24893
  }
24582
24894
  /**
24583
24895
  * Get system message with dynamic instructions and retriever context
@@ -26063,7 +26375,7 @@ ${retrieverContext}`;
26063
26375
  }
26064
26376
  }
26065
26377
  }
26066
- const responseMessages = event.response?.messages;
26378
+ const responseMessages = filterResponseMessages(event.response?.messages);
26067
26379
  if (responseMessages && responseMessages.length > 0) {
26068
26380
  buffer.addModelMessages(responseMessages, "response");
26069
26381
  }