Skip to content

Commit 5f95283

Browse files
authored
fix: AI discovery output rendering (#692)
* fix: AI discovery output rendering * fix: AI discovery output rendering
1 parent 7eca825 commit 5f95283

8 files changed

Lines changed: 67 additions & 15 deletions

File tree

cmd/ai/discover.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,10 @@ func printSummaryTable(inventory *aitool.AIToolInventory) {
104104
for _, tool := range inventory.Tools {
105105
detail := toolDetail(tool)
106106
tbl.AppendRow(table.Row{
107-
string(tool.Type),
107+
tool.Type.DisplayName(),
108108
tool.Name,
109-
tool.App,
110-
string(tool.Scope),
109+
tool.AppDisplay,
110+
tool.Scope.DisplayName(),
111111
detail,
112112
})
113113
}

pkg/aitool/ai_extension.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ var ideDirNames = map[string]string{
1919
".windsurf": "Windsurf",
2020
}
2121

22-
const ideExtensionsApp = "ide_extensions"
22+
const (
23+
ideExtensionsApp = "ide_extensions"
24+
ideExtensionsAppDisplay = "IDE Extensions"
25+
)
2326

2427
type aiExtensionDiscoverer struct {
2528
config DiscoveryConfig
@@ -58,6 +61,7 @@ func (d *aiExtensionDiscoverer) EnumTools(_ context.Context, handler AIToolHandl
5861
Type: AIToolTypeAIExtension,
5962
Scope: AIToolScopeSystem,
6063
App: ideExtensionsApp,
64+
AppDisplay: ideExtensionsAppDisplay,
6165
ConfigPath: manifest.GetPath(),
6266
}
6367

@@ -69,6 +73,7 @@ func (d *aiExtensionDiscoverer) EnumTools(_ context.Context, handler AIToolHandl
6973

7074
if ide := ideNameFromPath(manifest.GetPath()); ide != "" {
7175
tool.SetMeta("extension.ide", ide)
76+
tool.AppDisplay = ide
7277
}
7378

7479
return handler(tool)

pkg/aitool/claude_code.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import (
88
"github.com/safedep/vet/pkg/common/logger"
99
)
1010

11-
const claudeCodeApp = "claude_code"
11+
const (
12+
claudeCodeApp = "claude_code"
13+
claudeCodeAppDisplay = "Claude Code"
14+
)
1215

1316
type claudeCodeDiscoverer struct {
1417
homeDir string
@@ -73,6 +76,7 @@ func (d *claudeCodeDiscoverer) processSystemSettings(path string, handler AITool
7376
Type: AIToolTypeCodingAgent,
7477
Scope: AIToolScopeSystem,
7578
App: claudeCodeApp,
79+
AppDisplay: claudeCodeAppDisplay,
7680
ConfigPath: path,
7781
Agent: &AgentConfig{},
7882
}
@@ -93,7 +97,7 @@ func (d *claudeCodeDiscoverer) processSystemSettings(path string, handler AITool
9397
}
9498

9599
// Emit MCP servers from system settings
96-
return emitMCPServers(cfg, path, AIToolScopeSystem, claudeCodeApp, handler)
100+
return emitMCPServers(cfg, path, AIToolScopeSystem, claudeCodeApp, claudeCodeAppDisplay, handler)
97101
}
98102

99103
func (d *claudeCodeDiscoverer) walkProjectSettings(handler AIToolHandlerFn) error {
@@ -115,7 +119,7 @@ func (d *claudeCodeDiscoverer) walkProjectSettings(handler AIToolHandlerFn) erro
115119
continue
116120
}
117121

118-
if err := emitMCPServers(cfg, settingsPath, AIToolScopeSystem, claudeCodeApp, handler); err != nil {
122+
if err := emitMCPServers(cfg, settingsPath, AIToolScopeSystem, claudeCodeApp, claudeCodeAppDisplay, handler); err != nil {
119123
return err
120124
}
121125
}
@@ -127,15 +131,15 @@ func (d *claudeCodeDiscoverer) processProjectConfigs(handler AIToolHandlerFn) er
127131
// .mcp.json
128132
mcpJSONPath := filepath.Join(d.projectDir, ".mcp.json")
129133
if cfg, err := parseMCPAppConfig(mcpJSONPath); err == nil {
130-
if err := emitMCPServers(cfg, mcpJSONPath, AIToolScopeProject, claudeCodeApp, handler); err != nil {
134+
if err := emitMCPServers(cfg, mcpJSONPath, AIToolScopeProject, claudeCodeApp, claudeCodeAppDisplay, handler); err != nil {
131135
return err
132136
}
133137
}
134138

135139
// .claude/settings.json (project-scoped)
136140
projectSettingsPath := filepath.Join(d.projectDir, ".claude", "settings.json")
137141
if cfg, err := parseMCPAppConfig(projectSettingsPath); err == nil {
138-
if err := emitMCPServers(cfg, projectSettingsPath, AIToolScopeProject, claudeCodeApp, handler); err != nil {
142+
if err := emitMCPServers(cfg, projectSettingsPath, AIToolScopeProject, claudeCodeApp, claudeCodeAppDisplay, handler); err != nil {
139143
return err
140144
}
141145
}
@@ -153,6 +157,7 @@ func (d *claudeCodeDiscoverer) processProjectConfigs(handler AIToolHandlerFn) er
153157
Type: AIToolTypeProjectConfig,
154158
Scope: AIToolScopeProject,
155159
App: claudeCodeApp,
160+
AppDisplay: claudeCodeAppDisplay,
156161
ConfigPath: d.projectDir,
157162
Agent: &AgentConfig{
158163
InstructionFiles: instructionFiles,

pkg/aitool/cli_common.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func probeBinary(ctx context.Context, name string, verifier CLIToolVerifier) (*A
8585
Type: AIToolTypeCLITool,
8686
Scope: AIToolScopeSystem,
8787
App: verifier.App(),
88+
AppDisplay: verifier.DisplayName(),
8889
ConfigPath: binPath,
8990
}
9091

pkg/aitool/cursor.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import (
66
"path/filepath"
77
)
88

9-
const cursorApp = "cursor"
9+
const (
10+
cursorApp = "cursor"
11+
cursorAppDisplay = "Cursor"
12+
)
1013

1114
type cursorDiscoverer struct {
1215
homeDir string
@@ -41,7 +44,7 @@ func (d *cursorDiscoverer) EnumTools(_ context.Context, handler AIToolHandlerFn)
4144

4245
// System-level: ~/.cursor/mcp.json
4346
if cfg, err := parseMCPAppConfig(systemMCPPath); err == nil {
44-
if err := emitMCPServers(cfg, systemMCPPath, AIToolScopeSystem, cursorApp, handler); err != nil {
47+
if err := emitMCPServers(cfg, systemMCPPath, AIToolScopeSystem, cursorApp, cursorAppDisplay, handler); err != nil {
4548
return err
4649
}
4750
}
@@ -53,6 +56,7 @@ func (d *cursorDiscoverer) EnumTools(_ context.Context, handler AIToolHandlerFn)
5356
Type: AIToolTypeCodingAgent,
5457
Scope: AIToolScopeSystem,
5558
App: cursorApp,
59+
AppDisplay: cursorAppDisplay,
5660
ConfigPath: cursorDir,
5761
Agent: &AgentConfig{},
5862
}
@@ -78,7 +82,7 @@ func (d *cursorDiscoverer) processProjectConfigs(handler AIToolHandlerFn) error
7882
// .cursor/mcp.json (project-scoped)
7983
projectMCPPath := filepath.Join(d.projectDir, ".cursor", "mcp.json")
8084
if cfg, err := parseMCPAppConfig(projectMCPPath); err == nil {
81-
if err := emitMCPServers(cfg, projectMCPPath, AIToolScopeProject, cursorApp, handler); err != nil {
85+
if err := emitMCPServers(cfg, projectMCPPath, AIToolScopeProject, cursorApp, cursorAppDisplay, handler); err != nil {
8286
return err
8387
}
8488
}
@@ -109,6 +113,7 @@ func (d *cursorDiscoverer) processProjectConfigs(handler AIToolHandlerFn) error
109113
Type: AIToolTypeProjectConfig,
110114
Scope: AIToolScopeProject,
111115
App: cursorApp,
116+
AppDisplay: cursorAppDisplay,
112117
ConfigPath: d.projectDir,
113118
Agent: &AgentConfig{
114119
InstructionFiles: instructionFiles,

pkg/aitool/mcp_config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func detectTransport(entry mcpServerEntry) MCPTransport {
8484
}
8585

8686
// emitMCPServers creates and emits AITool entries for all MCP servers in a config.
87-
func emitMCPServers(cfg *mcpAppConfig, configPath string, scope AIToolScope, app string, handler AIToolHandlerFn) error {
87+
func emitMCPServers(cfg *mcpAppConfig, configPath string, scope AIToolScope, app, appDisplay string, handler AIToolHandlerFn) error {
8888
for _, name := range sortedKeys(cfg.MCPServers) {
8989
entry := cfg.MCPServers[name]
9090

@@ -105,6 +105,7 @@ func emitMCPServers(cfg *mcpAppConfig, configPath string, scope AIToolScope, app
105105
Type: AIToolTypeMCPServer,
106106
Scope: scope,
107107
App: app,
108+
AppDisplay: appDisplay,
108109
ConfigPath: configPath,
109110
MCPServer: mcpCfg,
110111
}

pkg/aitool/model.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@ const (
1818
AIToolTypeProjectConfig AIToolType = "project_config"
1919
)
2020

21+
// DisplayName returns a human-friendly label for the tool type.
22+
func (t AIToolType) DisplayName() string {
23+
switch t {
24+
case AIToolTypeMCPServer:
25+
return "MCP Server"
26+
case AIToolTypeCodingAgent:
27+
return "Coding Agent"
28+
case AIToolTypeAIExtension:
29+
return "AI Extension"
30+
case AIToolTypeCLITool:
31+
return "CLI Tool"
32+
case AIToolTypeProjectConfig:
33+
return "Project Config"
34+
default:
35+
return string(t)
36+
}
37+
}
38+
2139
// AIToolScope distinguishes system-level (global) from project-level (repo-scoped) configs.
2240
type AIToolScope string
2341

@@ -26,6 +44,18 @@ const (
2644
AIToolScopeProject AIToolScope = "project"
2745
)
2846

47+
// DisplayName returns a human-friendly label for the scope.
48+
func (s AIToolScope) DisplayName() string {
49+
switch s {
50+
case AIToolScopeSystem:
51+
return "System"
52+
case AIToolScopeProject:
53+
return "Project"
54+
default:
55+
return string(s)
56+
}
57+
}
58+
2959
// MCPTransport identifies the transport protocol for an MCP server.
3060
type MCPTransport string
3161

@@ -65,6 +95,7 @@ type AITool struct {
6595
Type AIToolType `json:"type"`
6696
Scope AIToolScope `json:"scope"`
6797
App string `json:"app"`
98+
AppDisplay string `json:"-"`
6899
ConfigPath string `json:"config_path"`
69100

70101
MCPServer *MCPServerConfig `json:"mcp_server,omitempty"`

pkg/aitool/windsurf.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import (
66
"path/filepath"
77
)
88

9-
const windsurfApp = "windsurf"
9+
const (
10+
windsurfApp = "windsurf"
11+
windsurfAppDisplay = "Windsurf"
12+
)
1013

1114
type windsurfDiscoverer struct {
1215
homeDir string
@@ -39,7 +42,7 @@ func (d *windsurfDiscoverer) EnumTools(_ context.Context, handler AIToolHandlerF
3942

4043
// System-level: ~/.codeium/windsurf/mcp_config.json
4144
if cfg, err := parseMCPAppConfig(mcpConfigPath); err == nil {
42-
if err := emitMCPServers(cfg, mcpConfigPath, AIToolScopeSystem, windsurfApp, handler); err != nil {
45+
if err := emitMCPServers(cfg, mcpConfigPath, AIToolScopeSystem, windsurfApp, windsurfAppDisplay, handler); err != nil {
4346
return err
4447
}
4548
}
@@ -51,6 +54,7 @@ func (d *windsurfDiscoverer) EnumTools(_ context.Context, handler AIToolHandlerF
5154
Type: AIToolTypeCodingAgent,
5255
Scope: AIToolScopeSystem,
5356
App: windsurfApp,
57+
AppDisplay: windsurfAppDisplay,
5458
ConfigPath: windsurfDir,
5559
Agent: &AgentConfig{},
5660
}

0 commit comments

Comments
 (0)