careervivid 1.12.26 → 1.12.27

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.
@@ -1 +1 @@
1
- {"version":3,"file":"configurator.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/configurator.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0D,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI3G,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKpD,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;GAyBrB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;GA+BtB,CAAC;AAEF,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAsEpD;AAED,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC;IACpE,gBAAgB,EAAE,WAAW,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAwJD"}
1
+ {"version":3,"file":"configurator.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/configurator.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0D,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI3G,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKpD,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;GAyBrB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;GA+BtB,CAAC;AAEF,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAsEpD;AAED,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC;IACpE,gBAAgB,EAAE,WAAW,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAiKD"}
@@ -187,16 +187,26 @@ export async function promptForAgentModel(options = {}) {
187
187
  chalk.dim("\n Your key will be saved locally — you only need to enter it once."));
188
188
  console.log(chalk.dim(`\n Get your key at: `) + chalk.cyan(providerKeyUrls[selectedProvider] ?? "the provider's website"));
189
189
  console.log();
190
- const keyAnswer = await prompt({
191
- type: "password",
192
- name: "key",
193
- message: `Enter your ${providerLabels[selectedProvider] ?? selectedProvider} API key:`,
194
- });
195
- apiKey = keyAnswer.key.trim();
190
+ try {
191
+ const keyAnswer = await prompt({
192
+ type: "password",
193
+ name: "key",
194
+ message: `Enter your ${providerLabels[selectedProvider] ?? selectedProvider} API key:`,
195
+ });
196
+ apiKey = (keyAnswer?.key ?? "").trim();
197
+ }
198
+ catch {
199
+ // User pressed Escape or Ctrl+C — exit cleanly
200
+ console.log(chalk.dim("\n Cancelled. Run `cv agent` again when you have your API key.\n"));
201
+ process.exit(0);
202
+ }
196
203
  if (apiKey) {
197
204
  setProviderKey(selectedProvider, apiKey);
198
205
  console.log(chalk.green(`\n✔ Key saved for ${providerLabels[selectedProvider] ?? selectedProvider}\n`));
199
206
  }
207
+ else {
208
+ console.log(chalk.yellow("\n⚠️ No key entered. Continuing without API key — the agent may fail.\n"));
209
+ }
200
210
  }
