codeshark-cli 0.1.7 → 0.1.8

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/PRIVACY.md CHANGED
@@ -18,7 +18,7 @@ or project files that you send to an AI provider.
18
18
  When you use the shared gateway, your prompts, selected tool definitions, and
19
19
  relevant conversation or file content are sent to the gateway and then to one
20
20
  or more upstream providers selected by the gateway, including OpenRouter,
21
- NVIDIA, Google, or
21
+ Google, or
22
22
  other providers selected by that service. When you use your own provider key,
23
23
  requests go to the provider configured by you.
24
24
 
package/README.md CHANGED
@@ -76,7 +76,7 @@ Inside a conversation:
76
76
  /quit End the session
77
77
  ```
78
78
 
79
- For example, `/model deepseek-v4-flash` switches to DeepSeek-V4 Flash. Your selection is saved locally.
79
+ For example, `/model glm` switches to GLM 5.3 Flash Think Search. Your selection is saved locally.
80
80
 
81
81
  ## Models
82
82
 
@@ -84,14 +84,10 @@ The catalog is checked at startup, and unavailable models are marked. These cont
84
84
 
85
85
  | Model | Context | Selection command |
86
86
  | --- | --- | --- |
87
- | Chat-GPT 5.6 Sol | 400K | `/model gpt-5.6-sol` |
88
- | DeepSeek-V4 Flash | 256K | `/model deepseek-v4-flash` |
89
- | MiniMax M3 | 128K | `/model minimax-m3` |
90
- | **GLM 5.3 Flash Think Search — default** | **1M** | `/model glm-5.3-flash-think-search` |
91
- | Gemini 3.6 Flash | 1M | `/model gemini-3.6-flash` |
92
- | Sarvam 30B | 128K | `/model sarvam-30b` |
93
- | GPT-OSS 120B | 128K | `/model gpt-oss-120b` |
94
- | Nemotron 3 Ultra 550B A55B | 256K | `/model nemotron-3-ultra-550b-a55b` |
87
+ | **GLM 5.3 Flash Think Search — default** | **1M** | `/model glm` |
88
+ | Gemini 3.6 Flash | 1M | `/model gemini-3.6` |
89
+ | Nemotron 3 Ultra 550B A55B | 256K | `/model nemotron` |
90
+ | MiniMax M2.7 | 128K | `/model minimax` |
95
91
 
96
92
  ## Connection and privacy
97
93
 
@@ -122,4 +118,4 @@ npm test
122
118
 
123
119
  ## Provider details
124
120
 
125
- The current free catalog uses UnoRouter through an OpenAI-compatible connection. Configure your own key with `codeshark setup`. Additional adapters support OpenRouter, NVIDIA NIM, Gemini, and local Ollama.
121
+ The current free catalog uses UnoRouter through an OpenAI-compatible connection. Configure your own key with `codeshark setup`. Additional adapters support OpenRouter, Gemini, and local Ollama.
package/dist/config.js CHANGED
@@ -27,14 +27,14 @@ export function loadConfig() {
27
27
  const cfg = parsed;
28
28
  if (cfg.maxIterations !== undefined && (!Number.isSafeInteger(cfg.maxIterations) || cfg.maxIterations < 1))
29
29
  delete cfg.maxIterations;
30
- const strings = ["model", "systemPrompt", "openrouterApiKey", "openrouterBaseUrl", "unorouterApiKey", "unorouterBaseUrl", "nvidiaApiKey", "nvidiaBaseUrl", "geminiApiKey", "geminiBaseUrl", "gatewayUrl", "gatewayKey", "ollamaBaseUrl", "ollamaModel"];
30
+ const strings = ["model", "systemPrompt", "openrouterApiKey", "openrouterBaseUrl", "unorouterApiKey", "unorouterBaseUrl", "geminiApiKey", "geminiBaseUrl", "gatewayUrl", "gatewayKey", "ollamaBaseUrl", "ollamaModel"];
31
31
  for (const key of strings)
32
32
  if (cfg[key] !== undefined && typeof cfg[key] !== "string")
33
33
  delete cfg[key];
34
34
  for (const key of ["termsAccepted", "setupCompleted"])
35
35
  if (typeof cfg[key] !== "boolean")
36
36
  delete cfg[key];
37
- if (cfg.provider && !["gateway", "openrouter", "nvidia", "gemini", "ollama", "unorouter"].includes(cfg.provider))
37
+ if (cfg.provider && !["gateway", "openrouter", "gemini", "ollama", "unorouter"].includes(cfg.provider))
38
38
  delete cfg.provider;
39
39
  // Self-heal: drop a saved model that a provider retired so the current default applies.
40
40
  if (cfg.model && isRetiredModel(cfg.model))
@@ -96,8 +96,6 @@ export function activeProvider(cfg) {
96
96
  return "unorouter";
97
97
  if (m.endsWith(":free") || m.startsWith("openrouter/"))
98
98
  return "openrouter";
99
- if (m.startsWith("moonshotai/") || m.startsWith("deepseek-ai/"))
100
- return "nvidia";
101
99
  return "gateway";
102
100
  }
103
101
  /** Effective model for a provider, honoring env overrides and config. */
@@ -120,12 +118,6 @@ export function effectiveModel(cfg, provider) {
120
118
  return process.env.UNOROUTER_MODEL ?? DEFAULT_MODEL;
121
119
  if (provider === "openrouter")
122
120
  return DEFAULT_OPENROUTER_MODEL;
123
- if (provider === "nvidia") {
124
- const raw = activeModelId(cfg);
125
- if (raw.startsWith("moonshotai/") || raw.startsWith("deepseek-ai/"))
126
- return raw;
127
- return "moonshotai/kimi-k3";
128
- }
129
121
  return DEFAULT_MODEL;
130
122
  }
131
123
  export function envApiKey(provider) {
@@ -134,8 +126,6 @@ export function envApiKey(provider) {
134
126
  return process.env.OPENROUTER_API_KEY;
135
127
  case "unorouter":
136
128
  return process.env.UNOROUTER_API_KEY;
137
- case "nvidia":
138
- return process.env.NVIDIA_API_KEY ?? process.env.NVIDIA_NIM_API_KEY;
139
129
  case "gemini":
140
130
  return process.env.GEMINI_API_KEY;
141
131
  default:
package/dist/index.js CHANGED
@@ -216,10 +216,9 @@ async function main() {
216
216
  // First run: let the user pick between the shared gateway, their own
217
217
  // API key (recommended), or local Ollama — the same flow as `codeshark setup`.
218
218
  const hasProviderSetup = Boolean(cfg.provider) ||
219
- Boolean(cfg.unorouterApiKey || cfg.openrouterApiKey || cfg.nvidiaApiKey || cfg.geminiApiKey) ||
219
+ Boolean(cfg.unorouterApiKey || cfg.openrouterApiKey || cfg.geminiApiKey) ||
220
220
  Boolean(process.env.UNOROUTER_API_KEY ||
221
221
  process.env.OPENROUTER_API_KEY ||
222
- process.env.NVIDIA_API_KEY ||
223
222
  process.env.GEMINI_API_KEY);
224
223
  const setupCompleted = cfg.setupCompleted ?? hasProviderSetup;
225
224
  if (!setupCompleted) {
package/dist/keysPage.js CHANGED
@@ -114,7 +114,7 @@ function loginPage(message = "") {
114
114
  function vaultPage(session) {
115
115
  const cfg = loadConfig();
116
116
  const secretInput = (id, label, placeholder) => `<label for="${id}">${label}</label><input id="${id}" name="${id}" type="password" value="" placeholder="${placeholder}" autocomplete="new-password" spellcheck="false"><label class="small"><input type="checkbox" name="clear_${id}" value="1" style="width:auto;margin-right:8px"> Clear this saved key</label>`;
117
- return page("API keys", `<h1>CodeShark key vault</h1><p>Unlocked locally. Values are saved to <code>${htmlEscape(configPath())}</code>. Keep this page on your own computer.</p><div class="card"><form method="post" action="/save"><input type="hidden" name="csrf" value="${htmlEscape(session.csrf)}"><h2>Provider keys</h2>${secretInput("unorouterApiKey", "Primary model API key", "paste a replacement (shown once)…")}${secretInput("openrouterApiKey", "OpenRouter API key", "paste a replacement: sk-or-v1-…")}${secretInput("nvidiaApiKey", "NVIDIA NIM API key", "paste a replacement: nvapi-…")}${secretInput("geminiApiKey", "Gemini API key", "paste a replacement: AIza…")}<p class="small">Saved keys are never placed in this page's HTML. Leave a field blank to keep its current value, or check Clear to remove it.</p><button>Save keys</button></form></div><div class="card"><h2>Current status</h2><p class="key">Primary model API: ${htmlEscape(mask(cfg.unorouterApiKey) || "not set")}</p><p class="key">OpenRouter: ${htmlEscape(mask(cfg.openrouterApiKey) || "not set")}</p><p class="key">NVIDIA: ${htmlEscape(mask(cfg.nvidiaApiKey) || "not set")}</p><p class="key">Gemini: ${htmlEscape(mask(cfg.geminiApiKey) || "not set")}</p><p class="hint">Your keys are never printed to the terminal by CodeShark.</p><form method="post" action="/logout"><input type="hidden" name="csrf" value="${htmlEscape(session.csrf)}"><button class="danger">Lock vault</button></form></div>`);
117
+ return page("API keys", `<h1>CodeShark key vault</h1><p>Unlocked locally. Values are saved to <code>${htmlEscape(configPath())}</code>. Keep this page on your own computer.</p><div class="card"><form method="post" action="/save"><input type="hidden" name="csrf" value="${htmlEscape(session.csrf)}"><h2>Provider keys</h2>${secretInput("unorouterApiKey", "Primary model API key", "paste a replacement (shown once)…")}${secretInput("openrouterApiKey", "OpenRouter API key", "paste a replacement: sk-or-v1-…")}${secretInput("geminiApiKey", "Gemini API key", "paste a replacement: AIza…")}<p class="small">Saved keys are never placed in this page's HTML. Leave a field blank to keep its current value, or check Clear to remove it.</p><button>Save keys</button></form></div><div class="card"><h2>Current status</h2><p class="key">Primary model API: ${htmlEscape(mask(cfg.unorouterApiKey) || "not set")}</p><p class="key">OpenRouter: ${htmlEscape(mask(cfg.openrouterApiKey) || "not set")}</p><p class="key">Gemini: ${htmlEscape(mask(cfg.geminiApiKey) || "not set")}</p><p class="hint">Your keys are never printed to the terminal by CodeShark.</p><form method="post" action="/logout"><input type="hidden" name="csrf" value="${htmlEscape(session.csrf)}"><button class="danger">Lock vault</button></form></div>`);
118
118
  }
