@modelprofile.com/authswitch 2.1.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.
Files changed (95) hide show
  1. package/.smartconfig.json +34 -0
  2. package/cli.js +21 -0
  3. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  4. package/dist_ts/00_commitinfo_data.js +9 -0
  5. package/dist_ts/accounts.d.ts +31 -0
  6. package/dist_ts/accounts.js +74 -0
  7. package/dist_ts/classes.accountlist.d.ts +17 -0
  8. package/dist_ts/classes.accountlist.js +214 -0
  9. package/dist_ts/classes.claudecodeharness.d.ts +34 -0
  10. package/dist_ts/classes.claudecodeharness.js +123 -0
  11. package/dist_ts/classes.claudestatus.d.ts +8 -0
  12. package/dist_ts/classes.claudestatus.js +139 -0
  13. package/dist_ts/classes.cli.d.ts +31 -0
  14. package/dist_ts/classes.cli.js +584 -0
  15. package/dist_ts/classes.codexauth.d.ts +35 -0
  16. package/dist_ts/classes.codexauth.js +184 -0
  17. package/dist_ts/classes.codexdaemon.d.ts +38 -0
  18. package/dist_ts/classes.codexdaemon.js +122 -0
  19. package/dist_ts/classes.codexharness.d.ts +35 -0
  20. package/dist_ts/classes.codexharness.js +199 -0
  21. package/dist_ts/classes.codexhome.d.ts +25 -0
  22. package/dist_ts/classes.codexhome.js +60 -0
  23. package/dist_ts/classes.codexpreuse.d.ts +8 -0
  24. package/dist_ts/classes.codexpreuse.js +90 -0
  25. package/dist_ts/classes.codexstatus.d.ts +20 -0
  26. package/dist_ts/classes.codexstatus.js +304 -0
  27. package/dist_ts/classes.codexswitcher.d.ts +61 -0
  28. package/dist_ts/classes.codexswitcher.js +226 -0
  29. package/dist_ts/classes.credentialstore.d.ts +32 -0
  30. package/dist_ts/classes.credentialstore.js +115 -0
  31. package/dist_ts/classes.fileharness.d.ts +47 -0
  32. package/dist_ts/classes.fileharness.js +119 -0
  33. package/dist_ts/classes.login.d.ts +42 -0
  34. package/dist_ts/classes.login.js +102 -0
  35. package/dist_ts/classes.opencodeharness.d.ts +34 -0
  36. package/dist_ts/classes.opencodeharness.js +125 -0
  37. package/dist_ts/classes.operations.d.ts +44 -0
  38. package/dist_ts/classes.operations.js +97 -0
  39. package/dist_ts/classes.remotecontrol.d.ts +46 -0
  40. package/dist_ts/classes.remotecontrol.js +169 -0
  41. package/dist_ts/classes.service.d.ts +47 -0
  42. package/dist_ts/classes.service.js +142 -0
  43. package/dist_ts/classes.stashstore.d.ts +63 -0
  44. package/dist_ts/classes.stashstore.js +192 -0
  45. package/dist_ts/classes.tui.d.ts +11 -0
  46. package/dist_ts/classes.tui.js +195 -0
  47. package/dist_ts/formatting.d.ts +8 -0
  48. package/dist_ts/formatting.js +13 -0
  49. package/dist_ts/helpers.d.ts +39 -0
  50. package/dist_ts/helpers.js +92 -0
  51. package/dist_ts/index.d.ts +22 -0
  52. package/dist_ts/index.js +27 -0
  53. package/dist_ts/interfaces.d.ts +145 -0
  54. package/dist_ts/interfaces.harness.d.ts +130 -0
  55. package/dist_ts/interfaces.harness.js +2 -0
  56. package/dist_ts/interfaces.js +2 -0
  57. package/dist_ts/interfaces.list.d.ts +19 -0
  58. package/dist_ts/interfaces.list.js +2 -0
  59. package/dist_ts/plugins.d.ts +14 -0
  60. package/dist_ts/plugins.js +18 -0
  61. package/dist_ts/preuse.d.ts +6 -0
  62. package/dist_ts/preuse.js +13 -0
  63. package/license.md +21 -0
  64. package/package.json +53 -0
  65. package/readme.md +502 -0
  66. package/ts/00_commitinfo_data.ts +8 -0
  67. package/ts/accounts.ts +78 -0
  68. package/ts/classes.accountlist.ts +211 -0
  69. package/ts/classes.claudecodeharness.ts +111 -0
  70. package/ts/classes.claudestatus.ts +99 -0
  71. package/ts/classes.cli.ts +479 -0
  72. package/ts/classes.codexauth.ts +199 -0
  73. package/ts/classes.codexdaemon.ts +137 -0
  74. package/ts/classes.codexharness.ts +233 -0
  75. package/ts/classes.codexhome.ts +68 -0
  76. package/ts/classes.codexpreuse.ts +76 -0
  77. package/ts/classes.codexstatus.ts +257 -0
  78. package/ts/classes.codexswitcher.ts +272 -0
  79. package/ts/classes.credentialstore.ts +101 -0
  80. package/ts/classes.fileharness.ts +120 -0
  81. package/ts/classes.login.ts +103 -0
  82. package/ts/classes.opencodeharness.ts +114 -0
  83. package/ts/classes.operations.ts +101 -0
  84. package/ts/classes.remotecontrol.ts +208 -0
  85. package/ts/classes.service.ts +152 -0
  86. package/ts/classes.stashstore.ts +223 -0
  87. package/ts/classes.tui.ts +138 -0
  88. package/ts/formatting.ts +14 -0
  89. package/ts/helpers.ts +109 -0
  90. package/ts/index.ts +28 -0
  91. package/ts/interfaces.harness.ts +112 -0
  92. package/ts/interfaces.list.ts +19 -0
  93. package/ts/interfaces.ts +158 -0
  94. package/ts/plugins.ts +20 -0
  95. package/ts/preuse.ts +15 -0
