topchester-ai 0.53.0 → 0.54.0
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/bin.mjs +1 -1
- package/dist/{cli-CqFhOvlt.mjs → cli-D1d-I3Fi.mjs} +205 -13
- package/dist/cli-D1d-I3Fi.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli-CqFhOvlt.mjs.map +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -127,13 +127,13 @@ function extractAccountIdFromClaims(claims) {
|
|
|
127
127
|
const flatClaim = getStringProperty(claims, "chatgpt_account_id");
|
|
128
128
|
if (flatClaim) return flatClaim;
|
|
129
129
|
const authClaims = claims["https://api.openai.com/auth"];
|
|
130
|
-
if (isPlainObject$
|
|
130
|
+
if (isPlainObject$3(authClaims)) {
|
|
131
131
|
const namespacedClaim = getStringProperty(authClaims, "chatgpt_account_id");
|
|
132
132
|
if (namespacedClaim) return namespacedClaim;
|
|
133
133
|
}
|
|
134
134
|
const organizations = claims.organizations;
|
|
135
135
|
if (Array.isArray(organizations)) {
|
|
136
|
-
const firstOrganization = organizations.find(isPlainObject$
|
|
136
|
+
const firstOrganization = organizations.find(isPlainObject$3);
|
|
137
137
|
const organizationId = firstOrganization ? getStringProperty(firstOrganization, "id") : void 0;
|
|
138
138
|
if (organizationId) return organizationId;
|
|
139
139
|
}
|
|
@@ -143,7 +143,7 @@ function parseJwtClaims(token) {
|
|
|
143
143
|
if (!parts || parts.length !== 3 || !parts[1]) return;
|
|
144
144
|
try {
|
|
145
145
|
const parsed = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
|
|
146
|
-
return isPlainObject$
|
|
146
|
+
return isPlainObject$3(parsed) ? parsed : void 0;
|
|
147
147
|
} catch {
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
@@ -190,7 +190,7 @@ async function readJsonObject(response, label) {
|
|
|
190
190
|
} catch (error) {
|
|
191
191
|
throw new CodexAuthError("invalid_response", `Invalid Codex ${label}: ${formatErrorMessage$4(error)}.`);
|
|
192
192
|
}
|
|
193
|
-
if (!isPlainObject$
|
|
193
|
+
if (!isPlainObject$3(parsed)) throw new CodexAuthError("invalid_response", `Invalid Codex ${label}: expected an object.`);
|
|
194
194
|
return parsed;
|
|
195
195
|
}
|
|
196
196
|
function isPendingDeviceAuthResponse(response) {
|
|
@@ -214,7 +214,7 @@ function optionalPositiveNumber(value) {
|
|
|
214
214
|
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
|
|
215
215
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
216
216
|
}
|
|
217
|
-
function isPlainObject$
|
|
217
|
+
function isPlainObject$3(value) {
|
|
218
218
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
219
219
|
}
|
|
220
220
|
function formatErrorMessage$4(error) {
|
|
@@ -325,13 +325,13 @@ async function getAuthStoreStatus(options = {}) {
|
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
327
|
function parseAuthStore(path, value) {
|
|
328
|
-
if (!isPlainObject$
|
|
328
|
+
if (!isPlainObject$2(value)) throw new AuthStoreError(path, "<root>: expected an object");
|
|
329
329
|
if (value.version !== 1) throw new AuthStoreError(path, "version: expected 1");
|
|
330
|
-
if (!isPlainObject$
|
|
330
|
+
if (!isPlainObject$2(value.providers)) throw new AuthStoreError(path, "providers: expected an object");
|
|
331
331
|
const providers = {};
|
|
332
332
|
for (const [providerId, providerRecord] of Object.entries(value.providers)) {
|
|
333
333
|
if (!providerId) throw new AuthStoreError(path, "providers: provider id must not be empty");
|
|
334
|
-
if (!isPlainObject$
|
|
334
|
+
if (!isPlainObject$2(providerRecord)) throw new AuthStoreError(path, `providers.${providerId}: expected an object`);
|
|
335
335
|
providers[providerId] = parseProviderRecord(path, providerId, providerRecord);
|
|
336
336
|
}
|
|
337
337
|
return {
|
|
@@ -392,7 +392,7 @@ async function setModeIfSupported(path, mode) {
|
|
|
392
392
|
throw error;
|
|
393
393
|
});
|
|
394
394
|
}
|
|
395
|
-
function isPlainObject$
|
|
395
|
+
function isPlainObject$2(value) {
|
|
396
396
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
397
397
|
}
|
|
398
398
|
function isNodeError$4(error) {
|
|
@@ -5335,6 +5335,7 @@ function createCodexProviderFetch(options = {}) {
|
|
|
5335
5335
|
const providerId = options.providerId ?? "codex";
|
|
5336
5336
|
const upstreamFetch = options.fetch ?? fetch;
|
|
5337
5337
|
return (async (input, init) => {
|
|
5338
|
+
const request = await rewriteCodexRequest(input, init);
|
|
5338
5339
|
const auth = await resolveCodexAuth({
|
|
5339
5340
|
...options,
|
|
5340
5341
|
providerId,
|
|
@@ -5344,10 +5345,13 @@ function createCodexProviderFetch(options = {}) {
|
|
|
5344
5345
|
headers.delete("authorization");
|
|
5345
5346
|
headers.set("Authorization", `Bearer ${auth.accessToken}`);
|
|
5346
5347
|
if (auth.accountId) headers.set("ChatGPT-Account-Id", auth.accountId);
|
|
5347
|
-
|
|
5348
|
-
...init,
|
|
5348
|
+
const response = await upstreamFetch(request.input, {
|
|
5349
|
+
...request.init,
|
|
5349
5350
|
headers
|
|
5350
5351
|
});
|
|
5352
|
+
if (request.responseMode === "chat-json") return codexResponsesSseToChatJson(response);
|
|
5353
|
+
if (request.responseMode === "chat-sse") return codexResponsesSseToChatSse(response);
|
|
5354
|
+
return response;
|
|
5351
5355
|
});
|
|
5352
5356
|
}
|
|
5353
5357
|
function rewriteCodexRequestUrl(input) {
|
|
@@ -5360,6 +5364,193 @@ function rewriteCodexRequestUrl(input) {
|
|
|
5360
5364
|
}
|
|
5361
5365
|
return input;
|
|
5362
5366
|
}
|
|
5367
|
+
async function rewriteCodexRequest(input, init) {
|
|
5368
|
+
const rewrittenUrl = rewriteCodexRequestUrl(input);
|
|
5369
|
+
const body = await readJsonBody(init?.body);
|
|
5370
|
+
if (!isChatCompletionsBody(body)) return {
|
|
5371
|
+
input: rewrittenUrl,
|
|
5372
|
+
...init ? { init } : {}
|
|
5373
|
+
};
|
|
5374
|
+
const stream = body.stream === true;
|
|
5375
|
+
const codexBody = chatCompletionsBodyToCodexResponsesBody(body);
|
|
5376
|
+
const headers = new Headers(init?.headers);
|
|
5377
|
+
headers.set("Content-Type", "application/json");
|
|
5378
|
+
return {
|
|
5379
|
+
input: rewrittenUrl,
|
|
5380
|
+
init: {
|
|
5381
|
+
...init,
|
|
5382
|
+
headers,
|
|
5383
|
+
body: JSON.stringify(codexBody)
|
|
5384
|
+
},
|
|
5385
|
+
responseMode: stream ? "chat-sse" : "chat-json"
|
|
5386
|
+
};
|
|
5387
|
+
}
|
|
5388
|
+
function chatCompletionsBodyToCodexResponsesBody(body) {
|
|
5389
|
+
const instructions = body.messages.filter((message) => message.role === "system" || message.role === "developer").map((message) => messageContentToText(message.content)).filter((text) => text.trim().length > 0).join("\n\n");
|
|
5390
|
+
const input = body.messages.filter((message) => message.role !== "system" && message.role !== "developer").map(chatMessageToResponseInputItem).filter((item) => item !== void 0);
|
|
5391
|
+
return {
|
|
5392
|
+
model: body.model,
|
|
5393
|
+
instructions: instructions || "You are a helpful assistant.",
|
|
5394
|
+
input,
|
|
5395
|
+
store: false,
|
|
5396
|
+
stream: true,
|
|
5397
|
+
...typeof body.temperature === "number" ? { temperature: body.temperature } : {},
|
|
5398
|
+
...typeof body.top_p === "number" ? { top_p: body.top_p } : {},
|
|
5399
|
+
...typeof body.max_tokens === "number" ? { max_output_tokens: body.max_tokens } : {}
|
|
5400
|
+
};
|
|
5401
|
+
}
|
|
5402
|
+
function chatMessageToResponseInputItem(message) {
|
|
5403
|
+
const text = messageContentToText(message.content);
|
|
5404
|
+
if (!text.trim()) return;
|
|
5405
|
+
return {
|
|
5406
|
+
type: "message",
|
|
5407
|
+
role: message.role === "assistant" ? "assistant" : "user",
|
|
5408
|
+
content: [{
|
|
5409
|
+
type: message.role === "assistant" ? "output_text" : "input_text",
|
|
5410
|
+
text
|
|
5411
|
+
}]
|
|
5412
|
+
};
|
|
5413
|
+
}
|
|
5414
|
+
async function codexResponsesSseToChatJson(response) {
|
|
5415
|
+
if (!response.ok) return response;
|
|
5416
|
+
const parsed = parseCodexResponsesSse(await response.text());
|
|
5417
|
+
const headers = new Headers(response.headers);
|
|
5418
|
+
headers.set("Content-Type", "application/json");
|
|
5419
|
+
return new Response(JSON.stringify({
|
|
5420
|
+
id: parsed.id ?? "codex-response",
|
|
5421
|
+
object: "chat.completion",
|
|
5422
|
+
created: parsed.created ?? Math.floor(Date.now() / 1e3),
|
|
5423
|
+
model: parsed.model ?? "codex",
|
|
5424
|
+
choices: [{
|
|
5425
|
+
index: 0,
|
|
5426
|
+
finish_reason: "stop",
|
|
5427
|
+
message: {
|
|
5428
|
+
role: "assistant",
|
|
5429
|
+
content: parsed.text
|
|
5430
|
+
}
|
|
5431
|
+
}],
|
|
5432
|
+
...parsed.usage ? { usage: parsed.usage } : {}
|
|
5433
|
+
}), {
|
|
5434
|
+
status: response.status,
|
|
5435
|
+
statusText: response.statusText,
|
|
5436
|
+
headers
|
|
5437
|
+
});
|
|
5438
|
+
}
|
|
5439
|
+
async function codexResponsesSseToChatSse(response) {
|
|
5440
|
+
if (!response.ok) return response;
|
|
5441
|
+
const parsed = parseCodexResponsesSse(await response.text());
|
|
5442
|
+
const encoder = new TextEncoder();
|
|
5443
|
+
const id = parsed.id ?? "codex-response";
|
|
5444
|
+
const created = parsed.created ?? Math.floor(Date.now() / 1e3);
|
|
5445
|
+
const model = parsed.model ?? "codex";
|
|
5446
|
+
const chunks = [
|
|
5447
|
+
{
|
|
5448
|
+
id,
|
|
5449
|
+
object: "chat.completion.chunk",
|
|
5450
|
+
created,
|
|
5451
|
+
model,
|
|
5452
|
+
choices: [{
|
|
5453
|
+
index: 0,
|
|
5454
|
+
delta: { role: "assistant" },
|
|
5455
|
+
finish_reason: null
|
|
5456
|
+
}]
|
|
5457
|
+
},
|
|
5458
|
+
...(parsed.text.match(/[\s\S]{1,2048}/gu) ?? []).map((delta) => ({
|
|
5459
|
+
id,
|
|
5460
|
+
object: "chat.completion.chunk",
|
|
5461
|
+
created,
|
|
5462
|
+
model,
|
|
5463
|
+
choices: [{
|
|
5464
|
+
index: 0,
|
|
5465
|
+
delta: { content: delta },
|
|
5466
|
+
finish_reason: null
|
|
5467
|
+
}]
|
|
5468
|
+
})),
|
|
5469
|
+
{
|
|
5470
|
+
id,
|
|
5471
|
+
object: "chat.completion.chunk",
|
|
5472
|
+
created,
|
|
5473
|
+
model,
|
|
5474
|
+
choices: [{
|
|
5475
|
+
index: 0,
|
|
5476
|
+
delta: {},
|
|
5477
|
+
finish_reason: "stop"
|
|
5478
|
+
}],
|
|
5479
|
+
...parsed.usage ? { usage: parsed.usage } : {}
|
|
5480
|
+
}
|
|
5481
|
+
];
|
|
5482
|
+
const stream = new ReadableStream({ start(controller) {
|
|
5483
|
+
for (const chunk of chunks) controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
|
|
5484
|
+
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
|
|
5485
|
+
controller.close();
|
|
5486
|
+
} });
|
|
5487
|
+
const headers = new Headers(response.headers);
|
|
5488
|
+
headers.set("Content-Type", "text/event-stream");
|
|
5489
|
+
return new Response(stream, {
|
|
5490
|
+
status: response.status,
|
|
5491
|
+
statusText: response.statusText,
|
|
5492
|
+
headers
|
|
5493
|
+
});
|
|
5494
|
+
}
|
|
5495
|
+
function parseCodexResponsesSse(source) {
|
|
5496
|
+
let text = "";
|
|
5497
|
+
let response;
|
|
5498
|
+
for (const event of source.split(/\n\n/u)) {
|
|
5499
|
+
const dataLines = event.split(/\r?\n/u).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart());
|
|
5500
|
+
if (dataLines.length === 0) continue;
|
|
5501
|
+
const data = dataLines.join("\n");
|
|
5502
|
+
if (data === "[DONE]") continue;
|
|
5503
|
+
const parsed = safeJsonParse(data);
|
|
5504
|
+
if (!isPlainObject$1(parsed)) continue;
|
|
5505
|
+
if (parsed.type === "response.output_text.delta" && typeof parsed.delta === "string") text += parsed.delta;
|
|
5506
|
+
if (parsed.type === "response.completed" && isPlainObject$1(parsed.response)) response = parsed.response;
|
|
5507
|
+
}
|
|
5508
|
+
return {
|
|
5509
|
+
...typeof response?.id === "string" ? { id: response.id } : {},
|
|
5510
|
+
...typeof response?.created_at === "number" ? { created: response.created_at } : {},
|
|
5511
|
+
...typeof response?.model === "string" ? { model: response.model } : {},
|
|
5512
|
+
text,
|
|
5513
|
+
...normalizeCodexUsage(response?.usage)
|
|
5514
|
+
};
|
|
5515
|
+
}
|
|
5516
|
+
function normalizeCodexUsage(usage) {
|
|
5517
|
+
if (!isPlainObject$1(usage)) return {};
|
|
5518
|
+
const promptTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : void 0;
|
|
5519
|
+
const completionTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : void 0;
|
|
5520
|
+
const totalTokens = typeof usage.total_tokens === "number" ? usage.total_tokens : void 0;
|
|
5521
|
+
return { usage: {
|
|
5522
|
+
...promptTokens === void 0 ? {} : { prompt_tokens: promptTokens },
|
|
5523
|
+
...completionTokens === void 0 ? {} : { completion_tokens: completionTokens },
|
|
5524
|
+
...totalTokens === void 0 ? {} : { total_tokens: totalTokens }
|
|
5525
|
+
} };
|
|
5526
|
+
}
|
|
5527
|
+
async function readJsonBody(body) {
|
|
5528
|
+
if (typeof body !== "string") return;
|
|
5529
|
+
return safeJsonParse(body);
|
|
5530
|
+
}
|
|
5531
|
+
function safeJsonParse(source) {
|
|
5532
|
+
try {
|
|
5533
|
+
return JSON.parse(source);
|
|
5534
|
+
} catch {
|
|
5535
|
+
return;
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5538
|
+
function isChatCompletionsBody(value) {
|
|
5539
|
+
return isPlainObject$1(value) && typeof value.model === "string" && Array.isArray(value.messages) && value.messages.every((message) => isPlainObject$1(message) && typeof message.role === "string");
|
|
5540
|
+
}
|
|
5541
|
+
function messageContentToText(content) {
|
|
5542
|
+
if (typeof content === "string") return content;
|
|
5543
|
+
if (!Array.isArray(content)) return "";
|
|
5544
|
+
return content.map((part) => {
|
|
5545
|
+
if (!isPlainObject$1(part)) return "";
|
|
5546
|
+
if (typeof part.text === "string") return part.text;
|
|
5547
|
+
if (typeof part.content === "string") return part.content;
|
|
5548
|
+
return "";
|
|
5549
|
+
}).filter(Boolean).join("\n");
|
|
5550
|
+
}
|
|
5551
|
+
function isPlainObject$1(value) {
|
|
5552
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5553
|
+
}
|
|
5363
5554
|
async function resolveCodexAuth(options = {}) {
|
|
5364
5555
|
const providerId = options.providerId ?? "codex";
|
|
5365
5556
|
const record = (await readAuthStore({ path: options.authStorePath })).providers[providerId];
|
|
@@ -6197,7 +6388,8 @@ const openRouterProviderDefaults = {
|
|
|
6197
6388
|
};
|
|
6198
6389
|
const codexProviderDefaults = {
|
|
6199
6390
|
type: "openai-compatible",
|
|
6200
|
-
baseURL: CODEX_BACKEND_BASE_URL
|
|
6391
|
+
baseURL: CODEX_BACKEND_BASE_URL,
|
|
6392
|
+
toolProtocol: "text-json"
|
|
6201
6393
|
};
|
|
6202
6394
|
const codexStarterModelChoices = [
|
|
6203
6395
|
"codex/gpt-5.5",
|
|
@@ -15650,4 +15842,4 @@ function formatDryRunSyncStatus(status) {
|
|
|
15650
15842
|
//#endregion
|
|
15651
15843
|
export { runTopchesterCli as t };
|
|
15652
15844
|
|
|
15653
|
-
//# sourceMappingURL=cli-
|
|
15845
|
+
//# sourceMappingURL=cli-D1d-I3Fi.mjs.map
|