@austinthesing/magic-shell 0.2.2 → 0.2.4
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 +4 -6
- package/dist/cli.js +59 -138
- package/dist/index.js +52 -121
- package/dist/tui.js +59 -138
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -174,16 +174,16 @@ You can also type commands directly in the TUI:
|
|
|
174
174
|
OpenCode Zen provides curated models optimized for coding tasks, including **free models**.
|
|
175
175
|
|
|
176
176
|
**Free Models:**
|
|
177
|
+
- `big-pickle` - Stealth model (default)
|
|
177
178
|
- `grok-code` - xAI's Grok Code Fast 1
|
|
178
179
|
- `glm-4.7-free` - GLM 4.7
|
|
179
180
|
- `minimax-m2.1-free` - MiniMax M2.1
|
|
180
|
-
- `big-pickle` - Stealth model
|
|
181
181
|
|
|
182
182
|
**Premium Models:**
|
|
183
183
|
- Claude Sonnet 4.5, Claude Opus 4.5
|
|
184
|
-
- Gemini 3 Flash, Gemini 3 Pro
|
|
185
184
|
- Kimi K2, Kimi K2 Thinking
|
|
186
185
|
- Qwen3 Coder 480B
|
|
186
|
+
- GLM 4.6
|
|
187
187
|
- And more...
|
|
188
188
|
|
|
189
189
|
Get your API key at: https://opencode.ai/auth
|
|
@@ -195,13 +195,11 @@ Access to a wide variety of models from different providers.
|
|
|
195
195
|
**Free Models:**
|
|
196
196
|
- MiMo V2 Flash
|
|
197
197
|
- DeepSeek V3
|
|
198
|
-
- Gemini 2.5 Flash
|
|
199
198
|
|
|
200
199
|
**Premium Models:**
|
|
201
200
|
- Claude Sonnet 4.5, Claude Opus 4.5
|
|
202
|
-
- GPT 5.2 Codex
|
|
203
|
-
- Gemini 2.5 Pro
|
|
204
201
|
- DeepSeek R1
|
|
202
|
+
- GLM 4.7
|
|
205
203
|
- And many more...
|
|
206
204
|
|
|
207
205
|
Get your API key at: https://openrouter.ai/keys
|
|
@@ -244,7 +242,7 @@ Configuration is stored in `~/.magic-shell/config.json`.
|
|
|
244
242
|
```json
|
|
245
243
|
{
|
|
246
244
|
"provider": "opencode-zen",
|
|
247
|
-
"defaultModel": "
|
|
245
|
+
"defaultModel": "big-pickle",
|
|
248
246
|
"safetyLevel": "moderate",
|
|
249
247
|
"dryRunByDefault": false,
|
|
250
248
|
"repoContext": false,
|
package/dist/cli.js
CHANGED
|
@@ -20500,23 +20500,6 @@ var OPENROUTER_MODELS = [
|
|
|
20500
20500
|
contextLength: 128000,
|
|
20501
20501
|
free: true
|
|
20502
20502
|
},
|
|
20503
|
-
{
|
|
20504
|
-
id: "google/gemini-2.5-flash-preview:free",
|
|
20505
|
-
name: "Gemini 2.5 Flash",
|
|
20506
|
-
description: "Free Google model with thinking capabilities",
|
|
20507
|
-
category: "fast",
|
|
20508
|
-
provider: "openrouter",
|
|
20509
|
-
contextLength: 1048576,
|
|
20510
|
-
free: true
|
|
20511
|
-
},
|
|
20512
|
-
{
|
|
20513
|
-
id: "google/gemini-3-flash-preview",
|
|
20514
|
-
name: "Gemini 3 Flash",
|
|
20515
|
-
description: "Google's fastest model, 1M context",
|
|
20516
|
-
category: "fast",
|
|
20517
|
-
provider: "openrouter",
|
|
20518
|
-
contextLength: 1048576
|
|
20519
|
-
},
|
|
20520
20503
|
{
|
|
20521
20504
|
id: "anthropic/claude-haiku-4-5",
|
|
20522
20505
|
name: "Claude Haiku 4.5",
|
|
@@ -20525,14 +20508,6 @@ var OPENROUTER_MODELS = [
|
|
|
20525
20508
|
provider: "openrouter",
|
|
20526
20509
|
contextLength: 200000
|
|
20527
20510
|
},
|
|
20528
|
-
{
|
|
20529
|
-
id: "openai/gpt-5.1-codex-mini",
|
|
20530
|
-
name: "GPT 5.1 Codex Mini",
|
|
20531
|
-
description: "OpenAI's efficient coding model",
|
|
20532
|
-
category: "fast",
|
|
20533
|
-
provider: "openrouter",
|
|
20534
|
-
contextLength: 128000
|
|
20535
|
-
},
|
|
20536
20511
|
{
|
|
20537
20512
|
id: "anthropic/claude-sonnet-4.5",
|
|
20538
20513
|
name: "Claude Sonnet 4.5",
|
|
@@ -20549,22 +20524,6 @@ var OPENROUTER_MODELS = [
|
|
|
20549
20524
|
provider: "openrouter",
|
|
20550
20525
|
contextLength: 200000
|
|
20551
20526
|
},
|
|
20552
|
-
{
|
|
20553
|
-
id: "openai/gpt-5.2-codex",
|
|
20554
|
-
name: "GPT 5.2 Codex",
|
|
20555
|
-
description: "OpenAI's latest coding model",
|
|
20556
|
-
category: "smart",
|
|
20557
|
-
provider: "openrouter",
|
|
20558
|
-
contextLength: 400000
|
|
20559
|
-
},
|
|
20560
|
-
{
|
|
20561
|
-
id: "google/gemini-2.5-pro",
|
|
20562
|
-
name: "Gemini 2.5 Pro",
|
|
20563
|
-
description: "Google's advanced reasoning model",
|
|
20564
|
-
category: "smart",
|
|
20565
|
-
provider: "openrouter",
|
|
20566
|
-
contextLength: 1048576
|
|
20567
|
-
},
|
|
20568
20527
|
{
|
|
20569
20528
|
id: "zhipu/glm-4.7",
|
|
20570
20529
|
name: "GLM 4.7",
|
|
@@ -20591,6 +20550,15 @@ var OPENROUTER_MODELS = [
|
|
|
20591
20550
|
}
|
|
20592
20551
|
];
|
|
20593
20552
|
var OPENCODE_ZEN_MODELS = [
|
|
20553
|
+
{
|
|
20554
|
+
id: "big-pickle",
|
|
20555
|
+
name: "Big Pickle",
|
|
20556
|
+
description: "Free stealth model (limited time)",
|
|
20557
|
+
category: "smart",
|
|
20558
|
+
provider: "opencode-zen",
|
|
20559
|
+
contextLength: 128000,
|
|
20560
|
+
free: true
|
|
20561
|
+
},
|
|
20594
20562
|
{
|
|
20595
20563
|
id: "grok-code",
|
|
20596
20564
|
name: "Grok Code Fast 1",
|
|
@@ -20618,34 +20586,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
20618
20586
|
contextLength: 128000,
|
|
20619
20587
|
free: true
|
|
20620
20588
|
},
|
|
20621
|
-
{
|
|
20622
|
-
id: "big-pickle",
|
|
20623
|
-
name: "Big Pickle",
|
|
20624
|
-
description: "Free stealth model (limited time)",
|
|
20625
|
-
category: "smart",
|
|
20626
|
-
provider: "opencode-zen",
|
|
20627
|
-
contextLength: 128000,
|
|
20628
|
-
free: true
|
|
20629
|
-
},
|
|
20630
|
-
{
|
|
20631
|
-
id: "gpt-5-nano",
|
|
20632
|
-
name: "GPT 5 Nano",
|
|
20633
|
-
description: "Free OpenAI model (temporarily disabled)",
|
|
20634
|
-
category: "fast",
|
|
20635
|
-
provider: "opencode-zen",
|
|
20636
|
-
contextLength: 128000,
|
|
20637
|
-
free: true,
|
|
20638
|
-
disabled: true,
|
|
20639
|
-
disabledReason: "OpenCode Zen API issue"
|
|
20640
|
-
},
|
|
20641
|
-
{
|
|
20642
|
-
id: "gemini-3-flash",
|
|
20643
|
-
name: "Gemini 3 Flash",
|
|
20644
|
-
description: "Google's fastest Gemini model",
|
|
20645
|
-
category: "fast",
|
|
20646
|
-
provider: "opencode-zen",
|
|
20647
|
-
contextLength: 1e6
|
|
20648
|
-
},
|
|
20649
20589
|
{
|
|
20650
20590
|
id: "claude-3-5-haiku",
|
|
20651
20591
|
name: "Claude Haiku 3.5",
|
|
@@ -20654,16 +20594,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
20654
20594
|
provider: "opencode-zen",
|
|
20655
20595
|
contextLength: 200000
|
|
20656
20596
|
},
|
|
20657
|
-
{
|
|
20658
|
-
id: "gpt-5.1-codex-mini",
|
|
20659
|
-
name: "GPT 5.1 Codex Mini",
|
|
20660
|
-
description: "OpenAI's efficient coding model (temporarily disabled)",
|
|
20661
|
-
category: "fast",
|
|
20662
|
-
provider: "opencode-zen",
|
|
20663
|
-
disabled: true,
|
|
20664
|
-
disabledReason: "OpenCode Zen API issue",
|
|
20665
|
-
contextLength: 128000
|
|
20666
|
-
},
|
|
20667
20597
|
{
|
|
20668
20598
|
id: "claude-sonnet-4",
|
|
20669
20599
|
name: "Claude Sonnet 4",
|
|
@@ -20680,34 +20610,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
20680
20610
|
provider: "opencode-zen",
|
|
20681
20611
|
contextLength: 200000
|
|
20682
20612
|
},
|
|
20683
|
-
{
|
|
20684
|
-
id: "gpt-5.1-codex",
|
|
20685
|
-
name: "GPT 5.1 Codex",
|
|
20686
|
-
description: "OpenAI's coding-optimized model (temporarily disabled)",
|
|
20687
|
-
category: "smart",
|
|
20688
|
-
provider: "opencode-zen",
|
|
20689
|
-
contextLength: 128000,
|
|
20690
|
-
disabled: true,
|
|
20691
|
-
disabledReason: "OpenCode Zen API issue"
|
|
20692
|
-
},
|
|
20693
|
-
{
|
|
20694
|
-
id: "gpt-5.2-codex",
|
|
20695
|
-
name: "GPT 5.2 Codex",
|
|
20696
|
-
description: "OpenAI's latest coding model (temporarily disabled)",
|
|
20697
|
-
category: "smart",
|
|
20698
|
-
provider: "opencode-zen",
|
|
20699
|
-
contextLength: 128000,
|
|
20700
|
-
disabled: true,
|
|
20701
|
-
disabledReason: "OpenCode Zen API issue"
|
|
20702
|
-
},
|
|
20703
|
-
{
|
|
20704
|
-
id: "gemini-3-pro",
|
|
20705
|
-
name: "Gemini 3 Pro",
|
|
20706
|
-
description: "Google's advanced Gemini model",
|
|
20707
|
-
category: "smart",
|
|
20708
|
-
provider: "opencode-zen",
|
|
20709
|
-
contextLength: 1e6
|
|
20710
|
-
},
|
|
20711
20613
|
{
|
|
20712
20614
|
id: "kimi-k2",
|
|
20713
20615
|
name: "Kimi K2",
|
|
@@ -21070,7 +20972,7 @@ var DEFAULT_CONFIG = {
|
|
|
21070
20972
|
provider: "opencode-zen",
|
|
21071
20973
|
openrouterApiKey: "",
|
|
21072
20974
|
opencodeZenApiKey: "",
|
|
21073
|
-
defaultModel: "
|
|
20975
|
+
defaultModel: "big-pickle",
|
|
21074
20976
|
safetyLevel: "moderate",
|
|
21075
20977
|
dryRunByDefault: false,
|
|
21076
20978
|
blockedCommands: [
|
|
@@ -21738,6 +21640,13 @@ async function callOpenRouter(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21738
21640
|
return data.choices[0]?.message?.content?.trim() || "";
|
|
21739
21641
|
}
|
|
21740
21642
|
var DEBUG_API = process.env.DEBUG_API === "1";
|
|
21643
|
+
function appendDebugInfo(message, status, responseText) {
|
|
21644
|
+
if (!DEBUG_API)
|
|
21645
|
+
return message;
|
|
21646
|
+
const snippet = responseText.slice(0, 1000);
|
|
21647
|
+
return `${message}
|
|
21648
|
+
[DEBUG] status=${status} response=${snippet}`;
|
|
21649
|
+
}
|
|
21741
21650
|
async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput) {
|
|
21742
21651
|
if (DEBUG_API) {
|
|
21743
21652
|
console.error(`[DEBUG] Calling OpenAI Responses API`);
|
|
@@ -21755,7 +21664,8 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
21755
21664
|
instructions: systemPrompt,
|
|
21756
21665
|
input: userInput,
|
|
21757
21666
|
max_output_tokens: 500,
|
|
21758
|
-
temperature: 0.1
|
|
21667
|
+
temperature: 0.1,
|
|
21668
|
+
stream: false
|
|
21759
21669
|
})
|
|
21760
21670
|
});
|
|
21761
21671
|
const responseText = await response.text();
|
|
@@ -21773,7 +21683,7 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
21773
21683
|
errorMessage = errorData.message;
|
|
21774
21684
|
}
|
|
21775
21685
|
} catch {}
|
|
21776
|
-
throw new Error(errorMessage);
|
|
21686
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
21777
21687
|
}
|
|
21778
21688
|
let data;
|
|
21779
21689
|
try {
|
|
@@ -21782,7 +21692,8 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
21782
21692
|
throw new Error(`Invalid JSON response: ${responseText.slice(0, 200)}`);
|
|
21783
21693
|
}
|
|
21784
21694
|
if (data.error) {
|
|
21785
|
-
|
|
21695
|
+
const errorMessage = data.error.message || data.error;
|
|
21696
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
21786
21697
|
}
|
|
21787
21698
|
if (typeof data.output_text === "string") {
|
|
21788
21699
|
return data.output_text.trim();
|
|
@@ -21837,7 +21748,7 @@ async function callZenAnthropic(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21837
21748
|
errorMessage = errorData.error.message;
|
|
21838
21749
|
}
|
|
21839
21750
|
} catch {}
|
|
21840
|
-
throw new Error(errorMessage);
|
|
21751
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, errorText));
|
|
21841
21752
|
}
|
|
21842
21753
|
const data = await response.json();
|
|
21843
21754
|
if (data.error) {
|
|
@@ -21876,21 +21787,38 @@ async function callZenOpenAICompatible(apiKey, modelId, systemPrompt, userInput)
|
|
|
21876
21787
|
errorMessage = errorData.error.message;
|
|
21877
21788
|
}
|
|
21878
21789
|
} catch {}
|
|
21879
|
-
throw new Error(errorMessage);
|
|
21790
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, errorText));
|
|
21880
21791
|
}
|
|
21881
21792
|
const data = await response.json();
|
|
21882
21793
|
if (data.error) {
|
|
21883
21794
|
throw new Error(data.error.message);
|
|
21884
21795
|
}
|
|
21885
|
-
|
|
21796
|
+
const choice = data.choices?.[0];
|
|
21797
|
+
const messageContent = choice?.message?.content;
|
|
21798
|
+
if (typeof messageContent === "string") {
|
|
21799
|
+
return messageContent.trim();
|
|
21800
|
+
}
|
|
21801
|
+
if (Array.isArray(messageContent)) {
|
|
21802
|
+
const textBlocks = messageContent.map((block) => typeof block === "string" ? block : block?.text).filter(Boolean);
|
|
21803
|
+
if (textBlocks.length > 0) {
|
|
21804
|
+
return textBlocks.join("").trim();
|
|
21805
|
+
}
|
|
21806
|
+
}
|
|
21807
|
+
if (typeof choice?.text === "string") {
|
|
21808
|
+
return choice.text.trim();
|
|
21809
|
+
}
|
|
21810
|
+
return "";
|
|
21886
21811
|
}
|
|
21887
21812
|
async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
21888
|
-
const endpoint = `https://opencode.ai/zen/v1/models/${modelId}
|
|
21813
|
+
const endpoint = `https://opencode.ai/zen/v1/models/${modelId}`;
|
|
21889
21814
|
if (DEBUG_API) {
|
|
21890
21815
|
console.error(`[DEBUG] Calling Google Gemini API`);
|
|
21891
21816
|
console.error(`[DEBUG] Model: ${modelId}`);
|
|
21892
21817
|
console.error(`[DEBUG] Endpoint: ${endpoint}`);
|
|
21893
21818
|
}
|
|
21819
|
+
const prompt = `${systemPrompt}
|
|
21820
|
+
|
|
21821
|
+
User request: ${userInput}`;
|
|
21894
21822
|
const response = await fetch(endpoint, {
|
|
21895
21823
|
method: "POST",
|
|
21896
21824
|
headers: {
|
|
@@ -21899,9 +21827,8 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21899
21827
|
},
|
|
21900
21828
|
body: JSON.stringify({
|
|
21901
21829
|
contents: [
|
|
21902
|
-
{ role: "user", parts: [{ text:
|
|
21830
|
+
{ role: "user", parts: [{ text: prompt }] }
|
|
21903
21831
|
],
|
|
21904
|
-
systemInstruction: { parts: [{ text: systemPrompt }] },
|
|
21905
21832
|
generationConfig: {
|
|
21906
21833
|
maxOutputTokens: 500,
|
|
21907
21834
|
temperature: 0.1
|
|
@@ -21921,7 +21848,7 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21921
21848
|
errorMessage = errorData.error.message;
|
|
21922
21849
|
}
|
|
21923
21850
|
} catch {}
|
|
21924
|
-
throw new Error(errorMessage);
|
|
21851
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
21925
21852
|
}
|
|
21926
21853
|
let data;
|
|
21927
21854
|
try {
|
|
@@ -21930,7 +21857,7 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21930
21857
|
throw new Error(`Invalid JSON response: ${responseText.slice(0, 200)}`);
|
|
21931
21858
|
}
|
|
21932
21859
|
if (data.error) {
|
|
21933
|
-
throw new Error(data.error.message);
|
|
21860
|
+
throw new Error(appendDebugInfo(data.error.message, response.status, responseText));
|
|
21934
21861
|
}
|
|
21935
21862
|
const candidate = data.candidates?.[0];
|
|
21936
21863
|
const textPart = candidate?.content?.parts?.find((p) => p.text);
|
|
@@ -21966,7 +21893,11 @@ async function translateToCommand(apiKey, model, userInput, cwd, history = [], r
|
|
|
21966
21893
|
break;
|
|
21967
21894
|
}
|
|
21968
21895
|
}
|
|
21969
|
-
|
|
21896
|
+
const cleaned = cleanCommand(rawCommand);
|
|
21897
|
+
if (!cleaned) {
|
|
21898
|
+
throw new Error("Model returned an empty command. Try another model or rephrase your request.");
|
|
21899
|
+
}
|
|
21900
|
+
return cleaned;
|
|
21970
21901
|
}
|
|
21971
21902
|
|
|
21972
21903
|
// src/lib/theme.ts
|
|
@@ -22319,7 +22250,7 @@ Enter your API key below:`,
|
|
|
22319
22250
|
const freeNote = new TextRenderable(renderer, {
|
|
22320
22251
|
id: "free-note",
|
|
22321
22252
|
content: t`
|
|
22322
|
-
${fg("#22c55e")("Tip:")} OpenCode Zen has free models like
|
|
22253
|
+
${fg("#22c55e")("Tip:")} OpenCode Zen has free models like Big Pickle and GLM 4.7!`,
|
|
22323
22254
|
marginTop: 1
|
|
22324
22255
|
});
|
|
22325
22256
|
container.add(freeNote);
|
|
@@ -22335,7 +22266,7 @@ ${fg("#64748b")("Press Enter to save | Ctrl+C to exit")}`,
|
|
|
22335
22266
|
if (value.trim()) {
|
|
22336
22267
|
setApiKey(provider, value.trim());
|
|
22337
22268
|
if (provider === "opencode-zen") {
|
|
22338
|
-
currentModel = OPENCODE_ZEN_MODELS.find((m) => m.id === "
|
|
22269
|
+
currentModel = OPENCODE_ZEN_MODELS.find((m) => m.id === "big-pickle") || OPENCODE_ZEN_MODELS[0];
|
|
22339
22270
|
} else {
|
|
22340
22271
|
currentModel = OPENROUTER_MODELS[0];
|
|
22341
22272
|
}
|
|
@@ -22371,11 +22302,6 @@ function createMainUI() {
|
|
|
22371
22302
|
flexGrow: 1
|
|
22372
22303
|
});
|
|
22373
22304
|
headerRow.add(headerText);
|
|
22374
|
-
const modelBadge = new TextRenderable(renderer, {
|
|
22375
|
-
id: "model-badge",
|
|
22376
|
-
content: getModelDisplay()
|
|
22377
|
-
});
|
|
22378
|
-
headerRow.add(modelBadge);
|
|
22379
22305
|
statusBarText = new TextRenderable(renderer, {
|
|
22380
22306
|
id: "status-bar-text",
|
|
22381
22307
|
content: getStatusBarContent(),
|
|
@@ -22458,14 +22384,14 @@ function getStatusBarContent() {
|
|
|
22458
22384
|
function getHelpBarContent() {
|
|
22459
22385
|
const theme = getTheme();
|
|
22460
22386
|
if (awaitingConfirmation) {
|
|
22461
|
-
return t`${fg(theme.colors.warning)("
|
|
22387
|
+
return t`${fg(theme.colors.warning)(">>> Press Enter to execute command <<<")} ${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")}`;
|
|
22462
22388
|
}
|
|
22463
22389
|
return t`${fg(theme.colors.textMuted)("Ctrl+X")} ${fg(theme.colors.primary)("P")}${fg(theme.colors.textMuted)(" Palette")} ${fg(theme.colors.primary)("M")}${fg(theme.colors.textMuted)(" Model")} ${fg(theme.colors.primary)("T")}${fg(theme.colors.textMuted)(" Theme")} ${fg(theme.colors.primary)("D")}${fg(theme.colors.textMuted)(" Dry-run")} ${fg(theme.colors.primary)("?")}${fg(theme.colors.textMuted)(" Help")}`;
|
|
22464
22390
|
}
|
|
22465
22391
|
function getWelcomeMessage() {
|
|
22466
22392
|
const providerName = config.provider === "opencode-zen" ? "OpenCode Zen" : "OpenRouter";
|
|
22467
22393
|
const freeNote = config.provider === "opencode-zen" ? `
|
|
22468
|
-
Free models:
|
|
22394
|
+
Free models: big-pickle, glm-4.7-free` : "";
|
|
22469
22395
|
return `Ready. Using ${providerName}.${freeNote}
|
|
22470
22396
|
Type what you want to do, or press Ctrl+X P for command palette.`;
|
|
22471
22397
|
}
|
|
@@ -22580,14 +22506,16 @@ function createAssistantMessageRenderable(msg, theme) {
|
|
|
22580
22506
|
if (isSelected && !msg.executed) {
|
|
22581
22507
|
const actionsText = new TextRenderable(renderer, {
|
|
22582
22508
|
id: `msg-${msg.id}-actions`,
|
|
22583
|
-
content: t`${fg(theme.colors.warning)("
|
|
22509
|
+
content: t`${fg(theme.colors.warning)("Press Enter to run")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.primary)("[c]")} ${fg(theme.colors.textMuted)("Copy")} ${fg(theme.colors.primary)("[e]")} ${fg(theme.colors.textMuted)("Edit")} ${fg(theme.colors.error)("[Esc]")} ${fg(theme.colors.textMuted)("Cancel")}`
|
|
22584
22510
|
});
|
|
22585
22511
|
card.add(actionsText);
|
|
22586
22512
|
}
|
|
22587
22513
|
if (msg.executed) {
|
|
22514
|
+
const wasAutoRun = !msg.safety?.isDangerous;
|
|
22515
|
+
const execLabel = wasAutoRun ? "Auto-executed (safe)" : "Executed";
|
|
22588
22516
|
const execText = new TextRenderable(renderer, {
|
|
22589
22517
|
id: `msg-${msg.id}-exec`,
|
|
22590
|
-
content: t`${fg(theme.colors.success)("
|
|
22518
|
+
content: t`${fg(theme.colors.success)("✓")} ${fg(theme.colors.success)(execLabel)}`
|
|
22591
22519
|
});
|
|
22592
22520
|
card.add(execText);
|
|
22593
22521
|
}
|
|
@@ -22702,13 +22630,6 @@ function toggleLastResultExpand() {
|
|
|
22702
22630
|
const lastResult = resultMessages[resultMessages.length - 1];
|
|
22703
22631
|
toggleResultExpand(lastResult.id);
|
|
22704
22632
|
}
|
|
22705
|
-
function getModelDisplay() {
|
|
22706
|
-
const theme = getTheme();
|
|
22707
|
-
const categoryColor = currentModel.category === "fast" ? theme.colors.success : currentModel.category === "smart" ? theme.colors.primary : theme.colors.secondary;
|
|
22708
|
-
const providerBadge = currentModel.provider === "opencode-zen" ? fg(theme.colors.accent)("[zen]") : fg(theme.colors.warning)("[or]");
|
|
22709
|
-
const freeBadge = currentModel.free ? fg(theme.colors.success)(" FREE") : "";
|
|
22710
|
-
return t`${providerBadge} ${fg(categoryColor)(currentModel.name)}${freeBadge}`;
|
|
22711
|
-
}
|
|
22712
22633
|
function refreshThemeColors() {
|
|
22713
22634
|
const theme = getTheme();
|
|
22714
22635
|
renderer.setBackgroundColor(theme.colors.background);
|
package/dist/index.js
CHANGED
|
@@ -43,23 +43,6 @@ var OPENROUTER_MODELS = [
|
|
|
43
43
|
contextLength: 128000,
|
|
44
44
|
free: true
|
|
45
45
|
},
|
|
46
|
-
{
|
|
47
|
-
id: "google/gemini-2.5-flash-preview:free",
|
|
48
|
-
name: "Gemini 2.5 Flash",
|
|
49
|
-
description: "Free Google model with thinking capabilities",
|
|
50
|
-
category: "fast",
|
|
51
|
-
provider: "openrouter",
|
|
52
|
-
contextLength: 1048576,
|
|
53
|
-
free: true
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
id: "google/gemini-3-flash-preview",
|
|
57
|
-
name: "Gemini 3 Flash",
|
|
58
|
-
description: "Google's fastest model, 1M context",
|
|
59
|
-
category: "fast",
|
|
60
|
-
provider: "openrouter",
|
|
61
|
-
contextLength: 1048576
|
|
62
|
-
},
|
|
63
46
|
{
|
|
64
47
|
id: "anthropic/claude-haiku-4-5",
|
|
65
48
|
name: "Claude Haiku 4.5",
|
|
@@ -68,14 +51,6 @@ var OPENROUTER_MODELS = [
|
|
|
68
51
|
provider: "openrouter",
|
|
69
52
|
contextLength: 200000
|
|
70
53
|
},
|
|
71
|
-
{
|
|
72
|
-
id: "openai/gpt-5.1-codex-mini",
|
|
73
|
-
name: "GPT 5.1 Codex Mini",
|
|
74
|
-
description: "OpenAI's efficient coding model",
|
|
75
|
-
category: "fast",
|
|
76
|
-
provider: "openrouter",
|
|
77
|
-
contextLength: 128000
|
|
78
|
-
},
|
|
79
54
|
{
|
|
80
55
|
id: "anthropic/claude-sonnet-4.5",
|
|
81
56
|
name: "Claude Sonnet 4.5",
|
|
@@ -92,22 +67,6 @@ var OPENROUTER_MODELS = [
|
|
|
92
67
|
provider: "openrouter",
|
|
93
68
|
contextLength: 200000
|
|
94
69
|
},
|
|
95
|
-
{
|
|
96
|
-
id: "openai/gpt-5.2-codex",
|
|
97
|
-
name: "GPT 5.2 Codex",
|
|
98
|
-
description: "OpenAI's latest coding model",
|
|
99
|
-
category: "smart",
|
|
100
|
-
provider: "openrouter",
|
|
101
|
-
contextLength: 400000
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: "google/gemini-2.5-pro",
|
|
105
|
-
name: "Gemini 2.5 Pro",
|
|
106
|
-
description: "Google's advanced reasoning model",
|
|
107
|
-
category: "smart",
|
|
108
|
-
provider: "openrouter",
|
|
109
|
-
contextLength: 1048576
|
|
110
|
-
},
|
|
111
70
|
{
|
|
112
71
|
id: "zhipu/glm-4.7",
|
|
113
72
|
name: "GLM 4.7",
|
|
@@ -134,6 +93,15 @@ var OPENROUTER_MODELS = [
|
|
|
134
93
|
}
|
|
135
94
|
];
|
|
136
95
|
var OPENCODE_ZEN_MODELS = [
|
|
96
|
+
{
|
|
97
|
+
id: "big-pickle",
|
|
98
|
+
name: "Big Pickle",
|
|
99
|
+
description: "Free stealth model (limited time)",
|
|
100
|
+
category: "smart",
|
|
101
|
+
provider: "opencode-zen",
|
|
102
|
+
contextLength: 128000,
|
|
103
|
+
free: true
|
|
104
|
+
},
|
|
137
105
|
{
|
|
138
106
|
id: "grok-code",
|
|
139
107
|
name: "Grok Code Fast 1",
|
|
@@ -161,34 +129,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
161
129
|
contextLength: 128000,
|
|
162
130
|
free: true
|
|
163
131
|
},
|
|
164
|
-
{
|
|
165
|
-
id: "big-pickle",
|
|
166
|
-
name: "Big Pickle",
|
|
167
|
-
description: "Free stealth model (limited time)",
|
|
168
|
-
category: "smart",
|
|
169
|
-
provider: "opencode-zen",
|
|
170
|
-
contextLength: 128000,
|
|
171
|
-
free: true
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
id: "gpt-5-nano",
|
|
175
|
-
name: "GPT 5 Nano",
|
|
176
|
-
description: "Free OpenAI model (temporarily disabled)",
|
|
177
|
-
category: "fast",
|
|
178
|
-
provider: "opencode-zen",
|
|
179
|
-
contextLength: 128000,
|
|
180
|
-
free: true,
|
|
181
|
-
disabled: true,
|
|
182
|
-
disabledReason: "OpenCode Zen API issue"
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
id: "gemini-3-flash",
|
|
186
|
-
name: "Gemini 3 Flash",
|
|
187
|
-
description: "Google's fastest Gemini model",
|
|
188
|
-
category: "fast",
|
|
189
|
-
provider: "opencode-zen",
|
|
190
|
-
contextLength: 1e6
|
|
191
|
-
},
|
|
192
132
|
{
|
|
193
133
|
id: "claude-3-5-haiku",
|
|
194
134
|
name: "Claude Haiku 3.5",
|
|
@@ -197,16 +137,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
197
137
|
provider: "opencode-zen",
|
|
198
138
|
contextLength: 200000
|
|
199
139
|
},
|
|
200
|
-
{
|
|
201
|
-
id: "gpt-5.1-codex-mini",
|
|
202
|
-
name: "GPT 5.1 Codex Mini",
|
|
203
|
-
description: "OpenAI's efficient coding model (temporarily disabled)",
|
|
204
|
-
category: "fast",
|
|
205
|
-
provider: "opencode-zen",
|
|
206
|
-
disabled: true,
|
|
207
|
-
disabledReason: "OpenCode Zen API issue",
|
|
208
|
-
contextLength: 128000
|
|
209
|
-
},
|
|
210
140
|
{
|
|
211
141
|
id: "claude-sonnet-4",
|
|
212
142
|
name: "Claude Sonnet 4",
|
|
@@ -223,34 +153,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
223
153
|
provider: "opencode-zen",
|
|
224
154
|
contextLength: 200000
|
|
225
155
|
},
|
|
226
|
-
{
|
|
227
|
-
id: "gpt-5.1-codex",
|
|
228
|
-
name: "GPT 5.1 Codex",
|
|
229
|
-
description: "OpenAI's coding-optimized model (temporarily disabled)",
|
|
230
|
-
category: "smart",
|
|
231
|
-
provider: "opencode-zen",
|
|
232
|
-
contextLength: 128000,
|
|
233
|
-
disabled: true,
|
|
234
|
-
disabledReason: "OpenCode Zen API issue"
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
id: "gpt-5.2-codex",
|
|
238
|
-
name: "GPT 5.2 Codex",
|
|
239
|
-
description: "OpenAI's latest coding model (temporarily disabled)",
|
|
240
|
-
category: "smart",
|
|
241
|
-
provider: "opencode-zen",
|
|
242
|
-
contextLength: 128000,
|
|
243
|
-
disabled: true,
|
|
244
|
-
disabledReason: "OpenCode Zen API issue"
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
id: "gemini-3-pro",
|
|
248
|
-
name: "Gemini 3 Pro",
|
|
249
|
-
description: "Google's advanced Gemini model",
|
|
250
|
-
category: "smart",
|
|
251
|
-
provider: "opencode-zen",
|
|
252
|
-
contextLength: 1e6
|
|
253
|
-
},
|
|
254
156
|
{
|
|
255
157
|
id: "kimi-k2",
|
|
256
158
|
name: "Kimi K2",
|
|
@@ -613,7 +515,7 @@ var DEFAULT_CONFIG = {
|
|
|
613
515
|
provider: "opencode-zen",
|
|
614
516
|
openrouterApiKey: "",
|
|
615
517
|
opencodeZenApiKey: "",
|
|
616
|
-
defaultModel: "
|
|
518
|
+
defaultModel: "big-pickle",
|
|
617
519
|
safetyLevel: "moderate",
|
|
618
520
|
dryRunByDefault: false,
|
|
619
521
|
blockedCommands: [
|
|
@@ -1259,6 +1161,13 @@ async function callOpenRouter(apiKey, modelId, systemPrompt, userInput) {
|
|
|
1259
1161
|
return data.choices[0]?.message?.content?.trim() || "";
|
|
1260
1162
|
}
|
|
1261
1163
|
var DEBUG_API = process.env.DEBUG_API === "1";
|
|
1164
|
+
function appendDebugInfo(message, status, responseText) {
|
|
1165
|
+
if (!DEBUG_API)
|
|
1166
|
+
return message;
|
|
1167
|
+
const snippet = responseText.slice(0, 1000);
|
|
1168
|
+
return `${message}
|
|
1169
|
+
[DEBUG] status=${status} response=${snippet}`;
|
|
1170
|
+
}
|
|
1262
1171
|
async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput) {
|
|
1263
1172
|
if (DEBUG_API) {
|
|
1264
1173
|
console.error(`[DEBUG] Calling OpenAI Responses API`);
|
|
@@ -1276,7 +1185,8 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
1276
1185
|
instructions: systemPrompt,
|
|
1277
1186
|
input: userInput,
|
|
1278
1187
|
max_output_tokens: 500,
|
|
1279
|
-
temperature: 0.1
|
|
1188
|
+
temperature: 0.1,
|
|
1189
|
+
stream: false
|
|
1280
1190
|
})
|
|
1281
1191
|
});
|
|
1282
1192
|
const responseText = await response.text();
|
|
@@ -1294,7 +1204,7 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
1294
1204
|
errorMessage = errorData.message;
|
|
1295
1205
|
}
|
|
1296
1206
|
} catch {}
|
|
1297
|
-
throw new Error(errorMessage);
|
|
1207
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
1298
1208
|
}
|
|
1299
1209
|
let data;
|
|
1300
1210
|
try {
|
|
@@ -1303,7 +1213,8 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
1303
1213
|
throw new Error(`Invalid JSON response: ${responseText.slice(0, 200)}`);
|
|
1304
1214
|
}
|
|
1305
1215
|
if (data.error) {
|
|
1306
|
-
|
|
1216
|
+
const errorMessage = data.error.message || data.error;
|
|
1217
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
1307
1218
|
}
|
|
1308
1219
|
if (typeof data.output_text === "string") {
|
|
1309
1220
|
return data.output_text.trim();
|
|
@@ -1358,7 +1269,7 @@ async function callZenAnthropic(apiKey, modelId, systemPrompt, userInput) {
|
|
|
1358
1269
|
errorMessage = errorData.error.message;
|
|
1359
1270
|
}
|
|
1360
1271
|
} catch {}
|
|
1361
|
-
throw new Error(errorMessage);
|
|
1272
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, errorText));
|
|
1362
1273
|
}
|
|
1363
1274
|
const data = await response.json();
|
|
1364
1275
|
if (data.error) {
|
|
@@ -1397,21 +1308,38 @@ async function callZenOpenAICompatible(apiKey, modelId, systemPrompt, userInput)
|
|
|
1397
1308
|
errorMessage = errorData.error.message;
|
|
1398
1309
|
}
|
|
1399
1310
|
} catch {}
|
|
1400
|
-
throw new Error(errorMessage);
|
|
1311
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, errorText));
|
|
1401
1312
|
}
|
|
1402
1313
|
const data = await response.json();
|
|
1403
1314
|
if (data.error) {
|
|
1404
1315
|
throw new Error(data.error.message);
|
|
1405
1316
|
}
|
|
1406
|
-
|
|
1317
|
+
const choice = data.choices?.[0];
|
|
1318
|
+
const messageContent = choice?.message?.content;
|
|
1319
|
+
if (typeof messageContent === "string") {
|
|
1320
|
+
return messageContent.trim();
|
|
1321
|
+
}
|
|
1322
|
+
if (Array.isArray(messageContent)) {
|
|
1323
|
+
const textBlocks = messageContent.map((block) => typeof block === "string" ? block : block?.text).filter(Boolean);
|
|
1324
|
+
if (textBlocks.length > 0) {
|
|
1325
|
+
return textBlocks.join("").trim();
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
if (typeof choice?.text === "string") {
|
|
1329
|
+
return choice.text.trim();
|
|
1330
|
+
}
|
|
1331
|
+
return "";
|
|
1407
1332
|
}
|
|
1408
1333
|
async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
1409
|
-
const endpoint = `https://opencode.ai/zen/v1/models/${modelId}
|
|
1334
|
+
const endpoint = `https://opencode.ai/zen/v1/models/${modelId}`;
|
|
1410
1335
|
if (DEBUG_API) {
|
|
1411
1336
|
console.error(`[DEBUG] Calling Google Gemini API`);
|
|
1412
1337
|
console.error(`[DEBUG] Model: ${modelId}`);
|
|
1413
1338
|
console.error(`[DEBUG] Endpoint: ${endpoint}`);
|
|
1414
1339
|
}
|
|
1340
|
+
const prompt = `${systemPrompt}
|
|
1341
|
+
|
|
1342
|
+
User request: ${userInput}`;
|
|
1415
1343
|
const response = await fetch(endpoint, {
|
|
1416
1344
|
method: "POST",
|
|
1417
1345
|
headers: {
|
|
@@ -1420,9 +1348,8 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
1420
1348
|
},
|
|
1421
1349
|
body: JSON.stringify({
|
|
1422
1350
|
contents: [
|
|
1423
|
-
{ role: "user", parts: [{ text:
|
|
1351
|
+
{ role: "user", parts: [{ text: prompt }] }
|
|
1424
1352
|
],
|
|
1425
|
-
systemInstruction: { parts: [{ text: systemPrompt }] },
|
|
1426
1353
|
generationConfig: {
|
|
1427
1354
|
maxOutputTokens: 500,
|
|
1428
1355
|
temperature: 0.1
|
|
@@ -1442,7 +1369,7 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
1442
1369
|
errorMessage = errorData.error.message;
|
|
1443
1370
|
}
|
|
1444
1371
|
} catch {}
|
|
1445
|
-
throw new Error(errorMessage);
|
|
1372
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
1446
1373
|
}
|
|
1447
1374
|
let data;
|
|
1448
1375
|
try {
|
|
@@ -1451,7 +1378,7 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
1451
1378
|
throw new Error(`Invalid JSON response: ${responseText.slice(0, 200)}`);
|
|
1452
1379
|
}
|
|
1453
1380
|
if (data.error) {
|
|
1454
|
-
throw new Error(data.error.message);
|
|
1381
|
+
throw new Error(appendDebugInfo(data.error.message, response.status, responseText));
|
|
1455
1382
|
}
|
|
1456
1383
|
const candidate = data.candidates?.[0];
|
|
1457
1384
|
const textPart = candidate?.content?.parts?.find((p) => p.text);
|
|
@@ -1487,7 +1414,11 @@ async function translateToCommand(apiKey, model, userInput, cwd, history = [], r
|
|
|
1487
1414
|
break;
|
|
1488
1415
|
}
|
|
1489
1416
|
}
|
|
1490
|
-
|
|
1417
|
+
const cleaned = cleanCommand(rawCommand);
|
|
1418
|
+
if (!cleaned) {
|
|
1419
|
+
throw new Error("Model returned an empty command. Try another model or rephrase your request.");
|
|
1420
|
+
}
|
|
1421
|
+
return cleaned;
|
|
1491
1422
|
}
|
|
1492
1423
|
|
|
1493
1424
|
// src/lib/config.ts
|
|
@@ -1503,7 +1434,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
1503
1434
|
provider: "opencode-zen",
|
|
1504
1435
|
openrouterApiKey: "",
|
|
1505
1436
|
opencodeZenApiKey: "",
|
|
1506
|
-
defaultModel: "
|
|
1437
|
+
defaultModel: "big-pickle",
|
|
1507
1438
|
safetyLevel: "moderate",
|
|
1508
1439
|
dryRunByDefault: false,
|
|
1509
1440
|
blockedCommands: [
|
package/dist/tui.js
CHANGED
|
@@ -20500,23 +20500,6 @@ var OPENROUTER_MODELS = [
|
|
|
20500
20500
|
contextLength: 128000,
|
|
20501
20501
|
free: true
|
|
20502
20502
|
},
|
|
20503
|
-
{
|
|
20504
|
-
id: "google/gemini-2.5-flash-preview:free",
|
|
20505
|
-
name: "Gemini 2.5 Flash",
|
|
20506
|
-
description: "Free Google model with thinking capabilities",
|
|
20507
|
-
category: "fast",
|
|
20508
|
-
provider: "openrouter",
|
|
20509
|
-
contextLength: 1048576,
|
|
20510
|
-
free: true
|
|
20511
|
-
},
|
|
20512
|
-
{
|
|
20513
|
-
id: "google/gemini-3-flash-preview",
|
|
20514
|
-
name: "Gemini 3 Flash",
|
|
20515
|
-
description: "Google's fastest model, 1M context",
|
|
20516
|
-
category: "fast",
|
|
20517
|
-
provider: "openrouter",
|
|
20518
|
-
contextLength: 1048576
|
|
20519
|
-
},
|
|
20520
20503
|
{
|
|
20521
20504
|
id: "anthropic/claude-haiku-4-5",
|
|
20522
20505
|
name: "Claude Haiku 4.5",
|
|
@@ -20525,14 +20508,6 @@ var OPENROUTER_MODELS = [
|
|
|
20525
20508
|
provider: "openrouter",
|
|
20526
20509
|
contextLength: 200000
|
|
20527
20510
|
},
|
|
20528
|
-
{
|
|
20529
|
-
id: "openai/gpt-5.1-codex-mini",
|
|
20530
|
-
name: "GPT 5.1 Codex Mini",
|
|
20531
|
-
description: "OpenAI's efficient coding model",
|
|
20532
|
-
category: "fast",
|
|
20533
|
-
provider: "openrouter",
|
|
20534
|
-
contextLength: 128000
|
|
20535
|
-
},
|
|
20536
20511
|
{
|
|
20537
20512
|
id: "anthropic/claude-sonnet-4.5",
|
|
20538
20513
|
name: "Claude Sonnet 4.5",
|
|
@@ -20549,22 +20524,6 @@ var OPENROUTER_MODELS = [
|
|
|
20549
20524
|
provider: "openrouter",
|
|
20550
20525
|
contextLength: 200000
|
|
20551
20526
|
},
|
|
20552
|
-
{
|
|
20553
|
-
id: "openai/gpt-5.2-codex",
|
|
20554
|
-
name: "GPT 5.2 Codex",
|
|
20555
|
-
description: "OpenAI's latest coding model",
|
|
20556
|
-
category: "smart",
|
|
20557
|
-
provider: "openrouter",
|
|
20558
|
-
contextLength: 400000
|
|
20559
|
-
},
|
|
20560
|
-
{
|
|
20561
|
-
id: "google/gemini-2.5-pro",
|
|
20562
|
-
name: "Gemini 2.5 Pro",
|
|
20563
|
-
description: "Google's advanced reasoning model",
|
|
20564
|
-
category: "smart",
|
|
20565
|
-
provider: "openrouter",
|
|
20566
|
-
contextLength: 1048576
|
|
20567
|
-
},
|
|
20568
20527
|
{
|
|
20569
20528
|
id: "zhipu/glm-4.7",
|
|
20570
20529
|
name: "GLM 4.7",
|
|
@@ -20591,6 +20550,15 @@ var OPENROUTER_MODELS = [
|
|
|
20591
20550
|
}
|
|
20592
20551
|
];
|
|
20593
20552
|
var OPENCODE_ZEN_MODELS = [
|
|
20553
|
+
{
|
|
20554
|
+
id: "big-pickle",
|
|
20555
|
+
name: "Big Pickle",
|
|
20556
|
+
description: "Free stealth model (limited time)",
|
|
20557
|
+
category: "smart",
|
|
20558
|
+
provider: "opencode-zen",
|
|
20559
|
+
contextLength: 128000,
|
|
20560
|
+
free: true
|
|
20561
|
+
},
|
|
20594
20562
|
{
|
|
20595
20563
|
id: "grok-code",
|
|
20596
20564
|
name: "Grok Code Fast 1",
|
|
@@ -20618,34 +20586,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
20618
20586
|
contextLength: 128000,
|
|
20619
20587
|
free: true
|
|
20620
20588
|
},
|
|
20621
|
-
{
|
|
20622
|
-
id: "big-pickle",
|
|
20623
|
-
name: "Big Pickle",
|
|
20624
|
-
description: "Free stealth model (limited time)",
|
|
20625
|
-
category: "smart",
|
|
20626
|
-
provider: "opencode-zen",
|
|
20627
|
-
contextLength: 128000,
|
|
20628
|
-
free: true
|
|
20629
|
-
},
|
|
20630
|
-
{
|
|
20631
|
-
id: "gpt-5-nano",
|
|
20632
|
-
name: "GPT 5 Nano",
|
|
20633
|
-
description: "Free OpenAI model (temporarily disabled)",
|
|
20634
|
-
category: "fast",
|
|
20635
|
-
provider: "opencode-zen",
|
|
20636
|
-
contextLength: 128000,
|
|
20637
|
-
free: true,
|
|
20638
|
-
disabled: true,
|
|
20639
|
-
disabledReason: "OpenCode Zen API issue"
|
|
20640
|
-
},
|
|
20641
|
-
{
|
|
20642
|
-
id: "gemini-3-flash",
|
|
20643
|
-
name: "Gemini 3 Flash",
|
|
20644
|
-
description: "Google's fastest Gemini model",
|
|
20645
|
-
category: "fast",
|
|
20646
|
-
provider: "opencode-zen",
|
|
20647
|
-
contextLength: 1e6
|
|
20648
|
-
},
|
|
20649
20589
|
{
|
|
20650
20590
|
id: "claude-3-5-haiku",
|
|
20651
20591
|
name: "Claude Haiku 3.5",
|
|
@@ -20654,16 +20594,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
20654
20594
|
provider: "opencode-zen",
|
|
20655
20595
|
contextLength: 200000
|
|
20656
20596
|
},
|
|
20657
|
-
{
|
|
20658
|
-
id: "gpt-5.1-codex-mini",
|
|
20659
|
-
name: "GPT 5.1 Codex Mini",
|
|
20660
|
-
description: "OpenAI's efficient coding model (temporarily disabled)",
|
|
20661
|
-
category: "fast",
|
|
20662
|
-
provider: "opencode-zen",
|
|
20663
|
-
disabled: true,
|
|
20664
|
-
disabledReason: "OpenCode Zen API issue",
|
|
20665
|
-
contextLength: 128000
|
|
20666
|
-
},
|
|
20667
20597
|
{
|
|
20668
20598
|
id: "claude-sonnet-4",
|
|
20669
20599
|
name: "Claude Sonnet 4",
|
|
@@ -20680,34 +20610,6 @@ var OPENCODE_ZEN_MODELS = [
|
|
|
20680
20610
|
provider: "opencode-zen",
|
|
20681
20611
|
contextLength: 200000
|
|
20682
20612
|
},
|
|
20683
|
-
{
|
|
20684
|
-
id: "gpt-5.1-codex",
|
|
20685
|
-
name: "GPT 5.1 Codex",
|
|
20686
|
-
description: "OpenAI's coding-optimized model (temporarily disabled)",
|
|
20687
|
-
category: "smart",
|
|
20688
|
-
provider: "opencode-zen",
|
|
20689
|
-
contextLength: 128000,
|
|
20690
|
-
disabled: true,
|
|
20691
|
-
disabledReason: "OpenCode Zen API issue"
|
|
20692
|
-
},
|
|
20693
|
-
{
|
|
20694
|
-
id: "gpt-5.2-codex",
|
|
20695
|
-
name: "GPT 5.2 Codex",
|
|
20696
|
-
description: "OpenAI's latest coding model (temporarily disabled)",
|
|
20697
|
-
category: "smart",
|
|
20698
|
-
provider: "opencode-zen",
|
|
20699
|
-
contextLength: 128000,
|
|
20700
|
-
disabled: true,
|
|
20701
|
-
disabledReason: "OpenCode Zen API issue"
|
|
20702
|
-
},
|
|
20703
|
-
{
|
|
20704
|
-
id: "gemini-3-pro",
|
|
20705
|
-
name: "Gemini 3 Pro",
|
|
20706
|
-
description: "Google's advanced Gemini model",
|
|
20707
|
-
category: "smart",
|
|
20708
|
-
provider: "opencode-zen",
|
|
20709
|
-
contextLength: 1e6
|
|
20710
|
-
},
|
|
20711
20613
|
{
|
|
20712
20614
|
id: "kimi-k2",
|
|
20713
20615
|
name: "Kimi K2",
|
|
@@ -21070,7 +20972,7 @@ var DEFAULT_CONFIG = {
|
|
|
21070
20972
|
provider: "opencode-zen",
|
|
21071
20973
|
openrouterApiKey: "",
|
|
21072
20974
|
opencodeZenApiKey: "",
|
|
21073
|
-
defaultModel: "
|
|
20975
|
+
defaultModel: "big-pickle",
|
|
21074
20976
|
safetyLevel: "moderate",
|
|
21075
20977
|
dryRunByDefault: false,
|
|
21076
20978
|
blockedCommands: [
|
|
@@ -21738,6 +21640,13 @@ async function callOpenRouter(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21738
21640
|
return data.choices[0]?.message?.content?.trim() || "";
|
|
21739
21641
|
}
|
|
21740
21642
|
var DEBUG_API = process.env.DEBUG_API === "1";
|
|
21643
|
+
function appendDebugInfo(message, status, responseText) {
|
|
21644
|
+
if (!DEBUG_API)
|
|
21645
|
+
return message;
|
|
21646
|
+
const snippet = responseText.slice(0, 1000);
|
|
21647
|
+
return `${message}
|
|
21648
|
+
[DEBUG] status=${status} response=${snippet}`;
|
|
21649
|
+
}
|
|
21741
21650
|
async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput) {
|
|
21742
21651
|
if (DEBUG_API) {
|
|
21743
21652
|
console.error(`[DEBUG] Calling OpenAI Responses API`);
|
|
@@ -21755,7 +21664,8 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
21755
21664
|
instructions: systemPrompt,
|
|
21756
21665
|
input: userInput,
|
|
21757
21666
|
max_output_tokens: 500,
|
|
21758
|
-
temperature: 0.1
|
|
21667
|
+
temperature: 0.1,
|
|
21668
|
+
stream: false
|
|
21759
21669
|
})
|
|
21760
21670
|
});
|
|
21761
21671
|
const responseText = await response.text();
|
|
@@ -21773,7 +21683,7 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
21773
21683
|
errorMessage = errorData.message;
|
|
21774
21684
|
}
|
|
21775
21685
|
} catch {}
|
|
21776
|
-
throw new Error(errorMessage);
|
|
21686
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
21777
21687
|
}
|
|
21778
21688
|
let data;
|
|
21779
21689
|
try {
|
|
@@ -21782,7 +21692,8 @@ async function callZenOpenAIResponses(apiKey, modelId, systemPrompt, userInput)
|
|
|
21782
21692
|
throw new Error(`Invalid JSON response: ${responseText.slice(0, 200)}`);
|
|
21783
21693
|
}
|
|
21784
21694
|
if (data.error) {
|
|
21785
|
-
|
|
21695
|
+
const errorMessage = data.error.message || data.error;
|
|
21696
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
21786
21697
|
}
|
|
21787
21698
|
if (typeof data.output_text === "string") {
|
|
21788
21699
|
return data.output_text.trim();
|
|
@@ -21837,7 +21748,7 @@ async function callZenAnthropic(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21837
21748
|
errorMessage = errorData.error.message;
|
|
21838
21749
|
}
|
|
21839
21750
|
} catch {}
|
|
21840
|
-
throw new Error(errorMessage);
|
|
21751
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, errorText));
|
|
21841
21752
|
}
|
|
21842
21753
|
const data = await response.json();
|
|
21843
21754
|
if (data.error) {
|
|
@@ -21876,21 +21787,38 @@ async function callZenOpenAICompatible(apiKey, modelId, systemPrompt, userInput)
|
|
|
21876
21787
|
errorMessage = errorData.error.message;
|
|
21877
21788
|
}
|
|
21878
21789
|
} catch {}
|
|
21879
|
-
throw new Error(errorMessage);
|
|
21790
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, errorText));
|
|
21880
21791
|
}
|
|
21881
21792
|
const data = await response.json();
|
|
21882
21793
|
if (data.error) {
|
|
21883
21794
|
throw new Error(data.error.message);
|
|
21884
21795
|
}
|
|
21885
|
-
|
|
21796
|
+
const choice = data.choices?.[0];
|
|
21797
|
+
const messageContent = choice?.message?.content;
|
|
21798
|
+
if (typeof messageContent === "string") {
|
|
21799
|
+
return messageContent.trim();
|
|
21800
|
+
}
|
|
21801
|
+
if (Array.isArray(messageContent)) {
|
|
21802
|
+
const textBlocks = messageContent.map((block) => typeof block === "string" ? block : block?.text).filter(Boolean);
|
|
21803
|
+
if (textBlocks.length > 0) {
|
|
21804
|
+
return textBlocks.join("").trim();
|
|
21805
|
+
}
|
|
21806
|
+
}
|
|
21807
|
+
if (typeof choice?.text === "string") {
|
|
21808
|
+
return choice.text.trim();
|
|
21809
|
+
}
|
|
21810
|
+
return "";
|
|
21886
21811
|
}
|
|
21887
21812
|
async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
21888
|
-
const endpoint = `https://opencode.ai/zen/v1/models/${modelId}
|
|
21813
|
+
const endpoint = `https://opencode.ai/zen/v1/models/${modelId}`;
|
|
21889
21814
|
if (DEBUG_API) {
|
|
21890
21815
|
console.error(`[DEBUG] Calling Google Gemini API`);
|
|
21891
21816
|
console.error(`[DEBUG] Model: ${modelId}`);
|
|
21892
21817
|
console.error(`[DEBUG] Endpoint: ${endpoint}`);
|
|
21893
21818
|
}
|
|
21819
|
+
const prompt = `${systemPrompt}
|
|
21820
|
+
|
|
21821
|
+
User request: ${userInput}`;
|
|
21894
21822
|
const response = await fetch(endpoint, {
|
|
21895
21823
|
method: "POST",
|
|
21896
21824
|
headers: {
|
|
@@ -21899,9 +21827,8 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21899
21827
|
},
|
|
21900
21828
|
body: JSON.stringify({
|
|
21901
21829
|
contents: [
|
|
21902
|
-
{ role: "user", parts: [{ text:
|
|
21830
|
+
{ role: "user", parts: [{ text: prompt }] }
|
|
21903
21831
|
],
|
|
21904
|
-
systemInstruction: { parts: [{ text: systemPrompt }] },
|
|
21905
21832
|
generationConfig: {
|
|
21906
21833
|
maxOutputTokens: 500,
|
|
21907
21834
|
temperature: 0.1
|
|
@@ -21921,7 +21848,7 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21921
21848
|
errorMessage = errorData.error.message;
|
|
21922
21849
|
}
|
|
21923
21850
|
} catch {}
|
|
21924
|
-
throw new Error(errorMessage);
|
|
21851
|
+
throw new Error(appendDebugInfo(errorMessage, response.status, responseText));
|
|
21925
21852
|
}
|
|
21926
21853
|
let data;
|
|
21927
21854
|
try {
|
|
@@ -21930,7 +21857,7 @@ async function callZenGoogle(apiKey, modelId, systemPrompt, userInput) {
|
|
|
21930
21857
|
throw new Error(`Invalid JSON response: ${responseText.slice(0, 200)}`);
|
|
21931
21858
|
}
|
|
21932
21859
|
if (data.error) {
|
|
21933
|
-
throw new Error(data.error.message);
|
|
21860
|
+
throw new Error(appendDebugInfo(data.error.message, response.status, responseText));
|
|
21934
21861
|
}
|
|
21935
21862
|
const candidate = data.candidates?.[0];
|
|
21936
21863
|
const textPart = candidate?.content?.parts?.find((p) => p.text);
|
|
@@ -21966,7 +21893,11 @@ async function translateToCommand(apiKey, model, userInput, cwd, history = [], r
|
|
|
21966
21893
|
break;
|
|
21967
21894
|
}
|
|
21968
21895
|
}
|
|
21969
|
-
|
|
21896
|
+
const cleaned = cleanCommand(rawCommand);
|
|
21897
|
+
if (!cleaned) {
|
|
21898
|
+
throw new Error("Model returned an empty command. Try another model or rephrase your request.");
|
|
21899
|
+
}
|
|
21900
|
+
return cleaned;
|
|
21970
21901
|
}
|
|
21971
21902
|
|
|
21972
21903
|
// src/lib/theme.ts
|
|
@@ -22319,7 +22250,7 @@ Enter your API key below:`,
|
|
|
22319
22250
|
const freeNote = new TextRenderable(renderer, {
|
|
22320
22251
|
id: "free-note",
|
|
22321
22252
|
content: t`
|
|
22322
|
-
${fg("#22c55e")("Tip:")} OpenCode Zen has free models like
|
|
22253
|
+
${fg("#22c55e")("Tip:")} OpenCode Zen has free models like Big Pickle and GLM 4.7!`,
|
|
22323
22254
|
marginTop: 1
|
|
22324
22255
|
});
|
|
22325
22256
|
container.add(freeNote);
|
|
@@ -22335,7 +22266,7 @@ ${fg("#64748b")("Press Enter to save | Ctrl+C to exit")}`,
|
|
|
22335
22266
|
if (value.trim()) {
|
|
22336
22267
|
setApiKey(provider, value.trim());
|
|
22337
22268
|
if (provider === "opencode-zen") {
|
|
22338
|
-
currentModel = OPENCODE_ZEN_MODELS.find((m) => m.id === "
|
|
22269
|
+
currentModel = OPENCODE_ZEN_MODELS.find((m) => m.id === "big-pickle") || OPENCODE_ZEN_MODELS[0];
|
|
22339
22270
|
} else {
|
|
22340
22271
|
currentModel = OPENROUTER_MODELS[0];
|
|
22341
22272
|
}
|
|
@@ -22371,11 +22302,6 @@ function createMainUI() {
|
|
|
22371
22302
|
flexGrow: 1
|
|
22372
22303
|
});
|
|
22373
22304
|
headerRow.add(headerText);
|
|
22374
|
-
const modelBadge = new TextRenderable(renderer, {
|
|
22375
|
-
id: "model-badge",
|
|
22376
|
-
content: getModelDisplay()
|
|
22377
|
-
});
|
|
22378
|
-
headerRow.add(modelBadge);
|
|
22379
22305
|
statusBarText = new TextRenderable(renderer, {
|
|
22380
22306
|
id: "status-bar-text",
|
|
22381
22307
|
content: getStatusBarContent(),
|
|
@@ -22458,14 +22384,14 @@ function getStatusBarContent() {
|
|
|
22458
22384
|
function getHelpBarContent() {
|
|
22459
22385
|
const theme = getTheme();
|
|
22460
22386
|
if (awaitingConfirmation) {
|
|
22461
|
-
return t`${fg(theme.colors.warning)("
|
|
22387
|
+
return t`${fg(theme.colors.warning)(">>> Press Enter to execute command <<<")} ${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")}`;
|
|
22462
22388
|
}
|
|
22463
22389
|
return t`${fg(theme.colors.textMuted)("Ctrl+X")} ${fg(theme.colors.primary)("P")}${fg(theme.colors.textMuted)(" Palette")} ${fg(theme.colors.primary)("M")}${fg(theme.colors.textMuted)(" Model")} ${fg(theme.colors.primary)("T")}${fg(theme.colors.textMuted)(" Theme")} ${fg(theme.colors.primary)("D")}${fg(theme.colors.textMuted)(" Dry-run")} ${fg(theme.colors.primary)("?")}${fg(theme.colors.textMuted)(" Help")}`;
|
|
22464
22390
|
}
|
|
22465
22391
|
function getWelcomeMessage() {
|
|
22466
22392
|
const providerName = config.provider === "opencode-zen" ? "OpenCode Zen" : "OpenRouter";
|
|
22467
22393
|
const freeNote = config.provider === "opencode-zen" ? `
|
|
22468
|
-
Free models:
|
|
22394
|
+
Free models: big-pickle, glm-4.7-free` : "";
|
|
22469
22395
|
return `Ready. Using ${providerName}.${freeNote}
|
|
22470
22396
|
Type what you want to do, or press Ctrl+X P for command palette.`;
|
|
22471
22397
|
}
|
|
@@ -22580,14 +22506,16 @@ function createAssistantMessageRenderable(msg, theme) {
|
|
|
22580
22506
|
if (isSelected && !msg.executed) {
|
|
22581
22507
|
const actionsText = new TextRenderable(renderer, {
|
|
22582
22508
|
id: `msg-${msg.id}-actions`,
|
|
22583
|
-
content: t`${fg(theme.colors.warning)("
|
|
22509
|
+
content: t`${fg(theme.colors.warning)("Press Enter to run")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.primary)("[c]")} ${fg(theme.colors.textMuted)("Copy")} ${fg(theme.colors.primary)("[e]")} ${fg(theme.colors.textMuted)("Edit")} ${fg(theme.colors.error)("[Esc]")} ${fg(theme.colors.textMuted)("Cancel")}`
|
|
22584
22510
|
});
|
|
22585
22511
|
card.add(actionsText);
|
|
22586
22512
|
}
|
|
22587
22513
|
if (msg.executed) {
|
|
22514
|
+
const wasAutoRun = !msg.safety?.isDangerous;
|
|
22515
|
+
const execLabel = wasAutoRun ? "Auto-executed (safe)" : "Executed";
|
|
22588
22516
|
const execText = new TextRenderable(renderer, {
|
|
22589
22517
|
id: `msg-${msg.id}-exec`,
|
|
22590
|
-
content: t`${fg(theme.colors.success)("
|
|
22518
|
+
content: t`${fg(theme.colors.success)("✓")} ${fg(theme.colors.success)(execLabel)}`
|
|
22591
22519
|
});
|
|
22592
22520
|
card.add(execText);
|
|
22593
22521
|
}
|
|
@@ -22702,13 +22630,6 @@ function toggleLastResultExpand() {
|
|
|
22702
22630
|
const lastResult = resultMessages[resultMessages.length - 1];
|
|
22703
22631
|
toggleResultExpand(lastResult.id);
|
|
22704
22632
|
}
|
|
22705
|
-
function getModelDisplay() {
|
|
22706
|
-
const theme = getTheme();
|
|
22707
|
-
const categoryColor = currentModel.category === "fast" ? theme.colors.success : currentModel.category === "smart" ? theme.colors.primary : theme.colors.secondary;
|
|
22708
|
-
const providerBadge = currentModel.provider === "opencode-zen" ? fg(theme.colors.accent)("[zen]") : fg(theme.colors.warning)("[or]");
|
|
22709
|
-
const freeBadge = currentModel.free ? fg(theme.colors.success)(" FREE") : "";
|
|
22710
|
-
return t`${providerBadge} ${fg(categoryColor)(currentModel.name)}${freeBadge}`;
|
|
22711
|
-
}
|
|
22712
22633
|
function refreshThemeColors() {
|
|
22713
22634
|
const theme = getTheme();
|
|
22714
22635
|
renderer.setBackgroundColor(theme.colors.background);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@austinthesing/magic-shell",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Natural language to terminal commands with safety features. Supports OpenCode Zen (with free models) and OpenRouter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|