@dbos-inc/vercel-ai 0.1.5
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/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +6 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +67 -0
- package/dist/internal.js.map +1 -0
- package/dist/mcp.d.ts +17 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +102 -0
- package/dist/mcp.js.map +1 -0
- package/dist/middleware.d.ts +13 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +496 -0
- package/dist/middleware.js.map +1 -0
- package/package.json +64 -0
- package/src/index.ts +2 -0
- package/src/internal.ts +66 -0
- package/src/mcp.ts +140 -0
- package/src/middleware.ts +520 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.durableCalls = durableCalls;
|
|
4
|
+
exports.durableEmbeddingCalls = durableEmbeddingCalls;
|
|
5
|
+
exports.durableImageCalls = durableImageCalls;
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
const dbos_sdk_1 = require("@dbos-inc/dbos-sdk");
|
|
8
|
+
const internal_1 = require("./internal");
|
|
9
|
+
// In-flight durable model calls per workflow; concurrent calls have a nondeterministic DBOS step order on replay, so we reject them.
|
|
10
|
+
const inflightModelCalls = new Map();
|
|
11
|
+
function enterDurableModelCall(operation) {
|
|
12
|
+
const workflowID = dbos_sdk_1.DBOS.workflowID;
|
|
13
|
+
const inflight = inflightModelCalls.get(workflowID) ?? 0;
|
|
14
|
+
if (inflight > 0) {
|
|
15
|
+
// embedMany parallelizes its batches; maxParallelCalls: 1 serializes them deterministically. Other callers use child workflows.
|
|
16
|
+
const remedy = operation === 'embed'
|
|
17
|
+
? 'pass maxParallelCalls: 1 to embedMany, or run each call in its own child workflow with DBOS.startWorkflow'
|
|
18
|
+
: 'run each call in its own child workflow with DBOS.startWorkflow';
|
|
19
|
+
throw new Error(`Concurrent durable model calls in workflow "${workflowID}" are not supported because their step order is nondeterministic on replay; ${remedy}.`);
|
|
20
|
+
}
|
|
21
|
+
inflightModelCalls.set(workflowID, inflight + 1);
|
|
22
|
+
return workflowID;
|
|
23
|
+
}
|
|
24
|
+
function exitDurableModelCall(workflowID) {
|
|
25
|
+
const inflight = (inflightModelCalls.get(workflowID) ?? 1) - 1;
|
|
26
|
+
if (inflight > 0) {
|
|
27
|
+
inflightModelCalls.set(workflowID, inflight);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
inflightModelCalls.delete(workflowID);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** AI SDK language-model middleware that runs each model call as a durable, checkpointed DBOS step (replayed on recovery); outside a workflow it calls the model directly. */
|
|
34
|
+
function durableCalls(options = {}) {
|
|
35
|
+
const stepConfig = (0, internal_1.withErrorClassification)(options);
|
|
36
|
+
return {
|
|
37
|
+
specificationVersion: 'v4',
|
|
38
|
+
wrapGenerate: async ({ doGenerate, model }) => {
|
|
39
|
+
(0, internal_1.assertNotInTransaction)('generate');
|
|
40
|
+
if (!(0, internal_1.isInWorkflowFunction)()) {
|
|
41
|
+
return await doGenerate();
|
|
42
|
+
}
|
|
43
|
+
const workflowID = enterDurableModelCall('generate');
|
|
44
|
+
try {
|
|
45
|
+
return await dbos_sdk_1.DBOS.runStep(async () => ensureResponseMetadata(encodeBinaryContent(await doGenerate())), {
|
|
46
|
+
...stepConfig,
|
|
47
|
+
name: stepConfig.name ?? stepName(model, 'generate'),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
// Restore the AI SDK error identity a replay revival strips, so the SDK's retry/catch logic behaves the same.
|
|
52
|
+
throw (0, internal_1.restoreAISDKErrorIdentity)(error);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
exitDurableModelCall(workflowID);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
wrapStream: async ({ doStream, params, model }) => {
|
|
59
|
+
(0, internal_1.assertNotInTransaction)('stream');
|
|
60
|
+
if (!(0, internal_1.isInWorkflowFunction)()) {
|
|
61
|
+
return await doStream();
|
|
62
|
+
}
|
|
63
|
+
const workflowID = enterDurableModelCall('stream');
|
|
64
|
+
// An aborted consumer is done with this call, like a cancelled one: post-abort failures must checkpoint as a (partial) success, or replay would fail where the live run ended gracefully.
|
|
65
|
+
const aborted = () => params.abortSignal?.aborted === true;
|
|
66
|
+
// Free the concurrency guard as soon as the consumer detaches (abort/cancel), not only when the step
|
|
67
|
+
// settles: this call's step is already sequenced, so a sequential follow-up in the same workflow is
|
|
68
|
+
// deterministic on replay and must not be rejected as concurrent while this step drains in the background.
|
|
69
|
+
let guardReleased = false;
|
|
70
|
+
const releaseGuard = () => {
|
|
71
|
+
if (guardReleased)
|
|
72
|
+
return;
|
|
73
|
+
guardReleased = true;
|
|
74
|
+
params.abortSignal?.removeEventListener('abort', releaseGuard);
|
|
75
|
+
exitDurableModelCall(workflowID);
|
|
76
|
+
};
|
|
77
|
+
params.abortSignal?.addEventListener('abort', releaseGuard, { once: true });
|
|
78
|
+
let executed = false;
|
|
79
|
+
let cancelled = false;
|
|
80
|
+
let emittedLive = false;
|
|
81
|
+
let controller;
|
|
82
|
+
let step;
|
|
83
|
+
const stream = new ReadableStream({
|
|
84
|
+
start(c) {
|
|
85
|
+
controller = c;
|
|
86
|
+
},
|
|
87
|
+
// Await the step so an early cancel still blocks until the model result is checkpointed.
|
|
88
|
+
async cancel() {
|
|
89
|
+
cancelled = true;
|
|
90
|
+
releaseGuard();
|
|
91
|
+
// Post-cancel failures normally checkpoint as a success; anything else (e.g. a failed checkpoint write) is only visible here.
|
|
92
|
+
await step.catch((error) => dbos_sdk_1.DBOS.logger.warn(`Durable model call step failed after consumer cancel: ${String(error)}`));
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
const emit = (part) => {
|
|
96
|
+
if (!cancelled) {
|
|
97
|
+
controller.enqueue(part);
|
|
98
|
+
// stream-start and response-metadata merge idempotently downstream, so they alone don't preclude a retry.
|
|
99
|
+
if (part.type !== 'stream-start' && part.type !== 'response-metadata')
|
|
100
|
+
emittedLive = true;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
// Once any output part has streamed live, a retry would re-stream from scratch and duplicate output, so stop retrying.
|
|
104
|
+
const streamStepConfig = {
|
|
105
|
+
...stepConfig,
|
|
106
|
+
shouldRetry: async (error) => !emittedLive && (stepConfig.shouldRetry ? await stepConfig.shouldRetry(error) : true),
|
|
107
|
+
};
|
|
108
|
+
try {
|
|
109
|
+
step = dbos_sdk_1.DBOS.runStep(async () => {
|
|
110
|
+
executed = true;
|
|
111
|
+
const accumulator = new StreamAccumulator();
|
|
112
|
+
// A timed-out attempt is abandoned by DBOS (its outcome is discarded) but keeps running; stop it so it can't emit alongside a retry.
|
|
113
|
+
const timeoutSignal = dbos_sdk_1.DBOS.stepStatus?.timeoutSignal;
|
|
114
|
+
let streamResult;
|
|
115
|
+
let reader;
|
|
116
|
+
let sawFinish = false;
|
|
117
|
+
const abandon = () => void reader?.cancel().catch(() => { });
|
|
118
|
+
timeoutSignal?.addEventListener('abort', abandon, { once: true });
|
|
119
|
+
// A consumer abort detaches this call; stop draining now so the checkpoint lands promptly and matches what streamed.
|
|
120
|
+
params.abortSignal?.addEventListener('abort', abandon, { once: true });
|
|
121
|
+
try {
|
|
122
|
+
streamResult = await doStream();
|
|
123
|
+
reader = streamResult.stream.getReader();
|
|
124
|
+
for (;;) {
|
|
125
|
+
const { done, value: part } = await reader.read();
|
|
126
|
+
if (timeoutSignal?.aborted)
|
|
127
|
+
throw (timeoutSignal.reason ?? new Error('step attempt timed out'));
|
|
128
|
+
if (done)
|
|
129
|
+
break;
|
|
130
|
+
if (part.type === 'error') {
|
|
131
|
+
// A cancelled or aborted consumer abandoned this call; don't let a late failure become the step outcome, or replay would fail where the live run succeeded.
|
|
132
|
+
if (cancelled || aborted())
|
|
133
|
+
break;
|
|
134
|
+
throw toStepError(part.error);
|
|
135
|
+
}
|
|
136
|
+
// Stream deltas live but withhold 'finish' until the checkpoint is durable: the AI SDK runs tool calls (and their durable steps) on 'finish', which must not checkpoint before this model step.
|
|
137
|
+
if (part.type === 'finish')
|
|
138
|
+
sawFinish = true;
|
|
139
|
+
else
|
|
140
|
+
emit(part);
|
|
141
|
+
accumulator.add(part);
|
|
142
|
+
}
|
|
143
|
+
// No terminal part and no output: fail (retryably) like the AI SDK's NoOutputGeneratedError, instead of checkpointing a permanent empty success.
|
|
144
|
+
if (!sawFinish && !accumulator.hasContent && !cancelled && !aborted()) {
|
|
145
|
+
throw new Error('Model stream ended without a finish part or any output.');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
// Same rule for stream-level failures (doStream or a read rejecting) after a cancel or abort.
|
|
150
|
+
if (!cancelled && !aborted())
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
timeoutSignal?.removeEventListener('abort', abandon);
|
|
155
|
+
params.abortSignal?.removeEventListener('abort', abandon);
|
|
156
|
+
// Tear down the provider stream on early exits (error part, post-cancel break); a no-op after a clean drain.
|
|
157
|
+
void reader?.cancel().catch(() => { });
|
|
158
|
+
}
|
|
159
|
+
// Give the response a durable id/timestamp when the provider sent none, and emit it live (before the
|
|
160
|
+
// withheld 'finish') so the SDK sees the same values live and on replay instead of a fresh fallback.
|
|
161
|
+
// Skip the live emit for a timed-out (abandoned) attempt so it can't interleave with its retry.
|
|
162
|
+
const responseMetadataPart = accumulator.fillResponseMetadata((0, node_crypto_1.randomUUID)(), new Date());
|
|
163
|
+
if (responseMetadataPart && !timeoutSignal?.aborted)
|
|
164
|
+
emit(responseMetadataPart);
|
|
165
|
+
return encodeBinaryContent(accumulator.result(streamResult?.request, streamResult?.response));
|
|
166
|
+
}, { ...streamStepConfig, name: stepConfig.name ?? stepName(model, 'stream') });
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
// runStep can throw synchronously (e.g. a shutdown race); don't leak the guard entry.
|
|
170
|
+
releaseGuard();
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
// Drive the returned stream from the settled step: a live run emits only the withheld 'finish' (deltas already
|
|
174
|
+
// streamed); a recovered run synthesizes the whole stream from the checkpoint. Either way consumers finish
|
|
175
|
+
// only after the result is durable.
|
|
176
|
+
void step
|
|
177
|
+
.then((recorded) => {
|
|
178
|
+
if (cancelled)
|
|
179
|
+
return;
|
|
180
|
+
if (executed) {
|
|
181
|
+
emit({
|
|
182
|
+
type: 'finish',
|
|
183
|
+
finishReason: recorded.finishReason,
|
|
184
|
+
usage: recorded.usage,
|
|
185
|
+
providerMetadata: recorded.providerMetadata,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
for (const part of replayParts(recorded))
|
|
190
|
+
emit(part);
|
|
191
|
+
}
|
|
192
|
+
controller.close();
|
|
193
|
+
}, (error) => {
|
|
194
|
+
if (!cancelled)
|
|
195
|
+
controller.error((0, internal_1.restoreAISDKErrorIdentity)(error));
|
|
196
|
+
})
|
|
197
|
+
.finally(releaseGuard);
|
|
198
|
+
return { stream };
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/** AI SDK embedding-model middleware that runs each embedding call as a durable DBOS step, like {@link durableCalls}. */
|
|
203
|
+
function durableEmbeddingCalls(options = {}) {
|
|
204
|
+
const stepConfig = (0, internal_1.withErrorClassification)(options);
|
|
205
|
+
return {
|
|
206
|
+
specificationVersion: 'v4',
|
|
207
|
+
wrapEmbed: async ({ doEmbed, model }) => {
|
|
208
|
+
(0, internal_1.assertNotInTransaction)('embed');
|
|
209
|
+
if (!(0, internal_1.isInWorkflowFunction)()) {
|
|
210
|
+
return await doEmbed();
|
|
211
|
+
}
|
|
212
|
+
const workflowID = enterDurableModelCall('embed');
|
|
213
|
+
try {
|
|
214
|
+
return await dbos_sdk_1.DBOS.runStep(async () => doEmbed(), {
|
|
215
|
+
...stepConfig,
|
|
216
|
+
name: stepConfig.name ?? stepName(model, 'embed'),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
throw (0, internal_1.restoreAISDKErrorIdentity)(error);
|
|
221
|
+
}
|
|
222
|
+
finally {
|
|
223
|
+
exitDurableModelCall(workflowID);
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* AI SDK image-model middleware that runs each image generation as a durable DBOS step, like {@link durableCalls}.
|
|
230
|
+
* No concurrency guard: generateImage splits `n > maxImagesPerCall` into batches it dispatches synchronously (no
|
|
231
|
+
* await before doGenerate), so their step order is deterministic on replay — unlike embedMany's parallel batches.
|
|
232
|
+
*/
|
|
233
|
+
function durableImageCalls(options = {}) {
|
|
234
|
+
const stepConfig = (0, internal_1.withErrorClassification)(options);
|
|
235
|
+
return {
|
|
236
|
+
specificationVersion: 'v4',
|
|
237
|
+
wrapGenerate: async ({ doGenerate, model }) => {
|
|
238
|
+
(0, internal_1.assertNotInTransaction)('generateImage');
|
|
239
|
+
if (!(0, internal_1.isInWorkflowFunction)()) {
|
|
240
|
+
return await doGenerate();
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
return await dbos_sdk_1.DBOS.runStep(async () => encodeImageResult(await doGenerate()), {
|
|
244
|
+
...stepConfig,
|
|
245
|
+
name: stepConfig.name ?? stepName(model, 'image'),
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
throw (0, internal_1.restoreAISDKErrorIdentity)(error);
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/** Convert generated image bytes (Uint8Array) to base64 (spec-allowed) to keep checkpoints compact. */
|
|
255
|
+
function encodeImageResult(result) {
|
|
256
|
+
const images = result.images;
|
|
257
|
+
if (images.every((image) => typeof image === 'string')) {
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
...result,
|
|
262
|
+
images: images.map((image) => (typeof image === 'string' ? image : Buffer.from(image).toString('base64'))),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function stepName(model, operation) {
|
|
266
|
+
return `${model.provider}.${model.modelId}.${operation}`;
|
|
267
|
+
}
|
|
268
|
+
/** Normalize an error-part payload to an Error, preserving the payload (JSON message, cause, isRetryable). */
|
|
269
|
+
function toStepError(error) {
|
|
270
|
+
if (error instanceof Error)
|
|
271
|
+
return error;
|
|
272
|
+
let message;
|
|
273
|
+
try {
|
|
274
|
+
message = typeof error === 'string' ? error : (JSON.stringify(error) ?? String(error));
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
message = String(error);
|
|
278
|
+
}
|
|
279
|
+
const result = new Error(message, { cause: error });
|
|
280
|
+
// Carry the payload's name so an abort/timeout error-part is classified terminal (isAbortError reads .name), not retried.
|
|
281
|
+
const name = error?.name;
|
|
282
|
+
if (typeof name === 'string')
|
|
283
|
+
result.name = name;
|
|
284
|
+
const isRetryable = error?.isRetryable;
|
|
285
|
+
return isRetryable === undefined ? result : Object.assign(result, { isRetryable });
|
|
286
|
+
}
|
|
287
|
+
// generateText fills response.id/timestamp with generateId()/new Date() OUTSIDE this step when the provider omits
|
|
288
|
+
// them, so they'd differ on every replay. Populate them here (checkpointed once) so that fallback never runs.
|
|
289
|
+
function ensureResponseMetadata(result) {
|
|
290
|
+
const response = result.response;
|
|
291
|
+
// Match the AI SDK's `?? generateId()` fallback (nullish, not just undefined): a null id would regenerate too.
|
|
292
|
+
if (response?.id != null && response?.timestamp != null) {
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
...result,
|
|
297
|
+
response: { ...response, id: response?.id ?? (0, node_crypto_1.randomUUID)(), timestamp: response?.timestamp ?? new Date() },
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/** Convert generated-file bytes (Uint8Array) to base64 (spec-allowed) to keep checkpoints compact. */
|
|
301
|
+
function encodeBinaryContent(result) {
|
|
302
|
+
const content = result.content.map(encodeBinaryPart);
|
|
303
|
+
return content.some((part, i) => part !== result.content[i]) ? { ...result, content } : result;
|
|
304
|
+
}
|
|
305
|
+
function encodeBinaryPart(part) {
|
|
306
|
+
if ((part.type === 'file' || part.type === 'reasoning-file') &&
|
|
307
|
+
part.data.type === 'data' &&
|
|
308
|
+
part.data.data instanceof Uint8Array) {
|
|
309
|
+
return { ...part, data: { type: 'data', data: Buffer.from(part.data.data).toString('base64') } };
|
|
310
|
+
}
|
|
311
|
+
return part;
|
|
312
|
+
}
|
|
313
|
+
/** Assembles stream parts into a LanguageModelV4GenerateResult so a stream can be checkpointed as one step result. */
|
|
314
|
+
class StreamAccumulator {
|
|
315
|
+
content = [];
|
|
316
|
+
finishReason = { unified: 'other', raw: undefined };
|
|
317
|
+
usage = {
|
|
318
|
+
inputTokens: { total: undefined, noCache: undefined, cacheRead: undefined, cacheWrite: undefined },
|
|
319
|
+
outputTokens: { total: undefined, text: undefined, reasoning: undefined },
|
|
320
|
+
};
|
|
321
|
+
warnings = [];
|
|
322
|
+
providerMetadata;
|
|
323
|
+
responseMetadata;
|
|
324
|
+
// Text/reasoning content objects (also in content), appended at -start and mutated in place so content keeps arrival order.
|
|
325
|
+
textBlocks = new Map();
|
|
326
|
+
reasoningBlocks = new Map();
|
|
327
|
+
add(part) {
|
|
328
|
+
switch (part.type) {
|
|
329
|
+
case 'stream-start':
|
|
330
|
+
this.warnings.push(...part.warnings);
|
|
331
|
+
break;
|
|
332
|
+
case 'text-start': {
|
|
333
|
+
const block = { type: 'text', text: '', providerMetadata: part.providerMetadata };
|
|
334
|
+
this.textBlocks.set(part.id, block);
|
|
335
|
+
this.content.push(block);
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
case 'text-delta': {
|
|
339
|
+
const block = this.getOrCreateText(part.id);
|
|
340
|
+
block.text += part.delta;
|
|
341
|
+
if (part.providerMetadata)
|
|
342
|
+
block.providerMetadata = part.providerMetadata;
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case 'text-end': {
|
|
346
|
+
const block = this.textBlocks.get(part.id);
|
|
347
|
+
if (block && part.providerMetadata)
|
|
348
|
+
block.providerMetadata = part.providerMetadata;
|
|
349
|
+
this.textBlocks.delete(part.id);
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
case 'reasoning-start': {
|
|
353
|
+
const block = {
|
|
354
|
+
type: 'reasoning',
|
|
355
|
+
text: '',
|
|
356
|
+
providerMetadata: part.providerMetadata,
|
|
357
|
+
};
|
|
358
|
+
this.reasoningBlocks.set(part.id, block);
|
|
359
|
+
this.content.push(block);
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
case 'reasoning-delta': {
|
|
363
|
+
const block = this.getOrCreateReasoning(part.id);
|
|
364
|
+
block.text += part.delta;
|
|
365
|
+
if (part.providerMetadata)
|
|
366
|
+
block.providerMetadata = part.providerMetadata;
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
case 'reasoning-end': {
|
|
370
|
+
const block = this.reasoningBlocks.get(part.id);
|
|
371
|
+
if (block && part.providerMetadata)
|
|
372
|
+
block.providerMetadata = part.providerMetadata;
|
|
373
|
+
this.reasoningBlocks.delete(part.id);
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
case 'response-metadata':
|
|
377
|
+
// Merge per-field like the AI SDK: later parts override only the fields they carry.
|
|
378
|
+
this.responseMetadata = {
|
|
379
|
+
id: part.id ?? this.responseMetadata?.id,
|
|
380
|
+
timestamp: part.timestamp ?? this.responseMetadata?.timestamp,
|
|
381
|
+
modelId: part.modelId ?? this.responseMetadata?.modelId,
|
|
382
|
+
};
|
|
383
|
+
break;
|
|
384
|
+
case 'finish':
|
|
385
|
+
this.finishReason = part.finishReason;
|
|
386
|
+
this.usage = part.usage;
|
|
387
|
+
this.providerMetadata = part.providerMetadata;
|
|
388
|
+
break;
|
|
389
|
+
case 'tool-input-start':
|
|
390
|
+
case 'tool-input-delta':
|
|
391
|
+
case 'tool-input-end':
|
|
392
|
+
case 'raw':
|
|
393
|
+
case 'error':
|
|
394
|
+
// Transient parts; the tool-call part carries the complete input.
|
|
395
|
+
break;
|
|
396
|
+
default:
|
|
397
|
+
// Complete content parts: tool-call, tool-result, tool-approval-request, file, reasoning-file, source, custom.
|
|
398
|
+
this.content.push(part);
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
get hasContent() {
|
|
403
|
+
return this.content.length > 0;
|
|
404
|
+
}
|
|
405
|
+
// Fill any missing response id/timestamp so the checkpoint carries them; returns the response-metadata part to
|
|
406
|
+
// emit live (or undefined if the provider already supplied both). replayParts re-emits it from the checkpoint.
|
|
407
|
+
fillResponseMetadata(id, timestamp) {
|
|
408
|
+
// Nullish check to match the AI SDK's `?? generateId()` fallback (a null id/timestamp would regenerate too).
|
|
409
|
+
if (this.responseMetadata?.id != null && this.responseMetadata?.timestamp != null) {
|
|
410
|
+
return undefined;
|
|
411
|
+
}
|
|
412
|
+
this.responseMetadata = {
|
|
413
|
+
id: this.responseMetadata?.id ?? id,
|
|
414
|
+
timestamp: this.responseMetadata?.timestamp ?? timestamp,
|
|
415
|
+
modelId: this.responseMetadata?.modelId,
|
|
416
|
+
};
|
|
417
|
+
return { type: 'response-metadata', ...this.responseMetadata };
|
|
418
|
+
}
|
|
419
|
+
// If a delta arrives with no preceding start, create the block in arrival position rather than dropping the text.
|
|
420
|
+
getOrCreateText(id) {
|
|
421
|
+
let block = this.textBlocks.get(id);
|
|
422
|
+
if (!block) {
|
|
423
|
+
block = { type: 'text', text: '' };
|
|
424
|
+
this.textBlocks.set(id, block);
|
|
425
|
+
this.content.push(block);
|
|
426
|
+
}
|
|
427
|
+
return block;
|
|
428
|
+
}
|
|
429
|
+
getOrCreateReasoning(id) {
|
|
430
|
+
let block = this.reasoningBlocks.get(id);
|
|
431
|
+
if (!block) {
|
|
432
|
+
block = { type: 'reasoning', text: '' };
|
|
433
|
+
this.reasoningBlocks.set(id, block);
|
|
434
|
+
this.content.push(block);
|
|
435
|
+
}
|
|
436
|
+
return block;
|
|
437
|
+
}
|
|
438
|
+
result(request, response) {
|
|
439
|
+
return {
|
|
440
|
+
content: this.content,
|
|
441
|
+
finishReason: this.finishReason,
|
|
442
|
+
usage: this.usage,
|
|
443
|
+
warnings: this.warnings,
|
|
444
|
+
providerMetadata: this.providerMetadata,
|
|
445
|
+
request,
|
|
446
|
+
response: this.responseMetadata ? { ...this.responseMetadata, ...response } : response,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
/** Synthesizes a stream from a checkpointed result on recovery; text/reasoning come back as one delta per block. */
|
|
451
|
+
function* replayParts(result) {
|
|
452
|
+
yield { type: 'stream-start', warnings: result.warnings ?? [] };
|
|
453
|
+
if (result.response?.id !== undefined || result.response?.timestamp !== undefined || result.response?.modelId !== undefined) {
|
|
454
|
+
yield {
|
|
455
|
+
type: 'response-metadata',
|
|
456
|
+
id: result.response.id,
|
|
457
|
+
timestamp: result.response.timestamp,
|
|
458
|
+
modelId: result.response.modelId,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
let blockIndex = 0;
|
|
462
|
+
for (const part of result.content) {
|
|
463
|
+
const id = `replay-${blockIndex++}`;
|
|
464
|
+
if (part.type === 'text') {
|
|
465
|
+
yield { type: 'text-start', id, providerMetadata: part.providerMetadata };
|
|
466
|
+
if (part.text.length > 0)
|
|
467
|
+
yield { type: 'text-delta', id, delta: part.text };
|
|
468
|
+
yield { type: 'text-end', id, providerMetadata: part.providerMetadata };
|
|
469
|
+
}
|
|
470
|
+
else if (part.type === 'reasoning') {
|
|
471
|
+
yield { type: 'reasoning-start', id, providerMetadata: part.providerMetadata };
|
|
472
|
+
if (part.text.length > 0)
|
|
473
|
+
yield { type: 'reasoning-delta', id, delta: part.text };
|
|
474
|
+
yield { type: 'reasoning-end', id, providerMetadata: part.providerMetadata };
|
|
475
|
+
}
|
|
476
|
+
else if (part.type === 'tool-call') {
|
|
477
|
+
// Re-synthesize the tool-input grammar: consumer tool callbacks (onInputStart/onInputAvailable) are keyed off tool-input-start.
|
|
478
|
+
const { toolCallId, toolName, providerExecuted, dynamic } = part;
|
|
479
|
+
yield { type: 'tool-input-start', id: toolCallId, toolName, providerExecuted, dynamic };
|
|
480
|
+
if (part.input.length > 0)
|
|
481
|
+
yield { type: 'tool-input-delta', id: toolCallId, delta: part.input };
|
|
482
|
+
yield { type: 'tool-input-end', id: toolCallId };
|
|
483
|
+
yield part;
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
yield part;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
yield {
|
|
490
|
+
type: 'finish',
|
|
491
|
+
finishReason: result.finishReason,
|
|
492
|
+
usage: result.usage,
|
|
493
|
+
providerMetadata: result.providerMetadata,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dbos-inc/vercel-ai",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "DBOS durable execution integration for the Vercel AI SDK",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/dbos-inc/dbos-vercel-ai.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/dbos-inc/dbos-vercel-ai/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://docs.dbos.dev/",
|
|
15
|
+
"main": "dist/index.js",
|
|
16
|
+
"types": "dist/index.d.ts",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=22"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"src"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc --project tsconfig.build.json",
|
|
29
|
+
"clean": "rm -rf dist",
|
|
30
|
+
"lint": "tsc --noEmit",
|
|
31
|
+
"pretest": "npm run build",
|
|
32
|
+
"test": "tsx --test tests/*.test.mts",
|
|
33
|
+
"check:package": "npm run build && publint && attw --pack .",
|
|
34
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"dbos",
|
|
38
|
+
"ai",
|
|
39
|
+
"vercel",
|
|
40
|
+
"ai-sdk",
|
|
41
|
+
"durable-execution",
|
|
42
|
+
"workflow",
|
|
43
|
+
"llm",
|
|
44
|
+
"agent"
|
|
45
|
+
],
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@dbos-inc/dbos-sdk": "^4.21.0",
|
|
48
|
+
"ai": "^7.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@ai-sdk/gateway": "^4.0.0",
|
|
52
|
+
"@ai-sdk/provider": "^4.0.0",
|
|
53
|
+
"@arethetypeswrong/cli": "^0.18.0",
|
|
54
|
+
"@dbos-inc/dbos-sdk": "^4.23.6",
|
|
55
|
+
"@types/node": "^24.0.0",
|
|
56
|
+
"@types/pg": "^8.20.0",
|
|
57
|
+
"ai": "^7.0.0",
|
|
58
|
+
"pg": "^8.22.0",
|
|
59
|
+
"publint": "^0.3.0",
|
|
60
|
+
"tsx": "^4.20.0",
|
|
61
|
+
"typescript": "^5.8.0",
|
|
62
|
+
"zod": "^4.0.0"
|
|
63
|
+
}
|
|
64
|
+
}
|
package/src/index.ts
ADDED
package/src/internal.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DBOS, StepConfig } from '@dbos-inc/dbos-sdk';
|
|
2
|
+
|
|
3
|
+
export function isInWorkflowFunction(): boolean {
|
|
4
|
+
// True only in workflow code proper: not in a step, transaction, or outside DBOS.
|
|
5
|
+
return DBOS.isInWorkflow();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function assertNotInTransaction(operation: string): void {
|
|
9
|
+
if (DBOS.isInTransaction()) {
|
|
10
|
+
throw new Error(`Cannot call ${operation} inside a DBOS transaction; run it in workflow or step code.`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Aborts/timeouts are deliberate cancellations, never transient; retrying just re-runs an already-cancelled call.
|
|
15
|
+
function isAbortError(error: unknown): boolean {
|
|
16
|
+
const name = (error as { name?: unknown } | null)?.name;
|
|
17
|
+
return name === 'AbortError' || name === 'TimeoutError';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// AI SDK errors (APICallError, GatewayError) expose an isRetryable flag; treat an explicit false, and any abort, as terminal.
|
|
21
|
+
function isNonRetryable(error: unknown): boolean {
|
|
22
|
+
try {
|
|
23
|
+
return (
|
|
24
|
+
isAbortError(error) ||
|
|
25
|
+
(typeof error === 'object' &&
|
|
26
|
+
error !== null &&
|
|
27
|
+
'isRetryable' in error &&
|
|
28
|
+
(error as { isRetryable?: unknown }).isRetryable === false)
|
|
29
|
+
);
|
|
30
|
+
} catch {
|
|
31
|
+
// A throwing accessor must not replace the step's real error; treat as retryable.
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// serialize-error drops the Symbol-keyed AI SDK error markers on replay, so isInstance() fails on the revived error.
|
|
37
|
+
// The markers derive from error.name (which survives), so re-attach them; no @ai-sdk/provider/@ai-sdk/gateway import.
|
|
38
|
+
// AISDKError (APICallError, ...) and GatewayError use distinct marker namespaces — ai's retry predicate checks both.
|
|
39
|
+
export function restoreAISDKErrorIdentity(error: unknown): unknown {
|
|
40
|
+
// Wrap the whole body: identity restoration must never replace or mask the real error (a frozen/non-extensible
|
|
41
|
+
// error throws on assignment, a throwing `name` getter throws on read) — on failure, return the error untouched.
|
|
42
|
+
try {
|
|
43
|
+
const name = (error as { name?: unknown } | null)?.name;
|
|
44
|
+
if (error === null || typeof error !== 'object' || typeof name !== 'string') return error;
|
|
45
|
+
const base = name.startsWith('AI_') ? 'vercel.ai.error' : name.startsWith('Gateway') ? 'vercel.ai.gateway.error' : undefined;
|
|
46
|
+
if (base !== undefined) {
|
|
47
|
+
(error as Record<symbol, unknown>)[Symbol.for(base)] = true;
|
|
48
|
+
(error as Record<symbol, unknown>)[Symbol.for(`${base}.${name}`)] = true;
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
// Fall through and return the error as-is.
|
|
52
|
+
}
|
|
53
|
+
return error;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Default to DBOS-owned retries so a transient provider error is absorbed inside one step (never checkpointed as an
|
|
57
|
+
// error that replay would re-run); the default shouldRetry skips provider-declared non-retryable errors and aborts.
|
|
58
|
+
// A caller's retriesAllowed/shouldRetry wins, but an explicit `undefined` falls back to the default.
|
|
59
|
+
export function withErrorClassification(options: StepConfig): StepConfig {
|
|
60
|
+
return {
|
|
61
|
+
...options,
|
|
62
|
+
retriesAllowed: options.retriesAllowed ?? true,
|
|
63
|
+
shouldRetry: options.shouldRetry ?? ((error: unknown) => !isNonRetryable(error)),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|