@ai-sdk/workflow 1.0.4 → 1.0.6
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 +16 -0
- package/dist/index.d.mts +59 -2
- package/dist/index.mjs +95 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/do-stream-step.ts +2 -0
- package/src/index.ts +2 -0
- package/src/normalize-ui-message-stream.ts +164 -0
- package/src/stream-text-iterator.ts +7 -0
- package/src/workflow-agent.ts +11 -0
- package/src/workflow-chat-transport.ts +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @ai-sdk/workflow
|
|
2
2
|
|
|
3
|
+
## 1.0.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4a9f4d5: `WorkflowChatTransport` now repairs UI message stream part framing, so duplicated or interleaved durable stream writes no longer crash the AI SDK consumer with `Received text-delta for missing text part`.
|
|
8
|
+
- 4016539: Forward `reasoning` generation settings from `WorkflowAgent` to model calls.
|
|
9
|
+
- Updated dependencies [989402d]
|
|
10
|
+
- ai@7.0.6
|
|
11
|
+
|
|
12
|
+
## 1.0.5
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [a2750db]
|
|
17
|
+
- ai@7.0.5
|
|
18
|
+
|
|
3
19
|
## 1.0.4
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LanguageModelV4,
|
|
1
|
+
import { LanguageModelV4, LanguageModelV4CallOptions, SharedV4ProviderOptions, LanguageModelV4Prompt, LanguageModelV4StreamPart } from '@ai-sdk/provider';
|
|
2
2
|
import { Context, HasRequiredKey, InferToolSetContext } from '@ai-sdk/provider-utils';
|
|
3
3
|
import { ToolSet, LanguageModel, Instructions, ToolChoice, TelemetryOptions as TelemetryOptions$1, StopCondition, ActiveTools, LanguageModelResponseMetadata, LanguageModelUsage, FinishReason, ToolCallRepairFunction, Experimental_SandboxSession, StepResult, GenerateTextOnStepEndCallback, ModelMessage, Experimental_LanguageModelStreamPart, UIMessage, UIMessageChunk, ChatTransport, PrepareSendMessagesRequest, PrepareReconnectToStreamRequest, ChatRequestOptions } from 'ai';
|
|
4
4
|
export { Experimental_LanguageModelStreamPart as ModelCallStreamPart, Output, ToolCallRepairFunction } from 'ai';
|
|
@@ -151,6 +151,11 @@ interface GenerationSettings {
|
|
|
151
151
|
* Only applicable for HTTP-based providers.
|
|
152
152
|
*/
|
|
153
153
|
headers?: Record<string, string | undefined>;
|
|
154
|
+
/**
|
|
155
|
+
* Reasoning effort level for the model. Controls how much reasoning
|
|
156
|
+
* the model performs before generating a response.
|
|
157
|
+
*/
|
|
158
|
+
reasoning?: LanguageModelV4CallOptions['reasoning'];
|
|
154
159
|
/**
|
|
155
160
|
* Additional provider-specific options. They are passed through
|
|
156
161
|
* to the provider from the AI SDK and enable provider-specific
|
|
@@ -1106,4 +1111,56 @@ declare class WorkflowChatTransport<UI_MESSAGE extends UIMessage> implements Cha
|
|
|
1106
1111
|
private onFinish;
|
|
1107
1112
|
}
|
|
1108
1113
|
|
|
1109
|
-
|
|
1114
|
+
/**
|
|
1115
|
+
* Normalizes the part framing of a UI message stream so it is always
|
|
1116
|
+
* well-formed for the AI SDK's stream consumer (`processUIMessageStream`,
|
|
1117
|
+
* which backs `useChat`/`readUIMessageStream`).
|
|
1118
|
+
*
|
|
1119
|
+
* ## Why this exists
|
|
1120
|
+
*
|
|
1121
|
+
* The consumer maintains a map of "active" text/reasoning parts keyed by id.
|
|
1122
|
+
* A `text-delta`/`text-end` for an id that has no open part is a fatal error
|
|
1123
|
+
* (`Received text-delta for missing text part with ID "0" ...`) that kills the
|
|
1124
|
+
* whole turn. Two properties of the durable streaming model make that error
|
|
1125
|
+
* reachable:
|
|
1126
|
+
*
|
|
1127
|
+
* - A workflow run owns a single shared stream, and the consumer resets its
|
|
1128
|
+
* active-part maps on every `finish-step`. Multi-step turns reuse the same
|
|
1129
|
+
* part id (commonly `"0"`) in each step, so a single dropped or duplicated
|
|
1130
|
+
* `*-start` across a step boundary orphans the rest of that step's content.
|
|
1131
|
+
* - The same stream is read across reconnects, and a stream-producing step can
|
|
1132
|
+
* run more than once (retry/redelivery, or the concurrent-worker duplication
|
|
1133
|
+
* tracked in vercel/workflow#2331 and #2039). Either can interleave or
|
|
1134
|
+
* duplicate chunks on the shared stream — e.g. a `finish-step` landing in the
|
|
1135
|
+
* middle of another execution's text part.
|
|
1136
|
+
*
|
|
1137
|
+
* Since the content is still flowing and only the framing is damaged, repairing
|
|
1138
|
+
* the framing here degrades the worst case to "text begins slightly into the
|
|
1139
|
+
* step" or "a duplicated tail is dropped" instead of a dead turn.
|
|
1140
|
+
*
|
|
1141
|
+
* ## What it does
|
|
1142
|
+
*
|
|
1143
|
+
* Mirrors the consumer's part-lifetime state machine, per part type, per step:
|
|
1144
|
+
* - resets tracking on `finish-step` (exactly where the consumer resets);
|
|
1145
|
+
* - synthesizes a missing `*-start` when an orphaned `*-delta`/`*-end` arrives;
|
|
1146
|
+
* - drops a re-delivered `*-start`/`*-delta`/`*-end` for a part already
|
|
1147
|
+
* open or ended in the current step (reconnect/replay overlap).
|
|
1148
|
+
*
|
|
1149
|
+
* A well-formed stream passes through unchanged.
|
|
1150
|
+
*
|
|
1151
|
+
* ## Scope: text and reasoning only
|
|
1152
|
+
*
|
|
1153
|
+
* `tool-input-delta` raises the same class of fatal error (`Received
|
|
1154
|
+
* tool-input-delta for missing tool call ...`), but tool parts are deliberately
|
|
1155
|
+
* left untouched: the consumer does not reset its tool-call map on `finish-step`
|
|
1156
|
+
* and tool-call ids are unique, so the step-boundary id-reuse orphaning that
|
|
1157
|
+
* makes text/reasoning fragile does not apply to them. If a future duplication
|
|
1158
|
+
* mode is found to orphan tool-input parts, extend the same machine to that
|
|
1159
|
+
* family rather than special-casing it.
|
|
1160
|
+
*
|
|
1161
|
+
* @param source the raw UI message chunk stream to normalize.
|
|
1162
|
+
* @yields the framing-corrected UI message chunks.
|
|
1163
|
+
*/
|
|
1164
|
+
declare function normalizeUIMessageStreamParts(source: AsyncIterable<UIMessageChunk>): AsyncGenerator<UIMessageChunk>;
|
|
1165
|
+
|
|
1166
|
+
export { type CompatibleLanguageModel, type DownloadFunction, type GenerationSettings, type InferWorkflowAgentTools, type InferWorkflowAgentUIMessage, type OutputSpecification, type PrepareCallCallback, type PrepareCallOptions, type PrepareCallResult, type PrepareStepCallback, type PrepareStepInfo, type PrepareStepResult, type ProviderOptions, type ReconnectToStreamOptions, type SendMessagesOptions, type StreamTextTransform, type TelemetryOptions, WorkflowAgent, type WorkflowAgentOnAbortCallback, type WorkflowAgentOnEndCallback, type WorkflowAgentOnErrorCallback, type WorkflowAgentOnFinishCallback, type WorkflowAgentOnStartCallback, type WorkflowAgentOnStepEndCallback, type WorkflowAgentOnStepFinishCallback, type WorkflowAgentOnStepStartCallback, type WorkflowAgentOnToolExecutionEndCallback, type WorkflowAgentOnToolExecutionStartCallback, type WorkflowAgentOptions, type WorkflowAgentStreamOptions, type WorkflowAgentStreamResult, WorkflowChatTransport, type WorkflowChatTransportOptions, createModelCallToUIChunkTransform, normalizeUIMessageStreamParts, toUIMessageChunk };
|
package/dist/index.mjs
CHANGED
|
@@ -160,6 +160,7 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
160
160
|
providerOptions: options == null ? void 0 : options.providerOptions,
|
|
161
161
|
abortSignal: options == null ? void 0 : options.abortSignal,
|
|
162
162
|
headers: options == null ? void 0 : options.headers,
|
|
163
|
+
reasoning: options == null ? void 0 : options.reasoning,
|
|
163
164
|
maxOutputTokens: options == null ? void 0 : options.maxOutputTokens,
|
|
164
165
|
temperature: options == null ? void 0 : options.temperature,
|
|
165
166
|
topP: options == null ? void 0 : options.topP,
|
|
@@ -492,6 +493,12 @@ async function* streamTextIterator({
|
|
|
492
493
|
headers: prepareResult.headers
|
|
493
494
|
};
|
|
494
495
|
}
|
|
496
|
+
if ((prepareResult == null ? void 0 : prepareResult.reasoning) !== void 0) {
|
|
497
|
+
currentGenerationSettings = {
|
|
498
|
+
...currentGenerationSettings,
|
|
499
|
+
reasoning: prepareResult.reasoning
|
|
500
|
+
};
|
|
501
|
+
}
|
|
495
502
|
if ((prepareResult == null ? void 0 : prepareResult.providerOptions) !== void 0) {
|
|
496
503
|
currentGenerationSettings = {
|
|
497
504
|
...currentGenerationSettings,
|
|
@@ -551,6 +558,7 @@ async function* streamTextIterator({
|
|
|
551
558
|
frequencyPenalty: currentGenerationSettings.frequencyPenalty,
|
|
552
559
|
stopSequences: currentGenerationSettings.stopSequences,
|
|
553
560
|
seed: currentGenerationSettings.seed,
|
|
561
|
+
reasoning: currentGenerationSettings.reasoning,
|
|
554
562
|
providerOptions: currentGenerationSettings.providerOptions,
|
|
555
563
|
headers: currentGenerationSettings.headers
|
|
556
564
|
}));
|
|
@@ -745,6 +753,7 @@ var WorkflowAgent = class {
|
|
|
745
753
|
maxRetries: options.maxRetries,
|
|
746
754
|
abortSignal: options.abortSignal,
|
|
747
755
|
headers: options.headers,
|
|
756
|
+
reasoning: options.reasoning,
|
|
748
757
|
providerOptions: options.providerOptions
|
|
749
758
|
};
|
|
750
759
|
}
|
|
@@ -809,6 +818,8 @@ var WorkflowAgent = class {
|
|
|
809
818
|
effectiveGenerationSettings.seed = prepared.seed;
|
|
810
819
|
if (prepared.headers !== void 0)
|
|
811
820
|
effectiveGenerationSettings.headers = prepared.headers;
|
|
821
|
+
if (prepared.reasoning !== void 0)
|
|
822
|
+
effectiveGenerationSettings.reasoning = prepared.reasoning;
|
|
812
823
|
if (prepared.providerOptions !== void 0)
|
|
813
824
|
effectiveGenerationSettings.providerOptions = prepared.providerOptions;
|
|
814
825
|
}
|
|
@@ -1110,6 +1121,7 @@ var WorkflowAgent = class {
|
|
|
1110
1121
|
abortSignal: effectiveAbortSignal
|
|
1111
1122
|
},
|
|
1112
1123
|
...options.headers !== void 0 && { headers: options.headers },
|
|
1124
|
+
...options.reasoning !== void 0 && { reasoning: options.reasoning },
|
|
1113
1125
|
...options.providerOptions !== void 0 && {
|
|
1114
1126
|
providerOptions: options.providerOptions
|
|
1115
1127
|
}
|
|
@@ -1183,6 +1195,7 @@ var WorkflowAgent = class {
|
|
|
1183
1195
|
maxRetries: (_t = mergedGenerationSettings.maxRetries) != null ? _t : 2,
|
|
1184
1196
|
timeout: void 0,
|
|
1185
1197
|
headers: mergedGenerationSettings.headers,
|
|
1198
|
+
reasoning: mergedGenerationSettings.reasoning,
|
|
1186
1199
|
providerOptions: mergedGenerationSettings.providerOptions,
|
|
1187
1200
|
output: (_u = options.output) != null ? _u : this.output,
|
|
1188
1201
|
runtimeContext,
|
|
@@ -2159,6 +2172,83 @@ import {
|
|
|
2159
2172
|
getErrorMessage as getErrorMessage2
|
|
2160
2173
|
} from "@ai-sdk/provider-utils";
|
|
2161
2174
|
import { createAsyncIterableStream } from "ai/internal";
|
|
2175
|
+
|
|
2176
|
+
// src/normalize-ui-message-stream.ts
|
|
2177
|
+
var newPartFrameState = () => ({
|
|
2178
|
+
open: /* @__PURE__ */ new Set(),
|
|
2179
|
+
ended: /* @__PURE__ */ new Set()
|
|
2180
|
+
});
|
|
2181
|
+
function* repairPart(kind, id, chunk, state, startType) {
|
|
2182
|
+
if (kind === "start") {
|
|
2183
|
+
if (state.open.has(id) || state.ended.has(id)) {
|
|
2184
|
+
return;
|
|
2185
|
+
}
|
|
2186
|
+
state.open.add(id);
|
|
2187
|
+
yield chunk;
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
if (state.ended.has(id)) {
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2193
|
+
if (!state.open.has(id)) {
|
|
2194
|
+
state.open.add(id);
|
|
2195
|
+
yield { type: startType, id };
|
|
2196
|
+
}
|
|
2197
|
+
if (kind === "end") {
|
|
2198
|
+
state.open.delete(id);
|
|
2199
|
+
state.ended.add(id);
|
|
2200
|
+
}
|
|
2201
|
+
yield chunk;
|
|
2202
|
+
}
|
|
2203
|
+
async function* normalizeUIMessageStreamParts(source) {
|
|
2204
|
+
const text = newPartFrameState();
|
|
2205
|
+
const reasoning = newPartFrameState();
|
|
2206
|
+
for await (const chunk of source) {
|
|
2207
|
+
switch (chunk.type) {
|
|
2208
|
+
case "finish-step":
|
|
2209
|
+
text.open.clear();
|
|
2210
|
+
text.ended.clear();
|
|
2211
|
+
reasoning.open.clear();
|
|
2212
|
+
reasoning.ended.clear();
|
|
2213
|
+
yield chunk;
|
|
2214
|
+
break;
|
|
2215
|
+
case "text-start":
|
|
2216
|
+
yield* repairPart("start", chunk.id, chunk, text, "text-start");
|
|
2217
|
+
break;
|
|
2218
|
+
case "text-delta":
|
|
2219
|
+
yield* repairPart("delta", chunk.id, chunk, text, "text-start");
|
|
2220
|
+
break;
|
|
2221
|
+
case "text-end":
|
|
2222
|
+
yield* repairPart("end", chunk.id, chunk, text, "text-start");
|
|
2223
|
+
break;
|
|
2224
|
+
case "reasoning-start":
|
|
2225
|
+
yield* repairPart(
|
|
2226
|
+
"start",
|
|
2227
|
+
chunk.id,
|
|
2228
|
+
chunk,
|
|
2229
|
+
reasoning,
|
|
2230
|
+
"reasoning-start"
|
|
2231
|
+
);
|
|
2232
|
+
break;
|
|
2233
|
+
case "reasoning-delta":
|
|
2234
|
+
yield* repairPart(
|
|
2235
|
+
"delta",
|
|
2236
|
+
chunk.id,
|
|
2237
|
+
chunk,
|
|
2238
|
+
reasoning,
|
|
2239
|
+
"reasoning-start"
|
|
2240
|
+
);
|
|
2241
|
+
break;
|
|
2242
|
+
case "reasoning-end":
|
|
2243
|
+
yield* repairPart("end", chunk.id, chunk, reasoning, "reasoning-start");
|
|
2244
|
+
break;
|
|
2245
|
+
default:
|
|
2246
|
+
yield chunk;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// src/workflow-chat-transport.ts
|
|
2162
2252
|
var WorkflowChatTransport = class {
|
|
2163
2253
|
/**
|
|
2164
2254
|
* Creates a new WorkflowChatTransport instance.
|
|
@@ -2203,7 +2293,7 @@ var WorkflowChatTransport = class {
|
|
|
2203
2293
|
*/
|
|
2204
2294
|
async sendMessages(options) {
|
|
2205
2295
|
return convertAsyncIteratorToReadableStream(
|
|
2206
|
-
this.sendMessagesIterator(options)
|
|
2296
|
+
normalizeUIMessageStreamParts(this.sendMessagesIterator(options))
|
|
2207
2297
|
);
|
|
2208
2298
|
}
|
|
2209
2299
|
async *sendMessagesIterator(options) {
|
|
@@ -2281,7 +2371,9 @@ var WorkflowChatTransport = class {
|
|
|
2281
2371
|
* @throws Error if the reconnection request fails or returns a non-OK status
|
|
2282
2372
|
*/
|
|
2283
2373
|
async reconnectToStream(options) {
|
|
2284
|
-
const reconnectIterator =
|
|
2374
|
+
const reconnectIterator = normalizeUIMessageStreamParts(
|
|
2375
|
+
this.reconnectToStreamIterator(options)
|
|
2376
|
+
);
|
|
2285
2377
|
return convertAsyncIteratorToReadableStream(reconnectIterator);
|
|
2286
2378
|
}
|
|
2287
2379
|
async *reconnectToStreamIterator(options, workflowRunId, initialChunkIndex = 0) {
|
|
@@ -2374,6 +2466,7 @@ export {
|
|
|
2374
2466
|
WorkflowAgent,
|
|
2375
2467
|
WorkflowChatTransport,
|
|
2376
2468
|
createModelCallToUIChunkTransform,
|
|
2469
|
+
normalizeUIMessageStreamParts,
|
|
2377
2470
|
toUIMessageChunk
|
|
2378
2471
|
};
|
|
2379
2472
|
//# sourceMappingURL=index.mjs.map
|