@thelioo/opencode-balancer 0.1.0 → 0.1.4
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/INSTALL.txt +16 -7
- package/README.md +24 -45
- package/dist/core/accounts.d.ts +14 -0
- package/dist/core/accounts.js +260 -0
- package/dist/core/accounts.js.map +1 -0
- package/dist/core/database.d.ts +4 -0
- package/dist/core/database.js +69 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/events.d.ts +18 -0
- package/dist/core/events.js +39 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/native-auth-suppression.d.ts +3 -0
- package/dist/core/native-auth-suppression.js +19 -0
- package/dist/core/native-auth-suppression.js.map +1 -0
- package/dist/core/native-connect.d.ts +4 -0
- package/dist/core/native-connect.js +19 -0
- package/dist/core/native-connect.js.map +1 -0
- package/dist/core/path.d.ts +4 -0
- package/dist/core/path.js +26 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/pending.d.ts +9 -0
- package/dist/core/pending.js +237 -0
- package/dist/core/pending.js.map +1 -0
- package/dist/core/priority.d.ts +20 -0
- package/dist/core/priority.js +120 -0
- package/dist/core/priority.js.map +1 -0
- package/dist/core/schema.d.ts +2 -0
- package/dist/core/schema.js +265 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/time.d.ts +1 -0
- package/dist/core/time.js +4 -0
- package/dist/core/time.js.map +1 -0
- package/dist/core/types.d.ts +59 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage/index.d.ts +4 -0
- package/dist/core/usage/index.js +16 -0
- package/dist/core/usage/index.js.map +1 -0
- package/dist/core/usage/providers/copilot.d.ts +2 -0
- package/dist/core/usage/providers/copilot.js +169 -0
- package/dist/core/usage/providers/copilot.js.map +1 -0
- package/dist/core/usage/providers/openai.d.ts +2 -0
- package/dist/core/usage/providers/openai.js +133 -0
- package/dist/core/usage/providers/openai.js.map +1 -0
- package/dist/core/usage/redact.d.ts +3 -0
- package/dist/core/usage/redact.js +67 -0
- package/dist/core/usage/redact.js.map +1 -0
- package/dist/core/usage/store.d.ts +4 -0
- package/dist/core/usage/store.js +31 -0
- package/dist/core/usage/store.js.map +1 -0
- package/dist/core/usage/types.d.ts +21 -0
- package/dist/core/usage/types.js +2 -0
- package/dist/core/usage/types.js.map +1 -0
- package/dist/index.d.ts +1 -37
- package/dist/index.js +1 -60
- package/dist/index.js.map +1 -1
- package/dist/server/auth-watcher.d.ts +31 -0
- package/dist/server/auth-watcher.js +227 -0
- package/dist/server/auth-watcher.js.map +1 -0
- package/dist/server/commands.d.ts +2 -0
- package/dist/server/commands.js +46 -0
- package/dist/server/commands.js.map +1 -0
- package/dist/server/fetch-patch.d.ts +3 -0
- package/dist/server/fetch-patch.js +118 -0
- package/dist/server/fetch-patch.js.map +1 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/index.js +94 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/native.d.ts +6 -0
- package/dist/server/native.js +35 -0
- package/dist/server/native.js.map +1 -0
- package/dist/server/request-balancer.d.ts +16 -0
- package/dist/server/request-balancer.js +43 -0
- package/dist/server/request-balancer.js.map +1 -0
- package/dist/tui/actions.d.ts +41 -0
- package/dist/tui/actions.js +88 -0
- package/dist/tui/actions.js.map +1 -0
- package/dist/tui/actions.ts +140 -0
- package/dist/tui/balancer-bar-sync.d.ts +19 -0
- package/dist/tui/balancer-bar-sync.js +45 -0
- package/dist/tui/balancer-bar-sync.js.map +1 -0
- package/dist/tui/balancer-bar-sync.ts +56 -0
- package/dist/tui/components/alias-dialog.d.ts +4 -0
- package/dist/tui/components/alias-dialog.js +57 -0
- package/dist/tui/components/alias-dialog.js.map +1 -0
- package/dist/tui/components/alias-dialog.tsx +72 -0
- package/dist/tui/components/dashboard.d.ts +12 -0
- package/dist/tui/components/dashboard.js +201 -0
- package/dist/tui/components/dashboard.js.map +1 -0
- package/dist/tui/components/dashboard.tsx +393 -0
- package/dist/tui/components/priority-screen.d.ts +9 -0
- package/dist/tui/components/priority-screen.js +120 -0
- package/dist/tui/components/priority-screen.js.map +1 -0
- package/dist/tui/components/priority-screen.tsx +302 -0
- package/dist/tui/components/provider-model-dialog.d.ts +13 -0
- package/dist/tui/components/provider-model-dialog.js +45 -0
- package/dist/tui/components/provider-model-dialog.js.map +1 -0
- package/dist/tui/components/provider-model-dialog.tsx +71 -0
- package/dist/tui/components/rename-dialog.d.ts +4 -0
- package/dist/tui/components/rename-dialog.js +24 -0
- package/dist/tui/components/rename-dialog.js.map +1 -0
- package/dist/tui/components/rename-dialog.tsx +40 -0
- package/dist/tui/components/sidebar.d.ts +10 -0
- package/dist/tui/components/sidebar.js +27 -0
- package/dist/tui/components/sidebar.js.map +1 -0
- package/dist/tui/components/sidebar.tsx +97 -0
- package/dist/tui/components/status-indicator.d.ts +9 -0
- package/dist/tui/components/status-indicator.js +59 -0
- package/dist/tui/components/status-indicator.js.map +1 -0
- package/dist/tui/components/status-indicator.tsx +78 -0
- package/dist/tui/components/usage-bar.d.ts +8 -0
- package/dist/tui/components/usage-bar.js +7 -0
- package/dist/tui/components/usage-bar.js.map +1 -0
- package/dist/tui/components/usage-bar.tsx +13 -0
- package/dist/tui/components/usage-display.d.ts +10 -0
- package/dist/tui/components/usage-display.js +32 -0
- package/dist/tui/components/usage-display.js.map +1 -0
- package/dist/tui/components/usage-display.tsx +29 -0
- package/dist/tui/connect.d.ts +30 -0
- package/dist/tui/connect.js +73 -0
- package/dist/tui/connect.js.map +1 -0
- package/dist/tui/connect.ts +100 -0
- package/dist/tui/dashboard-keys.d.ts +45 -0
- package/dist/tui/dashboard-keys.js +44 -0
- package/dist/tui/dashboard-keys.js.map +1 -0
- package/dist/tui/dashboard-keys.ts +60 -0
- package/dist/tui/native-model-apply.d.ts +21 -0
- package/dist/tui/native-model-apply.js +53 -0
- package/dist/tui/native-model-apply.js.map +1 -0
- package/dist/tui/native-model-apply.ts +73 -0
- package/dist/tui/priority-keys.d.ts +40 -0
- package/dist/tui/priority-keys.js +38 -0
- package/dist/tui/priority-keys.js.map +1 -0
- package/dist/tui/priority-keys.ts +59 -0
- package/dist/tui/provider-models.d.ts +19 -0
- package/dist/tui/provider-models.js +17 -0
- package/dist/tui/provider-models.js.map +1 -0
- package/dist/tui/provider-models.ts +36 -0
- package/dist/tui/responsive.d.ts +9 -0
- package/dist/tui/responsive.js +13 -0
- package/dist/tui/responsive.js.map +1 -0
- package/dist/tui/responsive.ts +16 -0
- package/dist/tui/selection-colors.d.ts +10 -0
- package/dist/tui/selection-colors.js +38 -0
- package/dist/tui/selection-colors.js.map +1 -0
- package/dist/tui/selection-colors.ts +45 -0
- package/dist/tui/state.d.ts +14 -0
- package/dist/tui/state.js +46 -0
- package/dist/tui/state.js.map +1 -0
- package/dist/tui/state.ts +65 -0
- package/dist/tui/status-format.d.ts +15 -0
- package/dist/tui/status-format.js +17 -0
- package/dist/tui/status-format.js.map +1 -0
- package/dist/tui/status-format.ts +29 -0
- package/dist/tui/tui.d.ts +7 -0
- package/dist/tui/tui.js +120 -0
- package/dist/tui/tui.js.map +1 -0
- package/dist/tui/tui.tsx +142 -0
- package/dist/tui/usage-auto-refresh.d.ts +16 -0
- package/dist/tui/usage-auto-refresh.js +46 -0
- package/dist/tui/usage-auto-refresh.js.map +1 -0
- package/dist/tui/usage-auto-refresh.ts +64 -0
- package/dist/tui/usage-format.d.ts +2 -0
- package/dist/tui/usage-format.js +17 -0
- package/dist/tui/usage-format.js.map +1 -0
- package/dist/tui/usage-format.ts +14 -0
- package/package.json +18 -3
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { now } from "./time";
|
|
2
|
+
const key = "native_connect_until";
|
|
3
|
+
export function markNativeConnectInProgress(db, durationMs = 180_000) {
|
|
4
|
+
db.query(`INSERT INTO settings (key, value) VALUES ('native_connect_until', ?)
|
|
5
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(String(now() + durationMs));
|
|
6
|
+
}
|
|
7
|
+
export function isNativeConnectInProgress(db) {
|
|
8
|
+
const row = db.query("SELECT value FROM settings WHERE key = ?").get(key);
|
|
9
|
+
const until = Number(row?.value ?? 0);
|
|
10
|
+
if (Number.isFinite(until) && until > now())
|
|
11
|
+
return true;
|
|
12
|
+
if (row)
|
|
13
|
+
db.query("DELETE FROM settings WHERE key = ?").run(key);
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
export function clearNativeConnectInProgress(db) {
|
|
17
|
+
db.query("DELETE FROM settings WHERE key = ?").run(key);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=native-connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-connect.js","sourceRoot":"","sources":["../../src/core/native-connect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAE7B,MAAM,GAAG,GAAG,sBAAsB,CAAC;AAEnC,MAAM,UAAU,2BAA2B,CAAC,EAAY,EAAE,UAAU,GAAG,OAAO;IAC1E,EAAE,CAAC,KAAK,CACJ;+DACuD,CAC1D,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,EAAY;IAClD,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAA8B,0CAA0C,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvG,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IACtC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,GAAG;QAAE,EAAE,CAAC,KAAK,CAAoB,oCAAoC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,EAAY;IACrD,EAAE,CAAC,KAAK,CAAoB,oCAAoC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
function joinPath(...parts) {
|
|
2
|
+
return parts.filter(Boolean).join("/").replace(/\/+/g, "/");
|
|
3
|
+
}
|
|
4
|
+
function homeDir() {
|
|
5
|
+
return Bun.env.HOME || "/";
|
|
6
|
+
}
|
|
7
|
+
function xdgConfigHome() {
|
|
8
|
+
return Bun.env.XDG_CONFIG_HOME || joinPath(homeDir(), ".config");
|
|
9
|
+
}
|
|
10
|
+
function xdgDataHome() {
|
|
11
|
+
return Bun.env.XDG_DATA_HOME || joinPath(homeDir(), ".local", "share");
|
|
12
|
+
}
|
|
13
|
+
export function configDir() {
|
|
14
|
+
const configured = Bun.env.OPENCODE_CONFIG_DIR;
|
|
15
|
+
return configured ? joinPath(configured) : joinPath(xdgConfigHome(), "opencode");
|
|
16
|
+
}
|
|
17
|
+
export function dataDir() {
|
|
18
|
+
return joinPath(xdgDataHome(), "opencode");
|
|
19
|
+
}
|
|
20
|
+
export function storePath() {
|
|
21
|
+
return joinPath(configDir(), "balancer.sqlite");
|
|
22
|
+
}
|
|
23
|
+
export function nativeAuthPath() {
|
|
24
|
+
return joinPath(dataDir(), "auth.json");
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/core/path.ts"],"names":[],"mappings":"AAAA,SAAS,QAAQ,CAAC,GAAG,KAAe;IAChC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,OAAO;IACZ,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC;AAC/B,CAAC;AAED,SAAS,aAAa;IAClB,OAAO,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,WAAW;IAChB,OAAO,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,SAAS;IACrB,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC/C,OAAO,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,UAAU,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,OAAO;IACnB,OAAO,QAAQ,CAAC,WAAW,EAAE,EAAE,UAAU,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,SAAS;IACrB,OAAO,QAAQ,CAAC,SAAS,EAAE,EAAE,iBAAiB,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,cAAc;IAC1B,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import type { AuthInfo, PendingConnection } from "./types";
|
|
3
|
+
export declare function pendingPromptGroupID(db: Database, id: string): string | undefined;
|
|
4
|
+
export declare function createPendingConnection(db: Database, providerID: string, auth: AuthInfo, source: PendingConnection["source"]): PendingConnection;
|
|
5
|
+
export declare function claimPendingPrompt(db: Database, id: string): PendingConnection | undefined;
|
|
6
|
+
export declare function releasePendingPrompt(db: Database, id: string): boolean;
|
|
7
|
+
export declare function listPendingConnections(db: Database): PendingConnection[];
|
|
8
|
+
export declare function completePendingConnection(db: Database, id: string, alias: string): import("./types").Account;
|
|
9
|
+
export declare function removePendingConnection(db: Database, id: string): boolean;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { saveAccount } from "./accounts";
|
|
3
|
+
import { now } from "./time";
|
|
4
|
+
const pendingSources = ["auth-file", "http", "oauth-callback"];
|
|
5
|
+
const promptStatuses = ["new", "prompted", "dismissed"];
|
|
6
|
+
const authTypes = ["api", "oauth", "wellknown"];
|
|
7
|
+
function isAuthType(value) {
|
|
8
|
+
return authTypes.includes(value);
|
|
9
|
+
}
|
|
10
|
+
function parsePendingAuth(row) {
|
|
11
|
+
let auth;
|
|
12
|
+
try {
|
|
13
|
+
auth = JSON.parse(row.auth_json);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new Error(`Invalid pending connection row ${row.id}: auth_json is invalid`);
|
|
17
|
+
}
|
|
18
|
+
if (!auth || typeof auth !== "object" || !("type" in auth) || typeof auth.type !== "string") {
|
|
19
|
+
throw new Error(`Invalid pending connection row ${row.id}: auth_json type is invalid`);
|
|
20
|
+
}
|
|
21
|
+
if (!isAuthType(auth.type)) {
|
|
22
|
+
throw new Error(`Invalid pending connection row ${row.id}: auth_json type ${auth.type} is invalid`);
|
|
23
|
+
}
|
|
24
|
+
return auth;
|
|
25
|
+
}
|
|
26
|
+
function validatePendingAuthType(row) {
|
|
27
|
+
if (!isAuthType(row.auth_type)) {
|
|
28
|
+
throw new Error(`Invalid pending connection row ${row.id}: auth_type ${row.auth_type} is invalid`);
|
|
29
|
+
}
|
|
30
|
+
return row.auth_type;
|
|
31
|
+
}
|
|
32
|
+
function validatePendingSource(row) {
|
|
33
|
+
if (!pendingSources.includes(row.source)) {
|
|
34
|
+
throw new Error(`Invalid pending connection row ${row.id}: source ${row.source} is invalid`);
|
|
35
|
+
}
|
|
36
|
+
return row.source;
|
|
37
|
+
}
|
|
38
|
+
function validatePromptStatus(row) {
|
|
39
|
+
if (!promptStatuses.includes(row.prompt_status)) {
|
|
40
|
+
throw new Error(`Invalid pending connection row ${row.id}: prompt_status ${row.prompt_status} is invalid`);
|
|
41
|
+
}
|
|
42
|
+
return row.prompt_status;
|
|
43
|
+
}
|
|
44
|
+
function pendingConnectionFromRow(row) {
|
|
45
|
+
const auth = parsePendingAuth(row);
|
|
46
|
+
const authType = validatePendingAuthType(row);
|
|
47
|
+
if (auth.type !== authType) {
|
|
48
|
+
throw new Error(`Invalid pending connection row ${row.id}: auth_type ${authType} does not match auth_json type ${auth.type}`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
id: row.id,
|
|
52
|
+
providerID: row.provider_id,
|
|
53
|
+
auth,
|
|
54
|
+
authType,
|
|
55
|
+
source: validatePendingSource(row),
|
|
56
|
+
capturedAt: row.captured_at,
|
|
57
|
+
promptStatus: validatePromptStatus(row),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function authIdentityKey(auth) {
|
|
61
|
+
if (auth.type === "api")
|
|
62
|
+
return `api\0${auth.key}`;
|
|
63
|
+
if (auth.type === "wellknown")
|
|
64
|
+
return `wellknown\0${auth.key}\0${auth.token}`;
|
|
65
|
+
const accountID = oauthAccountID(auth);
|
|
66
|
+
return accountID ? `oauth-account\0${accountID}` : `oauth-refresh\0${auth.refresh}`;
|
|
67
|
+
}
|
|
68
|
+
function decodeJwtPayload(token) {
|
|
69
|
+
const payload = token.split(".")[1];
|
|
70
|
+
if (!payload)
|
|
71
|
+
return undefined;
|
|
72
|
+
try {
|
|
73
|
+
const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
74
|
+
return decoded && typeof decoded === "object" && !Array.isArray(decoded) ? decoded : undefined;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function oauthAccountID(auth) {
|
|
81
|
+
if (auth.accountId)
|
|
82
|
+
return auth.accountId;
|
|
83
|
+
const claim = decodeJwtPayload(auth.access)?.["https://api.openai.com/auth"];
|
|
84
|
+
if (!claim || typeof claim !== "object" || Array.isArray(claim))
|
|
85
|
+
return undefined;
|
|
86
|
+
const accountID = claim.chatgpt_account_id;
|
|
87
|
+
return typeof accountID === "string" && accountID.length > 0 ? accountID : undefined;
|
|
88
|
+
}
|
|
89
|
+
function samePendingIdentity(auth, other) {
|
|
90
|
+
return authIdentityKey(auth) === authIdentityKey(other);
|
|
91
|
+
}
|
|
92
|
+
function pendingID(providerID, auth, source) {
|
|
93
|
+
const hash = createHash("sha256")
|
|
94
|
+
.update(`${providerID}\0${source}\0${authIdentityKey(auth)}`)
|
|
95
|
+
.digest("hex")
|
|
96
|
+
.slice(0, 32);
|
|
97
|
+
return `pending-${hash}`;
|
|
98
|
+
}
|
|
99
|
+
export function pendingPromptGroupID(db, id) {
|
|
100
|
+
const row = selectPendingRow(db, id);
|
|
101
|
+
if (!row)
|
|
102
|
+
return undefined;
|
|
103
|
+
const identity = pendingIdentity(row);
|
|
104
|
+
return `${identity.providerID}\0${identity.source}\0${authIdentityKey(identity.auth)}`;
|
|
105
|
+
}
|
|
106
|
+
function selectPendingRow(db, id) {
|
|
107
|
+
return db
|
|
108
|
+
.query(`SELECT id, provider_id, auth_json, auth_type, source, captured_at, prompt_status
|
|
109
|
+
FROM pending_connections
|
|
110
|
+
WHERE id = ?`)
|
|
111
|
+
.get(id);
|
|
112
|
+
}
|
|
113
|
+
function pendingIdentity(row) {
|
|
114
|
+
return {
|
|
115
|
+
providerID: row.provider_id,
|
|
116
|
+
auth: parsePendingAuth(row),
|
|
117
|
+
source: validatePendingSource(row),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function equivalentPendingRows(db, identity) {
|
|
121
|
+
return db
|
|
122
|
+
.query(`SELECT id, provider_id, auth_json, auth_type, source, captured_at, prompt_status
|
|
123
|
+
FROM pending_connections
|
|
124
|
+
WHERE provider_id = ? AND source = ? AND auth_type = ?`)
|
|
125
|
+
.all(identity.providerID, identity.source, identity.auth.type)
|
|
126
|
+
.filter((row) => samePendingIdentity(parsePendingAuth(row), identity.auth));
|
|
127
|
+
}
|
|
128
|
+
export function createPendingConnection(db, providerID, auth, source) {
|
|
129
|
+
const authJSON = JSON.stringify(auth);
|
|
130
|
+
const identity = { providerID, auth, source };
|
|
131
|
+
const existing = equivalentPendingRows(db, identity)[0];
|
|
132
|
+
if (existing)
|
|
133
|
+
return pendingConnectionFromRow(existing);
|
|
134
|
+
const pending = {
|
|
135
|
+
id: pendingID(providerID, auth, source),
|
|
136
|
+
providerID,
|
|
137
|
+
auth,
|
|
138
|
+
authType: auth.type,
|
|
139
|
+
source,
|
|
140
|
+
capturedAt: now(),
|
|
141
|
+
promptStatus: "new",
|
|
142
|
+
};
|
|
143
|
+
db.query(`INSERT INTO pending_connections (
|
|
144
|
+
id,
|
|
145
|
+
provider_id,
|
|
146
|
+
auth_json,
|
|
147
|
+
auth_type,
|
|
148
|
+
source,
|
|
149
|
+
captured_at,
|
|
150
|
+
prompt_status
|
|
151
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
152
|
+
ON CONFLICT(id) DO NOTHING`).run(pending.id, pending.providerID, authJSON, pending.authType, pending.source, pending.capturedAt, pending.promptStatus);
|
|
153
|
+
const row = selectPendingRow(db, pending.id);
|
|
154
|
+
return row ? pendingConnectionFromRow(row) : pending;
|
|
155
|
+
}
|
|
156
|
+
export function claimPendingPrompt(db, id) {
|
|
157
|
+
const claim = db.transaction(() => {
|
|
158
|
+
const row = selectPendingRow(db, id);
|
|
159
|
+
if (!row)
|
|
160
|
+
return undefined;
|
|
161
|
+
const identity = pendingIdentity(row);
|
|
162
|
+
const equivalent = equivalentPendingRows(db, identity);
|
|
163
|
+
const ids = equivalent.map((pending) => pending.id);
|
|
164
|
+
const result = db
|
|
165
|
+
.query(`UPDATE pending_connections
|
|
166
|
+
SET prompt_status = 'prompted'
|
|
167
|
+
WHERE id IN (${ids.map(() => "?").join(", ")})
|
|
168
|
+
AND prompt_status = 'new'`)
|
|
169
|
+
.run(...ids);
|
|
170
|
+
if (result.changes === 0)
|
|
171
|
+
return undefined;
|
|
172
|
+
return pendingConnectionFromRow({ ...row, prompt_status: "prompted" });
|
|
173
|
+
});
|
|
174
|
+
return claim();
|
|
175
|
+
}
|
|
176
|
+
export function releasePendingPrompt(db, id) {
|
|
177
|
+
const release = db.transaction(() => {
|
|
178
|
+
const row = selectPendingRow(db, id);
|
|
179
|
+
if (!row)
|
|
180
|
+
return false;
|
|
181
|
+
const identity = pendingIdentity(row);
|
|
182
|
+
const ids = equivalentPendingRows(db, identity).map((pending) => pending.id);
|
|
183
|
+
if (ids.length === 0)
|
|
184
|
+
return false;
|
|
185
|
+
const result = db
|
|
186
|
+
.query(`UPDATE pending_connections
|
|
187
|
+
SET prompt_status = 'new'
|
|
188
|
+
WHERE id IN (${ids.map(() => "?").join(", ")})
|
|
189
|
+
AND prompt_status = 'prompted'`)
|
|
190
|
+
.run(...ids);
|
|
191
|
+
return result.changes > 0;
|
|
192
|
+
});
|
|
193
|
+
return release();
|
|
194
|
+
}
|
|
195
|
+
export function listPendingConnections(db) {
|
|
196
|
+
const rows = db
|
|
197
|
+
.query(`SELECT id, provider_id, auth_json, auth_type, source, captured_at, prompt_status
|
|
198
|
+
FROM pending_connections
|
|
199
|
+
ORDER BY captured_at DESC, id DESC`)
|
|
200
|
+
.all();
|
|
201
|
+
return rows.map(pendingConnectionFromRow);
|
|
202
|
+
}
|
|
203
|
+
export function completePendingConnection(db, id, alias) {
|
|
204
|
+
const complete = db.transaction(() => {
|
|
205
|
+
const row = selectPendingRow(db, id);
|
|
206
|
+
if (!row)
|
|
207
|
+
throw new Error(`Pending connection not found: ${id}`);
|
|
208
|
+
const pending = pendingConnectionFromRow(row);
|
|
209
|
+
const account = saveAccount(db, pending.providerID, alias, pending.auth);
|
|
210
|
+
const identity = pendingIdentity(row);
|
|
211
|
+
const ids = equivalentPendingRows(db, identity).map((pending) => pending.id);
|
|
212
|
+
db.query(`DELETE FROM pending_connections
|
|
213
|
+
WHERE id IN (${ids.map(() => "?").join(", ")})`).run(...ids);
|
|
214
|
+
return account;
|
|
215
|
+
});
|
|
216
|
+
return complete();
|
|
217
|
+
}
|
|
218
|
+
export function removePendingConnection(db, id) {
|
|
219
|
+
const remove = db.transaction(() => {
|
|
220
|
+
const row = selectPendingRow(db, id);
|
|
221
|
+
if (!row)
|
|
222
|
+
return false;
|
|
223
|
+
const identity = pendingIdentity(row);
|
|
224
|
+
const ids = equivalentPendingRows(db, identity).map((pending) => pending.id);
|
|
225
|
+
if (ids.length === 0)
|
|
226
|
+
return false;
|
|
227
|
+
const result = db
|
|
228
|
+
.query(`UPDATE pending_connections
|
|
229
|
+
SET prompt_status = 'dismissed'
|
|
230
|
+
WHERE id IN (${ids.map(() => "?").join(", ")})
|
|
231
|
+
AND prompt_status != 'dismissed'`)
|
|
232
|
+
.run(...ids);
|
|
233
|
+
return result.changes > 0;
|
|
234
|
+
});
|
|
235
|
+
return remove();
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=pending.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/core/pending.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import type { Account } from "./types";
|
|
3
|
+
export type PriorityEntry = {
|
|
4
|
+
providerID: string;
|
|
5
|
+
position: number;
|
|
6
|
+
modelID?: string;
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type ActiveSelection = {
|
|
10
|
+
providerID: string;
|
|
11
|
+
modelID: string;
|
|
12
|
+
account: Account;
|
|
13
|
+
};
|
|
14
|
+
export declare function listProviderPriority(db: Database): PriorityEntry[];
|
|
15
|
+
export declare function setProviderModel(db: Database, providerID: string, modelID: string): void;
|
|
16
|
+
export declare function setProviderEnabled(db: Database, providerID: string, enabled: boolean): void;
|
|
17
|
+
export declare function moveProvider(db: Database, providerID: string, direction: -1 | 1): void;
|
|
18
|
+
export declare function getBalancingEnabled(db: Database): boolean;
|
|
19
|
+
export declare function setBalancingEnabled(db: Database, enabled: boolean): void;
|
|
20
|
+
export declare function resolveActiveSelection(db: Database, nowMs?: number, preferredProviderID?: string): ActiveSelection | undefined;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { getActiveAccount, listAccounts } from "./accounts";
|
|
2
|
+
import { now } from "./time";
|
|
3
|
+
function storedRows(db) {
|
|
4
|
+
const rows = db
|
|
5
|
+
.query("SELECT provider_id, position, model_id, enabled FROM provider_priority")
|
|
6
|
+
.all();
|
|
7
|
+
return new Map(rows.map((row) => [row.provider_id, row]));
|
|
8
|
+
}
|
|
9
|
+
function providersWithAccounts(db) {
|
|
10
|
+
return [...new Set(listAccounts(db).map((account) => account.providerID))];
|
|
11
|
+
}
|
|
12
|
+
function nextPosition(stored) {
|
|
13
|
+
let max = -1;
|
|
14
|
+
for (const row of stored.values())
|
|
15
|
+
max = Math.max(max, row.position);
|
|
16
|
+
return max + 1;
|
|
17
|
+
}
|
|
18
|
+
function upsert(db, providerID, patch) {
|
|
19
|
+
const stored = storedRows(db);
|
|
20
|
+
const existing = stored.get(providerID);
|
|
21
|
+
const position = patch.position ?? existing?.position ?? nextPosition(stored);
|
|
22
|
+
const modelID = patch.modelID !== undefined ? patch.modelID : (existing?.model_id ?? null);
|
|
23
|
+
const enabled = patch.enabled !== undefined ? (patch.enabled ? 1 : 0) : (existing?.enabled ?? 1);
|
|
24
|
+
db.query(`INSERT INTO provider_priority (provider_id, position, model_id, enabled, updated_at)
|
|
25
|
+
VALUES (?, ?, ?, ?, ?)
|
|
26
|
+
ON CONFLICT(provider_id) DO UPDATE SET
|
|
27
|
+
position = excluded.position,
|
|
28
|
+
model_id = excluded.model_id,
|
|
29
|
+
enabled = excluded.enabled,
|
|
30
|
+
updated_at = excluded.updated_at`).run(providerID, position, modelID, enabled, now());
|
|
31
|
+
}
|
|
32
|
+
export function listProviderPriority(db) {
|
|
33
|
+
const stored = storedRows(db);
|
|
34
|
+
const providers = providersWithAccounts(db);
|
|
35
|
+
const ordered = providers.slice().sort((a, b) => {
|
|
36
|
+
const ra = stored.get(a);
|
|
37
|
+
const rb = stored.get(b);
|
|
38
|
+
if (ra && rb)
|
|
39
|
+
return ra.position - rb.position || a.localeCompare(b);
|
|
40
|
+
if (ra)
|
|
41
|
+
return -1;
|
|
42
|
+
if (rb)
|
|
43
|
+
return 1;
|
|
44
|
+
return a.localeCompare(b);
|
|
45
|
+
});
|
|
46
|
+
return ordered.map((providerID, index) => {
|
|
47
|
+
const row = stored.get(providerID);
|
|
48
|
+
return {
|
|
49
|
+
providerID,
|
|
50
|
+
position: index,
|
|
51
|
+
modelID: row?.model_id ?? undefined,
|
|
52
|
+
enabled: row ? row.enabled === 1 : true,
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export function setProviderModel(db, providerID, modelID) {
|
|
57
|
+
upsert(db, providerID, { modelID });
|
|
58
|
+
}
|
|
59
|
+
export function setProviderEnabled(db, providerID, enabled) {
|
|
60
|
+
upsert(db, providerID, { enabled });
|
|
61
|
+
}
|
|
62
|
+
export function moveProvider(db, providerID, direction) {
|
|
63
|
+
const list = listProviderPriority(db);
|
|
64
|
+
const index = list.findIndex((entry) => entry.providerID === providerID);
|
|
65
|
+
if (index === -1)
|
|
66
|
+
return;
|
|
67
|
+
const target = index + direction;
|
|
68
|
+
if (target < 0 || target >= list.length)
|
|
69
|
+
return;
|
|
70
|
+
const reordered = list.slice();
|
|
71
|
+
const [moved] = reordered.splice(index, 1);
|
|
72
|
+
reordered.splice(target, 0, moved);
|
|
73
|
+
const persist = db.transaction(() => {
|
|
74
|
+
reordered.forEach((entry, position) => upsert(db, entry.providerID, { position }));
|
|
75
|
+
});
|
|
76
|
+
persist();
|
|
77
|
+
}
|
|
78
|
+
export function getBalancingEnabled(db) {
|
|
79
|
+
const row = db
|
|
80
|
+
.query("SELECT value FROM settings WHERE key = ?")
|
|
81
|
+
.get("balancing_enabled");
|
|
82
|
+
return row?.value === "1";
|
|
83
|
+
}
|
|
84
|
+
export function setBalancingEnabled(db, enabled) {
|
|
85
|
+
db.query(`INSERT INTO settings (key, value) VALUES ('balancing_enabled', ?)
|
|
86
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(enabled ? "1" : "0");
|
|
87
|
+
}
|
|
88
|
+
function chooseHealthyAccount(db, providerID, nowMs) {
|
|
89
|
+
const healthy = listAccounts(db, providerID).filter((account) => !account.disabled && (!account.rateLimitedUntil || account.rateLimitedUntil <= nowMs));
|
|
90
|
+
if (healthy.length === 0)
|
|
91
|
+
return undefined;
|
|
92
|
+
const active = getActiveAccount(db, providerID);
|
|
93
|
+
if (active && healthy.some((account) => account.alias === active.alias))
|
|
94
|
+
return active;
|
|
95
|
+
return healthy[0];
|
|
96
|
+
}
|
|
97
|
+
export function resolveActiveSelection(db, nowMs = now(), preferredProviderID) {
|
|
98
|
+
const entries = listProviderPriority(db);
|
|
99
|
+
const ordered = preferredProviderID
|
|
100
|
+
? entries.slice().sort((a, b) => {
|
|
101
|
+
if (a.providerID === preferredProviderID)
|
|
102
|
+
return -1;
|
|
103
|
+
if (b.providerID === preferredProviderID)
|
|
104
|
+
return 1;
|
|
105
|
+
return a.position - b.position;
|
|
106
|
+
})
|
|
107
|
+
: entries;
|
|
108
|
+
for (const entry of ordered) {
|
|
109
|
+
if (!entry.enabled)
|
|
110
|
+
continue;
|
|
111
|
+
if (!entry.modelID)
|
|
112
|
+
continue;
|
|
113
|
+
const account = chooseHealthyAccount(db, entry.providerID, nowMs);
|
|
114
|
+
if (!account)
|
|
115
|
+
continue;
|
|
116
|
+
return { providerID: entry.providerID, modelID: entry.modelID, account };
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=priority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"priority.js","sourceRoot":"","sources":["../../src/core/priority.ts"],"names":[],"mappings":"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"}
|