junecoder 1.0.6 → 1.0.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.
Files changed (3) hide show
  1. package/cli.js +7 -2
  2. package/package.json +1 -1
  3. package/tui.mjs +25 -3
package/cli.js CHANGED
@@ -152,9 +152,14 @@ if (existsSync(targetDir) && statSync(targetDir).isDirectory()) {
152
152
 
153
153
  // Load config and API key
154
154
  const config = loadConfig();
155
- const apiKey = config.provider.apiKey || process.env.DEEPSEEK_API_KEY;
155
+ let apiKey = config.provider.apiKey || process.env.DEEPSEEK_API_KEY || '';
156
156
 
157
- config.provider.apiKey = apiKey || '';
157
+ // Only treat as valid if it starts with sk- (DeepSeek key format)
158
+ if (apiKey && !apiKey.startsWith('sk-')) {
159
+ apiKey = ''; // invalid format, treat as not configured
160
+ }
161
+
162
+ config.provider.apiKey = apiKey;
158
163
 
159
164
  // Create Agent instance with target cwd
160
165
  const agent = createAgent({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "junecoder",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Zero Npm Dependencies Agent Framework",
5
5
  "main": "agent.mjs",
6
6
  "type": "module",
package/tui.mjs CHANGED
@@ -331,6 +331,16 @@ export async function startTUI(agent, opts = {}) {
331
331
  // ─── First-run setup: capture API key from input box ──────────────────────────
332
332
  let setupMode = opts.needsSetup;
333
333
  if (setupMode) {
334
+ pushLine("", C.dim);
335
+ pushLine("\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510", C.assistant);
336
+ pushLine("\u2502 Welcome to JuneCoder! \u2502", C.assistant);
337
+ pushLine("\u2502 \u2502", C.assistant);
338
+ pushLine("\u2502 Before you start, you need a DeepSeek API key. \u2502", C.assistant);
339
+ pushLine("\u2502 Get one at: https://platform.deepseek.com/api_keys \u2502", C.assistant);
340
+ pushLine("\u2502 \u2502", C.assistant);
341
+ pushLine("\u2502 Paste your key below and press Enter. \u2502", C.assistant);
342
+ pushLine("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518", C.assistant);
343
+ pushLine("", C.dim);
334
344
  state.status = "Paste your DeepSeek API key and press Enter (https://platform.deepseek.com/api_keys)";
335
345
  }
336
346
 
@@ -353,7 +363,12 @@ export async function startTUI(agent, opts = {}) {
353
363
  }
354
364
 
355
365
  if (!trimmed.startsWith("sk-")) {
356
- pushLine("Warning: API key doesn't start with 'sk-'. It may not work.", C.warn);
366
+ pushLine("Invalid key — DeepSeek API keys must start with 'sk-'. Try again:", C.error);
367
+ pushLine("", C.dim);
368
+ setupMode = true; // stay in setup mode
369
+ state.status = "Paste your DeepSeek API key and press Enter (https://platform.deepseek.com/api_keys)";
370
+ render();
371
+ return;
357
372
  }
358
373
 
359
374
  const configDir = join(homedir(), '.junecoder');
@@ -409,10 +424,17 @@ export async function startTUI(agent, opts = {}) {
409
424
  async function handleSlash(text) {
410
425
  const cmd = text.slice(1).split(/\s+/)[0].toLowerCase();
411
426
  switch (cmd) {
412
- case "help": for (const l of ["/help /plan /auto /model /session /clear /tasks /stats /new /distill /quit"]) pushLine(l, C.dim); break;
427
+ case "help": for (const l of ["/help /plan /auto /key /model /session /clear /tasks /stats /new /distill /quit"]) pushLine(l, C.dim); break;
413
428
  case "plan": agent.planMode = !agent.planMode; pushLine(" Plan mode " + (agent.planMode ? "ON" : "OFF"), C.tool); break;
414
429
  case "auto": agent.autoApprove = !agent.autoApprove; pushLine(" Auto-approve " + (agent.autoApprove ? "ON" : "OFF"), agent.autoApprove ? C.warn : C.tool); break;
415
430
  case "model": pushLine(" Model: " + agent.provider.model + " | Provider: " + (agent.provider.type || "?"), C.dim); break;
431
+ case "key": {
432
+ pushLine(" Current key: " + (agent.provider.apiKey ? agent.provider.apiKey.slice(0, 8) + "..." : "(none)"), C.dim);
433
+ pushLine(" To change, paste your new API key and press Enter.", C.tool);
434
+ setupMode = true;
435
+ state.status = "Paste your DeepSeek API key and press Enter (https://platform.deepseek.com/api_keys)";
436
+ break;
437
+ }
416
438
  case "session": { const slots = listSlots(agent.cwd); pushLine("Sessions:", C.tool); if (slots.length === 0) pushLine(" (none)", C.dim); else for (const s of slots) pushLine(" " + s.label, C.dim); break; }
417
439
  case "clear": archiveCurrent(agent.cwd); agent.history = []; state.lines = []; state.streaming = ""; state.reasoning = ""; state.tasks = []; state.scroll = 0; pushLine("Cleared (archived).", C.warn); break;
418
440
  case "new": archiveCurrent(agent.cwd); agent.history = []; state.lines = []; state.streaming = ""; state.reasoning = ""; state.toolStreams = {}; state.tasks = []; state.scroll = 0; state.tokens = { prompt: 0, completion: 0 }; pushLine("New session.", C.tool); break;
@@ -467,7 +489,7 @@ export async function startTUI(agent, opts = {}) {
467
489
  if (restored.tasks) { state.tasks = restored.tasks; agent.tasks = restored.tasks; }
468
490
  if (restored.planMode !== undefined) agent.planMode = restored.planMode;
469
491
  state.status = "Session restored";
470
- } else {
492
+ } else if (!setupMode) {
471
493
  pushLine("", C.dim);
472
494
  pushLine("JuneCoder TUI \u2014 " + (agent.provider.model || ""), ansi.bold + C.tool);
473
495
  pushLine("Type /help for commands, Ctrl+C to quit.", C.dim);