opencode-codex-auth-rotation 1.0.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/LICENSE +37 -0
- package/README.md +170 -0
- package/assets/codex-auth.schema.json +26 -0
- package/assets/opencode-logo-ornate-dark.svg +18 -0
- package/assets/readme-hero.svg +31 -0
- package/config/README.md +103 -0
- package/config/minimal-opencode.json +12 -0
- package/config/opencode-legacy.json +571 -0
- package/config/opencode-modern.json +239 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +299 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth/auth.d.ts +43 -0
- package/dist/lib/auth/auth.d.ts.map +1 -0
- package/dist/lib/auth/auth.js +163 -0
- package/dist/lib/auth/auth.js.map +1 -0
- package/dist/lib/auth/browser.d.ts +17 -0
- package/dist/lib/auth/browser.d.ts.map +1 -0
- package/dist/lib/auth/browser.js +76 -0
- package/dist/lib/auth/browser.js.map +1 -0
- package/dist/lib/auth/server.d.ts +10 -0
- package/dist/lib/auth/server.d.ts.map +1 -0
- package/dist/lib/auth/server.js +78 -0
- package/dist/lib/auth/server.js.map +1 -0
- package/dist/lib/config.d.ts +33 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +84 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +67 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +67 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/logger.d.ts +21 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +77 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/oauth-success.html +712 -0
- package/dist/lib/prompts/codex-opencode-bridge.d.ts +19 -0
- package/dist/lib/prompts/codex-opencode-bridge.d.ts.map +1 -0
- package/dist/lib/prompts/codex-opencode-bridge.js +152 -0
- package/dist/lib/prompts/codex-opencode-bridge.js.map +1 -0
- package/dist/lib/prompts/codex.d.ts +27 -0
- package/dist/lib/prompts/codex.d.ts.map +1 -0
- package/dist/lib/prompts/codex.js +241 -0
- package/dist/lib/prompts/codex.js.map +1 -0
- package/dist/lib/prompts/opencode-codex.d.ts +21 -0
- package/dist/lib/prompts/opencode-codex.d.ts.map +1 -0
- package/dist/lib/prompts/opencode-codex.js +91 -0
- package/dist/lib/prompts/opencode-codex.js.map +1 -0
- package/dist/lib/request/fetch-helpers.d.ts +73 -0
- package/dist/lib/request/fetch-helpers.d.ts.map +1 -0
- package/dist/lib/request/fetch-helpers.js +221 -0
- package/dist/lib/request/fetch-helpers.js.map +1 -0
- package/dist/lib/request/helpers/input-utils.d.ts +6 -0
- package/dist/lib/request/helpers/input-utils.d.ts.map +1 -0
- package/dist/lib/request/helpers/input-utils.js +174 -0
- package/dist/lib/request/helpers/input-utils.js.map +1 -0
- package/dist/lib/request/helpers/model-map.d.ts +28 -0
- package/dist/lib/request/helpers/model-map.d.ts.map +1 -0
- package/dist/lib/request/helpers/model-map.js +109 -0
- package/dist/lib/request/helpers/model-map.js.map +1 -0
- package/dist/lib/request/request-transformer.d.ts +93 -0
- package/dist/lib/request/request-transformer.d.ts.map +1 -0
- package/dist/lib/request/request-transformer.js +403 -0
- package/dist/lib/request/request-transformer.js.map +1 -0
- package/dist/lib/request/response-handler.d.ts +14 -0
- package/dist/lib/request/response-handler.d.ts.map +1 -0
- package/dist/lib/request/response-handler.js +88 -0
- package/dist/lib/request/response-handler.js.map +1 -0
- package/dist/lib/types.d.ts +184 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/src/plugin/accounts.d.ts +21 -0
- package/dist/src/plugin/accounts.d.ts.map +1 -0
- package/dist/src/plugin/accounts.js +53 -0
- package/dist/src/plugin/accounts.js.map +1 -0
- package/dist/src/plugin/config/schema.d.ts +38 -0
- package/dist/src/plugin/config/schema.d.ts.map +1 -0
- package/dist/src/plugin/config/schema.js +32 -0
- package/dist/src/plugin/config/schema.js.map +1 -0
- package/dist/src/plugin/storage.d.ts +15 -0
- package/dist/src/plugin/storage.d.ts.map +1 -0
- package/dist/src/plugin/storage.js +38 -0
- package/dist/src/plugin/storage.js.map +1 -0
- package/dist/src/plugin/usage.d.ts +9 -0
- package/dist/src/plugin/usage.d.ts.map +1 -0
- package/dist/src/plugin/usage.js +76 -0
- package/dist/src/plugin/usage.js.map +1 -0
- package/package.json +74 -0
- package/scripts/check-usage.ts +92 -0
- package/scripts/install-opencode-codex-auth.js +430 -0
- package/scripts/test-all-models.sh +259 -0
- package/scripts/validate-model-map.sh +97 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import type { Auth, Provider, Model } from "@opencode-ai/sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Account selection strategy
|
|
4
|
+
*/
|
|
5
|
+
export type AccountSelectionStrategy = "sticky" | "round-robin";
|
|
6
|
+
/**
|
|
7
|
+
* Plugin configuration from ~/.opencode/openai-codex-auth-config.json
|
|
8
|
+
*/
|
|
9
|
+
export interface PluginConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Enable CODEX_MODE (Codex-OpenCode bridge prompt instead of tool remap)
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
codexMode?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Account selection strategy
|
|
17
|
+
* - sticky: Stay with current account until rate-limited
|
|
18
|
+
* - round-robin: Rotate through accounts based on usage
|
|
19
|
+
* @default "sticky"
|
|
20
|
+
*/
|
|
21
|
+
strategy?: AccountSelectionStrategy;
|
|
22
|
+
/**
|
|
23
|
+
* Enable PID-based offset for initial account selection
|
|
24
|
+
* Distributes starting accounts across parallel processes
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
pidOffset?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* User configuration structure from opencode.json
|
|
31
|
+
*/
|
|
32
|
+
export interface UserConfig {
|
|
33
|
+
global: ConfigOptions;
|
|
34
|
+
models: {
|
|
35
|
+
[modelName: string]: {
|
|
36
|
+
options?: ConfigOptions;
|
|
37
|
+
variants?: Record<string, (ConfigOptions & {
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
}) | undefined>;
|
|
40
|
+
[key: string]: unknown;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Configuration options for reasoning and text settings
|
|
46
|
+
*/
|
|
47
|
+
export interface ConfigOptions {
|
|
48
|
+
reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
49
|
+
reasoningSummary?: "auto" | "concise" | "detailed" | "off" | "on";
|
|
50
|
+
textVerbosity?: "low" | "medium" | "high";
|
|
51
|
+
include?: string[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Reasoning configuration for requests
|
|
55
|
+
*/
|
|
56
|
+
export interface ReasoningConfig {
|
|
57
|
+
effort: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
58
|
+
summary: "auto" | "concise" | "detailed" | "off" | "on";
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* OAuth server information
|
|
62
|
+
*/
|
|
63
|
+
export interface OAuthServerInfo {
|
|
64
|
+
port: number;
|
|
65
|
+
ready: boolean;
|
|
66
|
+
close: () => void;
|
|
67
|
+
waitForCode: (state: string) => Promise<{
|
|
68
|
+
code: string;
|
|
69
|
+
} | null>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* PKCE challenge and verifier
|
|
73
|
+
*/
|
|
74
|
+
export interface PKCEPair {
|
|
75
|
+
challenge: string;
|
|
76
|
+
verifier: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Authorization flow result
|
|
80
|
+
*/
|
|
81
|
+
export interface AuthorizationFlow {
|
|
82
|
+
pkce: PKCEPair;
|
|
83
|
+
state: string;
|
|
84
|
+
url: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Token exchange success result
|
|
88
|
+
*/
|
|
89
|
+
export interface TokenSuccess {
|
|
90
|
+
type: "success";
|
|
91
|
+
access: string;
|
|
92
|
+
refresh: string;
|
|
93
|
+
expires: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Token exchange failure result
|
|
97
|
+
*/
|
|
98
|
+
export interface TokenFailure {
|
|
99
|
+
type: "failed";
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Token exchange result
|
|
103
|
+
*/
|
|
104
|
+
export type TokenResult = TokenSuccess | TokenFailure;
|
|
105
|
+
/**
|
|
106
|
+
* Parsed authorization input
|
|
107
|
+
*/
|
|
108
|
+
export interface ParsedAuthInput {
|
|
109
|
+
code?: string;
|
|
110
|
+
state?: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* JWT payload with ChatGPT account info
|
|
114
|
+
*/
|
|
115
|
+
export interface JWTPayload {
|
|
116
|
+
"https://api.openai.com/auth"?: {
|
|
117
|
+
chatgpt_account_id?: string;
|
|
118
|
+
};
|
|
119
|
+
[key: string]: unknown;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Message input item
|
|
123
|
+
*/
|
|
124
|
+
export interface InputItem {
|
|
125
|
+
id?: string;
|
|
126
|
+
type: string;
|
|
127
|
+
role: string;
|
|
128
|
+
content?: unknown;
|
|
129
|
+
[key: string]: unknown;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Request body structure
|
|
133
|
+
*/
|
|
134
|
+
export interface RequestBody {
|
|
135
|
+
model: string;
|
|
136
|
+
store?: boolean;
|
|
137
|
+
stream?: boolean;
|
|
138
|
+
instructions?: string;
|
|
139
|
+
input?: InputItem[];
|
|
140
|
+
tools?: unknown;
|
|
141
|
+
reasoning?: Partial<ReasoningConfig>;
|
|
142
|
+
text?: {
|
|
143
|
+
verbosity?: "low" | "medium" | "high";
|
|
144
|
+
};
|
|
145
|
+
include?: string[];
|
|
146
|
+
providerOptions?: {
|
|
147
|
+
openai?: Partial<ConfigOptions> & {
|
|
148
|
+
store?: boolean;
|
|
149
|
+
include?: string[];
|
|
150
|
+
};
|
|
151
|
+
[key: string]: unknown;
|
|
152
|
+
};
|
|
153
|
+
/** Stable key to enable prompt-token caching on Codex backend */
|
|
154
|
+
prompt_cache_key?: string;
|
|
155
|
+
max_output_tokens?: number;
|
|
156
|
+
max_completion_tokens?: number;
|
|
157
|
+
[key: string]: unknown;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* SSE event data structure
|
|
161
|
+
*/
|
|
162
|
+
export interface SSEEventData {
|
|
163
|
+
type: string;
|
|
164
|
+
response?: unknown;
|
|
165
|
+
[key: string]: unknown;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Cache metadata for Codex instructions
|
|
169
|
+
*/
|
|
170
|
+
export interface CacheMetadata {
|
|
171
|
+
etag: string | null;
|
|
172
|
+
tag: string;
|
|
173
|
+
lastChecked: number;
|
|
174
|
+
url: string;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* GitHub release data
|
|
178
|
+
*/
|
|
179
|
+
export interface GitHubRelease {
|
|
180
|
+
tag_name: string;
|
|
181
|
+
[key: string]: unknown;
|
|
182
|
+
}
|
|
183
|
+
export type { Auth, Provider, Model };
|
|
184
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../lib/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../lib/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface CodexAccount {
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
accessToken: string;
|
|
5
|
+
refreshToken: string;
|
|
6
|
+
chatgptAccountId: string;
|
|
7
|
+
rateLimitResetTime?: number;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare class AccountManager {
|
|
11
|
+
private accounts;
|
|
12
|
+
private currentIndex;
|
|
13
|
+
addAccount(account: CodexAccount): void;
|
|
14
|
+
getAccount(id: string): CodexAccount | undefined;
|
|
15
|
+
getCurrentAccount(): CodexAccount | null;
|
|
16
|
+
rotateAccount(): void;
|
|
17
|
+
getAccountCount(): number;
|
|
18
|
+
updateRateLimitResetTime(accountId: string, resetTime: number): void;
|
|
19
|
+
private getAvailableAccounts;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=accounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../src/plugin/accounts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,YAAY,CAAK;IAEzB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IASvC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIhD,iBAAiB,IAAI,YAAY,GAAG,IAAI;IAYxC,aAAa,IAAI,IAAI;IASrB,eAAe,IAAI,MAAM;IAIzB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAOpE,OAAO,CAAC,oBAAoB;CAY5B"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export class AccountManager {
|
|
2
|
+
accounts = [];
|
|
3
|
+
currentIndex = 0;
|
|
4
|
+
addAccount(account) {
|
|
5
|
+
const existingIndex = this.accounts.findIndex(acc => acc.id === account.id);
|
|
6
|
+
if (existingIndex >= 0) {
|
|
7
|
+
this.accounts[existingIndex] = account;
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
this.accounts.push(account);
|
|
11
|
+
}
|
|
12
|
+
getAccount(id) {
|
|
13
|
+
return this.accounts.find(acc => acc.id === id);
|
|
14
|
+
}
|
|
15
|
+
getCurrentAccount() {
|
|
16
|
+
const available = this.getAvailableAccounts();
|
|
17
|
+
if (available.length === 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const validIndex = this.currentIndex % available.length;
|
|
21
|
+
const currentId = available[validIndex]?.id;
|
|
22
|
+
return this.accounts.find(acc => acc.id === currentId) ?? null;
|
|
23
|
+
}
|
|
24
|
+
rotateAccount() {
|
|
25
|
+
const available = this.getAvailableAccounts();
|
|
26
|
+
if (available.length <= 1) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.currentIndex = (this.currentIndex + 1) % available.length;
|
|
30
|
+
}
|
|
31
|
+
getAccountCount() {
|
|
32
|
+
return this.getAvailableAccounts().length;
|
|
33
|
+
}
|
|
34
|
+
updateRateLimitResetTime(accountId, resetTime) {
|
|
35
|
+
const account = this.getAccount(accountId);
|
|
36
|
+
if (account) {
|
|
37
|
+
account.rateLimitResetTime = resetTime;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
getAvailableAccounts() {
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
return this.accounts.filter(acc => {
|
|
43
|
+
if (!acc.enabled) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (acc.rateLimitResetTime && acc.rateLimitResetTime > now) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=accounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../src/plugin/accounts.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,cAAc;IAClB,QAAQ,GAAmB,EAAE,CAAC;IAC9B,YAAY,GAAG,CAAC,CAAC;IAEzB,UAAU,CAAC,OAAqB;QAC/B,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC;YACvC,OAAO;QACR,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,UAAU,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,iBAAiB;QAChB,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC;QACxD,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;QAE5C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,SAAS,CAAC,IAAI,IAAI,CAAC;IAChE,CAAC;IAED,aAAa;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9C,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO;QACR,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;IAChE,CAAC;IAED,eAAe;QACd,OAAO,IAAI,CAAC,oBAAoB,EAAE,CAAC,MAAM,CAAC;IAC3C,CAAC;IAED,wBAAwB,CAAC,SAAiB,EAAE,SAAiB;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;QACxC,CAAC;IACF,CAAC;IAEO,oBAAoB;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACjC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO,KAAK,CAAC;YACd,CAAC;YACD,IAAI,GAAG,CAAC,kBAAkB,IAAI,GAAG,CAAC,kBAAkB,GAAG,GAAG,EAAE,CAAC;gBAC5D,OAAO,KAAK,CAAC;YACd,CAAC;YACD,OAAO,IAAI,CAAC;QACb,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Usage API response schema from ChatGPT backend
|
|
4
|
+
*/
|
|
5
|
+
export declare const UsageResponseSchema: z.ZodObject<{
|
|
6
|
+
rate_limit: z.ZodObject<{
|
|
7
|
+
primary_window: z.ZodObject<{
|
|
8
|
+
used_percent: z.ZodNumber;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
secondary_window: z.ZodObject<{
|
|
11
|
+
used_percent: z.ZodNumber;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type UsageResponse = z.infer<typeof UsageResponseSchema>;
|
|
16
|
+
/**
|
|
17
|
+
* Usage cache file structure
|
|
18
|
+
*/
|
|
19
|
+
export declare const UsageCacheSchema: z.ZodObject<{
|
|
20
|
+
accounts: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
21
|
+
primaryUsage: z.ZodNumber;
|
|
22
|
+
secondaryUsage: z.ZodNumber;
|
|
23
|
+
updatedAt: z.ZodNumber;
|
|
24
|
+
}, z.core.$strip>>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
export type UsageCache = z.infer<typeof UsageCacheSchema>;
|
|
27
|
+
/**
|
|
28
|
+
* Plugin configuration schema
|
|
29
|
+
*/
|
|
30
|
+
export declare const PluginConfigSchema: z.ZodObject<{
|
|
31
|
+
strategy: z.ZodEnum<{
|
|
32
|
+
sticky: "sticky";
|
|
33
|
+
"round-robin": "round-robin";
|
|
34
|
+
}>;
|
|
35
|
+
pidOffset: z.ZodBoolean;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export type PluginConfig = z.infer<typeof PluginConfigSchema>;
|
|
38
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/plugin/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;iBAS9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;iBAS3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;iBAG7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Usage API response schema from ChatGPT backend
|
|
4
|
+
*/
|
|
5
|
+
export const UsageResponseSchema = z.object({
|
|
6
|
+
rate_limit: z.object({
|
|
7
|
+
primary_window: z.object({
|
|
8
|
+
used_percent: z.number(),
|
|
9
|
+
}),
|
|
10
|
+
secondary_window: z.object({
|
|
11
|
+
used_percent: z.number(),
|
|
12
|
+
}),
|
|
13
|
+
}),
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Usage cache file structure
|
|
17
|
+
*/
|
|
18
|
+
export const UsageCacheSchema = z.object({
|
|
19
|
+
accounts: z.record(z.string(), z.object({
|
|
20
|
+
primaryUsage: z.number(),
|
|
21
|
+
secondaryUsage: z.number(),
|
|
22
|
+
updatedAt: z.number(),
|
|
23
|
+
})),
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Plugin configuration schema
|
|
27
|
+
*/
|
|
28
|
+
export const PluginConfigSchema = z.object({
|
|
29
|
+
strategy: z.enum(["sticky", "round-robin"]),
|
|
30
|
+
pidOffset: z.boolean(),
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/plugin/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC;YACvB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;SACzB,CAAC;QACF,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC;YACzB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;SACzB,CAAC;KACH,CAAC;CACH,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAChB,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,MAAM,CAAC;QACP,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;QAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB,CAAC,CACH;CACF,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;CACvB,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CodexAccount } from "./accounts";
|
|
2
|
+
/**
|
|
3
|
+
* 테스트를 위해 저장 경로를 설정합니다.
|
|
4
|
+
*/
|
|
5
|
+
export declare function setStoragePathForTest(pathVar: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* 저장된 계정 목록을 로드합니다.
|
|
8
|
+
* 파일이 없거나 오류가 발생하면 빈 배열을 반환합니다.
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadAccounts(): Promise<CodexAccount[]>;
|
|
11
|
+
/**
|
|
12
|
+
* 계정 목록을 디스크에 저장합니다.
|
|
13
|
+
*/
|
|
14
|
+
export declare function saveAccounts(accountsVar: CodexAccount[]): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/plugin/storage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAQ5D;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAW7E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
let storagePathVar = join(homedir(), ".config/opencode/codex-accounts.json");
|
|
5
|
+
/**
|
|
6
|
+
* 테스트를 위해 저장 경로를 설정합니다.
|
|
7
|
+
*/
|
|
8
|
+
export function setStoragePathForTest(pathVar) {
|
|
9
|
+
storagePathVar = pathVar;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 저장된 계정 목록을 로드합니다.
|
|
13
|
+
* 파일이 없거나 오류가 발생하면 빈 배열을 반환합니다.
|
|
14
|
+
*/
|
|
15
|
+
export async function loadAccounts() {
|
|
16
|
+
try {
|
|
17
|
+
const contentVar = await readFile(storagePathVar, "utf-8");
|
|
18
|
+
const dataVar = JSON.parse(contentVar);
|
|
19
|
+
return dataVar.accounts || [];
|
|
20
|
+
}
|
|
21
|
+
catch (errorVar) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 계정 목록을 디스크에 저장합니다.
|
|
27
|
+
*/
|
|
28
|
+
export async function saveAccounts(accountsVar) {
|
|
29
|
+
const dirVar = dirname(storagePathVar);
|
|
30
|
+
await mkdir(dirVar, { recursive: true });
|
|
31
|
+
const dataVar = {
|
|
32
|
+
version: 1,
|
|
33
|
+
accounts: accountsVar,
|
|
34
|
+
activeIndex: 0
|
|
35
|
+
};
|
|
36
|
+
await writeFile(storagePathVar, JSON.stringify(dataVar, null, 2), "utf-8");
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/plugin/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,IAAI,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,sCAAsC,CAAC,CAAC;AAE7E;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACpD,cAAc,GAAG,OAAO,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IACjC,IAAI,CAAC;QACJ,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,QAAQ,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAA2B;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACvC,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,OAAO,GAAG;QACf,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,CAAC;KACd,CAAC;IAEF,MAAM,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { UsageResponse, UsageCache } from "./config/schema";
|
|
2
|
+
import type { CodexAccount } from "./accounts";
|
|
3
|
+
export declare function fetchUsage(token: string, accountId: string): Promise<UsageResponse>;
|
|
4
|
+
export declare function loadUsageCache(pid: number): UsageCache | null;
|
|
5
|
+
export declare function saveUsageCache(pid: number, data: UsageCache): void;
|
|
6
|
+
export declare function getWeeklyBucket(percent: number): 0 | 1 | 2 | 3;
|
|
7
|
+
export declare function selectAccountByUsage(accounts: CodexAccount[], cache: UsageCache): number;
|
|
8
|
+
export declare function fetchUsageBackground(token: string, accountId: string, pid: number): void;
|
|
9
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/plugin/usage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAyC,MAAM,iBAAiB,CAAC;AACnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAUzF;AAMD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAU7D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAElE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAK9D;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,YAAY,EAAE,EACxB,KAAK,EAAE,UAAU,GAChB,MAAM,CAmBR;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,IAAI,CAYN"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { UsageResponseSchema, UsageCacheSchema } from "./config/schema";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
const USAGE_API_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
4
|
+
export async function fetchUsage(token, accountId) {
|
|
5
|
+
const res = await fetch(USAGE_API_URL, {
|
|
6
|
+
headers: {
|
|
7
|
+
Authorization: `Bearer ${token}`,
|
|
8
|
+
"oai-device-id": accountId,
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
if (!res.ok)
|
|
12
|
+
throw new Error(`Usage API failed: ${res.status}`);
|
|
13
|
+
const data = await res.json();
|
|
14
|
+
return UsageResponseSchema.parse(data);
|
|
15
|
+
}
|
|
16
|
+
function getCachePath(pid) {
|
|
17
|
+
return `/tmp/codex-usage-${pid}.json`;
|
|
18
|
+
}
|
|
19
|
+
export function loadUsageCache(pid) {
|
|
20
|
+
const path = getCachePath(pid);
|
|
21
|
+
if (!fs.existsSync(path))
|
|
22
|
+
return null;
|
|
23
|
+
try {
|
|
24
|
+
const data = JSON.parse(fs.readFileSync(path, "utf-8"));
|
|
25
|
+
return UsageCacheSchema.parse(data);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
fs.unlinkSync(path);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function saveUsageCache(pid, data) {
|
|
33
|
+
fs.writeFileSync(getCachePath(pid), JSON.stringify(data, null, 2));
|
|
34
|
+
}
|
|
35
|
+
export function getWeeklyBucket(percent) {
|
|
36
|
+
if (percent < 30)
|
|
37
|
+
return 0;
|
|
38
|
+
if (percent < 60)
|
|
39
|
+
return 1;
|
|
40
|
+
if (percent < 90)
|
|
41
|
+
return 2;
|
|
42
|
+
return 3;
|
|
43
|
+
}
|
|
44
|
+
export function selectAccountByUsage(accounts, cache) {
|
|
45
|
+
if (accounts.length === 0)
|
|
46
|
+
return -1;
|
|
47
|
+
if (accounts.length === 1)
|
|
48
|
+
return 0;
|
|
49
|
+
const accountsWithUsage = accounts.map((acc, index) => {
|
|
50
|
+
const usage = cache.accounts[acc.id];
|
|
51
|
+
return {
|
|
52
|
+
index,
|
|
53
|
+
primaryUsage: usage?.primaryUsage ?? 0,
|
|
54
|
+
secondaryUsage: usage?.secondaryUsage ?? 0,
|
|
55
|
+
weeklyBucket: getWeeklyBucket(usage?.secondaryUsage ?? 0),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
const minBucket = Math.min(...accountsWithUsage.map(a => a.weeklyBucket));
|
|
59
|
+
const candidates = accountsWithUsage.filter(a => a.weeklyBucket === minBucket);
|
|
60
|
+
candidates.sort((a, b) => a.primaryUsage - b.primaryUsage);
|
|
61
|
+
return candidates[0]?.index ?? 0;
|
|
62
|
+
}
|
|
63
|
+
export function fetchUsageBackground(token, accountId, pid) {
|
|
64
|
+
fetchUsage(token, accountId)
|
|
65
|
+
.then(response => {
|
|
66
|
+
const cache = loadUsageCache(pid) ?? { accounts: {} };
|
|
67
|
+
cache.accounts[accountId] = {
|
|
68
|
+
primaryUsage: response.rate_limit.primary_window.used_percent,
|
|
69
|
+
secondaryUsage: response.rate_limit.secondary_window.used_percent,
|
|
70
|
+
updatedAt: Date.now(),
|
|
71
|
+
};
|
|
72
|
+
saveUsageCache(pid, cache);
|
|
73
|
+
})
|
|
74
|
+
.catch(() => { });
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/plugin/usage.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-codex-auth-rotation",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenAI ChatGPT (Codex backend) OAuth auth plugin for opencode with multi-account rotation - use your ChatGPT Plus/Pro subscription instead of API credits",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"author": "professional-ALFIE",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/professional-ALFIE/opencode-codex-auth-rotation.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"opencode",
|
|
16
|
+
"openai",
|
|
17
|
+
"codex",
|
|
18
|
+
"chatgpt",
|
|
19
|
+
"oauth",
|
|
20
|
+
"gpt-5",
|
|
21
|
+
"plugin",
|
|
22
|
+
"auth",
|
|
23
|
+
"chatgpt-plus",
|
|
24
|
+
"chatgpt-pro",
|
|
25
|
+
"multi-account",
|
|
26
|
+
"rotation"
|
|
27
|
+
],
|
|
28
|
+
"homepage": "https://github.com/professional-ALFIE/opencode-codex-auth-rotation#readme",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/professional-ALFIE/opencode-codex-auth-rotation/issues"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc && cp lib/oauth-success.html dist/lib/",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest",
|
|
37
|
+
"test:ui": "vitest --ui",
|
|
38
|
+
"test:coverage": "vitest run --coverage"
|
|
39
|
+
},
|
|
40
|
+
"bin": {
|
|
41
|
+
"opencode-openai-codex-auth": "./scripts/install-opencode-codex-auth.js"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist/",
|
|
45
|
+
"assets/",
|
|
46
|
+
"config/",
|
|
47
|
+
"scripts/",
|
|
48
|
+
"README.md",
|
|
49
|
+
"LICENSE"
|
|
50
|
+
],
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20.0.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"@opencode-ai/plugin": "^1.0.150"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@opencode-ai/plugin": "^1.0.150",
|
|
59
|
+
"@opencode-ai/sdk": "^1.0.150",
|
|
60
|
+
"@types/node": "^24.6.2",
|
|
61
|
+
"@vitest/ui": "^3.2.4",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"vitest": "^3.2.4"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@openauthjs/openauth": "^0.4.3",
|
|
67
|
+
"hono": "^4.10.4",
|
|
68
|
+
"jsonc-parser": "^3.3.1"
|
|
69
|
+
},
|
|
70
|
+
"overrides": {
|
|
71
|
+
"hono": "^4.10.4",
|
|
72
|
+
"vite": "^7.1.12"
|
|
73
|
+
}
|
|
74
|
+
}
|