@corbat-tech/coco 2.29.0 → 2.31.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/README.md +1 -0
- package/dist/cli/index.js +568 -52
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +48 -8
- package/dist/index.js +272 -47
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { execFile, execFileSync, execSync, spawn, exec } from 'child_process';
|
|
2
3
|
import { setGlobalDispatcher, EnvHttpProxyAgent } from 'undici';
|
|
3
4
|
import * as fs5 from 'fs';
|
|
4
5
|
import fs5__default, { accessSync, readFileSync, constants as constants$1 } from 'fs';
|
|
@@ -14,7 +15,6 @@ import JSON5 from 'json5';
|
|
|
14
15
|
import * as crypto from 'crypto';
|
|
15
16
|
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
16
17
|
import * as http from 'http';
|
|
17
|
-
import { execFile, execSync, spawn, execFileSync, exec } from 'child_process';
|
|
18
18
|
import { promisify } from 'util';
|
|
19
19
|
import * as p26 from '@clack/prompts';
|
|
20
20
|
import chalk from 'chalk';
|
|
@@ -83,14 +83,111 @@ function maskProxyUrl(url) {
|
|
|
83
83
|
return "[invalid proxy URL]";
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
function defaultRunner(cmd, args) {
|
|
87
|
+
try {
|
|
88
|
+
return execFileSync(cmd, args, {
|
|
89
|
+
encoding: "utf-8",
|
|
90
|
+
timeout: 2e3,
|
|
91
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
92
|
+
});
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function parseMacOsProxy(output) {
|
|
98
|
+
const getField = (name) => {
|
|
99
|
+
const re = new RegExp(`^\\s*${name}\\s*:\\s*(.+?)\\s*$`, "m");
|
|
100
|
+
return output.match(re)?.[1];
|
|
101
|
+
};
|
|
102
|
+
if (getField("ProxyAutoConfigEnable") === "1") {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const pick = (prefix) => {
|
|
106
|
+
if (getField(`${prefix}Enable`) !== "1") return null;
|
|
107
|
+
const host = getField(`${prefix}Proxy`);
|
|
108
|
+
const port = getField(`${prefix}Port`);
|
|
109
|
+
if (!host) return null;
|
|
110
|
+
return `http://${host}${port ? `:${port}` : ""}`;
|
|
111
|
+
};
|
|
112
|
+
const proxyUrl = pick("HTTPS") ?? pick("HTTP");
|
|
113
|
+
if (!proxyUrl) return null;
|
|
114
|
+
const exceptionsMatch = output.match(/ExceptionsList\s*:\s*<array>\s*\{([\s\S]*?)\}/);
|
|
115
|
+
const exceptions = [];
|
|
116
|
+
const exceptionsBody = exceptionsMatch?.[1];
|
|
117
|
+
if (exceptionsBody) {
|
|
118
|
+
for (const line of exceptionsBody.split("\n")) {
|
|
119
|
+
const entry = line.match(/^\s*\d+\s*:\s*(.+?)\s*$/)?.[1];
|
|
120
|
+
if (entry) exceptions.push(entry);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
proxyUrl,
|
|
125
|
+
noProxy: exceptions.length > 0 ? exceptions.join(",") : void 0
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function parseWindowsProxy(output) {
|
|
129
|
+
if (/Direct access/i.test(output)) return null;
|
|
130
|
+
const raw = output.match(/Proxy\s+Server\(s\)\s*:\s*(\S.*?)\s*$/m)?.[1]?.trim();
|
|
131
|
+
if (!raw) return null;
|
|
132
|
+
let hostPort = raw;
|
|
133
|
+
if (raw.includes("=")) {
|
|
134
|
+
const parts = raw.split(";").map((p47) => p47.trim());
|
|
135
|
+
const httpsEntry = parts.find((p47) => p47.toLowerCase().startsWith("https="));
|
|
136
|
+
const httpEntry = parts.find((p47) => p47.toLowerCase().startsWith("http="));
|
|
137
|
+
const chosen = httpsEntry ?? httpEntry;
|
|
138
|
+
if (!chosen) return null;
|
|
139
|
+
hostPort = chosen.split("=", 2)[1]?.trim() ?? "";
|
|
140
|
+
if (!hostPort) return null;
|
|
141
|
+
}
|
|
142
|
+
const proxyUrl = /^https?:\/\//i.test(hostPort) ? hostPort : `http://${hostPort}`;
|
|
143
|
+
let noProxy;
|
|
144
|
+
const bypass = output.match(/Bypass\s+List\s*:\s*(\S.*?)\s*$/m)?.[1]?.trim();
|
|
145
|
+
if (bypass && !/\(none\)/i.test(bypass)) {
|
|
146
|
+
noProxy = bypass.replace(/;/g, ",");
|
|
147
|
+
}
|
|
148
|
+
return { proxyUrl, noProxy };
|
|
149
|
+
}
|
|
150
|
+
function getProxyFromSystem(platform = process.platform, run = defaultRunner) {
|
|
151
|
+
if (platform === "darwin") {
|
|
152
|
+
const out = run("scutil", ["--proxy"]);
|
|
153
|
+
return out ? parseMacOsProxy(out) : null;
|
|
154
|
+
}
|
|
155
|
+
if (platform === "win32") {
|
|
156
|
+
const out = run("netsh", ["winhttp", "show", "proxy"]);
|
|
157
|
+
return out ? parseWindowsProxy(out) : null;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
function installProxyDispatcher(resolveSystem = () => getProxyFromSystem()) {
|
|
162
|
+
if (installed) {
|
|
163
|
+
const existing = getProxyFromEnv();
|
|
164
|
+
return existing ? maskProxyUrl(existing) : null;
|
|
165
|
+
}
|
|
166
|
+
const envProxy = getProxyFromEnv();
|
|
167
|
+
if (envProxy) {
|
|
168
|
+
return applyDispatcher(envProxy);
|
|
169
|
+
}
|
|
170
|
+
const sys = resolveSystem();
|
|
171
|
+
if (sys) {
|
|
172
|
+
seedEnv("HTTPS_PROXY", sys.proxyUrl);
|
|
173
|
+
seedEnv("HTTP_PROXY", sys.proxyUrl);
|
|
174
|
+
if (sys.noProxy && !process.env.NO_PROXY && !process.env.no_proxy) {
|
|
175
|
+
seedEnv("NO_PROXY", sys.noProxy);
|
|
176
|
+
}
|
|
177
|
+
return applyDispatcher(sys.proxyUrl);
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
function seedEnv(key, value) {
|
|
182
|
+
if (process.env[key] !== void 0) return;
|
|
183
|
+
process.env[key] = value;
|
|
184
|
+
seededEnvKeys.push(key);
|
|
185
|
+
}
|
|
186
|
+
function applyDispatcher(proxyUrl) {
|
|
90
187
|
try {
|
|
91
188
|
setGlobalDispatcher(new EnvHttpProxyAgent());
|
|
92
189
|
installed = true;
|
|
93
|
-
return maskProxyUrl(
|
|
190
|
+
return maskProxyUrl(proxyUrl);
|
|
94
191
|
} catch {
|
|
95
192
|
return null;
|
|
96
193
|
}
|
|
@@ -119,11 +216,12 @@ function unwrapCause(error) {
|
|
|
119
216
|
}
|
|
120
217
|
return void 0;
|
|
121
218
|
}
|
|
122
|
-
var PROXY_ENV_VARS, installed;
|
|
219
|
+
var PROXY_ENV_VARS, installed, seededEnvKeys;
|
|
123
220
|
var init_proxy = __esm({
|
|
124
221
|
"src/utils/proxy.ts"() {
|
|
125
222
|
PROXY_ENV_VARS = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"];
|
|
126
223
|
installed = false;
|
|
224
|
+
seededEnvKeys = [];
|
|
127
225
|
}
|
|
128
226
|
});
|
|
129
227
|
function findPackageJson() {
|
|
@@ -161,6 +259,7 @@ __export(schema_exports, {
|
|
|
161
259
|
ShipConfigSchema: () => ShipConfigSchema,
|
|
162
260
|
SkillsConfigSchema: () => SkillsConfigSchema,
|
|
163
261
|
StackConfigSchema: () => StackConfigSchema,
|
|
262
|
+
ThinkingModeSchema: () => ThinkingModeSchema,
|
|
164
263
|
ToolsConfigSchema: () => ToolsConfigSchema,
|
|
165
264
|
createDefaultConfigObject: () => createDefaultConfigObject,
|
|
166
265
|
validateConfig: () => validateConfig
|
|
@@ -205,9 +304,13 @@ function createDefaultConfigObject(projectName, language = "typescript") {
|
|
|
205
304
|
}
|
|
206
305
|
};
|
|
207
306
|
}
|
|
208
|
-
var ProviderConfigSchema, QualityConfigSchema, PersistenceConfigSchema, StackConfigSchema, ProjectConfigSchema, GitHubConfigSchema, IntegrationsConfigSchema, MCPServerConfigEntrySchema, MCPConfigSchema, ToolsConfigSchema, ShipConfigSchema, SkillsConfigSchema, CocoConfigSchema;
|
|
307
|
+
var ThinkingModeSchema, ProviderConfigSchema, QualityConfigSchema, PersistenceConfigSchema, StackConfigSchema, ProjectConfigSchema, GitHubConfigSchema, IntegrationsConfigSchema, MCPServerConfigEntrySchema, MCPConfigSchema, ToolsConfigSchema, ShipConfigSchema, SkillsConfigSchema, CocoConfigSchema;
|
|
209
308
|
var init_schema = __esm({
|
|
210
309
|
"src/config/schema.ts"() {
|
|
310
|
+
ThinkingModeSchema = z.union([
|
|
311
|
+
z.enum(["off", "auto", "low", "medium", "high"]),
|
|
312
|
+
z.object({ budget: z.number().int().min(0).max(2e5) })
|
|
313
|
+
]);
|
|
211
314
|
ProviderConfigSchema = z.object({
|
|
212
315
|
type: z.enum([
|
|
213
316
|
"anthropic",
|
|
@@ -369,6 +472,7 @@ var init_schema = __esm({
|
|
|
369
472
|
timeout: 12e4
|
|
370
473
|
}),
|
|
371
474
|
providerModels: z.record(z.string(), z.string()).optional(),
|
|
475
|
+
providerThinking: z.record(z.string(), ThinkingModeSchema).optional(),
|
|
372
476
|
quality: QualityConfigSchema.default({
|
|
373
477
|
minScore: 85,
|
|
374
478
|
minCoverage: 80,
|
|
@@ -2589,10 +2693,12 @@ __export(env_exports, {
|
|
|
2589
2693
|
getInternalProviderId: () => getInternalProviderId,
|
|
2590
2694
|
getLastUsedModel: () => getLastUsedModel,
|
|
2591
2695
|
getLastUsedProvider: () => getLastUsedProvider,
|
|
2696
|
+
getLastUsedThinking: () => getLastUsedThinking,
|
|
2592
2697
|
isOAuthProvider: () => isOAuthProvider,
|
|
2593
2698
|
migrateOldPreferences: () => migrateOldPreferences,
|
|
2594
2699
|
removeEnvProvider: () => removeEnvProvider,
|
|
2595
|
-
saveProviderPreference: () => saveProviderPreference
|
|
2700
|
+
saveProviderPreference: () => saveProviderPreference,
|
|
2701
|
+
saveThinkingPreference: () => saveThinkingPreference
|
|
2596
2702
|
});
|
|
2597
2703
|
function loadGlobalCocoEnv() {
|
|
2598
2704
|
try {
|
|
@@ -2812,6 +2918,51 @@ async function getLastUsedModel(provider) {
|
|
|
2812
2918
|
}
|
|
2813
2919
|
return void 0;
|
|
2814
2920
|
}
|
|
2921
|
+
async function getLastUsedThinking(provider) {
|
|
2922
|
+
try {
|
|
2923
|
+
const config = await loadConfig(CONFIG_PATHS.config);
|
|
2924
|
+
const mode = config.providerThinking?.[provider];
|
|
2925
|
+
return mode;
|
|
2926
|
+
} catch {
|
|
2927
|
+
return void 0;
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
async function saveThinkingPreference(provider, mode) {
|
|
2931
|
+
let config;
|
|
2932
|
+
try {
|
|
2933
|
+
config = await loadConfig(CONFIG_PATHS.config);
|
|
2934
|
+
} catch {
|
|
2935
|
+
config = {
|
|
2936
|
+
project: { name: "global", version: "0.1.0" },
|
|
2937
|
+
provider: {
|
|
2938
|
+
type: "anthropic",
|
|
2939
|
+
model: "claude-sonnet-4-6",
|
|
2940
|
+
maxTokens: 8192,
|
|
2941
|
+
temperature: 0,
|
|
2942
|
+
timeout: 12e4
|
|
2943
|
+
},
|
|
2944
|
+
quality: {
|
|
2945
|
+
minScore: 85,
|
|
2946
|
+
minCoverage: 80,
|
|
2947
|
+
maxIterations: 10,
|
|
2948
|
+
minIterations: 2,
|
|
2949
|
+
convergenceThreshold: 2,
|
|
2950
|
+
securityThreshold: 100
|
|
2951
|
+
},
|
|
2952
|
+
persistence: {
|
|
2953
|
+
checkpointInterval: 3e5,
|
|
2954
|
+
maxCheckpoints: 50,
|
|
2955
|
+
retentionDays: 7,
|
|
2956
|
+
compressOldCheckpoints: true
|
|
2957
|
+
}
|
|
2958
|
+
};
|
|
2959
|
+
}
|
|
2960
|
+
config.providerThinking = {
|
|
2961
|
+
...config.providerThinking,
|
|
2962
|
+
[provider]: mode
|
|
2963
|
+
};
|
|
2964
|
+
await saveConfig(config, void 0, true);
|
|
2965
|
+
}
|
|
2815
2966
|
async function saveProviderPreference(provider, model, options) {
|
|
2816
2967
|
let config;
|
|
2817
2968
|
try {
|
|
@@ -3182,6 +3333,160 @@ var init_logger = __esm({
|
|
|
3182
3333
|
globalLogger = null;
|
|
3183
3334
|
}
|
|
3184
3335
|
});
|
|
3336
|
+
|
|
3337
|
+
// src/providers/thinking.ts
|
|
3338
|
+
function isAnthropicThinkingModel(model) {
|
|
3339
|
+
const m = model.toLowerCase();
|
|
3340
|
+
if (m === "kimi-for-coding") return false;
|
|
3341
|
+
return m.includes("claude-3-7") || m.includes("claude-opus-4") || m.includes("claude-sonnet-4") || m.includes("claude-haiku-4-5") || m.includes("claude-4");
|
|
3342
|
+
}
|
|
3343
|
+
function isOpenAIReasoningModel(model) {
|
|
3344
|
+
const m = model.toLowerCase();
|
|
3345
|
+
return m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.startsWith("gpt-5") || m.includes("codex");
|
|
3346
|
+
}
|
|
3347
|
+
function isGeminiThinkingModel(model) {
|
|
3348
|
+
const m = model.toLowerCase();
|
|
3349
|
+
return m.includes("gemini-2.5-pro") || m.includes("gemini-2.5-flash") || m.includes("gemini-3") && !m.includes("flash-lite") || m.includes("gemini-2.0-flash-thinking");
|
|
3350
|
+
}
|
|
3351
|
+
function isKimiThinkingModel(model) {
|
|
3352
|
+
const m = model.toLowerCase();
|
|
3353
|
+
return m.includes("kimi-k2") || m === "kimi-latest";
|
|
3354
|
+
}
|
|
3355
|
+
function getThinkingCapability(provider, model) {
|
|
3356
|
+
switch (provider) {
|
|
3357
|
+
case "anthropic":
|
|
3358
|
+
case "kimi-code":
|
|
3359
|
+
return isAnthropicThinkingModel(model) ? ANTHROPIC_CAPABILITY : UNSUPPORTED;
|
|
3360
|
+
case "openai":
|
|
3361
|
+
case "copilot":
|
|
3362
|
+
case "groq":
|
|
3363
|
+
case "openrouter":
|
|
3364
|
+
case "mistral":
|
|
3365
|
+
case "deepseek":
|
|
3366
|
+
case "together":
|
|
3367
|
+
case "huggingface":
|
|
3368
|
+
case "qwen":
|
|
3369
|
+
return isOpenAIReasoningModel(model) ? OPENAI_CAPABILITY : UNSUPPORTED;
|
|
3370
|
+
case "kimi":
|
|
3371
|
+
return isKimiThinkingModel(model) ? KIMI_CAPABILITY : UNSUPPORTED;
|
|
3372
|
+
case "gemini":
|
|
3373
|
+
case "vertex":
|
|
3374
|
+
return isGeminiThinkingModel(model) ? GEMINI_CAPABILITY : UNSUPPORTED;
|
|
3375
|
+
case "lmstudio":
|
|
3376
|
+
case "ollama":
|
|
3377
|
+
case "codex":
|
|
3378
|
+
return UNSUPPORTED;
|
|
3379
|
+
default:
|
|
3380
|
+
return UNSUPPORTED;
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
function resolveDefaultThinking(provider, model) {
|
|
3384
|
+
return getThinkingCapability(provider, model).defaultMode;
|
|
3385
|
+
}
|
|
3386
|
+
function formatThinkingMode(mode) {
|
|
3387
|
+
if (typeof mode === "object") return `${mode.budget}t`;
|
|
3388
|
+
return mode;
|
|
3389
|
+
}
|
|
3390
|
+
function mapToAnthropic(mode, model) {
|
|
3391
|
+
if (!mode || mode === "off") return void 0;
|
|
3392
|
+
if (!isAnthropicThinkingModel(model)) return void 0;
|
|
3393
|
+
const cap = ANTHROPIC_CAPABILITY;
|
|
3394
|
+
const { min, max } = cap.budgetRange;
|
|
3395
|
+
if (typeof mode === "object") {
|
|
3396
|
+
return { type: "enabled", budget_tokens: Math.min(Math.max(mode.budget, min), max) };
|
|
3397
|
+
}
|
|
3398
|
+
const budgetMap = {
|
|
3399
|
+
auto: cap.budgetRange.default,
|
|
3400
|
+
low: ANTHROPIC_BUDGET.low,
|
|
3401
|
+
medium: ANTHROPIC_BUDGET.medium,
|
|
3402
|
+
high: ANTHROPIC_BUDGET.high
|
|
3403
|
+
};
|
|
3404
|
+
const budget = budgetMap[mode];
|
|
3405
|
+
if (budget === void 0) return void 0;
|
|
3406
|
+
return { type: "enabled", budget_tokens: budget };
|
|
3407
|
+
}
|
|
3408
|
+
function mapToOpenAIEffort(mode, model) {
|
|
3409
|
+
if (!mode || mode === "off") return void 0;
|
|
3410
|
+
if (!isOpenAIReasoningModel(model)) return void 0;
|
|
3411
|
+
if (typeof mode === "object") {
|
|
3412
|
+
const { budget } = mode;
|
|
3413
|
+
if (budget <= 2048) return "low";
|
|
3414
|
+
if (budget <= 8e3) return "medium";
|
|
3415
|
+
return "high";
|
|
3416
|
+
}
|
|
3417
|
+
if (mode === "auto") return "medium";
|
|
3418
|
+
if (mode === "low" || mode === "medium" || mode === "high") return mode;
|
|
3419
|
+
return void 0;
|
|
3420
|
+
}
|
|
3421
|
+
function mapToGeminiBudget(mode, model) {
|
|
3422
|
+
if (!isGeminiThinkingModel(model)) return void 0;
|
|
3423
|
+
if (!mode) return void 0;
|
|
3424
|
+
if (mode === "off") return 0;
|
|
3425
|
+
if (mode === "auto") return -1;
|
|
3426
|
+
const { min, max } = GEMINI_CAPABILITY.budgetRange;
|
|
3427
|
+
if (typeof mode === "object") {
|
|
3428
|
+
return Math.min(Math.max(mode.budget, min), max);
|
|
3429
|
+
}
|
|
3430
|
+
const budgetMap = {
|
|
3431
|
+
low: GEMINI_BUDGET.low,
|
|
3432
|
+
medium: GEMINI_BUDGET.medium,
|
|
3433
|
+
high: GEMINI_BUDGET.high
|
|
3434
|
+
};
|
|
3435
|
+
return budgetMap[mode];
|
|
3436
|
+
}
|
|
3437
|
+
function mapToKimiExtraBody(mode, model) {
|
|
3438
|
+
if (!isKimiThinkingModel(model)) return void 0;
|
|
3439
|
+
const effectiveMode = mode ?? "off";
|
|
3440
|
+
const enabled = effectiveMode !== "off";
|
|
3441
|
+
return { thinking: { type: enabled ? "enabled" : "disabled" } };
|
|
3442
|
+
}
|
|
3443
|
+
var ANTHROPIC_BUDGET, GEMINI_BUDGET, UNSUPPORTED, ANTHROPIC_CAPABILITY, OPENAI_CAPABILITY, GEMINI_CAPABILITY, KIMI_CAPABILITY;
|
|
3444
|
+
var init_thinking = __esm({
|
|
3445
|
+
"src/providers/thinking.ts"() {
|
|
3446
|
+
ANTHROPIC_BUDGET = {
|
|
3447
|
+
low: 2048,
|
|
3448
|
+
medium: 8e3,
|
|
3449
|
+
high: 16e3
|
|
3450
|
+
};
|
|
3451
|
+
GEMINI_BUDGET = {
|
|
3452
|
+
low: 2048,
|
|
3453
|
+
medium: 8e3,
|
|
3454
|
+
high: 16e3
|
|
3455
|
+
};
|
|
3456
|
+
UNSUPPORTED = {
|
|
3457
|
+
supported: false,
|
|
3458
|
+
kinds: [],
|
|
3459
|
+
levels: ["off"],
|
|
3460
|
+
defaultMode: "off"
|
|
3461
|
+
};
|
|
3462
|
+
ANTHROPIC_CAPABILITY = {
|
|
3463
|
+
supported: true,
|
|
3464
|
+
kinds: ["budget"],
|
|
3465
|
+
levels: ["off", "auto", "low", "medium", "high"],
|
|
3466
|
+
budgetRange: { min: 1024, max: 64e3, default: ANTHROPIC_BUDGET.medium },
|
|
3467
|
+
defaultMode: "off"
|
|
3468
|
+
};
|
|
3469
|
+
OPENAI_CAPABILITY = {
|
|
3470
|
+
supported: true,
|
|
3471
|
+
kinds: ["effort"],
|
|
3472
|
+
levels: ["off", "auto", "low", "medium", "high"],
|
|
3473
|
+
defaultMode: "medium"
|
|
3474
|
+
};
|
|
3475
|
+
GEMINI_CAPABILITY = {
|
|
3476
|
+
supported: true,
|
|
3477
|
+
kinds: ["budget"],
|
|
3478
|
+
levels: ["off", "auto", "low", "medium", "high"],
|
|
3479
|
+
budgetRange: { min: 0, max: 32e3, default: GEMINI_BUDGET.medium },
|
|
3480
|
+
defaultMode: "auto"
|
|
3481
|
+
};
|
|
3482
|
+
KIMI_CAPABILITY = {
|
|
3483
|
+
supported: true,
|
|
3484
|
+
kinds: ["effort"],
|
|
3485
|
+
levels: ["off", "auto"],
|
|
3486
|
+
defaultMode: "off"
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
});
|
|
3185
3490
|
function createAnthropicProvider(config) {
|
|
3186
3491
|
const provider = new AnthropicProvider();
|
|
3187
3492
|
if (config) {
|
|
@@ -3210,6 +3515,7 @@ var init_anthropic = __esm({
|
|
|
3210
3515
|
init_errors();
|
|
3211
3516
|
init_retry();
|
|
3212
3517
|
init_logger();
|
|
3518
|
+
init_thinking();
|
|
3213
3519
|
DEFAULT_MODEL = "claude-opus-4-6";
|
|
3214
3520
|
CONTEXT_WINDOWS = {
|
|
3215
3521
|
// Kimi Code model (Anthropic-compatible endpoint)
|
|
@@ -3270,13 +3576,19 @@ var init_anthropic = __esm({
|
|
|
3270
3576
|
this.ensureInitialized();
|
|
3271
3577
|
return withRetry(async () => {
|
|
3272
3578
|
try {
|
|
3579
|
+
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL;
|
|
3580
|
+
const thinkingParam = mapToAnthropic(options?.thinking, model);
|
|
3581
|
+
const baseMaxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
3273
3582
|
const response = await this.client.messages.create({
|
|
3274
|
-
model
|
|
3275
|
-
|
|
3276
|
-
|
|
3583
|
+
model,
|
|
3584
|
+
// Anthropic requires max_tokens > budget_tokens
|
|
3585
|
+
max_tokens: thinkingParam ? Math.max(baseMaxTokens, thinkingParam.budget_tokens + 1024) : baseMaxTokens,
|
|
3586
|
+
// Anthropic requires temperature=1 when thinking is enabled
|
|
3587
|
+
temperature: thinkingParam ? 1 : options?.temperature ?? this.config.temperature ?? 0,
|
|
3277
3588
|
system: this.extractSystem(messages, options?.system),
|
|
3278
3589
|
messages: this.convertMessages(messages),
|
|
3279
|
-
stop_sequences: options?.stopSequences
|
|
3590
|
+
stop_sequences: options?.stopSequences,
|
|
3591
|
+
...thinkingParam && { thinking: thinkingParam }
|
|
3280
3592
|
});
|
|
3281
3593
|
return {
|
|
3282
3594
|
id: response.id,
|
|
@@ -3300,14 +3612,18 @@ var init_anthropic = __esm({
|
|
|
3300
3612
|
this.ensureInitialized();
|
|
3301
3613
|
return withRetry(async () => {
|
|
3302
3614
|
try {
|
|
3615
|
+
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL;
|
|
3616
|
+
const thinkingParam = mapToAnthropic(options?.thinking, model);
|
|
3617
|
+
const baseMaxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
3303
3618
|
const response = await this.client.messages.create({
|
|
3304
|
-
model
|
|
3305
|
-
max_tokens:
|
|
3306
|
-
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
3619
|
+
model,
|
|
3620
|
+
max_tokens: thinkingParam ? Math.max(baseMaxTokens, thinkingParam.budget_tokens + 1024) : baseMaxTokens,
|
|
3621
|
+
temperature: thinkingParam ? 1 : options?.temperature ?? this.config.temperature ?? 0,
|
|
3307
3622
|
system: this.extractSystem(messages, options?.system),
|
|
3308
3623
|
messages: this.convertMessages(messages),
|
|
3309
3624
|
tools: this.convertTools(options.tools),
|
|
3310
|
-
tool_choice: options.toolChoice ? this.convertToolChoice(options.toolChoice) : void 0
|
|
3625
|
+
tool_choice: options.toolChoice ? this.convertToolChoice(options.toolChoice) : void 0,
|
|
3626
|
+
...thinkingParam && { thinking: thinkingParam }
|
|
3311
3627
|
});
|
|
3312
3628
|
const toolCalls = this.extractToolCalls(response.content);
|
|
3313
3629
|
return {
|
|
@@ -3333,13 +3649,17 @@ var init_anthropic = __esm({
|
|
|
3333
3649
|
this.ensureInitialized();
|
|
3334
3650
|
let timeoutTriggered = false;
|
|
3335
3651
|
try {
|
|
3652
|
+
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL;
|
|
3653
|
+
const thinkingParam = mapToAnthropic(options?.thinking, model);
|
|
3654
|
+
const baseMaxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
3336
3655
|
const stream = await this.client.messages.stream(
|
|
3337
3656
|
{
|
|
3338
|
-
model
|
|
3339
|
-
max_tokens:
|
|
3340
|
-
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
3657
|
+
model,
|
|
3658
|
+
max_tokens: thinkingParam ? Math.max(baseMaxTokens, thinkingParam.budget_tokens + 1024) : baseMaxTokens,
|
|
3659
|
+
temperature: thinkingParam ? 1 : options?.temperature ?? this.config.temperature ?? 0,
|
|
3341
3660
|
system: this.extractSystem(messages, options?.system),
|
|
3342
|
-
messages: this.convertMessages(messages)
|
|
3661
|
+
messages: this.convertMessages(messages),
|
|
3662
|
+
...thinkingParam && { thinking: thinkingParam }
|
|
3343
3663
|
},
|
|
3344
3664
|
{ signal: options?.signal }
|
|
3345
3665
|
);
|
|
@@ -3395,15 +3715,19 @@ var init_anthropic = __esm({
|
|
|
3395
3715
|
this.ensureInitialized();
|
|
3396
3716
|
let timeoutTriggered = false;
|
|
3397
3717
|
try {
|
|
3718
|
+
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL;
|
|
3719
|
+
const thinkingParam = mapToAnthropic(options?.thinking, model);
|
|
3720
|
+
const baseMaxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
3398
3721
|
const stream = await this.client.messages.stream(
|
|
3399
3722
|
{
|
|
3400
|
-
model
|
|
3401
|
-
max_tokens:
|
|
3402
|
-
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
3723
|
+
model,
|
|
3724
|
+
max_tokens: thinkingParam ? Math.max(baseMaxTokens, thinkingParam.budget_tokens + 1024) : baseMaxTokens,
|
|
3725
|
+
temperature: thinkingParam ? 1 : options?.temperature ?? this.config.temperature ?? 0,
|
|
3403
3726
|
system: this.extractSystem(messages, options?.system),
|
|
3404
3727
|
messages: this.convertMessages(messages),
|
|
3405
3728
|
tools: this.convertTools(options.tools),
|
|
3406
|
-
tool_choice: options.toolChoice ? this.convertToolChoice(options.toolChoice) : void 0
|
|
3729
|
+
tool_choice: options.toolChoice ? this.convertToolChoice(options.toolChoice) : void 0,
|
|
3730
|
+
...thinkingParam && { thinking: thinkingParam }
|
|
3407
3731
|
},
|
|
3408
3732
|
{ signal: options?.signal }
|
|
3409
3733
|
);
|
|
@@ -3924,6 +4248,7 @@ var init_openai = __esm({
|
|
|
3924
4248
|
init_errors();
|
|
3925
4249
|
init_retry();
|
|
3926
4250
|
init_tool_call_normalizer();
|
|
4251
|
+
init_thinking();
|
|
3927
4252
|
DEFAULT_MODEL2 = "gpt-5.3-codex";
|
|
3928
4253
|
CONTEXT_WINDOWS2 = {
|
|
3929
4254
|
// OpenAI models
|
|
@@ -4076,26 +4401,15 @@ var init_openai = __esm({
|
|
|
4076
4401
|
return !MODELS_WITHOUT_TEMPERATURE.some((m) => model.toLowerCase().includes(m.toLowerCase()));
|
|
4077
4402
|
}
|
|
4078
4403
|
/**
|
|
4079
|
-
*
|
|
4080
|
-
*
|
|
4081
|
-
*
|
|
4082
|
-
*/
|
|
4083
|
-
needsThinkingDisabled(model) {
|
|
4084
|
-
return MODELS_WITH_THINKING_MODE.some((m) => model.toLowerCase().includes(m.toLowerCase()));
|
|
4085
|
-
}
|
|
4086
|
-
/**
|
|
4087
|
-
* Get extra body parameters for API calls
|
|
4088
|
-
* Used to disable thinking mode for Kimi models
|
|
4089
|
-
* See: https://huggingface.co/moonshotai/Kimi-K2.5
|
|
4090
|
-
*
|
|
4091
|
-
* For Official Moonshot API: {'thinking': {'type': 'disabled'}}
|
|
4092
|
-
* For vLLM/SGLang: {'chat_template_kwargs': {"thinking": False}}
|
|
4404
|
+
* Get extra body parameters for API calls.
|
|
4405
|
+
* Honors the user's ThinkingMode for Kimi models; defaults to disabled
|
|
4406
|
+
* (preserving existing behavior) when no mode is specified.
|
|
4093
4407
|
*/
|
|
4094
|
-
getExtraBody(model) {
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
};
|
|
4408
|
+
getExtraBody(model, thinking) {
|
|
4409
|
+
const kimiBody = mapToKimiExtraBody(thinking, model);
|
|
4410
|
+
if (kimiBody) return kimiBody;
|
|
4411
|
+
if (MODELS_WITH_THINKING_MODE.some((m) => model.toLowerCase().includes(m.toLowerCase()))) {
|
|
4412
|
+
return { thinking: { type: "disabled" } };
|
|
4099
4413
|
}
|
|
4100
4414
|
return void 0;
|
|
4101
4415
|
}
|
|
@@ -4112,6 +4426,7 @@ var init_openai = __esm({
|
|
|
4112
4426
|
try {
|
|
4113
4427
|
const supportsTemp = this.supportsTemperature(model);
|
|
4114
4428
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4429
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4115
4430
|
const response = await this.client.chat.completions.create({
|
|
4116
4431
|
model,
|
|
4117
4432
|
...buildMaxTokensParam(model, maxTokens),
|
|
@@ -4119,7 +4434,8 @@ var init_openai = __esm({
|
|
|
4119
4434
|
stop: options?.stopSequences,
|
|
4120
4435
|
...supportsTemp && {
|
|
4121
4436
|
temperature: options?.temperature ?? this.config.temperature ?? 0
|
|
4122
|
-
}
|
|
4437
|
+
},
|
|
4438
|
+
...reasoningEffort && { reasoning_effort: reasoningEffort }
|
|
4123
4439
|
});
|
|
4124
4440
|
const choice = response.choices[0];
|
|
4125
4441
|
return {
|
|
@@ -4149,7 +4465,8 @@ var init_openai = __esm({
|
|
|
4149
4465
|
return withRetry(async () => {
|
|
4150
4466
|
try {
|
|
4151
4467
|
const supportsTemp = this.supportsTemperature(model);
|
|
4152
|
-
const extraBody = this.getExtraBody(model);
|
|
4468
|
+
const extraBody = this.getExtraBody(model, options?.thinking);
|
|
4469
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4153
4470
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4154
4471
|
const requestParams = {
|
|
4155
4472
|
model,
|
|
@@ -4161,6 +4478,9 @@ var init_openai = __esm({
|
|
|
4161
4478
|
if (supportsTemp) {
|
|
4162
4479
|
requestParams.temperature = options?.temperature ?? this.config.temperature ?? 0;
|
|
4163
4480
|
}
|
|
4481
|
+
if (reasoningEffort) {
|
|
4482
|
+
requestParams.reasoning_effort = reasoningEffort;
|
|
4483
|
+
}
|
|
4164
4484
|
if (extraBody) {
|
|
4165
4485
|
Object.assign(requestParams, extraBody);
|
|
4166
4486
|
}
|
|
@@ -4198,12 +4518,14 @@ var init_openai = __esm({
|
|
|
4198
4518
|
try {
|
|
4199
4519
|
const supportsTemp = this.supportsTemperature(model);
|
|
4200
4520
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4521
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4201
4522
|
const stream = await this.client.chat.completions.create({
|
|
4202
4523
|
model,
|
|
4203
4524
|
...buildMaxTokensParam(model, maxTokens),
|
|
4204
4525
|
messages: this.convertMessages(messages, options?.system),
|
|
4205
4526
|
stream: true,
|
|
4206
|
-
...supportsTemp && { temperature: options?.temperature ?? this.config.temperature ?? 0 }
|
|
4527
|
+
...supportsTemp && { temperature: options?.temperature ?? this.config.temperature ?? 0 },
|
|
4528
|
+
...reasoningEffort && { reasoning_effort: reasoningEffort }
|
|
4207
4529
|
});
|
|
4208
4530
|
let streamStopReason;
|
|
4209
4531
|
for await (const chunk of stream) {
|
|
@@ -4234,7 +4556,8 @@ var init_openai = __esm({
|
|
|
4234
4556
|
let timeoutTriggered = false;
|
|
4235
4557
|
try {
|
|
4236
4558
|
const supportsTemp = this.supportsTemperature(model);
|
|
4237
|
-
const extraBody = this.getExtraBody(model);
|
|
4559
|
+
const extraBody = this.getExtraBody(model, options?.thinking);
|
|
4560
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4238
4561
|
const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
|
|
4239
4562
|
const requestParams = {
|
|
4240
4563
|
model,
|
|
@@ -4247,6 +4570,9 @@ var init_openai = __esm({
|
|
|
4247
4570
|
if (supportsTemp) {
|
|
4248
4571
|
requestParams.temperature = options?.temperature ?? this.config.temperature ?? 0;
|
|
4249
4572
|
}
|
|
4573
|
+
if (reasoningEffort) {
|
|
4574
|
+
requestParams.reasoning_effort = reasoningEffort;
|
|
4575
|
+
}
|
|
4250
4576
|
if (extraBody) {
|
|
4251
4577
|
Object.assign(requestParams, extraBody);
|
|
4252
4578
|
}
|
|
@@ -4714,6 +5040,7 @@ var init_openai = __esm({
|
|
|
4714
5040
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
4715
5041
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
4716
5042
|
const supportsTemp = this.supportsTemperature(model);
|
|
5043
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4717
5044
|
const response = await this.client.responses.create({
|
|
4718
5045
|
model,
|
|
4719
5046
|
input,
|
|
@@ -4722,6 +5049,8 @@ var init_openai = __esm({
|
|
|
4722
5049
|
...supportsTemp && {
|
|
4723
5050
|
temperature: options?.temperature ?? this.config.temperature ?? 0
|
|
4724
5051
|
},
|
|
5052
|
+
// Responses API uses nested reasoning.effort (not top-level reasoning_effort)
|
|
5053
|
+
...reasoningEffort && { reasoning: { effort: reasoningEffort } },
|
|
4725
5054
|
store: false
|
|
4726
5055
|
});
|
|
4727
5056
|
return {
|
|
@@ -4750,6 +5079,7 @@ var init_openai = __esm({
|
|
|
4750
5079
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
4751
5080
|
const tools = this.convertToolsForResponses(options.tools);
|
|
4752
5081
|
const supportsTemp = this.supportsTemperature(model);
|
|
5082
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4753
5083
|
const response = await this.client.responses.create({
|
|
4754
5084
|
model,
|
|
4755
5085
|
input,
|
|
@@ -4759,6 +5089,7 @@ var init_openai = __esm({
|
|
|
4759
5089
|
...supportsTemp && {
|
|
4760
5090
|
temperature: options?.temperature ?? this.config.temperature ?? 0
|
|
4761
5091
|
},
|
|
5092
|
+
...reasoningEffort && { reasoning: { effort: reasoningEffort } },
|
|
4762
5093
|
store: false
|
|
4763
5094
|
});
|
|
4764
5095
|
let content = "";
|
|
@@ -4804,12 +5135,14 @@ var init_openai = __esm({
|
|
|
4804
5135
|
const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
|
|
4805
5136
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
4806
5137
|
const supportsTemp = this.supportsTemperature(model);
|
|
5138
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4807
5139
|
const stream = await this.client.responses.create({
|
|
4808
5140
|
model,
|
|
4809
5141
|
input,
|
|
4810
5142
|
instructions: instructions ?? void 0,
|
|
4811
5143
|
max_output_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
|
|
4812
5144
|
...supportsTemp && { temperature: options?.temperature ?? this.config.temperature ?? 0 },
|
|
5145
|
+
...reasoningEffort && { reasoning: { effort: reasoningEffort } },
|
|
4813
5146
|
store: false,
|
|
4814
5147
|
stream: true
|
|
4815
5148
|
});
|
|
@@ -4867,12 +5200,14 @@ var init_openai = __esm({
|
|
|
4867
5200
|
const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
|
|
4868
5201
|
const tools = options.tools.length > 0 ? this.convertToolsForResponses(options.tools) : void 0;
|
|
4869
5202
|
const supportsTemp = this.supportsTemperature(model);
|
|
5203
|
+
const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
|
|
4870
5204
|
const requestParams = {
|
|
4871
5205
|
model,
|
|
4872
5206
|
input,
|
|
4873
5207
|
instructions: instructions ?? void 0,
|
|
4874
5208
|
max_output_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
|
|
4875
5209
|
...supportsTemp && { temperature: options?.temperature ?? this.config.temperature ?? 0 },
|
|
5210
|
+
...reasoningEffort && { reasoning: { effort: reasoningEffort } },
|
|
4876
5211
|
store: false,
|
|
4877
5212
|
stream: true
|
|
4878
5213
|
};
|
|
@@ -5912,6 +6247,7 @@ var DEFAULT_MODEL5, SKIP_THOUGHT_SIGNATURE_VALIDATOR, CONTEXT_WINDOWS5, GeminiPr
|
|
|
5912
6247
|
var init_gemini = __esm({
|
|
5913
6248
|
"src/providers/gemini.ts"() {
|
|
5914
6249
|
init_errors();
|
|
6250
|
+
init_thinking();
|
|
5915
6251
|
DEFAULT_MODEL5 = "gemini-3.1-pro-preview";
|
|
5916
6252
|
SKIP_THOUGHT_SIGNATURE_VALIDATOR = "skip_thought_signature_validator";
|
|
5917
6253
|
CONTEXT_WINDOWS5 = {
|
|
@@ -6070,12 +6406,17 @@ var init_gemini = __esm({
|
|
|
6070
6406
|
return model ?? this.config.model ?? DEFAULT_MODEL5;
|
|
6071
6407
|
}
|
|
6072
6408
|
buildConfig(messages, options, tools, toolChoice) {
|
|
6409
|
+
const model = this.getModel(options?.model);
|
|
6410
|
+
const thinkingBudget = mapToGeminiBudget(options?.thinking, model);
|
|
6073
6411
|
const config = {
|
|
6074
6412
|
maxOutputTokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
|
|
6075
6413
|
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
6076
6414
|
stopSequences: options?.stopSequences,
|
|
6077
6415
|
systemInstruction: this.extractSystem(messages, options?.system)
|
|
6078
6416
|
};
|
|
6417
|
+
if (thinkingBudget !== void 0) {
|
|
6418
|
+
config.thinkingConfig = { thinkingBudget };
|
|
6419
|
+
}
|
|
6079
6420
|
if (tools && tools.length > 0) {
|
|
6080
6421
|
config.tools = [{ functionDeclarations: this.convertTools(tools) }];
|
|
6081
6422
|
config.toolConfig = {
|
|
@@ -10443,11 +10784,15 @@ function generateToolCatalog(registry) {
|
|
|
10443
10784
|
async function createDefaultReplConfig() {
|
|
10444
10785
|
const providerType = await getLastUsedProvider();
|
|
10445
10786
|
const model = await getLastUsedModel(providerType) || getDefaultModel(providerType);
|
|
10787
|
+
const persistedThinking = await getLastUsedThinking(providerType);
|
|
10788
|
+
const thinking = persistedThinking ?? resolveDefaultThinking(providerType, model);
|
|
10789
|
+
const thinkingToStore = thinking === "off" ? void 0 : thinking;
|
|
10446
10790
|
return {
|
|
10447
10791
|
provider: {
|
|
10448
10792
|
type: providerType,
|
|
10449
10793
|
model,
|
|
10450
|
-
maxTokens: 8192
|
|
10794
|
+
maxTokens: 8192,
|
|
10795
|
+
thinking: thinkingToStore
|
|
10451
10796
|
},
|
|
10452
10797
|
ui: {
|
|
10453
10798
|
theme: "auto",
|
|
@@ -10882,6 +11227,7 @@ var MAX_SKILL_INSTRUCTIONS_CHARS, TRUST_SETTINGS_DIR, TRUST_SETTINGS_FILE, PROJE
|
|
|
10882
11227
|
var init_session = __esm({
|
|
10883
11228
|
"src/cli/repl/session.ts"() {
|
|
10884
11229
|
init_env();
|
|
11230
|
+
init_thinking();
|
|
10885
11231
|
init_manager();
|
|
10886
11232
|
init_compactor();
|
|
10887
11233
|
init_memory();
|
|
@@ -33585,6 +33931,7 @@ var helpCommand = {
|
|
|
33585
33931
|
commands: [
|
|
33586
33932
|
{ cmd: "/model, /m", desc: "View or change the current model" },
|
|
33587
33933
|
{ cmd: "/provider", desc: "View or change the LLM provider" },
|
|
33934
|
+
{ cmd: "/thinking, /think", desc: "View or change the reasoning/thinking mode" },
|
|
33588
33935
|
{ cmd: "/doctor, /dr", desc: "Run local diagnostics for config, auth, hooks, and tools" },
|
|
33589
33936
|
{ cmd: "/compact", desc: "Toggle compact mode (less verbose)" },
|
|
33590
33937
|
{ cmd: "/cost, /tokens", desc: "Show token usage and cost" },
|
|
@@ -34051,6 +34398,7 @@ function truncate2(str, maxLength, suffix = "...") {
|
|
|
34051
34398
|
|
|
34052
34399
|
// src/cli/repl/commands/model.ts
|
|
34053
34400
|
init_env();
|
|
34401
|
+
init_thinking();
|
|
34054
34402
|
async function fetchLocalModels(providerType) {
|
|
34055
34403
|
try {
|
|
34056
34404
|
const baseUrl = getBaseUrl(providerType);
|
|
@@ -34232,6 +34580,32 @@ async function persistModelPreference(provider, model) {
|
|
|
34232
34580
|
console.log(chalk.dim(" Model changed for this session only.\n"));
|
|
34233
34581
|
}
|
|
34234
34582
|
}
|
|
34583
|
+
function reconcileThinkingAfterModelChange(session, newModel) {
|
|
34584
|
+
const provider = session.config.provider.type;
|
|
34585
|
+
const cap = getThinkingCapability(provider, newModel);
|
|
34586
|
+
if (!cap.supported) {
|
|
34587
|
+
if (session.config.provider.thinking !== void 0) {
|
|
34588
|
+
session.config.provider.thinking = void 0;
|
|
34589
|
+
console.log(chalk.dim(" \u2139 Thinking not supported on this model \u2014 turned off."));
|
|
34590
|
+
}
|
|
34591
|
+
return;
|
|
34592
|
+
}
|
|
34593
|
+
const current = session.config.provider.thinking;
|
|
34594
|
+
if (current !== void 0 && typeof current === "object" && !cap.kinds.includes("budget")) {
|
|
34595
|
+
const newDefault = resolveDefaultThinking(provider, newModel);
|
|
34596
|
+
session.config.provider.thinking = newDefault === "off" ? void 0 : newDefault;
|
|
34597
|
+
console.log(
|
|
34598
|
+
chalk.dim(
|
|
34599
|
+
` \u2139 Thinking reset to ${session.config.provider.thinking ?? "off"} (model uses effort levels).`
|
|
34600
|
+
)
|
|
34601
|
+
);
|
|
34602
|
+
return;
|
|
34603
|
+
}
|
|
34604
|
+
if (current === void 0) {
|
|
34605
|
+
const def = resolveDefaultThinking(provider, newModel);
|
|
34606
|
+
session.config.provider.thinking = def === "off" ? void 0 : def;
|
|
34607
|
+
}
|
|
34608
|
+
}
|
|
34235
34609
|
var modelCommand = {
|
|
34236
34610
|
name: "model",
|
|
34237
34611
|
aliases: ["m"],
|
|
@@ -34280,6 +34654,7 @@ var modelCommand = {
|
|
|
34280
34654
|
return false;
|
|
34281
34655
|
}
|
|
34282
34656
|
session.config.provider.model = selectedModel;
|
|
34657
|
+
reconcileThinkingAfterModelChange(session, selectedModel);
|
|
34283
34658
|
await persistModelPreference(currentProvider, selectedModel);
|
|
34284
34659
|
const modelInfo2 = providerDef.models.find((m) => m.id === selectedModel);
|
|
34285
34660
|
console.log(chalk.green(`\u2713 Switched to ${modelInfo2?.name ?? selectedModel}
|
|
@@ -34302,6 +34677,7 @@ var modelCommand = {
|
|
|
34302
34677
|
if (!foundInProvider) {
|
|
34303
34678
|
console.log(chalk.yellow(`Model "${newModel}" not in known list, setting anyway...`));
|
|
34304
34679
|
session.config.provider.model = newModel;
|
|
34680
|
+
reconcileThinkingAfterModelChange(session, newModel);
|
|
34305
34681
|
await persistModelPreference(currentProvider, newModel);
|
|
34306
34682
|
console.log(chalk.green(`\u2713 Model set to: ${newModel}
|
|
34307
34683
|
`));
|
|
@@ -34317,6 +34693,7 @@ var modelCommand = {
|
|
|
34317
34693
|
return false;
|
|
34318
34694
|
}
|
|
34319
34695
|
session.config.provider.model = newModel;
|
|
34696
|
+
reconcileThinkingAfterModelChange(session, newModel);
|
|
34320
34697
|
await persistModelPreference(currentProvider, newModel);
|
|
34321
34698
|
const modelInfo = providerDef.models.find((m) => m.id === newModel);
|
|
34322
34699
|
console.log(chalk.green(`\u2713 Switched to ${modelInfo?.name ?? newModel}
|
|
@@ -36309,6 +36686,7 @@ async function promptVertexSettings2(defaults) {
|
|
|
36309
36686
|
// src/cli/repl/commands/status.ts
|
|
36310
36687
|
init_state();
|
|
36311
36688
|
init_trust_store();
|
|
36689
|
+
init_thinking();
|
|
36312
36690
|
function getGitStatus2(projectPath) {
|
|
36313
36691
|
try {
|
|
36314
36692
|
execSync("git rev-parse --git-dir", { cwd: projectPath, stdio: "pipe" });
|
|
@@ -36434,6 +36812,11 @@ var statusCommand = {
|
|
|
36434
36812
|
p26.log.step("Session");
|
|
36435
36813
|
p26.log.message(` \u{1F4C1} ${session.projectPath}`);
|
|
36436
36814
|
p26.log.message(` \u{1F916} ${session.config.provider.type} / ${session.config.provider.model}`);
|
|
36815
|
+
const cap = getThinkingCapability(session.config.provider.type, session.config.provider.model);
|
|
36816
|
+
if (cap.supported) {
|
|
36817
|
+
const thinkingLabel = session.config.provider.thinking !== void 0 ? formatThinkingMode(session.config.provider.thinking) : "off";
|
|
36818
|
+
p26.log.message(` \u{1F9E0} thinking: ${thinkingLabel} ${chalk.dim("(/thinking to change)")}`);
|
|
36819
|
+
}
|
|
36437
36820
|
p26.outro("Done");
|
|
36438
36821
|
return false;
|
|
36439
36822
|
}
|
|
@@ -50369,6 +50752,133 @@ var doctorCommand = {
|
|
|
50369
50752
|
}
|
|
50370
50753
|
};
|
|
50371
50754
|
|
|
50755
|
+
// src/cli/repl/commands/thinking.ts
|
|
50756
|
+
init_thinking();
|
|
50757
|
+
init_env();
|
|
50758
|
+
var EFFORT_LEVELS = ["off", "auto", "low", "medium", "high"];
|
|
50759
|
+
function isEffortLevel(s) {
|
|
50760
|
+
return EFFORT_LEVELS.includes(s);
|
|
50761
|
+
}
|
|
50762
|
+
function parseThinkingArg(arg) {
|
|
50763
|
+
if (isEffortLevel(arg)) return arg;
|
|
50764
|
+
const n = parseInt(arg, 10);
|
|
50765
|
+
if (!isNaN(n) && n >= 0) return { budget: n };
|
|
50766
|
+
return null;
|
|
50767
|
+
}
|
|
50768
|
+
var thinkingCommand = {
|
|
50769
|
+
name: "thinking",
|
|
50770
|
+
aliases: ["think", "reason"],
|
|
50771
|
+
description: "View or change the reasoning/thinking mode for the current model",
|
|
50772
|
+
usage: "/thinking [off|auto|low|medium|high|<budget-tokens>]",
|
|
50773
|
+
async execute(args, session) {
|
|
50774
|
+
const provider = session.config.provider.type;
|
|
50775
|
+
const model = session.config.provider.model;
|
|
50776
|
+
const capability = getThinkingCapability(provider, model);
|
|
50777
|
+
if (args.length === 0) {
|
|
50778
|
+
const current = session.config.provider.thinking;
|
|
50779
|
+
const display = current !== void 0 ? formatThinkingMode(current) : "off";
|
|
50780
|
+
if (!capability.supported) {
|
|
50781
|
+
console.log(
|
|
50782
|
+
chalk.yellow(`
|
|
50783
|
+
\u26A0 Thinking not supported for ${model} on ${provider}.
|
|
50784
|
+
`) + chalk.dim(
|
|
50785
|
+
" Compatible models: claude-3-7+, claude-4+, o3, o4-mini, gpt-5*, gemini-2.5+\n"
|
|
50786
|
+
)
|
|
50787
|
+
);
|
|
50788
|
+
return false;
|
|
50789
|
+
}
|
|
50790
|
+
console.log(chalk.cyan.bold("\n\u2550\u2550\u2550 Thinking Mode \u2550\u2550\u2550\n"));
|
|
50791
|
+
console.log(` Current: ${chalk.magenta(display)}`);
|
|
50792
|
+
console.log(` Provider: ${chalk.dim(provider)} / ${chalk.dim(model)}`);
|
|
50793
|
+
console.log(` Supports: ${capability.kinds.join(", ")}`);
|
|
50794
|
+
if (capability.budgetRange) {
|
|
50795
|
+
const { min, max, default: def } = capability.budgetRange;
|
|
50796
|
+
console.log(` Budget range: ${chalk.dim(`${min}\u2013${max} tokens (default ${def})`)}`);
|
|
50797
|
+
}
|
|
50798
|
+
console.log(`
|
|
50799
|
+
${chalk.dim("Available modes:")}`);
|
|
50800
|
+
for (const level of capability.levels) {
|
|
50801
|
+
const label = formatThinkingMode(level);
|
|
50802
|
+
const isCurrent = label === display;
|
|
50803
|
+
console.log(
|
|
50804
|
+
` ${isCurrent ? chalk.green("\u2192") : " "} ${isCurrent ? chalk.green(label) : chalk.dim(label)}`
|
|
50805
|
+
);
|
|
50806
|
+
}
|
|
50807
|
+
if (capability.kinds.includes("budget")) {
|
|
50808
|
+
console.log(chalk.dim(`
|
|
50809
|
+
You can also pass a token budget: /thinking 8000
|
|
50810
|
+
`));
|
|
50811
|
+
} else {
|
|
50812
|
+
console.log();
|
|
50813
|
+
}
|
|
50814
|
+
return false;
|
|
50815
|
+
}
|
|
50816
|
+
const rawArg = args[0].toLowerCase();
|
|
50817
|
+
const parsed = parseThinkingArg(rawArg);
|
|
50818
|
+
if (parsed === null) {
|
|
50819
|
+
console.log(chalk.red(`
|
|
50820
|
+
\u2717 Unknown thinking mode: "${args[0]}"`));
|
|
50821
|
+
console.log(
|
|
50822
|
+
chalk.dim(" Valid options: off, auto, low, medium, high, or a token budget number\n")
|
|
50823
|
+
);
|
|
50824
|
+
return false;
|
|
50825
|
+
}
|
|
50826
|
+
if (!capability.supported && parsed !== "off") {
|
|
50827
|
+
console.log(
|
|
50828
|
+
chalk.yellow(`
|
|
50829
|
+
\u26A0 Thinking not supported for ${model} on ${provider}.
|
|
50830
|
+
`) + chalk.dim(
|
|
50831
|
+
" Compatible models: claude-3-7+, claude-4+, o3, o4-mini, gpt-5*, gemini-2.5+\n"
|
|
50832
|
+
)
|
|
50833
|
+
);
|
|
50834
|
+
return false;
|
|
50835
|
+
}
|
|
50836
|
+
if (typeof parsed === "object" && !capability.kinds.includes("budget")) {
|
|
50837
|
+
console.log(
|
|
50838
|
+
chalk.red(`
|
|
50839
|
+
\u2717 ${provider}/${model} uses effort levels, not token budgets.`) + chalk.dim("\n Use: off, auto, low, medium, or high\n")
|
|
50840
|
+
);
|
|
50841
|
+
return false;
|
|
50842
|
+
}
|
|
50843
|
+
if (typeof parsed === "object" && capability.budgetRange) {
|
|
50844
|
+
const { min, max } = capability.budgetRange;
|
|
50845
|
+
if (parsed.budget < min || parsed.budget > max) {
|
|
50846
|
+
console.log(
|
|
50847
|
+
chalk.red(`
|
|
50848
|
+
\u2717 Budget ${parsed.budget} is out of range.`) + chalk.dim(`
|
|
50849
|
+
Valid range for ${model}: ${min}\u2013${max} tokens
|
|
50850
|
+
`)
|
|
50851
|
+
);
|
|
50852
|
+
return false;
|
|
50853
|
+
}
|
|
50854
|
+
}
|
|
50855
|
+
if ((provider === "kimi" || provider === "kimi-code") && parsed !== "off" && parsed !== "auto") {
|
|
50856
|
+
console.log(
|
|
50857
|
+
chalk.yellow(
|
|
50858
|
+
"\n\u26A0 Enabling thinking on Kimi may cause issues with tool calling.\n If you experience errors, run /thinking off to restore default behavior.\n"
|
|
50859
|
+
)
|
|
50860
|
+
);
|
|
50861
|
+
}
|
|
50862
|
+
const previousMode = session.config.provider.thinking;
|
|
50863
|
+
const newMode = parsed === "off" ? void 0 : parsed;
|
|
50864
|
+
session.config.provider.thinking = newMode;
|
|
50865
|
+
const modeToSave = newMode ?? resolveDefaultThinking(provider, model);
|
|
50866
|
+
await saveThinkingPreference(provider, modeToSave);
|
|
50867
|
+
const previousLabel = previousMode !== void 0 ? formatThinkingMode(previousMode) : "off";
|
|
50868
|
+
const newLabel = newMode !== void 0 ? formatThinkingMode(newMode) : "off";
|
|
50869
|
+
if (previousLabel === newLabel) {
|
|
50870
|
+
console.log(chalk.dim(`
|
|
50871
|
+
Already using thinking: ${newLabel}
|
|
50872
|
+
`));
|
|
50873
|
+
} else {
|
|
50874
|
+
console.log(chalk.green(`
|
|
50875
|
+
\u2713 Thinking: ${previousLabel} \u2192 ${newLabel}
|
|
50876
|
+
`));
|
|
50877
|
+
}
|
|
50878
|
+
return false;
|
|
50879
|
+
}
|
|
50880
|
+
};
|
|
50881
|
+
|
|
50372
50882
|
// src/cli/repl/output/renderer.ts
|
|
50373
50883
|
init_syntax();
|
|
50374
50884
|
var lineBuffer = "";
|
|
@@ -51400,7 +51910,8 @@ var commands = [
|
|
|
51400
51910
|
buildAppCommand,
|
|
51401
51911
|
contextCommand,
|
|
51402
51912
|
bestOfNCommand,
|
|
51403
|
-
doctorCommand
|
|
51913
|
+
doctorCommand,
|
|
51914
|
+
thinkingCommand
|
|
51404
51915
|
];
|
|
51405
51916
|
function isSlashCommand(input) {
|
|
51406
51917
|
return input.startsWith("/");
|
|
@@ -53770,6 +54281,7 @@ ${tail}`;
|
|
|
53770
54281
|
tools: [],
|
|
53771
54282
|
maxTokens: session.config.provider.maxTokens,
|
|
53772
54283
|
signal: options.signal
|
|
54284
|
+
// Omit thinking for the final explanation turn to avoid unnecessary cost
|
|
53773
54285
|
})) {
|
|
53774
54286
|
if (options.signal?.aborted) break;
|
|
53775
54287
|
if (chunk.type === "text" && chunk.text) {
|
|
@@ -53824,7 +54336,8 @@ ${tail}`;
|
|
|
53824
54336
|
for await (const chunk of provider.streamWithTools(messages, {
|
|
53825
54337
|
tools,
|
|
53826
54338
|
maxTokens: session.config.provider.maxTokens,
|
|
53827
|
-
signal: options.signal
|
|
54339
|
+
signal: options.signal,
|
|
54340
|
+
thinking: session.config.provider.thinking
|
|
53828
54341
|
})) {
|
|
53829
54342
|
if (options.signal?.aborted) {
|
|
53830
54343
|
break;
|
|
@@ -54936,6 +55449,7 @@ init_allowed_paths();
|
|
|
54936
55449
|
// src/cli/repl/status-bar.ts
|
|
54937
55450
|
init_env();
|
|
54938
55451
|
init_full_access_mode();
|
|
55452
|
+
init_thinking();
|
|
54939
55453
|
function formatContextUsage(percent) {
|
|
54940
55454
|
const label = `ctx ${percent.toFixed(0)}%`;
|
|
54941
55455
|
if (percent >= 90) return chalk.red(label);
|
|
@@ -54955,7 +55469,9 @@ function formatStatusBar(projectPath, config, gitCtx, contextUsagePercent) {
|
|
|
54955
55469
|
parts.push(chalk.dim("\u{1F4C1} ") + chalk.magenta(projectName));
|
|
54956
55470
|
const providerName = config.provider.type;
|
|
54957
55471
|
const modelName = getDisplayModel(config);
|
|
54958
|
-
|
|
55472
|
+
const thinkingMode = config.provider.thinking;
|
|
55473
|
+
const thinkingSuffix = thinkingMode !== void 0 ? chalk.dim(" [") + chalk.magenta(formatThinkingMode(thinkingMode)) + chalk.dim("]") : "";
|
|
55474
|
+
parts.push(chalk.dim(`${providerName}/`) + chalk.cyan(modelName) + thinkingSuffix);
|
|
54959
55475
|
if (isQualityLoop()) {
|
|
54960
55476
|
parts.push(chalk.green("\u{1F504} quality loop"));
|
|
54961
55477
|
}
|