@austinthesing/magic-shell 0.2.19 → 0.2.21
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 +28 -3
- package/dist/cli.js +221 -46
- package/dist/index.js +258 -50
- package/dist/tui.js +221 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -105,6 +105,7 @@ mshell
|
|
|
105
105
|
| `msh --list-custom` | List custom models |
|
|
106
106
|
| `msh --remove-model <id>` | Remove custom model |
|
|
107
107
|
| `msh --provider <name>` | Set provider (opencode-zen or openrouter) |
|
|
108
|
+
| `msh --thinking <level>` | Set thinking level (off, low, medium, high) |
|
|
108
109
|
| `msh --themes` | List available themes |
|
|
109
110
|
| `msh --theme <name>` | Set color theme |
|
|
110
111
|
| `msh --repo-context` | Enable project context detection |
|
|
@@ -184,8 +185,13 @@ OpenCode Zen provides curated models optimized for coding tasks, including **fre
|
|
|
184
185
|
|
|
185
186
|
**Free Models:**
|
|
186
187
|
|
|
187
|
-
- `
|
|
188
|
-
- `
|
|
188
|
+
- `minimax-m2.5-free` - MiniMax's free model (default)
|
|
189
|
+
- `ling-2.6-flash-free` - Ling's free flash model
|
|
190
|
+
- `hy3-preview-free` - Hy3 preview model
|
|
191
|
+
- `nemotron-3-super-free` - NVIDIA Nemotron free trial model
|
|
192
|
+
- `trinity-large-preview-free` - Trinity large preview model
|
|
193
|
+
- `big-pickle` - OpenCode stealth model
|
|
194
|
+
- `gpt-5-nano` - OpenAI's free lightweight GPT model
|
|
189
195
|
|
|
190
196
|
**Premium Models:**
|
|
191
197
|
|
|
@@ -297,7 +303,8 @@ Configuration is stored in `~/.magic-shell/config.json`.
|
|
|
297
303
|
```json
|
|
298
304
|
{
|
|
299
305
|
"provider": "opencode-zen",
|
|
300
|
-
"defaultModel": "
|
|
306
|
+
"defaultModel": "minimax-m2.5-free",
|
|
307
|
+
"thinkingLevel": "low",
|
|
301
308
|
"safetyLevel": "moderate",
|
|
302
309
|
"dryRunByDefault": false,
|
|
303
310
|
"repoContext": false,
|
|
@@ -576,6 +583,24 @@ MIT License - see [LICENSE](LICENSE) for details.
|
|
|
576
583
|
|
|
577
584
|
## Release Notes
|
|
578
585
|
|
|
586
|
+
### v0.2.20 - Thinking Controls and Zen Free Models
|
|
587
|
+
- Added `--thinking <level>` and `thinkingLevel` config support (`off`, `low`, `medium`, `high`)
|
|
588
|
+
- Added provider-specific reasoning controls for supported OpenRouter, OpenCode Zen, gateway, and custom models
|
|
589
|
+
- Updated OpenCode Zen free models and default model references to `minimax-m2.5-free`
|
|
590
|
+
- Disabled custom thinking parameters when the selected model/provider does not support them
|
|
591
|
+
|
|
592
|
+
### v0.2.19 - AI Gateway Providers
|
|
593
|
+
- Added Vercel AI Gateway, Cloudflare AI Gateway, and Cloudflare Workers AI providers
|
|
594
|
+
- Added gateway provider setup, switching, model listing, API-key handling, and environment variables
|
|
595
|
+
- Refreshed OpenCode Zen and OpenRouter registries with current OpenAI, Anthropic, Kimi, DeepSeek, GLM, MiniMax, and MiMo model IDs
|
|
596
|
+
- Added provider-scoped model helpers so model selection follows the active provider
|
|
597
|
+
|
|
598
|
+
### v0.2.18 - Model Registry Refresh
|
|
599
|
+
- Added latest MiMo V2.5 and MiMo V2.5 Pro entries for OpenCode Zen
|
|
600
|
+
- Added latest Xiaomi MiMo V2.5 and MiMo V2.5 Pro entries for OpenRouter
|
|
601
|
+
- Removed the older OpenRouter MiMo V2 Flash free entry from docs and model listings
|
|
602
|
+
- Updated runtime dependencies for the published CLI package
|
|
603
|
+
|
|
579
604
|
### v0.2.17 - Dependency Maintenance
|
|
580
605
|
- Updated published CLI dependencies to current releases
|
|
581
606
|
- Fixed TUI input typing compatibility after the `@opentui/core` upgrade
|
package/dist/cli.js
CHANGED
|
@@ -1734,7 +1734,7 @@ var require_tracestate_impl = __commonJS((exports) => {
|
|
|
1734
1734
|
const value = listMember.slice(i + 1, part.length);
|
|
1735
1735
|
if ((0, tracestate_validators_1.validateKey)(key) && (0, tracestate_validators_1.validateValue)(value)) {
|
|
1736
1736
|
agg.set(key, value);
|
|
1737
|
-
}
|
|
1737
|
+
}
|
|
1738
1738
|
}
|
|
1739
1739
|
return agg;
|
|
1740
1740
|
}, new Map);
|
|
@@ -37000,21 +37000,66 @@ var WORKERS_AI_MODELS = [
|
|
|
37000
37000
|
];
|
|
37001
37001
|
var OPENCODE_ZEN_MODELS = [
|
|
37002
37002
|
{
|
|
37003
|
-
id: "
|
|
37004
|
-
name: "
|
|
37005
|
-
description: "
|
|
37003
|
+
id: "minimax-m2.5-free",
|
|
37004
|
+
name: "MiniMax M2.5 Free",
|
|
37005
|
+
description: "MiniMax's free model (limited time)",
|
|
37006
37006
|
category: "smart",
|
|
37007
37007
|
provider: "opencode-zen",
|
|
37008
|
-
contextLength:
|
|
37008
|
+
contextLength: 196608,
|
|
37009
37009
|
free: true
|
|
37010
37010
|
},
|
|
37011
37011
|
{
|
|
37012
|
-
id: "
|
|
37013
|
-
name: "
|
|
37014
|
-
description: "
|
|
37012
|
+
id: "ling-2.6-flash-free",
|
|
37013
|
+
name: "Ling 2.6 Flash Free",
|
|
37014
|
+
description: "Ling's free flash model (limited time)",
|
|
37015
37015
|
category: "fast",
|
|
37016
37016
|
provider: "opencode-zen",
|
|
37017
|
-
contextLength:
|
|
37017
|
+
contextLength: 131072,
|
|
37018
|
+
free: true
|
|
37019
|
+
},
|
|
37020
|
+
{
|
|
37021
|
+
id: "hy3-preview-free",
|
|
37022
|
+
name: "Hy3 Preview Free",
|
|
37023
|
+
description: "Hy3 preview model (free, limited time)",
|
|
37024
|
+
category: "smart",
|
|
37025
|
+
provider: "opencode-zen",
|
|
37026
|
+
contextLength: 131072,
|
|
37027
|
+
free: true
|
|
37028
|
+
},
|
|
37029
|
+
{
|
|
37030
|
+
id: "nemotron-3-super-free",
|
|
37031
|
+
name: "Nemotron 3 Super Free",
|
|
37032
|
+
description: "NVIDIA Nemotron free trial model",
|
|
37033
|
+
category: "smart",
|
|
37034
|
+
provider: "opencode-zen",
|
|
37035
|
+
contextLength: 131072,
|
|
37036
|
+
free: true
|
|
37037
|
+
},
|
|
37038
|
+
{
|
|
37039
|
+
id: "trinity-large-preview-free",
|
|
37040
|
+
name: "Trinity Large Preview Free",
|
|
37041
|
+
description: "Trinity large preview model (free, limited time)",
|
|
37042
|
+
category: "smart",
|
|
37043
|
+
provider: "opencode-zen",
|
|
37044
|
+
contextLength: 131072,
|
|
37045
|
+
free: true
|
|
37046
|
+
},
|
|
37047
|
+
{
|
|
37048
|
+
id: "big-pickle",
|
|
37049
|
+
name: "Big Pickle",
|
|
37050
|
+
description: "OpenCode stealth model (free, limited time)",
|
|
37051
|
+
category: "smart",
|
|
37052
|
+
provider: "opencode-zen",
|
|
37053
|
+
contextLength: 131072,
|
|
37054
|
+
free: true
|
|
37055
|
+
},
|
|
37056
|
+
{
|
|
37057
|
+
id: "gpt-5-nano",
|
|
37058
|
+
name: "GPT 5 Nano",
|
|
37059
|
+
description: "OpenAI's free lightweight GPT model",
|
|
37060
|
+
category: "fast",
|
|
37061
|
+
provider: "opencode-zen",
|
|
37062
|
+
contextLength: 400000,
|
|
37018
37063
|
free: true
|
|
37019
37064
|
},
|
|
37020
37065
|
{
|
|
@@ -37583,7 +37628,8 @@ var DEFAULT_CONFIG = {
|
|
|
37583
37628
|
workersAiApiKey: "",
|
|
37584
37629
|
cloudflareAccountId: "",
|
|
37585
37630
|
cloudflareAiGatewayId: "default",
|
|
37586
|
-
defaultModel: "
|
|
37631
|
+
defaultModel: "minimax-m2.5-free",
|
|
37632
|
+
thinkingLevel: "low",
|
|
37587
37633
|
safetyLevel: "moderate",
|
|
37588
37634
|
dryRunByDefault: false,
|
|
37589
37635
|
blockedCommands: [
|
|
@@ -47749,7 +47795,7 @@ class JSONSchemaGenerator {
|
|
|
47749
47795
|
if (val === undefined) {
|
|
47750
47796
|
if (this.unrepresentable === "throw") {
|
|
47751
47797
|
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
47752
|
-
}
|
|
47798
|
+
}
|
|
47753
47799
|
} else if (typeof val === "bigint") {
|
|
47754
47800
|
if (this.unrepresentable === "throw") {
|
|
47755
47801
|
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
@@ -76352,7 +76398,94 @@ function cleanCommand(command) {
|
|
|
76352
76398
|
}
|
|
76353
76399
|
return cleaned.trim();
|
|
76354
76400
|
}
|
|
76355
|
-
|
|
76401
|
+
function getThinkingLevel(config2) {
|
|
76402
|
+
return config2?.thinkingLevel || "low";
|
|
76403
|
+
}
|
|
76404
|
+
function supportsThinkingControl(modelId) {
|
|
76405
|
+
return modelId.includes("thinking") || modelId.includes("gpt-5") || modelId.includes("claude-") || modelId.includes("gemini-");
|
|
76406
|
+
}
|
|
76407
|
+
function buildOpenRouterThinkingOptions(modelId, thinkingLevel) {
|
|
76408
|
+
if (thinkingLevel === "off" || !supportsThinkingControl(modelId)) {
|
|
76409
|
+
return {};
|
|
76410
|
+
}
|
|
76411
|
+
return {
|
|
76412
|
+
reasoning: {
|
|
76413
|
+
effort: thinkingLevel
|
|
76414
|
+
}
|
|
76415
|
+
};
|
|
76416
|
+
}
|
|
76417
|
+
function buildOpenAICompatibleThinkingOptions(modelId, thinkingLevel) {
|
|
76418
|
+
if (thinkingLevel === "off" || !supportsThinkingControl(modelId)) {
|
|
76419
|
+
return {};
|
|
76420
|
+
}
|
|
76421
|
+
return {
|
|
76422
|
+
reasoning_effort: thinkingLevel
|
|
76423
|
+
};
|
|
76424
|
+
}
|
|
76425
|
+
function buildAiSdkProviderOptions(modelId, thinkingLevel, providerOptionsName) {
|
|
76426
|
+
if (thinkingLevel === "off" || !supportsThinkingControl(modelId)) {
|
|
76427
|
+
return;
|
|
76428
|
+
}
|
|
76429
|
+
if (modelId.startsWith("gpt-")) {
|
|
76430
|
+
const compatibleOptions = providerOptionsName && providerOptionsName !== "openai" ? {
|
|
76431
|
+
[providerOptionsName]: {
|
|
76432
|
+
reasoningEffort: thinkingLevel
|
|
76433
|
+
}
|
|
76434
|
+
} : {};
|
|
76435
|
+
return {
|
|
76436
|
+
openai: {
|
|
76437
|
+
reasoningEffort: thinkingLevel
|
|
76438
|
+
},
|
|
76439
|
+
openaiCompatible: {
|
|
76440
|
+
reasoningEffort: thinkingLevel
|
|
76441
|
+
},
|
|
76442
|
+
...compatibleOptions
|
|
76443
|
+
};
|
|
76444
|
+
}
|
|
76445
|
+
if (modelId.startsWith("gemini-")) {
|
|
76446
|
+
return {
|
|
76447
|
+
google: {
|
|
76448
|
+
thinkingConfig: {
|
|
76449
|
+
thinkingLevel
|
|
76450
|
+
}
|
|
76451
|
+
}
|
|
76452
|
+
};
|
|
76453
|
+
}
|
|
76454
|
+
if (modelId.startsWith("claude-")) {
|
|
76455
|
+
const budgetByLevel = {
|
|
76456
|
+
low: 1024,
|
|
76457
|
+
medium: 4096,
|
|
76458
|
+
high: 8192
|
|
76459
|
+
};
|
|
76460
|
+
return {
|
|
76461
|
+
anthropic: {
|
|
76462
|
+
thinking: {
|
|
76463
|
+
type: "enabled",
|
|
76464
|
+
budgetTokens: budgetByLevel[thinkingLevel]
|
|
76465
|
+
}
|
|
76466
|
+
}
|
|
76467
|
+
};
|
|
76468
|
+
}
|
|
76469
|
+
if (modelId.includes("thinking")) {
|
|
76470
|
+
return {
|
|
76471
|
+
openaiCompatible: {
|
|
76472
|
+
reasoningEffort: thinkingLevel
|
|
76473
|
+
},
|
|
76474
|
+
...providerOptionsName ? {
|
|
76475
|
+
[providerOptionsName]: {
|
|
76476
|
+
reasoningEffort: thinkingLevel
|
|
76477
|
+
}
|
|
76478
|
+
} : {}
|
|
76479
|
+
};
|
|
76480
|
+
}
|
|
76481
|
+
return;
|
|
76482
|
+
}
|
|
76483
|
+
function shouldOmitTemperature(modelId, thinkingLevel) {
|
|
76484
|
+
return thinkingLevel !== "off" && (modelId.startsWith("claude-") || modelId.includes("gpt-5"));
|
|
76485
|
+
}
|
|
76486
|
+
async function callOpenRouter(apiKey, modelId, systemPrompt, userInput, thinkingLevel) {
|
|
76487
|
+
const thinkingOptions = buildOpenRouterThinkingOptions(modelId, thinkingLevel);
|
|
76488
|
+
const temperatureOptions = shouldOmitTemperature(modelId, thinkingLevel) ? {} : { temperature: 0.1 };
|
|
76356
76489
|
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
|
76357
76490
|
method: "POST",
|
|
76358
76491
|
headers: {
|
|
@@ -76368,7 +76501,8 @@ async function callOpenRouter(apiKey, modelId, systemPrompt, userInput) {
|
|
|
76368
76501
|
{ role: "user", content: userInput }
|
|
76369
76502
|
],
|
|
76370
76503
|
max_tokens: 500,
|
|
76371
|
-
|
|
76504
|
+
...temperatureOptions,
|
|
76505
|
+
...thinkingOptions
|
|
76372
76506
|
})
|
|
76373
76507
|
});
|
|
76374
76508
|
if (!response.ok) {
|
|
@@ -76388,7 +76522,9 @@ async function callOpenRouter(apiKey, modelId, systemPrompt, userInput) {
|
|
|
76388
76522
|
}
|
|
76389
76523
|
return data.choices[0]?.message?.content?.trim() || "";
|
|
76390
76524
|
}
|
|
76391
|
-
async function callOpenAICompatibleFetch(baseURL, apiKey, modelId, systemPrompt, userInput, headers = {}, includeAuthorization = true) {
|
|
76525
|
+
async function callOpenAICompatibleFetch(baseURL, apiKey, modelId, systemPrompt, userInput, thinkingLevel, headers = {}, includeAuthorization = true) {
|
|
76526
|
+
const thinkingOptions = buildOpenAICompatibleThinkingOptions(modelId, thinkingLevel);
|
|
76527
|
+
const temperatureOptions = shouldOmitTemperature(modelId, thinkingLevel) ? {} : { temperature: 0.1 };
|
|
76392
76528
|
const requestHeaders = {
|
|
76393
76529
|
"Content-Type": "application/json",
|
|
76394
76530
|
...headers
|
|
@@ -76406,8 +76542,9 @@ async function callOpenAICompatibleFetch(baseURL, apiKey, modelId, systemPrompt,
|
|
|
76406
76542
|
{ role: "user", content: userInput }
|
|
76407
76543
|
],
|
|
76408
76544
|
max_tokens: 500,
|
|
76409
|
-
|
|
76410
|
-
|
|
76545
|
+
stream: false,
|
|
76546
|
+
...temperatureOptions,
|
|
76547
|
+
...thinkingOptions
|
|
76411
76548
|
})
|
|
76412
76549
|
});
|
|
76413
76550
|
if (!response.ok) {
|
|
@@ -76439,42 +76576,45 @@ function getCloudflareAccountId(config2) {
|
|
|
76439
76576
|
function getCloudflareGatewayId(config2) {
|
|
76440
76577
|
return config2.cloudflareAiGatewayId || process.env.CLOUDFLARE_AI_GATEWAY_ID || process.env.CF_AIG_GATEWAY_ID || "default";
|
|
76441
76578
|
}
|
|
76442
|
-
async function callGatewayProvider(provider, apiKey, modelId, systemPrompt, userInput) {
|
|
76579
|
+
async function callGatewayProvider(provider, apiKey, modelId, systemPrompt, userInput, thinkingLevel) {
|
|
76443
76580
|
const config2 = loadConfig2();
|
|
76444
76581
|
switch (provider) {
|
|
76445
76582
|
case "vercel-ai-gateway":
|
|
76446
|
-
return await callOpenAICompatibleFetch("https://ai-gateway.vercel.sh/v1", apiKey, modelId, systemPrompt, userInput);
|
|
76583
|
+
return await callOpenAICompatibleFetch("https://ai-gateway.vercel.sh/v1", apiKey, modelId, systemPrompt, userInput, thinkingLevel);
|
|
76447
76584
|
case "cloudflare-ai-gateway": {
|
|
76448
76585
|
const accountId = getCloudflareAccountId(config2);
|
|
76449
76586
|
if (!accountId) {
|
|
76450
76587
|
throw new Error("Cloudflare account ID is required. Set cloudflareAccountId in config or CLOUDFLARE_ACCOUNT_ID.");
|
|
76451
76588
|
}
|
|
76452
76589
|
const gatewayId = getCloudflareGatewayId(config2);
|
|
76453
|
-
return await callOpenAICompatibleFetch(`https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/compat`, apiKey, modelId, systemPrompt, userInput, { "cf-aig-authorization": `Bearer ${apiKey}` }, false);
|
|
76590
|
+
return await callOpenAICompatibleFetch(`https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/compat`, apiKey, modelId, systemPrompt, userInput, thinkingLevel, { "cf-aig-authorization": `Bearer ${apiKey}` }, false);
|
|
76454
76591
|
}
|
|
76455
76592
|
case "workers-ai": {
|
|
76456
76593
|
const accountId = getCloudflareAccountId(config2);
|
|
76457
76594
|
if (!accountId) {
|
|
76458
76595
|
throw new Error("Cloudflare account ID is required. Set cloudflareAccountId in config or CLOUDFLARE_ACCOUNT_ID.");
|
|
76459
76596
|
}
|
|
76460
|
-
return await callOpenAICompatibleFetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`, apiKey, modelId, systemPrompt, userInput);
|
|
76597
|
+
return await callOpenAICompatibleFetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`, apiKey, modelId, systemPrompt, userInput, thinkingLevel);
|
|
76461
76598
|
}
|
|
76462
76599
|
default:
|
|
76463
76600
|
throw new Error(`Unsupported gateway provider: ${provider}`);
|
|
76464
76601
|
}
|
|
76465
76602
|
}
|
|
76466
76603
|
var DEBUG_API = process.env.DEBUG_API === "1";
|
|
76467
|
-
async function generateZenText(model, systemPrompt, userInput) {
|
|
76604
|
+
async function generateZenText(model, modelId, systemPrompt, userInput, thinkingLevel, providerOptionsName) {
|
|
76605
|
+
const providerOptions = buildAiSdkProviderOptions(modelId, thinkingLevel, providerOptionsName);
|
|
76606
|
+
const temperatureOptions = shouldOmitTemperature(modelId, thinkingLevel) ? {} : { temperature: 0.1 };
|
|
76468
76607
|
const { text: text2 } = await generateText({
|
|
76469
76608
|
model,
|
|
76470
76609
|
system: systemPrompt,
|
|
76471
76610
|
prompt: userInput,
|
|
76472
76611
|
maxOutputTokens: 500,
|
|
76473
|
-
|
|
76612
|
+
...temperatureOptions,
|
|
76613
|
+
...providerOptions ? { providerOptions } : {}
|
|
76474
76614
|
});
|
|
76475
76615
|
return text2.trim();
|
|
76476
76616
|
}
|
|
76477
|
-
async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput) {
|
|
76617
|
+
async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput, thinkingLevel) {
|
|
76478
76618
|
if (DEBUG_API) {
|
|
76479
76619
|
console.error(`[DEBUG] Calling OpenAI Responses API`);
|
|
76480
76620
|
console.error(`[DEBUG] Model: ${modelId}`);
|
|
@@ -76485,7 +76625,7 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
76485
76625
|
baseURL: ZEN_BASE_URL
|
|
76486
76626
|
});
|
|
76487
76627
|
try {
|
|
76488
|
-
return await generateZenText(openai2(modelId), systemPrompt, userInput);
|
|
76628
|
+
return await generateZenText(openai2(modelId), modelId, systemPrompt, userInput, thinkingLevel);
|
|
76489
76629
|
} catch (error40) {
|
|
76490
76630
|
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
76491
76631
|
if (DEBUG_API) {
|
|
@@ -76494,7 +76634,7 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
76494
76634
|
throw new Error(message);
|
|
76495
76635
|
}
|
|
76496
76636
|
}
|
|
76497
|
-
async function callZenAnthropic(apiKey, modelId, systemPrompt, userInput) {
|
|
76637
|
+
async function callZenAnthropic(apiKey, modelId, systemPrompt, userInput, thinkingLevel) {
|
|
76498
76638
|
if (DEBUG_API) {
|
|
76499
76639
|
console.error(`[DEBUG] Calling Anthropic Messages API`);
|
|
76500
76640
|
console.error(`[DEBUG] Model: ${modelId}`);
|
|
@@ -76505,7 +76645,7 @@ async function callZenAnthropic(apiKey, modelId, systemPrompt, userInput) {
|
|
|
76505
76645
|
baseURL: ZEN_BASE_URL
|
|
76506
76646
|
});
|
|
76507
76647
|
try {
|
|
76508
|
-
return await generateZenText(anthropic2(modelId), systemPrompt, userInput);
|
|
76648
|
+
return await generateZenText(anthropic2(modelId), modelId, systemPrompt, userInput, thinkingLevel);
|
|
76509
76649
|
} catch (error40) {
|
|
76510
76650
|
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
76511
76651
|
if (DEBUG_API) {
|
|
@@ -76514,7 +76654,7 @@ async function callZenAnthropic(apiKey, modelId, systemPrompt, userInput) {
|
|
|
76514
76654
|
throw new Error(message);
|
|
76515
76655
|
}
|
|
76516
76656
|
}
|
|
76517
|
-
async function callZenOpenAICompatible(apiKey, modelId, systemPrompt, userInput) {
|
|
76657
|
+
async function callZenOpenAICompatible(apiKey, modelId, systemPrompt, userInput, thinkingLevel) {
|
|
76518
76658
|
if (DEBUG_API) {
|
|
76519
76659
|
console.error(`[DEBUG] Calling OpenAI-compatible Chat Completions API`);
|
|
76520
76660
|
console.error(`[DEBUG] Model: ${modelId}`);
|
|
@@ -76525,7 +76665,7 @@ async function callZenOpenAICompatible(apiKey, modelId, systemPrompt, userInput)
|
|
|
76525
76665
|
baseURL: ZEN_BASE_URL
|
|
76526
76666
|
});
|
|
76527
76667
|
try {
|
|
76528
|
-
return await generateZenText(openaiCompatible(modelId), systemPrompt, userInput);
|
|
76668
|
+
return await generateZenText(openaiCompatible(modelId), modelId, systemPrompt, userInput, thinkingLevel, "opencodeZen");
|
|
76529
76669
|
} catch (error40) {
|
|
76530
76670
|
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
76531
76671
|
if (DEBUG_API) {
|
|
@@ -76534,7 +76674,7 @@ async function callZenOpenAICompatible(apiKey, modelId, systemPrompt, userInput)
|
|
|
76534
76674
|
throw new Error(message);
|
|
76535
76675
|
}
|
|
76536
76676
|
}
|
|
76537
|
-
async function callCustomModel(model, systemPrompt, userInput) {
|
|
76677
|
+
async function callCustomModel(model, systemPrompt, userInput, thinkingLevel) {
|
|
76538
76678
|
if (DEBUG_API) {
|
|
76539
76679
|
console.error(`[DEBUG] Calling Custom Model`);
|
|
76540
76680
|
console.error(`[DEBUG] Model: ${model.modelId}`);
|
|
@@ -76546,7 +76686,7 @@ async function callCustomModel(model, systemPrompt, userInput) {
|
|
|
76546
76686
|
baseURL: model.baseUrl
|
|
76547
76687
|
});
|
|
76548
76688
|
try {
|
|
76549
|
-
return await generateZenText(openaiCompatible(model.modelId), systemPrompt, userInput);
|
|
76689
|
+
return await generateZenText(openaiCompatible(model.modelId), model.modelId, systemPrompt, userInput, thinkingLevel, "custom");
|
|
76550
76690
|
} catch (error40) {
|
|
76551
76691
|
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
76552
76692
|
if (DEBUG_API) {
|
|
@@ -76555,7 +76695,7 @@ async function callCustomModel(model, systemPrompt, userInput) {
|
|
|
76555
76695
|
throw new Error(message);
|
|
76556
76696
|
}
|
|
76557
76697
|
}
|
|
76558
|
-
async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
76698
|
+
async function callZenGoogle(apiKey, modelId, systemPrompt, userInput, thinkingLevel) {
|
|
76559
76699
|
if (DEBUG_API) {
|
|
76560
76700
|
console.error(`[DEBUG] Calling Google Gemini API`);
|
|
76561
76701
|
console.error(`[DEBUG] Model: ${modelId}`);
|
|
@@ -76565,7 +76705,7 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
76565
76705
|
baseURL: `https://opencode.ai/zen/v1/models/${modelId}`
|
|
76566
76706
|
});
|
|
76567
76707
|
try {
|
|
76568
|
-
return await generateZenText(google2(modelId), systemPrompt, userInput);
|
|
76708
|
+
return await generateZenText(google2(modelId), modelId, systemPrompt, userInput, thinkingLevel);
|
|
76569
76709
|
} catch (error40) {
|
|
76570
76710
|
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
76571
76711
|
if (DEBUG_API) {
|
|
@@ -76581,30 +76721,31 @@ function getShellInfo() {
|
|
|
76581
76721
|
}
|
|
76582
76722
|
return cachedShellInfo;
|
|
76583
76723
|
}
|
|
76584
|
-
async function translateToCommand(apiKey, model, userInput, cwd, history = [], repoContextEnabled) {
|
|
76724
|
+
async function translateToCommand(apiKey, model, userInput, cwd, history = [], repoContextEnabled, config2) {
|
|
76585
76725
|
const shellInfo = getShellInfo();
|
|
76586
76726
|
const systemPrompt = buildSystemPrompt(cwd, history, shellInfo, repoContextEnabled);
|
|
76727
|
+
const thinkingLevel = getThinkingLevel(config2);
|
|
76587
76728
|
let rawCommand;
|
|
76588
76729
|
if (isCustomModel(model)) {
|
|
76589
|
-
rawCommand = await callCustomModel(model, systemPrompt, userInput);
|
|
76730
|
+
rawCommand = await callCustomModel(model, systemPrompt, userInput, "off");
|
|
76590
76731
|
} else if (model.provider === "openrouter") {
|
|
76591
|
-
rawCommand = await callOpenRouter(apiKey, model.id, systemPrompt, userInput);
|
|
76732
|
+
rawCommand = await callOpenRouter(apiKey, model.id, systemPrompt, userInput, thinkingLevel);
|
|
76592
76733
|
} else if (model.provider === "vercel-ai-gateway" || model.provider === "cloudflare-ai-gateway" || model.provider === "workers-ai") {
|
|
76593
|
-
rawCommand = await callGatewayProvider(model.provider, apiKey, model.id, systemPrompt, userInput);
|
|
76734
|
+
rawCommand = await callGatewayProvider(model.provider, apiKey, model.id, systemPrompt, userInput, thinkingLevel);
|
|
76594
76735
|
} else {
|
|
76595
76736
|
const apiType = getZenApiType(model.id);
|
|
76596
76737
|
switch (apiType) {
|
|
76597
76738
|
case "openai-responses":
|
|
76598
|
-
rawCommand = await callZenOpenAIResponses(apiKey, model.id, systemPrompt, userInput);
|
|
76739
|
+
rawCommand = await callZenOpenAIResponses(apiKey, model.id, systemPrompt, userInput, thinkingLevel);
|
|
76599
76740
|
break;
|
|
76600
76741
|
case "anthropic":
|
|
76601
|
-
rawCommand = await callZenAnthropic(apiKey, model.id, systemPrompt, userInput);
|
|
76742
|
+
rawCommand = await callZenAnthropic(apiKey, model.id, systemPrompt, userInput, thinkingLevel);
|
|
76602
76743
|
break;
|
|
76603
76744
|
case "google":
|
|
76604
|
-
rawCommand = await callZenGoogle(apiKey, model.id, systemPrompt, userInput);
|
|
76745
|
+
rawCommand = await callZenGoogle(apiKey, model.id, systemPrompt, userInput, thinkingLevel);
|
|
76605
76746
|
break;
|
|
76606
76747
|
case "openai-compatible":
|
|
76607
|
-
rawCommand = await callZenOpenAICompatible(apiKey, model.id, systemPrompt, userInput);
|
|
76748
|
+
rawCommand = await callZenOpenAICompatible(apiKey, model.id, systemPrompt, userInput, thinkingLevel);
|
|
76608
76749
|
break;
|
|
76609
76750
|
}
|
|
76610
76751
|
}
|
|
@@ -77141,15 +77282,16 @@ function getStatusBarContent() {
|
|
|
77141
77282
|
const safeModeIndicator = dryRunMode ? fg(theme.colors.warning)("[DRY RUN]") : "";
|
|
77142
77283
|
const safetyLevelColor = config2.safetyLevel === "strict" ? theme.colors.warning : config2.safetyLevel === "relaxed" ? theme.colors.error : theme.colors.success;
|
|
77143
77284
|
const safetyIndicator = fg(safetyLevelColor)(`[${config2.safetyLevel}]`);
|
|
77285
|
+
const thinkingIndicator = config2.thinkingLevel !== "off" ? fg(theme.colors.secondary)(`[Think:${config2.thinkingLevel}]`) : "";
|
|
77144
77286
|
const repoContextIndicator = config2.repoContext ? fg(theme.colors.info)("[Repo]") : "";
|
|
77145
|
-
return t`${fg(theme.colors.textMuted)("Provider:")} ${fg(theme.colors.text)(providerName)} ${fg(theme.colors.textMuted)("Model:")} ${fg(theme.colors.text)(currentModel.name)} ${safetyIndicator}${safeModeIndicator ? " " : ""}${safeModeIndicator}${repoContextIndicator ? " " : ""}${repoContextIndicator}`;
|
|
77287
|
+
return t`${fg(theme.colors.textMuted)("Provider:")} ${fg(theme.colors.text)(providerName)} ${fg(theme.colors.textMuted)("Model:")} ${fg(theme.colors.text)(currentModel.name)} ${safetyIndicator}${thinkingIndicator ? " " : ""}${thinkingIndicator}${safeModeIndicator ? " " : ""}${safeModeIndicator}${repoContextIndicator ? " " : ""}${repoContextIndicator}`;
|
|
77146
77288
|
}
|
|
77147
77289
|
function getHelpBarContent() {
|
|
77148
77290
|
const theme = getTheme();
|
|
77149
77291
|
if (awaitingConfirmation) {
|
|
77150
77292
|
return t`${fg(theme.colors.warning)(">>> Cmd+Enter or Enter to execute <<<")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.error)("Esc")}${fg(theme.colors.textMuted)(" Cancel")} ${fg(theme.colors.primary)("e")}${fg(theme.colors.textMuted)(" Edit")} ${fg(theme.colors.primary)("c")}${fg(theme.colors.textMuted)(" Copy")}`;
|
|
77151
77293
|
}
|
|
77152
|
-
return t`${fg(theme.colors.primary)("Ctrl+X P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+Y")}${fg(theme.colors.textMuted)(" Safety")} ${fg(theme.colors.primary)("Ctrl+Z")}${fg(theme.colors.textMuted)(" Exit")}`;
|
|
77294
|
+
return t`${fg(theme.colors.primary)("Ctrl+X P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+Y")}${fg(theme.colors.textMuted)(" Safety")} ${fg(theme.colors.primary)("Ctrl+K")}${fg(theme.colors.textMuted)(" Think")} ${fg(theme.colors.primary)("Ctrl+Z")}${fg(theme.colors.textMuted)(" Exit")}`;
|
|
77153
77295
|
}
|
|
77154
77296
|
function getInputHintContent() {
|
|
77155
77297
|
const theme = getTheme();
|
|
@@ -77472,7 +77614,7 @@ async function translateAndProcess(input) {
|
|
|
77472
77614
|
}
|
|
77473
77615
|
const loadingMsg = addSystemMessage("Translating...");
|
|
77474
77616
|
try {
|
|
77475
|
-
const command = await translateToCommand(apiKey, currentModel, input, currentCwd, history, config2.repoContext);
|
|
77617
|
+
const command = await translateToCommand(apiKey, currentModel, input, currentCwd, history, config2.repoContext, config2);
|
|
77476
77618
|
chatScrollBox.remove(`msg-${loadingMsg.id}`);
|
|
77477
77619
|
chatMessages = chatMessages.filter((m2) => m2.id !== loadingMsg.id);
|
|
77478
77620
|
const safety = analyzeCommand(command, config2);
|
|
@@ -77602,6 +77744,10 @@ async function handleSpecialCommand(input) {
|
|
|
77602
77744
|
statusBarText.content = getStatusBarContent();
|
|
77603
77745
|
addSystemMessage(`Dry-run mode: ${dryRunMode ? "ON" : "OFF"}`);
|
|
77604
77746
|
break;
|
|
77747
|
+
case "thinking":
|
|
77748
|
+
case "think":
|
|
77749
|
+
cycleThinkingLevel();
|
|
77750
|
+
break;
|
|
77605
77751
|
case "config":
|
|
77606
77752
|
await showConfig();
|
|
77607
77753
|
break;
|
|
@@ -77628,6 +77774,7 @@ function clearChat() {
|
|
|
77628
77774
|
function showHelp() {
|
|
77629
77775
|
const helpText = `Direct Shortcuts:
|
|
77630
77776
|
Ctrl+Y Cycle safety level (strict/moderate/relaxed)
|
|
77777
|
+
Ctrl+K Cycle thinking level (low/medium/high/off)
|
|
77631
77778
|
Ctrl+Z Exit magic-shell
|
|
77632
77779
|
Ctrl+C Cancel / Close popup
|
|
77633
77780
|
|
|
@@ -77636,19 +77783,26 @@ P Command palette M Change model
|
|
|
77636
77783
|
S Switch provider D Toggle dry-run
|
|
77637
77784
|
T Change theme R Toggle repo context
|
|
77638
77785
|
H Show history L Clear chat
|
|
77639
|
-
C Show config
|
|
77786
|
+
C Show config K Thinking level
|
|
77787
|
+
? This help
|
|
77640
77788
|
|
|
77641
77789
|
Commands (type ! or / followed by):
|
|
77642
77790
|
help Show this help model Change model
|
|
77643
77791
|
provider Switch provider dry Toggle dry-run
|
|
77644
|
-
config Show configuration
|
|
77645
|
-
clear Clear chat
|
|
77792
|
+
thinking Cycle thinking config Show configuration
|
|
77793
|
+
history Show history clear Clear chat
|
|
77646
77794
|
|
|
77647
77795
|
Safety Levels:
|
|
77648
77796
|
- strict: Confirm ALL potentially dangerous commands
|
|
77649
77797
|
- moderate: Confirm high/critical severity commands (default)
|
|
77650
77798
|
- relaxed: Only confirm critical commands
|
|
77651
77799
|
|
|
77800
|
+
Thinking Levels:
|
|
77801
|
+
- low: Default low-cost reasoning for supported models
|
|
77802
|
+
- medium: More reasoning for harder translations
|
|
77803
|
+
- high: Maximum reasoning for supported models
|
|
77804
|
+
- off: Do not request provider thinking controls
|
|
77805
|
+
|
|
77652
77806
|
Tips:
|
|
77653
77807
|
- Type naturally: "list all files" -> ls -la
|
|
77654
77808
|
- Use ! or / commands: !help or /help
|
|
@@ -77675,6 +77829,7 @@ Theme: ${theme.name}
|
|
|
77675
77829
|
Shell: ${shellInfo.shell} (${shellInfo.shellPath})
|
|
77676
77830
|
Platform: ${shellInfo.platform}${shellInfo.isWSL ? " (WSL)" : ""}
|
|
77677
77831
|
Safety: ${config2.safetyLevel}
|
|
77832
|
+
Thinking: ${config2.thinkingLevel}
|
|
77678
77833
|
Dry-run: ${dryRunMode ? "ON" : "OFF"}
|
|
77679
77834
|
Repo context: ${config2.repoContext ? "ON" : "OFF"}
|
|
77680
77835
|
API Key: ${apiKeyStatus}
|
|
@@ -77914,6 +78069,15 @@ function showThemeSelector() {
|
|
|
77914
78069
|
}
|
|
77915
78070
|
var commandPalette = null;
|
|
77916
78071
|
var chordMode = "none";
|
|
78072
|
+
function cycleThinkingLevel() {
|
|
78073
|
+
const levels = ["low", "medium", "high", "off"];
|
|
78074
|
+
const currentIndex = levels.indexOf(config2.thinkingLevel);
|
|
78075
|
+
const nextIndex = (currentIndex + 1) % levels.length;
|
|
78076
|
+
config2.thinkingLevel = levels[nextIndex];
|
|
78077
|
+
saveConfig(config2);
|
|
78078
|
+
statusBarText.content = getStatusBarContent();
|
|
78079
|
+
addSystemMessage(`Thinking level: ${config2.thinkingLevel}`);
|
|
78080
|
+
}
|
|
77917
78081
|
function getCommandPaletteOptions() {
|
|
77918
78082
|
return [
|
|
77919
78083
|
{
|
|
@@ -77968,6 +78132,13 @@ function getCommandPaletteOptions() {
|
|
|
77968
78132
|
addSystemMessage(`Safety level: ${config2.safetyLevel} (${descriptions[config2.safetyLevel]})`);
|
|
77969
78133
|
}
|
|
77970
78134
|
},
|
|
78135
|
+
{
|
|
78136
|
+
name: "Cycle Thinking Level",
|
|
78137
|
+
description: `Current: ${config2.thinkingLevel}`,
|
|
78138
|
+
key: "k",
|
|
78139
|
+
chord: "k",
|
|
78140
|
+
action: () => cycleThinkingLevel()
|
|
78141
|
+
},
|
|
77971
78142
|
{
|
|
77972
78143
|
name: "Toggle Project Context",
|
|
77973
78144
|
description: config2.repoContext ? "Currently ON (sends script names to AI)" : "Currently OFF",
|
|
@@ -78104,6 +78275,10 @@ function handleKeypress(key) {
|
|
|
78104
78275
|
addSystemMessage(`Safety level: ${config2.safetyLevel} (${descriptions[config2.safetyLevel]})`);
|
|
78105
78276
|
return;
|
|
78106
78277
|
}
|
|
78278
|
+
if (key.ctrl && key.name === "k") {
|
|
78279
|
+
cycleThinkingLevel();
|
|
78280
|
+
return;
|
|
78281
|
+
}
|
|
78107
78282
|
if (key.ctrl && key.name === "z") {
|
|
78108
78283
|
renderer.destroy();
|
|
78109
78284
|
process.exit(0);
|