careervivid 1.12.15 → 1.12.17

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":"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,CA6Wf"}
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,CA6Zf"}
@@ -31,13 +31,38 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
31
31
  let currentModel = selectedModel;
32
32
  let pasteBuffer = [];
33
33
  let byoHistory = []; // Track history for BYO providers
34
+ // ── SIGINT handler: Ctrl+C cancels current operation and returns to prompt ──
35
+ let activeAbort = null;
36
+ const handleSigInt = () => {
37
+ const ab = activeAbort;
38
+ if (ab !== null && !ab.signal.aborted) {
39
+ ab.abort();
40
+ process.stdout.write("\n" + chalk.yellow("⚡ Interrupted. Press Ctrl+C again or type 'exit' to quit.\n"));
41
+ }
42
+ else {
43
+ // Second Ctrl+C exits
44
+ console.log(chalk.gray("\nGoodbye! 👋\n"));
45
+ process.exit(0);
46
+ }
47
+ };
48
+ process.on("SIGINT", handleSigInt);
49
+ /** Wraps a promise with a timeout. Rejects with a friendly timeout error. */
50
+ function withTimeout(p, ms, label) {
51
+ return new Promise((resolve, reject) => {
52
+ const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms / 1000}s. Press Ctrl+C if stuck.`)), ms);
53
+ p.then(v => { clearTimeout(timer); resolve(v); })
54
+ .catch(e => { clearTimeout(timer); reject(e); });
55
+ });
56
+ }
34
57
  const ask = async () => {
35
58
  try {
36
59
  const promptStartTime = Date.now();
37
60
  const response = await prompt({
38
61
  type: "input",
39
62
  name: "query",
40
- message: pasteBuffer.length > 0 ? chalk.dim("... ") : chalk.bold.cyan("❯"),
63
+ message: pasteBuffer.length > 0
64
+ ? chalk.dim("... ")
65
+ : chalk.bold.cyan("❯") + chalk.dim(" ·"),
41
66
  });
42
67
  const duration = Date.now() - promptStartTime;
43
68
  let userInput = response.query;
@@ -83,6 +108,18 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
83
108
  userInput = userInput.trim();
84
109
  if (!userInput)
85
110
  return ask();
111
+ // ── Input length guard ──────────────────────────────────────────
112
+ // macOS terminal readline has a hard ~4096 char limit per line, meaning
113
+ // pasting very long job descriptions gets silently truncated mid-word.
114
+ // Detect this early and guide the user to <<< mode instead.
115
+ const MAX_INPUT_CHARS = 20_000; // ~3,000 words — safe above typical JD length
116
+ if (userInput.length > MAX_INPUT_CHARS) {
117
+ console.log(chalk.yellow("\n⚠️ Input is too long (" + userInput.length + " chars).") +
118
+ chalk.dim("\n Use <<< mode for long job descriptions so nothing gets cut off:") +
119
+ chalk.cyan("\n\n ❯ <<< ") +
120
+ chalk.dim("\n Then paste the job description, and press Enter twice to submit.\n"));
121
+ return ask();
122
+ }
86
123
  // ── Slash commands ──────────────────────────────────────────────
87
124
  if (userInput.startsWith("/")) {
88
125
  const [cmd, ...rest] = userInput.slice(1).split(" ");
@@ -311,13 +348,7 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
311
348
  let userTurn = { role: "user", parts: [{ text: userInput }] };
312
349
  let round = 0;
313
350
  while (round < 10) {
314
- const result = await provider.generate({
315
- model: currentModel,
316
- history: byoHistory,
317
- userTurn,
318
- tools,
319
- systemInstruction,
320
- });
351
+ const result = await withTimeout(provider.generate({ model: currentModel, history: byoHistory, userTurn, tools, systemInstruction }), 45_000, "LLM generate()");
321
352
  if (round === 0) {
322
353
  process.stdout.write("\r\x1b[K"); // clear initial thinking spinner
323
354
  }
@@ -339,10 +370,17 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
339
370
  const tool = tools.find((t) => t.name === fc.name);
340
371
  let out;
341
372
  try {
342
- out = tool ? await tool.execute(fc.args) : { error: "Tool not found" };
373
+ out = tool
374
+ ? await withTimeout(tool.execute(fc.args), 45_000, `tool:${fc.name}`)
375
+ : { error: "Tool not found" };
343
376
  }
344
377
  catch (e) {
345
- out = { error: e.message };
378
+ if (e.message?.includes("No API key configured")) {
379
+ out = { error: "CareerVivid API key not found. Run 'cv login' to authenticate." };
380
+ }
381
+ else {
382
+ out = { error: e.message };
383
+ }
346
384
  }
347
385
  handleToolResult(fc.name, out);
348
386
  fnResponses.push({ functionResponse: { id: fc.id, name: fc.name, response: out } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "careervivid",
3
- "version": "1.12.15",
3
+ "version": "1.12.17",
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": {