aegiscode 3.1.7 → 3.1.10
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 +23 -15
- package/dist/main.js +555 -556
- package/package.json +4 -2
- package/src/agent/Agent.ts +903 -0
- package/src/agent/SimpleAgent.ts +48 -0
- package/src/agent/index.ts +54 -0
- package/src/agent/orchestrator/AppBuilder.ts +443 -0
- package/src/agent/orchestrator/CouncilAgent.ts +310 -0
- package/src/agent/orchestrator/DiscussionRoom.ts +462 -0
- package/src/agent/orchestrator/OrchestratorAgent.ts +637 -0
- package/src/agent/orchestrator/index.ts +38 -0
- package/src/agent/orchestrator/utils.ts +397 -0
- package/src/agent/pricing.ts +115 -0
- package/src/agent/router.ts +74 -0
- package/src/agent/routerStats.ts +121 -0
- package/src/agent/types.ts +318 -0
- package/src/auth/login.ts +383 -0
- package/src/cli/config.ts +189 -0
- package/src/cli/index.ts +17 -0
- package/src/cli/middleware.ts +119 -0
- package/src/cli/types.ts +75 -0
- package/src/config/ConfigManager.ts +587 -0
- package/src/config/index.ts +7 -0
- package/src/config/types.ts +584 -0
- package/src/context/CompactionService.ts +300 -0
- package/src/context/ContextManager.ts +450 -0
- package/src/context/FileAnalyzer.ts +267 -0
- package/src/context/TokenCounter.ts +265 -0
- package/src/context/index.ts +27 -0
- package/src/context/storage/CacheStore.ts +176 -0
- package/src/context/storage/JSONLStore.ts +201 -0
- package/src/context/storage/MemoryStore.ts +205 -0
- package/src/context/storage/PersistentStore.ts +327 -0
- package/src/context/storage/index.ts +9 -0
- package/src/context/storage/pathUtils.ts +114 -0
- package/src/context/test.ts +309 -0
- package/src/context/types.ts +268 -0
- package/src/hooks/HookExecutor.ts +434 -0
- package/src/hooks/HookManager.ts +596 -0
- package/src/hooks/HookService.ts +269 -0
- package/src/hooks/Matcher.ts +157 -0
- package/src/hooks/index.ts +63 -0
- package/src/hooks/types.ts +424 -0
- package/src/main.tsx +596 -0
- package/src/mcp/HealthMonitor.ts +150 -0
- package/src/mcp/McpClient.ts +491 -0
- package/src/mcp/McpRegistry.ts +321 -0
- package/src/mcp/createMcpTool.ts +251 -0
- package/src/mcp/index.ts +15 -0
- package/src/mcp/server.ts +334 -0
- package/src/mcp/test-server.ts +88 -0
- package/src/mcp/test.ts +372 -0
- package/src/mcp/types.ts +247 -0
- package/src/memory/AgentMemoryBus.ts +432 -0
- package/src/memory/CloudSync.ts +99 -0
- package/src/memory/DriveSync.ts +106 -0
- package/src/memory/SharedMemory.ts +951 -0
- package/src/memory/index.ts +14 -0
- package/src/memory/machineFingerprint.ts +40 -0
- package/src/orchestrator/SubAgentMetadata.ts +136 -0
- package/src/prompts/builder.ts +213 -0
- package/src/prompts/default.ts +144 -0
- package/src/prompts/index.ts +16 -0
- package/src/prompts/plan.ts +64 -0
- package/src/prompts/test.ts +78 -0
- package/src/services/AnthropicChatService.ts +341 -0
- package/src/services/ChatService.ts +347 -0
- package/src/services/ClaudeCliChatService.ts +256 -0
- package/src/services/CloudSync.ts +168 -0
- package/src/services/CostLedger.ts +211 -0
- package/src/services/Heartbeat.ts +135 -0
- package/src/services/LearningCollector.ts +291 -0
- package/src/services/OllamaInstaller.ts +342 -0
- package/src/services/VersionChecker.ts +445 -0
- package/src/services/index.ts +57 -0
- package/src/services/streaming/OpenAIEventAdapter.ts +126 -0
- package/src/services/streaming/RenderingProfile.ts +90 -0
- package/src/services/streaming/StreamEventParser.ts +181 -0
- package/src/services/streaming/ThrottledRenderer.ts +139 -0
- package/src/services/streaming/TranscriptBuffer.ts +574 -0
- package/src/services/streaming/eventStatusMap.ts +52 -0
- package/src/services/streaming/index.ts +46 -0
- package/src/services/streaming/renderFormatting.ts +79 -0
- package/src/services/streaming/types.ts +234 -0
- package/src/skills/SkillLoader.ts +126 -0
- package/src/skills/SkillRegistry.ts +366 -0
- package/src/skills/index.ts +48 -0
- package/src/skills/types.ts +146 -0
- package/src/slash-commands/billing.ts +70 -0
- package/src/slash-commands/build.ts +413 -0
- package/src/slash-commands/builtinCommands.ts +2733 -0
- package/src/slash-commands/clone.ts +242 -0
- package/src/slash-commands/council.ts +125 -0
- package/src/slash-commands/custom/CustomCommandExecutor.ts +143 -0
- package/src/slash-commands/custom/CustomCommandLoader.ts +251 -0
- package/src/slash-commands/custom/CustomCommandRegistry.ts +144 -0
- package/src/slash-commands/custom/index.ts +7 -0
- package/src/slash-commands/debate.ts +254 -0
- package/src/slash-commands/gmail.ts +105 -0
- package/src/slash-commands/index.ts +388 -0
- package/src/slash-commands/mcpCommand.ts +205 -0
- package/src/slash-commands/types.ts +201 -0
- package/src/store/index.ts +76 -0
- package/src/store/selectors.ts +246 -0
- package/src/store/slices/appSlice.ts +205 -0
- package/src/store/slices/commandSlice.ts +115 -0
- package/src/store/slices/configSlice.ts +46 -0
- package/src/store/slices/focusSlice.ts +64 -0
- package/src/store/slices/index.ts +9 -0
- package/src/store/slices/sessionSlice.ts +424 -0
- package/src/store/streaming-buffer.ts +425 -0
- package/src/store/test.ts +296 -0
- package/src/store/types.ts +274 -0
- package/src/store/vanilla.ts +186 -0
- package/src/tools/builtin/bash.ts +236 -0
- package/src/tools/builtin/council.ts +105 -0
- package/src/tools/builtin/edit.ts +213 -0
- package/src/tools/builtin/glob.ts +136 -0
- package/src/tools/builtin/grep.ts +263 -0
- package/src/tools/builtin/index.ts +61 -0
- package/src/tools/builtin/memory.ts +66 -0
- package/src/tools/builtin/read.ts +168 -0
- package/src/tools/builtin/skill.ts +97 -0
- package/src/tools/builtin/snapshot.ts +40 -0
- package/src/tools/builtin/task.ts +106 -0
- package/src/tools/builtin/write.ts +134 -0
- package/src/tools/createTool.ts +221 -0
- package/src/tools/execution/ExecutionPipeline.ts +263 -0
- package/src/tools/execution/index.ts +40 -0
- package/src/tools/execution/stages/CacheStage.ts +131 -0
- package/src/tools/execution/stages/ConfirmationStage.ts +203 -0
- package/src/tools/execution/stages/DiscoveryStage.ts +46 -0
- package/src/tools/execution/stages/ExecutionStage.ts +48 -0
- package/src/tools/execution/stages/FormattingStage.ts +44 -0
- package/src/tools/execution/stages/HookStage.ts +72 -0
- package/src/tools/execution/stages/PermissionStage.ts +287 -0
- package/src/tools/execution/stages/PostHookStage.ts +71 -0
- package/src/tools/execution/stages/index.ts +12 -0
- package/src/tools/execution/test.ts +266 -0
- package/src/tools/execution/types.ts +273 -0
- package/src/tools/index.ts +81 -0
- package/src/tools/registry.ts +304 -0
- package/src/tools/schemas.ts +109 -0
- package/src/tools/test.ts +220 -0
- package/src/tools/types.ts +175 -0
- package/src/tools/validation/PermissionChecker.ts +242 -0
- package/src/tools/validation/SensitiveFileDetector.ts +210 -0
- package/src/tools/validation/index.ts +11 -0
- package/src/ui/App.tsx +166 -0
- package/src/ui/components/AegisInterface.tsx +484 -0
- package/src/ui/components/common/ChatSearch.tsx +150 -0
- package/src/ui/components/common/ErrorBoundary.tsx +82 -0
- package/src/ui/components/common/ExitMessage.tsx +120 -0
- package/src/ui/components/common/LoadingIndicator.tsx +49 -0
- package/src/ui/components/common/index.ts +6 -0
- package/src/ui/components/dialog/ConfirmationPrompt.tsx +208 -0
- package/src/ui/components/dialog/InteractiveSelector.tsx +149 -0
- package/src/ui/components/dialog/SetupWizard.tsx +297 -0
- package/src/ui/components/dialog/UpdatePrompt.tsx +155 -0
- package/src/ui/components/dialog/index.ts +8 -0
- package/src/ui/components/index.ts +28 -0
- package/src/ui/components/input/CommandSuggestions.tsx +139 -0
- package/src/ui/components/input/CustomTextInput.tsx +220 -0
- package/src/ui/components/input/InputArea.tsx +361 -0
- package/src/ui/components/input/PromptSuggestions.tsx +66 -0
- package/src/ui/components/input/index.ts +6 -0
- package/src/ui/components/layout/ChatStatusBar.tsx +90 -0
- package/src/ui/components/layout/ContextBar.tsx +79 -0
- package/src/ui/components/layout/MessageArea.tsx +96 -0
- package/src/ui/components/layout/MessageList.tsx +647 -0
- package/src/ui/components/layout/MessageSeparator.tsx +26 -0
- package/src/ui/components/layout/WelcomeMessage.tsx +93 -0
- package/src/ui/components/layout/index.ts +7 -0
- package/src/ui/components/markdown/CodeHighlighter.tsx +292 -0
- package/src/ui/components/markdown/MessageRenderer.tsx +1211 -0
- package/src/ui/components/markdown/index.ts +8 -0
- package/src/ui/components/markdown/parser.ts +336 -0
- package/src/ui/components/markdown/types.ts +66 -0
- package/src/ui/focus/FocusManager.ts +137 -0
- package/src/ui/focus/index.ts +13 -0
- package/src/ui/focus/types.ts +54 -0
- package/src/ui/focus/useFocus.ts +75 -0
- package/src/ui/hooks/index.ts +11 -0
- package/src/ui/hooks/useAgent.ts +284 -0
- package/src/ui/hooks/useCommandHistory.ts +87 -0
- package/src/ui/hooks/useCommandProcessor.ts +443 -0
- package/src/ui/hooks/useConfirmation.ts +99 -0
- package/src/ui/hooks/useCtrlCHandler.ts +100 -0
- package/src/ui/hooks/useInputBuffer.ts +122 -0
- package/src/ui/hooks/useTerminalSize.ts +68 -0
- package/src/ui/hooks/useTerminalWidth.ts +5 -0
- package/src/ui/hooks/useWindowedList.ts +118 -0
- package/src/ui/render-debugger.ts +621 -0
- package/src/ui/test.ts +189 -0
- package/src/ui/themes/ThemeManager.ts +332 -0
- package/src/ui/themes/aegisTheme.ts +87 -0
- package/src/ui/themes/darkTheme.ts +87 -0
- package/src/ui/themes/defaultTheme.ts +85 -0
- package/src/ui/themes/index.ts +10 -0
- package/src/ui/themes/lightTheme.ts +89 -0
- package/src/ui/themes/popularThemes.ts +187 -0
- package/src/ui/themes/types.ts +130 -0
- package/src/utils/clipboard.ts +48 -0
- package/src/utils/debug.ts +43 -0
- package/src/utils/environment.ts +68 -0
- package/src/utils/index.ts +10 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
export const ToolSchemas = {
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
filePath: (options?: { description?: string }) =>
|
|
17
|
+
z.string()
|
|
18
|
+
.min(1, '文件路径不能为空')
|
|
19
|
+
.describe(options?.description || '文件路径'),
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
absolutePath: (options?: { description?: string }) =>
|
|
25
|
+
z.string()
|
|
26
|
+
.min(1, '路径不能为空')
|
|
27
|
+
.refine(
|
|
28
|
+
(path) => path.startsWith('/') || path.startsWith('~'),
|
|
29
|
+
'必须是绝对路径(以 / 或 ~ 开头)'
|
|
30
|
+
)
|
|
31
|
+
.describe(options?.description || '绝对路径'),
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
lineNumber: (options?: { description?: string }) =>
|
|
37
|
+
z.number()
|
|
38
|
+
.int('必须是整数')
|
|
39
|
+
.min(0, '行号不能为负')
|
|
40
|
+
.describe(options?.description || '行号(从 0 开始)'),
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
lineLimit: (options?: { description?: string; max?: number }) =>
|
|
46
|
+
z.number()
|
|
47
|
+
.int('必须是整数')
|
|
48
|
+
.min(1, '至少读取 1 行')
|
|
49
|
+
.max(options?.max || 10000, `最多读取 ${options?.max || 10000} 行`)
|
|
50
|
+
.describe(options?.description || '读取行数'),
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
encoding: () =>
|
|
56
|
+
z.enum(['utf8', 'utf-8', 'ascii', 'base64', 'binary', 'hex'])
|
|
57
|
+
.default('utf8')
|
|
58
|
+
.describe('文件编码格式'),
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Glob 模式
|
|
62
|
+
*/
|
|
63
|
+
globPattern: (options?: { description?: string }) =>
|
|
64
|
+
z.string()
|
|
65
|
+
.min(1, '模式不能为空')
|
|
66
|
+
.describe(options?.description || 'Glob 匹配模式'),
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
*/
|
|
71
|
+
regexPattern: (options?: { description?: string }) =>
|
|
72
|
+
z.string()
|
|
73
|
+
.min(1, '模式不能为空')
|
|
74
|
+
.describe(options?.description || '正则表达式模式'),
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
*/
|
|
79
|
+
command: (options?: { description?: string }) =>
|
|
80
|
+
z.string()
|
|
81
|
+
.min(1, '命令不能为空')
|
|
82
|
+
.describe(options?.description || 'Shell 命令'),
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
*
|
|
86
|
+
*/
|
|
87
|
+
timeout: (options?: { max?: number; default?: number }) =>
|
|
88
|
+
z.number()
|
|
89
|
+
.int()
|
|
90
|
+
.min(0)
|
|
91
|
+
.max(options?.max || 600000)
|
|
92
|
+
.default(options?.default || 30000)
|
|
93
|
+
.describe('超时时间(毫秒)'),
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
98
|
+
booleanWithDefault: (defaultValue: boolean, description?: string) =>
|
|
99
|
+
z.boolean()
|
|
100
|
+
.default(defaultValue)
|
|
101
|
+
.describe(description || '布尔选项'),
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
*
|
|
106
|
+
*/
|
|
107
|
+
export function optional<T extends z.ZodType>(schema: T): z.ZodOptional<T> {
|
|
108
|
+
return schema.optional();
|
|
109
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ToolRegistry, getBuiltinTools, ToolKind, createTool } from './index.js';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import fs from 'fs/promises';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
|
|
13
|
+
async function testToolSystem() {
|
|
14
|
+
console.log('=== 工具系统测试 ===\n');
|
|
15
|
+
|
|
16
|
+
// 1. 创建注册表并注册内置工
|
|
17
|
+
console.log('1. 创建工具注册表并注册内置工具');
|
|
18
|
+
const registry = new ToolRegistry();
|
|
19
|
+
const builtinTools = getBuiltinTools();
|
|
20
|
+
registry.registerAll(builtinTools);
|
|
21
|
+
console.log(` 已注册 ${registry.size} 个工具: ${registry.getNames().join(', ')}`);
|
|
22
|
+
console.log(` - 内置工具: ${registry.builtinSize}`);
|
|
23
|
+
console.log(` - MCP 工具: ${registry.mcpSize}\n`);
|
|
24
|
+
|
|
25
|
+
// 2. 测试工具获
|
|
26
|
+
console.log('2. 测试工具获取');
|
|
27
|
+
const readTool = registry.get('Read');
|
|
28
|
+
console.log(` Read 工具: ${readTool ? '✅ 存在' : '❌ 不存在'}`);
|
|
29
|
+
console.log(` - 类型: ${readTool?.kind}`);
|
|
30
|
+
console.log(` - 只读: ${readTool?.isReadOnly}`);
|
|
31
|
+
console.log(` - 并发安全: ${readTool?.isConcurrencySafe}`);
|
|
32
|
+
console.log(` - 分类: ${readTool?.category}`);
|
|
33
|
+
console.log(` - 标签: ${readTool?.tags.join(', ')}\n`);
|
|
34
|
+
|
|
35
|
+
// 3. 测试只
|
|
36
|
+
console.log('3. 测试只读/写入工具过滤');
|
|
37
|
+
const readOnlyTools = registry.getReadOnlyTools();
|
|
38
|
+
const writeTools = registry.getWriteTools();
|
|
39
|
+
console.log(` 只读工具: ${readOnlyTools.map(t => t.name).join(', ')}`);
|
|
40
|
+
console.log(` 写入工具: ${writeTools.map(t => t.name).join(', ')}\n`);
|
|
41
|
+
|
|
42
|
+
// 4. 测试函数声明生
|
|
43
|
+
console.log('4. 测试函数声明生成');
|
|
44
|
+
const declarations = registry.getFunctionDeclarations();
|
|
45
|
+
for (const decl of declarations) {
|
|
46
|
+
console.log(` ${decl.name}:`);
|
|
47
|
+
console.log(` 描述: ${decl.description.slice(0, 60)}...`);
|
|
48
|
+
console.log(` 参数: ${Object.keys(decl.parameters.properties || {}).join(', ')}`);
|
|
49
|
+
}
|
|
50
|
+
console.log();
|
|
51
|
+
|
|
52
|
+
// 5. 测试 Plan 模式函数声
|
|
53
|
+
console.log('5. 测试 Plan 模式函数声明');
|
|
54
|
+
const planDeclarations = registry.getFunctionDeclarationsByMode('plan');
|
|
55
|
+
console.log(` Plan 模式工具数: ${planDeclarations.length}`);
|
|
56
|
+
console.log(` Plan 模式工具: ${planDeclarations.map(d => d.name).join(', ')}\n`);
|
|
57
|
+
|
|
58
|
+
// 6. 测试 Read 工具执
|
|
59
|
+
console.log('6. 测试 Read 工具执行');
|
|
60
|
+
if (readTool) {
|
|
61
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
62
|
+
const result = await readTool.execute({ file_path: packageJsonPath });
|
|
63
|
+
console.log(` 结果: ${result.success ? '✅ 成功' : '❌ 失败'}`);
|
|
64
|
+
console.log(` 显示内容: ${result.displayContent}`);
|
|
65
|
+
console.log(` LLM 内容长度: ${result.llmContent.length} 字符\n`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 7. 测试 Edit 工
|
|
69
|
+
console.log('7. 测试 Edit 工具');
|
|
70
|
+
const editTool = registry.get('Edit');
|
|
71
|
+
if (editTool) {
|
|
72
|
+
// 创建临时文
|
|
73
|
+
const tmpDir = os.tmpdir();
|
|
74
|
+
const testFile = path.join(tmpDir, `aegis-test-${Date.now()}.txt`);
|
|
75
|
+
await fs.writeFile(testFile, 'Hello World\nFoo Bar\n', 'utf8');
|
|
76
|
+
|
|
77
|
+
// 测试编
|
|
78
|
+
const result = await editTool.execute({
|
|
79
|
+
file_path: testFile,
|
|
80
|
+
old_string: 'World',
|
|
81
|
+
new_string: 'AEGIS',
|
|
82
|
+
});
|
|
83
|
+
console.log(` 结果: ${result.success ? '✅ 成功' : '❌ 失败'}`);
|
|
84
|
+
console.log(` 显示内容: ${result.displayContent}`);
|
|
85
|
+
|
|
86
|
+
// 验证内
|
|
87
|
+
const content = await fs.readFile(testFile, 'utf8');
|
|
88
|
+
console.log(` 验证: ${content.includes('AEGIS') ? '✅ 替换正确' : '❌ 替换失败'}`);
|
|
89
|
+
|
|
90
|
+
// 测试多重匹
|
|
91
|
+
await fs.writeFile(testFile, 'AAA BBB AAA', 'utf8');
|
|
92
|
+
const multiResult = await editTool.execute({
|
|
93
|
+
file_path: testFile,
|
|
94
|
+
old_string: 'AAA',
|
|
95
|
+
new_string: 'CCC',
|
|
96
|
+
});
|
|
97
|
+
console.log(` 多重匹配: ${multiResult.success ? '❌ 应该失败' : '✅ 正确拒绝'}`);
|
|
98
|
+
|
|
99
|
+
// 清
|
|
100
|
+
await fs.unlink(testFile);
|
|
101
|
+
console.log();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 8. 测试 Write 工
|
|
105
|
+
console.log('8. 测试 Write 工具');
|
|
106
|
+
const writeTool = registry.get('Write');
|
|
107
|
+
if (writeTool) {
|
|
108
|
+
const tmpDir = os.tmpdir();
|
|
109
|
+
const testFile = path.join(tmpDir, `aegis-write-${Date.now()}.txt`);
|
|
110
|
+
|
|
111
|
+
const result = await writeTool.execute({
|
|
112
|
+
file_path: testFile,
|
|
113
|
+
contents: 'Test content\nLine 2\n',
|
|
114
|
+
});
|
|
115
|
+
console.log(` 结果: ${result.success ? '✅ 成功' : '❌ 失败'}`);
|
|
116
|
+
console.log(` 显示内容: ${result.displayContent}`);
|
|
117
|
+
|
|
118
|
+
// 验
|
|
119
|
+
const exists = await fs.access(testFile).then(() => true).catch(() => false);
|
|
120
|
+
console.log(` 文件存在: ${exists ? '✅ 是' : '❌ 否'}`);
|
|
121
|
+
|
|
122
|
+
// 清
|
|
123
|
+
if (exists) await fs.unlink(testFile);
|
|
124
|
+
console.log();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 9. 测试 Bash 工
|
|
128
|
+
console.log('9. 测试 Bash 工具');
|
|
129
|
+
const bashTool = registry.get('Bash');
|
|
130
|
+
if (bashTool) {
|
|
131
|
+
const result = await bashTool.execute({
|
|
132
|
+
command: 'echo "Hello from Bash"',
|
|
133
|
+
description: '测试 echo 命令',
|
|
134
|
+
});
|
|
135
|
+
console.log(` 结果: ${result.success ? '✅ 成功' : '❌ 失败'}`);
|
|
136
|
+
console.log(` 显示内容: ${result.displayContent}`);
|
|
137
|
+
console.log(` 输出: ${result.llmContent.trim()}`);
|
|
138
|
+
|
|
139
|
+
// 测试失败命
|
|
140
|
+
const failResult = await bashTool.execute({
|
|
141
|
+
command: 'exit 1',
|
|
142
|
+
});
|
|
143
|
+
console.log(` 失败命令: ${failResult.success ? '❌ 应该失败' : '✅ 正确失败'}\n`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 10. 测试 Glob 工具执
|
|
147
|
+
console.log('10. 测试 Glob 工具执行');
|
|
148
|
+
const globTool = registry.get('Glob');
|
|
149
|
+
if (globTool) {
|
|
150
|
+
const result = await globTool.execute({ pattern: '*.ts', path: path.join(process.cwd(), 'src') });
|
|
151
|
+
console.log(` 结果: ${result.success ? '✅ 成功' : '❌ 失败'}`);
|
|
152
|
+
console.log(` 显示内容: ${result.displayContent}`);
|
|
153
|
+
if (result.metadata?.count) {
|
|
154
|
+
console.log(` 找到文件数: ${result.metadata.count}\n`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 11. 测试 Grep 工具执
|
|
159
|
+
console.log('11. 测试 Grep 工具执行');
|
|
160
|
+
const grepTool = registry.get('Grep');
|
|
161
|
+
if (grepTool) {
|
|
162
|
+
const result = await grepTool.execute({
|
|
163
|
+
pattern: 'export',
|
|
164
|
+
include: '*.ts',
|
|
165
|
+
path: path.join(process.cwd(), 'src/tools'),
|
|
166
|
+
});
|
|
167
|
+
console.log(` 结果: ${result.success ? '✅ 成功' : '❌ 失败'}`);
|
|
168
|
+
console.log(` 显示内容: ${result.displayContent}`);
|
|
169
|
+
if (result.metadata?.matches) {
|
|
170
|
+
console.log(` 匹配数: ${result.metadata.matches}\n`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 12. 测试 MCP 工具注
|
|
175
|
+
console.log('12. 测试 MCP 工具注册');
|
|
176
|
+
const mockMcpTool = createTool({
|
|
177
|
+
name: 'MockMcpTool',
|
|
178
|
+
displayName: 'Mock MCP Tool',
|
|
179
|
+
kind: ToolKind.ReadOnly,
|
|
180
|
+
schema: z.object({ input: z.string() }),
|
|
181
|
+
description: { short: 'A mock MCP tool for testing' },
|
|
182
|
+
async execute(params) {
|
|
183
|
+
return {
|
|
184
|
+
success: true,
|
|
185
|
+
llmContent: `Mock result for: ${params.input}`,
|
|
186
|
+
displayContent: '✅ Mock MCP 工具执行成功',
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
registry.registerMcpTool(mockMcpTool);
|
|
192
|
+
console.log(` MCP 工具注册: ✅`);
|
|
193
|
+
console.log(` 总工具数: ${registry.size}`);
|
|
194
|
+
console.log(` MCP 工具数: ${registry.mcpSize}`);
|
|
195
|
+
console.log(` 获取 MCP 工具: ${registry.get('MockMcpTool') ? '✅ 存在' : '❌ 不存在'}`);
|
|
196
|
+
|
|
197
|
+
// 测试注
|
|
198
|
+
registry.unregisterMcpTool('MockMcpTool');
|
|
199
|
+
console.log(` 注销后: ${registry.get('MockMcpTool') ? '❌ 仍存在' : '✅ 已移除'}\n`);
|
|
200
|
+
|
|
201
|
+
// 13. 测试 build 方
|
|
202
|
+
console.log('13. 测试 build 方法');
|
|
203
|
+
if (readTool) {
|
|
204
|
+
const invocation = readTool.build({ file_path: '/test/path.ts' });
|
|
205
|
+
console.log(` 工具名: ${invocation.toolName}`);
|
|
206
|
+
console.log(` 参数: ${JSON.stringify(invocation.params)}\n`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// 14. 测试参数验
|
|
210
|
+
console.log('14. 测试参数验证');
|
|
211
|
+
if (readTool) {
|
|
212
|
+
const invalidResult = await readTool.execute({ file_path: '' });
|
|
213
|
+
console.log(` 空路径测试: ${invalidResult.success ? '❌ 应该失败' : '✅ 正确失败'}`);
|
|
214
|
+
console.log(` 错误信息: ${invalidResult.displayContent}\n`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log('=== 测试完成 ===');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
testToolSystem().catch(console.error);
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ========== 工具类型枚
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
export enum ToolKind {
|
|
12
|
+
/** 只读操作,无副作用 */
|
|
13
|
+
ReadOnly = 'readonly',
|
|
14
|
+
/** 文件写入操作 */
|
|
15
|
+
Write = 'write',
|
|
16
|
+
/** 命令执行,可能有副作用 */
|
|
17
|
+
Execute = 'execute',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ========== 工具描
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
export interface ToolExample {
|
|
26
|
+
description: string;
|
|
27
|
+
params: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
export interface ToolDescription {
|
|
34
|
+
/** 简短描述(一行) */
|
|
35
|
+
short: string;
|
|
36
|
+
/** 详细说明 */
|
|
37
|
+
long?: string;
|
|
38
|
+
/** 使用注意事项 */
|
|
39
|
+
usageNotes?: string[];
|
|
40
|
+
/** 使用示例 */
|
|
41
|
+
examples?: ToolExample[];
|
|
42
|
+
/** 重要提示 */
|
|
43
|
+
important?: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ========== 工具错
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
export enum ToolErrorType {
|
|
52
|
+
/** 参数验证错误 */
|
|
53
|
+
VALIDATION_ERROR = 'validation_error',
|
|
54
|
+
/** 执行错误 */
|
|
55
|
+
EXECUTION_ERROR = 'execution_error',
|
|
56
|
+
/** 权限错误 */
|
|
57
|
+
PERMISSION_ERROR = 'permission_error',
|
|
58
|
+
/** 超时错误 */
|
|
59
|
+
TIMEOUT_ERROR = 'timeout_error',
|
|
60
|
+
/** 未知错误 */
|
|
61
|
+
UNKNOWN_ERROR = 'unknown_error',
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
export interface ToolError {
|
|
68
|
+
type: ToolErrorType;
|
|
69
|
+
message: string;
|
|
70
|
+
details?: unknown;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ========== 工具结
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
export interface ToolResult {
|
|
79
|
+
/** 执行是否成功 */
|
|
80
|
+
success: boolean;
|
|
81
|
+
/** 传递给 LLM 的内容(可能很长) */
|
|
82
|
+
llmContent: string;
|
|
83
|
+
/** 显示给用户的内容(简洁摘要) */
|
|
84
|
+
displayContent: string;
|
|
85
|
+
/** 错误信息 */
|
|
86
|
+
error?: ToolError;
|
|
87
|
+
/** 额外元数据 */
|
|
88
|
+
metadata?: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ========== 执行上下
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
*/
|
|
96
|
+
export interface ExecutionContext {
|
|
97
|
+
/** 会话 ID */
|
|
98
|
+
sessionId?: string;
|
|
99
|
+
/** 中断信号 */
|
|
100
|
+
signal?: AbortSignal;
|
|
101
|
+
/** 工作目录 */
|
|
102
|
+
cwd?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ========== 函数声
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* LLM 函数声明(OpenAI 格式)
|
|
109
|
+
*/
|
|
110
|
+
export interface FunctionDeclaration {
|
|
111
|
+
name: string;
|
|
112
|
+
description: string;
|
|
113
|
+
parameters: {
|
|
114
|
+
type: 'object';
|
|
115
|
+
properties: Record<string, unknown>;
|
|
116
|
+
required?: string[];
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ========== 工具调
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
*
|
|
124
|
+
*/
|
|
125
|
+
export interface ToolInvocation<TParams = unknown> {
|
|
126
|
+
/** 工具名称 */
|
|
127
|
+
toolName: string;
|
|
128
|
+
/** 参数 */
|
|
129
|
+
params: TParams;
|
|
130
|
+
/** 调用 ID */
|
|
131
|
+
callId?: string;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ========== 工具接
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
*/
|
|
139
|
+
export interface Tool<TParams = unknown> {
|
|
140
|
+
/** 工具唯一名称 */
|
|
141
|
+
readonly name: string;
|
|
142
|
+
/** 显示名称 */
|
|
143
|
+
readonly displayName: string;
|
|
144
|
+
/** 工具类型 */
|
|
145
|
+
readonly kind: ToolKind;
|
|
146
|
+
/** 是否只读 */
|
|
147
|
+
readonly isReadOnly: boolean;
|
|
148
|
+
/** 是否并发安全 */
|
|
149
|
+
readonly isConcurrencySafe: boolean;
|
|
150
|
+
/** 是否启用结构化输出 */
|
|
151
|
+
readonly strict: boolean;
|
|
152
|
+
/** 工具描述 */
|
|
153
|
+
readonly description: ToolDescription;
|
|
154
|
+
/** 版本 */
|
|
155
|
+
readonly version: string;
|
|
156
|
+
/** 分类 */
|
|
157
|
+
readonly category?: string;
|
|
158
|
+
/** 标签 */
|
|
159
|
+
readonly tags: string[];
|
|
160
|
+
|
|
161
|
+
/** 生成 LLM 函数声明 */
|
|
162
|
+
getFunctionDeclaration(): FunctionDeclaration;
|
|
163
|
+
|
|
164
|
+
/** 构建执行实例 */
|
|
165
|
+
build(params: TParams): ToolInvocation<TParams>;
|
|
166
|
+
|
|
167
|
+
/** 执行工具 */
|
|
168
|
+
execute(params: TParams, context?: ExecutionContext): Promise<ToolResult>;
|
|
169
|
+
|
|
170
|
+
/** 提取签名内容(用于权限规则) */
|
|
171
|
+
extractSignatureContent?: (params: unknown) => string;
|
|
172
|
+
|
|
173
|
+
/** 抽象权限规则(用于权限匹配) */
|
|
174
|
+
abstractPermissionRule?: (params: unknown) => string;
|
|
175
|
+
}
|