ai-zero-token 2.0.4 → 2.0.6
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 +26 -0
- package/README.md +23 -5
- package/README.zh-CN.md +24 -6
- package/admin-ui/dist/assets/StatCard-7TEzqn2i.js +1 -0
- package/admin-ui/dist/assets/accounts-bCDKXGg9.js +4 -0
- package/admin-ui/dist/assets/{docs-oNIugCIL.js → docs--eK_2fzC.js} +1 -1
- package/admin-ui/dist/assets/{image-bed-CQtIhjg_.js → image-bed-7wBZ1GhS.js} +1 -1
- package/admin-ui/dist/assets/index-C22_3Mxq.css +1 -0
- package/admin-ui/dist/assets/index-CdFYy5j6.js +10 -0
- package/admin-ui/dist/assets/{launch-B-2Zdz9m.js → launch-BiD1Khtg.js} +1 -1
- package/admin-ui/dist/assets/{logs-JFuSf56b.js → logs-BdoKDqh2.js} +1 -1
- package/admin-ui/dist/assets/{network-detect-SfvK6uhx.js → network-detect-BvKns5nQ.js} +1 -1
- package/admin-ui/dist/assets/overview-wm6M45fu.js +1 -0
- package/admin-ui/dist/assets/settings-DOOu7Kd8.js +5 -0
- package/admin-ui/dist/assets/{tester-ocpF053C.js → tester-NrARmlis.js} +1 -1
- package/admin-ui/dist/assets/usage-CdWRVMDV.js +1 -0
- package/admin-ui/dist/index.html +2 -2
- package/dist/core/context.js +3 -0
- package/dist/core/providers/http-client.js +247 -3
- package/dist/core/providers/openai-codex/chat.js +84 -23
- package/dist/core/providers/openai-codex/chatgpt-web-image.js +1404 -0
- package/dist/core/services/auth-service.js +64 -8
- package/dist/core/services/config-service.js +24 -5
- package/dist/core/services/image-service.js +31 -1
- package/dist/core/services/usage-service.js +349 -0
- package/dist/core/store/codex-auth-store.js +429 -4
- package/dist/core/store/settings-store.js +62 -26
- package/dist/core/store/state-paths.js +17 -1
- package/dist/server/app.js +1278 -119
- package/docs/API_USAGE.md +48 -1
- package/docs/DESKTOP_RELEASE.md +12 -1
- package/package.json +1 -1
- package/admin-ui/dist/assets/accounts-CTjk9c4F.js +0 -4
- package/admin-ui/dist/assets/index-By4r-wy3.css +0 -1
- package/admin-ui/dist/assets/index-rgcJgVAu.js +0 -10
- package/admin-ui/dist/assets/overview-X_WodIqE.js +0 -1
- package/admin-ui/dist/assets/settings-0eXUAvcm.js +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { DEFAULT_CODEX_MODEL } from "../../models/openai-codex-models.js";
|
|
3
|
-
import { requestText } from "../http-client.js";
|
|
3
|
+
import { requestStream, requestText } from "../http-client.js";
|
|
4
4
|
const CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
5
|
+
const CODEX_RESPONSES_COMPACT_URL = `${CODEX_RESPONSES_URL}/compact`;
|
|
5
6
|
const URL_KEY_RE = /(url|uri|href|download|preview|thumbnail|image|asset|file)/i;
|
|
6
7
|
const REFERENCE_KEY_RE = /(image|asset|file|media|blob|artifact|download|preview|thumbnail)/i;
|
|
7
8
|
const REFERENCE_VALUE_RE = /^(file|asset|image|img|media|blob)-[\w-]+$/i;
|
|
@@ -39,21 +40,65 @@ function parseOptionalText(value) {
|
|
|
39
40
|
function parseUpstreamErrorBody(body) {
|
|
40
41
|
try {
|
|
41
42
|
const parsed = JSON.parse(body);
|
|
42
|
-
const
|
|
43
|
-
if (!
|
|
43
|
+
const record = asRecord(parsed.error);
|
|
44
|
+
if (!record) {
|
|
44
45
|
return void 0;
|
|
45
46
|
}
|
|
46
|
-
const
|
|
47
|
+
const eligiblePromo = asRecord(record.eligible_promo);
|
|
47
48
|
return {
|
|
48
49
|
message: typeof record.message === "string" ? record.message : void 0,
|
|
49
50
|
type: typeof record.type === "string" ? record.type : void 0,
|
|
50
51
|
code: typeof record.code === "string" ? record.code : void 0,
|
|
51
|
-
param: typeof record.param === "string" || record.param === null ? record.param : void 0
|
|
52
|
+
param: typeof record.param === "string" || record.param === null ? record.param : void 0,
|
|
53
|
+
planType: typeof record.plan_type === "string" ? record.plan_type : void 0,
|
|
54
|
+
resetsAt: typeof record.resets_at === "number" && Number.isFinite(record.resets_at) ? record.resets_at : void 0,
|
|
55
|
+
resetsInSeconds: typeof record.resets_in_seconds === "number" && Number.isFinite(record.resets_in_seconds) ? record.resets_in_seconds : void 0,
|
|
56
|
+
promoCampaignId: typeof eligiblePromo?.campaign_id === "string" ? eligiblePromo.campaign_id : void 0,
|
|
57
|
+
promoMessage: typeof eligiblePromo?.message === "string" ? eligiblePromo.message : void 0
|
|
52
58
|
};
|
|
53
59
|
} catch {
|
|
54
60
|
return void 0;
|
|
55
61
|
}
|
|
56
62
|
}
|
|
63
|
+
function buildCodexRequestHeaders(profile) {
|
|
64
|
+
return {
|
|
65
|
+
Accept: "text/event-stream",
|
|
66
|
+
"Content-Type": "application/json",
|
|
67
|
+
Authorization: `Bearer ${profile.access}`,
|
|
68
|
+
"ChatGPT-Account-Id": profile.accountId,
|
|
69
|
+
"OpenAI-Beta": "responses=experimental",
|
|
70
|
+
Originator: "pi",
|
|
71
|
+
"User-Agent": "pi (bun demo)"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function createCodexUpstreamError(status, body, transport, quota, requestId) {
|
|
75
|
+
const upstreamError = parseUpstreamErrorBody(body);
|
|
76
|
+
const error = new Error(`\u8C03\u7528 Responses API \u5931\u8D25: HTTP ${status} via ${transport} ${body}`);
|
|
77
|
+
error.quota = quota ?? createUsageLimitQuotaSnapshot(status, upstreamError, requestId);
|
|
78
|
+
error.upstreamStatus = status;
|
|
79
|
+
error.upstreamErrorCode = upstreamError?.code;
|
|
80
|
+
error.upstreamErrorType = upstreamError?.type;
|
|
81
|
+
error.upstreamErrorMessage = upstreamError?.message;
|
|
82
|
+
return error;
|
|
83
|
+
}
|
|
84
|
+
function createUsageLimitQuotaSnapshot(status, upstreamError, requestId) {
|
|
85
|
+
const errorKind = `${upstreamError?.type ?? ""} ${upstreamError?.code ?? ""}`.toLowerCase();
|
|
86
|
+
if (status !== 429 && !errorKind.includes("usage_limit_reached")) {
|
|
87
|
+
return void 0;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
capturedAt: Date.now(),
|
|
91
|
+
sourceRequestId: requestId,
|
|
92
|
+
planType: upstreamError?.planType,
|
|
93
|
+
primaryUsedPercent: 100,
|
|
94
|
+
primaryResetAt: upstreamError?.resetsAt,
|
|
95
|
+
primaryResetAfterSeconds: upstreamError?.resetsInSeconds,
|
|
96
|
+
creditsHasCredits: false,
|
|
97
|
+
creditsBalance: "0",
|
|
98
|
+
promoCampaignId: upstreamError?.promoCampaignId,
|
|
99
|
+
promoMessage: upstreamError?.promoMessage
|
|
100
|
+
};
|
|
101
|
+
}
|
|
57
102
|
function extractCodexQuotaSnapshot(headers, requestId) {
|
|
58
103
|
const activeLimit = parseOptionalText(headers["x-codex-active-limit"]);
|
|
59
104
|
const planType = parseOptionalText(headers["x-codex-plan-type"]);
|
|
@@ -362,34 +407,50 @@ async function askOpenAICodex(params) {
|
|
|
362
407
|
const response = await requestText({
|
|
363
408
|
method: "POST",
|
|
364
409
|
url: CODEX_RESPONSES_URL,
|
|
365
|
-
headers:
|
|
366
|
-
Accept: "text/event-stream",
|
|
367
|
-
"Content-Type": "application/json",
|
|
368
|
-
Authorization: `Bearer ${params.profile.access}`,
|
|
369
|
-
"ChatGPT-Account-Id": params.profile.accountId,
|
|
370
|
-
"OpenAI-Beta": "responses=experimental",
|
|
371
|
-
Originator: "pi",
|
|
372
|
-
"User-Agent": "pi (bun demo)"
|
|
373
|
-
},
|
|
410
|
+
headers: buildCodexRequestHeaders(params.profile),
|
|
374
411
|
body: JSON.stringify(requestBody)
|
|
375
412
|
});
|
|
376
413
|
const quota = extractCodexQuotaSnapshot(response.headers, response.requestId);
|
|
377
414
|
if (response.status < 200 || response.status >= 300) {
|
|
378
|
-
|
|
379
|
-
const error = new Error(`\u8C03\u7528 Responses API \u5931\u8D25: HTTP ${response.status} via ${response.transport} ${response.body}`);
|
|
380
|
-
error.quota = quota;
|
|
381
|
-
error.upstreamStatus = response.status;
|
|
382
|
-
error.upstreamErrorCode = upstreamError?.code;
|
|
383
|
-
error.upstreamErrorType = upstreamError?.type;
|
|
384
|
-
error.upstreamErrorMessage = upstreamError?.message;
|
|
385
|
-
throw error;
|
|
415
|
+
throw createCodexUpstreamError(response.status, response.body, response.transport, quota, response.requestId);
|
|
386
416
|
}
|
|
387
417
|
return {
|
|
388
418
|
...extractCodexText(response.body, requestBody),
|
|
389
419
|
quota
|
|
390
420
|
};
|
|
391
421
|
}
|
|
422
|
+
async function streamOpenAICodex(params) {
|
|
423
|
+
const requestBody = params.passthroughBody ? { ...params.bodyOverride ?? {} } : {
|
|
424
|
+
...buildDefaultRequestBody(params),
|
|
425
|
+
...params.bodyOverride ?? {}
|
|
426
|
+
};
|
|
427
|
+
if (!params.passthroughBody && typeof requestBody.input === "undefined") {
|
|
428
|
+
throw new Error("Codex \u8BF7\u6C42\u7F3A\u5C11 input\u3002\u8BF7\u63D0\u4F9B prompt \u6216\u5728\u5B9E\u9A8C\u8BF7\u6C42\u4F53\u91CC\u663E\u5F0F\u4F20\u5165 input\u3002");
|
|
429
|
+
}
|
|
430
|
+
const response = await requestStream({
|
|
431
|
+
method: "POST",
|
|
432
|
+
url: params.endpoint === "responses/compact" ? CODEX_RESPONSES_COMPACT_URL : CODEX_RESPONSES_URL,
|
|
433
|
+
headers: buildCodexRequestHeaders(params.profile),
|
|
434
|
+
body: JSON.stringify(requestBody),
|
|
435
|
+
signal: params.signal
|
|
436
|
+
});
|
|
437
|
+
const headers = response.headers;
|
|
438
|
+
const requestId = headers["x-request-id"] ?? response.requestId;
|
|
439
|
+
const quota = extractCodexQuotaSnapshot(headers, requestId);
|
|
440
|
+
if (response.status < 200 || response.status >= 300) {
|
|
441
|
+
const body = await new Response(response.body).text();
|
|
442
|
+
throw createCodexUpstreamError(response.status, body, response.transport, quota, requestId);
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
body: response.body,
|
|
446
|
+
headers,
|
|
447
|
+
quota,
|
|
448
|
+
requestId,
|
|
449
|
+
status: response.status
|
|
450
|
+
};
|
|
451
|
+
}
|
|
392
452
|
export {
|
|
393
453
|
askOpenAICodex,
|
|
394
|
-
extractCodexQuotaSnapshot
|
|
454
|
+
extractCodexQuotaSnapshot,
|
|
455
|
+
streamOpenAICodex
|
|
395
456
|
};
|