thatgfsj-code 0.3.0 → 0.3.1
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/CHANGELOG.md +229 -0
- package/DEVELOPMENT.md +286 -0
- package/README.md +144 -79
- package/dist/agent/core.d.ts +56 -0
- package/dist/agent/core.d.ts.map +1 -0
- package/dist/agent/core.js +142 -0
- package/dist/agent/core.js.map +1 -0
- package/dist/agent/index.d.ts +8 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +8 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/intent.d.ts +36 -0
- package/dist/agent/intent.d.ts.map +1 -0
- package/dist/agent/intent.js +146 -0
- package/dist/agent/intent.js.map +1 -0
- package/dist/agent/streaming.d.ts +50 -0
- package/dist/agent/streaming.d.ts.map +1 -0
- package/dist/agent/streaming.js +110 -0
- package/dist/agent/streaming.js.map +1 -0
- package/dist/core/ai-engine.d.ts +76 -0
- package/dist/core/ai-engine.d.ts.map +1 -0
- package/dist/core/ai-engine.js +394 -0
- package/dist/core/ai-engine.js.map +1 -0
- package/dist/core/cli.d.ts +21 -0
- package/dist/core/cli.d.ts.map +1 -0
- package/dist/core/cli.js +143 -0
- package/dist/core/cli.js.map +1 -0
- package/dist/core/config.d.ts +55 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +162 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context-compactor.d.ts +54 -0
- package/dist/core/context-compactor.d.ts.map +1 -0
- package/dist/core/context-compactor.js +197 -0
- package/dist/core/context-compactor.js.map +1 -0
- package/dist/core/hooks.d.ts +75 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +146 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/permissions.d.ts +52 -0
- package/dist/core/permissions.d.ts.map +1 -0
- package/dist/core/permissions.js +237 -0
- package/dist/core/permissions.js.map +1 -0
- package/dist/core/session.d.ts +54 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +147 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/skills.d.ts +60 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +175 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/state.d.ts +60 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +106 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/subagent.d.ts +68 -0
- package/dist/core/subagent.d.ts.map +1 -0
- package/dist/core/subagent.js +142 -0
- package/dist/core/subagent.js.map +1 -0
- package/dist/core/system-prompt.d.ts +40 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +138 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/tool-registry.d.ts +53 -0
- package/dist/core/tool-registry.d.ts.map +1 -0
- package/dist/core/tool-registry.js +138 -0
- package/dist/core/tool-registry.js.map +1 -0
- package/dist/core/types.d.ts +206 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +127 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/{cmd/index.d.ts.map → index.d.ts.map} +1 -1
- package/dist/index.js +472 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/repl/index.d.ts +8 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/repl/index.js +8 -0
- package/dist/repl/index.js.map +1 -0
- package/dist/repl/input.d.ts +69 -0
- package/dist/repl/input.d.ts.map +1 -0
- package/dist/repl/input.js +139 -0
- package/dist/repl/input.js.map +1 -0
- package/dist/repl/loop.d.ts +184 -0
- package/dist/repl/loop.d.ts.map +1 -0
- package/dist/repl/loop.js +932 -0
- package/dist/repl/loop.js.map +1 -0
- package/dist/repl/output.d.ts +105 -0
- package/dist/repl/output.d.ts.map +1 -0
- package/dist/repl/output.js +199 -0
- package/dist/repl/output.js.map +1 -0
- package/dist/repl/welcome.d.ts +68 -0
- package/dist/repl/welcome.d.ts.map +1 -0
- package/dist/repl/welcome.js +254 -0
- package/dist/repl/welcome.js.map +1 -0
- package/dist/tools/file.d.ts +1 -1
- package/dist/tools/file.d.ts.map +1 -1
- package/dist/tools/git.d.ts +1 -1
- package/dist/tools/git.d.ts.map +1 -1
- package/dist/tools/index.d.ts +15 -35
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +31 -80
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/search.d.ts +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/shell.d.ts +11 -4
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +78 -42
- package/dist/tools/shell.js.map +1 -1
- package/dist/utils/diff-preview.d.ts +42 -0
- package/dist/utils/diff-preview.d.ts.map +1 -0
- package/dist/utils/diff-preview.js +174 -0
- package/dist/utils/diff-preview.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/memory.d.ts +81 -0
- package/dist/utils/memory.d.ts.map +1 -0
- package/dist/utils/memory.js +186 -0
- package/dist/utils/memory.js.map +1 -0
- package/dist/utils/project-context.d.ts +62 -0
- package/dist/utils/project-context.d.ts.map +1 -0
- package/dist/utils/project-context.js +197 -0
- package/dist/utils/project-context.js.map +1 -0
- package/docs/API_KEY_GUIDE.md +6 -0
- package/docs/FAQ.md +25 -3
- package/package.json +41 -9
- package/ROADMAP.md +0 -61
- package/dist/app/agent.d.ts +0 -31
- package/dist/app/agent.d.ts.map +0 -1
- package/dist/app/agent.js +0 -106
- package/dist/app/agent.js.map +0 -1
- package/dist/app/index.d.ts +0 -39
- package/dist/app/index.d.ts.map +0 -1
- package/dist/app/index.js +0 -80
- package/dist/app/index.js.map +0 -1
- package/dist/cmd/index.d.ts +0 -12
- package/dist/cmd/index.js +0 -85
- package/dist/cmd/index.js.map +0 -1
- package/dist/config/index.d.ts +0 -39
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -110
- package/dist/config/index.js.map +0 -1
- package/dist/config/providers.d.ts +0 -23
- package/dist/config/providers.d.ts.map +0 -1
- package/dist/config/providers.js +0 -152
- package/dist/config/providers.js.map +0 -1
- package/dist/config/types.d.ts +0 -33
- package/dist/config/types.d.ts.map +0 -1
- package/dist/config/types.js +0 -5
- package/dist/config/types.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -31
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -71
- package/dist/hooks/index.js.map +0 -1
- package/dist/llm/anthropic.d.ts +0 -17
- package/dist/llm/anthropic.d.ts.map +0 -1
- package/dist/llm/anthropic.js +0 -126
- package/dist/llm/anthropic.js.map +0 -1
- package/dist/llm/gemini.d.ts +0 -16
- package/dist/llm/gemini.d.ts.map +0 -1
- package/dist/llm/gemini.js +0 -107
- package/dist/llm/gemini.js.map +0 -1
- package/dist/llm/index.d.ts +0 -48
- package/dist/llm/index.d.ts.map +0 -1
- package/dist/llm/index.js +0 -174
- package/dist/llm/index.js.map +0 -1
- package/dist/llm/openai.d.ts +0 -17
- package/dist/llm/openai.d.ts.map +0 -1
- package/dist/llm/openai.js +0 -113
- package/dist/llm/openai.js.map +0 -1
- package/dist/llm/provider.d.ts +0 -33
- package/dist/llm/provider.d.ts.map +0 -1
- package/dist/llm/provider.js +0 -6
- package/dist/llm/provider.js.map +0 -1
- package/dist/prompts/index.d.ts +0 -27
- package/dist/prompts/index.d.ts.map +0 -1
- package/dist/prompts/index.js +0 -102
- package/dist/prompts/index.js.map +0 -1
- package/dist/session/compactor.d.ts +0 -48
- package/dist/session/compactor.d.ts.map +0 -1
- package/dist/session/compactor.js +0 -77
- package/dist/session/compactor.js.map +0 -1
- package/dist/session/index.d.ts +0 -48
- package/dist/session/index.d.ts.map +0 -1
- package/dist/session/index.js +0 -69
- package/dist/session/index.js.map +0 -1
- package/dist/session/message.d.ts +0 -26
- package/dist/session/message.d.ts.map +0 -1
- package/dist/session/message.js +0 -34
- package/dist/session/message.js.map +0 -1
- package/dist/tools/types.d.ts +0 -68
- package/dist/tools/types.d.ts.map +0 -1
- package/dist/tools/types.js +0 -57
- package/dist/tools/types.js.map +0 -1
- package/dist/tui/index.d.ts +0 -8
- package/dist/tui/index.d.ts.map +0 -1
- package/dist/tui/index.js +0 -8
- package/dist/tui/index.js.map +0 -1
- package/dist/tui/input.d.ts +0 -14
- package/dist/tui/input.d.ts.map +0 -1
- package/dist/tui/input.js +0 -50
- package/dist/tui/input.js.map +0 -1
- package/dist/tui/output.d.ts +0 -20
- package/dist/tui/output.d.ts.map +0 -1
- package/dist/tui/output.js +0 -70
- package/dist/tui/output.js.map +0 -1
- package/dist/tui/repl.d.ts +0 -25
- package/dist/tui/repl.d.ts.map +0 -1
- package/dist/tui/repl.js +0 -114
- package/dist/tui/repl.js.map +0 -1
- package/dist/tui/welcome.d.ts +0 -15
- package/dist/tui/welcome.d.ts.map +0 -1
- package/dist/tui/welcome.js +0 -86
- package/dist/tui/welcome.js.map +0 -1
- package/dist/types.d.ts +0 -38
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
- package/dist/utils/diff.d.ts +0 -22
- package/dist/utils/diff.d.ts.map +0 -1
- package/dist/utils/diff.js +0 -60
- package/dist/utils/diff.js.map +0 -1
- package/dist/utils/project.d.ts +0 -32
- package/dist/utils/project.d.ts.map +0 -1
- package/dist/utils/project.js +0 -89
- package/dist/utils/project.js.map +0 -1
- package/src/app/agent.ts +0 -140
- package/src/app/index.ts +0 -101
- package/src/cmd/index.ts +0 -96
- package/src/config/index.ts +0 -130
- package/src/config/providers.ts +0 -160
- package/src/config/types.ts +0 -46
- package/src/hooks/index.ts +0 -111
- package/src/llm/anthropic.ts +0 -146
- package/src/llm/gemini.ts +0 -127
- package/src/llm/index.ts +0 -209
- package/src/llm/openai.ts +0 -132
- package/src/llm/provider.ts +0 -38
- package/src/mcp/client.ts +0 -330
- package/src/prompts/index.ts +0 -123
- package/src/session/compactor.ts +0 -103
- package/src/session/index.ts +0 -81
- package/src/session/message.ts +0 -42
- package/src/tools/file.ts +0 -117
- package/src/tools/git.ts +0 -132
- package/src/tools/index.ts +0 -108
- package/src/tools/search.ts +0 -263
- package/src/tools/shell.ts +0 -136
- package/src/tools/types.ts +0 -122
- package/src/tui/index.ts +0 -8
- package/src/tui/input.ts +0 -56
- package/src/tui/output.ts +0 -83
- package/src/tui/repl.ts +0 -131
- package/src/tui/welcome.ts +0 -101
- package/src/types.ts +0 -42
- package/src/utils/diff.ts +0 -71
- package/src/utils/project.ts +0 -99
- package/tsconfig.json +0 -19
package/src/tools/file.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File Tool - File operations
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Tool, ToolResult } from './types.js';
|
|
6
|
-
import { readFileSync, writeFileSync, existsSync, readdirSync, statSync, mkdirSync, unlinkSync } from 'fs';
|
|
7
|
-
import { join, dirname, basename, extname } from 'path';
|
|
8
|
-
|
|
9
|
-
export class FileTool implements Tool {
|
|
10
|
-
name = 'file';
|
|
11
|
-
description = 'Perform file operations: read, write, list, delete, etc.';
|
|
12
|
-
|
|
13
|
-
inputSchema = {
|
|
14
|
-
type: 'object' as const,
|
|
15
|
-
properties: {
|
|
16
|
-
action: { type: 'string', description: 'Action: read, write, list, delete, exists, mkdir' },
|
|
17
|
-
path: { type: 'string', description: 'File or directory path' },
|
|
18
|
-
content: { type: 'string', description: 'Content to write (for write action)' }
|
|
19
|
-
},
|
|
20
|
-
required: ['action', 'path']
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
metadata = {
|
|
24
|
-
permissions: ['read', 'write'] as ('read' | 'write' | 'execute' | 'network')[],
|
|
25
|
-
tags: ['file', 'filesystem'],
|
|
26
|
-
maxDuration: 30000,
|
|
27
|
-
version: '1.0.0'
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
parameters = [
|
|
31
|
-
{ name: 'action', type: 'string', description: 'Action to perform: read, write, list, delete, exists', required: true },
|
|
32
|
-
{ name: 'path', type: 'string', description: 'File or directory path', required: true },
|
|
33
|
-
{ name: 'content', type: 'string', description: 'Content to write (for write action)', required: false }
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
async execute(params: Record<string, any>): Promise<ToolResult> {
|
|
37
|
-
const { action, path, content } = params;
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
switch (action) {
|
|
41
|
-
case 'read':
|
|
42
|
-
return this.readFile(path);
|
|
43
|
-
case 'write':
|
|
44
|
-
return this.writeFile(path, content || '');
|
|
45
|
-
case 'list':
|
|
46
|
-
return this.listDir(path);
|
|
47
|
-
case 'delete':
|
|
48
|
-
return this.deleteFile(path);
|
|
49
|
-
case 'exists':
|
|
50
|
-
return this.checkExists(path);
|
|
51
|
-
case 'mkdir':
|
|
52
|
-
return this.mkdir(path);
|
|
53
|
-
default:
|
|
54
|
-
return { success: false, error: `Unknown action: ${action}` };
|
|
55
|
-
}
|
|
56
|
-
} catch (error: any) {
|
|
57
|
-
return { success: false, error: error.message };
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private readFile(path: string): ToolResult {
|
|
62
|
-
if (!existsSync(path)) {
|
|
63
|
-
return { success: false, error: `File not found: ${path}` };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const content = readFileSync(path, 'utf-8');
|
|
67
|
-
return { success: true, output: content };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
private writeFile(path: string, content: string): ToolResult {
|
|
71
|
-
const dir = dirname(path);
|
|
72
|
-
if (!existsSync(dir)) {
|
|
73
|
-
mkdirSync(dir, { recursive: true });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
writeFileSync(path, content, 'utf-8');
|
|
77
|
-
return { success: true, output: `File written: ${path}` };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private listDir(path: string): ToolResult {
|
|
81
|
-
if (!existsSync(path)) {
|
|
82
|
-
return { success: false, error: `Directory not found: ${path}` };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const files = readdirSync(path);
|
|
86
|
-
const items = files.map(f => {
|
|
87
|
-
const fullPath = join(path, f);
|
|
88
|
-
const stat = statSync(fullPath);
|
|
89
|
-
return {
|
|
90
|
-
name: f,
|
|
91
|
-
type: stat.isDirectory() ? 'dir' : 'file',
|
|
92
|
-
size: stat.size,
|
|
93
|
-
modified: stat.mtime.toISOString()
|
|
94
|
-
};
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
return { success: true, output: JSON.stringify(items, null, 2) };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private deleteFile(path: string): ToolResult {
|
|
101
|
-
if (!existsSync(path)) {
|
|
102
|
-
return { success: false, error: `Path not found: ${path}` };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
unlinkSync(path);
|
|
106
|
-
return { success: true, output: `Deleted: ${path}` };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private checkExists(path: string): ToolResult {
|
|
110
|
-
return { success: true, output: existsSync(path) ? 'true' : 'false' };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
private mkdir(path: string): ToolResult {
|
|
114
|
-
mkdirSync(path, { recursive: true });
|
|
115
|
-
return { success: true, output: `Created: ${path}` };
|
|
116
|
-
}
|
|
117
|
-
}
|
package/src/tools/git.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Git Tool - Git operations
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Tool, ToolResult } from './types.js';
|
|
6
|
-
import { exec } from 'child_process';
|
|
7
|
-
import { promisify } from 'util';
|
|
8
|
-
import { existsSync } from 'fs';
|
|
9
|
-
|
|
10
|
-
const execAsync = promisify(exec);
|
|
11
|
-
|
|
12
|
-
export class GitTool implements Tool {
|
|
13
|
-
name = 'git';
|
|
14
|
-
description = 'Git operations: status, log, diff, commit, branch, etc.';
|
|
15
|
-
|
|
16
|
-
inputSchema = {
|
|
17
|
-
type: 'object' as const,
|
|
18
|
-
properties: {
|
|
19
|
-
action: { type: 'string', description: 'Git action: status, log, diff, commit, branch, checkout, pull, push' },
|
|
20
|
-
args: { type: 'string', description: 'Additional arguments' },
|
|
21
|
-
message: { type: 'string', description: 'Commit message' },
|
|
22
|
-
cwd: { type: 'string', description: 'Working directory' }
|
|
23
|
-
},
|
|
24
|
-
required: ['action']
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
metadata = {
|
|
28
|
-
permissions: ['execute'] as ('read' | 'write' | 'execute' | 'network')[],
|
|
29
|
-
tags: ['git', 'vcs'],
|
|
30
|
-
version: '1.0.0'
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
parameters = [
|
|
34
|
-
{ name: 'action', type: 'string', description: 'Git action: status, log, diff, commit, branch, checkout, pull, push', required: true },
|
|
35
|
-
{ name: 'args', type: 'string', description: 'Additional arguments', required: false },
|
|
36
|
-
{ name: 'message', type: 'string', description: 'Commit message (for commit action)', required: false },
|
|
37
|
-
{ name: 'cwd', type: 'string', description: 'Working directory', required: false }
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
async execute(params: Record<string, any>): Promise<ToolResult> {
|
|
41
|
-
const { action, args, message, cwd } = params;
|
|
42
|
-
const workDir = cwd || process.cwd();
|
|
43
|
-
|
|
44
|
-
// Check if git repo exists
|
|
45
|
-
if (!existsSync(`${workDir}/.git`)) {
|
|
46
|
-
return { success: false, error: 'Not a git repository' };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
switch (action) {
|
|
51
|
-
case 'status':
|
|
52
|
-
return await this.status(workDir);
|
|
53
|
-
case 'log':
|
|
54
|
-
return await this.log(workDir, args || '10');
|
|
55
|
-
case 'diff':
|
|
56
|
-
return await this.diff(workDir, args || '');
|
|
57
|
-
case 'commit':
|
|
58
|
-
return await this.commit(workDir, message || args);
|
|
59
|
-
case 'branch':
|
|
60
|
-
return await this.branch(workDir);
|
|
61
|
-
case 'checkout':
|
|
62
|
-
return await this.checkout(workDir, args);
|
|
63
|
-
case 'pull':
|
|
64
|
-
return await this.pull(workDir);
|
|
65
|
-
case 'push':
|
|
66
|
-
return await this.push(workDir);
|
|
67
|
-
case 'add':
|
|
68
|
-
return await this.add(workDir, args || '.');
|
|
69
|
-
default:
|
|
70
|
-
return { success: false, error: `Unknown action: ${action}` };
|
|
71
|
-
}
|
|
72
|
-
} catch (error: any) {
|
|
73
|
-
return { success: false, error: error.message };
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
private async status(cwd: string): Promise<ToolResult> {
|
|
78
|
-
const { stdout } = await execAsync('git status --short', { cwd });
|
|
79
|
-
return { success: true, output: stdout || '(clean)' };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
private async log(cwd: string, limit: string): Promise<ToolResult> {
|
|
83
|
-
const { stdout } = await execAsync(`git log --oneline -n ${limit}`, { cwd });
|
|
84
|
-
return { success: true, output: stdout || 'No commits yet' };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private async diff(cwd: string, args: string): Promise<ToolResult> {
|
|
88
|
-
const { stdout } = await execAsync(`git diff ${args}`, { cwd });
|
|
89
|
-
return { success: true, output: stdout || 'No changes' };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private async commit(cwd: string, message: string): Promise<ToolResult> {
|
|
93
|
-
if (!message) {
|
|
94
|
-
return { success: false, error: 'Commit message required' };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Stage all changes
|
|
98
|
-
await execAsync('git add -A', { cwd });
|
|
99
|
-
|
|
100
|
-
const { stdout } = await execAsync(`git commit -m "${message}"`, { cwd });
|
|
101
|
-
return { success: true, output: stdout || 'Committed successfully' };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private async branch(cwd: string): Promise<ToolResult> {
|
|
105
|
-
const { stdout } = await execAsync('git branch -a', { cwd });
|
|
106
|
-
return { success: true, output: stdout };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private async checkout(cwd: string, branch: string): Promise<ToolResult> {
|
|
110
|
-
if (!branch) {
|
|
111
|
-
return { success: false, error: 'Branch name required' };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const { stdout } = await execAsync(`git checkout ${branch}`, { cwd });
|
|
115
|
-
return { success: true, output: stdout };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private async pull(cwd: string): Promise<ToolResult> {
|
|
119
|
-
const { stdout } = await execAsync('git pull', { cwd });
|
|
120
|
-
return { success: true, output: stdout };
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
private async push(cwd: string): Promise<ToolResult> {
|
|
124
|
-
const { stdout } = await execAsync('git push', { cwd });
|
|
125
|
-
return { success: true, output: stdout };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private async add(cwd: string, files: string): Promise<ToolResult> {
|
|
129
|
-
const { stdout } = await execAsync(`git add ${files}`, { cwd });
|
|
130
|
-
return { success: true, output: stdout || 'Added successfully' };
|
|
131
|
-
}
|
|
132
|
-
}
|
package/src/tools/index.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool Registry - Manages available tools
|
|
3
|
-
* Migrated from old src/core/tool-registry.ts + src/tools/index.ts
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Tool, ToolResult, ToolContext, ToolInputSchema } from './types.js';
|
|
7
|
-
import { FileTool } from './file.js';
|
|
8
|
-
import { ShellTool } from './shell.js';
|
|
9
|
-
import { GitTool } from './git.js';
|
|
10
|
-
import { SearchTool } from './search.js';
|
|
11
|
-
|
|
12
|
-
export class ToolRegistry {
|
|
13
|
-
private tools: Map<string, Tool> = new Map();
|
|
14
|
-
private context: ToolContext = {};
|
|
15
|
-
|
|
16
|
-
constructor() {
|
|
17
|
-
this.registerDefaults();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Register default built-in tools
|
|
22
|
-
*/
|
|
23
|
-
private registerDefaults(): void {
|
|
24
|
-
this.register(new FileTool());
|
|
25
|
-
this.register(new ShellTool());
|
|
26
|
-
this.register(new GitTool());
|
|
27
|
-
this.register(new SearchTool());
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
setContext(ctx: Partial<ToolContext>): void {
|
|
31
|
-
this.context = { ...this.context, ...ctx };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
register(tool: Tool): void {
|
|
35
|
-
this.tools.set(tool.name, tool);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
unregister(name: string): boolean {
|
|
39
|
-
return this.tools.delete(name);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get(name: string): Tool | undefined {
|
|
43
|
-
return this.tools.get(name);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
list(): Tool[] {
|
|
47
|
-
return [...this.tools.values()];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
listNames(): string[] {
|
|
51
|
-
return [...this.tools.keys()];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Get tools formatted for AI API
|
|
56
|
-
*/
|
|
57
|
-
getToolsForAPI(): Array<{ type: 'function'; function: any }> {
|
|
58
|
-
return [...this.tools.values()].map(tool => ({
|
|
59
|
-
type: 'function' as const,
|
|
60
|
-
function: {
|
|
61
|
-
name: tool.name,
|
|
62
|
-
description: tool.description,
|
|
63
|
-
parameters: tool.inputSchema || this.buildInputSchema(tool),
|
|
64
|
-
},
|
|
65
|
-
}));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Build JSON Schema from legacy parameters array
|
|
70
|
-
*/
|
|
71
|
-
private buildInputSchema(tool: Tool): ToolInputSchema {
|
|
72
|
-
return {
|
|
73
|
-
type: 'object',
|
|
74
|
-
properties: tool.parameters.reduce((acc, p) => {
|
|
75
|
-
acc[p.name] = {
|
|
76
|
-
type: p.type === 'number' ? 'number' : p.type === 'boolean' ? 'boolean' : 'string',
|
|
77
|
-
description: p.description,
|
|
78
|
-
};
|
|
79
|
-
return acc;
|
|
80
|
-
}, {} as Record<string, { type: string; description: string }>),
|
|
81
|
-
required: tool.parameters.filter(p => p.required).map(p => p.name),
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Execute a tool by name
|
|
87
|
-
*/
|
|
88
|
-
async execute(name: string, params: Record<string, any>): Promise<ToolResult> {
|
|
89
|
-
const tool = this.tools.get(name);
|
|
90
|
-
if (!tool) {
|
|
91
|
-
return { success: false, error: `Tool "${name}" not found` };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
return await tool.execute(params, this.context);
|
|
96
|
-
} catch (error: any) {
|
|
97
|
-
return { success: false, error: error.message };
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Re-export types and tools
|
|
103
|
-
export type { Tool, ToolResult, ToolContext, ToolParameter, ToolInputSchema, ToolMetadata } from './types.js';
|
|
104
|
-
export { ToolBuilder } from './types.js';
|
|
105
|
-
export { FileTool } from './file.js';
|
|
106
|
-
export { ShellTool } from './shell.js';
|
|
107
|
-
export { GitTool } from './git.js';
|
|
108
|
-
export { SearchTool } from './search.js';
|
package/src/tools/search.ts
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Search Tool - Code search and file operations
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Tool, ToolResult } from './types.js';
|
|
6
|
-
import { exec } from 'child_process';
|
|
7
|
-
import { promisify } from 'util';
|
|
8
|
-
import { readdirSync, statSync, readFileSync } from 'fs';
|
|
9
|
-
import { join, relative } from 'path';
|
|
10
|
-
|
|
11
|
-
const execAsync = promisify(exec);
|
|
12
|
-
|
|
13
|
-
export class SearchTool implements Tool {
|
|
14
|
-
name = 'search';
|
|
15
|
-
description = 'Search and find: grep, find files, list directory tree';
|
|
16
|
-
|
|
17
|
-
parameters = [
|
|
18
|
-
{ name: 'action', type: 'string', description: 'Action: grep, find, tree, files', required: true },
|
|
19
|
-
{ name: 'pattern', type: 'string', description: 'Search pattern or file pattern', required: false },
|
|
20
|
-
{ name: 'path', type: 'string', description: 'Directory to search in', required: false },
|
|
21
|
-
{ name: 'options', type: 'string', description: 'Additional options', required: false }
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
async execute(params: Record<string, any>): Promise<ToolResult> {
|
|
25
|
-
const { action, pattern, path, options } = params;
|
|
26
|
-
const workDir = path || process.cwd();
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
switch (action) {
|
|
30
|
-
case 'grep':
|
|
31
|
-
case 'search':
|
|
32
|
-
return await this.grep(pattern || '', workDir, options || '');
|
|
33
|
-
|
|
34
|
-
case 'find':
|
|
35
|
-
return await this.find(pattern || '*', workDir);
|
|
36
|
-
|
|
37
|
-
case 'tree':
|
|
38
|
-
return await this.tree(workDir, parseInt(options) || 3);
|
|
39
|
-
|
|
40
|
-
case 'files':
|
|
41
|
-
return await this.listFiles(workDir, pattern || '*');
|
|
42
|
-
|
|
43
|
-
default:
|
|
44
|
-
return { success: false, error: `Unknown action: ${action}` };
|
|
45
|
-
}
|
|
46
|
-
} catch (error: any) {
|
|
47
|
-
return { success: false, error: error.message };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Grep - search for pattern in files
|
|
53
|
-
*/
|
|
54
|
-
private async grep(pattern: string, path: string, options: string): Promise<ToolResult> {
|
|
55
|
-
if (!pattern) {
|
|
56
|
-
return { success: false, error: 'Pattern required' };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Build grep command
|
|
60
|
-
let cmd = `grep -rn "${pattern}" "${path}"`;
|
|
61
|
-
|
|
62
|
-
if (options?.includes('i')) cmd += ' -i'; // Case insensitive
|
|
63
|
-
if (options?.includes('w')) cmd += ' -w'; // Whole word
|
|
64
|
-
if (options?.includes('l')) cmd += ' -l'; // Files only
|
|
65
|
-
if (options?.includes('n')) cmd += ' -n'; // Line numbers
|
|
66
|
-
|
|
67
|
-
cmd += ' --color=never';
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
const { stdout, stderr } = await execAsync(cmd, { timeout: 30000 });
|
|
71
|
-
|
|
72
|
-
if (!stdout && stderr) {
|
|
73
|
-
return { success: false, error: stderr };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const lines = (stdout || '').split('\n').filter(l => l.trim());
|
|
77
|
-
|
|
78
|
-
if (lines.length === 0) {
|
|
79
|
-
return { success: true, output: 'No matches found' };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Limit output
|
|
83
|
-
const limited = lines.slice(0, 50);
|
|
84
|
-
const output = limited.join('\n');
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
success: true,
|
|
88
|
-
output: lines.length > 50
|
|
89
|
-
? output + `\n... and ${lines.length - 50} more matches`
|
|
90
|
-
: output
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
} catch (error: any) {
|
|
94
|
-
if (error.killed) {
|
|
95
|
-
return { success: false, error: 'Search timed out (>30s)' };
|
|
96
|
-
}
|
|
97
|
-
return { success: false, error: error.message };
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Find - find files by pattern
|
|
103
|
-
*/
|
|
104
|
-
private async find(pattern: string, path: string): Promise<ToolResult> {
|
|
105
|
-
if (!pattern) {
|
|
106
|
-
pattern = '*';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const results: string[] = [];
|
|
110
|
-
|
|
111
|
-
const search = (dir: string, depth: number) => {
|
|
112
|
-
if (depth > 5) return; // Max depth
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
const items = readdirSync(dir);
|
|
116
|
-
|
|
117
|
-
for (const item of items) {
|
|
118
|
-
// Skip common ignored directories
|
|
119
|
-
if (item === 'node_modules' || item === '.git' || item === 'dist' || item === 'build') {
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const fullPath = join(dir, item);
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const stat = statSync(fullPath);
|
|
127
|
-
|
|
128
|
-
if (stat.isDirectory()) {
|
|
129
|
-
// Check if matches pattern
|
|
130
|
-
if (this.matchPattern(item, pattern)) {
|
|
131
|
-
results.push(fullPath);
|
|
132
|
-
}
|
|
133
|
-
search(fullPath, depth + 1);
|
|
134
|
-
} else if (stat.isFile()) {
|
|
135
|
-
if (this.matchPattern(item, pattern)) {
|
|
136
|
-
results.push(fullPath);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
} catch {
|
|
140
|
-
// Skip inaccessible files
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
} catch {
|
|
144
|
-
// Skip inaccessible directories
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
search(path, 0);
|
|
149
|
-
|
|
150
|
-
if (results.length === 0) {
|
|
151
|
-
return { success: true, output: 'No files found' };
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const limited = results.slice(0, 100);
|
|
155
|
-
const output = limited.join('\n');
|
|
156
|
-
|
|
157
|
-
return {
|
|
158
|
-
success: true,
|
|
159
|
-
output: results.length > 100
|
|
160
|
-
? output + `\n... and ${results.length - 100} more files`
|
|
161
|
-
: output
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Tree - show directory structure
|
|
167
|
-
*/
|
|
168
|
-
private async tree(path: string, maxDepth: number): Promise<ToolResult> {
|
|
169
|
-
const lines: string[] = [];
|
|
170
|
-
|
|
171
|
-
const walk = (dir: string, prefix: string, depth: number) => {
|
|
172
|
-
if (depth > maxDepth) return;
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
const items = readdirSync(dir).filter(i =>
|
|
176
|
-
!i.startsWith('.') && i !== 'node_modules' && i !== 'dist'
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
for (let i = 0; i < items.length; i++) {
|
|
180
|
-
const item = items[i];
|
|
181
|
-
const fullPath = join(dir, item);
|
|
182
|
-
const isLast = i === items.length - 1;
|
|
183
|
-
const connector = isLast ? '└── ' : '├── ';
|
|
184
|
-
|
|
185
|
-
lines.push(prefix + connector + item);
|
|
186
|
-
|
|
187
|
-
try {
|
|
188
|
-
const stat = statSync(fullPath);
|
|
189
|
-
if (stat.isDirectory()) {
|
|
190
|
-
const newPrefix = prefix + (isLast ? ' ' : '│ ');
|
|
191
|
-
walk(fullPath, newPrefix, depth + 1);
|
|
192
|
-
}
|
|
193
|
-
} catch {
|
|
194
|
-
// Skip
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
} catch {
|
|
198
|
-
// Skip inaccessible
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
lines.push(relative(process.cwd(), path) || '.');
|
|
203
|
-
walk(path, '', 0);
|
|
204
|
-
|
|
205
|
-
return { success: true, output: lines.join('\n') };
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* List files in directory
|
|
210
|
-
*/
|
|
211
|
-
private async listFiles(path: string, pattern: string): Promise<ToolResult> {
|
|
212
|
-
const files: string[] = [];
|
|
213
|
-
|
|
214
|
-
const scan = (dir: string) => {
|
|
215
|
-
try {
|
|
216
|
-
const items = readdirSync(dir);
|
|
217
|
-
|
|
218
|
-
for (const item of items) {
|
|
219
|
-
if (item === 'node_modules' || item === '.git') continue;
|
|
220
|
-
|
|
221
|
-
const fullPath = join(dir, item);
|
|
222
|
-
|
|
223
|
-
try {
|
|
224
|
-
const stat = statSync(fullPath);
|
|
225
|
-
if (stat.isFile() && this.matchPattern(item, pattern)) {
|
|
226
|
-
files.push(relative(process.cwd(), fullPath));
|
|
227
|
-
}
|
|
228
|
-
} catch {
|
|
229
|
-
// Skip
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
} catch {
|
|
233
|
-
// Skip
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
scan(path);
|
|
238
|
-
|
|
239
|
-
if (files.length === 0) {
|
|
240
|
-
return { success: true, output: 'No files found' };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return { success: true, output: files.join('\n') };
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Simple glob-like pattern matching
|
|
248
|
-
*/
|
|
249
|
-
private matchPattern(filename: string, pattern: string): boolean {
|
|
250
|
-
if (pattern === '*') return true;
|
|
251
|
-
|
|
252
|
-
// Convert glob to regex
|
|
253
|
-
const regex = new RegExp(
|
|
254
|
-
'^' + pattern
|
|
255
|
-
.replace(/\./g, '\\.')
|
|
256
|
-
.replace(/\*/g, '.*')
|
|
257
|
-
.replace(/\?/g, '.') + '$',
|
|
258
|
-
'i'
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
return regex.test(filename);
|
|
262
|
-
}
|
|
263
|
-
}
|