You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Keep activated tools advertised across resume and rebuild (#912)
* Keep activated tools advertised across resume and rebuild
* Wire exec tool_search promotion into the call gate
Exec installed the same advertised-set call gate as the TUI but left tool_search's promoter as a no-op, so MCP names the model was told to call were refused.
* Include pinnedTools in the local settings load fixture
@@ -178,16 +182,22 @@ export function createActivatedToolTracker(): ActivatedToolTracker {
178
182
}
179
183
returnchanged;
180
184
},
185
+
has(name: string): boolean{
186
+
returnactiveNames.has(name);
187
+
},
181
188
list(): string[]{
182
189
return[...activeNames];
183
190
},
191
+
clear(): void{
192
+
activeNames.clear();
193
+
},
184
194
};
185
195
}
186
196
187
197
exportconsttoolSearchDefinition: ToolDefinition={
188
198
name: "tool_search",
189
199
description:
190
-
"Discover callable tools by capability. Most tools — MCP servers, present, and other integrations — are dispatchable but not advertised in the tools list. Core tools (read_file, run_shell, web_fetch, web_search, spawn_agent, wait_agents, …) are already on the wire — do not tool_search for them. Call this with a short description of what you need (e.g. 'issue tracker', 'render layout', 'granola notes') to get matching tools' names, descriptions, and input schemas. The returned tools are already callable — invoke them directly, no separate load step.",
200
+
"Discover callable tools by capability. Most tools — MCP servers, present, and other integrations — are not advertised until this search promotes them onto the wire. Core tools (read_file, run_shell, web_fetch, web_search, spawn_agent, wait_agents, …) are already on the wire — do not tool_search for them. Call this with a short description of what you need (e.g. 'issue tracker', 'render layout', 'granola notes') to get matching tools' names, descriptions, and input schemas. Matched tools are promoted and callable on return — invoke them directly, no separate load step.",
191
201
inputSchema: {
192
202
type: "object",
193
203
properties: {
@@ -257,9 +267,9 @@ export function createToolIndex(
257
267
exportinterfaceToolSearchDeps{
258
268
search: (query: string)=>string[];
259
269
lookup: (name: string)=>ToolDefinition|undefined;
260
-
// Make the matched tools' names part of the advertised wire set on the next
261
-
// inference. Every registered tool is already dispatchable via `run`, so this
262
-
// only affects what the model can see without an intervening tool_search.
270
+
// Promote matches onto the advertised set and the call gate so the model can
271
+
// invoke them this turn. The next inference also declares them on the wire
? s.pinnedTools.filter((name): name is string=>typeofname==="string")
1082
+
: undefined,
1072
1083
};
1073
1084
}
1074
1085
@@ -1084,7 +1095,7 @@ function coerceLocalSettings(
1084
1095
{
1085
1096
path,
1086
1097
message: `Local settings in ${path} is not a JSON object.`,
1087
-
fix: `Edit ${path} to a JSON object with only: provider, model, reasoningEffort, mcpServers, sessionMode, env.`,
1098
+
fix: `Edit ${path} to a JSON object with only: provider, model, reasoningEffort, mcpServers, sessionMode, env, pinnedTools.`,
1088
1099
},
1089
1100
],
1090
1101
};
@@ -1141,7 +1152,7 @@ function coerceLocalSettings(
1141
1152
diagnostics.push({
1142
1153
path,
1143
1154
message: `Local settings in ${path} had invalid values and were partially ignored.`,
1144
-
fix: `Edit ${path}: only "provider", "model", "reasoningEffort", "mcpServers", "sessionMode", and "env" are allowed (no credentials).`,
1155
+
fix: `Edit ${path}: only "provider", "model", "reasoningEffort", "mcpServers", "sessionMode", "env", and "pinnedTools" are allowed (no credentials).`,
1145
1156
});
1146
1157
}
1147
1158
constsettings=pickDefined(optional);
@@ -1336,7 +1347,7 @@ export async function saveLocalSettings(
1336
1347
): Promise<void>{
1337
1348
if(!isLocalSettings(local)){
1338
1349
thrownewError(
1339
-
`Refusing to write invalid local settings: only "provider", "model", "reasoningEffort", "mcpServers", and "sessionMode" are allowed.`,
1350
+
`Refusing to write invalid local settings: only "provider", "model", "reasoningEffort", "mcpServers", "sessionMode", "env", and "pinnedTools" are allowed.`,
0 commit comments