@corbat-tech/coco 2.33.1 → 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 +439 -69
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +265 -55
- 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
|
}
|
|
@@ -4220,6 +4501,10 @@ function buildMaxTokensParam(model, maxTokens) {
|
|
|
4220
4501
|
}
|
|
4221
4502
|
return { max_tokens: maxTokens };
|
|
4222
4503
|
}
|
|
4504
|
+
function truncateToolDescription(description) {
|
|
4505
|
+
if (description.length <= MAX_TOOL_DESCRIPTION_LENGTH) return description;
|
|
4506
|
+
return description.slice(0, MAX_TOOL_DESCRIPTION_LENGTH - 1) + "\u2026";
|
|
4507
|
+
}
|
|
4223
4508
|
function createOpenAIProvider(config) {
|
|
4224
4509
|
const provider = new OpenAIProvider();
|
|
4225
4510
|
if (config) {
|
|
@@ -4242,13 +4527,14 @@ function createKimiProvider(config) {
|
|
|
4242
4527
|
}
|
|
4243
4528
|
return provider;
|
|
4244
4529
|
}
|
|
4245
|
-
var DEFAULT_MODEL2, CONTEXT_WINDOWS2, MODELS_WITHOUT_TEMPERATURE, LOCAL_MODEL_PATTERNS, MODELS_WITH_THINKING_MODE, OpenAIProvider;
|
|
4530
|
+
var DEFAULT_MODEL2, CONTEXT_WINDOWS2, MODELS_WITHOUT_TEMPERATURE, LOCAL_MODEL_PATTERNS, MODELS_WITH_THINKING_MODE, OpenAIProvider, MAX_TOOL_DESCRIPTION_LENGTH;
|
|
4246
4531
|
var init_openai = __esm({
|
|
4247
4532
|
"src/providers/openai.ts"() {
|
|
4248
4533
|
init_errors();
|
|
4249
4534
|
init_retry();
|
|
4250
4535
|
init_tool_call_normalizer();
|
|
4251
4536
|
init_thinking();
|
|
4537
|
+
init_model_tier();
|
|
4252
4538
|
DEFAULT_MODEL2 = "gpt-5.3-codex";
|
|
4253
4539
|
CONTEXT_WINDOWS2 = {
|
|
4254
4540
|
// OpenAI models
|
|
@@ -4400,6 +4686,14 @@ var init_openai = __esm({
|
|
|
4400
4686
|
supportsTemperature(model) {
|
|
4401
4687
|
return !MODELS_WITHOUT_TEMPERATURE.some((m) => model.toLowerCase().includes(m.toLowerCase()));
|
|
4402
4688
|
}
|
|
4689
|
+
/**
|
|
4690
|
+
* Whether this provider instance supports the Responses API for the given model.
|
|
4691
|
+
* Subclasses (e.g. CopilotProvider) can override to force Chat Completions
|
|
4692
|
+
* when their endpoint does not expose /v1/responses.
|
|
4693
|
+
*/
|
|
4694
|
+
modelNeedsResponsesApi(model) {
|
|
4695
|
+
return needsResponsesApi(model);
|
|
4696
|
+
}
|
|
4403
4697
|
/**
|
|
4404
4698
|
* Get extra body parameters for API calls.
|
|
4405
4699
|
* Honors the user's ThinkingMode for Kimi models; defaults to disabled
|
|
@@ -4419,7 +4713,7 @@ var init_openai = __esm({
|
|
|
4419
4713
|
async chat(messages, options) {
|
|
4420
4714
|
this.ensureInitialized();
|
|
4421
4715
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
4422
|
-
if (
|
|
4716
|
+
if (this.modelNeedsResponsesApi(model)) {
|
|
4423
4717
|
return this.chatViaResponses(messages, options);
|
|
4424
4718
|
}
|
|
4425
4719
|
return withRetry(async () => {
|
|
@@ -4459,21 +4753,24 @@ var init_openai = __esm({
|
|
|
4459
4753
|
async chatWithTools(messages, options) {
|
|
4460
4754
|
this.ensureInitialized();
|
|
4461
4755
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
4462
|
-
if (
|
|
4756
|
+
if (this.modelNeedsResponsesApi(model)) {
|
|
4463
4757
|
return this.chatWithToolsViaResponses(messages, options);
|
|
4464
4758
|
}
|
|
4759
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
4465
4760
|
return withRetry(async () => {
|
|
4466
4761
|
try {
|
|
4467
4762
|
const supportsTemp = this.supportsTemperature(model);
|
|
4468
4763
|
const extraBody = this.getExtraBody(model, options?.thinking);
|
|
4469
4764
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4470
4765
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4766
|
+
const tools = this.limitTools(options.tools, tierCfg.maxTools);
|
|
4471
4767
|
const requestParams = {
|
|
4472
4768
|
model,
|
|
4473
4769
|
...buildMaxTokensParam(model, maxTokens),
|
|
4474
4770
|
messages: this.convertMessages(messages, options?.system),
|
|
4475
|
-
tools: this.convertTools(
|
|
4476
|
-
tool_choice: this.convertToolChoice(options.toolChoice)
|
|
4771
|
+
tools: this.convertTools(tools),
|
|
4772
|
+
tool_choice: this.convertToolChoice(options.toolChoice),
|
|
4773
|
+
parallel_tool_calls: tierCfg.parallelToolCalls
|
|
4477
4774
|
};
|
|
4478
4775
|
if (supportsTemp) {
|
|
4479
4776
|
requestParams.temperature = options?.temperature ?? this.config.temperature ?? 0;
|
|
@@ -4511,7 +4808,7 @@ var init_openai = __esm({
|
|
|
4511
4808
|
async *stream(messages, options) {
|
|
4512
4809
|
this.ensureInitialized();
|
|
4513
4810
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
4514
|
-
if (
|
|
4811
|
+
if (this.modelNeedsResponsesApi(model)) {
|
|
4515
4812
|
yield* this.streamViaResponses(messages, options);
|
|
4516
4813
|
return;
|
|
4517
4814
|
}
|
|
@@ -4549,22 +4846,25 @@ var init_openai = __esm({
|
|
|
4549
4846
|
async *streamWithTools(messages, options) {
|
|
4550
4847
|
this.ensureInitialized();
|
|
4551
4848
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
4552
|
-
if (
|
|
4849
|
+
if (this.modelNeedsResponsesApi(model)) {
|
|
4553
4850
|
yield* this.streamWithToolsViaResponses(messages, options);
|
|
4554
4851
|
return;
|
|
4555
4852
|
}
|
|
4853
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
4556
4854
|
let timeoutTriggered = false;
|
|
4557
4855
|
try {
|
|
4558
4856
|
const supportsTemp = this.supportsTemperature(model);
|
|
4559
4857
|
const extraBody = this.getExtraBody(model, options?.thinking);
|
|
4560
4858
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4561
4859
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4860
|
+
const tools = this.limitTools(options.tools, tierCfg.maxTools);
|
|
4562
4861
|
const requestParams = {
|
|
4563
4862
|
model,
|
|
4564
4863
|
...buildMaxTokensParam(model, maxTokens),
|
|
4565
4864
|
messages: this.convertMessages(messages, options?.system),
|
|
4566
|
-
tools: this.convertTools(
|
|
4865
|
+
tools: this.convertTools(tools),
|
|
4567
4866
|
tool_choice: this.convertToolChoice(options.toolChoice),
|
|
4867
|
+
parallel_tool_calls: tierCfg.parallelToolCalls,
|
|
4568
4868
|
stream: true
|
|
4569
4869
|
};
|
|
4570
4870
|
if (supportsTemp) {
|
|
@@ -4801,7 +5101,7 @@ var init_openai = __esm({
|
|
|
4801
5101
|
} catch {
|
|
4802
5102
|
try {
|
|
4803
5103
|
const model = this.config.model || DEFAULT_MODEL2;
|
|
4804
|
-
if (
|
|
5104
|
+
if (this.modelNeedsResponsesApi(model)) {
|
|
4805
5105
|
await this.client.responses.create({
|
|
4806
5106
|
model,
|
|
4807
5107
|
input: [{ role: "user", content: [{ type: "input_text", text: "Hi" }] }],
|
|
@@ -4934,6 +5234,17 @@ var init_openai = __esm({
|
|
|
4934
5234
|
}
|
|
4935
5235
|
return content.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
4936
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
|
+
}
|
|
4937
5248
|
/**
|
|
4938
5249
|
* Convert tools to OpenAI format
|
|
4939
5250
|
*/
|
|
@@ -4942,8 +5253,9 @@ var init_openai = __esm({
|
|
|
4942
5253
|
type: "function",
|
|
4943
5254
|
function: {
|
|
4944
5255
|
name: tool.name,
|
|
4945
|
-
description: tool.description,
|
|
4946
|
-
parameters: tool.input_schema
|
|
5256
|
+
description: truncateToolDescription(tool.description),
|
|
5257
|
+
parameters: tool.input_schema,
|
|
5258
|
+
strict: true
|
|
4947
5259
|
}
|
|
4948
5260
|
}));
|
|
4949
5261
|
}
|
|
@@ -5076,8 +5388,11 @@ var init_openai = __esm({
|
|
|
5076
5388
|
return withRetry(async () => {
|
|
5077
5389
|
try {
|
|
5078
5390
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
5391
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
5079
5392
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
5080
|
-
const tools = this.convertToolsForResponses(
|
|
5393
|
+
const tools = this.convertToolsForResponses(
|
|
5394
|
+
this.limitTools(options.tools, tierCfg.maxTools)
|
|
5395
|
+
);
|
|
5081
5396
|
const supportsTemp = this.supportsTemperature(model);
|
|
5082
5397
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
5083
5398
|
const response = await this.client.responses.create({
|
|
@@ -5197,8 +5512,10 @@ var init_openai = __esm({
|
|
|
5197
5512
|
let timeoutTriggered = false;
|
|
5198
5513
|
try {
|
|
5199
5514
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
5515
|
+
const tierCfg = getTierConfig(this.id, model);
|
|
5200
5516
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
5201
|
-
const
|
|
5517
|
+
const limitedTools = this.limitTools(options.tools, tierCfg.maxTools);
|
|
5518
|
+
const tools = limitedTools.length > 0 ? this.convertToolsForResponses(limitedTools) : void 0;
|
|
5202
5519
|
const supportsTemp = this.supportsTemperature(model);
|
|
5203
5520
|
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
5204
5521
|
const requestParams = {
|
|
@@ -5428,12 +5745,13 @@ var init_openai = __esm({
|
|
|
5428
5745
|
return tools.map((tool) => ({
|
|
5429
5746
|
type: "function",
|
|
5430
5747
|
name: tool.name,
|
|
5431
|
-
description: tool.description
|
|
5748
|
+
description: tool.description ? truncateToolDescription(tool.description) : void 0,
|
|
5432
5749
|
parameters: tool.input_schema ?? null,
|
|
5433
|
-
strict:
|
|
5750
|
+
strict: true
|
|
5434
5751
|
}));
|
|
5435
5752
|
}
|
|
5436
5753
|
};
|
|
5754
|
+
MAX_TOOL_DESCRIPTION_LENGTH = 1024;
|
|
5437
5755
|
}
|
|
5438
5756
|
});
|
|
5439
5757
|
|
|
@@ -6210,6 +6528,14 @@ var init_copilot2 = __esm({
|
|
|
6210
6528
|
/**
|
|
6211
6529
|
* Count tokens (approximate — Copilot models vary in tokenizer)
|
|
6212
6530
|
*/
|
|
6531
|
+
/**
|
|
6532
|
+
* The GitHub Copilot endpoint (api.githubcopilot.com) does not expose the
|
|
6533
|
+
* OpenAI Responses API (/v1/responses). Always use Chat Completions so that
|
|
6534
|
+
* gpt-5-mini and similar models work correctly with MCP tools.
|
|
6535
|
+
*/
|
|
6536
|
+
modelNeedsResponsesApi(_model) {
|
|
6537
|
+
return false;
|
|
6538
|
+
}
|
|
6213
6539
|
countTokens(text15) {
|
|
6214
6540
|
if (!text15) return 0;
|
|
6215
6541
|
return Math.ceil(text15.length / 3.5);
|
|
@@ -10001,7 +10327,8 @@ var init_compactor = __esm({
|
|
|
10001
10327
|
conversationText,
|
|
10002
10328
|
provider,
|
|
10003
10329
|
signal,
|
|
10004
|
-
options.focusTopic
|
|
10330
|
+
options.focusTopic,
|
|
10331
|
+
options.summaryModel
|
|
10005
10332
|
);
|
|
10006
10333
|
const systemMessages = messages.filter((m) => m.role === "system");
|
|
10007
10334
|
const summaryMessage = {
|
|
@@ -10056,14 +10383,15 @@ ${summary}
|
|
|
10056
10383
|
/**
|
|
10057
10384
|
* Generate a summary of the conversation using the LLM
|
|
10058
10385
|
*/
|
|
10059
|
-
async generateSummary(conversationText, provider, signal, focusTopic) {
|
|
10386
|
+
async generateSummary(conversationText, provider, signal, focusTopic, summaryModel) {
|
|
10060
10387
|
if (signal?.aborted) return "[Compaction cancelled]";
|
|
10061
10388
|
const prompt = buildCompactionPrompt(focusTopic) + conversationText;
|
|
10062
10389
|
try {
|
|
10063
10390
|
const chatPromise = provider.chat([{ role: "user", content: prompt }], {
|
|
10064
10391
|
maxTokens: this.config.summaryMaxTokens,
|
|
10065
|
-
temperature: 0.3
|
|
10392
|
+
temperature: 0.3,
|
|
10066
10393
|
// Lower temperature for more consistent summaries
|
|
10394
|
+
...summaryModel ? { model: summaryModel } : {}
|
|
10067
10395
|
});
|
|
10068
10396
|
if (signal) {
|
|
10069
10397
|
const abortPromise = new Promise((_, reject) => {
|
|
@@ -10786,7 +11114,7 @@ async function createDefaultReplConfig() {
|
|
|
10786
11114
|
const model = await getLastUsedModel(providerType) || getDefaultModel(providerType);
|
|
10787
11115
|
const persistedThinking = await getLastUsedThinking(providerType);
|
|
10788
11116
|
const thinking = persistedThinking ?? resolveDefaultThinking(providerType, model);
|
|
10789
|
-
const thinkingToStore = thinking === "off" ? void 0 : thinking;
|
|
11117
|
+
const thinkingToStore = persistedThinking !== void 0 ? persistedThinking : thinking === "off" ? void 0 : thinking;
|
|
10790
11118
|
return {
|
|
10791
11119
|
provider: {
|
|
10792
11120
|
type: providerType,
|
|
@@ -10959,6 +11287,14 @@ ${finalInstructions}`;
|
|
|
10959
11287
|
systemPrompt = `${systemPrompt}
|
|
10960
11288
|
|
|
10961
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}`;
|
|
10962
11298
|
}
|
|
10963
11299
|
return [{ role: "system", content: systemPrompt }, ...session.messages];
|
|
10964
11300
|
}
|
|
@@ -11143,8 +11479,11 @@ async function initializeSessionTrust(session) {
|
|
|
11143
11479
|
}
|
|
11144
11480
|
function initializeContextManager(session, provider) {
|
|
11145
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);
|
|
11146
11485
|
session.contextManager = createContextManager(contextWindow, {
|
|
11147
|
-
compactionThreshold:
|
|
11486
|
+
compactionThreshold: tierCfg.compactionThreshold,
|
|
11148
11487
|
reservedTokens: 4096
|
|
11149
11488
|
});
|
|
11150
11489
|
}
|
|
@@ -11179,7 +11518,11 @@ async function checkAndCompactContext(session, provider, signal, toolRegistry) {
|
|
|
11179
11518
|
summaryMaxTokens: 1e3
|
|
11180
11519
|
});
|
|
11181
11520
|
try {
|
|
11182
|
-
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
|
+
});
|
|
11183
11526
|
if (result.wasCompacted) {
|
|
11184
11527
|
const compactedNonSystem = result.messages.filter((m) => m.role !== "system");
|
|
11185
11528
|
session.messages = compactedNonSystem;
|
|
@@ -11223,11 +11566,12 @@ function getSessionMemory(session) {
|
|
|
11223
11566
|
async function reloadSessionMemory(session) {
|
|
11224
11567
|
await initializeSessionMemory(session);
|
|
11225
11568
|
}
|
|
11226
|
-
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;
|
|
11227
11570
|
var init_session = __esm({
|
|
11228
11571
|
"src/cli/repl/session.ts"() {
|
|
11229
11572
|
init_env();
|
|
11230
11573
|
init_thinking();
|
|
11574
|
+
init_model_tier();
|
|
11231
11575
|
init_manager();
|
|
11232
11576
|
init_compactor();
|
|
11233
11577
|
init_memory();
|
|
@@ -11425,6 +11769,17 @@ Responses are short and direct by default. Lead with the answer or action, not r
|
|
|
11425
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.
|
|
11426
11770
|
|
|
11427
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.`;
|
|
11428
11783
|
SHELL_METACHARACTERS = /[;|&`$(){}<>!\n\\'"]/;
|
|
11429
11784
|
SAFE_COMMAND_VALIDATORS = {
|
|
11430
11785
|
git: (args) => {
|
|
@@ -12568,13 +12923,21 @@ var init_registry4 = __esm({
|
|
|
12568
12923
|
const field = issue.path.join(".") || "input";
|
|
12569
12924
|
return `${field} (${issue.message.toLowerCase()})`;
|
|
12570
12925
|
});
|
|
12571
|
-
errorMessage = `Invalid tool input \u2014 ${fields.join(", ")}`;
|
|
12926
|
+
errorMessage = `Invalid tool input for '${name}' \u2014 ${fields.join(", ")}`;
|
|
12572
12927
|
const allUndefined = error.issues.every(
|
|
12573
12928
|
(i) => i.message.toLowerCase().includes("received undefined")
|
|
12574
12929
|
);
|
|
12575
12930
|
if (allUndefined && error.issues.length > 1) {
|
|
12576
12931
|
errorMessage += ". All parameters are missing \u2014 this is likely a JSON serialization error on our side. Please retry with the same arguments.";
|
|
12577
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
|
+
}
|
|
12578
12941
|
} else if (isCocoError(error)) {
|
|
12579
12942
|
const causeMsg = error.cause instanceof Error ? error.cause.message : "";
|
|
12580
12943
|
const isRawEnoent = causeMsg.startsWith("ENOENT:");
|
|
@@ -18680,7 +19043,7 @@ var init_git = __esm({
|
|
|
18680
19043
|
init_errors();
|
|
18681
19044
|
gitStatusTool = defineTool({
|
|
18682
19045
|
name: "git_status",
|
|
18683
|
-
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.
|
|
18684
19047
|
|
|
18685
19048
|
Examples:
|
|
18686
19049
|
- Current dir: {} \u2192 { "branch": "main", "isClean": false, "modified": ["src/app.ts"] }
|
|
@@ -18714,7 +19077,7 @@ Examples:
|
|
|
18714
19077
|
});
|
|
18715
19078
|
gitDiffTool = defineTool({
|
|
18716
19079
|
name: "git_diff",
|
|
18717
|
-
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).
|
|
18718
19081
|
|
|
18719
19082
|
Examples:
|
|
18720
19083
|
- All changes: {} \u2192 { "diff": "...", "filesChanged": 3, "insertions": 42, "deletions": 10 }
|
|
@@ -18751,7 +19114,7 @@ Examples:
|
|
|
18751
19114
|
});
|
|
18752
19115
|
gitAddTool = defineTool({
|
|
18753
19116
|
name: "git_add",
|
|
18754
|
-
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).
|
|
18755
19118
|
|
|
18756
19119
|
Examples:
|
|
18757
19120
|
- Stage all: { "files": ["."] }
|
|
@@ -18777,7 +19140,7 @@ Examples:
|
|
|
18777
19140
|
});
|
|
18778
19141
|
gitCommitTool = defineTool({
|
|
18779
19142
|
name: "git_commit",
|
|
18780
|
-
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).
|
|
18781
19144
|
|
|
18782
19145
|
Examples:
|
|
18783
19146
|
- Simple commit: { "message": "fix: resolve auth bug" }
|
|
@@ -18810,7 +19173,7 @@ Examples:
|
|
|
18810
19173
|
});
|
|
18811
19174
|
gitLogTool = defineTool({
|
|
18812
19175
|
name: "git_log",
|
|
18813
|
-
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.
|
|
18814
19177
|
|
|
18815
19178
|
Examples:
|
|
18816
19179
|
- Last 10 commits: {} (default)
|
|
@@ -18850,7 +19213,7 @@ Examples:
|
|
|
18850
19213
|
});
|
|
18851
19214
|
gitBranchTool = defineTool({
|
|
18852
19215
|
name: "git_branch",
|
|
18853
|
-
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.
|
|
18854
19217
|
|
|
18855
19218
|
Examples:
|
|
18856
19219
|
- List branches: {} \u2192 { "branches": ["main", "feature/x"], "current": "main" }
|
|
@@ -18894,7 +19257,7 @@ Examples:
|
|
|
18894
19257
|
});
|
|
18895
19258
|
gitCheckoutTool = defineTool({
|
|
18896
19259
|
name: "git_checkout",
|
|
18897
|
-
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.
|
|
18898
19261
|
|
|
18899
19262
|
Examples:
|
|
18900
19263
|
- Switch branch: { "branch": "main" }
|
|
@@ -18924,7 +19287,7 @@ Examples:
|
|
|
18924
19287
|
});
|
|
18925
19288
|
gitPushTool = defineTool({
|
|
18926
19289
|
name: "git_push",
|
|
18927
|
-
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.
|
|
18928
19291
|
|
|
18929
19292
|
Examples:
|
|
18930
19293
|
- Push current: {} \u2192 pushes to origin
|
|
@@ -18962,7 +19325,7 @@ Examples:
|
|
|
18962
19325
|
});
|
|
18963
19326
|
gitPullTool = defineTool({
|
|
18964
19327
|
name: "git_pull",
|
|
18965
|
-
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.
|
|
18966
19329
|
|
|
18967
19330
|
Examples:
|
|
18968
19331
|
- Pull current: {} \u2192 pulls from origin
|
|
@@ -19220,16 +19583,11 @@ var init_bash = __esm({
|
|
|
19220
19583
|
];
|
|
19221
19584
|
bashExecTool = defineTool({
|
|
19222
19585
|
name: "bash_exec",
|
|
19223
|
-
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.
|
|
19224
19587
|
|
|
19225
19588
|
Runs with the user's full PATH and inherited environment \u2014 any tool installed
|
|
19226
19589
|
on the user's machine is available: kubectl, gcloud, aws, docker, git, node,
|
|
19227
|
-
pnpm, and others.
|
|
19228
|
-
kubeconfig contexts, gcloud auth, AWS profiles, SSH keys, etc.
|
|
19229
|
-
|
|
19230
|
-
IMPORTANT: never claim you cannot run a command because you lack credentials
|
|
19231
|
-
or access \u2014 the environment is the user's own shell. Always attempt; report
|
|
19232
|
-
failure only if the command actually returns a non-zero exit code.
|
|
19590
|
+
pnpm, and others.
|
|
19233
19591
|
|
|
19234
19592
|
Examples:
|
|
19235
19593
|
- List files: { "command": "ls -la" }
|
|
@@ -19474,7 +19832,7 @@ var init_github = __esm({
|
|
|
19474
19832
|
init_errors();
|
|
19475
19833
|
ghCheckAuthTool = defineTool({
|
|
19476
19834
|
name: "gh_check_auth",
|
|
19477
|
-
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.",
|
|
19478
19836
|
category: "git",
|
|
19479
19837
|
parameters: z.object({
|
|
19480
19838
|
cwd: z.string().optional()
|
|
@@ -19494,7 +19852,7 @@ var init_github = __esm({
|
|
|
19494
19852
|
});
|
|
19495
19853
|
ghRepoInfoTool = defineTool({
|
|
19496
19854
|
name: "gh_repo_info",
|
|
19497
|
-
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.",
|
|
19498
19856
|
category: "git",
|
|
19499
19857
|
parameters: z.object({
|
|
19500
19858
|
cwd: z.string().optional()
|
|
@@ -19516,7 +19874,7 @@ var init_github = __esm({
|
|
|
19516
19874
|
});
|
|
19517
19875
|
ghPrCreateTool = defineTool({
|
|
19518
19876
|
name: "gh_pr_create",
|
|
19519
|
-
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.",
|
|
19520
19878
|
category: "git",
|
|
19521
19879
|
parameters: z.object({
|
|
19522
19880
|
title: z.string().describe("PR title"),
|
|
@@ -19540,7 +19898,7 @@ var init_github = __esm({
|
|
|
19540
19898
|
});
|
|
19541
19899
|
ghPrMergeTool = defineTool({
|
|
19542
19900
|
name: "gh_pr_merge",
|
|
19543
|
-
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.",
|
|
19544
19902
|
category: "git",
|
|
19545
19903
|
parameters: z.object({
|
|
19546
19904
|
number: z.number().describe("PR number"),
|
|
@@ -19561,7 +19919,7 @@ var init_github = __esm({
|
|
|
19561
19919
|
});
|
|
19562
19920
|
ghPrChecksTool = defineTool({
|
|
19563
19921
|
name: "gh_pr_checks",
|
|
19564
|
-
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.",
|
|
19565
19923
|
category: "git",
|
|
19566
19924
|
parameters: z.object({
|
|
19567
19925
|
number: z.number().describe("PR number"),
|
|
@@ -19595,7 +19953,7 @@ var init_github = __esm({
|
|
|
19595
19953
|
});
|
|
19596
19954
|
ghPrListTool = defineTool({
|
|
19597
19955
|
name: "gh_pr_list",
|
|
19598
|
-
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.",
|
|
19599
19957
|
category: "git",
|
|
19600
19958
|
parameters: z.object({
|
|
19601
19959
|
head: z.string().optional().describe("Filter by head branch name"),
|
|
@@ -19612,7 +19970,7 @@ var init_github = __esm({
|
|
|
19612
19970
|
});
|
|
19613
19971
|
ghReleaseCreateTool = defineTool({
|
|
19614
19972
|
name: "gh_release_create",
|
|
19615
|
-
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.",
|
|
19616
19974
|
category: "git",
|
|
19617
19975
|
parameters: z.object({
|
|
19618
19976
|
tag: z.string().describe("Tag name (e.g., v1.2.3)"),
|
|
@@ -34319,6 +34677,12 @@ async function renderStartupPanel(session, gitCtx, mcpServers = []) {
|
|
|
34319
34677
|
}
|
|
34320
34678
|
const cocoStatus = isQualityLoop() ? chalk.magenta(" \u{1F504} quality mode: ") + chalk.green.bold("on") + chalk.dim(" \u2014 iterates until quality \u2265 85. /quality to disable") : chalk.dim(" \u{1F4A1} quality mode is Coco's edge for robust code. Enable with /quality on");
|
|
34321
34679
|
console.log(cocoStatus);
|
|
34680
|
+
if (thinkingCapability.supported) {
|
|
34681
|
+
const modeLabel = formatThinkingMode(session.config.provider.thinking ?? "off");
|
|
34682
|
+
console.log(
|
|
34683
|
+
chalk.dim(" \u{1F9E0} reasoning: ") + chalk.magenta(modeLabel) + chalk.dim(" \xB7 /thinking to change")
|
|
34684
|
+
);
|
|
34685
|
+
}
|
|
34322
34686
|
const skillTotal = session.skillRegistry?.size ?? 0;
|
|
34323
34687
|
const hasSomething = skillTotal > 0 || mcpServers.length > 0;
|
|
34324
34688
|
if (hasSomething) {
|
|
@@ -35928,6 +36292,7 @@ async function ensureConfiguredV2(config) {
|
|
|
35928
36292
|
const preferredHasOpenAIOAuth = preferredProviderDef?.id === "openai" && hasOpenAIOAuthTokens;
|
|
35929
36293
|
const preferredHasCopilotCreds = preferredProviderDef?.id === "copilot" && isProviderConfigured();
|
|
35930
36294
|
const preferredIsConfigured = preferredIsLocal || preferredHasApiKey || preferredHasOpenAIOAuth || preferredHasCopilotCreds;
|
|
36295
|
+
const preferredWasConfigured = Boolean(preferredProviderDef && preferredIsConfigured);
|
|
35931
36296
|
let preferredWasConfiguredButUnavailable = false;
|
|
35932
36297
|
let preferredUnavailableWasLocal = false;
|
|
35933
36298
|
if (preferredProviderDef && preferredIsConfigured) {
|
|
@@ -35973,7 +36338,9 @@ async function ensureConfiguredV2(config) {
|
|
|
35973
36338
|
}
|
|
35974
36339
|
const provider = await createProvider(providerId, { model });
|
|
35975
36340
|
if (await provider.isAvailable()) {
|
|
35976
|
-
|
|
36341
|
+
if (!preferredWasConfigured) {
|
|
36342
|
+
await saveProviderPreference(prov.id, model);
|
|
36343
|
+
}
|
|
35977
36344
|
return {
|
|
35978
36345
|
...config,
|
|
35979
36346
|
provider: {
|
|
@@ -35998,7 +36365,9 @@ async function ensureConfiguredV2(config) {
|
|
|
35998
36365
|
const model = recommended?.id || openaiDef.models[0]?.id || "";
|
|
35999
36366
|
const provider = await createProvider("codex", { model });
|
|
36000
36367
|
if (await provider.isAvailable()) {
|
|
36001
|
-
|
|
36368
|
+
if (!preferredWasConfigured) {
|
|
36369
|
+
await saveProviderPreference("openai", model);
|
|
36370
|
+
}
|
|
36002
36371
|
return {
|
|
36003
36372
|
...config,
|
|
36004
36373
|
provider: {
|
|
@@ -42581,7 +42950,7 @@ Use list_dir or glob to find the correct path.`;
|
|
|
42581
42950
|
}
|
|
42582
42951
|
var readFileTool = defineTool({
|
|
42583
42952
|
name: "read_file",
|
|
42584
|
-
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.
|
|
42585
42954
|
|
|
42586
42955
|
Examples:
|
|
42587
42956
|
- Read config: { "path": "package.json" }
|
|
@@ -42639,7 +43008,7 @@ Examples:
|
|
|
42639
43008
|
});
|
|
42640
43009
|
var writeFileTool = defineTool({
|
|
42641
43010
|
name: "write_file",
|
|
42642
|
-
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.
|
|
42643
43012
|
|
|
42644
43013
|
Examples:
|
|
42645
43014
|
- Create file: { "path": "src/utils.ts", "content": "export const foo = 1;" }
|
|
@@ -42700,7 +43069,7 @@ Examples:
|
|
|
42700
43069
|
});
|
|
42701
43070
|
var editFileTool = defineTool({
|
|
42702
43071
|
name: "edit_file",
|
|
42703
|
-
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).
|
|
42704
43073
|
|
|
42705
43074
|
Examples:
|
|
42706
43075
|
- Single replace: { "path": "src/app.ts", "oldText": "TODO:", "newText": "DONE:" }
|
|
@@ -42784,7 +43153,7 @@ Hint: Use read_file first to verify the exact content.`
|
|
|
42784
43153
|
});
|
|
42785
43154
|
var globTool = defineTool({
|
|
42786
43155
|
name: "glob",
|
|
42787
|
-
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.
|
|
42788
43157
|
|
|
42789
43158
|
Examples:
|
|
42790
43159
|
- All TypeScript: { "pattern": "**/*.ts" }
|
|
@@ -42826,7 +43195,7 @@ Examples:
|
|
|
42826
43195
|
});
|
|
42827
43196
|
var fileExistsTool = defineTool({
|
|
42828
43197
|
name: "file_exists",
|
|
42829
|
-
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.
|
|
42830
43199
|
|
|
42831
43200
|
Examples:
|
|
42832
43201
|
- Check file: { "path": "package.json" } \u2192 { "exists": true, "isFile": true, "isDirectory": false }
|
|
@@ -42856,7 +43225,7 @@ Examples:
|
|
|
42856
43225
|
});
|
|
42857
43226
|
var listDirTool = defineTool({
|
|
42858
43227
|
name: "list_dir",
|
|
42859
|
-
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.
|
|
42860
43229
|
|
|
42861
43230
|
Examples:
|
|
42862
43231
|
- List src: { "path": "src" }
|
|
@@ -44394,7 +44763,7 @@ init_registry4();
|
|
|
44394
44763
|
init_errors();
|
|
44395
44764
|
var grepTool = defineTool({
|
|
44396
44765
|
name: "grep",
|
|
44397
|
-
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.
|
|
44398
44767
|
|
|
44399
44768
|
Examples:
|
|
44400
44769
|
- Simple search: { "pattern": "TODO" }
|
|
@@ -44527,7 +44896,7 @@ Examples:
|
|
|
44527
44896
|
});
|
|
44528
44897
|
var findInFileTool = defineTool({
|
|
44529
44898
|
name: "find_in_file",
|
|
44530
|
-
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.
|
|
44531
44900
|
|
|
44532
44901
|
Examples:
|
|
44533
44902
|
- Find text: { "file": "src/app.ts", "pattern": "export" }
|
|
@@ -45668,7 +46037,7 @@ async function searchSerpApi(query, maxResults, timeout) {
|
|
|
45668
46037
|
}
|
|
45669
46038
|
var webSearchTool = defineTool({
|
|
45670
46039
|
name: "web_search",
|
|
45671
|
-
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.
|
|
45672
46041
|
|
|
45673
46042
|
Examples:
|
|
45674
46043
|
- Basic search: { "query": "typescript zod validation examples" }
|
|
@@ -45953,7 +46322,7 @@ ${rows.join("\n")}
|
|
|
45953
46322
|
}
|
|
45954
46323
|
var webFetchTool = defineTool({
|
|
45955
46324
|
name: "web_fetch",
|
|
45956
|
-
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.
|
|
45957
46326
|
|
|
45958
46327
|
Examples:
|
|
45959
46328
|
- Fetch documentation: { "url": "https://docs.example.com/api" }
|
|
@@ -46641,8 +47010,7 @@ async function saveMemory(scope, memory) {
|
|
|
46641
47010
|
}
|
|
46642
47011
|
var createMemoryTool = defineTool({
|
|
46643
47012
|
name: "create_memory",
|
|
46644
|
-
description: `
|
|
46645
|
-
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.
|
|
46646
47014
|
|
|
46647
47015
|
Examples:
|
|
46648
47016
|
- Save convention: { "key": "naming-convention", "value": "Use camelCase for variables", "tags": ["style"] }
|
|
@@ -46699,7 +47067,7 @@ Examples:
|
|
|
46699
47067
|
});
|
|
46700
47068
|
var recallMemoryTool = defineTool({
|
|
46701
47069
|
name: "recall_memory",
|
|
46702
|
-
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).
|
|
46703
47071
|
|
|
46704
47072
|
Examples:
|
|
46705
47073
|
- By key substring: { "query": "naming" }
|
|
@@ -46754,7 +47122,7 @@ Examples:
|
|
|
46754
47122
|
});
|
|
46755
47123
|
var listMemoriesTool = defineTool({
|
|
46756
47124
|
name: "list_memories",
|
|
46757
|
-
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).
|
|
46758
47126
|
|
|
46759
47127
|
Examples:
|
|
46760
47128
|
- List all: { "scope": "all" }
|
|
@@ -56973,7 +57341,7 @@ program.command("setup").description("Configure AI provider and API key").action
|
|
|
56973
57341
|
console.log("\n\u274C Setup cancelled.");
|
|
56974
57342
|
}
|
|
56975
57343
|
});
|
|
56976
|
-
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(
|
|
56977
57345
|
async (options) => {
|
|
56978
57346
|
if (options.setup) {
|
|
56979
57347
|
const result = await runOnboardingV2();
|
|
@@ -57008,7 +57376,9 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
57008
57376
|
provider: {
|
|
57009
57377
|
type: providerType,
|
|
57010
57378
|
model: options.model ?? "",
|
|
57011
|
-
maxTokens: 8192
|
|
57379
|
+
maxTokens: 8192,
|
|
57380
|
+
editorModel: options.editorModel,
|
|
57381
|
+
weakModel: options.weakModel
|
|
57012
57382
|
}
|
|
57013
57383
|
}
|
|
57014
57384
|
});
|