ai-sdk-ollama 3.8.0 → 3.8.2
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/CHANGELOG.md +12 -0
- package/dist/index.browser.cjs +105 -43
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.d.cts +7 -39
- package/dist/index.browser.d.ts +7 -39
- package/dist/index.browser.js +105 -43
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +105 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -39
- package/dist/index.d.ts +7 -39
- package/dist/index.js +105 -43
- package/dist/index.js.map +1 -1
- package/package.json +10 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.8.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 92ca938: Fix TypeScript 6.0 build failure caused by deprecated baseUrl option in tsup DTS generation
|
|
8
|
+
|
|
9
|
+
## 3.8.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- aeafdd6: - Update `generateText` to detect and use the stable `output` option instead of the deprecated `experimental_output` when `enableToolsWithStructuredOutput` is enabled, including a two-phase tools + structured output path and an integration test to guard this behavior.
|
|
14
|
+
|
|
3
15
|
## 3.8.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/index.browser.cjs
CHANGED
|
@@ -17066,6 +17066,17 @@ var ollama = createOllama();
|
|
|
17066
17066
|
|
|
17067
17067
|
// src/functions/generate-text.ts
|
|
17068
17068
|
var import_ai3 = require("ai");
|
|
17069
|
+
function resultWithOverrides(base, overrides) {
|
|
17070
|
+
const descriptors = {};
|
|
17071
|
+
for (const key of Object.keys(overrides)) {
|
|
17072
|
+
descriptors[key] = {
|
|
17073
|
+
value: overrides[key],
|
|
17074
|
+
enumerable: true,
|
|
17075
|
+
configurable: true
|
|
17076
|
+
};
|
|
17077
|
+
}
|
|
17078
|
+
return Object.create(base, descriptors);
|
|
17079
|
+
}
|
|
17069
17080
|
async function generateText(options) {
|
|
17070
17081
|
const { enhancedOptions = {}, ...generateTextOptions } = options;
|
|
17071
17082
|
const {
|
|
@@ -17076,33 +17087,42 @@ async function generateText(options) {
|
|
|
17076
17087
|
enableToolsWithStructuredOutput = false
|
|
17077
17088
|
} = enhancedOptions;
|
|
17078
17089
|
const hasTools = generateTextOptions.tools && Object.keys(generateTextOptions.tools).length > 0;
|
|
17079
|
-
const
|
|
17090
|
+
const hasOutput = "output" in generateTextOptions;
|
|
17080
17091
|
const requiresTools = generateTextOptions.toolChoice === "required" || typeof generateTextOptions.toolChoice === "object" && "type" in generateTextOptions.toolChoice && generateTextOptions.toolChoice.type === "tool";
|
|
17081
|
-
if (enableToolsWithStructuredOutput &&
|
|
17082
|
-
const
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
17092
|
+
if (enableToolsWithStructuredOutput && hasOutput && requiresTools && hasTools) {
|
|
17093
|
+
const phase1Options = Object.fromEntries(
|
|
17094
|
+
Object.entries(generateTextOptions).filter(([key]) => key !== "output")
|
|
17095
|
+
);
|
|
17096
|
+
const toolResult = await (0, import_ai3.generateText)(
|
|
17097
|
+
phase1Options
|
|
17098
|
+
);
|
|
17086
17099
|
if (toolResult.toolCalls && toolResult.toolCalls.length > 0) {
|
|
17087
17100
|
const toolContext = toolResult.toolResults?.map(
|
|
17088
|
-
(tr, i) => `${toolResult.toolCalls?.[i]?.toolName}: ${JSON.stringify(tr.output
|
|
17101
|
+
(tr, i) => `${toolResult.toolCalls?.[i]?.toolName}: ${JSON.stringify(tr.output ?? tr)}`
|
|
17089
17102
|
).join("\n");
|
|
17090
|
-
const
|
|
17103
|
+
const toolResultsSuffix = `
|
|
17091
17104
|
|
|
17092
17105
|
Tool Results:
|
|
17093
17106
|
${toolContext}
|
|
17094
17107
|
|
|
17095
|
-
Please provide a structured response based on these tool results
|
|
17096
|
-
const
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
}
|
|
17108
|
+
Please provide a structured response based on these tool results.`;
|
|
17109
|
+
const phase2Base = Object.fromEntries(
|
|
17110
|
+
Object.entries(generateTextOptions).filter(
|
|
17111
|
+
([key]) => key !== "tools" && key !== "toolChoice"
|
|
17112
|
+
)
|
|
17113
|
+
);
|
|
17114
|
+
const phase2OptionsWithPrompt = typeof phase2Base.prompt === "string" ? { ...phase2Base, prompt: phase2Base.prompt + toolResultsSuffix } : phase2Base.messages ? {
|
|
17115
|
+
...phase2Base,
|
|
17116
|
+
prompt: void 0,
|
|
17117
|
+
messages: [
|
|
17118
|
+
...phase2Base.messages,
|
|
17119
|
+
{ role: "user", content: toolResultsSuffix.trim() }
|
|
17120
|
+
]
|
|
17121
|
+
} : phase2Base;
|
|
17102
17122
|
const structuredResult = await (0, import_ai3.generateText)(
|
|
17103
|
-
|
|
17123
|
+
phase2OptionsWithPrompt
|
|
17104
17124
|
);
|
|
17105
|
-
const enhancedResult =
|
|
17125
|
+
const enhancedResult = resultWithOverrides(structuredResult, {
|
|
17106
17126
|
toolCalls: toolResult.toolCalls,
|
|
17107
17127
|
toolResults: toolResult.toolResults,
|
|
17108
17128
|
staticToolCalls: toolResult.staticToolCalls,
|
|
@@ -17110,9 +17130,9 @@ Please provide a structured response based on these tool results.` : generateTex
|
|
|
17110
17130
|
staticToolResults: toolResult.staticToolResults,
|
|
17111
17131
|
dynamicToolResults: toolResult.dynamicToolResults,
|
|
17112
17132
|
usage: {
|
|
17113
|
-
inputTokens: (toolResult.usage.inputTokens
|
|
17114
|
-
outputTokens: (toolResult.usage.outputTokens
|
|
17115
|
-
totalTokens: (toolResult.usage.totalTokens
|
|
17133
|
+
inputTokens: (toolResult.usage.inputTokens ?? 0) + (structuredResult.usage.inputTokens ?? 0),
|
|
17134
|
+
outputTokens: (toolResult.usage.outputTokens ?? 0) + (structuredResult.usage.outputTokens ?? 0),
|
|
17135
|
+
totalTokens: (toolResult.usage.totalTokens ?? 0) + (structuredResult.usage.totalTokens ?? 0)
|
|
17116
17136
|
}
|
|
17117
17137
|
});
|
|
17118
17138
|
return enhancedResult;
|
|
@@ -17123,7 +17143,9 @@ Please provide a structured response based on these tool results.` : generateTex
|
|
|
17123
17143
|
// Only set stopWhen default if user didn't provide one and tools are enabled
|
|
17124
17144
|
stopWhen: generateTextOptions.stopWhen ?? (hasTools ? (0, import_ai3.stepCountIs)(5) : void 0)
|
|
17125
17145
|
});
|
|
17126
|
-
const toolsWereCalled = result.steps?.some(
|
|
17146
|
+
const toolsWereCalled = result.steps?.some(
|
|
17147
|
+
(step) => step.toolCalls && step.toolCalls.length > 0
|
|
17148
|
+
) ?? false;
|
|
17127
17149
|
const hasMinimalText = !result.text || result.text.trim().length < minResponseLength;
|
|
17128
17150
|
if (!hasTools || !toolsWereCalled || !hasMinimalText || !enableSynthesis) {
|
|
17129
17151
|
return result;
|
|
@@ -17155,11 +17177,16 @@ Tool results:
|
|
|
17155
17177
|
${toolContext}
|
|
17156
17178
|
|
|
17157
17179
|
${synthesisPrompt}`;
|
|
17158
|
-
const
|
|
17159
|
-
const
|
|
17180
|
+
const generateOptions = generateTextOptions;
|
|
17181
|
+
const baseOptions = Object.fromEntries(
|
|
17182
|
+
Object.entries(generateOptions).filter(
|
|
17183
|
+
([key]) => key !== "tools" && key !== "prompt" && key !== "messages"
|
|
17184
|
+
)
|
|
17185
|
+
);
|
|
17186
|
+
const synthesisOptions = generateOptions.messages ? {
|
|
17160
17187
|
...baseOptions,
|
|
17161
17188
|
messages: [
|
|
17162
|
-
...messages || [],
|
|
17189
|
+
...generateOptions.messages || [],
|
|
17163
17190
|
{ role: "user", content: fullSynthesisPrompt }
|
|
17164
17191
|
]
|
|
17165
17192
|
} : {
|
|
@@ -17170,12 +17197,12 @@ ${synthesisPrompt}`;
|
|
|
17170
17197
|
synthesisOptions
|
|
17171
17198
|
);
|
|
17172
17199
|
if (synthesisResult.text && synthesisResult.text.trim().length >= minResponseLength) {
|
|
17173
|
-
const enhancedResult =
|
|
17200
|
+
const enhancedResult = resultWithOverrides(result, {
|
|
17174
17201
|
text: synthesisResult.text,
|
|
17175
17202
|
usage: {
|
|
17176
|
-
inputTokens: (result.usage.inputTokens
|
|
17177
|
-
outputTokens: (result.usage.outputTokens
|
|
17178
|
-
totalTokens: (result.usage.totalTokens
|
|
17203
|
+
inputTokens: (result.usage.inputTokens ?? 0) + (synthesisResult.usage.inputTokens ?? 0),
|
|
17204
|
+
outputTokens: (result.usage.outputTokens ?? 0) + (synthesisResult.usage.outputTokens ?? 0),
|
|
17205
|
+
totalTokens: (result.usage.totalTokens ?? 0) + (synthesisResult.usage.totalTokens ?? 0)
|
|
17179
17206
|
}
|
|
17180
17207
|
});
|
|
17181
17208
|
return enhancedResult;
|
|
@@ -17201,7 +17228,6 @@ async function streamText(options) {
|
|
|
17201
17228
|
}
|
|
17202
17229
|
const streamResult = await (0, import_ai4.streamText)({
|
|
17203
17230
|
...streamTextOptions,
|
|
17204
|
-
// Only set stopWhen default if user didn't provide one and tools are enabled
|
|
17205
17231
|
stopWhen: streamTextOptions.stopWhen ?? (hasTools ? (0, import_ai4.stepCountIs)(5) : void 0)
|
|
17206
17232
|
});
|
|
17207
17233
|
const state = {
|
|
@@ -17213,11 +17239,13 @@ async function streamText(options) {
|
|
|
17213
17239
|
};
|
|
17214
17240
|
let synthesisApplied = false;
|
|
17215
17241
|
let synthesisInProgress = false;
|
|
17216
|
-
const generateSynthesis = async () => {
|
|
17242
|
+
const generateSynthesis = async (toolCallsOverride, toolResultsOverride) => {
|
|
17217
17243
|
if (synthesisApplied || synthesisInProgress) {
|
|
17218
17244
|
return "";
|
|
17219
17245
|
}
|
|
17220
|
-
|
|
17246
|
+
const toolCalls = toolCallsOverride ?? state.toolCalls;
|
|
17247
|
+
const toolResults = toolResultsOverride ?? state.toolResults;
|
|
17248
|
+
if (toolCalls.length === 0) {
|
|
17221
17249
|
return "";
|
|
17222
17250
|
}
|
|
17223
17251
|
if (state.textContent.length >= minStreamLength) {
|
|
@@ -17225,7 +17253,7 @@ async function streamText(options) {
|
|
|
17225
17253
|
}
|
|
17226
17254
|
synthesisInProgress = true;
|
|
17227
17255
|
try {
|
|
17228
|
-
const toolContext =
|
|
17256
|
+
const toolContext = toolResults.map((tr) => {
|
|
17229
17257
|
return `${tr.toolName}: ${JSON.stringify(tr.output)}`;
|
|
17230
17258
|
}).join("\n") || "";
|
|
17231
17259
|
const originalPromptText = typeof options.prompt === "string" ? options.prompt : options.messages?.at(-1)?.content || "the user question";
|
|
@@ -17290,20 +17318,55 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
17290
17318
|
}
|
|
17291
17319
|
return false;
|
|
17292
17320
|
};
|
|
17293
|
-
const
|
|
17321
|
+
const applySynthesisFromSteps = async () => {
|
|
17294
17322
|
if (synthesisApplied || controllerClosed) return;
|
|
17295
|
-
|
|
17296
|
-
|
|
17297
|
-
|
|
17298
|
-
|
|
17323
|
+
try {
|
|
17324
|
+
const steps = await streamResult.steps;
|
|
17325
|
+
const allToolCalls = [];
|
|
17326
|
+
const allToolResults = [];
|
|
17327
|
+
if (steps) {
|
|
17328
|
+
for (const step of steps) {
|
|
17329
|
+
if (step.toolCalls) {
|
|
17330
|
+
for (const tc of step.toolCalls) {
|
|
17331
|
+
allToolCalls.push({
|
|
17332
|
+
toolCallId: tc.toolCallId,
|
|
17333
|
+
toolName: tc.toolName,
|
|
17334
|
+
input: tc.input
|
|
17335
|
+
});
|
|
17336
|
+
}
|
|
17337
|
+
}
|
|
17338
|
+
if (step.toolResults) {
|
|
17339
|
+
for (const tr of step.toolResults) {
|
|
17340
|
+
allToolResults.push({
|
|
17341
|
+
toolCallId: tr.toolCallId,
|
|
17342
|
+
toolName: tr.toolName,
|
|
17343
|
+
output: tr.output
|
|
17344
|
+
});
|
|
17345
|
+
}
|
|
17346
|
+
}
|
|
17347
|
+
}
|
|
17348
|
+
}
|
|
17349
|
+
if (allToolCalls.length > 0 && state.textContent.length < minStreamLength) {
|
|
17350
|
+
const synthesisText = await generateSynthesis(
|
|
17351
|
+
allToolCalls,
|
|
17352
|
+
allToolResults
|
|
17353
|
+
);
|
|
17354
|
+
if (synthesisText && !controllerClosed) {
|
|
17355
|
+
const chunkSize = 20;
|
|
17356
|
+
for (let i = 0; i < synthesisText.length; i += chunkSize) {
|
|
17357
|
+
if (!safeEnqueue(synthesisText.slice(i, i + chunkSize)))
|
|
17358
|
+
break;
|
|
17359
|
+
}
|
|
17360
|
+
}
|
|
17299
17361
|
}
|
|
17362
|
+
} catch {
|
|
17300
17363
|
}
|
|
17301
17364
|
};
|
|
17302
17365
|
const resetTimeout = () => {
|
|
17303
17366
|
if (streamTimeout) clearTimeout(streamTimeout);
|
|
17304
17367
|
streamTimeout = setTimeout(async () => {
|
|
17305
17368
|
if (!streamComplete && !synthesisApplied && !controllerClosed) {
|
|
17306
|
-
await
|
|
17369
|
+
await applySynthesisFromSteps();
|
|
17307
17370
|
}
|
|
17308
17371
|
safeClose();
|
|
17309
17372
|
}, synthesisTimeout);
|
|
@@ -17318,7 +17381,7 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
17318
17381
|
if (streamTimeout) clearTimeout(streamTimeout);
|
|
17319
17382
|
state.hasFinished = true;
|
|
17320
17383
|
if (!synthesisApplied && !controllerClosed) {
|
|
17321
|
-
await
|
|
17384
|
+
await applySynthesisFromSteps();
|
|
17322
17385
|
}
|
|
17323
17386
|
safeClose();
|
|
17324
17387
|
break;
|
|
@@ -17342,7 +17405,7 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
17342
17405
|
return new ReadableStream({
|
|
17343
17406
|
async start(controller) {
|
|
17344
17407
|
let controllerClosed = false;
|
|
17345
|
-
let
|
|
17408
|
+
let hasSeenMeaningfulText = false;
|
|
17346
17409
|
let currentTextId = null;
|
|
17347
17410
|
const safeClose = () => {
|
|
17348
17411
|
if (!controllerClosed) {
|
|
@@ -17392,7 +17455,7 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
17392
17455
|
output: tr.output
|
|
17393
17456
|
}));
|
|
17394
17457
|
}
|
|
17395
|
-
if (state.toolCalls.length > 0 && state.textContent.length < minStreamLength && !
|
|
17458
|
+
if (state.toolCalls.length > 0 && state.textContent.length < minStreamLength && !hasSeenMeaningfulText) {
|
|
17396
17459
|
const synthesisText = await generateSynthesis();
|
|
17397
17460
|
if (synthesisText && synthesisText.length > 0) {
|
|
17398
17461
|
currentTextId = crypto.randomUUID();
|
|
@@ -17428,12 +17491,12 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
17428
17491
|
switch (part.type) {
|
|
17429
17492
|
case "text-delta":
|
|
17430
17493
|
case "text-delta-text": {
|
|
17431
|
-
hasSeenText = true;
|
|
17432
17494
|
const delta = typeof part.delta === "string" ? part.delta : "";
|
|
17433
17495
|
const text = typeof part.text === "string" ? part.text : "";
|
|
17434
17496
|
const textDelta = delta || text;
|
|
17435
17497
|
if (textDelta) {
|
|
17436
17498
|
state.textContent += textDelta;
|
|
17499
|
+
hasSeenMeaningfulText = true;
|
|
17437
17500
|
}
|
|
17438
17501
|
if (!currentTextId && typeof part.id === "string") {
|
|
17439
17502
|
currentTextId = part.id;
|
|
@@ -17441,7 +17504,6 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
17441
17504
|
break;
|
|
17442
17505
|
}
|
|
17443
17506
|
case "text-start": {
|
|
17444
|
-
hasSeenText = true;
|
|
17445
17507
|
if (typeof part.id === "string") {
|
|
17446
17508
|
currentTextId = part.id;
|
|
17447
17509
|
}
|