@janole/ai-sdk-provider-codex-asp 0.2.3 → 0.2.4
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/dist/index.cjs +158 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -20
- package/dist/index.d.ts +93 -20
- package/dist/index.js +157 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var child_process = require('child_process');
|
|
4
|
+
var crypto = require('crypto');
|
|
5
|
+
var promises = require('fs/promises');
|
|
6
|
+
var os = require('os');
|
|
7
|
+
var path = require('path');
|
|
8
|
+
var url = require('url');
|
|
4
9
|
var provider = require('@ai-sdk/provider');
|
|
5
10
|
|
|
6
11
|
// src/utils/object.ts
|
|
@@ -930,7 +935,7 @@ var DynamicToolsDispatcher = class {
|
|
|
930
935
|
// package.json
|
|
931
936
|
var package_default = {
|
|
932
937
|
name: "@janole/ai-sdk-provider-codex-asp",
|
|
933
|
-
version: "0.2.
|
|
938
|
+
version: "0.2.4"};
|
|
934
939
|
|
|
935
940
|
// src/package-info.ts
|
|
936
941
|
var PACKAGE_NAME = package_default.name;
|
|
@@ -1317,8 +1322,6 @@ var CodexEventMapper = class {
|
|
|
1317
1322
|
return parts;
|
|
1318
1323
|
}
|
|
1319
1324
|
};
|
|
1320
|
-
|
|
1321
|
-
// src/protocol/prompt-mapper.ts
|
|
1322
1325
|
function mapSystemPrompt(prompt) {
|
|
1323
1326
|
const chunks = [];
|
|
1324
1327
|
for (const message of prompt) {
|
|
@@ -1331,8 +1334,111 @@ function mapSystemPrompt(prompt) {
|
|
|
1331
1334
|
}
|
|
1332
1335
|
return chunks.length > 0 ? chunks.join("\n\n") : void 0;
|
|
1333
1336
|
}
|
|
1334
|
-
function
|
|
1335
|
-
|
|
1337
|
+
function textItem(text) {
|
|
1338
|
+
return { type: "text", text, text_elements: [] };
|
|
1339
|
+
}
|
|
1340
|
+
var MEDIA_TYPE_TO_EXT = {
|
|
1341
|
+
"image/png": ".png",
|
|
1342
|
+
"image/jpeg": ".jpg",
|
|
1343
|
+
"image/gif": ".gif",
|
|
1344
|
+
"image/webp": ".webp",
|
|
1345
|
+
"image/svg+xml": ".svg",
|
|
1346
|
+
"image/bmp": ".bmp",
|
|
1347
|
+
"image/tiff": ".tiff"
|
|
1348
|
+
};
|
|
1349
|
+
function extensionForMediaType(mediaType) {
|
|
1350
|
+
return MEDIA_TYPE_TO_EXT[mediaType] ?? ".bin";
|
|
1351
|
+
}
|
|
1352
|
+
var LocalFileWriter = class {
|
|
1353
|
+
async write(data, mediaType) {
|
|
1354
|
+
const ext = extensionForMediaType(mediaType);
|
|
1355
|
+
const filename = `codex-ai-sdk-${crypto.randomUUID()}${ext}`;
|
|
1356
|
+
const filepath = path.join(os.tmpdir(), filename);
|
|
1357
|
+
const buffer = typeof data === "string" ? Buffer.from(data, "base64") : data;
|
|
1358
|
+
await promises.writeFile(filepath, buffer);
|
|
1359
|
+
return url.pathToFileURL(filepath);
|
|
1360
|
+
}
|
|
1361
|
+
async cleanup(urls) {
|
|
1362
|
+
await Promise.allSettled(
|
|
1363
|
+
urls.filter((u) => u.protocol === "file:").map((u) => promises.unlink(u))
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
var PromptFileResolver = class {
|
|
1368
|
+
writer;
|
|
1369
|
+
written = [];
|
|
1370
|
+
constructor(writer) {
|
|
1371
|
+
this.writer = writer ?? new LocalFileWriter();
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Resolve inline file data and map user content to Codex input items.
|
|
1375
|
+
*
|
|
1376
|
+
* - Inline image data (base64 / Uint8Array) is written via the
|
|
1377
|
+
* {@link FileWriter} and converted to `localImage` or `image` items.
|
|
1378
|
+
* - URL-based image file parts are converted directly.
|
|
1379
|
+
* - Inline text file data is decoded and inlined as text.
|
|
1380
|
+
* - Unsupported media types are silently skipped.
|
|
1381
|
+
*
|
|
1382
|
+
* @param isResume - When true only the last user message is extracted.
|
|
1383
|
+
* When false (fresh thread) all user text is accumulated with images
|
|
1384
|
+
* flushing the text buffer to preserve ordering.
|
|
1385
|
+
*/
|
|
1386
|
+
async resolve(prompt, isResume = false) {
|
|
1387
|
+
if (isResume) {
|
|
1388
|
+
return this.resolveResumed(prompt);
|
|
1389
|
+
}
|
|
1390
|
+
return this.resolveFresh(prompt);
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Remove all files created by previous {@link resolve} calls.
|
|
1394
|
+
* Best-effort — never throws.
|
|
1395
|
+
*/
|
|
1396
|
+
async cleanup() {
|
|
1397
|
+
const urls = this.written.splice(0);
|
|
1398
|
+
if (urls.length > 0) {
|
|
1399
|
+
await this.writer.cleanup(urls);
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Convert a resolved image URL to a Codex input item.
|
|
1404
|
+
*/
|
|
1405
|
+
mapImageUrl(mediaType, data) {
|
|
1406
|
+
if (!mediaType.startsWith("image/")) {
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
if (data.protocol === "file:") {
|
|
1410
|
+
return { type: "localImage", path: url.fileURLToPath(data) };
|
|
1411
|
+
}
|
|
1412
|
+
return { type: "image", url: data.href };
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Resolve a single file part: write inline data via the writer, then
|
|
1416
|
+
* convert to a Codex input item. Text files are decoded and returned
|
|
1417
|
+
* as text items. Returns `null` for unsupported media types.
|
|
1418
|
+
*/
|
|
1419
|
+
async resolveFilePart(part) {
|
|
1420
|
+
const { mediaType, data } = part;
|
|
1421
|
+
if (mediaType.startsWith("text/")) {
|
|
1422
|
+
if (data instanceof URL) {
|
|
1423
|
+
return textItem(data.href);
|
|
1424
|
+
}
|
|
1425
|
+
const text = typeof data === "string" ? Buffer.from(data, "base64").toString("utf-8") : new TextDecoder().decode(data);
|
|
1426
|
+
return textItem(text);
|
|
1427
|
+
}
|
|
1428
|
+
if (mediaType.startsWith("image/") && !(data instanceof URL)) {
|
|
1429
|
+
const url = await this.writer.write(data, mediaType);
|
|
1430
|
+
this.written.push(url);
|
|
1431
|
+
return this.mapImageUrl(mediaType, url);
|
|
1432
|
+
}
|
|
1433
|
+
if (data instanceof URL) {
|
|
1434
|
+
return this.mapImageUrl(mediaType, data);
|
|
1435
|
+
}
|
|
1436
|
+
return null;
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Resume path: extract parts from the last user message individually.
|
|
1440
|
+
*/
|
|
1441
|
+
async resolveResumed(prompt) {
|
|
1336
1442
|
for (let i = prompt.length - 1; i >= 0; i--) {
|
|
1337
1443
|
const message = prompt[i];
|
|
1338
1444
|
if (message?.role === "user") {
|
|
@@ -1341,7 +1447,12 @@ function mapPromptToTurnInput(prompt, isResume = false) {
|
|
|
1341
1447
|
if (part.type === "text") {
|
|
1342
1448
|
const text = part.text.trim();
|
|
1343
1449
|
if (text.length > 0) {
|
|
1344
|
-
items.push(
|
|
1450
|
+
items.push(textItem(text));
|
|
1451
|
+
}
|
|
1452
|
+
} else if (part.type === "file") {
|
|
1453
|
+
const mapped = await this.resolveFilePart(part);
|
|
1454
|
+
if (mapped) {
|
|
1455
|
+
items.push(mapped);
|
|
1345
1456
|
}
|
|
1346
1457
|
}
|
|
1347
1458
|
}
|
|
@@ -1350,21 +1461,45 @@ function mapPromptToTurnInput(prompt, isResume = false) {
|
|
|
1350
1461
|
}
|
|
1351
1462
|
return [];
|
|
1352
1463
|
}
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1464
|
+
/**
|
|
1465
|
+
* Fresh thread path: accumulate text chunks across all user messages,
|
|
1466
|
+
* flushing before each image to preserve ordering.
|
|
1467
|
+
*/
|
|
1468
|
+
async resolveFresh(prompt) {
|
|
1469
|
+
const items = [];
|
|
1470
|
+
const textChunks = [];
|
|
1471
|
+
const flushText = () => {
|
|
1472
|
+
if (textChunks.length > 0) {
|
|
1473
|
+
items.push(textItem(textChunks.join("\n\n")));
|
|
1474
|
+
textChunks.length = 0;
|
|
1475
|
+
}
|
|
1476
|
+
};
|
|
1477
|
+
for (const message of prompt) {
|
|
1478
|
+
if (message.role === "user") {
|
|
1479
|
+
for (const part of message.content) {
|
|
1480
|
+
if (part.type === "text") {
|
|
1481
|
+
const text = part.text.trim();
|
|
1482
|
+
if (text.length > 0) {
|
|
1483
|
+
textChunks.push(text);
|
|
1484
|
+
}
|
|
1485
|
+
} else if (part.type === "file") {
|
|
1486
|
+
const mapped = await this.resolveFilePart(part);
|
|
1487
|
+
if (mapped) {
|
|
1488
|
+
if (mapped.type === "text") {
|
|
1489
|
+
textChunks.push(mapped.text);
|
|
1490
|
+
} else {
|
|
1491
|
+
flushText();
|
|
1492
|
+
items.push(mapped);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1361
1495
|
}
|
|
1362
1496
|
}
|
|
1363
1497
|
}
|
|
1364
1498
|
}
|
|
1499
|
+
flushText();
|
|
1500
|
+
return items;
|
|
1365
1501
|
}
|
|
1366
|
-
|
|
1367
|
-
}
|
|
1502
|
+
};
|
|
1368
1503
|
|
|
1369
1504
|
// src/model.ts
|
|
1370
1505
|
function createEmptyUsage() {
|
|
@@ -1631,6 +1766,7 @@ var CodexLanguageModel = class {
|
|
|
1631
1766
|
debugLog?.("outbound", "turn/interrupt", interruptParams);
|
|
1632
1767
|
await client.request("turn/interrupt", interruptParams, interruptTimeoutMs);
|
|
1633
1768
|
};
|
|
1769
|
+
const fileResolver = new PromptFileResolver();
|
|
1634
1770
|
const stream = new ReadableStream({
|
|
1635
1771
|
start: (controller) => {
|
|
1636
1772
|
let closed = false;
|
|
@@ -1643,6 +1779,7 @@ var CodexLanguageModel = class {
|
|
|
1643
1779
|
try {
|
|
1644
1780
|
controller.close();
|
|
1645
1781
|
} finally {
|
|
1782
|
+
await fileResolver.cleanup();
|
|
1646
1783
|
await client.disconnect();
|
|
1647
1784
|
}
|
|
1648
1785
|
};
|
|
@@ -1654,6 +1791,7 @@ var CodexLanguageModel = class {
|
|
|
1654
1791
|
try {
|
|
1655
1792
|
controller.close();
|
|
1656
1793
|
} finally {
|
|
1794
|
+
await fileResolver.cleanup();
|
|
1657
1795
|
await client.disconnect();
|
|
1658
1796
|
}
|
|
1659
1797
|
};
|
|
@@ -1878,7 +2016,7 @@ var CodexLanguageModel = class {
|
|
|
1878
2016
|
closeSuccessfully
|
|
1879
2017
|
);
|
|
1880
2018
|
}
|
|
1881
|
-
const turnInput =
|
|
2019
|
+
const turnInput = await fileResolver.resolve(options.prompt, !!resumeThreadId);
|
|
1882
2020
|
const turnStartParams = stripUndefined({
|
|
1883
2021
|
threadId,
|
|
1884
2022
|
input: turnInput,
|
|
@@ -1902,6 +2040,7 @@ var CodexLanguageModel = class {
|
|
|
1902
2040
|
await interruptTurnIfPossible();
|
|
1903
2041
|
} catch {
|
|
1904
2042
|
}
|
|
2043
|
+
await fileResolver.cleanup();
|
|
1905
2044
|
await client.disconnect();
|
|
1906
2045
|
}
|
|
1907
2046
|
});
|
|
@@ -2083,16 +2222,17 @@ exports.CodexWorker = CodexWorker;
|
|
|
2083
2222
|
exports.CodexWorkerPool = CodexWorkerPool;
|
|
2084
2223
|
exports.DynamicToolsDispatcher = DynamicToolsDispatcher;
|
|
2085
2224
|
exports.JsonRpcError = JsonRpcError;
|
|
2225
|
+
exports.LocalFileWriter = LocalFileWriter;
|
|
2086
2226
|
exports.PACKAGE_NAME = PACKAGE_NAME;
|
|
2087
2227
|
exports.PACKAGE_VERSION = PACKAGE_VERSION;
|
|
2088
2228
|
exports.PersistentTransport = PersistentTransport;
|
|
2229
|
+
exports.PromptFileResolver = PromptFileResolver;
|
|
2089
2230
|
exports.StdioTransport = StdioTransport;
|
|
2090
2231
|
exports.WebSocketTransport = WebSocketTransport;
|
|
2091
2232
|
exports.codexAppServer = codexAppServer;
|
|
2092
2233
|
exports.codexProviderMetadata = codexProviderMetadata;
|
|
2093
2234
|
exports.createCodexAppServer = createCodexAppServer;
|
|
2094
2235
|
exports.createCodexProvider = createCodexProvider;
|
|
2095
|
-
exports.mapPromptToTurnInput = mapPromptToTurnInput;
|
|
2096
2236
|
exports.mapSystemPrompt = mapSystemPrompt;
|
|
2097
2237
|
exports.withProviderMetadata = withProviderMetadata;
|
|
2098
2238
|
//# sourceMappingURL=index.cjs.map
|