@poping/yome 0.0.2
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 +54 -0
- package/bin/yome.js +2 -0
- package/dist/agent.d.ts +43 -0
- package/dist/agent.js +140 -0
- package/dist/agent.js.map +1 -0
- package/dist/config.d.ts +41 -0
- package/dist/config.js +108 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +1 -0
- package/dist/context.js +101 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/llm.d.ts +13 -0
- package/dist/llm.js +317 -0
- package/dist/llm.js.map +1 -0
- package/dist/loops/chain.d.ts +15 -0
- package/dist/loops/chain.js +105 -0
- package/dist/loops/chain.js.map +1 -0
- package/dist/loops/evaluator.d.ts +12 -0
- package/dist/loops/evaluator.js +100 -0
- package/dist/loops/evaluator.js.map +1 -0
- package/dist/loops/index.d.ts +12 -0
- package/dist/loops/index.js +39 -0
- package/dist/loops/index.js.map +1 -0
- package/dist/loops/orchestrator.d.ts +13 -0
- package/dist/loops/orchestrator.js +107 -0
- package/dist/loops/orchestrator.js.map +1 -0
- package/dist/loops/parallel.d.ts +6 -0
- package/dist/loops/parallel.js +48 -0
- package/dist/loops/parallel.js.map +1 -0
- package/dist/loops/route.d.ts +13 -0
- package/dist/loops/route.js +88 -0
- package/dist/loops/route.js.map +1 -0
- package/dist/loops/simple.d.ts +6 -0
- package/dist/loops/simple.js +46 -0
- package/dist/loops/simple.js.map +1 -0
- package/dist/loops/types.d.ts +32 -0
- package/dist/loops/types.js +9 -0
- package/dist/loops/types.js.map +1 -0
- package/dist/permissions/checker.d.ts +18 -0
- package/dist/permissions/checker.js +89 -0
- package/dist/permissions/checker.js.map +1 -0
- package/dist/permissions/index.d.ts +4 -0
- package/dist/permissions/index.js +4 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/loader.d.ts +22 -0
- package/dist/permissions/loader.js +104 -0
- package/dist/permissions/loader.js.map +1 -0
- package/dist/permissions/ruleParser.d.ts +23 -0
- package/dist/permissions/ruleParser.js +59 -0
- package/dist/permissions/ruleParser.js.map +1 -0
- package/dist/permissions/types.d.ts +37 -0
- package/dist/permissions/types.js +2 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/sessions.d.ts +20 -0
- package/dist/sessions.js +119 -0
- package/dist/sessions.js.map +1 -0
- package/dist/skills/index.d.ts +2 -0
- package/dist/skills/index.js +2 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/loader.d.ts +4 -0
- package/dist/skills/loader.js +125 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/types.d.ts +22 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/subagent/agentTool.d.ts +7 -0
- package/dist/subagent/agentTool.js +121 -0
- package/dist/subagent/agentTool.js.map +1 -0
- package/dist/subagent/builtinAgents.d.ts +3 -0
- package/dist/subagent/builtinAgents.js +23 -0
- package/dist/subagent/builtinAgents.js.map +1 -0
- package/dist/subagent/index.d.ts +6 -0
- package/dist/subagent/index.js +5 -0
- package/dist/subagent/index.js.map +1 -0
- package/dist/subagent/loadAgents.d.ts +2 -0
- package/dist/subagent/loadAgents.js +98 -0
- package/dist/subagent/loadAgents.js.map +1 -0
- package/dist/subagent/runAgent.d.ts +18 -0
- package/dist/subagent/runAgent.js +115 -0
- package/dist/subagent/runAgent.js.map +1 -0
- package/dist/subagent/types.d.ts +20 -0
- package/dist/subagent/types.js +2 -0
- package/dist/subagent/types.js.map +1 -0
- package/dist/toggleState.d.ts +6 -0
- package/dist/toggleState.js +58 -0
- package/dist/toggleState.js.map +1 -0
- package/dist/tools/bash.d.ts +2 -0
- package/dist/tools/bash.js +78 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +103 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.d.ts +2 -0
- package/dist/tools/glob.js +44 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +2 -0
- package/dist/tools/grep.js +89 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.js +99 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/ls.d.ts +2 -0
- package/dist/tools/ls.js +47 -0
- package/dist/tools/ls.js.map +1 -0
- package/dist/tools/read.d.ts +2 -0
- package/dist/tools/read.js +52 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/write.d.ts +2 -0
- package/dist/tools/write.js +46 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/AgentPicker.d.ts +12 -0
- package/dist/ui/AgentPicker.js +32 -0
- package/dist/ui/AgentPicker.js.map +1 -0
- package/dist/ui/App.d.ts +6 -0
- package/dist/ui/App.js +327 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/Banner.d.ts +1 -0
- package/dist/ui/Banner.js +14 -0
- package/dist/ui/Banner.js.map +1 -0
- package/dist/ui/InputBar.d.ts +17 -0
- package/dist/ui/InputBar.js +93 -0
- package/dist/ui/InputBar.js.map +1 -0
- package/dist/ui/Markdown.d.ts +4 -0
- package/dist/ui/Markdown.js +97 -0
- package/dist/ui/Markdown.js.map +1 -0
- package/dist/ui/MessageList.d.ts +17 -0
- package/dist/ui/MessageList.js +50 -0
- package/dist/ui/MessageList.js.map +1 -0
- package/dist/ui/ModelPicker.d.ts +9 -0
- package/dist/ui/ModelPicker.js +70 -0
- package/dist/ui/ModelPicker.js.map +1 -0
- package/dist/ui/PermissionPrompt.d.ts +10 -0
- package/dist/ui/PermissionPrompt.js +37 -0
- package/dist/ui/PermissionPrompt.js.map +1 -0
- package/dist/ui/SessionPicker.d.ts +8 -0
- package/dist/ui/SessionPicker.js +64 -0
- package/dist/ui/SessionPicker.js.map +1 -0
- package/dist/ui/Spinner.d.ts +3 -0
- package/dist/ui/Spinner.js +15 -0
- package/dist/ui/Spinner.js.map +1 -0
- package/dist/ui/TogglePicker.d.ts +16 -0
- package/dist/ui/TogglePicker.js +35 -0
- package/dist/ui/TogglePicker.js.map +1 -0
- package/dist/ui/ToolResult.d.ts +6 -0
- package/dist/ui/ToolResult.js +59 -0
- package/dist/ui/ToolResult.js.map +1 -0
- package/dist/utils/imagePaste.d.ts +12 -0
- package/dist/utils/imagePaste.js +54 -0
- package/dist/utils/imagePaste.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
2
|
+
import { resolve, dirname } from 'path';
|
|
3
|
+
import { isContentAllowed, isContentDenied } from '../permissions/checker.js';
|
|
4
|
+
function buildDiffLines(fileContent, oldStr, newStr, contextLines = 3) {
|
|
5
|
+
const allLines = fileContent.split('\n');
|
|
6
|
+
const oldLines = oldStr.split('\n');
|
|
7
|
+
const newLines = newStr.split('\n');
|
|
8
|
+
// Find where old_string starts in the file
|
|
9
|
+
const matchIdx = fileContent.indexOf(oldStr);
|
|
10
|
+
if (matchIdx < 0)
|
|
11
|
+
return [];
|
|
12
|
+
const startLine = fileContent.slice(0, matchIdx).split('\n').length - 1;
|
|
13
|
+
const result = [];
|
|
14
|
+
// Context before
|
|
15
|
+
const ctxStart = Math.max(0, startLine - contextLines);
|
|
16
|
+
for (let i = ctxStart; i < startLine; i++) {
|
|
17
|
+
result.push(`@@CTX:${i + 1}:${allLines[i]}`);
|
|
18
|
+
}
|
|
19
|
+
// Removed lines
|
|
20
|
+
for (let i = 0; i < oldLines.length; i++) {
|
|
21
|
+
result.push(`@@-:${startLine + i + 1}:${oldLines[i]}`);
|
|
22
|
+
}
|
|
23
|
+
// Added lines
|
|
24
|
+
for (let i = 0; i < newLines.length; i++) {
|
|
25
|
+
result.push(`@@+:${startLine + i + 1}:${newLines[i]}`);
|
|
26
|
+
}
|
|
27
|
+
// Context after
|
|
28
|
+
const afterStart = startLine + oldLines.length;
|
|
29
|
+
const ctxEnd = Math.min(allLines.length, afterStart + contextLines);
|
|
30
|
+
for (let i = afterStart; i < ctxEnd; i++) {
|
|
31
|
+
result.push(`@@CTX:${i + 1}:${allLines[i]}`);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
export const editTool = {
|
|
36
|
+
name: 'Edit',
|
|
37
|
+
description: 'Edit a file by replacing old_string with new_string. The old_string must be unique in the file (or use replace_all). To create a new file, use empty old_string and provide new_string as the full content.',
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
file_path: { type: 'string', description: 'Absolute path to the file to edit' },
|
|
42
|
+
old_string: { type: 'string', description: 'The exact text to find and replace' },
|
|
43
|
+
new_string: { type: 'string', description: 'The replacement text' },
|
|
44
|
+
replace_all: { type: 'boolean', description: 'Replace all occurrences (default: false)' },
|
|
45
|
+
},
|
|
46
|
+
required: ['file_path', 'old_string', 'new_string'],
|
|
47
|
+
},
|
|
48
|
+
isReadOnly() { return false; },
|
|
49
|
+
checkPermissions(input, ctx) {
|
|
50
|
+
const filePath = input.file_path ?? '';
|
|
51
|
+
if (isContentDenied(ctx, 'Edit', filePath)) {
|
|
52
|
+
return { behavior: 'deny', message: `Editing denied for: ${filePath}` };
|
|
53
|
+
}
|
|
54
|
+
if (isContentAllowed(ctx, 'Edit', filePath)) {
|
|
55
|
+
return { behavior: 'allow' };
|
|
56
|
+
}
|
|
57
|
+
return { behavior: 'passthrough', message: `Allow editing ${filePath}?` };
|
|
58
|
+
},
|
|
59
|
+
validateInput(input) {
|
|
60
|
+
if (typeof input.file_path !== 'string' || !input.file_path.trim()) {
|
|
61
|
+
return { valid: false, error: 'file_path is required' };
|
|
62
|
+
}
|
|
63
|
+
return { valid: true };
|
|
64
|
+
},
|
|
65
|
+
getPath(input) { return input.file_path; },
|
|
66
|
+
async execute(input) {
|
|
67
|
+
const filePath = resolve(input.file_path);
|
|
68
|
+
const oldStr = input.old_string;
|
|
69
|
+
const newStr = input.new_string;
|
|
70
|
+
const replaceAll = input.replace_all ?? false;
|
|
71
|
+
if (oldStr === '') {
|
|
72
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
73
|
+
await writeFile(filePath, newStr, 'utf-8');
|
|
74
|
+
const lines = newStr.split('\n');
|
|
75
|
+
const diff = lines.map((l, i) => `@@+:${i + 1}:${l}`).join('\n');
|
|
76
|
+
return `@@FILE:${filePath}\n@@NEW\n${diff}`;
|
|
77
|
+
}
|
|
78
|
+
let content;
|
|
79
|
+
try {
|
|
80
|
+
content = await readFile(filePath, 'utf-8');
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return `Error: File not found: ${filePath}`;
|
|
84
|
+
}
|
|
85
|
+
const count = content.split(oldStr).length - 1;
|
|
86
|
+
if (count === 0) {
|
|
87
|
+
return `Error: old_string not found in file.`;
|
|
88
|
+
}
|
|
89
|
+
if (count > 1 && !replaceAll) {
|
|
90
|
+
return `Error: Found ${count} matches. Set replace_all=true or provide more context.`;
|
|
91
|
+
}
|
|
92
|
+
// Build diff BEFORE writing (need original content for context)
|
|
93
|
+
const diffLines = buildDiffLines(content, oldStr, newStr);
|
|
94
|
+
const updated = replaceAll
|
|
95
|
+
? content.replaceAll(oldStr, newStr)
|
|
96
|
+
: content.replace(oldStr, newStr);
|
|
97
|
+
await writeFile(filePath, updated, 'utf-8');
|
|
98
|
+
const addCount = newStr.split('\n').length;
|
|
99
|
+
const rmCount = oldStr.split('\n').length;
|
|
100
|
+
return `@@FILE:${filePath}\n@@EDIT:+${addCount}:-${rmCount}\n${diffLines.join('\n')}`;
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
//# 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,44 @@
|
|
|
1
|
+
import fg from 'fast-glob';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
export const globTool = {
|
|
4
|
+
name: 'Glob',
|
|
5
|
+
description: 'Find files matching a glob pattern. Returns file paths.',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
pattern: { type: 'string', description: 'Glob pattern to match (e.g. "**/*.ts")' },
|
|
10
|
+
path: { type: 'string', description: 'Directory to search in (default: cwd)' },
|
|
11
|
+
},
|
|
12
|
+
required: ['pattern'],
|
|
13
|
+
},
|
|
14
|
+
isReadOnly() { return true; },
|
|
15
|
+
validateInput(input) {
|
|
16
|
+
if (typeof input.pattern !== 'string' || !input.pattern.trim()) {
|
|
17
|
+
return { valid: false, error: 'pattern is required' };
|
|
18
|
+
}
|
|
19
|
+
return { valid: true };
|
|
20
|
+
},
|
|
21
|
+
getPath(input) { return input.path; },
|
|
22
|
+
async execute(input) {
|
|
23
|
+
const pattern = input.pattern;
|
|
24
|
+
const searchPath = resolve(input.path || process.cwd());
|
|
25
|
+
const files = await fg(pattern, {
|
|
26
|
+
cwd: searchPath,
|
|
27
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
28
|
+
dot: true,
|
|
29
|
+
onlyFiles: true,
|
|
30
|
+
absolute: false,
|
|
31
|
+
});
|
|
32
|
+
files.sort();
|
|
33
|
+
const limit = 100;
|
|
34
|
+
const truncated = files.length > limit;
|
|
35
|
+
const shown = truncated ? files.slice(0, limit) : files;
|
|
36
|
+
if (shown.length === 0)
|
|
37
|
+
return 'No files found';
|
|
38
|
+
let result = `Found ${files.length} file(s)\n${shown.join('\n')}`;
|
|
39
|
+
if (truncated)
|
|
40
|
+
result += '\n(Results truncated. Use a more specific pattern.)';
|
|
41
|
+
return result;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/tools/glob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/B,MAAM,CAAC,MAAM,QAAQ,GAAY;IAC/B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,yDAAyD;IACtE,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wCAAwC,EAAE;YAClF,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;SAC/E;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;IACD,UAAU,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;IAC7B,aAAa,CAAC,KAAK;QACjB,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,IAA0B,CAAC,CAAC,CAAC;IAC3D,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAiB,CAAC;QACxC,MAAM,UAAU,GAAG,OAAO,CAAE,KAAK,CAAC,IAAe,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAEpE,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,EAAE;YAC9B,GAAG,EAAE,UAAU;YACf,MAAM,EAAE,CAAC,oBAAoB,EAAE,YAAY,CAAC;YAC5C,GAAG,EAAE,IAAI;YACT,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAAG,CAAC;QAClB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;QACvC,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAExD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,gBAAgB,CAAC;QAEhD,IAAI,MAAM,GAAG,SAAS,KAAK,CAAC,MAAM,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClE,IAAI,SAAS;YAAE,MAAM,IAAI,qDAAqD,CAAC;QAC/E,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
function runGrep(args, cwd) {
|
|
4
|
+
return new Promise((resolveP) => {
|
|
5
|
+
const proc = spawn(args[0], args.slice(1), {
|
|
6
|
+
cwd,
|
|
7
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
8
|
+
timeout: 15_000,
|
|
9
|
+
});
|
|
10
|
+
let stdout = '';
|
|
11
|
+
let stderr = '';
|
|
12
|
+
proc.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
13
|
+
proc.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
14
|
+
proc.on('close', (code) => {
|
|
15
|
+
if (code === 1 && !stdout.trim()) {
|
|
16
|
+
resolveP('No matches found');
|
|
17
|
+
}
|
|
18
|
+
else if (code !== 0 && code !== 1) {
|
|
19
|
+
resolveP(`Error: ${stderr || `exit code ${code}`}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
resolveP(stdout.trim() || 'No matches found');
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
proc.on('error', (err) => {
|
|
26
|
+
resolveP(`Error: ${err.message}`);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function hasRipgrep() {
|
|
31
|
+
return new Promise((res) => {
|
|
32
|
+
const proc = spawn('which', ['rg']);
|
|
33
|
+
proc.on('close', (code) => res(code === 0));
|
|
34
|
+
proc.on('error', () => res(false));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export const grepTool = {
|
|
38
|
+
name: 'Grep',
|
|
39
|
+
description: 'Search file contents using grep (or ripgrep if available). Returns matching lines with file paths.',
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
pattern: { type: 'string', description: 'Regex pattern to search for' },
|
|
44
|
+
path: { type: 'string', description: 'File or directory to search in (default: cwd)' },
|
|
45
|
+
case_insensitive: { type: 'boolean', description: 'Case insensitive search (default: false)' },
|
|
46
|
+
glob: { type: 'string', description: 'File glob filter (e.g. "*.ts")' },
|
|
47
|
+
},
|
|
48
|
+
required: ['pattern'],
|
|
49
|
+
},
|
|
50
|
+
isReadOnly() { return true; },
|
|
51
|
+
validateInput(input) {
|
|
52
|
+
if (typeof input.pattern !== 'string' || !input.pattern.trim()) {
|
|
53
|
+
return { valid: false, error: 'pattern is required' };
|
|
54
|
+
}
|
|
55
|
+
return { valid: true };
|
|
56
|
+
},
|
|
57
|
+
getPath(input) { return input.path; },
|
|
58
|
+
async execute(input) {
|
|
59
|
+
const pattern = input.pattern;
|
|
60
|
+
const searchPath = resolve(input.path || process.cwd());
|
|
61
|
+
const caseInsensitive = input.case_insensitive;
|
|
62
|
+
const globFilter = input.glob;
|
|
63
|
+
// Use array args (no shell interpolation = no injection)
|
|
64
|
+
const useRg = await hasRipgrep();
|
|
65
|
+
let args;
|
|
66
|
+
if (useRg) {
|
|
67
|
+
args = ['rg', '--hidden', '-n', '--max-columns', '500', '--glob', '!.git', '--glob', '!node_modules'];
|
|
68
|
+
if (caseInsensitive)
|
|
69
|
+
args.push('-i');
|
|
70
|
+
if (globFilter)
|
|
71
|
+
args.push('--glob', globFilter);
|
|
72
|
+
args.push(pattern, searchPath);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
args = ['grep', '-rn'];
|
|
76
|
+
if (caseInsensitive)
|
|
77
|
+
args.push('-i');
|
|
78
|
+
args.push(pattern, searchPath);
|
|
79
|
+
}
|
|
80
|
+
const output = await runGrep(args, searchPath);
|
|
81
|
+
const lines = output.split('\n');
|
|
82
|
+
const limit = 200;
|
|
83
|
+
if (lines.length > limit) {
|
|
84
|
+
return lines.slice(0, limit).join('\n') + `\n\n[Showing ${limit} of ${lines.length} matches]`;
|
|
85
|
+
}
|
|
86
|
+
return output;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=grep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grep.js","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/B,SAAS,OAAO,CAAC,IAAc,EAAE,GAAW;IAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YACzC,GAAG;YACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3D,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBACjC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;YAC/B,CAAC;iBAAM,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACpC,QAAQ,CAAC,UAAU,MAAM,IAAI,aAAa,IAAI,EAAE,EAAE,CAAC,CAAC;YACtD,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,kBAAkB,CAAC,CAAC;YAChD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,QAAQ,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAY;IAC/B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,oGAAoG;IACjH,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6BAA6B,EAAE;YACvE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;YACtF,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,0CAA0C,EAAE;YAC9F,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;SACxE;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;IACD,UAAU,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;IAC7B,aAAa,CAAC,KAAK;QACjB,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,IAA0B,CAAC,CAAC,CAAC;IAC3D,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAiB,CAAC;QACxC,MAAM,UAAU,GAAG,OAAO,CAAE,KAAK,CAAC,IAAe,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACpE,MAAM,eAAe,GAAG,KAAK,CAAC,gBAA2B,CAAC;QAC1D,MAAM,UAAU,GAAG,KAAK,CAAC,IAAc,CAAC;QAExC,yDAAyD;QACzD,MAAM,KAAK,GAAG,MAAM,UAAU,EAAE,CAAC;QAEjC,IAAI,IAAc,CAAC;QACnB,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;YACtG,IAAI,eAAe;gBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,UAAU;gBAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAChD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACvB,IAAI,eAAe;gBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAE/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,GAAG,CAAC;QAClB,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,gBAAgB,KAAK,OAAO,KAAK,CAAC,MAAM,WAAW,CAAC;QAChG,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ToolDef, AnthropicTool } from '../types.js';
|
|
2
|
+
import type { ToolPermissionContext } from '../permissions/types.js';
|
|
3
|
+
export declare const BASE_TOOLS: ToolDef[];
|
|
4
|
+
export declare function registerTool(tool: ToolDef): void;
|
|
5
|
+
export declare function getToolByName(name: string): ToolDef | undefined;
|
|
6
|
+
export declare function getAllTools(): ToolDef[];
|
|
7
|
+
export declare function getAnthropicTools(): AnthropicTool[];
|
|
8
|
+
export declare function setPermissionContext(ctx: ToolPermissionContext): void;
|
|
9
|
+
export declare function getPermissionContext(): ToolPermissionContext | null;
|
|
10
|
+
/**
|
|
11
|
+
* Register a callback that will be called when a tool requires user approval.
|
|
12
|
+
* Return true to allow, false to deny.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setAskPermissionHandler(fn: (toolName: string, message: string, input: Record<string, unknown>) => Promise<boolean>): void;
|
|
15
|
+
export declare function executeTool(name: string, input: Record<string, unknown>, signal?: AbortSignal): Promise<string>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { checkPermission } from '../permissions/checker.js';
|
|
2
|
+
import { readTool } from './read.js';
|
|
3
|
+
import { editTool } from './edit.js';
|
|
4
|
+
import { writeTool } from './write.js';
|
|
5
|
+
import { bashTool } from './bash.js';
|
|
6
|
+
import { globTool } from './glob.js';
|
|
7
|
+
import { grepTool } from './grep.js';
|
|
8
|
+
import { lsTool } from './ls.js';
|
|
9
|
+
const DEFAULT_MAX_RESULT_CHARS = 20_000;
|
|
10
|
+
export const BASE_TOOLS = [
|
|
11
|
+
readTool,
|
|
12
|
+
editTool,
|
|
13
|
+
writeTool,
|
|
14
|
+
bashTool,
|
|
15
|
+
globTool,
|
|
16
|
+
grepTool,
|
|
17
|
+
lsTool,
|
|
18
|
+
];
|
|
19
|
+
const toolMap = new Map();
|
|
20
|
+
for (const t of BASE_TOOLS)
|
|
21
|
+
toolMap.set(t.name, t);
|
|
22
|
+
export function registerTool(tool) {
|
|
23
|
+
toolMap.set(tool.name, tool);
|
|
24
|
+
}
|
|
25
|
+
export function getToolByName(name) {
|
|
26
|
+
return toolMap.get(name);
|
|
27
|
+
}
|
|
28
|
+
export function getAllTools() {
|
|
29
|
+
return Array.from(toolMap.values());
|
|
30
|
+
}
|
|
31
|
+
export function getAnthropicTools() {
|
|
32
|
+
return getAllTools().map((t) => ({
|
|
33
|
+
name: t.name,
|
|
34
|
+
description: t.description,
|
|
35
|
+
input_schema: t.inputSchema,
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
/** Current permission context — set via setPermissionContext(). */
|
|
39
|
+
let _permCtx = null;
|
|
40
|
+
/** Callback invoked when a tool needs user approval. */
|
|
41
|
+
let _askPermissionFn = null;
|
|
42
|
+
export function setPermissionContext(ctx) {
|
|
43
|
+
_permCtx = ctx;
|
|
44
|
+
}
|
|
45
|
+
export function getPermissionContext() {
|
|
46
|
+
return _permCtx;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Register a callback that will be called when a tool requires user approval.
|
|
50
|
+
* Return true to allow, false to deny.
|
|
51
|
+
*/
|
|
52
|
+
export function setAskPermissionHandler(fn) {
|
|
53
|
+
_askPermissionFn = fn;
|
|
54
|
+
}
|
|
55
|
+
export async function executeTool(name, input, signal) {
|
|
56
|
+
const tool = toolMap.get(name);
|
|
57
|
+
if (!tool)
|
|
58
|
+
return `Error: Unknown tool: ${name}`;
|
|
59
|
+
// Validate input if the tool supports it
|
|
60
|
+
if (tool.validateInput) {
|
|
61
|
+
const validation = tool.validateInput(input);
|
|
62
|
+
if (!validation.valid) {
|
|
63
|
+
return `Error: ${validation.error}`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Permission check
|
|
67
|
+
if (_permCtx) {
|
|
68
|
+
const toolResult = tool.checkPermissions?.(input, _permCtx);
|
|
69
|
+
const decision = checkPermission(tool.name, tool.isReadOnly(), _permCtx, toolResult ?? undefined);
|
|
70
|
+
if (decision.behavior === 'deny') {
|
|
71
|
+
return `Permission denied: ${decision.message}`;
|
|
72
|
+
}
|
|
73
|
+
if (decision.behavior === 'ask') {
|
|
74
|
+
if (_askPermissionFn) {
|
|
75
|
+
const allowed = await _askPermissionFn(tool.name, decision.message, input);
|
|
76
|
+
if (!allowed) {
|
|
77
|
+
return `Permission denied by user for ${tool.name}.`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// If no handler is registered, fall through and allow (default permissive)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
let result = await tool.execute(input, signal);
|
|
85
|
+
// Truncate oversized results
|
|
86
|
+
const limit = tool.maxResultChars ?? DEFAULT_MAX_RESULT_CHARS;
|
|
87
|
+
if (result.length > limit) {
|
|
88
|
+
result = result.slice(0, limit) + `\n\n[Output truncated at ${limit} chars]`;
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
if (err.name === 'AbortError') {
|
|
94
|
+
return `Tool ${name} was cancelled.`;
|
|
95
|
+
}
|
|
96
|
+
return `Error executing ${name}: ${err.message}`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/ls.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readdir, stat } from 'fs/promises';
|
|
2
|
+
import { resolve, join } from 'path';
|
|
3
|
+
export const lsTool = {
|
|
4
|
+
name: 'LS',
|
|
5
|
+
description: 'List contents of a directory.',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
path: { type: 'string', description: 'Directory path to list (default: cwd)' },
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
isReadOnly() { return true; },
|
|
13
|
+
getPath(input) { return input.path; },
|
|
14
|
+
async execute(input) {
|
|
15
|
+
const dirPath = resolve(input.path || process.cwd());
|
|
16
|
+
try {
|
|
17
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
18
|
+
const lines = [];
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
if (entry.name.startsWith('.') && entry.name !== '.gitignore')
|
|
21
|
+
continue;
|
|
22
|
+
const fullPath = join(dirPath, entry.name);
|
|
23
|
+
try {
|
|
24
|
+
const s = await stat(fullPath);
|
|
25
|
+
const size = entry.isDirectory() ? '' : formatSize(s.size);
|
|
26
|
+
const type = entry.isDirectory() ? 'd' : '-';
|
|
27
|
+
lines.push(`${type} ${size.padStart(8)} ${entry.name}${entry.isDirectory() ? '/' : ''}`);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
lines.push(`? ${entry.name}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return lines.length > 0 ? lines.join('\n') : '(empty directory)';
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return `Error: Cannot read directory: ${dirPath}`;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
function formatSize(bytes) {
|
|
41
|
+
if (bytes < 1024)
|
|
42
|
+
return `${bytes}B`;
|
|
43
|
+
if (bytes < 1024 * 1024)
|
|
44
|
+
return `${(bytes / 1024).toFixed(1)}K`;
|
|
45
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}M`;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=ls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ls.js","sourceRoot":"","sources":["../../src/tools/ls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAGrC,MAAM,CAAC,MAAM,MAAM,GAAY;IAC7B,IAAI,EAAE,IAAI;IACV,WAAW,EAAE,+BAA+B;IAC5C,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;SAC/E;KACF;IACD,UAAU,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,IAA0B,CAAC,CAAC,CAAC;IAC3D,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,OAAO,GAAG,OAAO,CAAE,KAAK,CAAC,IAAe,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAEjE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,KAAK,GAAa,EAAE,CAAC;YAE3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;oBAAE,SAAS;gBACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,CAAC;oBACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;oBAC7C,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC7F,CAAC;gBAAC,MAAM,CAAC;oBACP,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;YAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,iCAAiC,OAAO,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,GAAG,CAAC;IACrC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAChE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFile, stat } from 'fs/promises';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
function addLineNumbers(content, startLine) {
|
|
4
|
+
return content
|
|
5
|
+
.split('\n')
|
|
6
|
+
.map((line, i) => `${startLine + i}\t${line}`)
|
|
7
|
+
.join('\n');
|
|
8
|
+
}
|
|
9
|
+
export const readTool = {
|
|
10
|
+
name: 'Read',
|
|
11
|
+
description: 'Read the contents of a file. Supports offset and limit for large files.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
file_path: { type: 'string', description: 'Absolute path to the file to read' },
|
|
16
|
+
offset: { type: 'number', description: 'Line number to start reading from (1-based). Default: 1' },
|
|
17
|
+
limit: { type: 'number', description: 'Maximum number of lines to read. Default: 2000' },
|
|
18
|
+
},
|
|
19
|
+
required: ['file_path'],
|
|
20
|
+
},
|
|
21
|
+
isReadOnly() { return true; },
|
|
22
|
+
validateInput(input) {
|
|
23
|
+
if (typeof input.file_path !== 'string' || !input.file_path.trim()) {
|
|
24
|
+
return { valid: false, error: 'file_path is required' };
|
|
25
|
+
}
|
|
26
|
+
return { valid: true };
|
|
27
|
+
},
|
|
28
|
+
getPath(input) { return input.file_path; },
|
|
29
|
+
async execute(input) {
|
|
30
|
+
const filePath = resolve(input.file_path);
|
|
31
|
+
const offset = Math.max(1, input.offset || 1);
|
|
32
|
+
const limit = input.limit || 2000;
|
|
33
|
+
try {
|
|
34
|
+
await stat(filePath);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return `Error: File not found: ${filePath}`;
|
|
38
|
+
}
|
|
39
|
+
const raw = await readFile(filePath, 'utf-8');
|
|
40
|
+
const lines = raw.split('\n');
|
|
41
|
+
const totalLines = lines.length;
|
|
42
|
+
const startIdx = offset - 1;
|
|
43
|
+
const slice = lines.slice(startIdx, startIdx + limit);
|
|
44
|
+
const numbered = addLineNumbers(slice.join('\n'), offset);
|
|
45
|
+
let result = numbered;
|
|
46
|
+
if (startIdx + limit < totalLines) {
|
|
47
|
+
result += `\n\n[Showing lines ${offset}-${startIdx + limit} of ${totalLines} total]`;
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/B,SAAS,cAAc,CAAC,OAAe,EAAE,SAAiB;IACxD,OAAO,OAAO;SACX,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,SAAS,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;SAC7C,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAY;IAC/B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,yEAAyE;IACtF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mCAAmC,EAAE;YAC/E,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yDAAyD,EAAE;YAClG,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gDAAgD,EAAE;SACzF;QACD,QAAQ,EAAE,CAAC,WAAW,CAAC;KACxB;IACD,UAAU,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;IAC7B,aAAa,CAAC,KAAK;QACjB,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACnE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC1D,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,SAA+B,CAAC,CAAC,CAAC;IAChE,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,SAAmB,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAG,KAAK,CAAC,MAAiB,IAAI,CAAC,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAI,KAAK,CAAC,KAAgB,IAAI,IAAI,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,0BAA0B,QAAQ,EAAE,CAAC;QAC9C,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;QAEtD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,MAAM,GAAG,QAAQ,CAAC;QAEtB,IAAI,QAAQ,GAAG,KAAK,GAAG,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,sBAAsB,MAAM,IAAI,QAAQ,GAAG,KAAK,OAAO,UAAU,SAAS,CAAC;QACvF,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
2
|
+
import { resolve, dirname } from 'path';
|
|
3
|
+
import { isContentAllowed, isContentDenied } from '../permissions/checker.js';
|
|
4
|
+
export const writeTool = {
|
|
5
|
+
name: 'Write',
|
|
6
|
+
description: 'Create a new file with the given content. Creates parent directories if needed.',
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
file_path: { type: 'string', description: 'Absolute path for the new file' },
|
|
11
|
+
content: { type: 'string', description: 'Content to write to the file' },
|
|
12
|
+
},
|
|
13
|
+
required: ['file_path', 'content'],
|
|
14
|
+
},
|
|
15
|
+
isReadOnly() { return false; },
|
|
16
|
+
checkPermissions(input, ctx) {
|
|
17
|
+
const filePath = input.file_path ?? '';
|
|
18
|
+
if (isContentDenied(ctx, 'Write', filePath)) {
|
|
19
|
+
return { behavior: 'deny', message: `Writing denied for: ${filePath}` };
|
|
20
|
+
}
|
|
21
|
+
if (isContentAllowed(ctx, 'Write', filePath)) {
|
|
22
|
+
return { behavior: 'allow' };
|
|
23
|
+
}
|
|
24
|
+
return { behavior: 'passthrough', message: `Allow creating ${filePath}?` };
|
|
25
|
+
},
|
|
26
|
+
validateInput(input) {
|
|
27
|
+
if (typeof input.file_path !== 'string' || !input.file_path.trim()) {
|
|
28
|
+
return { valid: false, error: 'file_path is required' };
|
|
29
|
+
}
|
|
30
|
+
if (typeof input.content !== 'string') {
|
|
31
|
+
return { valid: false, error: 'content is required' };
|
|
32
|
+
}
|
|
33
|
+
return { valid: true };
|
|
34
|
+
},
|
|
35
|
+
getPath(input) { return input.file_path; },
|
|
36
|
+
async execute(input) {
|
|
37
|
+
const filePath = resolve(input.file_path);
|
|
38
|
+
const content = input.content;
|
|
39
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
40
|
+
await writeFile(filePath, content, 'utf-8');
|
|
41
|
+
const lines = content.split('\n');
|
|
42
|
+
const diff = lines.map((l, i) => `@@+:${i + 1}:${l}`).join('\n');
|
|
43
|
+
return `@@FILE:${filePath}\n@@NEW:${lines.length} lines\n${diff}`;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAY,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE9E,MAAM,CAAC,MAAM,SAAS,GAAY;IAChC,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,iFAAiF;IAC9F,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;YAC5E,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;SACzE;QACD,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;KACnC;IACD,UAAU,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC;IAC9B,gBAAgB,CAAC,KAA8B,EAAE,GAA0B;QACzE,MAAM,QAAQ,GAAI,KAAK,CAAC,SAAoB,IAAI,EAAE,CAAC;QACnD,IAAI,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,QAAQ,EAAE,EAAE,CAAC;QAC1E,CAAC;QACD,IAAI,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC7C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC/B,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,kBAAkB,QAAQ,GAAG,EAAE,CAAC;IAC7E,CAAC;IACD,aAAa,CAAC,KAAK;QACjB,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACnE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC1D,CAAC;QACD,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,SAA+B,CAAC,CAAC,CAAC;IAChE,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,SAAmB,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAiB,CAAC;QAExC,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAE5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjE,OAAO,UAAU,QAAQ,WAAW,KAAK,CAAC,MAAM,WAAW,IAAI,EAAE,CAAC;IACpE,CAAC;CACF,CAAC"}
|