oc-chatgpt-multi-auth 5.3.0 → 5.3.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.
@@ -1,239 +1,239 @@
1
- {
2
- "$schema": "https://opencode.ai/config.json",
3
- "plugin": [
4
- "oc-chatgpt-multi-auth"
5
- ],
6
- "provider": {
7
- "openai": {
8
- "options": {
9
- "reasoningEffort": "medium",
10
- "reasoningSummary": "auto",
11
- "textVerbosity": "medium",
12
- "include": [
13
- "reasoning.encrypted_content"
14
- ],
15
- "store": false
16
- },
17
- "models": {
18
- "gpt-5.2": {
19
- "name": "GPT 5.2 (OAuth)",
20
- "limit": {
21
- "context": 272000,
22
- "output": 128000
23
- },
24
- "modalities": {
25
- "input": [
26
- "text",
27
- "image"
28
- ],
29
- "output": [
30
- "text"
31
- ]
32
- },
33
- "variants": {
34
- "none": {
35
- "reasoningEffort": "none",
36
- "reasoningSummary": "auto",
37
- "textVerbosity": "medium"
38
- },
39
- "low": {
40
- "reasoningEffort": "low",
41
- "reasoningSummary": "auto",
42
- "textVerbosity": "medium"
43
- },
44
- "medium": {
45
- "reasoningEffort": "medium",
46
- "reasoningSummary": "auto",
47
- "textVerbosity": "medium"
48
- },
49
- "high": {
50
- "reasoningEffort": "high",
51
- "reasoningSummary": "detailed",
52
- "textVerbosity": "medium"
53
- },
54
- "xhigh": {
55
- "reasoningEffort": "xhigh",
56
- "reasoningSummary": "detailed",
57
- "textVerbosity": "medium"
58
- }
59
- }
60
- },
61
- "gpt-5.1-codex-max": {
62
- "name": "GPT 5.1 Codex Max (OAuth)",
63
- "limit": {
64
- "context": 272000,
65
- "output": 128000
66
- },
67
- "modalities": {
68
- "input": [
69
- "text",
70
- "image"
71
- ],
72
- "output": [
73
- "text"
74
- ]
75
- },
76
- "variants": {
77
- "low": {
78
- "reasoningEffort": "low",
79
- "reasoningSummary": "detailed",
80
- "textVerbosity": "medium"
81
- },
82
- "medium": {
83
- "reasoningEffort": "medium",
84
- "reasoningSummary": "detailed",
85
- "textVerbosity": "medium"
86
- },
87
- "high": {
88
- "reasoningEffort": "high",
89
- "reasoningSummary": "detailed",
90
- "textVerbosity": "medium"
91
- },
92
- "xhigh": {
93
- "reasoningEffort": "xhigh",
94
- "reasoningSummary": "detailed",
95
- "textVerbosity": "medium"
96
- }
97
- }
98
- },
99
- "gpt-5.1-codex": {
100
- "name": "GPT 5.1 Codex (OAuth)",
101
- "limit": {
102
- "context": 272000,
103
- "output": 128000
104
- },
105
- "modalities": {
106
- "input": [
107
- "text",
108
- "image"
109
- ],
110
- "output": [
111
- "text"
112
- ]
113
- },
114
- "variants": {
115
- "low": {
116
- "reasoningEffort": "low",
117
- "reasoningSummary": "auto",
118
- "textVerbosity": "medium"
119
- },
120
- "medium": {
121
- "reasoningEffort": "medium",
122
- "reasoningSummary": "auto",
123
- "textVerbosity": "medium"
124
- },
125
- "high": {
126
- "reasoningEffort": "high",
127
- "reasoningSummary": "detailed",
128
- "textVerbosity": "medium"
129
- }
130
- }
131
- },
132
- "gpt-5.1-codex-mini": {
133
- "name": "GPT 5.1 Codex Mini (OAuth)",
134
- "limit": {
135
- "context": 272000,
136
- "output": 128000
137
- },
138
- "modalities": {
139
- "input": [
140
- "text",
141
- "image"
142
- ],
143
- "output": [
144
- "text"
145
- ]
146
- },
147
- "variants": {
148
- "medium": {
149
- "reasoningEffort": "medium",
150
- "reasoningSummary": "auto",
151
- "textVerbosity": "medium"
152
- },
153
- "high": {
154
- "reasoningEffort": "high",
155
- "reasoningSummary": "detailed",
156
- "textVerbosity": "medium"
157
- }
158
- }
159
- },
160
- "gpt-5.1": {
161
- "name": "GPT 5.1 (OAuth)",
162
- "limit": {
163
- "context": 272000,
164
- "output": 128000
165
- },
166
- "modalities": {
167
- "input": [
168
- "text",
169
- "image"
170
- ],
171
- "output": [
172
- "text"
173
- ]
174
- },
175
- "variants": {
176
- "none": {
177
- "reasoningEffort": "none",
178
- "reasoningSummary": "auto",
179
- "textVerbosity": "medium"
180
- },
181
- "low": {
182
- "reasoningEffort": "low",
183
- "reasoningSummary": "auto",
184
- "textVerbosity": "low"
185
- },
186
- "medium": {
187
- "reasoningEffort": "medium",
188
- "reasoningSummary": "auto",
189
- "textVerbosity": "medium"
190
- },
191
- "high": {
192
- "reasoningEffort": "high",
193
- "reasoningSummary": "detailed",
194
- "textVerbosity": "high"
195
- }
196
- }
197
- },
198
- "gpt-5-codex": {
199
- "name": "GPT 5 Codex (OAuth)",
200
- "limit": {
201
- "context": 272000,
202
- "output": 128000
203
- },
204
- "modalities": {
205
- "input": [
206
- "text",
207
- "image"
208
- ],
209
- "output": [
210
- "text"
211
- ]
212
- },
213
- "variants": {
214
- "low": {
215
- "reasoningEffort": "low",
216
- "reasoningSummary": "auto",
217
- "textVerbosity": "medium"
218
- },
219
- "medium": {
220
- "reasoningEffort": "medium",
221
- "reasoningSummary": "auto",
222
- "textVerbosity": "medium"
223
- },
224
- "high": {
225
- "reasoningEffort": "high",
226
- "reasoningSummary": "detailed",
227
- "textVerbosity": "medium"
228
- }
229
- },
230
- "options": {
231
- "reasoningEffort": "high",
232
- "reasoningSummary": "detailed",
233
- "textVerbosity": "medium"
234
- }
235
- }
236
- }
237
- }
238
- }
239
- }
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "plugin": [
4
+ "oc-chatgpt-multi-auth"
5
+ ],
6
+ "provider": {
7
+ "openai": {
8
+ "options": {
9
+ "reasoningEffort": "medium",
10
+ "reasoningSummary": "auto",
11
+ "textVerbosity": "medium",
12
+ "include": [
13
+ "reasoning.encrypted_content"
14
+ ],
15
+ "store": false
16
+ },
17
+ "models": {
18
+ "gpt-5.2": {
19
+ "name": "GPT 5.2 (OAuth)",
20
+ "limit": {
21
+ "context": 272000,
22
+ "output": 128000
23
+ },
24
+ "modalities": {
25
+ "input": [
26
+ "text",
27
+ "image"
28
+ ],
29
+ "output": [
30
+ "text"
31
+ ]
32
+ },
33
+ "variants": {
34
+ "none": {
35
+ "reasoningEffort": "none",
36
+ "reasoningSummary": "auto",
37
+ "textVerbosity": "medium"
38
+ },
39
+ "low": {
40
+ "reasoningEffort": "low",
41
+ "reasoningSummary": "auto",
42
+ "textVerbosity": "medium"
43
+ },
44
+ "medium": {
45
+ "reasoningEffort": "medium",
46
+ "reasoningSummary": "auto",
47
+ "textVerbosity": "medium"
48
+ },
49
+ "high": {
50
+ "reasoningEffort": "high",
51
+ "reasoningSummary": "detailed",
52
+ "textVerbosity": "medium"
53
+ },
54
+ "xhigh": {
55
+ "reasoningEffort": "xhigh",
56
+ "reasoningSummary": "detailed",
57
+ "textVerbosity": "medium"
58
+ }
59
+ }
60
+ },
61
+ "gpt-5.1-codex-max": {
62
+ "name": "GPT 5.1 Codex Max (OAuth)",
63
+ "limit": {
64
+ "context": 272000,
65
+ "output": 128000
66
+ },
67
+ "modalities": {
68
+ "input": [
69
+ "text",
70
+ "image"
71
+ ],
72
+ "output": [
73
+ "text"
74
+ ]
75
+ },
76
+ "variants": {
77
+ "low": {
78
+ "reasoningEffort": "low",
79
+ "reasoningSummary": "detailed",
80
+ "textVerbosity": "medium"
81
+ },
82
+ "medium": {
83
+ "reasoningEffort": "medium",
84
+ "reasoningSummary": "detailed",
85
+ "textVerbosity": "medium"
86
+ },
87
+ "high": {
88
+ "reasoningEffort": "high",
89
+ "reasoningSummary": "detailed",
90
+ "textVerbosity": "medium"
91
+ },
92
+ "xhigh": {
93
+ "reasoningEffort": "xhigh",
94
+ "reasoningSummary": "detailed",
95
+ "textVerbosity": "medium"
96
+ }
97
+ }
98
+ },
99
+ "gpt-5.1-codex": {
100
+ "name": "GPT 5.1 Codex (OAuth)",
101
+ "limit": {
102
+ "context": 272000,
103
+ "output": 128000
104
+ },
105
+ "modalities": {
106
+ "input": [
107
+ "text",
108
+ "image"
109
+ ],
110
+ "output": [
111
+ "text"
112
+ ]
113
+ },
114
+ "variants": {
115
+ "low": {
116
+ "reasoningEffort": "low",
117
+ "reasoningSummary": "auto",
118
+ "textVerbosity": "medium"
119
+ },
120
+ "medium": {
121
+ "reasoningEffort": "medium",
122
+ "reasoningSummary": "auto",
123
+ "textVerbosity": "medium"
124
+ },
125
+ "high": {
126
+ "reasoningEffort": "high",
127
+ "reasoningSummary": "detailed",
128
+ "textVerbosity": "medium"
129
+ }
130
+ }
131
+ },
132
+ "gpt-5.1-codex-mini": {
133
+ "name": "GPT 5.1 Codex Mini (OAuth)",
134
+ "limit": {
135
+ "context": 272000,
136
+ "output": 128000
137
+ },
138
+ "modalities": {
139
+ "input": [
140
+ "text",
141
+ "image"
142
+ ],
143
+ "output": [
144
+ "text"
145
+ ]
146
+ },
147
+ "variants": {
148
+ "medium": {
149
+ "reasoningEffort": "medium",
150
+ "reasoningSummary": "auto",
151
+ "textVerbosity": "medium"
152
+ },
153
+ "high": {
154
+ "reasoningEffort": "high",
155
+ "reasoningSummary": "detailed",
156
+ "textVerbosity": "medium"
157
+ }
158
+ }
159
+ },
160
+ "gpt-5.1": {
161
+ "name": "GPT 5.1 (OAuth)",
162
+ "limit": {
163
+ "context": 272000,
164
+ "output": 128000
165
+ },
166
+ "modalities": {
167
+ "input": [
168
+ "text",
169
+ "image"
170
+ ],
171
+ "output": [
172
+ "text"
173
+ ]
174
+ },
175
+ "variants": {
176
+ "none": {
177
+ "reasoningEffort": "none",
178
+ "reasoningSummary": "auto",
179
+ "textVerbosity": "medium"
180
+ },
181
+ "low": {
182
+ "reasoningEffort": "low",
183
+ "reasoningSummary": "auto",
184
+ "textVerbosity": "low"
185
+ },
186
+ "medium": {
187
+ "reasoningEffort": "medium",
188
+ "reasoningSummary": "auto",
189
+ "textVerbosity": "medium"
190
+ },
191
+ "high": {
192
+ "reasoningEffort": "high",
193
+ "reasoningSummary": "detailed",
194
+ "textVerbosity": "high"
195
+ }
196
+ }
197
+ },
198
+ "gpt-5-codex": {
199
+ "name": "GPT 5 Codex (OAuth)",
200
+ "limit": {
201
+ "context": 272000,
202
+ "output": 128000
203
+ },
204
+ "modalities": {
205
+ "input": [
206
+ "text",
207
+ "image"
208
+ ],
209
+ "output": [
210
+ "text"
211
+ ]
212
+ },
213
+ "variants": {
214
+ "low": {
215
+ "reasoningEffort": "low",
216
+ "reasoningSummary": "auto",
217
+ "textVerbosity": "medium"
218
+ },
219
+ "medium": {
220
+ "reasoningEffort": "medium",
221
+ "reasoningSummary": "auto",
222
+ "textVerbosity": "medium"
223
+ },
224
+ "high": {
225
+ "reasoningEffort": "high",
226
+ "reasoningSummary": "detailed",
227
+ "textVerbosity": "medium"
228
+ }
229
+ },
230
+ "options": {
231
+ "reasoningEffort": "high",
232
+ "reasoningSummary": "detailed",
233
+ "textVerbosity": "medium"
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AA0I/D;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAisG/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAElD,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AA0I/D;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAosG/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAElD,eAAe,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -432,41 +432,46 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
432
432
  if (accountsToHydrate.length === 0)
433
433
  return storage;
434
434
  let changed = false;
435
- await Promise.all(accountsToHydrate.map(async (account) => {
436
- try {
437
- const refreshed = await queuedRefresh(account.refreshToken);
438
- if (refreshed.type !== "success")
439
- return;
440
- const id = extractAccountId(refreshed.access);
441
- const email = sanitizeEmail(extractAccountEmail(refreshed.access, refreshed.idToken));
442
- if (id &&
443
- id !== account.accountId &&
444
- shouldUpdateAccountIdFromToken(account.accountIdSource, account.accountId)) {
445
- account.accountId = id;
446
- account.accountIdSource = "token";
447
- changed = true;
448
- }
449
- if (email && email !== account.email) {
450
- account.email = email;
451
- changed = true;
452
- }
453
- if (refreshed.access && refreshed.access !== account.accessToken) {
454
- account.accessToken = refreshed.access;
455
- changed = true;
456
- }
457
- if (typeof refreshed.expires === "number" && refreshed.expires !== account.expiresAt) {
458
- account.expiresAt = refreshed.expires;
459
- changed = true;
435
+ // process in chunks of 3 to avoid auth0 rate limits (429) on startup
436
+ const chunkSize = 3;
437
+ for (let i = 0; i < accountsToHydrate.length; i += chunkSize) {
438
+ const chunk = accountsToHydrate.slice(i, i + chunkSize);
439
+ await Promise.all(chunk.map(async (account) => {
440
+ try {
441
+ const refreshed = await queuedRefresh(account.refreshToken);
442
+ if (refreshed.type !== "success")
443
+ return;
444
+ const id = extractAccountId(refreshed.access);
445
+ const email = sanitizeEmail(extractAccountEmail(refreshed.access, refreshed.idToken));
446
+ if (id &&
447
+ id !== account.accountId &&
448
+ shouldUpdateAccountIdFromToken(account.accountIdSource, account.accountId)) {
449
+ account.accountId = id;
450
+ account.accountIdSource = "token";
451
+ changed = true;
452
+ }
453
+ if (email && email !== account.email) {
454
+ account.email = email;
455
+ changed = true;
456
+ }
457
+ if (refreshed.access && refreshed.access !== account.accessToken) {
458
+ account.accessToken = refreshed.access;
459
+ changed = true;
460
+ }
461
+ if (typeof refreshed.expires === "number" && refreshed.expires !== account.expiresAt) {
462
+ account.expiresAt = refreshed.expires;
463
+ changed = true;
464
+ }
465
+ if (refreshed.refresh && refreshed.refresh !== account.refreshToken) {
466
+ account.refreshToken = refreshed.refresh;
467
+ changed = true;
468
+ }
460
469
  }
461
- if (refreshed.refresh && refreshed.refresh !== account.refreshToken) {
462
- account.refreshToken = refreshed.refresh;
463
- changed = true;
470
+ catch {
471
+ logWarn(`[${PLUGIN_NAME}] Failed to hydrate email for account`);
464
472
  }
465
- }
466
- catch {
467
- logWarn(`[${PLUGIN_NAME}] Failed to hydrate email for account`);
468
- }
469
- }));
473
+ }));
474
+ }
470
475
  if (changed) {
471
476
  storage.accounts = accountsCopy;
472
477
  await saveAccounts(storage);
@@ -625,17 +630,17 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
625
630
  applyUiRuntimeFromConfig(pluginConfig);
626
631
  const perProjectAccounts = getPerProjectAccounts(pluginConfig);
627
632
  setStoragePath(perProjectAccounts ? process.cwd() : null);
628
- // Only handle OAuth auth type, skip API key auth
629
- if (auth.type !== "oauth") {
630
- return {};
631
- }
633
+ const authFallback = auth.type === "oauth" ? auth : undefined;
632
634
  // Prefer multi-account auth metadata when available, but still handle
633
635
  // plain OAuth credentials (for OpenCode versions that inject internal
634
636
  // Codex auth first and omit the multiAccount marker).
635
- const authWithMulti = auth;
636
- if (!authWithMulti.multiAccount) {
637
+ const authWithMulti = authFallback;
638
+ if (authWithMulti && !authWithMulti.multiAccount) {
637
639
  logDebug(`[${PLUGIN_NAME}] Auth is missing multiAccount marker; continuing with single-account compatibility mode`);
638
640
  }
641
+ if (!authFallback) {
642
+ logDebug(`[${PLUGIN_NAME}] Host auth is ${auth.type}; attempting stored Codex account compatibility mode`);
643
+ }
639
644
  // Acquire mutex for thread-safe initialization
640
645
  // Use while loop to handle multiple concurrent waiters correctly
641
646
  while (loaderMutex) {
@@ -647,18 +652,18 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
647
652
  });
648
653
  try {
649
654
  if (!accountManagerPromise) {
650
- accountManagerPromise = AccountManager.loadFromDisk(auth);
655
+ accountManagerPromise = AccountManager.loadFromDisk(authFallback);
651
656
  }
652
657
  let accountManager = await accountManagerPromise;
653
658
  cachedAccountManager = accountManager;
654
- const refreshToken = auth.type === "oauth" ? auth.refresh : "";
659
+ const refreshToken = authFallback?.refresh ?? "";
655
660
  const needsPersist = refreshToken &&
656
661
  !accountManager.hasRefreshToken(refreshToken);
657
662
  if (needsPersist) {
658
663
  await accountManager.saveToDisk();
659
664
  }
660
665
  if (accountManager.getAccountCount() === 0) {
661
- logDebug(`[${PLUGIN_NAME}] No OAuth accounts available (run opencode auth login)`);
666
+ logDebug(`[${PLUGIN_NAME}] No Codex accounts available (run opencode auth login)`);
662
667
  return {};
663
668
  }
664
669
  // Extract user configuration (global + per-model options)