@thelioo/opencode-balancer 0.1.6 → 0.1.8
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/server/auth-watcher.d.ts +1 -0
- package/dist/server/auth-watcher.js +1 -1
- package/dist/server/auth-watcher.js.map +1 -1
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +6 -2
- package/dist/tui/actions.js.map +1 -1
- package/dist/tui/actions.ts +7 -3
- package/dist/tui/components/priority-screen.d.ts +1 -1
- package/dist/tui/components/priority-screen.tsx +4 -3
- package/dist/tui/components/provider-model-dialog.d.ts +2 -1
- package/dist/tui/components/provider-model-dialog.tsx +21 -11
- package/dist/tui/connect.js +5 -3
- package/dist/tui/connect.js.map +1 -1
- package/dist/tui/connect.ts +5 -3
- package/dist/tui/selected-account-bar-sync.d.ts +10 -0
- package/dist/tui/selected-account-bar-sync.js +26 -0
- package/dist/tui/selected-account-bar-sync.js.map +1 -0
- package/dist/tui/selected-account-bar-sync.ts +32 -0
- package/dist/tui/tui.js +39 -6
- package/dist/tui/tui.js.map +1 -1
- package/dist/tui/tui.tsx +40 -8
- package/package.json +1 -1
- package/dist/balancer/accounts.d.ts +0 -9
- package/dist/balancer/accounts.js +0 -102
- package/dist/balancer/accounts.js.map +0 -1
- package/dist/balancer/auth-watcher.d.ts +0 -1
- package/dist/balancer/auth-watcher.js +0 -30
- package/dist/balancer/auth-watcher.js.map +0 -1
- package/dist/balancer/commands.d.ts +0 -1
- package/dist/balancer/commands.js +0 -94
- package/dist/balancer/commands.js.map +0 -1
- package/dist/balancer/core.d.ts +0 -6
- package/dist/balancer/core.js +0 -7
- package/dist/balancer/core.js.map +0 -1
- package/dist/balancer/fetch-patch.d.ts +0 -1
- package/dist/balancer/fetch-patch.js +0 -110
- package/dist/balancer/fetch-patch.js.map +0 -1
- package/dist/balancer/http.d.ts +0 -40
- package/dist/balancer/http.js +0 -199
- package/dist/balancer/http.js.map +0 -1
- package/dist/balancer/native.d.ts +0 -3
- package/dist/balancer/native.js +0 -16
- package/dist/balancer/native.js.map +0 -1
- package/dist/balancer/state.d.ts +0 -14
- package/dist/balancer/state.js +0 -16
- package/dist/balancer/state.js.map +0 -1
- package/dist/balancer/storage.d.ts +0 -8
- package/dist/balancer/storage.js +0 -92
- package/dist/balancer/storage.js.map +0 -1
- package/dist/balancer/types.d.ts +0 -44
- package/dist/balancer/types.js +0 -2
- package/dist/balancer/types.js.map +0 -1
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { now } from "./state";
|
|
2
|
-
import { readStore, writeStore } from "./storage";
|
|
3
|
-
export function normalizeAlias(alias) {
|
|
4
|
-
return alias
|
|
5
|
-
.trim()
|
|
6
|
-
.toLowerCase()
|
|
7
|
-
.replace(/[^a-z0-9._-]+/g, "-")
|
|
8
|
-
.replace(/^-+|-+$/g, "");
|
|
9
|
-
}
|
|
10
|
-
export async function saveAccount(providerID, aliasInput, auth) {
|
|
11
|
-
const alias = normalizeAlias(aliasInput);
|
|
12
|
-
if (!alias)
|
|
13
|
-
throw new Error("Invalid alias. Use letters, numbers, dots, hyphens, or underscores.");
|
|
14
|
-
const store = await readStore();
|
|
15
|
-
const provider = store.providers[providerID] ?? { accounts: {} };
|
|
16
|
-
const existing = provider.accounts[alias];
|
|
17
|
-
const account = {
|
|
18
|
-
alias,
|
|
19
|
-
providerID,
|
|
20
|
-
auth,
|
|
21
|
-
createdAt: existing?.createdAt ?? now(),
|
|
22
|
-
updatedAt: now(),
|
|
23
|
-
lastUsedAt: existing?.lastUsedAt,
|
|
24
|
-
failures: existing?.failures,
|
|
25
|
-
rateLimitedUntil: existing?.rateLimitedUntil,
|
|
26
|
-
};
|
|
27
|
-
provider.accounts[alias] = account;
|
|
28
|
-
provider.active = alias;
|
|
29
|
-
store.providers[providerID] = provider;
|
|
30
|
-
store.lastCaptured = {
|
|
31
|
-
providerID,
|
|
32
|
-
auth,
|
|
33
|
-
capturedAt: now(),
|
|
34
|
-
source: store.lastCaptured?.source ?? "auth-file",
|
|
35
|
-
};
|
|
36
|
-
await writeStore(store);
|
|
37
|
-
return account;
|
|
38
|
-
}
|
|
39
|
-
export async function getProviderState(providerID) {
|
|
40
|
-
return (await readStore()).providers[providerID];
|
|
41
|
-
}
|
|
42
|
-
export async function getActiveAccount(providerID) {
|
|
43
|
-
const provider = await getProviderState(providerID);
|
|
44
|
-
if (!provider?.active)
|
|
45
|
-
return undefined;
|
|
46
|
-
return provider.accounts[provider.active];
|
|
47
|
-
}
|
|
48
|
-
export async function listAccountsText() {
|
|
49
|
-
const store = await readStore();
|
|
50
|
-
const lines = [];
|
|
51
|
-
for (const [providerID, provider] of Object.entries(store.providers).sort(([a], [b]) => a.localeCompare(b))) {
|
|
52
|
-
lines.push(`${providerID}:`);
|
|
53
|
-
const accounts = Object.values(provider.accounts).sort((a, b) => a.alias.localeCompare(b.alias));
|
|
54
|
-
if (accounts.length === 0) {
|
|
55
|
-
lines.push(" (no accounts)");
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
for (const account of accounts) {
|
|
59
|
-
const marker = provider.active === account.alias ? "*" : " ";
|
|
60
|
-
const limited = account.rateLimitedUntil && account.rateLimitedUntil > now()
|
|
61
|
-
? ` rate-limited ${Math.ceil((account.rateLimitedUntil - now()) / 1000)}s`
|
|
62
|
-
: "healthy";
|
|
63
|
-
lines.push(` ${marker} ${account.alias} (${account.auth.type}, ${limited})`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (lines.length === 0)
|
|
67
|
-
return "No accounts saved. Use `/connect <provider>` and then `/balancer alias <name>`.";
|
|
68
|
-
const last = store.lastCaptured;
|
|
69
|
-
if (last)
|
|
70
|
-
lines.push("", `Last detected connection: ${last.providerID} (${last.auth.type})`);
|
|
71
|
-
return lines.join("\n");
|
|
72
|
-
}
|
|
73
|
-
export async function nextAvailableAccount(providerID, currentAlias) {
|
|
74
|
-
const provider = await getProviderState(providerID);
|
|
75
|
-
if (!provider)
|
|
76
|
-
return undefined;
|
|
77
|
-
const accounts = Object.values(provider.accounts);
|
|
78
|
-
return accounts.find((account) => account.alias !== currentAlias &&
|
|
79
|
-
(!account.rateLimitedUntil || account.rateLimitedUntil <= now()));
|
|
80
|
-
}
|
|
81
|
-
export async function markRateLimited(providerID, alias, retryAfterMs = 60_000) {
|
|
82
|
-
const store = await readStore();
|
|
83
|
-
const account = store.providers[providerID]?.accounts[alias];
|
|
84
|
-
if (!account)
|
|
85
|
-
return;
|
|
86
|
-
account.failures = (account.failures ?? 0) + 1;
|
|
87
|
-
account.rateLimitedUntil = now() + retryAfterMs;
|
|
88
|
-
account.updatedAt = now();
|
|
89
|
-
await writeStore(store);
|
|
90
|
-
}
|
|
91
|
-
export async function markUsed(providerID, alias) {
|
|
92
|
-
const store = await readStore();
|
|
93
|
-
const account = store.providers[providerID]?.accounts[alias];
|
|
94
|
-
if (!account)
|
|
95
|
-
return;
|
|
96
|
-
account.lastUsedAt = now();
|
|
97
|
-
account.updatedAt = now();
|
|
98
|
-
if (account.rateLimitedUntil && account.rateLimitedUntil <= now())
|
|
99
|
-
delete account.rateLimitedUntil;
|
|
100
|
-
await writeStore(store);
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=accounts.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/balancer/accounts.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function startAuthWatcher(client: any): void;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { authPath, captureAuth, isAuthInfo, now, readNativeAuth, showToast, state, } from "./core";
|
|
2
|
-
export function startAuthWatcher(client) {
|
|
3
|
-
if (state.watchStarted)
|
|
4
|
-
return;
|
|
5
|
-
state.watchStarted = true;
|
|
6
|
-
void readNativeAuth().then((auth) => {
|
|
7
|
-
state.lastAuthSnapshot = auth;
|
|
8
|
-
});
|
|
9
|
-
const path = authPath();
|
|
10
|
-
const handleChange = async () => {
|
|
11
|
-
const next = await readNativeAuth();
|
|
12
|
-
for (const [providerID, auth] of Object.entries(next)) {
|
|
13
|
-
if (!isAuthInfo(auth))
|
|
14
|
-
continue;
|
|
15
|
-
const suppressedUntil = state.suppressAuthCaptureUntil.get(providerID) ?? 0;
|
|
16
|
-
if (suppressedUntil > now())
|
|
17
|
-
continue;
|
|
18
|
-
const previous = JSON.stringify(state.lastAuthSnapshot[providerID] ?? null);
|
|
19
|
-
const current = JSON.stringify(auth);
|
|
20
|
-
if (previous === current)
|
|
21
|
-
continue;
|
|
22
|
-
await captureAuth(providerID, auth, "auth-file");
|
|
23
|
-
await showToast(client, `Balancer: new ${providerID} connection detected. Use /balancer alias <name>.`, "info");
|
|
24
|
-
}
|
|
25
|
-
state.lastAuthSnapshot = next;
|
|
26
|
-
};
|
|
27
|
-
const timer = setInterval(() => void handleChange(), 1_000);
|
|
28
|
-
timer.unref?.();
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=auth-watcher.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-watcher.js","sourceRoot":"","sources":["../../src/balancer/auth-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,QAAQ,EACR,WAAW,EACX,UAAU,EACV,GAAG,EACH,cAAc,EACd,SAAS,EACT,KAAK,GACR,MAAM,QAAQ,CAAC;AAEhB,MAAM,UAAU,gBAAgB,CAAC,MAAW;IACxC,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO;IAC/B,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IAC1B,KAAK,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAClC,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;QAC5B,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,SAAS;YAChC,MAAM,eAAe,GACjB,KAAK,CAAC,wBAAwB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACxD,IAAI,eAAe,GAAG,GAAG,EAAE;gBAAE,SAAS;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAC3B,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,IAAI,CAC7C,CAAC;YACF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,QAAQ,KAAK,OAAO;gBAAE,SAAS;YACnC,MAAM,WAAW,CAAC,UAAU,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;YACjD,MAAM,SAAS,CACX,MAAM,EACN,iBAAiB,UAAU,mDAAmD,EAC9E,MAAM,CACT,CAAC;QACN,CAAC;QACD,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAClC,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3D,KAAgC,CAAC,KAAK,EAAE,EAAE,CAAC;AAChD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function runBalancerCommand(client: any, raw: string): Promise<string>;
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { isAuthInfo, listAccountsText, normalizeAlias, readNativeAuth, readStore, saveAccount, setNativeAuth, storePath, writeStore, } from "./core";
|
|
2
|
-
function parseArgs(input) {
|
|
3
|
-
return (input
|
|
4
|
-
.match(/(?:[^\s"]+|"[^"]*")+/g)
|
|
5
|
-
?.map((x) => x.replace(/^"|"$/g, "")) ?? []);
|
|
6
|
-
}
|
|
7
|
-
export async function runBalancerCommand(client, raw) {
|
|
8
|
-
const [action = "help", ...args] = parseArgs(raw);
|
|
9
|
-
const store = await readStore();
|
|
10
|
-
if (["help", "--help", "-h"].includes(action)) {
|
|
11
|
-
return [
|
|
12
|
-
"Balancer commands:",
|
|
13
|
-
"",
|
|
14
|
-
" /balancer alias <name>",
|
|
15
|
-
" saves the last detected connection",
|
|
16
|
-
" with an alias",
|
|
17
|
-
"",
|
|
18
|
-
" /balancer save <provider> <name>",
|
|
19
|
-
" saves the provider's current credentials",
|
|
20
|
-
"",
|
|
21
|
-
" /balancer use <provider> <name>",
|
|
22
|
-
" switches the active account",
|
|
23
|
-
"",
|
|
24
|
-
" /balancer list",
|
|
25
|
-
" lists accounts",
|
|
26
|
-
"",
|
|
27
|
-
" /balancer status",
|
|
28
|
-
" shows current state",
|
|
29
|
-
"",
|
|
30
|
-
" /balancer remove <provider> <name>",
|
|
31
|
-
" removes an account",
|
|
32
|
-
].join("\n");
|
|
33
|
-
}
|
|
34
|
-
if (action === "alias") {
|
|
35
|
-
const alias = args[0];
|
|
36
|
-
if (!alias)
|
|
37
|
-
return "Usage: /balancer alias <name>";
|
|
38
|
-
const captured = store.lastCaptured;
|
|
39
|
-
if (!captured)
|
|
40
|
-
return "No connection detected yet. Run /connect <provider> first.";
|
|
41
|
-
const account = await saveAccount(captured.providerID, alias, captured.auth);
|
|
42
|
-
await setNativeAuth(client, captured.providerID, captured.auth);
|
|
43
|
-
return `Account saved and activated: ${captured.providerID}/${account.alias}`;
|
|
44
|
-
}
|
|
45
|
-
if (action === "save") {
|
|
46
|
-
const [providerID, alias] = args;
|
|
47
|
-
if (!providerID || !alias)
|
|
48
|
-
return "Usage: /balancer save <provider> <name>";
|
|
49
|
-
const auth = (await readNativeAuth())[providerID];
|
|
50
|
-
if (!isAuthInfo(auth))
|
|
51
|
-
return `No native credentials found for ${providerID}. Run /connect ${providerID} first.`;
|
|
52
|
-
const account = await saveAccount(providerID, alias, auth);
|
|
53
|
-
return `Account saved and activated: ${providerID}/${account.alias}`;
|
|
54
|
-
}
|
|
55
|
-
if (action === "use") {
|
|
56
|
-
const [providerID, aliasInput] = args;
|
|
57
|
-
const alias = normalizeAlias(aliasInput ?? "");
|
|
58
|
-
if (!providerID || !alias)
|
|
59
|
-
return "Usage: /balancer use <provider> <name>";
|
|
60
|
-
const account = store.providers[providerID]?.accounts[alias];
|
|
61
|
-
if (!account)
|
|
62
|
-
return `Account not found: ${providerID}/${alias}`;
|
|
63
|
-
store.providers[providerID].active = alias;
|
|
64
|
-
await writeStore(store);
|
|
65
|
-
await setNativeAuth(client, providerID, account.auth);
|
|
66
|
-
return `Active account changed to ${providerID}/${alias}`;
|
|
67
|
-
}
|
|
68
|
-
if (action === "list" || action === "accounts")
|
|
69
|
-
return listAccountsText();
|
|
70
|
-
if (action === "status") {
|
|
71
|
-
const last = store.lastCaptured;
|
|
72
|
-
const lines = [await listAccountsText()];
|
|
73
|
-
if (last)
|
|
74
|
-
lines.push("", `Last capture: ${last.providerID} via ${last.source} at ${new Date(last.capturedAt).toLocaleString()}`);
|
|
75
|
-
lines.push("", `Storage: ${storePath()}`);
|
|
76
|
-
return lines.join("\n");
|
|
77
|
-
}
|
|
78
|
-
if (action === "remove") {
|
|
79
|
-
const [providerID, aliasInput] = args;
|
|
80
|
-
const alias = normalizeAlias(aliasInput ?? "");
|
|
81
|
-
if (!providerID || !alias)
|
|
82
|
-
return "Usage: /balancer remove <provider> <name>";
|
|
83
|
-
const provider = store.providers[providerID];
|
|
84
|
-
if (!provider?.accounts[alias])
|
|
85
|
-
return `Account not found: ${providerID}/${alias}`;
|
|
86
|
-
delete provider.accounts[alias];
|
|
87
|
-
if (provider.active === alias)
|
|
88
|
-
provider.active = Object.keys(provider.accounts)[0];
|
|
89
|
-
await writeStore(store);
|
|
90
|
-
return `Account removed: ${providerID}/${alias}`;
|
|
91
|
-
}
|
|
92
|
-
return `Unknown command: ${action}. Use /balancer help.`;
|
|
93
|
-
}
|
|
94
|
-
//# sourceMappingURL=commands.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/balancer/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/balancer/core.d.ts
DELETED
package/dist/balancer/core.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/balancer/core.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function installFetchPatch(client: any): Promise<void>;
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { BALANCER_ALIAS_INPUT, applyAuthToHeaders, captureAuth, cloneRequestInput, fakeCommandResponse, headersFrom, INTERNAL_REQUEST_HEADER, isAuthInfo, isInternalUrl, markRateLimited, markUsed, maybeInjectAliasPrompt, nextAvailableAccount, normalizeAlias, now, parseAuthSetProvider, parseJsonBody, parseProviderAuthorize, parseProviderCallback, parseSessionCommand, parseUrl, readNativeAuth, readStore, RETRYABLE_STATUS, retryAfterMs, saveAccount, setNativeAuth, showToast, state, writeStore, } from "./core";
|
|
2
|
-
import { runBalancerCommand } from "./commands";
|
|
3
|
-
export async function installFetchPatch(client) {
|
|
4
|
-
if (state.fetchPatched)
|
|
5
|
-
return;
|
|
6
|
-
state.fetchPatched = true;
|
|
7
|
-
const originalFetch = globalThis.fetch.bind(globalThis);
|
|
8
|
-
globalThis.fetch = (async (input, init) => {
|
|
9
|
-
const url = parseUrl(input);
|
|
10
|
-
const commandSessionID = parseSessionCommand(url);
|
|
11
|
-
if (commandSessionID &&
|
|
12
|
-
(init?.method ?? "GET").toUpperCase() === "POST") {
|
|
13
|
-
const body = parseJsonBody(init);
|
|
14
|
-
if (body?.command === "balancer") {
|
|
15
|
-
const result = await runBalancerCommand(client, typeof body.arguments === "string" ? body.arguments : "");
|
|
16
|
-
await showToast(client, result.split("\n")[0] ?? result, "info");
|
|
17
|
-
return new Response(JSON.stringify(fakeCommandResponse(commandSessionID, result)), {
|
|
18
|
-
status: 200,
|
|
19
|
-
headers: { "content-type": "application/json" },
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
if (isInternalUrl(url) && url?.pathname === "/provider/auth") {
|
|
24
|
-
return maybeInjectAliasPrompt(await originalFetch(input, init));
|
|
25
|
-
}
|
|
26
|
-
const authorizeProvider = parseProviderAuthorize(url);
|
|
27
|
-
if (authorizeProvider &&
|
|
28
|
-
(init?.method ?? "GET").toUpperCase() === "POST") {
|
|
29
|
-
const body = parseJsonBody(init);
|
|
30
|
-
const alias = typeof body?.inputs?.[BALANCER_ALIAS_INPUT] === "string"
|
|
31
|
-
? normalizeAlias(body.inputs[BALANCER_ALIAS_INPUT])
|
|
32
|
-
: "";
|
|
33
|
-
if (alias)
|
|
34
|
-
state.pendingOauthAlias.set(authorizeProvider, alias);
|
|
35
|
-
if (body?.inputs && BALANCER_ALIAS_INPUT in body.inputs) {
|
|
36
|
-
delete body.inputs[BALANCER_ALIAS_INPUT];
|
|
37
|
-
init = { ...init, body: JSON.stringify(body) };
|
|
38
|
-
}
|
|
39
|
-
return originalFetch(input, init);
|
|
40
|
-
}
|
|
41
|
-
const callbackProvider = parseProviderCallback(url);
|
|
42
|
-
if (callbackProvider &&
|
|
43
|
-
(init?.method ?? "GET").toUpperCase() === "POST") {
|
|
44
|
-
const response = await originalFetch(input, init);
|
|
45
|
-
const alias = state.pendingOauthAlias.get(callbackProvider);
|
|
46
|
-
if (response.ok && alias) {
|
|
47
|
-
setTimeout(async () => {
|
|
48
|
-
const auth = (await readNativeAuth())[callbackProvider];
|
|
49
|
-
if (isAuthInfo(auth)) {
|
|
50
|
-
await saveAccount(callbackProvider, alias, auth);
|
|
51
|
-
await showToast(client, `Balancer: account ${callbackProvider}/${alias} saved.`, "success");
|
|
52
|
-
}
|
|
53
|
-
state.pendingOauthAlias.delete(callbackProvider);
|
|
54
|
-
}, 250);
|
|
55
|
-
}
|
|
56
|
-
return response;
|
|
57
|
-
}
|
|
58
|
-
const authSetProvider = parseAuthSetProvider(url);
|
|
59
|
-
if (authSetProvider &&
|
|
60
|
-
(init?.method ?? "GET").toUpperCase() === "PUT") {
|
|
61
|
-
const body = parseJsonBody(init);
|
|
62
|
-
const response = await originalFetch(input, init);
|
|
63
|
-
if (response.ok && isAuthInfo(body)) {
|
|
64
|
-
const suppressedUntil = state.suppressAuthCaptureUntil.get(authSetProvider) ?? 0;
|
|
65
|
-
if (suppressedUntil <= now()) {
|
|
66
|
-
await captureAuth(authSetProvider, body, "http");
|
|
67
|
-
await showToast(client, `Balancer: ${authSetProvider} connection detected. Use /balancer alias <name>.`, "info");
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return response;
|
|
71
|
-
}
|
|
72
|
-
const headers = headersFrom(input, init);
|
|
73
|
-
const requestID = headers.get(INTERNAL_REQUEST_HEADER);
|
|
74
|
-
if (!requestID)
|
|
75
|
-
return originalFetch(input, init);
|
|
76
|
-
const pending = state.pendingRequests.get(requestID);
|
|
77
|
-
headers.delete(INTERNAL_REQUEST_HEADER);
|
|
78
|
-
if (!pending?.account) {
|
|
79
|
-
const [nextInput, nextInit] = cloneRequestInput(input, init, headers);
|
|
80
|
-
return originalFetch(nextInput, nextInit);
|
|
81
|
-
}
|
|
82
|
-
let account = pending.account;
|
|
83
|
-
let attempt = 0;
|
|
84
|
-
while (true) {
|
|
85
|
-
attempt++;
|
|
86
|
-
const attemptHeaders = new Headers(headers);
|
|
87
|
-
applyAuthToHeaders(attemptHeaders, account);
|
|
88
|
-
const [nextInput, nextInit] = cloneRequestInput(input, init, attemptHeaders);
|
|
89
|
-
const response = await originalFetch(nextInput, nextInit);
|
|
90
|
-
if (!RETRYABLE_STATUS.has(response.status)) {
|
|
91
|
-
await markUsed(account.providerID, account.alias);
|
|
92
|
-
return response;
|
|
93
|
-
}
|
|
94
|
-
await markRateLimited(account.providerID, account.alias, retryAfterMs(response));
|
|
95
|
-
const next = await nextAvailableAccount(account.providerID, account.alias);
|
|
96
|
-
if (!next || attempt >= 3)
|
|
97
|
-
return response;
|
|
98
|
-
account = next;
|
|
99
|
-
const store = await readStore();
|
|
100
|
-
const provider = store.providers[account.providerID];
|
|
101
|
-
if (provider) {
|
|
102
|
-
provider.active = account.alias;
|
|
103
|
-
await writeStore(store);
|
|
104
|
-
}
|
|
105
|
-
await setNativeAuth(client, account.providerID, account.auth);
|
|
106
|
-
await showToast(client, `Balancer: ${pending.providerID}/${pending.account.alias} is rate limited. Switching to ${account.alias}.`, "warning");
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=fetch-patch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-patch.js","sourceRoot":"","sources":["../../src/balancer/fetch-patch.ts"],"names":[],"mappings":"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"}
|
package/dist/balancer/http.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { Account } from "./types";
|
|
2
|
-
export declare function applyAuthToHeaders(headers: Headers, account: Account): void;
|
|
3
|
-
export declare function cloneRequestInput(input: RequestInfo | URL, init: RequestInit | undefined, headers: Headers): [RequestInfo | URL, RequestInit | undefined];
|
|
4
|
-
export declare function parseUrl(input: RequestInfo | URL): URL | undefined;
|
|
5
|
-
export declare function headersFrom(input: RequestInfo | URL, init?: RequestInit): Headers;
|
|
6
|
-
export declare function parseJsonBody(init?: RequestInit): any;
|
|
7
|
-
export declare function isInternalUrl(url: URL | undefined): boolean;
|
|
8
|
-
export declare function parseAuthSetProvider(url: URL | undefined): string | undefined;
|
|
9
|
-
export declare function parseProviderAuthorize(url: URL | undefined): string | undefined;
|
|
10
|
-
export declare function parseProviderCallback(url: URL | undefined): string | undefined;
|
|
11
|
-
export declare function parseSessionCommand(url: URL | undefined): string | undefined;
|
|
12
|
-
export declare function fakeCommandResponse(sessionID: string, text: string): {
|
|
13
|
-
info: {
|
|
14
|
-
id: string;
|
|
15
|
-
sessionID: string;
|
|
16
|
-
role: string;
|
|
17
|
-
time: {
|
|
18
|
-
created: number;
|
|
19
|
-
};
|
|
20
|
-
agent: string;
|
|
21
|
-
model: {
|
|
22
|
-
providerID: string;
|
|
23
|
-
modelID: string;
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
parts: {
|
|
27
|
-
id: string;
|
|
28
|
-
sessionID: string;
|
|
29
|
-
messageID: string;
|
|
30
|
-
type: string;
|
|
31
|
-
text: string;
|
|
32
|
-
synthetic: boolean;
|
|
33
|
-
ignored: boolean;
|
|
34
|
-
metadata: {
|
|
35
|
-
opencodeBalancerCommand: boolean;
|
|
36
|
-
};
|
|
37
|
-
}[];
|
|
38
|
-
};
|
|
39
|
-
export declare function maybeInjectAliasPrompt(response: Response): Promise<Response>;
|
|
40
|
-
export declare function retryAfterMs(response: Response): number;
|
package/dist/balancer/http.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { BALANCER_ALIAS_INPUT, BALANCER_METADATA_KEY, now, } from "./state";
|
|
2
|
-
function getHeaderEntries(headers) {
|
|
3
|
-
return Array.from(headers.entries()).map(([key, value]) => [key.toLowerCase(), value]);
|
|
4
|
-
}
|
|
5
|
-
export function applyAuthToHeaders(headers, account) {
|
|
6
|
-
const auth = account.auth;
|
|
7
|
-
const entries = getHeaderEntries(headers);
|
|
8
|
-
if (auth.type === "oauth") {
|
|
9
|
-
if (auth.access)
|
|
10
|
-
headers.set("authorization", `Bearer ${auth.access}`);
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
if (auth.type === "wellknown") {
|
|
14
|
-
if (headers.has("authorization"))
|
|
15
|
-
headers.set("authorization", `Bearer ${auth.token}`);
|
|
16
|
-
else
|
|
17
|
-
headers.set(auth.key, auth.token);
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const authHeaderNames = [
|
|
21
|
-
"authorization",
|
|
22
|
-
"x-api-key",
|
|
23
|
-
"api-key",
|
|
24
|
-
"x-goog-api-key",
|
|
25
|
-
"x-stainless-api-key",
|
|
26
|
-
"anthropic-api-key",
|
|
27
|
-
"cohere-api-key",
|
|
28
|
-
];
|
|
29
|
-
let changed = false;
|
|
30
|
-
for (const name of authHeaderNames) {
|
|
31
|
-
const current = entries.find(([key]) => key === name)?.[1];
|
|
32
|
-
if (!current)
|
|
33
|
-
continue;
|
|
34
|
-
if (name === "authorization") {
|
|
35
|
-
headers.set(name, current.toLowerCase().startsWith("bearer ")
|
|
36
|
-
? `Bearer ${auth.key}`
|
|
37
|
-
: auth.key);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
headers.set(name, auth.key);
|
|
41
|
-
}
|
|
42
|
-
changed = true;
|
|
43
|
-
}
|
|
44
|
-
if (!changed)
|
|
45
|
-
headers.set("authorization", `Bearer ${auth.key}`);
|
|
46
|
-
}
|
|
47
|
-
export function cloneRequestInput(input, init, headers) {
|
|
48
|
-
if (typeof Request !== "undefined" && input instanceof Request) {
|
|
49
|
-
return [new Request(input, { ...init, headers }), undefined];
|
|
50
|
-
}
|
|
51
|
-
return [input, { ...init, headers }];
|
|
52
|
-
}
|
|
53
|
-
export function parseUrl(input) {
|
|
54
|
-
try {
|
|
55
|
-
if (typeof input === "string")
|
|
56
|
-
return new URL(input, "http://localhost");
|
|
57
|
-
if (input instanceof URL)
|
|
58
|
-
return input;
|
|
59
|
-
if (typeof Request !== "undefined" && input instanceof Request)
|
|
60
|
-
return new URL(input.url);
|
|
61
|
-
}
|
|
62
|
-
catch { }
|
|
63
|
-
return undefined;
|
|
64
|
-
}
|
|
65
|
-
export function headersFrom(input, init) {
|
|
66
|
-
if (init?.headers)
|
|
67
|
-
return new Headers(init.headers);
|
|
68
|
-
if (typeof Request !== "undefined" && input instanceof Request)
|
|
69
|
-
return new Headers(input.headers);
|
|
70
|
-
return new Headers();
|
|
71
|
-
}
|
|
72
|
-
function requestBodyText(init) {
|
|
73
|
-
const body = init?.body;
|
|
74
|
-
if (typeof body === "string")
|
|
75
|
-
return body;
|
|
76
|
-
if (body instanceof URLSearchParams)
|
|
77
|
-
return body.toString();
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
export function parseJsonBody(init) {
|
|
81
|
-
const text = requestBodyText(init);
|
|
82
|
-
if (!text)
|
|
83
|
-
return undefined;
|
|
84
|
-
try {
|
|
85
|
-
return JSON.parse(text);
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
export function isInternalUrl(url) {
|
|
92
|
-
if (!url)
|
|
93
|
-
return false;
|
|
94
|
-
return (url.hostname === "localhost" ||
|
|
95
|
-
url.hostname === "127.0.0.1" ||
|
|
96
|
-
url.hostname === "0.0.0.0");
|
|
97
|
-
}
|
|
98
|
-
export function parseAuthSetProvider(url) {
|
|
99
|
-
if (!url || !isInternalUrl(url))
|
|
100
|
-
return undefined;
|
|
101
|
-
const match = url.pathname.match(/^\/auth\/([^/]+)$/);
|
|
102
|
-
return match ? decodeURIComponent(match[1]) : undefined;
|
|
103
|
-
}
|
|
104
|
-
export function parseProviderAuthorize(url) {
|
|
105
|
-
if (!url || !isInternalUrl(url))
|
|
106
|
-
return undefined;
|
|
107
|
-
const match = url.pathname.match(/^\/provider\/([^/]+)\/oauth\/authorize$/);
|
|
108
|
-
return match ? decodeURIComponent(match[1]) : undefined;
|
|
109
|
-
}
|
|
110
|
-
export function parseProviderCallback(url) {
|
|
111
|
-
if (!url || !isInternalUrl(url))
|
|
112
|
-
return undefined;
|
|
113
|
-
const match = url.pathname.match(/^\/provider\/([^/]+)\/oauth\/callback$/);
|
|
114
|
-
return match ? decodeURIComponent(match[1]) : undefined;
|
|
115
|
-
}
|
|
116
|
-
export function parseSessionCommand(url) {
|
|
117
|
-
if (!url || !isInternalUrl(url))
|
|
118
|
-
return undefined;
|
|
119
|
-
const match = url.pathname.match(/^\/session\/([^/]+)\/command$/);
|
|
120
|
-
return match ? decodeURIComponent(match[1]) : undefined;
|
|
121
|
-
}
|
|
122
|
-
export function fakeCommandResponse(sessionID, text) {
|
|
123
|
-
const created = now();
|
|
124
|
-
const suffix = `${created.toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
125
|
-
const messageID = `msg_${suffix}`;
|
|
126
|
-
return {
|
|
127
|
-
info: {
|
|
128
|
-
id: messageID,
|
|
129
|
-
sessionID,
|
|
130
|
-
role: "user",
|
|
131
|
-
time: { created },
|
|
132
|
-
agent: "build",
|
|
133
|
-
model: { providerID: "opencode", modelID: "balancer-command" },
|
|
134
|
-
},
|
|
135
|
-
parts: [
|
|
136
|
-
{
|
|
137
|
-
id: `prt_${suffix}`,
|
|
138
|
-
sessionID,
|
|
139
|
-
messageID,
|
|
140
|
-
type: "text",
|
|
141
|
-
text,
|
|
142
|
-
synthetic: true,
|
|
143
|
-
ignored: true,
|
|
144
|
-
metadata: { [BALANCER_METADATA_KEY]: true },
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
export async function maybeInjectAliasPrompt(response) {
|
|
150
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
151
|
-
if (!response.ok || !contentType.includes("application/json"))
|
|
152
|
-
return response;
|
|
153
|
-
try {
|
|
154
|
-
const data = (await response.clone().json());
|
|
155
|
-
for (const methods of Object.values(data)) {
|
|
156
|
-
if (!Array.isArray(methods))
|
|
157
|
-
continue;
|
|
158
|
-
for (const method of methods) {
|
|
159
|
-
const prompts = Array.isArray(method.prompts)
|
|
160
|
-
? method.prompts
|
|
161
|
-
: [];
|
|
162
|
-
if (prompts.some((prompt) => prompt?.key === BALANCER_ALIAS_INPUT))
|
|
163
|
-
continue;
|
|
164
|
-
method.prompts = [
|
|
165
|
-
...prompts,
|
|
166
|
-
{
|
|
167
|
-
type: "text",
|
|
168
|
-
key: BALANCER_ALIAS_INPUT,
|
|
169
|
-
message: "Alias to save in the balancer (optional)",
|
|
170
|
-
placeholder: "work, personal, backup",
|
|
171
|
-
},
|
|
172
|
-
];
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
const headers = new Headers(response.headers);
|
|
176
|
-
headers.set("content-type", "application/json");
|
|
177
|
-
return new Response(JSON.stringify(data), {
|
|
178
|
-
status: response.status,
|
|
179
|
-
statusText: response.statusText,
|
|
180
|
-
headers,
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
catch {
|
|
184
|
-
return response;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
export function retryAfterMs(response) {
|
|
188
|
-
const retryAfter = response.headers.get("retry-after");
|
|
189
|
-
if (!retryAfter)
|
|
190
|
-
return 60_000;
|
|
191
|
-
const seconds = Number(retryAfter);
|
|
192
|
-
if (Number.isFinite(seconds))
|
|
193
|
-
return Math.max(1_000, seconds * 1000);
|
|
194
|
-
const date = Date.parse(retryAfter);
|
|
195
|
-
if (Number.isFinite(date))
|
|
196
|
-
return Math.max(1_000, date - now());
|
|
197
|
-
return 60_000;
|
|
198
|
-
}
|
|
199
|
-
//# sourceMappingURL=http.js.map
|