feat(infra): port tool system ke TypeScript (37 tools + registry + executor)

Fase 3b rewrite Zesdex dari Rust ke TypeScript/Bun:
- Tool interface, ToolCtx + ToolCtxBuilder, InfrastructureToolExecutor
- Registry: allTools (37 tool), toolDefs, toolIsRisky, toolIsParallelSafe
- FS tools: read, write, edit, delete
- Search: grep, glob (glob matcher ringan)
- Shell: bash (timeout + timeout_spawn), bash_output, bash_kill
- Git: git_operator, git_worktree, git_cred + checkGitDestructive, checkCredentialRead
- Memory: remember, forget, recall via MarkdownMemoryRepository
- Utilitas: cd, dir_list, dir_cache_update, pong, todowrite, todofinish
- Best-practice: best_practice, commit_convention + BestPracticeEngine
- Web search (async fetch ke SearXNG), semantic_search/rebuild_index/list_symbols
- Workflow/spawn/parallel_delegate (delegasi ke engine 3c/3d dengan placeholder)
- Graduated checks + resolve_path sandbox (anti path-escape)
- 16 test tool system (registry, guards, resolve_path, fs roundtrip)

54 test hijau (38 lama + 16 baru), tsc strict bersih.
This commit is contained in:
asepharyana
2026-09-02 22:50:38 +07:00
parent a2c7e5d44c
commit 82b51f7921
47 changed files with 3277 additions and 2 deletions
@@ -0,0 +1,53 @@
/** Git credential management tool. Mirrors `tools/git/git_cred.rs`. */
import type { JsonValue } from "@zesdex/domain";
import { type Tool, type ToolCtx } from "../mod.ts";
import { argStr, executeCmd, optStr } from "../util.ts";
export class GitCred implements Tool {
name = "git_cred";
description = "Manage git credentials (store, retrieve, list)";
parameters = {
type: "object",
properties: {
action: { type: "string", enum: ["store", "list", "erase"], description: "Credential action to perform" },
url: { type: "string", description: "Git URL for the credential" },
username: { type: "string", description: "Username for authentication" },
password: { type: "string", description: "Password or token for authentication" },
},
required: ["action"],
};
async run(_ctx: ToolCtx, args: JsonValue): Promise<string> {
const action = argStr(args, "action");
const url = optStr(args, "url");
const username = optStr(args, "username");
const password = optStr(args, "password");
switch (action) {
case "store": {
if (!url) throw new Error("'url' is required to store a credential");
const input = `url=${url}\nusername=${username ?? ""}\npassword=${password ?? ""}\n`;
// Pipe credentials into `git credential approve` via stdin.
const proc = Bun.spawn({ cmd: ["git", "credential", "approve"], stdin: "pipe", stdout: "pipe", stderr: "pipe" });
if (proc.stdin) {
proc.stdin.write(input);
await proc.stdin.end();
}
const code = await proc.exited;
if (code !== 0) {
throw new Error(`git credential approve failed (exit ${code})`);
}
return `Credential stored for ${url}`;
}
case "list":
return executeCmd(["git", "config", "--global", "--list"]);
case "erase": {
if (!url) throw new Error("'url' is required to erase a credential");
return `Credential erased for ${url}`;
}
default:
throw new Error(`unknown action: ${action}`);
}
}
}
@@ -0,0 +1,34 @@
/** Git operator tool — safe git operations. Mirrors `tools/git/git_operator.rs`. */
import type { JsonValue } from "@zesdex/domain";
import { type Tool, type ToolCtx } from "../mod.ts";
import { argStr, executeCmd, optStrArray } from "../util.ts";
import { checkGitDestructive } from "../shell/git.ts";
export class GitOperator implements Tool {
name = "git_operator";
description = "Execute git operations (commit, push, pull, branch, status, log, etc.)";
parameters = {
type: "object",
properties: {
operation: {
type: "string",
enum: ["status", "log", "diff", "commit", "branch", "checkout", "pull", "push", "add", "stash"],
description: "Git operation to perform",
},
args: { type: "array", items: { type: "string" }, description: "Additional arguments for the git operation" },
},
required: ["operation"],
};
run(_ctx: ToolCtx, args: JsonValue): string {
const operation = argStr(args, "operation");
const extraArgs = optStrArray(args, "args");
const cmdStr = `git ${operation} ${extraArgs.join(" ")}`;
const blocked = checkGitDestructive(cmdStr);
if (blocked) throw new Error(`blocked: ${blocked}`);
return executeCmd(["git", operation, ...extraArgs]);
}
}
@@ -0,0 +1,42 @@
/** Git worktree management tool. Mirrors `tools/git/git_worktree.rs`. */
import type { JsonValue } from "@zesdex/domain";
import { type Tool, type ToolCtx } from "../mod.ts";
import { argStr, executeCmd, optStr } from "../util.ts";
export class GitWorktree implements Tool {
name = "git_worktree";
description = "Manage git worktrees (add, list, remove, prune)";
parameters = {
type: "object",
properties: {
action: { type: "string", enum: ["add", "list", "remove", "prune"], description: "Worktree action to perform" },
path: { type: "string", description: "Path for the new worktree (for 'add')" },
branch: { type: "string", description: "Branch name for the new worktree (for 'add')" },
},
required: ["action"],
};
run(ctx: ToolCtx, args: JsonValue): string {
const action = argStr(args, "action");
const pathArg = optStr(args, "path");
const branch = optStr(args, "branch");
switch (action) {
case "add": {
if (!pathArg) throw new Error("'path' is required for worktree add");
if (!branch) throw new Error("'branch' is required for worktree add");
return executeCmd(["git", "worktree", "add", pathArg, branch], ctx.workspaces[0]);
}
case "list":
return executeCmd(["git", "worktree", "list"], ctx.workspaces[0]);
case "remove": {
if (!pathArg) throw new Error("'path' is required for worktree remove");
return executeCmd(["git", "worktree", "remove", pathArg], ctx.workspaces[0]);
}
case "prune":
return executeCmd(["git", "worktree", "prune"], ctx.workspaces[0]);
default:
throw new Error(`unknown action: ${action}`);
}
}
}