aegiscode 3.1.10 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aegis-cli-linux-x64 +0 -0
- package/bin/cli.js +68 -0
- package/package.json +11 -48
- package/scripts/download-binary.mjs +155 -0
- package/dist/main.js +0 -2171
- package/gui/run-gui.cjs +0 -13
- package/src/agent/Agent.ts +0 -903
- package/src/agent/SimpleAgent.ts +0 -48
- package/src/agent/index.ts +0 -54
- package/src/agent/orchestrator/AppBuilder.ts +0 -443
- package/src/agent/orchestrator/CouncilAgent.ts +0 -310
- package/src/agent/orchestrator/DiscussionRoom.ts +0 -462
- package/src/agent/orchestrator/OrchestratorAgent.ts +0 -637
- package/src/agent/orchestrator/index.ts +0 -38
- package/src/agent/orchestrator/utils.ts +0 -397
- package/src/agent/pricing.ts +0 -115
- package/src/agent/router.ts +0 -74
- package/src/agent/routerStats.ts +0 -121
- package/src/agent/types.ts +0 -318
- package/src/auth/login.ts +0 -383
- package/src/cli/config.ts +0 -189
- package/src/cli/index.ts +0 -17
- package/src/cli/middleware.ts +0 -119
- package/src/cli/types.ts +0 -75
- package/src/config/ConfigManager.ts +0 -587
- package/src/config/index.ts +0 -7
- package/src/config/types.ts +0 -584
- package/src/context/CompactionService.ts +0 -300
- package/src/context/ContextManager.ts +0 -450
- package/src/context/FileAnalyzer.ts +0 -267
- package/src/context/TokenCounter.ts +0 -265
- package/src/context/index.ts +0 -27
- package/src/context/storage/CacheStore.ts +0 -176
- package/src/context/storage/JSONLStore.ts +0 -201
- package/src/context/storage/MemoryStore.ts +0 -205
- package/src/context/storage/PersistentStore.ts +0 -327
- package/src/context/storage/index.ts +0 -9
- package/src/context/storage/pathUtils.ts +0 -114
- package/src/context/test.ts +0 -309
- package/src/context/types.ts +0 -268
- package/src/hooks/HookExecutor.ts +0 -434
- package/src/hooks/HookManager.ts +0 -596
- package/src/hooks/HookService.ts +0 -269
- package/src/hooks/Matcher.ts +0 -157
- package/src/hooks/index.ts +0 -63
- package/src/hooks/types.ts +0 -424
- package/src/main.tsx +0 -596
- package/src/mcp/HealthMonitor.ts +0 -150
- package/src/mcp/McpClient.ts +0 -491
- package/src/mcp/McpRegistry.ts +0 -321
- package/src/mcp/createMcpTool.ts +0 -251
- package/src/mcp/index.ts +0 -15
- package/src/mcp/server.ts +0 -334
- package/src/mcp/test-server.ts +0 -88
- package/src/mcp/test.ts +0 -372
- package/src/mcp/types.ts +0 -247
- package/src/memory/AgentMemoryBus.ts +0 -432
- package/src/memory/CloudSync.ts +0 -99
- package/src/memory/DriveSync.ts +0 -106
- package/src/memory/SharedMemory.ts +0 -951
- package/src/memory/index.ts +0 -14
- package/src/memory/machineFingerprint.ts +0 -40
- package/src/orchestrator/SubAgentMetadata.ts +0 -136
- package/src/prompts/builder.ts +0 -213
- package/src/prompts/default.ts +0 -144
- package/src/prompts/index.ts +0 -16
- package/src/prompts/plan.ts +0 -64
- package/src/prompts/test.ts +0 -78
- package/src/services/AnthropicChatService.ts +0 -341
- package/src/services/ChatService.ts +0 -347
- package/src/services/ClaudeCliChatService.ts +0 -256
- package/src/services/CloudSync.ts +0 -168
- package/src/services/CostLedger.ts +0 -211
- package/src/services/Heartbeat.ts +0 -135
- package/src/services/LearningCollector.ts +0 -291
- package/src/services/OllamaInstaller.ts +0 -342
- package/src/services/VersionChecker.ts +0 -445
- package/src/services/index.ts +0 -57
- package/src/services/streaming/OpenAIEventAdapter.ts +0 -126
- package/src/services/streaming/RenderingProfile.ts +0 -90
- package/src/services/streaming/StreamEventParser.ts +0 -181
- package/src/services/streaming/ThrottledRenderer.ts +0 -139
- package/src/services/streaming/TranscriptBuffer.ts +0 -574
- package/src/services/streaming/eventStatusMap.ts +0 -52
- package/src/services/streaming/index.ts +0 -46
- package/src/services/streaming/renderFormatting.ts +0 -79
- package/src/services/streaming/types.ts +0 -234
- package/src/skills/SkillLoader.ts +0 -126
- package/src/skills/SkillRegistry.ts +0 -366
- package/src/skills/index.ts +0 -48
- package/src/skills/types.ts +0 -146
- package/src/slash-commands/billing.ts +0 -70
- package/src/slash-commands/build.ts +0 -413
- package/src/slash-commands/builtinCommands.ts +0 -2733
- package/src/slash-commands/clone.ts +0 -242
- package/src/slash-commands/council.ts +0 -125
- package/src/slash-commands/custom/CustomCommandExecutor.ts +0 -143
- package/src/slash-commands/custom/CustomCommandLoader.ts +0 -251
- package/src/slash-commands/custom/CustomCommandRegistry.ts +0 -144
- package/src/slash-commands/custom/index.ts +0 -7
- package/src/slash-commands/debate.ts +0 -254
- package/src/slash-commands/gmail.ts +0 -105
- package/src/slash-commands/index.ts +0 -388
- package/src/slash-commands/mcpCommand.ts +0 -205
- package/src/slash-commands/types.ts +0 -201
- package/src/store/index.ts +0 -76
- package/src/store/selectors.ts +0 -246
- package/src/store/slices/appSlice.ts +0 -205
- package/src/store/slices/commandSlice.ts +0 -115
- package/src/store/slices/configSlice.ts +0 -46
- package/src/store/slices/focusSlice.ts +0 -64
- package/src/store/slices/index.ts +0 -9
- package/src/store/slices/sessionSlice.ts +0 -424
- package/src/store/streaming-buffer.ts +0 -425
- package/src/store/test.ts +0 -296
- package/src/store/types.ts +0 -274
- package/src/store/vanilla.ts +0 -186
- package/src/tools/builtin/bash.ts +0 -236
- package/src/tools/builtin/council.ts +0 -105
- package/src/tools/builtin/edit.ts +0 -213
- package/src/tools/builtin/glob.ts +0 -136
- package/src/tools/builtin/grep.ts +0 -263
- package/src/tools/builtin/index.ts +0 -61
- package/src/tools/builtin/memory.ts +0 -66
- package/src/tools/builtin/read.ts +0 -168
- package/src/tools/builtin/skill.ts +0 -97
- package/src/tools/builtin/snapshot.ts +0 -40
- package/src/tools/builtin/task.ts +0 -106
- package/src/tools/builtin/write.ts +0 -134
- package/src/tools/createTool.ts +0 -221
- package/src/tools/execution/ExecutionPipeline.ts +0 -263
- package/src/tools/execution/index.ts +0 -40
- package/src/tools/execution/stages/CacheStage.ts +0 -131
- package/src/tools/execution/stages/ConfirmationStage.ts +0 -203
- package/src/tools/execution/stages/DiscoveryStage.ts +0 -46
- package/src/tools/execution/stages/ExecutionStage.ts +0 -48
- package/src/tools/execution/stages/FormattingStage.ts +0 -44
- package/src/tools/execution/stages/HookStage.ts +0 -72
- package/src/tools/execution/stages/PermissionStage.ts +0 -287
- package/src/tools/execution/stages/PostHookStage.ts +0 -71
- package/src/tools/execution/stages/index.ts +0 -12
- package/src/tools/execution/test.ts +0 -266
- package/src/tools/execution/types.ts +0 -273
- package/src/tools/index.ts +0 -81
- package/src/tools/registry.ts +0 -304
- package/src/tools/schemas.ts +0 -109
- package/src/tools/test.ts +0 -220
- package/src/tools/types.ts +0 -175
- package/src/tools/validation/PermissionChecker.ts +0 -242
- package/src/tools/validation/SensitiveFileDetector.ts +0 -210
- package/src/tools/validation/index.ts +0 -11
- package/src/ui/App.tsx +0 -166
- package/src/ui/components/AegisInterface.tsx +0 -484
- package/src/ui/components/common/ChatSearch.tsx +0 -150
- package/src/ui/components/common/ErrorBoundary.tsx +0 -82
- package/src/ui/components/common/ExitMessage.tsx +0 -120
- package/src/ui/components/common/LoadingIndicator.tsx +0 -49
- package/src/ui/components/common/index.ts +0 -6
- package/src/ui/components/dialog/ConfirmationPrompt.tsx +0 -208
- package/src/ui/components/dialog/InteractiveSelector.tsx +0 -149
- package/src/ui/components/dialog/SetupWizard.tsx +0 -297
- package/src/ui/components/dialog/UpdatePrompt.tsx +0 -155
- package/src/ui/components/dialog/index.ts +0 -8
- package/src/ui/components/index.ts +0 -28
- package/src/ui/components/input/CommandSuggestions.tsx +0 -139
- package/src/ui/components/input/CustomTextInput.tsx +0 -220
- package/src/ui/components/input/InputArea.tsx +0 -361
- package/src/ui/components/input/PromptSuggestions.tsx +0 -66
- package/src/ui/components/input/index.ts +0 -6
- package/src/ui/components/layout/ChatStatusBar.tsx +0 -90
- package/src/ui/components/layout/ContextBar.tsx +0 -79
- package/src/ui/components/layout/MessageArea.tsx +0 -96
- package/src/ui/components/layout/MessageList.tsx +0 -647
- package/src/ui/components/layout/MessageSeparator.tsx +0 -26
- package/src/ui/components/layout/WelcomeMessage.tsx +0 -93
- package/src/ui/components/layout/index.ts +0 -7
- package/src/ui/components/markdown/CodeHighlighter.tsx +0 -292
- package/src/ui/components/markdown/MessageRenderer.tsx +0 -1211
- package/src/ui/components/markdown/index.ts +0 -8
- package/src/ui/components/markdown/parser.ts +0 -336
- package/src/ui/components/markdown/types.ts +0 -66
- package/src/ui/focus/FocusManager.ts +0 -137
- package/src/ui/focus/index.ts +0 -13
- package/src/ui/focus/types.ts +0 -54
- package/src/ui/focus/useFocus.ts +0 -75
- package/src/ui/hooks/index.ts +0 -11
- package/src/ui/hooks/useAgent.ts +0 -284
- package/src/ui/hooks/useCommandHistory.ts +0 -87
- package/src/ui/hooks/useCommandProcessor.ts +0 -443
- package/src/ui/hooks/useConfirmation.ts +0 -99
- package/src/ui/hooks/useCtrlCHandler.ts +0 -100
- package/src/ui/hooks/useInputBuffer.ts +0 -122
- package/src/ui/hooks/useTerminalSize.ts +0 -68
- package/src/ui/hooks/useTerminalWidth.ts +0 -5
- package/src/ui/hooks/useWindowedList.ts +0 -118
- package/src/ui/render-debugger.ts +0 -621
- package/src/ui/test.ts +0 -189
- package/src/ui/themes/ThemeManager.ts +0 -332
- package/src/ui/themes/aegisTheme.ts +0 -87
- package/src/ui/themes/darkTheme.ts +0 -87
- package/src/ui/themes/defaultTheme.ts +0 -85
- package/src/ui/themes/index.ts +0 -10
- package/src/ui/themes/lightTheme.ts +0 -89
- package/src/ui/themes/popularThemes.ts +0 -187
- package/src/ui/themes/types.ts +0 -130
- package/src/utils/clipboard.ts +0 -48
- package/src/utils/debug.ts +0 -43
- package/src/utils/environment.ts +0 -68
- package/src/utils/index.ts +0 -10
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memory 工具 - 按需检索共享记
|
|
3
|
-
*
|
|
4
|
-
* Shared memory is intentionally NOT injected into every turn's system
|
|
5
|
-
* prompt by default — auto-injecting semantically-similar past memories
|
|
6
|
-
* caused models to recall and repeat their own past mistakes (e.g. a stuck
|
|
7
|
-
* session's hallucinated text got stored, then recalled as "context" in
|
|
8
|
-
* later sessions, reinforcing itself). Memory is opt-in: the model calls
|
|
9
|
-
* this tool only when it decides recalling past conversations would help.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { z } from 'zod';
|
|
13
|
-
import { createTool } from '../createTool.js';
|
|
14
|
-
import { ToolKind } from '../types.js';
|
|
15
|
-
import { sharedMemory } from '../../memory/SharedMemory.js';
|
|
16
|
-
|
|
17
|
-
const MemorySchema = z.object({
|
|
18
|
-
query: z.string()
|
|
19
|
-
.min(1, 'query 不能为空')
|
|
20
|
-
.describe('What to recall — a topic, decision, or past conversation to search for'),
|
|
21
|
-
maxEntries: z.number().int().min(1).max(10).optional()
|
|
22
|
-
.describe('Maximum number of memory entries to return (default 4)'),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export const memoryTool = createTool({
|
|
26
|
-
name: 'Memory',
|
|
27
|
-
displayName: 'Recall Memory',
|
|
28
|
-
kind: ToolKind.ReadOnly,
|
|
29
|
-
schema: MemorySchema,
|
|
30
|
-
|
|
31
|
-
description: {
|
|
32
|
-
short: 'Recall relevant context from past conversations and sessions',
|
|
33
|
-
long: `Searches shared long-term memory for past conversations, decisions, and summaries
|
|
34
|
-
relevant to a query. This is opt-in — call it only when recalling prior context would
|
|
35
|
-
genuinely help (e.g. "what did we decide about X last time", "have we hit this error before").`,
|
|
36
|
-
usageNotes: [
|
|
37
|
-
'Do NOT call this by default at the start of every task — only when past context is actually useful',
|
|
38
|
-
'Treat results as recollections that may be incomplete, outdated, or about a different situation — verify against the current codebase/state before relying on them',
|
|
39
|
-
'Never treat a past assistant message recalled here as proof that something is currently blocked, broken, or unavailable — confirm directly instead',
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
category: '记忆',
|
|
44
|
-
tags: ['memory', 'recall', 'context'],
|
|
45
|
-
|
|
46
|
-
execute: async (params, context) => {
|
|
47
|
-
const { query, maxEntries } = params;
|
|
48
|
-
const result = await sharedMemory.buildContext(query, maxEntries || 4, context?.sessionId);
|
|
49
|
-
|
|
50
|
-
if (!result) {
|
|
51
|
-
return {
|
|
52
|
-
success: true,
|
|
53
|
-
llmContent: 'No relevant memory found for this query.',
|
|
54
|
-
displayContent: 'No relevant memory found',
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
success: true,
|
|
60
|
-
llmContent: result,
|
|
61
|
-
displayContent: `Recalled memory for: ${query}`,
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
export default memoryTool;
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Read 工具 - 文件读取
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import fs from 'fs/promises';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import { z } from 'zod';
|
|
8
|
-
import { createTool } from '../createTool.js';
|
|
9
|
-
import { ToolKind, ToolErrorType } from '../types.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
*/
|
|
14
|
-
const DEFAULT_LINE_LIMIT = 2000;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Read 工具 Schema
|
|
18
|
-
*/
|
|
19
|
-
const ReadSchema = z.object({
|
|
20
|
-
file_path: z.string()
|
|
21
|
-
.min(1, '文件路径不能为空')
|
|
22
|
-
.describe('The absolute path to the file to read'),
|
|
23
|
-
|
|
24
|
-
offset: z.number()
|
|
25
|
-
.int()
|
|
26
|
-
.min(0)
|
|
27
|
-
.optional()
|
|
28
|
-
.describe('The line number to start reading from (0-based)'),
|
|
29
|
-
|
|
30
|
-
limit: z.number()
|
|
31
|
-
.int()
|
|
32
|
-
.min(1)
|
|
33
|
-
.max(10000)
|
|
34
|
-
.optional()
|
|
35
|
-
.describe('The number of lines to read'),
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Read 工具
|
|
40
|
-
*/
|
|
41
|
-
export const readTool = createTool({
|
|
42
|
-
name: 'Read',
|
|
43
|
-
displayName: 'File Read',
|
|
44
|
-
kind: ToolKind.ReadOnly,
|
|
45
|
-
schema: ReadSchema,
|
|
46
|
-
|
|
47
|
-
description: {
|
|
48
|
-
short: 'Reads a file from the local filesystem',
|
|
49
|
-
long: `Reads a file from the local filesystem. You can access any file directly by using this tool.
|
|
50
|
-
If the User provides a path to a file assume that path is valid.`,
|
|
51
|
-
usageNotes: [
|
|
52
|
-
'The file_path parameter must be an absolute path, not a relative path',
|
|
53
|
-
`By default, it reads up to ${DEFAULT_LINE_LIMIT} lines starting from the beginning`,
|
|
54
|
-
'You can optionally specify a line offset and limit for long files',
|
|
55
|
-
'Lines in the output are numbered starting at 1',
|
|
56
|
-
'You can call multiple Read tools in parallel to read multiple files at once',
|
|
57
|
-
],
|
|
58
|
-
examples: [
|
|
59
|
-
{
|
|
60
|
-
description: 'Read entire file',
|
|
61
|
-
params: { file_path: '/path/to/file.ts' },
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
description: 'Read with offset and limit',
|
|
65
|
-
params: { file_path: '/path/to/file.ts', offset: 100, limit: 50 },
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
important: [
|
|
69
|
-
'file_path must be an absolute path',
|
|
70
|
-
'Prefer reading the whole file by not providing offset/limit',
|
|
71
|
-
],
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
category: '文件操作',
|
|
75
|
-
tags: ['file', 'read', 'io'],
|
|
76
|
-
|
|
77
|
-
async execute(params, context) {
|
|
78
|
-
const { file_path, offset = 0, limit } = params;
|
|
79
|
-
const effectiveLimit = limit ?? DEFAULT_LINE_LIMIT;
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
// 检查文件是否存
|
|
83
|
-
try {
|
|
84
|
-
await fs.access(file_path);
|
|
85
|
-
} catch {
|
|
86
|
-
return {
|
|
87
|
-
success: false,
|
|
88
|
-
llmContent: `File not found: ${file_path}`,
|
|
89
|
-
displayContent: `error: file not found: ${file_path}`,
|
|
90
|
-
error: {
|
|
91
|
-
type: ToolErrorType.EXECUTION_ERROR,
|
|
92
|
-
message: 'File not found',
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// 获取文件信
|
|
98
|
-
const stat = await fs.stat(file_path);
|
|
99
|
-
|
|
100
|
-
// 检查是否为目
|
|
101
|
-
if (stat.isDirectory()) {
|
|
102
|
-
return {
|
|
103
|
-
success: false,
|
|
104
|
-
llmContent: `Path is a directory, not a file: ${file_path}`,
|
|
105
|
-
displayContent: `error: ${file_path} is a directory`,
|
|
106
|
-
error: {
|
|
107
|
-
type: ToolErrorType.VALIDATION_ERROR,
|
|
108
|
-
message: 'Path is a directory',
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// 读取文件内
|
|
114
|
-
const content = await fs.readFile(file_path, 'utf-8');
|
|
115
|
-
const lines = content.split('\n');
|
|
116
|
-
const totalLines = lines.length;
|
|
117
|
-
|
|
118
|
-
// 应用 offset
|
|
119
|
-
const selectedLines = lines.slice(offset, offset + effectiveLimit);
|
|
120
|
-
|
|
121
|
-
// 格式化输出(带行
|
|
122
|
-
const formattedContent = selectedLines
|
|
123
|
-
.map((line, i) => {
|
|
124
|
-
const lineNum = (offset + i + 1).toString().padStart(6, ' ');
|
|
125
|
-
return `${lineNum}|${line}`;
|
|
126
|
-
})
|
|
127
|
-
.join('\n');
|
|
128
|
-
|
|
129
|
-
// 计算是否有更多内
|
|
130
|
-
const hasMore = offset + effectiveLimit < totalLines;
|
|
131
|
-
const fileName = path.basename(file_path);
|
|
132
|
-
|
|
133
|
-
let summary = fileName;
|
|
134
|
-
if (offset > 0 || limit) {
|
|
135
|
-
summary += ` lines ${offset + 1}–${Math.min(offset + effectiveLimit, totalLines)} of ${totalLines}`;
|
|
136
|
-
} else {
|
|
137
|
-
summary += ` ${totalLines} lines`;
|
|
138
|
-
}
|
|
139
|
-
if (hasMore) {
|
|
140
|
-
summary += ` ···`;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
success: true,
|
|
145
|
-
llmContent: formattedContent,
|
|
146
|
-
displayContent: summary,
|
|
147
|
-
metadata: {
|
|
148
|
-
file_path,
|
|
149
|
-
total_lines: totalLines,
|
|
150
|
-
lines_read: selectedLines.length,
|
|
151
|
-
offset,
|
|
152
|
-
has_more: hasMore,
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
} catch (error) {
|
|
156
|
-
const errorMessage = error instanceof Error ? error.message : 'unknown error';
|
|
157
|
-
return {
|
|
158
|
-
success: false,
|
|
159
|
-
llmContent: `Failed to read file: ${errorMessage}`,
|
|
160
|
-
displayContent: `error: ${errorMessage}`,
|
|
161
|
-
error: {
|
|
162
|
-
type: ToolErrorType.EXECUTION_ERROR,
|
|
163
|
-
message: errorMessage,
|
|
164
|
-
},
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
});
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill 工具
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { z } from 'zod';
|
|
9
|
-
import { createTool } from '../createTool.js';
|
|
10
|
-
import { ToolKind } from '../types.js';
|
|
11
|
-
import { getSkillRegistry } from '../../skills/index.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Skill 工具参数 Schema
|
|
15
|
-
*/
|
|
16
|
-
const SkillSchema = z.object({
|
|
17
|
-
skill: z.string().describe('The name of the skill to load'),
|
|
18
|
-
args: z.string().optional().describe('Optional arguments to pass to the skill'),
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Skill 工具
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*/
|
|
27
|
-
export const skillTool = createTool({
|
|
28
|
-
name: 'Skill',
|
|
29
|
-
displayName: 'Load Skill',
|
|
30
|
-
kind: ToolKind.ReadOnly,
|
|
31
|
-
schema: SkillSchema,
|
|
32
|
-
|
|
33
|
-
description: {
|
|
34
|
-
short: 'Load a skill to get specialized instructions',
|
|
35
|
-
long: `Load a skill to get specialized instructions for a task.
|
|
36
|
-
|
|
37
|
-
Use this tool when:
|
|
38
|
-
- You need specific guidance for a task that matches an available skill
|
|
39
|
-
- The user explicitly requests to use a skill
|
|
40
|
-
- You want to follow best practices defined in a skill
|
|
41
|
-
|
|
42
|
-
The skill's instructions will be returned and you should follow them.`,
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
execute: async ({ skill, args }) => {
|
|
46
|
-
const registry = getSkillRegistry();
|
|
47
|
-
|
|
48
|
-
// 检查 Skill 是否存
|
|
49
|
-
if (!registry.hasSkill(skill)) {
|
|
50
|
-
const allSkills = registry.getAllSkills();
|
|
51
|
-
const availableNames = allSkills.map(s => s.name).join(', ');
|
|
52
|
-
const errorMsg = `Skill "${skill}" not found. Available skills: ${availableNames || 'none'}`;
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
success: false,
|
|
56
|
-
llmContent: errorMsg,
|
|
57
|
-
displayContent: errorMsg,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 加载完整内
|
|
62
|
-
const content = await registry.loadContent(skill);
|
|
63
|
-
|
|
64
|
-
if (!content) {
|
|
65
|
-
const errorMsg = `Failed to load skill "${skill}"`;
|
|
66
|
-
return {
|
|
67
|
-
success: false,
|
|
68
|
-
llmContent: errorMsg,
|
|
69
|
-
displayContent: errorMsg,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// 构建返回内
|
|
74
|
-
let result = `## Skill: ${content.metadata.name}\n\n`;
|
|
75
|
-
|
|
76
|
-
// 如果有工具限制,提
|
|
77
|
-
if (content.metadata.allowedTools && content.metadata.allowedTools.length > 0) {
|
|
78
|
-
result += `**Allowed tools for this skill:** ${content.metadata.allowedTools.join(', ')}\n\n`;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// 添加指令内
|
|
82
|
-
result += content.instructions;
|
|
83
|
-
|
|
84
|
-
// 如果有参数,添加到末
|
|
85
|
-
if (args) {
|
|
86
|
-
result += `\n\n## Arguments\n\n${args}`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
success: true,
|
|
91
|
-
llmContent: result,
|
|
92
|
-
displayContent: `✓ Loaded skill: ${content.metadata.name}`,
|
|
93
|
-
};
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
export default skillTool;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import os from 'os';
|
|
4
|
-
|
|
5
|
-
const SNAPSHOTS_DIR = path.join(os.homedir(), '.aegiscode', 'snapshots');
|
|
6
|
-
const MAX_SNAPSHOTS = 50;
|
|
7
|
-
|
|
8
|
-
export async function createSnapshot(filePath: string): Promise<string | null> {
|
|
9
|
-
try {
|
|
10
|
-
await fs.mkdir(SNAPSHOTS_DIR, { recursive: true });
|
|
11
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
12
|
-
const basename = path.basename(filePath);
|
|
13
|
-
const snapshotPath = path.join(SNAPSHOTS_DIR, `${timestamp}_${basename}.bak`);
|
|
14
|
-
await fs.copyFile(filePath, snapshotPath);
|
|
15
|
-
await pruneSnapshots();
|
|
16
|
-
return snapshotPath;
|
|
17
|
-
} catch {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function pruneSnapshots(): Promise<void> {
|
|
23
|
-
try {
|
|
24
|
-
const entries = await fs.readdir(SNAPSHOTS_DIR);
|
|
25
|
-
if (entries.length <= MAX_SNAPSHOTS) return;
|
|
26
|
-
const files = await Promise.all(
|
|
27
|
-
entries.map(async (name) => {
|
|
28
|
-
const p = path.join(SNAPSHOTS_DIR, name);
|
|
29
|
-
const stat = await fs.stat(p);
|
|
30
|
-
return { path: p, mtime: stat.mtime.getTime() };
|
|
31
|
-
})
|
|
32
|
-
);
|
|
33
|
-
files.sort((a, b) => a.mtime - b.mtime);
|
|
34
|
-
await Promise.all(
|
|
35
|
-
files.slice(0, files.length - MAX_SNAPSHOTS).map(f => fs.unlink(f.path))
|
|
36
|
-
);
|
|
37
|
-
} catch {
|
|
38
|
-
// ignore prune errors
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Task tool — lets the running agent delegate read-only investigation
|
|
3
|
-
* work to parallel sub-agents, mid-conversation, without the user typing
|
|
4
|
-
* a slash command. Same machinery as /multi, restricted to Read/Grep/Glob
|
|
5
|
-
* (see plan: no confirmationHandler reaches a tool's execute(), so only
|
|
6
|
-
* ReadOnly-kind work is safe to trigger from inside a tool call).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { z } from 'zod';
|
|
10
|
-
import { createTool } from '../createTool.js';
|
|
11
|
-
import { ToolKind } from '../types.js';
|
|
12
|
-
import { OrchestratorAgent, type SubAgentConfig } from '../../agent/orchestrator/OrchestratorAgent.js';
|
|
13
|
-
import { requireModelConfig, buildSourceContext } from '../../agent/orchestrator/utils.js';
|
|
14
|
-
|
|
15
|
-
const TaskSchema = z.object({
|
|
16
|
-
tasks: z.array(z.object({
|
|
17
|
-
description: z.string().describe('Short label for this investigation, e.g. "find auth bugs"'),
|
|
18
|
-
prompt: z.string().describe('Detailed instructions for the sub-agent'),
|
|
19
|
-
})).min(1).max(5).describe('One or more independent investigations to run in parallel'),
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
export const taskTool = createTool({
|
|
23
|
-
name: 'Task',
|
|
24
|
-
displayName: 'Delegate Task',
|
|
25
|
-
kind: ToolKind.ReadOnly,
|
|
26
|
-
schema: TaskSchema,
|
|
27
|
-
|
|
28
|
-
description: {
|
|
29
|
-
short: 'Delegate read-only investigation work to parallel sub-agents',
|
|
30
|
-
long: `Spin up one or more read-only sub-agents (Read/Grep/Glob only) to investigate
|
|
31
|
-
the codebase in parallel, then return their findings.
|
|
32
|
-
|
|
33
|
-
Use this when:
|
|
34
|
-
- A question has multiple independent angles worth exploring at once
|
|
35
|
-
- You want a focused sub-agent to dig into one area without cluttering the main conversation
|
|
36
|
-
|
|
37
|
-
Sub-agents cannot write files or run commands — they only read and report back.
|
|
38
|
-
You're responsible for synthesizing their findings into your final answer.`,
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
execute: async ({ tasks }, context) => {
|
|
42
|
-
let modelConfig;
|
|
43
|
-
try {
|
|
44
|
-
modelConfig = requireModelConfig();
|
|
45
|
-
} catch (e) {
|
|
46
|
-
const msg = (e as Error).message;
|
|
47
|
-
return { success: false, llmContent: msg, displayContent: msg };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const agentConfig = {
|
|
51
|
-
apiKey: modelConfig.apiKey,
|
|
52
|
-
baseURL: modelConfig.baseURL,
|
|
53
|
-
model: modelConfig.model,
|
|
54
|
-
timeout: modelConfig.timeout,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const cwd = context?.cwd || process.cwd();
|
|
58
|
-
const sourceCtx = buildSourceContext(cwd);
|
|
59
|
-
const codeContext = sourceCtx
|
|
60
|
-
? `\n\nWorkspace context (project metadata + file tree + structure summaries + git changes):\n${sourceCtx}\n\nUse Read / Grep / Glob to examine these.`
|
|
61
|
-
: '\n\nUse Read / Grep / Glob to explore the codebase before responding.';
|
|
62
|
-
|
|
63
|
-
const orchestrator = new OrchestratorAgent(
|
|
64
|
-
'Task-Orchestrator',
|
|
65
|
-
'You coordinate read-only investigation sub-agents.',
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
tasks.forEach((task, i) => {
|
|
69
|
-
const agentCfg: SubAgentConfig = {
|
|
70
|
-
name: `agent-${i}`,
|
|
71
|
-
role: 'Investigator',
|
|
72
|
-
systemPrompt: `You are a focused investigation sub-agent. ${task.prompt}${codeContext}`,
|
|
73
|
-
config: agentConfig,
|
|
74
|
-
tools: ['Read', 'Grep', 'Glob'],
|
|
75
|
-
};
|
|
76
|
-
orchestrator.registerAgent(agentCfg);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
const responses = await orchestrator.delegateParallel(
|
|
81
|
-
tasks.map((task, i) => ({ agentName: `agent-${i}`, task: task.prompt })),
|
|
82
|
-
tasks.length,
|
|
83
|
-
context?.sessionId,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const lines: string[] = [];
|
|
87
|
-
responses.forEach((res, i) => {
|
|
88
|
-
lines.push(`### ${tasks[i]?.description || res.agentName}`);
|
|
89
|
-
lines.push(res.content || '*No response*');
|
|
90
|
-
lines.push('');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const formatted = lines.join('\n').trim();
|
|
94
|
-
return {
|
|
95
|
-
success: true,
|
|
96
|
-
llmContent: formatted,
|
|
97
|
-
displayContent: `✓ Ran ${tasks.length} investigation${tasks.length > 1 ? 's' : ''} in parallel`,
|
|
98
|
-
};
|
|
99
|
-
} catch (e) {
|
|
100
|
-
const msg = `Task delegation failed: ${(e as Error).message}`;
|
|
101
|
-
return { success: false, llmContent: msg, displayContent: msg };
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
export default taskTool;
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Write 工具
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import fs from 'fs/promises';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import { z } from 'zod';
|
|
10
|
-
import { createTool } from '../createTool.js';
|
|
11
|
-
import { ToolKind, ToolErrorType } from '../types.js';
|
|
12
|
-
import { createSnapshot } from './snapshot.js';
|
|
13
|
-
|
|
14
|
-
// ========== Schema 定
|
|
15
|
-
|
|
16
|
-
const WriteSchema = z.object({
|
|
17
|
-
file_path: z.string()
|
|
18
|
-
.min(1, '文件路径不能为空')
|
|
19
|
-
.describe('The absolute path to the file to write'),
|
|
20
|
-
contents: z.string()
|
|
21
|
-
.describe('The contents to write to the file'),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// ========== Write 工
|
|
25
|
-
|
|
26
|
-
export const writeTool = createTool({
|
|
27
|
-
name: 'Write',
|
|
28
|
-
displayName: 'File Write',
|
|
29
|
-
kind: ToolKind.Write,
|
|
30
|
-
schema: WriteSchema,
|
|
31
|
-
|
|
32
|
-
description: {
|
|
33
|
-
short: 'Writes a file to the local filesystem',
|
|
34
|
-
long: 'Creates a new file or overwrites an existing file with the specified contents.',
|
|
35
|
-
usageNotes: [
|
|
36
|
-
'This tool will overwrite the existing file if there is one at the provided path',
|
|
37
|
-
'ALWAYS prefer editing existing files in the codebase using Edit tool',
|
|
38
|
-
'NEVER write new files unless explicitly required',
|
|
39
|
-
'NEVER proactively create documentation files (*.md) or README files',
|
|
40
|
-
'Parent directories will be created automatically if they do not exist',
|
|
41
|
-
],
|
|
42
|
-
examples: [
|
|
43
|
-
{
|
|
44
|
-
description: 'Create a new TypeScript file',
|
|
45
|
-
params: {
|
|
46
|
-
file_path: '/path/to/new-file.ts',
|
|
47
|
-
contents: 'export const hello = "world";',
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
important: [
|
|
52
|
-
'Only create files that are absolutely necessary',
|
|
53
|
-
'Do not create README or documentation files unless explicitly requested',
|
|
54
|
-
],
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
category: '文件操作',
|
|
58
|
-
tags: ['file', 'io', 'write', 'create'],
|
|
59
|
-
|
|
60
|
-
// 提取签名内容(用于权限规
|
|
61
|
-
extractSignatureContent: (params: unknown) => {
|
|
62
|
-
const p = params as { file_path: string };
|
|
63
|
-
return p.file_path;
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
// 抽象权限规
|
|
67
|
-
abstractPermissionRule: (params: unknown) => {
|
|
68
|
-
const p = params as { file_path: string };
|
|
69
|
-
const dir = path.dirname(p.file_path);
|
|
70
|
-
return `Write:${dir}/*`;
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
async execute(params, context) {
|
|
74
|
-
const { file_path, contents } = params;
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
// 1. 检查目标是否是目
|
|
78
|
-
try {
|
|
79
|
-
const stat = await fs.stat(file_path);
|
|
80
|
-
if (stat.isDirectory()) {
|
|
81
|
-
return {
|
|
82
|
-
success: false,
|
|
83
|
-
llmContent: `Error: ${file_path} is a directory, cannot write to it`,
|
|
84
|
-
displayContent: `error: ${file_path} is a directory`,
|
|
85
|
-
error: {
|
|
86
|
-
type: ToolErrorType.VALIDATION_ERROR,
|
|
87
|
-
message: 'Path is a directory',
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
} catch {
|
|
92
|
-
// 文件不存在,这是允许
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// 2. 确保父目录存
|
|
96
|
-
const dir = path.dirname(file_path);
|
|
97
|
-
await fs.mkdir(dir, { recursive: true });
|
|
98
|
-
|
|
99
|
-
// 3. 快照原始文件(如果已存在)
|
|
100
|
-
let snapshotPath: string | null = null;
|
|
101
|
-
try { await fs.access(file_path); snapshotPath = await createSnapshot(file_path); } catch { /* new file */ }
|
|
102
|
-
|
|
103
|
-
// 4. 写入文
|
|
104
|
-
await fs.writeFile(file_path, contents, 'utf8');
|
|
105
|
-
|
|
106
|
-
// 5. 计算写入信
|
|
107
|
-
const lines = contents.split('\n').length;
|
|
108
|
-
const bytes = Buffer.byteLength(contents, 'utf8');
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
success: true,
|
|
112
|
-
llmContent: `Successfully wrote to ${file_path} (${lines} lines, ${bytes} bytes)`,
|
|
113
|
-
displayContent: `${path.basename(file_path)} ${lines} lines`,
|
|
114
|
-
metadata: {
|
|
115
|
-
file_path,
|
|
116
|
-
lines,
|
|
117
|
-
bytes,
|
|
118
|
-
snapshot: snapshotPath,
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
} catch (error) {
|
|
122
|
-
const errorMessage = error instanceof Error ? error.message : 'unknown error';
|
|
123
|
-
return {
|
|
124
|
-
success: false,
|
|
125
|
-
llmContent: `Error writing file: ${errorMessage}`,
|
|
126
|
-
displayContent: `error: ${errorMessage}`,
|
|
127
|
-
error: {
|
|
128
|
-
type: ToolErrorType.EXECUTION_ERROR,
|
|
129
|
-
message: errorMessage,
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
});
|