codeshark-cli 0.1.1 → 0.1.4
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/PRIVACY.md +73 -0
- package/README.md +79 -214
- package/TERMS.md +34 -15
- package/dist/agent.js +33 -3
- package/dist/banner.js +130 -71
- package/dist/config.js +35 -8
- package/dist/index.js +85 -9
- package/dist/keysPage.js +3 -3
- package/dist/modelAvailability.js +86 -0
- package/dist/models.js +49 -16
- package/dist/project.js +20 -6
- package/dist/provider/index.js +7 -1
- package/dist/provider/nvidia.js +1 -1
- package/dist/provider/openaiCompat.js +104 -50
- package/dist/repl.js +119 -51
- package/dist/setup.js +53 -9
- package/dist/system.js +29 -11
- package/dist/tools/files.js +29 -31
- package/dist/tools/registry.js +27 -4
- package/dist/tools/search.js +17 -6
- package/dist/tools/shell.js +40 -8
- package/dist/update.js +43 -0
- package/package.json +8 -8
package/dist/tools/search.js
CHANGED
|
@@ -9,12 +9,19 @@ function exec(cmd, args, timeoutMs) {
|
|
|
9
9
|
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
10
10
|
let stdout = "";
|
|
11
11
|
let stderr = "";
|
|
12
|
-
|
|
13
|
-
child.
|
|
12
|
+
let truncated = false;
|
|
13
|
+
child.stdout.setEncoding("utf8");
|
|
14
|
+
child.stderr.setEncoding("utf8");
|
|
15
|
+
child.stdout.on("data", (d) => {
|
|
16
|
+
if (stdout.length + d.length > 30_000)
|
|
17
|
+
truncated = true;
|
|
18
|
+
stdout += d.slice(0, Math.max(0, 30_000 - stdout.length));
|
|
19
|
+
});
|
|
20
|
+
child.stderr.on("data", (d) => { stderr += d.slice(0, Math.max(0, 1000 - stderr.length)); });
|
|
14
21
|
const timer = setTimeout(() => child.kill("SIGKILL"), timeoutMs);
|
|
15
22
|
child.on("close", (code) => {
|
|
16
23
|
clearTimeout(timer);
|
|
17
|
-
resolvePromise({ code, stdout, stderr });
|
|
24
|
+
resolvePromise({ code, stdout: stdout + (truncated ? "\n[Search output truncated; narrow the pattern.]" : ""), stderr });
|
|
18
25
|
});
|
|
19
26
|
child.on("error", () => {
|
|
20
27
|
clearTimeout(timer);
|
|
@@ -32,10 +39,10 @@ function parseFlags(flags) {
|
|
|
32
39
|
}
|
|
33
40
|
/** Dependency-free fallback when ripgrep isn't installed. */
|
|
34
41
|
function jsSearch(root, pattern, flags) {
|
|
35
|
-
const { caseInsensitive, filesOnly, context } = parseFlags(flags);
|
|
42
|
+
const { caseInsensitive, filesOnly, context, word } = parseFlags(flags);
|
|
36
43
|
let rx;
|
|
37
44
|
try {
|
|
38
|
-
rx = new RegExp(pattern, caseInsensitive ? "i" : "");
|
|
45
|
+
rx = new RegExp(word ? "\\b(?:" + pattern + ")\\b" : pattern, caseInsensitive ? "i" : "");
|
|
39
46
|
}
|
|
40
47
|
catch {
|
|
41
48
|
return `Invalid regex: ${pattern}`;
|
|
@@ -67,6 +74,8 @@ function jsSearch(root, pattern, flags) {
|
|
|
67
74
|
continue;
|
|
68
75
|
let text;
|
|
69
76
|
try {
|
|
77
|
+
if (statSync(full).size > 10 * 1024 * 1024)
|
|
78
|
+
continue;
|
|
70
79
|
text = readFileSync(full, "utf8");
|
|
71
80
|
}
|
|
72
81
|
catch {
|
|
@@ -81,7 +90,7 @@ function jsSearch(root, pattern, flags) {
|
|
|
81
90
|
results.push(rel);
|
|
82
91
|
continue;
|
|
83
92
|
}
|
|
84
|
-
for (let i = 0; i < lines.length; i++) {
|
|
93
|
+
for (let i = 0; i < lines.length && results.length < MAX_RESULTS; i++) {
|
|
85
94
|
const line = lines[i];
|
|
86
95
|
if (!rx.test(line))
|
|
87
96
|
continue;
|
|
@@ -102,6 +111,7 @@ function jsSearch(root, pattern, flags) {
|
|
|
102
111
|
}
|
|
103
112
|
export const codeSearchTool = {
|
|
104
113
|
name: "code_search",
|
|
114
|
+
readOnly: true,
|
|
105
115
|
description: "Search file contents with a regular expression (ripgrep if installed, a built-in fallback otherwise). Returns up to 200 matches with line numbers. Flags: -i case-insensitive, -l files only, -w whole word, -C n context lines.",
|
|
106
116
|
inputSchema: {
|
|
107
117
|
type: "object",
|
|
@@ -136,6 +146,7 @@ export const codeSearchTool = {
|
|
|
136
146
|
...(/-l/.test(flags) ? ["-l"] : []),
|
|
137
147
|
...(/-w/.test(flags) ? ["-w"] : []),
|
|
138
148
|
...(/-C\s*(\d+)/.test(flags) ? ["-C", /-C\s*(\d+)/.exec(flags)[1]] : []),
|
|
149
|
+
"--",
|
|
139
150
|
pattern,
|
|
140
151
|
cwd,
|
|
141
152
|
];
|
package/dist/tools/shell.js
CHANGED
|
@@ -68,35 +68,67 @@ export const runCommandTool = {
|
|
|
68
68
|
if (!command)
|
|
69
69
|
return "No command provided.";
|
|
70
70
|
const cwd = args.cwd ? resolveProjectPath(String(args.cwd), ctx.cwd) : ctx.cwd;
|
|
71
|
-
const timeoutMs = args.timeoutMs ? Math.max(1000, Number(args.timeoutMs)) : DEFAULT_TIMEOUT_MS;
|
|
71
|
+
const timeoutMs = args.timeoutMs ? Math.min(300_000, Math.max(1000, Number(args.timeoutMs))) : DEFAULT_TIMEOUT_MS;
|
|
72
72
|
const danger = isDangerousCommand(command);
|
|
73
73
|
if (danger && !process.env.CODESHARK_ALLOW_DANGEROUS) {
|
|
74
74
|
throw new Error(`Blocked: "${command}" matches the danger pattern "${danger}". CodeShark refuses destructive commands by default (set CODESHARK_ALLOW_DANGEROUS=1 to override).`);
|
|
75
75
|
}
|
|
76
76
|
const shell = pickShell();
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
ctx.signal?.throwIfAborted();
|
|
78
|
+
return new Promise((resolvePromise, reject) => {
|
|
79
|
+
const child = spawn(shell.cmd, shell.args(command), { cwd, stdio: ["ignore", "pipe", "pipe"], windowsHide: true, detached: process.platform !== "win32" });
|
|
79
80
|
let stdout = "";
|
|
80
81
|
let stderr = "";
|
|
81
82
|
let timedOut = false;
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
let stdoutChars = 0;
|
|
84
|
+
let stderrChars = 0;
|
|
85
|
+
child.stdout.setEncoding("utf8");
|
|
86
|
+
child.stderr.setEncoding("utf8");
|
|
87
|
+
child.stdout.on("data", (d) => { stdoutChars += d.length; stdout += d.slice(0, Math.max(0, MAX_OUTPUT_CHARS - stdout.length)); });
|
|
88
|
+
child.stderr.on("data", (d) => { stderrChars += d.length; stderr += d.slice(0, Math.max(0, MAX_OUTPUT_CHARS - stderr.length)); });
|
|
89
|
+
const stop = () => {
|
|
90
|
+
if (!child.pid)
|
|
91
|
+
return;
|
|
92
|
+
if (process.platform === "win32") {
|
|
93
|
+
const killer = spawn("taskkill", ["/pid", String(child.pid), "/t", "/f"], { windowsHide: true, stdio: "ignore" });
|
|
94
|
+
killer.on("error", () => child.kill());
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
try {
|
|
98
|
+
process.kill(-child.pid, "SIGKILL");
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
child.kill("SIGKILL");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
ctx.signal?.addEventListener("abort", stop, { once: true });
|
|
84
106
|
const timer = setTimeout(() => {
|
|
85
107
|
timedOut = true;
|
|
86
|
-
|
|
108
|
+
stop();
|
|
87
109
|
}, timeoutMs);
|
|
88
110
|
child.on("close", (code) => {
|
|
89
111
|
clearTimeout(timer);
|
|
112
|
+
ctx.signal?.removeEventListener("abort", stop);
|
|
90
113
|
const parts = [`$ ${command}`, `exit code: ${timedOut ? `timed out after ${timeoutMs}ms` : code}`];
|
|
91
114
|
if (stdout.trim())
|
|
92
115
|
parts.push(`stdout:\n${truncate(stdout).trimEnd()}`);
|
|
93
116
|
if (stderr.trim())
|
|
94
117
|
parts.push(`stderr:\n${truncate(stderr).trimEnd()}`);
|
|
95
|
-
|
|
118
|
+
if (stdoutChars > stdout.length || stderrChars > stderr.length)
|
|
119
|
+
parts.push("[Output truncated; use a narrower command.]");
|
|
120
|
+
const result = parts.join("\n");
|
|
121
|
+
if (ctx.signal?.aborted)
|
|
122
|
+
reject(ctx.signal.reason);
|
|
123
|
+
else if (timedOut || code !== 0)
|
|
124
|
+
reject(new Error(result));
|
|
125
|
+
else
|
|
126
|
+
resolvePromise(result);
|
|
96
127
|
});
|
|
97
128
|
child.on("error", (e) => {
|
|
98
129
|
clearTimeout(timer);
|
|
99
|
-
|
|
130
|
+
ctx.signal?.removeEventListener("abort", stop);
|
|
131
|
+
reject(new Error(`Failed to spawn shell: ${e.message}`));
|
|
100
132
|
});
|
|
101
133
|
});
|
|
102
134
|
},
|
package/dist/update.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
function npmCommand() {
|
|
3
|
+
return process.platform === "win32" ? "npm.cmd" : "npm";
|
|
4
|
+
}
|
|
5
|
+
function versionParts(version) {
|
|
6
|
+
return version
|
|
7
|
+
.replace(/^v/, "")
|
|
8
|
+
.split(".")
|
|
9
|
+
.slice(0, 3)
|
|
10
|
+
.map((part) => Number.parseInt(part, 10) || 0);
|
|
11
|
+
}
|
|
12
|
+
export function isNewerVersion(current, latest) {
|
|
13
|
+
const a = versionParts(current);
|
|
14
|
+
const b = versionParts(latest);
|
|
15
|
+
for (let i = 0; i < 3; i++) {
|
|
16
|
+
if ((b[i] ?? 0) !== (a[i] ?? 0))
|
|
17
|
+
return (b[i] ?? 0) > (a[i] ?? 0);
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
export function latestPublishedVersion() {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
exec(`${npmCommand()} view codeshark-cli version --json`, { timeout: 5000, windowsHide: true }, (error, stdout) => {
|
|
24
|
+
if (error) {
|
|
25
|
+
resolve(null);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const version = stdout.trim().replace(/^\"|\"$/g, "");
|
|
29
|
+
resolve(/^\d+\.\d+\.\d+$/.test(version) ? version : null);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export async function installLatestVersion() {
|
|
34
|
+
await new Promise((resolve, reject) => {
|
|
35
|
+
exec(`${npmCommand()} install --global codeshark-cli@latest`, { timeout: 120_000, windowsHide: true }, (error, stdout, stderr) => {
|
|
36
|
+
if (error) {
|
|
37
|
+
reject(new Error((stderr || stdout || error.message).trim()));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
resolve();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeshark-cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "An open-source terminal coding agent
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "An open-source terminal coding agent. Eight model choices, project tools, and approval before every tool action.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"codeshark": "
|
|
7
|
+
"codeshark": "dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
12
|
"README.md",
|
|
13
13
|
"TERMS.md",
|
|
14
|
+
"PRIVACY.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"repository": {
|
|
17
18
|
"type": "git",
|
|
18
|
-
"url": "https://github.com/
|
|
19
|
+
"url": "git+https://github.com/ajashratripathi-crypto/codeshark-cli.git"
|
|
19
20
|
},
|
|
20
|
-
"homepage": "https://github.com/
|
|
21
|
+
"homepage": "https://github.com/ajashratripathi-crypto/codeshark-cli#readme",
|
|
21
22
|
"bugs": {
|
|
22
|
-
"url": "https://github.com/
|
|
23
|
+
"url": "https://github.com/ajashratripathi-crypto/codeshark-cli/issues"
|
|
23
24
|
},
|
|
24
25
|
"publishConfig": {
|
|
25
26
|
"access": "public"
|
|
@@ -41,7 +42,6 @@
|
|
|
41
42
|
"ai",
|
|
42
43
|
"agent",
|
|
43
44
|
"coding-agent",
|
|
44
|
-
"unorouter",
|
|
45
45
|
"terminal",
|
|
46
46
|
"llm"
|
|
47
47
|
],
|
|
@@ -51,4 +51,4 @@
|
|
|
51
51
|
"@types/node": "^22.10.2",
|
|
52
52
|
"typescript": "^5.7.2"
|
|
53
53
|
}
|
|
54
|
-
}
|
|
54
|
+
}
|