bingocode 1.1.200-beta.13 → 1.1.200-beta.14
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 +1 -1
- package/src/constants/prompts.ts +9 -1
- package/src/hooks/useMergedTools.ts +3 -1
- package/src/main.tsx +2 -1
- package/src/screens/REPL.tsx +3 -2
- package/src/tools.ts +403 -390
package/package.json
CHANGED
package/src/constants/prompts.ts
CHANGED
|
@@ -976,6 +976,14 @@ Each agent prompt must include:
|
|
|
976
976
|
|
|
977
977
|
Report compressed: decisions made, blockers hit, next steps. Never narrate what
|
|
978
978
|
agents are doing moment-by-moment. "Agent A found X, agent B confirmed Y. Decision:
|
|
979
|
-
rollback needed." is enough
|
|
979
|
+
rollback needed." is enough.
|
|
980
|
+
|
|
981
|
+
## Sub-agent Capabilities
|
|
982
|
+
|
|
983
|
+
Sub-agents have full access to: Bash (shell execution), Read (file reading),
|
|
984
|
+
Write (file creation), Edit (precise string replacement), Grep (regex search),
|
|
985
|
+
Glob (file pattern matching), WebFetch (URL content), WebSearch (web search),
|
|
986
|
+
NotebookEdit (Jupyter editing), plus task management tools and any configured
|
|
987
|
+
MCP servers.`
|
|
980
988
|
}
|
|
981
989
|
|
|
@@ -22,12 +22,13 @@ export function useMergedTools(
|
|
|
22
22
|
mcpTools: Tools,
|
|
23
23
|
toolPermissionContext: ToolPermissionContext,
|
|
24
24
|
): Tools {
|
|
25
|
+
const brainMode = useAppState(s => s.brainMode ?? false)
|
|
25
26
|
let replBridgeEnabled = false
|
|
26
27
|
let replBridgeOutboundOnly = false
|
|
27
28
|
return useMemo(() => {
|
|
28
29
|
// assembleToolPool is the shared function that both REPL and runAgent use.
|
|
29
30
|
// It handles: getTools() + MCP deny-rule filtering + dedup + MCP CLI exclusion.
|
|
30
|
-
const assembled = assembleToolPool(toolPermissionContext, mcpTools)
|
|
31
|
+
const assembled = assembleToolPool(toolPermissionContext, mcpTools, brainMode)
|
|
31
32
|
|
|
32
33
|
return mergeAndFilterTools(
|
|
33
34
|
initialTools,
|
|
@@ -38,6 +39,7 @@ export function useMergedTools(
|
|
|
38
39
|
initialTools,
|
|
39
40
|
mcpTools,
|
|
40
41
|
toolPermissionContext,
|
|
42
|
+
brainMode,
|
|
41
43
|
replBridgeEnabled,
|
|
42
44
|
replBridgeOutboundOnly,
|
|
43
45
|
])
|
package/src/main.tsx
CHANGED
|
@@ -1865,7 +1865,8 @@ async function run(): Promise<CommanderCommand> {
|
|
|
1865
1865
|
// (which returns isProactiveActive()) passes and Sleep is included.
|
|
1866
1866
|
// The later REPL-path maybeActivateProactive() calls are idempotent.
|
|
1867
1867
|
maybeActivateProactive(options);
|
|
1868
|
-
|
|
1868
|
+
const brainMode = getInitialSettings().brainMode === true || getCurrentSessionBrainMode() === true
|
|
1869
|
+
let tools = getTools(toolPermissionContext, brainMode);
|
|
1869
1870
|
|
|
1870
1871
|
// Apply coordinator mode tool filtering for headless path
|
|
1871
1872
|
// (mirrors useMergedTools.ts filtering for REPL/interactive path)
|
package/src/screens/REPL.tsx
CHANGED
|
@@ -695,7 +695,8 @@ export function REPL({
|
|
|
695
695
|
// /brief mid-session leaves the stale tool list (no SendUserMessage) and
|
|
696
696
|
// the model emits plain text the brief filter hides.
|
|
697
697
|
const isBriefOnly = useAppState(s => s.isBriefOnly);
|
|
698
|
-
const
|
|
698
|
+
const isBrainMode = useAppState(s => s.brainMode ?? false);
|
|
699
|
+
const localTools = useMemo(() => getTools(toolPermissionContext, isBrainMode), [toolPermissionContext, proactiveActive, isBriefOnly, isBrainMode]);
|
|
699
700
|
useKickOffCheckAndDisableBypassPermissionsIfNeeded();
|
|
700
701
|
useKickOffCheckAndDisableAutoModeIfNeeded();
|
|
701
702
|
const [dynamicMcpConfig, setDynamicMcpConfig] = useState<Record<string, ScopedMcpServerConfig> | undefined>(initialDynamicMcpConfig);
|
|
@@ -2404,7 +2405,7 @@ export function REPL({
|
|
|
2404
2405
|
// for mid-query tool list updates.
|
|
2405
2406
|
const computeTools = () => {
|
|
2406
2407
|
const state = store.getState();
|
|
2407
|
-
const assembled = assembleToolPool(state.toolPermissionContext, state.mcp.tools);
|
|
2408
|
+
const assembled = assembleToolPool(state.toolPermissionContext, state.mcp.tools, state.brainMode);
|
|
2408
2409
|
const merged = mergeAndFilterTools(combinedInitialTools, assembled, state.toolPermissionContext.mode);
|
|
2409
2410
|
if (!mainThreadAgentDefinition) return merged;
|
|
2410
2411
|
return resolveAgentTools(mainThreadAgentDefinition, merged, false, true).resolvedTools;
|
package/src/tools.ts
CHANGED
|
@@ -1,390 +1,403 @@
|
|
|
1
|
-
// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered
|
|
2
|
-
import { toolMatchesName, type Tool, type Tools } from './Tool.js'
|
|
3
|
-
import { AgentTool } from './tools/AgentTool/AgentTool.js'
|
|
4
|
-
import { SkillTool } from './tools/SkillTool/SkillTool.js'
|
|
5
|
-
import { BashTool } from './tools/BashTool/BashTool.js'
|
|
6
|
-
import { FileEditTool } from './tools/FileEditTool/FileEditTool.js'
|
|
7
|
-
import { FileReadTool } from './tools/FileReadTool/FileReadTool.js'
|
|
8
|
-
import { FileWriteTool } from './tools/FileWriteTool/FileWriteTool.js'
|
|
9
|
-
import { GlobTool } from './tools/GlobTool/GlobTool.js'
|
|
10
|
-
import { NotebookEditTool } from './tools/NotebookEditTool/NotebookEditTool.js'
|
|
11
|
-
import { WebFetchTool } from './tools/WebFetchTool/WebFetchTool.js'
|
|
12
|
-
import { TaskStopTool } from './tools/TaskStopTool/TaskStopTool.js'
|
|
13
|
-
import { BriefTool } from './tools/BriefTool/BriefTool.js'
|
|
14
|
-
// Dead code elimination: conditional import for ant-only tools
|
|
15
|
-
/* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
16
|
-
const REPLTool =
|
|
17
|
-
process.env.USER_TYPE === 'ant'
|
|
18
|
-
? require('./tools/REPLTool/REPLTool.js').REPLTool
|
|
19
|
-
: null
|
|
20
|
-
const SuggestBackgroundPRTool =
|
|
21
|
-
process.env.USER_TYPE === 'ant'
|
|
22
|
-
? require('./tools/SuggestBackgroundPRTool/SuggestBackgroundPRTool.js')
|
|
23
|
-
.SuggestBackgroundPRTool
|
|
24
|
-
: null
|
|
25
|
-
const SleepTool =
|
|
26
|
-
feature('PROACTIVE') || feature('KAIROS')
|
|
27
|
-
? require('./tools/SleepTool/SleepTool.js').SleepTool
|
|
28
|
-
: null
|
|
29
|
-
const cronTools = feature('AGENT_TRIGGERS')
|
|
30
|
-
? [
|
|
31
|
-
require('./tools/ScheduleCronTool/CronCreateTool.js').CronCreateTool,
|
|
32
|
-
require('./tools/ScheduleCronTool/CronUpdateTool.js').CronUpdateTool,
|
|
33
|
-
require('./tools/ScheduleCronTool/CronDeleteTool.js').CronDeleteTool,
|
|
34
|
-
require('./tools/ScheduleCronTool/CronListTool.js').CronListTool,
|
|
35
|
-
]
|
|
36
|
-
: []
|
|
37
|
-
const RemoteTriggerTool = feature('AGENT_TRIGGERS_REMOTE')
|
|
38
|
-
? require('./tools/RemoteTriggerTool/RemoteTriggerTool.js').RemoteTriggerTool
|
|
39
|
-
: null
|
|
40
|
-
const MonitorTool = feature('MONITOR_TOOL')
|
|
41
|
-
? require('./tools/MonitorTool/MonitorTool.js').MonitorTool
|
|
42
|
-
: null
|
|
43
|
-
const SendUserFileTool = feature('KAIROS')
|
|
44
|
-
? require('./tools/SendUserFileTool/SendUserFileTool.js').SendUserFileTool
|
|
45
|
-
: null
|
|
46
|
-
const PushNotificationTool =
|
|
47
|
-
feature('KAIROS') || feature('KAIROS_PUSH_NOTIFICATION')
|
|
48
|
-
? require('./tools/PushNotificationTool/PushNotificationTool.js')
|
|
49
|
-
.PushNotificationTool
|
|
50
|
-
: null
|
|
51
|
-
const SubscribePRTool = feature('KAIROS_GITHUB_WEBHOOKS')
|
|
52
|
-
? require('./tools/SubscribePRTool/SubscribePRTool.js').SubscribePRTool
|
|
53
|
-
: null
|
|
54
|
-
/* eslint-enable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
55
|
-
import { TaskOutputTool } from './tools/TaskOutputTool/TaskOutputTool.js'
|
|
56
|
-
import { WebSearchTool } from './tools/WebSearchTool/WebSearchTool.js'
|
|
57
|
-
import { TodoWriteTool } from './tools/TodoWriteTool/TodoWriteTool.js'
|
|
58
|
-
import { ExitPlanModeV2Tool } from './tools/ExitPlanModeTool/ExitPlanModeV2Tool.js'
|
|
59
|
-
import { TestingPermissionTool } from './tools/testing/TestingPermissionTool.js'
|
|
60
|
-
import { GrepTool } from './tools/GrepTool/GrepTool.js'
|
|
61
|
-
import { TungstenTool } from './tools/TungstenTool/TungstenTool.js'
|
|
62
|
-
// Lazy require to break circular dependency: tools.ts -> TeamCreateTool/TeamDeleteTool -> ... -> tools.ts
|
|
63
|
-
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
64
|
-
const getTeamCreateTool = () =>
|
|
65
|
-
require('./tools/TeamCreateTool/TeamCreateTool.js')
|
|
66
|
-
.TeamCreateTool as typeof import('./tools/TeamCreateTool/TeamCreateTool.js').TeamCreateTool
|
|
67
|
-
const getTeamDeleteTool = () =>
|
|
68
|
-
require('./tools/TeamDeleteTool/TeamDeleteTool.js')
|
|
69
|
-
.TeamDeleteTool as typeof import('./tools/TeamDeleteTool/TeamDeleteTool.js').TeamDeleteTool
|
|
70
|
-
const getSendMessageTool = () =>
|
|
71
|
-
require('./tools/SendMessageTool/SendMessageTool.js')
|
|
72
|
-
.SendMessageTool as typeof import('./tools/SendMessageTool/SendMessageTool.js').SendMessageTool
|
|
73
|
-
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
74
|
-
import { AskUserQuestionTool } from './tools/AskUserQuestionTool/AskUserQuestionTool.js'
|
|
75
|
-
import { LSPTool } from './tools/LSPTool/LSPTool.js'
|
|
76
|
-
import { ListMcpResourcesTool } from './tools/ListMcpResourcesTool/ListMcpResourcesTool.js'
|
|
77
|
-
import { ReadMcpResourceTool } from './tools/ReadMcpResourceTool/ReadMcpResourceTool.js'
|
|
78
|
-
import { ToolSearchTool } from './tools/ToolSearchTool/ToolSearchTool.js'
|
|
79
|
-
import { EnterPlanModeTool } from './tools/EnterPlanModeTool/EnterPlanModeTool.js'
|
|
80
|
-
import { EnterWorktreeTool } from './tools/EnterWorktreeTool/EnterWorktreeTool.js'
|
|
81
|
-
import { ExitWorktreeTool } from './tools/ExitWorktreeTool/ExitWorktreeTool.js'
|
|
82
|
-
import { ConfigTool } from './tools/ConfigTool/ConfigTool.js'
|
|
83
|
-
import { TaskCreateTool } from './tools/TaskCreateTool/TaskCreateTool.js'
|
|
84
|
-
import { TaskGetTool } from './tools/TaskGetTool/TaskGetTool.js'
|
|
85
|
-
import { TaskUpdateTool } from './tools/TaskUpdateTool/TaskUpdateTool.js'
|
|
86
|
-
import { TaskListTool } from './tools/TaskListTool/TaskListTool.js'
|
|
87
|
-
import uniqBy from 'lodash-es/uniqBy.js'
|
|
88
|
-
import { isToolSearchEnabledOptimistic } from './utils/toolSearch.js'
|
|
89
|
-
import { isTodoV2Enabled } from './utils/tasks.js'
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
import {
|
|
140
|
-
import {
|
|
141
|
-
import {
|
|
142
|
-
import {
|
|
143
|
-
import {
|
|
144
|
-
import {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
export
|
|
165
|
-
|
|
166
|
-
export
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
*
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
...(
|
|
218
|
-
...(
|
|
219
|
-
...(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
...(
|
|
225
|
-
...(
|
|
226
|
-
...(
|
|
227
|
-
|
|
228
|
-
...(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
...(
|
|
235
|
-
...(
|
|
236
|
-
...
|
|
237
|
-
...(
|
|
238
|
-
...
|
|
239
|
-
|
|
240
|
-
...(
|
|
241
|
-
|
|
242
|
-
...(
|
|
243
|
-
...(
|
|
244
|
-
...(
|
|
245
|
-
...(
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
1
|
+
// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered
|
|
2
|
+
import { toolMatchesName, type Tool, type Tools } from './Tool.js'
|
|
3
|
+
import { AgentTool } from './tools/AgentTool/AgentTool.js'
|
|
4
|
+
import { SkillTool } from './tools/SkillTool/SkillTool.js'
|
|
5
|
+
import { BashTool } from './tools/BashTool/BashTool.js'
|
|
6
|
+
import { FileEditTool } from './tools/FileEditTool/FileEditTool.js'
|
|
7
|
+
import { FileReadTool } from './tools/FileReadTool/FileReadTool.js'
|
|
8
|
+
import { FileWriteTool } from './tools/FileWriteTool/FileWriteTool.js'
|
|
9
|
+
import { GlobTool } from './tools/GlobTool/GlobTool.js'
|
|
10
|
+
import { NotebookEditTool } from './tools/NotebookEditTool/NotebookEditTool.js'
|
|
11
|
+
import { WebFetchTool } from './tools/WebFetchTool/WebFetchTool.js'
|
|
12
|
+
import { TaskStopTool } from './tools/TaskStopTool/TaskStopTool.js'
|
|
13
|
+
import { BriefTool } from './tools/BriefTool/BriefTool.js'
|
|
14
|
+
// Dead code elimination: conditional import for ant-only tools
|
|
15
|
+
/* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
16
|
+
const REPLTool =
|
|
17
|
+
process.env.USER_TYPE === 'ant'
|
|
18
|
+
? require('./tools/REPLTool/REPLTool.js').REPLTool
|
|
19
|
+
: null
|
|
20
|
+
const SuggestBackgroundPRTool =
|
|
21
|
+
process.env.USER_TYPE === 'ant'
|
|
22
|
+
? require('./tools/SuggestBackgroundPRTool/SuggestBackgroundPRTool.js')
|
|
23
|
+
.SuggestBackgroundPRTool
|
|
24
|
+
: null
|
|
25
|
+
const SleepTool =
|
|
26
|
+
feature('PROACTIVE') || feature('KAIROS')
|
|
27
|
+
? require('./tools/SleepTool/SleepTool.js').SleepTool
|
|
28
|
+
: null
|
|
29
|
+
const cronTools = feature('AGENT_TRIGGERS')
|
|
30
|
+
? [
|
|
31
|
+
require('./tools/ScheduleCronTool/CronCreateTool.js').CronCreateTool,
|
|
32
|
+
require('./tools/ScheduleCronTool/CronUpdateTool.js').CronUpdateTool,
|
|
33
|
+
require('./tools/ScheduleCronTool/CronDeleteTool.js').CronDeleteTool,
|
|
34
|
+
require('./tools/ScheduleCronTool/CronListTool.js').CronListTool,
|
|
35
|
+
]
|
|
36
|
+
: []
|
|
37
|
+
const RemoteTriggerTool = feature('AGENT_TRIGGERS_REMOTE')
|
|
38
|
+
? require('./tools/RemoteTriggerTool/RemoteTriggerTool.js').RemoteTriggerTool
|
|
39
|
+
: null
|
|
40
|
+
const MonitorTool = feature('MONITOR_TOOL')
|
|
41
|
+
? require('./tools/MonitorTool/MonitorTool.js').MonitorTool
|
|
42
|
+
: null
|
|
43
|
+
const SendUserFileTool = feature('KAIROS')
|
|
44
|
+
? require('./tools/SendUserFileTool/SendUserFileTool.js').SendUserFileTool
|
|
45
|
+
: null
|
|
46
|
+
const PushNotificationTool =
|
|
47
|
+
feature('KAIROS') || feature('KAIROS_PUSH_NOTIFICATION')
|
|
48
|
+
? require('./tools/PushNotificationTool/PushNotificationTool.js')
|
|
49
|
+
.PushNotificationTool
|
|
50
|
+
: null
|
|
51
|
+
const SubscribePRTool = feature('KAIROS_GITHUB_WEBHOOKS')
|
|
52
|
+
? require('./tools/SubscribePRTool/SubscribePRTool.js').SubscribePRTool
|
|
53
|
+
: null
|
|
54
|
+
/* eslint-enable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
55
|
+
import { TaskOutputTool } from './tools/TaskOutputTool/TaskOutputTool.js'
|
|
56
|
+
import { WebSearchTool } from './tools/WebSearchTool/WebSearchTool.js'
|
|
57
|
+
import { TodoWriteTool } from './tools/TodoWriteTool/TodoWriteTool.js'
|
|
58
|
+
import { ExitPlanModeV2Tool } from './tools/ExitPlanModeTool/ExitPlanModeV2Tool.js'
|
|
59
|
+
import { TestingPermissionTool } from './tools/testing/TestingPermissionTool.js'
|
|
60
|
+
import { GrepTool } from './tools/GrepTool/GrepTool.js'
|
|
61
|
+
import { TungstenTool } from './tools/TungstenTool/TungstenTool.js'
|
|
62
|
+
// Lazy require to break circular dependency: tools.ts -> TeamCreateTool/TeamDeleteTool -> ... -> tools.ts
|
|
63
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
64
|
+
const getTeamCreateTool = () =>
|
|
65
|
+
require('./tools/TeamCreateTool/TeamCreateTool.js')
|
|
66
|
+
.TeamCreateTool as typeof import('./tools/TeamCreateTool/TeamCreateTool.js').TeamCreateTool
|
|
67
|
+
const getTeamDeleteTool = () =>
|
|
68
|
+
require('./tools/TeamDeleteTool/TeamDeleteTool.js')
|
|
69
|
+
.TeamDeleteTool as typeof import('./tools/TeamDeleteTool/TeamDeleteTool.js').TeamDeleteTool
|
|
70
|
+
const getSendMessageTool = () =>
|
|
71
|
+
require('./tools/SendMessageTool/SendMessageTool.js')
|
|
72
|
+
.SendMessageTool as typeof import('./tools/SendMessageTool/SendMessageTool.js').SendMessageTool
|
|
73
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
74
|
+
import { AskUserQuestionTool } from './tools/AskUserQuestionTool/AskUserQuestionTool.js'
|
|
75
|
+
import { LSPTool } from './tools/LSPTool/LSPTool.js'
|
|
76
|
+
import { ListMcpResourcesTool } from './tools/ListMcpResourcesTool/ListMcpResourcesTool.js'
|
|
77
|
+
import { ReadMcpResourceTool } from './tools/ReadMcpResourceTool/ReadMcpResourceTool.js'
|
|
78
|
+
import { ToolSearchTool } from './tools/ToolSearchTool/ToolSearchTool.js'
|
|
79
|
+
import { EnterPlanModeTool } from './tools/EnterPlanModeTool/EnterPlanModeTool.js'
|
|
80
|
+
import { EnterWorktreeTool } from './tools/EnterWorktreeTool/EnterWorktreeTool.js'
|
|
81
|
+
import { ExitWorktreeTool } from './tools/ExitWorktreeTool/ExitWorktreeTool.js'
|
|
82
|
+
import { ConfigTool } from './tools/ConfigTool/ConfigTool.js'
|
|
83
|
+
import { TaskCreateTool } from './tools/TaskCreateTool/TaskCreateTool.js'
|
|
84
|
+
import { TaskGetTool } from './tools/TaskGetTool/TaskGetTool.js'
|
|
85
|
+
import { TaskUpdateTool } from './tools/TaskUpdateTool/TaskUpdateTool.js'
|
|
86
|
+
import { TaskListTool } from './tools/TaskListTool/TaskListTool.js'
|
|
87
|
+
import uniqBy from 'lodash-es/uniqBy.js'
|
|
88
|
+
import { isToolSearchEnabledOptimistic } from './utils/toolSearch.js'
|
|
89
|
+
import { isTodoV2Enabled } from './utils/tasks.js'
|
|
90
|
+
import { getInitialSettings } from './utils/settings/settings.js'
|
|
91
|
+
import { getCurrentSessionBrainMode } from './utils/sessionStorage.js'
|
|
92
|
+
// Dead code elimination: conditional import for CLAUDE_CODE_VERIFY_PLAN
|
|
93
|
+
/* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
94
|
+
const VerifyPlanExecutionTool =
|
|
95
|
+
process.env.CLAUDE_CODE_VERIFY_PLAN === 'true'
|
|
96
|
+
? require('./tools/VerifyPlanExecutionTool/VerifyPlanExecutionTool.js')
|
|
97
|
+
.VerifyPlanExecutionTool
|
|
98
|
+
: null
|
|
99
|
+
/* eslint-enable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
100
|
+
import { SYNTHETIC_OUTPUT_TOOL_NAME } from './tools/SyntheticOutputTool/SyntheticOutputTool.js'
|
|
101
|
+
export {
|
|
102
|
+
ALL_AGENT_DISALLOWED_TOOLS,
|
|
103
|
+
CUSTOM_AGENT_DISALLOWED_TOOLS,
|
|
104
|
+
ASYNC_AGENT_ALLOWED_TOOLS,
|
|
105
|
+
COORDINATOR_MODE_ALLOWED_TOOLS,
|
|
106
|
+
} from './constants/tools.js'
|
|
107
|
+
import { feature } from 'bun:bundle'
|
|
108
|
+
// Dead code elimination: conditional import for OVERFLOW_TEST_TOOL
|
|
109
|
+
/* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
110
|
+
const OverflowTestTool = feature('OVERFLOW_TEST_TOOL')
|
|
111
|
+
? require('./tools/OverflowTestTool/OverflowTestTool.js').OverflowTestTool
|
|
112
|
+
: null
|
|
113
|
+
const CtxInspectTool = feature('CONTEXT_COLLAPSE')
|
|
114
|
+
? require('./tools/CtxInspectTool/CtxInspectTool.js').CtxInspectTool
|
|
115
|
+
: null
|
|
116
|
+
const TerminalCaptureTool = feature('TERMINAL_PANEL')
|
|
117
|
+
? require('./tools/TerminalCaptureTool/TerminalCaptureTool.js')
|
|
118
|
+
.TerminalCaptureTool
|
|
119
|
+
: null
|
|
120
|
+
const WebBrowserTool = feature('WEB_BROWSER_TOOL')
|
|
121
|
+
? require('./tools/WebBrowserTool/WebBrowserTool.js').WebBrowserTool
|
|
122
|
+
: null
|
|
123
|
+
const coordinatorModeModule = feature('COORDINATOR_MODE')
|
|
124
|
+
? (require('./coordinator/coordinatorMode.js') as typeof import('./coordinator/coordinatorMode.js'))
|
|
125
|
+
: null
|
|
126
|
+
const SnipTool = feature('HISTORY_SNIP')
|
|
127
|
+
? require('./tools/SnipTool/SnipTool.js').SnipTool
|
|
128
|
+
: null
|
|
129
|
+
const ListPeersTool = feature('UDS_INBOX')
|
|
130
|
+
? require('./tools/ListPeersTool/ListPeersTool.js').ListPeersTool
|
|
131
|
+
: null
|
|
132
|
+
const WorkflowTool = feature('WORKFLOW_SCRIPTS')
|
|
133
|
+
? (() => {
|
|
134
|
+
require('./tools/WorkflowTool/bundled/index.js').initBundledWorkflows()
|
|
135
|
+
return require('./tools/WorkflowTool/WorkflowTool.js').WorkflowTool
|
|
136
|
+
})()
|
|
137
|
+
: null
|
|
138
|
+
/* eslint-enable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
|
|
139
|
+
import type { ToolPermissionContext } from './Tool.js'
|
|
140
|
+
import { getDenyRuleForTool } from './utils/permissions/permissions.js'
|
|
141
|
+
import { hasEmbeddedSearchTools } from './utils/embeddedTools.js'
|
|
142
|
+
import { isEnvTruthy } from './utils/envUtils.js'
|
|
143
|
+
import { isPowerShellToolEnabled } from './utils/shell/shellToolUtils.js'
|
|
144
|
+
import { isAgentSwarmsEnabled } from './utils/agentSwarmsEnabled.js'
|
|
145
|
+
import { isWorktreeModeEnabled } from './utils/worktreeModeEnabled.js'
|
|
146
|
+
import {
|
|
147
|
+
REPL_TOOL_NAME,
|
|
148
|
+
REPL_ONLY_TOOLS,
|
|
149
|
+
isReplModeEnabled,
|
|
150
|
+
} from './tools/REPLTool/constants.js'
|
|
151
|
+
export { REPL_ONLY_TOOLS }
|
|
152
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
153
|
+
const getPowerShellTool = () => {
|
|
154
|
+
if (!isPowerShellToolEnabled()) return null
|
|
155
|
+
return (
|
|
156
|
+
require('./tools/PowerShellTool/PowerShellTool.js') as typeof import('./tools/PowerShellTool/PowerShellTool.js')
|
|
157
|
+
).PowerShellTool
|
|
158
|
+
}
|
|
159
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Predefined tool presets that can be used with --tools flag
|
|
163
|
+
*/
|
|
164
|
+
export const TOOL_PRESETS = ['default'] as const
|
|
165
|
+
|
|
166
|
+
export type ToolPreset = (typeof TOOL_PRESETS)[number]
|
|
167
|
+
|
|
168
|
+
export function parseToolPreset(preset: string): ToolPreset | null {
|
|
169
|
+
const presetString = preset.toLowerCase()
|
|
170
|
+
if (!TOOL_PRESETS.includes(presetString as ToolPreset)) {
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
return presetString as ToolPreset
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get the list of tool names for a given preset
|
|
178
|
+
* Filters out tools that are disabled via isEnabled() check
|
|
179
|
+
* @param preset The preset name
|
|
180
|
+
* @returns Array of tool names
|
|
181
|
+
*/
|
|
182
|
+
export function getToolsForDefaultPreset(): string[] {
|
|
183
|
+
const tools = getAllBaseTools()
|
|
184
|
+
const isEnabled = tools.map(tool => tool.isEnabled())
|
|
185
|
+
return tools.filter((_, i) => isEnabled[i]).map(tool => tool.name)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Get the complete exhaustive list of all tools that could be available
|
|
190
|
+
* in the current environment (respecting process.env flags).
|
|
191
|
+
* This is the source of truth for ALL tools.
|
|
192
|
+
*/
|
|
193
|
+
/**
|
|
194
|
+
* NOTE: This MUST stay in sync with https://console.statsig.com/4aF3Ewatb6xPVpCwxb5nA3/dynamic_configs/claude_code_global_system_caching, in order to cache the system prompt across users.
|
|
195
|
+
*/
|
|
196
|
+
export function getAllBaseTools(): Tools {
|
|
197
|
+
return [
|
|
198
|
+
AgentTool,
|
|
199
|
+
TaskOutputTool,
|
|
200
|
+
BashTool,
|
|
201
|
+
// Ant-native builds have bfs/ugrep embedded in the bun binary (same ARGV0
|
|
202
|
+
// trick as ripgrep). When available, find/grep in Claude's shell are aliased
|
|
203
|
+
// to these fast tools, so the dedicated Glob/Grep tools are unnecessary.
|
|
204
|
+
...(hasEmbeddedSearchTools() ? [] : [GlobTool, GrepTool]),
|
|
205
|
+
ExitPlanModeV2Tool,
|
|
206
|
+
FileReadTool,
|
|
207
|
+
FileEditTool,
|
|
208
|
+
FileWriteTool,
|
|
209
|
+
NotebookEditTool,
|
|
210
|
+
WebFetchTool,
|
|
211
|
+
TodoWriteTool,
|
|
212
|
+
WebSearchTool,
|
|
213
|
+
TaskStopTool,
|
|
214
|
+
AskUserQuestionTool,
|
|
215
|
+
SkillTool,
|
|
216
|
+
EnterPlanModeTool,
|
|
217
|
+
...(process.env.USER_TYPE === 'ant' ? [ConfigTool] : []),
|
|
218
|
+
...(process.env.USER_TYPE === 'ant' ? [TungstenTool] : []),
|
|
219
|
+
...(SuggestBackgroundPRTool ? [SuggestBackgroundPRTool] : []),
|
|
220
|
+
...(WebBrowserTool ? [WebBrowserTool] : []),
|
|
221
|
+
...(isTodoV2Enabled()
|
|
222
|
+
? [TaskCreateTool, TaskGetTool, TaskUpdateTool, TaskListTool]
|
|
223
|
+
: []),
|
|
224
|
+
...(OverflowTestTool ? [OverflowTestTool] : []),
|
|
225
|
+
...(CtxInspectTool ? [CtxInspectTool] : []),
|
|
226
|
+
...(TerminalCaptureTool ? [TerminalCaptureTool] : []),
|
|
227
|
+
...(isEnvTruthy(process.env.ENABLE_LSP_TOOL) ? [LSPTool] : []),
|
|
228
|
+
...(isWorktreeModeEnabled() ? [EnterWorktreeTool, ExitWorktreeTool] : []),
|
|
229
|
+
getSendMessageTool(),
|
|
230
|
+
...(ListPeersTool ? [ListPeersTool] : []),
|
|
231
|
+
...(isAgentSwarmsEnabled()
|
|
232
|
+
? [getTeamCreateTool(), getTeamDeleteTool()]
|
|
233
|
+
: []),
|
|
234
|
+
...(VerifyPlanExecutionTool ? [VerifyPlanExecutionTool] : []),
|
|
235
|
+
...(process.env.USER_TYPE === 'ant' && REPLTool ? [REPLTool] : []),
|
|
236
|
+
...(WorkflowTool ? [WorkflowTool] : []),
|
|
237
|
+
...(SleepTool ? [SleepTool] : []),
|
|
238
|
+
...cronTools,
|
|
239
|
+
...(RemoteTriggerTool ? [RemoteTriggerTool] : []),
|
|
240
|
+
...(MonitorTool ? [MonitorTool] : []),
|
|
241
|
+
BriefTool,
|
|
242
|
+
...(SendUserFileTool ? [SendUserFileTool] : []),
|
|
243
|
+
...(PushNotificationTool ? [PushNotificationTool] : []),
|
|
244
|
+
...(SubscribePRTool ? [SubscribePRTool] : []),
|
|
245
|
+
...(getPowerShellTool() ? [getPowerShellTool()] : []),
|
|
246
|
+
...(SnipTool ? [SnipTool] : []),
|
|
247
|
+
...(process.env.NODE_ENV === 'test' ? [TestingPermissionTool] : []),
|
|
248
|
+
ListMcpResourcesTool,
|
|
249
|
+
ReadMcpResourceTool,
|
|
250
|
+
// Include ToolSearchTool when tool search might be enabled (optimistic check)
|
|
251
|
+
// The actual decision to defer tools happens at request time in claude.ts
|
|
252
|
+
...(isToolSearchEnabledOptimistic() ? [ToolSearchTool] : []),
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Filters out tools that are blanket-denied by the permission context.
|
|
258
|
+
* A tool is filtered out if there's a deny rule matching its name with no
|
|
259
|
+
* ruleContent (i.e., a blanket deny for that tool).
|
|
260
|
+
*
|
|
261
|
+
* Uses the same matcher as the runtime permission check (step 1a), so MCP
|
|
262
|
+
* server-prefix rules like `mcp__server` strip all tools from that server
|
|
263
|
+
* before the model sees them — not just at call time.
|
|
264
|
+
*/
|
|
265
|
+
export function filterToolsByDenyRules<
|
|
266
|
+
T extends {
|
|
267
|
+
name: string
|
|
268
|
+
mcpInfo?: { serverName: string; toolName: string }
|
|
269
|
+
},
|
|
270
|
+
>(tools: readonly T[], permissionContext: ToolPermissionContext): T[] {
|
|
271
|
+
return tools.filter(tool => !getDenyRuleForTool(permissionContext, tool))
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function isBrainModeActive(): boolean {
|
|
275
|
+
return getInitialSettings().brainMode === true || getCurrentSessionBrainMode() === true
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export const getTools = (permissionContext: ToolPermissionContext, brainMode?: boolean): Tools => {
|
|
279
|
+
// Brain mode: coordinator only needs Agent + AskUserQuestion
|
|
280
|
+
if (brainMode ?? isBrainModeActive()) {
|
|
281
|
+
return filterToolsByDenyRules([AgentTool, AskUserQuestionTool], permissionContext)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Simple mode: only Bash, Read, and Edit tools
|
|
285
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)) {
|
|
286
|
+
// --bare + REPL mode: REPL wraps Bash/Read/Edit/etc inside the VM, so
|
|
287
|
+
// return REPL instead of the raw primitives. Matches the non-bare path
|
|
288
|
+
// below which also hides REPL_ONLY_TOOLS when REPL is enabled.
|
|
289
|
+
if (isReplModeEnabled() && REPLTool) {
|
|
290
|
+
const replSimple: Tool[] = [REPLTool]
|
|
291
|
+
if (
|
|
292
|
+
feature('COORDINATOR_MODE') &&
|
|
293
|
+
coordinatorModeModule?.isCoordinatorMode()
|
|
294
|
+
) {
|
|
295
|
+
replSimple.push(TaskStopTool, getSendMessageTool())
|
|
296
|
+
}
|
|
297
|
+
return filterToolsByDenyRules(replSimple, permissionContext)
|
|
298
|
+
}
|
|
299
|
+
const simpleTools: Tool[] = [BashTool, FileReadTool, FileEditTool]
|
|
300
|
+
// When coordinator mode is also active, include AgentTool and TaskStopTool
|
|
301
|
+
// so the coordinator gets Task+TaskStop (via useMergedTools filtering) and
|
|
302
|
+
// workers get Bash/Read/Edit (via filterToolsForAgent filtering).
|
|
303
|
+
if (
|
|
304
|
+
feature('COORDINATOR_MODE') &&
|
|
305
|
+
coordinatorModeModule?.isCoordinatorMode()
|
|
306
|
+
) {
|
|
307
|
+
simpleTools.push(AgentTool, TaskStopTool, getSendMessageTool())
|
|
308
|
+
}
|
|
309
|
+
return filterToolsByDenyRules(simpleTools, permissionContext)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Get all base tools and filter out special tools that get added conditionally
|
|
313
|
+
const specialTools = new Set([
|
|
314
|
+
ListMcpResourcesTool.name,
|
|
315
|
+
ReadMcpResourceTool.name,
|
|
316
|
+
SYNTHETIC_OUTPUT_TOOL_NAME,
|
|
317
|
+
])
|
|
318
|
+
|
|
319
|
+
const tools = getAllBaseTools().filter(tool => !specialTools.has(tool.name))
|
|
320
|
+
|
|
321
|
+
// Filter out tools that are denied by the deny rules
|
|
322
|
+
let allowedTools = filterToolsByDenyRules(tools, permissionContext)
|
|
323
|
+
|
|
324
|
+
// When REPL mode is enabled, hide primitive tools from direct use.
|
|
325
|
+
// They're still accessible inside REPL via the VM context.
|
|
326
|
+
if (isReplModeEnabled()) {
|
|
327
|
+
const replEnabled = allowedTools.some(tool =>
|
|
328
|
+
toolMatchesName(tool, REPL_TOOL_NAME),
|
|
329
|
+
)
|
|
330
|
+
if (replEnabled) {
|
|
331
|
+
allowedTools = allowedTools.filter(
|
|
332
|
+
tool => !REPL_ONLY_TOOLS.has(tool.name),
|
|
333
|
+
)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const isEnabled = allowedTools.map(_ => _.isEnabled())
|
|
338
|
+
return allowedTools.filter((_, i) => isEnabled[i])
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Assemble the full tool pool for a given permission context and MCP tools.
|
|
343
|
+
*
|
|
344
|
+
* This is the single source of truth for combining built-in tools with MCP tools.
|
|
345
|
+
* Both REPL.tsx (via useMergedTools hook) and runAgent.ts (for coordinator workers)
|
|
346
|
+
* use this function to ensure consistent tool pool assembly.
|
|
347
|
+
*
|
|
348
|
+
* The function:
|
|
349
|
+
* 1. Gets built-in tools via getTools() (respects mode filtering)
|
|
350
|
+
* 2. Filters MCP tools by deny rules
|
|
351
|
+
* 3. Deduplicates by tool name (built-in tools take precedence)
|
|
352
|
+
*
|
|
353
|
+
* @param permissionContext - Permission context for filtering built-in tools
|
|
354
|
+
* @param mcpTools - MCP tools from appState.mcp.tools
|
|
355
|
+
* @returns Combined, deduplicated array of built-in and MCP tools
|
|
356
|
+
*/
|
|
357
|
+
export function assembleToolPool(
|
|
358
|
+
permissionContext: ToolPermissionContext,
|
|
359
|
+
mcpTools: Tools,
|
|
360
|
+
brainMode?: boolean,
|
|
361
|
+
): Tools {
|
|
362
|
+
const effectiveBrainMode = brainMode ?? isBrainModeActive()
|
|
363
|
+
const builtInTools = getTools(permissionContext, effectiveBrainMode)
|
|
364
|
+
|
|
365
|
+
// When brainMode is active, skip MCP tools entirely
|
|
366
|
+
const filteredMcpTools = effectiveBrainMode ? [] : filterToolsByDenyRules(mcpTools, permissionContext)
|
|
367
|
+
|
|
368
|
+
// Sort each partition for prompt-cache stability, keeping built-ins as a
|
|
369
|
+
// contiguous prefix. The server's claude_code_system_cache_policy places a
|
|
370
|
+
// global cache breakpoint after the last prefix-matched built-in tool; a flat
|
|
371
|
+
// sort would interleave MCP tools into built-ins and invalidate all downstream
|
|
372
|
+
// cache keys whenever an MCP tool sorts between existing built-ins. uniqBy
|
|
373
|
+
// preserves insertion order, so built-ins win on name conflict.
|
|
374
|
+
// Avoid Array.toSorted (Node 20+) — we support Node 18. builtInTools is
|
|
375
|
+
// readonly so copy-then-sort; filteredMcpTools is a fresh .filter() result.
|
|
376
|
+
const byName = (a: Tool, b: Tool) => a.name.localeCompare(b.name)
|
|
377
|
+
return uniqBy(
|
|
378
|
+
[...builtInTools].sort(byName).concat(filteredMcpTools.sort(byName)),
|
|
379
|
+
'name',
|
|
380
|
+
)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Get all tools including both built-in tools and MCP tools.
|
|
385
|
+
*
|
|
386
|
+
* This is the preferred function when you need the complete tools list for:
|
|
387
|
+
* - Tool search threshold calculations (isToolSearchEnabled)
|
|
388
|
+
* - Token counting that includes MCP tools
|
|
389
|
+
* - Any context where MCP tools should be considered
|
|
390
|
+
*
|
|
391
|
+
* Use getTools() only when you specifically need just built-in tools.
|
|
392
|
+
*
|
|
393
|
+
* @param permissionContext - Permission context for filtering built-in tools
|
|
394
|
+
* @param mcpTools - MCP tools from appState.mcp.tools
|
|
395
|
+
* @returns Combined array of built-in and MCP tools
|
|
396
|
+
*/
|
|
397
|
+
export function getMergedTools(
|
|
398
|
+
permissionContext: ToolPermissionContext,
|
|
399
|
+
mcpTools: Tools,
|
|
400
|
+
): Tools {
|
|
401
|
+
const builtInTools = getTools(permissionContext)
|
|
402
|
+
return [...builtInTools, ...mcpTools]
|
|
403
|
+
}
|