@kavienw/deepseek-cli 0.1.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 +470 -0
- package/dist/agent.js +864 -0
- package/dist/agent.js.map +1 -0
- package/dist/attachments.js +54 -0
- package/dist/attachments.js.map +1 -0
- package/dist/btw.js +52 -0
- package/dist/btw.js.map +1 -0
- package/dist/client.js +88 -0
- package/dist/client.js.map +1 -0
- package/dist/commands.js +922 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.js +98 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks.js +90 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.js +149 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.js +408 -0
- package/dist/mcp.js.map +1 -0
- package/dist/permissions.js +30 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plugins.js +341 -0
- package/dist/plugins.js.map +1 -0
- package/dist/project.js +114 -0
- package/dist/project.js.map +1 -0
- package/dist/session.js +57 -0
- package/dist/session.js.map +1 -0
- package/dist/skills.js +147 -0
- package/dist/skills.js.map +1 -0
- package/dist/todo.js +67 -0
- package/dist/todo.js.map +1 -0
- package/dist/tools/bash.js +61 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/diff.js +26 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/edit.js +73 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.js +47 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.js +133 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.js +60 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read.js +62 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/setThinking.js +46 -0
- package/dist/tools/setThinking.js.map +1 -0
- package/dist/tools/task.js +40 -0
- package/dist/tools/task.js.map +1 -0
- package/dist/tools/todo.js +73 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/webFetch.js +64 -0
- package/dist/tools/webFetch.js.map +1 -0
- package/dist/tools/webSearch.js +200 -0
- package/dist/tools/webSearch.js.map +1 -0
- package/dist/tools/write.js +46 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/ui/render.js +248 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/repl.js +429 -0
- package/dist/ui/repl.js.map +1 -0
- package/package.json +48 -0
package/dist/skills.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { findProjectRoot } from "./project.js";
|
|
5
|
+
import { enabledPluginSkillSources } from "./plugins.js";
|
|
6
|
+
const SKILL_DIR = path.join(".deepseek", "skills");
|
|
7
|
+
const GLOBAL_SKILL_DIR = path.join(os.homedir(), ".deepseek-cli", "skills");
|
|
8
|
+
function normalizeCommandName(value) {
|
|
9
|
+
return value
|
|
10
|
+
.trim()
|
|
11
|
+
.replace(/^\//, "")
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
14
|
+
.replace(/^-+|-+$/g, "");
|
|
15
|
+
}
|
|
16
|
+
function parseSkillFile(raw) {
|
|
17
|
+
if (!raw.startsWith("---\n"))
|
|
18
|
+
return { metadata: {}, body: raw.trim() };
|
|
19
|
+
const end = raw.indexOf("\n---", 4);
|
|
20
|
+
if (end === -1)
|
|
21
|
+
return { metadata: {}, body: raw.trim() };
|
|
22
|
+
const frontmatter = raw.slice(4, end).trim();
|
|
23
|
+
const body = raw.slice(end + "\n---".length).trim();
|
|
24
|
+
const metadata = {};
|
|
25
|
+
for (const line of frontmatter.split("\n")) {
|
|
26
|
+
const idx = line.indexOf(":");
|
|
27
|
+
if (idx === -1)
|
|
28
|
+
continue;
|
|
29
|
+
const key = line.slice(0, idx).trim().toLowerCase();
|
|
30
|
+
const value = line.slice(idx + 1).trim().replace(/^['\"]|['\"]$/g, "");
|
|
31
|
+
if (key && value)
|
|
32
|
+
metadata[key] = value;
|
|
33
|
+
}
|
|
34
|
+
return { metadata, body };
|
|
35
|
+
}
|
|
36
|
+
function readSkillFile(file, scope, plugin) {
|
|
37
|
+
try {
|
|
38
|
+
const raw = fs.readFileSync(file, "utf8");
|
|
39
|
+
const parsed = parseSkillFile(raw);
|
|
40
|
+
const inferredName = path.basename(file, path.extname(file));
|
|
41
|
+
const name = normalizeCommandName(parsed.metadata.command ?? parsed.metadata.name ?? inferredName);
|
|
42
|
+
if (!name)
|
|
43
|
+
return null;
|
|
44
|
+
return {
|
|
45
|
+
name,
|
|
46
|
+
usage: `/${name}`,
|
|
47
|
+
description: parsed.metadata.description ?? parsed.metadata.summary ?? "custom skill",
|
|
48
|
+
prompt: parsed.body,
|
|
49
|
+
source: file,
|
|
50
|
+
scope,
|
|
51
|
+
plugin,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function loadSkillDir(dir, scope, plugin) {
|
|
59
|
+
if (!fs.existsSync(dir))
|
|
60
|
+
return [];
|
|
61
|
+
const skills = [];
|
|
62
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
63
|
+
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
64
|
+
continue;
|
|
65
|
+
const skill = readSkillFile(path.join(dir, entry.name), scope, plugin);
|
|
66
|
+
if (skill)
|
|
67
|
+
skills.push(skill);
|
|
68
|
+
}
|
|
69
|
+
return skills;
|
|
70
|
+
}
|
|
71
|
+
export function projectSkillDir(cwd) {
|
|
72
|
+
return path.join(findProjectRoot(cwd), SKILL_DIR);
|
|
73
|
+
}
|
|
74
|
+
export function globalSkillDir() {
|
|
75
|
+
return GLOBAL_SKILL_DIR;
|
|
76
|
+
}
|
|
77
|
+
export function loadSkillCommands(cwd) {
|
|
78
|
+
const merged = new Map();
|
|
79
|
+
// Precedence (later overrides earlier): global < plugin < project.
|
|
80
|
+
for (const skill of loadSkillDir(GLOBAL_SKILL_DIR, "global")) {
|
|
81
|
+
merged.set(skill.name, skill);
|
|
82
|
+
}
|
|
83
|
+
for (const { dir, plugin } of enabledPluginSkillSources()) {
|
|
84
|
+
for (const skill of loadSkillDir(dir, "plugin", plugin)) {
|
|
85
|
+
merged.set(skill.name, skill);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const skill of loadSkillDir(projectSkillDir(cwd), "project")) {
|
|
89
|
+
merged.set(skill.name, skill);
|
|
90
|
+
}
|
|
91
|
+
return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
92
|
+
}
|
|
93
|
+
export function findSkillCommand(cwd, name) {
|
|
94
|
+
const normalized = normalizeCommandName(name);
|
|
95
|
+
return loadSkillCommands(cwd).find((skill) => skill.name === normalized);
|
|
96
|
+
}
|
|
97
|
+
export function createSkillTemplate(cwd, rawName) {
|
|
98
|
+
const name = normalizeCommandName(rawName);
|
|
99
|
+
if (!name)
|
|
100
|
+
throw new Error("Skill name must contain letters or numbers.");
|
|
101
|
+
const dir = projectSkillDir(cwd);
|
|
102
|
+
const file = path.join(dir, `${name}.md`);
|
|
103
|
+
if (fs.existsSync(file))
|
|
104
|
+
return { created: false, path: file };
|
|
105
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
106
|
+
const title = name
|
|
107
|
+
.split(/[-_]/g)
|
|
108
|
+
.filter(Boolean)
|
|
109
|
+
.map((part) => part[0].toUpperCase() + part.slice(1))
|
|
110
|
+
.join(" ");
|
|
111
|
+
const content = [
|
|
112
|
+
"---",
|
|
113
|
+
`name: ${name}`,
|
|
114
|
+
`description: ${title} task`,
|
|
115
|
+
"---",
|
|
116
|
+
"",
|
|
117
|
+
`You are running the custom /${name} skill.`,
|
|
118
|
+
"",
|
|
119
|
+
"User input:",
|
|
120
|
+
"{{input}}",
|
|
121
|
+
"",
|
|
122
|
+
"Instructions:",
|
|
123
|
+
"- Describe exactly what this skill should do.",
|
|
124
|
+
"- Mention which files or commands it should inspect when relevant.",
|
|
125
|
+
"- Keep the final answer concise and actionable.",
|
|
126
|
+
"",
|
|
127
|
+
].join("\n");
|
|
128
|
+
fs.writeFileSync(file, content, "utf8");
|
|
129
|
+
return { created: true, path: file };
|
|
130
|
+
}
|
|
131
|
+
export function renderSkillPrompt(skill, input, cwd) {
|
|
132
|
+
const args = input.trim();
|
|
133
|
+
const rendered = skill.prompt
|
|
134
|
+
.replaceAll("{{input}}", args)
|
|
135
|
+
.replaceAll("{{args}}", args)
|
|
136
|
+
.replaceAll("{{cwd}}", cwd);
|
|
137
|
+
const includesInput = skill.prompt.includes("{{input}}") || skill.prompt.includes("{{args}}");
|
|
138
|
+
return [
|
|
139
|
+
`Run custom skill /${skill.name}.`,
|
|
140
|
+
`Skill file: ${skill.source}`,
|
|
141
|
+
`Description: ${skill.description}`,
|
|
142
|
+
"",
|
|
143
|
+
rendered,
|
|
144
|
+
includesInput ? "" : `\nUser input: ${args || "(none)"}`,
|
|
145
|
+
].join("\n").trim();
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/todo.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export const TODO_STATUSES = ["pending", "in_progress", "completed"];
|
|
2
|
+
function isTodoStatus(value) {
|
|
3
|
+
return typeof value === "string" && TODO_STATUSES.includes(value);
|
|
4
|
+
}
|
|
5
|
+
function fallbackId(index) {
|
|
6
|
+
return `todo-${index + 1}`;
|
|
7
|
+
}
|
|
8
|
+
export function validateTodos(rawTodos) {
|
|
9
|
+
if (!Array.isArray(rawTodos)) {
|
|
10
|
+
return { error: "todos must be an array." };
|
|
11
|
+
}
|
|
12
|
+
const ids = new Set();
|
|
13
|
+
const todos = [];
|
|
14
|
+
for (let i = 0; i < rawTodos.length; i++) {
|
|
15
|
+
const raw = rawTodos[i];
|
|
16
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
17
|
+
return { error: `todo ${i + 1} must be an object.` };
|
|
18
|
+
}
|
|
19
|
+
const item = raw;
|
|
20
|
+
const content = typeof item.content === "string" ? item.content.trim() : "";
|
|
21
|
+
if (!content) {
|
|
22
|
+
return { error: `todo ${i + 1} content must be a non-empty string.` };
|
|
23
|
+
}
|
|
24
|
+
if (!isTodoStatus(item.status)) {
|
|
25
|
+
return {
|
|
26
|
+
error: `todo ${i + 1} status must be one of: ${TODO_STATUSES.join(", ")}.`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const id = typeof item.id === "string" && item.id.trim() ? item.id.trim() : fallbackId(i);
|
|
30
|
+
if (ids.has(id)) {
|
|
31
|
+
return { error: `duplicate todo id: ${id}.` };
|
|
32
|
+
}
|
|
33
|
+
ids.add(id);
|
|
34
|
+
todos.push({ id, content, status: item.status });
|
|
35
|
+
}
|
|
36
|
+
const inProgress = todos.filter((todo) => todo.status === "in_progress");
|
|
37
|
+
if (inProgress.length > 1) {
|
|
38
|
+
return { error: "only one todo may be in_progress at a time." };
|
|
39
|
+
}
|
|
40
|
+
return { todos };
|
|
41
|
+
}
|
|
42
|
+
export class TodoStore {
|
|
43
|
+
todos = [];
|
|
44
|
+
list() {
|
|
45
|
+
return this.todos.map((todo) => ({ ...todo }));
|
|
46
|
+
}
|
|
47
|
+
replace(todos) {
|
|
48
|
+
this.todos = todos.map((todo) => ({ ...todo }));
|
|
49
|
+
}
|
|
50
|
+
clear() {
|
|
51
|
+
this.todos = [];
|
|
52
|
+
}
|
|
53
|
+
formatForModel() {
|
|
54
|
+
return formatTodoList(this.todos);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function formatTodoList(todos) {
|
|
58
|
+
if (todos.length === 0)
|
|
59
|
+
return "No active todos.";
|
|
60
|
+
const marker = {
|
|
61
|
+
pending: "[ ]",
|
|
62
|
+
in_progress: "[>]",
|
|
63
|
+
completed: "[x]",
|
|
64
|
+
};
|
|
65
|
+
return todos.map((todo) => `${marker[todo.status]} ${todo.content} (${todo.id})`).join("\n");
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=todo.js.map
|
package/dist/todo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo.js","sourceRoot":"","sources":["../src/todo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
const DEFAULT_TIMEOUT = 120_000;
|
|
3
|
+
const MAX_OUTPUT = 30_000;
|
|
4
|
+
export const bashTool = {
|
|
5
|
+
name: "bash",
|
|
6
|
+
description: "Execute a shell command in the working directory and return its stdout/stderr. " +
|
|
7
|
+
"Use for running builds, tests, git, and other shell tasks. Avoid destructive commands.",
|
|
8
|
+
needsApproval: true,
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
command: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "The shell command to run.",
|
|
15
|
+
},
|
|
16
|
+
timeout: {
|
|
17
|
+
type: "number",
|
|
18
|
+
description: `Timeout in milliseconds (optional, default ${DEFAULT_TIMEOUT}, max 600000).`,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
required: ["command"],
|
|
22
|
+
},
|
|
23
|
+
preview(args) {
|
|
24
|
+
return String(args.command);
|
|
25
|
+
},
|
|
26
|
+
run(args, ctx) {
|
|
27
|
+
const command = String(args.command);
|
|
28
|
+
const timeout = Math.min(Number(args.timeout) || DEFAULT_TIMEOUT, 600_000);
|
|
29
|
+
return new Promise((resolve) => {
|
|
30
|
+
exec(command, { cwd: ctx.cwd, timeout, maxBuffer: 10 * 1024 * 1024, shell: "/bin/bash" }, (error, stdout, stderr) => {
|
|
31
|
+
let out = "";
|
|
32
|
+
if (stdout)
|
|
33
|
+
out += stdout;
|
|
34
|
+
if (stderr)
|
|
35
|
+
out += (out ? "\n" : "") + stderr;
|
|
36
|
+
out = out.trim();
|
|
37
|
+
if (out.length > MAX_OUTPUT) {
|
|
38
|
+
out = out.slice(0, MAX_OUTPUT) + `\n…[output truncated, ${out.length} chars total]`;
|
|
39
|
+
}
|
|
40
|
+
const execErr = error;
|
|
41
|
+
const exitCode = execErr && typeof execErr.code === "number" ? execErr.code : 0;
|
|
42
|
+
const timedOut = Boolean(execErr && execErr.signal === "SIGTERM");
|
|
43
|
+
if (timedOut) {
|
|
44
|
+
resolve({
|
|
45
|
+
content: `Command timed out after ${timeout}ms.\n${out}`,
|
|
46
|
+
summary: `$ ${command} (timed out)`,
|
|
47
|
+
isError: true,
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const header = exitCode === 0 ? "" : `[exit code ${exitCode}]\n`;
|
|
52
|
+
resolve({
|
|
53
|
+
content: (header + out).trim() || "(no output)",
|
|
54
|
+
summary: `$ ${command}`,
|
|
55
|
+
isError: exitCode !== 0,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=bash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { structuredPatch } from "diff";
|
|
2
|
+
const MAX_DIFF_LINES = 80;
|
|
3
|
+
/**
|
|
4
|
+
* Produce a compact unified diff (hunks only) between two strings, or undefined
|
|
5
|
+
* if they are identical. Lines are prefixed with +/-/space; hunks with @@.
|
|
6
|
+
* The caller is responsible for colouring.
|
|
7
|
+
*/
|
|
8
|
+
export function makeDiff(label, oldStr, newStr) {
|
|
9
|
+
if (oldStr === newStr)
|
|
10
|
+
return undefined;
|
|
11
|
+
const patch = structuredPatch(label, label, oldStr, newStr, "", "", { context: 2 });
|
|
12
|
+
const out = [];
|
|
13
|
+
for (const hunk of patch.hunks) {
|
|
14
|
+
out.push(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`);
|
|
15
|
+
for (const line of hunk.lines)
|
|
16
|
+
out.push(line);
|
|
17
|
+
}
|
|
18
|
+
if (out.length === 0)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (out.length > MAX_DIFF_LINES) {
|
|
21
|
+
const omitted = out.length - MAX_DIFF_LINES;
|
|
22
|
+
return out.slice(0, MAX_DIFF_LINES).join("\n") + `\n…(${omitted} more diff lines)`;
|
|
23
|
+
}
|
|
24
|
+
return out.join("\n");
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAEvC,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,MAAc,EAAE,MAAc;IACpE,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IAExC,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACpF,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC;QACxF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEvC,IAAI,GAAG,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,cAAc,CAAC;QAC5C,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,OAAO,mBAAmB,CAAC;IACrF,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { makeDiff } from "./diff.js";
|
|
4
|
+
export const editTool = {
|
|
5
|
+
name: "edit_file",
|
|
6
|
+
description: "Replace an exact string in a file with new text. The old_string must appear exactly once " +
|
|
7
|
+
"(include surrounding context to make it unique), unless replace_all is true.",
|
|
8
|
+
needsApproval: true,
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
path: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Path to the file to edit (absolute or relative to the working directory).",
|
|
15
|
+
},
|
|
16
|
+
old_string: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "The exact text to replace.",
|
|
19
|
+
},
|
|
20
|
+
new_string: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "The replacement text.",
|
|
23
|
+
},
|
|
24
|
+
replace_all: {
|
|
25
|
+
type: "boolean",
|
|
26
|
+
description: "Replace every occurrence instead of requiring a unique match (default false).",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["path", "old_string", "new_string"],
|
|
30
|
+
},
|
|
31
|
+
preview(args) {
|
|
32
|
+
return `edit ${String(args.path)}`;
|
|
33
|
+
},
|
|
34
|
+
async run(args, ctx) {
|
|
35
|
+
const rel = String(args.path);
|
|
36
|
+
const oldStr = String(args.old_string ?? "");
|
|
37
|
+
const newStr = String(args.new_string ?? "");
|
|
38
|
+
const replaceAll = Boolean(args.replace_all);
|
|
39
|
+
const abs = path.isAbsolute(rel) ? rel : path.join(ctx.cwd, rel);
|
|
40
|
+
if (!fs.existsSync(abs)) {
|
|
41
|
+
return { content: `Error: file not found: ${rel}`, isError: true };
|
|
42
|
+
}
|
|
43
|
+
if (oldStr === newStr) {
|
|
44
|
+
return { content: "Error: old_string and new_string are identical.", isError: true };
|
|
45
|
+
}
|
|
46
|
+
const original = fs.readFileSync(abs, "utf8");
|
|
47
|
+
const count = original.split(oldStr).length - 1;
|
|
48
|
+
if (count === 0) {
|
|
49
|
+
return {
|
|
50
|
+
content: `Error: old_string not found in ${rel}. Read the file again to get exact text.`,
|
|
51
|
+
isError: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (count > 1 && !replaceAll) {
|
|
55
|
+
return {
|
|
56
|
+
content: `Error: old_string appears ${count} times in ${rel}. Add more context to make it unique, or set replace_all.`,
|
|
57
|
+
isError: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const updated = replaceAll
|
|
61
|
+
? original.split(oldStr).join(newStr)
|
|
62
|
+
: original.replace(oldStr, newStr);
|
|
63
|
+
ctx.recordFileBackup?.(abs, original);
|
|
64
|
+
fs.writeFileSync(abs, updated, "utf8");
|
|
65
|
+
const replacements = replaceAll ? count : 1;
|
|
66
|
+
return {
|
|
67
|
+
content: `Edited ${rel} (${replacements} replacement${replacements > 1 ? "s" : ""}).`,
|
|
68
|
+
summary: `Edited ${rel}`,
|
|
69
|
+
display: makeDiff(rel, original, updated),
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { glob } from "glob";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const MAX_RESULTS = 300;
|
|
4
|
+
export const globTool = {
|
|
5
|
+
name: "list_files",
|
|
6
|
+
description: "List files in a directory matching a glob pattern (e.g. 'src/**/*.ts'). Returns matching paths sorted by " +
|
|
7
|
+
"most recently modified. Skips node_modules and .git. Use this to discover project structure and locate files.",
|
|
8
|
+
needsApproval: false,
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
pattern: { type: "string", description: "Glob pattern, e.g. 'src/**/*.ts' or '**/*.json'." },
|
|
13
|
+
path: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Base directory to search from (optional, defaults to working directory).",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
required: ["pattern"],
|
|
19
|
+
},
|
|
20
|
+
preview(args) {
|
|
21
|
+
return `list ${String(args.pattern)}`;
|
|
22
|
+
},
|
|
23
|
+
async run(args, ctx) {
|
|
24
|
+
const pattern = String(args.pattern);
|
|
25
|
+
const rel = args.path ? String(args.path) : ".";
|
|
26
|
+
const base = path.isAbsolute(rel) ? rel : path.join(ctx.cwd, rel);
|
|
27
|
+
const matches = await glob(pattern, {
|
|
28
|
+
cwd: base,
|
|
29
|
+
nodir: true,
|
|
30
|
+
ignore: ["**/node_modules/**", "**/.git/**"],
|
|
31
|
+
stat: true,
|
|
32
|
+
withFileTypes: true,
|
|
33
|
+
});
|
|
34
|
+
matches.sort((a, b) => (b.mtimeMs ?? 0) - (a.mtimeMs ?? 0));
|
|
35
|
+
const paths = matches.map((m) => m.fullpath());
|
|
36
|
+
if (paths.length === 0) {
|
|
37
|
+
return { content: `No files match ${pattern}.`, summary: `list ${pattern}: 0 files` };
|
|
38
|
+
}
|
|
39
|
+
const shown = paths.slice(0, MAX_RESULTS);
|
|
40
|
+
const truncated = paths.length > MAX_RESULTS ? `\n…[${paths.length - MAX_RESULTS} more]` : "";
|
|
41
|
+
return {
|
|
42
|
+
content: shown.join("\n") + truncated,
|
|
43
|
+
summary: `list ${pattern}: ${paths.length} file(s)`,
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/tools/glob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,2GAA2G;QAC3G,+GAA+G;IACjH,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kDAAkD,EAAE;YAC5F,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0EAA0E;aACxF;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;IACD,OAAO,CAAC,IAAI;QACV,OAAO,QAAQ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IACxC,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG;QACjB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAElE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE;YAClC,GAAG,EAAE,IAAI;YACT,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,CAAC,oBAAoB,EAAE,YAAY,CAAC;YAC5C,IAAI,EAAE,IAAI;YACV,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,OAAO,EAAE,kBAAkB,OAAO,GAAG,EAAE,OAAO,EAAE,QAAQ,OAAO,WAAW,EAAE,CAAC;QACxF,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,MAAM,GAAG,WAAW,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,OAAO;YACL,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS;YACrC,OAAO,EAAE,QAAQ,OAAO,KAAK,KAAK,CAAC,MAAM,UAAU;SACpD,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const MAX_RESULTS = 200;
|
|
5
|
+
function hasRipgrep() {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
execFile("rg", ["--version"], (err) => resolve(!err));
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
function runRipgrep(pattern, searchPath, glob, ignoreCase) {
|
|
11
|
+
const rgArgs = ["--line-number", "--no-heading", "--color", "never", "--max-count", "50"];
|
|
12
|
+
if (ignoreCase)
|
|
13
|
+
rgArgs.push("-i");
|
|
14
|
+
if (glob)
|
|
15
|
+
rgArgs.push("--glob", glob);
|
|
16
|
+
rgArgs.push(pattern, searchPath);
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
execFile("rg", rgArgs, { maxBuffer: 10 * 1024 * 1024 }, (_err, stdout) => {
|
|
19
|
+
resolve(stdout || "");
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const IGNORE_DIRS = new Set(["node_modules", ".git", "dist", "build", ".next", "target"]);
|
|
24
|
+
function jsGrep(pattern, searchPath, ignoreCase) {
|
|
25
|
+
let re;
|
|
26
|
+
try {
|
|
27
|
+
re = new RegExp(pattern, ignoreCase ? "i" : undefined);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
re = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), ignoreCase ? "i" : undefined);
|
|
31
|
+
}
|
|
32
|
+
const results = [];
|
|
33
|
+
const walk = (dir) => {
|
|
34
|
+
if (results.length >= MAX_RESULTS)
|
|
35
|
+
return;
|
|
36
|
+
let entries;
|
|
37
|
+
try {
|
|
38
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
if (results.length >= MAX_RESULTS)
|
|
45
|
+
return;
|
|
46
|
+
const full = path.join(dir, entry.name);
|
|
47
|
+
if (entry.isDirectory()) {
|
|
48
|
+
if (!IGNORE_DIRS.has(entry.name))
|
|
49
|
+
walk(full);
|
|
50
|
+
}
|
|
51
|
+
else if (entry.isFile()) {
|
|
52
|
+
let content;
|
|
53
|
+
try {
|
|
54
|
+
content = fs.readFileSync(full, "utf8");
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const lines = content.split("\n");
|
|
60
|
+
for (let i = 0; i < lines.length; i++) {
|
|
61
|
+
if (re.test(lines[i])) {
|
|
62
|
+
results.push(`${full}:${i + 1}:${lines[i].slice(0, 300)}`);
|
|
63
|
+
if (results.length >= MAX_RESULTS)
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const stat = fs.existsSync(searchPath) ? fs.statSync(searchPath) : null;
|
|
71
|
+
if (stat?.isFile()) {
|
|
72
|
+
const content = fs.readFileSync(searchPath, "utf8").split("\n");
|
|
73
|
+
content.forEach((line, i) => {
|
|
74
|
+
if (re.test(line))
|
|
75
|
+
results.push(`${searchPath}:${i + 1}:${line.slice(0, 300)}`);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
walk(searchPath);
|
|
80
|
+
}
|
|
81
|
+
return results.join("\n");
|
|
82
|
+
}
|
|
83
|
+
export const grepTool = {
|
|
84
|
+
name: "search_text",
|
|
85
|
+
description: "Search file contents for a regular expression pattern. Returns matching lines with file:line:content. " +
|
|
86
|
+
"Uses ripgrep when available. Skips node_modules/.git/dist by default. " +
|
|
87
|
+
"Use this to find where a symbol, string, or pattern appears in the codebase.",
|
|
88
|
+
needsApproval: false,
|
|
89
|
+
parameters: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
pattern: { type: "string", description: "Regular expression to search for." },
|
|
93
|
+
path: {
|
|
94
|
+
type: "string",
|
|
95
|
+
description: "Directory or file to search (optional, defaults to working directory).",
|
|
96
|
+
},
|
|
97
|
+
glob: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "Filter files by glob, e.g. '*.ts' (optional, ripgrep only).",
|
|
100
|
+
},
|
|
101
|
+
ignore_case: { type: "boolean", description: "Case-insensitive search (optional)." },
|
|
102
|
+
},
|
|
103
|
+
required: ["pattern"],
|
|
104
|
+
},
|
|
105
|
+
preview(args) {
|
|
106
|
+
return `search /${String(args.pattern)}/`;
|
|
107
|
+
},
|
|
108
|
+
async run(args, ctx) {
|
|
109
|
+
const pattern = String(args.pattern);
|
|
110
|
+
const rel = args.path ? String(args.path) : ".";
|
|
111
|
+
const searchPath = path.isAbsolute(rel) ? rel : path.join(ctx.cwd, rel);
|
|
112
|
+
const glob = args.glob ? String(args.glob) : undefined;
|
|
113
|
+
const ignoreCase = Boolean(args.ignore_case);
|
|
114
|
+
let output;
|
|
115
|
+
if (await hasRipgrep()) {
|
|
116
|
+
output = await runRipgrep(pattern, searchPath, glob, ignoreCase);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
output = jsGrep(pattern, searchPath, ignoreCase);
|
|
120
|
+
}
|
|
121
|
+
const lines = output.trim() ? output.trim().split("\n") : [];
|
|
122
|
+
if (lines.length === 0) {
|
|
123
|
+
return { content: `No matches for /${pattern}/.`, summary: `search /${pattern}/: 0 matches` };
|
|
124
|
+
}
|
|
125
|
+
const shown = lines.slice(0, MAX_RESULTS);
|
|
126
|
+
const truncated = lines.length > MAX_RESULTS ? `\n…[${lines.length - MAX_RESULTS} more matches]` : "";
|
|
127
|
+
return {
|
|
128
|
+
content: shown.join("\n") + truncated,
|
|
129
|
+
summary: `search /${pattern}/: ${lines.length} match(es)`,
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
//# 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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"}
|