aegiscode 3.1.10 → 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aegis.js +165 -0
- package/package.json +18 -86
- package/LICENSE +0 -21
- package/README.md +0 -394
- 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
package/src/store/vanilla.ts
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Zustand Vanilla Store
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { createStore } from 'zustand/vanilla';
|
|
8
|
-
import { devtools, subscribeWithSelector } from 'zustand/middleware';
|
|
9
|
-
|
|
10
|
-
import type { ClawdStore } from './types.js';
|
|
11
|
-
import type { RuntimeConfig } from '../config/types.js';
|
|
12
|
-
import {
|
|
13
|
-
createSessionSlice,
|
|
14
|
-
createConfigSlice,
|
|
15
|
-
createAppSlice,
|
|
16
|
-
createFocusSlice,
|
|
17
|
-
createCommandSlice,
|
|
18
|
-
} from './slices/index.js';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* - devtools: 开发工具支持
|
|
25
|
-
* - subscribeWithSelector: 支持选择器订阅
|
|
26
|
-
*/
|
|
27
|
-
export const vanillaStore = createStore<ClawdStore>()(
|
|
28
|
-
devtools(
|
|
29
|
-
subscribeWithSelector((...a) => ({
|
|
30
|
-
session: createSessionSlice(...a),
|
|
31
|
-
config: createConfigSlice(...a),
|
|
32
|
-
app: createAppSlice(...a),
|
|
33
|
-
focus: createFocusSlice(...a),
|
|
34
|
-
command: createCommandSlice(...a),
|
|
35
|
-
})),
|
|
36
|
-
{
|
|
37
|
-
name: 'ClawdStore',
|
|
38
|
-
enabled: process.env.NODE_ENV === 'development',
|
|
39
|
-
}
|
|
40
|
-
)
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
// ========== 便捷访问
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
*/
|
|
48
|
-
export const getState = () => vanillaStore.getState();
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
*/
|
|
53
|
-
export const subscribe = vanillaStore.subscribe;
|
|
54
|
-
|
|
55
|
-
// ========== Actions 快捷访
|
|
56
|
-
|
|
57
|
-
export const sessionActions = () => getState().session.actions;
|
|
58
|
-
export const configActions = () => getState().config.actions;
|
|
59
|
-
export const appActions = () => getState().app.actions;
|
|
60
|
-
export const focusActions = () => getState().focus.actions;
|
|
61
|
-
export const commandActions = () => getState().command.actions;
|
|
62
|
-
|
|
63
|
-
// ========== 配置便捷访
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
*
|
|
67
|
-
*/
|
|
68
|
-
export const getConfig = (): RuntimeConfig | null => getState().config.config;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
*
|
|
72
|
-
*/
|
|
73
|
-
export const getCurrentModel = () => {
|
|
74
|
-
const config = getConfig();
|
|
75
|
-
if (!config) return undefined;
|
|
76
|
-
|
|
77
|
-
// 优先使用 currentModelId
|
|
78
|
-
if (config.currentModelId && config.models) {
|
|
79
|
-
const model = config.models.find((m) => m.id === config.currentModelId);
|
|
80
|
-
if (model) return model;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// 回退:按 model 字段匹配(兼容 currentModelId 被设为 model name 的情况)
|
|
84
|
-
if (config.currentModelId && config.models) {
|
|
85
|
-
const model = config.models.find((m) => m.model === config.currentModelId);
|
|
86
|
-
if (model) return model;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// 回退
|
|
90
|
-
if (config.models && config.models.length > 0) {
|
|
91
|
-
return config.models[0];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// 回退到 default
|
|
95
|
-
return config.default;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
*
|
|
100
|
-
*/
|
|
101
|
-
export const getPermissionMode = () => {
|
|
102
|
-
const config = getConfig();
|
|
103
|
-
return config?.defaultPermissionMode || 'default';
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
// ========== 初始化机
|
|
107
|
-
|
|
108
|
-
let initializationPromise: Promise<void> | null = null;
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* - 幂等:已初始化直接返回
|
|
115
|
-
* - 并发安全:共享 Promise
|
|
116
|
-
* - 失败重试:下次调用重新尝试
|
|
117
|
-
*/
|
|
118
|
-
export async function ensureStoreInitialized(): Promise<void> {
|
|
119
|
-
// 1. 快速路径:已初始
|
|
120
|
-
const config = getConfig();
|
|
121
|
-
if (config !== null) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// 2. 并发保护:等待共
|
|
126
|
-
if (initializationPromise) {
|
|
127
|
-
return initializationPromise;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// 3. 开始初始
|
|
131
|
-
initializationPromise = (async () => {
|
|
132
|
-
try {
|
|
133
|
-
// 动态导入避免循环依
|
|
134
|
-
const { ConfigManager } = await import('../config/ConfigManager.js');
|
|
135
|
-
const configManager = ConfigManager.getInstance();
|
|
136
|
-
const loadedConfig = await configManager.initialize();
|
|
137
|
-
getState().config.actions.setConfig(loadedConfig as RuntimeConfig);
|
|
138
|
-
} catch (error) {
|
|
139
|
-
initializationPromise = null; // 允许重
|
|
140
|
-
throw new Error(
|
|
141
|
-
`❌ Store 初始化失败\n\n` +
|
|
142
|
-
`原因: ${error instanceof Error ? error.message : '未知错误'}`
|
|
143
|
-
);
|
|
144
|
-
} finally {
|
|
145
|
-
initializationPromise = null;
|
|
146
|
-
}
|
|
147
|
-
})();
|
|
148
|
-
|
|
149
|
-
return initializationPromise;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// ========== 订阅工
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
*
|
|
156
|
-
*/
|
|
157
|
-
export function subscribeToState<T>(
|
|
158
|
-
selector: (state: ClawdStore) => T,
|
|
159
|
-
callback: (value: T, prevValue: T) => void
|
|
160
|
-
): () => void {
|
|
161
|
-
return vanillaStore.subscribe((state, prevState) => {
|
|
162
|
-
const value = selector(state);
|
|
163
|
-
const prevValue = selector(prevState);
|
|
164
|
-
if (value !== prevValue) {
|
|
165
|
-
callback(value, prevValue);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
*
|
|
172
|
-
*/
|
|
173
|
-
export function subscribeToTodos(
|
|
174
|
-
callback: (todos: ClawdStore['app']['todos']) => void
|
|
175
|
-
): () => void {
|
|
176
|
-
return subscribeToState((state) => state.app.todos, callback);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
*
|
|
181
|
-
*/
|
|
182
|
-
export function subscribeToMessages(
|
|
183
|
-
callback: (messages: ClawdStore['session']['messages']) => void
|
|
184
|
-
): () => void {
|
|
185
|
-
return subscribeToState((state) => state.session.messages, callback);
|
|
186
|
-
}
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bash 工具
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { exec, spawn } from 'child_process';
|
|
8
|
-
import { promisify } from 'util';
|
|
9
|
-
import { createWriteStream, mkdirSync } from 'fs';
|
|
10
|
-
import path from 'path';
|
|
11
|
-
import os from 'os';
|
|
12
|
-
import { z } from 'zod';
|
|
13
|
-
import { createTool } from '../createTool.js';
|
|
14
|
-
import { ToolKind, ToolErrorType } from '../types.js';
|
|
15
|
-
|
|
16
|
-
const BG_JOBS_DIR = path.join(os.homedir(), '.aegiscode', 'bg');
|
|
17
|
-
|
|
18
|
-
const execAsync = promisify(exec);
|
|
19
|
-
|
|
20
|
-
// ========== Schema 定
|
|
21
|
-
|
|
22
|
-
const BashSchema = z.object({
|
|
23
|
-
command: z.string()
|
|
24
|
-
.min(1, '命令不能为空')
|
|
25
|
-
.describe('The shell command to execute'),
|
|
26
|
-
description: z.string()
|
|
27
|
-
.optional()
|
|
28
|
-
.describe('A brief description of what the command does (for logging)'),
|
|
29
|
-
timeout: z.number()
|
|
30
|
-
.max(600000)
|
|
31
|
-
.default(120000)
|
|
32
|
-
.describe('Timeout in milliseconds (max 10 minutes, default 2 minutes)'),
|
|
33
|
-
working_directory: z.string()
|
|
34
|
-
.optional()
|
|
35
|
-
.describe('The working directory to execute the command in'),
|
|
36
|
-
run_in_background: z.boolean()
|
|
37
|
-
.default(false)
|
|
38
|
-
.describe('Whether to run the command in the background'),
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// ========== Bash 工
|
|
42
|
-
|
|
43
|
-
export const bashTool = createTool({
|
|
44
|
-
name: 'Bash',
|
|
45
|
-
displayName: 'Shell Command',
|
|
46
|
-
kind: ToolKind.Execute,
|
|
47
|
-
schema: BashSchema,
|
|
48
|
-
|
|
49
|
-
// Bash 不是并发安全的(可能修改共享状
|
|
50
|
-
isConcurrencySafe: false,
|
|
51
|
-
|
|
52
|
-
description: {
|
|
53
|
-
short: 'Executes bash commands in a shell session',
|
|
54
|
-
long: 'Executes shell commands and returns the output. Use this for system operations, git commands, package management, etc.',
|
|
55
|
-
usageNotes: [
|
|
56
|
-
'Avoid using for file operations - use dedicated tools (Read, Write, Edit) instead',
|
|
57
|
-
'Do not use cat/head/tail to read files - use the Read tool',
|
|
58
|
-
'Do not use sed/awk to edit files - use the Edit tool',
|
|
59
|
-
'Use && to chain dependent commands',
|
|
60
|
-
'Use run_in_background for long-running dev servers',
|
|
61
|
-
'Always quote file paths that contain spaces',
|
|
62
|
-
],
|
|
63
|
-
examples: [
|
|
64
|
-
{
|
|
65
|
-
description: 'Run npm install',
|
|
66
|
-
params: {
|
|
67
|
-
command: 'npm install',
|
|
68
|
-
description: 'Install npm dependencies',
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
description: 'Check git status',
|
|
73
|
-
params: {
|
|
74
|
-
command: 'git status',
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
description: 'Run a build command with timeout',
|
|
79
|
-
params: {
|
|
80
|
-
command: 'npm run build',
|
|
81
|
-
timeout: 300000,
|
|
82
|
-
description: 'Build the project',
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
important: [
|
|
87
|
-
'NEVER use git commands with -i flag (interactive mode)',
|
|
88
|
-
'NEVER run destructive commands like rm -rf / without explicit user request',
|
|
89
|
-
'NEVER use echo or printf to communicate - output text directly instead',
|
|
90
|
-
'Avoid long-running processes that block (like npm run dev) unless using run_in_background',
|
|
91
|
-
],
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
category: 'Shell',
|
|
95
|
-
tags: ['shell', 'bash', 'command', 'execute'],
|
|
96
|
-
|
|
97
|
-
// 提取签名内容(用于权限规
|
|
98
|
-
extractSignatureContent: (params: unknown) => {
|
|
99
|
-
const p = params as { command: string };
|
|
100
|
-
return p.command;
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
async execute(params, context) {
|
|
104
|
-
const { command, description, timeout, working_directory, run_in_background } = params;
|
|
105
|
-
|
|
106
|
-
// 危险命令检
|
|
107
|
-
const dangerousPatterns = [
|
|
108
|
-
/rm\s+-rf\s+\/(?!\w)/, // rm -rf / (但允许 rm -rf /path/to/dir)
|
|
109
|
-
/>\s*\/dev\/sd[a-z]/, // 写入磁盘设
|
|
110
|
-
/mkfs\./, // 格式化文件系
|
|
111
|
-
/dd\s+if=.*of=\/dev/, // dd 写入设
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
for (const pattern of dangerousPatterns) {
|
|
115
|
-
if (pattern.test(command)) {
|
|
116
|
-
return {
|
|
117
|
-
success: false,
|
|
118
|
-
llmContent: `Error: Potentially dangerous command detected: ${command}`,
|
|
119
|
-
displayContent: `blocked: dangerous command`,
|
|
120
|
-
error: {
|
|
121
|
-
type: ToolErrorType.PERMISSION_ERROR,
|
|
122
|
-
message: 'Dangerous command blocked',
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
if (run_in_background) {
|
|
130
|
-
const jobId = `bg-${Date.now()}`;
|
|
131
|
-
const logPath = path.join(BG_JOBS_DIR, `${jobId}.log`);
|
|
132
|
-
mkdirSync(BG_JOBS_DIR, { recursive: true });
|
|
133
|
-
|
|
134
|
-
const logStream = createWriteStream(logPath, { flags: 'a' });
|
|
135
|
-
logStream.write(`[${new Date().toISOString()}] $ ${command}\n\n`);
|
|
136
|
-
|
|
137
|
-
const child = spawn(command, [], {
|
|
138
|
-
shell: '/bin/bash',
|
|
139
|
-
cwd: working_directory || context?.cwd || process.cwd(),
|
|
140
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
child.stdout!.on('data', (chunk: Buffer) => logStream.write(chunk));
|
|
144
|
-
child.stderr!.on('data', (chunk: Buffer) => logStream.write(chunk));
|
|
145
|
-
child.on('close', (code: number | null) => {
|
|
146
|
-
logStream.write(`\n[${new Date().toISOString()}] exited with code ${code}\n`);
|
|
147
|
-
logStream.end();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
success: true,
|
|
152
|
-
llmContent: `Background process started.\nJob ID: ${jobId}\nPID: ${child.pid}\nLog file: ${logPath}\n\nMonitor with: tail -f ${logPath}\nCheck output: cat ${logPath}`,
|
|
153
|
-
displayContent: `▶ bg: ${description || command.substring(0, 50)} (PID ${child.pid})`,
|
|
154
|
-
metadata: { jobId, pid: child.pid, logPath, command },
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// 执行命
|
|
159
|
-
const options = {
|
|
160
|
-
timeout,
|
|
161
|
-
cwd: working_directory || context?.cwd || process.cwd(),
|
|
162
|
-
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
163
|
-
shell: '/bin/bash',
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const { stdout, stderr } = await execAsync(command, options);
|
|
167
|
-
|
|
168
|
-
// 组合输
|
|
169
|
-
const output = [
|
|
170
|
-
stdout ? stdout.trim() : '',
|
|
171
|
-
stderr ? `[stderr]\n${stderr.trim()}` : '',
|
|
172
|
-
].filter(Boolean).join('\n\n');
|
|
173
|
-
|
|
174
|
-
return {
|
|
175
|
-
success: true,
|
|
176
|
-
llmContent: output || '(no output)',
|
|
177
|
-
displayContent: description
|
|
178
|
-
? description
|
|
179
|
-
: command.length > 60 ? command.substring(0, 60) + '…' : command,
|
|
180
|
-
metadata: {
|
|
181
|
-
command,
|
|
182
|
-
exit_code: 0,
|
|
183
|
-
working_directory: options.cwd,
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
} catch (error: unknown) {
|
|
187
|
-
// 处理执行错
|
|
188
|
-
const execError = error as {
|
|
189
|
-
code?: number | string;
|
|
190
|
-
killed?: boolean;
|
|
191
|
-
signal?: string;
|
|
192
|
-
stdout?: string;
|
|
193
|
-
stderr?: string;
|
|
194
|
-
message?: string;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// 超时处
|
|
198
|
-
if (execError.killed && execError.signal === 'SIGTERM') {
|
|
199
|
-
return {
|
|
200
|
-
success: false,
|
|
201
|
-
llmContent: `Command timed out after ${timeout}ms: ${command}`,
|
|
202
|
-
displayContent: `error: timeout (${timeout}ms)`,
|
|
203
|
-
error: {
|
|
204
|
-
type: ToolErrorType.TIMEOUT_ERROR,
|
|
205
|
-
message: 'Command timed out',
|
|
206
|
-
},
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// 命令执行失
|
|
211
|
-
const exitCode = typeof execError.code === 'number' ? execError.code : 1;
|
|
212
|
-
const stderr = execError.stderr || execError.message || 'unknown error';
|
|
213
|
-
const stdout = execError.stdout || '';
|
|
214
|
-
|
|
215
|
-
const output = [
|
|
216
|
-
stdout ? stdout.trim() : '',
|
|
217
|
-
stderr ? stderr.trim() : '',
|
|
218
|
-
].filter(Boolean).join('\n\n');
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
success: false,
|
|
222
|
-
llmContent: `Command failed with exit code ${exitCode}:\n${output}`,
|
|
223
|
-
displayContent: `error: exit ${exitCode}`,
|
|
224
|
-
error: {
|
|
225
|
-
type: ToolErrorType.EXECUTION_ERROR,
|
|
226
|
-
message: stderr,
|
|
227
|
-
details: { exit_code: exitCode },
|
|
228
|
-
},
|
|
229
|
-
metadata: {
|
|
230
|
-
command,
|
|
231
|
-
exit_code: exitCode,
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Council tool — lets the running agent convene a multi-perspective
|
|
3
|
-
* deliberation mid-conversation, without the user typing /research.
|
|
4
|
-
* Mirrors the /research slash command (builtinCommands.ts) exactly:
|
|
5
|
-
* fixed 4-member council, read-only tools, no confirmation needed.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { z } from 'zod';
|
|
9
|
-
import { createTool } from '../createTool.js';
|
|
10
|
-
import { ToolKind } from '../types.js';
|
|
11
|
-
import { CouncilAgent } from '../../agent/orchestrator/CouncilAgent.js';
|
|
12
|
-
import { requireModelConfig, buildSourceContext } from '../../agent/orchestrator/utils.js';
|
|
13
|
-
|
|
14
|
-
const CouncilSchema = z.object({
|
|
15
|
-
question: z.string().describe('The question or decision to deliberate on'),
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export const councilTool = createTool({
|
|
19
|
-
name: 'Council',
|
|
20
|
-
displayName: 'Convene Council',
|
|
21
|
-
kind: ToolKind.ReadOnly,
|
|
22
|
-
schema: CouncilSchema,
|
|
23
|
-
|
|
24
|
-
description: {
|
|
25
|
-
short: 'Convene a 4-perspective council to deliberate on a question',
|
|
26
|
-
long: `Spawns a research council of read-only sub-agents with different perspectives —
|
|
27
|
-
Analyst (data/empirical), Architect (systems/design), Ethicist (safety/fairness),
|
|
28
|
-
Pragmatist (implementation reality) — who each vote and reason independently,
|
|
29
|
-
then returns their views plus a synthesis.
|
|
30
|
-
|
|
31
|
-
Use this for genuinely contested questions where multiple angles matter
|
|
32
|
-
(architecture tradeoffs, risk calls, "should we do X" decisions) — not for
|
|
33
|
-
straightforward lookups.`,
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
execute: async ({ question }, context) => {
|
|
37
|
-
let modelConfig;
|
|
38
|
-
try {
|
|
39
|
-
modelConfig = requireModelConfig();
|
|
40
|
-
} catch (e) {
|
|
41
|
-
const msg = (e as Error).message;
|
|
42
|
-
return { success: false, llmContent: msg, displayContent: msg };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const cwd = context?.cwd || process.cwd();
|
|
46
|
-
const sourceCtx = buildSourceContext(cwd);
|
|
47
|
-
const baseModelCfg = { model: modelConfig.model, baseURL: modelConfig.baseURL || undefined, apiKey: modelConfig.apiKey };
|
|
48
|
-
const researchTools = ['Read', 'Grep', 'Glob'];
|
|
49
|
-
const researchNote = `\n\nWorkspace context (project metadata + file tree + structure summaries + git changes):\n${sourceCtx}\n\nRead files with Read tool, search with Grep, browse with Glob.\nAlways state VOTE: approve, reject, or abstain and REASONING: with clear justification.`;
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
const council = new CouncilAgent('council', modelConfig, {
|
|
53
|
-
rule: 'majority',
|
|
54
|
-
maxTokensPerAgent: 800,
|
|
55
|
-
enableIteration: false,
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
council.addMember('analyst', 'Data Analyst',
|
|
59
|
-
`You are a Data Analyst on a research council. You reason from data, statistics, and empirical evidence.\nYou value measurable outcomes and quantitative reasoning.${researchNote}`,
|
|
60
|
-
1, baseModelCfg, researchTools);
|
|
61
|
-
|
|
62
|
-
council.addMember('architect', 'Systems Architect',
|
|
63
|
-
`You are a Systems Architect on a research council. You evaluate designs, tradeoffs, and architectural decisions.\nYou focus on scalability, maintainability, and system coherence.${researchNote}`,
|
|
64
|
-
1, baseModelCfg, researchTools);
|
|
65
|
-
|
|
66
|
-
council.addMember('ethicist', 'Ethics & Safety Officer',
|
|
67
|
-
`You are an Ethics & Safety Officer on a research council. You evaluate safety, fairness, privacy, and societal impact.\nYou raise concerns others might miss and advocate for responsible practices.${researchNote}`,
|
|
68
|
-
1, baseModelCfg, researchTools);
|
|
69
|
-
|
|
70
|
-
council.addMember('pragmatist', 'Pragmatic Engineer',
|
|
71
|
-
`You are a Pragmatic Engineer on a research council. You evaluate practicality, implementation effort, and real-world constraints.\nYou balance idealism with what actually works in production.${researchNote}`,
|
|
72
|
-
1, baseModelCfg, researchTools);
|
|
73
|
-
|
|
74
|
-
const result = await council.deliberate(question, context?.sessionId);
|
|
75
|
-
|
|
76
|
-
const lines: string[] = [];
|
|
77
|
-
for (const v of result.voteResults) {
|
|
78
|
-
lines.push(`### ${v.role}`);
|
|
79
|
-
lines.push(`VOTE: ${v.vote}`);
|
|
80
|
-
lines.push(v.reasoning);
|
|
81
|
-
lines.push('');
|
|
82
|
-
}
|
|
83
|
-
lines.push('### Synthesis');
|
|
84
|
-
lines.push('');
|
|
85
|
-
const summaryLines = result.summary.split('\n');
|
|
86
|
-
const verdictIdx = summaryLines.findIndex(l => l.includes('APPROVED') || l.includes('REJECTED'));
|
|
87
|
-
const synthesis = verdictIdx > -1
|
|
88
|
-
? summaryLines.slice(verdictIdx + 1).join('\n').trim()
|
|
89
|
-
: result.summary;
|
|
90
|
-
lines.push(synthesis || `${result.voteResults.length} perspectives gathered.`);
|
|
91
|
-
|
|
92
|
-
const formatted = lines.join('\n').trim();
|
|
93
|
-
return {
|
|
94
|
-
success: true,
|
|
95
|
-
llmContent: formatted,
|
|
96
|
-
displayContent: `✓ Council deliberated (${result.voteResults.length} perspectives, ${result.rounds} round${result.rounds === 1 ? '' : 's'})`,
|
|
97
|
-
};
|
|
98
|
-
} catch (e) {
|
|
99
|
-
const msg = `Council deliberation failed: ${(e as Error).message}`;
|
|
100
|
-
return { success: false, llmContent: msg, displayContent: msg };
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
export default councilTool;
|