Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
41c2266
refactor(cmd): split chat.go into focused files
Patel230 Jun 19, 2026
d23f4e1
refactor(review): extract built-in rules from review_bot.go into revi…
Patel230 Jun 19, 2026
d3f2afa
refactor(agents): move built-in persona definitions to persona_builti…
Patel230 Jun 19, 2026
7701e30
refactor(fingerprint): split project.go into project_detect.go and pr…
Patel230 Jun 19, 2026
a8d402b
refactor(repomap): split depgraph.go into depgraph_build.go and depgr…
Patel230 Jun 19, 2026
08354ae
refactor(project): split project_analyzer.go into metrics, patterns, …
Patel230 Jun 19, 2026
2fba194
refactor(scaffold): move built-in templates to scaffold_builtins.go
Patel230 Jun 19, 2026
bf25f0f
refactor(tool): move built-in codegen templates to codegen_builtins.go
Patel230 Jun 19, 2026
e46e0ee
refactor(eval): split Go benchmark tasks 9-15 into tasks_go_more.go
Patel230 Jun 19, 2026
ef27cd4
refactor(cmd): split struct-based markdown renderer into markdown_ren…
Patel230 Jun 19, 2026
787b01f
refactor(engine): split semantic diff AST helpers into semantic_diff_…
Patel230 Jun 19, 2026
173b335
refactor(repomap): split summary helpers into summary_helpers.go
Patel230 Jun 19, 2026
8c8ecc9
refactor(engine/code): split code explainer helpers into code_explain…
Patel230 Jun 19, 2026
920d231
refactor(repomap): split health score dimension scorers into health_s…
Patel230 Jun 19, 2026
3243600
refactor(codegraph): split helpers and read/traversal ops into codegr…
Patel230 Jun 19, 2026
3e29ef2
refactor(codegraph): split ranking/impact/coupling/cross-repo algorit…
Patel230 Jun 19, 2026
92def17
test(fingerprint): split project_test.go into detect and conventions …
Patel230 Jun 19, 2026
cabafb8
test(agents): split persona registry/selection tests into persona_reg…
Patel230 Jun 19, 2026
1b72e0e
test(tool): split commitlint config/check tests into commitlint_confi…
Patel230 Jun 19, 2026
e3e68b2
test(tool): split RefactorTool.Execute tests into refactor_tool_test.go
Patel230 Jun 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
923 changes: 2 additions & 921 deletions cmd/chat.go

Large diffs are not rendered by default.

152 changes: 152 additions & 0 deletions cmd/chat_tools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package cmd

import (
"context"
"fmt"
"os"
"strings"

hawkconfig "github.com/GrayCodeAI/hawk/internal/config"
"github.com/GrayCodeAI/hawk/internal/tool"
)

// This file holds the tool-registry construction used by the chat TUI:
// the essential/optional tool sets and the registry builder that wires in
// MCP servers and CLI tool filters. Split out of chat.go for clarity.

func essentialTools() []tool.Tool {
// Core tools needed for basic agent operation - always loaded at startup
return []tool.Tool{
tool.BashTool{},
tool.FileReadTool{},
tool.FileWriteTool{},
tool.FileEditTool{},
tool.StructuredEditTool{},
tool.LSTool{},
tool.GlobTool{},
tool.GrepTool{},
tool.WebFetchTool{},
tool.WebSearchTool{},
tool.ToolSearchTool{},
tool.SkillTool{},
tool.AgentTool{},
tool.AskUserQuestionTool{},
tool.TodoWriteTool{},
tool.TaskOutputTool{},
tool.TaskStopTool{},
tool.LSPTool{},
tool.MultiEditTool{},
}
}

func optionalTools() []tool.Tool {
// Specialized tools that can be lazy-loaded on demand
return []tool.Tool{
tool.EnterPlanModeTool{},
tool.ExitPlanModeTool{},
tool.NotebookEditTool{},
tool.EnterWorktreeTool{},
tool.ExitWorktreeTool{},
tool.ListMcpResourcesTool{},
tool.ReadMcpResourceTool{},
tool.ConfigTool{},
tool.BriefTool{},
tool.TaskCreateTool{},
tool.TaskGetTool{},
tool.TaskListTool{},
tool.TaskUpdateTool{},
tool.SleepTool{},
tool.CronCreateTool{},
tool.CronDeleteTool{},
tool.CronListTool{},
tool.VerifyPlanExecutionTool{},
tool.WorkflowTool{},
tool.McpAuthTool{},
tool.DiagnosticsTool{},
tool.CodeSearchTool{},
tool.CoreMemoryAppendTool{},
tool.CoreMemoryReplaceTool{},
tool.CoreMemoryRethinkTool{},
tool.DownloadTool{},
tool.AgenticFetchTool{},
tool.ImpactTool{},
tool.GitHistoryTool{},
tool.CodeGraphTool{},
tool.NilAwayTool{},
tool.ReviveTool{},
tool.MCPLanguageServerTool{},
tool.SQLTool{},
}
}

func defaultRegistry(settings hawkconfig.Settings) (*tool.Registry, error) {
// Load essential tools first for fast startup
tools := essentialTools()
if tool.IsPowerShellAvailable() {
tools = append(tools, tool.PowerShellTool{})
}
// Detect project-level MCP servers (supply chain attack vector).
// Project .hawk/settings.json can be committed to a repo and define
// arbitrary commands that execute on clone. Gate behind --allow-project-mcp.
projectMCPServers := hawkconfig.ProjectMCPServers()
projectMCPNames := make(map[string]bool, len(projectMCPServers))
for _, cfg := range projectMCPServers {
if cfg.Name != "" {
projectMCPNames[cfg.Name] = true
}
}
for _, cfg := range settings.MCPServers {
if cfg.Name == "" || cfg.Command == "" {
continue
}
if projectMCPNames[cfg.Name] && !allowProjectMCP {
fmt.Fprintf(os.Stderr, "hawk: skipping project-level MCP server %q (defined in .hawk/settings.json); use --allow-project-mcp to enable\n", cfg.Name)
continue
}
mcpTools, err := tool.LoadMCPTools(context.Background(), cfg.Name, cfg.Command, cfg.Args...)
if err != nil {
continue
}
tools = append(tools, mcpTools...)
}
// Load MCP server tools
for _, cmd := range mcpServers {
parts := strings.Fields(cmd)
if len(parts) == 0 {
continue
}
name := parts[0]
mcpTools, err := tool.LoadMCPTools(context.Background(), name, parts[0], parts[1:]...)
if err != nil {
// MCP server failed to connect — skip silently, will show in /doctor
continue
}
tools = append(tools, mcpTools...)
}

filtered, err := filterAvailableTools(
tools,
toolsFlagSet,
parseToolListFromCLI(toolsFlag),
parseToolListFromCLI(disallowedToolsFlag),
)
if err != nil {
return nil, err
}
registry := tool.NewRegistry(filtered...)

// Lazy-load optional tools in background
go func() {
for _, t := range optionalTools() {
_ = registry.Register(t)
}
}()

return registry, nil
}

func allTools() []tool.Tool {
t := essentialTools()
t = append(t, optionalTools()...)
return t
}
Loading
Loading