careervivid 1.12.14 → 1.12.16
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,
|
|
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,CA4Yf"}
|
|
@@ -31,6 +31,29 @@ 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();
|
|
@@ -41,8 +64,33 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
|
|
|
41
64
|
});
|
|
42
65
|
const duration = Date.now() - promptStartTime;
|
|
43
66
|
let userInput = response.query;
|
|
44
|
-
//
|
|
45
|
-
|
|
67
|
+
// ── Multi-line paste mode: user typed <<< (or <<<paste) ─────────────
|
|
68
|
+
// Allows pasting arbitrarily long content (e.g. full JD) without truncation.
|
|
69
|
+
if (userInput.trim() === "<<<" || userInput.trim().toLowerCase().startsWith("<<<")) {
|
|
70
|
+
const prefix = userInput.trim().slice(3).trim(); // text after <<<
|
|
71
|
+
console.log(chalk.dim(" 📋 Multi-line mode: paste your text, then press Enter twice to submit.\n"));
|
|
72
|
+
const lines = prefix ? [prefix] : [];
|
|
73
|
+
let emptyCount = 0;
|
|
74
|
+
while (emptyCount < 1) {
|
|
75
|
+
const lineResp = await prompt({
|
|
76
|
+
type: "input",
|
|
77
|
+
name: "line",
|
|
78
|
+
message: chalk.dim(" │"),
|
|
79
|
+
});
|
|
80
|
+
if (lineResp.line === "") {
|
|
81
|
+
emptyCount++;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
emptyCount = 0;
|
|
85
|
+
lines.push(lineResp.line);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
userInput = lines.join("\n").trim();
|
|
89
|
+
pasteBuffer = [];
|
|
90
|
+
}
|
|
91
|
+
else if (duration < 150) {
|
|
92
|
+
// Handle multiline copy & paste: prompt resolves extremely fast if stdin is buffered.
|
|
93
|
+
// 150ms threshold gives enough headroom for large pastes (long JDs, cover letters).
|
|
46
94
|
pasteBuffer.push(userInput);
|
|
47
95
|
return ask();
|
|
48
96
|
}
|
|
@@ -67,7 +115,10 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
|
|
|
67
115
|
console.log(chalk.dim(" /model <name> — Switch to a different model mid-session"));
|
|
68
116
|
console.log(chalk.dim(" /models — List all available CareerVivid models"));
|
|
69
117
|
console.log(chalk.dim(" /help — Show this help message"));
|
|
70
|
-
console.log(chalk.dim(" exit — End the session
|
|
118
|
+
console.log(chalk.dim(" exit — End the session"));
|
|
119
|
+
console.log(chalk.cyan("\n Paste long content (job descriptions, cover letters):"));
|
|
120
|
+
console.log(chalk.dim(" <<< — Open multi-line paste mode; press Enter twice when done"));
|
|
121
|
+
console.log(chalk.dim(" <<<your text — Start with text directly after <<<\n"));
|
|
71
122
|
return ask();
|
|
72
123
|
}
|
|
73
124
|
if (cmd === "models") {
|
|
@@ -283,13 +334,7 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
|
|
|
283
334
|
let userTurn = { role: "user", parts: [{ text: userInput }] };
|
|
284
335
|
let round = 0;
|
|
285
336
|
while (round < 10) {
|
|
286
|
-
const result = await provider.generate({
|
|
287
|
-
model: currentModel,
|
|
288
|
-
history: byoHistory,
|
|
289
|
-
userTurn,
|
|
290
|
-
tools,
|
|
291
|
-
systemInstruction,
|
|
292
|
-
});
|
|
337
|
+
const result = await withTimeout(provider.generate({ model: currentModel, history: byoHistory, userTurn, tools, systemInstruction }), 45_000, "LLM generate()");
|
|
293
338
|
if (round === 0) {
|
|
294
339
|
process.stdout.write("\r\x1b[K"); // clear initial thinking spinner
|
|
295
340
|
}
|
|
@@ -311,10 +356,17 @@ export async function askLoop(engine, options, selectedProvider, selectedModel,
|
|
|
311
356
|
const tool = tools.find((t) => t.name === fc.name);
|
|
312
357
|
let out;
|
|
313
358
|
try {
|
|
314
|
-
out = tool
|
|
359
|
+
out = tool
|
|
360
|
+
? await withTimeout(tool.execute(fc.args), 45_000, `tool:${fc.name}`)
|
|
361
|
+
: { error: "Tool not found" };
|
|
315
362
|
}
|
|
316
363
|
catch (e) {
|
|
317
|
-
|
|
364
|
+
if (e.message?.includes("No API key configured")) {
|
|
365
|
+
out = { error: "CareerVivid API key not found. Run 'cv login' to authenticate." };
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
out = { error: e.message };
|
|
369
|
+
}
|
|
318
370
|
}
|
|
319
371
|
handleToolResult(fc.name, out);
|
|
320
372
|
fnResponses.push({ functionResponse: { id: fc.id, name: fc.name, response: out } });
|