@ai-sdk/quiverai 2.0.47 → 2.0.50
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 +28 -0
- package/README.md +15 -1
- package/dist/index.d.ts +29 -2
- package/dist/index.js +277 -143
- package/dist/index.js.map +1 -1
- package/docs/180-quiverai.mdx +115 -2
- package/package.json +5 -4
- package/src/index.ts +3 -0
- package/src/quiverai-error.ts +28 -0
- package/src/quiverai-image-model.ts +1 -14
- package/src/quiverai-language-model-options.ts +11 -0
- package/src/quiverai-language-model-settings.ts +4 -0
- package/src/quiverai-language-model.ts +162 -0
- package/src/quiverai-provider.ts +69 -24
package/dist/index.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
NoSuchModelError
|
|
4
4
|
} from "@ai-sdk/provider";
|
|
5
|
+
import {
|
|
6
|
+
createOpenResponses as createOpenResponses2
|
|
7
|
+
} from "@ai-sdk/open-responses";
|
|
5
8
|
import {
|
|
6
9
|
loadApiKey,
|
|
7
10
|
loadOptionalSetting,
|
|
@@ -9,33 +12,168 @@ import {
|
|
|
9
12
|
withUserAgentSuffix
|
|
10
13
|
} from "@ai-sdk/provider-utils";
|
|
11
14
|
|
|
15
|
+
// src/quiverai-error.ts
|
|
16
|
+
import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
|
|
17
|
+
import { z } from "zod/v4";
|
|
18
|
+
var quiveraiErrorSchema = z.object({
|
|
19
|
+
status: z.number().int(),
|
|
20
|
+
code: z.string().min(1),
|
|
21
|
+
message: z.string().min(1),
|
|
22
|
+
request_id: z.string().min(1)
|
|
23
|
+
});
|
|
24
|
+
var quiveraiFailedResponseHandler = createJsonErrorResponseHandler({
|
|
25
|
+
errorSchema: quiveraiErrorSchema,
|
|
26
|
+
errorToMessage: (error) => error.message,
|
|
27
|
+
isRetryable: (response) => response.status === 429 || response.status >= 500
|
|
28
|
+
});
|
|
29
|
+
var getQuiverAIResponseErrorMetadata = (error) => ({
|
|
30
|
+
statusCode: typeof error.status_code === "number" && Number.isInteger(error.status_code) && error.status_code >= 400 && error.status_code <= 599 ? error.status_code : void 0
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// src/quiverai-language-model.ts
|
|
34
|
+
import {
|
|
35
|
+
InvalidArgumentError
|
|
36
|
+
} from "@ai-sdk/provider";
|
|
37
|
+
import {
|
|
38
|
+
createOpenResponses
|
|
39
|
+
} from "@ai-sdk/open-responses";
|
|
40
|
+
import {
|
|
41
|
+
serializeModelOptions,
|
|
42
|
+
WORKFLOW_DESERIALIZE,
|
|
43
|
+
WORKFLOW_SERIALIZE
|
|
44
|
+
} from "@ai-sdk/provider-utils";
|
|
45
|
+
var QuiverAILanguageModel = class _QuiverAILanguageModel {
|
|
46
|
+
constructor(model, config) {
|
|
47
|
+
this.model = model;
|
|
48
|
+
this.config = config;
|
|
49
|
+
this.specificationVersion = "v4";
|
|
50
|
+
}
|
|
51
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
52
|
+
return serializeModelOptions({
|
|
53
|
+
modelId: model.modelId,
|
|
54
|
+
config: model.config
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
58
|
+
const config = {
|
|
59
|
+
...options.config,
|
|
60
|
+
failedResponseHandler: quiveraiFailedResponseHandler,
|
|
61
|
+
getResponseErrorMetadata: getQuiverAIResponseErrorMetadata
|
|
62
|
+
};
|
|
63
|
+
return new _QuiverAILanguageModel(
|
|
64
|
+
createOpenResponses(config).languageModel(options.modelId),
|
|
65
|
+
config
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
get modelId() {
|
|
69
|
+
return this.model.modelId;
|
|
70
|
+
}
|
|
71
|
+
get provider() {
|
|
72
|
+
return this.model.provider;
|
|
73
|
+
}
|
|
74
|
+
get supportedUrls() {
|
|
75
|
+
return this.model.supportedUrls;
|
|
76
|
+
}
|
|
77
|
+
async doGenerate(options) {
|
|
78
|
+
const prepared = prepareQuiverAICall(options);
|
|
79
|
+
const result = await this.model.doGenerate(prepared.options);
|
|
80
|
+
return { ...result, warnings: [...prepared.warnings, ...result.warnings] };
|
|
81
|
+
}
|
|
82
|
+
async doStream(options) {
|
|
83
|
+
const prepared = prepareQuiverAICall(options);
|
|
84
|
+
const result = await this.model.doStream(prepared.options);
|
|
85
|
+
if (prepared.warnings.length === 0) return result;
|
|
86
|
+
return {
|
|
87
|
+
...result,
|
|
88
|
+
stream: result.stream.pipeThrough(
|
|
89
|
+
new TransformStream({
|
|
90
|
+
transform(part, controller) {
|
|
91
|
+
controller.enqueue(
|
|
92
|
+
part.type === "stream-start" ? {
|
|
93
|
+
...part,
|
|
94
|
+
warnings: [...prepared.warnings, ...part.warnings]
|
|
95
|
+
} : part
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
function prepareQuiverAICall(options) {
|
|
104
|
+
const { reasoningEffort, reasoningSummary } = options.providerOptions?.quiverai ?? {};
|
|
105
|
+
if (reasoningEffort != null && (typeof reasoningEffort !== "string" || !["low", "medium", "high", "xhigh"].includes(reasoningEffort))) {
|
|
106
|
+
throw new InvalidArgumentError({
|
|
107
|
+
argument: "providerOptions",
|
|
108
|
+
message: `Unsupported reasoning effort: ${reasoningEffort}`
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (reasoningSummary != null && reasoningSummary !== "auto") {
|
|
112
|
+
throw new InvalidArgumentError({
|
|
113
|
+
argument: "providerOptions",
|
|
114
|
+
message: `Unsupported reasoning summary: ${reasoningSummary}`
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const warnings = [];
|
|
118
|
+
const omitReasoning = options.reasoning === "none" && reasoningEffort == null;
|
|
119
|
+
if (omitReasoning) {
|
|
120
|
+
warnings.push({ type: "unsupported", feature: "reasoning effort none" });
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
warnings,
|
|
124
|
+
options: {
|
|
125
|
+
...options,
|
|
126
|
+
reasoning: omitReasoning ? void 0 : options.reasoning,
|
|
127
|
+
prompt: options.prompt.map(
|
|
128
|
+
(message) => message.role !== "assistant" ? message : {
|
|
129
|
+
...message,
|
|
130
|
+
content: message.content.map((part) => {
|
|
131
|
+
if (part.type !== "reasoning") return part;
|
|
132
|
+
const metadata = part.providerOptions?.quiverai ?? part.providerMetadata?.quiverai;
|
|
133
|
+
return {
|
|
134
|
+
...part,
|
|
135
|
+
text: "",
|
|
136
|
+
providerOptions: {
|
|
137
|
+
...part.providerOptions,
|
|
138
|
+
quiverai: {
|
|
139
|
+
itemId: metadata?.itemId,
|
|
140
|
+
reasoningSummary: metadata?.reasoningSummary
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
12
151
|
// src/quiverai-image-model.ts
|
|
13
152
|
import {
|
|
14
|
-
InvalidArgumentError as
|
|
153
|
+
InvalidArgumentError as InvalidArgumentError3
|
|
15
154
|
} from "@ai-sdk/provider";
|
|
16
155
|
import {
|
|
17
156
|
combineHeaders,
|
|
18
157
|
convertBase64ToUint8Array as convertBase64ToUint8Array2,
|
|
19
158
|
convertUint8ArrayToBase64 as convertUint8ArrayToBase642,
|
|
20
|
-
createJsonErrorResponseHandler,
|
|
21
159
|
createJsonResponseHandler,
|
|
22
160
|
parseProviderOptions,
|
|
23
161
|
postJsonToApi,
|
|
24
|
-
serializeModelOptions,
|
|
25
|
-
WORKFLOW_DESERIALIZE,
|
|
26
|
-
WORKFLOW_SERIALIZE
|
|
162
|
+
serializeModelOptions as serializeModelOptions2,
|
|
163
|
+
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2,
|
|
164
|
+
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2
|
|
27
165
|
} from "@ai-sdk/provider-utils";
|
|
28
|
-
import { z as
|
|
166
|
+
import { z as z3 } from "zod/v4";
|
|
29
167
|
|
|
30
168
|
// src/quiverai-image-model-options.ts
|
|
31
169
|
import {
|
|
32
170
|
lazySchema,
|
|
33
171
|
zodSchema
|
|
34
172
|
} from "@ai-sdk/provider-utils";
|
|
35
|
-
import { z } from "zod/v4";
|
|
173
|
+
import { z as z2 } from "zod/v4";
|
|
36
174
|
var quiveraiImageModelOptionsSchema = lazySchema(
|
|
37
175
|
() => zodSchema(
|
|
38
|
-
|
|
176
|
+
z2.object({
|
|
39
177
|
/**
|
|
40
178
|
* The operation to perform. Defaults to `generate`.
|
|
41
179
|
*
|
|
@@ -47,81 +185,81 @@ var quiveraiImageModelOptionsSchema = lazySchema(
|
|
|
47
185
|
* - `edit`: Edit a single SVG from `prompt.images` using `prompt.text`
|
|
48
186
|
* as the required instruction.
|
|
49
187
|
*/
|
|
50
|
-
operation:
|
|
188
|
+
operation: z2.enum(["generate", "vectorize", "animate", "edit"]).optional(),
|
|
51
189
|
/**
|
|
52
190
|
* Extra style guidance for prompt-based generation.
|
|
53
191
|
*/
|
|
54
|
-
instructions:
|
|
192
|
+
instructions: z2.string().min(1).optional(),
|
|
55
193
|
/**
|
|
56
194
|
* Reasoning effort applied to generation or vectorization.
|
|
57
195
|
*/
|
|
58
|
-
reasoningEffort:
|
|
196
|
+
reasoningEffort: z2.enum(["low", "medium", "high", "xhigh"]).optional(),
|
|
59
197
|
/**
|
|
60
198
|
* Optional reference images for SVG editing. Use
|
|
61
199
|
* `prepareQuiverAIImageReference` to convert binary inputs.
|
|
62
200
|
*/
|
|
63
|
-
referenceImages:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
201
|
+
referenceImages: z2.array(
|
|
202
|
+
z2.union([
|
|
203
|
+
z2.object({ url: z2.string().min(1) }).strict(),
|
|
204
|
+
z2.object({ base64: z2.string().min(1).max(16777216) }).strict()
|
|
67
205
|
])
|
|
68
206
|
).max(4).optional(),
|
|
69
207
|
/**
|
|
70
208
|
* Maximum number of edit review and redo steps (0-5).
|
|
71
209
|
*/
|
|
72
|
-
maxReviewSteps:
|
|
210
|
+
maxReviewSteps: z2.number().int().min(0).max(5).optional(),
|
|
73
211
|
/**
|
|
74
212
|
* SVG root attributes requested for generation or vectorization.
|
|
75
213
|
*/
|
|
76
|
-
attributes:
|
|
77
|
-
viewBox:
|
|
78
|
-
minX:
|
|
79
|
-
minY:
|
|
80
|
-
width:
|
|
81
|
-
height:
|
|
214
|
+
attributes: z2.object({
|
|
215
|
+
viewBox: z2.object({
|
|
216
|
+
minX: z2.number(),
|
|
217
|
+
minY: z2.number(),
|
|
218
|
+
width: z2.number().positive(),
|
|
219
|
+
height: z2.number().positive()
|
|
82
220
|
}).optional()
|
|
83
221
|
}).optional(),
|
|
84
222
|
/**
|
|
85
223
|
* Sampling temperature (0-2).
|
|
86
224
|
*/
|
|
87
|
-
temperature:
|
|
225
|
+
temperature: z2.number().min(0).max(2).optional(),
|
|
88
226
|
/**
|
|
89
227
|
* Nucleus sampling top-p (0-1).
|
|
90
228
|
*/
|
|
91
|
-
topP:
|
|
229
|
+
topP: z2.number().min(0).max(1).optional(),
|
|
92
230
|
/**
|
|
93
231
|
* Presence penalty (-2 to 2).
|
|
94
232
|
*/
|
|
95
|
-
presencePenalty:
|
|
233
|
+
presencePenalty: z2.number().min(-2).max(2).nullable().optional(),
|
|
96
234
|
/**
|
|
97
235
|
* Maximum number of output tokens (1 - 65536 for Arrow 2 models).
|
|
98
236
|
* The legacy upper bound of 131072 is retained for other model IDs.
|
|
99
237
|
*/
|
|
100
|
-
maxOutputTokens:
|
|
238
|
+
maxOutputTokens: z2.number().int().min(1).max(131072).optional(),
|
|
101
239
|
/**
|
|
102
240
|
* Provider orchestrator token budget for SVG editing (1-65536).
|
|
103
241
|
*/
|
|
104
|
-
orchestratorMaxOutputTokens:
|
|
242
|
+
orchestratorMaxOutputTokens: z2.number().int().min(1).max(65536).optional(),
|
|
105
243
|
/**
|
|
106
244
|
* Provider shallow edit token budget for SVG editing (1-65536).
|
|
107
245
|
*/
|
|
108
|
-
shallowMaxOutputTokens:
|
|
246
|
+
shallowMaxOutputTokens: z2.number().int().min(1).max(65536).optional(),
|
|
109
247
|
/**
|
|
110
248
|
* Whether to auto-crop the input image before vectorization.
|
|
111
249
|
* Only used when `operation` is `vectorize`.
|
|
112
250
|
*/
|
|
113
|
-
autoCrop:
|
|
251
|
+
autoCrop: z2.boolean().optional(),
|
|
114
252
|
/**
|
|
115
253
|
* Target canvas size in pixels for vectorization (128 - 4096).
|
|
116
254
|
* Only used when `operation` is `vectorize`.
|
|
117
255
|
*/
|
|
118
|
-
targetSize:
|
|
256
|
+
targetSize: z2.number().int().min(128).max(4096).optional()
|
|
119
257
|
})
|
|
120
258
|
)
|
|
121
259
|
);
|
|
122
260
|
|
|
123
261
|
// src/prepare-quiverai-image-reference.ts
|
|
124
|
-
import { InvalidArgumentError } from "@ai-sdk/provider";
|
|
262
|
+
import { InvalidArgumentError as InvalidArgumentError2 } from "@ai-sdk/provider";
|
|
125
263
|
import {
|
|
126
264
|
convertBase64ToUint8Array,
|
|
127
265
|
convertUint8ArrayToBase64,
|
|
@@ -147,7 +285,7 @@ function prepareQuiverAIImageReference(input) {
|
|
|
147
285
|
if (input.startsWith("data:")) {
|
|
148
286
|
const match = /^data:([^;,]+);base64,(.+)$/s.exec(input);
|
|
149
287
|
if (match == null || !supportedReferenceMediaTypes.has(match[1])) {
|
|
150
|
-
throw new
|
|
288
|
+
throw new InvalidArgumentError2({
|
|
151
289
|
argument: "input",
|
|
152
290
|
message: "QuiverAI reference image data URLs must use base64 encoding and a supported image media type."
|
|
153
291
|
});
|
|
@@ -166,14 +304,14 @@ function validateQuiverAIImageUrl(url) {
|
|
|
166
304
|
let parsed;
|
|
167
305
|
try {
|
|
168
306
|
parsed = new URL(url);
|
|
169
|
-
} catch
|
|
170
|
-
throw new
|
|
307
|
+
} catch {
|
|
308
|
+
throw new InvalidArgumentError2({
|
|
171
309
|
argument: "url",
|
|
172
310
|
message: "QuiverAI image URLs must be valid HTTP or HTTPS URLs."
|
|
173
311
|
});
|
|
174
312
|
}
|
|
175
313
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
176
|
-
throw new
|
|
314
|
+
throw new InvalidArgumentError2({
|
|
177
315
|
argument: "url",
|
|
178
316
|
message: "QuiverAI image URLs must use HTTP or HTTPS."
|
|
179
317
|
});
|
|
@@ -182,7 +320,7 @@ function validateQuiverAIImageUrl(url) {
|
|
|
182
320
|
}
|
|
183
321
|
function validateQuiverAIReferenceBase64(base64, argument) {
|
|
184
322
|
if (base64.length === 0 || base64.length > MAX_REFERENCE_BASE64_LENGTH) {
|
|
185
|
-
throw new
|
|
323
|
+
throw new InvalidArgumentError2({
|
|
186
324
|
argument,
|
|
187
325
|
message: `QuiverAI reference images must contain 1-${MAX_REFERENCE_BASE64_LENGTH} base64 characters.`
|
|
188
326
|
});
|
|
@@ -191,7 +329,7 @@ function validateQuiverAIReferenceBase64(base64, argument) {
|
|
|
191
329
|
try {
|
|
192
330
|
data = convertBase64ToUint8Array(base64);
|
|
193
331
|
} catch (cause) {
|
|
194
|
-
throw new
|
|
332
|
+
throw new InvalidArgumentError2({
|
|
195
333
|
argument,
|
|
196
334
|
message: "QuiverAI reference image data must be valid base64.",
|
|
197
335
|
cause
|
|
@@ -201,14 +339,14 @@ function validateQuiverAIReferenceBase64(base64, argument) {
|
|
|
201
339
|
}
|
|
202
340
|
function validateQuiverAIReferenceBytes(data, argument) {
|
|
203
341
|
if (data.length === 0 || data.length > MAX_REFERENCE_BYTES) {
|
|
204
|
-
throw new
|
|
342
|
+
throw new InvalidArgumentError2({
|
|
205
343
|
argument,
|
|
206
344
|
message: `QuiverAI reference images must decode to 1-${MAX_REFERENCE_BYTES} bytes.`
|
|
207
345
|
});
|
|
208
346
|
}
|
|
209
347
|
const mediaType = isSvg(data) ? "image/svg+xml" : detectMediaType({ data, topLevelType: "image" });
|
|
210
348
|
if (mediaType == null || !supportedReferenceMediaTypes.has(mediaType)) {
|
|
211
|
-
throw new
|
|
349
|
+
throw new InvalidArgumentError2({
|
|
212
350
|
argument,
|
|
213
351
|
message: "QuiverAI reference images must be PNG, JPEG, WebP, GIF, or SVG data."
|
|
214
352
|
});
|
|
@@ -218,7 +356,7 @@ function isSvg(data) {
|
|
|
218
356
|
let text;
|
|
219
357
|
try {
|
|
220
358
|
text = new TextDecoder("utf-8", { fatal: true }).decode(data);
|
|
221
|
-
} catch
|
|
359
|
+
} catch {
|
|
222
360
|
return false;
|
|
223
361
|
}
|
|
224
362
|
const normalized = text.replace(/^\uFEFF/, "").trim();
|
|
@@ -238,13 +376,13 @@ var QuiverAIImageModel = class _QuiverAIImageModel {
|
|
|
238
376
|
get provider() {
|
|
239
377
|
return this.config.provider;
|
|
240
378
|
}
|
|
241
|
-
static [
|
|
242
|
-
return
|
|
379
|
+
static [WORKFLOW_SERIALIZE2](model) {
|
|
380
|
+
return serializeModelOptions2({
|
|
243
381
|
modelId: model.modelId,
|
|
244
382
|
config: model.config
|
|
245
383
|
});
|
|
246
384
|
}
|
|
247
|
-
static [
|
|
385
|
+
static [WORKFLOW_DESERIALIZE2](options) {
|
|
248
386
|
return new _QuiverAIImageModel(options.modelId, options.config);
|
|
249
387
|
}
|
|
250
388
|
async doGenerate({
|
|
@@ -259,13 +397,12 @@ var QuiverAIImageModel = class _QuiverAIImageModel {
|
|
|
259
397
|
headers,
|
|
260
398
|
abortSignal
|
|
261
399
|
}) {
|
|
262
|
-
var _a, _b, _c, _d, _e, _f;
|
|
263
400
|
const quiveraiOptions = await parseProviderOptions({
|
|
264
401
|
provider: "quiverai",
|
|
265
402
|
providerOptions,
|
|
266
403
|
schema: quiveraiImageModelOptionsSchema
|
|
267
404
|
});
|
|
268
|
-
const operation =
|
|
405
|
+
const operation = quiveraiOptions?.operation ?? "generate";
|
|
269
406
|
const warnings = collectWarnings({ size, aspectRatio, seed, mask });
|
|
270
407
|
const body = buildRequestBody({
|
|
271
408
|
modelId: this.modelId,
|
|
@@ -274,10 +411,10 @@ var QuiverAIImageModel = class _QuiverAIImageModel {
|
|
|
274
411
|
files,
|
|
275
412
|
mask,
|
|
276
413
|
operation,
|
|
277
|
-
options: quiveraiOptions
|
|
414
|
+
options: quiveraiOptions ?? {}
|
|
278
415
|
});
|
|
279
|
-
const currentDate =
|
|
280
|
-
const combinedHeaders = combineHeaders(
|
|
416
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
417
|
+
const combinedHeaders = combineHeaders(this.config.headers?.(), headers);
|
|
281
418
|
const { value: response, responseHeaders } = await postJsonToApi({
|
|
282
419
|
url: `${this.config.baseURL}${getOperationPath(operation)}`,
|
|
283
420
|
headers: combinedHeaders,
|
|
@@ -349,19 +486,18 @@ function toQuiverAIImageReference(image) {
|
|
|
349
486
|
}
|
|
350
487
|
var maxAnimationSourceBase64Length = 1066668;
|
|
351
488
|
function toQuiverAIAnimationSource(image) {
|
|
352
|
-
var _a;
|
|
353
489
|
if (image.type === "url") {
|
|
354
490
|
let url;
|
|
355
491
|
try {
|
|
356
492
|
url = new URL(image.url);
|
|
357
|
-
} catch
|
|
358
|
-
throw new
|
|
493
|
+
} catch {
|
|
494
|
+
throw new InvalidArgumentError3({
|
|
359
495
|
argument: "files",
|
|
360
496
|
message: "QuiverAI animate requires a valid HTTP or HTTPS SVG URL."
|
|
361
497
|
});
|
|
362
498
|
}
|
|
363
499
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
364
|
-
throw new
|
|
500
|
+
throw new InvalidArgumentError3({
|
|
365
501
|
argument: "files",
|
|
366
502
|
message: "QuiverAI animate requires an HTTP or HTTPS SVG URL."
|
|
367
503
|
});
|
|
@@ -372,11 +508,11 @@ function toQuiverAIAnimationSource(image) {
|
|
|
372
508
|
let bytes;
|
|
373
509
|
if (typeof image.data === "string") {
|
|
374
510
|
const dataUrlMatch = /^data:image\/svg\+xml(?:;[^,]*)?;base64,([\s\S]+)$/i.exec(image.data);
|
|
375
|
-
const encodedData =
|
|
511
|
+
const encodedData = dataUrlMatch?.[1] ?? image.data;
|
|
376
512
|
try {
|
|
377
513
|
bytes = convertBase64ToUint8Array2(encodedData);
|
|
378
|
-
} catch
|
|
379
|
-
throw new
|
|
514
|
+
} catch {
|
|
515
|
+
throw new InvalidArgumentError3({
|
|
380
516
|
argument: "files",
|
|
381
517
|
message: "QuiverAI animate requires the source SVG string to be valid base64 or an SVG data URL."
|
|
382
518
|
});
|
|
@@ -387,13 +523,13 @@ function toQuiverAIAnimationSource(image) {
|
|
|
387
523
|
base64 = convertUint8ArrayToBase642(bytes);
|
|
388
524
|
}
|
|
389
525
|
if (!isSvg2(bytes)) {
|
|
390
|
-
throw new
|
|
526
|
+
throw new InvalidArgumentError3({
|
|
391
527
|
argument: "files",
|
|
392
528
|
message: "QuiverAI animate requires the input file to contain SVG data."
|
|
393
529
|
});
|
|
394
530
|
}
|
|
395
531
|
if (base64.length > maxAnimationSourceBase64Length) {
|
|
396
|
-
throw new
|
|
532
|
+
throw new InvalidArgumentError3({
|
|
397
533
|
argument: "files",
|
|
398
534
|
message: `QuiverAI animate accepts at most ${maxAnimationSourceBase64Length} base64 characters for the source SVG.`
|
|
399
535
|
});
|
|
@@ -416,7 +552,7 @@ function buildRequestBody({
|
|
|
416
552
|
options
|
|
417
553
|
}) {
|
|
418
554
|
if ((modelId === "arrow-2" || modelId === "arrow-2-telos") && options.maxOutputTokens != null && options.maxOutputTokens > 65536) {
|
|
419
|
-
throw new
|
|
555
|
+
throw new InvalidArgumentError3({
|
|
420
556
|
argument: "maxOutputTokens",
|
|
421
557
|
message: `QuiverAI model "${modelId}" supports at most 65536 output tokens.`
|
|
422
558
|
});
|
|
@@ -435,15 +571,15 @@ function buildRequestBody({
|
|
|
435
571
|
}
|
|
436
572
|
if (operation === "generate") {
|
|
437
573
|
if (prompt == null || prompt.trim().length === 0) {
|
|
438
|
-
throw new
|
|
574
|
+
throw new InvalidArgumentError3({
|
|
439
575
|
argument: "prompt",
|
|
440
576
|
message: "QuiverAI image generation requires a non-empty prompt for generateImage."
|
|
441
577
|
});
|
|
442
578
|
}
|
|
443
|
-
const references = files
|
|
579
|
+
const references = files?.map(toQuiverAIImageReference);
|
|
444
580
|
const maxReferences = getGenerateReferenceLimit(modelId);
|
|
445
581
|
if (references != null && references.length > maxReferences) {
|
|
446
|
-
throw new
|
|
582
|
+
throw new InvalidArgumentError3({
|
|
447
583
|
argument: "files",
|
|
448
584
|
message: `QuiverAI generate supports up to ${maxReferences} reference images for model "${modelId}".`
|
|
449
585
|
});
|
|
@@ -478,19 +614,19 @@ function buildRequestBody({
|
|
|
478
614
|
});
|
|
479
615
|
}
|
|
480
616
|
if (files == null || files.length === 0) {
|
|
481
|
-
throw new
|
|
617
|
+
throw new InvalidArgumentError3({
|
|
482
618
|
argument: "files",
|
|
483
619
|
message: 'QuiverAI vectorize requires an input image. Pass an image in the generateImage prompt and set providerOptions.quiverai.operation to "vectorize".'
|
|
484
620
|
});
|
|
485
621
|
}
|
|
486
622
|
if (files.length > 1) {
|
|
487
|
-
throw new
|
|
623
|
+
throw new InvalidArgumentError3({
|
|
488
624
|
argument: "files",
|
|
489
625
|
message: "QuiverAI vectorize accepts a single input image."
|
|
490
626
|
});
|
|
491
627
|
}
|
|
492
628
|
if (n !== 1) {
|
|
493
|
-
throw new
|
|
629
|
+
throw new InvalidArgumentError3({
|
|
494
630
|
argument: "n",
|
|
495
631
|
message: "QuiverAI vectorize returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to vectorize multiple times."
|
|
496
632
|
});
|
|
@@ -512,37 +648,37 @@ function buildAnimationRequestBody({
|
|
|
512
648
|
options
|
|
513
649
|
}) {
|
|
514
650
|
if (modelId !== "arrow-2" && modelId !== "arrow-2-telos") {
|
|
515
|
-
throw new
|
|
651
|
+
throw new InvalidArgumentError3({
|
|
516
652
|
argument: "modelId",
|
|
517
653
|
message: 'QuiverAI animate is supported by the "arrow-2" and "arrow-2-telos" models.'
|
|
518
654
|
});
|
|
519
655
|
}
|
|
520
656
|
if (files == null || files.length === 0) {
|
|
521
|
-
throw new
|
|
657
|
+
throw new InvalidArgumentError3({
|
|
522
658
|
argument: "files",
|
|
523
659
|
message: "QuiverAI animate requires exactly one source SVG in prompt.images."
|
|
524
660
|
});
|
|
525
661
|
}
|
|
526
662
|
if (files.length !== 1) {
|
|
527
|
-
throw new
|
|
663
|
+
throw new InvalidArgumentError3({
|
|
528
664
|
argument: "files",
|
|
529
665
|
message: "QuiverAI animate accepts exactly one source SVG in prompt.images."
|
|
530
666
|
});
|
|
531
667
|
}
|
|
532
668
|
if (n !== 1) {
|
|
533
|
-
throw new
|
|
669
|
+
throw new InvalidArgumentError3({
|
|
534
670
|
argument: "n",
|
|
535
671
|
message: "QuiverAI animate returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to animate multiple times."
|
|
536
672
|
});
|
|
537
673
|
}
|
|
538
674
|
if (mask != null) {
|
|
539
|
-
throw new
|
|
675
|
+
throw new InvalidArgumentError3({
|
|
540
676
|
argument: "mask",
|
|
541
677
|
message: "QuiverAI animate does not support masks."
|
|
542
678
|
});
|
|
543
679
|
}
|
|
544
680
|
if (prompt != null && prompt.trim().length === 0) {
|
|
545
|
-
throw new
|
|
681
|
+
throw new InvalidArgumentError3({
|
|
546
682
|
argument: "prompt",
|
|
547
683
|
message: "QuiverAI animate requires a non-empty prompt when an animation instruction is provided."
|
|
548
684
|
});
|
|
@@ -558,7 +694,7 @@ function buildAnimationRequestBody({
|
|
|
558
694
|
return option[1] !== void 0;
|
|
559
695
|
});
|
|
560
696
|
if (unsupportedOptions.length > 0) {
|
|
561
|
-
throw new
|
|
697
|
+
throw new InvalidArgumentError3({
|
|
562
698
|
argument: `providerOptions.quiverai.${unsupportedOptions[0][0]}`,
|
|
563
699
|
message: `QuiverAI animate does not support providerOptions.quiverai.${unsupportedOptions[0][0]}.`
|
|
564
700
|
});
|
|
@@ -583,45 +719,44 @@ function buildEditRequestBody({
|
|
|
583
719
|
mask,
|
|
584
720
|
options
|
|
585
721
|
}) {
|
|
586
|
-
var _a;
|
|
587
722
|
if (!editModelIds.has(modelId)) {
|
|
588
|
-
throw new
|
|
723
|
+
throw new InvalidArgumentError3({
|
|
589
724
|
argument: "modelId",
|
|
590
725
|
message: 'QuiverAI SVG editing is supported by the "arrow-2" and "arrow-2-telos" models.'
|
|
591
726
|
});
|
|
592
727
|
}
|
|
593
728
|
if (prompt == null || prompt.trim().length === 0) {
|
|
594
|
-
throw new
|
|
729
|
+
throw new InvalidArgumentError3({
|
|
595
730
|
argument: "prompt",
|
|
596
731
|
message: "QuiverAI SVG editing requires a non-empty instruction in generateImage prompt.text."
|
|
597
732
|
});
|
|
598
733
|
}
|
|
599
734
|
if (prompt.length > 4e3) {
|
|
600
|
-
throw new
|
|
735
|
+
throw new InvalidArgumentError3({
|
|
601
736
|
argument: "prompt",
|
|
602
737
|
message: "QuiverAI SVG editing instructions must contain at most 4000 characters."
|
|
603
738
|
});
|
|
604
739
|
}
|
|
605
740
|
if (files == null || files.length === 0) {
|
|
606
|
-
throw new
|
|
741
|
+
throw new InvalidArgumentError3({
|
|
607
742
|
argument: "files",
|
|
608
743
|
message: "QuiverAI SVG editing requires one source SVG in generateImage prompt.images."
|
|
609
744
|
});
|
|
610
745
|
}
|
|
611
746
|
if (files.length !== 1) {
|
|
612
|
-
throw new
|
|
747
|
+
throw new InvalidArgumentError3({
|
|
613
748
|
argument: "files",
|
|
614
749
|
message: "QuiverAI SVG editing accepts exactly one source SVG."
|
|
615
750
|
});
|
|
616
751
|
}
|
|
617
752
|
if (n !== 1) {
|
|
618
|
-
throw new
|
|
753
|
+
throw new InvalidArgumentError3({
|
|
619
754
|
argument: "n",
|
|
620
755
|
message: "QuiverAI SVG editing returns exactly one SVG per request. Set maxImagesPerCall to 1 in generateImage to edit multiple times."
|
|
621
756
|
});
|
|
622
757
|
}
|
|
623
758
|
if (mask != null) {
|
|
624
|
-
throw new
|
|
759
|
+
throw new InvalidArgumentError3({
|
|
625
760
|
argument: "mask",
|
|
626
761
|
message: "QuiverAI SVG editing does not support masks."
|
|
627
762
|
});
|
|
@@ -635,14 +770,14 @@ function buildEditRequestBody({
|
|
|
635
770
|
["targetSize", options.targetSize]
|
|
636
771
|
].flatMap(([name, value]) => value == null ? [] : [name]);
|
|
637
772
|
if (unsupportedOptions.length > 0) {
|
|
638
|
-
throw new
|
|
773
|
+
throw new InvalidArgumentError3({
|
|
639
774
|
argument: "providerOptions",
|
|
640
775
|
message: `QuiverAI SVG editing does not support these provider options: ${unsupportedOptions.join(
|
|
641
776
|
", "
|
|
642
777
|
)}.`
|
|
643
778
|
});
|
|
644
779
|
}
|
|
645
|
-
const referenceImages =
|
|
780
|
+
const referenceImages = options.referenceImages?.map((reference, index) => {
|
|
646
781
|
if ("url" in reference) {
|
|
647
782
|
return {
|
|
648
783
|
url: validateQuiverAIImageUrl(reference.url)
|
|
@@ -680,7 +815,7 @@ function rejectEditOnlyOptions(operation, options) {
|
|
|
680
815
|
["shallowMaxOutputTokens", options.shallowMaxOutputTokens]
|
|
681
816
|
].flatMap(([name, value]) => value == null ? [] : [name]);
|
|
682
817
|
if (editOnlyOptions.length > 0) {
|
|
683
|
-
throw new
|
|
818
|
+
throw new InvalidArgumentError3({
|
|
684
819
|
argument: "providerOptions",
|
|
685
820
|
message: `QuiverAI ${operation} does not support these edit-only provider options: ${editOnlyOptions.join(
|
|
686
821
|
", "
|
|
@@ -700,14 +835,14 @@ function toQuiverAIEditSource(file) {
|
|
|
700
835
|
try {
|
|
701
836
|
data = typeof file.data === "string" ? convertBase64ToUint8Array2(file.data) : file.data;
|
|
702
837
|
} catch (cause) {
|
|
703
|
-
throw new
|
|
838
|
+
throw new InvalidArgumentError3({
|
|
704
839
|
argument: "files",
|
|
705
840
|
message: "QuiverAI SVG source data must be valid base64 or binary data.",
|
|
706
841
|
cause
|
|
707
842
|
});
|
|
708
843
|
}
|
|
709
844
|
if (data.length === 0 || data.length > MAX_EDIT_SVG_BYTES) {
|
|
710
|
-
throw new
|
|
845
|
+
throw new InvalidArgumentError3({
|
|
711
846
|
argument: "files",
|
|
712
847
|
message: `QuiverAI SVG source data must contain 1-${MAX_EDIT_SVG_BYTES} bytes.`
|
|
713
848
|
});
|
|
@@ -716,14 +851,14 @@ function toQuiverAIEditSource(file) {
|
|
|
716
851
|
try {
|
|
717
852
|
svg = new TextDecoder("utf-8", { fatal: true }).decode(data);
|
|
718
853
|
} catch (cause) {
|
|
719
|
-
throw new
|
|
854
|
+
throw new InvalidArgumentError3({
|
|
720
855
|
argument: "files",
|
|
721
856
|
message: "QuiverAI SVG source data must be valid UTF-8.",
|
|
722
857
|
cause
|
|
723
858
|
});
|
|
724
859
|
}
|
|
725
860
|
if (svg.length > MAX_EDIT_SVG_BYTES || !isSvgMarkup(svg)) {
|
|
726
|
-
throw new
|
|
861
|
+
throw new InvalidArgumentError3({
|
|
727
862
|
argument: "files",
|
|
728
863
|
message: "QuiverAI SVG source data must contain a complete SVG document."
|
|
729
864
|
});
|
|
@@ -735,7 +870,6 @@ function toQuiverAIEditSource(file) {
|
|
|
735
870
|
};
|
|
736
871
|
}
|
|
737
872
|
function isSvgMarkup(svg) {
|
|
738
|
-
var _a;
|
|
739
873
|
const document = svg.replace(/^\uFEFF/, "");
|
|
740
874
|
const elements = [];
|
|
741
875
|
let position = 0;
|
|
@@ -781,14 +915,14 @@ function isSvgMarkup(svg) {
|
|
|
781
915
|
continue;
|
|
782
916
|
}
|
|
783
917
|
if (document.slice(position, position + 9).toUpperCase() === "<!DOCTYPE") {
|
|
784
|
-
if (rootSeen || doctypeSeen || elements.length > 0 || !/[\t\n\r ]/.test(
|
|
918
|
+
if (rootSeen || doctypeSeen || elements.length > 0 || !/[\t\n\r ]/.test(document[position + 9] ?? "")) {
|
|
785
919
|
return false;
|
|
786
920
|
}
|
|
787
921
|
const doctypeName = readXmlName(
|
|
788
922
|
document,
|
|
789
923
|
skipXmlWhitespace(document, position + 9)
|
|
790
924
|
);
|
|
791
|
-
if (
|
|
925
|
+
if (doctypeName?.name.toLowerCase() !== "svg") {
|
|
792
926
|
return false;
|
|
793
927
|
}
|
|
794
928
|
const doctypeEnd = findDoctypeEnd(document, doctypeName.end);
|
|
@@ -903,8 +1037,7 @@ function readXmlName(value, position) {
|
|
|
903
1037
|
};
|
|
904
1038
|
}
|
|
905
1039
|
function skipXmlWhitespace(value, position) {
|
|
906
|
-
|
|
907
|
-
while (/[\t\n\r ]/.test((_a = value[position]) != null ? _a : "")) {
|
|
1040
|
+
while (/[\t\n\r ]/.test(value[position] ?? "")) {
|
|
908
1041
|
position += 1;
|
|
909
1042
|
}
|
|
910
1043
|
return position;
|
|
@@ -988,64 +1121,67 @@ function collectWarnings({
|
|
|
988
1121
|
}
|
|
989
1122
|
return warnings;
|
|
990
1123
|
}
|
|
991
|
-
var svgUsageSchema =
|
|
992
|
-
total_tokens:
|
|
993
|
-
input_tokens:
|
|
994
|
-
output_tokens:
|
|
1124
|
+
var svgUsageSchema = z3.object({
|
|
1125
|
+
total_tokens: z3.number().int().nonnegative(),
|
|
1126
|
+
input_tokens: z3.number().int().nonnegative(),
|
|
1127
|
+
output_tokens: z3.number().int().nonnegative()
|
|
995
1128
|
});
|
|
996
|
-
var svgDocumentSchema =
|
|
997
|
-
svg:
|
|
998
|
-
mime_type:
|
|
999
|
-
loop_period_ms:
|
|
1000
|
-
opening_animation_ms:
|
|
1129
|
+
var svgDocumentSchema = z3.object({
|
|
1130
|
+
svg: z3.string().min(1),
|
|
1131
|
+
mime_type: z3.literal("image/svg+xml"),
|
|
1132
|
+
loop_period_ms: z3.number().int().nonnegative().nullish(),
|
|
1133
|
+
opening_animation_ms: z3.number().int().nonnegative().nullish()
|
|
1001
1134
|
});
|
|
1002
|
-
var svgGenerationResponseSchema =
|
|
1003
|
-
id:
|
|
1004
|
-
created:
|
|
1005
|
-
data:
|
|
1135
|
+
var svgGenerationResponseSchema = z3.object({
|
|
1136
|
+
id: z3.string().min(1),
|
|
1137
|
+
created: z3.number().int().nonnegative(),
|
|
1138
|
+
data: z3.array(svgDocumentSchema).min(1),
|
|
1006
1139
|
usage: svgUsageSchema.nullish(),
|
|
1007
|
-
credits:
|
|
1008
|
-
});
|
|
1009
|
-
var quiveraiErrorSchema = z2.object({
|
|
1010
|
-
status: z2.number().int(),
|
|
1011
|
-
code: z2.string().min(1),
|
|
1012
|
-
message: z2.string().min(1),
|
|
1013
|
-
request_id: z2.string().min(1)
|
|
1014
|
-
});
|
|
1015
|
-
var quiveraiFailedResponseHandler = createJsonErrorResponseHandler({
|
|
1016
|
-
errorSchema: quiveraiErrorSchema,
|
|
1017
|
-
errorToMessage: (error) => error.message,
|
|
1018
|
-
isRetryable: (response) => response.status === 429 || response.status >= 500
|
|
1140
|
+
credits: z3.number().int().nonnegative().nullish()
|
|
1019
1141
|
});
|
|
1020
1142
|
|
|
1021
1143
|
// src/version.ts
|
|
1022
|
-
var VERSION = true ? "2.0.
|
|
1144
|
+
var VERSION = true ? "2.0.50" : "0.0.0-test";
|
|
1023
1145
|
|
|
1024
1146
|
// src/quiverai-provider.ts
|
|
1025
1147
|
var defaultBaseURL = "https://api.quiver.ai/v1";
|
|
1026
1148
|
function createQuiverAI(options = {}) {
|
|
1027
|
-
|
|
1028
|
-
const baseURL = (_a = withoutTrailingSlash(
|
|
1149
|
+
const baseURL = withoutTrailingSlash(
|
|
1029
1150
|
loadOptionalSetting({
|
|
1030
1151
|
settingValue: options.baseURL,
|
|
1031
1152
|
environmentVariableName: "QUIVERAI_BASE_URL"
|
|
1032
1153
|
})
|
|
1033
|
-
)
|
|
1034
|
-
const getHeaders = () =>
|
|
1035
|
-
{
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1154
|
+
) ?? defaultBaseURL;
|
|
1155
|
+
const getHeaders = () => ({
|
|
1156
|
+
Authorization: `Bearer ${loadApiKey({
|
|
1157
|
+
apiKey: options.apiKey,
|
|
1158
|
+
environmentVariableName: "QUIVERAI_API_KEY",
|
|
1159
|
+
description: "QuiverAI"
|
|
1160
|
+
})}`,
|
|
1161
|
+
...options.headers
|
|
1162
|
+
});
|
|
1163
|
+
const getImageHeaders = () => withUserAgentSuffix(getHeaders(), `ai-sdk/quiverai/${VERSION}`);
|
|
1164
|
+
const responsesConfig = {
|
|
1165
|
+
name: "quiverai",
|
|
1166
|
+
url: `${baseURL}/responses`,
|
|
1167
|
+
headers: getHeaders,
|
|
1168
|
+
fetch: options.fetch,
|
|
1169
|
+
failedResponseHandler: quiveraiFailedResponseHandler,
|
|
1170
|
+
getResponseErrorMetadata: getQuiverAIResponseErrorMetadata,
|
|
1171
|
+
strictResponseInput: true,
|
|
1172
|
+
customToolId: "quiverai.custom",
|
|
1173
|
+
structuredOutputs: false,
|
|
1174
|
+
userAgentSuffix: `ai-sdk/quiverai/${VERSION}`
|
|
1175
|
+
};
|
|
1176
|
+
const responsesProvider = createOpenResponses2(responsesConfig);
|
|
1177
|
+
const createLanguageModel = (modelId) => new QuiverAILanguageModel(
|
|
1178
|
+
responsesProvider.languageModel(modelId),
|
|
1179
|
+
responsesConfig
|
|
1044
1180
|
);
|
|
1045
1181
|
const createImageModel = (modelId) => new QuiverAIImageModel(modelId, {
|
|
1046
1182
|
provider: "quiverai.image",
|
|
1047
1183
|
baseURL,
|
|
1048
|
-
headers:
|
|
1184
|
+
headers: getImageHeaders,
|
|
1049
1185
|
fetch: options.fetch
|
|
1050
1186
|
});
|
|
1051
1187
|
const embeddingModel = (modelId) => {
|
|
@@ -1054,19 +1190,17 @@ function createQuiverAI(options = {}) {
|
|
|
1054
1190
|
modelType: "embeddingModel"
|
|
1055
1191
|
});
|
|
1056
1192
|
};
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
image: createImageModel,
|
|
1060
|
-
imageModel: createImageModel,
|
|
1061
|
-
languageModel: (modelId) => {
|
|
1062
|
-
throw new NoSuchModelError({
|
|
1063
|
-
modelId,
|
|
1064
|
-
modelType: "languageModel"
|
|
1065
|
-
});
|
|
1066
|
-
},
|
|
1067
|
-
embeddingModel,
|
|
1068
|
-
textEmbeddingModel: embeddingModel
|
|
1193
|
+
const provider = function(modelId) {
|
|
1194
|
+
return createLanguageModel(modelId);
|
|
1069
1195
|
};
|
|
1196
|
+
provider.specificationVersion = "v4";
|
|
1197
|
+
provider.languageModel = createLanguageModel;
|
|
1198
|
+
provider.image = createImageModel;
|
|
1199
|
+
provider.imageModel = createImageModel;
|
|
1200
|
+
provider.embeddingModel = embeddingModel;
|
|
1201
|
+
provider.textEmbeddingModel = embeddingModel;
|
|
1202
|
+
provider.tools = responsesProvider.tools;
|
|
1203
|
+
return provider;
|
|
1070
1204
|
}
|
|
1071
1205
|
var quiverai = createQuiverAI();
|
|
1072
1206
|
export {
|