minimal-agent 0.11.0 → 0.12.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/package.json +4 -1
- package/plugins/workflow-runner/plugin.js +27 -15
- package/plugins/workflow-runner/plugin.ts +34 -20
- package/plugins/workflow-runner/src/agentCommon.js +13 -12
- package/plugins/workflow-runner/src/agentCommon.ts +22 -13
- package/plugins/workflow-runner/src/index.js +5 -3
- package/plugins/workflow-runner/src/index.ts +31 -13
- package/plugins/workflow-runner/src/multimodal.js +2 -1
- package/plugins/workflow-runner/src/multimodal.ts +2 -1
- package/plugins/workflow-runner/src/stepExecutors/skill.js +5 -6
- package/plugins/workflow-runner/src/stepExecutors/skill.ts +12 -7
- package/plugins/workflow-runner/src/stepExecutors/tool.js +68 -57
- package/plugins/workflow-runner/src/stepExecutors/tool.ts +88 -66
- package/plugins/workflow-runner/src/toolRuntime.js +48 -0
- package/plugins/workflow-runner/src/toolRuntime.ts +64 -0
- package/plugins/workflow-runner/src/types.ts +26 -7
- package/plugins/workflow-runner/test/context-files.test.ts +47 -16
- package/plugins/workflow-runner/test/hostCapability.test.ts +9 -3
- package/plugins/workflow-runner/test/multimodal.test.ts +61 -10
- package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +168 -0
- package/src/cli/print.js +19 -4
- package/src/cli/print.ts +17 -4
- package/src/cli/streamJson.js +19 -4
- package/src/cli/streamJson.ts +17 -4
- package/src/config/configDefaults.js +25 -0
- package/src/config/configDefaults.ts +33 -0
- package/src/config/configFile.js +2 -21
- package/src/config/configFile.ts +11 -24
- package/src/config/configManagement.js +1 -1
- package/src/config/configManagement.ts +2 -2
- package/src/context/compact.js +4 -0
- package/src/context/compact.ts +4 -0
- package/src/context/contextBundle.js +38 -13
- package/src/context/contextBundle.ts +47 -13
- package/src/harness/stallGuard.js +19 -4
- package/src/harness/stallGuard.ts +30 -7
- package/src/loop.js +95 -11
- package/src/loop.ts +125 -16
- package/src/main.js +8 -1
- package/src/main.tsx +7 -1
- package/src/memory/constants.js +10 -0
- package/src/memory/constants.ts +13 -0
- package/src/memory/episodicMemory.js +274 -2
- package/src/memory/episodicMemory.ts +306 -1
- package/src/memory/fileStore.js +24 -4
- package/src/memory/fileStore.ts +22 -2
- package/src/memory/memoryService.js +79 -12
- package/src/memory/memoryService.ts +108 -9
- package/src/memory/repository.js +415 -85
- package/src/memory/repository.ts +437 -86
- package/src/memory/turnJournal.js +95 -0
- package/src/memory/turnJournal.ts +120 -0
- package/src/memory/types.ts +16 -0
- package/src/plugins/pluginApi.ts +30 -6
- package/src/plugins/pluginRunner.js +6 -2
- package/src/plugins/pluginRunner.ts +12 -7
- package/src/prompts/policyRegistry.js +27 -0
- package/src/prompts/policyRegistry.ts +27 -0
- package/src/prompts/promptAssembly.js +39 -7
- package/src/prompts/promptAssembly.ts +145 -59
- package/src/session/runAgentTurn.js +43 -21
- package/src/session/runAgentTurn.ts +68 -26
- package/src/session/runTurn.js +11 -46
- package/src/session/runTurn.ts +12 -46
- package/src/session/runtimeStore.js +149 -0
- package/src/session/runtimeStore.ts +197 -0
- package/src/session/sessionState.js +5 -0
- package/src/session/sessionState.ts +14 -0
- package/src/tools/agent/agent.js +143 -14
- package/src/tools/agent/agent.ts +149 -14
- package/src/tools/agent/agentTaskService.js +60 -0
- package/src/tools/agent/agentTaskService.ts +113 -0
- package/src/tools/agent/agentTypes.js +5 -0
- package/src/tools/agent/agentTypes.ts +5 -0
- package/src/tools/bash/bash.js +31 -11
- package/src/tools/bash/bash.ts +29 -10
- package/src/tools/capabilities.js +5 -0
- package/src/tools/capabilities.ts +11 -1
- package/src/tools/edit/edit.js +7 -4
- package/src/tools/edit/edit.ts +7 -4
- package/src/tools/edit/multi-edit.js +4 -2
- package/src/tools/edit/multi-edit.ts +4 -2
- package/src/tools/glob/glob.js +156 -40
- package/src/tools/glob/glob.ts +185 -46
- package/src/tools/index.js +35 -17
- package/src/tools/index.ts +81 -20
- package/src/tools/lsp/lsp.js +165 -22
- package/src/tools/lsp/lsp.ts +206 -36
- package/src/tools/powershell/powershell.js +116 -26
- package/src/tools/powershell/powershell.ts +155 -30
- package/src/tools/presentresult/presentresult.js +10 -0
- package/src/tools/presentresult/presentresult.ts +10 -0
- package/src/tools/read/read.js +244 -29
- package/src/tools/read/read.ts +391 -59
- package/src/tools/shared/diffSummary.js +44 -0
- package/src/tools/shared/diffSummary.ts +63 -0
- package/src/tools/shared/fileActivity.js +2 -1
- package/src/tools/shared/fileActivity.ts +3 -0
- package/src/tools/shared/permanentDeleteGuard.js +26 -0
- package/src/tools/shared/permanentDeleteGuard.ts +34 -0
- package/src/tools/shared/toolOutputStore.js +97 -0
- package/src/tools/shared/toolOutputStore.ts +110 -0
- package/src/tools/skill/skill.js +86 -0
- package/src/tools/skill/skill.ts +94 -0
- package/src/tools/snip/snip.js +67 -0
- package/src/tools/snip/snip.ts +80 -0
- package/src/tools/tasks/backgroundTaskService.js +79 -28
- package/src/tools/tasks/backgroundTaskService.ts +165 -49
- package/src/tools/tasks/taskManagement.js +163 -0
- package/src/tools/tasks/taskManagement.ts +180 -0
- package/src/tools/tasks/taskOutput.js +64 -14
- package/src/tools/tasks/taskOutput.ts +102 -23
- package/src/tools/tasks/taskStop.js +48 -8
- package/src/tools/tasks/taskStop.ts +69 -9
- package/src/tools/tasks/taskStore.js +46 -0
- package/src/tools/tasks/taskStore.ts +77 -0
- package/src/tools/terminal/terminalCapture.js +167 -0
- package/src/tools/terminal/terminalCapture.ts +179 -0
- package/src/tools/trash/trash.js +233 -0
- package/src/tools/trash/trash.ts +283 -0
- package/src/tools/worktree/sessionWorktree.js +128 -0
- package/src/tools/worktree/sessionWorktree.ts +158 -0
- package/src/tools/write/write.js +6 -2
- package/src/tools/write/write.ts +6 -2
- package/src/types.ts +12 -0
- package/src/ui/hooks/useChat.js +31 -11
- package/src/ui/hooks/useChat.ts +31 -13
- package/src/web/protocol.ts +78 -3
package/src/tools/index.js
CHANGED
|
@@ -19,6 +19,8 @@ import { advisorTool } from './advisor/advisor.js';
|
|
|
19
19
|
import { agentTool } from './agent/agent.js';
|
|
20
20
|
import { askUserQuestionTool } from './ask/ask.js';
|
|
21
21
|
import { bashTool } from './bash/bash.js';
|
|
22
|
+
import { assertCapabilityRegistry } from './capabilities.js';
|
|
23
|
+
import { computerUseTool } from './computeruse/computeruse.js';
|
|
22
24
|
import { downloadTool } from './download/download.js';
|
|
23
25
|
import { editTool } from './edit/edit.js';
|
|
24
26
|
import { multiEditTool } from './edit/multi-edit.js';
|
|
@@ -26,20 +28,24 @@ import { genImageTool } from './genimage/genimage.js';
|
|
|
26
28
|
import { generateSpeechTool } from './genspeech/genspeech.js';
|
|
27
29
|
import { globTool } from './glob/glob.js';
|
|
28
30
|
import { grepTool } from './grep/grep.js';
|
|
29
|
-
import { readTool } from './read/read.js';
|
|
30
|
-
import { presentResultTool } from './presentresult/presentresult.js';
|
|
31
|
-
import { clearPersonaTool, confirmMemoryTool, forgetMemoryTool, listMemoriesTool, recallMemoryTool, rememberMemoryTool, reviewMemoriesTool, searchConversationsTool, setPersonaTool, updateMemoryTool, } from './memory/memory.js';
|
|
32
|
-
import { webfetchTool } from './webfetch/webfetch.js';
|
|
33
|
-
import { webbrowserTool } from './webbrowser/webbrowser.js';
|
|
34
|
-
import { webSearchTool } from './websearch/websearch.js';
|
|
35
|
-
import { writeTool } from './write/write.js';
|
|
36
|
-
import { computerUseTool } from './computeruse/computeruse.js';
|
|
37
|
-
import { assertCapabilityRegistry } from './capabilities.js';
|
|
38
31
|
import { lspTool } from './lsp/lsp.js';
|
|
32
|
+
import { clearPersonaTool, confirmMemoryTool, forgetMemoryTool, listMemoriesTool, recallMemoryTool, rememberMemoryTool, reviewMemoriesTool, searchConversationsTool, setPersonaTool, updateMemoryTool, } from './memory/memory.js';
|
|
39
33
|
import { notebookEditTool } from './notebook/notebookEdit.js';
|
|
40
34
|
import { powerShellTool } from './powershell/powershell.js';
|
|
35
|
+
import { presentResultTool } from './presentresult/presentresult.js';
|
|
36
|
+
import { readTool } from './read/read.js';
|
|
37
|
+
import { skillTool } from './skill/skill.js';
|
|
38
|
+
import { snipTool } from './snip/snip.js';
|
|
39
|
+
import { taskCreateTool, taskGetTool, taskListTool, taskUpdateTool, } from './tasks/taskManagement.js';
|
|
41
40
|
import { taskOutputTool } from './tasks/taskOutput.js';
|
|
42
41
|
import { taskStopTool } from './tasks/taskStop.js';
|
|
42
|
+
import { terminalCaptureTool } from './terminal/terminalCapture.js';
|
|
43
|
+
import { trashTool } from './trash/trash.js';
|
|
44
|
+
import { webbrowserTool } from './webbrowser/webbrowser.js';
|
|
45
|
+
import { webfetchTool } from './webfetch/webfetch.js';
|
|
46
|
+
import { webSearchTool } from './websearch/websearch.js';
|
|
47
|
+
import { enterWorktreeTool, exitWorktreeTool, } from './worktree/sessionWorktree.js';
|
|
48
|
+
import { writeTool } from './write/write.js';
|
|
43
49
|
/** 所有内置工具(顺序 = 给 LLM 呈现的顺序,不影响代码执行,但会影响模型的优先级直觉) */
|
|
44
50
|
export const ALL_TOOLS = [
|
|
45
51
|
readTool,
|
|
@@ -76,6 +82,17 @@ export const ALL_TOOLS = [
|
|
|
76
82
|
computerUseTool,
|
|
77
83
|
// 追加在末尾:主循环 tools schema 的原有前缀字节不动(提示词缓存友好)
|
|
78
84
|
agentTool,
|
|
85
|
+
// Product tools append at the end to preserve the existing schema prefix cache.
|
|
86
|
+
trashTool,
|
|
87
|
+
taskCreateTool,
|
|
88
|
+
taskGetTool,
|
|
89
|
+
taskUpdateTool,
|
|
90
|
+
taskListTool,
|
|
91
|
+
skillTool,
|
|
92
|
+
enterWorktreeTool,
|
|
93
|
+
exitWorktreeTool,
|
|
94
|
+
terminalCaptureTool,
|
|
95
|
+
snipTool,
|
|
79
96
|
];
|
|
80
97
|
assertCapabilityRegistry(ALL_TOOLS.map((tool) => tool.name));
|
|
81
98
|
/** 按名字查表 */
|
|
@@ -157,12 +174,7 @@ export async function executeTool(name, rawArguments, signal, ctx) {
|
|
|
157
174
|
.join('\n');
|
|
158
175
|
return {
|
|
159
176
|
ok: false,
|
|
160
|
-
error: `工具 ${name} 参数校验失败,**请按下面逐条改正后重新调用**:\n${issues}\n\n
|
|
161
|
-
+ '通用修法:\n'
|
|
162
|
-
+ ' · **只填你这次确实要用的字段**。可选字段不要用 ""、0、{} 之类的默认值占位 ——\n'
|
|
163
|
-
+ ' 留空不填即可;填了占位值反而会被当成"你要用它"而触发校验。\n'
|
|
164
|
-
+ ' · 枚举字段只能取列出的值;数值字段注意上下限。\n'
|
|
165
|
-
+ ' · 改完直接重发这次调用,不要因为这个错误就换一条完全不同的路子。',
|
|
177
|
+
error: `工具 ${name} 参数校验失败,**请按下面逐条改正后重新调用**:\n${issues}\n\n通用修法:\n · **只填你这次确实要用的字段**。可选字段不要用 ""、0、{} 之类的默认值占位 ——\n 留空不填即可;填了占位值反而会被当成"你要用它"而触发校验。\n · 枚举字段只能取列出的值;数值字段注意上下限。\n · 改完直接重发这次调用,不要因为这个错误就换一条完全不同的路子。`,
|
|
166
178
|
};
|
|
167
179
|
}
|
|
168
180
|
// 4. 调用 call(),捕获意外异常
|
|
@@ -180,16 +192,22 @@ export async function executeTool(name, rawArguments, signal, ctx) {
|
|
|
180
192
|
}
|
|
181
193
|
}
|
|
182
194
|
// 导出每个工具,方便测试单独 import
|
|
183
|
-
export { readTool, editTool, writeTool, globTool, grepTool, webSearchTool, webfetchTool, webbrowserTool, computerUseTool, downloadTool, presentResultTool, bashTool, askUserQuestionTool };
|
|
195
|
+
export { readTool, editTool, writeTool, globTool, grepTool, webSearchTool, webfetchTool, webbrowserTool, computerUseTool, downloadTool, presentResultTool, bashTool, askUserQuestionTool, };
|
|
184
196
|
export { clearPersonaTool, confirmMemoryTool, forgetMemoryTool, listMemoriesTool, recallMemoryTool, rememberMemoryTool, reviewMemoriesTool, searchConversationsTool, setPersonaTool, updateMemoryTool, } from './memory/memory.js';
|
|
185
197
|
export { multiEditTool } from './edit/multi-edit.js';
|
|
186
198
|
export { genImageTool } from './genimage/genimage.js';
|
|
187
199
|
export { advisorTool } from './advisor/advisor.js';
|
|
188
200
|
export { agentTool } from './agent/agent.js';
|
|
189
|
-
export { createGenerateSpeechTool, generateSpeechTool } from './genspeech/genspeech.js';
|
|
201
|
+
export { createGenerateSpeechTool, generateSpeechTool, } from './genspeech/genspeech.js';
|
|
190
202
|
export { createWebSearchTool } from './websearch/websearch.js';
|
|
191
203
|
export { lspTool } from './lsp/lsp.js';
|
|
192
204
|
export { notebookEditTool } from './notebook/notebookEdit.js';
|
|
193
205
|
export { powerShellTool } from './powershell/powershell.js';
|
|
194
206
|
export { taskOutputTool } from './tasks/taskOutput.js';
|
|
195
207
|
export { taskStopTool } from './tasks/taskStop.js';
|
|
208
|
+
export { taskCreateTool, taskGetTool, taskUpdateTool, taskListTool, } from './tasks/taskManagement.js';
|
|
209
|
+
export { trashTool } from './trash/trash.js';
|
|
210
|
+
export { skillTool } from './skill/skill.js';
|
|
211
|
+
export { snipTool } from './snip/snip.js';
|
|
212
|
+
export { enterWorktreeTool, exitWorktreeTool, } from './worktree/sessionWorktree.js';
|
|
213
|
+
export { terminalCaptureTool, installTerminalCapture, } from './terminal/terminalCapture.js';
|
package/src/tools/index.ts
CHANGED
|
@@ -21,6 +21,8 @@ import { advisorTool } from './advisor/advisor.js';
|
|
|
21
21
|
import { agentTool } from './agent/agent.js';
|
|
22
22
|
import { askUserQuestionTool } from './ask/ask.js';
|
|
23
23
|
import { bashTool } from './bash/bash.js';
|
|
24
|
+
import { assertCapabilityRegistry } from './capabilities.js';
|
|
25
|
+
import { computerUseTool } from './computeruse/computeruse.js';
|
|
24
26
|
import { downloadTool } from './download/download.js';
|
|
25
27
|
import { editTool } from './edit/edit.js';
|
|
26
28
|
import { multiEditTool } from './edit/multi-edit.js';
|
|
@@ -28,8 +30,7 @@ import { genImageTool } from './genimage/genimage.js';
|
|
|
28
30
|
import { generateSpeechTool } from './genspeech/genspeech.js';
|
|
29
31
|
import { globTool } from './glob/glob.js';
|
|
30
32
|
import { grepTool } from './grep/grep.js';
|
|
31
|
-
import {
|
|
32
|
-
import { presentResultTool } from './presentresult/presentresult.js';
|
|
33
|
+
import { lspTool } from './lsp/lsp.js';
|
|
33
34
|
import {
|
|
34
35
|
clearPersonaTool,
|
|
35
36
|
confirmMemoryTool,
|
|
@@ -42,17 +43,30 @@ import {
|
|
|
42
43
|
setPersonaTool,
|
|
43
44
|
updateMemoryTool,
|
|
44
45
|
} from './memory/memory.js';
|
|
45
|
-
import { webfetchTool } from './webfetch/webfetch.js';
|
|
46
|
-
import { webbrowserTool } from './webbrowser/webbrowser.js';
|
|
47
|
-
import { webSearchTool } from './websearch/websearch.js';
|
|
48
|
-
import { writeTool } from './write/write.js';
|
|
49
|
-
import { computerUseTool } from './computeruse/computeruse.js';
|
|
50
|
-
import { assertCapabilityRegistry } from './capabilities.js';
|
|
51
|
-
import { lspTool } from './lsp/lsp.js';
|
|
52
46
|
import { notebookEditTool } from './notebook/notebookEdit.js';
|
|
53
47
|
import { powerShellTool } from './powershell/powershell.js';
|
|
48
|
+
import { presentResultTool } from './presentresult/presentresult.js';
|
|
49
|
+
import { readTool } from './read/read.js';
|
|
50
|
+
import { skillTool } from './skill/skill.js';
|
|
51
|
+
import { snipTool } from './snip/snip.js';
|
|
52
|
+
import {
|
|
53
|
+
taskCreateTool,
|
|
54
|
+
taskGetTool,
|
|
55
|
+
taskListTool,
|
|
56
|
+
taskUpdateTool,
|
|
57
|
+
} from './tasks/taskManagement.js';
|
|
54
58
|
import { taskOutputTool } from './tasks/taskOutput.js';
|
|
55
59
|
import { taskStopTool } from './tasks/taskStop.js';
|
|
60
|
+
import { terminalCaptureTool } from './terminal/terminalCapture.js';
|
|
61
|
+
import { trashTool } from './trash/trash.js';
|
|
62
|
+
import { webbrowserTool } from './webbrowser/webbrowser.js';
|
|
63
|
+
import { webfetchTool } from './webfetch/webfetch.js';
|
|
64
|
+
import { webSearchTool } from './websearch/websearch.js';
|
|
65
|
+
import {
|
|
66
|
+
enterWorktreeTool,
|
|
67
|
+
exitWorktreeTool,
|
|
68
|
+
} from './worktree/sessionWorktree.js';
|
|
69
|
+
import { writeTool } from './write/write.js';
|
|
56
70
|
|
|
57
71
|
/** 所有内置工具(顺序 = 给 LLM 呈现的顺序,不影响代码执行,但会影响模型的优先级直觉) */
|
|
58
72
|
export const ALL_TOOLS: Tool[] = [
|
|
@@ -90,6 +104,17 @@ export const ALL_TOOLS: Tool[] = [
|
|
|
90
104
|
computerUseTool,
|
|
91
105
|
// 追加在末尾:主循环 tools schema 的原有前缀字节不动(提示词缓存友好)
|
|
92
106
|
agentTool,
|
|
107
|
+
// Product tools append at the end to preserve the existing schema prefix cache.
|
|
108
|
+
trashTool,
|
|
109
|
+
taskCreateTool,
|
|
110
|
+
taskGetTool,
|
|
111
|
+
taskUpdateTool,
|
|
112
|
+
taskListTool,
|
|
113
|
+
skillTool,
|
|
114
|
+
enterWorktreeTool,
|
|
115
|
+
exitWorktreeTool,
|
|
116
|
+
terminalCaptureTool,
|
|
117
|
+
snipTool,
|
|
93
118
|
];
|
|
94
119
|
|
|
95
120
|
assertCapabilityRegistry(ALL_TOOLS.map((tool) => tool.name));
|
|
@@ -103,7 +128,14 @@ export function getToolGateDetails(
|
|
|
103
128
|
name: string,
|
|
104
129
|
rawArguments: string,
|
|
105
130
|
context: ToolCallContext,
|
|
106
|
-
):
|
|
131
|
+
):
|
|
132
|
+
| Partial<
|
|
133
|
+
Pick<
|
|
134
|
+
import('../toolGate.js').ToolGateRequest,
|
|
135
|
+
'isReadOnly' | 'runContext' | 'action'
|
|
136
|
+
>
|
|
137
|
+
>
|
|
138
|
+
| undefined {
|
|
107
139
|
const tool = getToolByName(name);
|
|
108
140
|
if (!tool?.gateRequest) return undefined;
|
|
109
141
|
let parsed: unknown;
|
|
@@ -182,20 +214,15 @@ export async function executeTool(
|
|
|
182
214
|
.join('\n');
|
|
183
215
|
return {
|
|
184
216
|
ok: false,
|
|
185
|
-
error:
|
|
186
|
-
`工具 ${name} 参数校验失败,**请按下面逐条改正后重新调用**:\n${issues}\n\n`
|
|
187
|
-
+ '通用修法:\n'
|
|
188
|
-
+ ' · **只填你这次确实要用的字段**。可选字段不要用 ""、0、{} 之类的默认值占位 ——\n'
|
|
189
|
-
+ ' 留空不填即可;填了占位值反而会被当成"你要用它"而触发校验。\n'
|
|
190
|
-
+ ' · 枚举字段只能取列出的值;数值字段注意上下限。\n'
|
|
191
|
-
+ ' · 改完直接重发这次调用,不要因为这个错误就换一条完全不同的路子。',
|
|
217
|
+
error: `工具 ${name} 参数校验失败,**请按下面逐条改正后重新调用**:\n${issues}\n\n通用修法:\n · **只填你这次确实要用的字段**。可选字段不要用 ""、0、{} 之类的默认值占位 ——\n 留空不填即可;填了占位值反而会被当成"你要用它"而触发校验。\n · 枚举字段只能取列出的值;数值字段注意上下限。\n · 改完直接重发这次调用,不要因为这个错误就换一条完全不同的路子。`,
|
|
192
218
|
};
|
|
193
219
|
}
|
|
194
220
|
|
|
195
221
|
// 4. 调用 call(),捕获意外异常
|
|
196
222
|
//
|
|
197
223
|
try {
|
|
198
|
-
if (tool.callWithContext)
|
|
224
|
+
if (tool.callWithContext)
|
|
225
|
+
return await tool.callWithContext(checked.data, signal, ctx ?? {});
|
|
199
226
|
return await tool.call(checked.data, signal);
|
|
200
227
|
} catch (e) {
|
|
201
228
|
return {
|
|
@@ -206,7 +233,21 @@ export async function executeTool(
|
|
|
206
233
|
}
|
|
207
234
|
|
|
208
235
|
// 导出每个工具,方便测试单独 import
|
|
209
|
-
export {
|
|
236
|
+
export {
|
|
237
|
+
readTool,
|
|
238
|
+
editTool,
|
|
239
|
+
writeTool,
|
|
240
|
+
globTool,
|
|
241
|
+
grepTool,
|
|
242
|
+
webSearchTool,
|
|
243
|
+
webfetchTool,
|
|
244
|
+
webbrowserTool,
|
|
245
|
+
computerUseTool,
|
|
246
|
+
downloadTool,
|
|
247
|
+
presentResultTool,
|
|
248
|
+
bashTool,
|
|
249
|
+
askUserQuestionTool,
|
|
250
|
+
};
|
|
210
251
|
export {
|
|
211
252
|
clearPersonaTool,
|
|
212
253
|
confirmMemoryTool,
|
|
@@ -223,10 +264,30 @@ export { multiEditTool } from './edit/multi-edit.js';
|
|
|
223
264
|
export { genImageTool } from './genimage/genimage.js';
|
|
224
265
|
export { advisorTool } from './advisor/advisor.js';
|
|
225
266
|
export { agentTool } from './agent/agent.js';
|
|
226
|
-
export {
|
|
267
|
+
export {
|
|
268
|
+
createGenerateSpeechTool,
|
|
269
|
+
generateSpeechTool,
|
|
270
|
+
} from './genspeech/genspeech.js';
|
|
227
271
|
export { createWebSearchTool } from './websearch/websearch.js';
|
|
228
272
|
export { lspTool } from './lsp/lsp.js';
|
|
229
273
|
export { notebookEditTool } from './notebook/notebookEdit.js';
|
|
230
274
|
export { powerShellTool } from './powershell/powershell.js';
|
|
231
275
|
export { taskOutputTool } from './tasks/taskOutput.js';
|
|
232
276
|
export { taskStopTool } from './tasks/taskStop.js';
|
|
277
|
+
export {
|
|
278
|
+
taskCreateTool,
|
|
279
|
+
taskGetTool,
|
|
280
|
+
taskUpdateTool,
|
|
281
|
+
taskListTool,
|
|
282
|
+
} from './tasks/taskManagement.js';
|
|
283
|
+
export { trashTool } from './trash/trash.js';
|
|
284
|
+
export { skillTool } from './skill/skill.js';
|
|
285
|
+
export { snipTool } from './snip/snip.js';
|
|
286
|
+
export {
|
|
287
|
+
enterWorktreeTool,
|
|
288
|
+
exitWorktreeTool,
|
|
289
|
+
} from './worktree/sessionWorktree.js';
|
|
290
|
+
export {
|
|
291
|
+
terminalCaptureTool,
|
|
292
|
+
installTerminalCapture,
|
|
293
|
+
} from './terminal/terminalCapture.js';
|
package/src/tools/lsp/lsp.js
CHANGED
|
@@ -1,29 +1,71 @@
|
|
|
1
1
|
import { stat } from 'node:fs/promises';
|
|
2
2
|
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
import { getWorkingDir } from '../../bootstrap/workingDir.js';
|
|
6
7
|
import { toToolParameters } from '../../utils/zodToJson.js';
|
|
7
8
|
import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
|
|
8
9
|
import { discoverLspServers, lspAvailabilitySignature } from './config.js';
|
|
9
10
|
import { getLspManager } from './service.js';
|
|
10
|
-
const positionOperations = new Set([
|
|
11
|
-
|
|
11
|
+
const positionOperations = new Set([
|
|
12
|
+
'goToDefinition',
|
|
13
|
+
'findReferences',
|
|
14
|
+
'hover',
|
|
15
|
+
'goToImplementation',
|
|
16
|
+
'incomingCalls',
|
|
17
|
+
'outgoingCalls',
|
|
18
|
+
]);
|
|
19
|
+
const inputSchema = z
|
|
20
|
+
.object({
|
|
12
21
|
operation: z.enum([
|
|
13
|
-
'goToDefinition',
|
|
14
|
-
'
|
|
22
|
+
'goToDefinition',
|
|
23
|
+
'findReferences',
|
|
24
|
+
'hover',
|
|
25
|
+
'documentSymbols',
|
|
26
|
+
'workspaceSymbols',
|
|
27
|
+
'goToImplementation',
|
|
28
|
+
'incomingCalls',
|
|
29
|
+
'outgoingCalls',
|
|
30
|
+
'diagnostics',
|
|
15
31
|
]),
|
|
16
32
|
file_path: z.string().min(1),
|
|
17
|
-
line: z
|
|
18
|
-
|
|
33
|
+
line: z
|
|
34
|
+
.number()
|
|
35
|
+
.int()
|
|
36
|
+
.positive()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe('1-based source line for position operations'),
|
|
39
|
+
character: z
|
|
40
|
+
.number()
|
|
41
|
+
.int()
|
|
42
|
+
.positive()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe('1-based UTF-16 character for position operations'),
|
|
19
45
|
query: z.string().optional().describe('Symbol query for workspaceSymbols'),
|
|
20
|
-
limit: z
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
46
|
+
limit: z
|
|
47
|
+
.number()
|
|
48
|
+
.int()
|
|
49
|
+
.min(1)
|
|
50
|
+
.max(500)
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Maximum formatted results, default 200'),
|
|
53
|
+
output_format: z.enum(['compact', 'json']).default('compact').optional(),
|
|
54
|
+
})
|
|
55
|
+
.superRefine((input, context) => {
|
|
56
|
+
if (positionOperations.has(input.operation) &&
|
|
57
|
+
(!input.line || !input.character)) {
|
|
58
|
+
context.addIssue({
|
|
59
|
+
code: z.ZodIssueCode.custom,
|
|
60
|
+
message: `${input.operation} requires line and character`,
|
|
61
|
+
});
|
|
24
62
|
}
|
|
25
63
|
if (input.operation === 'workspaceSymbols' && !input.query?.trim()) {
|
|
26
|
-
context.addIssue({
|
|
64
|
+
context.addIssue({
|
|
65
|
+
code: z.ZodIssueCode.custom,
|
|
66
|
+
path: ['query'],
|
|
67
|
+
message: 'workspaceSymbols requires a non-empty query',
|
|
68
|
+
});
|
|
27
69
|
}
|
|
28
70
|
});
|
|
29
71
|
function compact(value, limit) {
|
|
@@ -35,6 +77,74 @@ function compact(value, limit) {
|
|
|
35
77
|
? `${text.slice(0, DEFAULT_MAX_RESULT_SIZE_CHARS)}\n... (LSP result truncated)`
|
|
36
78
|
: text;
|
|
37
79
|
}
|
|
80
|
+
function compactSemantic(value, cwd, limit) {
|
|
81
|
+
if (value == null)
|
|
82
|
+
return 'No results.';
|
|
83
|
+
const rows = [];
|
|
84
|
+
const walk = (item, label) => {
|
|
85
|
+
if (item == null)
|
|
86
|
+
return;
|
|
87
|
+
if (Array.isArray(item)) {
|
|
88
|
+
item.forEach((v) => walk(v, label));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (typeof item !== 'object') {
|
|
92
|
+
rows.push(String(item));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const location = item.location ?? item.fromRanges?.[0] ?? item;
|
|
96
|
+
const uri = location.uri ?? location.targetUri ?? item.uri;
|
|
97
|
+
const range = location.range ??
|
|
98
|
+
location.targetSelectionRange ??
|
|
99
|
+
item.range ??
|
|
100
|
+
item.selectionRange;
|
|
101
|
+
let where = '';
|
|
102
|
+
if (typeof uri === 'string') {
|
|
103
|
+
let path = uri;
|
|
104
|
+
try {
|
|
105
|
+
path = uri.startsWith('file:') ? fileURLToPath(uri) : uri;
|
|
106
|
+
}
|
|
107
|
+
catch { }
|
|
108
|
+
const rel = relative(resolve(cwd), path);
|
|
109
|
+
where = (rel && !rel.startsWith('..') ? rel : path).split(sep).join('/');
|
|
110
|
+
}
|
|
111
|
+
if (range?.start)
|
|
112
|
+
where += `:${Number(range.start.line) + 1}:${Number(range.start.character) + 1}`;
|
|
113
|
+
const message = item.message ?? item.name ?? item.detail ?? item.kind ?? label;
|
|
114
|
+
const severity = item.severity
|
|
115
|
+
? `[${['', 'error', 'warning', 'info', 'hint'][item.severity] ?? item.severity}] `
|
|
116
|
+
: '';
|
|
117
|
+
const code = item.code !== undefined ? `(${String(item.code)}) ` : '';
|
|
118
|
+
if (where || message)
|
|
119
|
+
rows.push(`${severity}${where || '<symbol>'} — ${code}${typeof message === 'string' ? message : JSON.stringify(message)}`);
|
|
120
|
+
if (item.contents) {
|
|
121
|
+
const contents = Array.isArray(item.contents)
|
|
122
|
+
? item.contents
|
|
123
|
+
: [item.contents];
|
|
124
|
+
for (const c of contents)
|
|
125
|
+
rows.push(typeof c === 'string'
|
|
126
|
+
? c
|
|
127
|
+
: typeof c?.value === 'string'
|
|
128
|
+
? c.value
|
|
129
|
+
: JSON.stringify(c));
|
|
130
|
+
}
|
|
131
|
+
if (item.from)
|
|
132
|
+
walk(item.from, 'caller');
|
|
133
|
+
if (item.to)
|
|
134
|
+
walk(item.to, 'callee');
|
|
135
|
+
if (Array.isArray(item.children))
|
|
136
|
+
item.children.forEach((v) => walk(v));
|
|
137
|
+
};
|
|
138
|
+
walk(value);
|
|
139
|
+
const unique = [...new Set(rows)].sort();
|
|
140
|
+
const selected = unique.slice(0, limit);
|
|
141
|
+
let text = selected.join('\n') || 'No results.';
|
|
142
|
+
if (unique.length > selected.length)
|
|
143
|
+
text += `\n... (${unique.length - selected.length} more; total=${unique.length})`;
|
|
144
|
+
return text.length > DEFAULT_MAX_RESULT_SIZE_CHARS
|
|
145
|
+
? `${text.slice(0, DEFAULT_MAX_RESULT_SIZE_CHARS)}\n... (LSP result truncated)`
|
|
146
|
+
: text;
|
|
147
|
+
}
|
|
38
148
|
async function call(input, cwd = getWorkingDir()) {
|
|
39
149
|
const filePath = resolve(cwd, input.file_path);
|
|
40
150
|
const rel = relative(resolve(cwd), filePath);
|
|
@@ -52,32 +162,54 @@ async function call(input, cwd = getWorkingDir()) {
|
|
|
52
162
|
try {
|
|
53
163
|
await server.openFile(filePath);
|
|
54
164
|
const uri = pathToFileURL(filePath).href;
|
|
55
|
-
const position = {
|
|
165
|
+
const position = {
|
|
166
|
+
line: (input.line ?? 1) - 1,
|
|
167
|
+
character: (input.character ?? 1) - 1,
|
|
168
|
+
};
|
|
56
169
|
let result;
|
|
57
170
|
switch (input.operation) {
|
|
58
171
|
case 'goToDefinition':
|
|
59
|
-
result = await server.request('textDocument/definition', {
|
|
172
|
+
result = await server.request('textDocument/definition', {
|
|
173
|
+
textDocument: { uri },
|
|
174
|
+
position,
|
|
175
|
+
});
|
|
60
176
|
break;
|
|
61
177
|
case 'findReferences':
|
|
62
|
-
result = await server.request('textDocument/references', {
|
|
178
|
+
result = await server.request('textDocument/references', {
|
|
179
|
+
textDocument: { uri },
|
|
180
|
+
position,
|
|
181
|
+
context: { includeDeclaration: true },
|
|
182
|
+
});
|
|
63
183
|
break;
|
|
64
184
|
case 'hover':
|
|
65
|
-
result = await server.request('textDocument/hover', {
|
|
185
|
+
result = await server.request('textDocument/hover', {
|
|
186
|
+
textDocument: { uri },
|
|
187
|
+
position,
|
|
188
|
+
});
|
|
66
189
|
break;
|
|
67
190
|
case 'documentSymbols':
|
|
68
|
-
result = await server.request('textDocument/documentSymbol', {
|
|
191
|
+
result = await server.request('textDocument/documentSymbol', {
|
|
192
|
+
textDocument: { uri },
|
|
193
|
+
});
|
|
69
194
|
break;
|
|
70
195
|
case 'workspaceSymbols':
|
|
71
|
-
result = await server.request('workspace/symbol', {
|
|
196
|
+
result = await server.request('workspace/symbol', {
|
|
197
|
+
query: input.query,
|
|
198
|
+
});
|
|
72
199
|
break;
|
|
73
200
|
case 'goToImplementation':
|
|
74
|
-
result = await server.request('textDocument/implementation', {
|
|
201
|
+
result = await server.request('textDocument/implementation', {
|
|
202
|
+
textDocument: { uri },
|
|
203
|
+
position,
|
|
204
|
+
});
|
|
75
205
|
break;
|
|
76
206
|
case 'incomingCalls':
|
|
77
207
|
case 'outgoingCalls': {
|
|
78
208
|
const prepared = await server.request('textDocument/prepareCallHierarchy', { textDocument: { uri }, position });
|
|
79
209
|
const item = prepared?.[0];
|
|
80
|
-
result = item
|
|
210
|
+
result = item
|
|
211
|
+
? await server.request(`callHierarchy/${input.operation}`, { item })
|
|
212
|
+
: [];
|
|
81
213
|
break;
|
|
82
214
|
}
|
|
83
215
|
case 'diagnostics': {
|
|
@@ -87,10 +219,18 @@ async function call(input, cwd = getWorkingDir()) {
|
|
|
87
219
|
break;
|
|
88
220
|
}
|
|
89
221
|
}
|
|
90
|
-
return {
|
|
222
|
+
return {
|
|
223
|
+
ok: true,
|
|
224
|
+
content: input.output_format === 'json'
|
|
225
|
+
? compact(result, input.limit ?? 200)
|
|
226
|
+
: compactSemantic(result, cwd, input.limit ?? 200),
|
|
227
|
+
};
|
|
91
228
|
}
|
|
92
229
|
catch (error) {
|
|
93
|
-
return {
|
|
230
|
+
return {
|
|
231
|
+
ok: false,
|
|
232
|
+
error: `LSP ${input.operation} failed: ${error.message}`,
|
|
233
|
+
};
|
|
94
234
|
}
|
|
95
235
|
}
|
|
96
236
|
export const lspTool = {
|
|
@@ -106,7 +246,10 @@ export const lspTool = {
|
|
|
106
246
|
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
107
247
|
resolveAvailability(runtime) {
|
|
108
248
|
const servers = discoverLspServers(runtime.cwd);
|
|
109
|
-
return {
|
|
249
|
+
return {
|
|
250
|
+
available: servers.length > 0,
|
|
251
|
+
signature: lspAvailabilitySignature(runtime.cwd, servers),
|
|
252
|
+
};
|
|
110
253
|
},
|
|
111
254
|
call: (input) => call(input),
|
|
112
255
|
callWithContext: (input, _signal, context) => call(input, context.cwd),
|