ai-zero-token 2.0.9 → 2.0.10

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.
@@ -19,6 +19,9 @@ import { createGatewayContext } from "../core/context.js";
19
19
  import { isTransientHttpError, requestText } from "../core/providers/http-client.js";
20
20
  import { streamOpenAICodex } from "../core/providers/openai-codex/chat.js";
21
21
  import { generateChatGPTWebImage } from "../core/providers/openai-codex/chatgpt-web-image.js";
22
+ import {
23
+ startOpenAICodexLogin
24
+ } from "../core/providers/openai-codex/oauth.js";
22
25
  const packageRoot = path.dirname(fileURLToPath(new URL("../../package.json", import.meta.url)));
23
26
  const adminUiDistDir = path.join(packageRoot, "admin-ui", "dist");
24
27
  const adminUiIndexPath = path.join(adminUiDistDir, "index.html");
@@ -187,6 +190,13 @@ const profileImportSchema = z.object({
187
190
  const runtimeRefreshSchema = z.object({
188
191
  staleOnly: z.boolean().optional()
189
192
  });
193
+ const oauthManualSchema = z.object({
194
+ loginId: z.string().min(1),
195
+ input: z.string().min(1)
196
+ });
197
+ const oauthCancelSchema = z.object({
198
+ loginId: z.string().min(1)
199
+ });
190
200
  const profileExportSchema = z.object({
191
201
  profileId: z.string().min(1).optional(),
192
202
  profileIds: z.array(z.string().min(1)).optional(),
@@ -1397,6 +1407,20 @@ function createApp(params) {
1397
1407
  const ctx = createGatewayContext();
1398
1408
  const gatewayRequestLogs = [];
1399
1409
  const codexResponseProfileBindings = /* @__PURE__ */ new Map();
1410
+ let pendingOAuthLogin = null;
1411
+ function clearPendingOAuthLogin(loginId) {
1412
+ if (!pendingOAuthLogin || loginId && pendingOAuthLogin.id !== loginId) {
1413
+ return;
1414
+ }
1415
+ pendingOAuthLogin.session.close();
1416
+ pendingOAuthLogin = null;
1417
+ }
1418
+ async function saveCompletedOAuthLogin(profile) {
1419
+ await ctx.authService.saveLoggedInProfile(profile);
1420
+ await ctx.authService.syncActiveProfileQuota("openai-codex", {
1421
+ suppressErrors: true
1422
+ });
1423
+ }
1400
1424
  function rememberCodexResponseProfile(responseId, profile) {
1401
1425
  codexResponseProfileBindings.set(responseId, {
1402
1426
  profileId: profile.profileId,
@@ -1645,10 +1669,66 @@ function createApp(params) {
1645
1669
  };
1646
1670
  });
1647
1671
  app.post("/_gateway/admin/login", async (request) => {
1648
- await ctx.authService.login("openai-codex");
1649
- await ctx.authService.syncActiveProfileQuota("openai-codex", {
1650
- suppressErrors: true
1651
- });
1672
+ clearPendingOAuthLogin();
1673
+ const session = await startOpenAICodexLogin();
1674
+ const loginId = randomUUID();
1675
+ pendingOAuthLogin = {
1676
+ id: loginId,
1677
+ session,
1678
+ createdAt: Date.now()
1679
+ };
1680
+ const code = await session.waitForCode(6e4);
1681
+ if (!code) {
1682
+ return {
1683
+ login: {
1684
+ status: "manual_required",
1685
+ loginId,
1686
+ message: "60 \u79D2\u5185\u6CA1\u6709\u6536\u5230 OAuth \u81EA\u52A8\u56DE\u8C03\u3002\u53EF\u4EE5\u7C98\u8D34\u6D4F\u89C8\u5668\u5730\u5740\u680F\u91CC\u7684\u5B8C\u6574\u56DE\u8C03 URL \u6216 authorization code \u7EE7\u7EED\u767B\u5F55\u3002"
1687
+ },
1688
+ config: await buildAdminConfig(request)
1689
+ };
1690
+ }
1691
+ try {
1692
+ const profile = await session.completeWithCode(code);
1693
+ await saveCompletedOAuthLogin(profile);
1694
+ return buildAdminConfig(request);
1695
+ } finally {
1696
+ clearPendingOAuthLogin(loginId);
1697
+ }
1698
+ });
1699
+ app.post("/_gateway/admin/login/manual", async (request, reply) => {
1700
+ const parsed = oauthManualSchema.safeParse(request.body);
1701
+ if (!parsed.success) {
1702
+ reply.code(400);
1703
+ return {
1704
+ error: {
1705
+ type: "validation_error",
1706
+ message: parsed.error.issues[0]?.message ?? "\u8BF7\u6C42\u4F53\u683C\u5F0F\u9519\u8BEF"
1707
+ }
1708
+ };
1709
+ }
1710
+ if (!pendingOAuthLogin || pendingOAuthLogin.id !== parsed.data.loginId) {
1711
+ reply.code(404);
1712
+ return {
1713
+ error: {
1714
+ type: "oauth_login_not_found",
1715
+ message: "\u6CA1\u6709\u627E\u5230\u7B49\u5F85\u4E2D\u7684 OAuth \u767B\u5F55\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u767B\u5F55\u3002"
1716
+ }
1717
+ };
1718
+ }
1719
+ try {
1720
+ const profile = await pendingOAuthLogin.session.completeWithInput(parsed.data.input);
1721
+ await saveCompletedOAuthLogin(profile);
1722
+ return buildAdminConfig(request);
1723
+ } finally {
1724
+ clearPendingOAuthLogin(parsed.data.loginId);
1725
+ }
1726
+ });
1727
+ app.post("/_gateway/admin/login/cancel", async (request) => {
1728
+ const parsed = oauthCancelSchema.safeParse(request.body);
1729
+ if (parsed.success) {
1730
+ clearPendingOAuthLogin(parsed.data.loginId);
1731
+ }
1652
1732
  return buildAdminConfig(request);
1653
1733
  });
1654
1734
  app.post("/_gateway/admin/logout", async (request) => {
@@ -2,6 +2,15 @@
2
2
 
3
3
  This project ships the desktop app with Electron. The desktop main process starts the existing local Fastify gateway and loads the React management UI served by that gateway.
4
4
 
5
+ ## 2.0.10 Release Notes
6
+
7
+ Version `2.0.10` improves OAuth login recovery and Codex auth freshness:
8
+
9
+ - Desktop OAuth login can continue with a pasted callback URL or authorization code when automatic callback capture times out.
10
+ - The local OAuth callback listener binds both IPv4 and IPv6 loopback addresses for browser redirect compatibility.
11
+ - Applying an account to local Codex refreshes the profile first so the written `auth.json` includes a current `id_token`.
12
+ - Saved `id_token` values are checked for expiry and account identity before use.
13
+
5
14
  ## 2.0.9 Release Notes
6
15
 
7
16
  Version `2.0.9` clarifies automatic account rotation eligibility and tightens Codex auth refresh handling:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-zero-token",
3
- "version": "2.0.9",
3
+ "version": "2.0.10",
4
4
  "description": "Local-first OpenAI-compatible AI CLI and gateway with Codex OAuth, multi-account management, and gpt-image-2 image generation/editing.",
5
5
  "license": "MIT",
6
6
  "author": "AI Zero Token Contributors",