diff --git a/src/cli/App.tsx b/src/cli/App.tsx
index 1dc45e1..446e94a 100644
--- a/src/cli/App.tsx
+++ b/src/cli/App.tsx
@@ -9798,7 +9798,7 @@ Plan file path: ${planFilePath}`;
{/* Hooks Manager - for managing hooks configuration */}
{activeOverlay === "hooks" && (
-
+
)}
{/* New Agent Dialog - for naming new agent before creation */}
diff --git a/src/cli/components/HooksManager.tsx b/src/cli/components/HooksManager.tsx
index 73bbed4..a577b82 100644
--- a/src/cli/components/HooksManager.tsx
+++ b/src/cli/components/HooksManager.tsx
@@ -37,6 +37,7 @@ const BOX_VERTICAL = "│";
interface HooksManagerProps {
onClose: () => void;
+ agentId?: string;
}
type Screen =
@@ -62,8 +63,8 @@ const HOOK_EVENTS: { event: HookEvent; description: string }[] = [
{ event: "SessionEnd", description: "When a session ends" },
];
-// Available tools for matcher suggestions
-const TOOL_NAMES = [
+// Fallback tool names if agent tools can't be fetched
+const FALLBACK_TOOL_NAMES = [
"Task",
"Bash",
"Glob",
@@ -71,14 +72,13 @@ const TOOL_NAMES = [
"Read",
"Edit",
"Write",
- "WebFetch",
"TodoWrite",
- "WebSearch",
"AskUserQuestion",
"Skill",
"EnterPlanMode",
"ExitPlanMode",
- "KillShell",
+ "BashOutput",
+ "KillBash",
];
// Save location options
@@ -130,6 +130,7 @@ function boxBottom(width: number): string {
export const HooksManager = memo(function HooksManager({
onClose,
+ agentId,
}: HooksManagerProps) {
const terminalWidth = useTerminalWidth();
const boxWidth = Math.min(terminalWidth - 4, 70);
@@ -141,6 +142,37 @@ export const HooksManager = memo(function HooksManager({
const [hooks, setHooks] = useState([]);
const [totalHooks, setTotalHooks] = useState(0);
+ // Dynamic tool names from agent
+ const [toolNames, setToolNames] = useState(FALLBACK_TOOL_NAMES);
+
+ // Fetch agent tools on mount
+ useEffect(() => {
+ if (!agentId) return;
+
+ const fetchAgentTools = async () => {
+ try {
+ const { getClient } = await import("../../agent/client");
+ const client = await getClient();
+ // Use dedicated tools endpoint instead of fetching whole agent
+ // Pass limit to avoid pagination issues
+ const toolsPage = await client.agents.tools.list(agentId, {
+ limit: 50,
+ });
+ const names = toolsPage.items
+ ?.map((t) => t.name)
+ .filter((n): n is string => !!n);
+ if (names && names.length > 0) {
+ // Sort alphabetically for easier scanning
+ setToolNames(names.sort());
+ }
+ } catch {
+ // Keep fallback tool names on error
+ }
+ };
+
+ fetchAgentTools();
+ }, [agentId]);
+
// New hook state
const [newMatcher, setNewMatcher] = useState("");
const [newCommand, setNewCommand] = useState("");
@@ -476,7 +508,7 @@ export const HooksManager = memo(function HooksManager({
Possible matcher values for field tool_name:
- {TOOL_NAMES.join(", ")}
+ {toolNames.join(", ")}
Tool matcher:
diff --git a/src/cli/components/McpSelector.tsx b/src/cli/components/McpSelector.tsx
index b315832..c2e0c33 100644
--- a/src/cli/components/McpSelector.tsx
+++ b/src/cli/components/McpSelector.tsx
@@ -111,10 +111,10 @@ export const McpSelector = memo(function McpSelector({
const fetchAttachedToolIds = useCallback(
async (client: Awaited>) => {
- const agent = await client.agents.retrieve(agentId, {
- include: ["agent.tools"],
- });
- return new Set(agent.tools?.map((t) => t.id) || []);
+ // Use dedicated tools endpoint instead of fetching whole agent
+ // Pass limit to avoid pagination issues
+ const toolsPage = await client.agents.tools.list(agentId, { limit: 50 });
+ return new Set(toolsPage.items?.map((t) => t.id) || []);
},
[agentId],
);
diff --git a/src/tools/toolset.ts b/src/tools/toolset.ts
index 66c335c..a90f3ea 100644
--- a/src/tools/toolset.ts
+++ b/src/tools/toolset.ts
@@ -48,6 +48,7 @@ export async function ensureCorrectMemoryTool(
: isOpenAIModel(resolvedModel);
try {
+ // Need full agent state for tool_rules, so use retrieve with include
const agentWithTools = await client.agents.retrieve(agentId, {
include: ["agent.tools"],
});