xsai-codex 0.0.1 → 0.0.2

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 CHANGED
@@ -6,12 +6,15 @@ Requires Baseline 2025 [`Uint8Array.fromBase64`](https://developer.mozilla.org/e
6
6
 
7
7
  ## Usage
8
8
 
9
+ > For more examples, please refer to the [xsAI Docs](https://xsai.js.org/docs/packages-ext/responses).
10
+
9
11
  ```ts
10
12
  import { responses } from '@xsai-ext/responses'
11
13
  import { authorizeCodexHeadless, createCodex } from 'xsai-codex'
12
14
 
13
15
  const auth = await authorizeCodexHeadless({
14
16
  onUserCode: ({ instructions }) => {
17
+ // Open https://auth.openai.com/codex/device and enter code: XXXX-XXXXX
15
18
  console.log(instructions)
16
19
  },
17
20
  })
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ interface CodexAuthTokens {
10
10
  }
11
11
  interface CodexHeadlessAuthorizeOptions {
12
12
  onUserCode?: (info: CodexUserCodeInfo) => Promise<void> | void;
13
+ signal?: AbortSignal;
13
14
  }
14
15
  interface CodexUserCodeInfo {
15
16
  instructions: string;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var version = "0.0.1";
1
+ var version = "0.0.2";
2
2
 
3
3
  const CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
4
4
  const CODEX_ISSUER = "https://auth.openai.com";
@@ -9,15 +9,22 @@ const CODEX_DEVICE_URL = `${CODEX_ISSUER}/codex/device`;
9
9
  const CODEX_DEVICE_REDIRECT_URL = `${CODEX_ISSUER}/deviceauth/callback`;
10
10
  const CODEX_OAUTH_POLLING_SAFETY_MARGIN_MS = 3e3;
11
11
  const CODEX_TOKEN_REFRESH_MARGIN_MS = 6e4;
12
- const CODEX_DUMMY_API_KEY = "codex-oauth";
13
12
  const CODEX_DEFAULT_ORIGINATOR = "xsai-codex";
14
13
  const CODEX_DEFAULT_USER_AGENT = `xsai-codex/${version}`;
15
14
  const CODEX_BASE_URL = "https://chatgpt.com/backend-api/codex/";
16
15
 
17
- const sleep = async (ms) => (
18
- // eslint-disable-next-line @masknet/prefer-timer-id
19
- new Promise((resolve) => setTimeout(resolve, ms))
20
- );
16
+ const sleep = async (ms, signal) => {
17
+ if (signal?.aborted) {
18
+ throw signal.reason;
19
+ }
20
+ return new Promise((resolve, reject) => {
21
+ const timer = setTimeout(resolve, ms);
22
+ signal?.addEventListener("abort", () => {
23
+ clearTimeout(timer);
24
+ reject(signal.reason);
25
+ }, { once: true });
26
+ });
27
+ };
21
28
  const formatResponseError = async (message, response) => {
22
29
  const body = await response.text().catch(() => "");
23
30
  const details = body.trim().slice(0, 500);
@@ -55,12 +62,19 @@ const extractAccountId = (tokens) => {
55
62
  const claims = parseJwtClaims(tokens.access_token);
56
63
  return claims === void 0 ? void 0 : extractAccountIdFromClaims(claims);
57
64
  };
58
- const toCodexAuthTokens = (tokens, accountId = extractAccountId(tokens)) => ({
59
- access: tokens.access_token,
60
- expires: Date.now() + (tokens.expires_in ?? 3600) * 1e3,
61
- refresh: tokens.refresh_token,
62
- ...accountId !== void 0 && accountId.length > 0 && { accountId }
63
- });
65
+ const toCodexAuthTokens = (tokens, options = {}) => {
66
+ const accountId = options.accountId ?? extractAccountId(tokens);
67
+ const refresh = tokens.refresh_token ?? options.refreshToken;
68
+ if (refresh === void 0 || refresh.length === 0) {
69
+ throw new Error("Codex token response did not include a refresh token.");
70
+ }
71
+ return {
72
+ access: tokens.access_token,
73
+ ...accountId !== void 0 && accountId.length > 0 && { accountId },
74
+ expires: Date.now() + (tokens.expires_in ?? 3600) * 1e3,
75
+ refresh
76
+ };
77
+ };
64
78
  const refreshCodexAccessToken = async (refreshToken) => {
65
79
  const tokens = await jsonFetch(
66
80
  CODEX_TOKEN_URL,
@@ -75,7 +89,7 @@ const refreshCodexAccessToken = async (refreshToken) => {
75
89
  },
76
90
  "Codex token refresh failed"
77
91
  );
78
- return toCodexAuthTokens(tokens);
92
+ return toCodexAuthTokens(tokens, { refreshToken });
79
93
  };
80
94
  const authorizeCodexHeadless = async (options = {}) => {
81
95
  const deviceData = await jsonFetch(
@@ -86,7 +100,8 @@ const authorizeCodexHeadless = async (options = {}) => {
86
100
  "Content-Type": "application/json",
87
101
  "User-Agent": CODEX_DEFAULT_USER_AGENT
88
102
  },
89
- method: "POST"
103
+ method: "POST",
104
+ signal: options.signal
90
105
  },
91
106
  "Failed to initiate Codex device authorization"
92
107
  );
@@ -107,7 +122,8 @@ const authorizeCodexHeadless = async (options = {}) => {
107
122
  "Content-Type": "application/json",
108
123
  "User-Agent": CODEX_DEFAULT_USER_AGENT
109
124
  },
110
- method: "POST"
125
+ method: "POST",
126
+ signal: options.signal
111
127
  });
112
128
  if (response.ok) {
113
129
  const deviceToken = await response.json();
@@ -122,7 +138,8 @@ const authorizeCodexHeadless = async (options = {}) => {
122
138
  redirect_uri: CODEX_DEVICE_REDIRECT_URL
123
139
  }).toString(),
124
140
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
125
- method: "POST"
141
+ method: "POST",
142
+ signal: options.signal
126
143
  },
127
144
  "Codex token exchange failed"
128
145
  );
@@ -131,7 +148,7 @@ const authorizeCodexHeadless = async (options = {}) => {
131
148
  if (response.status !== 403 && response.status !== 404) {
132
149
  throw new Error(await formatResponseError("Codex device authorization failed", response));
133
150
  }
134
- await sleep(interval + CODEX_OAUTH_POLLING_SAFETY_MARGIN_MS);
151
+ await sleep(interval + CODEX_OAUTH_POLLING_SAFETY_MARGIN_MS, options.signal);
135
152
  }
136
153
  };
137
154
 
@@ -151,10 +168,9 @@ const createCodex = async (options) => {
151
168
  return async (model) => {
152
169
  const auth = await resolveAuth();
153
170
  return {
154
- apiKey: CODEX_DUMMY_API_KEY,
171
+ apiKey: auth.access,
155
172
  baseURL: CODEX_BASE_URL,
156
173
  headers: {
157
- "Authorization": `Bearer ${auth.access}`,
158
174
  ...auth.accountId !== void 0 && auth.accountId.length > 0 && { "ChatGPT-Account-Id": auth.accountId },
159
175
  "originator": options.originator ?? CODEX_DEFAULT_ORIGINATOR,
160
176
  "User-Agent": options.userAgent ?? CODEX_DEFAULT_USER_AGENT,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "xsai-codex",
3
3
  "type": "module",
4
- "version": "0.0.1",
4
+ "version": "0.0.2",
5
5
  "description": "OpenAI Codex provider for xsAI.",
6
6
  "author": "Moeru AI",
7
7
  "license": "MIT",