opencode-copilot-account-switcher 0.13.3 → 0.13.5
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/codex-network-retry.d.ts +2 -0
- package/dist/codex-network-retry.js +9 -0
- package/dist/codex-status-fetcher.d.ts +1 -0
- package/dist/codex-status-fetcher.js +10 -0
- package/dist/codex-store.js +11 -8
- package/dist/common-settings-actions.d.ts +15 -0
- package/dist/common-settings-actions.js +42 -0
- package/dist/common-settings-store.d.ts +20 -0
- package/dist/common-settings-store.js +125 -0
- package/dist/menu-runtime.d.ts +1 -0
- package/dist/plugin-actions.d.ts +9 -0
- package/dist/plugin-actions.js +15 -35
- package/dist/plugin-hooks.d.ts +5 -0
- package/dist/plugin-hooks.js +167 -43
- package/dist/plugin.js +54 -33
- package/dist/providers/codex-menu-adapter.d.ts +5 -2
- package/dist/providers/codex-menu-adapter.js +23 -0
- package/dist/providers/copilot-menu-adapter.d.ts +3 -0
- package/dist/providers/copilot-menu-adapter.js +5 -0
- package/dist/providers/descriptor.d.ts +3 -2
- package/dist/providers/descriptor.js +4 -1
- package/dist/providers/registry.d.ts +1 -1
- package/dist/providers/registry.js +38 -2
- package/dist/retry/codex-policy.d.ts +5 -0
- package/dist/retry/codex-policy.js +75 -0
- package/dist/retry/common-policy.d.ts +37 -0
- package/dist/retry/common-policy.js +68 -0
- package/dist/retry/copilot-policy.d.ts +1 -10
- package/dist/retry/copilot-policy.js +24 -58
- package/dist/store-paths.d.ts +6 -0
- package/dist/store-paths.js +24 -0
- package/dist/store.js +34 -8
- package/dist/ui/menu.d.ts +3 -0
- package/dist/ui/menu.js +57 -46
- package/dist/upstream/codex-loader-adapter.d.ts +69 -0
- package/dist/upstream/codex-loader-adapter.js +55 -0
- package/dist/upstream/codex-plugin.snapshot.d.ts +13 -0
- package/dist/upstream/codex-plugin.snapshot.js +98 -0
- package/package.json +3 -1
package/dist/ui/menu.js
CHANGED
|
@@ -10,10 +10,10 @@ function defaultMenuCapabilities(provider) {
|
|
|
10
10
|
checkModels: false,
|
|
11
11
|
defaultAccountGroup: false,
|
|
12
12
|
assignModels: false,
|
|
13
|
-
loopSafety:
|
|
14
|
-
policyScope:
|
|
15
|
-
experimentalSlashCommands:
|
|
16
|
-
networkRetry:
|
|
13
|
+
loopSafety: true,
|
|
14
|
+
policyScope: true,
|
|
15
|
+
experimentalSlashCommands: true,
|
|
16
|
+
networkRetry: true,
|
|
17
17
|
syntheticAgentInitiator: false,
|
|
18
18
|
};
|
|
19
19
|
}
|
|
@@ -39,6 +39,8 @@ export function getMenuCopy(language = "zh", provider = "copilot") {
|
|
|
39
39
|
menuSubtitle: "Select an action or account",
|
|
40
40
|
switchLanguageLabel: "切换到中文",
|
|
41
41
|
actionsHeading: "Actions",
|
|
42
|
+
commonSettingsHeading: "Common settings",
|
|
43
|
+
providerSettingsHeading: "Provider settings",
|
|
42
44
|
addAccount: "Add account",
|
|
43
45
|
addAccountHint: "OpenAI OAuth login",
|
|
44
46
|
importAuth: "Import from auth.json",
|
|
@@ -75,6 +77,8 @@ export function getMenuCopy(language = "zh", provider = "copilot") {
|
|
|
75
77
|
menuSubtitle: "请选择操作或账号",
|
|
76
78
|
switchLanguageLabel: "Switch to English",
|
|
77
79
|
actionsHeading: "操作",
|
|
80
|
+
commonSettingsHeading: "通用设置",
|
|
81
|
+
providerSettingsHeading: "Provider 专属设置",
|
|
78
82
|
addAccount: "添加账号",
|
|
79
83
|
addAccountHint: "OpenAI OAuth 登录",
|
|
80
84
|
importAuth: "从 auth.json 导入",
|
|
@@ -112,6 +116,8 @@ export function getMenuCopy(language = "zh", provider = "copilot") {
|
|
|
112
116
|
menuSubtitle: "Select an action or account",
|
|
113
117
|
switchLanguageLabel: "切换到中文",
|
|
114
118
|
actionsHeading: "Actions",
|
|
119
|
+
commonSettingsHeading: "Common settings",
|
|
120
|
+
providerSettingsHeading: "Provider settings",
|
|
115
121
|
addAccount: "Add account",
|
|
116
122
|
addAccountHint: "device login or manual",
|
|
117
123
|
importAuth: "Import from auth.json",
|
|
@@ -132,9 +138,9 @@ export function getMenuCopy(language = "zh", provider = "copilot") {
|
|
|
132
138
|
experimentalSlashCommandsOn: "Experimental slash commands: On",
|
|
133
139
|
experimentalSlashCommandsOff: "Experimental slash commands: Off",
|
|
134
140
|
experimentalSlashCommandsHint: "Controls whether /copilot-status, /copilot-compact, /copilot-stop-tool, /copilot-inject, and /copilot-policy-all-models are registered",
|
|
135
|
-
retryOn: "
|
|
136
|
-
retryOff: "
|
|
137
|
-
retryHint: "Helps recover some requests after
|
|
141
|
+
retryOn: "Network Retry: On",
|
|
142
|
+
retryOff: "Network Retry: Off",
|
|
143
|
+
retryHint: "Helps recover some requests after retries or malformed responses",
|
|
138
144
|
syntheticInitiatorOn: "Send synthetic messages as agent: On",
|
|
139
145
|
syntheticInitiatorOff: "Send synthetic messages as agent: Off",
|
|
140
146
|
syntheticInitiatorHint: "Changes upstream behavior; misuse may increase billing risk or trigger abuse signals",
|
|
@@ -148,6 +154,8 @@ export function getMenuCopy(language = "zh", provider = "copilot") {
|
|
|
148
154
|
menuSubtitle: "请选择操作或账号",
|
|
149
155
|
switchLanguageLabel: "Switch to English",
|
|
150
156
|
actionsHeading: "操作",
|
|
157
|
+
commonSettingsHeading: "通用设置",
|
|
158
|
+
providerSettingsHeading: "Provider 专属设置",
|
|
151
159
|
addAccount: "添加账号",
|
|
152
160
|
addAccountHint: "设备登录或手动录入",
|
|
153
161
|
importAuth: "从 auth.json 导入",
|
|
@@ -168,9 +176,9 @@ export function getMenuCopy(language = "zh", provider = "copilot") {
|
|
|
168
176
|
experimentalSlashCommandsOn: "实验性 Slash Commands:已开启",
|
|
169
177
|
experimentalSlashCommandsOff: "实验性 Slash Commands:已关闭",
|
|
170
178
|
experimentalSlashCommandsHint: "控制 /copilot-status、/copilot-compact、/copilot-stop-tool、/copilot-inject、/copilot-policy-all-models 是否注册",
|
|
171
|
-
retryOn: "
|
|
172
|
-
retryOff: "
|
|
173
|
-
retryHint: "
|
|
179
|
+
retryOn: "Network Retry:已开启",
|
|
180
|
+
retryOff: "Network Retry:已关闭",
|
|
181
|
+
retryHint: "请求异常时可自动重试并修复部分请求",
|
|
174
182
|
syntheticInitiatorOn: "synthetic 消息按 agent 身份发送:已开启",
|
|
175
183
|
syntheticInitiatorOff: "synthetic 消息按 agent 身份发送:已关闭",
|
|
176
184
|
syntheticInitiatorHint: "会改变与 upstream 的默认行为;误用可能带来异常计费或 abuse 风险",
|
|
@@ -215,34 +223,30 @@ export function buildMenuItems(input) {
|
|
|
215
223
|
capabilities.checkModels = false;
|
|
216
224
|
capabilities.defaultAccountGroup = false;
|
|
217
225
|
capabilities.assignModels = false;
|
|
218
|
-
capabilities.loopSafety = false;
|
|
219
|
-
capabilities.policyScope = false;
|
|
220
|
-
capabilities.experimentalSlashCommands = false;
|
|
221
|
-
capabilities.networkRetry = false;
|
|
222
226
|
capabilities.syntheticAgentInitiator = false;
|
|
223
227
|
}
|
|
224
228
|
const quotaHint = input.lastQuotaRefresh ? `last ${formatRelativeTime(input.lastQuotaRefresh)}` : undefined;
|
|
225
229
|
const loopSafetyProviderScope = input.loopSafetyProviderScope ?? "copilot-only";
|
|
226
230
|
const experimentalSlashCommandsEnabled = input.experimentalSlashCommandsEnabled !== false;
|
|
227
|
-
const
|
|
231
|
+
const providerActions = [
|
|
228
232
|
{ label: copy.actionsHeading, value: { type: "cancel" }, kind: "heading" },
|
|
229
233
|
{ label: copy.switchLanguageLabel, value: { type: "toggle-language" }, color: "cyan" },
|
|
230
234
|
{ label: copy.addAccount, value: { type: "add" }, color: "cyan", hint: copy.addAccountHint },
|
|
231
235
|
];
|
|
232
236
|
if (capabilities.importAuth) {
|
|
233
|
-
|
|
237
|
+
providerActions.push({ label: copy.importAuth, value: { type: "import" }, color: "cyan" });
|
|
234
238
|
}
|
|
235
239
|
if (capabilities.quota) {
|
|
236
|
-
|
|
240
|
+
providerActions.push({ label: copy.checkQuotas, value: { type: "quota" }, color: "cyan", hint: quotaHint });
|
|
237
241
|
}
|
|
238
242
|
if (capabilities.refreshIdentity) {
|
|
239
|
-
|
|
243
|
+
providerActions.push({ label: copy.refreshIdentity, value: { type: "refresh-identity" }, color: "cyan" });
|
|
240
244
|
}
|
|
241
245
|
if (capabilities.checkModels) {
|
|
242
|
-
|
|
246
|
+
providerActions.push({ label: copy.checkModels, value: { type: "check-models" }, color: "cyan" });
|
|
243
247
|
}
|
|
244
248
|
if (capabilities.defaultAccountGroup) {
|
|
245
|
-
|
|
249
|
+
providerActions.push({
|
|
246
250
|
label: copy.defaultAccountGroup,
|
|
247
251
|
value: { type: "configure-default-group" },
|
|
248
252
|
color: "cyan",
|
|
@@ -250,54 +254,56 @@ export function buildMenuItems(input) {
|
|
|
250
254
|
});
|
|
251
255
|
}
|
|
252
256
|
if (capabilities.assignModels) {
|
|
253
|
-
|
|
257
|
+
providerActions.push({
|
|
254
258
|
label: copy.assignModels,
|
|
255
259
|
value: { type: "assign-models" },
|
|
256
260
|
color: "cyan",
|
|
257
261
|
hint: input.modelAccountAssignmentCount ? `${input.modelAccountAssignmentCount} groups` : undefined,
|
|
258
262
|
});
|
|
259
263
|
}
|
|
260
|
-
|
|
261
|
-
label:
|
|
262
|
-
|
|
263
|
-
color: "cyan",
|
|
264
|
-
hint: input.refresh ? `${input.refresh.minutes}m` : undefined,
|
|
265
|
-
});
|
|
266
|
-
actions.push({ label: copy.setRefresh, value: { type: "set-interval" }, color: "cyan" });
|
|
267
|
-
if (capabilities.loopSafety) {
|
|
268
|
-
actions.push({
|
|
264
|
+
const commonSettings = [
|
|
265
|
+
{ label: copy.commonSettingsHeading, value: { type: "cancel" }, kind: "heading" },
|
|
266
|
+
{
|
|
269
267
|
label: input.loopSafetyEnabled ? copy.loopSafetyOn : copy.loopSafetyOff,
|
|
270
268
|
value: { type: "toggle-loop-safety" },
|
|
271
269
|
color: "cyan",
|
|
272
270
|
hint: copy.loopSafetyHint,
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
actions.push({
|
|
271
|
+
disabled: !capabilities.loopSafety,
|
|
272
|
+
},
|
|
273
|
+
{
|
|
277
274
|
label: loopSafetyProviderScope === "all-models" ? copy.policyScopeAllModels : copy.policyScopeCopilotOnly,
|
|
278
275
|
value: { type: "toggle-loop-safety-provider-scope" },
|
|
279
276
|
color: "cyan",
|
|
280
277
|
hint: copy.policyScopeHint,
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
actions.push({
|
|
278
|
+
disabled: !capabilities.policyScope,
|
|
279
|
+
},
|
|
280
|
+
{
|
|
285
281
|
label: experimentalSlashCommandsEnabled ? copy.experimentalSlashCommandsOn : copy.experimentalSlashCommandsOff,
|
|
286
282
|
value: { type: "toggle-experimental-slash-commands" },
|
|
287
283
|
color: "cyan",
|
|
288
284
|
hint: copy.experimentalSlashCommandsHint,
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
actions.push({
|
|
285
|
+
disabled: !capabilities.experimentalSlashCommands,
|
|
286
|
+
},
|
|
287
|
+
{
|
|
293
288
|
label: input.networkRetryEnabled ? copy.retryOn : copy.retryOff,
|
|
294
289
|
value: { type: "toggle-network-retry" },
|
|
295
290
|
color: "cyan",
|
|
296
291
|
hint: copy.retryHint,
|
|
297
|
-
|
|
298
|
-
|
|
292
|
+
disabled: !capabilities.networkRetry,
|
|
293
|
+
},
|
|
294
|
+
];
|
|
295
|
+
const providerSettings = [
|
|
296
|
+
{ label: copy.providerSettingsHeading, value: { type: "cancel" }, kind: "heading" },
|
|
297
|
+
];
|
|
298
|
+
providerSettings.push({
|
|
299
|
+
label: input.refresh?.enabled ? copy.autoRefreshOn : copy.autoRefreshOff,
|
|
300
|
+
value: { type: "toggle-refresh" },
|
|
301
|
+
color: "cyan",
|
|
302
|
+
hint: input.refresh ? `${input.refresh.minutes}m` : undefined,
|
|
303
|
+
});
|
|
304
|
+
providerSettings.push({ label: copy.setRefresh, value: { type: "set-interval" }, color: "cyan" });
|
|
299
305
|
if (capabilities.syntheticAgentInitiator) {
|
|
300
|
-
|
|
306
|
+
providerSettings.push({
|
|
301
307
|
label: input.syntheticAgentInitiatorEnabled ? copy.syntheticInitiatorOn : copy.syntheticInitiatorOff,
|
|
302
308
|
value: { type: "toggle-synthetic-agent-initiator" },
|
|
303
309
|
color: "cyan",
|
|
@@ -305,7 +311,11 @@ export function buildMenuItems(input) {
|
|
|
305
311
|
});
|
|
306
312
|
}
|
|
307
313
|
return [
|
|
308
|
-
...
|
|
314
|
+
...providerActions,
|
|
315
|
+
{ label: "", value: { type: "cancel" }, separator: true },
|
|
316
|
+
...commonSettings,
|
|
317
|
+
{ label: "", value: { type: "cancel" }, separator: true },
|
|
318
|
+
...providerSettings,
|
|
309
319
|
{ label: "", value: { type: "cancel" }, separator: true },
|
|
310
320
|
{ label: copy.accountsHeading, value: { type: "cancel" }, kind: "heading" },
|
|
311
321
|
...input.accounts.map((account) => {
|
|
@@ -318,6 +328,7 @@ export function buildMenuItems(input) {
|
|
|
318
328
|
const numbered = `${account.index + 1}. ${account.name}`;
|
|
319
329
|
const label = `${numbered}${currentBadge}${statusBadge ? " " + statusBadge : ""}${quotaBadge}`;
|
|
320
330
|
const detail = [
|
|
331
|
+
account.workspaceName,
|
|
321
332
|
account.lastUsed ? formatRelativeTime(account.lastUsed) : undefined,
|
|
322
333
|
account.plan,
|
|
323
334
|
account.models ? `${account.models.enabled}/${account.models.enabled + account.models.disabled} mods` : undefined,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export type CodexAuthState = {
|
|
2
|
+
type: string;
|
|
3
|
+
refresh?: string;
|
|
4
|
+
access?: string;
|
|
5
|
+
expires?: number;
|
|
6
|
+
accountId?: string;
|
|
7
|
+
};
|
|
8
|
+
export type CodexProviderModel = {
|
|
9
|
+
id?: string;
|
|
10
|
+
api?: {
|
|
11
|
+
id?: string;
|
|
12
|
+
url?: string;
|
|
13
|
+
npm?: string;
|
|
14
|
+
};
|
|
15
|
+
cost?: {
|
|
16
|
+
input: number;
|
|
17
|
+
output: number;
|
|
18
|
+
cache: {
|
|
19
|
+
read: number;
|
|
20
|
+
write: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type CodexProviderConfig = {
|
|
25
|
+
models: Record<string, CodexProviderModel>;
|
|
26
|
+
};
|
|
27
|
+
export type OfficialCodexConfig = {
|
|
28
|
+
apiKey: string;
|
|
29
|
+
fetch: (request: Request | URL | string, init?: RequestInit) => Promise<Response>;
|
|
30
|
+
};
|
|
31
|
+
export type OfficialCodexChatHeadersHook = (input: {
|
|
32
|
+
sessionID: string;
|
|
33
|
+
model: {
|
|
34
|
+
providerID: string;
|
|
35
|
+
};
|
|
36
|
+
}, output: {
|
|
37
|
+
headers: Record<string, string>;
|
|
38
|
+
}) => Promise<void>;
|
|
39
|
+
export declare function loadOfficialCodexConfig(input: {
|
|
40
|
+
getAuth: () => Promise<CodexAuthState | undefined>;
|
|
41
|
+
provider?: CodexProviderConfig;
|
|
42
|
+
baseFetch?: typeof fetch;
|
|
43
|
+
version?: string;
|
|
44
|
+
client?: {
|
|
45
|
+
auth?: {
|
|
46
|
+
set?: (value: unknown) => Promise<unknown>;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}): Promise<OfficialCodexConfig | undefined>;
|
|
50
|
+
export declare function createOfficialCodexFetchAdapter(input: {
|
|
51
|
+
getAuth: () => Promise<CodexAuthState | undefined>;
|
|
52
|
+
provider?: CodexProviderConfig;
|
|
53
|
+
baseFetch?: typeof fetch;
|
|
54
|
+
version?: string;
|
|
55
|
+
client?: {
|
|
56
|
+
auth?: {
|
|
57
|
+
set?: (value: unknown) => Promise<unknown>;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
}): (request: Request | URL | string, init?: RequestInit) => Promise<Response>;
|
|
61
|
+
export declare function loadOfficialCodexChatHeaders(input?: {
|
|
62
|
+
client?: {
|
|
63
|
+
auth?: {
|
|
64
|
+
set?: (value: unknown) => Promise<unknown>;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
baseFetch?: typeof fetch;
|
|
68
|
+
version?: string;
|
|
69
|
+
}): Promise<OfficialCodexChatHeadersHook>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CodexAuthPlugin, officialCodexExportBridge } from "./codex-plugin.snapshot.js";
|
|
2
|
+
function runWithOfficialBridge(input, fn) {
|
|
3
|
+
return officialCodexExportBridge.run({
|
|
4
|
+
fetchImpl: input.baseFetch ?? globalThis.fetch,
|
|
5
|
+
version: input.version,
|
|
6
|
+
}, fn);
|
|
7
|
+
}
|
|
8
|
+
async function loadOfficialHooks(input) {
|
|
9
|
+
return runWithOfficialBridge(input, async () => {
|
|
10
|
+
const hooks = await CodexAuthPlugin({
|
|
11
|
+
client: input.client,
|
|
12
|
+
});
|
|
13
|
+
return hooks;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export async function loadOfficialCodexConfig(input) {
|
|
17
|
+
const hooks = await loadOfficialHooks({
|
|
18
|
+
client: input.client,
|
|
19
|
+
baseFetch: input.baseFetch,
|
|
20
|
+
version: input.version,
|
|
21
|
+
});
|
|
22
|
+
const loader = hooks.auth?.loader;
|
|
23
|
+
if (typeof loader !== "function") {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const provider = input.provider ?? { models: {} };
|
|
27
|
+
const result = await runWithOfficialBridge(input, async () => loader(input.getAuth, provider));
|
|
28
|
+
if (!("fetch" in result) || typeof result.fetch !== "function") {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
apiKey: result.apiKey,
|
|
33
|
+
fetch(request, init) {
|
|
34
|
+
return runWithOfficialBridge(input, async () => result.fetch(request, init));
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function createOfficialCodexFetchAdapter(input) {
|
|
39
|
+
return async function fetchWithOfficialHeaders(request, init) {
|
|
40
|
+
const config = await loadOfficialCodexConfig(input);
|
|
41
|
+
const fallback = input.baseFetch ?? fetch;
|
|
42
|
+
if (!config) {
|
|
43
|
+
return fallback(request, init);
|
|
44
|
+
}
|
|
45
|
+
return config.fetch(request, init);
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export async function loadOfficialCodexChatHeaders(input = {}) {
|
|
49
|
+
const hooks = await loadOfficialHooks(input);
|
|
50
|
+
const chatHeaders = hooks["chat.headers"];
|
|
51
|
+
if (typeof chatHeaders !== "function") {
|
|
52
|
+
throw new Error("Official Codex plugin is missing chat.headers hook");
|
|
53
|
+
}
|
|
54
|
+
return async (hookInput, output) => runWithOfficialBridge(input, async () => chatHeaders(hookInput, output));
|
|
55
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type RequestInfo = Request | URL | string;
|
|
2
|
+
type Hooks = any;
|
|
3
|
+
type PluginInput = any;
|
|
4
|
+
declare const officialCodexExportBridge: {
|
|
5
|
+
version: string;
|
|
6
|
+
fetchImpl(request: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
7
|
+
run(options: {
|
|
8
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
9
|
+
version?: string;
|
|
10
|
+
} | undefined, fn: () => Promise<any>): Promise<any>;
|
|
11
|
+
};
|
|
12
|
+
export declare function CodexAuthPlugin(input: PluginInput): Promise<Hooks>;
|
|
13
|
+
export { officialCodexExportBridge };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
const officialCodexExportBridgeStorage = new AsyncLocalStorage();
|
|
5
|
+
const officialCodexExportBridge = {
|
|
6
|
+
version: "snapshot",
|
|
7
|
+
fetchImpl(request, init) {
|
|
8
|
+
return globalThis.fetch(request, init);
|
|
9
|
+
},
|
|
10
|
+
async run(options = {}, fn) {
|
|
11
|
+
return officialCodexExportBridgeStorage.run({
|
|
12
|
+
fetchImpl: options.fetchImpl ?? this.fetchImpl,
|
|
13
|
+
version: options.version ?? this.version,
|
|
14
|
+
}, fn);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
const Installation = {
|
|
18
|
+
get VERSION() {
|
|
19
|
+
return officialCodexExportBridgeStorage.getStore()?.version ?? officialCodexExportBridge.version;
|
|
20
|
+
},
|
|
21
|
+
set VERSION(value) {
|
|
22
|
+
officialCodexExportBridge.version = value;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
const OAUTH_DUMMY_KEY = "official-codex-oauth";
|
|
26
|
+
function fetch(request, init) {
|
|
27
|
+
return (officialCodexExportBridgeStorage.getStore()?.fetchImpl ?? officialCodexExportBridge.fetchImpl)(request, init);
|
|
28
|
+
}
|
|
29
|
+
/* LOCAL_SHIMS_END */
|
|
30
|
+
const CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
31
|
+
export async function CodexAuthPlugin(input) {
|
|
32
|
+
return {
|
|
33
|
+
auth: {
|
|
34
|
+
provider: "openai",
|
|
35
|
+
async loader(getAuth, provider) {
|
|
36
|
+
const auth = await getAuth();
|
|
37
|
+
if (auth.type !== "oauth")
|
|
38
|
+
return {};
|
|
39
|
+
if (provider?.models) {
|
|
40
|
+
for (const model of Object.values(provider.models)) {
|
|
41
|
+
model.cost = {
|
|
42
|
+
input: 0,
|
|
43
|
+
output: 0,
|
|
44
|
+
cache: { read: 0, write: 0 },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
apiKey: OAUTH_DUMMY_KEY,
|
|
50
|
+
async fetch(requestInput, init) {
|
|
51
|
+
const currentAuth = await getAuth();
|
|
52
|
+
if (currentAuth.type !== "oauth")
|
|
53
|
+
return fetch(requestInput, init);
|
|
54
|
+
const headers = new Headers(init?.headers);
|
|
55
|
+
headers.delete("authorization");
|
|
56
|
+
headers.delete("Authorization");
|
|
57
|
+
headers.set("authorization", `Bearer ${currentAuth.access}`);
|
|
58
|
+
if (currentAuth.accountId) {
|
|
59
|
+
headers.set("ChatGPT-Account-Id", currentAuth.accountId);
|
|
60
|
+
}
|
|
61
|
+
const parsed = requestInput instanceof URL
|
|
62
|
+
? requestInput
|
|
63
|
+
: new URL(typeof requestInput === "string" ? requestInput : requestInput.url);
|
|
64
|
+
const url = parsed.pathname.includes("/v1/responses") || parsed.pathname.includes("/chat/completions")
|
|
65
|
+
? new URL(CODEX_API_ENDPOINT)
|
|
66
|
+
: parsed;
|
|
67
|
+
return fetch(url, {
|
|
68
|
+
...init,
|
|
69
|
+
headers,
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
methods: [
|
|
75
|
+
{
|
|
76
|
+
label: "ChatGPT Pro/Plus (browser)",
|
|
77
|
+
type: "oauth",
|
|
78
|
+
authorize: async () => ({
|
|
79
|
+
url: "",
|
|
80
|
+
instructions: "",
|
|
81
|
+
method: "auto",
|
|
82
|
+
callback: async () => ({ type: "failed" }),
|
|
83
|
+
}),
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
"chat.headers": async (input, output) => {
|
|
88
|
+
if (input.model.providerID !== "openai")
|
|
89
|
+
return;
|
|
90
|
+
output.headers.originator = "opencode";
|
|
91
|
+
output.headers["User-Agent"] = `opencode/${Installation.VERSION} (${os.platform()} ${os.release()}; ${os.arch()})`;
|
|
92
|
+
output.headers.session_id = input.sessionID;
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/* GENERATED_EXPORT_BRIDGE_START */
|
|
97
|
+
export { officialCodexExportBridge };
|
|
98
|
+
/* GENERATED_EXPORT_BRIDGE_END */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-copilot-account-switcher",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.5",
|
|
4
4
|
"description": "GitHub Copilot account switcher plugin for OpenCode",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"build": "tsc -p tsconfig.build.json",
|
|
45
45
|
"sync:copilot-snapshot": "node scripts/sync-copilot-upstream.mjs --output src/upstream/copilot-plugin.snapshot.ts",
|
|
46
46
|
"check:copilot-sync": "node scripts/sync-copilot-upstream.mjs --output src/upstream/copilot-plugin.snapshot.ts --check",
|
|
47
|
+
"sync:codex-snapshot": "node scripts/sync-codex-upstream.mjs --output src/upstream/codex-plugin.snapshot.ts",
|
|
48
|
+
"check:codex-sync": "node scripts/sync-codex-upstream.mjs --output src/upstream/codex-plugin.snapshot.ts --check",
|
|
47
49
|
"test": "npm run build && node --test",
|
|
48
50
|
"typecheck": "tsc --noEmit",
|
|
49
51
|
"prepublishOnly": "npm run build"
|