ai-sdk-ollama 2.1.0 → 2.2.1
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 +13 -0
- package/binding.gyp +9 -0
- package/dist/index.browser.cjs +107 -68
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.d.cts +8 -19
- package/dist/index.browser.d.ts +8 -19
- package/dist/index.browser.js +107 -68
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +107 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -19
- package/dist/index.d.ts +8 -19
- package/dist/index.js +107 -68
- package/dist/index.js.map +1 -1
- package/index.js +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 72a26e3: ### Fixed
|
|
8
|
+
- **Real-time streaming for flow-based UIs**: Fixed issue where `streamText`'s `fullStream` was waiting for completion before emitting events, causing flow interfaces to only receive control events (start, finish) without text or tool call events. The enhanced `fullStream` now streams all events (text-delta, tool-call, tool-result) in real-time as they occur. Resolves [#344](https://github.com/jagreehal/ai-sdk-ollama/issues/344).
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`stopWhen` support**: Added support for the `stopWhen` property in both `streamText` and `generateText` functions, allowing users to customize multi-turn tool calling behavior. When not provided and tools are enabled, defaults to `stepCountIs(5)` for multi-turn tool calling.
|
|
12
|
+
|
|
13
|
+
### Improved
|
|
14
|
+
- **AI SDK compatibility**: Enhanced both `streamText` and `generateText` to automatically support all AI SDK properties using `Parameters<typeof _streamText>[0]` type extraction, ensuring 100% forward compatibility with future AI SDK changes without manual updates.
|
|
15
|
+
|
|
3
16
|
## 2.1.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/binding.gyp
ADDED
package/dist/index.browser.cjs
CHANGED
|
@@ -15956,8 +15956,8 @@ Please provide a structured response based on these tool results.` : generateTex
|
|
|
15956
15956
|
}
|
|
15957
15957
|
const result = await (0, import_ai3.generateText)({
|
|
15958
15958
|
...generateTextOptions,
|
|
15959
|
-
stopWhen
|
|
15960
|
-
|
|
15959
|
+
// Only set stopWhen default if user didn't provide one and tools are enabled
|
|
15960
|
+
stopWhen: generateTextOptions.stopWhen ?? (hasTools ? (0, import_ai3.stepCountIs)(5) : void 0)
|
|
15961
15961
|
});
|
|
15962
15962
|
const toolsWereCalled = result.steps?.some((step) => step.toolCalls && step.toolCalls.length > 0) ?? false;
|
|
15963
15963
|
const hasMinimalText = !result.text || result.text.trim().length < minResponseLength;
|
|
@@ -16045,8 +16045,8 @@ async function streamText(options) {
|
|
|
16045
16045
|
}
|
|
16046
16046
|
const streamResult = await (0, import_ai4.streamText)({
|
|
16047
16047
|
...streamTextOptions,
|
|
16048
|
-
stopWhen
|
|
16049
|
-
|
|
16048
|
+
// Only set stopWhen default if user didn't provide one and tools are enabled
|
|
16049
|
+
stopWhen: streamTextOptions.stopWhen ?? (hasTools ? (0, import_ai4.stepCountIs)(5) : void 0)
|
|
16050
16050
|
});
|
|
16051
16051
|
const state = {
|
|
16052
16052
|
textContent: "",
|
|
@@ -16182,9 +16182,12 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
16182
16182
|
});
|
|
16183
16183
|
};
|
|
16184
16184
|
const createEnhancedFullStream = () => {
|
|
16185
|
+
const originalFullStream = streamResult.fullStream;
|
|
16185
16186
|
return new ReadableStream({
|
|
16186
16187
|
async start(controller) {
|
|
16187
16188
|
let controllerClosed = false;
|
|
16189
|
+
let hasSeenText = false;
|
|
16190
|
+
let currentTextId = null;
|
|
16188
16191
|
const safeClose = () => {
|
|
16189
16192
|
if (!controllerClosed) {
|
|
16190
16193
|
controllerClosed = true;
|
|
@@ -16207,73 +16210,109 @@ Based on the tool results above, please provide a comprehensive response to the
|
|
|
16207
16210
|
return false;
|
|
16208
16211
|
};
|
|
16209
16212
|
try {
|
|
16210
|
-
|
|
16211
|
-
|
|
16212
|
-
|
|
16213
|
-
|
|
16214
|
-
|
|
16215
|
-
|
|
16216
|
-
|
|
16217
|
-
|
|
16218
|
-
|
|
16219
|
-
|
|
16220
|
-
|
|
16221
|
-
|
|
16222
|
-
|
|
16223
|
-
|
|
16224
|
-
|
|
16225
|
-
|
|
16226
|
-
|
|
16227
|
-
|
|
16228
|
-
|
|
16229
|
-
|
|
16230
|
-
|
|
16231
|
-
|
|
16232
|
-
|
|
16233
|
-
|
|
16234
|
-
|
|
16235
|
-
|
|
16236
|
-
|
|
16237
|
-
|
|
16238
|
-
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
|
|
16242
|
-
|
|
16243
|
-
|
|
16244
|
-
|
|
16245
|
-
|
|
16246
|
-
|
|
16247
|
-
|
|
16248
|
-
|
|
16249
|
-
|
|
16250
|
-
|
|
16251
|
-
|
|
16252
|
-
|
|
16213
|
+
const reader = originalFullStream.getReader();
|
|
16214
|
+
while (true) {
|
|
16215
|
+
const { done, value } = await reader.read();
|
|
16216
|
+
if (done) {
|
|
16217
|
+
state.hasFinished = true;
|
|
16218
|
+
const finalResult = await streamResult;
|
|
16219
|
+
const [toolCalls, toolResults, text] = await Promise.all([
|
|
16220
|
+
finalResult.toolCalls,
|
|
16221
|
+
finalResult.toolResults,
|
|
16222
|
+
finalResult.text
|
|
16223
|
+
]);
|
|
16224
|
+
state.textContent = text || "";
|
|
16225
|
+
if (toolCalls) {
|
|
16226
|
+
state.toolCalls = toolCalls.map((tc) => ({
|
|
16227
|
+
toolCallId: tc.toolCallId,
|
|
16228
|
+
toolName: tc.toolName,
|
|
16229
|
+
input: tc.input
|
|
16230
|
+
}));
|
|
16231
|
+
}
|
|
16232
|
+
if (toolResults) {
|
|
16233
|
+
state.toolResults = toolResults.map((tr) => ({
|
|
16234
|
+
toolCallId: tr.toolCallId,
|
|
16235
|
+
toolName: tr.toolName,
|
|
16236
|
+
output: tr.output
|
|
16237
|
+
}));
|
|
16238
|
+
}
|
|
16239
|
+
if (state.toolCalls.length > 0 && state.textContent.length < minStreamLength && !hasSeenText) {
|
|
16240
|
+
const synthesisText = await generateSynthesis();
|
|
16241
|
+
if (synthesisText && synthesisText.length > 0) {
|
|
16242
|
+
currentTextId = crypto.randomUUID();
|
|
16243
|
+
safeEnqueue({ type: "text-start", id: currentTextId });
|
|
16244
|
+
const chunkSize = 10;
|
|
16245
|
+
for (let i = 0; i < synthesisText.length; i += chunkSize) {
|
|
16246
|
+
const chunk = synthesisText.slice(i, i + chunkSize);
|
|
16247
|
+
safeEnqueue({
|
|
16248
|
+
type: "text-delta",
|
|
16249
|
+
id: currentTextId,
|
|
16250
|
+
text: chunk
|
|
16251
|
+
});
|
|
16252
|
+
}
|
|
16253
|
+
safeEnqueue({ type: "text-end", id: currentTextId });
|
|
16254
|
+
}
|
|
16255
|
+
}
|
|
16256
|
+
const usage = await finalResult.usage;
|
|
16257
|
+
const finishReason = await finalResult.finishReason;
|
|
16258
|
+
safeEnqueue({
|
|
16259
|
+
type: "finish",
|
|
16260
|
+
finishReason: finishReason || "stop",
|
|
16261
|
+
totalUsage: {
|
|
16262
|
+
inputTokens: usage?.inputTokens || 0,
|
|
16263
|
+
outputTokens: usage?.outputTokens || 0,
|
|
16264
|
+
totalTokens: usage?.totalTokens || 0
|
|
16265
|
+
}
|
|
16266
|
+
});
|
|
16267
|
+
safeClose();
|
|
16268
|
+
break;
|
|
16253
16269
|
}
|
|
16254
|
-
|
|
16255
|
-
|
|
16256
|
-
|
|
16257
|
-
|
|
16258
|
-
|
|
16259
|
-
|
|
16260
|
-
|
|
16261
|
-
|
|
16270
|
+
if (value) {
|
|
16271
|
+
const part = value;
|
|
16272
|
+
switch (part.type) {
|
|
16273
|
+
case "text-delta":
|
|
16274
|
+
case "text-delta-text": {
|
|
16275
|
+
hasSeenText = true;
|
|
16276
|
+
const delta = typeof part.delta === "string" ? part.delta : "";
|
|
16277
|
+
const text = typeof part.text === "string" ? part.text : "";
|
|
16278
|
+
const textDelta = delta || text;
|
|
16279
|
+
if (textDelta) {
|
|
16280
|
+
state.textContent += textDelta;
|
|
16281
|
+
}
|
|
16282
|
+
if (!currentTextId && typeof part.id === "string") {
|
|
16283
|
+
currentTextId = part.id;
|
|
16284
|
+
}
|
|
16285
|
+
break;
|
|
16286
|
+
}
|
|
16287
|
+
case "text-start": {
|
|
16288
|
+
hasSeenText = true;
|
|
16289
|
+
if (typeof part.id === "string") {
|
|
16290
|
+
currentTextId = part.id;
|
|
16291
|
+
}
|
|
16292
|
+
break;
|
|
16293
|
+
}
|
|
16294
|
+
case "text-end": {
|
|
16295
|
+
currentTextId = null;
|
|
16296
|
+
break;
|
|
16297
|
+
}
|
|
16298
|
+
}
|
|
16299
|
+
if (part.type === "tool-call") {
|
|
16300
|
+
state.toolCalls.push({
|
|
16301
|
+
toolCallId: typeof part.toolCallId === "string" ? part.toolCallId : "",
|
|
16302
|
+
toolName: typeof part.toolName === "string" ? part.toolName : "",
|
|
16303
|
+
input: part.input
|
|
16304
|
+
});
|
|
16305
|
+
}
|
|
16306
|
+
if (part.type === "tool-result") {
|
|
16307
|
+
state.toolResults.push({
|
|
16308
|
+
toolCallId: typeof part.toolCallId === "string" ? part.toolCallId : "",
|
|
16309
|
+
toolName: typeof part.toolName === "string" ? part.toolName : "",
|
|
16310
|
+
output: part.output
|
|
16311
|
+
});
|
|
16312
|
+
}
|
|
16313
|
+
safeEnqueue(part);
|
|
16262
16314
|
}
|
|
16263
|
-
safeEnqueue({ type: "text-end", id: textId });
|
|
16264
16315
|
}
|
|
16265
|
-
const usage = await finalResult.usage;
|
|
16266
|
-
const finishReason = await finalResult.finishReason;
|
|
16267
|
-
safeEnqueue({
|
|
16268
|
-
type: "finish",
|
|
16269
|
-
finishReason: finishReason || "stop",
|
|
16270
|
-
totalUsage: {
|
|
16271
|
-
inputTokens: usage?.inputTokens || 0,
|
|
16272
|
-
outputTokens: usage?.outputTokens || 0,
|
|
16273
|
-
totalTokens: usage?.totalTokens || 0
|
|
16274
|
-
}
|
|
16275
|
-
});
|
|
16276
|
-
safeClose();
|
|
16277
16316
|
} catch (error46) {
|
|
16278
16317
|
if (!controllerClosed) {
|
|
16279
16318
|
controller.error(error46);
|