@voltagent/core 2.6.8 → 2.6.11

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
@@ -8796,6 +8796,7 @@ declare class Memory {
8796
8796
  * Get messages by their IDs
8797
8797
  */
8798
8798
  private getMessagesByIds;
8799
+ private getMessageVectorIdsForClear;
8799
8800
  /**
8800
8801
  * Merge two arrays of messages, removing duplicates
8801
8802
  */
@@ -9405,6 +9406,7 @@ declare class Agent {
9405
9406
  private createLLMSpanFinalizer;
9406
9407
  private buildLLMSpanAttributes;
9407
9408
  private recordLLMUsage;
9409
+ private recordProviderCost;
9408
9410
  private createEvalHost;
9409
9411
  /**
9410
9412
  * Get observability instance (lazy initialization)
@@ -9683,6 +9685,7 @@ declare class Agent {
9683
9685
  * Maps AI SDK's LanguageModelUsage to trace context format
9684
9686
  */
9685
9687
  private setTraceContextUsage;
9688
+ private recordRootSpanUsageAndProviderCost;
9686
9689
  /**
9687
9690
  * Create working memory tools if configured
9688
9691
  */
package/dist/index.d.ts CHANGED
@@ -8796,6 +8796,7 @@ declare class Memory {
8796
8796
  * Get messages by their IDs
8797
8797
  */
8798
8798
  private getMessagesByIds;
8799
+ private getMessageVectorIdsForClear;
8799
8800
  /**
8800
8801
  * Merge two arrays of messages, removing duplicates
8801
8802
  */
@@ -9405,6 +9406,7 @@ declare class Agent {
9405
9406
  private createLLMSpanFinalizer;
9406
9407
  private buildLLMSpanAttributes;
9407
9408
  private recordLLMUsage;
9409
+ private recordProviderCost;
9408
9410
  private createEvalHost;
9409
9411
  /**
9410
9412
  * Get observability instance (lazy initialization)
@@ -9683,6 +9685,7 @@ declare class Agent {
9683
9685
  * Maps AI SDK's LanguageModelUsage to trace context format
9684
9686
  */
9685
9687
  private setTraceContextUsage;
9688
+ private recordRootSpanUsageAndProviderCost;
9686
9689
  /**
9687
9690
  * Create working memory tools if configured
9688
9691
  */
package/dist/index.js CHANGED
@@ -5248,6 +5248,7 @@ __name(cosineSimilarity, "cosineSimilarity");
5248
5248
  // src/memory/index.ts
5249
5249
  var isEmbeddingAdapter = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && "embed" in value && typeof value.embed === "function" && "embedBatch" in value && typeof value.embedBatch === "function", "isEmbeddingAdapter");
5250
5250
  var isEmbeddingAdapterConfig = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && "model" in value && !isEmbeddingAdapter(value), "isEmbeddingAdapterConfig");
5251
+ var VECTOR_CLEAR_CONVERSATION_PAGE_SIZE = 200;
5251
5252
  var resolveEmbeddingAdapter = /* @__PURE__ */ __name((embedding) => {
5252
5253
  if (!embedding) {
5253
5254
  return void 0;
@@ -5333,6 +5334,19 @@ var Memory = class {
5333
5334
  * Clear messages for a user
5334
5335
  */
5335
5336
  async clearMessages(userId, conversationId, context8) {
5337
+ if (this.vector) {
5338
+ try {
5339
+ const vectorIds = await this.getMessageVectorIdsForClear(userId, conversationId);
5340
+ if (vectorIds.length > 0) {
5341
+ await this.vector.deleteBatch(vectorIds);
5342
+ }
5343
+ } catch (error) {
5344
+ console.warn(
5345
+ `Failed to delete vectors while clearing messages for user ${userId}${conversationId ? ` conversation ${conversationId}` : ""}:`,
5346
+ error
5347
+ );
5348
+ }
5349
+ }
5336
5350
  return this.storage.clearMessages(userId, conversationId, context8);
5337
5351
  }
5338
5352
  /**
@@ -5469,6 +5483,36 @@ var Memory = class {
5469
5483
  const ordered = messageIds.map((id) => byId.get(id)).filter((m) => Boolean(m));
5470
5484
  return ordered;
5471
5485
  }
5486
+ async getMessageVectorIdsForClear(userId, conversationId) {
5487
+ const vectorIds = /* @__PURE__ */ new Set();
5488
+ if (conversationId) {
5489
+ const messages = await this.storage.getMessages(userId, conversationId);
5490
+ for (const message of messages) {
5491
+ vectorIds.add(`msg_${conversationId}_${message.id}`);
5492
+ }
5493
+ return Array.from(vectorIds);
5494
+ }
5495
+ const totalConversations = await this.storage.countConversations({ userId });
5496
+ let offset = 0;
5497
+ while (offset < totalConversations) {
5498
+ const conversations = await this.storage.queryConversations({
5499
+ userId,
5500
+ limit: VECTOR_CLEAR_CONVERSATION_PAGE_SIZE,
5501
+ offset
5502
+ });
5503
+ for (const conversation of conversations) {
5504
+ const messages = await this.storage.getMessages(userId, conversation.id);
5505
+ for (const message of messages) {
5506
+ vectorIds.add(`msg_${conversation.id}_${message.id}`);
5507
+ }
5508
+ }
5509
+ if (conversations.length === 0) {
5510
+ break;
5511
+ }
5512
+ offset += conversations.length;
5513
+ }
5514
+ return Array.from(vectorIds);
5515
+ }
5472
5516
  /**
5473
5517
  * Merge two arrays of messages, removing duplicates
5474
5518
  */
@@ -24881,6 +24925,41 @@ function createScorerSpanAttributes(host, descriptor, config, storagePayload, me
24881
24925
  if (metrics.datasetMetadata?.datasetItemHash) {
24882
24926
  attributes["eval.dataset.item_hash"] = metrics.datasetMetadata.datasetItemHash;
24883
24927
  }
24928
+ const judgeTelemetry = extractJudgeTelemetry(metrics.combinedMetadata);
24929
+ if (judgeTelemetry?.modelName) {
24930
+ attributes["ai.model.name"] = judgeTelemetry.modelName;
24931
+ const provider = judgeTelemetry.modelName.includes("/") ? judgeTelemetry.modelName.split("/")[0] : void 0;
24932
+ if (provider) {
24933
+ attributes["ai.model.provider"] = provider;
24934
+ }
24935
+ }
24936
+ if (judgeTelemetry?.promptTokens !== void 0) {
24937
+ attributes["usage.prompt_tokens"] = judgeTelemetry.promptTokens;
24938
+ }
24939
+ if (judgeTelemetry?.completionTokens !== void 0) {
24940
+ attributes["usage.completion_tokens"] = judgeTelemetry.completionTokens;
24941
+ }
24942
+ if (judgeTelemetry?.totalTokens !== void 0) {
24943
+ attributes["usage.total_tokens"] = judgeTelemetry.totalTokens;
24944
+ }
24945
+ if (judgeTelemetry?.cachedTokens !== void 0) {
24946
+ attributes["usage.cached_tokens"] = judgeTelemetry.cachedTokens;
24947
+ }
24948
+ if (judgeTelemetry?.reasoningTokens !== void 0) {
24949
+ attributes["usage.reasoning_tokens"] = judgeTelemetry.reasoningTokens;
24950
+ }
24951
+ if (judgeTelemetry?.providerCost?.cost !== void 0) {
24952
+ attributes["usage.cost"] = judgeTelemetry.providerCost.cost;
24953
+ }
24954
+ if (judgeTelemetry?.providerCost?.upstreamInferenceCost !== void 0) {
24955
+ attributes["usage.cost_details.upstream_inference_cost"] = judgeTelemetry.providerCost.upstreamInferenceCost;
24956
+ }
24957
+ if (judgeTelemetry?.providerCost?.upstreamInferenceInputCost !== void 0) {
24958
+ attributes["usage.cost_details.upstream_inference_input_cost"] = judgeTelemetry.providerCost.upstreamInferenceInputCost;
24959
+ }
24960
+ if (judgeTelemetry?.providerCost?.upstreamInferenceOutputCost !== void 0) {
24961
+ attributes["usage.cost_details.upstream_inference_output_cost"] = judgeTelemetry.providerCost.upstreamInferenceOutputCost;
24962
+ }
24884
24963
  if (storagePayload.userId) {
24885
24964
  attributes["user.id"] = storagePayload.userId;
24886
24965
  }
@@ -25763,6 +25842,64 @@ function extractErrorMessage(error) {
25763
25842
  }
25764
25843
  }
25765
25844
  __name(extractErrorMessage, "extractErrorMessage");
25845
+ function extractJudgeTelemetry(metadata) {
25846
+ const record = isPlainRecord(metadata) ? metadata : void 0;
25847
+ if (!record) {
25848
+ return void 0;
25849
+ }
25850
+ const sources = [];
25851
+ if (isPlainRecord(record.voltAgent)) {
25852
+ sources.push(record.voltAgent);
25853
+ }
25854
+ if (isPlainRecord(record.scorer)) {
25855
+ sources.push(record.scorer);
25856
+ }
25857
+ if (isPlainRecord(record.payload)) {
25858
+ sources.push(record.payload);
25859
+ }
25860
+ for (const source of sources) {
25861
+ const judge = isPlainRecord(source?.judge) ? source?.judge : void 0;
25862
+ if (!judge) {
25863
+ continue;
25864
+ }
25865
+ const usage = isPlainRecord(judge.usage) ? judge.usage : void 0;
25866
+ const providerCost = isPlainRecord(judge.providerCost) ? judge.providerCost : void 0;
25867
+ const telemetry = {
25868
+ modelName: readString(judge.model),
25869
+ promptTokens: readNumber(usage?.promptTokens),
25870
+ completionTokens: readNumber(usage?.completionTokens),
25871
+ totalTokens: readNumber(usage?.totalTokens),
25872
+ cachedTokens: readNumber(usage?.cachedInputTokens ?? usage?.cachedTokens),
25873
+ reasoningTokens: readNumber(usage?.reasoningTokens),
25874
+ providerCost: providerCost ? {
25875
+ cost: readNumber(providerCost.cost),
25876
+ upstreamInferenceCost: readNumber(providerCost.upstreamInferenceCost),
25877
+ upstreamInferenceInputCost: readNumber(providerCost.upstreamInferenceInputCost),
25878
+ upstreamInferenceOutputCost: readNumber(providerCost.upstreamInferenceOutputCost)
25879
+ } : void 0
25880
+ };
25881
+ if (telemetry.modelName || telemetry.promptTokens !== void 0 || telemetry.completionTokens !== void 0 || telemetry.totalTokens !== void 0 || telemetry.cachedTokens !== void 0 || telemetry.reasoningTokens !== void 0 || telemetry.providerCost?.cost !== void 0 || telemetry.providerCost?.upstreamInferenceCost !== void 0 || telemetry.providerCost?.upstreamInferenceInputCost !== void 0 || telemetry.providerCost?.upstreamInferenceOutputCost !== void 0) {
25882
+ return telemetry;
25883
+ }
25884
+ }
25885
+ return void 0;
25886
+ }
25887
+ __name(extractJudgeTelemetry, "extractJudgeTelemetry");
25888
+ function readString(value) {
25889
+ return typeof value === "string" && value.length > 0 ? value : void 0;
25890
+ }
25891
+ __name(readString, "readString");
25892
+ function readNumber(value) {
25893
+ if (typeof value === "number") {
25894
+ return Number.isFinite(value) ? value : void 0;
25895
+ }
25896
+ if (typeof value === "string") {
25897
+ const parsed = Number(value);
25898
+ return Number.isFinite(parsed) ? parsed : void 0;
25899
+ }
25900
+ return void 0;
25901
+ }
25902
+ __name(readNumber, "readNumber");
25766
25903
  async function invokeEvalResultCallback(host, config, result) {
25767
25904
  if (!config.onResult) {
25768
25905
  return;
@@ -26315,6 +26452,10 @@ var AgentTraceContext = class {
26315
26452
  function addModelAttributesToSpan(span, modelName, options, defaultMaxOutputTokens, defaultTemperature) {
26316
26453
  if (!span) return;
26317
26454
  span.setAttribute("ai.model.name", modelName);
26455
+ const provider = typeof modelName === "string" && modelName.includes("/") ? modelName.split("/")[0] : void 0;
26456
+ if (provider) {
26457
+ span.setAttribute("ai.model.provider", provider);
26458
+ }
26318
26459
  const temperature = options?.temperature ?? options?.providerOptions?.temperature ?? defaultTemperature;
26319
26460
  if (temperature !== void 0 && typeof temperature === "number") {
26320
26461
  span.setAttribute("ai.model.temperature", temperature);
@@ -30028,6 +30169,7 @@ var DEFAULT_CONVERSATION_PERSISTENCE_OPTIONS = {
30028
30169
  flushOnToolResult: true
30029
30170
  };
30030
30171
  var isRecord4 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null, "isRecord");
30172
+ var isPlainObject = /* @__PURE__ */ __name((value) => isRecord4(value) && !Array.isArray(value), "isPlainObject");
30031
30173
  var hasNonEmptyString2 = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim().length > 0, "hasNonEmptyString");
30032
30174
  var firstNonBlank = /* @__PURE__ */ __name((...values) => {
30033
30175
  for (const value of values) {
@@ -30045,6 +30187,79 @@ var firstDefined = /* @__PURE__ */ __name((...values) => {
30045
30187
  }
30046
30188
  return void 0;
30047
30189
  }, "firstDefined");
30190
+ var toFiniteNumber = /* @__PURE__ */ __name((value) => {
30191
+ if (typeof value === "number") {
30192
+ return Number.isFinite(value) ? value : void 0;
30193
+ }
30194
+ if (typeof value === "string") {
30195
+ const parsed = Number(value);
30196
+ return Number.isFinite(parsed) ? parsed : void 0;
30197
+ }
30198
+ return void 0;
30199
+ }, "toFiniteNumber");
30200
+ var toBoolean = /* @__PURE__ */ __name((value) => {
30201
+ if (typeof value === "boolean") {
30202
+ return value;
30203
+ }
30204
+ if (typeof value === "string") {
30205
+ const normalized = value.trim().toLowerCase();
30206
+ if (normalized === "true") return true;
30207
+ if (normalized === "false") return false;
30208
+ }
30209
+ return void 0;
30210
+ }, "toBoolean");
30211
+ var extractOpenRouterUsageCost = /* @__PURE__ */ __name((providerMetadata) => {
30212
+ if (!isPlainObject(providerMetadata)) {
30213
+ return void 0;
30214
+ }
30215
+ const openRouterMetadata = isPlainObject(providerMetadata.openrouter) ? providerMetadata.openrouter : void 0;
30216
+ const usage = openRouterMetadata && isPlainObject(openRouterMetadata.usage) ? openRouterMetadata.usage : void 0;
30217
+ if (!usage) {
30218
+ return void 0;
30219
+ }
30220
+ const costDetails = firstDefined(
30221
+ isPlainObject(usage.costDetails) ? usage.costDetails : void 0,
30222
+ isPlainObject(usage.cost_details) ? usage.cost_details : void 0
30223
+ );
30224
+ const result = {
30225
+ cost: toFiniteNumber(usage.cost),
30226
+ isByok: firstDefined(toBoolean(usage.isByok), toBoolean(usage.is_byok)),
30227
+ upstreamInferenceCost: firstDefined(
30228
+ toFiniteNumber(costDetails?.upstreamInferenceCost),
30229
+ toFiniteNumber(costDetails?.upstream_inference_cost)
30230
+ ),
30231
+ upstreamInferenceInputCost: firstDefined(
30232
+ toFiniteNumber(costDetails?.upstreamInferenceInputCost),
30233
+ toFiniteNumber(costDetails?.upstream_inference_input_cost)
30234
+ ),
30235
+ upstreamInferenceOutputCost: firstDefined(
30236
+ toFiniteNumber(costDetails?.upstreamInferenceOutputCost),
30237
+ toFiniteNumber(costDetails?.upstream_inference_output_cost)
30238
+ )
30239
+ };
30240
+ return Object.values(result).some((value) => value !== void 0) ? result : void 0;
30241
+ }, "extractOpenRouterUsageCost");
30242
+ var toLanguageModelUsage = /* @__PURE__ */ __name((value) => isPlainObject(value) ? value : void 0, "toLanguageModelUsage");
30243
+ var extractGenerationErrorDetails = /* @__PURE__ */ __name((error) => {
30244
+ const metadata = isRecord4(error) && isPlainObject(error.metadata) ? error.metadata : void 0;
30245
+ const originalError = isRecord4(error) ? error.originalError : void 0;
30246
+ const usage = firstDefined(
30247
+ isRecord4(error) ? toLanguageModelUsage(error.usage) : void 0,
30248
+ metadata ? toLanguageModelUsage(metadata.usage) : void 0,
30249
+ isRecord4(originalError) ? toLanguageModelUsage(originalError.usage) : void 0
30250
+ );
30251
+ const providerMetadata = firstDefined(
30252
+ metadata?.providerMetadata,
30253
+ isRecord4(error) ? error.providerMetadata : void 0,
30254
+ isRecord4(originalError) ? originalError.providerMetadata : void 0
30255
+ );
30256
+ const finishReason = firstNonBlank(
30257
+ isRecord4(error) ? error.finishReason : void 0,
30258
+ metadata?.finishReason,
30259
+ isRecord4(originalError) ? originalError.finishReason : void 0
30260
+ );
30261
+ return { usage, providerMetadata, finishReason };
30262
+ }, "extractGenerationErrorDetails");
30048
30263
  var isAssistantContentPart = /* @__PURE__ */ __name((value) => {
30049
30264
  if (!isRecord4(value)) {
30050
30265
  return false;
@@ -30604,7 +30819,7 @@ var Agent = class {
30604
30819
  onStepFinish: this.createStepHandler(oc, options)
30605
30820
  })
30606
30821
  );
30607
- this.ensureStructuredOutputGenerated({
30822
+ await this.ensureStructuredOutputGenerated({
30608
30823
  result: response,
30609
30824
  output,
30610
30825
  tools,
@@ -30613,11 +30828,18 @@ var Agent = class {
30613
30828
  const resolvedProviderUsage = response.usage ? await Promise.resolve(response.usage) : void 0;
30614
30829
  finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
30615
30830
  usage: resolvedProviderUsage,
30616
- finishReason: response.finishReason
30831
+ finishReason: response.finishReason,
30832
+ providerMetadata: response.providerMetadata
30617
30833
  });
30618
30834
  return response;
30619
30835
  } catch (error) {
30620
- finalizeLLMSpan(import_api16.SpanStatusCode.ERROR, { message: error.message });
30836
+ const errorDetails = extractGenerationErrorDetails(error);
30837
+ finalizeLLMSpan(import_api16.SpanStatusCode.ERROR, {
30838
+ message: error.message,
30839
+ usage: errorDetails.usage,
30840
+ finishReason: errorDetails.finishReason,
30841
+ providerMetadata: errorDetails.providerMetadata
30842
+ });
30621
30843
  throw error;
30622
30844
  }
30623
30845
  }, "run")
@@ -30635,6 +30857,11 @@ var Agent = class {
30635
30857
  usage: providerUsage,
30636
30858
  totalUsage: result.totalUsage
30637
30859
  });
30860
+ this.recordRootSpanUsageAndProviderCost(
30861
+ oc.traceContext,
30862
+ usageForFinish,
30863
+ result.providerMetadata
30864
+ );
30638
30865
  const { toolCalls: aggregatedToolCalls, toolResults: aggregatedToolResults } = this.collectToolDataFromResult(result);
30639
30866
  const usageInfo = convertUsage(usageForFinish);
30640
30867
  const middlewareText = await runOutputMiddlewares(
@@ -30696,7 +30923,6 @@ var Agent = class {
30696
30923
  text: finalText
30697
30924
  }
30698
30925
  );
30699
- this.setTraceContextUsage(oc.traceContext, usageForFinish);
30700
30926
  oc.traceContext.setOutput(finalText);
30701
30927
  oc.traceContext.setFinishReason(result.finishReason);
30702
30928
  if (result.steps && result.steps.length >= maxSteps) {
@@ -31170,14 +31396,19 @@ var Agent = class {
31170
31396
  usage: providerUsage,
31171
31397
  totalUsage: finalResult.totalUsage
31172
31398
  });
31399
+ this.recordRootSpanUsageAndProviderCost(
31400
+ oc.traceContext,
31401
+ usageForFinish,
31402
+ finalResult.providerMetadata
31403
+ );
31173
31404
  finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
31174
31405
  usage: providerUsage,
31175
- finishReason: finalResult.finishReason
31406
+ finishReason: finalResult.finishReason,
31407
+ providerMetadata: finalResult.providerMetadata
31176
31408
  });
31177
31409
  if (!shouldDeferPersist && shouldPersistMemory) {
31178
31410
  await persistQueue.flush(buffer, oc);
31179
31411
  }
31180
- this.setTraceContextUsage(oc.traceContext, usageForFinish);
31181
31412
  const usage = convertUsage(usageForFinish);
31182
31413
  let finalText;
31183
31414
  const bailedResult = oc.systemContext.get("bailedResult");
@@ -31279,7 +31510,8 @@ var Agent = class {
31279
31510
  });
31280
31511
  finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
31281
31512
  usage: usageForFinish,
31282
- finishReason: finalResult.finishReason
31513
+ finishReason: finalResult.finishReason,
31514
+ providerMetadata: finalResult.providerMetadata
31283
31515
  });
31284
31516
  oc.traceContext.end("completed");
31285
31517
  feedbackFinalizeRequested = true;
@@ -31735,6 +31967,11 @@ var Agent = class {
31735
31967
  usage: providerUsage,
31736
31968
  totalUsage: result.totalUsage
31737
31969
  });
31970
+ this.recordRootSpanUsageAndProviderCost(
31971
+ oc.traceContext,
31972
+ usageForFinish,
31973
+ result.providerMetadata
31974
+ );
31738
31975
  const usageInfo = convertUsage(usageForFinish);
31739
31976
  const middlewareObject = await runOutputMiddlewares(
31740
31977
  result.object,
@@ -31782,7 +32019,6 @@ var Agent = class {
31782
32019
  };
31783
32020
  this.addStepToHistory(step, oc);
31784
32021
  }
31785
- this.setTraceContextUsage(oc.traceContext, usageForFinish);
31786
32022
  oc.traceContext.setOutput(finalObject);
31787
32023
  oc.output = finalObject;
31788
32024
  this.enqueueEvalScoring({
@@ -32090,6 +32326,11 @@ var Agent = class {
32090
32326
  usage: providerUsage,
32091
32327
  totalUsage: finalResult.totalUsage
32092
32328
  });
32329
+ this.recordRootSpanUsageAndProviderCost(
32330
+ oc.traceContext,
32331
+ usageForFinish,
32332
+ finalResult.providerMetadata
32333
+ );
32093
32334
  const usageInfo = convertUsage(usageForFinish);
32094
32335
  let finalObject = finalResult.object;
32095
32336
  if (guardrailSet.output.length > 0) {
@@ -32128,7 +32369,6 @@ var Agent = class {
32128
32369
  };
32129
32370
  this.addStepToHistory(step, oc);
32130
32371
  }
32131
- this.setTraceContextUsage(oc.traceContext, usageForFinish);
32132
32372
  oc.traceContext.setOutput(finalObject);
32133
32373
  oc.output = finalObject;
32134
32374
  await this.getMergedHooks(options).onEnd?.({
@@ -32351,7 +32591,7 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32351
32591
  toolResults: stepToolResults.length > 0 ? stepToolResults : result.toolResults ?? []
32352
32592
  };
32353
32593
  }
32354
- ensureStructuredOutputGenerated(params) {
32594
+ async ensureStructuredOutputGenerated(params) {
32355
32595
  const { result, output, tools, maxSteps } = params;
32356
32596
  if (!output) {
32357
32597
  return;
@@ -32368,6 +32608,13 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32368
32608
  const stepCount = result.steps?.length ?? 0;
32369
32609
  const finishReason = result.finishReason ?? "unknown";
32370
32610
  const reachedMaxSteps = stepCount >= maxSteps;
32611
+ const providerMetadata = result.providerMetadata;
32612
+ const providerUsage = result.usage ? await Promise.resolve(result.usage) : void 0;
32613
+ const usageForFinish = resolveFinishUsage({
32614
+ providerMetadata,
32615
+ usage: providerUsage,
32616
+ totalUsage: result.totalUsage
32617
+ });
32371
32618
  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
32619
  const maxStepHint = reachedMaxSteps ? ` Generation stopped after ${stepCount} steps (maxSteps=${maxSteps}).` : "";
32373
32620
  throw createVoltAgentError(
@@ -32381,7 +32628,9 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32381
32628
  stepCount,
32382
32629
  maxSteps,
32383
32630
  configuredToolCount,
32384
- toolCallCount: toolCalls.length
32631
+ toolCallCount: toolCalls.length,
32632
+ usage: usageForFinish ? JSON.parse((0, import_utils33.safeStringify)(usageForFinish)) : void 0,
32633
+ providerMetadata: providerMetadata !== void 0 ? JSON.parse((0, import_utils33.safeStringify)(providerMetadata)) : void 0
32385
32634
  }
32386
32635
  }
32387
32636
  );
@@ -32735,6 +32984,9 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32735
32984
  if (details?.usage) {
32736
32985
  this.recordLLMUsage(span, details.usage);
32737
32986
  }
32987
+ if (details?.providerMetadata !== void 0) {
32988
+ this.recordProviderCost(span, details.providerMetadata);
32989
+ }
32738
32990
  if (details?.finishReason) {
32739
32991
  span.setAttribute("llm.finish_reason", String(details.finishReason));
32740
32992
  }
@@ -32840,6 +33092,36 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
32840
33092
  span.setAttribute("llm.usage.total_tokens", totalTokens);
32841
33093
  }
32842
33094
  }
33095
+ recordProviderCost(span, providerMetadata) {
33096
+ const openRouterUsageCost = extractOpenRouterUsageCost(providerMetadata);
33097
+ if (!openRouterUsageCost) {
33098
+ return;
33099
+ }
33100
+ if (openRouterUsageCost.cost !== void 0) {
33101
+ span.setAttribute("usage.cost", openRouterUsageCost.cost);
33102
+ }
33103
+ if (openRouterUsageCost.isByok !== void 0) {
33104
+ span.setAttribute("usage.is_byok", openRouterUsageCost.isByok);
33105
+ }
33106
+ if (openRouterUsageCost.upstreamInferenceCost !== void 0) {
33107
+ span.setAttribute(
33108
+ "usage.cost_details.upstream_inference_cost",
33109
+ openRouterUsageCost.upstreamInferenceCost
33110
+ );
33111
+ }
33112
+ if (openRouterUsageCost.upstreamInferenceInputCost !== void 0) {
33113
+ span.setAttribute(
33114
+ "usage.cost_details.upstream_inference_input_cost",
33115
+ openRouterUsageCost.upstreamInferenceInputCost
33116
+ );
33117
+ }
33118
+ if (openRouterUsageCost.upstreamInferenceOutputCost !== void 0) {
33119
+ span.setAttribute(
33120
+ "usage.cost_details.upstream_inference_output_cost",
33121
+ openRouterUsageCost.upstreamInferenceOutputCost
33122
+ );
33123
+ }
33124
+ }
32843
33125
  createEvalHost() {
32844
33126
  return {
32845
33127
  id: this.id,
@@ -33044,7 +33326,8 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
33044
33326
  }
33045
33327
  finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
33046
33328
  usage: resolvedUsage,
33047
- finishReason: result.finishReason
33329
+ finishReason: result.finishReason,
33330
+ providerMetadata: result.providerMetadata
33048
33331
  });
33049
33332
  return title || null;
33050
33333
  } catch (error) {
@@ -34824,7 +35107,8 @@ ${retrieverContext}`;
34824
35107
  const resolvedUsage = response.usage ? await Promise.resolve(response.usage) : void 0;
34825
35108
  finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
34826
35109
  usage: resolvedUsage,
34827
- finishReason: response.finishReason
35110
+ finishReason: response.finishReason,
35111
+ providerMetadata: response.providerMetadata
34828
35112
  });
34829
35113
  return response;
34830
35114
  } catch (error) {
@@ -35255,7 +35539,18 @@ ${retrieverContext}`;
35255
35539
  if (!oc.isActive && oc.cancellationError) {
35256
35540
  throw oc.cancellationError;
35257
35541
  }
35258
- const voltagentError = createVoltAgentError(error);
35542
+ const voltagentError = isVoltAgentError(error) ? error : createVoltAgentError(error);
35543
+ const errorDetails = extractGenerationErrorDetails(voltagentError);
35544
+ if (errorDetails.usage || errorDetails.providerMetadata !== void 0) {
35545
+ this.recordRootSpanUsageAndProviderCost(
35546
+ oc.traceContext,
35547
+ errorDetails.usage,
35548
+ errorDetails.providerMetadata
35549
+ );
35550
+ }
35551
+ if (errorDetails.finishReason) {
35552
+ oc.traceContext.setFinishReason(errorDetails.finishReason);
35553
+ }
35259
35554
  oc.traceContext.end("error", error);
35260
35555
  const hooks = this.getMergedHooks(options);
35261
35556
  await hooks.onEnd?.({
@@ -35841,6 +36136,10 @@ ${retrieverContext}`;
35841
36136
  reasoningTokens: resolvedUsage.reasoningTokens
35842
36137
  });
35843
36138
  }
36139
+ recordRootSpanUsageAndProviderCost(traceContext, usage, providerMetadata) {
36140
+ this.setTraceContextUsage(traceContext, usage);
36141
+ this.recordProviderCost(traceContext.getRootSpan(), providerMetadata);
36142
+ }
35844
36143
  /**
35845
36144
  * Create working memory tools if configured
35846
36145
  */