@sentrial/sdk 0.4.2 → 0.4.4
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.cjs +391 -291
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -6
- package/dist/index.d.ts +14 -6
- package/dist/index.js +391 -291
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -364,8 +364,18 @@ function wrapOpenAI(client, options = {}) {
|
|
|
364
364
|
const completionTokens = response.usage?.completion_tokens ?? 0;
|
|
365
365
|
const totalTokens = response.usage?.total_tokens ?? 0;
|
|
366
366
|
let outputContent = "";
|
|
367
|
-
|
|
368
|
-
|
|
367
|
+
const toolCalls = [];
|
|
368
|
+
const msg = response.choices?.[0]?.message;
|
|
369
|
+
if (msg?.content) {
|
|
370
|
+
outputContent = msg.content;
|
|
371
|
+
}
|
|
372
|
+
if (msg?.tool_calls) {
|
|
373
|
+
for (const tc of msg.tool_calls) {
|
|
374
|
+
toolCalls.push({
|
|
375
|
+
name: tc.function?.name ?? "unknown",
|
|
376
|
+
arguments: tc.function?.arguments ?? "{}"
|
|
377
|
+
});
|
|
378
|
+
}
|
|
369
379
|
}
|
|
370
380
|
const cost = calculateOpenAICost({ model, inputTokens: promptTokens, outputTokens: completionTokens });
|
|
371
381
|
trackLLMCall({
|
|
@@ -373,6 +383,7 @@ function wrapOpenAI(client, options = {}) {
|
|
|
373
383
|
model,
|
|
374
384
|
messages,
|
|
375
385
|
output: outputContent,
|
|
386
|
+
toolCalls,
|
|
376
387
|
promptTokens,
|
|
377
388
|
completionTokens,
|
|
378
389
|
totalTokens,
|
|
@@ -427,10 +438,16 @@ function wrapAnthropic(client, options = {}) {
|
|
|
427
438
|
const completionTokens = response.usage?.output_tokens ?? 0;
|
|
428
439
|
const totalTokens = promptTokens + completionTokens;
|
|
429
440
|
let outputContent = "";
|
|
441
|
+
const toolCalls = [];
|
|
430
442
|
if (response.content) {
|
|
431
443
|
for (const block of response.content) {
|
|
432
444
|
if (block.type === "text") {
|
|
433
445
|
outputContent += block.text;
|
|
446
|
+
} else if (block.type === "tool_use") {
|
|
447
|
+
toolCalls.push({
|
|
448
|
+
name: block.name ?? "unknown",
|
|
449
|
+
arguments: JSON.stringify(block.input ?? {})
|
|
450
|
+
});
|
|
434
451
|
}
|
|
435
452
|
}
|
|
436
453
|
}
|
|
@@ -441,6 +458,7 @@ function wrapAnthropic(client, options = {}) {
|
|
|
441
458
|
model,
|
|
442
459
|
messages: fullMessages,
|
|
443
460
|
output: outputContent,
|
|
461
|
+
toolCalls,
|
|
444
462
|
promptTokens,
|
|
445
463
|
completionTokens,
|
|
446
464
|
totalTokens,
|
|
@@ -554,6 +572,7 @@ function wrapLLM(client, provider) {
|
|
|
554
572
|
function wrapOpenAIStream(stream, ctx) {
|
|
555
573
|
let fullContent = "";
|
|
556
574
|
let usage = null;
|
|
575
|
+
const toolCallMap = /* @__PURE__ */ new Map();
|
|
557
576
|
let tracked = false;
|
|
558
577
|
const originalIterator = stream[Symbol.asyncIterator]?.bind(stream);
|
|
559
578
|
if (!originalIterator) return stream;
|
|
@@ -570,6 +589,7 @@ function wrapOpenAIStream(stream, ctx) {
|
|
|
570
589
|
model: ctx.model,
|
|
571
590
|
messages: ctx.messages,
|
|
572
591
|
output: fullContent,
|
|
592
|
+
toolCalls: Array.from(toolCallMap.values()),
|
|
573
593
|
promptTokens,
|
|
574
594
|
completionTokens,
|
|
575
595
|
totalTokens,
|
|
@@ -588,8 +608,17 @@ function wrapOpenAIStream(stream, ctx) {
|
|
|
588
608
|
const result = await iter.next();
|
|
589
609
|
if (!result.done) {
|
|
590
610
|
const chunk = result.value;
|
|
591
|
-
const delta = chunk.choices?.[0]?.delta
|
|
592
|
-
if (delta) fullContent += delta;
|
|
611
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
612
|
+
if (delta?.content) fullContent += delta.content;
|
|
613
|
+
if (delta?.tool_calls) {
|
|
614
|
+
for (const tc of delta.tool_calls) {
|
|
615
|
+
const idx = tc.index ?? 0;
|
|
616
|
+
const existing = toolCallMap.get(idx) ?? { name: "", arguments: "" };
|
|
617
|
+
if (tc.function?.name) existing.name = tc.function.name;
|
|
618
|
+
if (tc.function?.arguments) existing.arguments += tc.function.arguments;
|
|
619
|
+
toolCallMap.set(idx, existing);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
593
622
|
if (chunk.usage) usage = chunk.usage;
|
|
594
623
|
} else {
|
|
595
624
|
trackResult();
|
|
@@ -614,6 +643,8 @@ function wrapAnthropicStream(stream, ctx) {
|
|
|
614
643
|
let fullContent = "";
|
|
615
644
|
let inputTokens = 0;
|
|
616
645
|
let outputTokens = 0;
|
|
646
|
+
const toolCallsById = /* @__PURE__ */ new Map();
|
|
647
|
+
let currentBlockIdx = -1;
|
|
617
648
|
let tracked = false;
|
|
618
649
|
const originalIterator = stream[Symbol.asyncIterator]?.bind(stream);
|
|
619
650
|
if (!originalIterator) return stream;
|
|
@@ -629,6 +660,7 @@ function wrapAnthropicStream(stream, ctx) {
|
|
|
629
660
|
model: ctx.model,
|
|
630
661
|
messages: fullMessages,
|
|
631
662
|
output: fullContent,
|
|
663
|
+
toolCalls: Array.from(toolCallsById.values()),
|
|
632
664
|
promptTokens: inputTokens,
|
|
633
665
|
completionTokens: outputTokens,
|
|
634
666
|
totalTokens,
|
|
@@ -647,8 +679,26 @@ function wrapAnthropicStream(stream, ctx) {
|
|
|
647
679
|
const result = await iter.next();
|
|
648
680
|
if (!result.done) {
|
|
649
681
|
const event = result.value;
|
|
650
|
-
if (event.type === "
|
|
651
|
-
|
|
682
|
+
if (event.type === "content_block_start") {
|
|
683
|
+
currentBlockIdx = event.index ?? currentBlockIdx + 1;
|
|
684
|
+
if (event.content_block?.type === "tool_use") {
|
|
685
|
+
toolCallsById.set(currentBlockIdx, {
|
|
686
|
+
name: event.content_block.name ?? "unknown",
|
|
687
|
+
arguments: ""
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
if (event.type === "content_block_delta") {
|
|
692
|
+
if (event.delta?.text) {
|
|
693
|
+
fullContent += event.delta.text;
|
|
694
|
+
}
|
|
695
|
+
if (event.delta?.type === "input_json_delta" && event.delta?.partial_json) {
|
|
696
|
+
const idx = event.index ?? currentBlockIdx;
|
|
697
|
+
const existing = toolCallsById.get(idx);
|
|
698
|
+
if (existing) {
|
|
699
|
+
existing.arguments += event.delta.partial_json;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
652
702
|
}
|
|
653
703
|
if (event.type === "message_start" && event.message?.usage) {
|
|
654
704
|
inputTokens = event.message.usage.input_tokens ?? 0;
|
|
@@ -682,6 +732,18 @@ function trackLLMCall(params) {
|
|
|
682
732
|
if (!sessionId && !params.trackWithoutSession) {
|
|
683
733
|
return;
|
|
684
734
|
}
|
|
735
|
+
const toolOutput = {
|
|
736
|
+
content: params.output,
|
|
737
|
+
tokens: {
|
|
738
|
+
prompt: params.promptTokens,
|
|
739
|
+
completion: params.completionTokens,
|
|
740
|
+
total: params.totalTokens
|
|
741
|
+
},
|
|
742
|
+
cost_usd: params.cost
|
|
743
|
+
};
|
|
744
|
+
if (params.toolCalls && params.toolCalls.length > 0) {
|
|
745
|
+
toolOutput.tool_calls = params.toolCalls;
|
|
746
|
+
}
|
|
685
747
|
if (sessionId) {
|
|
686
748
|
client.trackToolCall({
|
|
687
749
|
sessionId,
|
|
@@ -691,15 +753,7 @@ function trackLLMCall(params) {
|
|
|
691
753
|
model: params.model,
|
|
692
754
|
provider: params.provider
|
|
693
755
|
},
|
|
694
|
-
toolOutput
|
|
695
|
-
content: params.output,
|
|
696
|
-
tokens: {
|
|
697
|
-
prompt: params.promptTokens,
|
|
698
|
-
completion: params.completionTokens,
|
|
699
|
-
total: params.totalTokens
|
|
700
|
-
},
|
|
701
|
-
cost_usd: params.cost
|
|
702
|
-
},
|
|
756
|
+
toolOutput,
|
|
703
757
|
reasoning: `LLM call to ${params.provider} ${params.model}`,
|
|
704
758
|
estimatedCost: params.cost,
|
|
705
759
|
tokenCount: params.totalTokens,
|
|
@@ -728,15 +782,7 @@ function trackLLMCall(params) {
|
|
|
728
782
|
model: params.model,
|
|
729
783
|
provider: params.provider
|
|
730
784
|
},
|
|
731
|
-
toolOutput
|
|
732
|
-
content: params.output,
|
|
733
|
-
tokens: {
|
|
734
|
-
prompt: params.promptTokens,
|
|
735
|
-
completion: params.completionTokens,
|
|
736
|
-
total: params.totalTokens
|
|
737
|
-
},
|
|
738
|
-
cost_usd: params.cost
|
|
739
|
-
},
|
|
785
|
+
toolOutput,
|
|
740
786
|
estimatedCost: params.cost,
|
|
741
787
|
tokenCount: params.totalTokens,
|
|
742
788
|
metadata: {
|
|
@@ -1519,6 +1565,7 @@ function getClient() {
|
|
|
1519
1565
|
}
|
|
1520
1566
|
function configure(config) {
|
|
1521
1567
|
defaultClient = new SentrialClient(config);
|
|
1568
|
+
setDefaultClient(defaultClient);
|
|
1522
1569
|
}
|
|
1523
1570
|
function begin(params) {
|
|
1524
1571
|
return getClient().begin(params);
|
|
@@ -1537,6 +1584,10 @@ var sentrial = {
|
|
|
1537
1584
|
};
|
|
1538
1585
|
|
|
1539
1586
|
// src/vercel.ts
|
|
1587
|
+
function resolveStringOrFn(value, fallback) {
|
|
1588
|
+
if (typeof value === "function") return value() ?? fallback;
|
|
1589
|
+
return value ?? fallback;
|
|
1590
|
+
}
|
|
1540
1591
|
var _defaultClient2 = null;
|
|
1541
1592
|
var _globalConfig = {};
|
|
1542
1593
|
function configureVercel(config) {
|
|
@@ -1545,6 +1596,7 @@ function configureVercel(config) {
|
|
|
1545
1596
|
apiUrl: config.apiUrl,
|
|
1546
1597
|
failSilently: config.failSilently ?? true
|
|
1547
1598
|
});
|
|
1599
|
+
setDefaultClient(_defaultClient2);
|
|
1548
1600
|
_globalConfig = {
|
|
1549
1601
|
defaultAgent: config.defaultAgent,
|
|
1550
1602
|
userId: config.userId,
|
|
@@ -1559,7 +1611,8 @@ function getClient2() {
|
|
|
1559
1611
|
}
|
|
1560
1612
|
function extractModelInfo(model) {
|
|
1561
1613
|
const modelId = model.modelId || model.id || "unknown";
|
|
1562
|
-
const
|
|
1614
|
+
const rawProvider = model.provider || "";
|
|
1615
|
+
const provider = rawProvider.split(".")[0] || guessProvider(modelId);
|
|
1563
1616
|
return { modelId, provider };
|
|
1564
1617
|
}
|
|
1565
1618
|
function guessProvider(modelId) {
|
|
@@ -1593,17 +1646,38 @@ function calculateCostForCall(provider, modelId, promptTokens, completionTokens)
|
|
|
1593
1646
|
return 0;
|
|
1594
1647
|
}
|
|
1595
1648
|
}
|
|
1649
|
+
function extractContentText(content) {
|
|
1650
|
+
if (typeof content === "string") return content;
|
|
1651
|
+
if (Array.isArray(content)) {
|
|
1652
|
+
const textParts = content.filter((part) => part && part.type === "text" && typeof part.text === "string").map((part) => part.text);
|
|
1653
|
+
if (textParts.length > 0) return textParts.join("\n");
|
|
1654
|
+
}
|
|
1655
|
+
return JSON.stringify(content);
|
|
1656
|
+
}
|
|
1596
1657
|
function extractInput(params) {
|
|
1597
1658
|
if (params.prompt) return params.prompt;
|
|
1598
1659
|
if (params.messages && params.messages.length > 0) {
|
|
1599
1660
|
const lastUserMessage = [...params.messages].reverse().find((m) => m.role === "user");
|
|
1600
1661
|
if (lastUserMessage) {
|
|
1601
|
-
return
|
|
1662
|
+
return extractContentText(lastUserMessage.content);
|
|
1663
|
+
}
|
|
1664
|
+
const lastNonSystem = [...params.messages].reverse().find((m) => m.role !== "system");
|
|
1665
|
+
if (lastNonSystem) {
|
|
1666
|
+
return extractContentText(lastNonSystem.content);
|
|
1602
1667
|
}
|
|
1603
|
-
return
|
|
1668
|
+
return "";
|
|
1604
1669
|
}
|
|
1605
1670
|
return "";
|
|
1606
1671
|
}
|
|
1672
|
+
function normalizeUsage(usage) {
|
|
1673
|
+
if (!usage) return void 0;
|
|
1674
|
+
const u = usage;
|
|
1675
|
+
const promptTokens = (u.inputTokens ?? u.promptTokens ?? 0) || 0;
|
|
1676
|
+
const completionTokens = (u.outputTokens ?? u.completionTokens ?? 0) || 0;
|
|
1677
|
+
const totalTokens = (u.totalTokens ?? promptTokens + completionTokens) || 0;
|
|
1678
|
+
if (promptTokens === 0 && completionTokens === 0 && totalTokens === 0) return void 0;
|
|
1679
|
+
return { promptTokens, completionTokens, totalTokens };
|
|
1680
|
+
}
|
|
1607
1681
|
function wrapTools(tools, sessionId, client) {
|
|
1608
1682
|
if (!tools) return void 0;
|
|
1609
1683
|
const wrappedTools = {};
|
|
@@ -1656,34 +1730,37 @@ function wrapToolsAsync(tools, sessionPromise, client) {
|
|
|
1656
1730
|
...tool,
|
|
1657
1731
|
execute: async (...args) => {
|
|
1658
1732
|
const startTime = Date.now();
|
|
1659
|
-
const sid = await sessionPromise;
|
|
1660
1733
|
try {
|
|
1661
1734
|
const result = await originalExecute(...args);
|
|
1662
1735
|
const durationMs = Date.now() - startTime;
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1736
|
+
sessionPromise.then((sid) => {
|
|
1737
|
+
if (sid) {
|
|
1738
|
+
client.trackToolCall({
|
|
1739
|
+
sessionId: sid,
|
|
1740
|
+
toolName,
|
|
1741
|
+
toolInput: args[0],
|
|
1742
|
+
toolOutput: result,
|
|
1743
|
+
reasoning: `Tool executed in ${durationMs}ms`
|
|
1744
|
+
}).catch(() => {
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1673
1748
|
return result;
|
|
1674
1749
|
} catch (error) {
|
|
1675
1750
|
const durationMs = Date.now() - startTime;
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1751
|
+
sessionPromise.then((sid) => {
|
|
1752
|
+
if (sid) {
|
|
1753
|
+
client.trackToolCall({
|
|
1754
|
+
sessionId: sid,
|
|
1755
|
+
toolName,
|
|
1756
|
+
toolInput: args[0],
|
|
1757
|
+
toolOutput: {},
|
|
1758
|
+
toolError: { message: error instanceof Error ? error.message : "Unknown error" },
|
|
1759
|
+
reasoning: `Tool failed after ${durationMs}ms`
|
|
1760
|
+
}).catch(() => {
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1687
1764
|
throw error;
|
|
1688
1765
|
}
|
|
1689
1766
|
}
|
|
@@ -1702,8 +1779,8 @@ function wrapGenerateText(originalFn, client, config) {
|
|
|
1702
1779
|
const sessionId = await client.createSession({
|
|
1703
1780
|
name: `generateText: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
1704
1781
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
1705
|
-
userId: config.userId
|
|
1706
|
-
convoId: config.convoId,
|
|
1782
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
1783
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
1707
1784
|
metadata: {
|
|
1708
1785
|
model: modelId,
|
|
1709
1786
|
provider,
|
|
@@ -1723,44 +1800,50 @@ function wrapGenerateText(originalFn, client, config) {
|
|
|
1723
1800
|
const result = await originalFn(wrappedParams);
|
|
1724
1801
|
const durationMs = Date.now() - startTime;
|
|
1725
1802
|
const resolvedModelId = result.response?.modelId || modelId;
|
|
1726
|
-
const
|
|
1727
|
-
const
|
|
1728
|
-
const
|
|
1803
|
+
const usage = normalizeUsage(result.usage);
|
|
1804
|
+
const promptTokens = usage?.promptTokens ?? 0;
|
|
1805
|
+
const completionTokens = usage?.completionTokens ?? 0;
|
|
1806
|
+
const totalTokens = usage?.totalTokens ?? 0;
|
|
1729
1807
|
const cost = calculateCostForCall(provider, resolvedModelId, promptTokens, completionTokens);
|
|
1730
1808
|
const steps = result.steps;
|
|
1731
1809
|
if (steps && steps.length >= 1) {
|
|
1732
|
-
const stepPromises = steps.map(
|
|
1733
|
-
|
|
1810
|
+
const stepPromises = steps.map((step) => {
|
|
1811
|
+
const su = normalizeUsage(step.usage);
|
|
1812
|
+
return client.trackToolCall({
|
|
1734
1813
|
sessionId,
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1814
|
+
toolName: `llm:${provider}:${resolvedModelId}`,
|
|
1815
|
+
toolInput: { finishReason: step.finishReason },
|
|
1816
|
+
toolOutput: {
|
|
1817
|
+
text: step.text?.slice(0, 500),
|
|
1818
|
+
tokens: {
|
|
1819
|
+
prompt: su?.promptTokens ?? 0,
|
|
1820
|
+
completion: su?.completionTokens ?? 0
|
|
1821
|
+
}
|
|
1822
|
+
},
|
|
1823
|
+
estimatedCost: calculateCostForCall(provider, resolvedModelId, su?.promptTokens ?? 0, su?.completionTokens ?? 0),
|
|
1824
|
+
tokenCount: su?.totalTokens,
|
|
1825
|
+
metadata: {
|
|
1745
1826
|
tool_calls: step.toolCalls?.map((tc) => tc.toolName)
|
|
1746
1827
|
}
|
|
1747
1828
|
}).catch(() => {
|
|
1748
|
-
})
|
|
1749
|
-
);
|
|
1829
|
+
});
|
|
1830
|
+
});
|
|
1750
1831
|
await Promise.all(stepPromises);
|
|
1751
1832
|
} else {
|
|
1752
|
-
await client.
|
|
1833
|
+
await client.trackToolCall({
|
|
1753
1834
|
sessionId,
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1835
|
+
toolName: `llm:${provider}:${resolvedModelId}`,
|
|
1836
|
+
toolInput: { finishReason: result.finishReason },
|
|
1837
|
+
toolOutput: {
|
|
1838
|
+
text: result.text?.slice(0, 500),
|
|
1839
|
+
tokens: { prompt: promptTokens, completion: completionTokens }
|
|
1840
|
+
},
|
|
1841
|
+
estimatedCost: cost,
|
|
1842
|
+
tokenCount: totalTokens,
|
|
1843
|
+
metadata: {
|
|
1762
1844
|
tool_calls: result.toolCalls?.map((tc) => tc.toolName)
|
|
1763
1845
|
}
|
|
1846
|
+
}).catch(() => {
|
|
1764
1847
|
});
|
|
1765
1848
|
}
|
|
1766
1849
|
await client.completeSession({
|
|
@@ -1797,13 +1880,18 @@ function wrapStreamText(originalFn, client, config) {
|
|
|
1797
1880
|
const { modelId, provider } = extractModelInfo(params.model);
|
|
1798
1881
|
const input = extractInput(params);
|
|
1799
1882
|
let sessionId = null;
|
|
1800
|
-
|
|
1883
|
+
let sessionCompleted = false;
|
|
1884
|
+
let resolveSessionReady;
|
|
1885
|
+
const sessionReady = new Promise((resolve) => {
|
|
1886
|
+
resolveSessionReady = resolve;
|
|
1887
|
+
});
|
|
1888
|
+
(async () => {
|
|
1801
1889
|
try {
|
|
1802
1890
|
const id = await client.createSession({
|
|
1803
1891
|
name: `streamText: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
1804
1892
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
1805
|
-
userId: config.userId
|
|
1806
|
-
convoId: config.convoId,
|
|
1893
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
1894
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
1807
1895
|
metadata: {
|
|
1808
1896
|
model: modelId,
|
|
1809
1897
|
provider,
|
|
@@ -1815,143 +1903,122 @@ function wrapStreamText(originalFn, client, config) {
|
|
|
1815
1903
|
client.setInput(id, input).catch(() => {
|
|
1816
1904
|
});
|
|
1817
1905
|
}
|
|
1818
|
-
return id;
|
|
1819
1906
|
} catch {
|
|
1820
|
-
|
|
1907
|
+
sessionId = null;
|
|
1821
1908
|
}
|
|
1909
|
+
resolveSessionReady();
|
|
1822
1910
|
})();
|
|
1911
|
+
const userOnStepFinish = params.onStepFinish;
|
|
1912
|
+
const userOnFinish = params.onFinish;
|
|
1913
|
+
const userOnError = params.onError;
|
|
1823
1914
|
const wrappedParams = {
|
|
1824
1915
|
...params,
|
|
1825
|
-
tools: params.tools ? wrapToolsAsync(params.tools,
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
sessionId: sid,
|
|
1846
|
-
success: false,
|
|
1847
|
-
failureReason: error.message || "Unknown error",
|
|
1848
|
-
durationMs
|
|
1849
|
-
}).catch(() => {
|
|
1850
|
-
});
|
|
1851
|
-
return;
|
|
1852
|
-
}
|
|
1853
|
-
let resolvedModelId = modelId;
|
|
1854
|
-
try {
|
|
1855
|
-
const resp = result.response ? await result.response : void 0;
|
|
1856
|
-
if (resp?.modelId) resolvedModelId = resp.modelId;
|
|
1857
|
-
} catch {
|
|
1858
|
-
}
|
|
1859
|
-
let usage;
|
|
1860
|
-
try {
|
|
1861
|
-
usage = result.usage ? await result.usage : void 0;
|
|
1862
|
-
} catch {
|
|
1863
|
-
}
|
|
1864
|
-
let steps;
|
|
1865
|
-
try {
|
|
1866
|
-
steps = result.steps ? await result.steps : void 0;
|
|
1867
|
-
} catch {
|
|
1868
|
-
}
|
|
1869
|
-
if (steps && steps.length >= 1) {
|
|
1870
|
-
let totalPrompt = 0, totalCompletion = 0;
|
|
1871
|
-
const stepPromises = steps.map((step, i) => {
|
|
1872
|
-
const sp = step.usage?.promptTokens ?? 0;
|
|
1873
|
-
const sc = step.usage?.completionTokens ?? 0;
|
|
1874
|
-
totalPrompt += sp;
|
|
1875
|
-
totalCompletion += sc;
|
|
1876
|
-
return client.trackEvent({
|
|
1877
|
-
sessionId: sid,
|
|
1878
|
-
eventType: "llm_call",
|
|
1879
|
-
eventData: {
|
|
1880
|
-
model: resolvedModelId,
|
|
1881
|
-
provider,
|
|
1882
|
-
step: i + 1,
|
|
1883
|
-
total_steps: steps.length,
|
|
1884
|
-
prompt_tokens: sp,
|
|
1885
|
-
completion_tokens: sc,
|
|
1886
|
-
total_tokens: step.usage?.totalTokens ?? 0,
|
|
1887
|
-
finish_reason: step.finishReason,
|
|
1916
|
+
tools: params.tools ? wrapToolsAsync(params.tools, sessionReady.then(() => sessionId), client) : void 0,
|
|
1917
|
+
onStepFinish: async (step) => {
|
|
1918
|
+
await sessionReady;
|
|
1919
|
+
if (sessionId) {
|
|
1920
|
+
const su = normalizeUsage(step.usage);
|
|
1921
|
+
const resolvedStepModel = step.response?.modelId ?? modelId;
|
|
1922
|
+
client.trackToolCall({
|
|
1923
|
+
sessionId,
|
|
1924
|
+
toolName: `llm:${provider}:${resolvedStepModel}`,
|
|
1925
|
+
toolInput: { finishReason: step.finishReason },
|
|
1926
|
+
toolOutput: {
|
|
1927
|
+
text: step.text?.slice(0, 500),
|
|
1928
|
+
tokens: {
|
|
1929
|
+
prompt: su?.promptTokens ?? 0,
|
|
1930
|
+
completion: su?.completionTokens ?? 0
|
|
1931
|
+
}
|
|
1932
|
+
},
|
|
1933
|
+
estimatedCost: calculateCostForCall(provider, resolvedStepModel, su?.promptTokens ?? 0, su?.completionTokens ?? 0),
|
|
1934
|
+
tokenCount: su?.totalTokens,
|
|
1935
|
+
metadata: {
|
|
1888
1936
|
tool_calls: step.toolCalls?.map((tc) => tc.toolName)
|
|
1889
1937
|
}
|
|
1890
1938
|
}).catch(() => {
|
|
1891
1939
|
});
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1940
|
+
}
|
|
1941
|
+
if (userOnStepFinish) {
|
|
1942
|
+
try {
|
|
1943
|
+
userOnStepFinish(step);
|
|
1944
|
+
} catch {
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
},
|
|
1948
|
+
onFinish: async (event) => {
|
|
1949
|
+
await sessionReady;
|
|
1950
|
+
if (sessionId && !sessionCompleted) {
|
|
1951
|
+
sessionCompleted = true;
|
|
1952
|
+
const durationMs = Date.now() - startTime;
|
|
1953
|
+
const usage = normalizeUsage(event.totalUsage ?? event.usage);
|
|
1954
|
+
const resolvedModelId = event.response?.modelId ?? modelId;
|
|
1955
|
+
const text = event.text ?? "";
|
|
1956
|
+
const promptTokens = usage?.promptTokens ?? 0;
|
|
1957
|
+
const completionTokens = usage?.completionTokens ?? 0;
|
|
1958
|
+
const totalTokens = usage?.totalTokens ?? promptTokens + completionTokens;
|
|
1959
|
+
const cost = calculateCostForCall(provider, resolvedModelId, promptTokens, completionTokens);
|
|
1960
|
+
await client.completeSession({
|
|
1961
|
+
sessionId,
|
|
1962
|
+
success: true,
|
|
1963
|
+
output: text,
|
|
1964
|
+
durationMs,
|
|
1965
|
+
estimatedCost: cost,
|
|
1966
|
+
promptTokens,
|
|
1967
|
+
completionTokens,
|
|
1968
|
+
totalTokens
|
|
1969
|
+
}).catch(() => {
|
|
1970
|
+
});
|
|
1971
|
+
}
|
|
1972
|
+
if (userOnFinish) {
|
|
1973
|
+
try {
|
|
1974
|
+
userOnFinish(event);
|
|
1975
|
+
} catch {
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
},
|
|
1979
|
+
onError: async (event) => {
|
|
1980
|
+
await sessionReady;
|
|
1981
|
+
if (sessionId && !sessionCompleted) {
|
|
1982
|
+
sessionCompleted = true;
|
|
1983
|
+
const durationMs = Date.now() - startTime;
|
|
1984
|
+
const msg = event.error?.message ?? "Unknown error";
|
|
1985
|
+
await client.trackError({
|
|
1986
|
+
sessionId,
|
|
1987
|
+
errorType: event.error?.name ?? "Error",
|
|
1988
|
+
errorMessage: msg
|
|
1989
|
+
}).catch(() => {
|
|
1990
|
+
});
|
|
1991
|
+
await client.completeSession({
|
|
1992
|
+
sessionId,
|
|
1993
|
+
success: false,
|
|
1994
|
+
failureReason: msg,
|
|
1995
|
+
durationMs
|
|
1996
|
+
}).catch(() => {
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
if (userOnError) {
|
|
2000
|
+
try {
|
|
2001
|
+
userOnError(event);
|
|
2002
|
+
} catch {
|
|
1923
2003
|
}
|
|
1924
|
-
}).catch(() => {
|
|
1925
|
-
});
|
|
1926
|
-
await client.completeSession({
|
|
1927
|
-
sessionId: sid,
|
|
1928
|
-
success: true,
|
|
1929
|
-
output: text,
|
|
1930
|
-
durationMs,
|
|
1931
|
-
estimatedCost: cost,
|
|
1932
|
-
promptTokens,
|
|
1933
|
-
completionTokens,
|
|
1934
|
-
totalTokens
|
|
1935
|
-
}).catch(() => {
|
|
1936
|
-
});
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
result.textStream = (async function* () {
|
|
1940
|
-
try {
|
|
1941
|
-
for await (const chunk of originalTextStream) {
|
|
1942
|
-
fullText += chunk;
|
|
1943
|
-
yield chunk;
|
|
1944
2004
|
}
|
|
1945
|
-
await trackCompletion(fullText);
|
|
1946
|
-
} catch (error) {
|
|
1947
|
-
await trackCompletion(
|
|
1948
|
-
fullText,
|
|
1949
|
-
error instanceof Error ? error : new Error(String(error))
|
|
1950
|
-
);
|
|
1951
|
-
throw error;
|
|
1952
2005
|
}
|
|
1953
|
-
}
|
|
1954
|
-
|
|
2006
|
+
};
|
|
2007
|
+
try {
|
|
2008
|
+
return originalFn(wrappedParams);
|
|
2009
|
+
} catch (error) {
|
|
2010
|
+
sessionReady.then(() => {
|
|
2011
|
+
if (sessionId) {
|
|
2012
|
+
const durationMs = Date.now() - startTime;
|
|
2013
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2014
|
+
client.trackError({ sessionId, errorType: error instanceof Error ? error.name : "Error", errorMessage: msg }).catch(() => {
|
|
2015
|
+
});
|
|
2016
|
+
client.completeSession({ sessionId, success: false, failureReason: msg, durationMs }).catch(() => {
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
});
|
|
2020
|
+
throw error;
|
|
2021
|
+
}
|
|
1955
2022
|
};
|
|
1956
2023
|
}
|
|
1957
2024
|
function wrapGenerateObject(originalFn, client, config) {
|
|
@@ -1962,8 +2029,8 @@ function wrapGenerateObject(originalFn, client, config) {
|
|
|
1962
2029
|
const sessionId = await client.createSession({
|
|
1963
2030
|
name: `generateObject: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
1964
2031
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
1965
|
-
userId: config.userId
|
|
1966
|
-
convoId: config.convoId,
|
|
2032
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
2033
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
1967
2034
|
metadata: {
|
|
1968
2035
|
model: modelId,
|
|
1969
2036
|
provider,
|
|
@@ -1978,20 +2045,21 @@ function wrapGenerateObject(originalFn, client, config) {
|
|
|
1978
2045
|
const result = await originalFn(params);
|
|
1979
2046
|
const durationMs = Date.now() - startTime;
|
|
1980
2047
|
const resolvedModelId = result.response?.modelId || modelId;
|
|
1981
|
-
const
|
|
1982
|
-
const
|
|
1983
|
-
const
|
|
2048
|
+
const usage = normalizeUsage(result.usage);
|
|
2049
|
+
const promptTokens = usage?.promptTokens ?? 0;
|
|
2050
|
+
const completionTokens = usage?.completionTokens ?? 0;
|
|
2051
|
+
const totalTokens = usage?.totalTokens ?? 0;
|
|
1984
2052
|
const cost = calculateCostForCall(provider, resolvedModelId, promptTokens, completionTokens);
|
|
1985
|
-
await client.
|
|
2053
|
+
await client.trackToolCall({
|
|
1986
2054
|
sessionId,
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
2055
|
+
toolName: `llm:${provider}:${resolvedModelId}`,
|
|
2056
|
+
toolInput: { function: "generateObject" },
|
|
2057
|
+
toolOutput: {
|
|
2058
|
+
object: result.object,
|
|
2059
|
+
tokens: { prompt: promptTokens, completion: completionTokens }
|
|
2060
|
+
},
|
|
2061
|
+
estimatedCost: cost,
|
|
2062
|
+
tokenCount: totalTokens
|
|
1995
2063
|
}).catch(() => {
|
|
1996
2064
|
});
|
|
1997
2065
|
await client.completeSession({
|
|
@@ -2027,99 +2095,131 @@ function wrapStreamObject(originalFn, client, config) {
|
|
|
2027
2095
|
const startTime = Date.now();
|
|
2028
2096
|
const { modelId, provider } = extractModelInfo(params.model);
|
|
2029
2097
|
const input = extractInput(params);
|
|
2030
|
-
|
|
2098
|
+
let sessionId = null;
|
|
2099
|
+
let resolveSessionReady;
|
|
2100
|
+
const sessionReady = new Promise((resolve) => {
|
|
2101
|
+
resolveSessionReady = resolve;
|
|
2102
|
+
});
|
|
2103
|
+
(async () => {
|
|
2031
2104
|
try {
|
|
2032
2105
|
const id = await client.createSession({
|
|
2033
2106
|
name: `streamObject: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
2034
2107
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
2035
|
-
userId: config.userId
|
|
2036
|
-
convoId: config.convoId,
|
|
2108
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
2109
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
2037
2110
|
metadata: {
|
|
2038
2111
|
model: modelId,
|
|
2039
2112
|
provider,
|
|
2040
2113
|
function: "streamObject"
|
|
2041
2114
|
}
|
|
2042
2115
|
});
|
|
2116
|
+
sessionId = id;
|
|
2043
2117
|
if (id) {
|
|
2044
2118
|
client.setInput(id, input).catch(() => {
|
|
2045
2119
|
});
|
|
2046
2120
|
}
|
|
2047
|
-
return id;
|
|
2048
2121
|
} catch {
|
|
2049
|
-
|
|
2122
|
+
sessionId = null;
|
|
2050
2123
|
}
|
|
2124
|
+
resolveSessionReady();
|
|
2051
2125
|
})();
|
|
2052
|
-
const
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2126
|
+
const userOnFinish = params.onFinish;
|
|
2127
|
+
const userOnError = params.onError;
|
|
2128
|
+
const wrappedParams = {
|
|
2129
|
+
...params,
|
|
2130
|
+
onFinish: async (event) => {
|
|
2131
|
+
await sessionReady;
|
|
2132
|
+
if (sessionId) {
|
|
2133
|
+
const durationMs = Date.now() - startTime;
|
|
2134
|
+
const usage = normalizeUsage(event.usage);
|
|
2135
|
+
const resolvedModelId = event.response?.modelId ?? modelId;
|
|
2136
|
+
const promptTokens = usage?.promptTokens ?? 0;
|
|
2137
|
+
const completionTokens = usage?.completionTokens ?? 0;
|
|
2138
|
+
const totalTokens = usage?.totalTokens ?? 0;
|
|
2139
|
+
const cost = calculateCostForCall(provider, resolvedModelId, promptTokens, completionTokens);
|
|
2140
|
+
if (event.error) {
|
|
2141
|
+
const errMsg = event.error instanceof Error ? event.error.message : String(event.error);
|
|
2142
|
+
await client.trackError({
|
|
2143
|
+
sessionId,
|
|
2144
|
+
errorType: "SchemaValidationError",
|
|
2145
|
+
errorMessage: errMsg
|
|
2146
|
+
}).catch(() => {
|
|
2147
|
+
});
|
|
2148
|
+
}
|
|
2149
|
+
await client.trackToolCall({
|
|
2150
|
+
sessionId,
|
|
2151
|
+
toolName: `llm:${provider}:${resolvedModelId}`,
|
|
2152
|
+
toolInput: { function: "streamObject" },
|
|
2153
|
+
toolOutput: {
|
|
2154
|
+
object: event.object,
|
|
2155
|
+
tokens: { prompt: promptTokens, completion: completionTokens }
|
|
2156
|
+
},
|
|
2157
|
+
estimatedCost: cost,
|
|
2158
|
+
tokenCount: totalTokens
|
|
2159
|
+
}).catch(() => {
|
|
2160
|
+
});
|
|
2161
|
+
await client.completeSession({
|
|
2162
|
+
sessionId,
|
|
2163
|
+
success: !event.error,
|
|
2164
|
+
output: event.object != null ? JSON.stringify(event.object) : void 0,
|
|
2165
|
+
failureReason: event.error ? String(event.error) : void 0,
|
|
2166
|
+
durationMs,
|
|
2167
|
+
estimatedCost: cost,
|
|
2168
|
+
promptTokens,
|
|
2169
|
+
completionTokens,
|
|
2170
|
+
totalTokens
|
|
2171
|
+
}).catch(() => {
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2174
|
+
if (userOnFinish) {
|
|
2175
|
+
try {
|
|
2176
|
+
userOnFinish(event);
|
|
2177
|
+
} catch {
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
},
|
|
2181
|
+
onError: async (event) => {
|
|
2182
|
+
await sessionReady;
|
|
2183
|
+
if (sessionId) {
|
|
2184
|
+
const durationMs = Date.now() - startTime;
|
|
2185
|
+
const msg = event.error?.message ?? "Unknown error";
|
|
2186
|
+
await client.trackError({
|
|
2187
|
+
sessionId,
|
|
2188
|
+
errorType: event.error?.name ?? "Error",
|
|
2189
|
+
errorMessage: msg
|
|
2190
|
+
}).catch(() => {
|
|
2191
|
+
});
|
|
2192
|
+
await client.completeSession({
|
|
2193
|
+
sessionId,
|
|
2194
|
+
success: false,
|
|
2195
|
+
failureReason: msg,
|
|
2196
|
+
durationMs
|
|
2197
|
+
}).catch(() => {
|
|
2198
|
+
});
|
|
2199
|
+
}
|
|
2200
|
+
if (userOnError) {
|
|
2201
|
+
try {
|
|
2202
|
+
userOnError(event);
|
|
2203
|
+
} catch {
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2077
2206
|
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
sessionId
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
total_tokens: totalTokens
|
|
2207
|
+
};
|
|
2208
|
+
try {
|
|
2209
|
+
return originalFn(wrappedParams);
|
|
2210
|
+
} catch (error) {
|
|
2211
|
+
sessionReady.then(() => {
|
|
2212
|
+
if (sessionId) {
|
|
2213
|
+
const durationMs = Date.now() - startTime;
|
|
2214
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2215
|
+
client.trackError({ sessionId, errorType: error instanceof Error ? error.name : "Error", errorMessage: msg }).catch(() => {
|
|
2216
|
+
});
|
|
2217
|
+
client.completeSession({ sessionId, success: false, failureReason: msg, durationMs }).catch(() => {
|
|
2218
|
+
});
|
|
2091
2219
|
}
|
|
2092
|
-
}).catch(() => {
|
|
2093
|
-
});
|
|
2094
|
-
await client.completeSession({
|
|
2095
|
-
sessionId: sid,
|
|
2096
|
-
success: true,
|
|
2097
|
-
output: JSON.stringify(obj),
|
|
2098
|
-
durationMs,
|
|
2099
|
-
estimatedCost: cost,
|
|
2100
|
-
promptTokens,
|
|
2101
|
-
completionTokens,
|
|
2102
|
-
totalTokens
|
|
2103
|
-
}).catch(() => {
|
|
2104
|
-
});
|
|
2105
|
-
}
|
|
2106
|
-
if (result.object) {
|
|
2107
|
-
const originalObjectPromise = result.object;
|
|
2108
|
-
result.object = originalObjectPromise.then(async (obj) => {
|
|
2109
|
-
await completeStreamObject(obj);
|
|
2110
|
-
return obj;
|
|
2111
|
-
}).catch(async (error) => {
|
|
2112
|
-
await completeStreamObject(void 0, error instanceof Error ? error : new Error(String(error)));
|
|
2113
|
-
throw error;
|
|
2114
|
-
});
|
|
2115
|
-
} else if (result.usage) {
|
|
2116
|
-
result.usage.then(async () => {
|
|
2117
|
-
await completeStreamObject(void 0);
|
|
2118
|
-
}).catch(async (error) => {
|
|
2119
|
-
await completeStreamObject(void 0, error instanceof Error ? error : new Error(String(error)));
|
|
2120
2220
|
});
|
|
2221
|
+
throw error;
|
|
2121
2222
|
}
|
|
2122
|
-
return result;
|
|
2123
2223
|
};
|
|
2124
2224
|
}
|
|
2125
2225
|
function wrapAISDK(ai, options) {
|