@openai-oauth/core 2.0.0-beta.3 → 2.0.0-beta.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/README.md +1 -7
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +1 -1
- package/dist/runtime.d.ts +4 -21
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +4 -24
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +1 -0
- package/package.json +7 -8
- package/dist/auth.d.ts +0 -34
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js +0 -256
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ const baseURL = transport.baseURL;
|
|
|
27
27
|
const fetch = transport.fetch;
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
The transport supports Responses,
|
|
30
|
+
The transport supports Responses, model discovery, image generation, and multipart image editing. Client adapters build higher-level interfaces such as Chat Completions on top.
|
|
31
31
|
|
|
32
32
|
Create an OAuth request:
|
|
33
33
|
|
|
@@ -39,18 +39,12 @@ const request = await createOpenAIOAuthRequest({
|
|
|
39
39
|
});
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
Node auth-file helpers are also exported for the CLI and `@openai-oauth/local`.
|
|
43
|
-
|
|
44
42
|
Core exports include:
|
|
45
43
|
|
|
46
44
|
- `createOpenAIOAuthTransport`
|
|
47
45
|
- `createOpenAIOAuthRequest`
|
|
48
|
-
- `createCodexOAuthClient`
|
|
49
46
|
- `exchangeOpenAIOAuthCode`
|
|
50
47
|
- `refreshOpenAIOAuthTokens`
|
|
51
|
-
- `loadAuthTokens`
|
|
52
|
-
- `saveAuthTokens`
|
|
53
|
-
- `resolveCodexAuthFilePath`
|
|
54
48
|
- `OpenAIOAuth`
|
|
55
49
|
- `OpenAIOAuthSession`
|
|
56
50
|
- `SessionStore`
|
package/dist/images.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../src/images.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../src/images.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,gBAAgB,CAAA;AAY9C,MAAM,MAAM,yBAAyB,GAAG;IACvC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACnB,CAAA;AAmLD,eAAO,MAAM,wBAAwB,GACpC,UAAU,MAAM,EAChB,SAAS,OAAO,EAChB,MAAM,QAAQ,GAAG,IAAI,GAAG,SAAS,KAC/B,OAAO,CAAC,yBAAyB,CA6CnC,CAAA"}
|
package/dist/images.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from "./utils.js";
|
|
1
2
|
export const CODEX_IMAGE_MODEL = "gpt-image-2";
|
|
2
3
|
const MAX_REFERENCE_IMAGES = 5;
|
|
3
4
|
const MAX_REFERENCE_IMAGE_BYTES = 50 * 1024 * 1024;
|
|
@@ -8,7 +9,6 @@ const unsupportedOptions = [
|
|
|
8
9
|
"output_format",
|
|
9
10
|
"partial_images",
|
|
10
11
|
];
|
|
11
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12
12
|
const errorResponse = (message) => Response.json({
|
|
13
13
|
error: {
|
|
14
14
|
message,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export type
|
|
2
|
-
export { loadAuthTokens, resolveAuthFileCandidates, resolveCodexAuthFilePath, saveAuthTokens, shouldRefreshAuthTokens, } from "./auth.js";
|
|
3
|
-
export { type CodexOAuthClient, type CodexOAuthRuntimeSettings, CodexResponsesState, type CodexResponsesStateOptions, type CodexResponsesStateSnapshot, collectCompletedResponseFromSse, createCodexOAuthClient, createCodexOAuthFetch, createOpenAIOAuthRequest, createOpenAIOAuthTransport, DEFAULT_CODEX_BASE_URL, DEFAULT_OPENAI_COMPATIBLE_BASE_URL, DEFAULT_OPENAI_OAUTH_CLIENT_ID, DEFAULT_OPENAI_OAUTH_ISSUER, DEFAULT_OPENAI_OAUTH_SCOPE, deriveAccountId, exchangeOpenAIOAuthCode, type FetchFunction, getDefaultCodexInstructions, iterateServerSentEvents, type NormalizeCodexResponsesBodyOptions, normalizeCodexResponsesBody, type OpenAIOAuth, type OpenAIOAuthRequest, type OpenAIOAuthRequestOptions, type OpenAIOAuthSession, type OpenAIOAuthTokenResponse, type OpenAIOAuthTransport, type OpenAIOAuthTransportOptions, parseJwtClaims, refreshOpenAIOAuthTokens, type SessionStore, usesServerReplayState, } from "./runtime.js";
|
|
1
|
+
export { createOpenAIOAuthRequest, createOpenAIOAuthTransport, DEFAULT_CODEX_BASE_URL, DEFAULT_OPENAI_COMPATIBLE_BASE_URL, DEFAULT_OPENAI_OAUTH_CLIENT_ID, DEFAULT_OPENAI_OAUTH_ISSUER, DEFAULT_OPENAI_OAUTH_SCOPE, deriveAccountId, deriveChatGptAccountIsFedRamp, exchangeOpenAIOAuthCode, type FetchFunction, type OpenAIOAuth, type OpenAIOAuthRequest, type OpenAIOAuthRequestOptions, type OpenAIOAuthSession, type OpenAIOAuthTokenResponse, type OpenAIOAuthTransport, type OpenAIOAuthTransportOptions, parseJwtClaims, refreshOpenAIOAuthTokens, type SessionStore, } from "./runtime.js";
|
|
4
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,kCAAkC,EAClC,8BAA8B,EAC9B,2BAA2B,EAC3B,0BAA0B,EAC1B,eAAe,EACf,6BAA6B,EAC7B,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,cAAc,EACd,wBAAwB,EACxB,KAAK,YAAY,GACjB,MAAM,cAAc,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { CodexResponsesState, collectCompletedResponseFromSse, createCodexOAuthClient, createCodexOAuthFetch, createOpenAIOAuthRequest, createOpenAIOAuthTransport, DEFAULT_CODEX_BASE_URL, DEFAULT_OPENAI_COMPATIBLE_BASE_URL, DEFAULT_OPENAI_OAUTH_CLIENT_ID, DEFAULT_OPENAI_OAUTH_ISSUER, DEFAULT_OPENAI_OAUTH_SCOPE, deriveAccountId, exchangeOpenAIOAuthCode, getDefaultCodexInstructions, iterateServerSentEvents, normalizeCodexResponsesBody, parseJwtClaims, refreshOpenAIOAuthTokens, usesServerReplayState, } from "./runtime.js";
|
|
1
|
+
export { createOpenAIOAuthRequest, createOpenAIOAuthTransport, DEFAULT_CODEX_BASE_URL, DEFAULT_OPENAI_COMPATIBLE_BASE_URL, DEFAULT_OPENAI_OAUTH_CLIENT_ID, DEFAULT_OPENAI_OAUTH_ISSUER, DEFAULT_OPENAI_OAUTH_SCOPE, deriveAccountId, deriveChatGptAccountIsFedRamp, exchangeOpenAIOAuthCode, parseJwtClaims, refreshOpenAIOAuthTokens, } from "./runtime.js";
|
package/dist/models.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,4BAA4B,YAAY,CAAA;AAKrD,KAAK,SAAS,GAAG,OAAO,KAAK,CAAA;AAE7B,MAAM,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,gCAAgC,GAAG;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG,gCAAgC,CAAA;AAE5E,MAAM,MAAM,uBAAuB,GAAG;IACrC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC5D,CAAA;AA8ED,eAAO,MAAM,yBAAyB,GACrC,UAAS,gCAAqC,KAC5C,OAAO,CAAC,MAAM,CA4ChB,CAAA;AAED,eAAO,MAAM,4BAA4B,QAAO,IAI/C,CAAA;AAED,eAAO,MAAM,sBAAsB,GAClC,QAAQ,uBAAuB,EAC/B,UAAS,6BAAkC,KACzC,OAAO,CAAC,cAAc,EAAE,CA8B1B,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,cAAc,KAAG,OAEK,CAAA"}
|
package/dist/models.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { isRecord } from "./utils.js";
|
|
1
2
|
export const DEFAULT_CODEX_CLIENT_VERSION = "0.144.1";
|
|
2
3
|
const CODEX_VERSION_CACHE_TTL_MS = 60 * 60 * 1000;
|
|
3
4
|
const CODEX_REGISTRY_URL = "https://registry.npmjs.org/@openai/codex/latest";
|
|
4
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
5
|
const normalizeVersion = (value) => {
|
|
6
6
|
if (typeof value !== "string") {
|
|
7
7
|
return undefined;
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { CodexResponsesState } from "./state.js";
|
|
2
|
-
export { collectCompletedResponseFromSse, iterateServerSentEvents, type ServerSentEvent, } from "./sse.js";
|
|
3
|
-
export { CodexResponsesState, type CodexResponsesStateOptions, type CodexResponsesStateSnapshot, } from "./state.js";
|
|
4
2
|
export declare const DEFAULT_CODEX_BASE_URL = "https://chatgpt.com/backend-api/codex";
|
|
5
3
|
export declare const DEFAULT_OPENAI_COMPATIBLE_BASE_URL = "https://openai-oauth.local/v1";
|
|
6
4
|
export declare const DEFAULT_OPENAI_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -20,7 +18,6 @@ export type OpenAIOAuthSessionInput = OpenAIOAuthSession | (() => Promise<OpenAI
|
|
|
20
18
|
export type OpenAIOAuth = {
|
|
21
19
|
kind: "openai-oauth";
|
|
22
20
|
getSession(): Promise<OpenAIOAuthSession | null>;
|
|
23
|
-
refreshSession(): Promise<OpenAIOAuthSession | null>;
|
|
24
21
|
baseURL?: string;
|
|
25
22
|
fetch?: FetchFunction;
|
|
26
23
|
headers?: Record<string, string>;
|
|
@@ -77,7 +74,7 @@ export type RefreshOpenAIOAuthTokensOptions = {
|
|
|
77
74
|
fetch?: FetchFunction;
|
|
78
75
|
signal?: AbortSignal;
|
|
79
76
|
};
|
|
80
|
-
|
|
77
|
+
type CodexOAuthRuntimeSettings = {
|
|
81
78
|
auth: OpenAIOAuthSessionInput;
|
|
82
79
|
baseURL?: string;
|
|
83
80
|
codexVersion?: string;
|
|
@@ -86,25 +83,12 @@ export type CodexOAuthRuntimeSettings = {
|
|
|
86
83
|
instructions?: string;
|
|
87
84
|
responsesState?: CodexResponsesState | false;
|
|
88
85
|
};
|
|
89
|
-
export type OpenAIOAuthTransportOptions = CodexOAuthRuntimeSettings & {
|
|
86
|
+
export type OpenAIOAuthTransportOptions = Omit<CodexOAuthRuntimeSettings, "responsesState"> & {
|
|
90
87
|
openAIBaseURL?: string;
|
|
88
|
+
responsesState?: false;
|
|
91
89
|
};
|
|
92
90
|
export type OpenAIOAuthTransport = {
|
|
93
91
|
kind: "openai-compatible";
|
|
94
|
-
provider: "chatgpt-codex";
|
|
95
|
-
baseURL: string;
|
|
96
|
-
fetch: FetchFunction;
|
|
97
|
-
request: (path: string, init?: RequestInit) => Promise<Response>;
|
|
98
|
-
capabilities: {
|
|
99
|
-
responses: true;
|
|
100
|
-
chatCompletions: true;
|
|
101
|
-
models: true;
|
|
102
|
-
streaming: true;
|
|
103
|
-
imageGeneration: true;
|
|
104
|
-
imageEditing: true;
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
export type CodexOAuthClient = {
|
|
108
92
|
baseURL: string;
|
|
109
93
|
fetch: FetchFunction;
|
|
110
94
|
request: (path: string, init?: RequestInit) => Promise<Response>;
|
|
@@ -122,7 +106,6 @@ export declare const exchangeOpenAIOAuthCode: (options: ExchangeOpenAIOAuthCodeO
|
|
|
122
106
|
export declare const refreshOpenAIOAuthTokens: (options: RefreshOpenAIOAuthTokensOptions) => Promise<OpenAIOAuthTokenResponse>;
|
|
123
107
|
export declare const getDefaultCodexInstructions: () => string;
|
|
124
108
|
export declare const normalizeCodexResponsesBody: (body: Record<string, unknown>, options?: NormalizeCodexResponsesBodyOptions) => Record<string, unknown>;
|
|
125
|
-
export declare const createCodexOAuthFetch: (settings: CodexOAuthRuntimeSettings) => FetchFunction;
|
|
126
|
-
export declare const createCodexOAuthClient: (settings: CodexOAuthRuntimeSettings) => CodexOAuthClient;
|
|
127
109
|
export declare const createOpenAIOAuthTransport: (settings: OpenAIOAuthTransportOptions) => OpenAIOAuthTransport;
|
|
110
|
+
export {};
|
|
128
111
|
//# sourceMappingURL=runtime.d.ts.map
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { withoutTrailingSlash } from "@ai-sdk/provider-utils";
|
|
2
1
|
import { CODEX_IMAGE_MODEL, prepareCodexImageRequest } from "./images.js";
|
|
3
2
|
import { fetchCodexModelCatalog, isPublicCodexModel, } from "./models.js";
|
|
4
|
-
import { CodexResponsesState } from "./state.js";
|
|
5
|
-
export { collectCompletedResponseFromSse, iterateServerSentEvents, } from "./sse.js";
|
|
6
|
-
export { CodexResponsesState, } from "./state.js";
|
|
7
3
|
import { collectCompletedResponseFromSse } from "./sse.js";
|
|
4
|
+
import { CodexResponsesState } from "./state.js";
|
|
5
|
+
import { isRecord } from "./utils.js";
|
|
8
6
|
export const DEFAULT_CODEX_BASE_URL = "https://chatgpt.com/backend-api/codex";
|
|
9
7
|
export const DEFAULT_OPENAI_COMPATIBLE_BASE_URL = "https://openai-oauth.local/v1";
|
|
10
8
|
export const DEFAULT_OPENAI_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -35,7 +33,7 @@ const createCodeChallenge = async (codeVerifier) => {
|
|
|
35
33
|
return bytesToBase64Url(new Uint8Array(digest));
|
|
36
34
|
};
|
|
37
35
|
const trimTrailingSlash = (value) => value.replace(/\/$/, "");
|
|
38
|
-
const
|
|
36
|
+
const withoutTrailingSlash = (value) => value?.replace(/\/$/, "");
|
|
39
37
|
export const usesServerReplayState = (value) => {
|
|
40
38
|
if (typeof value.previous_response_id === "string") {
|
|
41
39
|
return true;
|
|
@@ -572,7 +570,7 @@ const resolveAuth = async (source) => {
|
|
|
572
570
|
}
|
|
573
571
|
return auth;
|
|
574
572
|
};
|
|
575
|
-
|
|
573
|
+
const createCodexOAuthFetch = (settings) => {
|
|
576
574
|
const fetch = pickFetch(settings.fetch);
|
|
577
575
|
const baseURL = resolveBaseURL(settings.baseURL);
|
|
578
576
|
const responsesState = settings.responsesState === false
|
|
@@ -647,31 +645,13 @@ const resolveOpenAICompatibleUrl = (path, baseURL) => {
|
|
|
647
645
|
: path.replace(/^\//, "");
|
|
648
646
|
return new URL(normalizedPath, `${baseURL}/`).toString();
|
|
649
647
|
};
|
|
650
|
-
export const createCodexOAuthClient = (settings) => {
|
|
651
|
-
const baseURL = resolveBaseURL(settings.baseURL);
|
|
652
|
-
const fetch = createCodexOAuthFetch(settings);
|
|
653
|
-
return {
|
|
654
|
-
baseURL,
|
|
655
|
-
fetch,
|
|
656
|
-
request: (path, init) => fetch(new URL(path, `${baseURL}/`).toString(), init),
|
|
657
|
-
};
|
|
658
|
-
};
|
|
659
648
|
export const createOpenAIOAuthTransport = (settings) => {
|
|
660
649
|
const baseURL = resolveOpenAIBaseURL(settings.openAIBaseURL);
|
|
661
650
|
const fetch = createCodexOAuthFetch(settings);
|
|
662
651
|
return {
|
|
663
652
|
kind: "openai-compatible",
|
|
664
|
-
provider: "chatgpt-codex",
|
|
665
653
|
baseURL,
|
|
666
654
|
fetch,
|
|
667
655
|
request: (path, init) => fetch(resolveOpenAICompatibleUrl(path, baseURL), init),
|
|
668
|
-
capabilities: {
|
|
669
|
-
responses: true,
|
|
670
|
-
chatCompletions: true,
|
|
671
|
-
models: true,
|
|
672
|
-
streaming: true,
|
|
673
|
-
imageGeneration: true,
|
|
674
|
-
imageEditing: true,
|
|
675
|
-
},
|
|
676
656
|
};
|
|
677
657
|
};
|
package/dist/sse.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../src/sse.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../src/sse.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAwBD,wBAAuB,uBAAuB,CAC7C,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAChC,cAAc,CAAC,eAAe,CAAC,CAkCjC;AAoDD,eAAO,MAAM,+BAA+B,GAC3C,QAAQ,cAAc,CAAC,UAAU,CAAC,KAChC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmEjC,CAAA"}
|
package/dist/sse.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from "./utils.js";
|
|
1
2
|
const SSE_SEPARATOR = /\r?\n\r?\n/;
|
|
2
3
|
const parseEventBlock = (block) => {
|
|
3
4
|
const event = {};
|
|
@@ -48,7 +49,6 @@ export async function* iterateServerSentEvents(stream) {
|
|
|
48
49
|
reader.releaseLock();
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
52
52
|
const terminalServerSentEvents = new Set([
|
|
53
53
|
"error",
|
|
54
54
|
"response.completed",
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACJ,CAAA"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openai-oauth/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.4",
|
|
4
4
|
"description": "Core auth and in-memory OpenAI-compatible transport for openai-oauth.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openai",
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"transport"
|
|
11
11
|
],
|
|
12
12
|
"type": "module",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=20"
|
|
15
|
+
},
|
|
13
16
|
"sideEffects": false,
|
|
14
17
|
"main": "./dist/index.js",
|
|
15
18
|
"types": "./dist/index.d.ts",
|
|
@@ -26,7 +29,7 @@
|
|
|
26
29
|
"LICENSE"
|
|
27
30
|
],
|
|
28
31
|
"scripts": {
|
|
29
|
-
"build": "tsc -p tsconfig.build.json",
|
|
32
|
+
"build": "node ../../scripts/clean-dist.mjs && tsc -p tsconfig.build.json",
|
|
30
33
|
"prepublishOnly": "bun run build",
|
|
31
34
|
"typecheck": "tsc --noEmit",
|
|
32
35
|
"test": "vitest run"
|
|
@@ -34,13 +37,9 @@
|
|
|
34
37
|
"publishConfig": {
|
|
35
38
|
"access": "public"
|
|
36
39
|
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"@ai-sdk/provider-utils": "4.0.19"
|
|
39
|
-
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"vitest": "latest"
|
|
41
|
+
"typescript": "5.9.2",
|
|
42
|
+
"vitest": "4.1.10"
|
|
44
43
|
},
|
|
45
44
|
"author": "EvanZhouDev",
|
|
46
45
|
"license": "AGPL-3.0-only",
|
package/dist/auth.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { type FetchFunction, type OpenAIOAuthTokenResponse } from "./runtime.js";
|
|
2
|
-
export type EffectiveAuth = {
|
|
3
|
-
accessToken: string;
|
|
4
|
-
accountId: string;
|
|
5
|
-
isFedRamp?: boolean;
|
|
6
|
-
idToken?: string;
|
|
7
|
-
refreshToken?: string;
|
|
8
|
-
sourcePath?: string;
|
|
9
|
-
lastRefresh?: string;
|
|
10
|
-
};
|
|
11
|
-
export type AuthLoaderOptions = {
|
|
12
|
-
clientId?: string;
|
|
13
|
-
issuer?: string;
|
|
14
|
-
tokenUrl?: string;
|
|
15
|
-
authFilePath?: string;
|
|
16
|
-
fetch: FetchFunction;
|
|
17
|
-
ensureFresh?: boolean;
|
|
18
|
-
now?: () => Date;
|
|
19
|
-
};
|
|
20
|
-
export type SaveAuthTokensOptions = {
|
|
21
|
-
token: OpenAIOAuthTokenResponse;
|
|
22
|
-
authFilePath?: string;
|
|
23
|
-
now?: () => Date;
|
|
24
|
-
};
|
|
25
|
-
export type SavedAuthTokens = {
|
|
26
|
-
path: string;
|
|
27
|
-
auth: EffectiveAuth;
|
|
28
|
-
};
|
|
29
|
-
export declare const shouldRefreshAuthTokens: (auth: Pick<EffectiveAuth, "accessToken" | "lastRefresh">, now?: Date) => boolean;
|
|
30
|
-
export declare const resolveAuthFileCandidates: (authFilePath?: string) => string[];
|
|
31
|
-
export declare const resolveCodexAuthFilePath: (authFilePath?: string) => string;
|
|
32
|
-
export declare const saveAuthTokens: (options: SaveAuthTokensOptions) => Promise<SavedAuthTokens>;
|
|
33
|
-
export declare const loadAuthTokens: (options: AuthLoaderOptions) => Promise<EffectiveAuth>;
|
|
34
|
-
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAGA,OAAO,EAKN,KAAK,aAAa,EAClB,KAAK,wBAAwB,EAG7B,MAAM,cAAc,CAAA;AAwBrB,MAAM,MAAM,aAAa,GAAG;IAC3B,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,aAAa,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,KAAK,EAAE,wBAAwB,CAAA;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,aAAa,CAAA;CACnB,CAAA;AAmDD,eAAO,MAAM,uBAAuB,GACnC,MAAM,IAAI,CAAC,aAAa,EAAE,aAAa,GAAG,aAAa,CAAC,EACxD,MAAK,IAAiB,KACpB,OAA4E,CAAA;AAgB/E,eAAO,MAAM,yBAAyB,GAAI,eAAe,MAAM,KAAG,MAAM,EAmBvE,CAAA;AAsFD,eAAO,MAAM,wBAAwB,GAAI,eAAe,MAAM,KAAG,MAUhE,CAAA;AAED,eAAO,MAAM,cAAc,GAC1B,SAAS,qBAAqB,KAC5B,OAAO,CAAC,eAAe,CAwCzB,CAAA;AAsCD,eAAO,MAAM,cAAc,GAC1B,SAAS,iBAAiB,KACxB,OAAO,CAAC,aAAa,CA0FvB,CAAA"}
|
package/dist/auth.js
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { DEFAULT_OPENAI_OAUTH_CLIENT_ID, DEFAULT_OPENAI_OAUTH_ISSUER, deriveAccountId, deriveChatGptAccountIsFedRamp, parseJwtClaims, refreshOpenAIOAuthTokens, } from "./runtime.js";
|
|
5
|
-
const DEFAULT_AUTH_CLIENT_ID = process.env.CHATGPT_LOCAL_CLIENT_ID ?? DEFAULT_OPENAI_OAUTH_CLIENT_ID;
|
|
6
|
-
const DEFAULT_AUTH_ISSUER = process.env.CHATGPT_LOCAL_ISSUER ?? DEFAULT_OPENAI_OAUTH_ISSUER;
|
|
7
|
-
const AUTH_FILENAME = "auth.json";
|
|
8
|
-
const REFRESH_EXPIRY_MARGIN_MS = 5 * 60 * 1000;
|
|
9
|
-
const REFRESH_INTERVAL_MS = 55 * 60 * 1000;
|
|
10
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
|
-
const parseIsoDate = (value) => {
|
|
12
|
-
if (typeof value !== "string" || !value) {
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
|
-
const date = new Date(value);
|
|
16
|
-
return Number.isNaN(date.getTime()) ? undefined : date;
|
|
17
|
-
};
|
|
18
|
-
const shouldRefreshAccessToken = (accessToken, lastRefresh, now) => {
|
|
19
|
-
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
const claims = parseJwtClaims(accessToken);
|
|
23
|
-
const exp = claims && typeof claims.exp === "number" ? claims.exp : undefined;
|
|
24
|
-
if (typeof exp === "number") {
|
|
25
|
-
const expiryMs = exp * 1000;
|
|
26
|
-
if (expiryMs <= now.getTime() + REFRESH_EXPIRY_MARGIN_MS) {
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const refreshedAt = parseIsoDate(lastRefresh);
|
|
31
|
-
if (refreshedAt) {
|
|
32
|
-
return refreshedAt.getTime() <= now.getTime() - REFRESH_INTERVAL_MS;
|
|
33
|
-
}
|
|
34
|
-
return false;
|
|
35
|
-
};
|
|
36
|
-
export const shouldRefreshAuthTokens = (auth, now = new Date()) => shouldRefreshAccessToken(auth.accessToken, auth.lastRefresh, now);
|
|
37
|
-
const uniquePaths = (paths) => {
|
|
38
|
-
const seen = new Set();
|
|
39
|
-
const result = [];
|
|
40
|
-
for (const candidate of paths) {
|
|
41
|
-
if (!seen.has(candidate)) {
|
|
42
|
-
seen.add(candidate);
|
|
43
|
-
result.push(candidate);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return result;
|
|
47
|
-
};
|
|
48
|
-
export const resolveAuthFileCandidates = (authFilePath) => {
|
|
49
|
-
if (typeof authFilePath === "string" && authFilePath.length > 0) {
|
|
50
|
-
return [authFilePath];
|
|
51
|
-
}
|
|
52
|
-
const envHome = process.env.CHATGPT_LOCAL_HOME;
|
|
53
|
-
const codexHome = process.env.CODEX_HOME;
|
|
54
|
-
return uniquePaths([
|
|
55
|
-
authFilePath,
|
|
56
|
-
envHome ? path.join(envHome, AUTH_FILENAME) : undefined,
|
|
57
|
-
codexHome ? path.join(codexHome, AUTH_FILENAME) : undefined,
|
|
58
|
-
path.join(os.homedir(), ".chatgpt-local", AUTH_FILENAME),
|
|
59
|
-
path.join(os.homedir(), ".codex", AUTH_FILENAME),
|
|
60
|
-
].filter((value) => typeof value === "string" && value.length > 0));
|
|
61
|
-
};
|
|
62
|
-
const resolveWritePath = (preferred) => {
|
|
63
|
-
if (preferred) {
|
|
64
|
-
return preferred;
|
|
65
|
-
}
|
|
66
|
-
const envHome = process.env.CHATGPT_LOCAL_HOME ?? process.env.CODEX_HOME;
|
|
67
|
-
if (envHome) {
|
|
68
|
-
return path.join(envHome, AUTH_FILENAME);
|
|
69
|
-
}
|
|
70
|
-
return path.join(os.homedir(), ".chatgpt-local", AUTH_FILENAME);
|
|
71
|
-
};
|
|
72
|
-
const toAuthFile = (input) => {
|
|
73
|
-
const auth = { ...input };
|
|
74
|
-
const tokensValue = input.tokens;
|
|
75
|
-
if (typeof input.OPENAI_API_KEY === "string" && input.OPENAI_API_KEY) {
|
|
76
|
-
auth.OPENAI_API_KEY = input.OPENAI_API_KEY;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
delete auth.OPENAI_API_KEY;
|
|
80
|
-
}
|
|
81
|
-
if (isRecord(tokensValue) && Object.keys(tokensValue).length > 0) {
|
|
82
|
-
auth.tokens = {
|
|
83
|
-
id_token: typeof tokensValue.id_token === "string"
|
|
84
|
-
? tokensValue.id_token
|
|
85
|
-
: undefined,
|
|
86
|
-
access_token: typeof tokensValue.access_token === "string"
|
|
87
|
-
? tokensValue.access_token
|
|
88
|
-
: undefined,
|
|
89
|
-
refresh_token: typeof tokensValue.refresh_token === "string"
|
|
90
|
-
? tokensValue.refresh_token
|
|
91
|
-
: undefined,
|
|
92
|
-
account_id: typeof tokensValue.account_id === "string"
|
|
93
|
-
? tokensValue.account_id
|
|
94
|
-
: undefined,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
delete auth.tokens;
|
|
99
|
-
}
|
|
100
|
-
if (typeof input.last_refresh === "string" && input.last_refresh) {
|
|
101
|
-
auth.last_refresh = input.last_refresh;
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
delete auth.last_refresh;
|
|
105
|
-
}
|
|
106
|
-
return auth;
|
|
107
|
-
};
|
|
108
|
-
const readAuthFile = async (candidates) => {
|
|
109
|
-
for (const candidate of candidates) {
|
|
110
|
-
try {
|
|
111
|
-
const content = await fs.readFile(candidate, "utf-8");
|
|
112
|
-
const parsed = JSON.parse(content);
|
|
113
|
-
if (isRecord(parsed)) {
|
|
114
|
-
return { path: candidate, data: toAuthFile(parsed) };
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
catch { }
|
|
118
|
-
}
|
|
119
|
-
return {};
|
|
120
|
-
};
|
|
121
|
-
const ensureDirectory = async (filePath) => {
|
|
122
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
123
|
-
};
|
|
124
|
-
const writeAuthFile = async (filePath, data) => {
|
|
125
|
-
await ensureDirectory(filePath);
|
|
126
|
-
await fs.writeFile(filePath, JSON.stringify(data, null, 2), {
|
|
127
|
-
encoding: "utf-8",
|
|
128
|
-
mode: 0o600,
|
|
129
|
-
});
|
|
130
|
-
};
|
|
131
|
-
export const resolveCodexAuthFilePath = (authFilePath) => {
|
|
132
|
-
if (authFilePath) {
|
|
133
|
-
return authFilePath;
|
|
134
|
-
}
|
|
135
|
-
const codexHome = process.env.CODEX_HOME;
|
|
136
|
-
return path.join(codexHome ?? path.join(os.homedir(), ".codex"), AUTH_FILENAME);
|
|
137
|
-
};
|
|
138
|
-
export const saveAuthTokens = async (options) => {
|
|
139
|
-
const filePath = resolveCodexAuthFilePath(options.authFilePath);
|
|
140
|
-
const existing = (await readAuthFile([filePath])).data ?? {};
|
|
141
|
-
const now = options.now ?? (() => new Date());
|
|
142
|
-
const savedAt = now().toISOString();
|
|
143
|
-
const accountId = options.token.accountId ??
|
|
144
|
-
deriveAccountId(options.token.idToken) ??
|
|
145
|
-
deriveAccountId(options.token.accessToken);
|
|
146
|
-
if (!accountId) {
|
|
147
|
-
throw new Error("ChatGPT account id not found in OpenAI OAuth token response.");
|
|
148
|
-
}
|
|
149
|
-
await writeAuthFile(filePath, {
|
|
150
|
-
...existing,
|
|
151
|
-
auth_mode: "chatgpt",
|
|
152
|
-
tokens: {
|
|
153
|
-
id_token: options.token.idToken,
|
|
154
|
-
access_token: options.token.accessToken,
|
|
155
|
-
refresh_token: options.token.refreshToken,
|
|
156
|
-
account_id: accountId,
|
|
157
|
-
},
|
|
158
|
-
last_refresh: savedAt,
|
|
159
|
-
});
|
|
160
|
-
return {
|
|
161
|
-
path: filePath,
|
|
162
|
-
auth: {
|
|
163
|
-
accessToken: options.token.accessToken,
|
|
164
|
-
accountId,
|
|
165
|
-
isFedRamp: options.token.isFedRamp,
|
|
166
|
-
idToken: options.token.idToken,
|
|
167
|
-
refreshToken: options.token.refreshToken,
|
|
168
|
-
sourcePath: filePath,
|
|
169
|
-
lastRefresh: savedAt,
|
|
170
|
-
},
|
|
171
|
-
};
|
|
172
|
-
};
|
|
173
|
-
const refreshChatGptTokens = async (refreshToken, clientId, issuer, tokenUrl, fetchFn) => {
|
|
174
|
-
const refreshed = await refreshOpenAIOAuthTokens({
|
|
175
|
-
refreshToken,
|
|
176
|
-
clientId,
|
|
177
|
-
issuer,
|
|
178
|
-
tokenUrl,
|
|
179
|
-
fetch: fetchFn,
|
|
180
|
-
});
|
|
181
|
-
return {
|
|
182
|
-
accessToken: refreshed.accessToken,
|
|
183
|
-
idToken: refreshed.idToken,
|
|
184
|
-
refreshToken: refreshed.refreshToken ?? refreshToken,
|
|
185
|
-
accountId: refreshed.accountId,
|
|
186
|
-
isFedRamp: refreshed.isFedRamp,
|
|
187
|
-
};
|
|
188
|
-
};
|
|
189
|
-
const normalizeTokens = (tokens) => {
|
|
190
|
-
const maybeString = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
191
|
-
return {
|
|
192
|
-
id_token: maybeString(tokens?.id_token),
|
|
193
|
-
access_token: maybeString(tokens?.access_token),
|
|
194
|
-
refresh_token: maybeString(tokens?.refresh_token),
|
|
195
|
-
account_id: maybeString(tokens?.account_id),
|
|
196
|
-
};
|
|
197
|
-
};
|
|
198
|
-
export const loadAuthTokens = async (options) => {
|
|
199
|
-
const { clientId = DEFAULT_AUTH_CLIENT_ID, issuer = DEFAULT_AUTH_ISSUER, tokenUrl, authFilePath, fetch, ensureFresh = true, now = () => new Date(), } = options;
|
|
200
|
-
if (typeof fetch !== "function") {
|
|
201
|
-
throw new Error("A fetch implementation is required to refresh ChatGPT tokens.");
|
|
202
|
-
}
|
|
203
|
-
const readResult = await readAuthFile(resolveAuthFileCandidates(authFilePath));
|
|
204
|
-
const authData = readResult.data ?? {};
|
|
205
|
-
const tokens = normalizeTokens(authData.tokens);
|
|
206
|
-
let accessToken = tokens.access_token;
|
|
207
|
-
let idToken = tokens.id_token;
|
|
208
|
-
let refreshToken = tokens.refresh_token;
|
|
209
|
-
let accountId = tokens.account_id ?? deriveAccountId(idToken);
|
|
210
|
-
let isFedRamp = deriveChatGptAccountIsFedRamp(idToken) ||
|
|
211
|
-
deriveChatGptAccountIsFedRamp(accessToken);
|
|
212
|
-
let lastRefresh = authData.last_refresh;
|
|
213
|
-
const needsRefresh = ensureFresh &&
|
|
214
|
-
typeof refreshToken === "string" &&
|
|
215
|
-
shouldRefreshAccessToken(accessToken, lastRefresh, now());
|
|
216
|
-
if (needsRefresh && typeof refreshToken === "string") {
|
|
217
|
-
const refreshed = await refreshChatGptTokens(refreshToken, clientId, issuer, tokenUrl, fetch);
|
|
218
|
-
accessToken = refreshed.accessToken;
|
|
219
|
-
idToken = refreshed.idToken ?? idToken;
|
|
220
|
-
refreshToken = refreshed.refreshToken ?? refreshToken;
|
|
221
|
-
accountId = refreshed.accountId ?? accountId;
|
|
222
|
-
isFedRamp =
|
|
223
|
-
isFedRamp ||
|
|
224
|
-
refreshed.isFedRamp === true ||
|
|
225
|
-
deriveChatGptAccountIsFedRamp(idToken) ||
|
|
226
|
-
deriveChatGptAccountIsFedRamp(accessToken);
|
|
227
|
-
lastRefresh = now().toISOString();
|
|
228
|
-
const writePath = resolveWritePath(readResult.path ?? authFilePath);
|
|
229
|
-
await writeAuthFile(writePath, {
|
|
230
|
-
...authData,
|
|
231
|
-
auth_mode: "chatgpt",
|
|
232
|
-
tokens: {
|
|
233
|
-
id_token: idToken,
|
|
234
|
-
access_token: accessToken,
|
|
235
|
-
refresh_token: refreshToken,
|
|
236
|
-
account_id: accountId,
|
|
237
|
-
},
|
|
238
|
-
last_refresh: lastRefresh,
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
242
|
-
throw new Error("ChatGPT access token not found. Run `codex login` to create auth.json.");
|
|
243
|
-
}
|
|
244
|
-
if (typeof accountId !== "string" || accountId.length === 0) {
|
|
245
|
-
throw new Error("ChatGPT account id not found in auth.json. Run `codex login` to create auth.json.");
|
|
246
|
-
}
|
|
247
|
-
return {
|
|
248
|
-
accessToken,
|
|
249
|
-
accountId,
|
|
250
|
-
isFedRamp,
|
|
251
|
-
idToken,
|
|
252
|
-
refreshToken,
|
|
253
|
-
sourcePath: readResult.path ?? resolveWritePath(authFilePath),
|
|
254
|
-
lastRefresh,
|
|
255
|
-
};
|
|
256
|
-
};
|