opencode-codex-multi-account 0.1.1 → 0.2.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/README.md CHANGED
@@ -26,8 +26,6 @@ Add to `opencode.json`:
26
26
  opencode-codex-multi-account ← you are here
27
27
 
28
28
  opencode-multi-account-core
29
-
30
- opencode-oauth-adapters
31
29
  ```
32
30
 
33
31
  See the [root README](../../README.md) for full documentation.
@@ -0,0 +1,2 @@
1
+ export declare const AccountManager: import("opencode-multi-account-core").AccountManagerClass;
2
+ export type AccountManager = InstanceType<typeof AccountManager>;
@@ -0,0 +1,2 @@
1
+ import { AccountStore, type DiskCredentials } from "opencode-multi-account-core";
2
+ export { AccountStore, type DiskCredentials, };
@@ -0,0 +1,20 @@
1
+ import { AccountManager } from "./account-manager";
2
+ import type { PluginClient } from "./types";
3
+ type OAuthCallbackResponse = ({
4
+ type: "success";
5
+ } & {
6
+ refresh: string;
7
+ access: string;
8
+ expires: number;
9
+ accountId?: string;
10
+ }) | {
11
+ type: "failed";
12
+ };
13
+ export interface OAuthFlowResult {
14
+ url: string;
15
+ instructions: string;
16
+ method: "auto";
17
+ callback(): Promise<OAuthCallbackResponse>;
18
+ }
19
+ export declare function handleAuthorize(manager: AccountManager | null, inputs?: Record<string, string>, client?: PluginClient): Promise<OAuthFlowResult>;
20
+ export {};
@@ -0,0 +1 @@
1
+ export { isClaimedByOther, readClaims, releaseClaim, writeClaim, type ClaimsMap, } from "opencode-multi-account-core";
@@ -0,0 +1,2 @@
1
+ import { getConfig, loadConfig, resetConfigCache, updateConfigField } from "opencode-multi-account-core";
2
+ export { getConfig, loadConfig, resetConfigCache, updateConfigField, };
@@ -0,0 +1,32 @@
1
+ /** OpenAI OAuth adapter config */
2
+ export declare const OPENAI_OAUTH_ADAPTER: import("opencode-multi-account-core").OAuthAdapter;
3
+ /** OpenAI OAuth Client ID */
4
+ export declare const OPENAI_CLIENT_ID: string;
5
+ /** Token exchange / refresh endpoint */
6
+ export declare const OPENAI_TOKEN_ENDPOINT: string;
7
+ /** OAuth usage stats endpoint */
8
+ export declare const OPENAI_USAGE_ENDPOINT: string;
9
+ /** OAuth profile endpoint */
10
+ export declare const OPENAI_PROFILE_ENDPOINT: string;
11
+ /** Codex upstream endpoint used by OpenCode */
12
+ export declare const CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
13
+ /** Codex usage/quota endpoint (WHAM API) */
14
+ export declare const CODEX_USAGE_ENDPOINT = "https://chatgpt.com/backend-api/wham/usage";
15
+ /** OpenAI OAuth issuer */
16
+ export declare const OAUTH_ISSUER = "https://auth.openai.com";
17
+ /** Local callback port for browser OAuth */
18
+ export declare const OAUTH_PORT = 1455;
19
+ /** Required beta header for OAuth requests */
20
+ export declare const OPENAI_BETA_HEADER: string;
21
+ /** User-Agent header */
22
+ export declare const OPENAI_CLI_USER_AGENT: string;
23
+ /** Tool name prefix */
24
+ export declare const TOOL_PREFIX: string;
25
+ /** Account storage filename */
26
+ export declare const ACCOUNTS_FILENAME: string;
27
+ /** Plan display labels derived from adapter */
28
+ export declare const PLAN_LABELS: import("opencode-multi-account-core").OAuthAdapterPlanLabels;
29
+ /** Access token expiry buffer (refresh 60s before expiry) */
30
+ export declare const TOKEN_EXPIRY_BUFFER_MS = 60000;
31
+ /** Maximum time to wait for a token refresh HTTP request */
32
+ export declare const TOKEN_REFRESH_TIMEOUT_MS = 30000;
@@ -0,0 +1,2 @@
1
+ declare const executeWithAccountRotation: (manager: import("opencode-multi-account-core").ExecutorAccountManager, runtimeFactory: import("opencode-multi-account-core").ExecutorRuntimeFactory, client: import("opencode-multi-account-core").PluginClient, input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
2
+ export { executeWithAccountRotation };
@@ -0,0 +1,26 @@
1
+ import { OPENAI_OAUTH_ADAPTER } from "./constants";
2
+ export declare const CodexMultiAuthPlugin: (ctx: unknown) => Promise<{
3
+ tool: {
4
+ [OPENAI_OAUTH_ADAPTER.statusToolName]: {
5
+ description: string;
6
+ args: {};
7
+ execute(args: Record<string, never>, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
8
+ };
9
+ };
10
+ auth: {
11
+ provider: string;
12
+ methods: ({
13
+ label: string;
14
+ type: "oauth";
15
+ authorize(): Promise<import("./auth-handler").OAuthFlowResult>;
16
+ } | {
17
+ type: "api";
18
+ label: string;
19
+ authorize?: undefined;
20
+ })[];
21
+ loader(getAuth: () => Promise<unknown>, provider: Record<string, unknown>): Promise<{
22
+ apiKey: string;
23
+ fetch: typeof fetch;
24
+ }>;
25
+ };
26
+ }>;
package/dist/index.js CHANGED
@@ -1739,7 +1739,7 @@ async function confirm(message, defaultYes = false) {
1739
1739
  return result ?? false;
1740
1740
  }
1741
1741
 
1742
- // ../oauth-adapters/src/openai.ts
1742
+ // ../multi-account-core/src/adapters/openai.ts
1743
1743
  var ISSUER = "https://auth.openai.com";
1744
1744
  var openAIOAuthAdapter = {
1745
1745
  id: "openai",
@@ -0,0 +1,37 @@
1
+ import type { TokenResponse } from "./types";
2
+ type PKCE = {
3
+ verifier: string;
4
+ challenge: string;
5
+ };
6
+ export declare function generatePKCE(): Promise<{
7
+ verifier: string;
8
+ challenge: string;
9
+ }>;
10
+ export declare function generateState(): string;
11
+ export declare function exchangeCodeForTokens(code: string, redirectUri: string, pkce: PKCE): Promise<TokenResponse>;
12
+ export declare function refreshAccessToken(refreshToken: string): Promise<TokenResponse>;
13
+ export interface IdTokenClaims {
14
+ chatgpt_account_id?: string;
15
+ organizations?: Array<{
16
+ id: string;
17
+ }>;
18
+ email?: string;
19
+ "https://api.openai.com/auth"?: {
20
+ chatgpt_account_id?: string;
21
+ };
22
+ }
23
+ export declare function parseJwtClaims(token: string): IdTokenClaims | undefined;
24
+ export declare function extractAccountId(tokens: {
25
+ id_token?: string;
26
+ access_token: string;
27
+ }): string | undefined;
28
+ export declare function startOAuthServer(): Promise<{
29
+ port: number;
30
+ redirectUri: string;
31
+ }>;
32
+ export declare function stopOAuthServer(): void;
33
+ export declare function waitForOAuthCallback(pkce: PKCE, state: string): Promise<TokenResponse>;
34
+ export declare function buildAuthorizeUrl(redirectUri: string, pkce: {
35
+ challenge: string;
36
+ }, state: string): string;
37
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const ProactiveRefreshQueue: import("opencode-multi-account-core").ProactiveRefreshQueueClass;
2
+ export type ProactiveRefreshQueue = InstanceType<typeof ProactiveRefreshQueue>;
@@ -0,0 +1,2 @@
1
+ declare const fetchUsageLimits: (accessToken: string, accountId?: string) => Promise<import("opencode-multi-account-core").UsageLimits | null>, getResetMsFromUsage: (account: import("opencode-multi-account-core").ManagedAccount) => number | null, handleRateLimitResponse: (manager: import("opencode-multi-account-core").RateLimitAccountManager, client: import("opencode-multi-account-core").PluginClient, account: import("opencode-multi-account-core").ManagedAccount, response: Response) => Promise<void>, retryAfterMsFromResponse: (response: Response) => number;
2
+ export { fetchUsageLimits, getResetMsFromUsage, handleRateLimitResponse, retryAfterMsFromResponse, };
@@ -0,0 +1,2 @@
1
+ export declare function buildRequestHeaders(input: RequestInfo | URL, init: RequestInit | undefined, accessToken: string, accountId?: string): Headers;
2
+ export declare function transformRequestUrl(input: RequestInfo | URL): RequestInfo | URL;
@@ -0,0 +1,18 @@
1
+ import { AccountStore } from "./account-store";
2
+ import type { PluginClient } from "./types";
3
+ type BaseFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
4
+ interface AccountRuntime {
5
+ fetch: BaseFetch;
6
+ }
7
+ export declare class AccountRuntimeFactory {
8
+ private readonly store;
9
+ private readonly client;
10
+ private runtimes;
11
+ private initLocks;
12
+ constructor(store: AccountStore, client: PluginClient);
13
+ getRuntime(uuid: string): Promise<AccountRuntime>;
14
+ invalidate(uuid: string): void;
15
+ invalidateAll(): void;
16
+ private createRuntime;
17
+ }
18
+ export {};
@@ -0,0 +1 @@
1
+ export { deduplicateAccounts, loadAccounts, readStorageFromDisk, } from "opencode-multi-account-core";
@@ -0,0 +1,4 @@
1
+ import { type ManagedAccount, type PluginClient, type TokenRefreshResult } from "./types";
2
+ export declare function isTokenExpired(account: Pick<ManagedAccount, "accessToken" | "expiresAt">): boolean;
3
+ export declare function refreshToken(currentRefreshToken: string, accountId: string, client: PluginClient): Promise<TokenRefreshResult>;
4
+ export declare function clearRefreshMutex(accountId?: string): void;
@@ -0,0 +1,216 @@
1
+ import * as v from "valibot";
2
+ export declare const OAuthCredentialsSchema: v.ObjectSchema<{
3
+ readonly type: v.LiteralSchema<"oauth", undefined>;
4
+ readonly refresh: v.StringSchema<undefined>;
5
+ readonly access: v.StringSchema<undefined>;
6
+ readonly expires: v.NumberSchema<undefined>;
7
+ }, undefined>;
8
+ export declare const UsageLimitEntrySchema: v.ObjectSchema<{
9
+ readonly utilization: v.NumberSchema<undefined>;
10
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
11
+ }, undefined>;
12
+ export declare const UsageLimitsSchema: v.ObjectSchema<{
13
+ readonly five_hour: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
14
+ readonly utilization: v.NumberSchema<undefined>;
15
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
16
+ }, undefined>, undefined>, null>;
17
+ readonly seven_day: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
18
+ readonly utilization: v.NumberSchema<undefined>;
19
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
20
+ }, undefined>, undefined>, null>;
21
+ readonly seven_day_sonnet: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
22
+ readonly utilization: v.NumberSchema<undefined>;
23
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
24
+ }, undefined>, undefined>, null>;
25
+ }, undefined>;
26
+ export declare const CredentialRefreshPatchSchema: v.ObjectSchema<{
27
+ readonly accessToken: v.StringSchema<undefined>;
28
+ readonly expiresAt: v.NumberSchema<undefined>;
29
+ readonly refreshToken: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
30
+ readonly uuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
31
+ readonly accountId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
32
+ readonly email: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
33
+ }, undefined>;
34
+ export declare const StoredAccountSchema: v.ObjectSchema<{
35
+ readonly uuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
36
+ readonly accountId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
37
+ readonly label: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
38
+ readonly email: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
39
+ readonly planTier: v.OptionalSchema<v.StringSchema<undefined>, "">;
40
+ readonly refreshToken: v.StringSchema<undefined>;
41
+ readonly accessToken: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
42
+ readonly expiresAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
43
+ readonly addedAt: v.NumberSchema<undefined>;
44
+ readonly lastUsed: v.NumberSchema<undefined>;
45
+ readonly enabled: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
46
+ readonly rateLimitResetAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
47
+ readonly cachedUsage: v.OptionalSchema<v.ObjectSchema<{
48
+ readonly five_hour: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
49
+ readonly utilization: v.NumberSchema<undefined>;
50
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
51
+ }, undefined>, undefined>, null>;
52
+ readonly seven_day: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
53
+ readonly utilization: v.NumberSchema<undefined>;
54
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
55
+ }, undefined>, undefined>, null>;
56
+ readonly seven_day_sonnet: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
57
+ readonly utilization: v.NumberSchema<undefined>;
58
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
59
+ }, undefined>, undefined>, null>;
60
+ }, undefined>, undefined>;
61
+ readonly cachedUsageAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
62
+ readonly consecutiveAuthFailures: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
63
+ readonly isAuthDisabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
64
+ readonly authDisabledReason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
65
+ }, undefined>;
66
+ export declare const AccountStorageSchema: v.ObjectSchema<{
67
+ readonly version: v.LiteralSchema<1, undefined>;
68
+ readonly accounts: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
69
+ readonly uuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
70
+ readonly accountId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
71
+ readonly label: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
72
+ readonly email: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
73
+ readonly planTier: v.OptionalSchema<v.StringSchema<undefined>, "">;
74
+ readonly refreshToken: v.StringSchema<undefined>;
75
+ readonly accessToken: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
76
+ readonly expiresAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
77
+ readonly addedAt: v.NumberSchema<undefined>;
78
+ readonly lastUsed: v.NumberSchema<undefined>;
79
+ readonly enabled: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
80
+ readonly rateLimitResetAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
81
+ readonly cachedUsage: v.OptionalSchema<v.ObjectSchema<{
82
+ readonly five_hour: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
83
+ readonly utilization: v.NumberSchema<undefined>;
84
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
85
+ }, undefined>, undefined>, null>;
86
+ readonly seven_day: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
87
+ readonly utilization: v.NumberSchema<undefined>;
88
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
89
+ }, undefined>, undefined>, null>;
90
+ readonly seven_day_sonnet: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
91
+ readonly utilization: v.NumberSchema<undefined>;
92
+ readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
93
+ }, undefined>, undefined>, null>;
94
+ }, undefined>, undefined>;
95
+ readonly cachedUsageAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
96
+ readonly consecutiveAuthFailures: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
97
+ readonly isAuthDisabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
98
+ readonly authDisabledReason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
99
+ }, undefined>, undefined>, readonly []>;
100
+ readonly activeAccountUuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
101
+ }, undefined>;
102
+ /** OpenAI /oauth/token response */
103
+ export declare const TokenResponseSchema: v.ObjectSchema<{
104
+ readonly id_token: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
105
+ readonly access_token: v.StringSchema<undefined>;
106
+ readonly refresh_token: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
107
+ readonly expires_in: v.NumberSchema<undefined>;
108
+ }, undefined>;
109
+ export type OAuthCredentials = v.InferOutput<typeof OAuthCredentialsSchema>;
110
+ export type UsageLimitEntry = v.InferOutput<typeof UsageLimitEntrySchema>;
111
+ export type UsageLimits = v.InferOutput<typeof UsageLimitsSchema>;
112
+ export type CredentialRefreshPatch = v.InferOutput<typeof CredentialRefreshPatchSchema>;
113
+ export type StoredAccount = v.InferOutput<typeof StoredAccountSchema>;
114
+ export type AccountStorage = v.InferOutput<typeof AccountStorageSchema>;
115
+ export type TokenResponse = v.InferOutput<typeof TokenResponseSchema>;
116
+ export declare const AccountSelectionStrategySchema: v.PicklistSchema<["sticky", "round-robin", "hybrid"], undefined>;
117
+ export type AccountSelectionStrategy = v.InferOutput<typeof AccountSelectionStrategySchema>;
118
+ export declare const PluginConfigSchema: v.ObjectSchema<{
119
+ /** sticky: same account until failure, round-robin: rotate every request, hybrid: health+usage scoring */
120
+ readonly account_selection_strategy: v.OptionalSchema<v.PicklistSchema<["sticky", "round-robin", "hybrid"], undefined>, "sticky">;
121
+ /** Use cross-process claim file to distribute parallel sessions across accounts */
122
+ readonly cross_process_claims: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
123
+ /** Skip account when any usage tier utilization >= this % (100 = disabled) */
124
+ readonly soft_quota_threshold_percent: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 100, undefined>]>, 100>;
125
+ /** Minimum backoff after rate limit (ms) */
126
+ readonly rate_limit_min_backoff_ms: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, 30000>;
127
+ /** Default retry-after when header is missing (ms) */
128
+ readonly default_retry_after_ms: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, 60000>;
129
+ /** Consecutive auth failures before disabling account */
130
+ readonly max_consecutive_auth_failures: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, 3>;
131
+ /** Backoff after token refresh failure (ms) */
132
+ readonly token_failure_backoff_ms: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, 30000>;
133
+ /** Enable proactive background token refresh */
134
+ readonly proactive_refresh: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
135
+ /** Seconds before expiry to trigger proactive refresh (default 30 min) */
136
+ readonly proactive_refresh_buffer_seconds: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60, undefined>]>, 1800>;
137
+ /** Interval between background refresh checks in seconds (default 5 min) */
138
+ readonly proactive_refresh_interval_seconds: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 30, undefined>]>, 300>;
139
+ /** Suppress toast notifications */
140
+ readonly quiet_mode: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
141
+ /** Enable debug logging */
142
+ readonly debug: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
143
+ }, undefined>;
144
+ export type PluginConfig = v.InferOutput<typeof PluginConfigSchema>;
145
+ export interface OriginalAuthHook {
146
+ methods?: Array<{
147
+ authorize?: (inputs?: Record<string, string>) => Promise<unknown>;
148
+ }>;
149
+ loader: (getAuth: () => Promise<unknown>, provider: unknown) => Promise<{
150
+ apiKey: string;
151
+ fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
152
+ }>;
153
+ }
154
+ export type TokenRefreshResult = {
155
+ ok: true;
156
+ patch: CredentialRefreshPatch;
157
+ } | {
158
+ ok: false;
159
+ permanent: boolean;
160
+ status?: number;
161
+ };
162
+ export interface ManagedAccount {
163
+ index: number;
164
+ uuid?: string;
165
+ accountId?: string;
166
+ label?: string;
167
+ email?: string;
168
+ planTier?: string;
169
+ refreshToken: string;
170
+ accessToken?: string;
171
+ expiresAt?: number;
172
+ addedAt: number;
173
+ lastUsed: number;
174
+ enabled: boolean;
175
+ rateLimitResetAt?: number;
176
+ last429At?: number;
177
+ cachedUsage?: UsageLimits;
178
+ cachedUsageAt?: number;
179
+ consecutiveAuthFailures: number;
180
+ isAuthDisabled: boolean;
181
+ authDisabledReason?: string;
182
+ }
183
+ export interface PluginClient {
184
+ auth: {
185
+ set: (params: {
186
+ path: {
187
+ id: string;
188
+ };
189
+ body: {
190
+ type: string;
191
+ refresh: string;
192
+ access: string;
193
+ expires: number;
194
+ };
195
+ }) => Promise<void>;
196
+ };
197
+ tui: {
198
+ showToast: (params: {
199
+ body: {
200
+ title?: string;
201
+ message: string;
202
+ variant: "info" | "warning" | "success" | "error";
203
+ };
204
+ }) => Promise<void>;
205
+ };
206
+ app: {
207
+ log: (params: {
208
+ body: {
209
+ service: string;
210
+ level: "debug" | "info" | "warn" | "error";
211
+ message: string;
212
+ extra?: Record<string, unknown>;
213
+ };
214
+ }) => Promise<void>;
215
+ };
216
+ }
@@ -0,0 +1 @@
1
+ export { ANSI, isTTY, parseKey, type KeyAction, } from "opencode-multi-account-core";
@@ -0,0 +1,25 @@
1
+ import type { AccountSelectionStrategy, ManagedAccount, UsageLimits } from "../types";
2
+ export type AuthMenuAction = {
3
+ type: "add";
4
+ } | {
5
+ type: "check-quotas";
6
+ } | {
7
+ type: "manage";
8
+ } | {
9
+ type: "load-balancing";
10
+ } | {
11
+ type: "delete-all";
12
+ } | {
13
+ type: "cancel";
14
+ };
15
+ export type AccountAction = "back" | "toggle" | "delete" | "retry-auth" | "cancel";
16
+ export declare function showAuthMenu(accounts: ManagedAccount[]): Promise<AuthMenuAction>;
17
+ export declare function showManageAccounts(accounts: ManagedAccount[]): Promise<{
18
+ action: AccountAction;
19
+ account?: ManagedAccount;
20
+ }>;
21
+ export declare function printQuotaReport(account: ManagedAccount, usage: UsageLimits): void;
22
+ export declare function showStrategySelect(current: AccountSelectionStrategy): Promise<AccountSelectionStrategy | null>;
23
+ export type AuthMethod = "browser" | "headless";
24
+ export declare function showMethodSelect(): Promise<AuthMethod | null>;
25
+ export declare function printQuotaError(account: ManagedAccount, error: string): void;
@@ -0,0 +1 @@
1
+ export { confirm } from "opencode-multi-account-core";
@@ -0,0 +1 @@
1
+ export { select, type MenuItem, type SelectOptions, } from "opencode-multi-account-core";
@@ -0,0 +1,25 @@
1
+ import type { ManagedAccount, UsageLimits } from "./types";
2
+ export type ProfileData = {
3
+ email?: string;
4
+ planTier: string;
5
+ };
6
+ export type FetchUsageResult = {
7
+ ok: true;
8
+ data: UsageLimits;
9
+ planType?: string;
10
+ } | {
11
+ ok: false;
12
+ reason: string;
13
+ };
14
+ export type FetchProfileResult = {
15
+ ok: true;
16
+ data: ProfileData;
17
+ } | {
18
+ ok: false;
19
+ reason: string;
20
+ };
21
+ export declare function fetchUsage(accessToken: string, accountId?: string): Promise<FetchUsageResult>;
22
+ export declare function derivePlanTier(planType: string): string;
23
+ export declare function fetchProfile(accessToken: string): FetchProfileResult;
24
+ export declare function getUsageSummary(account: ManagedAccount): string;
25
+ export declare function getPlanLabel(account: ManagedAccount): string;
@@ -0,0 +1 @@
1
+ export { createMinimalClient, debugLog, formatWaitTime, getAccountLabel, getConfigDir, getErrorCode, showToast, sleep, } from "opencode-multi-account-core";
package/package.json CHANGED
@@ -1,16 +1,21 @@
1
1
  {
2
2
  "name": "opencode-codex-multi-account",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "OpenCode plugin for Codex (OpenAI) multi-account management with automatic rate limit switching",
5
- "main": "./src/index.ts",
5
+ "main": "./dist/index.js",
6
6
  "type": "module",
7
+ "types": "./dist/index.d.ts",
7
8
  "exports": {
8
- ".": "./src/index.ts"
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
9
14
  },
10
15
  "scripts": {
11
- "build": "esbuild src/index.ts --bundle --outdir=dist --platform=node --format=esm --packages=external",
16
+ "build": "esbuild src/index.ts --bundle --outdir=dist --platform=node --format=esm --packages=external && tsc -p tsconfig.build.json --emitDeclarationOnly",
12
17
  "typecheck": "tsc --noEmit",
13
- "test": "vitest run",
18
+ "test": "for f in tests/*.test.ts; do bun test \"$f\" || exit 1; done",
14
19
  "prepack": "bun run build",
15
20
  "dev": "bun run build --watch"
16
21
  },
@@ -35,27 +40,17 @@
35
40
  "directory": "packages/codex-multi-account"
36
41
  },
37
42
  "dependencies": {
38
- "opencode-multi-account-core": "^0.1.1",
39
- "opencode-oauth-adapters": "^0.1.1",
40
- "proper-lockfile": "^4.1.2",
43
+ "opencode-multi-account-core": "^0.2.0",
41
44
  "valibot": "^1.2.0"
42
45
  },
43
46
  "devDependencies": {
44
47
  "@opencode-ai/plugin": "^0.15.30",
45
48
  "@types/node": "^25.2.2",
46
- "@types/proper-lockfile": "^4.1.4",
47
49
  "typescript": "^5.8.0"
48
50
  },
49
51
  "publishConfig": {
50
52
  "registry": "https://registry.npmjs.org",
51
- "access": "public",
52
- "main": "./dist/index.js",
53
- "exports": {
54
- ".": {
55
- "import": "./dist/index.js",
56
- "default": "./dist/index.js"
57
- }
58
- }
53
+ "access": "public"
59
54
  },
60
55
  "files": [
61
56
  "dist",