@@ -0,0 +1,304 @@
1
+ import { commitinfo } from './00_commitinfo_data.js';
2
+ // Verified Chromium-compatible billing request profile, independent of any locally installed browser.
3
+ const billingUserAgent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36';
4
+ const record = (valueArg) => {
5
+ if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg))
6
+ throw new Error('Unexpected status response.');
7
+ return valueArg;
8
+ };
9
+ const numeric = (valueArg) => {
10
+ if (typeof valueArg !== 'number' || !Number.isFinite(valueArg) || valueArg < 0)
11
+ throw new Error('Unexpected numeric status field.');
12
+ return valueArg;
13
+ };
14
+ const text = (valueArg) => {
15
+ if (typeof valueArg !== 'string' || !valueArg.trim())
16
+ throw new Error('Unexpected text status field.');
17
+ return valueArg;
18
+ };
19
+ const boolean = (valueArg) => {
20
+ if (typeof valueArg !== 'boolean')
21
+ throw new Error('Unexpected boolean status field.');
22
+ return valueArg;
23
+ };
24
+ const timestamp = (secondsArg) => new Date(numeric(secondsArg) * 1000).toISOString();
25
+ const count = (valueArg) => {
26
+ const value = numeric(valueArg);
27
+ if (!Number.isSafeInteger(value))
28
+ throw new Error('Invalid status count.');
29
+ return value;
30
+ };
31
+ /** Only fixed, local diagnostics may cross the HTTP error boundary. */
32
+ class StatusRequestError extends Error {
33
+ }
34
+ /**
35
+ * Read-only ChatGPT status contract verified against Codex 0.154.0.
36
+ * These source-defined backend routes are isolated here. No token refresh,
37
+ * credential writes, app-server lifecycle changes or reset consumption occur.
38
+ */
39
+ export class CodexAccountStatus {
40
+ fetcher;
41
+ constructor(fetcher = globalThis.fetch) {
42
+ this.fetcher = fetcher;
43
+ }
44
+ async read(rawArg, identityArg) {
45
+ if (identityArg.kind !== 'chatgpt')
46
+ return {
47
+ facts: [{ label: 'Authentication', value: 'API key' }, { label: 'Subscription and usage', value: 'Not exposed by Codex for API-key logins' }], problems: [],
48
+ };
49
+ let accessToken;
50
+ try {
51
+ accessToken = text(record(record(JSON.parse(rawArg)).tokens).access_token);
52
+ }
53
+ catch {
54
+ return { facts: [], problems: ['The login has no usable access token. Log in again with Codex, then save the account.'] };
55
+ }
56
+ if (!identityArg.accountId)
57
+ return { facts: [], problems: ['The login has no account ID for a status lookup.'] };
58
+ return this.readCredential(accessToken, identityArg.accountId, identityArg.planType);
59
+ }
60
+ /** Read the ChatGPT account directly, independent of a harness's on-disk format. */
61
+ async readCredential(accessToken, accountId, planType) {
62
+ const result = { facts: [], problems: [] };
63
+ const identityArg = { accountId, planType };
64
+ const sections = await Promise.allSettled([
65
+ this.get('wham/usage', accessToken, identityArg.accountId),
66
+ this.get('wham/rate-limit-reset-credits', accessToken, identityArg.accountId),
67
+ this.get('wham/profiles/me', accessToken, identityArg.accountId),
68
+ this.get('accounts/check/v4-2023-04-27', accessToken, identityArg.accountId),
69
+ ]);
70
+ const usage = sections[0];
71
+ if (usage.status === 'fulfilled' && usage.value.account_id != null && usage.value.account_id !== identityArg.accountId) {
72
+ return { facts: [], problems: ['The status service returned a different account ID; no account data was displayed.'] };
73
+ }
74
+ const parsers = [
75
+ (bodyArg) => this.limits(bodyArg, identityArg.accountId),
76
+ (bodyArg) => this.resets(bodyArg),
77
+ (bodyArg) => ({ facts: this.activity(bodyArg), summary: undefined }),
78
+ (bodyArg) => this.billing(bodyArg, identityArg.accountId),
79
+ ];
80
+ const labels = ['Subscription and limits', 'Earned reset details', 'Token usage', 'Billing'];
81
+ for (let index = 0; index < sections.length; index++) {
82
+ const section = sections[index];
83
+ if (section.status === 'rejected') {
84
+ result.problems.push(`${labels[index]}: ${section.reason instanceof Error ? section.reason.message : 'Request failed.'}`);
85
+ continue;
86
+ }
87
+ try {
88
+ // Each parser validates its whole section before returning any facts or summary.
89
+ const parsed = parsers[index](section.value);
90
+ result.facts.push(...parsed.facts);
91
+ if (parsed.summary)
92
+ result.summary = { ...result.summary, ...parsed.summary };
93
+ }
94
+ catch {
95
+ result.problems.push(`${labels[index]}: the service returned an unsupported response; no values were inferred.`);
96
+ }
97
+ }
98
+ if (!result.summary?.subscription && identityArg.planType) {
99
+ result.facts.unshift({ section: 'Subscription', summaryKey: 'subscription', label: 'Last known plan', value: `${identityArg.planType} (from stored login; not verified live)` });
100
+ result.summary = { ...result.summary, subscription: { plan: identityArg.planType, source: 'stored' } };
101
+ }
102
+ return result;
103
+ }
104
+ async get(pathArg, tokenArg, accountIdArg) {
105
+ const signal = AbortSignal.timeout(10_000);
106
+ try {
107
+ const response = await this.fetcher(`https://chatgpt.com/backend-api/${pathArg}`, {
108
+ method: 'GET', redirect: 'error', signal,
109
+ headers: { Authorization: `Bearer ${tokenArg}`, 'ChatGPT-Account-ID': accountIdArg,
110
+ 'User-Agent': `authswitch/${commitinfo.version}`, Accept: 'application/json',
111
+ ...(pathArg === 'accounts/check/v4-2023-04-27' ? { originator: 'Codex Desktop', 'OAI-Language': 'en', 'User-Agent': billingUserAgent } : {}) },
112
+ });
113
+ if (!response.ok) {
114
+ await response.body?.cancel();
115
+ if (response.headers.get('cf-mitigated') === 'challenge')
116
+ throw new StatusRequestError('Blocked by a service verification challenge (Cloudflare); this lookup is unavailable to the current HTTP client.');
117
+ if (response.status === 401)
118
+ throw new StatusRequestError('Login expired or was rejected. Log in again with the account’s harness, then save the account.');
119
+ if (response.status === 403)
120
+ throw new StatusRequestError('Access denied by the service (HTTP 403).');
121
+ throw new StatusRequestError(`Service returned HTTP ${response.status}.`);
122
+ }
123
+ const reader = response.body?.getReader();
124
+ if (!reader)
125
+ throw new StatusRequestError('The service returned an empty response.');
126
+ const chunks = [];
127
+ let size = 0;
128
+ try {
129
+ while (true) {
130
+ const part = await reader.read();
131
+ if (part.done)
132
+ break;
133
+ size += part.value.byteLength;
134
+ if (size > 1024 * 1024) {
135
+ await reader.cancel();
136
+ throw new StatusRequestError('The status response is too large.');
137
+ }
138
+ chunks.push(part.value);
139
+ }
140
+ }
141
+ finally {
142
+ reader.releaseLock();
143
+ }
144
+ try {
145
+ return record(JSON.parse(Buffer.concat(chunks).toString('utf8')));
146
+ }
147
+ catch {
148
+ throw new StatusRequestError('The service returned invalid status data.');
149
+ }
150
+ }
151
+ catch (errorArg) {
152
+ // Never surface remote bodies, request headers, token strings or arbitrary fetch errors.
153
+ if (signal.aborted)
154
+ throw new Error('The status request timed out.');
155
+ if (errorArg instanceof StatusRequestError)
156
+ throw errorArg;
157
+ throw new Error('The status service could not be reached.');
158
+ }
159
+ }
160
+ /** Desktop 26.908.40834 account-check contract; select the credential's exact account. */
161
+ billing(bodyArg, accountIdArg) {
162
+ const accounts = record(bodyArg.accounts);
163
+ const match = (valueArg) => {
164
+ const value = record(valueArg);
165
+ return record(value.account).account_id === accountIdArg;
166
+ };
167
+ // A default workspace must never supply another account's billing information.
168
+ const selected = Object.hasOwn(accounts, accountIdArg) ? accounts[accountIdArg]
169
+ : Object.values(accounts).find(value => match(value));
170
+ if (selected === undefined || !match(selected))
171
+ throw new Error('No matching billing account.');
172
+ const account = record(selected);
173
+ const entitlement = record(account.entitlement);
174
+ const subscription = record(account.last_active_subscription);
175
+ const billing = {};
176
+ if (entitlement.has_active_subscription != null)
177
+ billing.hasActiveSubscription = boolean(entitlement.has_active_subscription);
178
+ if (subscription.will_renew != null)
179
+ billing.autoRenew = boolean(subscription.will_renew) && entitlement.cancels_at == null;
180
+ for (const [field, key] of [['renews_at', 'renewsAt'], ['cancels_at', 'cancelsAt'], ['expires_at', 'expiresAt']]) {
181
+ if (entitlement[field] != null)
182
+ billing[key] = new Date(text(entitlement[field])).toISOString();
183
+ }
184
+ if (!Object.keys(billing).length)
185
+ throw new Error('No billing fields returned.');
186
+ const facts = [];
187
+ const append = (label, value) => facts.push({ section: 'Billing', summaryKey: 'billing', label, value });
188
+ if (billing.hasActiveSubscription !== undefined)
189
+ append('Active subscription', billing.hasActiveSubscription ? 'yes' : 'no');
190
+ if (billing.autoRenew !== undefined)
191
+ append('Automatic renewal', billing.autoRenew ? 'on' : 'off');
192
+ if (billing.renewsAt)
193
+ append('Renewal date (UTC)', billing.renewsAt);
194
+ if (billing.cancelsAt)
195
+ append('Cancellation date (UTC)', billing.cancelsAt);
196
+ if (billing.expiresAt)
197
+ append('Subscription expiry (UTC)', billing.expiresAt);
198
+ return { facts, summary: { billing } };
199
+ }
200
+ limits(bodyArg, accountIdArg) {
201
+ if (bodyArg.account_id != null && bodyArg.account_id !== accountIdArg)
202
+ throw new Error('Account mismatch.');
203
+ const plan = text(bodyArg.plan_type);
204
+ const facts = [{ section: 'Subscription', summaryKey: 'subscription', label: 'Subscription plan', value: `${plan} (live)` }];
205
+ const usageWindows = [];
206
+ const summary = { subscription: { plan, source: 'live' }, usageWindows };
207
+ const appendLimit = (nameArg, valueArg, scopeArg) => {
208
+ if (valueArg == null)
209
+ return;
210
+ const limit = record(valueArg);
211
+ facts.push({ section: 'Limits & credits', label: `${nameArg} usage allowed`, value: boolean(limit.allowed) ? 'yes' : 'no' });
212
+ facts.push({ section: 'Limits & credits', label: `${nameArg} limit reached`, value: boolean(limit.limit_reached) ? 'yes' : 'no' });
213
+ for (const [key, name] of [['primary_window', 'primary'], ['secondary_window', 'secondary']]) {
214
+ if (limit[key] == null)
215
+ continue;
216
+ const window = record(limit[key]);
217
+ const used = numeric(window.used_percent);
218
+ const durationSeconds = numeric(window.limit_window_seconds);
219
+ const minutes = durationSeconds / 60;
220
+ const duration = minutes % 1440 === 0 ? `${minutes / 1440}d` : minutes % 60 === 0 ? `${minutes / 60}h` : `${minutes}m`;
221
+ const resetAt = timestamp(window.reset_at);
222
+ usageWindows.push({ label: `${nameArg} ${name}`, scope: scopeArg, durationSeconds, usedPercent: used, resetAt });
223
+ facts.push({ section: 'Usage', summaryKey: 'usageWindows', label: `${nameArg} ${name} (${duration})`, value: `${used}% used, ${Math.max(0, 100 - used)}% remaining; resets ${resetAt}` });
224
+ }
225
+ };
226
+ appendLimit('Codex', bodyArg.rate_limit, 'account');
227
+ if (bodyArg.additional_rate_limits != null) {
228
+ if (!Array.isArray(bodyArg.additional_rate_limits))
229
+ throw new Error('Invalid additional limits.');
230
+ for (const value of bodyArg.additional_rate_limits) {
231
+ const limit = record(value);
232
+ appendLimit(text(limit.limit_name), limit.rate_limit, 'feature');
233
+ }
234
+ }
235
+ if (bodyArg.credits != null) {
236
+ const credits = record(bodyArg.credits);
237
+ const unlimited = boolean(credits.unlimited);
238
+ const hasCredits = boolean(credits.has_credits);
239
+ facts.push({ section: 'Limits & credits', label: 'Credits', value: unlimited ? 'unlimited' : credits.balance != null ? text(credits.balance) : hasCredits ? 'available (balance not returned)' : 'none available' });
240
+ }
241
+ if (bodyArg.spend_control != null) {
242
+ const spend = record(bodyArg.spend_control);
243
+ facts.push({ section: 'Limits & credits', label: 'Spend limit reached', value: boolean(spend.reached) ? 'yes' : 'no' });
244
+ if (spend.individual_limit != null) {
245
+ const limit = record(spend.individual_limit);
246
+ facts.push({ section: 'Limits & credits', label: 'Individual spend', value: `${text(limit.used)} used of ${text(limit.limit)}; ${text(limit.remaining)} remaining; resets ${timestamp(limit.reset_at)}` });
247
+ }
248
+ }
249
+ if (bodyArg.rate_limit_reached_type != null)
250
+ facts.push({ section: 'Limits & credits', label: 'Limit state', value: text(record(bodyArg.rate_limit_reached_type).type) });
251
+ if (bodyArg.rate_limit_reset_credits != null) {
252
+ summary.resets = { available: count(record(bodyArg.rate_limit_reset_credits).available_count) };
253
+ facts.push({ section: 'Earned resets', summaryKey: 'resets', label: 'Available earned resets', value: String(summary.resets.available) });
254
+ }
255
+ else
256
+ facts.push({ section: 'Earned resets', summaryKey: 'resets', label: 'Available earned resets', value: 'Not returned by the limits service' });
257
+ return { facts, summary };
258
+ }
259
+ resets(bodyArg) {
260
+ const availableCount = count(bodyArg.available_count);
261
+ if (!Array.isArray(bodyArg.credits))
262
+ throw new Error('Invalid reset details.');
263
+ const facts = [{ section: 'Earned resets', summaryKey: 'resets', label: 'Earned resets (detail lookup)', value: `${availableCount} available` }];
264
+ const details = [];
265
+ for (const raw of bodyArg.credits) {
266
+ const credit = record(raw);
267
+ const expiresAt = credit.expires_at == null ? null : new Date(text(credit.expires_at)).toISOString();
268
+ const status = text(credit.status);
269
+ const kind = text(credit.reset_type);
270
+ details.push({ status, kind, expiresAt });
271
+ facts.push({ section: 'Earned resets', summaryKey: 'resetDetails', label: 'Earned reset', value: `${status}; ${kind}; ${expiresAt === null ? 'no expiry reported' : 'expires ' + expiresAt}` });
272
+ }
273
+ if (bodyArg.credits.length < availableCount)
274
+ facts.push({ section: 'Earned resets', label: 'Reset details', value: `${bodyArg.credits.length} shown; the available count includes all credits` });
275
+ // A successful detail lookup supersedes the count from the limits response.
276
+ return { facts, summary: { resets: { available: availableCount, details } } };
277
+ }
278
+ activity(bodyArg) {
279
+ const stats = record(bodyArg.stats);
280
+ const facts = [];
281
+ for (const [key, label] of [
282
+ ['lifetime_tokens', 'Lifetime tokens'], ['peak_daily_tokens', 'Peak daily tokens'],
283
+ ['longest_running_turn_sec', 'Longest turn (seconds)'], ['current_streak_days', 'Current streak (days)'], ['longest_streak_days', 'Longest streak (days)'],
284
+ ])
285
+ facts.push({ section: 'Activity', label, value: stats[key] == null ? 'Not returned' : numeric(stats[key]).toLocaleString('en-US') });
286
+ if (stats.daily_usage_buckets != null) {
287
+ if (!Array.isArray(stats.daily_usage_buckets))
288
+ throw new Error('Invalid daily usage.');
289
+ const days = stats.daily_usage_buckets.map((valueArg) => {
290
+ const day = record(valueArg);
291
+ const date = text(day.start_date);
292
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date))
293
+ throw new Error('Invalid daily date.');
294
+ return { date, tokens: numeric(day.tokens) };
295
+ }).sort((leftArg, rightArg) => rightArg.date.localeCompare(leftArg.date));
296
+ for (const day of days.slice(0, 7))
297
+ facts.push({ section: 'Daily tokens', label: `Tokens ${day.date}`, value: day.tokens.toLocaleString('en-US') });
298
+ if (days.length > 7)
299
+ facts.push({ section: 'Daily tokens', label: 'Daily activity', value: `Showing the latest 7 of ${days.length} reported days` });
300
+ }
301
+ return facts;
302
+ }
303
+ }
304
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb2RleHN0YXR1cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuY29kZXhzdGF0dXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRXJELHNHQUFzRztBQUN0RyxNQUFNLGdCQUFnQixHQUFHLHVHQUF1RyxDQUFDO0FBRWpJLE1BQU0sTUFBTSxHQUFHLENBQUMsUUFBaUIsRUFBMkIsRUFBRTtJQUM1RCxJQUFJLENBQUMsUUFBUSxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUN6SCxPQUFPLFFBQW1DLENBQUM7QUFDN0MsQ0FBQyxDQUFDO0FBQ0YsTUFBTSxPQUFPLEdBQUcsQ0FBQyxRQUFpQixFQUFVLEVBQUU7SUFDNUMsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsR0FBRyxDQUFDO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0lBQ3BJLE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQUNGLE1BQU0sSUFBSSxHQUFHLENBQUMsUUFBaUIsRUFBVSxFQUFFO0lBQ3pDLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUN2RyxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFDRixNQUFNLE9BQU8sR0FBRyxDQUFDLFFBQWlCLEVBQVcsRUFBRTtJQUM3QyxJQUFJLE9BQU8sUUFBUSxLQUFLLFNBQVM7UUFBRSxNQUFNLElBQUks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
@@ -0,0 +1,61 @@
1
+ import type { IActiveAuth, ICodexSwitcherOptions, IStashResult, IStashListing, ISwitchResult } from './interfaces.js';
2
+ import { CodexAuth } from './classes.codexauth.js';
3
+ import { CodexDaemon } from './classes.codexdaemon.js';
4
+ import { CodexHome } from './classes.codexhome.js';
5
+ import { RemoteControlStore } from './classes.remotecontrol.js';
6
+ import { StashStore } from './classes.stashstore.js';
7
+ /**
8
+ * Orchestrates stashing and restoring Codex credentials.
9
+ *
10
+ * Two invariants this class defends:
11
+ *
12
+ * 1. A credential is never destroyed or overwritten until a copy has been
13
+ * written to the stash *and read back*.
14
+ * 2. Every operation that stops the app-server starts it again, including when
15
+ * the operation fails partway. Leaving remote control down would turn a
16
+ * failed switch into a broken machine.
17
+ *
18
+ * Both stash and use quiesce the app-server first. It refreshes tokens on its
19
+ * own schedule, so reading or writing `auth.json` while it runs races that
20
+ * refresh: the copy taken could be a token the daemon has already rotated away,
21
+ * and a credential the daemon wrote after the copy would be destroyed unstashed.
22
+ */
23
+ export declare class CodexSwitcher {
24
+ readonly home: CodexHome;
25
+ readonly auth: CodexAuth;
26
+ readonly remoteControl: RemoteControlStore;
27
+ readonly stashes: StashStore;
28
+ readonly daemon: CodexDaemon;
29
+ constructor(optionsArg?: ICodexSwitcherOptions);
30
+ readActive(): IActiveAuth;
31
+ /**
32
+ * Saves the active credential under its account email, together with the
33
+ * remote-control enrollments belonging to that account, then clears the active
34
+ * slot so a different account can be logged in.
35
+ *
36
+ * `keepActive` saves without clearing, for taking a checkpoint.
37
+ */
38
+ stash(optionsArg?: {
39
+ keepActive?: boolean;
40
+ }): IStashResult;
41
+ /** Every stash, annotated with whether it is the account currently in use. */
42
+ list(): IStashListing[];
43
+ /**
44
+ * Makes a stashed account the active one.
45
+ *
46
+ * Re-running it for the account that is already active is not a no-op: it
47
+ * restores that account's enrollments, which is the repair path when remote
48
+ * control has stopped working for the current login.
49
+ */
50
+ use(emailArg: string): ISwitchResult;
51
+ drop(emailArg: string): boolean;
52
+ private assertNotKeyring;
53
+ /**
54
+ * Stops the app-server if it is up. Returns whether it was running, which is
55
+ * also the signal for whether to start it again afterwards -- a daemon that
56
+ * was down before a command stays down after it.
57
+ */
58
+ private quiesceDaemon;
59
+ /** Brings the app-server back, on the success path and the failure path alike. */
60
+ private resumeDaemon;
61
+ }
@@ -0,0 +1,226 @@
1
+ import { CodexAuth } from './classes.codexauth.js';
2
+ import { CodexDaemon } from './classes.codexdaemon.js';
3
+ import { CodexHome } from './classes.codexhome.js';
4
+ import { RemoteControlStore } from './classes.remotecontrol.js';
5
+ import { StashStore } from './classes.stashstore.js';
6
+ import { countPaired } from './helpers.js';
7
+ const KEYRING_MESSAGE = 'the active Codex credential is held in an OS keyring, which authswitch cannot move.\n' +
8
+ 'Set `auth_credentials_store_mode` to file storage in ~/.codex/config.toml and log in again to use authswitch.';
9
+ /**
10
+ * Orchestrates stashing and restoring Codex credentials.
11
+ *
12
+ * Two invariants this class defends:
13
+ *
14
+ * 1. A credential is never destroyed or overwritten until a copy has been
15
+ * written to the stash *and read back*.
16
+ * 2. Every operation that stops the app-server starts it again, including when
17
+ * the operation fails partway. Leaving remote control down would turn a
18
+ * failed switch into a broken machine.
19
+ *
20
+ * Both stash and use quiesce the app-server first. It refreshes tokens on its
21
+ * own schedule, so reading or writing `auth.json` while it runs races that
22
+ * refresh: the copy taken could be a token the daemon has already rotated away,
23
+ * and a credential the daemon wrote after the copy would be destroyed unstashed.
24
+ */
25
+ export class CodexSwitcher {
26
+ home;
27
+ auth;
28
+ remoteControl;
29
+ stashes;
30
+ daemon;
31
+ constructor(optionsArg = {}) {
32
+ this.home = new CodexHome(optionsArg.codexHome);
33
+ this.auth = new CodexAuth(this.home);
34
+ this.remoteControl = new RemoteControlStore(this.home);
35
+ this.stashes = new StashStore('codex', optionsArg.stashRoot);
36
+ this.daemon = new CodexDaemon(this.home, optionsArg.codexBinary);
37
+ }
38
+ readActive() {
39
+ return this.auth.readActive();
40
+ }
41
+ /**
42
+ * Saves the active credential under its account email, together with the
43
+ * remote-control enrollments belonging to that account, then clears the active
44
+ * slot so a different account can be logged in.
45
+ *
46
+ * `keepActive` saves without clearing, for taking a checkpoint.
47
+ */
48
+ stash(optionsArg = {}) {
49
+ const notes = [];
50
+ const problems = [];
51
+ const before = this.auth.readActive();
52
+ this.assertNotKeyring(before);
53
+ if (before.source === 'none') {
54
+ // Nothing on disk means nothing to save, and a daemon holding no
55
+ // credential cannot produce one. Fail here rather than bouncing the
56
+ // app-server -- and remote control with it -- to learn the same thing.
57
+ throw new Error(`no active Codex credential found at ${before.authFilePath}; run \`codex login\` first`);
58
+ }
59
+ const daemonWasRunning = this.quiesceDaemon(notes);
60
+ let daemonRestarted = false;
61
+ let entry;
62
+ try {
63
+ // Re-read only now that the daemon is down: whatever it may have refreshed
64
+ // between the check above and the stop is the credential we must save.
65
+ const active = this.auth.readActive();
66
+ this.assertNotKeyring(active);
67
+ if (!active.raw) {
68
+ throw new Error(`no active Codex credential found at ${active.authFilePath}`);
69
+ }
70
+ if (!active.identity) {
71
+ throw new Error(`could not identify the account behind ${active.authFilePath}; refusing to stash an unlabelled credential`);
72
+ }
73
+ const enrollments = this.remoteControl.read(active.identity.accountId);
74
+ entry = this.stashes.write(active.identity, active.raw, enrollments, this.home.dir);
75
+ if (!this.stashes.readBack(entry.email, active.raw)) {
76
+ throw new Error(`the stash for ${entry.email} could not be read back from ${this.stashes.entryDir(entry.email)}; leaving the active credential in place`);
77
+ }
78
+ if (!optionsArg.keepActive) {
79
+ this.auth.clearActive();
80
+ }
81
+ if (enrollments.length === 0) {
82
+ notes.push('no remote-control enrollment found for this account');
83
+ }
84
+ }
85
+ finally {
86
+ daemonRestarted = this.resumeDaemon(daemonWasRunning, notes, problems);
87
+ }
88
+ return {
89
+ entry,
90
+ daemonRestarted,
91
+ complete: problems.length === 0,
92
+ notes,
93
+ problems,
94
+ };
95
+ }
96
+ /** Every stash, annotated with whether it is the account currently in use. */
97
+ list() {
98
+ const active = this.auth.readActive();
99
+ return this.stashes.list().map((entryArg) => {
100
+ const paired = countPaired(entryArg.enrollments);
101
+ return {
102
+ ...entryArg,
103
+ slug: this.stashes.slugFor(entryArg.email),
104
+ isActive: active.identity !== null && active.identity.email === entryArg.email && active.identity.accountId === entryArg.accountId && active.identity.kind === entryArg.kind,
105
+ enrollmentsTotal: entryArg.enrollments.length,
106
+ enrollmentsPaired: paired,
107
+ hasRemoteControl: paired > 0,
108
+ };
109
+ });
110
+ }
111
+ /**
112
+ * Makes a stashed account the active one.
113
+ *
114
+ * Re-running it for the account that is already active is not a no-op: it
115
+ * restores that account's enrollments, which is the repair path when remote
116
+ * control has stopped working for the current login.
117
+ */
118
+ use(emailArg) {
119
+ const target = this.stashes.readMeta(emailArg);
120
+ let targetAuth = this.stashes.readAuth(emailArg);
121
+ if (!target || targetAuth === null) {
122
+ throw new Error(`no stash for "${emailArg}"`);
123
+ }
124
+ const targetIdentity = this.auth.identityFromRaw(targetAuth);
125
+ if (!targetIdentity || targetIdentity.email !== target.email || targetIdentity.accountId !== target.accountId || targetIdentity.kind !== target.kind) {
126
+ throw new Error('the saved Codex credential does not match its metadata; refusing to switch');
127
+ }
128
+ const notes = [];
129
+ const problems = [];
130
+ this.assertNotKeyring(this.auth.readActive());
131
+ const daemonWasRunning = this.quiesceDaemon(notes);
132
+ let enrollmentsRestored = 0;
133
+ let fromEmail = null;
134
+ let daemonRestarted = false;
135
+ try {
136
+ // Everything below reads the credential state only after the daemon is
137
+ // down, so nothing it refreshed mid-command is missed or overwritten.
138
+ const active = this.auth.readActive();
139
+ this.assertNotKeyring(active);
140
+ fromEmail = active.identity?.email ?? null;
141
+ if (fromEmail !== null && fromEmail !== target.email) {
142
+ // Never drop a credential on the floor: check the outgoing one into the
143
+ // stash, and prove it landed, before the incoming one overwrites it.
144
+ const outgoingEnrollments = this.remoteControl.read(active.identity.accountId);
145
+ this.stashes.write(active.identity, active.raw, outgoingEnrollments, this.home.dir);
146
+ if (!this.stashes.readBack(fromEmail, active.raw)) {
147
+ throw new Error(`could not save the outgoing credential for ${fromEmail}; aborting before it would be overwritten`);
148
+ }
149
+ notes.push(`stashed the outgoing credential for ${fromEmail}`);
150
+ }
151
+ else if (fromEmail === null && active.raw) {
152
+ throw new Error(`refusing to overwrite the unidentifiable credential at ${active.authFilePath}; move it aside manually first`);
153
+ }
154
+ if (fromEmail === target.email) {
155
+ if (active.identity.accountId !== target.accountId || active.identity.kind !== target.kind) {
156
+ throw new Error('the active and saved Codex accounts share an email but have different identities; refusing to overwrite either credential');
157
+ }
158
+ // A daemon refresh may have made the saved tokens obsolete. Keep the current
159
+ // login while restoring the saved pairing, and verify its updated stash.
160
+ targetAuth = active.raw;
161
+ this.stashes.write(active.identity, targetAuth, target.enrollments, this.home.dir);
162
+ if (!this.stashes.readBack(target.email, targetAuth))
163
+ throw new Error('could not verify the current credential in its stash; refusing to overwrite it');
164
+ notes.push(`${target.email} was already active; refreshing its remote-control enrollments`);
165
+ }
166
+ this.auth.writeActive(targetAuth);
167
+ if (target.enrollments.length > 0) {
168
+ enrollmentsRestored = this.remoteControl.restore(target.enrollments);
169
+ notes.push(`restored ${enrollmentsRestored} remote-control enrollment(s)`);
170
+ }
171
+ else {
172
+ notes.push('no remote-control enrollment was stashed for this account');
173
+ }
174
+ }
175
+ finally {
176
+ daemonRestarted = this.resumeDaemon(daemonWasRunning, notes, problems);
177
+ }
178
+ return {
179
+ from: fromEmail,
180
+ to: target.email,
181
+ enrollmentsRestored,
182
+ daemonRestarted,
183
+ complete: problems.length === 0,
184
+ notes,
185
+ problems,
186
+ };
187
+ }
188
+ drop(emailArg) {
189
+ return this.stashes.remove(emailArg);
190
+ }
191
+ assertNotKeyring(activeArg) {
192
+ if (activeArg.source === 'keyring') {
193
+ throw new Error(KEYRING_MESSAGE);
194
+ }
195
+ }
196
+ /**
197
+ * Stops the app-server if it is up. Returns whether it was running, which is
198
+ * also the signal for whether to start it again afterwards -- a daemon that
199
+ * was down before a command stays down after it.
200
+ */
201
+ quiesceDaemon(notesArg) {
202
+ if (!this.daemon.isDaemonRunning()) {
203
+ notesArg.push('app-server was not running');
204
+ return false;
205
+ }
206
+ const stopResult = this.daemon.stop();
207
+ if (!stopResult.ok) {
208
+ throw new Error(`could not stop the Codex app-server, refusing to touch credentials underneath it: ${this.daemon.describeFailure(stopResult)}`);
209
+ }
210
+ return true;
211
+ }
212
+ /** Brings the app-server back, on the success path and the failure path alike. */
213
+ resumeDaemon(wasRunningArg, notesArg, problemsArg) {
214
+ if (!wasRunningArg) {
215
+ return false;
216
+ }
217
+ const startResult = this.daemon.start();
218
+ if (!startResult.ok) {
219
+ problemsArg.push(`the app-server did not come back up (${this.daemon.describeFailure(startResult)}); remote control is down until you run \`codex app-server daemon start\``);
220
+ return false;
221
+ }
222
+ notesArg.push('app-server restarted');
223
+ return true;
224
+ }
225
+ }
226
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb2RleHN3aXRjaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5jb2RleHN3aXRjaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU9BLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTNDLE1BQU0sZUFBZSxHQUNuQix1RkFBdUY7SUFDdkYsK0dBQStHLENBQUM7QUFFbEg7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFDUixJQUFJLENBQVk7SUFDaEIsSUFBSSxDQUFZO0lBQ2hCLGFBQWEsQ0FBcUI7SUFDbEMsT0FBTyxDQUFhO0lBQ3BCLE1BQU0sQ0FBYztJQUVwQyxZQUFZLGFBQW9DLEVBQUU7UUFDaEQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDckMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksVUFBVSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLFdBQVcsQ0FBQyxJ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