opencode-anthropic-multi-account 0.1.2 → 0.2.1
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 +0 -2
- package/dist/account-manager.d.ts +2 -0
- package/dist/account-store.d.ts +2 -0
- package/dist/auth-handler.d.ts +19 -0
- package/dist/claims.d.ts +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/constants.d.ts +24 -0
- package/dist/executor.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +24 -4
- package/dist/proactive-refresh.d.ts +2 -0
- package/dist/rate-limit.d.ts +2 -0
- package/dist/request-transform.d.ts +4 -0
- package/dist/runtime-factory.d.ts +23 -0
- package/dist/storage.d.ts +1 -0
- package/dist/token.d.ts +4 -0
- package/dist/types.d.ts +214 -0
- package/dist/ui/ansi.d.ts +1 -0
- package/dist/ui/auth-menu.d.ts +26 -0
- package/dist/ui/confirm.d.ts +1 -0
- package/dist/ui/select.d.ts +1 -0
- package/dist/usage.d.ts +23 -0
- package/dist/utils.d.ts +1 -0
- package/package.json +7 -9
package/README.md
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AccountManager } from "./account-manager";
|
|
2
|
+
import type { OriginalAuthHook, PluginClient } from "./types";
|
|
3
|
+
type OAuthCallbackResponse = ({
|
|
4
|
+
type: "success";
|
|
5
|
+
} & {
|
|
6
|
+
refresh: string;
|
|
7
|
+
access: string;
|
|
8
|
+
expires: number;
|
|
9
|
+
}) | {
|
|
10
|
+
type: "failed";
|
|
11
|
+
};
|
|
12
|
+
export interface OAuthFlowResult {
|
|
13
|
+
url: string;
|
|
14
|
+
instructions: string;
|
|
15
|
+
method: "auto";
|
|
16
|
+
callback(code?: string): Promise<OAuthCallbackResponse>;
|
|
17
|
+
}
|
|
18
|
+
export declare function handleAuthorize(originalAuth: OriginalAuthHook, manager: AccountManager | null, inputs?: Record<string, string>, client?: PluginClient): Promise<OAuthFlowResult>;
|
|
19
|
+
export {};
|
package/dist/claims.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { isClaimedByOther, readClaims, releaseClaim, writeClaim, type ClaimsMap, } from "opencode-multi-account-core";
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Anthropic OAuth adapter config */
|
|
2
|
+
export declare const ANTHROPIC_OAUTH_ADAPTER: import("opencode-multi-account-core").OAuthAdapter;
|
|
3
|
+
/** Anthropic OAuth Client ID (same as builtin opencode-anthropic-auth) */
|
|
4
|
+
export declare const ANTHROPIC_CLIENT_ID: string;
|
|
5
|
+
/** Token exchange / refresh endpoint */
|
|
6
|
+
export declare const ANTHROPIC_TOKEN_ENDPOINT: string;
|
|
7
|
+
/** OAuth usage stats endpoint */
|
|
8
|
+
export declare const ANTHROPIC_USAGE_ENDPOINT: string;
|
|
9
|
+
/** OAuth profile endpoint for email/plan info */
|
|
10
|
+
export declare const ANTHROPIC_PROFILE_ENDPOINT: string;
|
|
11
|
+
/** Required beta header for OAuth requests */
|
|
12
|
+
export declare const ANTHROPIC_BETA_HEADER: string;
|
|
13
|
+
/** User-Agent header to mimic Claude CLI */
|
|
14
|
+
export declare const CLAUDE_CLI_USER_AGENT: string;
|
|
15
|
+
/** Tool name prefix required by Anthropic servers */
|
|
16
|
+
export declare const TOOL_PREFIX: string;
|
|
17
|
+
/** Account storage filename */
|
|
18
|
+
export declare const ACCOUNTS_FILENAME: string;
|
|
19
|
+
/** Plan display labels derived from adapter */
|
|
20
|
+
export declare const PLAN_LABELS: import("opencode-multi-account-core").OAuthAdapterPlanLabels;
|
|
21
|
+
/** Access token expiry buffer (refresh 60s before expiry) */
|
|
22
|
+
export declare const TOKEN_EXPIRY_BUFFER_MS = 60000;
|
|
23
|
+
/** Maximum time to wait for a token refresh HTTP request */
|
|
24
|
+
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 };
|
package/dist/index.d.ts
ADDED
package/dist/index.js
CHANGED
|
@@ -1740,7 +1740,7 @@ async function confirm(message, defaultYes = false) {
|
|
|
1740
1740
|
return result ?? false;
|
|
1741
1741
|
}
|
|
1742
1742
|
|
|
1743
|
-
// ../
|
|
1743
|
+
// ../multi-account-core/src/adapters/anthropic.ts
|
|
1744
1744
|
var anthropicOAuthAdapter = {
|
|
1745
1745
|
id: "anthropic",
|
|
1746
1746
|
authProviderId: "anthropic",
|
|
@@ -2019,11 +2019,11 @@ function getUsageSummary(account) {
|
|
|
2019
2019
|
const parts = [];
|
|
2020
2020
|
const { five_hour, seven_day } = account.cachedUsage;
|
|
2021
2021
|
if (five_hour) {
|
|
2022
|
-
const reset = five_hour.resets_at ? ` (resets ${formatTimeRemaining(five_hour.resets_at)})` : "";
|
|
2022
|
+
const reset = five_hour.utilization >= 100 && five_hour.resets_at ? ` (resets ${formatTimeRemaining(five_hour.resets_at)})` : "";
|
|
2023
2023
|
parts.push(`5h: ${five_hour.utilization.toFixed(0)}%${reset}`);
|
|
2024
2024
|
}
|
|
2025
2025
|
if (seven_day) {
|
|
2026
|
-
const reset = seven_day.resets_at ? ` (resets ${formatTimeRemaining(seven_day.resets_at)})` : "";
|
|
2026
|
+
const reset = seven_day.utilization >= 100 && seven_day.resets_at ? ` (resets ${formatTimeRemaining(seven_day.resets_at)})` : "";
|
|
2027
2027
|
parts.push(`7d: ${seven_day.utilization.toFixed(0)}%${reset}`);
|
|
2028
2028
|
}
|
|
2029
2029
|
return parts.length > 0 ? parts.join(", ") : "no data";
|
|
@@ -2079,6 +2079,16 @@ function getAccountStatus(account) {
|
|
|
2079
2079
|
if (account.isAuthDisabled) return "auth-disabled";
|
|
2080
2080
|
if (!account.enabled) return "disabled";
|
|
2081
2081
|
if (account.rateLimitResetAt && account.rateLimitResetAt > Date.now()) return "rate-limited";
|
|
2082
|
+
if (account.cachedUsage) {
|
|
2083
|
+
const now = Date.now();
|
|
2084
|
+
const usage = account.cachedUsage;
|
|
2085
|
+
const exhaustedTiers = [usage.five_hour, usage.seven_day].filter(
|
|
2086
|
+
(tier) => tier && tier.utilization >= 100 && tier.resets_at != null && Date.parse(tier.resets_at) > now
|
|
2087
|
+
);
|
|
2088
|
+
if (exhaustedTiers.length > 0) {
|
|
2089
|
+
return "rate-limited";
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2082
2092
|
return "active";
|
|
2083
2093
|
}
|
|
2084
2094
|
var STATUS_BADGE = {
|
|
@@ -2198,7 +2208,7 @@ function printUsageEntry(name, entry, isLast) {
|
|
|
2198
2208
|
return;
|
|
2199
2209
|
}
|
|
2200
2210
|
const bar = createProgressBar(entry.utilization);
|
|
2201
|
-
const reset = formatResetTime(entry.resets_at);
|
|
2211
|
+
const reset = entry.utilization >= 100 && entry.resets_at ? formatResetTime(entry.resets_at) : "";
|
|
2202
2212
|
console.log(` ${connector} ${name.padEnd(16)} ${bar}${reset}`);
|
|
2203
2213
|
}
|
|
2204
2214
|
function printQuotaReport(account, usage) {
|
|
@@ -2725,6 +2735,16 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
2725
2735
|
const remaining = formatWaitTime(account.rateLimitResetAt - Date.now());
|
|
2726
2736
|
statusParts.push(`RATE LIMITED (resets in ${remaining})`);
|
|
2727
2737
|
}
|
|
2738
|
+
if (account.cachedUsage) {
|
|
2739
|
+
const now = Date.now();
|
|
2740
|
+
const usage2 = account.cachedUsage;
|
|
2741
|
+
const exhaustedTiers = [usage2.five_hour, usage2.seven_day].filter(
|
|
2742
|
+
(tier) => tier && tier.utilization >= 100 && tier.resets_at != null && Date.parse(tier.resets_at) > now
|
|
2743
|
+
);
|
|
2744
|
+
if (exhaustedTiers.length > 0) {
|
|
2745
|
+
statusParts.push("USAGE EXHAUSTED");
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2728
2748
|
lines.push(
|
|
2729
2749
|
`- **${label}**${planBadge}${marker}: ${statusParts.join(" | ")} | ${usage}`
|
|
2730
2750
|
);
|
|
@@ -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,4 @@
|
|
|
1
|
+
export declare function buildRequestHeaders(input: RequestInfo | URL, init: RequestInit | undefined, accessToken: string): Headers;
|
|
2
|
+
export declare function transformRequestBody(body: string | undefined): string | undefined;
|
|
3
|
+
export declare function transformRequestUrl(input: RequestInfo | URL): RequestInfo | URL;
|
|
4
|
+
export declare function createResponseStreamTransform(response: Response): Response;
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
/** Per-account base plugin instances — delegates all auth mechanics to AnthropicAuthPlugin. */
|
|
8
|
+
export declare class AccountRuntimeFactory {
|
|
9
|
+
private readonly pluginCtx;
|
|
10
|
+
private readonly store;
|
|
11
|
+
private readonly client;
|
|
12
|
+
private readonly provider;
|
|
13
|
+
private runtimes;
|
|
14
|
+
private initLocks;
|
|
15
|
+
constructor(pluginCtx: Record<string, unknown>, store: AccountStore, client: PluginClient, provider: unknown);
|
|
16
|
+
getRuntime(uuid: string): Promise<AccountRuntime>;
|
|
17
|
+
invalidate(uuid: string): void;
|
|
18
|
+
invalidateAll(): void;
|
|
19
|
+
private createRuntime;
|
|
20
|
+
private createScopedGetAuth;
|
|
21
|
+
private createScopedClient;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { deduplicateAccounts, loadAccounts, readStorageFromDisk, } from "opencode-multi-account-core";
|
package/dist/token.d.ts
ADDED
|
@@ -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;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
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 email: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
32
|
+
}, undefined>;
|
|
33
|
+
export declare const StoredAccountSchema: v.ObjectSchema<{
|
|
34
|
+
readonly uuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
35
|
+
readonly label: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
36
|
+
readonly email: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
37
|
+
readonly planTier: v.OptionalSchema<v.StringSchema<undefined>, "">;
|
|
38
|
+
readonly refreshToken: v.StringSchema<undefined>;
|
|
39
|
+
readonly accessToken: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
40
|
+
readonly expiresAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
41
|
+
readonly addedAt: v.NumberSchema<undefined>;
|
|
42
|
+
readonly lastUsed: v.NumberSchema<undefined>;
|
|
43
|
+
readonly enabled: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
|
|
44
|
+
readonly rateLimitResetAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
45
|
+
readonly cachedUsage: v.OptionalSchema<v.ObjectSchema<{
|
|
46
|
+
readonly five_hour: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
|
|
47
|
+
readonly utilization: v.NumberSchema<undefined>;
|
|
48
|
+
readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
49
|
+
}, undefined>, undefined>, null>;
|
|
50
|
+
readonly seven_day: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
|
|
51
|
+
readonly utilization: v.NumberSchema<undefined>;
|
|
52
|
+
readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
53
|
+
}, undefined>, undefined>, null>;
|
|
54
|
+
readonly seven_day_sonnet: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
|
|
55
|
+
readonly utilization: v.NumberSchema<undefined>;
|
|
56
|
+
readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
57
|
+
}, undefined>, undefined>, null>;
|
|
58
|
+
}, undefined>, undefined>;
|
|
59
|
+
readonly cachedUsageAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
60
|
+
readonly consecutiveAuthFailures: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
|
|
61
|
+
readonly isAuthDisabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
62
|
+
readonly authDisabledReason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
63
|
+
}, undefined>;
|
|
64
|
+
export declare const AccountStorageSchema: v.ObjectSchema<{
|
|
65
|
+
readonly version: v.LiteralSchema<1, undefined>;
|
|
66
|
+
readonly accounts: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
67
|
+
readonly uuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
68
|
+
readonly label: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
69
|
+
readonly email: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
70
|
+
readonly planTier: v.OptionalSchema<v.StringSchema<undefined>, "">;
|
|
71
|
+
readonly refreshToken: v.StringSchema<undefined>;
|
|
72
|
+
readonly accessToken: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
73
|
+
readonly expiresAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
74
|
+
readonly addedAt: v.NumberSchema<undefined>;
|
|
75
|
+
readonly lastUsed: v.NumberSchema<undefined>;
|
|
76
|
+
readonly enabled: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
|
|
77
|
+
readonly rateLimitResetAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
78
|
+
readonly cachedUsage: v.OptionalSchema<v.ObjectSchema<{
|
|
79
|
+
readonly five_hour: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
|
|
80
|
+
readonly utilization: v.NumberSchema<undefined>;
|
|
81
|
+
readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
82
|
+
}, undefined>, undefined>, null>;
|
|
83
|
+
readonly seven_day: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
|
|
84
|
+
readonly utilization: v.NumberSchema<undefined>;
|
|
85
|
+
readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
86
|
+
}, undefined>, undefined>, null>;
|
|
87
|
+
readonly seven_day_sonnet: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
|
|
88
|
+
readonly utilization: v.NumberSchema<undefined>;
|
|
89
|
+
readonly resets_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
90
|
+
}, undefined>, undefined>, null>;
|
|
91
|
+
}, undefined>, undefined>;
|
|
92
|
+
readonly cachedUsageAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
93
|
+
readonly consecutiveAuthFailures: v.OptionalSchema<v.NumberSchema<undefined>, 0>;
|
|
94
|
+
readonly isAuthDisabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
95
|
+
readonly authDisabledReason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
96
|
+
}, undefined>, undefined>, readonly []>;
|
|
97
|
+
readonly activeAccountUuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
98
|
+
}, undefined>;
|
|
99
|
+
/** Anthropic /v1/oauth/token response */
|
|
100
|
+
export declare const TokenResponseSchema: v.ObjectSchema<{
|
|
101
|
+
readonly access_token: v.StringSchema<undefined>;
|
|
102
|
+
readonly refresh_token: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
103
|
+
readonly expires_in: v.NumberSchema<undefined>;
|
|
104
|
+
readonly account: v.OptionalSchema<v.ObjectSchema<{
|
|
105
|
+
readonly uuid: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
106
|
+
readonly email_address: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
107
|
+
}, undefined>, 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
|
+
};
|
|
161
|
+
export interface ManagedAccount {
|
|
162
|
+
index: number;
|
|
163
|
+
uuid?: string;
|
|
164
|
+
label?: string;
|
|
165
|
+
email?: string;
|
|
166
|
+
planTier?: string;
|
|
167
|
+
refreshToken: string;
|
|
168
|
+
accessToken?: string;
|
|
169
|
+
expiresAt?: number;
|
|
170
|
+
addedAt: number;
|
|
171
|
+
lastUsed: number;
|
|
172
|
+
enabled: boolean;
|
|
173
|
+
rateLimitResetAt?: number;
|
|
174
|
+
last429At?: number;
|
|
175
|
+
cachedUsage?: UsageLimits;
|
|
176
|
+
cachedUsageAt?: number;
|
|
177
|
+
consecutiveAuthFailures: number;
|
|
178
|
+
isAuthDisabled: boolean;
|
|
179
|
+
authDisabledReason?: string;
|
|
180
|
+
}
|
|
181
|
+
export interface PluginClient {
|
|
182
|
+
auth: {
|
|
183
|
+
set: (params: {
|
|
184
|
+
path: {
|
|
185
|
+
id: string;
|
|
186
|
+
};
|
|
187
|
+
body: {
|
|
188
|
+
type: string;
|
|
189
|
+
refresh: string;
|
|
190
|
+
access: string;
|
|
191
|
+
expires: number;
|
|
192
|
+
};
|
|
193
|
+
}) => Promise<void>;
|
|
194
|
+
};
|
|
195
|
+
tui: {
|
|
196
|
+
showToast: (params: {
|
|
197
|
+
body: {
|
|
198
|
+
title?: string;
|
|
199
|
+
message: string;
|
|
200
|
+
variant: "info" | "warning" | "success" | "error";
|
|
201
|
+
};
|
|
202
|
+
}) => Promise<void>;
|
|
203
|
+
};
|
|
204
|
+
app: {
|
|
205
|
+
log: (params: {
|
|
206
|
+
body: {
|
|
207
|
+
service: string;
|
|
208
|
+
level: "debug" | "info" | "warn" | "error";
|
|
209
|
+
message: string;
|
|
210
|
+
extra?: Record<string, unknown>;
|
|
211
|
+
};
|
|
212
|
+
}) => Promise<void>;
|
|
213
|
+
};
|
|
214
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ANSI, isTTY, parseKey, type KeyAction, } from "opencode-multi-account-core";
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
type AccountStatus = "active" | "rate-limited" | "auth-disabled" | "disabled";
|
|
17
|
+
export declare function getAccountStatus(account: ManagedAccount): AccountStatus;
|
|
18
|
+
export declare function showAuthMenu(accounts: ManagedAccount[]): Promise<AuthMenuAction>;
|
|
19
|
+
export declare function showManageAccounts(accounts: ManagedAccount[]): Promise<{
|
|
20
|
+
action: AccountAction;
|
|
21
|
+
account?: ManagedAccount;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function printQuotaReport(account: ManagedAccount, usage: UsageLimits): void;
|
|
24
|
+
export declare function showStrategySelect(current: AccountSelectionStrategy): Promise<AccountSelectionStrategy | null>;
|
|
25
|
+
export declare function printQuotaError(account: ManagedAccount, error: string): void;
|
|
26
|
+
export {};
|
|
@@ -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";
|
package/dist/usage.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
reason: string;
|
|
12
|
+
};
|
|
13
|
+
export type FetchProfileResult = {
|
|
14
|
+
ok: true;
|
|
15
|
+
data: ProfileData;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
reason: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function fetchUsage(accessToken: string): Promise<FetchUsageResult>;
|
|
21
|
+
export declare function fetchProfile(accessToken: string): Promise<FetchProfileResult>;
|
|
22
|
+
export declare function getUsageSummary(account: ManagedAccount): string;
|
|
23
|
+
export declare function getPlanLabel(account: ManagedAccount): string;
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createMinimalClient, debugLog, formatWaitTime, getAccountLabel, getConfigDir, getErrorCode, showToast, sleep, } from "opencode-multi-account-core";
|
package/package.json
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-anthropic-multi-account",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "OpenCode plugin for Anthropic multi-account management with automatic rate limit switching",
|
|
5
|
-
"main": "./
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": {
|
|
9
|
-
"
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
10
11
|
"import": "./dist/index.js",
|
|
11
12
|
"default": "./dist/index.js"
|
|
12
13
|
}
|
|
13
14
|
},
|
|
14
15
|
"scripts": {
|
|
15
|
-
"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",
|
|
16
17
|
"typecheck": "tsc --noEmit",
|
|
17
|
-
"test": "
|
|
18
|
+
"test": "for f in tests/*.test.ts; do bun test \"$f\" || exit 1; done",
|
|
18
19
|
"prepack": "bun run build",
|
|
19
20
|
"dev": "bun run build --watch"
|
|
20
21
|
},
|
|
@@ -38,16 +39,13 @@
|
|
|
38
39
|
"directory": "packages/anthropic-multi-account"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"opencode-multi-account-core": "^0.1
|
|
42
|
-
"opencode-oauth-adapters": "^0.1.2",
|
|
42
|
+
"opencode-multi-account-core": "^0.2.1",
|
|
43
43
|
"opencode-anthropic-auth": "^0.0.13",
|
|
44
|
-
"proper-lockfile": "^4.1.2",
|
|
45
44
|
"valibot": "^1.2.0"
|
|
46
45
|
},
|
|
47
46
|
"devDependencies": {
|
|
48
47
|
"@opencode-ai/plugin": "^0.15.30",
|
|
49
48
|
"@types/node": "^25.2.2",
|
|
50
|
-
"@types/proper-lockfile": "^4.1.4",
|
|
51
49
|
"typescript": "^5.8.0"
|
|
52
50
|
},
|
|
53
51
|
"publishConfig": {
|