All files / src/components/tools classifyTool.ts

77.77% Statements 14/18
64.28% Branches 9/14
100% Functions 2/2
77.77% Lines 14/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 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                                                  2x                         21x       21x 3x 3x 3x 3x 2x         19x 19x           19x     2x                                                                                                                                           21x 21x    
/**
 * Classifies a tool name into a rendering category.
 *
 * Maps tool names from all supported runtimes (Claude Code, Copilot, Codex)
 * to a UI category that determines which card component renders the event.
 */
 
/** Tool rendering categories corresponding to specialized card components. */
export type ToolCategory =
  | "file-read"
  | "file-edit"
  | "file-write"
  | "shell"
  | "search"
  | "todo"
  | "metadata"
  | "task"
  | "workpad"
  | "knowledge"
  | "ipc"
  | "tool-search"
  | "agent"
  | "generic";
 
/** Known MCP server names for bare-name extraction from Copilot dash format. */
const KNOWN_MCP_SERVERS: Set<string> = new Set(["grackle"]);
 
/**
 * Extracts the bare tool name from runtime-specific naming conventions.
 *
 * - Claude Code / Codex: `mcp__grackle__task_create` -> `task_create`
 * - Copilot: `grackle-task_create` -> `task_create`
 * - Built-in: `Read` -> `read` (unchanged, lowered later)
 */
export function extractBareName(toolName: string): string {
  // Defensive: callers may pass undefined for legacy events that never carried
  // a tool name (e.g. stub fixtures, runtimes that emit tool_use with only
  // tool_name / display_name in `content`). Treat as empty string.
  Iif (!toolName) {
    return "";
  }
  // MCP double-underscore format: mcp__<server>__<tool> (only for known servers)
  if (toolName.startsWith("mcp__")) {
    const serverSep = toolName.indexOf("__", 5);
    Eif (serverSep > 5) {
      const server = toolName.slice(5, serverSep);
      if (KNOWN_MCP_SERVERS.has(server)) {
        return toolName.slice(serverSep + 2);
      }
    }
  }
  // Copilot dash format: <server>-<tool> (only for known servers)
  const dashIndex = toolName.indexOf("-");
  Iif (dashIndex > 0) {
    const server = toolName.slice(0, dashIndex);
    if (KNOWN_MCP_SERVERS.has(server)) {
      return toolName.slice(dashIndex + 1);
    }
  }
  return toolName;
}
 
const TOOL_MAP: Record<string, ToolCategory> = {
  // File read — Claude Code: Read, Copilot: view
  read: "file-read",
  view: "file-read",
 
  // File edit — Claude Code: Edit, Copilot: edit, Codex: file_change
  edit: "file-edit",
  file_change: "file-edit",
 
  // File write — Claude Code: Write
  write: "file-write",
 
  // Shell — Claude Code: Bash, Copilot: powershell, Codex: command_execution
  bash: "shell",
  powershell: "shell",
  command_execution: "shell",
 
  // Search — Claude Code: Grep, Glob
  grep: "search",
  glob: "search",
 
  // Todo — Claude Code: TodoWrite, Codex: update_plan, Goose: todo_write
  todowrite: "todo",
  update_plan: "todo",
  todo_write: "todo",
 
  // Metadata — Copilot: report_intent
  report_intent: "metadata",
 
  // Task — Grackle MCP
  task_list: "task",
  task_create: "task",
  task_show: "task",
  task_update: "task",
  task_start: "task",
  task_complete: "task",
  task_resume: "task",
  task_delete: "task",
 
  // Workpad — Grackle MCP
  workpad_write: "workpad",
  workpad_read: "workpad",
 
  // Knowledge — Grackle MCP
  knowledge_search: "knowledge",
  knowledge_get_node: "knowledge",
  knowledge_create_node: "knowledge",
 
  // IPC — Grackle MCP
  ipc_spawn: "ipc",
  ipc_write: "ipc",
  ipc_close: "ipc",
  ipc_list_fds: "ipc",
  ipc_terminate: "ipc",
  ipc_create_stream: "ipc",
  ipc_attach: "ipc",
  ipc_share_stream: "ipc",
  ipc_list_streams: "ipc",
 
  // ToolSearch — Claude Code built-in
  toolsearch: "tool-search",
 
  // Agent — Claude Code: Agent (formerly Task), Copilot: task, read_agent
  agent: "agent",
  task: "agent",
  read_agent: "agent",
};
 
/** Classifies a tool name to determine which card component should render it. */
export function classifyTool(toolName: string): ToolCategory {
  const bare = extractBareName(toolName);
  return TOOL_MAP[bare.toLowerCase()] ?? "generic";
}