@ai-sdk/quiverai 2.0.42 → 2.0.44
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 +21 -0
- package/README.md +1 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.js +199 -9
- package/dist/index.js.map +1 -1
- package/docs/180-quiverai.mdx +71 -13
- package/package.json +3 -3
- package/src/quiverai-image-model-options.ts +26 -2
- package/src/quiverai-image-model.ts +222 -5
- package/src/quiverai-image-settings.ts +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @ai-sdk/quiverai
|
|
2
2
|
|
|
3
|
+
## 2.0.44
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 351b2ac: feat(quiverai): support Arrow 2 SVG animation through generateImage
|
|
8
|
+
- Updated dependencies [0455398]
|
|
9
|
+
- @ai-sdk/provider-utils@5.0.44
|
|
10
|
+
|
|
11
|
+
## 2.0.43
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 89febde: Add Arrow 2 and Arrow 2 Telos model IDs, reasoning effort and SVG viewBox options, and fixed-credit billing metadata. Respect Arrow 2 output-token limits, stop applying legacy reference limits to newer models, and omit the unsupported vectorization output count with guidance for splitting multiple vectorizations into separate calls.
|
|
16
|
+
- Updated dependencies [215b25e]
|
|
17
|
+
- Updated dependencies [d4d96bf]
|
|
18
|
+
- Updated dependencies [a7dd893]
|
|
19
|
+
- Updated dependencies [3456e2c]
|
|
20
|
+
- Updated dependencies [c4e76de]
|
|
21
|
+
- @ai-sdk/provider-utils@5.0.43
|
|
22
|
+
- @ai-sdk/provider@4.0.17
|
|
23
|
+
|
|
3
24
|
## 2.0.42
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { FetchFunction, InferSchema } from '@ai-sdk/provider-utils';
|
|
|
7
7
|
*
|
|
8
8
|
* @see https://quiver.ai/
|
|
9
9
|
*/
|
|
10
|
-
type QuiverAIImageModelId = 'arrow-1' | 'arrow-1.1' | 'arrow-1.1-max' | (string & {});
|
|
10
|
+
type QuiverAIImageModelId = 'arrow-1' | 'arrow-1.1' | 'arrow-1.1-max' | 'arrow-2' | 'arrow-2-telos' | (string & {});
|
|
11
11
|
|
|
12
12
|
interface QuiverAIProviderSettings {
|
|
13
13
|
/**
|
|
@@ -53,8 +53,17 @@ declare const quiverai: QuiverAIProvider;
|
|
|
53
53
|
* @see https://quiver.ai/
|
|
54
54
|
*/
|
|
55
55
|
declare const quiveraiImageModelOptionsSchema: _ai_sdk_provider_utils.LazySchema<{
|
|
56
|
-
operation?: "generate" | "vectorize" | undefined;
|
|
56
|
+
operation?: "generate" | "vectorize" | "animate" | undefined;
|
|
57
57
|
instructions?: string | undefined;
|
|
58
|
+
reasoningEffort?: "low" | "medium" | "high" | "xhigh" | undefined;
|
|
59
|
+
attributes?: {
|
|
60
|
+
viewBox?: {
|
|
61
|
+
minX: number;
|
|
62
|
+
minY: number;
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
} | undefined;
|
|
66
|
+
} | undefined;
|
|
58
67
|
temperature?: number | undefined;
|
|
59
68
|
topP?: number | undefined;
|
|
60
69
|
presencePenalty?: number | null | undefined;
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from "@ai-sdk/provider";
|
|
16
16
|
import {
|
|
17
17
|
combineHeaders,
|
|
18
|
+
convertBase64ToUint8Array,
|
|
18
19
|
convertUint8ArrayToBase64,
|
|
19
20
|
createJsonErrorResponseHandler,
|
|
20
21
|
createJsonResponseHandler,
|
|
@@ -41,12 +42,29 @@ var quiveraiImageModelOptionsSchema = lazySchema(
|
|
|
41
42
|
* - `generate`: Text-to-SVG generation. Requires `prompt`.
|
|
42
43
|
* - `vectorize`: Convert an input raster image into an SVG. Requires a
|
|
43
44
|
* single image in `prompt.images` / `files`.
|
|
45
|
+
* - `animate`: Animate an input SVG. Requires a single SVG in
|
|
46
|
+
* `prompt.images` / `files`; the text prompt is optional.
|
|
44
47
|
*/
|
|
45
|
-
operation: z.enum(["generate", "vectorize"]).optional(),
|
|
48
|
+
operation: z.enum(["generate", "vectorize", "animate"]).optional(),
|
|
46
49
|
/**
|
|
47
50
|
* Extra style guidance for prompt-based generation.
|
|
48
51
|
*/
|
|
49
52
|
instructions: z.string().min(1).optional(),
|
|
53
|
+
/**
|
|
54
|
+
* Reasoning effort applied to generation or vectorization.
|
|
55
|
+
*/
|
|
56
|
+
reasoningEffort: z.enum(["low", "medium", "high", "xhigh"]).optional(),
|
|
57
|
+
/**
|
|
58
|
+
* SVG root attributes requested for generation or vectorization.
|
|
59
|
+
*/
|
|
60
|
+
attributes: z.object({
|
|
61
|
+
viewBox: z.object({
|
|
62
|
+
minX: z.number(),
|
|
63
|
+
minY: z.number(),
|
|
64
|
+
width: z.number().positive(),
|
|
65
|
+
height: z.number().positive()
|
|
66
|
+
}).optional()
|
|
67
|
+
}).optional(),
|
|
50
68
|
/**
|
|
51
69
|
* Sampling temperature (0-2).
|
|
52
70
|
*/
|
|
@@ -60,7 +78,8 @@ var quiveraiImageModelOptionsSchema = lazySchema(
|
|
|
60
78
|
*/
|
|
61
79
|
presencePenalty: z.number().min(-2).max(2).nullable().optional(),
|
|
62
80
|
/**
|
|
63
|
-
* Maximum number of output tokens (1 -
|
|
81
|
+
* Maximum number of output tokens (1 - 65536 for Arrow 2 models).
|
|
82
|
+
* The legacy upper bound of 131072 is retained for other model IDs.
|
|
64
83
|
*/
|
|
65
84
|
maxOutputTokens: z.number().int().min(1).max(131072).optional(),
|
|
66
85
|
/**
|
|
@@ -122,6 +141,7 @@ var QuiverAIImageModel = class _QuiverAIImageModel {
|
|
|
122
141
|
n,
|
|
123
142
|
prompt,
|
|
124
143
|
files,
|
|
144
|
+
mask,
|
|
125
145
|
operation,
|
|
126
146
|
options: quiveraiOptions != null ? quiveraiOptions : {}
|
|
127
147
|
});
|
|
@@ -145,9 +165,16 @@ var QuiverAIImageModel = class _QuiverAIImageModel {
|
|
|
145
165
|
warnings,
|
|
146
166
|
providerMetadata: {
|
|
147
167
|
quiverai: {
|
|
168
|
+
...response.credits != null && { credits: response.credits },
|
|
148
169
|
images: response.data.map((image, index) => ({
|
|
149
170
|
index,
|
|
150
|
-
mimeType: image.mime_type
|
|
171
|
+
mimeType: image.mime_type,
|
|
172
|
+
...image.loop_period_ms !== void 0 && {
|
|
173
|
+
loopPeriodMs: image.loop_period_ms
|
|
174
|
+
},
|
|
175
|
+
...image.opening_animation_ms !== void 0 && {
|
|
176
|
+
openingAnimationMs: image.opening_animation_ms
|
|
177
|
+
}
|
|
151
178
|
}))
|
|
152
179
|
}
|
|
153
180
|
},
|
|
@@ -167,10 +194,17 @@ var QuiverAIImageModel = class _QuiverAIImageModel {
|
|
|
167
194
|
}
|
|
168
195
|
};
|
|
169
196
|
function getOperationPath(operation) {
|
|
170
|
-
|
|
197
|
+
switch (operation) {
|
|
198
|
+
case "generate":
|
|
199
|
+
return "/svgs/generations";
|
|
200
|
+
case "vectorize":
|
|
201
|
+
return "/svgs/vectorizations";
|
|
202
|
+
case "animate":
|
|
203
|
+
return "/svgs/animations";
|
|
204
|
+
}
|
|
171
205
|
}
|
|
172
206
|
function getGenerateReferenceLimit(modelId) {
|
|
173
|
-
return
|
|
207
|
+
return ["arrow-1", "arrow-1.0", "arrow-1.1"].includes(modelId) ? 4 : 16;
|
|
174
208
|
}
|
|
175
209
|
function toQuiverAIImageReference(image) {
|
|
176
210
|
if (image.type === "url") {
|
|
@@ -180,19 +214,87 @@ function toQuiverAIImageReference(image) {
|
|
|
180
214
|
base64: typeof image.data === "string" ? image.data : convertUint8ArrayToBase64(image.data)
|
|
181
215
|
};
|
|
182
216
|
}
|
|
217
|
+
var maxAnimationSourceBase64Length = 1066668;
|
|
218
|
+
function toQuiverAIAnimationSource(image) {
|
|
219
|
+
var _a;
|
|
220
|
+
if (image.type === "url") {
|
|
221
|
+
let url;
|
|
222
|
+
try {
|
|
223
|
+
url = new URL(image.url);
|
|
224
|
+
} catch (e) {
|
|
225
|
+
throw new InvalidArgumentError({
|
|
226
|
+
argument: "files",
|
|
227
|
+
message: "QuiverAI animate requires a valid HTTP or HTTPS SVG URL."
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
231
|
+
throw new InvalidArgumentError({
|
|
232
|
+
argument: "files",
|
|
233
|
+
message: "QuiverAI animate requires an HTTP or HTTPS SVG URL."
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return { url: image.url };
|
|
237
|
+
}
|
|
238
|
+
let base64;
|
|
239
|
+
let bytes;
|
|
240
|
+
if (typeof image.data === "string") {
|
|
241
|
+
const dataUrlMatch = /^data:image\/svg\+xml(?:;[^,]*)?;base64,([\s\S]+)$/i.exec(image.data);
|
|
242
|
+
const encodedData = (_a = dataUrlMatch == null ? void 0 : dataUrlMatch[1]) != null ? _a : image.data;
|
|
243
|
+
try {
|
|
244
|
+
bytes = convertBase64ToUint8Array(encodedData);
|
|
245
|
+
} catch (e) {
|
|
246
|
+
throw new InvalidArgumentError({
|
|
247
|
+
argument: "files",
|
|
248
|
+
message: "QuiverAI animate requires the source SVG string to be valid base64 or an SVG data URL."
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
base64 = convertUint8ArrayToBase64(bytes);
|
|
252
|
+
} else {
|
|
253
|
+
bytes = image.data;
|
|
254
|
+
base64 = convertUint8ArrayToBase64(bytes);
|
|
255
|
+
}
|
|
256
|
+
if (!isSvg(bytes)) {
|
|
257
|
+
throw new InvalidArgumentError({
|
|
258
|
+
argument: "files",
|
|
259
|
+
message: "QuiverAI animate requires the input file to contain SVG data."
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
if (base64.length > maxAnimationSourceBase64Length) {
|
|
263
|
+
throw new InvalidArgumentError({
|
|
264
|
+
argument: "files",
|
|
265
|
+
message: `QuiverAI animate accepts at most ${maxAnimationSourceBase64Length} base64 characters for the source SVG.`
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return { base64 };
|
|
269
|
+
}
|
|
270
|
+
function isSvg(data) {
|
|
271
|
+
const head = new TextDecoder("utf-8", { fatal: false }).decode(data.subarray(0, 4096)).trimStart();
|
|
272
|
+
return /^(?:(?:<\?xml[\s\S]*?\?>|<!--[\s\S]*?-->|<!DOCTYPE[\s\S]*?>)\s*)*<svg(?:\s|>)/i.test(
|
|
273
|
+
head
|
|
274
|
+
);
|
|
275
|
+
}
|
|
183
276
|
function buildRequestBody({
|
|
184
277
|
modelId,
|
|
185
278
|
n,
|
|
186
279
|
prompt,
|
|
187
280
|
files,
|
|
281
|
+
mask,
|
|
188
282
|
operation,
|
|
189
283
|
options
|
|
190
284
|
}) {
|
|
285
|
+
if ((modelId === "arrow-2" || modelId === "arrow-2-telos") && options.maxOutputTokens != null && options.maxOutputTokens > 65536) {
|
|
286
|
+
throw new InvalidArgumentError({
|
|
287
|
+
argument: "maxOutputTokens",
|
|
288
|
+
message: `QuiverAI model "${modelId}" supports at most 65536 output tokens.`
|
|
289
|
+
});
|
|
290
|
+
}
|
|
191
291
|
const sharedOptions = {
|
|
192
292
|
temperature: options.temperature,
|
|
193
293
|
top_p: options.topP,
|
|
194
294
|
presence_penalty: options.presencePenalty,
|
|
195
295
|
max_output_tokens: options.maxOutputTokens,
|
|
296
|
+
reasoning_effort: options.reasoningEffort,
|
|
297
|
+
attributes: options.attributes,
|
|
196
298
|
stream: false
|
|
197
299
|
};
|
|
198
300
|
if (operation === "generate") {
|
|
@@ -219,6 +321,16 @@ function buildRequestBody({
|
|
|
219
321
|
references
|
|
220
322
|
};
|
|
221
323
|
}
|
|
324
|
+
if (operation === "animate") {
|
|
325
|
+
return buildAnimationRequestBody({
|
|
326
|
+
modelId,
|
|
327
|
+
n,
|
|
328
|
+
prompt,
|
|
329
|
+
files,
|
|
330
|
+
mask,
|
|
331
|
+
options
|
|
332
|
+
});
|
|
333
|
+
}
|
|
222
334
|
if (files == null || files.length === 0) {
|
|
223
335
|
throw new InvalidArgumentError({
|
|
224
336
|
argument: "files",
|
|
@@ -231,15 +343,90 @@ function buildRequestBody({
|
|
|
231
343
|
message: "QuiverAI vectorize accepts a single input image."
|
|
232
344
|
});
|
|
233
345
|
}
|
|
346
|
+
if (n !== 1) {
|
|
347
|
+
throw new InvalidArgumentError({
|
|
348
|
+
argument: "n",
|
|
349
|
+
message: "QuiverAI vectorize returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to vectorize multiple times."
|
|
350
|
+
});
|
|
351
|
+
}
|
|
234
352
|
return {
|
|
235
353
|
model: modelId,
|
|
236
|
-
n,
|
|
237
354
|
image: toQuiverAIImageReference(files[0]),
|
|
238
355
|
...sharedOptions,
|
|
239
356
|
auto_crop: options.autoCrop,
|
|
240
357
|
target_size: options.targetSize
|
|
241
358
|
};
|
|
242
359
|
}
|
|
360
|
+
function buildAnimationRequestBody({
|
|
361
|
+
modelId,
|
|
362
|
+
n,
|
|
363
|
+
prompt,
|
|
364
|
+
files,
|
|
365
|
+
mask,
|
|
366
|
+
options
|
|
367
|
+
}) {
|
|
368
|
+
if (modelId !== "arrow-2" && modelId !== "arrow-2-telos") {
|
|
369
|
+
throw new InvalidArgumentError({
|
|
370
|
+
argument: "modelId",
|
|
371
|
+
message: 'QuiverAI animate is supported by the "arrow-2" and "arrow-2-telos" models.'
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
if (files == null || files.length === 0) {
|
|
375
|
+
throw new InvalidArgumentError({
|
|
376
|
+
argument: "files",
|
|
377
|
+
message: "QuiverAI animate requires exactly one source SVG in prompt.images."
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
if (files.length !== 1) {
|
|
381
|
+
throw new InvalidArgumentError({
|
|
382
|
+
argument: "files",
|
|
383
|
+
message: "QuiverAI animate accepts exactly one source SVG in prompt.images."
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
if (n !== 1) {
|
|
387
|
+
throw new InvalidArgumentError({
|
|
388
|
+
argument: "n",
|
|
389
|
+
message: "QuiverAI animate returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to animate multiple times."
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
if (mask != null) {
|
|
393
|
+
throw new InvalidArgumentError({
|
|
394
|
+
argument: "mask",
|
|
395
|
+
message: "QuiverAI animate does not support masks."
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
if (prompt != null && prompt.trim().length === 0) {
|
|
399
|
+
throw new InvalidArgumentError({
|
|
400
|
+
argument: "prompt",
|
|
401
|
+
message: "QuiverAI animate requires a non-empty prompt when an animation instruction is provided."
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
const unsupportedOptions = [
|
|
405
|
+
["instructions", options.instructions],
|
|
406
|
+
["topP", options.topP],
|
|
407
|
+
["presencePenalty", options.presencePenalty],
|
|
408
|
+
["attributes", options.attributes],
|
|
409
|
+
["autoCrop", options.autoCrop],
|
|
410
|
+
["targetSize", options.targetSize]
|
|
411
|
+
].filter((option) => {
|
|
412
|
+
return option[1] !== void 0;
|
|
413
|
+
});
|
|
414
|
+
if (unsupportedOptions.length > 0) {
|
|
415
|
+
throw new InvalidArgumentError({
|
|
416
|
+
argument: `providerOptions.quiverai.${unsupportedOptions[0][0]}`,
|
|
417
|
+
message: `QuiverAI animate does not support providerOptions.quiverai.${unsupportedOptions[0][0]}.`
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
return {
|
|
421
|
+
model: modelId,
|
|
422
|
+
svg_source: toQuiverAIAnimationSource(files[0]),
|
|
423
|
+
prompt,
|
|
424
|
+
temperature: options.temperature,
|
|
425
|
+
max_output_tokens: options.maxOutputTokens,
|
|
426
|
+
reasoning_effort: options.reasoningEffort,
|
|
427
|
+
stream: false
|
|
428
|
+
};
|
|
429
|
+
}
|
|
243
430
|
function collectWarnings({
|
|
244
431
|
size,
|
|
245
432
|
aspectRatio,
|
|
@@ -284,13 +471,16 @@ var svgUsageSchema = z2.object({
|
|
|
284
471
|
});
|
|
285
472
|
var svgDocumentSchema = z2.object({
|
|
286
473
|
svg: z2.string().min(1),
|
|
287
|
-
mime_type: z2.literal("image/svg+xml")
|
|
474
|
+
mime_type: z2.literal("image/svg+xml"),
|
|
475
|
+
loop_period_ms: z2.number().int().nonnegative().nullish(),
|
|
476
|
+
opening_animation_ms: z2.number().int().nonnegative().nullish()
|
|
288
477
|
});
|
|
289
478
|
var svgGenerationResponseSchema = z2.object({
|
|
290
479
|
id: z2.string().min(1),
|
|
291
480
|
created: z2.number().int().nonnegative(),
|
|
292
481
|
data: z2.array(svgDocumentSchema).min(1),
|
|
293
|
-
usage: svgUsageSchema.nullish()
|
|
482
|
+
usage: svgUsageSchema.nullish(),
|
|
483
|
+
credits: z2.number().int().nonnegative().nullish()
|
|
294
484
|
});
|
|
295
485
|
var quiveraiErrorSchema = z2.object({
|
|
296
486
|
status: z2.number().int(),
|
|
@@ -305,7 +495,7 @@ var quiveraiFailedResponseHandler = createJsonErrorResponseHandler({
|
|
|
305
495
|
});
|
|
306
496
|
|
|
307
497
|
// src/version.ts
|
|
308
|
-
var VERSION = true ? "2.0.
|
|
498
|
+
var VERSION = true ? "2.0.44" : "0.0.0-test";
|
|
309
499
|
|
|
310
500
|
// src/quiverai-provider.ts
|
|
311
501
|
var defaultBaseURL = "https://api.quiver.ai/v1";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/quiverai-provider.ts","../src/quiverai-image-model.ts","../src/quiverai-image-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ImageModelV4,\n type ProviderV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n loadOptionalSetting,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { QuiverAIImageModel } from './quiverai-image-model';\nimport type { QuiverAIImageModelId } from './quiverai-image-settings';\nimport { VERSION } from './version';\n\nexport interface QuiverAIProviderSettings {\n /**\n * QuiverAI API key. Default value is taken from the `QUIVERAI_API_KEY`\n * environment variable.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls. Defaults to `https://api.quiver.ai/v1` and\n * falls back to the `QUIVERAI_BASE_URL` environment variable.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept\n * requests, or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface QuiverAIProvider extends ProviderV4 {\n /**\n * Creates a model for image generation.\n */\n image(modelId: QuiverAIImageModelId): ImageModelV4;\n\n /**\n * Creates a model for image generation.\n */\n imageModel(modelId: QuiverAIImageModelId): ImageModelV4;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\nconst defaultBaseURL = 'https://api.quiver.ai/v1';\n\nexport function createQuiverAI(\n options: QuiverAIProviderSettings = {},\n): QuiverAIProvider {\n const baseURL =\n withoutTrailingSlash(\n loadOptionalSetting({\n settingValue: options.baseURL,\n environmentVariableName: 'QUIVERAI_BASE_URL',\n }),\n ) ?? defaultBaseURL;\n\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'QUIVERAI_API_KEY',\n description: 'QuiverAI',\n })}`,\n ...options.headers,\n },\n `ai-sdk/quiverai/${VERSION}`,\n );\n\n const createImageModel = (modelId: QuiverAIImageModelId) =>\n new QuiverAIImageModel(modelId, {\n provider: 'quiverai.image',\n baseURL,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v4',\n image: createImageModel,\n imageModel: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\nexport const quiverai = createQuiverAI();\n","import {\n InvalidArgumentError,\n type ImageModelV4,\n type ImageModelV4CallOptions,\n type ImageModelV4File,\n type SharedV4Warning,\n} from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertUint8ArrayToBase64,\n createJsonErrorResponseHandler,\n createJsonResponseHandler,\n parseProviderOptions,\n postJsonToApi,\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport {\n quiveraiImageModelOptionsSchema,\n type QuiverAIImageModelOptions,\n} from './quiverai-image-model-options';\nimport type {\n QuiverAIImageModelId,\n QuiverAIOperation,\n} from './quiverai-image-settings';\n\ninterface QuiverAIImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: () => Record<string, string>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class QuiverAIImageModel implements ImageModelV4 {\n readonly specificationVersion = 'v4';\n readonly maxImagesPerCall = 16;\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: QuiverAIImageModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: QuiverAIImageModelId;\n config: QuiverAIImageModelConfig;\n }) {\n return new QuiverAIImageModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: QuiverAIImageModelId,\n private readonly config: QuiverAIImageModelConfig,\n ) {}\n\n async doGenerate({\n prompt,\n n,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n headers,\n abortSignal,\n }: ImageModelV4CallOptions): Promise<\n Awaited<ReturnType<ImageModelV4['doGenerate']>>\n > {\n const quiveraiOptions = await parseProviderOptions({\n provider: 'quiverai',\n providerOptions,\n schema: quiveraiImageModelOptionsSchema,\n });\n\n const operation: QuiverAIOperation =\n quiveraiOptions?.operation ?? 'generate';\n\n const warnings = collectWarnings({ size, aspectRatio, seed, mask });\n\n const body = buildRequestBody({\n modelId: this.modelId,\n n,\n prompt,\n files,\n operation,\n options: quiveraiOptions ?? {},\n });\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const combinedHeaders = combineHeaders(this.config.headers?.(), headers);\n\n const { value: response, responseHeaders } = await postJsonToApi({\n url: `${this.config.baseURL}${getOperationPath(operation)}`,\n headers: combinedHeaders,\n body,\n failedResponseHandler: quiveraiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n svgGenerationResponseSchema,\n ),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const encoder = new TextEncoder();\n const images = response.data.map(image => encoder.encode(image.svg));\n\n return {\n images,\n warnings,\n providerMetadata: {\n quiverai: {\n images: response.data.map((image, index) => ({\n index,\n mimeType: image.mime_type,\n })),\n },\n },\n response: {\n timestamp: response.created\n ? new Date(response.created * 1000)\n : currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n ...(response.usage && {\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.total_tokens,\n },\n }),\n };\n }\n}\n\nfunction getOperationPath(operation: QuiverAIOperation) {\n return operation === 'generate'\n ? '/svgs/generations'\n : '/svgs/vectorizations';\n}\n\nfunction getGenerateReferenceLimit(modelId: string) {\n return modelId === 'arrow-1.1-max' ? 16 : 4;\n}\n\nfunction toQuiverAIImageReference(image: ImageModelV4File) {\n if (image.type === 'url') {\n return { url: image.url };\n }\n return {\n base64:\n typeof image.data === 'string'\n ? image.data\n : convertUint8ArrayToBase64(image.data),\n };\n}\n\nfunction buildRequestBody({\n modelId,\n n,\n prompt,\n files,\n operation,\n options,\n}: {\n modelId: string;\n n: number;\n prompt: string | undefined;\n files: ImageModelV4File[] | undefined;\n operation: QuiverAIOperation;\n options: QuiverAIImageModelOptions;\n}) {\n const sharedOptions = {\n temperature: options.temperature,\n top_p: options.topP,\n presence_penalty: options.presencePenalty,\n max_output_tokens: options.maxOutputTokens,\n stream: false as const,\n };\n\n if (operation === 'generate') {\n if (prompt == null || prompt.trim().length === 0) {\n throw new InvalidArgumentError({\n argument: 'prompt',\n message:\n 'QuiverAI image generation requires a non-empty prompt for generateImage.',\n });\n }\n\n const references = files?.map(toQuiverAIImageReference);\n const maxReferences = getGenerateReferenceLimit(modelId);\n\n if (references != null && references.length > maxReferences) {\n throw new InvalidArgumentError({\n argument: 'files',\n message: `QuiverAI generate supports up to ${maxReferences} reference images for model \"${modelId}\".`,\n });\n }\n\n return {\n model: modelId,\n n,\n prompt,\n ...sharedOptions,\n instructions: options.instructions,\n references,\n };\n }\n\n if (files == null || files.length === 0) {\n throw new InvalidArgumentError({\n argument: 'files',\n message:\n 'QuiverAI vectorize requires an input image. Pass an image in the generateImage prompt and set providerOptions.quiverai.operation to \"vectorize\".',\n });\n }\n\n if (files.length > 1) {\n throw new InvalidArgumentError({\n argument: 'files',\n message: 'QuiverAI vectorize accepts a single input image.',\n });\n }\n\n return {\n model: modelId,\n n,\n image: toQuiverAIImageReference(files[0]),\n ...sharedOptions,\n auto_crop: options.autoCrop,\n target_size: options.targetSize,\n };\n}\n\nfunction collectWarnings({\n size,\n aspectRatio,\n seed,\n mask,\n}: {\n size: `${number}x${number}` | undefined;\n aspectRatio: `${number}:${number}` | undefined;\n seed: number | undefined;\n mask: ImageModelV4File | undefined;\n}): SharedV4Warning[] {\n const warnings: SharedV4Warning[] = [];\n\n if (size != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'size',\n details:\n 'QuiverAI SVG generation does not support the `size` option. The setting was ignored.',\n });\n }\n\n if (aspectRatio != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'aspectRatio',\n details:\n 'QuiverAI SVG generation does not support the `aspectRatio` option. The setting was ignored.',\n });\n }\n\n if (seed != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'seed',\n details:\n 'QuiverAI SVG generation does not support the `seed` option. The setting was ignored.',\n });\n }\n\n if (mask != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'mask',\n details:\n 'QuiverAI SVG generation does not support masks. The mask was ignored.',\n });\n }\n\n return warnings;\n}\n\n// Limited schemas focused on what is needed for the implementation.\n// This approach limits breakages when the API changes and keeps the\n// response handler efficient.\nconst svgUsageSchema = z.object({\n total_tokens: z.number().int().nonnegative(),\n input_tokens: z.number().int().nonnegative(),\n output_tokens: z.number().int().nonnegative(),\n});\n\nconst svgDocumentSchema = z.object({\n svg: z.string().min(1),\n mime_type: z.literal('image/svg+xml'),\n});\n\nconst svgGenerationResponseSchema = z.object({\n id: z.string().min(1),\n created: z.number().int().nonnegative(),\n data: z.array(svgDocumentSchema).min(1),\n usage: svgUsageSchema.nullish(),\n});\n\nconst quiveraiErrorSchema = z.object({\n status: z.number().int(),\n code: z.string().min(1),\n message: z.string().min(1),\n request_id: z.string().min(1),\n});\n\nexport const quiveraiFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: quiveraiErrorSchema,\n errorToMessage: error => error.message,\n isRetryable: response => response.status === 429 || response.status >= 500,\n});\n","import {\n lazySchema,\n zodSchema,\n type InferSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\n/**\n * Provider options schema for QuiverAI image generation.\n *\n * @see https://quiver.ai/\n */\nexport const quiveraiImageModelOptionsSchema = lazySchema(() =>\n zodSchema(\n z.object({\n /**\n * The operation to perform. Defaults to `generate`.\n *\n * - `generate`: Text-to-SVG generation. Requires `prompt`.\n * - `vectorize`: Convert an input raster image into an SVG. Requires a\n * single image in `prompt.images` / `files`.\n */\n operation: z.enum(['generate', 'vectorize']).optional(),\n\n /**\n * Extra style guidance for prompt-based generation.\n */\n instructions: z.string().min(1).optional(),\n\n /**\n * Sampling temperature (0-2).\n */\n temperature: z.number().min(0).max(2).optional(),\n\n /**\n * Nucleus sampling top-p (0-1).\n */\n topP: z.number().min(0).max(1).optional(),\n\n /**\n * Presence penalty (-2 to 2).\n */\n presencePenalty: z.number().min(-2).max(2).nullable().optional(),\n\n /**\n * Maximum number of output tokens (1 - 131072).\n */\n maxOutputTokens: z.number().int().min(1).max(131072).optional(),\n\n /**\n * Whether to auto-crop the input image before vectorization.\n * Only used when `operation` is `vectorize`.\n */\n autoCrop: z.boolean().optional(),\n\n /**\n * Target canvas size in pixels for vectorization (128 - 4096).\n * Only used when `operation` is `vectorize`.\n */\n targetSize: z.number().int().min(128).max(4096).optional(),\n }),\n ),\n);\n\nexport type QuiverAIImageModelOptions = InferSchema<\n typeof quiveraiImageModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":"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","names":["z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/quiverai-provider.ts","../src/quiverai-image-model.ts","../src/quiverai-image-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ImageModelV4,\n type ProviderV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n loadOptionalSetting,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { QuiverAIImageModel } from './quiverai-image-model';\nimport type { QuiverAIImageModelId } from './quiverai-image-settings';\nimport { VERSION } from './version';\n\nexport interface QuiverAIProviderSettings {\n /**\n * QuiverAI API key. Default value is taken from the `QUIVERAI_API_KEY`\n * environment variable.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls. Defaults to `https://api.quiver.ai/v1` and\n * falls back to the `QUIVERAI_BASE_URL` environment variable.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept\n * requests, or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface QuiverAIProvider extends ProviderV4 {\n /**\n * Creates a model for image generation.\n */\n image(modelId: QuiverAIImageModelId): ImageModelV4;\n\n /**\n * Creates a model for image generation.\n */\n imageModel(modelId: QuiverAIImageModelId): ImageModelV4;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\nconst defaultBaseURL = 'https://api.quiver.ai/v1';\n\nexport function createQuiverAI(\n options: QuiverAIProviderSettings = {},\n): QuiverAIProvider {\n const baseURL =\n withoutTrailingSlash(\n loadOptionalSetting({\n settingValue: options.baseURL,\n environmentVariableName: 'QUIVERAI_BASE_URL',\n }),\n ) ?? defaultBaseURL;\n\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'QUIVERAI_API_KEY',\n description: 'QuiverAI',\n })}`,\n ...options.headers,\n },\n `ai-sdk/quiverai/${VERSION}`,\n );\n\n const createImageModel = (modelId: QuiverAIImageModelId) =>\n new QuiverAIImageModel(modelId, {\n provider: 'quiverai.image',\n baseURL,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v4',\n image: createImageModel,\n imageModel: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\nexport const quiverai = createQuiverAI();\n","import {\n InvalidArgumentError,\n type ImageModelV4,\n type ImageModelV4CallOptions,\n type ImageModelV4File,\n type SharedV4Warning,\n} from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertBase64ToUint8Array,\n convertUint8ArrayToBase64,\n createJsonErrorResponseHandler,\n createJsonResponseHandler,\n parseProviderOptions,\n postJsonToApi,\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport {\n quiveraiImageModelOptionsSchema,\n type QuiverAIImageModelOptions,\n} from './quiverai-image-model-options';\nimport type {\n QuiverAIImageModelId,\n QuiverAIOperation,\n} from './quiverai-image-settings';\n\ninterface QuiverAIImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: () => Record<string, string>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class QuiverAIImageModel implements ImageModelV4 {\n readonly specificationVersion = 'v4';\n readonly maxImagesPerCall = 16;\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: QuiverAIImageModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: QuiverAIImageModelId;\n config: QuiverAIImageModelConfig;\n }) {\n return new QuiverAIImageModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: QuiverAIImageModelId,\n private readonly config: QuiverAIImageModelConfig,\n ) {}\n\n async doGenerate({\n prompt,\n n,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n headers,\n abortSignal,\n }: ImageModelV4CallOptions): Promise<\n Awaited<ReturnType<ImageModelV4['doGenerate']>>\n > {\n const quiveraiOptions = await parseProviderOptions({\n provider: 'quiverai',\n providerOptions,\n schema: quiveraiImageModelOptionsSchema,\n });\n\n const operation: QuiverAIOperation =\n quiveraiOptions?.operation ?? 'generate';\n\n const warnings = collectWarnings({ size, aspectRatio, seed, mask });\n\n const body = buildRequestBody({\n modelId: this.modelId,\n n,\n prompt,\n files,\n mask,\n operation,\n options: quiveraiOptions ?? {},\n });\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const combinedHeaders = combineHeaders(this.config.headers?.(), headers);\n\n const { value: response, responseHeaders } = await postJsonToApi({\n url: `${this.config.baseURL}${getOperationPath(operation)}`,\n headers: combinedHeaders,\n body,\n failedResponseHandler: quiveraiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n svgGenerationResponseSchema,\n ),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const encoder = new TextEncoder();\n const images = response.data.map(image => encoder.encode(image.svg));\n\n return {\n images,\n warnings,\n providerMetadata: {\n quiverai: {\n ...(response.credits != null && { credits: response.credits }),\n images: response.data.map((image, index) => ({\n index,\n mimeType: image.mime_type,\n ...(image.loop_period_ms !== undefined && {\n loopPeriodMs: image.loop_period_ms,\n }),\n ...(image.opening_animation_ms !== undefined && {\n openingAnimationMs: image.opening_animation_ms,\n }),\n })),\n },\n },\n response: {\n timestamp: response.created\n ? new Date(response.created * 1000)\n : currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n ...(response.usage && {\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.total_tokens,\n },\n }),\n };\n }\n}\n\nfunction getOperationPath(operation: QuiverAIOperation) {\n switch (operation) {\n case 'generate':\n return '/svgs/generations';\n case 'vectorize':\n return '/svgs/vectorizations';\n case 'animate':\n return '/svgs/animations';\n }\n}\n\nfunction getGenerateReferenceLimit(modelId: string) {\n // Only apply the lower limit to documented Arrow 1.x models. The API\n // enforces model-specific limits within its 16-reference request limit.\n return ['arrow-1', 'arrow-1.0', 'arrow-1.1'].includes(modelId) ? 4 : 16;\n}\n\nfunction toQuiverAIImageReference(image: ImageModelV4File) {\n if (image.type === 'url') {\n return { url: image.url };\n }\n return {\n base64:\n typeof image.data === 'string'\n ? image.data\n : convertUint8ArrayToBase64(image.data),\n };\n}\n\nconst maxAnimationSourceBase64Length = 1_066_668;\n\nfunction toQuiverAIAnimationSource(image: ImageModelV4File) {\n if (image.type === 'url') {\n let url: URL;\n try {\n url = new URL(image.url);\n } catch {\n throw new InvalidArgumentError({\n argument: 'files',\n message: 'QuiverAI animate requires a valid HTTP or HTTPS SVG URL.',\n });\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new InvalidArgumentError({\n argument: 'files',\n message: 'QuiverAI animate requires an HTTP or HTTPS SVG URL.',\n });\n }\n\n return { url: image.url };\n }\n\n let base64: string;\n let bytes: Uint8Array;\n\n if (typeof image.data === 'string') {\n const dataUrlMatch =\n /^data:image\\/svg\\+xml(?:;[^,]*)?;base64,([\\s\\S]+)$/i.exec(image.data);\n const encodedData = dataUrlMatch?.[1] ?? image.data;\n\n try {\n bytes = convertBase64ToUint8Array(encodedData);\n } catch {\n throw new InvalidArgumentError({\n argument: 'files',\n message:\n 'QuiverAI animate requires the source SVG string to be valid base64 or an SVG data URL.',\n });\n }\n base64 = convertUint8ArrayToBase64(bytes);\n } else {\n bytes = image.data;\n base64 = convertUint8ArrayToBase64(bytes);\n }\n\n if (!isSvg(bytes)) {\n throw new InvalidArgumentError({\n argument: 'files',\n message: 'QuiverAI animate requires the input file to contain SVG data.',\n });\n }\n\n if (base64.length > maxAnimationSourceBase64Length) {\n throw new InvalidArgumentError({\n argument: 'files',\n message: `QuiverAI animate accepts at most ${maxAnimationSourceBase64Length} base64 characters for the source SVG.`,\n });\n }\n\n return { base64 };\n}\n\nfunction isSvg(data: Uint8Array): boolean {\n const head = new TextDecoder('utf-8', { fatal: false })\n .decode(data.subarray(0, 4096))\n .trimStart();\n\n return /^(?:(?:<\\?xml[\\s\\S]*?\\?>|<!--[\\s\\S]*?-->|<!DOCTYPE[\\s\\S]*?>)\\s*)*<svg(?:\\s|>)/i.test(\n head,\n );\n}\n\nfunction buildRequestBody({\n modelId,\n n,\n prompt,\n files,\n mask,\n operation,\n options,\n}: {\n modelId: string;\n n: number;\n prompt: string | undefined;\n files: ImageModelV4File[] | undefined;\n mask: ImageModelV4File | undefined;\n operation: QuiverAIOperation;\n options: QuiverAIImageModelOptions;\n}) {\n if (\n (modelId === 'arrow-2' || modelId === 'arrow-2-telos') &&\n options.maxOutputTokens != null &&\n options.maxOutputTokens > 65536\n ) {\n throw new InvalidArgumentError({\n argument: 'maxOutputTokens',\n message: `QuiverAI model \"${modelId}\" supports at most 65536 output tokens.`,\n });\n }\n\n const sharedOptions = {\n temperature: options.temperature,\n top_p: options.topP,\n presence_penalty: options.presencePenalty,\n max_output_tokens: options.maxOutputTokens,\n reasoning_effort: options.reasoningEffort,\n attributes: options.attributes,\n stream: false as const,\n };\n\n if (operation === 'generate') {\n if (prompt == null || prompt.trim().length === 0) {\n throw new InvalidArgumentError({\n argument: 'prompt',\n message:\n 'QuiverAI image generation requires a non-empty prompt for generateImage.',\n });\n }\n\n const references = files?.map(toQuiverAIImageReference);\n const maxReferences = getGenerateReferenceLimit(modelId);\n\n if (references != null && references.length > maxReferences) {\n throw new InvalidArgumentError({\n argument: 'files',\n message: `QuiverAI generate supports up to ${maxReferences} reference images for model \"${modelId}\".`,\n });\n }\n\n return {\n model: modelId,\n n,\n prompt,\n ...sharedOptions,\n instructions: options.instructions,\n references,\n };\n }\n\n if (operation === 'animate') {\n return buildAnimationRequestBody({\n modelId,\n n,\n prompt,\n files,\n mask,\n options,\n });\n }\n\n if (files == null || files.length === 0) {\n throw new InvalidArgumentError({\n argument: 'files',\n message:\n 'QuiverAI vectorize requires an input image. Pass an image in the generateImage prompt and set providerOptions.quiverai.operation to \"vectorize\".',\n });\n }\n\n if (files.length > 1) {\n throw new InvalidArgumentError({\n argument: 'files',\n message: 'QuiverAI vectorize accepts a single input image.',\n });\n }\n\n if (n !== 1) {\n throw new InvalidArgumentError({\n argument: 'n',\n message:\n 'QuiverAI vectorize returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to vectorize multiple times.',\n });\n }\n\n return {\n model: modelId,\n image: toQuiverAIImageReference(files[0]),\n ...sharedOptions,\n auto_crop: options.autoCrop,\n target_size: options.targetSize,\n };\n}\n\nfunction buildAnimationRequestBody({\n modelId,\n n,\n prompt,\n files,\n mask,\n options,\n}: {\n modelId: string;\n n: number;\n prompt: string | undefined;\n files: ImageModelV4File[] | undefined;\n mask: ImageModelV4File | undefined;\n options: QuiverAIImageModelOptions;\n}) {\n if (modelId !== 'arrow-2' && modelId !== 'arrow-2-telos') {\n throw new InvalidArgumentError({\n argument: 'modelId',\n message:\n 'QuiverAI animate is supported by the \"arrow-2\" and \"arrow-2-telos\" models.',\n });\n }\n\n if (files == null || files.length === 0) {\n throw new InvalidArgumentError({\n argument: 'files',\n message:\n 'QuiverAI animate requires exactly one source SVG in prompt.images.',\n });\n }\n\n if (files.length !== 1) {\n throw new InvalidArgumentError({\n argument: 'files',\n message:\n 'QuiverAI animate accepts exactly one source SVG in prompt.images.',\n });\n }\n\n if (n !== 1) {\n throw new InvalidArgumentError({\n argument: 'n',\n message:\n 'QuiverAI animate returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to animate multiple times.',\n });\n }\n\n if (mask != null) {\n throw new InvalidArgumentError({\n argument: 'mask',\n message: 'QuiverAI animate does not support masks.',\n });\n }\n\n if (prompt != null && prompt.trim().length === 0) {\n throw new InvalidArgumentError({\n argument: 'prompt',\n message:\n 'QuiverAI animate requires a non-empty prompt when an animation instruction is provided.',\n });\n }\n\n const unsupportedOptions = [\n ['instructions', options.instructions],\n ['topP', options.topP],\n ['presencePenalty', options.presencePenalty],\n ['attributes', options.attributes],\n ['autoCrop', options.autoCrop],\n ['targetSize', options.targetSize],\n ].filter((option): option is [string, NonNullable<unknown>] => {\n return option[1] !== undefined;\n });\n\n if (unsupportedOptions.length > 0) {\n throw new InvalidArgumentError({\n argument: `providerOptions.quiverai.${unsupportedOptions[0][0]}`,\n message: `QuiverAI animate does not support providerOptions.quiverai.${unsupportedOptions[0][0]}.`,\n });\n }\n\n return {\n model: modelId,\n svg_source: toQuiverAIAnimationSource(files[0]),\n prompt,\n temperature: options.temperature,\n max_output_tokens: options.maxOutputTokens,\n reasoning_effort: options.reasoningEffort,\n stream: false as const,\n };\n}\n\nfunction collectWarnings({\n size,\n aspectRatio,\n seed,\n mask,\n}: {\n size: `${number}x${number}` | undefined;\n aspectRatio: `${number}:${number}` | undefined;\n seed: number | undefined;\n mask: ImageModelV4File | undefined;\n}): SharedV4Warning[] {\n const warnings: SharedV4Warning[] = [];\n\n if (size != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'size',\n details:\n 'QuiverAI SVG generation does not support the `size` option. The setting was ignored.',\n });\n }\n\n if (aspectRatio != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'aspectRatio',\n details:\n 'QuiverAI SVG generation does not support the `aspectRatio` option. The setting was ignored.',\n });\n }\n\n if (seed != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'seed',\n details:\n 'QuiverAI SVG generation does not support the `seed` option. The setting was ignored.',\n });\n }\n\n if (mask != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'mask',\n details:\n 'QuiverAI SVG generation does not support masks. The mask was ignored.',\n });\n }\n\n return warnings;\n}\n\n// Limited schemas focused on what is needed for the implementation.\n// This approach limits breakages when the API changes and keeps the\n// response handler efficient.\nconst svgUsageSchema = z.object({\n total_tokens: z.number().int().nonnegative(),\n input_tokens: z.number().int().nonnegative(),\n output_tokens: z.number().int().nonnegative(),\n});\n\nconst svgDocumentSchema = z.object({\n svg: z.string().min(1),\n mime_type: z.literal('image/svg+xml'),\n loop_period_ms: z.number().int().nonnegative().nullish(),\n opening_animation_ms: z.number().int().nonnegative().nullish(),\n});\n\nconst svgGenerationResponseSchema = z.object({\n id: z.string().min(1),\n created: z.number().int().nonnegative(),\n data: z.array(svgDocumentSchema).min(1),\n usage: svgUsageSchema.nullish(),\n credits: z.number().int().nonnegative().nullish(),\n});\n\nconst quiveraiErrorSchema = z.object({\n status: z.number().int(),\n code: z.string().min(1),\n message: z.string().min(1),\n request_id: z.string().min(1),\n});\n\nexport const quiveraiFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: quiveraiErrorSchema,\n errorToMessage: error => error.message,\n isRetryable: response => response.status === 429 || response.status >= 500,\n});\n","import {\n lazySchema,\n zodSchema,\n type InferSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\n/**\n * Provider options schema for QuiverAI image generation.\n *\n * @see https://quiver.ai/\n */\nexport const quiveraiImageModelOptionsSchema = lazySchema(() =>\n zodSchema(\n z.object({\n /**\n * The operation to perform. Defaults to `generate`.\n *\n * - `generate`: Text-to-SVG generation. Requires `prompt`.\n * - `vectorize`: Convert an input raster image into an SVG. Requires a\n * single image in `prompt.images` / `files`.\n * - `animate`: Animate an input SVG. Requires a single SVG in\n * `prompt.images` / `files`; the text prompt is optional.\n */\n operation: z.enum(['generate', 'vectorize', 'animate']).optional(),\n\n /**\n * Extra style guidance for prompt-based generation.\n */\n instructions: z.string().min(1).optional(),\n\n /**\n * Reasoning effort applied to generation or vectorization.\n */\n reasoningEffort: z.enum(['low', 'medium', 'high', 'xhigh']).optional(),\n\n /**\n * SVG root attributes requested for generation or vectorization.\n */\n attributes: z\n .object({\n viewBox: z\n .object({\n minX: z.number(),\n minY: z.number(),\n width: z.number().positive(),\n height: z.number().positive(),\n })\n .optional(),\n })\n .optional(),\n\n /**\n * Sampling temperature (0-2).\n */\n temperature: z.number().min(0).max(2).optional(),\n\n /**\n * Nucleus sampling top-p (0-1).\n */\n topP: z.number().min(0).max(1).optional(),\n\n /**\n * Presence penalty (-2 to 2).\n */\n presencePenalty: z.number().min(-2).max(2).nullable().optional(),\n\n /**\n * Maximum number of output tokens (1 - 65536 for Arrow 2 models).\n * The legacy upper bound of 131072 is retained for other model IDs.\n */\n maxOutputTokens: z.number().int().min(1).max(131072).optional(),\n\n /**\n * Whether to auto-crop the input image before vectorization.\n * Only used when `operation` is `vectorize`.\n */\n autoCrop: z.boolean().optional(),\n\n /**\n * Target canvas size in pixels for vectorization (128 - 4096).\n * Only used when `operation` is `vectorize`.\n */\n targetSize: z.number().int().min(128).max(4096).optional(),\n }),\n ),\n);\n\nexport type QuiverAIImageModelOptions = InferSchema<\n typeof quiveraiImageModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":"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","names":["z","z"]}
|
package/docs/180-quiverai.mdx
CHANGED
|
@@ -5,7 +5,7 @@ description: Learn how to use QuiverAI models with the AI SDK.
|
|
|
5
5
|
|
|
6
6
|
# QuiverAI Provider
|
|
7
7
|
|
|
8
|
-
[QuiverAI](https://quiver.ai/) generates SVG documents directly from text prompts
|
|
8
|
+
[QuiverAI](https://quiver.ai/) generates SVG documents directly from text prompts, vectorizes raster images, and animates existing SVGs. The QuiverAI provider for the AI SDK exposes these operations through `generateImage`.
|
|
9
9
|
|
|
10
10
|
## Setup
|
|
11
11
|
|
|
@@ -70,7 +70,7 @@ import { generateImage } from 'ai';
|
|
|
70
70
|
import fs from 'fs';
|
|
71
71
|
|
|
72
72
|
const { image } = await generateImage({
|
|
73
|
-
model: quiverai.image('arrow-
|
|
73
|
+
model: quiverai.image('arrow-2'),
|
|
74
74
|
prompt: 'A logo for the next AI Design startup',
|
|
75
75
|
});
|
|
76
76
|
|
|
@@ -83,10 +83,12 @@ QuiverAI returns SVG documents. The generated SVG bytes are available through `r
|
|
|
83
83
|
|
|
84
84
|
### Model Capabilities
|
|
85
85
|
|
|
86
|
-
QuiverAI
|
|
86
|
+
QuiverAI supports the following Arrow models:
|
|
87
87
|
|
|
88
88
|
| Model | Description |
|
|
89
89
|
| --------------- | -------------------------------------------------------------------------------- |
|
|
90
|
+
| `arrow-2` | Arrow 2 balances SVG generation quality and speed. Uses token-based billing. |
|
|
91
|
+
| `arrow-2-telos` | Higher-fidelity Arrow 2 variant for complex designs. Uses token-based billing. |
|
|
90
92
|
| `arrow-1` | Base text-to-SVG model. Accepts up to 4 reference images. |
|
|
91
93
|
| `arrow-1.1` | Improved text-to-SVG model. Accepts up to 4 reference images. |
|
|
92
94
|
| `arrow-1.1-max` | Higher quality variant with extended context. Accepts up to 16 reference images. |
|
|
@@ -100,13 +102,15 @@ import { quiverai, type QuiverAIImageModelOptions } from '@ai-sdk/quiverai';
|
|
|
100
102
|
import { generateImage } from 'ai';
|
|
101
103
|
|
|
102
104
|
await generateImage({
|
|
103
|
-
model: quiverai.image('arrow-
|
|
105
|
+
model: quiverai.image('arrow-2'),
|
|
104
106
|
prompt: 'A geometric unicorn icon',
|
|
105
107
|
providerOptions: {
|
|
106
108
|
quiverai: {
|
|
107
109
|
instructions: 'Use a flat monochrome style with clean geometry.',
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
reasoningEffort: 'high',
|
|
111
|
+
attributes: {
|
|
112
|
+
viewBox: { minX: 0, minY: 0, width: 100, height: 100 },
|
|
113
|
+
},
|
|
110
114
|
maxOutputTokens: 4096,
|
|
111
115
|
} satisfies QuiverAIImageModelOptions,
|
|
112
116
|
},
|
|
@@ -115,14 +119,22 @@ await generateImage({
|
|
|
115
119
|
|
|
116
120
|
Supported options:
|
|
117
121
|
|
|
118
|
-
- **operation** _'generate' | 'vectorize'_
|
|
122
|
+
- **operation** _'generate' | 'vectorize' | 'animate'_
|
|
119
123
|
|
|
120
|
-
Choose between text-to-SVG generation (`generate`, default)
|
|
124
|
+
Choose between text-to-SVG generation (`generate`, default), image-to-SVG vectorization (`vectorize`), and SVG animation (`animate`).
|
|
121
125
|
|
|
122
126
|
- **instructions** _string_
|
|
123
127
|
|
|
124
128
|
Extra style guidance for prompt-based generation.
|
|
125
129
|
|
|
130
|
+
- **reasoningEffort** _'low' | 'medium' | 'high' | 'xhigh'_
|
|
131
|
+
|
|
132
|
+
Reasoning effort for generation or vectorization. When omitted, QuiverAI uses its default.
|
|
133
|
+
|
|
134
|
+
- **attributes** _object_
|
|
135
|
+
|
|
136
|
+
Requested SVG root attributes. Supports `viewBox` with numeric `minX`, `minY`, and positive `width` and `height`. This is separate from the unsupported `size` and `aspectRatio` options.
|
|
137
|
+
|
|
126
138
|
- **temperature** _number_ (0-2)
|
|
127
139
|
|
|
128
140
|
Sampling temperature.
|
|
@@ -135,9 +147,9 @@ Supported options:
|
|
|
135
147
|
|
|
136
148
|
Presence penalty.
|
|
137
149
|
|
|
138
|
-
- **maxOutputTokens** _number_
|
|
150
|
+
- **maxOutputTokens** _number_
|
|
139
151
|
|
|
140
|
-
Maximum number of output tokens.
|
|
152
|
+
Maximum number of output tokens. Arrow 2 and Arrow 2 Telos accept 1-65536. The provider retains its legacy validation bound of 131072 for other model IDs; the API may enforce a lower model-specific limit.
|
|
141
153
|
|
|
142
154
|
- **autoCrop** _boolean_
|
|
143
155
|
|
|
@@ -153,7 +165,7 @@ Pass reference images through `prompt.images`:
|
|
|
153
165
|
|
|
154
166
|
```ts
|
|
155
167
|
await generateImage({
|
|
156
|
-
model: quiverai.image('arrow-
|
|
168
|
+
model: quiverai.image('arrow-2'),
|
|
157
169
|
prompt: {
|
|
158
170
|
text: 'A geometric unicorn icon',
|
|
159
171
|
images: ['https://example.com/reference-1.png'],
|
|
@@ -161,7 +173,7 @@ await generateImage({
|
|
|
161
173
|
});
|
|
162
174
|
```
|
|
163
175
|
|
|
164
|
-
`arrow-1` and `arrow-1.1` accept up to 4 reference images. `arrow-1.1-max` accepts up to 16.
|
|
176
|
+
`arrow-1` and `arrow-1.1` accept up to 4 reference images. `arrow-1.1-max` accepts up to 16. For Arrow 2 and other model IDs, the provider allows the endpoint maximum of 16 references and lets the API enforce any lower model-specific limit.
|
|
165
177
|
|
|
166
178
|
### Vectorizing a Raster Image
|
|
167
179
|
|
|
@@ -173,7 +185,7 @@ import { generateImage } from 'ai';
|
|
|
173
185
|
import fs from 'fs';
|
|
174
186
|
|
|
175
187
|
const { image } = await generateImage({
|
|
176
|
-
model: quiverai.image('arrow-
|
|
188
|
+
model: quiverai.image('arrow-2'),
|
|
177
189
|
prompt: {
|
|
178
190
|
images: [fs.readFileSync('./logo.png')],
|
|
179
191
|
},
|
|
@@ -188,3 +200,49 @@ const { image } = await generateImage({
|
|
|
188
200
|
|
|
189
201
|
fs.writeFileSync('logo.svg', image.uint8Array);
|
|
190
202
|
```
|
|
203
|
+
|
|
204
|
+
Vectorization returns one SVG per API request. To request multiple vectorizations with `n`, also set `maxImagesPerCall: 1` so `generateImage` splits them into separate calls.
|
|
205
|
+
|
|
206
|
+
### Animating an SVG
|
|
207
|
+
|
|
208
|
+
Arrow 2 and Arrow 2 Telos can animate an existing SVG. Set `operation` to `animate` and pass exactly one source SVG in `prompt.images`. The text instruction is optional; omit `text` to let QuiverAI choose an animation.
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import { quiverai, type QuiverAIImageModelOptions } from '@ai-sdk/quiverai';
|
|
212
|
+
import { generateImage } from 'ai';
|
|
213
|
+
import fs from 'fs';
|
|
214
|
+
|
|
215
|
+
const { image, providerMetadata } = await generateImage({
|
|
216
|
+
model: quiverai.image('arrow-2'),
|
|
217
|
+
prompt: {
|
|
218
|
+
images: [fs.readFileSync('./logo.svg')],
|
|
219
|
+
text: 'Make the logo pulse gently.',
|
|
220
|
+
},
|
|
221
|
+
providerOptions: {
|
|
222
|
+
quiverai: {
|
|
223
|
+
operation: 'animate',
|
|
224
|
+
reasoningEffort: 'medium',
|
|
225
|
+
maxOutputTokens: 4096,
|
|
226
|
+
} satisfies QuiverAIImageModelOptions,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
fs.writeFileSync('animated-logo.svg', image.uint8Array);
|
|
231
|
+
|
|
232
|
+
const timing = providerMetadata.quiverai?.images?.[0];
|
|
233
|
+
console.log(timing?.loopPeriodMs, timing?.openingAnimationMs);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The animation source can be an HTTP or HTTPS URL, SVG bytes, raw base64, or an `image/svg+xml` base64 data URL. Local file inputs are inspected before the request and rejected when they do not contain SVG data. Remote URLs are validated for their scheme and fetched and validated by QuiverAI.
|
|
237
|
+
|
|
238
|
+
Animation returns an animated SVG as bytes in `image.uint8Array`. When QuiverAI returns timing information, the per-image metadata includes `loopPeriodMs` and `openingAnimationMs`; either timing value can be `null`.
|
|
239
|
+
|
|
240
|
+
Animation requests must use `arrow-2` or `arrow-2-telos`, contain exactly one source SVG, omit masks, and produce one result per provider request. To request multiple animations with `n`, set `maxImagesPerCall: 1` so `generateImage` splits them into separate calls. Animation supports `temperature`, `reasoningEffort`, and `maxOutputTokens`; generation-only and vectorization-only provider options are rejected.
|
|
241
|
+
|
|
242
|
+
Source SVGs, text instructions, and remote source URLs are sent to QuiverAI. Animated SVG is active document content. Sanitize it or render it in an isolated context before embedding output from an untrusted source inline in a page.
|
|
243
|
+
|
|
244
|
+
### Billing and Usage
|
|
245
|
+
|
|
246
|
+
Arrow 2 models return measured token counts in `result.usage`. Fixed-credit models may return compatibility token counts of zero; their credit charge is available in `result.providerMetadata?.quiverai?.credits` when supplied by the API.
|
|
247
|
+
|
|
248
|
+
Model availability and supported operations depend on your organization and API key permissions. Consult QuiverAI's [model catalog](https://docs.quiver.ai/developers/models) for current capabilities and billing. Editing and the Responses API are not yet exposed by this provider.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/quiverai",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.44",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/provider": "4.0.
|
|
33
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
32
|
+
"@ai-sdk/provider": "4.0.17",
|
|
33
|
+
"@ai-sdk/provider-utils": "5.0.44"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@ai-sdk/test-server": "2.0.1",
|
|
@@ -19,14 +19,37 @@ export const quiveraiImageModelOptionsSchema = lazySchema(() =>
|
|
|
19
19
|
* - `generate`: Text-to-SVG generation. Requires `prompt`.
|
|
20
20
|
* - `vectorize`: Convert an input raster image into an SVG. Requires a
|
|
21
21
|
* single image in `prompt.images` / `files`.
|
|
22
|
+
* - `animate`: Animate an input SVG. Requires a single SVG in
|
|
23
|
+
* `prompt.images` / `files`; the text prompt is optional.
|
|
22
24
|
*/
|
|
23
|
-
operation: z.enum(['generate', 'vectorize']).optional(),
|
|
25
|
+
operation: z.enum(['generate', 'vectorize', 'animate']).optional(),
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* Extra style guidance for prompt-based generation.
|
|
27
29
|
*/
|
|
28
30
|
instructions: z.string().min(1).optional(),
|
|
29
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Reasoning effort applied to generation or vectorization.
|
|
34
|
+
*/
|
|
35
|
+
reasoningEffort: z.enum(['low', 'medium', 'high', 'xhigh']).optional(),
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* SVG root attributes requested for generation or vectorization.
|
|
39
|
+
*/
|
|
40
|
+
attributes: z
|
|
41
|
+
.object({
|
|
42
|
+
viewBox: z
|
|
43
|
+
.object({
|
|
44
|
+
minX: z.number(),
|
|
45
|
+
minY: z.number(),
|
|
46
|
+
width: z.number().positive(),
|
|
47
|
+
height: z.number().positive(),
|
|
48
|
+
})
|
|
49
|
+
.optional(),
|
|
50
|
+
})
|
|
51
|
+
.optional(),
|
|
52
|
+
|
|
30
53
|
/**
|
|
31
54
|
* Sampling temperature (0-2).
|
|
32
55
|
*/
|
|
@@ -43,7 +66,8 @@ export const quiveraiImageModelOptionsSchema = lazySchema(() =>
|
|
|
43
66
|
presencePenalty: z.number().min(-2).max(2).nullable().optional(),
|
|
44
67
|
|
|
45
68
|
/**
|
|
46
|
-
* Maximum number of output tokens (1 -
|
|
69
|
+
* Maximum number of output tokens (1 - 65536 for Arrow 2 models).
|
|
70
|
+
* The legacy upper bound of 131072 is retained for other model IDs.
|
|
47
71
|
*/
|
|
48
72
|
maxOutputTokens: z.number().int().min(1).max(131072).optional(),
|
|
49
73
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from '@ai-sdk/provider';
|
|
8
8
|
import {
|
|
9
9
|
combineHeaders,
|
|
10
|
+
convertBase64ToUint8Array,
|
|
10
11
|
convertUint8ArrayToBase64,
|
|
11
12
|
createJsonErrorResponseHandler,
|
|
12
13
|
createJsonResponseHandler,
|
|
@@ -94,6 +95,7 @@ export class QuiverAIImageModel implements ImageModelV4 {
|
|
|
94
95
|
n,
|
|
95
96
|
prompt,
|
|
96
97
|
files,
|
|
98
|
+
mask,
|
|
97
99
|
operation,
|
|
98
100
|
options: quiveraiOptions ?? {},
|
|
99
101
|
});
|
|
@@ -121,9 +123,16 @@ export class QuiverAIImageModel implements ImageModelV4 {
|
|
|
121
123
|
warnings,
|
|
122
124
|
providerMetadata: {
|
|
123
125
|
quiverai: {
|
|
126
|
+
...(response.credits != null && { credits: response.credits }),
|
|
124
127
|
images: response.data.map((image, index) => ({
|
|
125
128
|
index,
|
|
126
129
|
mimeType: image.mime_type,
|
|
130
|
+
...(image.loop_period_ms !== undefined && {
|
|
131
|
+
loopPeriodMs: image.loop_period_ms,
|
|
132
|
+
}),
|
|
133
|
+
...(image.opening_animation_ms !== undefined && {
|
|
134
|
+
openingAnimationMs: image.opening_animation_ms,
|
|
135
|
+
}),
|
|
127
136
|
})),
|
|
128
137
|
},
|
|
129
138
|
},
|
|
@@ -146,13 +155,20 @@ export class QuiverAIImageModel implements ImageModelV4 {
|
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
function getOperationPath(operation: QuiverAIOperation) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
switch (operation) {
|
|
159
|
+
case 'generate':
|
|
160
|
+
return '/svgs/generations';
|
|
161
|
+
case 'vectorize':
|
|
162
|
+
return '/svgs/vectorizations';
|
|
163
|
+
case 'animate':
|
|
164
|
+
return '/svgs/animations';
|
|
165
|
+
}
|
|
152
166
|
}
|
|
153
167
|
|
|
154
168
|
function getGenerateReferenceLimit(modelId: string) {
|
|
155
|
-
|
|
169
|
+
// Only apply the lower limit to documented Arrow 1.x models. The API
|
|
170
|
+
// enforces model-specific limits within its 16-reference request limit.
|
|
171
|
+
return ['arrow-1', 'arrow-1.0', 'arrow-1.1'].includes(modelId) ? 4 : 16;
|
|
156
172
|
}
|
|
157
173
|
|
|
158
174
|
function toQuiverAIImageReference(image: ImageModelV4File) {
|
|
@@ -167,11 +183,86 @@ function toQuiverAIImageReference(image: ImageModelV4File) {
|
|
|
167
183
|
};
|
|
168
184
|
}
|
|
169
185
|
|
|
186
|
+
const maxAnimationSourceBase64Length = 1_066_668;
|
|
187
|
+
|
|
188
|
+
function toQuiverAIAnimationSource(image: ImageModelV4File) {
|
|
189
|
+
if (image.type === 'url') {
|
|
190
|
+
let url: URL;
|
|
191
|
+
try {
|
|
192
|
+
url = new URL(image.url);
|
|
193
|
+
} catch {
|
|
194
|
+
throw new InvalidArgumentError({
|
|
195
|
+
argument: 'files',
|
|
196
|
+
message: 'QuiverAI animate requires a valid HTTP or HTTPS SVG URL.',
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
201
|
+
throw new InvalidArgumentError({
|
|
202
|
+
argument: 'files',
|
|
203
|
+
message: 'QuiverAI animate requires an HTTP or HTTPS SVG URL.',
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return { url: image.url };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let base64: string;
|
|
211
|
+
let bytes: Uint8Array;
|
|
212
|
+
|
|
213
|
+
if (typeof image.data === 'string') {
|
|
214
|
+
const dataUrlMatch =
|
|
215
|
+
/^data:image\/svg\+xml(?:;[^,]*)?;base64,([\s\S]+)$/i.exec(image.data);
|
|
216
|
+
const encodedData = dataUrlMatch?.[1] ?? image.data;
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
bytes = convertBase64ToUint8Array(encodedData);
|
|
220
|
+
} catch {
|
|
221
|
+
throw new InvalidArgumentError({
|
|
222
|
+
argument: 'files',
|
|
223
|
+
message:
|
|
224
|
+
'QuiverAI animate requires the source SVG string to be valid base64 or an SVG data URL.',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
base64 = convertUint8ArrayToBase64(bytes);
|
|
228
|
+
} else {
|
|
229
|
+
bytes = image.data;
|
|
230
|
+
base64 = convertUint8ArrayToBase64(bytes);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!isSvg(bytes)) {
|
|
234
|
+
throw new InvalidArgumentError({
|
|
235
|
+
argument: 'files',
|
|
236
|
+
message: 'QuiverAI animate requires the input file to contain SVG data.',
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (base64.length > maxAnimationSourceBase64Length) {
|
|
241
|
+
throw new InvalidArgumentError({
|
|
242
|
+
argument: 'files',
|
|
243
|
+
message: `QuiverAI animate accepts at most ${maxAnimationSourceBase64Length} base64 characters for the source SVG.`,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return { base64 };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function isSvg(data: Uint8Array): boolean {
|
|
251
|
+
const head = new TextDecoder('utf-8', { fatal: false })
|
|
252
|
+
.decode(data.subarray(0, 4096))
|
|
253
|
+
.trimStart();
|
|
254
|
+
|
|
255
|
+
return /^(?:(?:<\?xml[\s\S]*?\?>|<!--[\s\S]*?-->|<!DOCTYPE[\s\S]*?>)\s*)*<svg(?:\s|>)/i.test(
|
|
256
|
+
head,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
170
260
|
function buildRequestBody({
|
|
171
261
|
modelId,
|
|
172
262
|
n,
|
|
173
263
|
prompt,
|
|
174
264
|
files,
|
|
265
|
+
mask,
|
|
175
266
|
operation,
|
|
176
267
|
options,
|
|
177
268
|
}: {
|
|
@@ -179,14 +270,28 @@ function buildRequestBody({
|
|
|
179
270
|
n: number;
|
|
180
271
|
prompt: string | undefined;
|
|
181
272
|
files: ImageModelV4File[] | undefined;
|
|
273
|
+
mask: ImageModelV4File | undefined;
|
|
182
274
|
operation: QuiverAIOperation;
|
|
183
275
|
options: QuiverAIImageModelOptions;
|
|
184
276
|
}) {
|
|
277
|
+
if (
|
|
278
|
+
(modelId === 'arrow-2' || modelId === 'arrow-2-telos') &&
|
|
279
|
+
options.maxOutputTokens != null &&
|
|
280
|
+
options.maxOutputTokens > 65536
|
|
281
|
+
) {
|
|
282
|
+
throw new InvalidArgumentError({
|
|
283
|
+
argument: 'maxOutputTokens',
|
|
284
|
+
message: `QuiverAI model "${modelId}" supports at most 65536 output tokens.`,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
185
288
|
const sharedOptions = {
|
|
186
289
|
temperature: options.temperature,
|
|
187
290
|
top_p: options.topP,
|
|
188
291
|
presence_penalty: options.presencePenalty,
|
|
189
292
|
max_output_tokens: options.maxOutputTokens,
|
|
293
|
+
reasoning_effort: options.reasoningEffort,
|
|
294
|
+
attributes: options.attributes,
|
|
190
295
|
stream: false as const,
|
|
191
296
|
};
|
|
192
297
|
|
|
@@ -219,6 +324,17 @@ function buildRequestBody({
|
|
|
219
324
|
};
|
|
220
325
|
}
|
|
221
326
|
|
|
327
|
+
if (operation === 'animate') {
|
|
328
|
+
return buildAnimationRequestBody({
|
|
329
|
+
modelId,
|
|
330
|
+
n,
|
|
331
|
+
prompt,
|
|
332
|
+
files,
|
|
333
|
+
mask,
|
|
334
|
+
options,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
222
338
|
if (files == null || files.length === 0) {
|
|
223
339
|
throw new InvalidArgumentError({
|
|
224
340
|
argument: 'files',
|
|
@@ -234,9 +350,16 @@ function buildRequestBody({
|
|
|
234
350
|
});
|
|
235
351
|
}
|
|
236
352
|
|
|
353
|
+
if (n !== 1) {
|
|
354
|
+
throw new InvalidArgumentError({
|
|
355
|
+
argument: 'n',
|
|
356
|
+
message:
|
|
357
|
+
'QuiverAI vectorize returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to vectorize multiple times.',
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
|
|
237
361
|
return {
|
|
238
362
|
model: modelId,
|
|
239
|
-
n,
|
|
240
363
|
image: toQuiverAIImageReference(files[0]),
|
|
241
364
|
...sharedOptions,
|
|
242
365
|
auto_crop: options.autoCrop,
|
|
@@ -244,6 +367,97 @@ function buildRequestBody({
|
|
|
244
367
|
};
|
|
245
368
|
}
|
|
246
369
|
|
|
370
|
+
function buildAnimationRequestBody({
|
|
371
|
+
modelId,
|
|
372
|
+
n,
|
|
373
|
+
prompt,
|
|
374
|
+
files,
|
|
375
|
+
mask,
|
|
376
|
+
options,
|
|
377
|
+
}: {
|
|
378
|
+
modelId: string;
|
|
379
|
+
n: number;
|
|
380
|
+
prompt: string | undefined;
|
|
381
|
+
files: ImageModelV4File[] | undefined;
|
|
382
|
+
mask: ImageModelV4File | undefined;
|
|
383
|
+
options: QuiverAIImageModelOptions;
|
|
384
|
+
}) {
|
|
385
|
+
if (modelId !== 'arrow-2' && modelId !== 'arrow-2-telos') {
|
|
386
|
+
throw new InvalidArgumentError({
|
|
387
|
+
argument: 'modelId',
|
|
388
|
+
message:
|
|
389
|
+
'QuiverAI animate is supported by the "arrow-2" and "arrow-2-telos" models.',
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (files == null || files.length === 0) {
|
|
394
|
+
throw new InvalidArgumentError({
|
|
395
|
+
argument: 'files',
|
|
396
|
+
message:
|
|
397
|
+
'QuiverAI animate requires exactly one source SVG in prompt.images.',
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (files.length !== 1) {
|
|
402
|
+
throw new InvalidArgumentError({
|
|
403
|
+
argument: 'files',
|
|
404
|
+
message:
|
|
405
|
+
'QuiverAI animate accepts exactly one source SVG in prompt.images.',
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (n !== 1) {
|
|
410
|
+
throw new InvalidArgumentError({
|
|
411
|
+
argument: 'n',
|
|
412
|
+
message:
|
|
413
|
+
'QuiverAI animate returns one SVG per request. Set maxImagesPerCall to 1 in generateImage to animate multiple times.',
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (mask != null) {
|
|
418
|
+
throw new InvalidArgumentError({
|
|
419
|
+
argument: 'mask',
|
|
420
|
+
message: 'QuiverAI animate does not support masks.',
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (prompt != null && prompt.trim().length === 0) {
|
|
425
|
+
throw new InvalidArgumentError({
|
|
426
|
+
argument: 'prompt',
|
|
427
|
+
message:
|
|
428
|
+
'QuiverAI animate requires a non-empty prompt when an animation instruction is provided.',
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const unsupportedOptions = [
|
|
433
|
+
['instructions', options.instructions],
|
|
434
|
+
['topP', options.topP],
|
|
435
|
+
['presencePenalty', options.presencePenalty],
|
|
436
|
+
['attributes', options.attributes],
|
|
437
|
+
['autoCrop', options.autoCrop],
|
|
438
|
+
['targetSize', options.targetSize],
|
|
439
|
+
].filter((option): option is [string, NonNullable<unknown>] => {
|
|
440
|
+
return option[1] !== undefined;
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
if (unsupportedOptions.length > 0) {
|
|
444
|
+
throw new InvalidArgumentError({
|
|
445
|
+
argument: `providerOptions.quiverai.${unsupportedOptions[0][0]}`,
|
|
446
|
+
message: `QuiverAI animate does not support providerOptions.quiverai.${unsupportedOptions[0][0]}.`,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return {
|
|
451
|
+
model: modelId,
|
|
452
|
+
svg_source: toQuiverAIAnimationSource(files[0]),
|
|
453
|
+
prompt,
|
|
454
|
+
temperature: options.temperature,
|
|
455
|
+
max_output_tokens: options.maxOutputTokens,
|
|
456
|
+
reasoning_effort: options.reasoningEffort,
|
|
457
|
+
stream: false as const,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
247
461
|
function collectWarnings({
|
|
248
462
|
size,
|
|
249
463
|
aspectRatio,
|
|
@@ -308,6 +522,8 @@ const svgUsageSchema = z.object({
|
|
|
308
522
|
const svgDocumentSchema = z.object({
|
|
309
523
|
svg: z.string().min(1),
|
|
310
524
|
mime_type: z.literal('image/svg+xml'),
|
|
525
|
+
loop_period_ms: z.number().int().nonnegative().nullish(),
|
|
526
|
+
opening_animation_ms: z.number().int().nonnegative().nullish(),
|
|
311
527
|
});
|
|
312
528
|
|
|
313
529
|
const svgGenerationResponseSchema = z.object({
|
|
@@ -315,6 +531,7 @@ const svgGenerationResponseSchema = z.object({
|
|
|
315
531
|
created: z.number().int().nonnegative(),
|
|
316
532
|
data: z.array(svgDocumentSchema).min(1),
|
|
317
533
|
usage: svgUsageSchema.nullish(),
|
|
534
|
+
credits: z.number().int().nonnegative().nullish(),
|
|
318
535
|
});
|
|
319
536
|
|
|
320
537
|
const quiveraiErrorSchema = z.object({
|
|
@@ -7,11 +7,14 @@ export type QuiverAIImageModelId =
|
|
|
7
7
|
| 'arrow-1'
|
|
8
8
|
| 'arrow-1.1'
|
|
9
9
|
| 'arrow-1.1-max'
|
|
10
|
+
| 'arrow-2'
|
|
11
|
+
| 'arrow-2-telos'
|
|
10
12
|
| (string & {});
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* QuiverAI image operation:
|
|
14
16
|
* - `generate`: Text-to-SVG generation (default).
|
|
15
17
|
* - `vectorize`: Convert a raster image into an SVG.
|
|
18
|
+
* - `animate`: Animate a single source SVG.
|
|
16
19
|
*/
|
|
17
|
-
export type QuiverAIOperation = 'generate' | 'vectorize';
|
|
20
|
+
export type QuiverAIOperation = 'generate' | 'vectorize' | 'animate';
|