@pentoshi/clai 0.5.5 → 0.5.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/dist/agent/runner.js +54 -3
- package/dist/agent/runner.js.map +1 -1
- package/dist/commands/doctor.js +12 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/llm/http.d.ts +4 -0
- package/dist/llm/http.js +184 -75
- package/dist/llm/http.js.map +1 -1
- package/dist/modes/ask.js +2 -2
- package/dist/modes/ask.js.map +1 -1
- package/dist/repl.js +49 -9
- package/dist/repl.js.map +1 -1
- package/dist/store/history.js +8 -0
- package/dist/store/history.js.map +1 -1
- package/dist/store/keys.d.ts +13 -0
- package/dist/store/keys.js +80 -16
- package/dist/store/keys.js.map +1 -1
- package/dist/tools/registry.d.ts +1 -0
- package/dist/tools/registry.js +6 -4
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/shell.d.ts +1 -0
- package/dist/tools/shell.js +8 -4
- package/dist/tools/shell.js.map +1 -1
- package/dist/ui/spinner.d.ts +2 -0
- package/dist/ui/spinner.js +64 -22
- package/dist/ui/spinner.js.map +1 -1
- package/package.json +2 -3
package/dist/ui/spinner.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
2
|
+
// Live, dependency-free thinking indicator. Renders below the prompt as
|
|
3
|
+
// up to two dim lines:
|
|
4
|
+
// ⠋ thinking 12.3s · 240 reasoning tokens
|
|
5
|
+
// tail of the most recent reasoning text…
|
|
6
|
+
// On stop() it erases its own lines so subsequent output starts clean.
|
|
6
7
|
const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
7
8
|
const FRAME_INTERVAL_MS = 80;
|
|
9
|
+
const PREVIEW_TAIL_CHARS = 220;
|
|
10
|
+
function stripAnsi(text) {
|
|
11
|
+
// biome-ignore lint: ANSI escape pattern is intentional.
|
|
12
|
+
return text.replace(/\x1b\[[0-9;]*m/g, "");
|
|
13
|
+
}
|
|
14
|
+
function clamp(n, lo, hi) {
|
|
15
|
+
return Math.max(lo, Math.min(hi, n));
|
|
16
|
+
}
|
|
8
17
|
export function startThinkingSpinner(initialLabel = "thinking", signal) {
|
|
9
18
|
if (!process.stdout.isTTY) {
|
|
10
|
-
// No-op for piped output so logs stay grep-friendly.
|
|
11
19
|
return {
|
|
12
20
|
setLabel: () => { },
|
|
13
21
|
bumpReasoning: () => { },
|
|
22
|
+
pushPreview: () => { },
|
|
14
23
|
stop: () => { },
|
|
15
24
|
};
|
|
16
25
|
}
|
|
@@ -19,31 +28,61 @@ export function startThinkingSpinner(initialLabel = "thinking", signal) {
|
|
|
19
28
|
let frame = 0;
|
|
20
29
|
const start = Date.now();
|
|
21
30
|
let stopped = false;
|
|
22
|
-
let
|
|
31
|
+
let renderedLines = 0;
|
|
32
|
+
let preview = "";
|
|
33
|
+
const erase = () => {
|
|
34
|
+
if (renderedLines === 0)
|
|
35
|
+
return;
|
|
36
|
+
// Cursor is currently after the last rendered line. Move back up,
|
|
37
|
+
// clearing each line as we go.
|
|
38
|
+
for (let i = 0; i < renderedLines; i += 1) {
|
|
39
|
+
process.stdout.write("\r\x1b[2K"); // clear current line
|
|
40
|
+
if (i < renderedLines - 1)
|
|
41
|
+
process.stdout.write("\x1b[1A"); // move up
|
|
42
|
+
}
|
|
43
|
+
renderedLines = 0;
|
|
44
|
+
};
|
|
45
|
+
const truncateForWidth = (text, width) => {
|
|
46
|
+
const visibleLen = stripAnsi(text).length;
|
|
47
|
+
if (visibleLen <= width)
|
|
48
|
+
return text;
|
|
49
|
+
// For preview text that has no ANSI codes, simple slice works.
|
|
50
|
+
return text.slice(0, Math.max(0, width - 1)) + "…";
|
|
51
|
+
};
|
|
23
52
|
const render = () => {
|
|
24
53
|
if (stopped)
|
|
25
54
|
return;
|
|
55
|
+
erase();
|
|
26
56
|
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
|
27
57
|
const tokenSuffix = reasoningTokens > 0
|
|
28
58
|
? chalk.dim(` · ${reasoningTokens.toLocaleString()} reasoning tokens`)
|
|
29
59
|
: "";
|
|
30
|
-
const
|
|
60
|
+
const headLine = chalk.magenta(FRAMES[frame % FRAMES.length]) +
|
|
31
61
|
" " +
|
|
32
62
|
chalk.dim(`${label} ${elapsed}s`) +
|
|
33
63
|
tokenSuffix;
|
|
34
|
-
process.stdout.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
64
|
+
const cols = clamp(process.stdout.columns ?? 80, 40, 200);
|
|
65
|
+
let lines = [headLine];
|
|
66
|
+
if (preview) {
|
|
67
|
+
// Take last N chars, drop ANSI/control noise, collapse whitespace,
|
|
68
|
+
// and indent so the preview lines up under the spinner.
|
|
69
|
+
const tail = preview
|
|
70
|
+
.slice(-PREVIEW_TAIL_CHARS)
|
|
71
|
+
// biome-ignore lint: control char strip
|
|
72
|
+
.replace(/[\x00-\x09\x0b-\x1f\x7f]/g, "")
|
|
73
|
+
.replace(/\s+/g, " ")
|
|
74
|
+
.trim();
|
|
75
|
+
if (tail) {
|
|
76
|
+
const previewLine = chalk.dim.italic(` ${tail}`);
|
|
77
|
+
lines.push(truncateForWidth(previewLine, cols));
|
|
78
|
+
}
|
|
40
79
|
}
|
|
41
|
-
|
|
80
|
+
process.stdout.write(lines.join("\n"));
|
|
81
|
+
renderedLines = lines.length;
|
|
42
82
|
frame += 1;
|
|
43
83
|
};
|
|
44
84
|
render();
|
|
45
85
|
const timer = setInterval(render, FRAME_INTERVAL_MS);
|
|
46
|
-
// Don't keep the process alive just for the spinner.
|
|
47
86
|
if (typeof timer.unref === "function")
|
|
48
87
|
timer.unref();
|
|
49
88
|
const stop = () => {
|
|
@@ -51,11 +90,8 @@ export function startThinkingSpinner(initialLabel = "thinking", signal) {
|
|
|
51
90
|
return;
|
|
52
91
|
stopped = true;
|
|
53
92
|
clearInterval(timer);
|
|
54
|
-
|
|
55
|
-
process.stdout.write(`\r${" ".repeat(Math.max(lastWidth, 1))}\r`);
|
|
93
|
+
erase();
|
|
56
94
|
};
|
|
57
|
-
// Stop the moment the user aborts so the spinner can never linger past
|
|
58
|
-
// an ESC, even if upstream cleanup paths are skipped by an exception.
|
|
59
95
|
if (signal) {
|
|
60
96
|
if (signal.aborted)
|
|
61
97
|
stop();
|
|
@@ -69,10 +105,16 @@ export function startThinkingSpinner(initialLabel = "thinking", signal) {
|
|
|
69
105
|
bumpReasoning(tokens) {
|
|
70
106
|
reasoningTokens += tokens;
|
|
71
107
|
},
|
|
108
|
+
pushPreview(text) {
|
|
109
|
+
if (!text)
|
|
110
|
+
return;
|
|
111
|
+
preview += text;
|
|
112
|
+
// Only keep what we'll actually show, plus a small overflow buffer.
|
|
113
|
+
if (preview.length > PREVIEW_TAIL_CHARS * 4) {
|
|
114
|
+
preview = preview.slice(-PREVIEW_TAIL_CHARS * 2);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
72
117
|
stop,
|
|
73
118
|
};
|
|
74
119
|
}
|
|
75
|
-
function stripAnsi(text) {
|
|
76
|
-
return text.replace(/\x1b\[[0-9;]*m/g, "");
|
|
77
|
-
}
|
|
78
120
|
//# sourceMappingURL=spinner.js.map
|
package/dist/ui/spinner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pentoshi/clai",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "A fast, cross-platform AI CLI assistant with ask and agent modes for shell tasks, file operations, and cybersecurity workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,8 +53,7 @@
|
|
|
53
53
|
"zod": "^3.24.1"
|
|
54
54
|
},
|
|
55
55
|
"optionalDependencies": {
|
|
56
|
-
"
|
|
57
|
-
"keytar": "^7.9.0"
|
|
56
|
+
"@napi-rs/keyring": "^1.3.0"
|
|
58
57
|
},
|
|
59
58
|
"devDependencies": {
|
|
60
59
|
"@types/node": "^25.6.0",
|