@voltagent/core 2.6.8 → 2.6.10
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 +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +168 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +168 -9
- package/dist/index.mjs.map +1 -1
- package/docs/observability-platform/llm-usage-and-costs.md +122 -2
- package/package.json +1 -1
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
|
*/
|
|
@@ -26315,6 +26359,10 @@ var AgentTraceContext = class {
|
|
|
26315
26359
|
function addModelAttributesToSpan(span, modelName, options, defaultMaxOutputTokens, defaultTemperature) {
|
|
26316
26360
|
if (!span) return;
|
|
26317
26361
|
span.setAttribute("ai.model.name", modelName);
|
|
26362
|
+
const provider = typeof modelName === "string" && modelName.includes("/") ? modelName.split("/")[0] : void 0;
|
|
26363
|
+
if (provider) {
|
|
26364
|
+
span.setAttribute("ai.model.provider", provider);
|
|
26365
|
+
}
|
|
26318
26366
|
const temperature = options?.temperature ?? options?.providerOptions?.temperature ?? defaultTemperature;
|
|
26319
26367
|
if (temperature !== void 0 && typeof temperature === "number") {
|
|
26320
26368
|
span.setAttribute("ai.model.temperature", temperature);
|
|
@@ -30028,6 +30076,7 @@ var DEFAULT_CONVERSATION_PERSISTENCE_OPTIONS = {
|
|
|
30028
30076
|
flushOnToolResult: true
|
|
30029
30077
|
};
|
|
30030
30078
|
var isRecord4 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null, "isRecord");
|
|
30079
|
+
var isPlainObject = /* @__PURE__ */ __name((value) => isRecord4(value) && !Array.isArray(value), "isPlainObject");
|
|
30031
30080
|
var hasNonEmptyString2 = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim().length > 0, "hasNonEmptyString");
|
|
30032
30081
|
var firstNonBlank = /* @__PURE__ */ __name((...values) => {
|
|
30033
30082
|
for (const value of values) {
|
|
@@ -30045,6 +30094,58 @@ var firstDefined = /* @__PURE__ */ __name((...values) => {
|
|
|
30045
30094
|
}
|
|
30046
30095
|
return void 0;
|
|
30047
30096
|
}, "firstDefined");
|
|
30097
|
+
var toFiniteNumber = /* @__PURE__ */ __name((value) => {
|
|
30098
|
+
if (typeof value === "number") {
|
|
30099
|
+
return Number.isFinite(value) ? value : void 0;
|
|
30100
|
+
}
|
|
30101
|
+
if (typeof value === "string") {
|
|
30102
|
+
const parsed = Number(value);
|
|
30103
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
30104
|
+
}
|
|
30105
|
+
return void 0;
|
|
30106
|
+
}, "toFiniteNumber");
|
|
30107
|
+
var toBoolean = /* @__PURE__ */ __name((value) => {
|
|
30108
|
+
if (typeof value === "boolean") {
|
|
30109
|
+
return value;
|
|
30110
|
+
}
|
|
30111
|
+
if (typeof value === "string") {
|
|
30112
|
+
const normalized = value.trim().toLowerCase();
|
|
30113
|
+
if (normalized === "true") return true;
|
|
30114
|
+
if (normalized === "false") return false;
|
|
30115
|
+
}
|
|
30116
|
+
return void 0;
|
|
30117
|
+
}, "toBoolean");
|
|
30118
|
+
var extractOpenRouterUsageCost = /* @__PURE__ */ __name((providerMetadata) => {
|
|
30119
|
+
if (!isPlainObject(providerMetadata)) {
|
|
30120
|
+
return void 0;
|
|
30121
|
+
}
|
|
30122
|
+
const openRouterMetadata = isPlainObject(providerMetadata.openrouter) ? providerMetadata.openrouter : void 0;
|
|
30123
|
+
const usage = openRouterMetadata && isPlainObject(openRouterMetadata.usage) ? openRouterMetadata.usage : void 0;
|
|
30124
|
+
if (!usage) {
|
|
30125
|
+
return void 0;
|
|
30126
|
+
}
|
|
30127
|
+
const costDetails = firstDefined(
|
|
30128
|
+
isPlainObject(usage.costDetails) ? usage.costDetails : void 0,
|
|
30129
|
+
isPlainObject(usage.cost_details) ? usage.cost_details : void 0
|
|
30130
|
+
);
|
|
30131
|
+
const result = {
|
|
30132
|
+
cost: toFiniteNumber(usage.cost),
|
|
30133
|
+
isByok: firstDefined(toBoolean(usage.isByok), toBoolean(usage.is_byok)),
|
|
30134
|
+
upstreamInferenceCost: firstDefined(
|
|
30135
|
+
toFiniteNumber(costDetails?.upstreamInferenceCost),
|
|
30136
|
+
toFiniteNumber(costDetails?.upstream_inference_cost)
|
|
30137
|
+
),
|
|
30138
|
+
upstreamInferenceInputCost: firstDefined(
|
|
30139
|
+
toFiniteNumber(costDetails?.upstreamInferenceInputCost),
|
|
30140
|
+
toFiniteNumber(costDetails?.upstream_inference_input_cost)
|
|
30141
|
+
),
|
|
30142
|
+
upstreamInferenceOutputCost: firstDefined(
|
|
30143
|
+
toFiniteNumber(costDetails?.upstreamInferenceOutputCost),
|
|
30144
|
+
toFiniteNumber(costDetails?.upstream_inference_output_cost)
|
|
30145
|
+
)
|
|
30146
|
+
};
|
|
30147
|
+
return Object.values(result).some((value) => value !== void 0) ? result : void 0;
|
|
30148
|
+
}, "extractOpenRouterUsageCost");
|
|
30048
30149
|
var isAssistantContentPart = /* @__PURE__ */ __name((value) => {
|
|
30049
30150
|
if (!isRecord4(value)) {
|
|
30050
30151
|
return false;
|
|
@@ -30613,7 +30714,8 @@ var Agent = class {
|
|
|
30613
30714
|
const resolvedProviderUsage = response.usage ? await Promise.resolve(response.usage) : void 0;
|
|
30614
30715
|
finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
|
|
30615
30716
|
usage: resolvedProviderUsage,
|
|
30616
|
-
finishReason: response.finishReason
|
|
30717
|
+
finishReason: response.finishReason,
|
|
30718
|
+
providerMetadata: response.providerMetadata
|
|
30617
30719
|
});
|
|
30618
30720
|
return response;
|
|
30619
30721
|
} catch (error) {
|
|
@@ -30635,6 +30737,11 @@ var Agent = class {
|
|
|
30635
30737
|
usage: providerUsage,
|
|
30636
30738
|
totalUsage: result.totalUsage
|
|
30637
30739
|
});
|
|
30740
|
+
this.recordRootSpanUsageAndProviderCost(
|
|
30741
|
+
oc.traceContext,
|
|
30742
|
+
usageForFinish,
|
|
30743
|
+
result.providerMetadata
|
|
30744
|
+
);
|
|
30638
30745
|
const { toolCalls: aggregatedToolCalls, toolResults: aggregatedToolResults } = this.collectToolDataFromResult(result);
|
|
30639
30746
|
const usageInfo = convertUsage(usageForFinish);
|
|
30640
30747
|
const middlewareText = await runOutputMiddlewares(
|
|
@@ -30696,7 +30803,6 @@ var Agent = class {
|
|
|
30696
30803
|
text: finalText
|
|
30697
30804
|
}
|
|
30698
30805
|
);
|
|
30699
|
-
this.setTraceContextUsage(oc.traceContext, usageForFinish);
|
|
30700
30806
|
oc.traceContext.setOutput(finalText);
|
|
30701
30807
|
oc.traceContext.setFinishReason(result.finishReason);
|
|
30702
30808
|
if (result.steps && result.steps.length >= maxSteps) {
|
|
@@ -31170,14 +31276,19 @@ var Agent = class {
|
|
|
31170
31276
|
usage: providerUsage,
|
|
31171
31277
|
totalUsage: finalResult.totalUsage
|
|
31172
31278
|
});
|
|
31279
|
+
this.recordRootSpanUsageAndProviderCost(
|
|
31280
|
+
oc.traceContext,
|
|
31281
|
+
usageForFinish,
|
|
31282
|
+
finalResult.providerMetadata
|
|
31283
|
+
);
|
|
31173
31284
|
finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
|
|
31174
31285
|
usage: providerUsage,
|
|
31175
|
-
finishReason: finalResult.finishReason
|
|
31286
|
+
finishReason: finalResult.finishReason,
|
|
31287
|
+
providerMetadata: finalResult.providerMetadata
|
|
31176
31288
|
});
|
|
31177
31289
|
if (!shouldDeferPersist && shouldPersistMemory) {
|
|
31178
31290
|
await persistQueue.flush(buffer, oc);
|
|
31179
31291
|
}
|
|
31180
|
-
this.setTraceContextUsage(oc.traceContext, usageForFinish);
|
|
31181
31292
|
const usage = convertUsage(usageForFinish);
|
|
31182
31293
|
let finalText;
|
|
31183
31294
|
const bailedResult = oc.systemContext.get("bailedResult");
|
|
@@ -31279,7 +31390,8 @@ var Agent = class {
|
|
|
31279
31390
|
});
|
|
31280
31391
|
finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
|
|
31281
31392
|
usage: usageForFinish,
|
|
31282
|
-
finishReason: finalResult.finishReason
|
|
31393
|
+
finishReason: finalResult.finishReason,
|
|
31394
|
+
providerMetadata: finalResult.providerMetadata
|
|
31283
31395
|
});
|
|
31284
31396
|
oc.traceContext.end("completed");
|
|
31285
31397
|
feedbackFinalizeRequested = true;
|
|
@@ -31735,6 +31847,11 @@ var Agent = class {
|
|
|
31735
31847
|
usage: providerUsage,
|
|
31736
31848
|
totalUsage: result.totalUsage
|
|
31737
31849
|
});
|
|
31850
|
+
this.recordRootSpanUsageAndProviderCost(
|
|
31851
|
+
oc.traceContext,
|
|
31852
|
+
usageForFinish,
|
|
31853
|
+
result.providerMetadata
|
|
31854
|
+
);
|
|
31738
31855
|
const usageInfo = convertUsage(usageForFinish);
|
|
31739
31856
|
const middlewareObject = await runOutputMiddlewares(
|
|
31740
31857
|
result.object,
|
|
@@ -31782,7 +31899,6 @@ var Agent = class {
|
|
|
31782
31899
|
};
|
|
31783
31900
|
this.addStepToHistory(step, oc);
|
|
31784
31901
|
}
|
|
31785
|
-
this.setTraceContextUsage(oc.traceContext, usageForFinish);
|
|
31786
31902
|
oc.traceContext.setOutput(finalObject);
|
|
31787
31903
|
oc.output = finalObject;
|
|
31788
31904
|
this.enqueueEvalScoring({
|
|
@@ -32090,6 +32206,11 @@ var Agent = class {
|
|
|
32090
32206
|
usage: providerUsage,
|
|
32091
32207
|
totalUsage: finalResult.totalUsage
|
|
32092
32208
|
});
|
|
32209
|
+
this.recordRootSpanUsageAndProviderCost(
|
|
32210
|
+
oc.traceContext,
|
|
32211
|
+
usageForFinish,
|
|
32212
|
+
finalResult.providerMetadata
|
|
32213
|
+
);
|
|
32093
32214
|
const usageInfo = convertUsage(usageForFinish);
|
|
32094
32215
|
let finalObject = finalResult.object;
|
|
32095
32216
|
if (guardrailSet.output.length > 0) {
|
|
@@ -32128,7 +32249,6 @@ var Agent = class {
|
|
|
32128
32249
|
};
|
|
32129
32250
|
this.addStepToHistory(step, oc);
|
|
32130
32251
|
}
|
|
32131
|
-
this.setTraceContextUsage(oc.traceContext, usageForFinish);
|
|
32132
32252
|
oc.traceContext.setOutput(finalObject);
|
|
32133
32253
|
oc.output = finalObject;
|
|
32134
32254
|
await this.getMergedHooks(options).onEnd?.({
|
|
@@ -32735,6 +32855,9 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
|
|
|
32735
32855
|
if (details?.usage) {
|
|
32736
32856
|
this.recordLLMUsage(span, details.usage);
|
|
32737
32857
|
}
|
|
32858
|
+
if (details?.providerMetadata !== void 0) {
|
|
32859
|
+
this.recordProviderCost(span, details.providerMetadata);
|
|
32860
|
+
}
|
|
32738
32861
|
if (details?.finishReason) {
|
|
32739
32862
|
span.setAttribute("llm.finish_reason", String(details.finishReason));
|
|
32740
32863
|
}
|
|
@@ -32840,6 +32963,36 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
|
|
|
32840
32963
|
span.setAttribute("llm.usage.total_tokens", totalTokens);
|
|
32841
32964
|
}
|
|
32842
32965
|
}
|
|
32966
|
+
recordProviderCost(span, providerMetadata) {
|
|
32967
|
+
const openRouterUsageCost = extractOpenRouterUsageCost(providerMetadata);
|
|
32968
|
+
if (!openRouterUsageCost) {
|
|
32969
|
+
return;
|
|
32970
|
+
}
|
|
32971
|
+
if (openRouterUsageCost.cost !== void 0) {
|
|
32972
|
+
span.setAttribute("usage.cost", openRouterUsageCost.cost);
|
|
32973
|
+
}
|
|
32974
|
+
if (openRouterUsageCost.isByok !== void 0) {
|
|
32975
|
+
span.setAttribute("usage.is_byok", openRouterUsageCost.isByok);
|
|
32976
|
+
}
|
|
32977
|
+
if (openRouterUsageCost.upstreamInferenceCost !== void 0) {
|
|
32978
|
+
span.setAttribute(
|
|
32979
|
+
"usage.cost_details.upstream_inference_cost",
|
|
32980
|
+
openRouterUsageCost.upstreamInferenceCost
|
|
32981
|
+
);
|
|
32982
|
+
}
|
|
32983
|
+
if (openRouterUsageCost.upstreamInferenceInputCost !== void 0) {
|
|
32984
|
+
span.setAttribute(
|
|
32985
|
+
"usage.cost_details.upstream_inference_input_cost",
|
|
32986
|
+
openRouterUsageCost.upstreamInferenceInputCost
|
|
32987
|
+
);
|
|
32988
|
+
}
|
|
32989
|
+
if (openRouterUsageCost.upstreamInferenceOutputCost !== void 0) {
|
|
32990
|
+
span.setAttribute(
|
|
32991
|
+
"usage.cost_details.upstream_inference_output_cost",
|
|
32992
|
+
openRouterUsageCost.upstreamInferenceOutputCost
|
|
32993
|
+
);
|
|
32994
|
+
}
|
|
32995
|
+
}
|
|
32843
32996
|
createEvalHost() {
|
|
32844
32997
|
return {
|
|
32845
32998
|
id: this.id,
|
|
@@ -33044,7 +33197,8 @@ Metadata: ${(0, import_utils33.safeStringify)(metadata)}`;
|
|
|
33044
33197
|
}
|
|
33045
33198
|
finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
|
|
33046
33199
|
usage: resolvedUsage,
|
|
33047
|
-
finishReason: result.finishReason
|
|
33200
|
+
finishReason: result.finishReason,
|
|
33201
|
+
providerMetadata: result.providerMetadata
|
|
33048
33202
|
});
|
|
33049
33203
|
return title || null;
|
|
33050
33204
|
} catch (error) {
|
|
@@ -34824,7 +34978,8 @@ ${retrieverContext}`;
|
|
|
34824
34978
|
const resolvedUsage = response.usage ? await Promise.resolve(response.usage) : void 0;
|
|
34825
34979
|
finalizeLLMSpan(import_api16.SpanStatusCode.OK, {
|
|
34826
34980
|
usage: resolvedUsage,
|
|
34827
|
-
finishReason: response.finishReason
|
|
34981
|
+
finishReason: response.finishReason,
|
|
34982
|
+
providerMetadata: response.providerMetadata
|
|
34828
34983
|
});
|
|
34829
34984
|
return response;
|
|
34830
34985
|
} catch (error) {
|
|
@@ -35841,6 +35996,10 @@ ${retrieverContext}`;
|
|
|
35841
35996
|
reasoningTokens: resolvedUsage.reasoningTokens
|
|
35842
35997
|
});
|
|
35843
35998
|
}
|
|
35999
|
+
recordRootSpanUsageAndProviderCost(traceContext, usage, providerMetadata) {
|
|
36000
|
+
this.setTraceContextUsage(traceContext, usage);
|
|
36001
|
+
this.recordProviderCost(traceContext.getRootSpan(), providerMetadata);
|
|
36002
|
+
}
|
|
35844
36003
|
/**
|
|
35845
36004
|
* Create working memory tools if configured
|
|
35846
36005
|
*/
|