opencode-copilot-account-switcher 0.14.26 → 0.14.28
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/dist/plugin.js +16 -0
- package/dist/providers/codex-menu-adapter.d.ts +2 -2
- package/dist/providers/codex-menu-adapter.js +56 -15
- package/dist/providers/copilot-menu-adapter.js +1 -1
- package/dist/upstream/codex-loader-adapter.d.ts +30 -0
- package/dist/upstream/codex-loader-adapter.js +25 -0
- package/dist/upstream/codex-plugin.snapshot.d.ts +19 -0
- package/dist/upstream/codex-plugin.snapshot.js +555 -19
- package/dist/wechat/bind-flow.js +2 -1
- package/dist/wechat/compat/jiti-loader.d.ts +11 -0
- package/dist/wechat/compat/jiti-loader.js +27 -0
- package/dist/wechat/compat/openclaw-account-helpers.js +2 -2
- package/dist/wechat/compat/openclaw-public-entry.js +2 -2
- package/dist/wechat/compat/openclaw-sync-buf.js +2 -2
- package/dist/wechat/compat/openclaw-updates-send.js +2 -2
- package/dist/wechat/compat/qrcode-terminal-loader.d.ts +12 -0
- package/dist/wechat/compat/qrcode-terminal-loader.js +16 -0
- package/package.json +1 -1
- package/dist/codex-oauth.d.ts +0 -64
- package/dist/codex-oauth.js +0 -344
package/dist/plugin.js
CHANGED
|
@@ -10,6 +10,7 @@ import { brokerStartupDiagnosticsPath, ensureWechatStateLayout } from "./wechat/
|
|
|
10
10
|
import { createCodexMenuAdapter } from "./providers/codex-menu-adapter.js";
|
|
11
11
|
import { createCopilotMenuAdapter } from "./providers/copilot-menu-adapter.js";
|
|
12
12
|
import { createProviderRegistry } from "./providers/registry.js";
|
|
13
|
+
import { loadOfficialCodexAuthMethods } from "./upstream/codex-loader-adapter.js";
|
|
13
14
|
import { isTTY } from "./ui/ansi.js";
|
|
14
15
|
import { showMenu } from "./ui/menu.js";
|
|
15
16
|
import { select, selectMany } from "./ui/select.js";
|
|
@@ -73,6 +74,14 @@ function toSharedRuntimeAction(action) {
|
|
|
73
74
|
return { type: "provider", name: "toggle-experimental-slash-commands" };
|
|
74
75
|
if (action.type === "toggle-network-retry")
|
|
75
76
|
return { type: "provider", name: "toggle-network-retry" };
|
|
77
|
+
if (action.type === "toggle-wechat-notifications")
|
|
78
|
+
return { type: "provider", name: "toggle-wechat-notifications" };
|
|
79
|
+
if (action.type === "toggle-wechat-question-notify")
|
|
80
|
+
return { type: "provider", name: "toggle-wechat-question-notify" };
|
|
81
|
+
if (action.type === "toggle-wechat-permission-notify")
|
|
82
|
+
return { type: "provider", name: "toggle-wechat-permission-notify" };
|
|
83
|
+
if (action.type === "toggle-wechat-session-error-notify")
|
|
84
|
+
return { type: "provider", name: "toggle-wechat-session-error-notify" };
|
|
76
85
|
if (action.type === "wechat-bind")
|
|
77
86
|
return { type: "provider", name: "wechat-bind" };
|
|
78
87
|
if (action.type === "wechat-rebind")
|
|
@@ -386,6 +395,13 @@ async function createAccountSwitcherPlugin(input, provider) {
|
|
|
386
395
|
}
|
|
387
396
|
const adapter = createCodexMenuAdapter({
|
|
388
397
|
client: codexClient,
|
|
398
|
+
loadOfficialCodexAuthMethods: () => loadOfficialCodexAuthMethods({
|
|
399
|
+
client: {
|
|
400
|
+
auth: {
|
|
401
|
+
set: async (value) => client.auth.set(value),
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
}),
|
|
389
405
|
readCommonSettings: readCommonSettingsStore,
|
|
390
406
|
writeCommonSettings: async (settings) => {
|
|
391
407
|
await writeCommonSettingsStore(settings);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CodexStatusFetcherResult } from "../codex-status-fetcher.js";
|
|
2
|
-
import { type
|
|
2
|
+
import { type OfficialCodexAuthMethod } from "../upstream/codex-loader-adapter.js";
|
|
3
3
|
import { type CodexAccountEntry, type CodexStoreFile } from "../codex-store.js";
|
|
4
4
|
import type { ProviderMenuAdapter } from "../menu-runtime.js";
|
|
5
5
|
import { type AccountEntry } from "../store.js";
|
|
@@ -42,7 +42,7 @@ type AdapterDependencies = {
|
|
|
42
42
|
};
|
|
43
43
|
accountId?: string;
|
|
44
44
|
}) => Promise<CodexStatusFetcherResult>;
|
|
45
|
-
|
|
45
|
+
loadOfficialCodexAuthMethods?: () => Promise<OfficialCodexAuthMethod[]>;
|
|
46
46
|
readCommonSettings?: () => Promise<CommonSettingsStore>;
|
|
47
47
|
writeCommonSettings?: (settings: CommonSettingsStore, meta?: WriteMeta) => Promise<void>;
|
|
48
48
|
};
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import { stdin as input, stdout as output } from "node:process";
|
|
3
3
|
import { fetchCodexStatus } from "../codex-status-fetcher.js";
|
|
4
|
-
import {
|
|
4
|
+
import { loadOfficialCodexAuthMethods, } from "../upstream/codex-loader-adapter.js";
|
|
5
5
|
import { getActiveCodexAccount, readCodexStore, writeCodexStore, } from "../codex-store.js";
|
|
6
6
|
import { recoverInvalidCodexAccount } from "../codex-invalid-account.js";
|
|
7
7
|
import { readAuth } from "../store.js";
|
|
8
8
|
import { readCommonSettingsStore, writeCommonSettingsStore, } from "../common-settings-store.js";
|
|
9
9
|
import { applyCommonSettingsAction } from "../common-settings-actions.js";
|
|
10
|
-
|
|
10
|
+
function pickOfficialOauthMethodByKind(methods, kind) {
|
|
11
|
+
return methods.find((method) => {
|
|
12
|
+
if (method.type !== "oauth")
|
|
13
|
+
return false;
|
|
14
|
+
if (typeof method.authorize !== "function")
|
|
15
|
+
return false;
|
|
16
|
+
const label = method.label.toLowerCase();
|
|
17
|
+
if (kind === "browser")
|
|
18
|
+
return label.includes("browser");
|
|
19
|
+
return label.includes("headless") || label.includes("device");
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function parseOfficialOauthSelection(raw) {
|
|
23
|
+
const value = raw.trim().toLowerCase();
|
|
24
|
+
if (!value)
|
|
25
|
+
return "cancel";
|
|
26
|
+
if (value === "1" || value === "browser" || value === "b")
|
|
27
|
+
return "browser";
|
|
28
|
+
if (value === "2" || value === "headless" || value === "h" || value === "device")
|
|
29
|
+
return "headless";
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
11
32
|
function pickName(input) {
|
|
12
33
|
const accountId = input.accountId?.trim();
|
|
13
34
|
if (accountId)
|
|
@@ -74,7 +95,14 @@ export function createCodexMenuAdapter(inputDeps) {
|
|
|
74
95
|
});
|
|
75
96
|
const loadAuth = inputDeps.readAuthEntries ?? readAuth;
|
|
76
97
|
const fetchStatus = inputDeps.fetchStatus ?? ((input) => fetchCodexStatus(input));
|
|
77
|
-
const
|
|
98
|
+
const loadOfficialMethods = inputDeps.loadOfficialCodexAuthMethods
|
|
99
|
+
?? (() => loadOfficialCodexAuthMethods({
|
|
100
|
+
client: {
|
|
101
|
+
auth: {
|
|
102
|
+
set: async (value) => inputDeps.client.auth.set(value),
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
}));
|
|
78
106
|
const readCommonSettings = inputDeps.readCommonSettings ?? readCommonSettingsStore;
|
|
79
107
|
const writeCommonSettings = async (settings, meta) => {
|
|
80
108
|
if (inputDeps.writeCommonSettings) {
|
|
@@ -244,34 +272,46 @@ export function createCodexMenuAdapter(inputDeps) {
|
|
|
244
272
|
return true;
|
|
245
273
|
},
|
|
246
274
|
authorizeNewAccount: async () => {
|
|
247
|
-
const
|
|
248
|
-
|
|
275
|
+
const methods = await loadOfficialMethods();
|
|
276
|
+
const browserMethod = pickOfficialOauthMethodByKind(methods, "browser");
|
|
277
|
+
const headlessMethod = pickOfficialOauthMethodByKind(methods, "headless");
|
|
278
|
+
const selectedKey = parseOfficialOauthSelection(await prompt("Choose Codex auth method (1/browser/b, 2/headless/h/device, Enter to cancel): "));
|
|
279
|
+
if (selectedKey === "cancel" || !selectedKey)
|
|
280
|
+
return undefined;
|
|
281
|
+
const selectedMethod = selectedKey === "browser" ? browserMethod : headlessMethod;
|
|
282
|
+
if (!selectedMethod || typeof selectedMethod.authorize !== "function")
|
|
283
|
+
return undefined;
|
|
284
|
+
const pending = await selectedMethod.authorize();
|
|
285
|
+
if (pending.method && pending.method !== "auto") {
|
|
286
|
+
throw new Error(`Unsupported official Codex auth method: ${pending.method}`);
|
|
287
|
+
}
|
|
288
|
+
if (typeof pending.callback !== "function")
|
|
289
|
+
return undefined;
|
|
290
|
+
const result = await pending.callback();
|
|
291
|
+
if (result.type !== "success" || (!result.refresh && !result.access))
|
|
249
292
|
return undefined;
|
|
250
|
-
const refresh =
|
|
251
|
-
const access =
|
|
293
|
+
const refresh = result.refresh ?? result.access;
|
|
294
|
+
const access = result.access ?? result.refresh;
|
|
252
295
|
await inputDeps.client.auth.set({
|
|
253
296
|
path: { id: "openai" },
|
|
254
297
|
body: {
|
|
255
298
|
type: "oauth",
|
|
256
299
|
refresh,
|
|
257
300
|
access,
|
|
258
|
-
expires:
|
|
259
|
-
accountId:
|
|
301
|
+
expires: result.expires,
|
|
302
|
+
accountId: result.accountId,
|
|
260
303
|
},
|
|
261
304
|
});
|
|
262
305
|
return {
|
|
263
306
|
name: pickName({
|
|
264
|
-
accountId:
|
|
265
|
-
email: oauth.email,
|
|
307
|
+
accountId: result.accountId,
|
|
266
308
|
fallback: `openai-${now()}`,
|
|
267
309
|
}),
|
|
268
310
|
providerId: "openai",
|
|
269
|
-
workspaceName: oauth.workspaceName,
|
|
270
311
|
refresh,
|
|
271
312
|
access,
|
|
272
|
-
expires:
|
|
273
|
-
accountId:
|
|
274
|
-
email: oauth.email,
|
|
313
|
+
expires: result.expires,
|
|
314
|
+
accountId: result.accountId,
|
|
275
315
|
source: "manual",
|
|
276
316
|
addedAt: now(),
|
|
277
317
|
};
|
|
@@ -384,6 +424,7 @@ export function createCodexMenuAdapter(inputDeps) {
|
|
|
384
424
|
return false;
|
|
385
425
|
}
|
|
386
426
|
if (action.name === "wechat-bind" || action.name === "wechat-rebind") {
|
|
427
|
+
const { runWechatBindFlow } = await import("../wechat/bind-flow.js");
|
|
387
428
|
await runWechatBindFlow({
|
|
388
429
|
action: action.name,
|
|
389
430
|
readCommonSettings,
|
|
@@ -5,7 +5,6 @@ import { getGitHubToken, normalizeDomain } from "../copilot-api-helpers.js";
|
|
|
5
5
|
import { listAssignableAccountsForModel, listKnownCopilotModels, rewriteModelAccountAssignments, } from "../model-account-map.js";
|
|
6
6
|
import { applyMenuAction, persistAccountSwitch } from "../plugin-actions.js";
|
|
7
7
|
import { readCommonSettingsStore, writeCommonSettingsStore, } from "../common-settings-store.js";
|
|
8
|
-
import { runWechatBindFlow } from "../wechat/bind-flow.js";
|
|
9
8
|
import { select, selectMany } from "../ui/select.js";
|
|
10
9
|
import { authPath, readAuth, readStore } from "../store.js";
|
|
11
10
|
const CLIENT_ID = "Ov23li8tweQw6odWQebz";
|
|
@@ -742,6 +741,7 @@ export function createCopilotMenuAdapter(inputDeps) {
|
|
|
742
741
|
return false;
|
|
743
742
|
}
|
|
744
743
|
if (action.name === "wechat-bind" || action.name === "wechat-rebind") {
|
|
744
|
+
const { runWechatBindFlow } = await import("../wechat/bind-flow.js");
|
|
745
745
|
await runWechatBindFlow({
|
|
746
746
|
action: action.name,
|
|
747
747
|
readCommonSettings,
|
|
@@ -36,6 +36,35 @@ export type OfficialCodexChatHeadersHook = (input: {
|
|
|
36
36
|
}, output: {
|
|
37
37
|
headers: Record<string, string>;
|
|
38
38
|
}) => Promise<void>;
|
|
39
|
+
type OfficialCodexAuthResult = {
|
|
40
|
+
type: "success";
|
|
41
|
+
refresh: string;
|
|
42
|
+
access: string;
|
|
43
|
+
expires: number;
|
|
44
|
+
accountId?: string;
|
|
45
|
+
} | {
|
|
46
|
+
type: "failed";
|
|
47
|
+
};
|
|
48
|
+
type OfficialCodexAuthorizePending = {
|
|
49
|
+
url: string;
|
|
50
|
+
instructions?: string;
|
|
51
|
+
method?: string;
|
|
52
|
+
callback?: () => Promise<OfficialCodexAuthResult>;
|
|
53
|
+
};
|
|
54
|
+
export type OfficialCodexAuthMethod = {
|
|
55
|
+
label: string;
|
|
56
|
+
type: string;
|
|
57
|
+
authorize?: () => Promise<OfficialCodexAuthorizePending>;
|
|
58
|
+
};
|
|
59
|
+
export declare function loadOfficialCodexAuthMethods(input?: {
|
|
60
|
+
client?: {
|
|
61
|
+
auth?: {
|
|
62
|
+
set?: (value: unknown) => Promise<unknown>;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
baseFetch?: typeof fetch;
|
|
66
|
+
version?: string;
|
|
67
|
+
}): Promise<OfficialCodexAuthMethod[]>;
|
|
39
68
|
export declare function loadOfficialCodexConfig(input: {
|
|
40
69
|
getAuth: () => Promise<CodexAuthState | undefined>;
|
|
41
70
|
provider?: CodexProviderConfig;
|
|
@@ -67,3 +96,4 @@ export declare function loadOfficialCodexChatHeaders(input?: {
|
|
|
67
96
|
baseFetch?: typeof fetch;
|
|
68
97
|
version?: string;
|
|
69
98
|
}): Promise<OfficialCodexChatHeadersHook>;
|
|
99
|
+
export {};
|
|
@@ -13,6 +13,31 @@ async function loadOfficialHooks(input) {
|
|
|
13
13
|
return hooks;
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
|
+
export async function loadOfficialCodexAuthMethods(input = {}) {
|
|
17
|
+
const hooks = await loadOfficialHooks(input);
|
|
18
|
+
const methods = hooks.auth?.methods;
|
|
19
|
+
if (!Array.isArray(methods)) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
return methods.map((method) => {
|
|
23
|
+
if (typeof method.authorize !== "function") {
|
|
24
|
+
return method;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
...method,
|
|
28
|
+
authorize: async () => {
|
|
29
|
+
const pending = await runWithOfficialBridge(input, () => method.authorize());
|
|
30
|
+
if (!pending || typeof pending.callback !== "function") {
|
|
31
|
+
return pending;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
...pending,
|
|
35
|
+
callback: () => runWithOfficialBridge(input, () => pending.callback()),
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
}
|
|
16
41
|
export async function loadOfficialCodexConfig(input) {
|
|
17
42
|
const hooks = await loadOfficialHooks({
|
|
18
43
|
client: input.client,
|
|
@@ -9,5 +9,24 @@ declare const officialCodexExportBridge: {
|
|
|
9
9
|
version?: string;
|
|
10
10
|
} | undefined, fn: () => Promise<any>): Promise<any>;
|
|
11
11
|
};
|
|
12
|
+
export interface IdTokenClaims {
|
|
13
|
+
chatgpt_account_id?: string;
|
|
14
|
+
organizations?: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
}>;
|
|
17
|
+
email?: string;
|
|
18
|
+
"https://api.openai.com/auth"?: {
|
|
19
|
+
chatgpt_account_id?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare function parseJwtClaims(token: string): IdTokenClaims | undefined;
|
|
23
|
+
export declare function extractAccountIdFromClaims(claims: IdTokenClaims): string | undefined;
|
|
24
|
+
export declare function extractAccountId(tokens: TokenResponse): string | undefined;
|
|
25
|
+
interface TokenResponse {
|
|
26
|
+
id_token: string;
|
|
27
|
+
access_token: string;
|
|
28
|
+
refresh_token: string;
|
|
29
|
+
expires_in?: number;
|
|
30
|
+
}
|
|
12
31
|
export declare function CodexAuthPlugin(input: PluginInput): Promise<Hooks>;
|
|
13
32
|
export { officialCodexExportBridge };
|