summaryrefslogtreecommitdiffhomepage
path: root/packages/core/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'packages/core/src/tools')
-rw-r--r--packages/core/src/tools/bash-arity.ts60
-rw-r--r--packages/core/src/tools/run-shell.ts14
-rw-r--r--packages/core/src/tools/shell-analyze.ts29
3 files changed, 60 insertions, 43 deletions
diff --git a/packages/core/src/tools/bash-arity.ts b/packages/core/src/tools/bash-arity.ts
index 5dde955..1aaba8e 100644
--- a/packages/core/src/tools/bash-arity.ts
+++ b/packages/core/src/tools/bash-arity.ts
@@ -1,37 +1,37 @@
// Hardcoded dictionary of well-known commands and their arity
// (number of tokens that form the "human-understandable" prefix)
const ARITY: Record<string, number> = {
- "git": 2, // "git checkout", "git commit", etc.
- "npm": 3, // "npm run dev", "npm install -g"
- "docker": 2, // "docker compose", "docker build"
- "kubectl": 2, // "kubectl get", "kubectl apply"
- "bun": 2, // "bun install", "bun test"
- "cargo": 2, // "cargo build", "cargo test"
- "go": 2, // "go build", "go test"
- "python": 2, // "python -m", "python script.py"
- "python3": 2,
- "pip": 2,
- "pip3": 2,
- "brew": 2,
- "apt": 2,
+ git: 2, // "git checkout", "git commit", etc.
+ npm: 3, // "npm run dev", "npm install -g"
+ docker: 2, // "docker compose", "docker build"
+ kubectl: 2, // "kubectl get", "kubectl apply"
+ bun: 2, // "bun install", "bun test"
+ cargo: 2, // "cargo build", "cargo test"
+ go: 2, // "go build", "go test"
+ python: 2, // "python -m", "python script.py"
+ python3: 2,
+ pip: 2,
+ pip3: 2,
+ brew: 2,
+ apt: 2,
"apt-get": 2,
- "dnf": 2,
- "yum": 2,
- "pacman": 2,
- "systemctl": 2,
- "journalctl": 2,
- "ssh": 2,
- "scp": 2,
- "rsync": 2,
- "curl": 2, // "curl -X", "curl https://"
- "wget": 2,
- "tar": 2, // "tar -xzf", "tar -czf"
- "zip": 2,
- "unzip": 2,
- "chown": 2,
- "chmod": 2,
- "mount": 2,
- "umount": 2,
+ dnf: 2,
+ yum: 2,
+ pacman: 2,
+ systemctl: 2,
+ journalctl: 2,
+ ssh: 2,
+ scp: 2,
+ rsync: 2,
+ curl: 2, // "curl -X", "curl https://"
+ wget: 2,
+ tar: 2, // "tar -xzf", "tar -czf"
+ zip: 2,
+ unzip: 2,
+ chown: 2,
+ chmod: 2,
+ mount: 2,
+ umount: 2,
// Default: all other commands are arity 1
};
diff --git a/packages/core/src/tools/run-shell.ts b/packages/core/src/tools/run-shell.ts
index d549316..608c91d 100644
--- a/packages/core/src/tools/run-shell.ts
+++ b/packages/core/src/tools/run-shell.ts
@@ -11,12 +11,12 @@ export function createRunShellTool(workingDirectory: string): ToolDefinition {
"Execute a shell command in the working directory. Returns stdout, stderr, and exit code. Use for running tests, builds, git operations, package management, and other development tasks.",
parameters: z.object({
command: z.string().describe("The shell command to execute"),
- timeout: z
- .number()
- .optional()
- .describe("Timeout in milliseconds (default 2 minutes)"),
+ timeout: z.number().optional().describe("Timeout in milliseconds (default 2 minutes)"),
}),
- execute: async (args: Record<string, unknown>, context?: ToolExecuteContext): Promise<string> => {
+ execute: async (
+ args: Record<string, unknown>,
+ context?: ToolExecuteContext,
+ ): Promise<string> => {
const command = args.command as string;
const timeout = (args.timeout as number | undefined) ?? DEFAULT_TIMEOUT;
@@ -68,7 +68,5 @@ export function createRunShellTool(workingDirectory: string): ToolDefinition {
}
function getShell(): [string, string[]] {
- return process.platform === "win32"
- ? ["powershell", ["-Command"]]
- : ["bash", ["-c"]];
+ return process.platform === "win32" ? ["powershell", ["-Command"]] : ["bash", ["-c"]];
}
diff --git a/packages/core/src/tools/shell-analyze.ts b/packages/core/src/tools/shell-analyze.ts
index 23bbfc9..b70108b 100644
--- a/packages/core/src/tools/shell-analyze.ts
+++ b/packages/core/src/tools/shell-analyze.ts
@@ -1,6 +1,6 @@
-import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
import { readFile } from "node:fs/promises";
import { createRequire } from "node:module";
+import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
import * as BashArity from "./bash-arity.js";
// Commands that touch files — triggers external_directory check.
@@ -12,9 +12,27 @@ import * as BashArity from "./bash-arity.js";
// - `cd` state changes: we don't track cwd mutations across pipeline stages
// - Interpreter escapes: `python -c "open('/etc/passwd')"`, `node -e "..."` bypass this entirely
const FILE_COMMANDS = new Set([
- "rm", "cp", "mv", "mkdir", "touch", "chmod", "chown",
- "cat", "ls", "find", "grep",
- "head", "tail", "less", "more", "wc", "diff", "file", "stat", "du", "df",
+ "rm",
+ "cp",
+ "mv",
+ "mkdir",
+ "touch",
+ "chmod",
+ "chown",
+ "cat",
+ "ls",
+ "find",
+ "grep",
+ "head",
+ "tail",
+ "less",
+ "more",
+ "wc",
+ "diff",
+ "file",
+ "stat",
+ "du",
+ "df",
]);
// Lazy-initialized parser
@@ -142,6 +160,7 @@ function isInsideWorkspace(filePath: string, wd: string): boolean {
// rel === "" means filePath IS the workspace root — that is inside.
// If relative path starts with "../" or is ".." exactly, or is an absolute path
// (on Windows when drives differ), the file is outside the workspace.
- const isOutside = rel.startsWith(`..${sep}`) || rel.startsWith("../") || rel === ".." || isAbsolute(rel);
+ const isOutside =
+ rel.startsWith(`..${sep}`) || rel.startsWith("../") || rel === ".." || isAbsolute(rel);
return !isOutside;
}