gearbox-code 0.1.2 → 0.1.3
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/cli.mjs +259 -1061
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
// @bun
|
|
1
|
+
#!/usr/bin/env node
|
|
3
2
|
import { createRequire } from "node:module";
|
|
4
3
|
var __create = Object.create;
|
|
5
4
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -61639,6 +61638,23 @@ var require_src5 = __commonJS((exports) => {
|
|
|
61639
61638
|
});
|
|
61640
61639
|
|
|
61641
61640
|
// src/accounts/store.ts
|
|
61641
|
+
var exports_store = {};
|
|
61642
|
+
__export(exports_store, {
|
|
61643
|
+
setSecret: () => setSecret,
|
|
61644
|
+
setDefaultAccount: () => setDefaultAccount,
|
|
61645
|
+
secretRefs: () => secretRefs,
|
|
61646
|
+
saveAccounts: () => saveAccounts,
|
|
61647
|
+
removeAccount: () => removeAccount,
|
|
61648
|
+
putAccount: () => putAccount,
|
|
61649
|
+
markUsed: () => markUsed,
|
|
61650
|
+
loadAccounts: () => loadAccounts,
|
|
61651
|
+
listAccounts: () => listAccounts,
|
|
61652
|
+
getSecret: () => getSecret,
|
|
61653
|
+
getAccount: () => getAccount,
|
|
61654
|
+
deleteSecret: () => deleteSecret,
|
|
61655
|
+
defaultAccount: () => defaultAccount,
|
|
61656
|
+
accountsForProvider: () => accountsForProvider
|
|
61657
|
+
});
|
|
61642
61658
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
61643
61659
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "node:fs";
|
|
61644
61660
|
import { join as join3 } from "node:path";
|
|
@@ -61819,6 +61835,12 @@ var SERVICE = "gearbox", home2 = () => process.env.GEARBOX_HOME || join3(homedir
|
|
|
61819
61835
|
var init_store = () => {};
|
|
61820
61836
|
|
|
61821
61837
|
// src/accounts/catalog.ts
|
|
61838
|
+
var exports_catalog = {};
|
|
61839
|
+
__export(exports_catalog, {
|
|
61840
|
+
detectProviderByKey: () => detectProviderByKey,
|
|
61841
|
+
catalogProvider: () => catalogProvider,
|
|
61842
|
+
CATALOG: () => CATALOG
|
|
61843
|
+
});
|
|
61822
61844
|
function catalogProvider(id) {
|
|
61823
61845
|
return BY_ID.get(id);
|
|
61824
61846
|
}
|
|
@@ -64032,6 +64054,123 @@ var init_resolve = __esm(() => {
|
|
|
64032
64054
|
init_catalog();
|
|
64033
64055
|
});
|
|
64034
64056
|
|
|
64057
|
+
// src/accounts/detect.ts
|
|
64058
|
+
var exports_detect = {};
|
|
64059
|
+
__export(exports_detect, {
|
|
64060
|
+
importableEnvCreds: () => importableEnvCreds,
|
|
64061
|
+
importableCloudCreds: () => importableCloudCreds,
|
|
64062
|
+
importEnvCred: () => importEnvCred,
|
|
64063
|
+
importCloudCred: () => importCloudCred,
|
|
64064
|
+
detectEnvCreds: () => detectEnvCreds,
|
|
64065
|
+
detectCloudCreds: () => detectCloudCreds
|
|
64066
|
+
});
|
|
64067
|
+
import { readFileSync as readFileSync11, existsSync as existsSync6 } from "node:fs";
|
|
64068
|
+
import { join as join9 } from "node:path";
|
|
64069
|
+
import { homedir as homedir7 } from "node:os";
|
|
64070
|
+
function detectEnvCreds() {
|
|
64071
|
+
const out = [];
|
|
64072
|
+
for (const p of CATALOG) {
|
|
64073
|
+
if (p.authKind !== "api-key" && p.authKind !== "openai-compat")
|
|
64074
|
+
continue;
|
|
64075
|
+
for (const ev of p.envVars) {
|
|
64076
|
+
const v = process.env[ev];
|
|
64077
|
+
if (v) {
|
|
64078
|
+
out.push({ provider: p.id, label: p.label, envVar: ev, value: v });
|
|
64079
|
+
break;
|
|
64080
|
+
}
|
|
64081
|
+
}
|
|
64082
|
+
}
|
|
64083
|
+
return out;
|
|
64084
|
+
}
|
|
64085
|
+
async function importEnvCred(c) {
|
|
64086
|
+
const id = `${c.provider}-env`;
|
|
64087
|
+
const ref = `${id}:api-key`;
|
|
64088
|
+
await setSecret(ref, c.value);
|
|
64089
|
+
const cat = CATALOG.find((p) => p.id === c.provider);
|
|
64090
|
+
const account = {
|
|
64091
|
+
id,
|
|
64092
|
+
label: `${c.label} (from ${c.envVar})`,
|
|
64093
|
+
provider: c.provider,
|
|
64094
|
+
exec: "in-loop",
|
|
64095
|
+
auth: cat.authKind === "openai-compat" ? { kind: "openai-compat", ref } : { kind: "api-key", ref },
|
|
64096
|
+
baseUrl: cat.baseUrl,
|
|
64097
|
+
enabled: true,
|
|
64098
|
+
addedAt: Date.now()
|
|
64099
|
+
};
|
|
64100
|
+
putAccount(account);
|
|
64101
|
+
return account;
|
|
64102
|
+
}
|
|
64103
|
+
function importableEnvCreds() {
|
|
64104
|
+
return detectEnvCreds().filter((c) => !getAccount(`${c.provider}-env`));
|
|
64105
|
+
}
|
|
64106
|
+
function awsIni(file5, profile = "default") {
|
|
64107
|
+
if (!existsSync6(file5))
|
|
64108
|
+
return {};
|
|
64109
|
+
const out = {};
|
|
64110
|
+
let cur = "";
|
|
64111
|
+
for (const raw of readFileSync11(file5, "utf8").split(`
|
|
64112
|
+
`)) {
|
|
64113
|
+
const line = raw.trim();
|
|
64114
|
+
if (line.startsWith("["))
|
|
64115
|
+
cur = line.slice(1, -1).replace(/^profile\s+/, "");
|
|
64116
|
+
else if (cur === profile && line.includes("=")) {
|
|
64117
|
+
const i2 = line.indexOf("=");
|
|
64118
|
+
out[line.slice(0, i2).trim().toLowerCase()] = line.slice(i2 + 1).trim();
|
|
64119
|
+
}
|
|
64120
|
+
}
|
|
64121
|
+
return out;
|
|
64122
|
+
}
|
|
64123
|
+
function detectCloudCreds() {
|
|
64124
|
+
const out = [];
|
|
64125
|
+
const home5 = homedir7();
|
|
64126
|
+
const creds = awsIni(join9(home5, ".aws", "credentials"));
|
|
64127
|
+
const conf = awsIni(join9(home5, ".aws", "config"));
|
|
64128
|
+
const akid = process.env.AWS_ACCESS_KEY_ID ?? creds.aws_access_key_id;
|
|
64129
|
+
const secret = process.env.AWS_SECRET_ACCESS_KEY ?? creds.aws_secret_access_key;
|
|
64130
|
+
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? conf.region;
|
|
64131
|
+
if (akid && secret) {
|
|
64132
|
+
out.push({
|
|
64133
|
+
provider: "bedrock",
|
|
64134
|
+
label: "Amazon Bedrock",
|
|
64135
|
+
source: process.env.AWS_ACCESS_KEY_ID ? "env" : "~/.aws/credentials",
|
|
64136
|
+
aws: { accessKeyId: akid, secretAccessKey: secret, sessionToken: process.env.AWS_SESSION_TOKEN ?? creds.aws_session_token, region: region ?? "us-east-1" }
|
|
64137
|
+
});
|
|
64138
|
+
}
|
|
64139
|
+
if (process.env.AZURE_API_KEY && process.env.AZURE_RESOURCE_NAME) {
|
|
64140
|
+
out.push({ provider: "azure", label: "Azure OpenAI", source: "env", azure: { resourceName: process.env.AZURE_RESOURCE_NAME, apiKey: process.env.AZURE_API_KEY } });
|
|
64141
|
+
}
|
|
64142
|
+
if (process.env.GOOGLE_VERTEX_PROJECT) {
|
|
64143
|
+
out.push({ provider: "vertex", label: "Google Vertex AI", source: "env", vertex: { project: process.env.GOOGLE_VERTEX_PROJECT, location: process.env.GOOGLE_VERTEX_LOCATION ?? "us-central1" } });
|
|
64144
|
+
}
|
|
64145
|
+
return out;
|
|
64146
|
+
}
|
|
64147
|
+
async function importCloudCred(c) {
|
|
64148
|
+
const id = `${c.provider}-import`;
|
|
64149
|
+
let auth;
|
|
64150
|
+
if (c.aws) {
|
|
64151
|
+
await setSecret(`${id}:akid`, c.aws.accessKeyId);
|
|
64152
|
+
await setSecret(`${id}:secret`, c.aws.secretAccessKey);
|
|
64153
|
+
if (c.aws.sessionToken)
|
|
64154
|
+
await setSecret(`${id}:token`, c.aws.sessionToken);
|
|
64155
|
+
auth = { kind: "aws", accessKeyIdRef: `${id}:akid`, secretKeyRef: `${id}:secret`, sessionTokenRef: c.aws.sessionToken ? `${id}:token` : undefined, region: c.aws.region };
|
|
64156
|
+
} else if (c.azure) {
|
|
64157
|
+
await setSecret(`${id}:api-key`, c.azure.apiKey);
|
|
64158
|
+
auth = { kind: "azure", resourceName: c.azure.resourceName, ref: `${id}:api-key` };
|
|
64159
|
+
} else {
|
|
64160
|
+
auth = { kind: "vertex", project: c.vertex.project, location: c.vertex.location, adc: true };
|
|
64161
|
+
}
|
|
64162
|
+
const account = { id, label: `${c.label} (from ${c.source})`, provider: c.provider, exec: "in-loop", auth, enabled: true, addedAt: Date.now() };
|
|
64163
|
+
putAccount(account);
|
|
64164
|
+
return account;
|
|
64165
|
+
}
|
|
64166
|
+
function importableCloudCreds() {
|
|
64167
|
+
return detectCloudCreds().filter((c) => !getAccount(`${c.provider}-import`));
|
|
64168
|
+
}
|
|
64169
|
+
var init_detect = __esm(() => {
|
|
64170
|
+
init_catalog();
|
|
64171
|
+
init_store();
|
|
64172
|
+
});
|
|
64173
|
+
|
|
64035
64174
|
// src/agent/cli-backend.ts
|
|
64036
64175
|
function newState() {
|
|
64037
64176
|
return { text: "", usage: { inputTokens: 0, outputTokens: 0 }, rates: new Map, toolNames: new Map };
|
|
@@ -64267,345 +64406,23 @@ var init_cli_backend = __esm(() => {
|
|
|
64267
64406
|
CONFIG_DIR_VAR = { claude: "CLAUDE_CONFIG_DIR", codex: "CODEX_HOME" };
|
|
64268
64407
|
});
|
|
64269
64408
|
|
|
64270
|
-
// node_modules/react/jsx-dev-runtime.js
|
|
64271
|
-
var require_jsx_dev_runtime2 = __commonJS((exports, module) => {
|
|
64272
|
-
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development());
|
|
64273
|
-
if (false) {} else {
|
|
64274
|
-
module.exports = react_jsx_dev_runtime_development;
|
|
64275
|
-
}
|
|
64276
|
-
});
|
|
64277
|
-
|
|
64278
|
-
// src/accounts/store.ts
|
|
64279
|
-
var exports_store = {};
|
|
64280
|
-
__export(exports_store, {
|
|
64281
|
-
setSecret: () => setSecret2,
|
|
64282
|
-
setDefaultAccount: () => setDefaultAccount2,
|
|
64283
|
-
secretRefs: () => secretRefs2,
|
|
64284
|
-
saveAccounts: () => saveAccounts2,
|
|
64285
|
-
removeAccount: () => removeAccount2,
|
|
64286
|
-
putAccount: () => putAccount2,
|
|
64287
|
-
markUsed: () => markUsed2,
|
|
64288
|
-
loadAccounts: () => loadAccounts3,
|
|
64289
|
-
listAccounts: () => listAccounts2,
|
|
64290
|
-
getSecret: () => getSecret2,
|
|
64291
|
-
getAccount: () => getAccount2,
|
|
64292
|
-
deleteSecret: () => deleteSecret2,
|
|
64293
|
-
defaultAccount: () => defaultAccount2,
|
|
64294
|
-
accountsForProvider: () => accountsForProvider2
|
|
64295
|
-
});
|
|
64296
|
-
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "node:crypto";
|
|
64297
|
-
import { readFileSync as readFileSync15, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, existsSync as existsSync8 } from "node:fs";
|
|
64298
|
-
import { join as join13 } from "node:path";
|
|
64299
|
-
import { homedir as homedir11 } from "node:os";
|
|
64300
|
-
async function setSecret2(ref, value) {
|
|
64301
|
-
if (typeof Bun !== "undefined" && mode2() !== "file") {
|
|
64302
|
-
try {
|
|
64303
|
-
await Bun.secrets.set({ service: SERVICE2, name: ref, value });
|
|
64304
|
-
return;
|
|
64305
|
-
} catch (e2) {
|
|
64306
|
-
if (mode2() === "keychain")
|
|
64307
|
-
throw e2;
|
|
64308
|
-
}
|
|
64309
|
-
}
|
|
64310
|
-
fileSet2(ref, value);
|
|
64311
|
-
}
|
|
64312
|
-
async function getSecret2(ref) {
|
|
64313
|
-
if (typeof Bun !== "undefined" && mode2() !== "file") {
|
|
64314
|
-
try {
|
|
64315
|
-
const v = await Bun.secrets.get({ service: SERVICE2, name: ref });
|
|
64316
|
-
if (v != null)
|
|
64317
|
-
return v;
|
|
64318
|
-
} catch {
|
|
64319
|
-
if (mode2() === "keychain")
|
|
64320
|
-
return null;
|
|
64321
|
-
}
|
|
64322
|
-
}
|
|
64323
|
-
return fileGet2(ref);
|
|
64324
|
-
}
|
|
64325
|
-
async function deleteSecret2(ref) {
|
|
64326
|
-
if (typeof Bun !== "undefined" && mode2() !== "file") {
|
|
64327
|
-
try {
|
|
64328
|
-
await Bun.secrets.delete({ service: SERVICE2, name: ref });
|
|
64329
|
-
} catch {}
|
|
64330
|
-
}
|
|
64331
|
-
fileDelete2(ref);
|
|
64332
|
-
}
|
|
64333
|
-
function masterKey2() {
|
|
64334
|
-
ensure3();
|
|
64335
|
-
if (existsSync8(keyFile2()))
|
|
64336
|
-
return Buffer.from(readFileSync15(keyFile2(), "utf8").trim(), "base64");
|
|
64337
|
-
const k = randomBytes2(32);
|
|
64338
|
-
writeFileSync9(keyFile2(), k.toString("base64"), { mode: 384 });
|
|
64339
|
-
return k;
|
|
64340
|
-
}
|
|
64341
|
-
function encrypt2(plain) {
|
|
64342
|
-
const iv = randomBytes2(12);
|
|
64343
|
-
const c = createCipheriv2("aes-256-gcm", masterKey2(), iv);
|
|
64344
|
-
const data = Buffer.concat([c.update(plain, "utf8"), c.final()]);
|
|
64345
|
-
return [iv.toString("base64"), c.getAuthTag().toString("base64"), data.toString("base64")].join(".");
|
|
64346
|
-
}
|
|
64347
|
-
function decrypt2(blob) {
|
|
64348
|
-
try {
|
|
64349
|
-
const [iv, tag2, data] = blob.split(".").map((x2) => Buffer.from(x2, "base64"));
|
|
64350
|
-
const d = createDecipheriv2("aes-256-gcm", masterKey2(), iv);
|
|
64351
|
-
d.setAuthTag(tag2);
|
|
64352
|
-
return Buffer.concat([d.update(data), d.final()]).toString("utf8");
|
|
64353
|
-
} catch {
|
|
64354
|
-
return null;
|
|
64355
|
-
}
|
|
64356
|
-
}
|
|
64357
|
-
function readEnc2() {
|
|
64358
|
-
try {
|
|
64359
|
-
return JSON.parse(readFileSync15(encFile2(), "utf8"));
|
|
64360
|
-
} catch {
|
|
64361
|
-
return {};
|
|
64362
|
-
}
|
|
64363
|
-
}
|
|
64364
|
-
function writeEnc2(m2) {
|
|
64365
|
-
ensure3();
|
|
64366
|
-
writeFileSync9(encFile2(), JSON.stringify(m2), { mode: 384 });
|
|
64367
|
-
}
|
|
64368
|
-
function fileSet2(ref, v) {
|
|
64369
|
-
const m2 = readEnc2();
|
|
64370
|
-
m2[ref] = encrypt2(v);
|
|
64371
|
-
writeEnc2(m2);
|
|
64372
|
-
}
|
|
64373
|
-
function fileGet2(ref) {
|
|
64374
|
-
const blob = readEnc2()[ref];
|
|
64375
|
-
return blob ? decrypt2(blob) : null;
|
|
64376
|
-
}
|
|
64377
|
-
function fileDelete2(ref) {
|
|
64378
|
-
const m2 = readEnc2();
|
|
64379
|
-
delete m2[ref];
|
|
64380
|
-
writeEnc2(m2);
|
|
64381
|
-
}
|
|
64382
|
-
function loadAccounts3() {
|
|
64383
|
-
try {
|
|
64384
|
-
const f3 = JSON.parse(readFileSync15(accountsFile2(), "utf8"));
|
|
64385
|
-
if (f3 && Array.isArray(f3.accounts))
|
|
64386
|
-
return { version: 1, defaults: {}, ...f3 };
|
|
64387
|
-
} catch {}
|
|
64388
|
-
return { version: 1, accounts: [], defaults: {} };
|
|
64389
|
-
}
|
|
64390
|
-
function saveAccounts2(f3) {
|
|
64391
|
-
try {
|
|
64392
|
-
ensure3();
|
|
64393
|
-
writeFileSync9(accountsFile2(), JSON.stringify(f3, null, 2), { mode: 384 });
|
|
64394
|
-
} catch {}
|
|
64395
|
-
}
|
|
64396
|
-
function listAccounts2() {
|
|
64397
|
-
return loadAccounts3().accounts;
|
|
64398
|
-
}
|
|
64399
|
-
function accountsForProvider2(provider) {
|
|
64400
|
-
return listAccounts2().filter((a) => a.provider === provider && a.enabled);
|
|
64401
|
-
}
|
|
64402
|
-
function getAccount2(id) {
|
|
64403
|
-
return listAccounts2().find((a) => a.id === id);
|
|
64404
|
-
}
|
|
64405
|
-
function putAccount2(account) {
|
|
64406
|
-
const f3 = loadAccounts3();
|
|
64407
|
-
const i2 = f3.accounts.findIndex((a) => a.id === account.id);
|
|
64408
|
-
if (i2 >= 0)
|
|
64409
|
-
f3.accounts[i2] = account;
|
|
64410
|
-
else
|
|
64411
|
-
f3.accounts.push(account);
|
|
64412
|
-
if (!f3.defaults[account.provider])
|
|
64413
|
-
f3.defaults[account.provider] = account.id;
|
|
64414
|
-
saveAccounts2(f3);
|
|
64415
|
-
}
|
|
64416
|
-
async function removeAccount2(id) {
|
|
64417
|
-
const f3 = loadAccounts3();
|
|
64418
|
-
const acc = f3.accounts.find((a) => a.id === id);
|
|
64419
|
-
f3.accounts = f3.accounts.filter((a) => a.id !== id);
|
|
64420
|
-
for (const [p, aid] of Object.entries(f3.defaults)) {
|
|
64421
|
-
if (aid === id) {
|
|
64422
|
-
const next = f3.accounts.find((a) => a.provider === p);
|
|
64423
|
-
if (next)
|
|
64424
|
-
f3.defaults[p] = next.id;
|
|
64425
|
-
else
|
|
64426
|
-
delete f3.defaults[p];
|
|
64427
|
-
}
|
|
64428
|
-
}
|
|
64429
|
-
saveAccounts2(f3);
|
|
64430
|
-
if (acc)
|
|
64431
|
-
for (const ref of secretRefs2(acc))
|
|
64432
|
-
await deleteSecret2(ref);
|
|
64433
|
-
}
|
|
64434
|
-
function setDefaultAccount2(provider, id) {
|
|
64435
|
-
const f3 = loadAccounts3();
|
|
64436
|
-
if (!f3.accounts.some((a) => a.id === id && a.provider === provider))
|
|
64437
|
-
return;
|
|
64438
|
-
f3.defaults[provider] = id;
|
|
64439
|
-
saveAccounts2(f3);
|
|
64440
|
-
}
|
|
64441
|
-
function defaultAccount2(provider) {
|
|
64442
|
-
const f3 = loadAccounts3();
|
|
64443
|
-
const id = f3.defaults[provider];
|
|
64444
|
-
const byDefault = id ? f3.accounts.find((a) => a.id === id && a.enabled) : undefined;
|
|
64445
|
-
return byDefault ?? f3.accounts.find((a) => a.provider === provider && a.enabled);
|
|
64446
|
-
}
|
|
64447
|
-
function markUsed2(id) {
|
|
64448
|
-
const f3 = loadAccounts3();
|
|
64449
|
-
const a = f3.accounts.find((x2) => x2.id === id);
|
|
64450
|
-
if (a) {
|
|
64451
|
-
a.lastUsedAt = Date.now();
|
|
64452
|
-
saveAccounts2(f3);
|
|
64453
|
-
}
|
|
64454
|
-
}
|
|
64455
|
-
function secretRefs2(a) {
|
|
64456
|
-
const refs = [];
|
|
64457
|
-
const auth = a.auth;
|
|
64458
|
-
if (auth.kind === "api-key" || auth.kind === "azure" || auth.kind === "openai-compat")
|
|
64459
|
-
refs.push(auth.ref);
|
|
64460
|
-
if (auth.kind === "aws") {
|
|
64461
|
-
refs.push(auth.accessKeyIdRef, auth.secretKeyRef);
|
|
64462
|
-
if (auth.sessionTokenRef)
|
|
64463
|
-
refs.push(auth.sessionTokenRef);
|
|
64464
|
-
}
|
|
64465
|
-
if (auth.kind === "vertex" && auth.serviceAccountRef)
|
|
64466
|
-
refs.push(auth.serviceAccountRef);
|
|
64467
|
-
return refs;
|
|
64468
|
-
}
|
|
64469
|
-
var SERVICE2 = "gearbox", home5 = () => process.env.GEARBOX_HOME || join13(homedir11(), ".gearbox"), ensure3 = () => mkdirSync10(home5(), { recursive: true }), mode2 = () => {
|
|
64470
|
-
const m2 = process.env.GEARBOX_SECRET_STORE;
|
|
64471
|
-
return m2 === "file" || m2 === "keychain" ? m2 : "auto";
|
|
64472
|
-
}, encFile2 = () => join13(home5(), "credentials.enc"), keyFile2 = () => join13(home5(), ".enckey"), accountsFile2 = () => join13(home5(), "accounts.json");
|
|
64473
|
-
var init_store2 = () => {};
|
|
64474
|
-
|
|
64475
|
-
// src/accounts/detect.ts
|
|
64476
|
-
var exports_detect = {};
|
|
64477
|
-
__export(exports_detect, {
|
|
64478
|
-
importableEnvCreds: () => importableEnvCreds2,
|
|
64479
|
-
importableCloudCreds: () => importableCloudCreds2,
|
|
64480
|
-
importEnvCred: () => importEnvCred2,
|
|
64481
|
-
importCloudCred: () => importCloudCred2,
|
|
64482
|
-
detectEnvCreds: () => detectEnvCreds2,
|
|
64483
|
-
detectCloudCreds: () => detectCloudCreds2
|
|
64484
|
-
});
|
|
64485
|
-
import { readFileSync as readFileSync16, existsSync as existsSync9 } from "node:fs";
|
|
64486
|
-
import { join as join14 } from "node:path";
|
|
64487
|
-
import { homedir as homedir12 } from "node:os";
|
|
64488
|
-
function detectEnvCreds2() {
|
|
64489
|
-
const out = [];
|
|
64490
|
-
for (const p of CATALOG) {
|
|
64491
|
-
if (p.authKind !== "api-key" && p.authKind !== "openai-compat")
|
|
64492
|
-
continue;
|
|
64493
|
-
for (const ev of p.envVars) {
|
|
64494
|
-
const v = process.env[ev];
|
|
64495
|
-
if (v) {
|
|
64496
|
-
out.push({ provider: p.id, label: p.label, envVar: ev, value: v });
|
|
64497
|
-
break;
|
|
64498
|
-
}
|
|
64499
|
-
}
|
|
64500
|
-
}
|
|
64501
|
-
return out;
|
|
64502
|
-
}
|
|
64503
|
-
async function importEnvCred2(c) {
|
|
64504
|
-
const id = `${c.provider}-env`;
|
|
64505
|
-
const ref = `${id}:api-key`;
|
|
64506
|
-
await setSecret(ref, c.value);
|
|
64507
|
-
const cat = CATALOG.find((p) => p.id === c.provider);
|
|
64508
|
-
const account = {
|
|
64509
|
-
id,
|
|
64510
|
-
label: `${c.label} (from ${c.envVar})`,
|
|
64511
|
-
provider: c.provider,
|
|
64512
|
-
exec: "in-loop",
|
|
64513
|
-
auth: cat.authKind === "openai-compat" ? { kind: "openai-compat", ref } : { kind: "api-key", ref },
|
|
64514
|
-
baseUrl: cat.baseUrl,
|
|
64515
|
-
enabled: true,
|
|
64516
|
-
addedAt: Date.now()
|
|
64517
|
-
};
|
|
64518
|
-
putAccount(account);
|
|
64519
|
-
return account;
|
|
64520
|
-
}
|
|
64521
|
-
function importableEnvCreds2() {
|
|
64522
|
-
return detectEnvCreds2().filter((c) => !getAccount(`${c.provider}-env`));
|
|
64523
|
-
}
|
|
64524
|
-
function awsIni2(file6, profile = "default") {
|
|
64525
|
-
if (!existsSync9(file6))
|
|
64526
|
-
return {};
|
|
64527
|
-
const out = {};
|
|
64528
|
-
let cur = "";
|
|
64529
|
-
for (const raw of readFileSync16(file6, "utf8").split(`
|
|
64530
|
-
`)) {
|
|
64531
|
-
const line = raw.trim();
|
|
64532
|
-
if (line.startsWith("["))
|
|
64533
|
-
cur = line.slice(1, -1).replace(/^profile\s+/, "");
|
|
64534
|
-
else if (cur === profile && line.includes("=")) {
|
|
64535
|
-
const i2 = line.indexOf("=");
|
|
64536
|
-
out[line.slice(0, i2).trim().toLowerCase()] = line.slice(i2 + 1).trim();
|
|
64537
|
-
}
|
|
64538
|
-
}
|
|
64539
|
-
return out;
|
|
64540
|
-
}
|
|
64541
|
-
function detectCloudCreds2() {
|
|
64542
|
-
const out = [];
|
|
64543
|
-
const home6 = homedir12();
|
|
64544
|
-
const creds = awsIni2(join14(home6, ".aws", "credentials"));
|
|
64545
|
-
const conf = awsIni2(join14(home6, ".aws", "config"));
|
|
64546
|
-
const akid = process.env.AWS_ACCESS_KEY_ID ?? creds.aws_access_key_id;
|
|
64547
|
-
const secret = process.env.AWS_SECRET_ACCESS_KEY ?? creds.aws_secret_access_key;
|
|
64548
|
-
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? conf.region;
|
|
64549
|
-
if (akid && secret) {
|
|
64550
|
-
out.push({
|
|
64551
|
-
provider: "bedrock",
|
|
64552
|
-
label: "Amazon Bedrock",
|
|
64553
|
-
source: process.env.AWS_ACCESS_KEY_ID ? "env" : "~/.aws/credentials",
|
|
64554
|
-
aws: { accessKeyId: akid, secretAccessKey: secret, sessionToken: process.env.AWS_SESSION_TOKEN ?? creds.aws_session_token, region: region ?? "us-east-1" }
|
|
64555
|
-
});
|
|
64556
|
-
}
|
|
64557
|
-
if (process.env.AZURE_API_KEY && process.env.AZURE_RESOURCE_NAME) {
|
|
64558
|
-
out.push({ provider: "azure", label: "Azure OpenAI", source: "env", azure: { resourceName: process.env.AZURE_RESOURCE_NAME, apiKey: process.env.AZURE_API_KEY } });
|
|
64559
|
-
}
|
|
64560
|
-
if (process.env.GOOGLE_VERTEX_PROJECT) {
|
|
64561
|
-
out.push({ provider: "vertex", label: "Google Vertex AI", source: "env", vertex: { project: process.env.GOOGLE_VERTEX_PROJECT, location: process.env.GOOGLE_VERTEX_LOCATION ?? "us-central1" } });
|
|
64562
|
-
}
|
|
64563
|
-
return out;
|
|
64564
|
-
}
|
|
64565
|
-
async function importCloudCred2(c) {
|
|
64566
|
-
const id = `${c.provider}-import`;
|
|
64567
|
-
let auth;
|
|
64568
|
-
if (c.aws) {
|
|
64569
|
-
await setSecret(`${id}:akid`, c.aws.accessKeyId);
|
|
64570
|
-
await setSecret(`${id}:secret`, c.aws.secretAccessKey);
|
|
64571
|
-
if (c.aws.sessionToken)
|
|
64572
|
-
await setSecret(`${id}:token`, c.aws.sessionToken);
|
|
64573
|
-
auth = { kind: "aws", accessKeyIdRef: `${id}:akid`, secretKeyRef: `${id}:secret`, sessionTokenRef: c.aws.sessionToken ? `${id}:token` : undefined, region: c.aws.region };
|
|
64574
|
-
} else if (c.azure) {
|
|
64575
|
-
await setSecret(`${id}:api-key`, c.azure.apiKey);
|
|
64576
|
-
auth = { kind: "azure", resourceName: c.azure.resourceName, ref: `${id}:api-key` };
|
|
64577
|
-
} else {
|
|
64578
|
-
auth = { kind: "vertex", project: c.vertex.project, location: c.vertex.location, adc: true };
|
|
64579
|
-
}
|
|
64580
|
-
const account = { id, label: `${c.label} (from ${c.source})`, provider: c.provider, exec: "in-loop", auth, enabled: true, addedAt: Date.now() };
|
|
64581
|
-
putAccount(account);
|
|
64582
|
-
return account;
|
|
64583
|
-
}
|
|
64584
|
-
function importableCloudCreds2() {
|
|
64585
|
-
return detectCloudCreds2().filter((c) => !getAccount(`${c.provider}-import`));
|
|
64586
|
-
}
|
|
64587
|
-
var init_detect = __esm(() => {
|
|
64588
|
-
init_catalog();
|
|
64589
|
-
init_store();
|
|
64590
|
-
});
|
|
64591
|
-
|
|
64592
64409
|
// src/accounts/onboard.ts
|
|
64593
64410
|
var exports_onboard = {};
|
|
64594
64411
|
__export(exports_onboard, {
|
|
64595
|
-
testAccount: () =>
|
|
64596
|
-
cliLoginArgs: () =>
|
|
64597
|
-
cliAuthStatus: () =>
|
|
64412
|
+
testAccount: () => testAccount,
|
|
64413
|
+
cliLoginArgs: () => cliLoginArgs,
|
|
64414
|
+
cliAuthStatus: () => cliAuthStatus,
|
|
64598
64415
|
addableProviders: () => addableProviders,
|
|
64599
|
-
addCliAccount: () =>
|
|
64600
|
-
addByPastedKey: () =>
|
|
64601
|
-
addAzureFoundryAccount: () =>
|
|
64602
|
-
addAzureAccount: () =>
|
|
64603
|
-
addApiKeyAccount: () =>
|
|
64604
|
-
});
|
|
64605
|
-
import { mkdirSync as
|
|
64606
|
-
import { join as
|
|
64607
|
-
import { homedir as
|
|
64608
|
-
async function
|
|
64416
|
+
addCliAccount: () => addCliAccount,
|
|
64417
|
+
addByPastedKey: () => addByPastedKey,
|
|
64418
|
+
addAzureFoundryAccount: () => addAzureFoundryAccount,
|
|
64419
|
+
addAzureAccount: () => addAzureAccount,
|
|
64420
|
+
addApiKeyAccount: () => addApiKeyAccount
|
|
64421
|
+
});
|
|
64422
|
+
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
64423
|
+
import { join as join10 } from "node:path";
|
|
64424
|
+
import { homedir as homedir8 } from "node:os";
|
|
64425
|
+
async function addApiKeyAccount(provider, key, opts = {}) {
|
|
64609
64426
|
const cat = catalogProvider(provider);
|
|
64610
64427
|
if (!cat)
|
|
64611
64428
|
return { ok: false, message: `unknown provider "${provider}" — see /accounts catalog` };
|
|
@@ -64614,7 +64431,7 @@ async function addApiKeyAccount2(provider, key, opts = {}) {
|
|
|
64614
64431
|
if (cat.authKind !== "api-key" && cat.authKind !== "openai-compat") {
|
|
64615
64432
|
return { ok: false, message: `${cat.label} needs ${cat.authKind} credentials — use the guided add (P2)` };
|
|
64616
64433
|
}
|
|
64617
|
-
const id = opts.id ?? `${provider}-${
|
|
64434
|
+
const id = opts.id ?? `${provider}-${shortId()}`;
|
|
64618
64435
|
const ref = `${id}:api-key`;
|
|
64619
64436
|
await setSecret(ref, key.trim());
|
|
64620
64437
|
const account = {
|
|
@@ -64630,7 +64447,7 @@ async function addApiKeyAccount2(provider, key, opts = {}) {
|
|
|
64630
64447
|
putAccount(account);
|
|
64631
64448
|
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
64632
64449
|
}
|
|
64633
|
-
function
|
|
64450
|
+
function azureResourceName(input) {
|
|
64634
64451
|
const s2 = input.trim();
|
|
64635
64452
|
try {
|
|
64636
64453
|
const host = new URL(s2).hostname;
|
|
@@ -64639,7 +64456,7 @@ function azureResourceName2(input) {
|
|
|
64639
64456
|
return s2;
|
|
64640
64457
|
}
|
|
64641
64458
|
}
|
|
64642
|
-
function
|
|
64459
|
+
function azureFoundryBaseUrl(endpoint) {
|
|
64643
64460
|
const trimmed = endpoint.trim().replace(/\/+$/, "");
|
|
64644
64461
|
if (/\/openai\/v1$/i.test(trimmed))
|
|
64645
64462
|
return trimmed;
|
|
@@ -64647,32 +64464,32 @@ function azureFoundryBaseUrl2(endpoint) {
|
|
|
64647
64464
|
return `${trimmed}/v1`;
|
|
64648
64465
|
return `${trimmed}/openai/v1`;
|
|
64649
64466
|
}
|
|
64650
|
-
async function
|
|
64467
|
+
async function addAzureFoundryAccount(endpoint, key, opts = {}) {
|
|
64651
64468
|
if (!/^https?:\/\//i.test(endpoint) || !key.trim())
|
|
64652
64469
|
return { ok: false, message: "usage: /account add azure <foundry-endpoint> <api-key>" };
|
|
64653
64470
|
const host = new URL(endpoint).hostname;
|
|
64654
|
-
const
|
|
64655
|
-
const id = opts.id ?? `azure-foundry-${
|
|
64471
|
+
const slug3 = host.split(".")[0]?.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || shortId();
|
|
64472
|
+
const id = opts.id ?? `azure-foundry-${slug3}`;
|
|
64656
64473
|
const ref = `${id}:api-key`;
|
|
64657
64474
|
await setSecret(ref, key.trim());
|
|
64658
64475
|
const account = {
|
|
64659
64476
|
id,
|
|
64660
|
-
label: opts.label ?? `Azure Foundry (${
|
|
64477
|
+
label: opts.label ?? `Azure Foundry (${slug3})`,
|
|
64661
64478
|
provider: "azure-foundry",
|
|
64662
64479
|
exec: "in-loop",
|
|
64663
64480
|
auth: { kind: "openai-compat", ref },
|
|
64664
|
-
baseUrl:
|
|
64481
|
+
baseUrl: azureFoundryBaseUrl(endpoint),
|
|
64665
64482
|
enabled: true,
|
|
64666
64483
|
addedAt: Date.now()
|
|
64667
64484
|
};
|
|
64668
64485
|
putAccount(account);
|
|
64669
64486
|
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
64670
64487
|
}
|
|
64671
|
-
async function
|
|
64672
|
-
const resourceName =
|
|
64488
|
+
async function addAzureAccount(resourceOrEndpoint, key, opts = {}) {
|
|
64489
|
+
const resourceName = azureResourceName(resourceOrEndpoint);
|
|
64673
64490
|
if (!resourceName || !key.trim())
|
|
64674
64491
|
return { ok: false, message: "usage: /account add azure <resource-or-endpoint> <api-key> [api-version]" };
|
|
64675
|
-
const id = opts.id ?? `azure-${resourceName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") ||
|
|
64492
|
+
const id = opts.id ?? `azure-${resourceName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || shortId()}`;
|
|
64676
64493
|
const ref = `${id}:api-key`;
|
|
64677
64494
|
await setSecret(ref, key.trim());
|
|
64678
64495
|
const account = {
|
|
@@ -64687,24 +64504,24 @@ async function addAzureAccount2(resourceOrEndpoint, key, opts = {}) {
|
|
|
64687
64504
|
putAccount(account);
|
|
64688
64505
|
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
64689
64506
|
}
|
|
64690
|
-
function
|
|
64691
|
-
const
|
|
64692
|
-
return
|
|
64507
|
+
function cliProfileDir(id) {
|
|
64508
|
+
const home5 = process.env.GEARBOX_HOME || join10(homedir8(), ".gearbox");
|
|
64509
|
+
return join10(home5, "cli", id);
|
|
64693
64510
|
}
|
|
64694
|
-
function
|
|
64511
|
+
function addCliAccount(provider, name31) {
|
|
64695
64512
|
const cat = catalogProvider(provider);
|
|
64696
64513
|
if (!cat || cat.group !== "cli" || !cat.binary)
|
|
64697
64514
|
return { ok: false, message: `"${provider}" is not a CLI subscription provider` };
|
|
64698
64515
|
if (!which(cat.binary))
|
|
64699
64516
|
return { ok: false, message: `the ${cat.binary} binary isn't on your PATH — install it first` };
|
|
64700
|
-
const
|
|
64701
|
-
const id =
|
|
64702
|
-
const profile =
|
|
64517
|
+
const slug3 = name31 ? name31.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") : "";
|
|
64518
|
+
const id = slug3 ? `${provider}-${slug3}` : provider;
|
|
64519
|
+
const profile = slug3 ? cliProfileDir(id) : undefined;
|
|
64703
64520
|
if (profile)
|
|
64704
|
-
|
|
64521
|
+
mkdirSync7(profile, { recursive: true });
|
|
64705
64522
|
const account = {
|
|
64706
64523
|
id,
|
|
64707
|
-
label:
|
|
64524
|
+
label: slug3 ? `${cat.label.replace(/ \(.*\)$/, "")} (${name31.trim()})` : cat.label,
|
|
64708
64525
|
provider,
|
|
64709
64526
|
exec: "cli",
|
|
64710
64527
|
auth: { kind: "cli", binary: cat.binary, loginProfile: profile },
|
|
@@ -64715,7 +64532,7 @@ function addCliAccount2(provider, name31) {
|
|
|
64715
64532
|
putAccount(account);
|
|
64716
64533
|
return { ok: true, account, message: `${account.label} ready — runs via the ${cat.binary} CLI${profile ? " (separate login)" : ""}` };
|
|
64717
64534
|
}
|
|
64718
|
-
async function
|
|
64535
|
+
async function cliAuthStatus(binary, profile) {
|
|
64719
64536
|
const env3 = subscriptionEnv(binary, profile);
|
|
64720
64537
|
const readBoth = async (cmd, timeoutMs = 5000) => {
|
|
64721
64538
|
const p = spawnProc(cmd, { stdin: "ignore", stdout: "pipe", stderr: "pipe", env: env3 });
|
|
@@ -64768,16 +64585,16 @@ ${e2}`.trim(), timedOut };
|
|
|
64768
64585
|
return { loggedIn: false };
|
|
64769
64586
|
}
|
|
64770
64587
|
}
|
|
64771
|
-
function
|
|
64588
|
+
function cliLoginArgs(binary) {
|
|
64772
64589
|
return binary === "codex" ? ["login"] : ["auth", "login"];
|
|
64773
64590
|
}
|
|
64774
|
-
async function
|
|
64591
|
+
async function addByPastedKey(key) {
|
|
64775
64592
|
const provider = detectProviderByKey(key);
|
|
64776
64593
|
if (!provider)
|
|
64777
64594
|
return { ok: false, message: "couldn't identify the provider from that key — use /accounts add <provider> <key>" };
|
|
64778
|
-
return
|
|
64595
|
+
return addApiKeyAccount(provider, key);
|
|
64779
64596
|
}
|
|
64780
|
-
async function
|
|
64597
|
+
async function testAccount(a) {
|
|
64781
64598
|
const creds = await resolveCreds(a);
|
|
64782
64599
|
if (!creds.apiKey && a.auth.kind !== "cli")
|
|
64783
64600
|
return { ok: false, message: "no key stored" };
|
|
@@ -64788,17 +64605,17 @@ async function testAccount2(a) {
|
|
|
64788
64605
|
headers: { "x-api-key": creds.apiKey ?? "", "anthropic-version": "2023-06-01", "content-type": "application/json" },
|
|
64789
64606
|
body: JSON.stringify({ model: "claude-haiku-4-5", messages: [{ role: "user", content: "hi" }] })
|
|
64790
64607
|
});
|
|
64791
|
-
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await
|
|
64608
|
+
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
64792
64609
|
}
|
|
64793
64610
|
if (a.provider === "google") {
|
|
64794
64611
|
const r3 = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${creds.apiKey ?? ""}`);
|
|
64795
|
-
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await
|
|
64612
|
+
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
64796
64613
|
}
|
|
64797
64614
|
const base2 = creds.baseURL ?? "https://api.openai.com/v1";
|
|
64798
64615
|
const r2 = await fetch(`${base2.replace(/\/$/, "")}/models`, {
|
|
64799
64616
|
headers: { Authorization: `Bearer ${creds.apiKey ?? ""}`, ...creds.headers ?? {} }
|
|
64800
64617
|
});
|
|
64801
|
-
return r2.ok ? { ok: true, message: "credential works" } : { ok: false, message: await
|
|
64618
|
+
return r2.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r2) };
|
|
64802
64619
|
} catch (e2) {
|
|
64803
64620
|
return { ok: false, message: e2?.message ?? "request failed" };
|
|
64804
64621
|
}
|
|
@@ -64806,7 +64623,7 @@ async function testAccount2(a) {
|
|
|
64806
64623
|
function addableProviders() {
|
|
64807
64624
|
return CATALOG.filter((p) => p.authKind === "api-key" || p.authKind === "openai-compat").map((p) => ({ id: p.id, label: p.label, group: p.group }));
|
|
64808
64625
|
}
|
|
64809
|
-
async function
|
|
64626
|
+
async function errMessage(r2) {
|
|
64810
64627
|
try {
|
|
64811
64628
|
const j = await r2.json();
|
|
64812
64629
|
const m2 = j?.error?.message ?? j?.message ?? j?.error;
|
|
@@ -64815,7 +64632,7 @@ async function errMessage2(r2) {
|
|
|
64815
64632
|
} catch {}
|
|
64816
64633
|
return `HTTP ${r2.status}`;
|
|
64817
64634
|
}
|
|
64818
|
-
function
|
|
64635
|
+
function shortId() {
|
|
64819
64636
|
return Date.now().toString(36).slice(-4) + Math.floor(Math.random() * 1296).toString(36).padStart(2, "0");
|
|
64820
64637
|
}
|
|
64821
64638
|
var init_onboard = __esm(() => {
|
|
@@ -64826,62 +64643,6 @@ var init_onboard = __esm(() => {
|
|
|
64826
64643
|
init_proc();
|
|
64827
64644
|
});
|
|
64828
64645
|
|
|
64829
|
-
// src/accounts/catalog.ts
|
|
64830
|
-
var exports_catalog = {};
|
|
64831
|
-
__export(exports_catalog, {
|
|
64832
|
-
detectProviderByKey: () => detectProviderByKey2,
|
|
64833
|
-
catalogProvider: () => catalogProvider2,
|
|
64834
|
-
CATALOG: () => CATALOG2
|
|
64835
|
-
});
|
|
64836
|
-
function catalogProvider2(id) {
|
|
64837
|
-
return BY_ID3.get(id);
|
|
64838
|
-
}
|
|
64839
|
-
function detectProviderByKey2(key) {
|
|
64840
|
-
const k = key.trim();
|
|
64841
|
-
const ranked = CATALOG2.flatMap((p) => (p.keyPrefix ?? []).map((pre) => ({ id: p.id, pre }))).sort((a, b) => b.pre.length - a.pre.length);
|
|
64842
|
-
return ranked.find(({ pre }) => k.startsWith(pre))?.id;
|
|
64843
|
-
}
|
|
64844
|
-
var CATALOG2, BY_ID3;
|
|
64845
|
-
var init_catalog2 = __esm(() => {
|
|
64846
|
-
CATALOG2 = [
|
|
64847
|
-
{ id: "anthropic", label: "Anthropic", group: "native", exec: "in-loop", authKind: "api-key", envVars: ["ANTHROPIC_API_KEY"], keyPrefix: ["sk-ant-"], signupUrl: "https://console.anthropic.com/settings/keys", defaultModels: ["claude-sonnet-4-6", "claude-haiku-4-5", "claude-opus-4-8"] },
|
|
64848
|
-
{ id: "openai", label: "OpenAI", group: "native", exec: "in-loop", authKind: "api-key", envVars: ["OPENAI_API_KEY"], keyPrefix: ["sk-proj-", "sk-"], signupUrl: "https://platform.openai.com/api-keys", defaultModels: ["gpt-5.5", "gpt-5.5-pro", "gpt-5.5-mini"] },
|
|
64849
|
-
{ id: "google", label: "Google Gemini", group: "native", exec: "in-loop", authKind: "api-key", envVars: ["GOOGLE_GENERATIVE_AI_API_KEY", "GEMINI_API_KEY"], keyPrefix: ["AIza"], signupUrl: "https://aistudio.google.com/apikey", defaultModels: ["gemini-3.5-flash", "gemini-3.1-pro-preview", "gemini-3.1-flash-lite"] },
|
|
64850
|
-
{ id: "deepseek", label: "DeepSeek", group: "native", exec: "in-loop", authKind: "api-key", envVars: ["DEEPSEEK_API_KEY"], baseUrl: "https://api.deepseek.com/v1", signupUrl: "https://platform.deepseek.com/api_keys", defaultModels: ["deepseek-v4-pro", "deepseek-v4-flash"] },
|
|
64851
|
-
{ id: "xai", label: "xAI (Grok)", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["XAI_API_KEY"], keyPrefix: ["xai-"], baseUrl: "https://api.x.ai/v1", signupUrl: "https://console.x.ai", defaultModels: ["grok-4.3", "grok-4.1-fast"] },
|
|
64852
|
-
{ id: "mistral", label: "Mistral", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["MISTRAL_API_KEY"], baseUrl: "https://api.mistral.ai/v1", signupUrl: "https://console.mistral.ai/api-keys", defaultModels: ["mistral-large-latest", "codestral-latest"] },
|
|
64853
|
-
{ id: "groq", label: "Groq", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["GROQ_API_KEY"], keyPrefix: ["gsk_"], baseUrl: "https://api.groq.com/openai/v1", signupUrl: "https://console.groq.com/keys", defaultModels: ["llama-3.3-70b-versatile", "moonshotai/kimi-k2-instruct"] },
|
|
64854
|
-
{ id: "together", label: "Together AI", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["TOGETHER_API_KEY"], baseUrl: "https://api.together.xyz/v1", signupUrl: "https://api.together.ai/settings/api-keys", defaultModels: ["deepseek-ai/DeepSeek-V3", "Qwen/Qwen2.5-Coder-32B-Instruct"] },
|
|
64855
|
-
{ id: "fireworks", label: "Fireworks", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["FIREWORKS_API_KEY"], keyPrefix: ["fw_"], baseUrl: "https://api.fireworks.ai/inference/v1", signupUrl: "https://fireworks.ai/account/api-keys", defaultModels: ["accounts/fireworks/models/deepseek-v3"] },
|
|
64856
|
-
{ id: "deepinfra", label: "DeepInfra", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["DEEPINFRA_API_KEY"], baseUrl: "https://api.deepinfra.com/v1/openai", signupUrl: "https://deepinfra.com/dash/api_keys" },
|
|
64857
|
-
{ id: "cerebras", label: "Cerebras", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["CEREBRAS_API_KEY"], keyPrefix: ["csk-"], baseUrl: "https://api.cerebras.ai/v1", signupUrl: "https://cloud.cerebras.ai", defaultModels: ["qwen-3-coder-480b", "llama-3.3-70b"] },
|
|
64858
|
-
{ id: "perplexity", label: "Perplexity", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["PERPLEXITY_API_KEY"], keyPrefix: ["pplx-"], baseUrl: "https://api.perplexity.ai", signupUrl: "https://www.perplexity.ai/settings/api", defaultModels: ["sonar-pro", "sonar-reasoning-pro"] },
|
|
64859
|
-
{ id: "baseten", label: "Baseten", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["BASETEN_API_KEY"], baseUrl: "https://inference.baseten.co/v1", signupUrl: "https://app.baseten.co/settings/api_keys" },
|
|
64860
|
-
{ id: "moonshot", label: "Moonshot (Kimi)", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["MOONSHOT_API_KEY"], baseUrl: "https://api.moonshot.ai/v1", signupUrl: "https://platform.moonshot.ai/console/api-keys", defaultModels: ["kimi-k2-0905-preview"] },
|
|
64861
|
-
{ id: "zai", label: "Z.ai (GLM)", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["ZAI_API_KEY", "ZHIPU_API_KEY"], baseUrl: "https://api.z.ai/api/paas/v4", signupUrl: "https://z.ai/manage-apikey/apikey-list", defaultModels: ["glm-4.6", "glm-4.5-air"] },
|
|
64862
|
-
{ id: "nebius", label: "Nebius AI Studio", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["NEBIUS_API_KEY"], baseUrl: "https://api.studio.nebius.com/v1", signupUrl: "https://studio.nebius.com" },
|
|
64863
|
-
{ id: "hyperbolic", label: "Hyperbolic", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["HYPERBOLIC_API_KEY"], baseUrl: "https://api.hyperbolic.xyz/v1", signupUrl: "https://app.hyperbolic.xyz/settings" },
|
|
64864
|
-
{ id: "sambanova", label: "SambaNova", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["SAMBANOVA_API_KEY"], baseUrl: "https://api.sambanova.ai/v1", signupUrl: "https://cloud.sambanova.ai/apis" },
|
|
64865
|
-
{ id: "novita", label: "Novita", group: "openai-compat", exec: "in-loop", authKind: "openai-compat", envVars: ["NOVITA_API_KEY"], baseUrl: "https://api.novita.ai/v3/openai", signupUrl: "https://novita.ai/settings/key-management" },
|
|
64866
|
-
{ id: "openrouter", label: "OpenRouter", group: "gateway", exec: "in-loop", authKind: "openai-compat", envVars: ["OPENROUTER_API_KEY"], keyPrefix: ["sk-or-"], baseUrl: "https://openrouter.ai/api/v1", signupUrl: "https://openrouter.ai/keys", notes: "Hundreds of models via one key. extraHeaders HTTP-Referer/X-Title recommended." },
|
|
64867
|
-
{ id: "vercel-gateway", label: "Vercel AI Gateway", group: "gateway", exec: "in-loop", authKind: "openai-compat", envVars: ["AI_GATEWAY_API_KEY"], baseUrl: "https://ai-gateway.vercel.sh/v1", signupUrl: "https://vercel.com/docs/ai-gateway", notes: "Spend + credit telemetry; feeds the future ACCOUNT pillar." },
|
|
64868
|
-
{ id: "requesty", label: "Requesty", group: "gateway", exec: "in-loop", authKind: "openai-compat", envVars: ["REQUESTY_API_KEY"], baseUrl: "https://router.requesty.ai/v1", signupUrl: "https://app.requesty.ai" },
|
|
64869
|
-
{ id: "portkey", label: "Portkey", group: "gateway", exec: "in-loop", authKind: "openai-compat", envVars: ["PORTKEY_API_KEY"], baseUrl: "https://api.portkey.ai/v1", signupUrl: "https://app.portkey.ai", notes: "Config-driven routing via x-portkey-* headers." },
|
|
64870
|
-
{ id: "litellm", label: "LiteLLM proxy", group: "gateway", exec: "in-loop", authKind: "openai-compat", envVars: ["LITELLM_API_KEY"], signupUrl: "https://docs.litellm.ai/docs/simple_proxy", notes: "Self-hosted; set baseUrl to your proxy." },
|
|
64871
|
-
{ id: "azure-foundry", label: "Azure AI Foundry", group: "gateway", exec: "in-loop", authKind: "openai-compat", envVars: ["AZURE_AI_FOUNDRY_API_KEY", "AZURE_AI_INFERENCE_API_KEY"], signupUrl: "https://ai.azure.com", defaultModels: ["gpt-5.5", "gpt-5.5-mini", "gpt-4.1", "o4-mini"], notes: "OpenAI-compatible Foundry endpoint. Use baseUrl ending in /openai/v1." },
|
|
64872
|
-
{ id: "bedrock", label: "Amazon Bedrock", group: "cloud", exec: "in-loop", authKind: "aws", envVars: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION", "AWS_PROFILE"], keyPrefix: ["AKIA", "ASIA"], signupUrl: "https://console.aws.amazon.com/bedrock", defaultModels: ["anthropic.claude-sonnet-4-20250514-v1:0"], notes: "Needs @ai-sdk/amazon-bedrock (P2)." },
|
|
64873
|
-
{ id: "vertex", label: "Google Vertex AI", group: "cloud", exec: "in-loop", authKind: "vertex", envVars: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_APPLICATION_CREDENTIALS"], signupUrl: "https://console.cloud.google.com/vertex-ai", defaultModels: ["gemini-3.1-pro-preview"], notes: "ADC or a service-account JSON." },
|
|
64874
|
-
{ id: "azure", label: "Azure OpenAI", group: "cloud", exec: "in-loop", authKind: "azure", envVars: ["AZURE_API_KEY", "AZURE_RESOURCE_NAME"], signupUrl: "https://oai.azure.com", notes: "Needs @ai-sdk/azure (P2); resourceName + deployment." },
|
|
64875
|
-
{ id: "ollama", label: "Ollama (local)", group: "local", exec: "in-loop", authKind: "openai-compat", envVars: [], baseUrl: "http://localhost:11434/v1", signupUrl: "https://ollama.com", defaultModels: ["qwen2.5-coder:7b", "llama3.3"], notes: "No key; runs on your machine." },
|
|
64876
|
-
{ id: "lmstudio", label: "LM Studio (local)", group: "local", exec: "in-loop", authKind: "openai-compat", envVars: [], baseUrl: "http://localhost:1234/v1", signupUrl: "https://lmstudio.ai" },
|
|
64877
|
-
{ id: "vllm", label: "vLLM (local/self-host)", group: "local", exec: "in-loop", authKind: "openai-compat", envVars: [], baseUrl: "http://localhost:8000/v1", signupUrl: "https://docs.vllm.ai" },
|
|
64878
|
-
{ id: "llamacpp", label: "llama.cpp (local)", group: "local", exec: "in-loop", authKind: "openai-compat", envVars: [], baseUrl: "http://localhost:8080/v1", signupUrl: "https://github.com/ggml-org/llama.cpp" },
|
|
64879
|
-
{ id: "claude-cli", label: "Claude (Pro/Max via claude CLI)", group: "cli", exec: "cli", authKind: "cli", envVars: [], binary: "claude", signupUrl: "https://claude.com/product/claude-code", defaultModels: ["claude-opus-4-8", "claude-sonnet-4-6"], notes: "Wraps the official binary (like Conductor). Runs its own tools/permissions. ToS-clean: no token is read." },
|
|
64880
|
-
{ id: "codex-cli", label: "ChatGPT (Plus/Pro via codex CLI)", group: "cli", exec: "cli", authKind: "cli", envVars: [], binary: "codex", signupUrl: "https://developers.openai.com/codex/cli", defaultModels: ["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"], notes: "Wraps the official binary. Runs its own tools/permissions. ToS-clean." }
|
|
64881
|
-
];
|
|
64882
|
-
BY_ID3 = new Map(CATALOG2.map((p) => [p.id, p]));
|
|
64883
|
-
});
|
|
64884
|
-
|
|
64885
64646
|
// node_modules/ink/build/render.js
|
|
64886
64647
|
import { Stream } from "node:stream";
|
|
64887
64648
|
import process12 from "node:process";
|
|
@@ -70406,12 +70167,13 @@ var import_react20 = __toESM(require_react(), 1);
|
|
|
70406
70167
|
// node_modules/ink/build/hooks/use-focus-manager.js
|
|
70407
70168
|
var import_react21 = __toESM(require_react(), 1);
|
|
70408
70169
|
// src/cli.tsx
|
|
70409
|
-
import { execFileSync as execFileSync4 } from "child_process";
|
|
70410
|
-
import { resolve as resolve11 } from "path";
|
|
70411
|
-
import { existsSync as
|
|
70170
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
70171
|
+
import { resolve as resolve11 } from "node:path";
|
|
70172
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
70412
70173
|
|
|
70413
70174
|
// src/ui/App.tsx
|
|
70414
70175
|
var import_react26 = __toESM(require_react(), 1);
|
|
70176
|
+
|
|
70415
70177
|
// src/ui/theme.ts
|
|
70416
70178
|
var color = {
|
|
70417
70179
|
accent: "#7DD3FC",
|
|
@@ -119403,6 +119165,9 @@ function detectImageMode() {
|
|
|
119403
119165
|
return "blocks";
|
|
119404
119166
|
}
|
|
119405
119167
|
var resolved = null;
|
|
119168
|
+
function setImageMode(m2) {
|
|
119169
|
+
resolved = m2;
|
|
119170
|
+
}
|
|
119406
119171
|
function getImageMode() {
|
|
119407
119172
|
return resolved ?? detectImageMode();
|
|
119408
119173
|
}
|
|
@@ -119413,6 +119178,30 @@ function idColor(id) {
|
|
|
119413
119178
|
const bytes = [id >> 16 & 255, id >> 8 & 255, id & 255];
|
|
119414
119179
|
return "#" + bytes.map((x2) => x2.toString(16).padStart(2, "0")).join("");
|
|
119415
119180
|
}
|
|
119181
|
+
function transmitOne(id, b64, cols, rows) {
|
|
119182
|
+
const ESC2 = "\x1B";
|
|
119183
|
+
const CHUNK = 4096;
|
|
119184
|
+
if (b64.length <= CHUNK) {
|
|
119185
|
+
return `${ESC2}_Ga=T,U=1,i=${id},c=${cols},r=${rows},f=100,q=2;${b64}${ESC2}\\`;
|
|
119186
|
+
}
|
|
119187
|
+
let out = "";
|
|
119188
|
+
for (let i2 = 0;i2 < b64.length; i2 += CHUNK) {
|
|
119189
|
+
const chunk2 = b64.slice(i2, i2 + CHUNK);
|
|
119190
|
+
const more = i2 + CHUNK < b64.length ? 1 : 0;
|
|
119191
|
+
out += i2 === 0 ? `${ESC2}_Ga=T,U=1,i=${id},c=${cols},r=${rows},f=100,q=2,m=${more};${chunk2}${ESC2}\\` : `${ESC2}_Gm=${more};${chunk2}${ESC2}\\`;
|
|
119192
|
+
}
|
|
119193
|
+
return out;
|
|
119194
|
+
}
|
|
119195
|
+
function transmitAll() {
|
|
119196
|
+
let out = "";
|
|
119197
|
+
for (const variant of VARIANTS) {
|
|
119198
|
+
for (const size2 of SIZES) {
|
|
119199
|
+
const data = GHOSTS[variant][size2];
|
|
119200
|
+
out += transmitOne(imageId(variant, size2), GHOST_PNG[variant], data[0]?.length ?? 0, data.length);
|
|
119201
|
+
}
|
|
119202
|
+
}
|
|
119203
|
+
return out;
|
|
119204
|
+
}
|
|
119416
119205
|
function placeholderRows(cols, rows) {
|
|
119417
119206
|
const lines = [];
|
|
119418
119207
|
for (let r2 = 0;r2 < rows; r2++) {
|
|
@@ -121297,6 +121086,9 @@ function listSessions() {
|
|
|
121297
121086
|
return [];
|
|
121298
121087
|
}
|
|
121299
121088
|
}
|
|
121089
|
+
function latestSession() {
|
|
121090
|
+
return listSessions()[0] ?? null;
|
|
121091
|
+
}
|
|
121300
121092
|
var histFile = () => join4(dir(), "history.json");
|
|
121301
121093
|
function loadHistory() {
|
|
121302
121094
|
try {
|
|
@@ -121395,6 +121187,9 @@ function pickDefaultModel(preferredId) {
|
|
|
121395
121187
|
return wanted;
|
|
121396
121188
|
return MODELS.find((m2) => providerAvailable(m2.provider));
|
|
121397
121189
|
}
|
|
121190
|
+
function anyProviderAvailable() {
|
|
121191
|
+
return MODELS.some((m2) => providerAvailable(m2.provider));
|
|
121192
|
+
}
|
|
121398
121193
|
|
|
121399
121194
|
// src/model/selector.ts
|
|
121400
121195
|
class FixedSelector {
|
|
@@ -133323,334 +133118,8 @@ function friendlyToolPhase(name31) {
|
|
|
133323
133118
|
// src/ui/App.tsx
|
|
133324
133119
|
init_resolve();
|
|
133325
133120
|
init_store();
|
|
133326
|
-
|
|
133327
|
-
|
|
133328
|
-
init_catalog();
|
|
133329
|
-
init_store();
|
|
133330
|
-
import { readFileSync as readFileSync11, existsSync as existsSync6 } from "node:fs";
|
|
133331
|
-
import { join as join9 } from "node:path";
|
|
133332
|
-
import { homedir as homedir7 } from "node:os";
|
|
133333
|
-
function detectEnvCreds() {
|
|
133334
|
-
const out = [];
|
|
133335
|
-
for (const p of CATALOG) {
|
|
133336
|
-
if (p.authKind !== "api-key" && p.authKind !== "openai-compat")
|
|
133337
|
-
continue;
|
|
133338
|
-
for (const ev of p.envVars) {
|
|
133339
|
-
const v = process.env[ev];
|
|
133340
|
-
if (v) {
|
|
133341
|
-
out.push({ provider: p.id, label: p.label, envVar: ev, value: v });
|
|
133342
|
-
break;
|
|
133343
|
-
}
|
|
133344
|
-
}
|
|
133345
|
-
}
|
|
133346
|
-
return out;
|
|
133347
|
-
}
|
|
133348
|
-
async function importEnvCred(c) {
|
|
133349
|
-
const id = `${c.provider}-env`;
|
|
133350
|
-
const ref = `${id}:api-key`;
|
|
133351
|
-
await setSecret(ref, c.value);
|
|
133352
|
-
const cat = CATALOG.find((p) => p.id === c.provider);
|
|
133353
|
-
const account = {
|
|
133354
|
-
id,
|
|
133355
|
-
label: `${c.label} (from ${c.envVar})`,
|
|
133356
|
-
provider: c.provider,
|
|
133357
|
-
exec: "in-loop",
|
|
133358
|
-
auth: cat.authKind === "openai-compat" ? { kind: "openai-compat", ref } : { kind: "api-key", ref },
|
|
133359
|
-
baseUrl: cat.baseUrl,
|
|
133360
|
-
enabled: true,
|
|
133361
|
-
addedAt: Date.now()
|
|
133362
|
-
};
|
|
133363
|
-
putAccount(account);
|
|
133364
|
-
return account;
|
|
133365
|
-
}
|
|
133366
|
-
function importableEnvCreds() {
|
|
133367
|
-
return detectEnvCreds().filter((c) => !getAccount(`${c.provider}-env`));
|
|
133368
|
-
}
|
|
133369
|
-
function awsIni(file5, profile = "default") {
|
|
133370
|
-
if (!existsSync6(file5))
|
|
133371
|
-
return {};
|
|
133372
|
-
const out = {};
|
|
133373
|
-
let cur = "";
|
|
133374
|
-
for (const raw of readFileSync11(file5, "utf8").split(`
|
|
133375
|
-
`)) {
|
|
133376
|
-
const line = raw.trim();
|
|
133377
|
-
if (line.startsWith("["))
|
|
133378
|
-
cur = line.slice(1, -1).replace(/^profile\s+/, "");
|
|
133379
|
-
else if (cur === profile && line.includes("=")) {
|
|
133380
|
-
const i2 = line.indexOf("=");
|
|
133381
|
-
out[line.slice(0, i2).trim().toLowerCase()] = line.slice(i2 + 1).trim();
|
|
133382
|
-
}
|
|
133383
|
-
}
|
|
133384
|
-
return out;
|
|
133385
|
-
}
|
|
133386
|
-
function detectCloudCreds() {
|
|
133387
|
-
const out = [];
|
|
133388
|
-
const home5 = homedir7();
|
|
133389
|
-
const creds = awsIni(join9(home5, ".aws", "credentials"));
|
|
133390
|
-
const conf = awsIni(join9(home5, ".aws", "config"));
|
|
133391
|
-
const akid = process.env.AWS_ACCESS_KEY_ID ?? creds.aws_access_key_id;
|
|
133392
|
-
const secret = process.env.AWS_SECRET_ACCESS_KEY ?? creds.aws_secret_access_key;
|
|
133393
|
-
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? conf.region;
|
|
133394
|
-
if (akid && secret) {
|
|
133395
|
-
out.push({
|
|
133396
|
-
provider: "bedrock",
|
|
133397
|
-
label: "Amazon Bedrock",
|
|
133398
|
-
source: process.env.AWS_ACCESS_KEY_ID ? "env" : "~/.aws/credentials",
|
|
133399
|
-
aws: { accessKeyId: akid, secretAccessKey: secret, sessionToken: process.env.AWS_SESSION_TOKEN ?? creds.aws_session_token, region: region ?? "us-east-1" }
|
|
133400
|
-
});
|
|
133401
|
-
}
|
|
133402
|
-
if (process.env.AZURE_API_KEY && process.env.AZURE_RESOURCE_NAME) {
|
|
133403
|
-
out.push({ provider: "azure", label: "Azure OpenAI", source: "env", azure: { resourceName: process.env.AZURE_RESOURCE_NAME, apiKey: process.env.AZURE_API_KEY } });
|
|
133404
|
-
}
|
|
133405
|
-
if (process.env.GOOGLE_VERTEX_PROJECT) {
|
|
133406
|
-
out.push({ provider: "vertex", label: "Google Vertex AI", source: "env", vertex: { project: process.env.GOOGLE_VERTEX_PROJECT, location: process.env.GOOGLE_VERTEX_LOCATION ?? "us-central1" } });
|
|
133407
|
-
}
|
|
133408
|
-
return out;
|
|
133409
|
-
}
|
|
133410
|
-
async function importCloudCred(c) {
|
|
133411
|
-
const id = `${c.provider}-import`;
|
|
133412
|
-
let auth;
|
|
133413
|
-
if (c.aws) {
|
|
133414
|
-
await setSecret(`${id}:akid`, c.aws.accessKeyId);
|
|
133415
|
-
await setSecret(`${id}:secret`, c.aws.secretAccessKey);
|
|
133416
|
-
if (c.aws.sessionToken)
|
|
133417
|
-
await setSecret(`${id}:token`, c.aws.sessionToken);
|
|
133418
|
-
auth = { kind: "aws", accessKeyIdRef: `${id}:akid`, secretKeyRef: `${id}:secret`, sessionTokenRef: c.aws.sessionToken ? `${id}:token` : undefined, region: c.aws.region };
|
|
133419
|
-
} else if (c.azure) {
|
|
133420
|
-
await setSecret(`${id}:api-key`, c.azure.apiKey);
|
|
133421
|
-
auth = { kind: "azure", resourceName: c.azure.resourceName, ref: `${id}:api-key` };
|
|
133422
|
-
} else {
|
|
133423
|
-
auth = { kind: "vertex", project: c.vertex.project, location: c.vertex.location, adc: true };
|
|
133424
|
-
}
|
|
133425
|
-
const account = { id, label: `${c.label} (from ${c.source})`, provider: c.provider, exec: "in-loop", auth, enabled: true, addedAt: Date.now() };
|
|
133426
|
-
putAccount(account);
|
|
133427
|
-
return account;
|
|
133428
|
-
}
|
|
133429
|
-
function importableCloudCreds() {
|
|
133430
|
-
return detectCloudCreds().filter((c) => !getAccount(`${c.provider}-import`));
|
|
133431
|
-
}
|
|
133432
|
-
|
|
133433
|
-
// src/accounts/onboard.ts
|
|
133434
|
-
init_store();
|
|
133435
|
-
init_catalog();
|
|
133436
|
-
init_resolve();
|
|
133437
|
-
init_cli_backend();
|
|
133438
|
-
init_proc();
|
|
133439
|
-
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
133440
|
-
import { join as join10 } from "node:path";
|
|
133441
|
-
import { homedir as homedir8 } from "node:os";
|
|
133442
|
-
async function addApiKeyAccount(provider, key, opts = {}) {
|
|
133443
|
-
const cat = catalogProvider(provider);
|
|
133444
|
-
if (!cat)
|
|
133445
|
-
return { ok: false, message: `unknown provider "${provider}" — see /accounts catalog` };
|
|
133446
|
-
if (cat.group === "cli")
|
|
133447
|
-
return { ok: false, message: `${cat.label} is a subscription account — use /login ${provider} (P3), not a key` };
|
|
133448
|
-
if (cat.authKind !== "api-key" && cat.authKind !== "openai-compat") {
|
|
133449
|
-
return { ok: false, message: `${cat.label} needs ${cat.authKind} credentials — use the guided add (P2)` };
|
|
133450
|
-
}
|
|
133451
|
-
const id = opts.id ?? `${provider}-${shortId()}`;
|
|
133452
|
-
const ref = `${id}:api-key`;
|
|
133453
|
-
await setSecret(ref, key.trim());
|
|
133454
|
-
const account = {
|
|
133455
|
-
id,
|
|
133456
|
-
label: opts.label ?? cat.label,
|
|
133457
|
-
provider,
|
|
133458
|
-
exec: "in-loop",
|
|
133459
|
-
auth: cat.authKind === "openai-compat" ? { kind: "openai-compat", ref } : { kind: "api-key", ref },
|
|
133460
|
-
baseUrl: cat.baseUrl,
|
|
133461
|
-
enabled: true,
|
|
133462
|
-
addedAt: Date.now()
|
|
133463
|
-
};
|
|
133464
|
-
putAccount(account);
|
|
133465
|
-
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
133466
|
-
}
|
|
133467
|
-
function azureResourceName(input) {
|
|
133468
|
-
const s2 = input.trim();
|
|
133469
|
-
try {
|
|
133470
|
-
const host = new URL(s2).hostname;
|
|
133471
|
-
return host.split(".")[0] || s2;
|
|
133472
|
-
} catch {
|
|
133473
|
-
return s2;
|
|
133474
|
-
}
|
|
133475
|
-
}
|
|
133476
|
-
function azureFoundryBaseUrl(endpoint) {
|
|
133477
|
-
const trimmed = endpoint.trim().replace(/\/+$/, "");
|
|
133478
|
-
if (/\/openai\/v1$/i.test(trimmed))
|
|
133479
|
-
return trimmed;
|
|
133480
|
-
if (/\/openai$/i.test(trimmed))
|
|
133481
|
-
return `${trimmed}/v1`;
|
|
133482
|
-
return `${trimmed}/openai/v1`;
|
|
133483
|
-
}
|
|
133484
|
-
async function addAzureFoundryAccount(endpoint, key, opts = {}) {
|
|
133485
|
-
if (!/^https?:\/\//i.test(endpoint) || !key.trim())
|
|
133486
|
-
return { ok: false, message: "usage: /account add azure <foundry-endpoint> <api-key>" };
|
|
133487
|
-
const host = new URL(endpoint).hostname;
|
|
133488
|
-
const slug3 = host.split(".")[0]?.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || shortId();
|
|
133489
|
-
const id = opts.id ?? `azure-foundry-${slug3}`;
|
|
133490
|
-
const ref = `${id}:api-key`;
|
|
133491
|
-
await setSecret(ref, key.trim());
|
|
133492
|
-
const account = {
|
|
133493
|
-
id,
|
|
133494
|
-
label: opts.label ?? `Azure Foundry (${slug3})`,
|
|
133495
|
-
provider: "azure-foundry",
|
|
133496
|
-
exec: "in-loop",
|
|
133497
|
-
auth: { kind: "openai-compat", ref },
|
|
133498
|
-
baseUrl: azureFoundryBaseUrl(endpoint),
|
|
133499
|
-
enabled: true,
|
|
133500
|
-
addedAt: Date.now()
|
|
133501
|
-
};
|
|
133502
|
-
putAccount(account);
|
|
133503
|
-
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
133504
|
-
}
|
|
133505
|
-
async function addAzureAccount(resourceOrEndpoint, key, opts = {}) {
|
|
133506
|
-
const resourceName = azureResourceName(resourceOrEndpoint);
|
|
133507
|
-
if (!resourceName || !key.trim())
|
|
133508
|
-
return { ok: false, message: "usage: /account add azure <resource-or-endpoint> <api-key> [api-version]" };
|
|
133509
|
-
const id = opts.id ?? `azure-${resourceName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || shortId()}`;
|
|
133510
|
-
const ref = `${id}:api-key`;
|
|
133511
|
-
await setSecret(ref, key.trim());
|
|
133512
|
-
const account = {
|
|
133513
|
-
id,
|
|
133514
|
-
label: opts.label ?? `Azure (${resourceName})`,
|
|
133515
|
-
provider: "azure",
|
|
133516
|
-
exec: "in-loop",
|
|
133517
|
-
auth: { kind: "azure", resourceName, ref, apiVersion: opts.apiVersion },
|
|
133518
|
-
enabled: true,
|
|
133519
|
-
addedAt: Date.now()
|
|
133520
|
-
};
|
|
133521
|
-
putAccount(account);
|
|
133522
|
-
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
133523
|
-
}
|
|
133524
|
-
function cliProfileDir(id) {
|
|
133525
|
-
const home5 = process.env.GEARBOX_HOME || join10(homedir8(), ".gearbox");
|
|
133526
|
-
return join10(home5, "cli", id);
|
|
133527
|
-
}
|
|
133528
|
-
function addCliAccount(provider, name31) {
|
|
133529
|
-
const cat = catalogProvider(provider);
|
|
133530
|
-
if (!cat || cat.group !== "cli" || !cat.binary)
|
|
133531
|
-
return { ok: false, message: `"${provider}" is not a CLI subscription provider` };
|
|
133532
|
-
if (!which(cat.binary))
|
|
133533
|
-
return { ok: false, message: `the ${cat.binary} binary isn't on your PATH — install it first` };
|
|
133534
|
-
const slug3 = name31 ? name31.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") : "";
|
|
133535
|
-
const id = slug3 ? `${provider}-${slug3}` : provider;
|
|
133536
|
-
const profile = slug3 ? cliProfileDir(id) : undefined;
|
|
133537
|
-
if (profile)
|
|
133538
|
-
mkdirSync7(profile, { recursive: true });
|
|
133539
|
-
const account = {
|
|
133540
|
-
id,
|
|
133541
|
-
label: slug3 ? `${cat.label.replace(/ \(.*\)$/, "")} (${name31.trim()})` : cat.label,
|
|
133542
|
-
provider,
|
|
133543
|
-
exec: "cli",
|
|
133544
|
-
auth: { kind: "cli", binary: cat.binary, loginProfile: profile },
|
|
133545
|
-
models: cat.defaultModels,
|
|
133546
|
-
enabled: true,
|
|
133547
|
-
addedAt: Date.now()
|
|
133548
|
-
};
|
|
133549
|
-
putAccount(account);
|
|
133550
|
-
return { ok: true, account, message: `${account.label} ready — runs via the ${cat.binary} CLI${profile ? " (separate login)" : ""}` };
|
|
133551
|
-
}
|
|
133552
|
-
async function cliAuthStatus(binary, profile) {
|
|
133553
|
-
const env3 = subscriptionEnv(binary, profile);
|
|
133554
|
-
const readBoth = async (cmd, timeoutMs = 5000) => {
|
|
133555
|
-
const p = spawnProc(cmd, { stdin: "ignore", stdout: "pipe", stderr: "pipe", env: env3 });
|
|
133556
|
-
let timedOut = false;
|
|
133557
|
-
const timer = setTimeout(() => {
|
|
133558
|
-
timedOut = true;
|
|
133559
|
-
try {
|
|
133560
|
-
p.kill();
|
|
133561
|
-
} catch {}
|
|
133562
|
-
}, timeoutMs);
|
|
133563
|
-
try {
|
|
133564
|
-
const [o, e2] = await Promise.all([readStream(p.stdout), readStream(p.stderr)]);
|
|
133565
|
-
await p.exited.catch(() => {});
|
|
133566
|
-
return { out: `${o}
|
|
133567
|
-
${e2}`.trim(), timedOut };
|
|
133568
|
-
} finally {
|
|
133569
|
-
clearTimeout(timer);
|
|
133570
|
-
}
|
|
133571
|
-
};
|
|
133572
|
-
try {
|
|
133573
|
-
if (binary === "codex") {
|
|
133574
|
-
const { out: out2, timedOut: timedOut2 } = await readBoth(["codex", "login", "status"]);
|
|
133575
|
-
if (timedOut2)
|
|
133576
|
-
return { loggedIn: false, detail: "`codex login status` timed out" };
|
|
133577
|
-
const loggedIn = /logged in|signed in|account:|email|using chatgpt/i.test(out2) && !/not logged in|not signed in/i.test(out2);
|
|
133578
|
-
const email3 = out2.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i)?.[0]?.toLowerCase();
|
|
133579
|
-
const detail = loggedIn ? out2.split(`
|
|
133580
|
-
`).map((l) => l.trim()).find((l) => /@|plan|chatgpt/i.test(l))?.slice(0, 80) || "ChatGPT" : undefined;
|
|
133581
|
-
return { loggedIn, detail, identity: email3 ? `codex:${email3}` : undefined, identityLabel: email3 };
|
|
133582
|
-
}
|
|
133583
|
-
const { out, timedOut } = await readBoth(["claude", "auth", "status"]);
|
|
133584
|
-
if (timedOut)
|
|
133585
|
-
return { loggedIn: false, detail: "`claude auth status` timed out" };
|
|
133586
|
-
const m2 = out.match(/\{[^{}]*"loggedIn"[\s\S]*?\}/);
|
|
133587
|
-
try {
|
|
133588
|
-
const j = JSON.parse(m2 ? m2[0] : out);
|
|
133589
|
-
const parts = [];
|
|
133590
|
-
if (j.email)
|
|
133591
|
-
parts.push(j.email);
|
|
133592
|
-
if (j.subscriptionType)
|
|
133593
|
-
parts.push(`Claude ${String(j.subscriptionType).replace(/^\w/, (c) => c.toUpperCase())}`);
|
|
133594
|
-
else if (j.authMethod && j.authMethod !== "claude.ai")
|
|
133595
|
-
parts.push(`auth: ${j.authMethod}`);
|
|
133596
|
-
const email3 = typeof j.email === "string" ? j.email.toLowerCase() : undefined;
|
|
133597
|
-
return { loggedIn: !!j.loggedIn, detail: parts.join(" · ") || undefined, identity: email3 ? `claude:${email3}` : undefined, identityLabel: email3 };
|
|
133598
|
-
} catch {
|
|
133599
|
-
return { loggedIn: /"loggedIn"\s*:\s*true/.test(out) };
|
|
133600
|
-
}
|
|
133601
|
-
} catch {
|
|
133602
|
-
return { loggedIn: false };
|
|
133603
|
-
}
|
|
133604
|
-
}
|
|
133605
|
-
function cliLoginArgs(binary) {
|
|
133606
|
-
return binary === "codex" ? ["login"] : ["auth", "login"];
|
|
133607
|
-
}
|
|
133608
|
-
async function addByPastedKey(key) {
|
|
133609
|
-
const provider = detectProviderByKey(key);
|
|
133610
|
-
if (!provider)
|
|
133611
|
-
return { ok: false, message: "couldn't identify the provider from that key — use /accounts add <provider> <key>" };
|
|
133612
|
-
return addApiKeyAccount(provider, key);
|
|
133613
|
-
}
|
|
133614
|
-
async function testAccount(a) {
|
|
133615
|
-
const creds = await resolveCreds(a);
|
|
133616
|
-
if (!creds.apiKey && a.auth.kind !== "cli")
|
|
133617
|
-
return { ok: false, message: "no key stored" };
|
|
133618
|
-
try {
|
|
133619
|
-
if (a.provider === "anthropic") {
|
|
133620
|
-
const r3 = await fetch("https://api.anthropic.com/v1/messages/count_tokens", {
|
|
133621
|
-
method: "POST",
|
|
133622
|
-
headers: { "x-api-key": creds.apiKey ?? "", "anthropic-version": "2023-06-01", "content-type": "application/json" },
|
|
133623
|
-
body: JSON.stringify({ model: "claude-haiku-4-5", messages: [{ role: "user", content: "hi" }] })
|
|
133624
|
-
});
|
|
133625
|
-
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
133626
|
-
}
|
|
133627
|
-
if (a.provider === "google") {
|
|
133628
|
-
const r3 = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${creds.apiKey ?? ""}`);
|
|
133629
|
-
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
133630
|
-
}
|
|
133631
|
-
const base2 = creds.baseURL ?? "https://api.openai.com/v1";
|
|
133632
|
-
const r2 = await fetch(`${base2.replace(/\/$/, "")}/models`, {
|
|
133633
|
-
headers: { Authorization: `Bearer ${creds.apiKey ?? ""}`, ...creds.headers ?? {} }
|
|
133634
|
-
});
|
|
133635
|
-
return r2.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r2) };
|
|
133636
|
-
} catch (e2) {
|
|
133637
|
-
return { ok: false, message: e2?.message ?? "request failed" };
|
|
133638
|
-
}
|
|
133639
|
-
}
|
|
133640
|
-
async function errMessage(r2) {
|
|
133641
|
-
try {
|
|
133642
|
-
const j = await r2.json();
|
|
133643
|
-
const m2 = j?.error?.message ?? j?.message ?? j?.error;
|
|
133644
|
-
if (typeof m2 === "string" && m2)
|
|
133645
|
-
return `${m2} (HTTP ${r2.status})`;
|
|
133646
|
-
} catch {}
|
|
133647
|
-
return `HTTP ${r2.status}`;
|
|
133648
|
-
}
|
|
133649
|
-
function shortId() {
|
|
133650
|
-
return Date.now().toString(36).slice(-4) + Math.floor(Math.random() * 1296).toString(36).padStart(2, "0");
|
|
133651
|
-
}
|
|
133652
|
-
|
|
133653
|
-
// src/ui/App.tsx
|
|
133121
|
+
init_detect();
|
|
133122
|
+
init_onboard();
|
|
133654
133123
|
init_catalog();
|
|
133655
133124
|
init_cli_backend();
|
|
133656
133125
|
|
|
@@ -136484,304 +135953,33 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
136484
135953
|
}, undefined, true, undefined, this);
|
|
136485
135954
|
}
|
|
136486
135955
|
|
|
136487
|
-
// src/model/selector.ts
|
|
136488
|
-
class FixedSelector2 {
|
|
136489
|
-
preferredId;
|
|
136490
|
-
constructor(preferredId) {
|
|
136491
|
-
this.preferredId = preferredId;
|
|
136492
|
-
}
|
|
136493
|
-
select(_task) {
|
|
136494
|
-
const model = pickDefaultModel(this.preferredId);
|
|
136495
|
-
if (!model) {
|
|
136496
|
-
throw new Error("No model available. Set a key: ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_GENERATIVE_AI_API_KEY / DEEPSEEK_API_KEY");
|
|
136497
|
-
}
|
|
136498
|
-
return { model, reason: "fixed default · routing not enabled yet" };
|
|
136499
|
-
}
|
|
136500
|
-
}
|
|
136501
|
-
|
|
136502
|
-
// src/model/router.ts
|
|
136503
|
-
var BAR2 = {
|
|
136504
|
-
summarize: 0,
|
|
136505
|
-
classify: 0,
|
|
136506
|
-
search: 0.2,
|
|
136507
|
-
chat: 0.3,
|
|
136508
|
-
plan: 0.7,
|
|
136509
|
-
code: 0.7
|
|
136510
|
-
};
|
|
136511
|
-
var MUTATION2 = /\b(fix|implement|refactor|edit|modif|debug|rewrite|replace|add|create|delete|remove|patch|migrat|rename)\b/;
|
|
136512
|
-
function classify2(prompt) {
|
|
136513
|
-
const p = prompt.toLowerCase().trim();
|
|
136514
|
-
if (!p)
|
|
136515
|
-
return "code";
|
|
136516
|
-
if (MUTATION2.test(p))
|
|
136517
|
-
return "code";
|
|
136518
|
-
if (/\b(summari[sz]e|tl;?dr|recap|condense|digest|gist)\b/.test(p))
|
|
136519
|
-
return "summarize";
|
|
136520
|
-
if (/\bclassif|\bcategori[sz]|\blabel this\b|\bsentiment\b/.test(p))
|
|
136521
|
-
return "classify";
|
|
136522
|
-
if (/^(find|search|locate|grep)\b|\bwhere is\b|\bwhich file\b/.test(p))
|
|
136523
|
-
return "search";
|
|
136524
|
-
return "code";
|
|
136525
|
-
}
|
|
136526
|
-
function qualityOf2(m2) {
|
|
136527
|
-
const pr = profileFor(m2.id);
|
|
136528
|
-
if (!pr)
|
|
136529
|
-
return 0.5;
|
|
136530
|
-
if (pr.quality.sweBenchVerified != null)
|
|
136531
|
-
return pr.quality.sweBenchVerified;
|
|
136532
|
-
if (pr.quality.intelligenceIndex != null)
|
|
136533
|
-
return pr.quality.intelligenceIndex / 100;
|
|
136534
|
-
return 0.5;
|
|
136535
|
-
}
|
|
136536
|
-
function costOf2(m2) {
|
|
136537
|
-
const pr = profileFor(m2.id);
|
|
136538
|
-
if (!pr)
|
|
136539
|
-
return Number.POSITIVE_INFINITY;
|
|
136540
|
-
return pr.cost.inUSDPerMtok + 0.2 * pr.cost.outUSDPerMtok;
|
|
136541
|
-
}
|
|
136542
|
-
function tpsOf2(m2) {
|
|
136543
|
-
return profileFor(m2.id)?.latency?.tps ?? 0;
|
|
136544
|
-
}
|
|
136545
|
-
|
|
136546
|
-
class RoutingSelector2 {
|
|
136547
|
-
fallbackId;
|
|
136548
|
-
constructor(fallbackId) {
|
|
136549
|
-
this.fallbackId = fallbackId;
|
|
136550
|
-
}
|
|
136551
|
-
select(task) {
|
|
136552
|
-
const kind = task.kind ?? classify2(task.prompt);
|
|
136553
|
-
const bar = BAR2[kind];
|
|
136554
|
-
const available = MODELS.filter((m2) => providerAvailable(m2.provider) && profileFor(m2.id));
|
|
136555
|
-
if (available.length === 0) {
|
|
136556
|
-
const m2 = pickDefaultModel(this.fallbackId);
|
|
136557
|
-
if (!m2) {
|
|
136558
|
-
throw new Error("No model available. Set a key: ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_GENERATIVE_AI_API_KEY / DEEPSEEK_API_KEY");
|
|
136559
|
-
}
|
|
136560
|
-
return { model: m2, reason: "only model with a key" };
|
|
136561
|
-
}
|
|
136562
|
-
const need = (task.estTokens ?? 0) * 1.2;
|
|
136563
|
-
const fits = need > 0 ? available.filter((m2) => m2.contextWindow >= need) : available;
|
|
136564
|
-
const pool = fits.length ? fits : available;
|
|
136565
|
-
const clears = pool.filter((m2) => qualityOf2(m2) >= bar);
|
|
136566
|
-
const candidates = clears.length ? clears : pool;
|
|
136567
|
-
const pref = preferenceFor(kind);
|
|
136568
|
-
const preferredPool = pref?.modelId ? pool.find((m2) => m2.id === pref.modelId) : pref?.provider ? pool.find((m2) => m2.provider === pref.provider) : undefined;
|
|
136569
|
-
const preferred = pref?.modelId ? candidates.find((m2) => m2.id === pref.modelId) : pref?.provider ? candidates.find((m2) => m2.provider === pref.provider) : undefined;
|
|
136570
|
-
if (preferred && qualityOf2(preferred) >= bar) {
|
|
136571
|
-
return { model: preferred, reason: `${kind} · remembered preference` };
|
|
136572
|
-
}
|
|
136573
|
-
candidates.sort((a, b) => costOf2(a) - costOf2(b) || tpsOf2(b) - tpsOf2(a) || qualityOf2(b) - qualityOf2(a));
|
|
136574
|
-
const model = candidates[0];
|
|
136575
|
-
const skipped = preferredPool && qualityOf2(preferredPool) < bar ? ` · ${preferredPool.label} skipped below quality bar` : "";
|
|
136576
|
-
const reason = `${kind} · $${costOf2(model).toFixed(2)}/Mtok${skipped}`;
|
|
136577
|
-
return { model, reason };
|
|
136578
|
-
}
|
|
136579
|
-
}
|
|
136580
|
-
|
|
136581
|
-
// src/config.ts
|
|
136582
|
-
var config3 = {
|
|
136583
|
-
defaultModelId: process.env.GEARBOX_MODEL ?? "claude-sonnet-4-6",
|
|
136584
|
-
maxSteps: Number(process.env.GEARBOX_MAX_STEPS ?? 24)
|
|
136585
|
-
};
|
|
136586
|
-
function anyProviderAvailable() {
|
|
136587
|
-
return MODELS.some((m2) => providerAvailable(m2.provider));
|
|
136588
|
-
}
|
|
136589
|
-
|
|
136590
|
-
// src/providers.ts
|
|
136591
|
-
init_store();
|
|
136592
|
-
init_catalog();
|
|
136593
|
-
var NATIVE2 = new Set(["anthropic", "openai", "google", "deepseek"]);
|
|
136594
|
-
var CURATED2 = [
|
|
136595
|
-
{ id: "claude-opus-4-8", provider: "anthropic", sdkId: "claude-opus-4-8", label: "opus-4.8", contextWindow: 1e6, cost: { inUSDPerMtok: 5, outUSDPerMtok: 25 }, reasoning: true, efforts: ["low", "medium", "high", "xhigh", "max"] },
|
|
136596
|
-
{ id: "claude-sonnet-4-6", provider: "anthropic", sdkId: "claude-sonnet-4-6", label: "sonnet-4.6", contextWindow: 1e6, cost: { inUSDPerMtok: 3, outUSDPerMtok: 15 }, reasoning: true, efforts: ["low", "medium", "high", "xhigh", "max"] },
|
|
136597
|
-
{ id: "claude-haiku-4-5", provider: "anthropic", sdkId: "claude-haiku-4-5", label: "haiku-4.5", contextWindow: 200000, cost: { inUSDPerMtok: 1, outUSDPerMtok: 5 } },
|
|
136598
|
-
{ id: "gpt-5.5", provider: "openai", sdkId: "gpt-5.5", label: "gpt-5.5", contextWindow: 400000, cost: { inUSDPerMtok: 2.5, outUSDPerMtok: 10 }, reasoning: true, efforts: ["none", "minimal", "low", "medium", "high", "xhigh"] },
|
|
136599
|
-
{ id: "gpt-5.5-pro", provider: "openai", sdkId: "gpt-5.5-pro", label: "gpt-5.5-pro", contextWindow: 400000, cost: { inUSDPerMtok: 15, outUSDPerMtok: 120 }, reasoning: true, efforts: ["none", "minimal", "low", "medium", "high", "xhigh"] },
|
|
136600
|
-
{ id: "gemini-3.1-pro-preview", provider: "google", sdkId: "gemini-3.1-pro-preview", label: "gemini-3.1-pro", contextWindow: 1e6, cost: { inUSDPerMtok: 2, outUSDPerMtok: 12 }, reasoning: true, efforts: ["minimal", "low", "medium", "high"] },
|
|
136601
|
-
{ id: "gemini-3.5-flash", provider: "google", sdkId: "gemini-3.5-flash", label: "gemini-3.5-flash", contextWindow: 1e6, cost: { inUSDPerMtok: 0.3, outUSDPerMtok: 2.5 }, reasoning: true, efforts: ["minimal", "low", "medium", "high"] },
|
|
136602
|
-
{ id: "deepseek-v4-pro", provider: "deepseek", sdkId: "deepseek-v4-pro", label: "deepseek-v4-pro", contextWindow: 128000, cost: { inUSDPerMtok: 0.4, outUSDPerMtok: 1.75 }, reasoning: true },
|
|
136603
|
-
{ id: "deepseek-v4-flash", provider: "deepseek", sdkId: "deepseek-v4-flash", label: "deepseek-v4-flash", contextWindow: 128000, cost: { inUSDPerMtok: 0.27, outUSDPerMtok: 1.1 } }
|
|
136604
|
-
];
|
|
136605
|
-
function generatedModels2() {
|
|
136606
|
-
const out = [];
|
|
136607
|
-
for (const p of CATALOG) {
|
|
136608
|
-
if (p.group === "cli")
|
|
136609
|
-
continue;
|
|
136610
|
-
for (const m2 of p.defaultModels ?? []) {
|
|
136611
|
-
if (CURATED2.some((c) => c.provider === p.id && c.sdkId === m2))
|
|
136612
|
-
continue;
|
|
136613
|
-
out.push({ id: `${p.id}/${m2}`, provider: p.id, sdkId: m2, label: m2.length > 24 ? m2.slice(0, 24) : m2, contextWindow: 128000 });
|
|
136614
|
-
}
|
|
136615
|
-
}
|
|
136616
|
-
return out;
|
|
136617
|
-
}
|
|
136618
|
-
var MODELS2 = [...CURATED2, ...generatedModels2()];
|
|
136619
|
-
|
|
136620
|
-
// src/ui/image.ts
|
|
136621
|
-
var SIZES2 = ["big", "mini", "micro"];
|
|
136622
|
-
var VARIANTS2 = Object.keys(GHOST_PNG);
|
|
136623
|
-
var DIACRITICS2 = [
|
|
136624
|
-
773,
|
|
136625
|
-
781,
|
|
136626
|
-
782,
|
|
136627
|
-
784,
|
|
136628
|
-
786,
|
|
136629
|
-
829,
|
|
136630
|
-
830,
|
|
136631
|
-
831,
|
|
136632
|
-
838,
|
|
136633
|
-
842,
|
|
136634
|
-
843,
|
|
136635
|
-
844,
|
|
136636
|
-
848,
|
|
136637
|
-
849,
|
|
136638
|
-
850,
|
|
136639
|
-
855,
|
|
136640
|
-
859,
|
|
136641
|
-
867,
|
|
136642
|
-
868,
|
|
136643
|
-
869,
|
|
136644
|
-
870,
|
|
136645
|
-
871,
|
|
136646
|
-
872,
|
|
136647
|
-
873,
|
|
136648
|
-
874,
|
|
136649
|
-
875,
|
|
136650
|
-
876,
|
|
136651
|
-
877,
|
|
136652
|
-
878,
|
|
136653
|
-
879,
|
|
136654
|
-
1155,
|
|
136655
|
-
1156,
|
|
136656
|
-
1157,
|
|
136657
|
-
1158,
|
|
136658
|
-
1159,
|
|
136659
|
-
1426,
|
|
136660
|
-
1427,
|
|
136661
|
-
1428,
|
|
136662
|
-
1429,
|
|
136663
|
-
1431,
|
|
136664
|
-
1432,
|
|
136665
|
-
1433,
|
|
136666
|
-
1436,
|
|
136667
|
-
1437,
|
|
136668
|
-
1438,
|
|
136669
|
-
1439,
|
|
136670
|
-
1440,
|
|
136671
|
-
1441,
|
|
136672
|
-
1448,
|
|
136673
|
-
1449
|
|
136674
|
-
].map((c) => String.fromCodePoint(c));
|
|
136675
|
-
function detectImageMode2() {
|
|
136676
|
-
const force = process.env.GEARBOX_GHOST;
|
|
136677
|
-
if (force === "kitty" || force === "iterm")
|
|
136678
|
-
return force;
|
|
136679
|
-
return "blocks";
|
|
136680
|
-
}
|
|
136681
|
-
var resolved2 = null;
|
|
136682
|
-
function setImageMode(m2) {
|
|
136683
|
-
resolved2 = m2;
|
|
136684
|
-
}
|
|
136685
|
-
function imageId2(variant, size2) {
|
|
136686
|
-
return VARIANTS2.indexOf(variant) * SIZES2.length + SIZES2.indexOf(size2) + 1;
|
|
136687
|
-
}
|
|
136688
|
-
function transmitOne(id, b64, cols, rows) {
|
|
136689
|
-
const ESC2 = "\x1B";
|
|
136690
|
-
const CHUNK = 4096;
|
|
136691
|
-
if (b64.length <= CHUNK) {
|
|
136692
|
-
return `${ESC2}_Ga=T,U=1,i=${id},c=${cols},r=${rows},f=100,q=2;${b64}${ESC2}\\`;
|
|
136693
|
-
}
|
|
136694
|
-
let out = "";
|
|
136695
|
-
for (let i2 = 0;i2 < b64.length; i2 += CHUNK) {
|
|
136696
|
-
const chunk2 = b64.slice(i2, i2 + CHUNK);
|
|
136697
|
-
const more = i2 + CHUNK < b64.length ? 1 : 0;
|
|
136698
|
-
out += i2 === 0 ? `${ESC2}_Ga=T,U=1,i=${id},c=${cols},r=${rows},f=100,q=2,m=${more};${chunk2}${ESC2}\\` : `${ESC2}_Gm=${more};${chunk2}${ESC2}\\`;
|
|
136699
|
-
}
|
|
136700
|
-
return out;
|
|
136701
|
-
}
|
|
136702
|
-
function transmitAll() {
|
|
136703
|
-
let out = "";
|
|
136704
|
-
for (const variant of VARIANTS2) {
|
|
136705
|
-
for (const size2 of SIZES2) {
|
|
136706
|
-
const data = GHOSTS[variant][size2];
|
|
136707
|
-
out += transmitOne(imageId2(variant, size2), GHOST_PNG[variant], data[0]?.length ?? 0, data.length);
|
|
136708
|
-
}
|
|
136709
|
-
}
|
|
136710
|
-
return out;
|
|
136711
|
-
}
|
|
136712
|
-
|
|
136713
|
-
// src/ui/prefs.ts
|
|
136714
|
-
import { homedir as homedir9 } from "node:os";
|
|
136715
|
-
import { join as join11, dirname as dirname3 } from "node:path";
|
|
136716
|
-
import { readFileSync as readFileSync13, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8 } from "node:fs";
|
|
136717
|
-
function file5() {
|
|
136718
|
-
const dir2 = process.env.GEARBOX_HOME || join11(homedir9(), ".gearbox");
|
|
136719
|
-
return join11(dir2, "prefs.json");
|
|
136720
|
-
}
|
|
136721
|
-
function loadPrefs2() {
|
|
136722
|
-
try {
|
|
136723
|
-
return JSON.parse(readFileSync13(file5(), "utf8"));
|
|
136724
|
-
} catch {
|
|
136725
|
-
return {};
|
|
136726
|
-
}
|
|
136727
|
-
}
|
|
136728
|
-
|
|
136729
|
-
// src/permission.ts
|
|
136730
|
-
var granted2 = new Set;
|
|
136731
|
-
var yolo2 = false;
|
|
136732
|
-
function setYolo2(on) {
|
|
136733
|
-
yolo2 = on;
|
|
136734
|
-
}
|
|
136735
|
-
|
|
136736
|
-
// src/session.ts
|
|
136737
|
-
import { mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync8, readdirSync as readdirSync4 } from "node:fs";
|
|
136738
|
-
import { join as join12 } from "node:path";
|
|
136739
|
-
import { homedir as homedir10 } from "node:os";
|
|
136740
|
-
var root2 = () => join12(process.env.GEARBOX_HOME || join12(homedir10(), ".gearbox"), "sessions");
|
|
136741
|
-
var slug3 = () => process.cwd().replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "root";
|
|
136742
|
-
var dir2 = () => join12(root2(), slug3());
|
|
136743
|
-
function listSessions2() {
|
|
136744
|
-
try {
|
|
136745
|
-
return readdirSync4(dir2()).filter((f3) => f3.endsWith(".json") && f3 !== "history.json").map((f3) => {
|
|
136746
|
-
try {
|
|
136747
|
-
return JSON.parse(readFileSync14(join12(dir2(), f3), "utf8"));
|
|
136748
|
-
} catch {
|
|
136749
|
-
return null;
|
|
136750
|
-
}
|
|
136751
|
-
}).filter((s2) => s2 !== null && Array.isArray(s2.items)).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
136752
|
-
} catch {
|
|
136753
|
-
return [];
|
|
136754
|
-
}
|
|
136755
|
-
}
|
|
136756
|
-
function latestSession() {
|
|
136757
|
-
return listSessions2()[0] ?? null;
|
|
136758
|
-
}
|
|
136759
|
-
|
|
136760
135956
|
// src/cli.tsx
|
|
136761
|
-
var jsx_dev_runtime13 = __toESM(
|
|
135957
|
+
var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
|
|
135958
|
+
process.env.LANG = process.env.LANG || "en_US.UTF-8";
|
|
135959
|
+
process.env.LC_ALL = process.env.LC_ALL || "en_US.UTF-8";
|
|
136762
135960
|
var VERSION16 = "0.1.0";
|
|
136763
135961
|
var args = process.argv.slice(2);
|
|
136764
135962
|
if (args[0] === "upgrade" || args[0] === "update") {
|
|
136765
|
-
const
|
|
136766
|
-
if (!
|
|
135963
|
+
const root2 = resolve11(import.meta.dir, "..");
|
|
135964
|
+
if (!existsSync8(resolve11(root2, ".git"))) {
|
|
136767
135965
|
console.log("This build can't self-update (not a git checkout).");
|
|
136768
135966
|
console.log("Update by pulling the repo and reinstalling: git pull && bun install");
|
|
136769
135967
|
process.exit(0);
|
|
136770
135968
|
}
|
|
136771
135969
|
try {
|
|
136772
|
-
console.log("
|
|
136773
|
-
console.log(execFileSync4("git", ["-C",
|
|
136774
|
-
console.log("
|
|
136775
|
-
execFileSync4("bun", ["install"], { cwd:
|
|
136776
|
-
console.log("
|
|
135970
|
+
console.log("→ Pulling latest…");
|
|
135971
|
+
console.log(execFileSync4("git", ["-C", root2, "pull", "--ff-only"], { encoding: "utf8" }).trim());
|
|
135972
|
+
console.log("→ Installing dependencies…");
|
|
135973
|
+
execFileSync4("bun", ["install"], { cwd: root2, stdio: "inherit" });
|
|
135974
|
+
console.log("✓ Gearbox is up to date. Restart any running session to use the new version.");
|
|
136777
135975
|
} catch (e2) {
|
|
136778
135976
|
console.log("Upgrade failed: " + (e2?.message ?? String(e2)));
|
|
136779
|
-
console.log(`Try manually: cd ${
|
|
135977
|
+
console.log(`Try manually: cd ${root2} && git pull && bun install`);
|
|
136780
135978
|
}
|
|
136781
135979
|
process.exit(0);
|
|
136782
135980
|
}
|
|
136783
135981
|
if (args.includes("--help") || args.includes("-h")) {
|
|
136784
|
-
console.log(`gearbox ${VERSION16}
|
|
135982
|
+
console.log(`gearbox ${VERSION16} — multi-provider coding agent for the terminal
|
|
136785
135983
|
|
|
136786
135984
|
Usage:
|
|
136787
135985
|
gearbox start in the current directory (it becomes the workspace)
|
|
@@ -136799,9 +135997,9 @@ Options:
|
|
|
136799
135997
|
-h, --help this help
|
|
136800
135998
|
|
|
136801
135999
|
Set at least one provider key first (each user uses their own):
|
|
136802
|
-
ANTHROPIC_API_KEY
|
|
136000
|
+
ANTHROPIC_API_KEY · OPENAI_API_KEY · GOOGLE_GENERATIVE_AI_API_KEY · DEEPSEEK_API_KEY
|
|
136803
136001
|
|
|
136804
|
-
Models: ${
|
|
136002
|
+
Models: ${MODELS.map((m2) => m2.label).join(", ")}
|
|
136805
136003
|
In-app: / for commands, @ for files, !cmd for shell, shift+tab for plan mode.`);
|
|
136806
136004
|
process.exit(0);
|
|
136807
136005
|
}
|
|
@@ -136810,43 +136008,43 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
136810
136008
|
process.exit(0);
|
|
136811
136009
|
}
|
|
136812
136010
|
if (args[0] === "auth") {
|
|
136813
|
-
const { listAccounts:
|
|
136814
|
-
const { importableEnvCreds:
|
|
136815
|
-
const { addApiKeyAccount:
|
|
136816
|
-
const { detectProviderByKey:
|
|
136011
|
+
const { listAccounts: listAccounts2, loadAccounts: loadAccounts3, removeAccount: removeAccount2 } = await Promise.resolve().then(() => (init_store(), exports_store));
|
|
136012
|
+
const { importableEnvCreds: importableEnvCreds2, importEnvCred: importEnvCred2, importableCloudCreds: importableCloudCreds2, importCloudCred: importCloudCred2 } = await Promise.resolve().then(() => (init_detect(), exports_detect));
|
|
136013
|
+
const { addApiKeyAccount: addApiKeyAccount2, addByPastedKey: addByPastedKey2, testAccount: testAccount2, addableProviders: addableProviders2 } = await Promise.resolve().then(() => (init_onboard(), exports_onboard));
|
|
136014
|
+
const { detectProviderByKey: detectProviderByKey2 } = await Promise.resolve().then(() => (init_catalog(), exports_catalog));
|
|
136817
136015
|
const sub = args[1];
|
|
136818
136016
|
const rest2 = args.slice(2);
|
|
136819
136017
|
if (sub === "list" || !sub) {
|
|
136820
|
-
const f3 =
|
|
136018
|
+
const f3 = loadAccounts3();
|
|
136821
136019
|
if (!f3.accounts.length)
|
|
136822
136020
|
console.log("No accounts yet. Add one: gearbox auth add <key> (or) gearbox auth import");
|
|
136823
136021
|
for (const a of f3.accounts)
|
|
136824
|
-
console.log(`${f3.defaults[a.provider] === a.id ? "*" : " "} ${a.id.padEnd(22)} ${a.label}${a.exec === "cli" ? "
|
|
136825
|
-
const imp =
|
|
136022
|
+
console.log(`${f3.defaults[a.provider] === a.id ? "*" : " "} ${a.id.padEnd(22)} ${a.label}${a.exec === "cli" ? " · cli" : ""}`);
|
|
136023
|
+
const imp = importableEnvCreds2();
|
|
136826
136024
|
if (imp.length)
|
|
136827
136025
|
console.log(`
|
|
136828
136026
|
Importable from your env (gearbox auth import): ${imp.map((c) => c.envVar).join(", ")}`);
|
|
136829
136027
|
} else if (sub === "import") {
|
|
136830
|
-
const keys2 =
|
|
136831
|
-
const cloud =
|
|
136028
|
+
const keys2 = importableEnvCreds2();
|
|
136029
|
+
const cloud = importableCloudCreds2();
|
|
136832
136030
|
for (const c of keys2)
|
|
136833
|
-
await
|
|
136031
|
+
await importEnvCred2(c);
|
|
136834
136032
|
for (const c of cloud)
|
|
136835
|
-
await
|
|
136033
|
+
await importCloudCred2(c);
|
|
136836
136034
|
const names = [...keys2.map((c) => c.provider), ...cloud.map((c) => c.provider)];
|
|
136837
136035
|
console.log(names.length ? `Imported ${names.length}: ${names.join(", ")}` : "Nothing to import.");
|
|
136838
136036
|
} else if (sub === "add") {
|
|
136839
|
-
const res = rest2[0] && !rest2[1] &&
|
|
136037
|
+
const res = rest2[0] && !rest2[1] && detectProviderByKey2(rest2[0]) ? await addByPastedKey2(rest2[0]) : rest2[0] && rest2[1] ? await addApiKeyAccount2(rest2[0], rest2[1]) : { ok: false, message: "usage: gearbox auth add <key> | gearbox auth add <provider> <key>" };
|
|
136840
136038
|
console.log(res.message);
|
|
136841
136039
|
if (res.ok && res.account) {
|
|
136842
|
-
const t2 = await
|
|
136843
|
-
console.log(t2.ok ? " test:
|
|
136040
|
+
const t2 = await testAccount2(res.account);
|
|
136041
|
+
console.log(t2.ok ? " test: ✓ " + t2.message : " test: ✗ " + t2.message + " (stored anyway)");
|
|
136844
136042
|
}
|
|
136845
136043
|
} else if (sub === "test" && rest2[0]) {
|
|
136846
|
-
const a =
|
|
136847
|
-
console.log(a ? `${rest2[0]}: ${(await
|
|
136044
|
+
const a = listAccounts2().find((x2) => x2.id === rest2[0]);
|
|
136045
|
+
console.log(a ? `${rest2[0]}: ${(await testAccount2(a)).message}` : `no account ${rest2[0]}`);
|
|
136848
136046
|
} else if (sub === "rm" && rest2[0]) {
|
|
136849
|
-
await
|
|
136047
|
+
await removeAccount2(rest2[0]);
|
|
136850
136048
|
console.log(`removed ${rest2[0]}`);
|
|
136851
136049
|
} else if (sub === "providers") {
|
|
136852
136050
|
for (const p of addableProviders2())
|
|
@@ -136859,16 +136057,16 @@ Importable from your env (gearbox auth import): ${imp.map((c) => c.envVar).join(
|
|
|
136859
136057
|
var mi = args.indexOf("--model");
|
|
136860
136058
|
var preferred = mi >= 0 ? args[mi + 1] : undefined;
|
|
136861
136059
|
var demo = !anyProviderAvailable();
|
|
136862
|
-
var pinned = preferred ??
|
|
136863
|
-
var selector = pinned ? new
|
|
136060
|
+
var pinned = preferred ?? loadPrefs().pinnedModel;
|
|
136061
|
+
var selector = pinned ? new FixedSelector(pinned) : new RoutingSelector;
|
|
136864
136062
|
if (args.includes("--yolo"))
|
|
136865
|
-
|
|
136063
|
+
setYolo(true);
|
|
136866
136064
|
var resumeId = args.includes("--continue") || args.includes("-c") ? latestSession()?.id ?? undefined : undefined;
|
|
136867
|
-
var imageMode =
|
|
136065
|
+
var imageMode = detectImageMode();
|
|
136868
136066
|
setImageMode(imageMode);
|
|
136869
136067
|
if (process.stdout.isTTY && imageMode === "kitty")
|
|
136870
136068
|
process.stdout.write(transmitAll());
|
|
136871
|
-
var uiPrefs =
|
|
136069
|
+
var uiPrefs = loadPrefs();
|
|
136872
136070
|
var explicitInline = args.includes("--inline") || process.env.GEARBOX_INLINE === "1" || process.env.GEARBOX_FULLSCREEN === "0";
|
|
136873
136071
|
var explicitFullscreen = args.includes("--fullscreen") || process.env.GEARBOX_FULLSCREEN === "1";
|
|
136874
136072
|
var wantsInline = explicitInline || !explicitFullscreen && uiPrefs.fullscreen === false;
|