@thejeetsingh/kalcode 2.0.0 → 2.2.0
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/README.md +0 -4
- package/dist/bin/kalcode.d.ts +2 -0
- package/dist/bin/kalcode.js +12 -0
- package/dist/bin/kalcode.js.map +1 -0
- package/dist/src/agent/context.d.ts +6 -0
- package/dist/src/agent/context.js +60 -0
- package/dist/src/agent/context.js.map +1 -0
- package/dist/src/agent/history.d.ts +8 -0
- package/dist/src/agent/history.js +59 -0
- package/dist/src/agent/history.js.map +1 -0
- package/dist/src/agent/loop.d.ts +6 -0
- package/dist/src/agent/loop.js +235 -0
- package/dist/src/agent/loop.js.map +1 -0
- package/dist/src/agent/memory.d.ts +2 -0
- package/dist/src/agent/memory.js +27 -0
- package/dist/src/agent/memory.js.map +1 -0
- package/dist/src/agent/permissions.d.ts +5 -0
- package/dist/src/agent/permissions.js +66 -0
- package/dist/src/agent/permissions.js.map +1 -0
- package/dist/src/agent/text-tool-parser.d.ts +2 -0
- package/dist/src/agent/text-tool-parser.js +68 -0
- package/dist/src/agent/text-tool-parser.js.map +1 -0
- package/dist/src/api/client.d.ts +2 -0
- package/dist/src/api/client.js +86 -0
- package/dist/src/api/client.js.map +1 -0
- package/dist/src/api/stream-parser.d.ts +2 -0
- package/dist/src/api/stream-parser.js +97 -0
- package/dist/src/api/stream-parser.js.map +1 -0
- package/dist/src/config.d.ts +7 -0
- package/dist/src/config.js +52 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/constants.d.ts +25 -0
- package/{src/constants.ts → dist/src/constants.js} +17 -19
- package/dist/src/constants.js.map +1 -0
- package/dist/src/git/git.d.ts +15 -0
- package/dist/src/git/git.js +73 -0
- package/dist/src/git/git.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +415 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/proxy/server.d.ts +1 -0
- package/dist/src/proxy/server.js +92 -0
- package/dist/src/proxy/server.js.map +1 -0
- package/dist/src/tools/edit-file.d.ts +2 -0
- package/dist/src/tools/edit-file.js +88 -0
- package/dist/src/tools/edit-file.js.map +1 -0
- package/dist/src/tools/glob-tool.d.ts +2 -0
- package/dist/src/tools/glob-tool.js +52 -0
- package/dist/src/tools/glob-tool.js.map +1 -0
- package/dist/src/tools/grep.d.ts +2 -0
- package/dist/src/tools/grep.js +93 -0
- package/dist/src/tools/grep.js.map +1 -0
- package/dist/src/tools/list-directory.d.ts +2 -0
- package/dist/src/tools/list-directory.js +90 -0
- package/dist/src/tools/list-directory.js.map +1 -0
- package/dist/src/tools/read-file.d.ts +2 -0
- package/dist/src/tools/read-file.js +64 -0
- package/dist/src/tools/read-file.js.map +1 -0
- package/dist/src/tools/registry.d.ts +4 -0
- package/dist/src/tools/registry.js +32 -0
- package/dist/src/tools/registry.js.map +1 -0
- package/dist/src/tools/run-command.d.ts +2 -0
- package/dist/src/tools/run-command.js +98 -0
- package/dist/src/tools/run-command.js.map +1 -0
- package/dist/src/tools/write-file.d.ts +2 -0
- package/dist/src/tools/write-file.js +39 -0
- package/dist/src/tools/write-file.js.map +1 -0
- package/dist/src/types.d.ts +61 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/ui/input.d.ts +5 -0
- package/dist/src/ui/input.js +52 -0
- package/dist/src/ui/input.js.map +1 -0
- package/dist/src/ui/model-picker.d.ts +7 -0
- package/dist/src/ui/model-picker.js +70 -0
- package/dist/src/ui/model-picker.js.map +1 -0
- package/dist/src/ui/skills-picker.d.ts +2 -0
- package/dist/src/ui/skills-picker.js +95 -0
- package/dist/src/ui/skills-picker.js.map +1 -0
- package/dist/src/ui/skills.d.ts +14 -0
- package/dist/src/ui/skills.js +137 -0
- package/dist/src/ui/skills.js.map +1 -0
- package/dist/src/ui/spinner.d.ts +5 -0
- package/dist/src/ui/spinner.js +49 -0
- package/dist/src/ui/spinner.js.map +1 -0
- package/dist/src/ui/stream-renderer.d.ts +2 -0
- package/dist/src/ui/stream-renderer.js +66 -0
- package/dist/src/ui/stream-renderer.js.map +1 -0
- package/dist/src/ui/terminal.d.ts +24 -0
- package/dist/src/ui/terminal.js +272 -0
- package/dist/src/ui/terminal.js.map +1 -0
- package/package.json +16 -16
- package/api/health.ts +0 -10
- package/api/v1/chat/completions.ts +0 -59
- package/bin/kalcode.ts +0 -14
- package/src/agent/context.ts +0 -62
- package/src/agent/history.ts +0 -70
- package/src/agent/loop.ts +0 -282
- package/src/agent/memory.ts +0 -26
- package/src/agent/permissions.ts +0 -84
- package/src/agent/text-tool-parser.ts +0 -71
- package/src/api/client.ts +0 -110
- package/src/api/stream-parser.ts +0 -109
- package/src/config.ts +0 -61
- package/src/git/git.ts +0 -86
- package/src/index.ts +0 -403
- package/src/proxy/server.ts +0 -128
- package/src/tools/edit-file.ts +0 -97
- package/src/tools/glob-tool.ts +0 -59
- package/src/tools/grep.ts +0 -96
- package/src/tools/list-directory.ts +0 -101
- package/src/tools/read-file.ts +0 -71
- package/src/tools/registry.ts +0 -41
- package/src/tools/run-command.ts +0 -99
- package/src/tools/write-file.ts +0 -42
- package/src/types.ts +0 -68
- package/src/ui/input.ts +0 -60
- package/src/ui/model-picker.ts +0 -92
- package/src/ui/skills-picker.ts +0 -113
- package/src/ui/skills.ts +0 -152
- package/src/ui/spinner.ts +0 -56
- package/src/ui/stream-renderer.ts +0 -69
- package/src/ui/terminal.ts +0 -337
- package/tsconfig.json +0 -15
- package/vercel.json +0 -12
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import { glob } from "glob";
|
|
3
|
+
import { MAX_GLOB_RESULTS } from "../constants.js";
|
|
4
|
+
export const globTool = {
|
|
5
|
+
definition: {
|
|
6
|
+
type: "function",
|
|
7
|
+
function: {
|
|
8
|
+
name: "glob",
|
|
9
|
+
description: "Find files matching a glob pattern. Returns matching file paths sorted by modification time.",
|
|
10
|
+
parameters: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
pattern: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Glob pattern (e.g., '**/*.ts', 'src/**/*.json')",
|
|
16
|
+
},
|
|
17
|
+
path: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Base directory to search from. Default: current directory",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: ["pattern"],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
async execute(args) {
|
|
27
|
+
const pattern = String(args.pattern);
|
|
28
|
+
const basePath = resolve(String(args.path || "."));
|
|
29
|
+
try {
|
|
30
|
+
const matches = await glob(pattern, {
|
|
31
|
+
cwd: basePath,
|
|
32
|
+
dot: false,
|
|
33
|
+
ignore: ["node_modules/**", ".git/**"],
|
|
34
|
+
maxDepth: 20,
|
|
35
|
+
});
|
|
36
|
+
if (matches.length === 0) {
|
|
37
|
+
return `No files matching pattern: ${pattern} in ${basePath}`;
|
|
38
|
+
}
|
|
39
|
+
const limited = matches.sort().slice(0, MAX_GLOB_RESULTS);
|
|
40
|
+
let result = `Found ${limited.length} file(s) matching "${pattern}":\n`;
|
|
41
|
+
result += limited.join("\n");
|
|
42
|
+
if (matches.length > MAX_GLOB_RESULTS) {
|
|
43
|
+
result += `\n... (results limited to ${MAX_GLOB_RESULTS})`;
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
return `Error searching for files: ${err instanceof Error ? err.message : String(err)}`;
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=glob-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-tool.js","sourceRoot":"","sources":["../../../src/tools/glob-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,CAAC,MAAM,QAAQ,GAAgB;IACnC,UAAU,EAAE;QACV,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,MAAM;YACZ,WAAW,EACT,8FAA8F;YAChG,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,OAAO,EAAE;wBACP,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,iDAAiD;qBAC/D;oBACD,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,2DAA2D;qBACzE;iBACF;gBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;aACtB;SACF;KACF;IAED,KAAK,CAAC,OAAO,CAAC,IAAI;QAChB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;QAEnD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE;gBAClC,GAAG,EAAE,QAAQ;gBACb,GAAG,EAAE,KAAK;gBACV,MAAM,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC;gBACtC,QAAQ,EAAE,EAAE;aACb,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,8BAA8B,OAAO,OAAO,QAAQ,EAAE,CAAC;YAChE,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;YAC1D,IAAI,MAAM,GAAG,SAAS,OAAO,CAAC,MAAM,sBAAsB,OAAO,MAAM,CAAC;YACxE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,OAAO,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;gBACtC,MAAM,IAAI,6BAA6B,gBAAgB,GAAG,CAAC;YAC7D,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1F,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { MAX_GREP_RESULTS } from "../constants.js";
|
|
3
|
+
export const grepTool = {
|
|
4
|
+
definition: {
|
|
5
|
+
type: "function",
|
|
6
|
+
function: {
|
|
7
|
+
name: "grep",
|
|
8
|
+
description: "Search file contents for a pattern. Uses ripgrep if available, otherwise falls back to grep. Returns matching lines with file paths and line numbers.",
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
pattern: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Search pattern (regex supported)",
|
|
15
|
+
},
|
|
16
|
+
path: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "Directory or file to search in. Default: current directory",
|
|
19
|
+
},
|
|
20
|
+
include: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "File glob pattern to include (e.g., '*.ts')",
|
|
23
|
+
},
|
|
24
|
+
maxResults: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: `Maximum number of results. Default: ${MAX_GREP_RESULTS}`,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["pattern"],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
async execute(args) {
|
|
34
|
+
const pattern = String(args.pattern);
|
|
35
|
+
const searchPath = String(args.path || ".");
|
|
36
|
+
const include = args.include ? String(args.include) : null;
|
|
37
|
+
const maxResults = Number(args.maxResults) || MAX_GREP_RESULTS;
|
|
38
|
+
const hasRg = await checkCommand("rg");
|
|
39
|
+
let cmd;
|
|
40
|
+
if (hasRg) {
|
|
41
|
+
cmd = `rg --line-number --max-count ${maxResults} --no-heading --glob '!node_modules' --glob '!.git'`;
|
|
42
|
+
if (include)
|
|
43
|
+
cmd += ` --glob '${include}'`;
|
|
44
|
+
cmd += ` -- ${escapeShellArg(pattern)} ${escapeShellArg(searchPath)}`;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
cmd = `grep -rn --max-count=${maxResults} --exclude-dir=node_modules --exclude-dir=.git`;
|
|
48
|
+
if (include)
|
|
49
|
+
cmd += ` --include='${include}'`;
|
|
50
|
+
cmd += ` -- ${escapeShellArg(pattern)} ${escapeShellArg(searchPath)}`;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const { stdout } = await runShell(cmd);
|
|
54
|
+
if (!stdout.trim()) {
|
|
55
|
+
return `No matches found for pattern: ${pattern}`;
|
|
56
|
+
}
|
|
57
|
+
const lines = stdout.trim().split("\n");
|
|
58
|
+
const limited = lines.slice(0, maxResults);
|
|
59
|
+
let result = limited.join("\n");
|
|
60
|
+
if (lines.length > maxResults) {
|
|
61
|
+
result += `\n... (${lines.length - maxResults} more matches)`;
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
return `Error searching: ${err instanceof Error ? err.message : String(err)}`;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
function runShell(cmd) {
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
const proc = spawn("sh", ["-c", cmd], { stdio: ["ignore", "pipe", "pipe"] });
|
|
73
|
+
let stdout = "";
|
|
74
|
+
let stderr = "";
|
|
75
|
+
proc.stdout.on("data", (d) => { stdout += d.toString(); });
|
|
76
|
+
proc.stderr.on("data", (d) => { stderr += d.toString(); });
|
|
77
|
+
proc.on("close", (code) => resolve({ stdout, stderr, exitCode: code ?? 1 }));
|
|
78
|
+
proc.on("error", (err) => resolve({ stdout: "", stderr: err.message, exitCode: 1 }));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async function checkCommand(cmd) {
|
|
82
|
+
try {
|
|
83
|
+
const { exitCode } = await runShell(`which ${cmd}`);
|
|
84
|
+
return exitCode === 0;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function escapeShellArg(arg) {
|
|
91
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=grep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/tools/grep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { readdirSync, statSync, existsSync } from "fs";
|
|
2
|
+
import { resolve, join } from "path";
|
|
3
|
+
import { MAX_DIR_ENTRIES, MAX_DIR_DEPTH } from "../constants.js";
|
|
4
|
+
export const listDirectoryTool = {
|
|
5
|
+
definition: {
|
|
6
|
+
type: "function",
|
|
7
|
+
function: {
|
|
8
|
+
name: "listDirectory",
|
|
9
|
+
description: "List the contents of a directory. Shows file names, types, and sizes.",
|
|
10
|
+
parameters: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
dirPath: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Path to the directory to list. Default: current directory",
|
|
16
|
+
},
|
|
17
|
+
recursive: {
|
|
18
|
+
type: "boolean",
|
|
19
|
+
description: "List recursively (max depth 3). Default: false",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
async execute(args) {
|
|
26
|
+
const dirPath = resolve(String(args.dirPath || "."));
|
|
27
|
+
const recursive = Boolean(args.recursive);
|
|
28
|
+
if (!existsSync(dirPath)) {
|
|
29
|
+
return `Error: Directory not found: ${dirPath}`;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const entries = [];
|
|
33
|
+
listDir(dirPath, "", recursive ? MAX_DIR_DEPTH : 0, entries);
|
|
34
|
+
if (entries.length === 0) {
|
|
35
|
+
return `Directory is empty: ${dirPath}`;
|
|
36
|
+
}
|
|
37
|
+
let result = `Contents of ${dirPath} (${entries.length} entries):\n`;
|
|
38
|
+
result += entries.join("\n");
|
|
39
|
+
if (entries.length >= MAX_DIR_ENTRIES) {
|
|
40
|
+
result += `\n... (limited to ${MAX_DIR_ENTRIES} entries)`;
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
return `Error listing directory: ${err instanceof Error ? err.message : String(err)}`;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
function listDir(basePath, prefix, depth, entries) {
|
|
50
|
+
if (entries.length >= MAX_DIR_ENTRIES)
|
|
51
|
+
return;
|
|
52
|
+
let items;
|
|
53
|
+
try {
|
|
54
|
+
items = readdirSync(join(basePath, prefix));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
items.sort();
|
|
60
|
+
for (const item of items) {
|
|
61
|
+
if (entries.length >= MAX_DIR_ENTRIES)
|
|
62
|
+
return;
|
|
63
|
+
const relPath = prefix ? `${prefix}/${item}` : item;
|
|
64
|
+
const fullPath = join(basePath, relPath);
|
|
65
|
+
try {
|
|
66
|
+
const stat = statSync(fullPath);
|
|
67
|
+
if (stat.isDirectory()) {
|
|
68
|
+
entries.push(`${relPath}/`);
|
|
69
|
+
if (depth > 0) {
|
|
70
|
+
listDir(basePath, relPath, depth - 1, entries);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const size = formatSize(stat.size);
|
|
75
|
+
entries.push(`${relPath} (${size})`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
entries.push(`${relPath} (unreadable)`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function formatSize(bytes) {
|
|
84
|
+
if (bytes < 1024)
|
|
85
|
+
return `${bytes}B`;
|
|
86
|
+
if (bytes < 1024 * 1024)
|
|
87
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
88
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=list-directory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-directory.js","sourceRoot":"","sources":["../../../src/tools/list-directory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { readFileSync, statSync, existsSync } from "fs";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import { MAX_FILE_SIZE, DEFAULT_LINE_LIMIT } from "../constants.js";
|
|
4
|
+
export const readFileTool = {
|
|
5
|
+
definition: {
|
|
6
|
+
type: "function",
|
|
7
|
+
function: {
|
|
8
|
+
name: "readFile",
|
|
9
|
+
description: "Read the contents of a file with line numbers. Returns line-numbered output. Use offset and limit to read specific portions of large files.",
|
|
10
|
+
parameters: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
filePath: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Path to the file to read (absolute or relative to cwd)",
|
|
16
|
+
},
|
|
17
|
+
offset: {
|
|
18
|
+
type: "number",
|
|
19
|
+
description: "Line number to start reading from (1-based). Default: 1",
|
|
20
|
+
},
|
|
21
|
+
limit: {
|
|
22
|
+
type: "number",
|
|
23
|
+
description: `Maximum number of lines to read. Default: ${DEFAULT_LINE_LIMIT}`,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
required: ["filePath"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
async execute(args) {
|
|
31
|
+
const filePath = resolve(String(args.filePath));
|
|
32
|
+
const offset = Math.max(1, Number(args.offset) || 1);
|
|
33
|
+
const limit = Number(args.limit) || DEFAULT_LINE_LIMIT;
|
|
34
|
+
if (!existsSync(filePath)) {
|
|
35
|
+
return `Error: File not found: ${filePath}`;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const stat = statSync(filePath);
|
|
39
|
+
if (stat.isDirectory()) {
|
|
40
|
+
return `Error: Path is a directory, not a file: ${filePath}`;
|
|
41
|
+
}
|
|
42
|
+
if (stat.size > MAX_FILE_SIZE) {
|
|
43
|
+
return `Error: File too large (${(stat.size / 1024 / 1024).toFixed(1)}MB). Use offset/limit to read portions.`;
|
|
44
|
+
}
|
|
45
|
+
const content = readFileSync(filePath, "utf-8");
|
|
46
|
+
const lines = content.split("\n");
|
|
47
|
+
const startIdx = offset - 1;
|
|
48
|
+
const endIdx = Math.min(startIdx + limit, lines.length);
|
|
49
|
+
const slice = lines.slice(startIdx, endIdx);
|
|
50
|
+
const numbered = slice
|
|
51
|
+
.map((line, i) => {
|
|
52
|
+
const lineNum = String(startIdx + i + 1).padStart(4, " ");
|
|
53
|
+
return `${lineNum} | ${line}`;
|
|
54
|
+
})
|
|
55
|
+
.join("\n");
|
|
56
|
+
const header = `File: ${filePath} (${lines.length} lines total, showing ${offset}-${endIdx})`;
|
|
57
|
+
return `${header}\n${numbered}`;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
return `Error reading file: ${err instanceof Error ? err.message : String(err)}`;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=read-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../../src/tools/read-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ToolDefinition, ToolHandler } from "../types.js";
|
|
2
|
+
export declare function getToolHandler(name: string): ToolHandler | undefined;
|
|
3
|
+
export declare function getAllDefinitions(): ToolDefinition[];
|
|
4
|
+
export declare function executeToolCall(name: string, args: Record<string, unknown>): Promise<string>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readFileTool } from "./read-file.js";
|
|
2
|
+
import { writeFileTool } from "./write-file.js";
|
|
3
|
+
import { editFileTool } from "./edit-file.js";
|
|
4
|
+
import { runCommandTool } from "./run-command.js";
|
|
5
|
+
import { grepTool } from "./grep.js";
|
|
6
|
+
import { globTool } from "./glob-tool.js";
|
|
7
|
+
import { listDirectoryTool } from "./list-directory.js";
|
|
8
|
+
const tools = new Map();
|
|
9
|
+
function register(handler) {
|
|
10
|
+
tools.set(handler.definition.function.name, handler);
|
|
11
|
+
}
|
|
12
|
+
register(readFileTool);
|
|
13
|
+
register(writeFileTool);
|
|
14
|
+
register(editFileTool);
|
|
15
|
+
register(runCommandTool);
|
|
16
|
+
register(grepTool);
|
|
17
|
+
register(globTool);
|
|
18
|
+
register(listDirectoryTool);
|
|
19
|
+
export function getToolHandler(name) {
|
|
20
|
+
return tools.get(name);
|
|
21
|
+
}
|
|
22
|
+
export function getAllDefinitions() {
|
|
23
|
+
return Array.from(tools.values()).map((t) => t.definition);
|
|
24
|
+
}
|
|
25
|
+
export function executeToolCall(name, args) {
|
|
26
|
+
const handler = tools.get(name);
|
|
27
|
+
if (!handler) {
|
|
28
|
+
return Promise.resolve(`Error: Unknown tool "${name}"`);
|
|
29
|
+
}
|
|
30
|
+
return handler.execute(args);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/tools/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,KAAK,GAA6B,IAAI,GAAG,EAAE,CAAC;AAElD,SAAS,QAAQ,CAAC,OAAoB;IACpC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACvD,CAAC;AAED,QAAQ,CAAC,YAAY,CAAC,CAAC;AACvB,QAAQ,CAAC,aAAa,CAAC,CAAC;AACxB,QAAQ,CAAC,YAAY,CAAC,CAAC;AACvB,QAAQ,CAAC,cAAc,CAAC,CAAC;AACzB,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACnB,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACnB,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAE5B,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,IAA6B;IAE7B,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,OAAO,CAAC,OAAO,CAAC,wBAAwB,IAAI,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { DEFAULT_COMMAND_TIMEOUT, MAX_COMMAND_TIMEOUT, MAX_OUTPUT_BYTES } from "../constants.js";
|
|
4
|
+
export const runCommandTool = {
|
|
5
|
+
definition: {
|
|
6
|
+
type: "function",
|
|
7
|
+
function: {
|
|
8
|
+
name: "runCommand",
|
|
9
|
+
description: "Execute a shell command and return its output. Default timeout is 30s and hard-capped at 45s. Output is truncated at 50KB.",
|
|
10
|
+
parameters: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
command: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "The shell command to execute",
|
|
16
|
+
},
|
|
17
|
+
cwd: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Working directory for the command. Default: current directory",
|
|
20
|
+
},
|
|
21
|
+
timeout: {
|
|
22
|
+
type: "number",
|
|
23
|
+
description: "Timeout in milliseconds. Default: 30000, max: 45000",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
required: ["command"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
async execute(args) {
|
|
31
|
+
const command = String(args.command);
|
|
32
|
+
const cwd = args.cwd ? resolve(String(args.cwd)) : process.cwd();
|
|
33
|
+
const requestedTimeout = Number(args.timeout) || DEFAULT_COMMAND_TIMEOUT;
|
|
34
|
+
const timeout = Math.min(Math.max(1_000, requestedTimeout), MAX_COMMAND_TIMEOUT);
|
|
35
|
+
try {
|
|
36
|
+
const { exitCode, stdout, stderr } = await runShell(command, cwd, timeout);
|
|
37
|
+
if (exitCode === 124) {
|
|
38
|
+
return [
|
|
39
|
+
`Exit code: 124`,
|
|
40
|
+
`STDERR:`,
|
|
41
|
+
`Command timed out after ${Math.round(timeout / 1000)}s.`,
|
|
42
|
+
`Tip: use a shorter command, reduce scope, or run background/dev servers manually outside kalcode.`,
|
|
43
|
+
].join("\n\n");
|
|
44
|
+
}
|
|
45
|
+
let stdoutTrimmed = stdout;
|
|
46
|
+
let stderrTrimmed = stderr;
|
|
47
|
+
if (stdoutTrimmed.length > MAX_OUTPUT_BYTES) {
|
|
48
|
+
stdoutTrimmed = stdoutTrimmed.slice(0, MAX_OUTPUT_BYTES) + "\n... (output truncated)";
|
|
49
|
+
}
|
|
50
|
+
if (stderrTrimmed.length > MAX_OUTPUT_BYTES) {
|
|
51
|
+
stderrTrimmed = stderrTrimmed.slice(0, MAX_OUTPUT_BYTES) + "\n... (output truncated)";
|
|
52
|
+
}
|
|
53
|
+
let result = `Exit code: ${exitCode}`;
|
|
54
|
+
if (stdoutTrimmed.trim())
|
|
55
|
+
result += `\n\nSTDOUT:\n${stdoutTrimmed.trim()}`;
|
|
56
|
+
if (stderrTrimmed.trim())
|
|
57
|
+
result += `\n\nSTDERR:\n${stderrTrimmed.trim()}`;
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
return `Error running command: ${err instanceof Error ? err.message : String(err)}`;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
function runShell(command, cwd, timeout) {
|
|
66
|
+
return new Promise((resolve) => {
|
|
67
|
+
const proc = spawn("sh", ["-c", command], {
|
|
68
|
+
cwd,
|
|
69
|
+
env: { ...process.env },
|
|
70
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
71
|
+
});
|
|
72
|
+
let stdout = "";
|
|
73
|
+
let stderr = "";
|
|
74
|
+
let timedOut = false;
|
|
75
|
+
const timer = setTimeout(() => {
|
|
76
|
+
timedOut = true;
|
|
77
|
+
try {
|
|
78
|
+
proc.kill("SIGKILL");
|
|
79
|
+
}
|
|
80
|
+
catch { /* already exited */ }
|
|
81
|
+
}, timeout);
|
|
82
|
+
proc.stdout.on("data", (d) => { stdout += d.toString(); });
|
|
83
|
+
proc.stderr.on("data", (d) => { stderr += d.toString(); });
|
|
84
|
+
proc.on("close", (code) => {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
resolve({
|
|
87
|
+
exitCode: timedOut ? 124 : (code ?? 1),
|
|
88
|
+
stdout,
|
|
89
|
+
stderr,
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
proc.on("error", (err) => {
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
resolve({ exitCode: 1, stdout: "", stderr: err.message });
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=run-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../../src/tools/run-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync } from "fs";
|
|
2
|
+
import { resolve, dirname } from "path";
|
|
3
|
+
export const writeFileTool = {
|
|
4
|
+
definition: {
|
|
5
|
+
type: "function",
|
|
6
|
+
function: {
|
|
7
|
+
name: "writeFile",
|
|
8
|
+
description: "Write content to a file. Creates the file if it doesn't exist. Automatically creates parent directories as needed.",
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
filePath: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Path to the file to write (absolute or relative to cwd)",
|
|
15
|
+
},
|
|
16
|
+
content: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "Content to write to the file",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
required: ["filePath", "content"],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
async execute(args) {
|
|
26
|
+
const filePath = resolve(String(args.filePath));
|
|
27
|
+
const content = String(args.content);
|
|
28
|
+
try {
|
|
29
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
30
|
+
writeFileSync(filePath, content);
|
|
31
|
+
const lineCount = content.split("\n").length;
|
|
32
|
+
return `Successfully wrote ${lineCount} lines to ${filePath}`;
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
return `Error writing file: ${err instanceof Error ? err.message : String(err)}`;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=write-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.js","sourceRoot":"","sources":["../../../src/tools/write-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGxC,MAAM,CAAC,MAAM,aAAa,GAAgB;IACxC,UAAU,EAAE;QACV,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,WAAW;YACjB,WAAW,EACT,oHAAoH;YACtH,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,QAAQ,EAAE;wBACR,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,yDAAyD;qBACvE;oBACD,OAAO,EAAE;wBACP,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,8BAA8B;qBAC5C;iBACF;gBACD,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;aAClC;SACF;KACF;IAED,KAAK,CAAC,OAAO,CAAC,IAAI;QAChB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAErC,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACjC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAC7C,OAAO,sBAAsB,SAAS,aAAa,QAAQ,EAAE,CAAC;QAChE,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACnF,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export interface Config {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
model: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Message {
|
|
6
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
7
|
+
content: string | null;
|
|
8
|
+
tool_calls?: ToolCall[];
|
|
9
|
+
tool_call_id?: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ToolCall {
|
|
13
|
+
id: string;
|
|
14
|
+
type: "function";
|
|
15
|
+
function: {
|
|
16
|
+
name: string;
|
|
17
|
+
arguments: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface ToolDefinition {
|
|
21
|
+
type: "function";
|
|
22
|
+
function: {
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
parameters: {
|
|
26
|
+
type: "object";
|
|
27
|
+
properties: Record<string, unknown>;
|
|
28
|
+
required?: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface StreamDelta {
|
|
33
|
+
type: "content" | "tool_call" | "done" | "error";
|
|
34
|
+
content?: string;
|
|
35
|
+
toolCall?: {
|
|
36
|
+
index: number;
|
|
37
|
+
id?: string;
|
|
38
|
+
function?: {
|
|
39
|
+
name?: string;
|
|
40
|
+
arguments?: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
error?: string;
|
|
44
|
+
usage?: TokenUsage;
|
|
45
|
+
}
|
|
46
|
+
export interface ToolHandler {
|
|
47
|
+
definition: ToolDefinition;
|
|
48
|
+
execute: (args: Record<string, unknown>) => Promise<string>;
|
|
49
|
+
}
|
|
50
|
+
export interface ToolCallAccumulator {
|
|
51
|
+
id: string;
|
|
52
|
+
function: {
|
|
53
|
+
name: string;
|
|
54
|
+
arguments: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export interface TokenUsage {
|
|
58
|
+
prompt_tokens: number;
|
|
59
|
+
completion_tokens: number;
|
|
60
|
+
total_tokens: number;
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|