201
211
  else {
202
212
  apiKey = savedKey;
@@ -1 +1 @@
1
- {"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/repl.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAA4B,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI7E,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,GAAE,MAAM,GAAG,IAAW,QAwBtF;AAED,wBAAsB,OAAO,CAC3B,MAAM,EAAE,WAAW,GAAG,sBAAsB,GAAG,IAAI,EACnD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EAC9K,gBAAgB,EAAE,WAAW,EAC7B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,GAAG,EAAE,GACX,OAAO,CAAC,IAAI,CAAC,CA+bf"}
1
+ {"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/repl.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAA4D,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI7G,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,GAAE,MAAM,GAAG,IAAW,QAwBtF;AAED,wBAAsB,OAAO,CAC3B,MAAM,EAAE,WAAW,GAAG,sBAAsB,GAAG,IAAI,EACnD,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EAC9K,gBAAgB,EAAE,WAAW,EAC7B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,GAAG,EAAE,GACX,OAAO,CAAC,IAAI,CAAC,CA4ff"}
@@ -4,7 +4,7 @@ import ora from "ora";
4
4
  import { isSafeCommand } from "../../agent/tools/coding.js";
5
5
  import { CareerVividProxyEngine } from "../../agent/CareerVividProxyEngine.js";
6
6
  import { CV_MODELS } from "./configurator.js";
7
- import { loadConfig, getGeminiKey } from "../../config.js";
7
+ import { loadConfig, getProviderKey, setProviderKey } from "../../config.js";
8
8
  const { prompt } = pkg;
9
9
  export function printCreditStatus(remaining, limit = null) {
10
10
  if (remaining === null)
@@ -366,8 +366,8 @@ ${label}
366
366
  sessionTurns++;
367
367
  const { createOpenAICompatibleProvider } = await import("../../agent/providers/OpenAIProvider.js");
368
368
  const { AnthropicProvider } = await import("../../agent/providers/AnthropicProvider.js");
369
- const byoApiKey = options["api-key"] || loadConfig().llmApiKey;
370
- const key = byoApiKey || getGeminiKey() || "";
369
+ const byoApiKey = options["api-key"] || getProviderKey(selectedProvider) || loadConfig().llmApiKey;
370
+ const key = byoApiKey || "";
371
371
  const baseUrl = options["base-url"] || loadConfig().llmBaseUrl;
372
372
  let provider;
373
373
  if (selectedProvider === "anthropic") {
@@ -425,11 +425,71 @@ ${label}
425
425
  return ask();
426
426
  }
427
427
  catch (err) {
428
- if (err.message && err.message.includes("cancelled")) {
428
+ const msg = err?.message ?? "";
429
+ // ── Clean exit on Ctrl+C / enquirer cancel ────────────────────────
430
+ if (!msg || msg.includes("cancelled") || msg.includes("User force closed")) {
429
431
  console.log(chalk.gray("\nCancelled. Exiting.\n"));
430
432
  process.exit(0);
431
433
  }
432
- console.error(chalk.red(`\nAgent encountered an error: ${err.message}`));
434
+ // ── 401 unauthorized — offer key reset ───────────────────────────
435
+ const is401 = msg.includes("401") || msg.toLowerCase().includes("user not found") ||
436
+ msg.toLowerCase().includes("invalid api key") || msg.toLowerCase().includes("unauthorized");
437
+ if (is401 && selectedProvider && selectedProvider !== "careervivid") {
438
+ const providerLabels = {
439
+ openai: "OpenAI", anthropic: "Anthropic",
440
+ gemini: "Gemini", openrouter: "OpenRouter", custom: "Custom",
441
+ };
442
+ const providerKeyUrls = {
443
+ openai: "https://platform.openai.com/api-keys",
444
+ anthropic: "https://console.anthropic.com/settings/keys",
445
+ gemini: "https://aistudio.google.com/app/apikey",
446
+ openrouter: "https://openrouter.ai/settings/keys",
447
+ };
448
+ const label = providerLabels[selectedProvider] ?? selectedProvider;
449
+ console.log();
450
+ console.log(chalk.red(`❌ API key rejected by ${label} (401 Unauthorized).`));
451
+ console.log(chalk.dim(` The saved key may be expired or invalid.`));
452
+ if (providerKeyUrls[selectedProvider]) {
453
+ console.log(chalk.dim(` Get a new key at: `) + chalk.cyan(providerKeyUrls[selectedProvider]));
454
+ }
455
+ console.log();
456
+ try {
457
+ const resetAnswer = await prompt({
458
+ type: "select",
459
+ name: "action",
460
+ message: "What would you like to do?",
461
+ choices: [
462
+ { name: "reset", message: `🔑 Enter a new ${label} API key` },
463
+ { name: "continue", message: "⏭️ Continue anyway (will keep failing)" },
464
+ { name: "exit", message: "🚪 Exit the agent" },
465
+ ],
466
+ });
467
+ if (resetAnswer.action === "reset") {
468
+ const keyAnswer = await prompt({
469
+ type: "password",
470
+ name: "key",
471
+ message: `Enter your new ${label} API key:`,
472
+ });
473
+ const newKey = (keyAnswer?.key ?? "").trim();
474
+ if (newKey) {
475
+ setProviderKey(selectedProvider, newKey);
476
+ // Update the key used for subsequent turns this session
477
+ options["api-key"] = newKey;
478
+ console.log(chalk.green(`\n✔ New ${label} key saved. Resuming session...\n`));
479
+ }
480
+ }
481
+ else if (resetAnswer.action === "exit") {
482
+ console.log(chalk.gray("\nGoodbye! 👋\n"));
483
+ process.exit(0);
484
+ }
485
+ }
486
+ catch {
487
+ // User cancelled the reset prompt — just continue
488
+ }
489
+ return ask();
490
+ }
491
+ // ── Generic error ────────────────────────────────────────────────
492
+ console.error(chalk.red(`\nAgent encountered an error: ${msg}`));
433
493
  return ask();
434
494
  }
435
495
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "careervivid",
3
- "version": "1.12.26",
3
+ "version": "1.12.27",
4
4
  "description": "Official CLI for CareerVivid — publish articles, diagrams, and portfolio updates from your terminal or AI agent",
5
5
  "type": "module",
6
6
  "bin": {