@voltagent/core 2.6.6 → 2.6.8

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
@@ -8404,6 +8404,11 @@ interface CommonRuntimeMemoryBehaviorOptions {
8404
8404
  contextLimit?: number;
8405
8405
  semanticMemory?: CommonSemanticMemoryOptions;
8406
8406
  conversationPersistence?: AgentConversationPersistenceOptions;
8407
+ /**
8408
+ * When true, memory is read-only for the current call.
8409
+ * Existing memory context can be loaded, but no writes are persisted.
8410
+ */
8411
+ readOnly?: boolean;
8407
8412
  }
8408
8413
  interface CommonRuntimeMemoryEnvelope {
8409
8414
  conversationId?: string;
@@ -8418,6 +8423,7 @@ interface CommonResolvedRuntimeMemoryOptions {
8418
8423
  contextLimit?: number;
8419
8424
  semanticMemory?: CommonSemanticMemoryOptions;
8420
8425
  conversationPersistence?: AgentConversationPersistenceOptions;
8426
+ readOnly?: boolean;
8421
8427
  }
8422
8428
  /**
8423
8429
  * Agent status information
@@ -9039,7 +9045,9 @@ declare class MemoryManager {
9039
9045
  * Ensures context is always loaded, optimizes non-critical operations in background
9040
9046
  * PRESERVED FROM ORIGINAL
9041
9047
  */
9042
- prepareConversationContext(context: OperationContext, input: string | UIMessage[], userId?: string, conversationIdParam?: string, contextLimit?: number): Promise<{
9048
+ prepareConversationContext(context: OperationContext, input: string | UIMessage[], userId?: string, conversationIdParam?: string, contextLimit?: number, options?: {
9049
+ persistInput?: boolean;
9050
+ }): Promise<{
9043
9051
  messages: UIMessage<{
9044
9052
  createdAt: Date;
9045
9053
  }>[];
@@ -9361,6 +9369,7 @@ declare class Agent {
9361
9369
  */
9362
9370
  private prepareExecution;
9363
9371
  private collectToolDataFromResult;
9372
+ private ensureStructuredOutputGenerated;
9364
9373
  /**
9365
9374
  * Create execution context
9366
9375
  */
@@ -9376,6 +9385,8 @@ declare class Agent {
9376
9385
  private resetOperationAttemptState;
9377
9386
  private getConversationBuffer;
9378
9387
  private getMemoryPersistQueue;
9388
+ private isReadOnlyMemoryForContext;
9389
+ private shouldPersistMemoryForContext;
9379
9390
  private ensureStreamingResponseMessageId;
9380
9391
  private getOrCreateStepResponseMessageId;
9381
9392
  private getStepResponseMessageFingerprints;
package/dist/index.d.ts CHANGED
@@ -8404,6 +8404,11 @@ interface CommonRuntimeMemoryBehaviorOptions {
8404
8404
  contextLimit?: number;
8405
8405
  semanticMemory?: CommonSemanticMemoryOptions;
8406
8406
  conversationPersistence?: AgentConversationPersistenceOptions;
8407
+ /**
8408
+ * When true, memory is read-only for the current call.
8409
+ * Existing memory context can be loaded, but no writes are persisted.
8410
+ */
8411
+ readOnly?: boolean;
8407
8412
  }
8408
8413
  interface CommonRuntimeMemoryEnvelope {
8409
8414
  conversationId?: string;
@@ -8418,6 +8423,7 @@ interface CommonResolvedRuntimeMemoryOptions {
8418
8423
  contextLimit?: number;
8419
8424
  semanticMemory?: CommonSemanticMemoryOptions;
8420
8425
  conversationPersistence?: AgentConversationPersistenceOptions;
8426
+ readOnly?: boolean;
8421
8427
  }
8422
8428
  /**
8423
8429
  * Agent status information
@@ -9039,7 +9045,9 @@ declare class MemoryManager {
9039
9045
  * Ensures context is always loaded, optimizes non-critical operations in background
9040
9046
  * PRESERVED FROM ORIGINAL
9041
9047
  */
9042
- prepareConversationContext(context: OperationContext, input: string | UIMessage[], userId?: string, conversationIdParam?: string, contextLimit?: number): Promise<{
9048
+ prepareConversationContext(context: OperationContext, input: string | UIMessage[], userId?: string, conversationIdParam?: string, contextLimit?: number, options?: {
9049
+ persistInput?: boolean;
9050
+ }): Promise<{
9043
9051
  messages: UIMessage<{
9044
9052
  createdAt: Date;
9045
9053
  }>[];
@@ -9361,6 +9369,7 @@ declare class Agent {
9361
9369
  */
9362
9370
  private prepareExecution;
9363
9371
  private collectToolDataFromResult;
9372
+ private ensureStructuredOutputGenerated;
9364
9373
  /**
9365
9374
  * Create execution context
9366
9375
  */
@@ -9376,6 +9385,8 @@ declare class Agent {
9376
9385
  private resetOperationAttemptState;
9377
9386
  private getConversationBuffer;
9378
9387
  private getMemoryPersistQueue;
9388
+ private isReadOnlyMemoryForContext;
9389
+ private shouldPersistMemoryForContext;
9379
9390
  private ensureStreamingResponseMessageId;
9380
9391
  private getOrCreateStepResponseMessageId;
9381
9392
  private getStepResponseMessageFingerprints;
package/dist/index.js CHANGED
@@ -352,7 +352,7 @@ __export(index_exports, {
352
352
  hasFilePart: () => hasFilePart,
353
353
  hasImagePart: () => hasImagePart,
354
354
  hasTextPart: () => hasTextPart,
355
- hasToolCall: () => import_ai8.hasToolCall,
355
+ hasToolCall: () => import_ai9.hasToolCall,
356
356
  isAbortError: () => isAbortError,
357
357
  isMiddlewareAbortError: () => isMiddlewareAbortError,
358
358
  isNodeRuntime: () => isNodeRuntime,
@@ -375,7 +375,7 @@ __export(index_exports, {
375
375
  serializeValueForDebug: () => serializeValueForDebug,
376
376
  setWaitUntil: () => setWaitUntil,
377
377
  shouldSample: () => shouldSample,
378
- stepCountIs: () => import_ai8.stepCountIs,
378
+ stepCountIs: () => import_ai9.stepCountIs,
379
379
  tool: () => tool,
380
380
  trace: () => import_api9.trace,
381
381
  transformTextContent: () => transformTextContent,
@@ -13068,7 +13068,7 @@ var MemoryManager = class {
13068
13068
  * Ensures context is always loaded, optimizes non-critical operations in background
13069
13069
  * PRESERVED FROM ORIGINAL
13070
13070
  */
13071
- async prepareConversationContext(context8, input, userId, conversationIdParam, contextLimit = 10) {
13071
+ async prepareConversationContext(context8, input, userId, conversationIdParam, contextLimit = 10, options) {
13072
13072
  const conversationId = conversationIdParam || randomUUID();
13073
13073
  if (contextLimit === 0) {
13074
13074
  return { messages: [], conversationId };
@@ -13098,7 +13098,9 @@ var MemoryManager = class {
13098
13098
  error
13099
13099
  });
13100
13100
  }
13101
- this.handleSequentialBackgroundOperations(context8, input, userId, conversationId);
13101
+ if (options?.persistInput !== false) {
13102
+ this.handleSequentialBackgroundOperations(context8, input, userId, conversationId);
13103
+ }
13102
13104
  return { messages, conversationId };
13103
13105
  }
13104
13106
  /**
@@ -21481,24 +21483,18 @@ var truncateByBytes = /* @__PURE__ */ __name((value, maxBytes) => {
21481
21483
  const truncated = buf.subarray(0, targetBytes).toString("utf-8");
21482
21484
  return `${truncated}${TRUNCATION_SUFFIX}`;
21483
21485
  }, "truncateByBytes");
21484
- var formatStreamOutput = /* @__PURE__ */ __name((label, info) => {
21485
- const lines = [];
21486
+ var formatStreamSummary = /* @__PURE__ */ __name((label, info) => {
21486
21487
  if (info.evicted && info.path) {
21487
- const note = info.truncated ? " (truncated)" : "";
21488
- lines.push(`${label}: saved to ${info.path} (${info.bytes} bytes${note})`);
21489
- if (info.error) {
21490
- lines.push(`${label} eviction error: ${info.error}`);
21491
- }
21492
- return lines;
21488
+ const note = info.truncated ? ", truncated" : "";
21489
+ const errorNote = info.error ? `, eviction error: ${info.error}` : "";
21490
+ return `${label}: saved to ${info.path} (${info.bytes} bytes${note}${errorNote})`;
21493
21491
  }
21494
21492
  if (info.content) {
21495
- lines.push(`${label}:`);
21496
- lines.push(info.content);
21497
- return lines;
21493
+ const note = info.truncated ? ", truncated" : "";
21494
+ return `${label}: captured inline (${info.bytes} bytes${note})`;
21498
21495
  }
21499
- lines.push(`${label}: (empty)`);
21500
- return lines;
21501
- }, "formatStreamOutput");
21496
+ return `${label}: (empty)`;
21497
+ }, "formatStreamSummary");
21502
21498
  var createWorkspaceSandboxToolkit = /* @__PURE__ */ __name((context8, options = {}) => {
21503
21499
  const pathContext = resolvePathContext(context8);
21504
21500
  const systemPrompt = options.systemPrompt === void 0 ? buildSystemPrompt(pathContext) : options.systemPrompt;
@@ -21631,8 +21627,8 @@ var createWorkspaceSandboxToolkit = /* @__PURE__ */ __name((context8, options =
21631
21627
  const stderrInfo = await evictStream("stderr", result.stderr, result.stderrTruncated);
21632
21628
  const lines = [];
21633
21629
  lines.push(...formatSandboxHeader(result));
21634
- lines.push(...formatStreamOutput("STDOUT", stdoutInfo));
21635
- lines.push(...formatStreamOutput("STDERR", stderrInfo));
21630
+ lines.push(formatStreamSummary("STDOUT", stdoutInfo));
21631
+ lines.push(formatStreamSummary("STDERR", stderrInfo));
21636
21632
  const summary = lines.join("\n");
21637
21633
  const streamErrors = [stdoutInfo.error, stderrInfo.error].filter(
21638
21634
  (value) => Boolean(value)
@@ -30041,6 +30037,14 @@ var firstNonBlank = /* @__PURE__ */ __name((...values) => {
30041
30037
  }
30042
30038
  return void 0;
30043
30039
  }, "firstNonBlank");
30040
+ var firstDefined = /* @__PURE__ */ __name((...values) => {
30041
+ for (const value of values) {
30042
+ if (value !== null && value !== void 0) {
30043
+ return value;
30044
+ }
30045
+ }
30046
+ return void 0;
30047
+ }, "firstDefined");
30044
30048
  var isAssistantContentPart = /* @__PURE__ */ __name((value) => {
30045
30049
  if (!isRecord4(value)) {
30046
30050
  return false;
@@ -30445,6 +30449,7 @@ var Agent = class {
30445
30449
  const feedbackOptions = this.resolveFeedbackOptions(options);
30446
30450
  const feedbackClient = feedbackOptions ? this.getFeedbackClient() : void 0;
30447
30451
  const shouldDeferPersist = Boolean(feedbackOptions && feedbackClient);
30452
+ const shouldPersistMemory = this.shouldPersistMemoryForContext(oc);
30448
30453
  let feedbackMetadata = null;
30449
30454
  const rootSpan = oc.traceContext.getRootSpan();
30450
30455
  return await oc.traceContext.withSpan(rootSpan, async () => {
@@ -30599,6 +30604,12 @@ var Agent = class {
30599
30604
  onStepFinish: this.createStepHandler(oc, options)
30600
30605
  })
30601
30606
  );
30607
+ this.ensureStructuredOutputGenerated({
30608
+ result: response,
30609
+ output,
30610
+ tools,
30611
+ maxSteps
30612
+ });
30602
30613
  const resolvedProviderUsage = response.usage ? await Promise.resolve(response.usage) : void 0;
30603
30614
  finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
30604
30615
  usage: resolvedProviderUsage,
@@ -30640,7 +30651,7 @@ var Agent = class {
30640
30651
  }
30641
30652
  );
30642
30653
  void this.recordStepResults(result.steps, oc);
30643
- if (!shouldDeferPersist) {
30654
+ if (!shouldDeferPersist && shouldPersistMemory) {
30644
30655
  await persistQueue.flush(buffer, oc);
30645
30656
  }
30646
30657
  const finalText = await runOutputGuardrails({
@@ -30722,7 +30733,7 @@ var Agent = class {
30722
30733
  }
30723
30734
  }
30724
30735
  }
30725
- if (shouldDeferPersist) {
30736
+ if (shouldDeferPersist && shouldPersistMemory) {
30726
30737
  await persistQueue.flush(buffer, oc);
30727
30738
  }
30728
30739
  const feedbackValue = (() => {
@@ -30848,6 +30859,7 @@ var Agent = class {
30848
30859
  const feedbackOptions = this.resolveFeedbackOptions(options);
30849
30860
  const feedbackClient = feedbackOptions ? this.getFeedbackClient() : void 0;
30850
30861
  const shouldDeferPersist = Boolean(feedbackOptions && feedbackClient);
30862
+ const shouldPersistMemory = this.shouldPersistMemoryForContext(oc);
30851
30863
  const feedbackDeferred = feedbackOptions ? createDeferred() : null;
30852
30864
  let feedbackMetadataValue = null;
30853
30865
  let feedbackValue = null;
@@ -30887,7 +30899,7 @@ var Agent = class {
30887
30899
  { requirePending: true }
30888
30900
  );
30889
30901
  }
30890
- if (shouldDeferPersist) {
30902
+ if (shouldDeferPersist && shouldPersistMemory) {
30891
30903
  void persistQueue.flush(buffer, oc).catch((error) => {
30892
30904
  oc.logger?.debug?.("Failed to persist feedback metadata", { error });
30893
30905
  });
@@ -31162,7 +31174,7 @@ var Agent = class {
31162
31174
  usage: providerUsage,
31163
31175
  finishReason: finalResult.finishReason
31164
31176
  });
31165
- if (!shouldDeferPersist) {
31177
+ if (!shouldDeferPersist && shouldPersistMemory) {
31166
31178
  await persistQueue.flush(buffer, oc);
31167
31179
  }
31168
31180
  this.setTraceContextUsage(oc.traceContext, usageForFinish);
@@ -31276,7 +31288,7 @@ var Agent = class {
31276
31288
  }
31277
31289
  if (feedbackResolved && feedbackMetadataValue) {
31278
31290
  scheduleFeedbackPersist(feedbackMetadataValue);
31279
- } else if (shouldDeferPersist) {
31291
+ } else if (shouldDeferPersist && shouldPersistMemory) {
31280
31292
  void persistQueue.flush(buffer, oc).catch((error) => {
31281
31293
  oc.logger?.debug?.("Failed to persist deferred messages", { error });
31282
31294
  });
@@ -31749,7 +31761,7 @@ var Agent = class {
31749
31761
  warnings: result.warnings ?? null
31750
31762
  }
31751
31763
  });
31752
- if (oc.userId && oc.conversationId) {
31764
+ if (this.shouldPersistMemoryForContext(oc) && oc.userId && oc.conversationId) {
31753
31765
  const message = {
31754
31766
  id: randomUUID(),
31755
31767
  role: "assistant",
@@ -32095,7 +32107,7 @@ var Agent = class {
32095
32107
  });
32096
32108
  resolveGuardrailObject?.(finalObject);
32097
32109
  }
32098
- if (oc.userId && oc.conversationId) {
32110
+ if (this.shouldPersistMemoryForContext(oc) && oc.userId && oc.conversationId) {
32099
32111
  const message = {
32100
32112
  id: randomUUID(),
32101
32113
  role: "assistant",
@@ -32339,6 +32351,42 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32339
32351
  toolResults: stepToolResults.length > 0 ? stepToolResults : result.toolResults ?? []
32340
32352
  };
32341
32353
  }
32354
+ ensureStructuredOutputGenerated(params) {
32355
+ const { result, output, tools, maxSteps } = params;
32356
+ if (!output) {
32357
+ return;
32358
+ }
32359
+ try {
32360
+ void result.output;
32361
+ } catch (error) {
32362
+ const isNoOutputGeneratedError = error instanceof import_ai7.NoOutputGeneratedError || error instanceof Error && error.name === "AI_NoOutputGeneratedError";
32363
+ if (!isNoOutputGeneratedError) {
32364
+ throw error;
32365
+ }
32366
+ const { toolCalls } = this.collectToolDataFromResult(result);
32367
+ const configuredToolCount = Object.keys(tools ?? {}).length;
32368
+ const stepCount = result.steps?.length ?? 0;
32369
+ const finishReason = result.finishReason ?? "unknown";
32370
+ const reachedMaxSteps = stepCount >= maxSteps;
32371
+ const guidance = configuredToolCount > 0 || toolCalls.length > 0 ? "When tools are enabled, ensure the model emits a final non-tool response that matches the output schema, or split this into two calls (tools first, schema formatting second)." : "Ensure the model emits a final response that matches the requested output schema.";
32372
+ const maxStepHint = reachedMaxSteps ? ` Generation stopped after ${stepCount} steps (maxSteps=${maxSteps}).` : "";
32373
+ throw createVoltAgentError(
32374
+ `Structured output was requested but no final output was generated (finishReason: ${finishReason}). ${guidance}${maxStepHint}`,
32375
+ {
32376
+ stage: "response_parsing",
32377
+ code: "STRUCTURED_OUTPUT_NOT_GENERATED",
32378
+ originalError: error,
32379
+ metadata: {
32380
+ finishReason,
32381
+ stepCount,
32382
+ maxSteps,
32383
+ configuredToolCount,
32384
+ toolCallCount: toolCalls.length
32385
+ }
32386
+ }
32387
+ );
32388
+ }
32389
+ }
32342
32390
  /**
32343
32391
  * Create execution context
32344
32392
  */
@@ -32388,7 +32436,12 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32388
32436
  ),
32389
32437
  contextLimit: contextResolvedMemory?.contextLimit ?? memoryOptions?.contextLimit ?? options?.contextLimit ?? parentResolvedMemory?.contextLimit,
32390
32438
  semanticMemory: contextResolvedMemory?.semanticMemory ?? memoryOptions?.semanticMemory ?? options?.semanticMemory ?? parentResolvedMemory?.semanticMemory,
32391
- conversationPersistence: contextResolvedMemory?.conversationPersistence ?? memoryOptions?.conversationPersistence ?? options?.conversationPersistence ?? parentResolvedMemory?.conversationPersistence
32439
+ conversationPersistence: contextResolvedMemory?.conversationPersistence ?? memoryOptions?.conversationPersistence ?? options?.conversationPersistence ?? parentResolvedMemory?.conversationPersistence,
32440
+ readOnly: firstDefined(
32441
+ contextResolvedMemory?.readOnly,
32442
+ memoryOptions?.readOnly,
32443
+ parentResolvedMemory?.readOnly
32444
+ )
32392
32445
  };
32393
32446
  }
32394
32447
  getConversationPersistenceOptionsForContext(oc) {
@@ -32546,6 +32599,12 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32546
32599
  }
32547
32600
  return queue;
32548
32601
  }
32602
+ isReadOnlyMemoryForContext(oc) {
32603
+ return oc.resolvedMemory?.readOnly === true;
32604
+ }
32605
+ shouldPersistMemoryForContext(oc) {
32606
+ return !this.isReadOnlyMemoryForContext(oc);
32607
+ }
32549
32608
  async ensureStreamingResponseMessageId(oc, buffer) {
32550
32609
  const messageId = this.getOrCreateStepResponseMessageId(oc);
32551
32610
  const placeholder = {
@@ -32598,6 +32657,9 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32598
32657
  return normalized.length > 0 ? normalized : void 0;
32599
32658
  }
32600
32659
  async flushPendingMessagesOnError(oc) {
32660
+ if (!this.shouldPersistMemoryForContext(oc)) {
32661
+ return;
32662
+ }
32601
32663
  const buffer = this.getConversationBuffer(oc);
32602
32664
  const queue = this.getMemoryPersistQueue(oc);
32603
32665
  if (!buffer || !queue) {
@@ -33006,6 +33068,7 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
33006
33068
  const messages = [];
33007
33069
  const resolvedMemory = this.resolveMemoryRuntimeOptions(options, oc);
33008
33070
  const canIUseMemory = Boolean(resolvedMemory.userId);
33071
+ const shouldPersistMemory = resolvedMemory.readOnly !== true;
33009
33072
  const memoryContextMessages = [];
33010
33073
  if (canIUseMemory) {
33011
33074
  const useSemanticSearch = resolvedMemory.semanticMemory?.enabled ?? this.hasSemanticSearchSupport();
@@ -33061,7 +33124,8 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
33061
33124
  inputForMemory,
33062
33125
  oc.userId,
33063
33126
  oc.conversationId,
33064
- resolvedMemory.contextLimit
33127
+ resolvedMemory.contextLimit,
33128
+ { persistInput: shouldPersistMemory }
33065
33129
  );
33066
33130
  oc.conversationId = result.conversationId;
33067
33131
  if (oc.resolvedMemory) {
@@ -33084,7 +33148,7 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
33084
33148
  }
33085
33149
  }
33086
33150
  memoryContextMessages.push(...memoryResult);
33087
- if (isSemanticSearch && oc.userId && oc.conversationId) {
33151
+ if (isSemanticSearch && shouldPersistMemory && oc.userId && oc.conversationId) {
33088
33152
  try {
33089
33153
  const inputForMemory = typeof resolvedInput === "string" ? resolvedInput : Array.isArray(resolvedInput) && resolvedInput[0]?.parts ? resolvedInput : convertModelMessagesToUIMessages(resolvedInput);
33090
33154
  this.memoryManager.queueSaveInput(oc, inputForMemory, oc.userId, oc.conversationId);
@@ -33629,6 +33693,9 @@ ${retrieverContext}`;
33629
33693
  return true;
33630
33694
  }
33631
33695
  isRetryableError(error) {
33696
+ if (isVoltAgentError(error) && error.code === "STRUCTURED_OUTPUT_NOT_GENERATED") {
33697
+ return true;
33698
+ }
33632
33699
  const retryable = error?.isRetryable;
33633
33700
  if (typeof retryable === "boolean") {
33634
33701
  return retryable;
@@ -34770,7 +34837,8 @@ ${retrieverContext}`;
34770
34837
  */
34771
34838
  createStepHandler(oc, options) {
34772
34839
  const buffer = this.getConversationBuffer(oc);
34773
- const persistQueue = this.getMemoryPersistQueue(oc);
34840
+ const shouldPersistMemory = this.shouldPersistMemoryForContext(oc);
34841
+ const persistQueue = shouldPersistMemory ? this.getMemoryPersistQueue(oc) : null;
34774
34842
  const conversationPersistence = this.getConversationPersistenceOptionsForContext(oc);
34775
34843
  return async (event) => {
34776
34844
  const { shouldFlushForToolCompletion, bailedResult } = this.processStepContent(oc, event);
@@ -34788,7 +34856,7 @@ ${retrieverContext}`;
34788
34856
  awaitPersistence: shouldFlushStepPersistence
34789
34857
  });
34790
34858
  }
34791
- if (conversationPersistence.mode === "step" && (hasResponseMessages || shouldFlushStepPersistence)) {
34859
+ if (shouldPersistMemory && persistQueue && conversationPersistence.mode === "step" && (hasResponseMessages || shouldFlushStepPersistence)) {
34792
34860
  try {
34793
34861
  if (shouldFlushStepPersistence) {
34794
34862
  await persistQueue.flush(buffer, oc);
@@ -35025,7 +35093,7 @@ ${retrieverContext}`;
35025
35093
  }
35026
35094
  recordTimestamp = (/* @__PURE__ */ new Date()).toISOString();
35027
35095
  });
35028
- if (stepRecords.length > 0 && oc.userId && oc.conversationId) {
35096
+ if (this.shouldPersistMemoryForContext(oc) && stepRecords.length > 0 && oc.userId && oc.conversationId) {
35029
35097
  const persistStepsPromise = this.memoryManager.saveConversationSteps(oc, stepRecords, oc.userId, oc.conversationId).catch((error) => {
35030
35098
  oc.logger.debug("Failed to persist conversation steps", {
35031
35099
  error,
@@ -35730,7 +35798,8 @@ ${retrieverContext}`;
35730
35798
  const memoryBehaviorOverrides = resolvedMemory ? {
35731
35799
  ...resolvedMemory.contextLimit !== void 0 ? { contextLimit: resolvedMemory.contextLimit } : {},
35732
35800
  ...resolvedMemory.semanticMemory !== void 0 ? { semanticMemory: resolvedMemory.semanticMemory } : {},
35733
- ...resolvedMemory.conversationPersistence !== void 0 ? { conversationPersistence: resolvedMemory.conversationPersistence } : {}
35801
+ ...resolvedMemory.conversationPersistence !== void 0 ? { conversationPersistence: resolvedMemory.conversationPersistence } : {},
35802
+ ...resolvedMemory.readOnly !== void 0 ? { readOnly: resolvedMemory.readOnly } : {}
35734
35803
  } : void 0;
35735
35804
  const memory = resolvedMemory || options2?.conversationId || options2?.userId ? {
35736
35805
  conversationId: resolvedMemory?.conversationId ?? options2?.conversationId,
@@ -35780,6 +35849,7 @@ ${retrieverContext}`;
35780
35849
  return [];
35781
35850
  }
35782
35851
  const resolvedMemory = this.resolveMemoryRuntimeOptions(options, operationContext);
35852
+ const isReadOnly = resolvedMemory.readOnly === true;
35783
35853
  const memoryManager = this.memoryManager;
35784
35854
  const memory = memoryManager.getMemory();
35785
35855
  if (!memory) {
@@ -35800,60 +35870,62 @@ ${retrieverContext}`;
35800
35870
  }, "execute")
35801
35871
  })
35802
35872
  );
35803
- const schema = memory.getWorkingMemorySchema();
35804
- const template = memory.getWorkingMemoryTemplate();
35805
- const baseParams = schema ? { content: schema } : { content: import_zod7.z.string().describe("The content to store in working memory") };
35806
- const modeParam = {
35807
- mode: import_zod7.z.enum(["replace", "append"]).default("append").describe(
35808
- "How to update: 'append' (default - safely merge with existing) or 'replace' (complete overwrite - DELETES other fields!)"
35809
- )
35810
- };
35811
- tools.push(
35812
- createTool({
35813
- name: "update_working_memory",
35814
- description: template ? `Update working memory. Default mode is 'append' which safely merges new data. Only use 'replace' if you want to COMPLETELY OVERWRITE all data. Current data is in <current_context>. Template: ${template}` : `Update working memory with important context. Default mode is 'append' which safely merges new data. Only use 'replace' if you want to COMPLETELY OVERWRITE all data. Current data is in <current_context>.`,
35815
- parameters: import_zod7.z.object({ ...baseParams, ...modeParam }),
35816
- execute: /* @__PURE__ */ __name(async ({ content, mode }, oc) => {
35817
- await memory.updateWorkingMemory({
35818
- conversationId: resolvedMemory.conversationId,
35819
- userId: resolvedMemory.userId,
35820
- content,
35821
- options: {
35822
- mode
35873
+ if (!isReadOnly) {
35874
+ const schema = memory.getWorkingMemorySchema();
35875
+ const template = memory.getWorkingMemoryTemplate();
35876
+ const baseParams = schema ? { content: schema } : { content: import_zod7.z.string().describe("The content to store in working memory") };
35877
+ const modeParam = {
35878
+ mode: import_zod7.z.enum(["replace", "append"]).default("append").describe(
35879
+ "How to update: 'append' (default - safely merge with existing) or 'replace' (complete overwrite - DELETES other fields!)"
35880
+ )
35881
+ };
35882
+ tools.push(
35883
+ createTool({
35884
+ name: "update_working_memory",
35885
+ description: template ? `Update working memory. Default mode is 'append' which safely merges new data. Only use 'replace' if you want to COMPLETELY OVERWRITE all data. Current data is in <current_context>. Template: ${template}` : `Update working memory with important context. Default mode is 'append' which safely merges new data. Only use 'replace' if you want to COMPLETELY OVERWRITE all data. Current data is in <current_context>.`,
35886
+ parameters: import_zod7.z.object({ ...baseParams, ...modeParam }),
35887
+ execute: /* @__PURE__ */ __name(async ({ content, mode }, oc) => {
35888
+ await memory.updateWorkingMemory({
35889
+ conversationId: resolvedMemory.conversationId,
35890
+ userId: resolvedMemory.userId,
35891
+ content,
35892
+ options: {
35893
+ mode
35894
+ }
35895
+ });
35896
+ if (oc?.traceContext) {
35897
+ const finalContent = await memory.getWorkingMemory({
35898
+ conversationId: resolvedMemory.conversationId,
35899
+ userId: resolvedMemory.userId
35900
+ });
35901
+ const rootSpan = oc.traceContext.getRootSpan();
35902
+ rootSpan.setAttribute("agent.workingMemory.finalContent", finalContent || "");
35903
+ rootSpan.setAttribute("agent.workingMemory.lastUpdateTime", (/* @__PURE__ */ new Date()).toISOString());
35823
35904
  }
35824
- });
35825
- if (oc?.traceContext) {
35826
- const finalContent = await memory.getWorkingMemory({
35905
+ return `Working memory ${mode === "replace" ? "replaced" : "updated (appended)"} successfully.`;
35906
+ }, "execute")
35907
+ })
35908
+ );
35909
+ tools.push(
35910
+ createTool({
35911
+ name: "clear_working_memory",
35912
+ description: "Clear the working memory content",
35913
+ parameters: import_zod7.z.object({}),
35914
+ execute: /* @__PURE__ */ __name(async (_, oc) => {
35915
+ await memory.clearWorkingMemory({
35827
35916
  conversationId: resolvedMemory.conversationId,
35828
35917
  userId: resolvedMemory.userId
35829
35918
  });
35830
- const rootSpan = oc.traceContext.getRootSpan();
35831
- rootSpan.setAttribute("agent.workingMemory.finalContent", finalContent || "");
35832
- rootSpan.setAttribute("agent.workingMemory.lastUpdateTime", (/* @__PURE__ */ new Date()).toISOString());
35833
- }
35834
- return `Working memory ${mode === "replace" ? "replaced" : "updated (appended)"} successfully.`;
35835
- }, "execute")
35836
- })
35837
- );
35838
- tools.push(
35839
- createTool({
35840
- name: "clear_working_memory",
35841
- description: "Clear the working memory content",
35842
- parameters: import_zod7.z.object({}),
35843
- execute: /* @__PURE__ */ __name(async (_, oc) => {
35844
- await memory.clearWorkingMemory({
35845
- conversationId: resolvedMemory.conversationId,
35846
- userId: resolvedMemory.userId
35847
- });
35848
- if (oc?.traceContext) {
35849
- const rootSpan = oc.traceContext.getRootSpan();
35850
- rootSpan.setAttribute("agent.workingMemory.finalContent", "");
35851
- rootSpan.setAttribute("agent.workingMemory.lastUpdateTime", (/* @__PURE__ */ new Date()).toISOString());
35852
- }
35853
- return "Working memory cleared.";
35854
- }, "execute")
35855
- })
35856
- );
35919
+ if (oc?.traceContext) {
35920
+ const rootSpan = oc.traceContext.getRootSpan();
35921
+ rootSpan.setAttribute("agent.workingMemory.finalContent", "");
35922
+ rootSpan.setAttribute("agent.workingMemory.lastUpdateTime", (/* @__PURE__ */ new Date()).toISOString());
35923
+ }
35924
+ return "Working memory cleared.";
35925
+ }, "execute")
35926
+ })
35927
+ );
35928
+ }
35857
35929
  return tools;
35858
35930
  }
35859
35931
  };
@@ -41288,6 +41360,9 @@ var TriggerRegistry = class _TriggerRegistry {
41288
41360
  }
41289
41361
  };
41290
41362
 
41363
+ // src/voltagent.ts
41364
+ var import_ai8 = require("ai");
41365
+
41291
41366
  // src/utils/voltops-validation.ts
41292
41367
  function isValidVoltOpsKeys(publicKey, secretKey) {
41293
41368
  if (!publicKey || !secretKey) {
@@ -41608,9 +41683,12 @@ var VoltAgent = class {
41608
41683
  process.once("SIGTERM", () => handleSignal("SIGTERM"));
41609
41684
  process.once("SIGINT", () => handleSignal("SIGINT"));
41610
41685
  process.on("unhandledRejection", (reason) => {
41686
+ const isStructuredOutputWrapperError = isVoltAgentError(reason) && reason.code === "STRUCTURED_OUTPUT_NOT_GENERATED";
41687
+ const isNoOutputGeneratedError = isStructuredOutputWrapperError || reason instanceof import_ai8.NoOutputGeneratedError || reason instanceof Error && reason.name === "AI_NoOutputGeneratedError";
41611
41688
  this.logger.error("[VoltAgent] Unhandled Promise Rejection:", {
41612
41689
  reason: reason instanceof Error ? reason.message : reason,
41613
- stack: reason instanceof Error ? reason.stack : void 0
41690
+ stack: reason instanceof Error ? reason.stack : void 0,
41691
+ hint: isNoOutputGeneratedError ? "Structured output was requested but no final output was generated. If tools are enabled, ensure a final schema-matching response or split into two calls." : void 0
41614
41692
  });
41615
41693
  });
41616
41694
  }
@@ -41916,7 +41994,7 @@ var VoltAgent = class {
41916
41994
 
41917
41995
  // src/index.ts
41918
41996
  var import_utils40 = require("@voltagent/internal/utils");
41919
- var import_ai8 = require("ai");
41997
+ var import_ai9 = require("ai");
41920
41998
  // Annotate the CommonJS export names for ESM import in node:
41921
41999
  0 && (module.exports = {
41922
42000
  A2AServerRegistry,