119
119
  function parseBody(req) {
120
120
  return new Promise((resolve, reject) => {
@@ -175,7 +175,7 @@ async function handle(req, res) {
175
175
  return;
176
176
  }
177
177
  const cfg = loadConfig();
178
- for (const field of ["unorouterApiKey", "openrouterApiKey", "nvidiaApiKey", "geminiApiKey"]) {
178
+ for (const field of ["unorouterApiKey", "openrouterApiKey", "geminiApiKey"]) {
179
179
  const value = body[field]?.trim();
180
180
  if (body[`clear_${field}`] === "1")
181
181
  delete cfg[field];
@@ -2,7 +2,7 @@ import { DEFAULT_GATEWAY_URL, envApiKey } from "./config.js";
2
2
  import { MODELS } from "./models.js";
3
3
  const statuses = new Map();
4
4
  const reasons = new Map();
5
- const TIMEOUT_MS = 15_000;
5
+ const TIMEOUT_MS = 30_000; // slow-but-alive lanes are common on free tiers — don't read slowness as death
6
6
  /** Match the gateway's per-IP inflight cap so probes never queue behind themselves. */
7
7
  const MAX_CONCURRENT_CHECKS = 2;
8
8
  export function modelAvailability(modelId) {
package/dist/models.js CHANGED
@@ -1,28 +1,4 @@
1
1
  export const MODELS = [
2
- {
3
- id: "unorouter/gpt-5.6-sol",
4
- label: "Chat-GPT 5.6 Sol",
5
- provider: "unorouter",
6
- model: "gpt-5.6-sol:free",
7
- context: "400K",
8
- notes: "Frontier reasoning model when available.",
9
- },
10
- {
11
- id: "unorouter/deepseek-v4-flash",
12
- label: "DeepSeek-V4 Flash",
13
- provider: "unorouter",
14
- model: "deepseek-v4-flash:free",
15
- context: "256K",
16
- notes: "Fast coding model when available.",
17
- },
18
- {
19
- id: "unorouter/minimax-m3",
20
- label: "MiniMax M3",
21
- provider: "unorouter",
22
- model: "minimax-m3:free",
23
- context: "128K",
24
- notes: "Fast general-purpose coding and reasoning.",
25
- },
26
2
  {
27
3
  id: "unorouter/glm-5.3-flash-think-search",
28
4
  label: "GLM 5.3 Flash Think Search",
@@ -39,22 +15,6 @@ export const MODELS = [
39
15
  context: "1M",
40
16
  notes: "Fast long-context model for large codebases.",
41
17
  },
42
- {
43
- id: "unorouter/sarvam-30b",
44
- label: "Sarvam 30B",
45
- provider: "unorouter",
46
- model: "sarvam-30b:free",
47
- context: "128K",
48
- notes: "Open coding model from Sarvam AI.",
49
- },
50
- {
51
- id: "unorouter/gpt-oss-120b",
52
- label: "GPT-OSS 120B",
53
- provider: "unorouter",
54
- model: "gpt-oss-120b:free",
55
- context: "128K",
56
- notes: "Large open-weight model for demanding coding tasks.",
57
- },
58
18
  {
59
19
  id: "unorouter/nemotron-3-ultra-550b-a55b",
60
20
  label: "Nemotron 3 Ultra 550B A55B",
@@ -63,11 +23,24 @@ export const MODELS = [
63
23
  context: "256K",
64
24
  notes: "Large-scale open model for deep reasoning.",
65
25
  },
26
+ {
27
+ id: "unorouter/minimax-m2.7",
28
+ label: "MiniMax M2.7",
29
+ provider: "unorouter",
30
+ model: "minimax-m2.7:free",
31
+ context: "128K",
32
+ notes: "Fast general-purpose coding and reasoning.",
33
+ },
66
34
  ];
67
35
  export const RETIRED_MODELS = [
68
36
  { id: "gemini/gemini-3.8-flash", label: "Gemini 3.8 Flash", provider: "gemini", model: "gemini-3.8-flash", context: "-", notes: "Removed from the catalog.", available: false },
69
37
  { id: "unorouter/glm-5.3-flash-thinking", label: "GLM 5.3 Flash Thinking", provider: "unorouter", model: "glm-5.3-flash-thinking:free", context: "-", notes: "Removed from UnoRouter.", available: false },
70
38
  { id: "unorouter/kimi-k3", label: "Kimi-K3", provider: "unorouter", model: "kimi-k3:free", context: "-", notes: "Removed from UnoRouter.", available: false },
39
+ { id: "unorouter/gpt-5.6-sol", label: "Chat-GPT 5.6 Sol", provider: "unorouter", model: "gpt-5.6-sol:free", context: "-", notes: "Removed from the catalog.", available: false },
40
+ { id: "unorouter/deepseek-v4-flash", label: "DeepSeek-V4 Flash", provider: "unorouter", model: "deepseek-v4-flash:free", context: "-", notes: "Removed from the catalog.", available: false },
41
+ { id: "unorouter/minimax-m3", label: "MiniMax M3", provider: "unorouter", model: "minimax-m3:free", context: "-", notes: "Replaced by MiniMax M2.7.", available: false },
42
+ { id: "unorouter/sarvam-30b", label: "Sarvam 30B", provider: "unorouter", model: "sarvam-30b:free", context: "-", notes: "Shut down by the provider.", available: false },
43
+ { id: "unorouter/gpt-oss-120b", label: "GPT-OSS 120B", provider: "unorouter", model: "gpt-oss-120b:free", context: "-", notes: "Removed from the catalog.", available: false },
71
44
  ];
72
45
  export const DEFAULT_MODEL_ID = "unorouter/glm-5.3-flash-think-search";
73
46
  export function listModels() {
@@ -1,7 +1,6 @@
1
1
  import { activeModelId, activeProvider, envApiKey } from "../config.js";
2
2
  import { createGatewayClient } from "./gateway.js";
3
3
  import { createGeminiClient } from "./gemini.js";
4
- import { createNvidiaClient } from "./nvidia.js";
5
4
  import { createOllamaClient } from "./ollama.js";
6
5
  import { createOpenRouterClient } from "./openrouter.js";
7
6
  import { createUnoRouterClient } from "./unorouter.js";
@@ -40,15 +39,6 @@ export function resolveClients(cfg, debug) {
40
39
  add(createGatewayClient(cfg));
41
40
  break;
42
41
  }
43
- case "nvidia": {
44
- const key = cfg.nvidiaApiKey ?? envApiKey("nvidia");
45
- // NVIDIA-hosted models can't run through the OpenRouter gateway.
46
- if (key)
47
- add(createNvidiaClient(cfg, key));
48
- else
49
- debug?.("NVIDIA model selected but no NVIDIA_API_KEY found — run `codeshark setup`.");
50
- break;
51
- }
52
42
  case "gemini": {
53
43
  const key = cfg.geminiApiKey ?? envApiKey("gemini");
54
44
  if (key)
@@ -80,11 +70,6 @@ export function resolveClients(cfg, debug) {
80
70
  if (key)
81
71
  add(createUnoRouterClient(cfg, key));
82
72
  }
83
- if (!has("nvidia")) {
84
- const key = cfg.nvidiaApiKey ?? envApiKey("nvidia");
85
- if (key)
86
- add(createNvidiaClient(cfg, key));
87
- }
88
73
  if (!has("gemini")) {
89
74
  const key = cfg.geminiApiKey ?? envApiKey("gemini");
90
75
  if (key)
package/dist/repl.js CHANGED
@@ -29,7 +29,7 @@ function printHelp() {
29
29
  bold(" CodeShark commands"),
30
30
  dim(" /help show this help"),
31
31
  dim(" /model show the active model and the full catalog"),
32
- dim(" /model <name> switch model, e.g. /model glm or /model deepseek"),
32
+ dim(" /model <name> switch model, e.g. /model glm or /model minimax"),
33
33
  dim(" /keys open the password-protected local API key page"),
34
34
  dim(" /key-status show masked key status in the terminal"),
35
35
  dim(" /setup guided setup wizard (providers / keys)"),
@@ -60,7 +60,7 @@ export function printModelInfo() {
60
60
  }
61
61
  console.log("");
62
62
  console.log(dim(" Switch with: /model <name>"));
63
- console.log(dim(" Names: gpt, deepseek, minimax, glm, gemini-3.6, sarvam, gpt-oss, nemotron"));
63
+ console.log(dim(" Names: glm, gemini-3.6, nemotron, minimax"));
64
64
  console.log("");
65
65
  }
66
66
  export function switchModel(query) {
@@ -102,11 +102,9 @@ function printKeys() {
102
102
  console.log(bold(" API keys"));
103
103
  const ur = Boolean(cfg.unorouterApiKey ?? process.env.UNOROUTER_API_KEY);
104
104
  const or = Boolean(cfg.openrouterApiKey ?? process.env.OPENROUTER_API_KEY);
105
- const nv = Boolean(cfg.nvidiaApiKey ?? process.env.NVIDIA_API_KEY);
106
105
  const gm = Boolean(cfg.geminiApiKey ?? process.env.GEMINI_API_KEY);
107
106
  console.log(` ${ur ? hex("#4ade80", "✓") : dim("○")} Model API ${ur ? dim("(configured)") : dim("(not set)")} ${dim("key: shown once")}`);
108
107
  console.log(` ${or ? hex("#4ade80", "✓") : dim("○")} OpenRouter ${or ? dim("(configured)") : dim("(not set)")} → https://openrouter.ai/keys ${dim("key: sk-or-v1-…")}`);
109
- console.log(` ${nv ? hex("#4ade80", "✓") : dim("○")} NVIDIA NIM ${nv ? dim("(configured)") : dim("(not set)")} → https://build.nvidia.com ${dim("key: nvapi-…")}`);
110
108
  console.log(` ${gm ? hex("#4ade80", "✓") : dim("○")} Google AI Studio ${gm ? dim("(configured)") : dim("(not set)")} → https://aistudio.google.com/apikey ${dim("key: AIza…")}`);
111
109
  console.log("");
112
110
  console.log(dim(" Add one: run /setup, or paste it into ~/.codeshark.json like:"));
package/dist/setup.js CHANGED
@@ -5,7 +5,6 @@ import { bold, dim, hex } from "./ansi.js";
5
5
  import { DEFAULT_GEMINI_MODEL, configPath, hasApiKey, loadConfig, saveConfig } from "./config.js";
6
6
  import { createUnoRouterClient } from "./provider/unorouter.js";
7
7
  import { createGeminiClient } from "./provider/gemini.js";
8
- import { createNvidiaClient } from "./provider/nvidia.js";
9
8
  import { createOpenRouterClient } from "./provider/openrouter.js";
10
9
  import { ollamaAvailable } from "./provider/ollama.js";
11
10
  import { MODELS } from "./models.js";
@@ -130,13 +129,12 @@ export async function runSetupFlow(cfg, rl, opts = {}) {
130
129
  }
131
130
  // Choice 2 — choose which provider key to configure.
132
131
  console.log(bold(" Choose an API provider"));
133
- console.log(dim(" [1] Primary model API — eight free catalog models"));
132
+ console.log(dim(" [1] Primary model API — four free catalog models"));
134
133
  console.log(dim(" [2] Gemini API"));
135
- console.log(dim(" [3] NVIDIA NIM"));
136
- console.log(dim(" [4] OpenRouter"));
137
- console.log(dim(" [5] Cancel"));
138
- const keyChoice = (await rl.question(" Choose [1-5]: ")).trim();
139
- if (keyChoice === "5")
134
+ console.log(dim(" [3] OpenRouter"));
135
+ console.log(dim(" [4] Cancel"));
136
+ const keyChoice = (await rl.question(" Choose [1-4]: ")).trim();
137
+ if (keyChoice === "4")
140
138
  return false;
141
139
  if (keyChoice === "2") {
142
140
  const gk = await askSecret(" Paste your Gemini API key (Enter to skip): ");
@@ -150,16 +148,6 @@ export async function runSetupFlow(cfg, rl, opts = {}) {
150
148
  return true;
151
149
  }
152
150
  if (keyChoice === "3") {
153
- const nk = await askSecret(" Paste your NVIDIA API key (Enter to skip): ");
154
- if (!nk)
155
- return false;
156
- cfg.nvidiaApiKey = nk;
157
- cfg.provider = "nvidia";
158
- await testClient("NVIDIA", createNvidiaClient(cfg, nk));
159
- saveDone(cfg);
160
- return true;
161
- }
162
- if (keyChoice === "4") {
163
151
  const ok = await askSecret(" Paste your OpenRouter API key (Enter to skip): ");
164
152
  if (!ok)
165
153
  return false;
@@ -169,7 +157,7 @@ export async function runSetupFlow(cfg, rl, opts = {}) {
169
157
  saveDone(cfg);
170
158
  return true;
171
159
  }
172
- console.log(bold(" Step 1 — Model API key (unlocks all 8 free models)"));
160
+ console.log(bold(" Step 1 — Model API key (unlocks all 4 free models)"));
173
161
  console.log(dim(" 1. Open the provider token page shown by your administrator"));
174
162
  console.log(dim(" 2. Create an API key — it is shown exactly once — and copy it"));
175
163
  console.log(dim(" Your key is typed hidden: it will not appear on screen."));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "codeshark-cli",
3
- "version": "0.1.7",
4
- "description": "An open-source terminal coding agent. Eight model choices, project tools, and approval before every tool action.",
3
+ "version": "0.1.8",
4
+ "description": "An open-source terminal coding agent. Four model choices, project tools, and approval before every tool action.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "codeshark": "dist/index.js"