gearbox-code 0.1.15 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +773 -241
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -106134,7 +106134,7 @@ var init_catalog = __esm(() => {
|
|
|
106134
106134
|
{ 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"] },
|
|
106135
106135
|
{ 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"] },
|
|
106136
106136
|
{ 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"] },
|
|
106137
|
-
{ 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", "
|
|
106137
|
+
{ 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", "qwen-qwq-32b", "gemma2-9b-it"] },
|
|
106138
106138
|
{ 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"] },
|
|
106139
106139
|
{ 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"] },
|
|
106140
106140
|
{ 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" },
|
|
@@ -106153,9 +106153,9 @@ var init_catalog = __esm(() => {
|
|
|
106153
106153
|
{ 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." },
|
|
106154
106154
|
{ 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." },
|
|
106155
106155
|
{ 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." },
|
|
106156
|
-
{ 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"
|
|
106157
|
-
{ 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." },
|
|
106158
|
-
{ id: "azure", label: "Azure OpenAI", group: "cloud", exec: "in-loop", authKind: "azure", envVars: ["AZURE_API_KEY", "AZURE_RESOURCE_NAME"], signupUrl: "https://oai.azure.com",
|
|
106156
|
+
{ 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", "anthropic.claude-haiku-4-5-20251001-v1:0", "anthropic.claude-opus-4-20250514-v1:0", "amazon.nova-pro-v1:0", "amazon.nova-lite-v1:0", "amazon.nova-micro-v1:0", "meta.llama4-maverick-17b-instruct-v1:0", "meta.llama4-scout-17b-instruct-v1:0"], notes: "AWS IAM credentials or ~/.aws profile. Enable models in the Bedrock console first." },
|
|
106157
|
+
{ 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", "gemini-3.5-flash", "gemini-3.1-flash-lite"], notes: "ADC (gcloud auth application-default login) or a service-account JSON." },
|
|
106158
|
+
{ id: "azure", label: "Azure OpenAI", group: "cloud", exec: "in-loop", authKind: "azure", envVars: ["AZURE_API_KEY", "AZURE_RESOURCE_NAME"], signupUrl: "https://oai.azure.com", defaultModels: ["gpt-5.5", "gpt-5.5-mini", "gpt-4.1"], notes: "resourceName (e.g. my-resource) + API key. Model IDs are your deployment names." },
|
|
106159
106159
|
{ 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." },
|
|
106160
106160
|
{ id: "lmstudio", label: "LM Studio (local)", group: "local", exec: "in-loop", authKind: "openai-compat", envVars: [], baseUrl: "http://localhost:1234/v1", signupUrl: "https://lmstudio.ai" },
|
|
106161
106161
|
{ 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" },
|
|
@@ -106180,6 +106180,41 @@ function generatedModels() {
|
|
|
106180
106180
|
}
|
|
106181
106181
|
return out;
|
|
106182
106182
|
}
|
|
106183
|
+
function accountModelSpecs() {
|
|
106184
|
+
const out = [];
|
|
106185
|
+
for (const account of listAccounts()) {
|
|
106186
|
+
if (!account.enabled || account.exec === "cli")
|
|
106187
|
+
continue;
|
|
106188
|
+
for (const sdkId of account.models ?? []) {
|
|
106189
|
+
if (!sdkId)
|
|
106190
|
+
continue;
|
|
106191
|
+
if (MODELS.some((m2) => m2.provider === account.provider && m2.sdkId === sdkId))
|
|
106192
|
+
continue;
|
|
106193
|
+
const id = `${account.provider}/${sdkId}`;
|
|
106194
|
+
out.push({
|
|
106195
|
+
id,
|
|
106196
|
+
provider: account.provider,
|
|
106197
|
+
sdkId,
|
|
106198
|
+
label: sdkId.length > 24 ? sdkId.slice(0, 24) : sdkId,
|
|
106199
|
+
contextWindow: 128000,
|
|
106200
|
+
capabilities: { source: "user-configured", tools: "unknown", images: "unknown", jsonSchema: "unknown", usage: "partial" }
|
|
106201
|
+
});
|
|
106202
|
+
}
|
|
106203
|
+
}
|
|
106204
|
+
return out;
|
|
106205
|
+
}
|
|
106206
|
+
function modelRegistry() {
|
|
106207
|
+
const seen = new Set;
|
|
106208
|
+
const out = [];
|
|
106209
|
+
for (const m2 of [...MODELS, ...accountModelSpecs()]) {
|
|
106210
|
+
const key = `${m2.provider}\x00${m2.sdkId}`;
|
|
106211
|
+
if (seen.has(key))
|
|
106212
|
+
continue;
|
|
106213
|
+
seen.add(key);
|
|
106214
|
+
out.push(m2);
|
|
106215
|
+
}
|
|
106216
|
+
return out;
|
|
106217
|
+
}
|
|
106183
106218
|
function envVarFor(provider) {
|
|
106184
106219
|
return ENV_KEY[provider] ?? catalogProvider(provider)?.envVars[0];
|
|
106185
106220
|
}
|
|
@@ -106210,12 +106245,12 @@ function providerAvailable(p) {
|
|
|
106210
106245
|
return ev ? Boolean(process.env[ev]) : false;
|
|
106211
106246
|
}
|
|
106212
106247
|
function findModel(idOrLabel) {
|
|
106213
|
-
return
|
|
106248
|
+
return modelRegistry().find((m2) => m2.id === idOrLabel || m2.label === idOrLabel);
|
|
106214
106249
|
}
|
|
106215
106250
|
function estimateCost(turns) {
|
|
106216
106251
|
let usd2 = 0;
|
|
106217
106252
|
for (const t2 of turns) {
|
|
106218
|
-
const c =
|
|
106253
|
+
const c = modelRegistry().find((m2) => m2.id === t2.model)?.cost;
|
|
106219
106254
|
if (!c)
|
|
106220
106255
|
continue;
|
|
106221
106256
|
usd2 += t2.inputTokens / 1e6 * c.inUSDPerMtok + t2.outputTokens / 1e6 * c.outUSDPerMtok;
|
|
@@ -106281,14 +106316,25 @@ var init_providers = __esm(() => {
|
|
|
106281
106316
|
NATIVE = new Set(["anthropic", "openai", "google", "deepseek"]);
|
|
106282
106317
|
CURATED = [
|
|
106283
106318
|
{ 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"] },
|
|
106284
|
-
{ 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", "
|
|
106319
|
+
{ 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", "max"] },
|
|
106285
106320
|
{ id: "claude-haiku-4-5", provider: "anthropic", sdkId: "claude-haiku-4-5", label: "haiku-4.5", contextWindow: 200000, cost: { inUSDPerMtok: 1, outUSDPerMtok: 5 } },
|
|
106286
106321
|
{ 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"] },
|
|
106287
106322
|
{ 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"] },
|
|
106288
106323
|
{ 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"] },
|
|
106289
106324
|
{ 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"] },
|
|
106290
|
-
{ id: "deepseek-v4-pro", provider: "deepseek", sdkId: "deepseek-v4-pro", label: "deepseek-v4-pro", contextWindow: 128000, cost: { inUSDPerMtok: 0.4, outUSDPerMtok: 1.75 }
|
|
106291
|
-
{ id: "deepseek-v4-flash", provider: "deepseek", sdkId: "deepseek-v4-flash", label: "deepseek-v4-flash", contextWindow: 128000, cost: { inUSDPerMtok: 0.27, outUSDPerMtok: 1.1 } }
|
|
106325
|
+
{ id: "deepseek-v4-pro", provider: "deepseek", sdkId: "deepseek-v4-pro", label: "deepseek-v4-pro", contextWindow: 128000, cost: { inUSDPerMtok: 0.4, outUSDPerMtok: 1.75 } },
|
|
106326
|
+
{ id: "deepseek-v4-flash", provider: "deepseek", sdkId: "deepseek-v4-flash", label: "deepseek-v4-flash", contextWindow: 128000, cost: { inUSDPerMtok: 0.27, outUSDPerMtok: 1.1 } },
|
|
106327
|
+
{ id: "bedrock/anthropic.claude-sonnet-4-20250514-v1:0", provider: "bedrock", sdkId: "anthropic.claude-sonnet-4-20250514-v1:0", label: "bedrock/sonnet-4", contextWindow: 200000, cost: { inUSDPerMtok: 3.3, outUSDPerMtok: 16.5 }, reasoning: true, efforts: ["low", "medium", "high", "max"] },
|
|
106328
|
+
{ id: "bedrock/anthropic.claude-haiku-4-5-20251001-v1:0", provider: "bedrock", sdkId: "anthropic.claude-haiku-4-5-20251001-v1:0", label: "bedrock/haiku-4.5", contextWindow: 200000, cost: { inUSDPerMtok: 1.1, outUSDPerMtok: 5.5 }, reasoning: true, efforts: ["low", "medium", "high", "max"] },
|
|
106329
|
+
{ id: "bedrock/anthropic.claude-opus-4-20250514-v1:0", provider: "bedrock", sdkId: "anthropic.claude-opus-4-20250514-v1:0", label: "bedrock/opus-4", contextWindow: 200000, cost: { inUSDPerMtok: 5.5, outUSDPerMtok: 27.5 }, reasoning: true, efforts: ["low", "medium", "high", "max"] },
|
|
106330
|
+
{ id: "bedrock/amazon.nova-pro-v1:0", provider: "bedrock", sdkId: "amazon.nova-pro-v1:0", label: "bedrock/nova-pro", contextWindow: 300000, cost: { inUSDPerMtok: 0.8, outUSDPerMtok: 3.2 } },
|
|
106331
|
+
{ id: "bedrock/amazon.nova-lite-v1:0", provider: "bedrock", sdkId: "amazon.nova-lite-v1:0", label: "bedrock/nova-lite", contextWindow: 300000, cost: { inUSDPerMtok: 0.06, outUSDPerMtok: 0.24 } },
|
|
106332
|
+
{ id: "bedrock/amazon.nova-micro-v1:0", provider: "bedrock", sdkId: "amazon.nova-micro-v1:0", label: "bedrock/nova-micro", contextWindow: 128000, cost: { inUSDPerMtok: 0.035, outUSDPerMtok: 0.14 } },
|
|
106333
|
+
{ id: "bedrock/meta.llama4-maverick-17b-instruct-v1:0", provider: "bedrock", sdkId: "meta.llama4-maverick-17b-instruct-v1:0", label: "bedrock/llama-4-mav", contextWindow: 128000, cost: { inUSDPerMtok: 0.24, outUSDPerMtok: 0.97 } },
|
|
106334
|
+
{ id: "bedrock/meta.llama4-scout-17b-instruct-v1:0", provider: "bedrock", sdkId: "meta.llama4-scout-17b-instruct-v1:0", label: "bedrock/llama-4-scout", contextWindow: 128000, cost: { inUSDPerMtok: 0.17, outUSDPerMtok: 0.66 } },
|
|
106335
|
+
{ id: "vertex/gemini-3.1-pro-preview", provider: "vertex", sdkId: "gemini-3.1-pro-preview", label: "vertex/gemini-3.1-pro", contextWindow: 1e6, cost: { inUSDPerMtok: 2, outUSDPerMtok: 12 }, reasoning: true, efforts: ["minimal", "low", "medium", "high"] },
|
|
106336
|
+
{ id: "vertex/gemini-3.5-flash", provider: "vertex", sdkId: "gemini-3.5-flash", label: "vertex/gemini-3.5-flash", contextWindow: 1e6, cost: { inUSDPerMtok: 0.3, outUSDPerMtok: 2.5 }, reasoning: true, efforts: ["minimal", "low", "medium", "high"] },
|
|
106337
|
+
{ id: "vertex/gemini-3.1-flash-lite", provider: "vertex", sdkId: "gemini-3.1-flash-lite", label: "vertex/gemini-3.1-flash-lite", contextWindow: 1e6, cost: { inUSDPerMtok: 0.1, outUSDPerMtok: 0.4 } }
|
|
106292
106338
|
];
|
|
106293
106339
|
MODELS = [...CURATED, ...generatedModels()];
|
|
106294
106340
|
ENV_KEY = {
|
|
@@ -106336,12 +106382,13 @@ var init_permission = __esm(() => {
|
|
|
106336
106382
|
function profileFor(id) {
|
|
106337
106383
|
return BY_ID2.get(id);
|
|
106338
106384
|
}
|
|
106339
|
-
var CLAUDE_TOK, TIKTOKEN, GEMINI_TOK, DEEPSEEK_TOK, PROFILES, BY_ID2;
|
|
106385
|
+
var CLAUDE_TOK, TIKTOKEN, GEMINI_TOK, DEEPSEEK_TOK, LLAMA_TOK, PROFILES, BY_ID2;
|
|
106340
106386
|
var init_profiles = __esm(() => {
|
|
106341
106387
|
CLAUDE_TOK = { family: "claude", calibration: 1.35, calibrationSrc: "measured" };
|
|
106342
106388
|
TIKTOKEN = { family: "tiktoken-o200k", calibration: 1, calibrationSrc: "measured" };
|
|
106343
106389
|
GEMINI_TOK = { family: "gemini", calibration: 1.1, calibrationSrc: "seeded" };
|
|
106344
106390
|
DEEPSEEK_TOK = { family: "deepseek", calibration: 1.05, calibrationSrc: "seeded" };
|
|
106391
|
+
LLAMA_TOK = { family: "llama", calibration: 1.1, calibrationSrc: "seeded" };
|
|
106345
106392
|
PROFILES = [
|
|
106346
106393
|
{
|
|
106347
106394
|
id: "claude-opus-4-8",
|
|
@@ -106433,12 +106480,171 @@ var init_profiles = __esm(() => {
|
|
|
106433
106480
|
strengths: ["far cheaper than frontier", "strong coding for the price", "reasoning"],
|
|
106434
106481
|
weaknesses: ["smaller context", "slower hosted latency"],
|
|
106435
106482
|
asOf: "2026-06"
|
|
106483
|
+
},
|
|
106484
|
+
{
|
|
106485
|
+
id: "bedrock/anthropic.claude-sonnet-4-20250514-v1:0",
|
|
106486
|
+
provider: "bedrock",
|
|
106487
|
+
contextWindow: 200000,
|
|
106488
|
+
maxOutput: 64000,
|
|
106489
|
+
tokenizer: CLAUDE_TOK,
|
|
106490
|
+
cost: { inUSDPerMtok: 3.3, outUSDPerMtok: 16.5, src: "seeded" },
|
|
106491
|
+
latency: { ttftMs: 1900, tps: 90, src: "seeded" },
|
|
106492
|
+
quality: { sweBenchVerified: 0.77, intelligenceIndex: 50, src: "seeded" },
|
|
106493
|
+
strengths: ["agentic coding", "tool use", "instruction-following", "AWS-native deployment", "extended thinking"],
|
|
106494
|
+
weaknesses: ["10% pricier than Anthropic direct", "Bedrock model enablement required"],
|
|
106495
|
+
asOf: "2026-06"
|
|
106496
|
+
},
|
|
106497
|
+
{
|
|
106498
|
+
id: "bedrock/anthropic.claude-haiku-4-5-20251001-v1:0",
|
|
106499
|
+
provider: "bedrock",
|
|
106500
|
+
contextWindow: 200000,
|
|
106501
|
+
maxOutput: 32000,
|
|
106502
|
+
tokenizer: CLAUDE_TOK,
|
|
106503
|
+
cost: { inUSDPerMtok: 1.1, outUSDPerMtok: 5.5, src: "seeded" },
|
|
106504
|
+
latency: { ttftMs: 1400, tps: 170, src: "seeded" },
|
|
106505
|
+
quality: { intelligenceIndex: 38, src: "seeded" },
|
|
106506
|
+
strengths: ["fast", "cheap", "AWS-native", "good for bounded sub-tasks"],
|
|
106507
|
+
weaknesses: ["weaker on hard reasoning", "10% premium over Anthropic direct"],
|
|
106508
|
+
asOf: "2026-06"
|
|
106509
|
+
},
|
|
106510
|
+
{
|
|
106511
|
+
id: "bedrock/anthropic.claude-opus-4-20250514-v1:0",
|
|
106512
|
+
provider: "bedrock",
|
|
106513
|
+
contextWindow: 200000,
|
|
106514
|
+
maxOutput: 128000,
|
|
106515
|
+
tokenizer: CLAUDE_TOK,
|
|
106516
|
+
cost: { inUSDPerMtok: 5.5, outUSDPerMtok: 27.5, src: "seeded" },
|
|
106517
|
+
latency: { ttftMs: 2500, tps: 65, src: "seeded" },
|
|
106518
|
+
quality: { sweBenchVerified: 0.83, intelligenceIndex: 64, src: "seeded" },
|
|
106519
|
+
strengths: ["most capable", "long-horizon agentic work", "AWS-native deployment", "extended thinking"],
|
|
106520
|
+
weaknesses: ["most expensive", "slower", "10% premium over Anthropic direct"],
|
|
106521
|
+
asOf: "2026-06"
|
|
106522
|
+
},
|
|
106523
|
+
{
|
|
106524
|
+
id: "bedrock/amazon.nova-pro-v1:0",
|
|
106525
|
+
provider: "bedrock",
|
|
106526
|
+
contextWindow: 300000,
|
|
106527
|
+
maxOutput: 5000,
|
|
106528
|
+
tokenizer: TIKTOKEN,
|
|
106529
|
+
cost: { inUSDPerMtok: 0.8, outUSDPerMtok: 3.2, src: "seeded" },
|
|
106530
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106531
|
+
quality: { intelligenceIndex: 42, src: "seeded" },
|
|
106532
|
+
strengths: ["native AWS model", "multimodal (text+image+video)", "large context", "reasonable price"],
|
|
106533
|
+
weaknesses: ["weaker than Claude on hard coding/reasoning"],
|
|
106534
|
+
asOf: "2026-06"
|
|
106535
|
+
},
|
|
106536
|
+
{
|
|
106537
|
+
id: "bedrock/amazon.nova-lite-v1:0",
|
|
106538
|
+
provider: "bedrock",
|
|
106539
|
+
contextWindow: 300000,
|
|
106540
|
+
maxOutput: 5000,
|
|
106541
|
+
tokenizer: TIKTOKEN,
|
|
106542
|
+
cost: { inUSDPerMtok: 0.06, outUSDPerMtok: 0.24, src: "seeded" },
|
|
106543
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106544
|
+
quality: { intelligenceIndex: 32, src: "seeded" },
|
|
106545
|
+
strengths: ["very cheap", "native AWS", "large context", "good for bulk tasks"],
|
|
106546
|
+
weaknesses: ["lower ceiling on complex tasks"],
|
|
106547
|
+
asOf: "2026-06"
|
|
106548
|
+
},
|
|
106549
|
+
{
|
|
106550
|
+
id: "bedrock/amazon.nova-micro-v1:0",
|
|
106551
|
+
provider: "bedrock",
|
|
106552
|
+
contextWindow: 128000,
|
|
106553
|
+
maxOutput: 5000,
|
|
106554
|
+
tokenizer: TIKTOKEN,
|
|
106555
|
+
cost: { inUSDPerMtok: 0.035, outUSDPerMtok: 0.14, src: "seeded" },
|
|
106556
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106557
|
+
quality: { intelligenceIndex: 25, src: "seeded" },
|
|
106558
|
+
strengths: ["cheapest AWS model", "text-only, fast", "classify/summarize"],
|
|
106559
|
+
weaknesses: ["no image input", "lower quality ceiling"],
|
|
106560
|
+
asOf: "2026-06"
|
|
106561
|
+
},
|
|
106562
|
+
{
|
|
106563
|
+
id: "bedrock/meta.llama4-maverick-17b-instruct-v1:0",
|
|
106564
|
+
provider: "bedrock",
|
|
106565
|
+
contextWindow: 128000,
|
|
106566
|
+
maxOutput: 8000,
|
|
106567
|
+
tokenizer: LLAMA_TOK,
|
|
106568
|
+
cost: { inUSDPerMtok: 0.24, outUSDPerMtok: 0.97, src: "seeded" },
|
|
106569
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106570
|
+
quality: { intelligenceIndex: 44, src: "seeded" },
|
|
106571
|
+
strengths: ["multimodal (text+image)", "competitive quality per dollar", "AWS-native"],
|
|
106572
|
+
weaknesses: ["smaller context than Nova", "OSS model quality ceiling"],
|
|
106573
|
+
asOf: "2026-06"
|
|
106574
|
+
},
|
|
106575
|
+
{
|
|
106576
|
+
id: "bedrock/meta.llama4-scout-17b-instruct-v1:0",
|
|
106577
|
+
provider: "bedrock",
|
|
106578
|
+
contextWindow: 128000,
|
|
106579
|
+
maxOutput: 8000,
|
|
106580
|
+
tokenizer: LLAMA_TOK,
|
|
106581
|
+
cost: { inUSDPerMtok: 0.17, outUSDPerMtok: 0.66, src: "seeded" },
|
|
106582
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106583
|
+
quality: { intelligenceIndex: 38, src: "seeded" },
|
|
106584
|
+
strengths: ["cheap", "fast", "multimodal", "AWS-native"],
|
|
106585
|
+
weaknesses: ["lower quality than Maverick", "OSS model quality ceiling"],
|
|
106586
|
+
asOf: "2026-06"
|
|
106587
|
+
},
|
|
106588
|
+
{
|
|
106589
|
+
id: "vertex/gemini-3.1-pro-preview",
|
|
106590
|
+
provider: "vertex",
|
|
106591
|
+
contextWindow: 1e6,
|
|
106592
|
+
maxOutput: 64000,
|
|
106593
|
+
tokenizer: GEMINI_TOK,
|
|
106594
|
+
cost: { inUSDPerMtok: 2, outUSDPerMtok: 12, src: "seeded" },
|
|
106595
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106596
|
+
quality: { sweBenchVerified: 0.76, intelligenceIndex: 60, src: "seeded" },
|
|
106597
|
+
strengths: ["1M context", "strong reasoning", "thinking config", "GCP-native deployment"],
|
|
106598
|
+
weaknesses: ["preview", "agentic tool-use behind Claude"],
|
|
106599
|
+
asOf: "2026-06"
|
|
106600
|
+
},
|
|
106601
|
+
{
|
|
106602
|
+
id: "vertex/gemini-3.5-flash",
|
|
106603
|
+
provider: "vertex",
|
|
106604
|
+
contextWindow: 1e6,
|
|
106605
|
+
maxOutput: 64000,
|
|
106606
|
+
tokenizer: GEMINI_TOK,
|
|
106607
|
+
cost: { inUSDPerMtok: 0.3, outUSDPerMtok: 2.5, src: "seeded" },
|
|
106608
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106609
|
+
quality: { intelligenceIndex: 48, src: "seeded" },
|
|
106610
|
+
strengths: ["very cheap", "fast", "1M context", "thinking config", "GCP-native"],
|
|
106611
|
+
weaknesses: ["lower ceiling on hard tasks"],
|
|
106612
|
+
asOf: "2026-06"
|
|
106613
|
+
},
|
|
106614
|
+
{
|
|
106615
|
+
id: "vertex/gemini-3.1-flash-lite",
|
|
106616
|
+
provider: "vertex",
|
|
106617
|
+
contextWindow: 1e6,
|
|
106618
|
+
maxOutput: 8000,
|
|
106619
|
+
tokenizer: GEMINI_TOK,
|
|
106620
|
+
cost: { inUSDPerMtok: 0.1, outUSDPerMtok: 0.4, src: "seeded" },
|
|
106621
|
+
latency: { ttftMs: 0, tps: 0, src: "seeded" },
|
|
106622
|
+
quality: { intelligenceIndex: 30, src: "seeded" },
|
|
106623
|
+
strengths: ["cheapest Vertex model", "1M context", "fast", "classify/summarize"],
|
|
106624
|
+
weaknesses: ["no thinking config", "lower quality ceiling"],
|
|
106625
|
+
asOf: "2026-06"
|
|
106436
106626
|
}
|
|
106437
106627
|
];
|
|
106438
106628
|
BY_ID2 = new Map(PROFILES.map((p) => [p.id, p]));
|
|
106439
106629
|
});
|
|
106440
106630
|
|
|
106441
106631
|
// src/model/reasoning.ts
|
|
106632
|
+
function clampEffort(current, allowed) {
|
|
106633
|
+
if (!allowed.length)
|
|
106634
|
+
return { level: "medium", clamped: current !== "medium" };
|
|
106635
|
+
if (allowed.includes(current))
|
|
106636
|
+
return { level: current, clamped: false };
|
|
106637
|
+
const idx = EFFORT_ORDER.indexOf(current);
|
|
106638
|
+
for (let d = 1;d <= EFFORT_ORDER.length; d++) {
|
|
106639
|
+
const hi = EFFORT_ORDER[idx + d];
|
|
106640
|
+
if (hi && allowed.includes(hi))
|
|
106641
|
+
return { level: hi, clamped: true };
|
|
106642
|
+
const lo = EFFORT_ORDER[idx - d];
|
|
106643
|
+
if (lo && allowed.includes(lo))
|
|
106644
|
+
return { level: lo, clamped: true };
|
|
106645
|
+
}
|
|
106646
|
+
return { level: allowed[allowed.length - 1], clamped: true };
|
|
106647
|
+
}
|
|
106442
106648
|
function effortLevels(spec6) {
|
|
106443
106649
|
if (spec6.efforts)
|
|
106444
106650
|
return spec6.efforts;
|
|
@@ -106446,6 +106652,8 @@ function effortLevels(spec6) {
|
|
|
106446
106652
|
return [];
|
|
106447
106653
|
if (spec6.provider === "openai")
|
|
106448
106654
|
return OPENAI_EFFORTS;
|
|
106655
|
+
if (spec6.provider === "azure" || spec6.provider === "azure-foundry")
|
|
106656
|
+
return OPENAI_EFFORTS;
|
|
106449
106657
|
if (spec6.provider === "anthropic")
|
|
106450
106658
|
return ANTHROPIC_EFFORTS;
|
|
106451
106659
|
if (spec6.provider === "google" || spec6.provider === "vertex")
|
|
@@ -106470,7 +106678,7 @@ function reasoningOptions(spec6, effort) {
|
|
|
106470
106678
|
if (!level)
|
|
106471
106679
|
return {};
|
|
106472
106680
|
const p = spec6.provider;
|
|
106473
|
-
if (p === "openai") {
|
|
106681
|
+
if (p === "openai" || p === "azure" || p === "azure-foundry") {
|
|
106474
106682
|
return { openai: { reasoningEffort: level } };
|
|
106475
106683
|
}
|
|
106476
106684
|
if (p === "google" || p === "vertex") {
|
|
@@ -106481,11 +106689,12 @@ function reasoningOptions(spec6, effort) {
|
|
|
106481
106689
|
}
|
|
106482
106690
|
return {};
|
|
106483
106691
|
}
|
|
106484
|
-
var OPENAI_EFFORTS, ANTHROPIC_EFFORTS, GOOGLE_EFFORTS;
|
|
106692
|
+
var OPENAI_EFFORTS, ANTHROPIC_EFFORTS, GOOGLE_EFFORTS, EFFORT_ORDER;
|
|
106485
106693
|
var init_reasoning = __esm(() => {
|
|
106486
106694
|
OPENAI_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh"];
|
|
106487
106695
|
ANTHROPIC_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
106488
106696
|
GOOGLE_EFFORTS = ["minimal", "low", "medium", "high"];
|
|
106697
|
+
EFFORT_ORDER = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
106489
106698
|
});
|
|
106490
106699
|
|
|
106491
106700
|
// src/model/capabilities.ts
|
|
@@ -106497,12 +106706,16 @@ __export(exports_capabilities, {
|
|
|
106497
106706
|
capabilitiesFor: () => capabilitiesFor
|
|
106498
106707
|
});
|
|
106499
106708
|
function providerSource(spec6) {
|
|
106709
|
+
if (spec6.capabilities?.source)
|
|
106710
|
+
return spec6.capabilities.source;
|
|
106500
106711
|
const group = catalogProvider(spec6.provider)?.group;
|
|
106501
106712
|
if (group === "gateway" || group === "openai-compat" || group === "local")
|
|
106502
106713
|
return "seeded";
|
|
106503
106714
|
return "seeded";
|
|
106504
106715
|
}
|
|
106505
106716
|
function exactUsage(spec6) {
|
|
106717
|
+
if (spec6.capabilities?.usage)
|
|
106718
|
+
return spec6.capabilities.usage;
|
|
106506
106719
|
if (spec6.provider === "anthropic" || spec6.provider === "openai" || spec6.provider === "google" || spec6.provider === "deepseek")
|
|
106507
106720
|
return "exact";
|
|
106508
106721
|
const group = catalogProvider(spec6.provider)?.group;
|
|
@@ -106511,25 +106724,41 @@ function exactUsage(spec6) {
|
|
|
106511
106724
|
return "none";
|
|
106512
106725
|
}
|
|
106513
106726
|
function toolSupport(spec6) {
|
|
106727
|
+
if (spec6.capabilities?.tools != null)
|
|
106728
|
+
return spec6.capabilities.tools;
|
|
106514
106729
|
const group = catalogProvider(spec6.provider)?.group;
|
|
106515
106730
|
if (spec6.provider === "anthropic" || spec6.provider === "openai" || spec6.provider === "google" || spec6.provider === "deepseek")
|
|
106516
106731
|
return true;
|
|
106517
|
-
if (spec6.provider === "bedrock"
|
|
106518
|
-
return "
|
|
106732
|
+
if (spec6.provider === "bedrock")
|
|
106733
|
+
return !spec6.sdkId.includes("nova-micro");
|
|
106734
|
+
if (spec6.provider === "vertex" || spec6.provider === "azure" || spec6.provider === "azure-foundry")
|
|
106735
|
+
return true;
|
|
106519
106736
|
if (group === "gateway" || group === "openai-compat" || group === "local")
|
|
106520
106737
|
return "unknown";
|
|
106521
106738
|
return "unknown";
|
|
106522
106739
|
}
|
|
106523
106740
|
function imageSupport(spec6) {
|
|
106741
|
+
if (spec6.capabilities?.images != null)
|
|
106742
|
+
return spec6.capabilities.images;
|
|
106524
106743
|
if (spec6.provider === "anthropic" || spec6.provider === "openai" || spec6.provider === "google" || spec6.provider === "vertex")
|
|
106525
106744
|
return true;
|
|
106526
106745
|
if (spec6.provider === "deepseek")
|
|
106527
106746
|
return false;
|
|
106747
|
+
if (spec6.provider === "bedrock")
|
|
106748
|
+
return !spec6.sdkId.includes("nova-micro");
|
|
106749
|
+
if (spec6.provider === "azure" || spec6.provider === "azure-foundry")
|
|
106750
|
+
return true;
|
|
106528
106751
|
return "unknown";
|
|
106529
106752
|
}
|
|
106530
106753
|
function schemaSupport(spec6) {
|
|
106754
|
+
if (spec6.capabilities?.jsonSchema != null)
|
|
106755
|
+
return spec6.capabilities.jsonSchema;
|
|
106531
106756
|
if (spec6.provider === "openai" || spec6.provider === "google" || spec6.provider === "anthropic")
|
|
106532
106757
|
return true;
|
|
106758
|
+
if (spec6.provider === "bedrock")
|
|
106759
|
+
return spec6.sdkId.startsWith("anthropic.") ? true : "unknown";
|
|
106760
|
+
if (spec6.provider === "vertex" || spec6.provider === "azure" || spec6.provider === "azure-foundry")
|
|
106761
|
+
return true;
|
|
106533
106762
|
if (spec6.provider === "deepseek")
|
|
106534
106763
|
return "unknown";
|
|
106535
106764
|
return "unknown";
|
|
@@ -106551,7 +106780,7 @@ function capabilitiesFor(spec6) {
|
|
|
106551
106780
|
images: imageSupport(spec6),
|
|
106552
106781
|
jsonSchema: schemaSupport(spec6),
|
|
106553
106782
|
reasoningEffort: efforts.length ? efforts : false,
|
|
106554
|
-
systemPrompt: true,
|
|
106783
|
+
systemPrompt: spec6.capabilities?.systemPrompt ?? true,
|
|
106555
106784
|
usage: exactUsage(spec6),
|
|
106556
106785
|
contextWindow: profile?.contextWindow ?? spec6.contextWindow,
|
|
106557
106786
|
maxOutputTokens: profile?.maxOutput,
|
|
@@ -106583,7 +106812,7 @@ function cell(v) {
|
|
|
106583
106812
|
return "?";
|
|
106584
106813
|
return String(v ?? "");
|
|
106585
106814
|
}
|
|
106586
|
-
function formatCapabilityMatrix(models =
|
|
106815
|
+
function formatCapabilityMatrix(models = modelRegistry()) {
|
|
106587
106816
|
const rows = models.map((m2) => {
|
|
106588
106817
|
const c = capabilitiesFor(m2);
|
|
106589
106818
|
return {
|
|
@@ -128749,12 +128978,19 @@ var init_stdio2 = __esm(() => {
|
|
|
128749
128978
|
// src/mcp.ts
|
|
128750
128979
|
var exports_mcp = {};
|
|
128751
128980
|
__export(exports_mcp, {
|
|
128981
|
+
shellSplit: () => shellSplit,
|
|
128982
|
+
removeMcpServer: () => removeMcpServer,
|
|
128983
|
+
reloadMcpConnections: () => reloadMcpConnections,
|
|
128752
128984
|
mcpTools: () => mcpTools,
|
|
128753
128985
|
mcpToolSummary: () => mcpToolSummary,
|
|
128754
|
-
mcpConfigPaths: () => mcpConfigPaths
|
|
128986
|
+
mcpConfigPaths: () => mcpConfigPaths,
|
|
128987
|
+
mcpConfigPath: () => mcpConfigPath,
|
|
128988
|
+
formatMcpConfigList: () => formatMcpConfigList,
|
|
128989
|
+
configuredMcpServers: () => configuredMcpServers,
|
|
128990
|
+
addMcpServer: () => addMcpServer
|
|
128755
128991
|
});
|
|
128756
|
-
import { existsSync as existsSync3, readFileSync as readFileSync7 } from "node:fs";
|
|
128757
|
-
import { join as join7 } from "node:path";
|
|
128992
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
|
|
128993
|
+
import { dirname as dirname3, join as join7 } from "node:path";
|
|
128758
128994
|
import { homedir as homedir6 } from "node:os";
|
|
128759
128995
|
function readConfigFile(path) {
|
|
128760
128996
|
if (!existsSync3(path))
|
|
@@ -128765,6 +129001,11 @@ function readConfigFile(path) {
|
|
|
128765
129001
|
return {};
|
|
128766
129002
|
}
|
|
128767
129003
|
}
|
|
129004
|
+
function writeConfigFile(path, config3) {
|
|
129005
|
+
mkdirSync6(dirname3(path), { recursive: true });
|
|
129006
|
+
writeFileSync6(path, JSON.stringify(config3, null, 2) + `
|
|
129007
|
+
`, { mode: 384 });
|
|
129008
|
+
}
|
|
128768
129009
|
function expandEnv(value) {
|
|
128769
129010
|
return value.replace(/\$\{([A-Z0-9_]+)\}/gi, (_, name31) => process.env[name31] ?? "");
|
|
128770
129011
|
}
|
|
@@ -128813,6 +129054,9 @@ async function connected() {
|
|
|
128813
129054
|
connectedPromise ??= connectAll();
|
|
128814
129055
|
return connectedPromise;
|
|
128815
129056
|
}
|
|
129057
|
+
function reloadMcpConnections() {
|
|
129058
|
+
connectedPromise = null;
|
|
129059
|
+
}
|
|
128816
129060
|
function formatMcpResult(result2) {
|
|
128817
129061
|
const content = result2?.content ?? [];
|
|
128818
129062
|
if (!Array.isArray(content) || !content.length)
|
|
@@ -128839,6 +129083,122 @@ async function mcpToolSummary() {
|
|
|
128839
129083
|
return rows.flatMap((s2) => s2.tools.map((t2) => `${safeToolName(s2.name, t2.name).padEnd(34)} ${t2.description ?? ""}`)).join(`
|
|
128840
129084
|
`);
|
|
128841
129085
|
}
|
|
129086
|
+
function mcpConfigPath(scope = "project", cwd2 = process.cwd()) {
|
|
129087
|
+
return scope === "global" ? join7(HOME(), "mcp.json") : join7(cwd2, ".gearbox", "mcp.json");
|
|
129088
|
+
}
|
|
129089
|
+
function configuredMcpServers(cwd2 = process.cwd()) {
|
|
129090
|
+
const paths = [
|
|
129091
|
+
{ scope: "global", path: join7(HOME(), "mcp.json") },
|
|
129092
|
+
{ scope: "compat", path: join7(cwd2, ".mcp.json") },
|
|
129093
|
+
{ scope: "project", path: join7(cwd2, ".gearbox", "mcp.json") }
|
|
129094
|
+
];
|
|
129095
|
+
const rows = [];
|
|
129096
|
+
for (const p of paths) {
|
|
129097
|
+
const file5 = readConfigFile(p.path);
|
|
129098
|
+
for (const [name31, config3] of Object.entries(file5.mcpServers ?? file5.servers ?? {})) {
|
|
129099
|
+
if (!config3?.command)
|
|
129100
|
+
continue;
|
|
129101
|
+
rows.push({ name: name31, scope: p.scope, config: config3 });
|
|
129102
|
+
}
|
|
129103
|
+
}
|
|
129104
|
+
return rows;
|
|
129105
|
+
}
|
|
129106
|
+
function formatMcpConfigList(cwd2 = process.cwd()) {
|
|
129107
|
+
const rows = configuredMcpServers(cwd2);
|
|
129108
|
+
if (!rows.length) {
|
|
129109
|
+
return [
|
|
129110
|
+
"MCP servers",
|
|
129111
|
+
" none configured",
|
|
129112
|
+
"",
|
|
129113
|
+
"Add one:",
|
|
129114
|
+
" /mcp add github npx -y @modelcontextprotocol/server-github",
|
|
129115
|
+
" /mcp add --global linear npx -y @modelcontextprotocol/server-linear"
|
|
129116
|
+
].join(`
|
|
129117
|
+
`);
|
|
129118
|
+
}
|
|
129119
|
+
return [
|
|
129120
|
+
"MCP servers",
|
|
129121
|
+
...rows.map((r2) => {
|
|
129122
|
+
const args = r2.config.args?.length ? " " + r2.config.args.join(" ") : "";
|
|
129123
|
+
const off = r2.config.disabled ? " · disabled" : "";
|
|
129124
|
+
return ` ${r2.name.padEnd(18)} ${r2.scope.padEnd(7)} ${r2.config.command}${args}${off}`;
|
|
129125
|
+
}),
|
|
129126
|
+
"",
|
|
129127
|
+
"Tools: /mcp tools",
|
|
129128
|
+
"Remove: /mcp remove <name>"
|
|
129129
|
+
].join(`
|
|
129130
|
+
`);
|
|
129131
|
+
}
|
|
129132
|
+
function shellSplit(input) {
|
|
129133
|
+
const out = [];
|
|
129134
|
+
let cur = "";
|
|
129135
|
+
let quote = null;
|
|
129136
|
+
let esc2 = false;
|
|
129137
|
+
for (const ch of input) {
|
|
129138
|
+
if (esc2) {
|
|
129139
|
+
cur += ch;
|
|
129140
|
+
esc2 = false;
|
|
129141
|
+
continue;
|
|
129142
|
+
}
|
|
129143
|
+
if (ch === "\\") {
|
|
129144
|
+
esc2 = true;
|
|
129145
|
+
continue;
|
|
129146
|
+
}
|
|
129147
|
+
if (quote) {
|
|
129148
|
+
if (ch === quote)
|
|
129149
|
+
quote = null;
|
|
129150
|
+
else
|
|
129151
|
+
cur += ch;
|
|
129152
|
+
continue;
|
|
129153
|
+
}
|
|
129154
|
+
if (ch === "'" || ch === '"') {
|
|
129155
|
+
quote = ch;
|
|
129156
|
+
continue;
|
|
129157
|
+
}
|
|
129158
|
+
if (/\s/.test(ch)) {
|
|
129159
|
+
if (cur) {
|
|
129160
|
+
out.push(cur);
|
|
129161
|
+
cur = "";
|
|
129162
|
+
}
|
|
129163
|
+
continue;
|
|
129164
|
+
}
|
|
129165
|
+
cur += ch;
|
|
129166
|
+
}
|
|
129167
|
+
if (cur)
|
|
129168
|
+
out.push(cur);
|
|
129169
|
+
return out;
|
|
129170
|
+
}
|
|
129171
|
+
function cleanServerName(name31) {
|
|
129172
|
+
return name31.trim().toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
129173
|
+
}
|
|
129174
|
+
function addMcpServer(name31, command, args = [], opts = {}) {
|
|
129175
|
+
const serverName = cleanServerName(name31);
|
|
129176
|
+
if (!serverName || !command)
|
|
129177
|
+
throw new Error("usage: /mcp add <name> <command> [args...]");
|
|
129178
|
+
const path = mcpConfigPath(opts.scope ?? "project", opts.cwd ?? process.cwd());
|
|
129179
|
+
const file5 = readConfigFile(path);
|
|
129180
|
+
const servers = { ...file5.mcpServers ?? file5.servers ?? {} };
|
|
129181
|
+
servers[serverName] = { command, args };
|
|
129182
|
+
writeConfigFile(path, { mcpServers: servers });
|
|
129183
|
+
reloadMcpConnections();
|
|
129184
|
+
return `connected ${serverName} (${opts.scope ?? "project"})`;
|
|
129185
|
+
}
|
|
129186
|
+
function removeMcpServer(name31, opts = {}) {
|
|
129187
|
+
const serverName = cleanServerName(name31);
|
|
129188
|
+
const scopes = opts.scope ? [opts.scope] : ["project", "global"];
|
|
129189
|
+
for (const scope of scopes) {
|
|
129190
|
+
const path = mcpConfigPath(scope, opts.cwd ?? process.cwd());
|
|
129191
|
+
const file5 = readConfigFile(path);
|
|
129192
|
+
const servers = { ...file5.mcpServers ?? file5.servers ?? {} };
|
|
129193
|
+
if (!(serverName in servers))
|
|
129194
|
+
continue;
|
|
129195
|
+
delete servers[serverName];
|
|
129196
|
+
writeConfigFile(path, { mcpServers: servers });
|
|
129197
|
+
reloadMcpConnections();
|
|
129198
|
+
return `removed ${serverName} (${scope})`;
|
|
129199
|
+
}
|
|
129200
|
+
return `no MCP server named ${serverName}`;
|
|
129201
|
+
}
|
|
128842
129202
|
async function mcpTools(onEvent, readOnly = false) {
|
|
128843
129203
|
const rows = await connected();
|
|
128844
129204
|
const out = {};
|
|
@@ -128993,9 +129353,10 @@ function awsIni(file5, profile = "default") {
|
|
|
128993
129353
|
}
|
|
128994
129354
|
function detectCloudCreds() {
|
|
128995
129355
|
const out = [];
|
|
129356
|
+
const awsProfile = process.env.AWS_PROFILE ?? "default";
|
|
128996
129357
|
const home5 = homedir8();
|
|
128997
|
-
const creds = awsIni(join10(home5, ".aws", "credentials"));
|
|
128998
|
-
const conf = awsIni(join10(home5, ".aws", "config"));
|
|
129358
|
+
const creds = awsIni(join10(home5, ".aws", "credentials"), awsProfile);
|
|
129359
|
+
const conf = awsIni(join10(home5, ".aws", "config"), awsProfile);
|
|
128999
129360
|
const akid = process.env.AWS_ACCESS_KEY_ID ?? creds.aws_access_key_id;
|
|
129000
129361
|
const secret = process.env.AWS_SECRET_ACCESS_KEY ?? creds.aws_secret_access_key;
|
|
129001
129362
|
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? conf.region;
|
|
@@ -129415,15 +129776,19 @@ __export(exports_onboard, {
|
|
|
129415
129776
|
cliLoginArgs: () => cliLoginArgs,
|
|
129416
129777
|
cliAuthStatus: () => cliAuthStatus,
|
|
129417
129778
|
addableProviders: () => addableProviders,
|
|
129779
|
+
addOpenAICompatAccount: () => addOpenAICompatAccount,
|
|
129418
129780
|
addCliAccount: () => addCliAccount,
|
|
129419
129781
|
addByPastedKey: () => addByPastedKey,
|
|
129420
129782
|
addAzureFoundryAccount: () => addAzureFoundryAccount,
|
|
129421
129783
|
addAzureAccount: () => addAzureAccount,
|
|
129422
129784
|
addApiKeyAccount: () => addApiKeyAccount
|
|
129423
129785
|
});
|
|
129424
|
-
import { mkdirSync as
|
|
129786
|
+
import { mkdirSync as mkdirSync8 } from "node:fs";
|
|
129425
129787
|
import { join as join11 } from "node:path";
|
|
129426
129788
|
import { homedir as homedir9 } from "node:os";
|
|
129789
|
+
function slugify(input) {
|
|
129790
|
+
return input.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || shortId();
|
|
129791
|
+
}
|
|
129427
129792
|
async function addApiKeyAccount(provider, key, opts = {}) {
|
|
129428
129793
|
provider = normalizeProviderId(provider);
|
|
129429
129794
|
const cat = catalogProvider(provider);
|
|
@@ -129450,6 +129815,29 @@ async function addApiKeyAccount(provider, key, opts = {}) {
|
|
|
129450
129815
|
putAccount(account);
|
|
129451
129816
|
return { ok: true, account, message: `added ${account.label} (${id})` };
|
|
129452
129817
|
}
|
|
129818
|
+
async function addOpenAICompatAccount(name31, baseUrl, key, models, opts = {}) {
|
|
129819
|
+
if (!/^https?:\/\//i.test(baseUrl) || !models.length) {
|
|
129820
|
+
return { ok: false, message: "usage: /account add openai-compat <name> <base-url> <api-key> <model> [model...]" };
|
|
129821
|
+
}
|
|
129822
|
+
const known = catalogProvider(normalizeProviderId(name31));
|
|
129823
|
+
const provider = known?.authKind === "openai-compat" ? known.id : `custom-${slugify(name31)}`;
|
|
129824
|
+
const id = opts.id ?? `${provider}-${shortId()}`;
|
|
129825
|
+
const ref = `${id}:api-key`;
|
|
129826
|
+
await setSecret(ref, key.trim());
|
|
129827
|
+
const account = {
|
|
129828
|
+
id,
|
|
129829
|
+
label: opts.label ?? (known?.label ?? (name31.trim() || "OpenAI-compatible")),
|
|
129830
|
+
provider,
|
|
129831
|
+
exec: "in-loop",
|
|
129832
|
+
auth: { kind: "openai-compat", ref },
|
|
129833
|
+
baseUrl: baseUrl.replace(/\/+$/, ""),
|
|
129834
|
+
models,
|
|
129835
|
+
enabled: true,
|
|
129836
|
+
addedAt: Date.now()
|
|
129837
|
+
};
|
|
129838
|
+
putAccount(account);
|
|
129839
|
+
return { ok: true, account, message: `added ${account.label} (${models.length} model${models.length === 1 ? "" : "s"})` };
|
|
129840
|
+
}
|
|
129453
129841
|
function azureResourceName(input) {
|
|
129454
129842
|
const s2 = input.trim();
|
|
129455
129843
|
try {
|
|
@@ -129492,7 +129880,7 @@ async function addAzureAccount(resourceOrEndpoint, key, opts = {}) {
|
|
|
129492
129880
|
const resourceName = azureResourceName(resourceOrEndpoint);
|
|
129493
129881
|
if (!resourceName || !key.trim())
|
|
129494
129882
|
return { ok: false, message: "usage: /account add azure <resource-or-endpoint> <api-key> [api-version]" };
|
|
129495
|
-
const id = opts.id ?? `azure-${resourceName
|
|
129883
|
+
const id = opts.id ?? `azure-${slugify(resourceName)}`;
|
|
129496
129884
|
const ref = `${id}:api-key`;
|
|
129497
129885
|
await setSecret(ref, key.trim());
|
|
129498
129886
|
const account = {
|
|
@@ -129521,7 +129909,7 @@ function addCliAccount(provider, name31) {
|
|
|
129521
129909
|
const id = slug3 ? `${provider}-${slug3}` : provider;
|
|
129522
129910
|
const profile = slug3 ? cliProfileDir(id) : undefined;
|
|
129523
129911
|
if (profile)
|
|
129524
|
-
|
|
129912
|
+
mkdirSync8(profile, { recursive: true });
|
|
129525
129913
|
const account = {
|
|
129526
129914
|
id,
|
|
129527
129915
|
label: slug3 ? `${cat.label.replace(/ \(.*\)$/, "")} (${name31.trim()})` : cat.label,
|
|
@@ -129599,7 +129987,8 @@ async function addByPastedKey(key) {
|
|
|
129599
129987
|
}
|
|
129600
129988
|
async function testAccount(a) {
|
|
129601
129989
|
const creds = await resolveCreds(a);
|
|
129602
|
-
|
|
129990
|
+
const isCloud = a.auth.kind === "aws" || a.auth.kind === "azure" || a.auth.kind === "vertex";
|
|
129991
|
+
if (!creds.apiKey && !isCloud && a.auth.kind !== "cli")
|
|
129603
129992
|
return { ok: false, message: "no key stored" };
|
|
129604
129993
|
try {
|
|
129605
129994
|
if (a.provider === "anthropic") {
|
|
@@ -129614,6 +130003,32 @@ async function testAccount(a) {
|
|
|
129614
130003
|
const r3 = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${creds.apiKey ?? ""}`);
|
|
129615
130004
|
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
129616
130005
|
}
|
|
130006
|
+
if (a.provider === "azure" && creds.azure) {
|
|
130007
|
+
const { resourceName, apiKey, apiVersion = "2024-08-01-preview" } = creds.azure;
|
|
130008
|
+
if (!resourceName || !apiKey)
|
|
130009
|
+
return { ok: false, message: "azure: resourceName and apiKey are required" };
|
|
130010
|
+
const r3 = await fetch(`https://${resourceName}.openai.azure.com/openai/models?api-version=${apiVersion}`, { headers: { "api-key": apiKey } });
|
|
130011
|
+
return r3.ok ? { ok: true, message: "credential works" } : { ok: false, message: await errMessage(r3) };
|
|
130012
|
+
}
|
|
130013
|
+
if (a.provider === "bedrock" && creds.aws) {
|
|
130014
|
+
const { accessKeyId, secretAccessKey, region } = creds.aws;
|
|
130015
|
+
if (!accessKeyId || !secretAccessKey)
|
|
130016
|
+
return { ok: false, message: "bedrock: AWS access key and secret are required" };
|
|
130017
|
+
if (!region)
|
|
130018
|
+
return { ok: false, message: "bedrock: AWS_REGION is required" };
|
|
130019
|
+
const keyOk = /^(AKIA|ASIA)[A-Z0-9]{16}$/.test(accessKeyId);
|
|
130020
|
+
if (!keyOk)
|
|
130021
|
+
return { ok: false, message: `bedrock: access key ID looks malformed (expected AKIA… or ASIA…, got ${accessKeyId.slice(0, 8)}…)` };
|
|
130022
|
+
return { ok: true, message: "credential fields present (Bedrock connectivity verified on first use)" };
|
|
130023
|
+
}
|
|
130024
|
+
if (a.provider === "vertex" && creds.vertex) {
|
|
130025
|
+
const { project, location } = creds.vertex;
|
|
130026
|
+
if (!project)
|
|
130027
|
+
return { ok: false, message: "vertex: GOOGLE_VERTEX_PROJECT is required" };
|
|
130028
|
+
if (!location)
|
|
130029
|
+
return { ok: false, message: "vertex: GOOGLE_VERTEX_LOCATION is required" };
|
|
130030
|
+
return { ok: true, message: "credential fields present (Vertex connectivity verified on first use — run `gcloud auth application-default login` if not done)" };
|
|
130031
|
+
}
|
|
129617
130032
|
const base2 = creds.baseURL ?? "https://api.openai.com/v1";
|
|
129618
130033
|
const r2 = await fetch(`${base2.replace(/\/$/, "")}/models`, {
|
|
129619
130034
|
headers: { Authorization: `Bearer ${creds.apiKey ?? ""}`, ...creds.headers ?? {} }
|
|
@@ -135173,7 +135588,7 @@ var import_react21 = __toESM(require_react(), 1);
|
|
|
135173
135588
|
// src/cli.tsx
|
|
135174
135589
|
import { createInterface } from "node:readline/promises";
|
|
135175
135590
|
import { execFileSync as execFileSync4, spawnSync } from "node:child_process";
|
|
135176
|
-
import { resolve as
|
|
135591
|
+
import { resolve as resolve13 } from "node:path";
|
|
135177
135592
|
import { existsSync as existsSync12 } from "node:fs";
|
|
135178
135593
|
|
|
135179
135594
|
// src/ui/App.tsx
|
|
@@ -139383,6 +139798,7 @@ var COMMANDS = [
|
|
|
139383
139798
|
{ name: "/memory", usage: "/memory [note]", desc: "show or add facts to remember (or start a line with #)", group: "chat" },
|
|
139384
139799
|
{ name: "/account", usage: "/account", desc: "list accounts; /account <number> to switch, /account add to add one", group: "accounts" },
|
|
139385
139800
|
{ name: "/onboard", usage: "/onboard", desc: "first-run setup; provider list and import/add commands", group: "accounts" },
|
|
139801
|
+
{ name: "/mcp", usage: "/mcp", desc: "list or connect MCP servers: /mcp add <name> <command> [args]", group: "accounts" },
|
|
139386
139802
|
{ name: "/cost", usage: "/cost", desc: "see what you've spent per account", group: "accounts" },
|
|
139387
139803
|
{ name: "/copy", usage: "/copy", desc: "copy the last reply to the clipboard", group: "output" },
|
|
139388
139804
|
{ name: "/export", usage: "/export [file]", desc: "save the conversation to a file", group: "output" },
|
|
@@ -139413,7 +139829,7 @@ var GROUP_TITLES = [
|
|
|
139413
139829
|
{ id: "accounts", title: "accounts & cost" },
|
|
139414
139830
|
{ id: "output", title: "save & copy" },
|
|
139415
139831
|
{ id: "modes", title: "modes" },
|
|
139416
|
-
{ id: "settings", title: "
|
|
139832
|
+
{ id: "settings", title: "settings" },
|
|
139417
139833
|
{ id: "other", title: "other" }
|
|
139418
139834
|
];
|
|
139419
139835
|
function helpText() {
|
|
@@ -139503,9 +139919,10 @@ var ENV_LABEL = {
|
|
|
139503
139919
|
deepseek: "DEEPSEEK_API_KEY"
|
|
139504
139920
|
};
|
|
139505
139921
|
function formatModelList(currentId, showAll = false) {
|
|
139922
|
+
const MODELS2 = modelRegistry();
|
|
139506
139923
|
const line = (m2) => ` ${m2.id === currentId ? glyph.on : glyph.off} ${m2.label.padEnd(18)} ${m2.provider}`;
|
|
139507
|
-
const usable =
|
|
139508
|
-
const rest2 =
|
|
139924
|
+
const usable = MODELS2.filter((m2) => providerAvailable(m2.provider));
|
|
139925
|
+
const rest2 = MODELS2.filter((m2) => !providerAvailable(m2.provider));
|
|
139509
139926
|
const rows = ["models · /model <name> pins one · /model auto routes per task"];
|
|
139510
139927
|
if (usable.length) {
|
|
139511
139928
|
rows.push("", "ready to use");
|
|
@@ -139528,7 +139945,8 @@ function resolveModelSwitch(query) {
|
|
|
139528
139945
|
const q = query.trim().toLowerCase();
|
|
139529
139946
|
if (!q)
|
|
139530
139947
|
return { ok: false, message: "usage: /model <name>" };
|
|
139531
|
-
const
|
|
139948
|
+
const MODELS2 = modelRegistry();
|
|
139949
|
+
const matches2 = MODELS2.filter((m3) => m3.label.toLowerCase().includes(q) || m3.id.toLowerCase().includes(q));
|
|
139532
139950
|
if (matches2.length === 0)
|
|
139533
139951
|
return { ok: false, message: `no model matching “${query}” — /model to list` };
|
|
139534
139952
|
const exact = matches2.find((m3) => m3.label.toLowerCase() === q || m3.id.toLowerCase() === q);
|
|
@@ -142120,10 +142538,10 @@ function pickDefaultModel(preferredId) {
|
|
|
142120
142538
|
const wanted = findModel(pref);
|
|
142121
142539
|
if (wanted && providerAvailable(wanted.provider))
|
|
142122
142540
|
return wanted;
|
|
142123
|
-
return
|
|
142541
|
+
return modelRegistry().find((m2) => providerAvailable(m2.provider));
|
|
142124
142542
|
}
|
|
142125
142543
|
function anyProviderAvailable() {
|
|
142126
|
-
return
|
|
142544
|
+
return modelRegistry().some((m2) => providerAvailable(m2.provider));
|
|
142127
142545
|
}
|
|
142128
142546
|
|
|
142129
142547
|
// src/model/selector.ts
|
|
@@ -142239,7 +142657,7 @@ class RoutingSelector {
|
|
|
142239
142657
|
const kind = task.kind ?? classify(task.prompt);
|
|
142240
142658
|
const bar = BAR[kind];
|
|
142241
142659
|
const required2 = task.requires ?? [];
|
|
142242
|
-
const available =
|
|
142660
|
+
const available = modelRegistry().filter((m2) => providerAvailable(m2.provider));
|
|
142243
142661
|
const capable = required2.length ? available.filter((m2) => supportsRequirements(m2, required2)) : available;
|
|
142244
142662
|
if (available.length > 0 && capable.length === 0) {
|
|
142245
142663
|
const missing = available.slice(0, 4).map((m2) => `${m2.label}: ${missingRequirements(m2, required2).join(", ")}`).join("; ");
|
|
@@ -143204,7 +143622,7 @@ function countTokens(text2, modelId) {
|
|
|
143204
143622
|
}
|
|
143205
143623
|
|
|
143206
143624
|
// src/context/memory.ts
|
|
143207
|
-
import { mkdirSync as
|
|
143625
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync5 } from "node:fs";
|
|
143208
143626
|
import { join as join8 } from "node:path";
|
|
143209
143627
|
import { homedir as homedir7 } from "node:os";
|
|
143210
143628
|
var DOC_CANDIDATES = ["GEARBOX.md", "CLAUDE.md", "AGENTS.md"];
|
|
@@ -143240,9 +143658,9 @@ function appendFact(text2, cwd2 = process.cwd()) {
|
|
|
143240
143658
|
if (!fact)
|
|
143241
143659
|
return false;
|
|
143242
143660
|
try {
|
|
143243
|
-
|
|
143661
|
+
mkdirSync7(memDir(cwd2), { recursive: true });
|
|
143244
143662
|
const stamp = new Date().toISOString().slice(0, 10);
|
|
143245
|
-
|
|
143663
|
+
writeFileSync7(factsFile(cwd2), `- [${stamp}] ${fact}
|
|
143246
143664
|
`, { flag: "a" });
|
|
143247
143665
|
return true;
|
|
143248
143666
|
} catch {
|
|
@@ -144109,7 +144527,7 @@ ${summary}` },
|
|
|
144109
144527
|
|
|
144110
144528
|
// src/image.ts
|
|
144111
144529
|
import { existsSync as existsSync8, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
|
|
144112
|
-
import { isAbsolute as isAbsolute2, resolve as resolve11 } from "node:path";
|
|
144530
|
+
import { basename as basename2, isAbsolute as isAbsolute2, resolve as resolve11 } from "node:path";
|
|
144113
144531
|
var MAX_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
144114
144532
|
var IMAGE_EXT = {
|
|
144115
144533
|
".png": "image/png",
|
|
@@ -144121,6 +144539,39 @@ var IMAGE_EXT = {
|
|
|
144121
144539
|
function unquotePath(raw) {
|
|
144122
144540
|
return raw.trim().replace(/^file:\/\//, "").replace(/^['"]|['"]$/g, "").replace(/\\ /g, " ");
|
|
144123
144541
|
}
|
|
144542
|
+
function imageMimeForPath(path) {
|
|
144543
|
+
const ext = path.toLowerCase().match(/\.[^.]+$/)?.[0] ?? "";
|
|
144544
|
+
return IMAGE_EXT[ext];
|
|
144545
|
+
}
|
|
144546
|
+
function isImageFilePath(path) {
|
|
144547
|
+
return Boolean(imageMimeForPath(unquotePath(path)));
|
|
144548
|
+
}
|
|
144549
|
+
function shortName(path, max2 = 42) {
|
|
144550
|
+
const name31 = basename2(path);
|
|
144551
|
+
if (name31.length <= max2)
|
|
144552
|
+
return name31;
|
|
144553
|
+
const ext = name31.match(/\.[^.]+$/)?.[0] ?? "";
|
|
144554
|
+
const stem = ext ? name31.slice(0, -ext.length) : name31;
|
|
144555
|
+
return `${stem.slice(0, Math.max(8, max2 - ext.length - 1))}…${ext}`;
|
|
144556
|
+
}
|
|
144557
|
+
function imageChipLabel(path, index2) {
|
|
144558
|
+
return `[image${index2 && index2 > 1 ? ` ${index2}` : ""}: ${shortName(path)}]`;
|
|
144559
|
+
}
|
|
144560
|
+
function escapeRegExp2(s2) {
|
|
144561
|
+
return s2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
144562
|
+
}
|
|
144563
|
+
function replaceImagePathWithMarker(text2, path, marker16) {
|
|
144564
|
+
const raw = path;
|
|
144565
|
+
const file5 = `file://${raw}`;
|
|
144566
|
+
const escaped = raw.replace(/ /g, "\\ ");
|
|
144567
|
+
const candidates = [file5, raw, escaped];
|
|
144568
|
+
let out = text2;
|
|
144569
|
+
for (const c of candidates) {
|
|
144570
|
+
out = out.replace(new RegExp(`(["'])${escapeRegExp2(c)}\\1`, "g"), marker16);
|
|
144571
|
+
out = out.replace(new RegExp(escapeRegExp2(c), "g"), marker16);
|
|
144572
|
+
}
|
|
144573
|
+
return out;
|
|
144574
|
+
}
|
|
144124
144575
|
function imagePathsInText(text2, cwd2 = process.cwd(), limit = 6) {
|
|
144125
144576
|
const found = [];
|
|
144126
144577
|
const add2 = (rawMatch) => {
|
|
@@ -144146,8 +144597,7 @@ function imagePathsInText(text2, cwd2 = process.cwd(), limit = 6) {
|
|
|
144146
144597
|
}
|
|
144147
144598
|
function loadImageAttachment(path) {
|
|
144148
144599
|
const abs = isAbsolute2(path) ? path : resolve11(process.cwd(), path);
|
|
144149
|
-
const
|
|
144150
|
-
const mimeType = IMAGE_EXT[ext];
|
|
144600
|
+
const mimeType = imageMimeForPath(abs);
|
|
144151
144601
|
if (!mimeType)
|
|
144152
144602
|
throw new Error(`unsupported image type: ${path}`);
|
|
144153
144603
|
const size2 = statSync4(abs).size;
|
|
@@ -144168,7 +144618,7 @@ function imageContent(text2, images) {
|
|
|
144168
144618
|
init_capabilities();
|
|
144169
144619
|
|
|
144170
144620
|
// src/init.ts
|
|
144171
|
-
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync15, writeFileSync as
|
|
144621
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
|
|
144172
144622
|
import { join as join13 } from "node:path";
|
|
144173
144623
|
|
|
144174
144624
|
// src/verify.ts
|
|
@@ -144327,11 +144777,14 @@ function writeProjectGuide(cwd2 = process.cwd()) {
|
|
|
144327
144777
|
const path = join13(cwd2, "GEARBOX.md");
|
|
144328
144778
|
const before2 = existsSync10(path) ? readFileSync15(path, "utf8") : "";
|
|
144329
144779
|
const after2 = buildProjectGuide(cwd2);
|
|
144330
|
-
|
|
144780
|
+
writeFileSync8(path, after2, "utf8");
|
|
144331
144781
|
const diff2 = computeDiff(before2, after2);
|
|
144332
144782
|
return { path, summary: `wrote GEARBOX.md (${diffStat(diff2)})`, diff: diff2 };
|
|
144333
144783
|
}
|
|
144334
144784
|
|
|
144785
|
+
// src/ui/App.tsx
|
|
144786
|
+
init_mcp();
|
|
144787
|
+
|
|
144335
144788
|
// src/ui/clipboard.ts
|
|
144336
144789
|
init_proc();
|
|
144337
144790
|
function osc52(text2) {
|
|
@@ -144534,7 +144987,7 @@ function gitBranch() {
|
|
|
144534
144987
|
// src/ui/App.tsx
|
|
144535
144988
|
init_proc();
|
|
144536
144989
|
var jsx_dev_runtime12 = __toESM(require_jsx_dev_runtime(), 1);
|
|
144537
|
-
import { basename as
|
|
144990
|
+
import { basename as basename3, extname, resolve as resolve12 } from "node:path";
|
|
144538
144991
|
import { existsSync as existsSync11, readFileSync as readFileSync16, statSync as statSync5 } from "node:fs";
|
|
144539
144992
|
import { writeFile as fsWriteFile } from "node:fs/promises";
|
|
144540
144993
|
import { spawnSync as nodeSpawnSync2 } from "node:child_process";
|
|
@@ -144598,6 +145051,7 @@ function firstPath(text2) {
|
|
|
144598
145051
|
function uniq2(xs) {
|
|
144599
145052
|
return [...new Set(xs)];
|
|
144600
145053
|
}
|
|
145054
|
+
var CLAUDE_CLI_EFFORTS = [];
|
|
144601
145055
|
var FALLBACK_CODEX_MODELS = [
|
|
144602
145056
|
{ id: "gpt-5.5", label: "gpt-5.5", provider: "codex", efforts: ["low", "medium", "high", "xhigh"] },
|
|
144603
145057
|
{ id: "gpt-5.4", label: "gpt-5.4", provider: "codex", efforts: ["low", "medium", "high", "xhigh"] },
|
|
@@ -144687,33 +145141,8 @@ function ActivityRail({ items, width }) {
|
|
|
144687
145141
|
}, undefined, true, undefined, this);
|
|
144688
145142
|
}
|
|
144689
145143
|
function SetupSplash({ state, width, skin, splashSize }) {
|
|
144690
|
-
const providers = featuredApiKeyProviders().slice(0, width >= 92 ? 12 : 8);
|
|
144691
|
-
const left = providers.filter((_, i2) => i2 % 2 === 0);
|
|
144692
|
-
const right = providers.filter((_, i2) => i2 % 2 === 1);
|
|
144693
145144
|
const detected = state.importable.length + state.cloudImportable.length;
|
|
144694
|
-
const panelWidth = Math.min(Math.max(width - 4,
|
|
144695
|
-
const showTwoCols = panelWidth >= 82;
|
|
144696
|
-
const firstColumn = showTwoCols ? left : providers;
|
|
144697
|
-
const secondColumn = showTwoCols ? right : [];
|
|
144698
|
-
const providerLine = (id, label) => /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144699
|
-
color: color.dim,
|
|
144700
|
-
children: [
|
|
144701
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144702
|
-
color: color.accent,
|
|
144703
|
-
children: [
|
|
144704
|
-
"/account add ",
|
|
144705
|
-
id
|
|
144706
|
-
]
|
|
144707
|
-
}, undefined, true, undefined, this),
|
|
144708
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144709
|
-
color: color.faint,
|
|
144710
|
-
children: [
|
|
144711
|
-
" ",
|
|
144712
|
-
label
|
|
144713
|
-
]
|
|
144714
|
-
}, undefined, true, undefined, this)
|
|
144715
|
-
]
|
|
144716
|
-
}, id, true, undefined, this);
|
|
145145
|
+
const panelWidth = Math.min(Math.max(width - 4, 30), 58);
|
|
144717
145146
|
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144718
145147
|
flexDirection: "column",
|
|
144719
145148
|
alignItems: "center",
|
|
@@ -144730,188 +145159,130 @@ function SetupSplash({ state, width, skin, splashSize }) {
|
|
|
144730
145159
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144731
145160
|
color: color.accent,
|
|
144732
145161
|
bold: true,
|
|
144733
|
-
children: "
|
|
144734
|
-
}, undefined, false, undefined, this),
|
|
144735
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144736
|
-
color: color.text,
|
|
144737
|
-
children: "one terminal, every model account you already pay for"
|
|
145162
|
+
children: "gearbox"
|
|
144738
145163
|
}, undefined, false, undefined, this),
|
|
144739
145164
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144740
|
-
color: color.
|
|
144741
|
-
children: "
|
|
145165
|
+
color: color.dim,
|
|
145166
|
+
children: "one terminal · every model you already pay for"
|
|
144742
145167
|
}, undefined, false, undefined, this)
|
|
144743
145168
|
]
|
|
144744
145169
|
}, undefined, true, undefined, this),
|
|
144745
145170
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144746
|
-
marginTop:
|
|
145171
|
+
marginTop: 2,
|
|
144747
145172
|
width: panelWidth,
|
|
144748
145173
|
borderStyle: "round",
|
|
144749
|
-
borderColor: color.
|
|
145174
|
+
borderColor: color.faint,
|
|
144750
145175
|
paddingX: 2,
|
|
144751
145176
|
paddingY: 1,
|
|
144752
145177
|
flexDirection: "column",
|
|
144753
145178
|
children: [
|
|
144754
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(
|
|
144755
|
-
justifyContent: "space-between",
|
|
144756
|
-
children: [
|
|
144757
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144758
|
-
color: color.text,
|
|
144759
|
-
bold: true,
|
|
144760
|
-
children: "start here"
|
|
144761
|
-
}, undefined, false, undefined, this),
|
|
144762
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144763
|
-
color: detected ? color.ok : color.faint,
|
|
144764
|
-
children: detected ? `${detected} detected` : "no account yet"
|
|
144765
|
-
}, undefined, false, undefined, this)
|
|
144766
|
-
]
|
|
144767
|
-
}, undefined, true, undefined, this),
|
|
144768
|
-
detected ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144769
|
-
marginTop: 1,
|
|
144770
|
-
children: [
|
|
144771
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144772
|
-
color: color.ok,
|
|
144773
|
-
children: [
|
|
144774
|
-
glyph.on,
|
|
144775
|
-
" "
|
|
144776
|
-
]
|
|
144777
|
-
}, undefined, true, undefined, this),
|
|
144778
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144779
|
-
color: color.text,
|
|
144780
|
-
children: "Credentials found on this machine: "
|
|
144781
|
-
}, undefined, false, undefined, this),
|
|
144782
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144783
|
-
color: color.accent,
|
|
144784
|
-
children: "/account import"
|
|
144785
|
-
}, undefined, false, undefined, this)
|
|
144786
|
-
]
|
|
144787
|
-
}, undefined, true, undefined, this) : null,
|
|
144788
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144789
|
-
marginTop: 1,
|
|
144790
|
-
flexDirection: showTwoCols ? "row" : "column",
|
|
145179
|
+
detected > 0 ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(jsx_dev_runtime12.Fragment, {
|
|
144791
145180
|
children: [
|
|
144792
145181
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144793
|
-
flexDirection: "column",
|
|
144794
|
-
width: showTwoCols ? Math.floor((panelWidth - 6) / 2) : undefined,
|
|
144795
145182
|
children: [
|
|
144796
145183
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144797
|
-
color: color.
|
|
144798
|
-
children: "API key"
|
|
144799
|
-
}, undefined, false, undefined, this),
|
|
144800
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144801
|
-
color: color.text,
|
|
145184
|
+
color: color.ok,
|
|
144802
145185
|
children: [
|
|
144803
|
-
|
|
144804
|
-
|
|
144805
|
-
children: "/account add <api-key>"
|
|
144806
|
-
}, undefined, false, undefined, this),
|
|
144807
|
-
" auto-detect when possible"
|
|
145186
|
+
glyph.on,
|
|
145187
|
+
" "
|
|
144808
145188
|
]
|
|
144809
145189
|
}, undefined, true, undefined, this),
|
|
144810
145190
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144811
145191
|
color: color.text,
|
|
144812
|
-
children:
|
|
144813
|
-
|
|
144814
|
-
|
|
144815
|
-
|
|
144816
|
-
|
|
145192
|
+
children: [
|
|
145193
|
+
detected,
|
|
145194
|
+
" credential",
|
|
145195
|
+
detected > 1 ? "s" : "",
|
|
145196
|
+
" found on this machine"
|
|
145197
|
+
]
|
|
145198
|
+
}, undefined, true, undefined, this)
|
|
144817
145199
|
]
|
|
144818
145200
|
}, undefined, true, undefined, this),
|
|
144819
145201
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144820
|
-
|
|
144821
|
-
marginLeft: showTwoCols ? 4 : 0,
|
|
144822
|
-
marginTop: showTwoCols ? 0 : 1,
|
|
145202
|
+
marginTop: 1,
|
|
144823
145203
|
children: [
|
|
144824
145204
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144825
|
-
color: color.
|
|
144826
|
-
children: "
|
|
145205
|
+
color: color.accent,
|
|
145206
|
+
children: "/account import"
|
|
144827
145207
|
}, undefined, false, undefined, this),
|
|
144828
145208
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144829
|
-
color: color.
|
|
144830
|
-
children:
|
|
144831
|
-
|
|
144832
|
-
|
|
144833
|
-
|
|
145209
|
+
color: color.dim,
|
|
145210
|
+
children: " connect automatically"
|
|
145211
|
+
}, undefined, false, undefined, this)
|
|
145212
|
+
]
|
|
145213
|
+
}, undefined, true, undefined, this),
|
|
145214
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
145215
|
+
marginTop: 1,
|
|
145216
|
+
children: [
|
|
145217
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
145218
|
+
color: color.faint,
|
|
145219
|
+
children: "or add a different key: "
|
|
144834
145220
|
}, undefined, false, undefined, this),
|
|
144835
145221
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144836
|
-
color: color.
|
|
144837
|
-
children:
|
|
144838
|
-
|
|
144839
|
-
color: color.accent,
|
|
144840
|
-
children: "/account add claude"
|
|
144841
|
-
}, undefined, false, undefined, this),
|
|
144842
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144843
|
-
color: color.faint,
|
|
144844
|
-
children: " "
|
|
144845
|
-
}, undefined, false, undefined, this),
|
|
144846
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144847
|
-
color: color.accent,
|
|
144848
|
-
children: "/account add codex"
|
|
144849
|
-
}, undefined, false, undefined, this)
|
|
144850
|
-
]
|
|
144851
|
-
}, undefined, true, undefined, this)
|
|
145222
|
+
color: color.accent,
|
|
145223
|
+
children: "/account add <api-key>"
|
|
145224
|
+
}, undefined, false, undefined, this)
|
|
144852
145225
|
]
|
|
144853
145226
|
}, undefined, true, undefined, this)
|
|
144854
145227
|
]
|
|
144855
|
-
}, undefined, true, undefined, this),
|
|
144856
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144857
|
-
marginTop: 1,
|
|
144858
|
-
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144859
|
-
color: color.faint,
|
|
144860
|
-
children: glyph.rule.repeat(Math.max(panelWidth - 6, 20))
|
|
144861
|
-
}, undefined, false, undefined, this)
|
|
144862
|
-
}, undefined, false, undefined, this),
|
|
144863
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144864
|
-
marginTop: 1,
|
|
144865
|
-
flexDirection: showTwoCols ? "row" : "column",
|
|
145228
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(jsx_dev_runtime12.Fragment, {
|
|
144866
145229
|
children: [
|
|
145230
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
145231
|
+
color: color.dim,
|
|
145232
|
+
children: "paste or type a key to get started"
|
|
145233
|
+
}, undefined, false, undefined, this),
|
|
144867
145234
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144868
|
-
|
|
144869
|
-
|
|
145235
|
+
marginTop: 1,
|
|
145236
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
145237
|
+
color: color.accent,
|
|
145238
|
+
children: "/account add <api-key>"
|
|
145239
|
+
}, undefined, false, undefined, this)
|
|
145240
|
+
}, undefined, false, undefined, this)
|
|
145241
|
+
]
|
|
145242
|
+
}, undefined, true, undefined, this),
|
|
145243
|
+
(state.hasClaudeCli || state.hasCodexCli) && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
145244
|
+
marginTop: 2,
|
|
145245
|
+
flexDirection: "column",
|
|
145246
|
+
children: [
|
|
145247
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
145248
|
+
color: color.faint,
|
|
145249
|
+
children: "subscriptions detected"
|
|
145250
|
+
}, undefined, false, undefined, this),
|
|
145251
|
+
state.hasClaudeCli && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144870
145252
|
children: [
|
|
144871
145253
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144872
|
-
color: color.
|
|
144873
|
-
children: "
|
|
145254
|
+
color: color.accent,
|
|
145255
|
+
children: "/account add claude"
|
|
144874
145256
|
}, undefined, false, undefined, this),
|
|
144875
|
-
|
|
145257
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
145258
|
+
color: color.faint,
|
|
145259
|
+
children: " Claude Pro / Max"
|
|
145260
|
+
}, undefined, false, undefined, this)
|
|
144876
145261
|
]
|
|
144877
145262
|
}, undefined, true, undefined, this),
|
|
144878
|
-
|
|
144879
|
-
flexDirection: "column",
|
|
144880
|
-
marginLeft: 4,
|
|
145263
|
+
state.hasCodexCli && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144881
145264
|
children: [
|
|
144882
145265
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144883
|
-
color: color.
|
|
144884
|
-
children: " "
|
|
145266
|
+
color: color.accent,
|
|
145267
|
+
children: "/account add codex"
|
|
144885
145268
|
}, undefined, false, undefined, this),
|
|
144886
|
-
|
|
145269
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
145270
|
+
color: color.faint,
|
|
145271
|
+
children: " ChatGPT Plus"
|
|
145272
|
+
}, undefined, false, undefined, this)
|
|
144887
145273
|
]
|
|
144888
|
-
}, undefined, true, undefined, this)
|
|
144889
|
-
]
|
|
144890
|
-
}, undefined, true, undefined, this),
|
|
144891
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
144892
|
-
marginTop: 1,
|
|
144893
|
-
justifyContent: "space-between",
|
|
144894
|
-
children: [
|
|
144895
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144896
|
-
color: color.faint,
|
|
144897
|
-
children: "Full catalog: "
|
|
144898
|
-
}, undefined, false, undefined, this),
|
|
144899
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144900
|
-
color: color.accent,
|
|
144901
|
-
children: "/onboard providers"
|
|
144902
|
-
}, undefined, false, undefined, this),
|
|
144903
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144904
|
-
color: color.faint,
|
|
144905
|
-
children: " Help: "
|
|
144906
|
-
}, undefined, false, undefined, this),
|
|
144907
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
144908
|
-
color: color.accent,
|
|
144909
|
-
children: "/account"
|
|
144910
|
-
}, undefined, false, undefined, this)
|
|
145274
|
+
}, undefined, true, undefined, this)
|
|
144911
145275
|
]
|
|
144912
145276
|
}, undefined, true, undefined, this)
|
|
144913
145277
|
]
|
|
144914
|
-
}, undefined, true, undefined, this)
|
|
145278
|
+
}, undefined, true, undefined, this),
|
|
145279
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
145280
|
+
marginTop: 1,
|
|
145281
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
145282
|
+
color: color.faint,
|
|
145283
|
+
children: "/onboard · /account · /help"
|
|
145284
|
+
}, undefined, false, undefined, this)
|
|
145285
|
+
}, undefined, false, undefined, this)
|
|
144915
145286
|
]
|
|
144916
145287
|
}, undefined, true, undefined, this);
|
|
144917
145288
|
}
|
|
@@ -144999,7 +145370,7 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
144999
145370
|
return () => clearInterval(t2);
|
|
145000
145371
|
}, [busy]);
|
|
145001
145372
|
import_react26.useEffect(() => {
|
|
145002
|
-
const proj =
|
|
145373
|
+
const proj = basename3(process.cwd());
|
|
145003
145374
|
setTitle(busy ? `✳ ${proj} · working` : `${proj} · gearbox`);
|
|
145004
145375
|
}, [busy]);
|
|
145005
145376
|
const editRef = import_react26.useRef(edit2);
|
|
@@ -145029,6 +145400,7 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145029
145400
|
const activeCliModelRef = import_react26.useRef(undefined);
|
|
145030
145401
|
const cliSessionRef = import_react26.useRef(undefined);
|
|
145031
145402
|
const activeImagesRef = import_react26.useRef([]);
|
|
145403
|
+
const imageChipPathsRef = import_react26.useRef(new Map);
|
|
145032
145404
|
const accountStatusCacheRef = import_react26.useRef({});
|
|
145033
145405
|
const usedAccountRef = import_react26.useRef(null);
|
|
145034
145406
|
const cliMetaRef = import_react26.useRef(null);
|
|
@@ -145072,12 +145444,12 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145072
145444
|
}
|
|
145073
145445
|
}, []);
|
|
145074
145446
|
import_react26.useEffect(() => {
|
|
145075
|
-
setPermissionHandler((req) => new Promise((
|
|
145447
|
+
setPermissionHandler((req) => new Promise((resolve13) => {
|
|
145076
145448
|
if (modeRef.current === "auto-accept" && (req.kind === "write" || req.kind === "edit")) {
|
|
145077
|
-
|
|
145449
|
+
resolve13("once");
|
|
145078
145450
|
return;
|
|
145079
145451
|
}
|
|
145080
|
-
permQueue.current.push({ req, resolve:
|
|
145452
|
+
permQueue.current.push({ req, resolve: resolve13 });
|
|
145081
145453
|
pumpPerm();
|
|
145082
145454
|
}));
|
|
145083
145455
|
return () => setPermissionHandler(null);
|
|
@@ -145199,9 +145571,9 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145199
145571
|
const y = Number(m2[3]);
|
|
145200
145572
|
const up2 = m2[4] === "m";
|
|
145201
145573
|
if (b === 64)
|
|
145202
|
-
delta -=
|
|
145574
|
+
delta -= 1;
|
|
145203
145575
|
else if (b === 65)
|
|
145204
|
-
delta +=
|
|
145576
|
+
delta += 1;
|
|
145205
145577
|
else {
|
|
145206
145578
|
const off = composerOffset(x2, y);
|
|
145207
145579
|
const point = transcriptPoint(x2, y);
|
|
@@ -145210,9 +145582,9 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145210
145582
|
if (isPrimary && isDrag && transcriptMouseAnchorRef.current && !point) {
|
|
145211
145583
|
const bottom = viewportTop + transcriptHeightLiveRef.current - 1;
|
|
145212
145584
|
if (y < viewportTop)
|
|
145213
|
-
scrollBy(-
|
|
145585
|
+
scrollBy(-2);
|
|
145214
145586
|
else if (y > bottom)
|
|
145215
|
-
scrollBy(
|
|
145587
|
+
scrollBy(2);
|
|
145216
145588
|
const edgeLine = y < viewportTop ? scrollTopLiveRef.current : scrollTopLiveRef.current + transcriptHeightLiveRef.current - 1;
|
|
145217
145589
|
const edgeText = lineText(linesRef.current[edgeLine] ?? []);
|
|
145218
145590
|
setTranscriptSel({
|
|
@@ -145372,6 +145744,28 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145372
145744
|
transcriptSelectionRef.current = sel;
|
|
145373
145745
|
setTranscriptSelectionState(sel);
|
|
145374
145746
|
};
|
|
145747
|
+
const imageMarkerFor = (path) => {
|
|
145748
|
+
for (const [marker50, existing] of imageChipPathsRef.current) {
|
|
145749
|
+
if (existing === path)
|
|
145750
|
+
return marker50;
|
|
145751
|
+
}
|
|
145752
|
+
let idx = 1;
|
|
145753
|
+
let marker16 = imageChipLabel(path);
|
|
145754
|
+
while (imageChipPathsRef.current.has(marker16)) {
|
|
145755
|
+
idx++;
|
|
145756
|
+
marker16 = imageChipLabel(path, idx);
|
|
145757
|
+
}
|
|
145758
|
+
imageChipPathsRef.current.set(marker16, path);
|
|
145759
|
+
return marker16;
|
|
145760
|
+
};
|
|
145761
|
+
const chipImagePathsIn = (text2) => {
|
|
145762
|
+
const paths = [];
|
|
145763
|
+
for (const [marker16, path] of imageChipPathsRef.current) {
|
|
145764
|
+
if (text2.includes(marker16))
|
|
145765
|
+
paths.push(path);
|
|
145766
|
+
}
|
|
145767
|
+
return paths;
|
|
145768
|
+
};
|
|
145375
145769
|
const cliCatalogId = (binary) => binary.includes("codex") ? "codex-cli" : binary.includes("claude") ? "claude-cli" : "";
|
|
145376
145770
|
const cliModelChoices = (binary) => {
|
|
145377
145771
|
if (binary.includes("codex"))
|
|
@@ -145379,7 +145773,7 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145379
145773
|
const provider = binary.includes("claude") ? "anthropic" : binary;
|
|
145380
145774
|
return (catalogProvider(cliCatalogId(binary))?.defaultModels ?? []).map((id) => {
|
|
145381
145775
|
const m2 = findModel(id);
|
|
145382
|
-
return { id, label: m2?.label ?? id, provider, efforts: m2 ? effortLevels(m2) : undefined };
|
|
145776
|
+
return { id, label: m2?.label ?? id, provider, efforts: binary.includes("claude") ? CLAUDE_CLI_EFFORTS : m2 ? effortLevels(m2) : undefined };
|
|
145383
145777
|
});
|
|
145384
145778
|
};
|
|
145385
145779
|
const cliSupportsModel = (binary, modelId) => {
|
|
@@ -145417,7 +145811,8 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145417
145811
|
rows2.push(" no named subscription models exposed yet");
|
|
145418
145812
|
for (const m2 of models)
|
|
145419
145813
|
rows2.push(` ${m2.id === currentId ? glyph.on : glyph.off} ${m2.label}`);
|
|
145420
|
-
rows2.push("",
|
|
145814
|
+
rows2.push("", `API models are hidden while a subscription is active — /account off returns to API routing
|
|
145815
|
+
tip: /model haiku (or any API model name) switches directly and leaves the subscription`);
|
|
145421
145816
|
return rows2.join(`
|
|
145422
145817
|
`);
|
|
145423
145818
|
};
|
|
@@ -145443,7 +145838,7 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145443
145838
|
const take2 = (rows2) => rows2.filter((r2) => !q || `${r2.label} ${r2.detail ?? ""} ${r2.value}`.toLowerCase().includes(q)).slice(0, 7);
|
|
145444
145839
|
if (head2 === "/model") {
|
|
145445
145840
|
const cli = activeCliRef.current;
|
|
145446
|
-
const models = cli ? cliModelChoices(cli.binary) :
|
|
145841
|
+
const models = cli ? cliModelChoices(cli.binary) : modelRegistry();
|
|
145447
145842
|
return take2([
|
|
145448
145843
|
{ value: "/model auto", label: "auto", detail: cli ? "use subscription default" : "route per task" },
|
|
145449
145844
|
...models.map((m2) => ({ value: `/model ${m2.label}`, label: m2.label, detail: cli ? `${cli.binary} subscription` : `${m2.provider} · ${m2.id}` }))
|
|
@@ -145504,6 +145899,16 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145504
145899
|
const subscription = activeCli ? activeCli.label : null;
|
|
145505
145900
|
const routing = setupRequired || activeCli ? null : lastPick?.reason ?? choice?.reason ?? null;
|
|
145506
145901
|
const ctxPct = !activeCli && model && lastInput > 0 ? Math.round(lastInput / model.contextWindow * 100) : null;
|
|
145902
|
+
const activeModelEfforts = (() => {
|
|
145903
|
+
const cli = activeCliRef.current;
|
|
145904
|
+
if (cli) {
|
|
145905
|
+
const choices = cliModelChoices(cli.binary);
|
|
145906
|
+
const m2 = choices.find((c) => c.id === activeCliModel) ?? choices[0];
|
|
145907
|
+
return m2?.efforts ?? [];
|
|
145908
|
+
}
|
|
145909
|
+
return model ? effortLevels(model) : [];
|
|
145910
|
+
})();
|
|
145911
|
+
const displayEffort = activeModelEfforts.length > 0 ? effort : undefined;
|
|
145507
145912
|
const push = (it) => setItems((prev) => [...prev, it]);
|
|
145508
145913
|
const pushPhase = (label, detail) => {
|
|
145509
145914
|
const id = idRef.current++;
|
|
@@ -145588,7 +145993,14 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145588
145993
|
onEvent({ type: "phase", label: "using subscription", detail: `${cli.binary}${modelLabel2 ? ` · ${modelLabel2}` : ""} owns tools and permissions`, state: "running" });
|
|
145589
145994
|
const cliChoices = cliModelChoices(cli.binary);
|
|
145590
145995
|
const cliChoice = cliChoices.find((m2) => m2.id === activeCliModelRef.current) ?? cliChoices[0];
|
|
145591
|
-
const
|
|
145996
|
+
const _cliEffortRaw = cliChoice ? normalizeEffort(effortRef.current, cliChoice.efforts ?? []) : null;
|
|
145997
|
+
if (_cliEffortRaw === null && effortRef.current !== "medium") {
|
|
145998
|
+
const supported = cliChoice?.efforts ?? [];
|
|
145999
|
+
const { level: nearest } = clampEffort(effortRef.current, supported);
|
|
146000
|
+
const hint = supported.length ? ` — try /effort ${nearest}` : "";
|
|
146001
|
+
throw new Error(`effort "${effortRef.current}" is not supported by ${cliChoice?.label ?? cli.binary} (supports: ${supported.join(", ") || "none"}${hint})`);
|
|
146002
|
+
}
|
|
146003
|
+
const cliEffort = _cliEffortRaw ?? undefined;
|
|
145592
146004
|
const activeAccount = getAccount(cli.id);
|
|
145593
146005
|
const activeName = activeAccount ? accountName(activeAccount).match(/\((.*)\)/)?.[1] : undefined;
|
|
145594
146006
|
const reloginCommand = cli.binary.includes("codex") ? `/account add codex${activeName ? ` ${activeName}` : ""}` : `/account add claude${activeName ? ` ${activeName}` : ""}`;
|
|
@@ -145629,12 +146041,19 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145629
146041
|
cliMetaRef.current = null;
|
|
145630
146042
|
if (account)
|
|
145631
146043
|
markUsed(account.id);
|
|
145632
|
-
const
|
|
146044
|
+
const _effortRaw = normalizeEffort(effortRef.current, effortLevels(choice2.model));
|
|
146045
|
+
if (_effortRaw === null && effortRef.current !== "medium") {
|
|
146046
|
+
const supported = effortLevels(choice2.model);
|
|
146047
|
+
const { level: nearest } = clampEffort(effortRef.current, supported);
|
|
146048
|
+
const hint = supported.length ? ` — try /effort ${nearest}` : "";
|
|
146049
|
+
throw new Error(`effort "${effortRef.current}" is not supported by ${choice2.model.label} (supports: ${supported.join(", ") || "none"}${hint})`);
|
|
146050
|
+
}
|
|
146051
|
+
const modelEffort = _effortRaw ?? undefined;
|
|
145633
146052
|
const r2 = await runTask({ model: choice2.model, messages: ctx, onEvent, signal, plan, system, creds, effort: modelEffort });
|
|
145634
146053
|
const produced = r2.messages.slice(ctx.length);
|
|
145635
146054
|
const imageNote = activeImagesRef.current.length ? `
|
|
145636
146055
|
|
|
145637
|
-
[Attached images: ${activeImagesRef.current.map((img) =>
|
|
146056
|
+
[Attached images: ${activeImagesRef.current.map((img) => basename3(img.path)).join(", ")}]` : "";
|
|
145638
146057
|
const ledger = sanitizeToolPairs([...messages, { role: "user", content: prompt + imageNote }, ...produced]);
|
|
145639
146058
|
return { messages: ledger, usage: r2.usage };
|
|
145640
146059
|
}, []);
|
|
@@ -145680,6 +146099,17 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145680
146099
|
updatePrefs({ activeAccount: null });
|
|
145681
146100
|
return " (left the subscription)";
|
|
145682
146101
|
};
|
|
146102
|
+
const applyEffortClamp = (allowed) => {
|
|
146103
|
+
const { level, clamped } = clampEffort(effortRef.current, allowed);
|
|
146104
|
+
if (!clamped)
|
|
146105
|
+
return "";
|
|
146106
|
+
const prev = effortRef.current;
|
|
146107
|
+
effortRef.current = level;
|
|
146108
|
+
setEffortState(level);
|
|
146109
|
+
if (!allowed.length)
|
|
146110
|
+
return ` — effort reset to ${level} (no reasoning support)`;
|
|
146111
|
+
return ` — effort clamped: ${prev} → ${level} (${prev} not supported)`;
|
|
146112
|
+
};
|
|
145683
146113
|
const setEffort = (raw) => {
|
|
145684
146114
|
const target = effortTarget();
|
|
145685
146115
|
if (!target?.efforts.length) {
|
|
@@ -145721,28 +146151,34 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
|
|
|
145721
146151
|
}
|
|
145722
146152
|
};
|
|
145723
146153
|
const runTurn = import_react26.useCallback(async (prompt) => {
|
|
145724
|
-
echo(prompt);
|
|
145725
|
-
lastPromptRef.current = prompt;
|
|
145726
146154
|
setVerb(nextVerb());
|
|
145727
146155
|
activeImagesRef.current = [];
|
|
145728
146156
|
let { text: modelPrompt, attached } = expandMentions(prompt);
|
|
145729
146157
|
if (attached.length)
|
|
145730
146158
|
notice(`attached ${attached.length} file${attached.length > 1 ? "s" : ""}: ${attached.join(", ")}`);
|
|
145731
|
-
const imagePaths = imagePathsInText(modelPrompt);
|
|
146159
|
+
const imagePaths = uniq2([...chipImagePathsIn(modelPrompt), ...imagePathsInText(modelPrompt)]);
|
|
146160
|
+
let displayPrompt = prompt;
|
|
146161
|
+
for (const path of imagePaths) {
|
|
146162
|
+
const marker16 = imageMarkerFor(path);
|
|
146163
|
+
modelPrompt = replaceImagePathWithMarker(modelPrompt, path, marker16);
|
|
146164
|
+
displayPrompt = replaceImagePathWithMarker(displayPrompt, path, marker16);
|
|
146165
|
+
}
|
|
145732
146166
|
const images = [];
|
|
145733
146167
|
for (const path of imagePaths) {
|
|
145734
146168
|
try {
|
|
145735
146169
|
images.push(loadImageAttachment(path));
|
|
145736
146170
|
} catch (e2) {
|
|
145737
|
-
notice(`couldn't attach ${path}: ${(e2?.message ?? String(e2)).split(`
|
|
146171
|
+
notice(`couldn't attach ${basename3(path)}: ${(e2?.message ?? String(e2)).split(`
|
|
145738
146172
|
`)[0]}`);
|
|
145739
146173
|
}
|
|
145740
146174
|
}
|
|
145741
146175
|
activeImagesRef.current = images;
|
|
145742
146176
|
if (images.length) {
|
|
145743
|
-
const names = images.map((img) =>
|
|
146177
|
+
const names = images.map((img) => imageMarkerFor(img.path)).join(", ");
|
|
145744
146178
|
notice(`attached ${images.length} image${images.length === 1 ? "" : "s"}: ${names}`);
|
|
145745
146179
|
}
|
|
146180
|
+
echo(displayPrompt);
|
|
146181
|
+
lastPromptRef.current = displayPrompt;
|
|
145746
146182
|
const urls = urlsInText(modelPrompt);
|
|
145747
146183
|
if (urls.length) {
|
|
145748
146184
|
const fetched = [];
|
|
@@ -146267,11 +146703,27 @@ ${fetched.join(`
|
|
|
146267
146703
|
if (cli) {
|
|
146268
146704
|
const cr = resolveCliModel(cli.binary, arg);
|
|
146269
146705
|
if (!cr.ok) {
|
|
146706
|
+
const r3 = resolveModelSwitch(arg);
|
|
146707
|
+
if (r3.ok && r3.modelId) {
|
|
146708
|
+
const left = leaveSubscription();
|
|
146709
|
+
setSelector(new FixedSelector(r3.modelId));
|
|
146710
|
+
setLastPick(null);
|
|
146711
|
+
routedRef.current = null;
|
|
146712
|
+
updatePrefs({ pinnedModel: r3.modelId });
|
|
146713
|
+
const newSpec2 = findModel(r3.modelId);
|
|
146714
|
+
const effortSuffix2 = applyEffortClamp(newSpec2 ? effortLevels(newSpec2) : []);
|
|
146715
|
+
notice(`${r3.message} — pinned (left subscription).${left}${effortSuffix2}`);
|
|
146716
|
+
const kind = classify(lastPromptRef.current ?? "").replace("code", "code");
|
|
146717
|
+
push({ kind: "preference", id: idRef.current++, text: `Remember ${r3.modelId} for ${kind} tasks?`, acceptCommand: `/prefer ${kind} ${r3.modelId}` });
|
|
146718
|
+
return;
|
|
146719
|
+
}
|
|
146270
146720
|
notice(cr.message);
|
|
146271
146721
|
return;
|
|
146272
146722
|
}
|
|
146273
146723
|
setActiveCliModelId(cr.modelId);
|
|
146274
|
-
|
|
146724
|
+
const newCliModel = cliModelChoices(cli.binary).find((m2) => m2.id === cr.modelId);
|
|
146725
|
+
const effortSuffix = applyEffortClamp(newCliModel?.efforts ?? []);
|
|
146726
|
+
notice(`subscription model → ${cr.label} — using ${cli.binary}; tools and permissions still owned by the subscription${effortSuffix}`);
|
|
146275
146727
|
return;
|
|
146276
146728
|
}
|
|
146277
146729
|
const r2 = resolveModelSwitch(arg);
|
|
@@ -146281,7 +146733,9 @@ ${fetched.join(`
|
|
|
146281
146733
|
setLastPick(null);
|
|
146282
146734
|
routedRef.current = null;
|
|
146283
146735
|
updatePrefs({ pinnedModel: r2.modelId });
|
|
146284
|
-
|
|
146736
|
+
const newSpec = findModel(r2.modelId);
|
|
146737
|
+
const effortSuffix = applyEffortClamp(newSpec ? effortLevels(newSpec) : []);
|
|
146738
|
+
notice(`${r2.message} — pinned (persists across sessions). /model auto to route per task again.${left}${effortSuffix}`);
|
|
146285
146739
|
const kind = classify(lastPromptRef.current ?? "").replace("code", "code");
|
|
146286
146740
|
push({ kind: "preference", id: idRef.current++, text: `Remember ${r2.modelId} for ${kind} tasks?`, acceptCommand: `/prefer ${kind} ${r2.modelId}` });
|
|
146287
146741
|
} else {
|
|
@@ -146348,6 +146802,54 @@ ${fetched.join(`
|
|
|
146348
146802
|
}
|
|
146349
146803
|
return;
|
|
146350
146804
|
}
|
|
146805
|
+
case "mcp": {
|
|
146806
|
+
echo(text2);
|
|
146807
|
+
const parts = shellSplit(arg);
|
|
146808
|
+
const sub = (parts[0] ?? "list").toLowerCase();
|
|
146809
|
+
if (sub === "list" || sub === "servers") {
|
|
146810
|
+
notice(formatMcpConfigList());
|
|
146811
|
+
return;
|
|
146812
|
+
}
|
|
146813
|
+
if (sub === "tools") {
|
|
146814
|
+
notice("checking MCP servers…");
|
|
146815
|
+
mcpToolSummary().then(notice).catch((e2) => notice(`couldn't list MCP tools: ${e2?.message ?? String(e2)}`));
|
|
146816
|
+
return;
|
|
146817
|
+
}
|
|
146818
|
+
if (sub === "paths") {
|
|
146819
|
+
notice(mcpConfigPaths().join(`
|
|
146820
|
+
`));
|
|
146821
|
+
return;
|
|
146822
|
+
}
|
|
146823
|
+
if (sub === "add") {
|
|
146824
|
+
const global2 = parts[1] === "--global";
|
|
146825
|
+
const offset = global2 ? 2 : 1;
|
|
146826
|
+
const serverName = parts[offset] ?? "";
|
|
146827
|
+
const command = parts[offset + 1] ?? "";
|
|
146828
|
+
const commandArgs = parts.slice(offset + 2);
|
|
146829
|
+
try {
|
|
146830
|
+
notice(addMcpServer(serverName, command, commandArgs, { scope: global2 ? "global" : "project" }) + `
|
|
146831
|
+
Restarting is not required; new turns can use the tools.`);
|
|
146832
|
+
} catch (e2) {
|
|
146833
|
+
notice(`${e2?.message ?? String(e2)}
|
|
146834
|
+
Example: /mcp add github npx -y @modelcontextprotocol/server-github`);
|
|
146835
|
+
}
|
|
146836
|
+
return;
|
|
146837
|
+
}
|
|
146838
|
+
if (sub === "remove" || sub === "rm") {
|
|
146839
|
+
const global2 = parts[1] === "--global";
|
|
146840
|
+
const name50 = parts[global2 ? 2 : 1] ?? "";
|
|
146841
|
+
notice(removeMcpServer(name50, { scope: global2 ? "global" : undefined }));
|
|
146842
|
+
return;
|
|
146843
|
+
}
|
|
146844
|
+
notice(`MCP commands:
|
|
146845
|
+
` + ` /mcp list
|
|
146846
|
+
` + ` /mcp tools
|
|
146847
|
+
` + ` /mcp add <name> <command> [args...]
|
|
146848
|
+
` + ` /mcp add --global <name> <command> [args...]
|
|
146849
|
+
` + ` /mcp remove <name>
|
|
146850
|
+
` + " /mcp paths");
|
|
146851
|
+
return;
|
|
146852
|
+
}
|
|
146351
146853
|
case "accounts":
|
|
146352
146854
|
case "account": {
|
|
146353
146855
|
echo(text2);
|
|
@@ -146498,6 +147000,7 @@ ${fetched.join(`
|
|
|
146498
147000
|
` + ` /account add codex <name> a 2nd ChatGPT account, e.g. /account add codex work
|
|
146499
147001
|
` + ` /account add azure <foundry-endpoint> <api-key>
|
|
146500
147002
|
` + ` /account add azure <resource-name> <api-key> [api-version]
|
|
147003
|
+
` + ` /account add openai-compat <name> <base-url> <api-key> <model> [model...]
|
|
146501
147004
|
` + ` /account add <api-key> paste any provider key (auto-detected)
|
|
146502
147005
|
` + " /account add <provider> <api-key> e.g. anthropic, openai, openrouter");
|
|
146503
147006
|
return;
|
|
@@ -146509,6 +147012,10 @@ ${fetched.join(`
|
|
|
146509
147012
|
const azureKey = parts[3] ?? "";
|
|
146510
147013
|
const apiVersion = parts[4];
|
|
146511
147014
|
res = /^https?:\/\//i.test(resource) ? await addAzureFoundryAccount(resource, azureKey) : await addAzureAccount(resource, azureKey, { apiVersion });
|
|
147015
|
+
} else if (["openai-compat", "openai-compatible", "custom", "proxy"].includes(first)) {
|
|
147016
|
+
res = await addOpenAICompatAccount(parts[2] ?? "", parts[3] ?? "", parts[4] ?? "", parts.slice(5));
|
|
147017
|
+
} else if (catalogProvider(first)?.authKind === "openai-compat" && !catalogProvider(first)?.baseUrl && /^https?:\/\//i.test(parts[2] ?? "")) {
|
|
147018
|
+
res = await addOpenAICompatAccount(first, parts[2] ?? "", parts[3] ?? "", parts.slice(4));
|
|
146512
147019
|
} else if (provGiven)
|
|
146513
147020
|
res = await addApiKeyAccount(provGiven, keyVal);
|
|
146514
147021
|
else if (detectProviderByKey(key))
|
|
@@ -146577,7 +147084,7 @@ ${fetched.join(`
|
|
|
146577
147084
|
case "usage": {
|
|
146578
147085
|
echo(text2);
|
|
146579
147086
|
const accounts = listAccounts();
|
|
146580
|
-
const
|
|
147087
|
+
const resolve13 = (id) => {
|
|
146581
147088
|
const a = getAccount(id);
|
|
146582
147089
|
if (a) {
|
|
146583
147090
|
const bin = a.auth.kind === "cli" ? a.auth.binary : undefined;
|
|
@@ -146595,7 +147102,7 @@ ${fetched.join(`
|
|
|
146595
147102
|
const session = estimateCost(sessionRef.current.turns);
|
|
146596
147103
|
const withBalance = accounts.filter((a) => a.exec !== "cli" && balanceExposed(a.provider));
|
|
146597
147104
|
if (!withBalance.length) {
|
|
146598
|
-
pushUsage(buildUsageView(session,
|
|
147105
|
+
pushUsage(buildUsageView(session, resolve13, Date.now(), accounts.map((a) => a.id)));
|
|
146599
147106
|
return;
|
|
146600
147107
|
}
|
|
146601
147108
|
notice("checking balances…");
|
|
@@ -146605,7 +147112,7 @@ ${fetched.join(`
|
|
|
146605
147112
|
if (bal?.remainingUSD != null)
|
|
146606
147113
|
recordBalance(a.id, bal);
|
|
146607
147114
|
}
|
|
146608
|
-
pushUsage(buildUsageView(session,
|
|
147115
|
+
pushUsage(buildUsageView(session, resolve13, Date.now(), accounts.map((a) => a.id)));
|
|
146609
147116
|
})();
|
|
146610
147117
|
return;
|
|
146611
147118
|
}
|
|
@@ -146941,8 +147448,15 @@ ${fetched.join(`
|
|
|
146941
147448
|
if (!busyRef.current && input.length > 3 && !input.includes(`
|
|
146942
147449
|
`)) {
|
|
146943
147450
|
const p = sanitizeInputText(input).trim().replace(/^'|'$/g, "").replace(/\\ /g, " ");
|
|
146944
|
-
|
|
147451
|
+
const abs = p.startsWith("~") ? p.replace(/^~/, process.env.HOME ?? "~") : resolve12(process.cwd(), p);
|
|
147452
|
+
if (/[/\\.]/.test(p) && p.length < 1024 && existsSync11(abs)) {
|
|
146945
147453
|
const e2 = editRef.current;
|
|
147454
|
+
if (isImageFilePath(abs)) {
|
|
147455
|
+
const marker16 = imageMarkerFor(abs);
|
|
147456
|
+
setEdit({ value: e2.value.slice(0, e2.cursor) + marker16 + " " + e2.value.slice(e2.cursor), cursor: e2.cursor + marker16.length + 1 });
|
|
147457
|
+
flashStatus(`attached ${basename3(abs)}`);
|
|
147458
|
+
return;
|
|
147459
|
+
}
|
|
146946
147460
|
const ins = `@${p} `;
|
|
146947
147461
|
setEdit({ value: e2.value.slice(0, e2.cursor) + ins + e2.value.slice(e2.cursor), cursor: e2.cursor + ins.length });
|
|
146948
147462
|
return;
|
|
@@ -147272,7 +147786,7 @@ ${fetched.join(`
|
|
|
147272
147786
|
cost: estimateCost(sessionRef.current.turns),
|
|
147273
147787
|
width,
|
|
147274
147788
|
mode: mode2,
|
|
147275
|
-
effort,
|
|
147789
|
+
effort: displayEffort,
|
|
147276
147790
|
online
|
|
147277
147791
|
}, undefined, false, undefined, this),
|
|
147278
147792
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
@@ -147297,7 +147811,7 @@ ${fetched.join(`
|
|
|
147297
147811
|
children: [
|
|
147298
147812
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Banner, {
|
|
147299
147813
|
model: modelLabel,
|
|
147300
|
-
cwd:
|
|
147814
|
+
cwd: basename3(process.cwd()),
|
|
147301
147815
|
width
|
|
147302
147816
|
}, undefined, false, undefined, this),
|
|
147303
147817
|
welcome ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
@@ -147321,7 +147835,7 @@ ${fetched.join(`
|
|
|
147321
147835
|
}
|
|
147322
147836
|
const banner = /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Banner, {
|
|
147323
147837
|
model: modelLabel,
|
|
147324
|
-
cwd:
|
|
147838
|
+
cwd: basename3(process.cwd()),
|
|
147325
147839
|
width
|
|
147326
147840
|
}, undefined, false, undefined, this);
|
|
147327
147841
|
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
@@ -147353,7 +147867,7 @@ init_permission();
|
|
|
147353
147867
|
var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
|
|
147354
147868
|
process.env.LANG = process.env.LANG || "en_US.UTF-8";
|
|
147355
147869
|
process.env.LC_ALL = process.env.LC_ALL || "en_US.UTF-8";
|
|
147356
|
-
var VERSION16 = "0.1.
|
|
147870
|
+
var VERSION16 = "0.1.18";
|
|
147357
147871
|
var args = process.argv.slice(2);
|
|
147358
147872
|
var supportsAnsi = process.env.FORCE_COLOR === "1" || process.env.TERM !== "dumb" && process.env.NO_COLOR !== "1" && process.stdout.isTTY;
|
|
147359
147873
|
var ansi = (code) => supportsAnsi ? `\x1B[${code}m` : "";
|
|
@@ -147582,8 +148096,8 @@ async function readStdin() {
|
|
|
147582
148096
|
return input;
|
|
147583
148097
|
}
|
|
147584
148098
|
if (args[0] === "upgrade" || args[0] === "update") {
|
|
147585
|
-
const root2 =
|
|
147586
|
-
if (!existsSync12(
|
|
148099
|
+
const root2 = resolve13(import.meta.dir, "..");
|
|
148100
|
+
if (!existsSync12(resolve13(root2, ".git"))) {
|
|
147587
148101
|
console.log("This build can't self-update (not a git checkout).");
|
|
147588
148102
|
console.log("Update by pulling the repo and reinstalling: git pull && bun install");
|
|
147589
148103
|
process.exit(0);
|
|
@@ -147608,7 +148122,8 @@ Usage:
|
|
|
147608
148122
|
gearbox onboard set up a provider before opening the app
|
|
147609
148123
|
gearbox --model <name> start with a specific model
|
|
147610
148124
|
gearbox --continue resume the most recent session in this directory
|
|
147611
|
-
gearbox mcp list show configured MCP
|
|
148125
|
+
gearbox mcp list show configured MCP servers
|
|
148126
|
+
gearbox mcp add <name> <command> [args...]
|
|
147612
148127
|
gearbox doctor models show provider/model capability matrix
|
|
147613
148128
|
gearbox upgrade pull the latest version + reinstall deps
|
|
147614
148129
|
|
|
@@ -147625,11 +148140,12 @@ Set up at least one provider first:
|
|
|
147625
148140
|
gearbox onboard
|
|
147626
148141
|
gearbox auth add <api-key>
|
|
147627
148142
|
gearbox auth add <provider> <api-key>
|
|
148143
|
+
gearbox auth add openai-compat <name> <base-url> <api-key> <model>
|
|
147628
148144
|
gearbox auth add codex [name]
|
|
147629
148145
|
gearbox auth add claude [name]
|
|
147630
148146
|
gearbox auth import
|
|
147631
148147
|
|
|
147632
|
-
Models: ${
|
|
148148
|
+
Models: ${modelRegistry().map((m2) => m2.label).join(", ")}
|
|
147633
148149
|
In-app: / for commands, @ for files, !cmd for shell, shift+tab for plan mode.`);
|
|
147634
148150
|
process.exit(0);
|
|
147635
148151
|
}
|
|
@@ -147642,15 +148158,31 @@ if (args[0] === "onboard" || args[0] === "setup") {
|
|
|
147642
148158
|
process.exit(0);
|
|
147643
148159
|
}
|
|
147644
148160
|
if (args[0] === "mcp") {
|
|
147645
|
-
const { mcpToolSummary: mcpToolSummary2, mcpConfigPaths: mcpConfigPaths2 } = await Promise.resolve().then(() => (init_mcp(), exports_mcp));
|
|
148161
|
+
const { addMcpServer: addMcpServer2, formatMcpConfigList: formatMcpConfigList2, mcpToolSummary: mcpToolSummary2, mcpConfigPaths: mcpConfigPaths2, removeMcpServer: removeMcpServer2 } = await Promise.resolve().then(() => (init_mcp(), exports_mcp));
|
|
147646
148162
|
const sub = args[1] ?? "list";
|
|
147647
148163
|
if (sub === "list" || sub === "tools") {
|
|
147648
|
-
|
|
148164
|
+
if (sub === "tools")
|
|
148165
|
+
console.log(await mcpToolSummary2());
|
|
148166
|
+
else
|
|
148167
|
+
console.log(formatMcpConfigList2());
|
|
147649
148168
|
} else if (sub === "paths") {
|
|
147650
148169
|
console.log(mcpConfigPaths2().join(`
|
|
147651
148170
|
`));
|
|
148171
|
+
} else if (sub === "add") {
|
|
148172
|
+
const global2 = args[2] === "--global";
|
|
148173
|
+
const offset = global2 ? 3 : 2;
|
|
148174
|
+
try {
|
|
148175
|
+
console.log(addMcpServer2(args[offset] ?? "", args[offset + 1] ?? "", args.slice(offset + 2), { scope: global2 ? "global" : "project" }));
|
|
148176
|
+
} catch (e2) {
|
|
148177
|
+
console.log(e2?.message ?? String(e2));
|
|
148178
|
+
console.log("example: gearbox mcp add github npx -y @modelcontextprotocol/server-github");
|
|
148179
|
+
process.exit(1);
|
|
148180
|
+
}
|
|
148181
|
+
} else if (sub === "remove" || sub === "rm") {
|
|
148182
|
+
const global2 = args[2] === "--global";
|
|
148183
|
+
console.log(removeMcpServer2(args[global2 ? 3 : 2] ?? "", { scope: global2 ? "global" : undefined }));
|
|
147652
148184
|
} else {
|
|
147653
|
-
console.log("gearbox mcp [list|paths]");
|
|
148185
|
+
console.log("gearbox mcp [list|tools|paths|add <name> <command> [args...]|remove <name>]");
|
|
147654
148186
|
}
|
|
147655
148187
|
process.exit(0);
|
|
147656
148188
|
}
|
|
@@ -147667,7 +148199,7 @@ if (args[0] === "doctor") {
|
|
|
147667
148199
|
if (args[0] === "auth") {
|
|
147668
148200
|
const { listAccounts: listAccounts2, loadAccounts: loadAccounts3, removeAccount: removeAccount2 } = await Promise.resolve().then(() => (init_store(), exports_store));
|
|
147669
148201
|
const { importableEnvCreds: importableEnvCreds2, importEnvCred: importEnvCred2, importableCloudCreds: importableCloudCreds2, importCloudCred: importCloudCred2 } = await Promise.resolve().then(() => (init_detect(), exports_detect));
|
|
147670
|
-
const { addApiKeyAccount: addApiKeyAccount2, addByPastedKey: addByPastedKey2, testAccount: testAccount2, addableProviders: addableProviders2, addCliAccount: addCliAccount2, cliAuthStatus: cliAuthStatus2, cliLoginArgs: cliLoginArgs2 } = await Promise.resolve().then(() => (init_onboard(), exports_onboard));
|
|
148202
|
+
const { addApiKeyAccount: addApiKeyAccount2, addByPastedKey: addByPastedKey2, addOpenAICompatAccount: addOpenAICompatAccount2, testAccount: testAccount2, addableProviders: addableProviders2, addCliAccount: addCliAccount2, cliAuthStatus: cliAuthStatus2, cliLoginArgs: cliLoginArgs2 } = await Promise.resolve().then(() => (init_onboard(), exports_onboard));
|
|
147671
148203
|
const { subscriptionEnv: subscriptionEnv2 } = await Promise.resolve().then(() => (init_cli_backend(), exports_cli_backend));
|
|
147672
148204
|
const { detectProviderByKey: detectProviderByKey2 } = await Promise.resolve().then(() => (init_catalog(), exports_catalog));
|
|
147673
148205
|
const sub = args[1];
|
|
@@ -147694,7 +148226,7 @@ Importable from your env (gearbox auth import): ${imp.map((c) => c.envVar).join(
|
|
|
147694
148226
|
} else if (sub === "add") {
|
|
147695
148227
|
const head2 = (rest2[0] ?? "").toLowerCase();
|
|
147696
148228
|
const cliProvider = head2 === "codex" || head2 === "chatgpt" ? "codex-cli" : head2 === "claude" ? "claude-cli" : "";
|
|
147697
|
-
const res = cliProvider ? addCliAccount2(cliProvider, rest2.slice(1).join(" ").trim() || undefined) : 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> | gearbox auth add codex [name]" };
|
|
148229
|
+
const res = cliProvider ? addCliAccount2(cliProvider, rest2.slice(1).join(" ").trim() || undefined) : ["openai-compat", "openai-compatible", "custom", "proxy"].includes(head2) ? await addOpenAICompatAccount2(rest2[1] ?? "", rest2[2] ?? "", rest2[3] ?? "", rest2.slice(4)) : 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> | gearbox auth add openai-compat <name> <base-url> <key> <model> | gearbox auth add codex [name]" };
|
|
147698
148230
|
console.log(res.message);
|
|
147699
148231
|
if (res.ok && res.account) {
|
|
147700
148232
|
if (res.account.exec === "cli" && res.account.auth.kind === "cli") {
|