gearbox-code 0.1.2 → 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/README.md +5 -3
- package/dist/cli.mjs +549 -1209
- 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,221 @@ 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
|
+
|
|
64174
|
+
// src/accounts/onboarding.ts
|
|
64175
|
+
function normalizeProviderId(input) {
|
|
64176
|
+
const key = input.trim().toLowerCase().replace(/[_\s]+/g, "-");
|
|
64177
|
+
return ALIASES[key] ?? key;
|
|
64178
|
+
}
|
|
64179
|
+
function apiKeyProviders() {
|
|
64180
|
+
return CATALOG.filter((p) => (p.authKind === "api-key" || p.authKind === "openai-compat") && p.group !== "local" && (p.authKind !== "openai-compat" || Boolean(p.baseUrl)));
|
|
64181
|
+
}
|
|
64182
|
+
function featuredApiKeyProviders() {
|
|
64183
|
+
const providers = apiKeyProviders();
|
|
64184
|
+
const byId = new Map(providers.map((p) => [p.id, p]));
|
|
64185
|
+
const first = FEATURED.map((id) => byId.get(id)).filter((p) => Boolean(p));
|
|
64186
|
+
const rest2 = providers.filter((p) => !FEATURED.includes(p.id)).sort((a, b) => a.label.localeCompare(b.label));
|
|
64187
|
+
return [...first, ...rest2];
|
|
64188
|
+
}
|
|
64189
|
+
function needsOnboarding(state) {
|
|
64190
|
+
return state.configured.length === 0;
|
|
64191
|
+
}
|
|
64192
|
+
function onboardingSummary(state) {
|
|
64193
|
+
if (!needsOnboarding(state))
|
|
64194
|
+
return "ready";
|
|
64195
|
+
const lines = [
|
|
64196
|
+
"setup required",
|
|
64197
|
+
" Add any common provider API key:",
|
|
64198
|
+
...featuredApiKeyProviders().slice(0, 10).map((p) => ` /account add ${p.id} <api-key>`.padEnd(38) + `${p.label}`)
|
|
64199
|
+
];
|
|
64200
|
+
const more = featuredApiKeyProviders().length - 10;
|
|
64201
|
+
if (more > 0)
|
|
64202
|
+
lines.push(` /onboard providers show ${more} more providers`);
|
|
64203
|
+
if (state.importable.length || state.cloudImportable.length)
|
|
64204
|
+
lines.push("", " /account import import detected env/cloud credentials");
|
|
64205
|
+
lines.push(" /account add azure <endpoint> <api-key> Azure OpenAI / Foundry");
|
|
64206
|
+
if (state.hasClaudeCli)
|
|
64207
|
+
lines.push(" /account add claude use Claude subscription CLI");
|
|
64208
|
+
if (state.hasCodexCli)
|
|
64209
|
+
lines.push(" /account add codex use ChatGPT subscription CLI");
|
|
64210
|
+
lines.push("", "Paste-detect works for known key prefixes: /account add <api-key>");
|
|
64211
|
+
return lines.join(`
|
|
64212
|
+
`);
|
|
64213
|
+
}
|
|
64214
|
+
var ALIASES, FEATURED;
|
|
64215
|
+
var init_onboarding = __esm(() => {
|
|
64216
|
+
init_catalog();
|
|
64217
|
+
ALIASES = {
|
|
64218
|
+
anthropic: "anthropic",
|
|
64219
|
+
claude: "anthropic",
|
|
64220
|
+
openai: "openai",
|
|
64221
|
+
gpt: "openai",
|
|
64222
|
+
google: "google",
|
|
64223
|
+
gemini: "google",
|
|
64224
|
+
deepseek: "deepseek",
|
|
64225
|
+
grok: "xai",
|
|
64226
|
+
xai: "xai",
|
|
64227
|
+
"x-ai": "xai",
|
|
64228
|
+
mistral: "mistral",
|
|
64229
|
+
groq: "groq",
|
|
64230
|
+
together: "together",
|
|
64231
|
+
fireworks: "fireworks",
|
|
64232
|
+
deepinfra: "deepinfra",
|
|
64233
|
+
cerebras: "cerebras",
|
|
64234
|
+
perplexity: "perplexity",
|
|
64235
|
+
baseten: "baseten",
|
|
64236
|
+
moonshot: "moonshot",
|
|
64237
|
+
kimi: "moonshot",
|
|
64238
|
+
zai: "zai",
|
|
64239
|
+
zhipu: "zai",
|
|
64240
|
+
nebius: "nebius",
|
|
64241
|
+
hyperbolic: "hyperbolic",
|
|
64242
|
+
sambanova: "sambanova",
|
|
64243
|
+
novita: "novita",
|
|
64244
|
+
openrouter: "openrouter",
|
|
64245
|
+
requesty: "requesty",
|
|
64246
|
+
portkey: "portkey",
|
|
64247
|
+
litellm: "litellm",
|
|
64248
|
+
"vercel-gateway": "vercel-gateway",
|
|
64249
|
+
vercel: "vercel-gateway",
|
|
64250
|
+
"ai-gateway": "vercel-gateway",
|
|
64251
|
+
azure: "azure",
|
|
64252
|
+
"azure-foundry": "azure-foundry",
|
|
64253
|
+
foundry: "azure-foundry"
|
|
64254
|
+
};
|
|
64255
|
+
FEATURED = [
|
|
64256
|
+
"anthropic",
|
|
64257
|
+
"openai",
|
|
64258
|
+
"google",
|
|
64259
|
+
"deepseek",
|
|
64260
|
+
"openrouter",
|
|
64261
|
+
"xai",
|
|
64262
|
+
"mistral",
|
|
64263
|
+
"groq",
|
|
64264
|
+
"together",
|
|
64265
|
+
"fireworks",
|
|
64266
|
+
"perplexity",
|
|
64267
|
+
"cerebras",
|
|
64268
|
+
"requesty"
|
|
64269
|
+
];
|
|
64270
|
+
});
|
|
64271
|
+
|
|
64035
64272
|
// src/agent/cli-backend.ts
|
|
64036
64273
|
function newState() {
|
|
64037
64274
|
return { text: "", usage: { inputTokens: 0, outputTokens: 0 }, rates: new Map, toolNames: new Map };
|
|
@@ -64267,354 +64504,33 @@ var init_cli_backend = __esm(() => {
|
|
|
64267
64504
|
CONFIG_DIR_VAR = { claude: "CLAUDE_CONFIG_DIR", codex: "CODEX_HOME" };
|
|
64268
64505
|
});
|
|
64269
64506
|
|
|
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
64507
|
// src/accounts/onboard.ts
|
|
64593
64508
|
var exports_onboard = {};
|
|
64594
64509
|
__export(exports_onboard, {
|
|
64595
|
-
testAccount: () =>
|
|
64596
|
-
cliLoginArgs: () =>
|
|
64597
|
-
cliAuthStatus: () =>
|
|
64510
|
+
testAccount: () => testAccount,
|
|
64511
|
+
cliLoginArgs: () => cliLoginArgs,
|
|
64512
|
+
cliAuthStatus: () => cliAuthStatus,
|
|
64598
64513
|
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
|
|
64514
|
+
addCliAccount: () => addCliAccount,
|
|
64515
|
+
addByPastedKey: () => addByPastedKey,
|
|
64516
|
+
addAzureFoundryAccount: () => addAzureFoundryAccount,
|
|
64517
|
+
addAzureAccount: () => addAzureAccount,
|
|
64518
|
+
addApiKeyAccount: () => addApiKeyAccount
|
|
64519
|
+
});
|
|
64520
|
+
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
64521
|
+
import { join as join10 } from "node:path";
|
|
64522
|
+
import { homedir as homedir8 } from "node:os";
|
|
64523
|
+
async function addApiKeyAccount(provider, key, opts = {}) {
|
|
64524
|
+
provider = normalizeProviderId(provider);
|
|
64609
64525
|
const cat = catalogProvider(provider);
|
|
64610
64526
|
if (!cat)
|
|
64611
|
-
return { ok: false, message: `unknown provider "${provider}" —
|
|
64527
|
+
return { ok: false, message: `unknown provider "${provider}" — use /onboard providers` };
|
|
64612
64528
|
if (cat.group === "cli")
|
|
64613
64529
|
return { ok: false, message: `${cat.label} is a subscription account — use /login ${provider} (P3), not a key` };
|
|
64614
64530
|
if (cat.authKind !== "api-key" && cat.authKind !== "openai-compat") {
|
|
64615
64531
|
return { ok: false, message: `${cat.label} needs ${cat.authKind} credentials — use the guided add (P2)` };
|
|
64616
64532
|
}
|
|
64617
|
-
const id = opts.id ?? `${provider}-${
|
|
64533
|
+
const id = opts.id ?? `${provider}-${shortId()}`;
|
|
64618
64534
|
const ref = `${id}:api-key`;
|
|
64619
64535
|
await setSecret(ref, key.trim());
|
|
64620
64536
|
const account = {
|
|
@@ -64630,7 +64546,7 @@ async function addApiKeyAccount2(provider, key, opts = {}) {
|
|
|
64630
64546
|
putAccount(account);
|
|
64631
64547
|
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
64632
64548
|
}
|
|
64633
|
-
function
|
|
64549
|
+
function azureResourceName(input) {
|
|
64634
64550
|
const s2 = input.trim();
|
|
64635
64551
|
try {
|
|
64636
64552
|
const host = new URL(s2).hostname;
|
|
@@ -64639,7 +64555,7 @@ function azureResourceName2(input) {
|
|
|
64639
64555
|
return s2;
|
|
64640
64556
|
}
|
|
64641
64557
|
}
|
|
64642
|
-
function
|
|
64558
|
+
function azureFoundryBaseUrl(endpoint) {
|
|
64643
64559
|
const trimmed = endpoint.trim().replace(/\/+$/, "");
|
|
64644
64560
|
if (/\/openai\/v1$/i.test(trimmed))
|
|
64645
64561
|
return trimmed;
|
|
@@ -64647,32 +64563,32 @@ function azureFoundryBaseUrl2(endpoint) {
|
|
|
64647
64563
|
return `${trimmed}/v1`;
|
|
64648
64564
|
return `${trimmed}/openai/v1`;
|
|
64649
64565
|
}
|
|
64650
|
-
async function
|
|
64566
|
+
async function addAzureFoundryAccount(endpoint, key, opts = {}) {
|
|
64651
64567
|
if (!/^https?:\/\//i.test(endpoint) || !key.trim())
|
|
64652
64568
|
return { ok: false, message: "usage: /account add azure <foundry-endpoint> <api-key>" };
|
|
64653
64569
|
const host = new URL(endpoint).hostname;
|
|
64654
|
-
const
|
|
64655
|
-
const id = opts.id ?? `azure-foundry-${
|
|
64570
|
+
const slug3 = host.split(".")[0]?.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || shortId();
|
|
64571
|
+
const id = opts.id ?? `azure-foundry-${slug3}`;
|
|
64656
64572
|
const ref = `${id}:api-key`;
|
|
64657
64573
|
await setSecret(ref, key.trim());
|
|
64658
64574
|
const account = {
|
|
64659
64575
|
id,
|
|
64660
|
-
label: opts.label ?? `Azure Foundry (${
|
|
64576
|
+
label: opts.label ?? `Azure Foundry (${slug3})`,
|
|
64661
64577
|
provider: "azure-foundry",
|
|
64662
64578
|
exec: "in-loop",
|
|
64663
64579
|
auth: { kind: "openai-compat", ref },
|
|
64664
|
-
baseUrl:
|
|
64580
|
+
baseUrl: azureFoundryBaseUrl(endpoint),
|
|
64665
64581
|
enabled: true,
|
|
64666
64582
|
addedAt: Date.now()
|
|
64667
64583
|
};
|
|
64668
64584
|
putAccount(account);
|
|
64669
64585
|
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
64670
64586
|
}
|
|
64671
|
-
async function
|
|
64672
|
-
const resourceName =
|
|
64587
|
+
async function addAzureAccount(resourceOrEndpoint, key, opts = {}) {
|
|
64588
|
+
const resourceName = azureResourceName(resourceOrEndpoint);
|
|
64673
64589
|
if (!resourceName || !key.trim())
|
|
64674
64590
|
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, "") ||
|
|
64591
|
+
const id = opts.id ?? `azure-${resourceName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || shortId()}`;
|
|
64676
64592
|
const ref = `${id}:api-key`;
|
|
64677
64593
|
await setSecret(ref, key.trim());
|
|
64678
64594
|
const account = {
|
|
@@ -64687,24 +64603,24 @@ async function addAzureAccount2(resourceOrEndpoint, key, opts = {}) {
|
|
|
64687
64603
|
putAccount(account);
|
|
64688
64604
|
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
64689
64605
|
}
|
|
64690
|
-
function
|
|
64691
|
-
const
|
|
64692
|
-
return
|
|
64606
|
+
function cliProfileDir(id) {
|
|
64607
|
+
const home5 = process.env.GEARBOX_HOME || join10(homedir8(), ".gearbox");
|
|
64608
|
+
return join10(home5, "cli", id);
|
|
64693
64609
|
}
|
|
64694
|
-
function
|
|
64610
|
+
function addCliAccount(provider, name31) {
|
|
64695
64611
|
const cat = catalogProvider(provider);
|
|
64696
64612
|
if (!cat || cat.group !== "cli" || !cat.binary)
|
|
64697
64613
|
return { ok: false, message: `"${provider}" is not a CLI subscription provider` };
|
|
64698
64614
|
if (!which(cat.binary))
|
|
64699
64615
|
return { ok: false, message: `the ${cat.binary} binary isn't on your PATH — install it first` };
|
|
64700
|
-
const
|
|
64701
|
-
const id =
|
|
64702
|
-
const profile =
|
|
64616
|
+
const slug3 = name31 ? name31.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") : "";
|
|
64617
|
+
const id = slug3 ? `${provider}-${slug3}` : provider;
|
|
64618
|
+
const profile = slug3 ? cliProfileDir(id) : undefined;
|
|
64703
64619
|
if (profile)
|
|
64704
|
-
|
|
64620
|
+
mkdirSync7(profile, { recursive: true });
|
|
64705
64621
|
const account = {
|
|
64706
64622
|
id,
|
|
64707
|
-
label:
|
|
64623
|
+
label: slug3 ? `${cat.label.replace(/ \(.*\)$/, "")} (${name31.trim()})` : cat.label,
|
|
64708
64624
|
provider,
|
|
64709
64625
|
exec: "cli",
|
|
64710
64626
|
auth: { kind: "cli", binary: cat.binary, loginProfile: profile },
|
|
@@ -64715,7 +64631,7 @@ function addCliAccount2(provider, name31) {
|
|
|
64715
64631
|
putAccount(account);
|
|
64716
64632
|
return { ok: true, account, message: `${account.label} ready — runs via the ${cat.binary} CLI${profile ? " (separate login)" : ""}` };
|
|
64717
64633
|
}
|
|
64718
|
-
async function
|
|
64634
|
+
async function cliAuthStatus(binary, profile) {
|
|
64719
64635
|
const env3 = subscriptionEnv(binary, profile);
|
|
64720
64636
|
const readBoth = async (cmd, timeoutMs = 5000) => {
|
|
64721
64637
|
const p = spawnProc(cmd, { stdin: "ignore", stdout: "pipe", stderr: "pipe", env: env3 });
|
|
@@ -64768,16 +64684,16 @@ ${e2}`.trim(), timedOut };
|
|
|
64768
64684
|
return { loggedIn: false };
|
|
64769
64685
|
}
|
|
64770
64686
|
}
|
|
64771
|
-
function
|
|
64687
|
+
function cliLoginArgs(binary) {
|
|
64772
64688
|
return binary === "codex" ? ["login"] : ["auth", "login"];
|
|
64773
64689
|
}
|
|
64774
|
-
async function
|
|
64690
|
+
async function addByPastedKey(key) {
|
|
64775
64691
|
const provider = detectProviderByKey(key);
|
|
64776
64692
|
if (!provider)
|
|
64777
64693
|
return { ok: false, message: "couldn't identify the provider from that key — use /accounts add <provider> <key>" };
|
|
64778
|
-
return
|
|
64694
|
+
return addApiKeyAccount(provider, key);
|
|
64779
64695
|
}
|
|
64780
|
-
async function
|
|
64696
|
+
async function testAccount(a) {
|
|
64781
64697
|
const creds = await resolveCreds(a);
|
|
64782
64698
|
if (!creds.apiKey && a.auth.kind !== "cli")
|
|
64783
64699
|
return { ok: false, message: "no key stored" };
|
|
@@ -64788,17 +64704,17 @@ async function testAccount2(a) {
|
|
|
64788
64704
|
headers: { "x-api-key": creds.apiKey ?? "", "anthropic-version": "2023-06-01", "content-type": "application/json" },
|
|
64789
64705
|
body: JSON.stringify({ model: "claude-haiku-4-5", messages: [{ role: "user", content: "hi" }] })
|
|
64790
64706
|
});
|
|
64791
|
-
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await
|
|
64707
|
+
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
64792
64708
|
}
|
|
64793
64709
|
if (a.provider === "google") {
|
|
64794
64710
|
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
|
|
64711
|
+
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
64796
64712
|
}
|
|
64797
64713
|
const base2 = creds.baseURL ?? "https://api.openai.com/v1";
|
|
64798
64714
|
const r2 = await fetch(`${base2.replace(/\/$/, "")}/models`, {
|
|
64799
64715
|
headers: { Authorization: `Bearer ${creds.apiKey ?? ""}`, ...creds.headers ?? {} }
|
|
64800
64716
|
});
|
|
64801
|
-
return r2.ok ? { ok: true, message: "credential works" } : { ok: false, message: await
|
|
64717
|
+
return r2.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r2) };
|
|
64802
64718
|
} catch (e2) {
|
|
64803
64719
|
return { ok: false, message: e2?.message ?? "request failed" };
|
|
64804
64720
|
}
|
|
@@ -64806,7 +64722,7 @@ async function testAccount2(a) {
|
|
|
64806
64722
|
function addableProviders() {
|
|
64807
64723
|
return CATALOG.filter((p) => p.authKind === "api-key" || p.authKind === "openai-compat").map((p) => ({ id: p.id, label: p.label, group: p.group }));
|
|
64808
64724
|
}
|
|
64809
|
-
async function
|
|
64725
|
+
async function errMessage(r2) {
|
|
64810
64726
|
try {
|
|
64811
64727
|
const j = await r2.json();
|
|
64812
64728
|
const m2 = j?.error?.message ?? j?.message ?? j?.error;
|
|
@@ -64815,73 +64731,18 @@ async function errMessage2(r2) {
|
|
|
64815
64731
|
} catch {}
|
|
64816
64732
|
return `HTTP ${r2.status}`;
|
|
64817
64733
|
}
|
|
64818
|
-
function
|
|
64734
|
+
function shortId() {
|
|
64819
64735
|
return Date.now().toString(36).slice(-4) + Math.floor(Math.random() * 1296).toString(36).padStart(2, "0");
|
|
64820
64736
|
}
|
|
64821
64737
|
var init_onboard = __esm(() => {
|
|
64822
64738
|
init_store();
|
|
64823
64739
|
init_catalog();
|
|
64740
|
+
init_onboarding();
|
|
64824
64741
|
init_resolve();
|
|
64825
64742
|
init_cli_backend();
|
|
64826
64743
|
init_proc();
|
|
64827
64744
|
});
|
|
64828
64745
|
|
|
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
64746
|
// node_modules/ink/build/render.js
|
|
64886
64747
|
import { Stream } from "node:stream";
|
|
64887
64748
|
import process12 from "node:process";
|
|
@@ -70406,12 +70267,13 @@ var import_react20 = __toESM(require_react(), 1);
|
|
|
70406
70267
|
// node_modules/ink/build/hooks/use-focus-manager.js
|
|
70407
70268
|
var import_react21 = __toESM(require_react(), 1);
|
|
70408
70269
|
// src/cli.tsx
|
|
70409
|
-
import { execFileSync as execFileSync4 } from "child_process";
|
|
70410
|
-
import { resolve as resolve11 } from "path";
|
|
70411
|
-
import { existsSync as
|
|
70270
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
70271
|
+
import { resolve as resolve11 } from "node:path";
|
|
70272
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
70412
70273
|
|
|
70413
70274
|
// src/ui/App.tsx
|
|
70414
70275
|
var import_react26 = __toESM(require_react(), 1);
|
|
70276
|
+
|
|
70415
70277
|
// src/ui/theme.ts
|
|
70416
70278
|
var color = {
|
|
70417
70279
|
accent: "#7DD3FC",
|
|
@@ -118658,6 +118520,7 @@ var COMMANDS = [
|
|
|
118658
118520
|
{ name: "/context", usage: "/context", desc: "see what's loaded and how many tokens it uses", group: "chat" },
|
|
118659
118521
|
{ name: "/memory", usage: "/memory [note]", desc: "show or add facts to remember (or start a line with #)", group: "chat" },
|
|
118660
118522
|
{ name: "/account", usage: "/account", desc: "list accounts; /account <number> to switch, /account add to add one", group: "accounts" },
|
|
118523
|
+
{ name: "/onboard", usage: "/onboard", desc: "first-run setup; provider list and import/add commands", group: "accounts" },
|
|
118661
118524
|
{ name: "/cost", usage: "/cost", desc: "see what you've spent per account", group: "accounts" },
|
|
118662
118525
|
{ name: "/copy", usage: "/copy", desc: "copy the last reply to the clipboard", group: "output" },
|
|
118663
118526
|
{ name: "/export", usage: "/export [file]", desc: "save the conversation to a file", group: "output" },
|
|
@@ -119403,6 +119266,9 @@ function detectImageMode() {
|
|
|
119403
119266
|
return "blocks";
|
|
119404
119267
|
}
|
|
119405
119268
|
var resolved = null;
|
|
119269
|
+
function setImageMode(m2) {
|
|
119270
|
+
resolved = m2;
|
|
119271
|
+
}
|
|
119406
119272
|
function getImageMode() {
|
|
119407
119273
|
return resolved ?? detectImageMode();
|
|
119408
119274
|
}
|
|
@@ -119413,6 +119279,30 @@ function idColor(id) {
|
|
|
119413
119279
|
const bytes = [id >> 16 & 255, id >> 8 & 255, id & 255];
|
|
119414
119280
|
return "#" + bytes.map((x2) => x2.toString(16).padStart(2, "0")).join("");
|
|
119415
119281
|
}
|
|
119282
|
+
function transmitOne(id, b64, cols, rows) {
|
|
119283
|
+
const ESC2 = "\x1B";
|
|
119284
|
+
const CHUNK = 4096;
|
|
119285
|
+
if (b64.length <= CHUNK) {
|
|
119286
|
+
return `${ESC2}_Ga=T,U=1,i=${id},c=${cols},r=${rows},f=100,q=2;${b64}${ESC2}\\`;
|
|
119287
|
+
}
|
|
119288
|
+
let out = "";
|
|
119289
|
+
for (let i2 = 0;i2 < b64.length; i2 += CHUNK) {
|
|
119290
|
+
const chunk2 = b64.slice(i2, i2 + CHUNK);
|
|
119291
|
+
const more = i2 + CHUNK < b64.length ? 1 : 0;
|
|
119292
|
+
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}\\`;
|
|
119293
|
+
}
|
|
119294
|
+
return out;
|
|
119295
|
+
}
|
|
119296
|
+
function transmitAll() {
|
|
119297
|
+
let out = "";
|
|
119298
|
+
for (const variant of VARIANTS) {
|
|
119299
|
+
for (const size2 of SIZES) {
|
|
119300
|
+
const data = GHOSTS[variant][size2];
|
|
119301
|
+
out += transmitOne(imageId(variant, size2), GHOST_PNG[variant], data[0]?.length ?? 0, data.length);
|
|
119302
|
+
}
|
|
119303
|
+
}
|
|
119304
|
+
return out;
|
|
119305
|
+
}
|
|
119416
119306
|
function placeholderRows(cols, rows) {
|
|
119417
119307
|
const lines = [];
|
|
119418
119308
|
for (let r2 = 0;r2 < rows; r2++) {
|
|
@@ -121297,6 +121187,9 @@ function listSessions() {
|
|
|
121297
121187
|
return [];
|
|
121298
121188
|
}
|
|
121299
121189
|
}
|
|
121190
|
+
function latestSession() {
|
|
121191
|
+
return listSessions()[0] ?? null;
|
|
121192
|
+
}
|
|
121300
121193
|
var histFile = () => join4(dir(), "history.json");
|
|
121301
121194
|
function loadHistory() {
|
|
121302
121195
|
try {
|
|
@@ -133323,335 +133216,10 @@ function friendlyToolPhase(name31) {
|
|
|
133323
133216
|
// src/ui/App.tsx
|
|
133324
133217
|
init_resolve();
|
|
133325
133218
|
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
|
|
133219
|
+
init_detect();
|
|
133220
|
+
init_onboard();
|
|
133654
133221
|
init_catalog();
|
|
133222
|
+
init_onboarding();
|
|
133655
133223
|
init_cli_backend();
|
|
133656
133224
|
|
|
133657
133225
|
// src/accounts/balance.ts
|
|
@@ -133764,72 +133332,6 @@ ${summary}` },
|
|
|
133764
133332
|
return { messages, summarizedTurns: old.length, before: before2, after: after2 };
|
|
133765
133333
|
}
|
|
133766
133334
|
|
|
133767
|
-
// src/agent/mock.ts
|
|
133768
|
-
var sleep = (ms) => new Promise((r2) => setTimeout(r2, ms));
|
|
133769
|
-
async function stream(text2, onEvent, chunk2 = 3, delay3 = 8) {
|
|
133770
|
-
for (let i2 = 0;i2 < text2.length; i2 += chunk2) {
|
|
133771
|
-
onEvent({ type: "text", text: text2.slice(i2, i2 + chunk2) });
|
|
133772
|
-
await sleep(delay3);
|
|
133773
|
-
}
|
|
133774
|
-
}
|
|
133775
|
-
async function streamWrite(id, path, content, onEvent, stop) {
|
|
133776
|
-
onEvent({ type: "tool-start", id, name: "write_file", arg: "" });
|
|
133777
|
-
onEvent({ type: "tool-stream", id, arg: path });
|
|
133778
|
-
for (let i2 = 0;i2 < content.length; i2 += 8) {
|
|
133779
|
-
if (stop())
|
|
133780
|
-
return;
|
|
133781
|
-
onEvent({ type: "tool-stream", id, delta: content.slice(i2, i2 + 8) });
|
|
133782
|
-
await sleep(16);
|
|
133783
|
-
}
|
|
133784
|
-
const diff2 = content.replace(/\n$/, "").split(`
|
|
133785
|
-
`).map((text2) => ({ sign: "+", text: text2 }));
|
|
133786
|
-
onEvent({ type: "tool-end", id, ok: true, summary: `wrote ${path} (+${diff2.length} −0)`, diff: diff2 });
|
|
133787
|
-
}
|
|
133788
|
-
async function runTaskMock(opts) {
|
|
133789
|
-
const { prompt, messages, onEvent, signal } = opts;
|
|
133790
|
-
const stop = () => signal?.aborted === true;
|
|
133791
|
-
await stream(`Sure — let me take a look around first.
|
|
133792
|
-
`, onEvent);
|
|
133793
|
-
if (stop())
|
|
133794
|
-
return done(messages, onEvent);
|
|
133795
|
-
onEvent({ type: "tool-start", id: "1", name: "list_dir", arg: "." });
|
|
133796
|
-
await sleep(260);
|
|
133797
|
-
if (stop())
|
|
133798
|
-
return done(messages, onEvent);
|
|
133799
|
-
onEvent({ type: "tool-end", id: "1", ok: true, summary: "src · package.json · README.md · 5 more" });
|
|
133800
|
-
onEvent({ type: "tool-start", id: "2", name: "read_file", arg: "src/cli.tsx" });
|
|
133801
|
-
await sleep(220);
|
|
133802
|
-
if (stop())
|
|
133803
|
-
return done(messages, onEvent);
|
|
133804
|
-
onEvent({ type: "tool-end", id: "2", ok: true, summary: "renders the Ink app · 38 lines" });
|
|
133805
|
-
await stream(`
|
|
133806
|
-
Here's a quick file — watch it stream in:
|
|
133807
|
-
`, onEvent);
|
|
133808
|
-
if (stop())
|
|
133809
|
-
return done(messages, onEvent);
|
|
133810
|
-
const demoFile = `# hello.py — written live in demo mode
|
|
133811
|
-
|
|
133812
|
-
def greet(name: str) -> str:
|
|
133813
|
-
return f"Hello, {name}!"
|
|
133814
|
-
|
|
133815
|
-
if __name__ == "__main__":
|
|
133816
|
-
for who in ("world", "gearbox", "Boo"):
|
|
133817
|
-
print(greet(who))
|
|
133818
|
-
`;
|
|
133819
|
-
await streamWrite("3", "hello.py", demoFile, onEvent, stop);
|
|
133820
|
-
if (stop())
|
|
133821
|
-
return done(messages, onEvent);
|
|
133822
|
-
await stream(`
|
|
133823
|
-
This is demo mode — no API key is set, so I'm not calling a real model. ` + `Set ANTHROPIC_API_KEY (or OPENAI / GOOGLE / DEEPSEEK) and I'll actually work on: "${prompt}".
|
|
133824
|
-
`, onEvent);
|
|
133825
|
-
return done(messages, onEvent);
|
|
133826
|
-
}
|
|
133827
|
-
function done(messages, onEvent) {
|
|
133828
|
-
const usage = { inputTokens: 0, outputTokens: 0 };
|
|
133829
|
-
onEvent({ type: "done", usage });
|
|
133830
|
-
return { messages, usage };
|
|
133831
|
-
}
|
|
133832
|
-
|
|
133833
133335
|
// src/ui/clipboard.ts
|
|
133834
133336
|
init_proc();
|
|
133835
133337
|
function osc52(text2) {
|
|
@@ -134184,11 +133686,11 @@ function ActivityRail({ items, width }) {
|
|
|
134184
133686
|
]
|
|
134185
133687
|
}, undefined, true, undefined, this);
|
|
134186
133688
|
}
|
|
134187
|
-
function App2({ selector: initialSelector,
|
|
133689
|
+
function App2({ selector: initialSelector, runner, fullscreen = false, resumeId }) {
|
|
134188
133690
|
const { exit } = use_app_default();
|
|
134189
133691
|
const { stdin, isRawModeSupported, setRawMode } = use_stdin_default();
|
|
134190
133692
|
const { columns, rows } = useTerminalSize();
|
|
134191
|
-
const online = useOnline(20000,
|
|
133693
|
+
const online = useOnline(20000, true);
|
|
134192
133694
|
const width = columns;
|
|
134193
133695
|
const splashSize = rows >= 24 && columns >= 42 ? "big" : rows >= 13 && columns >= 22 ? "mini" : "none";
|
|
134194
133696
|
const [items, setItems] = import_react26.useState([]);
|
|
@@ -134267,10 +133769,6 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134267
133769
|
const t2 = setInterval(() => setElapsed(Math.floor((Date.now() - start) / 1000)), 500);
|
|
134268
133770
|
return () => clearInterval(t2);
|
|
134269
133771
|
}, [busy]);
|
|
134270
|
-
import_react26.useEffect(() => {
|
|
134271
|
-
if (firstRunRef.current)
|
|
134272
|
-
updatePrefs({ onboarded: true });
|
|
134273
|
-
}, []);
|
|
134274
133772
|
import_react26.useEffect(() => {
|
|
134275
133773
|
const proj = basename2(process.cwd());
|
|
134276
133774
|
setTitle(busy ? `✳ ${proj} · working` : `${proj} · gearbox`);
|
|
@@ -134331,8 +133829,6 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134331
133829
|
setTimeout(pumpPerm, 0);
|
|
134332
133830
|
};
|
|
134333
133831
|
import_react26.useEffect(() => {
|
|
134334
|
-
if (demo)
|
|
134335
|
-
return;
|
|
134336
133832
|
const acctId = loadPrefs().activeAccount;
|
|
134337
133833
|
if (!acctId)
|
|
134338
133834
|
return;
|
|
@@ -134344,7 +133840,7 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134344
133840
|
setActiveCliModelId(undefined);
|
|
134345
133841
|
setActiveCli({ id: a.id, label: bin });
|
|
134346
133842
|
}
|
|
134347
|
-
}, [
|
|
133843
|
+
}, []);
|
|
134348
133844
|
import_react26.useEffect(() => {
|
|
134349
133845
|
setPermissionHandler((req) => new Promise((resolve11) => {
|
|
134350
133846
|
if (modeRef.current === "auto-accept" && (req.kind === "write" || req.kind === "edit")) {
|
|
@@ -134586,8 +134082,6 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134586
134082
|
};
|
|
134587
134083
|
}, [stdin, fullscreen, rows, scrollBy, copyWithFeedback]);
|
|
134588
134084
|
const persist = import_react26.useCallback(() => {
|
|
134589
|
-
if (demo)
|
|
134590
|
-
return;
|
|
134591
134085
|
const s2 = sessionRef.current;
|
|
134592
134086
|
if (!itemsRef.current.length)
|
|
134593
134087
|
return;
|
|
@@ -134601,7 +134095,7 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134601
134095
|
items: itemsRef.current,
|
|
134602
134096
|
turns: s2.turns
|
|
134603
134097
|
});
|
|
134604
|
-
}, [
|
|
134098
|
+
}, []);
|
|
134605
134099
|
const loadInto = (s2) => {
|
|
134606
134100
|
idRef.current = s2.items.reduce((m2, i2) => Math.max(m2, i2.id), 0) + 1;
|
|
134607
134101
|
setItems(s2.items);
|
|
@@ -134761,10 +134255,24 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134761
134255
|
const [lastPick, setLastPick] = import_react26.useState(null);
|
|
134762
134256
|
const [activeCli, setActiveCli] = import_react26.useState(null);
|
|
134763
134257
|
const [activeCliModel, setActiveCliModel] = import_react26.useState(null);
|
|
134258
|
+
const onboardingState = {
|
|
134259
|
+
configured: listAccounts(),
|
|
134260
|
+
importable: importableEnvCreds(),
|
|
134261
|
+
cloudImportable: importableCloudCreds().map((c) => ({ provider: c.provider, label: c.label, source: c.source })),
|
|
134262
|
+
hasClaudeCli: Boolean(which("claude")),
|
|
134263
|
+
hasCodexCli: Boolean(which("codex"))
|
|
134264
|
+
};
|
|
134265
|
+
const setupRequired = needsOnboarding(onboardingState);
|
|
134266
|
+
import_react26.useEffect(() => {
|
|
134267
|
+
if (!setupRequired && firstRunRef.current) {
|
|
134268
|
+
firstRunRef.current = false;
|
|
134269
|
+
updatePrefs({ onboarded: true });
|
|
134270
|
+
}
|
|
134271
|
+
}, [setupRequired]);
|
|
134764
134272
|
const model = lastPick?.model ?? choice?.model ?? null;
|
|
134765
|
-
const modelLabel =
|
|
134273
|
+
const modelLabel = setupRequired ? "setup required" : activeCli ? `${activeCli.label}${activeCliModel ? ` · ${activeCliModel}` : ""}` : model?.label ?? "none";
|
|
134766
134274
|
const subscription = activeCli ? activeCli.label : null;
|
|
134767
|
-
const routing =
|
|
134275
|
+
const routing = setupRequired || activeCli ? null : lastPick?.reason ?? choice?.reason ?? null;
|
|
134768
134276
|
const ctxPct = !activeCli && model && lastInput > 0 ? Math.round(lastInput / model.contextWindow * 100) : null;
|
|
134769
134277
|
const push = (it) => setItems((prev) => [...prev, it]);
|
|
134770
134278
|
const pushPhase = (label, detail) => {
|
|
@@ -134835,8 +134343,6 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134835
134343
|
};
|
|
134836
134344
|
};
|
|
134837
134345
|
const defaultRunner = import_react26.useCallback(async ({ prompt, messages, onEvent, selector: sel, signal }) => {
|
|
134838
|
-
if (demo)
|
|
134839
|
-
return runTaskMock({ prompt, messages, onEvent, signal });
|
|
134840
134346
|
const cli = activeCliRef.current;
|
|
134841
134347
|
if (cli) {
|
|
134842
134348
|
routedRef.current = null;
|
|
@@ -134869,10 +134375,8 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134869
134375
|
const produced = r2.messages.slice(ctx.length);
|
|
134870
134376
|
const ledger = sanitizeToolPairs([...messages, { role: "user", content: prompt }, ...produced]);
|
|
134871
134377
|
return { messages: ledger, usage: r2.usage };
|
|
134872
|
-
}, [
|
|
134378
|
+
}, []);
|
|
134873
134379
|
const compactNow = import_react26.useCallback(async (keepRecent, signal) => {
|
|
134874
|
-
if (demo)
|
|
134875
|
-
return "compaction needs a model (no key in demo)";
|
|
134876
134380
|
let model2;
|
|
134877
134381
|
try {
|
|
134878
134382
|
model2 = selectorRef.current.select({ prompt: "", kind: "summarize" }).model;
|
|
@@ -134886,7 +134390,7 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
134886
134390
|
const saved = res.before - res.after;
|
|
134887
134391
|
const savedStr = saved >= 1000 ? `${(saved / 1000).toFixed(1)}k` : String(Math.max(0, saved));
|
|
134888
134392
|
return `compacted ${res.summarizedTurns} earlier turn${res.summarizedTurns > 1 ? "s" : ""} · ~${savedStr} tokens freed`;
|
|
134889
|
-
}, [
|
|
134393
|
+
}, []);
|
|
134890
134394
|
const MODE_NOTE = {
|
|
134891
134395
|
normal: "normal mode — I'll ask before writes, edits, and shell",
|
|
134892
134396
|
"auto-accept": "auto-accept edits — file writes/edits apply without asking (shell still gated)",
|
|
@@ -135134,7 +134638,7 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
135134
134638
|
recordUsage({ accountId: acctId, inputTokens: r2.usage.inputTokens, outputTokens: r2.usage.outputTokens, costUSD: cost, estimated: cm?.costUSD == null });
|
|
135135
134639
|
if (cm?.rates?.length)
|
|
135136
134640
|
recordRateLimits(acctId, cm.rates);
|
|
135137
|
-
if (!
|
|
134641
|
+
if (!ac.signal.aborted) {
|
|
135138
134642
|
try {
|
|
135139
134643
|
const cm2 = selectorRef.current.select({ prompt: "", kind: "summarize" }).model;
|
|
135140
134644
|
const budget = Math.max(8000, cm2.contextWindow - 32000);
|
|
@@ -135512,13 +135016,26 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
135512
135016
|
}
|
|
135513
135017
|
})();
|
|
135514
135018
|
if (!m2) {
|
|
135515
|
-
notice(
|
|
135019
|
+
notice(`no model available — add a provider first
|
|
135020
|
+
|
|
135021
|
+
` + onboardingSummary(onboardingState));
|
|
135516
135022
|
return;
|
|
135517
135023
|
}
|
|
135518
135024
|
const { sections } = buildContext({ history: msgRef.current, userText: lastPromptRef.current || "(your next message)", model: m2, plan: modeRef.current === "plan" });
|
|
135519
135025
|
push({ kind: "context", id: idRef.current++, view: buildContextView(sections, m2.contextWindow, process.cwd()) });
|
|
135520
135026
|
return;
|
|
135521
135027
|
}
|
|
135028
|
+
case "onboard": {
|
|
135029
|
+
echo(text2);
|
|
135030
|
+
if (arg.trim().toLowerCase() === "providers") {
|
|
135031
|
+
const rows2 = featuredApiKeyProviders().map((p) => ` ${p.id.padEnd(18)} ${p.label.padEnd(24)} ${p.envVars[0] ?? ""}`.trimEnd());
|
|
135032
|
+
notice(["providers you can add with /account add <provider> <api-key>", ...rows2, "", "Aliases work for common names, e.g. gemini -> google, grok -> xai, kimi -> moonshot."].join(`
|
|
135033
|
+
`));
|
|
135034
|
+
} else {
|
|
135035
|
+
notice(onboardingSummary(onboardingState));
|
|
135036
|
+
}
|
|
135037
|
+
return;
|
|
135038
|
+
}
|
|
135522
135039
|
case "accounts":
|
|
135523
135040
|
case "account": {
|
|
135524
135041
|
echo(text2);
|
|
@@ -135786,10 +135303,6 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
135786
135303
|
notice("busy — try /compact once the current turn finishes");
|
|
135787
135304
|
return;
|
|
135788
135305
|
}
|
|
135789
|
-
if (demo) {
|
|
135790
|
-
notice("compaction needs a model (no key in demo)");
|
|
135791
|
-
return;
|
|
135792
|
-
}
|
|
135793
135306
|
setBusy(true);
|
|
135794
135307
|
setVerb("Compacting context");
|
|
135795
135308
|
setMascotState("thinking");
|
|
@@ -135827,7 +135340,7 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
135827
135340
|
notice(`/${name31} hit an error: ${(e2?.message ?? String(e2)).split(`
|
|
135828
135341
|
`)[0]}`);
|
|
135829
135342
|
}
|
|
135830
|
-
}, [exit, runTurn]);
|
|
135343
|
+
}, [exit, runTurn, onboardingState]);
|
|
135831
135344
|
const submit = import_react26.useCallback((value) => {
|
|
135832
135345
|
let text2 = value.trim();
|
|
135833
135346
|
if (pasteStoreRef.current.size) {
|
|
@@ -135881,6 +135394,13 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
135881
135394
|
handleCommand(text2);
|
|
135882
135395
|
return;
|
|
135883
135396
|
}
|
|
135397
|
+
if (setupRequired) {
|
|
135398
|
+
echo(text2);
|
|
135399
|
+
notice(`set up a provider before sending a task
|
|
135400
|
+
|
|
135401
|
+
` + onboardingSummary(onboardingState));
|
|
135402
|
+
return;
|
|
135403
|
+
}
|
|
135884
135404
|
if (busyRef.current) {
|
|
135885
135405
|
queueRef.current.push(text2);
|
|
135886
135406
|
setQueued([...queueRef.current]);
|
|
@@ -135888,7 +135408,7 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
135888
135408
|
return;
|
|
135889
135409
|
}
|
|
135890
135410
|
runTurn(text2);
|
|
135891
|
-
}, [handleCommand, runTurn]);
|
|
135411
|
+
}, [handleCommand, runTurn, setupRequired, onboardingState]);
|
|
135892
135412
|
import_react26.useEffect(() => {
|
|
135893
135413
|
if (busy || queueRef.current.length === 0)
|
|
135894
135414
|
return;
|
|
@@ -136212,78 +135732,169 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
136212
135732
|
skin: ghostSkin,
|
|
136213
135733
|
size: splashSize
|
|
136214
135734
|
}, undefined, false, undefined, this),
|
|
136215
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
135735
|
+
setupRequired ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
136216
135736
|
marginTop: 1,
|
|
135737
|
+
flexDirection: "column",
|
|
135738
|
+
alignItems: "center",
|
|
136217
135739
|
children: [
|
|
136218
135740
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136219
|
-
color: color.
|
|
136220
|
-
children: "
|
|
135741
|
+
color: color.text,
|
|
135742
|
+
children: "setup required"
|
|
136221
135743
|
}, undefined, false, undefined, this),
|
|
135744
|
+
onboardingState.importable.length || onboardingState.cloudImportable.length ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135745
|
+
color: color.faint,
|
|
135746
|
+
children: [
|
|
135747
|
+
"detected credentials: ",
|
|
135748
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135749
|
+
color: color.accent,
|
|
135750
|
+
children: "/account import"
|
|
135751
|
+
}, undefined, false, undefined, this)
|
|
135752
|
+
]
|
|
135753
|
+
}, undefined, true, undefined, this) : null,
|
|
136222
135754
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136223
135755
|
color: color.faint,
|
|
136224
135756
|
children: [
|
|
136225
|
-
|
|
136226
|
-
|
|
135757
|
+
"add any provider key: ",
|
|
135758
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135759
|
+
color: color.accent,
|
|
135760
|
+
children: "/account add <provider> <api-key>"
|
|
135761
|
+
}, undefined, false, undefined, this)
|
|
136227
135762
|
]
|
|
136228
135763
|
}, undefined, true, undefined, this),
|
|
136229
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136230
|
-
color: color.accentDim,
|
|
136231
|
-
children: "/"
|
|
136232
|
-
}, undefined, false, undefined, this),
|
|
136233
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136234
|
-
color: color.dim,
|
|
136235
|
-
children: "commands "
|
|
136236
|
-
}, undefined, false, undefined, this),
|
|
136237
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136238
|
-
color: color.accentDim,
|
|
136239
|
-
children: "@"
|
|
136240
|
-
}, undefined, false, undefined, this),
|
|
136241
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136242
|
-
color: color.dim,
|
|
136243
|
-
children: "files "
|
|
136244
|
-
}, undefined, false, undefined, this),
|
|
136245
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136246
|
-
color: color.accentDim,
|
|
136247
|
-
children: "!"
|
|
136248
|
-
}, undefined, false, undefined, this),
|
|
136249
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136250
|
-
color: color.dim,
|
|
136251
|
-
children: "shell"
|
|
136252
|
-
}, undefined, false, undefined, this)
|
|
136253
|
-
]
|
|
136254
|
-
}, undefined, true, undefined, this),
|
|
136255
|
-
firstRunRef.current ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
136256
|
-
marginTop: 1,
|
|
136257
|
-
flexDirection: "column",
|
|
136258
|
-
alignItems: "center",
|
|
136259
|
-
children: [
|
|
136260
135764
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136261
135765
|
color: color.faint,
|
|
136262
135766
|
children: [
|
|
136263
|
-
"
|
|
135767
|
+
"paste-detect: ",
|
|
136264
135768
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136265
135769
|
color: color.accent,
|
|
136266
|
-
children: "
|
|
135770
|
+
children: "/account add <api-key>"
|
|
136267
135771
|
}, undefined, false, undefined, this),
|
|
136268
|
-
"
|
|
135772
|
+
" · list: ",
|
|
136269
135773
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136270
135774
|
color: color.accent,
|
|
136271
|
-
children: "
|
|
135775
|
+
children: "/onboard providers"
|
|
135776
|
+
}, undefined, false, undefined, this)
|
|
135777
|
+
]
|
|
135778
|
+
}, undefined, true, undefined, this),
|
|
135779
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
135780
|
+
marginTop: 1,
|
|
135781
|
+
flexDirection: "column",
|
|
135782
|
+
alignItems: "flex-start",
|
|
135783
|
+
children: [
|
|
135784
|
+
featuredApiKeyProviders().slice(0, 6).map((p) => /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135785
|
+
color: color.dim,
|
|
135786
|
+
children: [
|
|
135787
|
+
" ",
|
|
135788
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135789
|
+
color: color.accent,
|
|
135790
|
+
children: [
|
|
135791
|
+
"/account add ",
|
|
135792
|
+
p.id,
|
|
135793
|
+
" <api-key>"
|
|
135794
|
+
]
|
|
135795
|
+
}, undefined, true, undefined, this),
|
|
135796
|
+
" ",
|
|
135797
|
+
p.label
|
|
135798
|
+
]
|
|
135799
|
+
}, p.id, true, undefined, this)),
|
|
135800
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135801
|
+
color: color.dim,
|
|
135802
|
+
children: [
|
|
135803
|
+
" ",
|
|
135804
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135805
|
+
color: color.accent,
|
|
135806
|
+
children: "/account add azure <endpoint> <api-key>"
|
|
135807
|
+
}, undefined, false, undefined, this),
|
|
135808
|
+
" Azure OpenAI / Foundry"
|
|
135809
|
+
]
|
|
135810
|
+
}, undefined, true, undefined, this)
|
|
135811
|
+
]
|
|
135812
|
+
}, undefined, true, undefined, this),
|
|
135813
|
+
onboardingState.hasClaudeCli || onboardingState.hasCodexCli ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135814
|
+
color: color.faint,
|
|
135815
|
+
children: [
|
|
135816
|
+
onboardingState.hasClaudeCli ? "/account add claude" : "",
|
|
135817
|
+
onboardingState.hasClaudeCli && onboardingState.hasCodexCli ? " · " : "",
|
|
135818
|
+
onboardingState.hasCodexCli ? "/account add codex" : ""
|
|
135819
|
+
]
|
|
135820
|
+
}, undefined, true, undefined, this) : null
|
|
135821
|
+
]
|
|
135822
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(jsx_dev_runtime12.Fragment, {
|
|
135823
|
+
children: [
|
|
135824
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
135825
|
+
marginTop: 1,
|
|
135826
|
+
children: [
|
|
135827
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135828
|
+
color: color.dim,
|
|
135829
|
+
children: "talk or type "
|
|
136272
135830
|
}, undefined, false, undefined, this),
|
|
136273
|
-
" cycles modes · ",
|
|
136274
135831
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
136275
|
-
color: color.
|
|
136276
|
-
children:
|
|
135832
|
+
color: color.faint,
|
|
135833
|
+
children: [
|
|
135834
|
+
glyph.bullet,
|
|
135835
|
+
" "
|
|
135836
|
+
]
|
|
135837
|
+
}, undefined, true, undefined, this),
|
|
135838
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135839
|
+
color: color.accentDim,
|
|
135840
|
+
children: "/"
|
|
136277
135841
|
}, undefined, false, undefined, this),
|
|
136278
|
-
|
|
135842
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135843
|
+
color: color.dim,
|
|
135844
|
+
children: "commands "
|
|
135845
|
+
}, undefined, false, undefined, this),
|
|
135846
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135847
|
+
color: color.accentDim,
|
|
135848
|
+
children: "@"
|
|
135849
|
+
}, undefined, false, undefined, this),
|
|
135850
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135851
|
+
color: color.dim,
|
|
135852
|
+
children: "files "
|
|
135853
|
+
}, undefined, false, undefined, this),
|
|
135854
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135855
|
+
color: color.accentDim,
|
|
135856
|
+
children: "!"
|
|
135857
|
+
}, undefined, false, undefined, this),
|
|
135858
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135859
|
+
color: color.dim,
|
|
135860
|
+
children: "shell"
|
|
135861
|
+
}, undefined, false, undefined, this)
|
|
136279
135862
|
]
|
|
136280
135863
|
}, undefined, true, undefined, this),
|
|
136281
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(
|
|
136282
|
-
|
|
136283
|
-
|
|
136284
|
-
|
|
135864
|
+
firstRunRef.current ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
135865
|
+
marginTop: 1,
|
|
135866
|
+
flexDirection: "column",
|
|
135867
|
+
alignItems: "center",
|
|
135868
|
+
children: [
|
|
135869
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135870
|
+
color: color.faint,
|
|
135871
|
+
children: [
|
|
135872
|
+
"new here? press ",
|
|
135873
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135874
|
+
color: color.accent,
|
|
135875
|
+
children: "?"
|
|
135876
|
+
}, undefined, false, undefined, this),
|
|
135877
|
+
" for shortcuts · ",
|
|
135878
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135879
|
+
color: color.accent,
|
|
135880
|
+
children: "shift+tab"
|
|
135881
|
+
}, undefined, false, undefined, this),
|
|
135882
|
+
" cycles modes · ",
|
|
135883
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135884
|
+
color: color.accent,
|
|
135885
|
+
children: "⌃Y"
|
|
135886
|
+
}, undefined, false, undefined, this),
|
|
135887
|
+
" copies the last reply"
|
|
135888
|
+
]
|
|
135889
|
+
}, undefined, true, undefined, this),
|
|
135890
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
135891
|
+
color: color.faint,
|
|
135892
|
+
children: "/config inline on for terminal scrollback · /keys for shortcuts"
|
|
135893
|
+
}, undefined, false, undefined, this)
|
|
135894
|
+
]
|
|
135895
|
+
}, undefined, true, undefined, this) : null
|
|
136285
135896
|
]
|
|
136286
|
-
}, undefined, true, undefined, this)
|
|
135897
|
+
}, undefined, true, undefined, this)
|
|
136287
135898
|
]
|
|
136288
135899
|
}, undefined, true, undefined, this);
|
|
136289
135900
|
const paletteJsx = pickerRows.length || cmdMatches.length || fileMatches.length ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
@@ -136311,7 +135922,7 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
136311
135922
|
value: edit2.value,
|
|
136312
135923
|
cursor: edit2.cursor,
|
|
136313
135924
|
selectionAnchor: edit2.selectionAnchor,
|
|
136314
|
-
placeholder: mode2 === "plan" ? "describe what to plan…" : "ask anything",
|
|
135925
|
+
placeholder: setupRequired ? "add a provider with /account add <provider> <api-key>" : mode2 === "plan" ? "describe what to plan…" : "ask anything",
|
|
136315
135926
|
suggestion,
|
|
136316
135927
|
busy,
|
|
136317
135928
|
width,
|
|
@@ -136484,304 +136095,33 @@ function App2({ selector: initialSelector, demo, runner, fullscreen = false, res
|
|
|
136484
136095
|
}, undefined, true, undefined, this);
|
|
136485
136096
|
}
|
|
136486
136097
|
|
|
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
136098
|
// src/cli.tsx
|
|
136761
|
-
var jsx_dev_runtime13 = __toESM(
|
|
136099
|
+
var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
|
|
136100
|
+
process.env.LANG = process.env.LANG || "en_US.UTF-8";
|
|
136101
|
+
process.env.LC_ALL = process.env.LC_ALL || "en_US.UTF-8";
|
|
136762
136102
|
var VERSION16 = "0.1.0";
|
|
136763
136103
|
var args = process.argv.slice(2);
|
|
136764
136104
|
if (args[0] === "upgrade" || args[0] === "update") {
|
|
136765
|
-
const
|
|
136766
|
-
if (!
|
|
136105
|
+
const root2 = resolve11(import.meta.dir, "..");
|
|
136106
|
+
if (!existsSync8(resolve11(root2, ".git"))) {
|
|
136767
136107
|
console.log("This build can't self-update (not a git checkout).");
|
|
136768
136108
|
console.log("Update by pulling the repo and reinstalling: git pull && bun install");
|
|
136769
136109
|
process.exit(0);
|
|
136770
136110
|
}
|
|
136771
136111
|
try {
|
|
136772
|
-
console.log("
|
|
136773
|
-
console.log(execFileSync4("git", ["-C",
|
|
136774
|
-
console.log("
|
|
136775
|
-
execFileSync4("bun", ["install"], { cwd:
|
|
136776
|
-
console.log("
|
|
136112
|
+
console.log("→ Pulling latest…");
|
|
136113
|
+
console.log(execFileSync4("git", ["-C", root2, "pull", "--ff-only"], { encoding: "utf8" }).trim());
|
|
136114
|
+
console.log("→ Installing dependencies…");
|
|
136115
|
+
execFileSync4("bun", ["install"], { cwd: root2, stdio: "inherit" });
|
|
136116
|
+
console.log("✓ Gearbox is up to date. Restart any running session to use the new version.");
|
|
136777
136117
|
} catch (e2) {
|
|
136778
136118
|
console.log("Upgrade failed: " + (e2?.message ?? String(e2)));
|
|
136779
|
-
console.log(`Try manually: cd ${
|
|
136119
|
+
console.log(`Try manually: cd ${root2} && git pull && bun install`);
|
|
136780
136120
|
}
|
|
136781
136121
|
process.exit(0);
|
|
136782
136122
|
}
|
|
136783
136123
|
if (args.includes("--help") || args.includes("-h")) {
|
|
136784
|
-
console.log(`gearbox ${VERSION16}
|
|
136124
|
+
console.log(`gearbox ${VERSION16} — multi-provider coding agent for the terminal
|
|
136785
136125
|
|
|
136786
136126
|
Usage:
|
|
136787
136127
|
gearbox start in the current directory (it becomes the workspace)
|
|
@@ -136798,10 +136138,12 @@ Options:
|
|
|
136798
136138
|
-v, --version print version
|
|
136799
136139
|
-h, --help this help
|
|
136800
136140
|
|
|
136801
|
-
Set at least one provider
|
|
136802
|
-
|
|
136141
|
+
Set up at least one provider first:
|
|
136142
|
+
gearbox auth add <api-key>
|
|
136143
|
+
gearbox auth add <provider> <api-key>
|
|
136144
|
+
gearbox auth import
|
|
136803
136145
|
|
|
136804
|
-
Models: ${
|
|
136146
|
+
Models: ${MODELS.map((m2) => m2.label).join(", ")}
|
|
136805
136147
|
In-app: / for commands, @ for files, !cmd for shell, shift+tab for plan mode.`);
|
|
136806
136148
|
process.exit(0);
|
|
136807
136149
|
}
|
|
@@ -136810,43 +136152,43 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
136810
136152
|
process.exit(0);
|
|
136811
136153
|
}
|
|
136812
136154
|
if (args[0] === "auth") {
|
|
136813
|
-
const { listAccounts:
|
|
136814
|
-
const { importableEnvCreds:
|
|
136815
|
-
const { addApiKeyAccount:
|
|
136816
|
-
const { detectProviderByKey:
|
|
136155
|
+
const { listAccounts: listAccounts2, loadAccounts: loadAccounts3, removeAccount: removeAccount2 } = await Promise.resolve().then(() => (init_store(), exports_store));
|
|
136156
|
+
const { importableEnvCreds: importableEnvCreds2, importEnvCred: importEnvCred2, importableCloudCreds: importableCloudCreds2, importCloudCred: importCloudCred2 } = await Promise.resolve().then(() => (init_detect(), exports_detect));
|
|
136157
|
+
const { addApiKeyAccount: addApiKeyAccount2, addByPastedKey: addByPastedKey2, testAccount: testAccount2, addableProviders: addableProviders2 } = await Promise.resolve().then(() => (init_onboard(), exports_onboard));
|
|
136158
|
+
const { detectProviderByKey: detectProviderByKey2 } = await Promise.resolve().then(() => (init_catalog(), exports_catalog));
|
|
136817
136159
|
const sub = args[1];
|
|
136818
136160
|
const rest2 = args.slice(2);
|
|
136819
136161
|
if (sub === "list" || !sub) {
|
|
136820
|
-
const f3 =
|
|
136162
|
+
const f3 = loadAccounts3();
|
|
136821
136163
|
if (!f3.accounts.length)
|
|
136822
136164
|
console.log("No accounts yet. Add one: gearbox auth add <key> (or) gearbox auth import");
|
|
136823
136165
|
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 =
|
|
136166
|
+
console.log(`${f3.defaults[a.provider] === a.id ? "*" : " "} ${a.id.padEnd(22)} ${a.label}${a.exec === "cli" ? " · cli" : ""}`);
|
|
136167
|
+
const imp = importableEnvCreds2();
|
|
136826
136168
|
if (imp.length)
|
|
136827
136169
|
console.log(`
|
|
136828
136170
|
Importable from your env (gearbox auth import): ${imp.map((c) => c.envVar).join(", ")}`);
|
|
136829
136171
|
} else if (sub === "import") {
|
|
136830
|
-
const keys2 =
|
|
136831
|
-
const cloud =
|
|
136172
|
+
const keys2 = importableEnvCreds2();
|
|
136173
|
+
const cloud = importableCloudCreds2();
|
|
136832
136174
|
for (const c of keys2)
|
|
136833
|
-
await
|
|
136175
|
+
await importEnvCred2(c);
|
|
136834
136176
|
for (const c of cloud)
|
|
136835
|
-
await
|
|
136177
|
+
await importCloudCred2(c);
|
|
136836
136178
|
const names = [...keys2.map((c) => c.provider), ...cloud.map((c) => c.provider)];
|
|
136837
136179
|
console.log(names.length ? `Imported ${names.length}: ${names.join(", ")}` : "Nothing to import.");
|
|
136838
136180
|
} else if (sub === "add") {
|
|
136839
|
-
const res = rest2[0] && !rest2[1] &&
|
|
136181
|
+
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
136182
|
console.log(res.message);
|
|
136841
136183
|
if (res.ok && res.account) {
|
|
136842
|
-
const t2 = await
|
|
136843
|
-
console.log(t2.ok ? " test:
|
|
136184
|
+
const t2 = await testAccount2(res.account);
|
|
136185
|
+
console.log(t2.ok ? " test: ✓ " + t2.message : " test: ✗ " + t2.message + " (stored anyway)");
|
|
136844
136186
|
}
|
|
136845
136187
|
} else if (sub === "test" && rest2[0]) {
|
|
136846
|
-
const a =
|
|
136847
|
-
console.log(a ? `${rest2[0]}: ${(await
|
|
136188
|
+
const a = listAccounts2().find((x2) => x2.id === rest2[0]);
|
|
136189
|
+
console.log(a ? `${rest2[0]}: ${(await testAccount2(a)).message}` : `no account ${rest2[0]}`);
|
|
136848
136190
|
} else if (sub === "rm" && rest2[0]) {
|
|
136849
|
-
await
|
|
136191
|
+
await removeAccount2(rest2[0]);
|
|
136850
136192
|
console.log(`removed ${rest2[0]}`);
|
|
136851
136193
|
} else if (sub === "providers") {
|
|
136852
136194
|
for (const p of addableProviders2())
|
|
@@ -136858,17 +136200,16 @@ Importable from your env (gearbox auth import): ${imp.map((c) => c.envVar).join(
|
|
|
136858
136200
|
}
|
|
136859
136201
|
var mi = args.indexOf("--model");
|
|
136860
136202
|
var preferred = mi >= 0 ? args[mi + 1] : undefined;
|
|
136861
|
-
var
|
|
136862
|
-
var
|
|
136863
|
-
var selector = pinned ? new FixedSelector2(pinned) : new RoutingSelector2;
|
|
136203
|
+
var pinned = preferred ?? loadPrefs().pinnedModel;
|
|
136204
|
+
var selector = pinned ? new FixedSelector(pinned) : new RoutingSelector;
|
|
136864
136205
|
if (args.includes("--yolo"))
|
|
136865
|
-
|
|
136206
|
+
setYolo(true);
|
|
136866
136207
|
var resumeId = args.includes("--continue") || args.includes("-c") ? latestSession()?.id ?? undefined : undefined;
|
|
136867
|
-
var imageMode =
|
|
136208
|
+
var imageMode = detectImageMode();
|
|
136868
136209
|
setImageMode(imageMode);
|
|
136869
136210
|
if (process.stdout.isTTY && imageMode === "kitty")
|
|
136870
136211
|
process.stdout.write(transmitAll());
|
|
136871
|
-
var uiPrefs =
|
|
136212
|
+
var uiPrefs = loadPrefs();
|
|
136872
136213
|
var explicitInline = args.includes("--inline") || process.env.GEARBOX_INLINE === "1" || process.env.GEARBOX_FULLSCREEN === "0";
|
|
136873
136214
|
var explicitFullscreen = args.includes("--fullscreen") || process.env.GEARBOX_FULLSCREEN === "1";
|
|
136874
136215
|
var wantsInline = explicitInline || !explicitFullscreen && uiPrefs.fullscreen === false;
|
|
@@ -136892,7 +136233,6 @@ if (mouse)
|
|
|
136892
136233
|
process.stdout.write("\x1B[?1000h\x1B[?1002h\x1B[?1006h");
|
|
136893
136234
|
var app = render_default(/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(App2, {
|
|
136894
136235
|
selector,
|
|
136895
|
-
demo,
|
|
136896
136236
|
fullscreen,
|
|
136897
136237
|
resumeId
|
|
136898
136238
|
}, undefined, false, undefined, this), { exitOnCtrlC: false });
|