@providerprotocol/ai 0.0.18 → 0.0.19
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/README.md +294 -114
- package/dist/anthropic/index.d.ts +1 -1
- package/dist/chunk-WAKD3OO5.js +224 -0
- package/dist/chunk-WAKD3OO5.js.map +1 -0
- package/dist/content-DEl3z_W2.d.ts +276 -0
- package/dist/google/index.d.ts +3 -1
- package/dist/google/index.js +117 -1
- package/dist/google/index.js.map +1 -1
- package/dist/http/index.d.ts +2 -2
- package/dist/image-Dhq-Yuq4.d.ts +456 -0
- package/dist/index.d.ts +55 -163
- package/dist/index.js +79 -211
- package/dist/index.js.map +1 -1
- package/dist/ollama/index.d.ts +1 -1
- package/dist/openai/index.d.ts +47 -20
- package/dist/openai/index.js +304 -1
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +1 -1
- package/dist/{provider-D5MO3-pS.d.ts → provider-BBMBZuGn.d.ts} +11 -11
- package/dist/proxy/index.d.ts +126 -85
- package/dist/proxy/index.js.map +1 -1
- package/dist/{retry-DZ4Sqmxp.d.ts → retry-DR7YRJDz.d.ts} +1 -1
- package/dist/{stream-BjyVzBxV.d.ts → stream-DRHy6q1a.d.ts} +2 -275
- package/dist/xai/index.d.ts +29 -1
- package/dist/xai/index.js +113 -1
- package/dist/xai/index.js.map +1 -1
- package/package.json +1 -1
package/dist/openai/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Image
|
|
3
|
+
} from "../chunk-WAKD3OO5.js";
|
|
1
4
|
import {
|
|
2
5
|
AssistantMessage,
|
|
3
6
|
isAssistantMessage,
|
|
@@ -1381,6 +1384,303 @@ function createEmbeddingHandler() {
|
|
|
1381
1384
|
};
|
|
1382
1385
|
}
|
|
1383
1386
|
|
|
1387
|
+
// src/providers/openai/image.ts
|
|
1388
|
+
var OPENAI_IMAGES_API_URL = "https://api.openai.com/v1/images/generations";
|
|
1389
|
+
var OPENAI_IMAGES_EDIT_URL = "https://api.openai.com/v1/images/edits";
|
|
1390
|
+
function getCapabilities(modelId) {
|
|
1391
|
+
const isGptImage = modelId.startsWith("gpt-image");
|
|
1392
|
+
const isDalle2 = modelId === "dall-e-2";
|
|
1393
|
+
return {
|
|
1394
|
+
generate: true,
|
|
1395
|
+
streaming: isGptImage,
|
|
1396
|
+
edit: true,
|
|
1397
|
+
maxImages: isDalle2 ? 10 : isGptImage ? 10 : 1
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
function createImageHandler() {
|
|
1401
|
+
let providerRef = null;
|
|
1402
|
+
return {
|
|
1403
|
+
_setProvider(provider) {
|
|
1404
|
+
providerRef = provider;
|
|
1405
|
+
},
|
|
1406
|
+
bind(modelId) {
|
|
1407
|
+
if (!providerRef) {
|
|
1408
|
+
throw new UPPError(
|
|
1409
|
+
"Provider reference not set. Handler must be used with createProvider().",
|
|
1410
|
+
"INVALID_REQUEST",
|
|
1411
|
+
"openai",
|
|
1412
|
+
"image"
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1415
|
+
const capabilities = getCapabilities(modelId);
|
|
1416
|
+
const model = {
|
|
1417
|
+
modelId,
|
|
1418
|
+
capabilities,
|
|
1419
|
+
get provider() {
|
|
1420
|
+
return providerRef;
|
|
1421
|
+
},
|
|
1422
|
+
async generate(request) {
|
|
1423
|
+
return executeGenerate(modelId, request);
|
|
1424
|
+
},
|
|
1425
|
+
async edit(request) {
|
|
1426
|
+
return executeEdit(modelId, request);
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
if (capabilities.streaming) {
|
|
1430
|
+
model.stream = function(request) {
|
|
1431
|
+
return executeStream(modelId, request);
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
return model;
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
async function executeGenerate(modelId, request) {
|
|
1439
|
+
const apiKey = await resolveApiKey(
|
|
1440
|
+
request.config,
|
|
1441
|
+
"OPENAI_API_KEY",
|
|
1442
|
+
"openai",
|
|
1443
|
+
"image"
|
|
1444
|
+
);
|
|
1445
|
+
const baseUrl = request.config.baseUrl ? `${request.config.baseUrl.replace(/\/$/, "")}/v1/images/generations` : OPENAI_IMAGES_API_URL;
|
|
1446
|
+
const body = {
|
|
1447
|
+
model: modelId,
|
|
1448
|
+
prompt: request.prompt
|
|
1449
|
+
};
|
|
1450
|
+
if (request.params) {
|
|
1451
|
+
const { n, size, quality, style, background, output_format, output_compression, response_format, moderation, user } = request.params;
|
|
1452
|
+
if (n !== void 0) body.n = n;
|
|
1453
|
+
if (size !== void 0) body.size = size;
|
|
1454
|
+
if (quality !== void 0) body.quality = quality;
|
|
1455
|
+
if (style !== void 0) body.style = style;
|
|
1456
|
+
if (background !== void 0) body.background = background;
|
|
1457
|
+
if (output_format !== void 0) body.output_format = output_format;
|
|
1458
|
+
if (output_compression !== void 0) body.output_compression = output_compression;
|
|
1459
|
+
if (response_format !== void 0) body.response_format = response_format;
|
|
1460
|
+
if (moderation !== void 0) body.moderation = moderation;
|
|
1461
|
+
if (user !== void 0) body.user = user;
|
|
1462
|
+
}
|
|
1463
|
+
const headers = {
|
|
1464
|
+
"Content-Type": "application/json",
|
|
1465
|
+
Authorization: `Bearer ${apiKey}`
|
|
1466
|
+
};
|
|
1467
|
+
if (request.config.headers) {
|
|
1468
|
+
for (const [key, value] of Object.entries(request.config.headers)) {
|
|
1469
|
+
if (value !== void 0) {
|
|
1470
|
+
headers[key] = value;
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
const response = await doFetch(baseUrl, {
|
|
1475
|
+
method: "POST",
|
|
1476
|
+
headers,
|
|
1477
|
+
body: JSON.stringify(body),
|
|
1478
|
+
signal: request.signal
|
|
1479
|
+
}, request.config, "openai", "image");
|
|
1480
|
+
const data = await response.json();
|
|
1481
|
+
return transformResponse3(data);
|
|
1482
|
+
}
|
|
1483
|
+
async function executeEdit(modelId, request) {
|
|
1484
|
+
const apiKey = await resolveApiKey(
|
|
1485
|
+
request.config,
|
|
1486
|
+
"OPENAI_API_KEY",
|
|
1487
|
+
"openai",
|
|
1488
|
+
"image"
|
|
1489
|
+
);
|
|
1490
|
+
const baseUrl = request.config.baseUrl ? `${request.config.baseUrl.replace(/\/$/, "")}/v1/images/edits` : OPENAI_IMAGES_EDIT_URL;
|
|
1491
|
+
const formData = new FormData();
|
|
1492
|
+
formData.append("model", modelId);
|
|
1493
|
+
formData.append("prompt", request.prompt);
|
|
1494
|
+
const imageBytes = request.image.toBytes();
|
|
1495
|
+
const imageBlob = new Blob([imageBytes], { type: request.image.mimeType });
|
|
1496
|
+
formData.append("image", imageBlob, "image.png");
|
|
1497
|
+
if (request.mask) {
|
|
1498
|
+
const maskBytes = request.mask.toBytes();
|
|
1499
|
+
const maskBlob = new Blob([maskBytes], { type: request.mask.mimeType });
|
|
1500
|
+
formData.append("mask", maskBlob, "mask.png");
|
|
1501
|
+
}
|
|
1502
|
+
if (request.params) {
|
|
1503
|
+
const { n, size, response_format, user } = request.params;
|
|
1504
|
+
if (n !== void 0) formData.append("n", String(n));
|
|
1505
|
+
if (size !== void 0) formData.append("size", size);
|
|
1506
|
+
if (response_format !== void 0) formData.append("response_format", response_format);
|
|
1507
|
+
if (user !== void 0) formData.append("user", user);
|
|
1508
|
+
}
|
|
1509
|
+
const headers = {
|
|
1510
|
+
Authorization: `Bearer ${apiKey}`
|
|
1511
|
+
};
|
|
1512
|
+
if (request.config.headers) {
|
|
1513
|
+
for (const [key, value] of Object.entries(request.config.headers)) {
|
|
1514
|
+
if (value !== void 0) {
|
|
1515
|
+
headers[key] = value;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
const response = await doFetch(baseUrl, {
|
|
1520
|
+
method: "POST",
|
|
1521
|
+
headers,
|
|
1522
|
+
body: formData,
|
|
1523
|
+
signal: request.signal
|
|
1524
|
+
}, request.config, "openai", "image");
|
|
1525
|
+
const data = await response.json();
|
|
1526
|
+
return transformResponse3(data);
|
|
1527
|
+
}
|
|
1528
|
+
function executeStream(modelId, request) {
|
|
1529
|
+
const abortController = new AbortController();
|
|
1530
|
+
let resolveResponse;
|
|
1531
|
+
let rejectResponse;
|
|
1532
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
1533
|
+
resolveResponse = resolve;
|
|
1534
|
+
rejectResponse = reject;
|
|
1535
|
+
});
|
|
1536
|
+
async function* generateStream() {
|
|
1537
|
+
try {
|
|
1538
|
+
const apiKey = await resolveApiKey(
|
|
1539
|
+
request.config,
|
|
1540
|
+
"OPENAI_API_KEY",
|
|
1541
|
+
"openai",
|
|
1542
|
+
"image"
|
|
1543
|
+
);
|
|
1544
|
+
const baseUrl = request.config.baseUrl ? `${request.config.baseUrl.replace(/\/$/, "")}/v1/images/generations` : OPENAI_IMAGES_API_URL;
|
|
1545
|
+
const body = {
|
|
1546
|
+
model: modelId,
|
|
1547
|
+
prompt: request.prompt,
|
|
1548
|
+
stream: true
|
|
1549
|
+
};
|
|
1550
|
+
if (request.params) {
|
|
1551
|
+
const { n, size, quality, background, output_format, partial_images, moderation, user } = request.params;
|
|
1552
|
+
if (n !== void 0) body.n = n;
|
|
1553
|
+
if (size !== void 0) body.size = size;
|
|
1554
|
+
if (quality !== void 0) body.quality = quality;
|
|
1555
|
+
if (background !== void 0) body.background = background;
|
|
1556
|
+
if (output_format !== void 0) body.output_format = output_format;
|
|
1557
|
+
if (partial_images !== void 0) body.partial_images = partial_images;
|
|
1558
|
+
if (moderation !== void 0) body.moderation = moderation;
|
|
1559
|
+
if (user !== void 0) body.user = user;
|
|
1560
|
+
}
|
|
1561
|
+
const headers = {
|
|
1562
|
+
"Content-Type": "application/json",
|
|
1563
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1564
|
+
Accept: "text/event-stream"
|
|
1565
|
+
};
|
|
1566
|
+
if (request.config.headers) {
|
|
1567
|
+
for (const [key, value] of Object.entries(request.config.headers)) {
|
|
1568
|
+
if (value !== void 0) {
|
|
1569
|
+
headers[key] = value;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
const mergedSignal = request.signal ? AbortSignal.any([abortController.signal, request.signal]) : abortController.signal;
|
|
1574
|
+
const response = await doFetch(baseUrl, {
|
|
1575
|
+
method: "POST",
|
|
1576
|
+
headers,
|
|
1577
|
+
body: JSON.stringify(body),
|
|
1578
|
+
signal: mergedSignal
|
|
1579
|
+
}, request.config, "openai", "image");
|
|
1580
|
+
const reader = response.body?.getReader();
|
|
1581
|
+
if (!reader) {
|
|
1582
|
+
throw new UPPError(
|
|
1583
|
+
"No response body for streaming",
|
|
1584
|
+
"PROVIDER_ERROR",
|
|
1585
|
+
"openai",
|
|
1586
|
+
"image"
|
|
1587
|
+
);
|
|
1588
|
+
}
|
|
1589
|
+
const decoder = new TextDecoder();
|
|
1590
|
+
let buffer = "";
|
|
1591
|
+
const generatedImages = [];
|
|
1592
|
+
let responseMetadata = {};
|
|
1593
|
+
while (true) {
|
|
1594
|
+
const { done, value } = await reader.read();
|
|
1595
|
+
if (done) break;
|
|
1596
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1597
|
+
const lines = buffer.split("\n");
|
|
1598
|
+
buffer = lines.pop() ?? "";
|
|
1599
|
+
for (const line of lines) {
|
|
1600
|
+
if (line.startsWith("data: ")) {
|
|
1601
|
+
const data = line.slice(6);
|
|
1602
|
+
if (data === "[DONE]") {
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
try {
|
|
1606
|
+
const chunk = JSON.parse(data);
|
|
1607
|
+
if (chunk.type === "image_generation.partial_image" && chunk.data?.b64_json) {
|
|
1608
|
+
const previewImage = Image.fromBase64(chunk.data.b64_json, "image/png");
|
|
1609
|
+
yield {
|
|
1610
|
+
type: "preview",
|
|
1611
|
+
image: previewImage,
|
|
1612
|
+
index: chunk.index ?? 0
|
|
1613
|
+
};
|
|
1614
|
+
} else if (chunk.type === "image_generation.completed" && chunk.data) {
|
|
1615
|
+
const image = chunk.data.b64_json ? Image.fromBase64(chunk.data.b64_json, "image/png") : Image.fromUrl(chunk.data.url ?? "", "image/png");
|
|
1616
|
+
const genImage = {
|
|
1617
|
+
image,
|
|
1618
|
+
metadata: chunk.data.revised_prompt ? { revised_prompt: chunk.data.revised_prompt } : void 0
|
|
1619
|
+
};
|
|
1620
|
+
generatedImages.push(genImage);
|
|
1621
|
+
yield {
|
|
1622
|
+
type: "complete",
|
|
1623
|
+
image: genImage,
|
|
1624
|
+
index: chunk.index ?? generatedImages.length - 1
|
|
1625
|
+
};
|
|
1626
|
+
} else if (chunk.type === "response.done") {
|
|
1627
|
+
responseMetadata = chunk.data;
|
|
1628
|
+
}
|
|
1629
|
+
} catch {
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
resolveResponse({
|
|
1635
|
+
images: generatedImages,
|
|
1636
|
+
metadata: responseMetadata,
|
|
1637
|
+
usage: {
|
|
1638
|
+
imagesGenerated: generatedImages.length
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
} catch (error) {
|
|
1642
|
+
rejectResponse(error);
|
|
1643
|
+
throw error;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
const generator = generateStream();
|
|
1647
|
+
return {
|
|
1648
|
+
[Symbol.asyncIterator]: () => generator,
|
|
1649
|
+
response: responsePromise
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
function transformResponse3(data) {
|
|
1653
|
+
const images = data.data.map((item) => {
|
|
1654
|
+
let image;
|
|
1655
|
+
if (item.b64_json) {
|
|
1656
|
+
image = Image.fromBase64(item.b64_json, "image/png");
|
|
1657
|
+
} else if (item.url) {
|
|
1658
|
+
image = Image.fromUrl(item.url, "image/png");
|
|
1659
|
+
} else {
|
|
1660
|
+
throw new UPPError(
|
|
1661
|
+
"No image data in response",
|
|
1662
|
+
"PROVIDER_ERROR",
|
|
1663
|
+
"openai",
|
|
1664
|
+
"image"
|
|
1665
|
+
);
|
|
1666
|
+
}
|
|
1667
|
+
return {
|
|
1668
|
+
image,
|
|
1669
|
+
metadata: item.revised_prompt ? { revised_prompt: item.revised_prompt } : void 0
|
|
1670
|
+
};
|
|
1671
|
+
});
|
|
1672
|
+
return {
|
|
1673
|
+
images,
|
|
1674
|
+
usage: data.usage ? {
|
|
1675
|
+
imagesGenerated: images.length,
|
|
1676
|
+
inputTokens: data.usage.input_tokens,
|
|
1677
|
+
outputTokens: data.usage.output_tokens
|
|
1678
|
+
} : {
|
|
1679
|
+
imagesGenerated: images.length
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1384
1684
|
// src/providers/openai/types.ts
|
|
1385
1685
|
function webSearchTool(options) {
|
|
1386
1686
|
if (options) {
|
|
@@ -1454,6 +1754,7 @@ function createOpenAIProvider() {
|
|
|
1454
1754
|
const responsesHandler = createResponsesLLMHandler();
|
|
1455
1755
|
const completionsHandler = createCompletionsLLMHandler();
|
|
1456
1756
|
const embeddingHandler = createEmbeddingHandler();
|
|
1757
|
+
const imageHandler = createImageHandler();
|
|
1457
1758
|
const fn = function(modelId, options) {
|
|
1458
1759
|
const apiMode = options?.api ?? "responses";
|
|
1459
1760
|
currentApiMode = apiMode;
|
|
@@ -1463,7 +1764,8 @@ function createOpenAIProvider() {
|
|
|
1463
1764
|
get llm() {
|
|
1464
1765
|
return currentApiMode === "completions" ? completionsHandler : responsesHandler;
|
|
1465
1766
|
},
|
|
1466
|
-
embedding: embeddingHandler
|
|
1767
|
+
embedding: embeddingHandler,
|
|
1768
|
+
image: imageHandler
|
|
1467
1769
|
};
|
|
1468
1770
|
Object.defineProperties(fn, {
|
|
1469
1771
|
name: {
|
|
@@ -1486,6 +1788,7 @@ function createOpenAIProvider() {
|
|
|
1486
1788
|
responsesHandler._setProvider?.(provider);
|
|
1487
1789
|
completionsHandler._setProvider?.(provider);
|
|
1488
1790
|
embeddingHandler._setProvider?.(provider);
|
|
1791
|
+
imageHandler._setProvider?.(provider);
|
|
1489
1792
|
return provider;
|
|
1490
1793
|
}
|
|
1491
1794
|
var openai = createOpenAIProvider();
|