@corbat-tech/coco 2.33.2 → 2.34.0
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/index.js +396 -58
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +237 -48
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -158,6 +158,19 @@ function getProxyFromSystem(platform = process.platform, run = defaultRunner) {
|
|
|
158
158
|
}
|
|
159
159
|
return null;
|
|
160
160
|
}
|
|
161
|
+
function detectPacProxy(run = defaultRunner, platform = process.platform) {
|
|
162
|
+
if (platform !== "darwin") return null;
|
|
163
|
+
const out = run("scutil", ["--proxy"]);
|
|
164
|
+
if (!out) return null;
|
|
165
|
+
const getField = (name) => {
|
|
166
|
+
const re = new RegExp(`^\\s*${name}\\s*:\\s*(.+?)\\s*$`, "m");
|
|
167
|
+
return out.match(re)?.[1];
|
|
168
|
+
};
|
|
169
|
+
if (getField("ProxyAutoConfigEnable") === "1") {
|
|
170
|
+
return getField("ProxyAutoConfigURLString") ?? "PAC script";
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
161
174
|
function installProxyDispatcher(resolveSystem = () => getProxyFromSystem()) {
|
|
162
175
|
if (installed) {
|
|
163
176
|
const existing = getProxyFromEnv();
|
|
@@ -1706,6 +1719,44 @@ function isCopilotTokenExpired(creds) {
|
|
|
1706
1719
|
if (!creds.copilotToken || !creds.copilotTokenExpiresAt) return true;
|
|
1707
1720
|
return Date.now() >= creds.copilotTokenExpiresAt - REFRESH_BUFFER_MS;
|
|
1708
1721
|
}
|
|
1722
|
+
function exchangeForCopilotTokenViaGhCli() {
|
|
1723
|
+
return new Promise((resolve4) => {
|
|
1724
|
+
execFile("gh", ["api", "/copilot_internal/v2/token"], { timeout: 1e4 }, (err, stdout) => {
|
|
1725
|
+
if (err || !stdout) {
|
|
1726
|
+
resolve4(null);
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
try {
|
|
1730
|
+
const parsed = JSON.parse(stdout);
|
|
1731
|
+
resolve4(parsed.token && parsed.expires_at ? parsed : null);
|
|
1732
|
+
} catch {
|
|
1733
|
+
resolve4(null);
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
function getGitHubCliAuthStatus() {
|
|
1739
|
+
return new Promise((resolve4) => {
|
|
1740
|
+
execFile(
|
|
1741
|
+
"gh",
|
|
1742
|
+
["auth", "status", "--hostname", "github.com"],
|
|
1743
|
+
{ timeout: 5e3 },
|
|
1744
|
+
(_err, stdout, stderr) => {
|
|
1745
|
+
const combined = (stdout ?? "") + (stderr ?? "");
|
|
1746
|
+
const match = combined.match(/Logged in to github\.com account (\S+)/);
|
|
1747
|
+
if (match) {
|
|
1748
|
+
resolve4(match[1]);
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
if (combined.includes("Logged in")) {
|
|
1752
|
+
resolve4("authenticated");
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
resolve4(null);
|
|
1756
|
+
}
|
|
1757
|
+
);
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1709
1760
|
async function getValidCopilotToken() {
|
|
1710
1761
|
const creds = await loadCopilotCredentials();
|
|
1711
1762
|
const envToken = process.env["COPILOT_GITHUB_TOKEN"] || process.env["GH_TOKEN"] || process.env["GITHUB_TOKEN"];
|
|
@@ -1719,8 +1770,7 @@ async function getValidCopilotToken() {
|
|
|
1719
1770
|
isNew: false
|
|
1720
1771
|
};
|
|
1721
1772
|
}
|
|
1722
|
-
|
|
1723
|
-
const copilotToken = await exchangeForCopilotToken(githubToken);
|
|
1773
|
+
const saveAndReturn = async (copilotToken) => {
|
|
1724
1774
|
const updatedCreds = {
|
|
1725
1775
|
...creds ?? { githubToken },
|
|
1726
1776
|
githubToken: creds?.githubToken ?? githubToken,
|
|
@@ -1734,11 +1784,23 @@ async function getValidCopilotToken() {
|
|
|
1734
1784
|
baseUrl: getCopilotBaseUrl(updatedCreds.accountType),
|
|
1735
1785
|
isNew: true
|
|
1736
1786
|
};
|
|
1787
|
+
};
|
|
1788
|
+
try {
|
|
1789
|
+
const copilotToken = await exchangeForCopilotToken(githubToken);
|
|
1790
|
+
return saveAndReturn(copilotToken);
|
|
1737
1791
|
} catch (error) {
|
|
1738
1792
|
if (error instanceof CopilotAuthError && error.permanent) {
|
|
1793
|
+
const ghCliToken2 = await exchangeForCopilotTokenViaGhCli();
|
|
1794
|
+
if (ghCliToken2) {
|
|
1795
|
+
return saveAndReturn(ghCliToken2);
|
|
1796
|
+
}
|
|
1739
1797
|
await deleteCopilotCredentials();
|
|
1740
1798
|
return null;
|
|
1741
1799
|
}
|
|
1800
|
+
const ghCliToken = await exchangeForCopilotTokenViaGhCli();
|
|
1801
|
+
if (ghCliToken) {
|
|
1802
|
+
return saveAndReturn(ghCliToken);
|
|
1803
|
+
}
|
|
1742
1804
|
throw error;
|
|
1743
1805
|
}
|
|
1744
1806
|
}
|
|
@@ -2310,6 +2372,51 @@ async function runApiKeyFlow(provider) {
|
|
|
2310
2372
|
console.log(chalk.green("\n \u2705 API key saved!\n"));
|
|
2311
2373
|
return { tokens, accessToken: apiKey };
|
|
2312
2374
|
}
|
|
2375
|
+
async function runCopilotAuthViaGhCli(ghCliUser) {
|
|
2376
|
+
const spinner18 = p26.spinner();
|
|
2377
|
+
spinner18.start("Exchanging GitHub CLI credentials for Copilot token...");
|
|
2378
|
+
try {
|
|
2379
|
+
const githubToken = await getGitHubCliToken();
|
|
2380
|
+
if (!githubToken) {
|
|
2381
|
+
spinner18.stop(chalk.red("\u2717 Could not read gh auth token"));
|
|
2382
|
+
return null;
|
|
2383
|
+
}
|
|
2384
|
+
let copilotToken;
|
|
2385
|
+
try {
|
|
2386
|
+
copilotToken = await exchangeForCopilotToken(githubToken);
|
|
2387
|
+
} catch {
|
|
2388
|
+
copilotToken = await exchangeForCopilotTokenViaGhCli();
|
|
2389
|
+
}
|
|
2390
|
+
if (!copilotToken) {
|
|
2391
|
+
spinner18.stop(chalk.red("\u2717 Could not obtain Copilot token via gh CLI"));
|
|
2392
|
+
console.log(chalk.dim(" Ensure your GitHub account has an active Copilot subscription:"));
|
|
2393
|
+
console.log(chalk.cyan(" \u2192 https://github.com/settings/copilot"));
|
|
2394
|
+
return null;
|
|
2395
|
+
}
|
|
2396
|
+
const creds = {
|
|
2397
|
+
githubToken,
|
|
2398
|
+
copilotToken: copilotToken.token,
|
|
2399
|
+
copilotTokenExpiresAt: copilotToken.expires_at * 1e3,
|
|
2400
|
+
accountType: copilotToken.annotations?.copilot_plan
|
|
2401
|
+
};
|
|
2402
|
+
await saveCopilotCredentials(creds);
|
|
2403
|
+
spinner18.stop(chalk.green("\u2713 GitHub Copilot authenticated via gh CLI!"));
|
|
2404
|
+
const userLabel = ghCliUser !== "authenticated" ? ` (@${ghCliUser})` : "";
|
|
2405
|
+
console.log(chalk.dim(` Account${userLabel} \xB7 Plan: ${creds.accountType ?? "individual"}`));
|
|
2406
|
+
console.log(chalk.dim(" Credentials stored in ~/.coco/tokens/copilot.json\n"));
|
|
2407
|
+
const tokens = {
|
|
2408
|
+
accessToken: copilotToken.token,
|
|
2409
|
+
tokenType: "Bearer",
|
|
2410
|
+
expiresAt: copilotToken.expires_at * 1e3
|
|
2411
|
+
};
|
|
2412
|
+
return { tokens, accessToken: copilotToken.token };
|
|
2413
|
+
} catch (error) {
|
|
2414
|
+
const { code } = describeFetchError(error);
|
|
2415
|
+
spinner18.stop(chalk.red("\u2717 Failed to authenticate via gh CLI"));
|
|
2416
|
+
printNetworkTroubleshooting(code);
|
|
2417
|
+
return null;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2313
2420
|
async function runCopilotDeviceFlow() {
|
|
2314
2421
|
console.log();
|
|
2315
2422
|
console.log(chalk.magenta(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
|
|
@@ -2321,6 +2428,21 @@ async function runCopilotDeviceFlow() {
|
|
|
2321
2428
|
console.log(chalk.dim(" Requires an active GitHub Copilot subscription."));
|
|
2322
2429
|
console.log(chalk.dim(" https://github.com/settings/copilot"));
|
|
2323
2430
|
console.log();
|
|
2431
|
+
const ghCliUser = await getGitHubCliAuthStatus();
|
|
2432
|
+
if (ghCliUser) {
|
|
2433
|
+
console.log(
|
|
2434
|
+
chalk.dim(` \u2139 GitHub CLI session detected`) + (ghCliUser !== "authenticated" ? chalk.dim(` (@${ghCliUser})`) : "") + chalk.dim(".")
|
|
2435
|
+
);
|
|
2436
|
+
const useGhSession = await p26.confirm({
|
|
2437
|
+
message: "Use your existing `gh` session? (recommended on corporate networks)",
|
|
2438
|
+
initialValue: true
|
|
2439
|
+
});
|
|
2440
|
+
if (p26.isCancel(useGhSession)) return null;
|
|
2441
|
+
if (useGhSession) {
|
|
2442
|
+
return runCopilotAuthViaGhCli(ghCliUser);
|
|
2443
|
+
}
|
|
2444
|
+
console.log();
|
|
2445
|
+
}
|
|
2324
2446
|
try {
|
|
2325
2447
|
console.log(chalk.dim(" Requesting device code from GitHub..."));
|
|
2326
2448
|
const deviceCode = await requestGitHubDeviceCode();
|
|
@@ -2423,23 +2545,38 @@ async function runCopilotDeviceFlow() {
|
|
|
2423
2545
|
}
|
|
2424
2546
|
function printNetworkTroubleshooting(code) {
|
|
2425
2547
|
const proxy = getProxyFromEnv();
|
|
2548
|
+
const pacUrl = detectPacProxy();
|
|
2426
2549
|
if (proxy) {
|
|
2427
2550
|
console.log(chalk.dim(` Proxy in use: ${maskProxyUrl(proxy)}`));
|
|
2428
2551
|
console.log(chalk.dim(" \u2192 Verify the proxy allows github.com and api.github.com."));
|
|
2552
|
+
} else if (pacUrl) {
|
|
2553
|
+
console.log(
|
|
2554
|
+
chalk.dim(" Automatic proxy (PAC script) detected \u2014 Node.js cannot evaluate it.")
|
|
2555
|
+
);
|
|
2556
|
+
console.log(chalk.dim(" You have two options:"));
|
|
2557
|
+
console.log(chalk.dim(" 1. Run `gh auth login` first, then re-run /provider copilot."));
|
|
2558
|
+
console.log(
|
|
2559
|
+
chalk.dim(
|
|
2560
|
+
" Coco will reuse your `gh` session (Go HTTP client handles PAC automatically)."
|
|
2561
|
+
)
|
|
2562
|
+
);
|
|
2563
|
+
console.log(chalk.dim(" 2. Set HTTPS_PROXY=http://<your-proxy>:<port> manually and retry."));
|
|
2429
2564
|
} else {
|
|
2430
2565
|
console.log(chalk.dim(" No HTTPS_PROXY / HTTP_PROXY env vars detected."));
|
|
2431
2566
|
console.log(chalk.dim(" \u2192 If you're behind a corporate proxy, set HTTPS_PROXY and retry."));
|
|
2567
|
+
console.log(chalk.dim(" \u2192 Or run `gh auth login` first \u2014 Coco will reuse the gh session."));
|
|
2432
2568
|
}
|
|
2433
2569
|
if (code === "SELF_SIGNED_CERT_IN_CHAIN" || code === "UNABLE_TO_VERIFY_LEAF_SIGNATURE") {
|
|
2434
2570
|
console.log(
|
|
2435
2571
|
chalk.dim(
|
|
2436
|
-
" \u2192
|
|
2572
|
+
" \u2192 TLS interceptor detected. Add your corporate root CA to NODE_EXTRA_CA_CERTS."
|
|
2437
2573
|
)
|
|
2438
2574
|
);
|
|
2575
|
+
console.log(chalk.dim(" Example: NODE_EXTRA_CA_CERTS=/path/to/corp-ca.crt coco"));
|
|
2439
2576
|
} else if (code === "ENOTFOUND") {
|
|
2440
2577
|
console.log(chalk.dim(" \u2192 Check DNS: `nslookup github.com`"));
|
|
2441
2578
|
} else if (code === "ETIMEDOUT" || code === "UND_ERR_CONNECT_TIMEOUT") {
|
|
2442
|
-
console.log(chalk.dim(" \u2192 A firewall may be
|
|
2579
|
+
console.log(chalk.dim(" \u2192 A firewall may be blocking the connection. Try `gh auth login`."));
|
|
2443
2580
|
}
|
|
2444
2581
|
}
|
|
2445
2582
|
async function getOrRefreshOAuthToken(provider) {
|
|
@@ -2690,10 +2827,12 @@ __export(env_exports, {
|
|
|
2690
2827
|
getBaseUrl: () => getBaseUrl,
|
|
2691
2828
|
getDefaultModel: () => getDefaultModel,
|
|
2692
2829
|
getDefaultProvider: () => getDefaultProvider,
|
|
2830
|
+
getEditorModel: () => getEditorModel,
|
|
2693
2831
|
getInternalProviderId: () => getInternalProviderId,
|
|
2694
2832
|
getLastUsedModel: () => getLastUsedModel,
|
|
2695
2833
|
getLastUsedProvider: () => getLastUsedProvider,
|
|
2696
2834
|
getLastUsedThinking: () => getLastUsedThinking,
|
|
2835
|
+
getWeakModel: () => getWeakModel,
|
|
2697
2836
|
isOAuthProvider: () => isOAuthProvider,
|
|
2698
2837
|
migrateOldPreferences: () => migrateOldPreferences,
|
|
2699
2838
|
removeEnvProvider: () => removeEnvProvider,
|
|
@@ -3137,6 +3276,18 @@ async function migrateOldPreferences() {
|
|
|
3137
3276
|
} catch {
|
|
3138
3277
|
}
|
|
3139
3278
|
}
|
|
3279
|
+
function getEditorModel() {
|
|
3280
|
+
const raw = process.env["COCO_EDITOR_MODEL"]?.trim();
|
|
3281
|
+
if (!raw || raw.length === 0) return void 0;
|
|
3282
|
+
if (["none", "default", "null", "undefined"].includes(raw.toLowerCase())) return void 0;
|
|
3283
|
+
return raw;
|
|
3284
|
+
}
|
|
3285
|
+
function getWeakModel() {
|
|
3286
|
+
const raw = process.env["COCO_WEAK_MODEL"]?.trim();
|
|
3287
|
+
if (!raw || raw.length === 0) return void 0;
|
|
3288
|
+
if (["none", "default", "null", "undefined"].includes(raw.toLowerCase())) return void 0;
|
|
3289
|
+
return raw;
|
|
3290
|
+
}
|
|
3140
3291
|
var VALID_PROVIDERS, env;
|
|
3141
3292
|
var init_env = __esm({
|
|
3142
3293
|
"src/config/env.ts"() {
|
|
@@ -3166,7 +3317,9 @@ var init_env = __esm({
|
|
|
3166
3317
|
provider: getDefaultProvider(),
|
|
3167
3318
|
getApiKey,
|
|
3168
3319
|
getBaseUrl,
|
|
3169
|
-
getDefaultModel
|
|
3320
|
+
getDefaultModel,
|
|
3321
|
+
getWeakModel,
|
|
3322
|
+
getEditorModel
|
|
3170
3323
|
};
|
|
3171
3324
|
}
|
|
3172
3325
|
});
|
|
@@ -4208,6 +4361,134 @@ var init_tool_call_normalizer = __esm({
|
|
|
4208
4361
|
};
|
|
4209
4362
|
}
|
|
4210
4363
|
});
|
|
4364
|
+
|
|
4365
|
+
// src/providers/model-tier.ts
|
|
4366
|
+
function matchTier(model, table) {
|
|
4367
|
+
const lower = model.toLowerCase();
|
|
4368
|
+
const sorted = [...table].sort((a, b) => b.prefix.length - a.prefix.length);
|
|
4369
|
+
for (const { prefix, tier } of sorted) {
|
|
4370
|
+
if (lower.startsWith(prefix.toLowerCase())) return tier;
|
|
4371
|
+
}
|
|
4372
|
+
return null;
|
|
4373
|
+
}
|
|
4374
|
+
function getModelTier(provider, model) {
|
|
4375
|
+
if (!model) return "standard";
|
|
4376
|
+
const p47 = provider.toLowerCase();
|
|
4377
|
+
if (p47 === "anthropic") {
|
|
4378
|
+
return matchTier(model, ANTHROPIC_TIERS) ?? "standard";
|
|
4379
|
+
}
|
|
4380
|
+
if (p47 === "kimi-code") {
|
|
4381
|
+
return matchTier(model, KIMI_TIERS) ?? matchTier(model, ANTHROPIC_TIERS) ?? "standard";
|
|
4382
|
+
}
|
|
4383
|
+
if (p47 === "openai" || p47 === "copilot" || p47 === "codex") {
|
|
4384
|
+
if (model.startsWith("claude-")) {
|
|
4385
|
+
return matchTier(model, ANTHROPIC_TIERS) ?? "standard";
|
|
4386
|
+
}
|
|
4387
|
+
const evalMatch = matchTier(model, EVAL_TIERS);
|
|
4388
|
+
if (evalMatch) return evalMatch;
|
|
4389
|
+
return matchTier(model, OPENAI_TIERS) ?? "standard";
|
|
4390
|
+
}
|
|
4391
|
+
if (p47 === "gemini" || p47 === "vertex") {
|
|
4392
|
+
return matchTier(model, GEMINI_TIERS) ?? "standard";
|
|
4393
|
+
}
|
|
4394
|
+
if (p47 === "kimi" || p47 === "moonshot") {
|
|
4395
|
+
return matchTier(model, KIMI_TIERS) ?? "standard";
|
|
4396
|
+
}
|
|
4397
|
+
return "standard";
|
|
4398
|
+
}
|
|
4399
|
+
function getTierConfig(provider, model) {
|
|
4400
|
+
return TIER_CONFIGS[getModelTier(provider, model)];
|
|
4401
|
+
}
|
|
4402
|
+
var TIER_CONFIGS, ANTHROPIC_TIERS, OPENAI_TIERS, GEMINI_TIERS, KIMI_TIERS, EVAL_TIERS;
|
|
4403
|
+
var init_model_tier = __esm({
|
|
4404
|
+
"src/providers/model-tier.ts"() {
|
|
4405
|
+
TIER_CONFIGS = {
|
|
4406
|
+
mini: {
|
|
4407
|
+
maxTools: 12,
|
|
4408
|
+
parallelToolCalls: false,
|
|
4409
|
+
compactionThreshold: 0.5,
|
|
4410
|
+
supportsCoT: false
|
|
4411
|
+
},
|
|
4412
|
+
standard: {
|
|
4413
|
+
maxTools: 40,
|
|
4414
|
+
parallelToolCalls: true,
|
|
4415
|
+
compactionThreshold: 0.75,
|
|
4416
|
+
supportsCoT: true
|
|
4417
|
+
},
|
|
4418
|
+
advanced: {
|
|
4419
|
+
maxTools: 128,
|
|
4420
|
+
parallelToolCalls: true,
|
|
4421
|
+
compactionThreshold: 0.8,
|
|
4422
|
+
supportsCoT: true
|
|
4423
|
+
}
|
|
4424
|
+
};
|
|
4425
|
+
ANTHROPIC_TIERS = [
|
|
4426
|
+
// Haiku — mini tier
|
|
4427
|
+
{ prefix: "claude-haiku", tier: "mini" },
|
|
4428
|
+
{ prefix: "claude-3-haiku", tier: "mini" },
|
|
4429
|
+
// Sonnet / Claude 3.5 — standard tier
|
|
4430
|
+
{ prefix: "claude-3-5-sonnet", tier: "standard" },
|
|
4431
|
+
{ prefix: "claude-3-7-sonnet", tier: "standard" },
|
|
4432
|
+
{ prefix: "claude-sonnet", tier: "standard" },
|
|
4433
|
+
// Opus — advanced tier
|
|
4434
|
+
{ prefix: "claude-opus", tier: "advanced" },
|
|
4435
|
+
{ prefix: "claude-3-opus", tier: "advanced" }
|
|
4436
|
+
// claude-4+ (future) — default to standard unless matched above
|
|
4437
|
+
];
|
|
4438
|
+
OPENAI_TIERS = [
|
|
4439
|
+
// Mini models
|
|
4440
|
+
{ prefix: "gpt-4o-mini", tier: "mini" },
|
|
4441
|
+
{ prefix: "gpt-5-mini", tier: "mini" },
|
|
4442
|
+
{ prefix: "gpt-5.4-mini", tier: "mini" },
|
|
4443
|
+
{ prefix: "gpt-5.3-mini", tier: "mini" },
|
|
4444
|
+
{ prefix: "o1-mini", tier: "mini" },
|
|
4445
|
+
{ prefix: "o3-mini", tier: "mini" },
|
|
4446
|
+
// Advanced / reasoning models
|
|
4447
|
+
{ prefix: "o1", tier: "advanced" },
|
|
4448
|
+
{ prefix: "o3", tier: "advanced" },
|
|
4449
|
+
{ prefix: "o4", tier: "advanced" },
|
|
4450
|
+
{ prefix: "gpt-4.1", tier: "advanced" },
|
|
4451
|
+
{ prefix: "gpt-5.4-codex", tier: "advanced" },
|
|
4452
|
+
{ prefix: "gpt-5.3-codex", tier: "advanced" },
|
|
4453
|
+
{ prefix: "gpt-5.2-codex", tier: "advanced" },
|
|
4454
|
+
{ prefix: "gpt-5.1-codex", tier: "advanced" },
|
|
4455
|
+
{ prefix: "gpt-5.4", tier: "advanced" },
|
|
4456
|
+
{ prefix: "gpt-5.3", tier: "advanced" },
|
|
4457
|
+
{ prefix: "gpt-5.2", tier: "advanced" },
|
|
4458
|
+
{ prefix: "gpt-5.1", tier: "advanced" },
|
|
4459
|
+
// GPT-5 catch-all (non-mini/codex) — advanced
|
|
4460
|
+
{ prefix: "gpt-5", tier: "advanced" },
|
|
4461
|
+
// GPT-4o — standard
|
|
4462
|
+
{ prefix: "gpt-4o", tier: "standard" },
|
|
4463
|
+
// GPT-4 — standard
|
|
4464
|
+
{ prefix: "gpt-4", tier: "standard" }
|
|
4465
|
+
];
|
|
4466
|
+
GEMINI_TIERS = [
|
|
4467
|
+
// Flash — mini tier
|
|
4468
|
+
{ prefix: "gemini-3-flash", tier: "mini" },
|
|
4469
|
+
{ prefix: "gemini-2.5-flash", tier: "mini" },
|
|
4470
|
+
{ prefix: "gemini-2.0-flash", tier: "mini" },
|
|
4471
|
+
{ prefix: "gemini-1.5-flash", tier: "mini" },
|
|
4472
|
+
// Pro — standard/advanced
|
|
4473
|
+
{ prefix: "gemini-3.1-pro", tier: "advanced" },
|
|
4474
|
+
{ prefix: "gemini-3-pro", tier: "advanced" },
|
|
4475
|
+
{ prefix: "gemini-2.5-pro", tier: "standard" },
|
|
4476
|
+
{ prefix: "gemini-2.0-pro", tier: "standard" },
|
|
4477
|
+
{ prefix: "gemini-1.5-pro", tier: "standard" }
|
|
4478
|
+
];
|
|
4479
|
+
KIMI_TIERS = [
|
|
4480
|
+
{ prefix: "kimi-for-coding", tier: "advanced" },
|
|
4481
|
+
{ prefix: "kimi-k2", tier: "advanced" },
|
|
4482
|
+
{ prefix: "kimi-latest", tier: "standard" },
|
|
4483
|
+
{ prefix: "kimi", tier: "standard" }
|
|
4484
|
+
];
|
|
4485
|
+
EVAL_TIERS = [
|
|
4486
|
+
{ prefix: "grok-code", tier: "standard" },
|
|
4487
|
+
{ prefix: "raptor", tier: "mini" },
|
|
4488
|
+
{ prefix: "goldeneye", tier: "standard" }
|
|
4489
|
+
];
|
|
4490
|
+
}
|
|
4491
|
+
});
|
|
4211
4492
|
function needsResponsesApi(model) {
|
|
4212
4493
|
return model.includes("codex") || model.startsWith("gpt-5") || model.startsWith("o4-") || model === "o3";
|
|
4213
4494
|
}
|
|
@@ -4253,6 +4534,7 @@ var init_openai = __esm({
|
|
|
4253
4534
|
init_retry();
|
|
4254
4535
|
init_tool_call_normalizer();
|
|
4255
4536
|
init_thinking();
|
|
4537
|
+
init_model_tier();
|
|
4256
4538
|
DEFAULT_MODEL2 = "gpt-5.3-codex";
|
|
4257
4539
|
CONTEXT_WINDOWS2 = {
|
|
4258
4540
|
// OpenAI models
|
|
@@ -4474,18 +4756,21 @@ var init_openai = __esm({
|
|
|
4474
4756
|
if (this.modelNeedsResponsesApi(model)) {
|
|
4475
4757
|
return this.chatWithToolsViaResponses(messages, options);
|
|
4476
4758
|
}
|
|
4759
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
4477
4760
|
return withRetry(async () => {
|
|
4478
4761
|
try {
|
|
4479
4762
|
const supportsTemp = this.supportsTemperature(model);
|
|
4480
4763
|
const extraBody = this.getExtraBody(model, options?.thinking);
|
|
4481
4764
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4482
4765
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4766
|
+
const tools = this.limitTools(options.tools, tierCfg.maxTools);
|
|
4483
4767
|
const requestParams = {
|
|
4484
4768
|
model,
|
|
4485
4769
|
...buildMaxTokensParam(model, maxTokens),
|
|
4486
4770
|
messages: this.convertMessages(messages, options?.system),
|
|
4487
|
-
tools: this.convertTools(
|
|
4488
|
-
tool_choice: this.convertToolChoice(options.toolChoice)
|
|
4771
|
+
tools: this.convertTools(tools),
|
|
4772
|
+
tool_choice: this.convertToolChoice(options.toolChoice),
|
|
4773
|
+
parallel_tool_calls: tierCfg.parallelToolCalls
|
|
4489
4774
|
};
|
|
4490
4775
|
if (supportsTemp) {
|
|
4491
4776
|
requestParams.temperature = options?.temperature ?? this.config.temperature ?? 0;
|
|
@@ -4565,18 +4850,21 @@ var init_openai = __esm({
|
|
|
4565
4850
|
yield* this.streamWithToolsViaResponses(messages, options);
|
|
4566
4851
|
return;
|
|
4567
4852
|
}
|
|
4853
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
4568
4854
|
let timeoutTriggered = false;
|
|
4569
4855
|
try {
|
|
4570
4856
|
const supportsTemp = this.supportsTemperature(model);
|
|
4571
4857
|
const extraBody = this.getExtraBody(model, options?.thinking);
|
|
4572
4858
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4573
4859
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4860
|
+
const tools = this.limitTools(options.tools, tierCfg.maxTools);
|
|
4574
4861
|
const requestParams = {
|
|
4575
4862
|
model,
|
|
4576
4863
|
...buildMaxTokensParam(model, maxTokens),
|
|
4577
4864
|
messages: this.convertMessages(messages, options?.system),
|
|
4578
|
-
tools: this.convertTools(
|
|
4865
|
+
tools: this.convertTools(tools),
|
|
4579
4866
|
tool_choice: this.convertToolChoice(options.toolChoice),
|
|
4867
|
+
parallel_tool_calls: tierCfg.parallelToolCalls,
|
|
4580
4868
|
stream: true
|
|
4581
4869
|
};
|
|
4582
4870
|
if (supportsTemp) {
|
|
@@ -4946,6 +5234,17 @@ var init_openai = __esm({
|
|
|
4946
5234
|
}
|
|
4947
5235
|
return content.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
4948
5236
|
}
|
|
5237
|
+
/**
|
|
5238
|
+
* Limit the tool list to at most `max` entries.
|
|
5239
|
+
* Built-in tools (those without an `mcp_server` tag) are prioritised over
|
|
5240
|
+
* MCP tools so core capabilities are never dropped.
|
|
5241
|
+
*/
|
|
5242
|
+
limitTools(tools, max) {
|
|
5243
|
+
if (tools.length <= max) return tools;
|
|
5244
|
+
const builtin = tools.filter((t) => !("serverName" in t && t.serverName));
|
|
5245
|
+
const mcp = tools.filter((t) => "serverName" in t && t.serverName);
|
|
5246
|
+
return [...builtin, ...mcp].slice(0, max);
|
|
5247
|
+
}
|
|
4949
5248
|
/**
|
|
4950
5249
|
* Convert tools to OpenAI format
|
|
4951
5250
|
*/
|
|
@@ -4955,7 +5254,8 @@ var init_openai = __esm({
|
|
|
4955
5254
|
function: {
|
|
4956
5255
|
name: tool.name,
|
|
4957
5256
|
description: truncateToolDescription(tool.description),
|
|
4958
|
-
parameters: tool.input_schema
|
|
5257
|
+
parameters: tool.input_schema,
|
|
5258
|
+
strict: true
|
|
4959
5259
|
}
|
|
4960
5260
|
}));
|
|
4961
5261
|
}
|
|
@@ -5088,8 +5388,11 @@ var init_openai = __esm({
|
|
|
5088
5388
|
return withRetry(async () => {
|
|
5089
5389
|
try {
|
|
5090
5390
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
5391
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
5091
5392
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
5092
|
-
const tools = this.convertToolsForResponses(
|
|
5393
|
+
const tools = this.convertToolsForResponses(
|
|
5394
|
+
this.limitTools(options.tools, tierCfg.maxTools)
|
|
5395
|
+
);
|
|
5093
5396
|
const supportsTemp = this.supportsTemperature(model);
|
|
5094
5397
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
5095
5398
|
const response = await this.client.responses.create({
|
|
@@ -5209,8 +5512,10 @@ var init_openai = __esm({
|
|
|
5209
5512
|
let timeoutTriggered = false;
|
|
5210
5513
|
try {
|
|
5211
5514
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
5515
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
5212
5516
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
5213
|
-
const
|
|
5517
|
+
const limitedTools = this.limitTools(options.tools, tierCfg.maxTools);
|
|
5518
|
+
const tools = limitedTools.length > 0 ? this.convertToolsForResponses(limitedTools) : void 0;
|
|
5214
5519
|
const supportsTemp = this.supportsTemperature(model);
|
|
5215
5520
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
5216
5521
|
const requestParams = {
|
|
@@ -5442,7 +5747,7 @@ var init_openai = __esm({
|
|
|
5442
5747
|
name: tool.name,
|
|
5443
5748
|
description: tool.description ? truncateToolDescription(tool.description) : void 0,
|
|
5444
5749
|
parameters: tool.input_schema ?? null,
|
|
5445
|
-
strict:
|
|
5750
|
+
strict: true
|
|
5446
5751
|
}));
|
|
5447
5752
|
}
|
|
5448
5753
|
};
|
|
@@ -10022,7 +10327,8 @@ var init_compactor = __esm({
|
|
|
10022
10327
|
conversationText,
|
|
10023
10328
|
provider,
|
|
10024
10329
|
signal,
|
|
10025
|
-
options.focusTopic
|
|
10330
|
+
options.focusTopic,
|
|
10331
|
+
options.summaryModel
|
|
10026
10332
|
);
|
|
10027
10333
|
const systemMessages = messages.filter((m) => m.role === "system");
|
|
10028
10334
|
const summaryMessage = {
|
|
@@ -10077,14 +10383,15 @@ ${summary}
|
|
|
10077
10383
|
/**
|
|
10078
10384
|
* Generate a summary of the conversation using the LLM
|
|
10079
10385
|
*/
|
|
10080
|
-
async generateSummary(conversationText, provider, signal, focusTopic) {
|
|
10386
|
+
async generateSummary(conversationText, provider, signal, focusTopic, summaryModel) {
|
|
10081
10387
|
if (signal?.aborted) return "[Compaction cancelled]";
|
|
10082
10388
|
const prompt = buildCompactionPrompt(focusTopic) + conversationText;
|
|
10083
10389
|
try {
|
|
10084
10390
|
const chatPromise = provider.chat([{ role: "user", content: prompt }], {
|
|
10085
10391
|
maxTokens: this.config.summaryMaxTokens,
|
|
10086
|
-
temperature: 0.3
|
|
10392
|
+
temperature: 0.3,
|
|
10087
10393
|
// Lower temperature for more consistent summaries
|
|
10394
|
+
...summaryModel ? { model: summaryModel } : {}
|
|
10088
10395
|
});
|
|
10089
10396
|
if (signal) {
|
|
10090
10397
|
const abortPromise = new Promise((_, reject) => {
|
|
@@ -10980,6 +11287,14 @@ ${finalInstructions}`;
|
|
|
10980
11287
|
systemPrompt = `${systemPrompt}
|
|
10981
11288
|
|
|
10982
11289
|
${PLAN_MODE_SYSTEM_PROMPT}`;
|
|
11290
|
+
}
|
|
11291
|
+
const providerType = session.config.provider.type;
|
|
11292
|
+
const currentModel = session.config.provider.model ?? "";
|
|
11293
|
+
const tierCfg = getTierConfig(providerType, currentModel);
|
|
11294
|
+
if (!tierCfg.supportsCoT) {
|
|
11295
|
+
systemPrompt = `${systemPrompt}
|
|
11296
|
+
|
|
11297
|
+
${MINI_MODEL_ADDENDUM}`;
|
|
10983
11298
|
}
|
|
10984
11299
|
return [{ role: "system", content: systemPrompt }, ...session.messages];
|
|
10985
11300
|
}
|
|
@@ -11164,8 +11479,11 @@ async function initializeSessionTrust(session) {
|
|
|
11164
11479
|
}
|
|
11165
11480
|
function initializeContextManager(session, provider) {
|
|
11166
11481
|
const contextWindow = provider.getContextWindow();
|
|
11482
|
+
const providerType = session.config.provider.type;
|
|
11483
|
+
const model = session.config.provider.model ?? "";
|
|
11484
|
+
const tierCfg = getTierConfig(providerType, model);
|
|
11167
11485
|
session.contextManager = createContextManager(contextWindow, {
|
|
11168
|
-
compactionThreshold:
|
|
11486
|
+
compactionThreshold: tierCfg.compactionThreshold,
|
|
11169
11487
|
reservedTokens: 4096
|
|
11170
11488
|
});
|
|
11171
11489
|
}
|
|
@@ -11200,7 +11518,11 @@ async function checkAndCompactContext(session, provider, signal, toolRegistry) {
|
|
|
11200
11518
|
summaryMaxTokens: 1e3
|
|
11201
11519
|
});
|
|
11202
11520
|
try {
|
|
11203
|
-
const
|
|
11521
|
+
const summaryModel = session.config.provider.weakModel ?? session.config.provider.editorModel ?? getWeakModel() ?? getEditorModel();
|
|
11522
|
+
const result = await compactor.compact(session.messages, provider, {
|
|
11523
|
+
signal,
|
|
11524
|
+
...summaryModel ? { summaryModel } : {}
|
|
11525
|
+
});
|
|
11204
11526
|
if (result.wasCompacted) {
|
|
11205
11527
|
const compactedNonSystem = result.messages.filter((m) => m.role !== "system");
|
|
11206
11528
|
session.messages = compactedNonSystem;
|
|
@@ -11244,11 +11566,12 @@ function getSessionMemory(session) {
|
|
|
11244
11566
|
async function reloadSessionMemory(session) {
|
|
11245
11567
|
await initializeSessionMemory(session);
|
|
11246
11568
|
}
|
|
11247
|
-
var MAX_SKILL_INSTRUCTIONS_CHARS, TRUST_SETTINGS_DIR, TRUST_SETTINGS_FILE, PROJECT_TRUST_FILE_RELATIVE_PATH, CATEGORY_LABELS, COCO_SYSTEM_PROMPT, SHELL_METACHARACTERS, SAFE_COMMAND_VALIDATORS;
|
|
11569
|
+
var MAX_SKILL_INSTRUCTIONS_CHARS, TRUST_SETTINGS_DIR, TRUST_SETTINGS_FILE, PROJECT_TRUST_FILE_RELATIVE_PATH, CATEGORY_LABELS, COCO_SYSTEM_PROMPT, MINI_MODEL_ADDENDUM, SHELL_METACHARACTERS, SAFE_COMMAND_VALIDATORS;
|
|
11248
11570
|
var init_session = __esm({
|
|
11249
11571
|
"src/cli/repl/session.ts"() {
|
|
11250
11572
|
init_env();
|
|
11251
11573
|
init_thinking();
|
|
11574
|
+
init_model_tier();
|
|
11252
11575
|
init_manager();
|
|
11253
11576
|
init_compactor();
|
|
11254
11577
|
init_memory();
|
|
@@ -11446,6 +11769,17 @@ Responses are short and direct by default. Lead with the answer or action, not r
|
|
|
11446
11769
|
**During tool-calling iterations, keep text minimal.** A single short orienting line before tool calls is acceptable. Do NOT explain every step, narrate what you are about to do, or produce paragraphs between tool calls. Reserve explanatory text for your final response after all tools have completed.
|
|
11447
11770
|
|
|
11448
11771
|
**Code blocks in responses are expensive.** Only include a code block when the user explicitly asks to see code, or when the code IS the deliverable (e.g., a script to paste in a terminal). Never include a code block to "show your work" when you can write the file directly instead.`;
|
|
11772
|
+
MINI_MODEL_ADDENDUM = `
|
|
11773
|
+
## Mini-Model Mode
|
|
11774
|
+
|
|
11775
|
+
You are running on a fast, compact model. Keep outputs minimal and actions direct.
|
|
11776
|
+
|
|
11777
|
+
- Call ONE tool at a time. Do NOT combine multiple tool calls per turn.
|
|
11778
|
+
- Skip multi-step planning \u2014 just do the next concrete action.
|
|
11779
|
+
- Debugging: read the error, fix it, verify. No analysis phases.
|
|
11780
|
+
- Verification: run the command, report the result. No elaborate protocols.
|
|
11781
|
+
- Skip "Parallel Execution" \u2014 serialize all tool calls for reliability.
|
|
11782
|
+
- NEVER narrate your plan. NEVER explain what you are about to do. Just do it.`;
|
|
11449
11783
|
SHELL_METACHARACTERS = /[;|&`$(){}<>!\n\\'"]/;
|
|
11450
11784
|
SAFE_COMMAND_VALIDATORS = {
|
|
11451
11785
|
git: (args) => {
|
|
@@ -12589,13 +12923,21 @@ var init_registry4 = __esm({
|
|
|
12589
12923
|
const field = issue.path.join(".") || "input";
|
|
12590
12924
|
return `${field} (${issue.message.toLowerCase()})`;
|
|
12591
12925
|
});
|
|
12592
|
-
errorMessage = `Invalid tool input \u2014 ${fields.join(", ")}`;
|
|
12926
|
+
errorMessage = `Invalid tool input for '${name}' \u2014 ${fields.join(", ")}`;
|
|
12593
12927
|
const allUndefined = error.issues.every(
|
|
12594
12928
|
(i) => i.message.toLowerCase().includes("received undefined")
|
|
12595
12929
|
);
|
|
12596
12930
|
if (allUndefined && error.issues.length > 1) {
|
|
12597
12931
|
errorMessage += ". All parameters are missing \u2014 this is likely a JSON serialization error on our side. Please retry with the same arguments.";
|
|
12598
12932
|
}
|
|
12933
|
+
try {
|
|
12934
|
+
const schema = zodToJsonSchema(tool.parameters);
|
|
12935
|
+
errorMessage += `
|
|
12936
|
+
|
|
12937
|
+
Expected schema for '${name}':
|
|
12938
|
+
${JSON.stringify(schema, null, 2)}`;
|
|
12939
|
+
} catch {
|
|
12940
|
+
}
|
|
12599
12941
|
} else if (isCocoError(error)) {
|
|
12600
12942
|
const causeMsg = error.cause instanceof Error ? error.cause.message : "";
|
|
12601
12943
|
const isRawEnoent = causeMsg.startsWith("ENOENT:");
|
|
@@ -18701,7 +19043,7 @@ var init_git = __esm({
|
|
|
18701
19043
|
init_errors();
|
|
18702
19044
|
gitStatusTool = defineTool({
|
|
18703
19045
|
name: "git_status",
|
|
18704
|
-
description: `
|
|
19046
|
+
description: `Return the current git repository state: branch name, staged files, modified files, and untracked files. Use this before committing to see what has changed, or to check which branch is active. Do NOT use this to see the content of changes (use git_diff), or to view history (use git_log). Returns isClean: true when the working tree is clean with nothing to commit.
|
|
18705
19047
|
|
|
18706
19048
|
Examples:
|
|
18707
19049
|
- Current dir: {} \u2192 { "branch": "main", "isClean": false, "modified": ["src/app.ts"] }
|
|
@@ -18735,7 +19077,7 @@ Examples:
|
|
|
18735
19077
|
});
|
|
18736
19078
|
gitDiffTool = defineTool({
|
|
18737
19079
|
name: "git_diff",
|
|
18738
|
-
description: `
|
|
19080
|
+
description: `Show the unified diff of changes in the working tree or staging area. Use this to see exactly what lines changed in files before committing, or to review changes the user just made. Use staged: true to see only what has been staged (git add), or omit it to see all unstaged changes. Do NOT use this to see commit history (use git_log) or file status summary (use git_status).
|
|
18739
19081
|
|
|
18740
19082
|
Examples:
|
|
18741
19083
|
- All changes: {} \u2192 { "diff": "...", "filesChanged": 3, "insertions": 42, "deletions": 10 }
|
|
@@ -18772,7 +19114,7 @@ Examples:
|
|
|
18772
19114
|
});
|
|
18773
19115
|
gitAddTool = defineTool({
|
|
18774
19116
|
name: "git_add",
|
|
18775
|
-
description: `Stage files for commit.
|
|
19117
|
+
description: `Stage one or more files (or patterns) so they are included in the next git commit. Use this after making file edits to mark them ready for commit. Pass ["."] to stage all changes, or list specific file paths to stage selectively. Do NOT use this to commit (use git_commit after staging) or to view what is staged (use git_status or git_diff with staged: true).
|
|
18776
19118
|
|
|
18777
19119
|
Examples:
|
|
18778
19120
|
- Stage all: { "files": ["."] }
|
|
@@ -18798,7 +19140,7 @@ Examples:
|
|
|
18798
19140
|
});
|
|
18799
19141
|
gitCommitTool = defineTool({
|
|
18800
19142
|
name: "git_commit",
|
|
18801
|
-
description: `Create a git commit
|
|
19143
|
+
description: `Create a git commit from whatever is currently staged (git add must run first). Use conventional commit format (feat/fix/docs/chore). Do NOT use this when nothing is staged \u2014 check git_status first; do NOT use this to stage files (use git_add) or to see what will be committed (use git_diff with staged: true).
|
|
18802
19144
|
|
|
18803
19145
|
Examples:
|
|
18804
19146
|
- Simple commit: { "message": "fix: resolve auth bug" }
|
|
@@ -18831,7 +19173,7 @@ Examples:
|
|
|
18831
19173
|
});
|
|
18832
19174
|
gitLogTool = defineTool({
|
|
18833
19175
|
name: "git_log",
|
|
18834
|
-
description: `
|
|
19176
|
+
description: `Show git commit history with hashes, messages, authors, and dates. Use this to understand what changed recently, find the commit that introduced a bug, or check whether a feature was already merged. Do NOT use this to see the content of changes \u2014 use git_diff; do NOT use this to check current file state \u2014 use git_status.
|
|
18835
19177
|
|
|
18836
19178
|
Examples:
|
|
18837
19179
|
- Last 10 commits: {} (default)
|
|
@@ -18871,7 +19213,7 @@ Examples:
|
|
|
18871
19213
|
});
|
|
18872
19214
|
gitBranchTool = defineTool({
|
|
18873
19215
|
name: "git_branch",
|
|
18874
|
-
description: `
|
|
19216
|
+
description: `List all local branches, create a new branch from the current HEAD, or delete a branch. Use this to see available branches before checking out, or to create a feature branch. Do NOT use this to switch the active branch \u2014 use git_checkout; do NOT delete branches that have unmerged work.
|
|
18875
19217
|
|
|
18876
19218
|
Examples:
|
|
18877
19219
|
- List branches: {} \u2192 { "branches": ["main", "feature/x"], "current": "main" }
|
|
@@ -18915,7 +19257,7 @@ Examples:
|
|
|
18915
19257
|
});
|
|
18916
19258
|
gitCheckoutTool = defineTool({
|
|
18917
19259
|
name: "git_checkout",
|
|
18918
|
-
description: `Switch
|
|
19260
|
+
description: `Switch the working directory to an existing branch, or create a new branch and switch to it in one step. Use this to move between branches or start a new feature branch. Do NOT use this with unsaved file edits (stage or stash first); do NOT use this to just list branches \u2014 use git_branch.
|
|
18919
19261
|
|
|
18920
19262
|
Examples:
|
|
18921
19263
|
- Switch branch: { "branch": "main" }
|
|
@@ -18945,7 +19287,7 @@ Examples:
|
|
|
18945
19287
|
});
|
|
18946
19288
|
gitPushTool = defineTool({
|
|
18947
19289
|
name: "git_push",
|
|
18948
|
-
description: `
|
|
19290
|
+
description: `Upload local commits to a remote repository. Use setUpstream: true the first time you push a new branch to create the tracking relationship. Do NOT use this on main/master without explicit user confirmation \u2014 it modifies shared history; do NOT push without first checking git_status to confirm all commits are clean.
|
|
18949
19291
|
|
|
18950
19292
|
Examples:
|
|
18951
19293
|
- Push current: {} \u2192 pushes to origin
|
|
@@ -18983,7 +19325,7 @@ Examples:
|
|
|
18983
19325
|
});
|
|
18984
19326
|
gitPullTool = defineTool({
|
|
18985
19327
|
name: "git_pull",
|
|
18986
|
-
description: `
|
|
19328
|
+
description: `Fetch and integrate remote commits into the current branch. Use rebase: true to keep a linear history (preferred for feature branches). Do NOT use this when you have uncommitted local changes \u2014 stage or stash them first; if a merge conflict is reported, use read_file / edit_file to resolve then git_add and git_commit.
|
|
18987
19329
|
|
|
18988
19330
|
Examples:
|
|
18989
19331
|
- Pull current: {} \u2192 pulls from origin
|
|
@@ -19241,16 +19583,11 @@ var init_bash = __esm({
|
|
|
19241
19583
|
];
|
|
19242
19584
|
bashExecTool = defineTool({
|
|
19243
19585
|
name: "bash_exec",
|
|
19244
|
-
description: `Execute a
|
|
19586
|
+
description: `Execute a shell command and return its stdout, stderr, and exit code. Use this for running build scripts, test runners, linters, package managers, CLI tools, git commands, or any other shell operation. Runs in the user's shell environment with their full PATH and locally-configured credentials (kubeconfig, gcloud auth, AWS profiles, SSH keys) so never claim you cannot run a command due to missing credentials \u2014 always attempt and report the actual exit code. Do NOT use this to read or write files (use read_file / write_file / edit_file which are safer); prefer specific file tools for file operations.
|
|
19245
19587
|
|
|
19246
19588
|
Runs with the user's full PATH and inherited environment \u2014 any tool installed
|
|
19247
19589
|
on the user's machine is available: kubectl, gcloud, aws, docker, git, node,
|
|
19248
|
-
pnpm, and others.
|
|
19249
|
-
kubeconfig contexts, gcloud auth, AWS profiles, SSH keys, etc.
|
|
19250
|
-
|
|
19251
|
-
IMPORTANT: never claim you cannot run a command because you lack credentials
|
|
19252
|
-
or access \u2014 the environment is the user's own shell. Always attempt; report
|
|
19253
|
-
failure only if the command actually returns a non-zero exit code.
|
|
19590
|
+
pnpm, and others.
|
|
19254
19591
|
|
|
19255
19592
|
Examples:
|
|
19256
19593
|
- List files: { "command": "ls -la" }
|
|
@@ -19495,7 +19832,7 @@ var init_github = __esm({
|
|
|
19495
19832
|
init_errors();
|
|
19496
19833
|
ghCheckAuthTool = defineTool({
|
|
19497
19834
|
name: "gh_check_auth",
|
|
19498
|
-
description: "
|
|
19835
|
+
description: "Verify the gh CLI is installed and the user is logged into GitHub. Call this before any other gh_ tool to confirm authentication is working. Returns the logged-in username if authenticated.",
|
|
19499
19836
|
category: "git",
|
|
19500
19837
|
parameters: z.object({
|
|
19501
19838
|
cwd: z.string().optional()
|
|
@@ -19515,7 +19852,7 @@ var init_github = __esm({
|
|
|
19515
19852
|
});
|
|
19516
19853
|
ghRepoInfoTool = defineTool({
|
|
19517
19854
|
name: "gh_repo_info",
|
|
19518
|
-
description: "Get GitHub repository
|
|
19855
|
+
description: "Get the remote GitHub repository's name, owner, default branch, and URL from within the current git working directory. Use before creating PRs to confirm the target repo. Requires gh_check_auth to pass first.",
|
|
19519
19856
|
category: "git",
|
|
19520
19857
|
parameters: z.object({
|
|
19521
19858
|
cwd: z.string().optional()
|
|
@@ -19537,7 +19874,7 @@ var init_github = __esm({
|
|
|
19537
19874
|
});
|
|
19538
19875
|
ghPrCreateTool = defineTool({
|
|
19539
19876
|
name: "gh_pr_create",
|
|
19540
|
-
description: "
|
|
19877
|
+
description: "Open a pull request on GitHub from the current branch. Requires commits to be pushed first (use git_push with setUpstream: true). Do NOT use this if a PR for this branch already exists \u2014 use gh_pr_list to check first. Use draft: true for work in progress.",
|
|
19541
19878
|
category: "git",
|
|
19542
19879
|
parameters: z.object({
|
|
19543
19880
|
title: z.string().describe("PR title"),
|
|
@@ -19561,7 +19898,7 @@ var init_github = __esm({
|
|
|
19561
19898
|
});
|
|
19562
19899
|
ghPrMergeTool = defineTool({
|
|
19563
19900
|
name: "gh_pr_merge",
|
|
19564
|
-
description: "Merge a
|
|
19901
|
+
description: "Merge a pull request into its base branch. Use squash (default) for feature branches to keep history clean. Always confirm with gh_pr_checks first to ensure CI passed. Do NOT merge if anyFailed is true.",
|
|
19565
19902
|
category: "git",
|
|
19566
19903
|
parameters: z.object({
|
|
19567
19904
|
number: z.number().describe("PR number"),
|
|
@@ -19582,7 +19919,7 @@ var init_github = __esm({
|
|
|
19582
19919
|
});
|
|
19583
19920
|
ghPrChecksTool = defineTool({
|
|
19584
19921
|
name: "gh_pr_checks",
|
|
19585
|
-
description: "
|
|
19922
|
+
description: "Poll the CI check results for a pull request \u2014 returns pass/fail/pending per check and convenience flags (allPassed, anyFailed). Call this after pushing to confirm CI is green before merging. Check anyPending to know if results are still arriving.",
|
|
19586
19923
|
category: "git",
|
|
19587
19924
|
parameters: z.object({
|
|
19588
19925
|
number: z.number().describe("PR number"),
|
|
@@ -19616,7 +19953,7 @@ var init_github = __esm({
|
|
|
19616
19953
|
});
|
|
19617
19954
|
ghPrListTool = defineTool({
|
|
19618
19955
|
name: "gh_pr_list",
|
|
19619
|
-
description: "List pull requests, optionally filtered
|
|
19956
|
+
description: "List open (or all) pull requests for this repository, optionally filtered to a specific branch. Use before gh_pr_create to ensure a PR for the current branch doesn't already exist. Returns PR number, title, URL, and state.",
|
|
19620
19957
|
category: "git",
|
|
19621
19958
|
parameters: z.object({
|
|
19622
19959
|
head: z.string().optional().describe("Filter by head branch name"),
|
|
@@ -19633,7 +19970,7 @@ var init_github = __esm({
|
|
|
19633
19970
|
});
|
|
19634
19971
|
ghReleaseCreateTool = defineTool({
|
|
19635
19972
|
name: "gh_release_create",
|
|
19636
|
-
description: "
|
|
19973
|
+
description: "Publish a versioned GitHub release attached to a tag. The tag must already exist in the repo (push it with git_push first). Provide markdown release notes. Use prerelease: true for release candidates or beta builds.",
|
|
19637
19974
|
category: "git",
|
|
19638
19975
|
parameters: z.object({
|
|
19639
19976
|
tag: z.string().describe("Tag name (e.g., v1.2.3)"),
|
|
@@ -42613,7 +42950,7 @@ Use list_dir or glob to find the correct path.`;
|
|
|
42613
42950
|
}
|
|
42614
42951
|
var readFileTool = defineTool({
|
|
42615
42952
|
name: "read_file",
|
|
42616
|
-
description: `Read the
|
|
42953
|
+
description: `Read the full text content of a file at the given path and return it as a string. Use this when you need the actual source code, configuration values, or text content of a specific file you already know the path to. Do NOT use this to list files in a directory (use list_directory), to check if a file exists (use file_exists), or to search for files by name pattern (use find_files). Returns an error if the path does not exist or is not a readable text file.
|
|
42617
42954
|
|
|
42618
42955
|
Examples:
|
|
42619
42956
|
- Read config: { "path": "package.json" }
|
|
@@ -42671,7 +43008,7 @@ Examples:
|
|
|
42671
43008
|
});
|
|
42672
43009
|
var writeFileTool = defineTool({
|
|
42673
43010
|
name: "write_file",
|
|
42674
|
-
description: `Write content to a file, creating it if it
|
|
43011
|
+
description: `Write text content to a file, replacing it entirely if it already exists or creating it if it does not. Use this when you want to create a new file or fully replace an existing file's content. Do NOT use this to make a small change to an existing file (use edit_file instead, which performs a targeted find-and-replace without rewriting the whole file). Set createDirs: true to automatically create missing parent directories; otherwise the parent directory must already exist.
|
|
42675
43012
|
|
|
42676
43013
|
Examples:
|
|
42677
43014
|
- Create file: { "path": "src/utils.ts", "content": "export const foo = 1;" }
|
|
@@ -42732,7 +43069,7 @@ Examples:
|
|
|
42732
43069
|
});
|
|
42733
43070
|
var editFileTool = defineTool({
|
|
42734
43071
|
name: "edit_file",
|
|
42735
|
-
description: `
|
|
43072
|
+
description: `Make a targeted text replacement inside an existing file by finding oldText and replacing it with newText. Use this for surgical edits to source code, configuration files, or documentation \u2014 it is much safer than rewriting the whole file with write_file because it only touches the exact bytes you specify. The oldText must match exactly (including whitespace and indentation); if it appears more than once in the file, use all: true to replace every occurrence or make oldText longer to be unique. Do NOT use this to create new files (use write_file) or to rename/move files (use move_path).
|
|
42736
43073
|
|
|
42737
43074
|
Examples:
|
|
42738
43075
|
- Single replace: { "path": "src/app.ts", "oldText": "TODO:", "newText": "DONE:" }
|
|
@@ -42816,7 +43153,7 @@ Hint: Use read_file first to verify the exact content.`
|
|
|
42816
43153
|
});
|
|
42817
43154
|
var globTool = defineTool({
|
|
42818
43155
|
name: "glob",
|
|
42819
|
-
description: `Find files
|
|
43156
|
+
description: `Find files whose paths match a glob pattern and return their relative paths as a list. Use this when you know the file extension or naming convention but not the exact path (e.g. find all TypeScript test files, all JSON configs). Do NOT use this to search inside file contents \u2014 use grep or search for that. Returns an empty list when nothing matches; does not throw an error for zero results. node_modules, .git, and dist directories are excluded by default.
|
|
42820
43157
|
|
|
42821
43158
|
Examples:
|
|
42822
43159
|
- All TypeScript: { "pattern": "**/*.ts" }
|
|
@@ -42858,7 +43195,7 @@ Examples:
|
|
|
42858
43195
|
});
|
|
42859
43196
|
var fileExistsTool = defineTool({
|
|
42860
43197
|
name: "file_exists",
|
|
42861
|
-
description: `Check
|
|
43198
|
+
description: `Check whether a path exists on disk and whether it is a file or directory. Use this before attempting to read or write a path when you are unsure it exists \u2014 it never throws, always returning { exists: false } for missing paths. Do NOT use this to read file contents (use read_file) or to list directory contents (use list_directory). Returns isFile and isDirectory flags so you can distinguish files from directories in a single call.
|
|
42862
43199
|
|
|
42863
43200
|
Examples:
|
|
42864
43201
|
- Check file: { "path": "package.json" } \u2192 { "exists": true, "isFile": true, "isDirectory": false }
|
|
@@ -42888,7 +43225,7 @@ Examples:
|
|
|
42888
43225
|
});
|
|
42889
43226
|
var listDirTool = defineTool({
|
|
42890
43227
|
name: "list_dir",
|
|
42891
|
-
description: `List contents
|
|
43228
|
+
description: `List the immediate entries (files and subdirectories) inside a directory and return their names, types, and sizes. Use this to understand what's in a folder before deciding which files to read. Do NOT use this to find files matching a pattern across the whole project (use glob) or to read file contents (use read_file). Returns an error if the path does not exist or is not a directory.
|
|
42892
43229
|
|
|
42893
43230
|
Examples:
|
|
42894
43231
|
- List src: { "path": "src" }
|
|
@@ -44426,7 +44763,7 @@ init_registry4();
|
|
|
44426
44763
|
init_errors();
|
|
44427
44764
|
var grepTool = defineTool({
|
|
44428
44765
|
name: "grep",
|
|
44429
|
-
description: `Search for
|
|
44766
|
+
description: `Search for a regex pattern across all files in a directory and return matching lines with file paths and line numbers. Use this when you know a symbol name, string literal, or pattern and want to find where it appears in the codebase (function definitions, imports, error messages, config keys). Do NOT use this to find files by name \u2014 use glob for that. Do NOT use this when you already know the file path \u2014 use read_file directly. Searches are recursive by default; narrow with the include glob to restrict to specific file types.
|
|
44430
44767
|
|
|
44431
44768
|
Examples:
|
|
44432
44769
|
- Simple search: { "pattern": "TODO" }
|
|
@@ -44559,7 +44896,7 @@ Examples:
|
|
|
44559
44896
|
});
|
|
44560
44897
|
var findInFileTool = defineTool({
|
|
44561
44898
|
name: "find_in_file",
|
|
44562
|
-
description: `Search for a pattern
|
|
44899
|
+
description: `Search for a text or regex pattern inside a single known file and return matching line numbers and content. Use this when you already have the file path and want to quickly find which lines match (e.g. locate a function signature, find an import, or confirm a value exists). Do NOT use this to search across the whole project \u2014 use grep for that. Returns line numbers so you can navigate directly to the match.
|
|
44563
44900
|
|
|
44564
44901
|
Examples:
|
|
44565
44902
|
- Find text: { "file": "src/app.ts", "pattern": "export" }
|
|
@@ -45700,7 +46037,7 @@ async function searchSerpApi(query, maxResults, timeout) {
|
|
|
45700
46037
|
}
|
|
45701
46038
|
var webSearchTool = defineTool({
|
|
45702
46039
|
name: "web_search",
|
|
45703
|
-
description: `Search the web
|
|
46040
|
+
description: `Search the web using a natural-language query and return a list of result titles, URLs, and short excerpts. Use this when you need to find documentation, research an error message, discover API references, or learn about a library before you have a specific URL. Do NOT use this when you already have the URL \u2014 use web_fetch to read a known page directly. Returns result titles and URLs you can then fetch with web_fetch for full content.
|
|
45704
46041
|
|
|
45705
46042
|
Examples:
|
|
45706
46043
|
- Basic search: { "query": "typescript zod validation examples" }
|
|
@@ -45985,7 +46322,7 @@ ${rows.join("\n")}
|
|
|
45985
46322
|
}
|
|
45986
46323
|
var webFetchTool = defineTool({
|
|
45987
46324
|
name: "web_fetch",
|
|
45988
|
-
description: `Fetch a URL and
|
|
46325
|
+
description: `Fetch the content of a specific URL and return it as clean, readable markdown text. Use this when you already have the exact URL \u2014 for example a documentation page, a GitHub file, or an API response \u2014 and want to read its content. Do NOT use this to find information without a URL; use web_search instead to discover relevant URLs first. By default strips navigation menus, headers, and ads to return only the main content; set extractContent: false to get the raw HTML/text.
|
|
45989
46326
|
|
|
45990
46327
|
Examples:
|
|
45991
46328
|
- Fetch documentation: { "url": "https://docs.example.com/api" }
|
|
@@ -46673,8 +47010,7 @@ async function saveMemory(scope, memory) {
|
|
|
46673
47010
|
}
|
|
46674
47011
|
var createMemoryTool = defineTool({
|
|
46675
47012
|
name: "create_memory",
|
|
46676
|
-
description: `
|
|
46677
|
-
Use for storing project conventions, patterns, preferences, and learnings.
|
|
47013
|
+
description: `Persist a named key-value fact that survives across sessions \u2014 use this for project conventions, patterns, user preferences, or discovered constraints you'll need later. If the key already exists the value is overwritten. Do NOT use this for temporary scratch data within a single session; do NOT use this to store file contents \u2014 use write_file for that.
|
|
46678
47014
|
|
|
46679
47015
|
Examples:
|
|
46680
47016
|
- Save convention: { "key": "naming-convention", "value": "Use camelCase for variables", "tags": ["style"] }
|
|
@@ -46731,7 +47067,7 @@ Examples:
|
|
|
46731
47067
|
});
|
|
46732
47068
|
var recallMemoryTool = defineTool({
|
|
46733
47069
|
name: "recall_memory",
|
|
46734
|
-
description: `Search
|
|
47070
|
+
description: `Search previously saved memories by key substring, tags, or free-text value match. Use this at the start of a task to check if relevant conventions or patterns were already learned. Returns full memory content. Do NOT use this to list all memories (use list_memories) or to search file content (use grep).
|
|
46735
47071
|
|
|
46736
47072
|
Examples:
|
|
46737
47073
|
- By key substring: { "query": "naming" }
|
|
@@ -46786,7 +47122,7 @@ Examples:
|
|
|
46786
47122
|
});
|
|
46787
47123
|
var listMemoriesTool = defineTool({
|
|
46788
47124
|
name: "list_memories",
|
|
46789
|
-
description: `List
|
|
47125
|
+
description: `List stored memory keys and tags without loading full values \u2014 useful for browsing what has been saved before recalling specific entries. Do NOT use this to get memory content (use recall_memory for that).
|
|
46790
47126
|
|
|
46791
47127
|
Examples:
|
|
46792
47128
|
- List all: { "scope": "all" }
|
|
@@ -57005,7 +57341,7 @@ program.command("setup").description("Configure AI provider and API key").action
|
|
|
57005
57341
|
console.log("\n\u274C Setup cancelled.");
|
|
57006
57342
|
}
|
|
57007
57343
|
});
|
|
57008
|
-
program.command("chat", { isDefault: true }).description("Start interactive chat session with the agent").option("-m, --model <model>", "LLM model to use").option("--provider <provider>", "LLM provider (anthropic, openai, codex, gemini, kimi)").option("-p, --path <path>", "Project path", process.cwd()).option("-P, --print [task]", "Headless mode: run task and print output (no interactive UI)").option("--output <format>", "Output format for headless mode (text or json)", "text").option("--setup", "Run setup wizard before starting").action(
|
|
57344
|
+
program.command("chat", { isDefault: true }).description("Start interactive chat session with the agent").option("-m, --model <model>", "LLM model to use").option("--provider <provider>", "LLM provider (anthropic, openai, codex, gemini, kimi)").option("--editor-model <model>", "Cheap model for file edits (architect/editor split)").option("--weak-model <model>", "Cheap model for background tasks (compaction, summaries)").option("-p, --path <path>", "Project path", process.cwd()).option("-P, --print [task]", "Headless mode: run task and print output (no interactive UI)").option("--output <format>", "Output format for headless mode (text or json)", "text").option("--setup", "Run setup wizard before starting").action(
|
|
57009
57345
|
async (options) => {
|
|
57010
57346
|
if (options.setup) {
|
|
57011
57347
|
const result = await runOnboardingV2();
|
|
@@ -57040,7 +57376,9 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
57040
57376
|
provider: {
|
|
57041
57377
|
type: providerType,
|
|
57042
57378
|
model: options.model ?? "",
|
|
57043
|
-
maxTokens: 8192
|
|
57379
|
+
maxTokens: 8192,
|
|
57380
|
+
editorModel: options.editorModel,
|
|
57381
|
+
weakModel: options.weakModel
|
|
57044
57382
|
}
|
|
57045
57383
|
}
|
|
57046
57384
|
});
|