@dcode-dev/dcode-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/NPM_README.md +78 -0
  2. package/README.md +341 -0
  3. package/bin/dcode-bin +0 -0
  4. package/bin/dcode.js +44 -0
  5. package/cmd/agent_v2.go +448 -0
  6. package/cmd/analyze.go +97 -0
  7. package/cmd/auth.go +338 -0
  8. package/cmd/compose.go +284 -0
  9. package/cmd/context.go +111 -0
  10. package/cmd/edit.go +116 -0
  11. package/cmd/env.go +10 -0
  12. package/cmd/fix.go +145 -0
  13. package/cmd/gemini.go +20 -0
  14. package/cmd/generate.go +47 -0
  15. package/cmd/interactive.go +33 -0
  16. package/cmd/mcp.go +196 -0
  17. package/cmd/patch.go +19 -0
  18. package/cmd/providers.go +67 -0
  19. package/cmd/root.go +41 -0
  20. package/cmd/search.go +61 -0
  21. package/cmd/server.go +36 -0
  22. package/cmd/switch.go +122 -0
  23. package/cmd/terminal.go +277 -0
  24. package/go.mod +42 -0
  25. package/go.sum +86 -0
  26. package/internal/agent/agent.go +332 -0
  27. package/internal/agent/parse.go +25 -0
  28. package/internal/agents/base.go +154 -0
  29. package/internal/agents/documenter.go +77 -0
  30. package/internal/agents/generalist.go +266 -0
  31. package/internal/agents/investigator.go +60 -0
  32. package/internal/agents/registry.go +34 -0
  33. package/internal/agents/reviewer.go +67 -0
  34. package/internal/agents/tester.go +73 -0
  35. package/internal/ai/client.go +634 -0
  36. package/internal/ai/tools.go +332 -0
  37. package/internal/auth/adc.go +108 -0
  38. package/internal/auth/apikey.go +67 -0
  39. package/internal/auth/factory.go +145 -0
  40. package/internal/auth/oauth2.go +227 -0
  41. package/internal/auth/store.go +216 -0
  42. package/internal/auth/types.go +79 -0
  43. package/internal/auth/vertex.go +138 -0
  44. package/internal/config/config.go +428 -0
  45. package/internal/config/policy.go +251 -0
  46. package/internal/context/builder.go +312 -0
  47. package/internal/detector/detector.go +204 -0
  48. package/internal/diffutil/diffutil.go +30 -0
  49. package/internal/fsutil/fsutil.go +35 -0
  50. package/internal/mcp/client.go +314 -0
  51. package/internal/mcp/manager.go +221 -0
  52. package/internal/policy/policy.go +89 -0
  53. package/internal/prompt/interactive.go +338 -0
  54. package/internal/registry/agent.go +201 -0
  55. package/internal/registry/tool.go +181 -0
  56. package/internal/scheduler/scheduler.go +250 -0
  57. package/internal/server/server.go +167 -0
  58. package/internal/tools/file.go +183 -0
  59. package/internal/tools/filesystem.go +286 -0
  60. package/internal/tools/git.go +355 -0
  61. package/internal/tools/memory.go +269 -0
  62. package/internal/tools/registry.go +49 -0
  63. package/internal/tools/search.go +230 -0
  64. package/internal/tools/shell.go +84 -0
  65. package/internal/websearch/search.go +40 -0
  66. package/internal/websearch/tavily.go +79 -0
  67. package/main.go +19 -0
  68. package/package.json +57 -0
  69. package/scripts/install.js +59 -0
  70. package/scripts/uninstall.js +28 -0
package/cmd/context.go ADDED
@@ -0,0 +1,111 @@
1
+ package cmd
2
+
3
+ import (
4
+ "fmt"
5
+ "os"
6
+
7
+ "github.com/ddhanush1/dcode/internal/context"
8
+ "github.com/spf13/cobra"
9
+ )
10
+
11
+ var (
12
+ contextListAll bool
13
+ contextAdd []string
14
+ contextRemove []string
15
+ )
16
+
17
+ var contextCmd = &cobra.Command{
18
+ Use: "context",
19
+ Short: "Manage context for AI operations",
20
+ Long: `Smart context management for better AI understanding
21
+
22
+ The context system helps DCode understand your codebase by:
23
+ • Auto-detecting relevant files
24
+ • Tracking dependencies and imports
25
+ • Building a knowledge graph
26
+ • Remembering conversation history
27
+
28
+ Subcommands:
29
+ analyze - Analyze project and build context
30
+ list - List current context files
31
+ clear - Clear context cache
32
+ `,
33
+ }
34
+
35
+ var contextAnalyzeCmd = &cobra.Command{
36
+ Use: "analyze",
37
+ Short: "Analyze project and build context",
38
+ RunE: func(cmd *cobra.Command, args []string) error {
39
+ wd, _ := os.Getwd()
40
+
41
+ fmt.Println("\033[1;36m🔍 Analyzing project...\033[0m\n")
42
+
43
+ builder := context.NewBuilder(wd)
44
+ projectCtx, err := builder.Build()
45
+ if err != nil {
46
+ return fmt.Errorf("failed to analyze: %w", err)
47
+ }
48
+
49
+ // Print detailed summary
50
+ fmt.Println(projectCtx.Summary)
51
+
52
+ fmt.Println("\n\033[90m💡 Use 'dcode agent' to interact with this project\033[0m")
53
+
54
+ return nil
55
+ },
56
+ }
57
+
58
+ var contextListCmd = &cobra.Command{
59
+ Use: "list",
60
+ Short: "List current context files",
61
+ RunE: func(cmd *cobra.Command, args []string) error {
62
+ wd, _ := os.Getwd()
63
+
64
+ builder := context.NewBuilder(wd)
65
+ projectCtx, err := builder.Build()
66
+ if err != nil {
67
+ return fmt.Errorf("failed to analyze: %w", err)
68
+ }
69
+
70
+ files := projectCtx.RelevantFiles
71
+
72
+ if len(files) == 0 {
73
+ fmt.Println("\033[90mNo files in context\033[0m")
74
+ return nil
75
+ }
76
+
77
+ fmt.Printf("\033[1;36mContext files (%d):\033[0m\n\n", len(files))
78
+ for i, f := range files {
79
+ if contextListAll || i < 20 {
80
+ fmt.Printf(" %3d. %.1f%% %s\n", i+1, f.Relevance*100, f.RelPath)
81
+ }
82
+ }
83
+
84
+ if !contextListAll && len(files) > 20 {
85
+ fmt.Printf("\n\033[90m... and %d more (use --all to show all)\033[0m\n", len(files)-20)
86
+ }
87
+
88
+ return nil
89
+ },
90
+ }
91
+
92
+ var contextClearCmd = &cobra.Command{
93
+ Use: "clear",
94
+ Short: "Clear context cache",
95
+ RunE: func(cmd *cobra.Command, args []string) error {
96
+ // For now, this is a no-op since we don't persist context yet
97
+ // In future: clear cache, embeddings, etc.
98
+ fmt.Println("\033[32m✓ Context cleared\033[0m")
99
+ return nil
100
+ },
101
+ }
102
+
103
+ func init() {
104
+ contextListCmd.Flags().BoolVarP(&contextListAll, "all", "a", false, "Show all files")
105
+
106
+ contextCmd.AddCommand(contextAnalyzeCmd)
107
+ contextCmd.AddCommand(contextListCmd)
108
+ contextCmd.AddCommand(contextClearCmd)
109
+
110
+ rootCmd.AddCommand(contextCmd)
111
+ }
package/cmd/edit.go ADDED
@@ -0,0 +1,116 @@
1
+ package cmd
2
+
3
+ import (
4
+ "context"
5
+ "fmt"
6
+ "os"
7
+ "path/filepath"
8
+ "strings"
9
+ "time"
10
+
11
+ "github.com/ddhanush1/dcode/internal/agent"
12
+ "github.com/ddhanush1/dcode/internal/fsutil"
13
+ "github.com/spf13/cobra"
14
+ )
15
+
16
+ var (
17
+ editFile string
18
+ editPrompt string
19
+ aiProvider string
20
+ aiModel string
21
+ useWebSearch bool
22
+ dryRun bool
23
+ )
24
+
25
+ var editCmd = &cobra.Command{
26
+ Use: "edit",
27
+ Short: "Edit code using AI",
28
+ Long: `Edit code intelligently using AI providers (OpenAI, Gemini, Claude).
29
+
30
+ Examples:
31
+ dcode edit --file main.go --prompt "Add error handling" --provider openai --model gpt-4
32
+ dcode edit --file app.py --prompt "Optimize this function" --provider gemini
33
+ dcode edit --file api.js --prompt "Add validation" --provider claude --search`,
34
+ RunE: func(cmd *cobra.Command, args []string) error {
35
+ if strings.TrimSpace(editFile) == "" {
36
+ return fmt.Errorf("--file is required")
37
+ }
38
+
39
+ // Allow overriding provider/model via flags.
40
+ if aiProvider != "" {
41
+ _ = os.Setenv("AI_PROVIDER", aiProvider)
42
+ }
43
+ if aiModel != "" {
44
+ _ = os.Setenv("AI_MODEL", aiModel)
45
+ }
46
+
47
+ content, err := fsutil.ReadFile(editFile)
48
+ if err != nil {
49
+ return err
50
+ }
51
+
52
+ ag, err := agent.New()
53
+ if err != nil {
54
+ return err
55
+ }
56
+
57
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
58
+ defer cancel()
59
+
60
+ resp, err := ag.Edit(ctx, agent.EditRequest{
61
+ Prompt: editPrompt,
62
+ Files: []agent.FileInput{{Path: filepath.ToSlash(editFile), Content: content}},
63
+ WebSearch: agent.WebSearchRequest{Enabled: useWebSearch},
64
+ })
65
+ if err != nil {
66
+ return err
67
+ }
68
+
69
+ if len(resp.Edits) == 0 {
70
+ fmt.Println("No edits returned.")
71
+ return nil
72
+ }
73
+
74
+ for _, e := range resp.Edits {
75
+ if filepath.Clean(e.Path) != filepath.Clean(filepath.ToSlash(editFile)) && filepath.Clean(e.Path) != filepath.Clean(editFile) {
76
+ fmt.Printf("Skipping unexpected edit path: %s\n", e.Path)
77
+ continue
78
+ }
79
+ if e.NewContent == content {
80
+ fmt.Println("No changes needed.")
81
+ continue
82
+ }
83
+
84
+ if dryRun {
85
+ fmt.Printf("--- %s (dry-run, not written) ---\n", editFile)
86
+ fmt.Println(e.NewContent)
87
+ continue
88
+ }
89
+
90
+ perm := fsutil.FilePermOrDefault(editFile, 0o644)
91
+ if err := fsutil.WriteFileAtomic(editFile, []byte(e.NewContent), perm); err != nil {
92
+ return err
93
+ }
94
+ fmt.Printf("Updated %s\n", editFile)
95
+ }
96
+
97
+ if strings.TrimSpace(resp.Explanation) != "" {
98
+ fmt.Println("\nExplanation:")
99
+ fmt.Println(resp.Explanation)
100
+ }
101
+
102
+ return nil
103
+ },
104
+ }
105
+
106
+ func init() {
107
+ editCmd.Flags().StringVarP(&editFile, "file", "f", "", "File to edit")
108
+ editCmd.Flags().StringVarP(&editPrompt, "prompt", "p", "", "Editing instructions (required)")
109
+ editCmd.Flags().StringVar(&aiProvider, "provider", "", "AI provider: openai, gemini, claude (default from .env)")
110
+ editCmd.Flags().StringVar(&aiModel, "model", "", "Model name (default from .env)")
111
+ editCmd.Flags().BoolVar(&useWebSearch, "search", false, "Enable web search for context")
112
+ editCmd.Flags().BoolVar(&dryRun, "dry-run", false, "Print new content but do not write")
113
+
114
+ editCmd.MarkFlagRequired("prompt")
115
+ rootCmd.AddCommand(editCmd)
116
+ }
package/cmd/env.go ADDED
@@ -0,0 +1,10 @@
1
+ package cmd
2
+
3
+ import "os"
4
+
5
+ func getEnv(key, fallback string) string {
6
+ if value := os.Getenv(key); value != "" {
7
+ return value
8
+ }
9
+ return fallback
10
+ }
package/cmd/fix.go ADDED
@@ -0,0 +1,145 @@
1
+ package cmd
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "fmt"
7
+ "os"
8
+ "os/exec"
9
+ "path/filepath"
10
+ "strings"
11
+ "time"
12
+
13
+ "github.com/ddhanush1/dcode/internal/agent"
14
+ "github.com/ddhanush1/dcode/internal/fsutil"
15
+ "github.com/spf13/cobra"
16
+ )
17
+
18
+ var (
19
+ fixFile string
20
+ fixPrompt string
21
+ fixCommand string
22
+ fixDryRun bool
23
+ )
24
+
25
+ var fixCmd = &cobra.Command{
26
+ Use: "fix",
27
+ Short: "Find and fix errors",
28
+ RunE: func(cmd *cobra.Command, args []string) error {
29
+ if strings.TrimSpace(fixFile) == "" {
30
+ return fmt.Errorf("--file is required")
31
+ }
32
+
33
+ content, err := fsutil.ReadFile(fixFile)
34
+ if err != nil {
35
+ return err
36
+ }
37
+
38
+ // Allow overriding provider/model via flags inherited from edit if set.
39
+ if aiProvider != "" {
40
+ _ = os.Setenv("AI_PROVIDER", aiProvider)
41
+ }
42
+ if aiModel != "" {
43
+ _ = os.Setenv("AI_MODEL", aiModel)
44
+ }
45
+
46
+ var testOutput string
47
+ if strings.TrimSpace(fixCommand) != "" {
48
+ out, err := runShellCommand(fixCommand)
49
+ testOutput = out
50
+ if err != nil {
51
+ // keep output; model can still try to fix
52
+ fmt.Printf("Command failed (continuing): %v\n", err)
53
+ }
54
+ } else {
55
+ // If this looks like a Go workspace, run tests by default.
56
+ if _, err := os.Stat("go.mod"); err == nil {
57
+ out, err := runShellCommand("go test ./...")
58
+ testOutput = out
59
+ if err != nil {
60
+ fmt.Printf("go test failed (continuing): %v\n", err)
61
+ }
62
+ }
63
+ }
64
+
65
+ ag, err := agent.New()
66
+ if err != nil {
67
+ return err
68
+ }
69
+
70
+ ctx, cancel := context.WithTimeout(context.Background(), 8*time.Minute)
71
+ defer cancel()
72
+
73
+ resp, err := ag.Fix(ctx, agent.FixRequest{
74
+ Prompt: fixPrompt,
75
+ Files: []agent.FileInput{{Path: filepath.ToSlash(fixFile), Content: content}},
76
+ TestOutput: testOutput,
77
+ })
78
+ if err != nil {
79
+ return err
80
+ }
81
+
82
+ for _, e := range resp.Edits {
83
+ if filepath.Clean(e.Path) != filepath.Clean(filepath.ToSlash(fixFile)) && filepath.Clean(e.Path) != filepath.Clean(fixFile) {
84
+ fmt.Printf("Skipping unexpected edit path: %s\n", e.Path)
85
+ continue
86
+ }
87
+ if e.NewContent == content {
88
+ fmt.Println("No changes needed.")
89
+ continue
90
+ }
91
+
92
+ if fixDryRun {
93
+ fmt.Printf("--- %s (dry-run, not written) ---\n", fixFile)
94
+ fmt.Println(e.NewContent)
95
+ continue
96
+ }
97
+
98
+ perm := fsutil.FilePermOrDefault(fixFile, 0o644)
99
+ if err := fsutil.WriteFileAtomic(fixFile, []byte(e.NewContent), perm); err != nil {
100
+ return err
101
+ }
102
+ fmt.Printf("Updated %s\n", fixFile)
103
+ }
104
+
105
+ if strings.TrimSpace(resp.Explanation) != "" {
106
+ fmt.Println("\nExplanation:")
107
+ fmt.Println(resp.Explanation)
108
+ }
109
+
110
+ return nil
111
+ },
112
+ }
113
+
114
+ func runShellCommand(command string) (string, error) {
115
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
116
+ defer cancel()
117
+
118
+ // Use `bash -lc` when available (WSL/Linux/mac). On Windows, users can pass a single command supported by their shell.
119
+ var cmd *exec.Cmd
120
+ if _, err := exec.LookPath("bash"); err == nil {
121
+ cmd = exec.CommandContext(ctx, "bash", "-lc", command)
122
+ } else {
123
+ parts := strings.Fields(command)
124
+ if len(parts) == 0 {
125
+ return "", fmt.Errorf("empty command")
126
+ }
127
+ cmd = exec.CommandContext(ctx, parts[0], parts[1:]...)
128
+ }
129
+
130
+ var buf bytes.Buffer
131
+ cmd.Stdout = &buf
132
+ cmd.Stderr = &buf
133
+ cmd.Dir = "."
134
+ cmd.Env = os.Environ()
135
+ err := cmd.Run()
136
+ return buf.String(), err
137
+ }
138
+
139
+ func init() {
140
+ fixCmd.Flags().StringVarP(&fixFile, "file", "f", "", "File to fix (required)")
141
+ fixCmd.Flags().StringVarP(&fixPrompt, "prompt", "p", "", "Optional extra instructions")
142
+ fixCmd.Flags().StringVar(&fixCommand, "command", "", "Command to run for error output (default: go test ./... if go.mod exists)")
143
+ fixCmd.Flags().BoolVar(&fixDryRun, "dry-run", false, "Print new content but do not write")
144
+ rootCmd.AddCommand(fixCmd)
145
+ }
package/cmd/gemini.go ADDED
@@ -0,0 +1,20 @@
1
+ package cmd
2
+
3
+ import (
4
+ "os"
5
+
6
+ "github.com/spf13/cobra"
7
+ )
8
+
9
+ var geminiCmd = &cobra.Command{
10
+ Use: "gemini",
11
+ Short: "Start agent with Google Gemini (shortcut)",
12
+ RunE: func(cmd *cobra.Command, args []string) error {
13
+ _ = os.Setenv("AI_PROVIDER", "gemini")
14
+ return agentV2Cmd.RunE(cmd, args)
15
+ },
16
+ }
17
+
18
+ func init() {
19
+ rootCmd.AddCommand(geminiCmd)
20
+ }
@@ -0,0 +1,47 @@
1
+ package cmd
2
+
3
+ import (
4
+ "fmt"
5
+ "github.com/spf13/cobra"
6
+ )
7
+
8
+ var generateCmd = &cobra.Command{
9
+ Use: "generate",
10
+ Short: "Generate code using AI",
11
+ Long: `Generate code from natural language descriptions using AI.
12
+
13
+ Examples:
14
+ dcode generate --prompt "REST API with authentication" --language go --provider openai
15
+ dcode generate --prompt "Binary search algorithm" --language python --provider gemini
16
+ dcode generate --prompt "React component for login form" --language typescript --provider claude`,
17
+ RunE: func(cmd *cobra.Command, args []string) error {
18
+ genPrompt, _ := cmd.Flags().GetString("prompt")
19
+ genLang, _ := cmd.Flags().GetString("language")
20
+ provider, _ := cmd.Flags().GetString("provider")
21
+ model, _ := cmd.Flags().GetString("model")
22
+
23
+ if provider == "" {
24
+ provider = getEnv("AI_PROVIDER", "openai")
25
+ }
26
+ if model == "" {
27
+ model = getEnv("AI_MODEL", "gpt-4")
28
+ }
29
+
30
+ fmt.Printf(" Using %s (%s)\n", provider, model)
31
+ fmt.Printf(" Generating %s code...\n", genLang)
32
+ fmt.Printf(" Prompt: %s\n\n", genPrompt)
33
+
34
+ fmt.Println("Generated code will appear here...")
35
+ return nil
36
+ },
37
+ }
38
+
39
+ func init() {
40
+ generateCmd.Flags().StringP("prompt", "p", "", "Description of code to generate (required)")
41
+ generateCmd.Flags().StringP("language", "l", "go", "Programming language")
42
+ generateCmd.Flags().String("provider", "", "AI provider: openai, gemini, claude")
43
+ generateCmd.Flags().String("model", "", "Model name")
44
+
45
+ generateCmd.MarkFlagRequired("prompt")
46
+ rootCmd.AddCommand(generateCmd)
47
+ }
@@ -0,0 +1,33 @@
1
+ package cmd
2
+
3
+ import (
4
+ "fmt"
5
+
6
+ "github.com/ddhanush1/dcode/internal/prompt"
7
+ "github.com/spf13/cobra"
8
+ )
9
+
10
+ var interactiveCmd = &cobra.Command{
11
+ Use: "interactive",
12
+ Short: "Start interactive mode with slash command suggestions",
13
+ Long: `Start an interactive session with a prompt that shows command suggestions
14
+ when you type /. Use arrow keys to navigate, Tab or Enter to select.
15
+
16
+ Features:
17
+ • Type / to see all available commands
18
+ • Autocomplete filters as you type
19
+ • Use ↑↓ arrow keys to navigate suggestions
20
+ • Press Tab or Enter to select a command
21
+ • Type regular prompts without / for normal input`,
22
+ Run: func(cmd *cobra.Command, args []string) {
23
+ fmt.Println("Starting interactive mode...")
24
+ fmt.Println()
25
+ if err := prompt.StartInteractive(); err != nil {
26
+ fmt.Printf("Error: %v\n", err)
27
+ }
28
+ },
29
+ }
30
+
31
+ func init() {
32
+ rootCmd.AddCommand(interactiveCmd)
33
+ }
package/cmd/mcp.go ADDED
@@ -0,0 +1,196 @@
1
+ package cmd
2
+
3
+ import (
4
+ "fmt"
5
+
6
+ "github.com/spf13/cobra"
7
+ "github.com/ddhanush1/dcode/internal/mcp"
8
+ "github.com/ddhanush1/dcode/internal/registry"
9
+ )
10
+
11
+ var mcpCmd = &cobra.Command{
12
+ Use: "mcp",
13
+ Short: "Manage MCP (Model Context Protocol) servers",
14
+ Long: `Manage MCP servers that provide additional tools, resources, and prompts.
15
+
16
+ MCP servers extend dcode's capabilities by providing:
17
+ - External tools (file systems, APIs, databases)
18
+ - Resources (documents, URLs, data)
19
+ - Prompts (reusable templates)`,
20
+ }
21
+
22
+ var mcpListCmd = &cobra.Command{
23
+ Use: "list",
24
+ Short: "List all configured MCP servers",
25
+ Run: func(cmd *cobra.Command, args []string) {
26
+ // Create tool registry (needed for manager)
27
+ toolRegistry := registry.NewToolRegistry()
28
+
29
+ // Create MCP manager
30
+ manager := mcp.NewMCPManager(toolRegistry)
31
+
32
+ // List servers
33
+ servers := manager.ListServers()
34
+
35
+ if len(servers) == 0 {
36
+ fmt.Println("No MCP servers configured.")
37
+ fmt.Println("\nAdd a server with: dcode mcp add <url>")
38
+ return
39
+ }
40
+
41
+ fmt.Println("╔════════════════════════════════════════════════════════════╗")
42
+ fmt.Println("║ MCP Servers ║")
43
+ fmt.Println("╚════════════════════════════════════════════════════════════╝")
44
+ fmt.Println()
45
+
46
+ for _, server := range servers {
47
+ status := "❌ Disabled"
48
+ if server.Enabled {
49
+ status = "✅ Enabled"
50
+ }
51
+
52
+ fmt.Printf("📡 %s (%s)\n", server.Name, server.ID)
53
+ fmt.Printf(" URL: %s\n", server.URL)
54
+ fmt.Printf(" Status: %s\n", status)
55
+ fmt.Println()
56
+ }
57
+
58
+ fmt.Printf("Total: %d server(s)\n", len(servers))
59
+ },
60
+ }
61
+
62
+ var mcpAddCmd = &cobra.Command{
63
+ Use: "add <url>",
64
+ Short: "Add a new MCP server",
65
+ Args: cobra.ExactArgs(1),
66
+ Run: func(cmd *cobra.Command, args []string) {
67
+ url := args[0]
68
+ name, _ := cmd.Flags().GetString("name")
69
+ id, _ := cmd.Flags().GetString("id")
70
+
71
+ // Generate ID if not provided
72
+ if id == "" {
73
+ id = fmt.Sprintf("mcp_%d", len(args))
74
+ }
75
+
76
+ // Use URL as name if not provided
77
+ if name == "" {
78
+ name = url
79
+ }
80
+
81
+ // Create tool registry
82
+ toolRegistry := registry.NewToolRegistry()
83
+
84
+ // Create MCP manager
85
+ manager := mcp.NewMCPManager(toolRegistry)
86
+
87
+ // Add server
88
+ server := &mcp.MCPServer{
89
+ ID: id,
90
+ Name: name,
91
+ URL: url,
92
+ Enabled: true,
93
+ }
94
+
95
+ if err := manager.AddServer(server); err != nil {
96
+ fmt.Printf("❌ Failed to add server: %v\n", err)
97
+ return
98
+ }
99
+
100
+ fmt.Printf("✅ Added MCP server: %s\n", name)
101
+ fmt.Printf(" ID: %s\n", id)
102
+ fmt.Printf(" URL: %s\n", url)
103
+ fmt.Println("\nDiscovering tools...")
104
+
105
+ // Enable and discover tools
106
+ if err := manager.EnableServer(id); err != nil {
107
+ fmt.Printf("⚠️ Warning: failed to discover tools: %v\n", err)
108
+ } else {
109
+ fmt.Println("✅ Tools discovered and registered")
110
+ }
111
+ },
112
+ }
113
+
114
+ var mcpRemoveCmd = &cobra.Command{
115
+ Use: "remove <id>",
116
+ Short: "Remove an MCP server",
117
+ Args: cobra.ExactArgs(1),
118
+ Run: func(cmd *cobra.Command, args []string) {
119
+ id := args[0]
120
+
121
+ // Create tool registry
122
+ toolRegistry := registry.NewToolRegistry()
123
+
124
+ // Create MCP manager
125
+ manager := mcp.NewMCPManager(toolRegistry)
126
+
127
+ // Remove server
128
+ if err := manager.RemoveServer(id); err != nil {
129
+ fmt.Printf("❌ Failed to remove server: %v\n", err)
130
+ return
131
+ }
132
+
133
+ fmt.Printf("✅ Removed MCP server: %s\n", id)
134
+ },
135
+ }
136
+
137
+ var mcpEnableCmd = &cobra.Command{
138
+ Use: "enable <id>",
139
+ Short: "Enable an MCP server",
140
+ Args: cobra.ExactArgs(1),
141
+ Run: func(cmd *cobra.Command, args []string) {
142
+ id := args[0]
143
+
144
+ // Create tool registry
145
+ toolRegistry := registry.NewToolRegistry()
146
+
147
+ // Create MCP manager
148
+ manager := mcp.NewMCPManager(toolRegistry)
149
+
150
+ // Enable server
151
+ if err := manager.EnableServer(id); err != nil {
152
+ fmt.Printf("❌ Failed to enable server: %v\n", err)
153
+ return
154
+ }
155
+
156
+ fmt.Printf("✅ Enabled MCP server: %s\n", id)
157
+ },
158
+ }
159
+
160
+ var mcpDisableCmd = &cobra.Command{
161
+ Use: "disable <id>",
162
+ Short: "Disable an MCP server",
163
+ Args: cobra.ExactArgs(1),
164
+ Run: func(cmd *cobra.Command, args []string) {
165
+ id := args[0]
166
+
167
+ // Create tool registry
168
+ toolRegistry := registry.NewToolRegistry()
169
+
170
+ // Create MCP manager
171
+ manager := mcp.NewMCPManager(toolRegistry)
172
+
173
+ // Disable server
174
+ if err := manager.DisableServer(id); err != nil {
175
+ fmt.Printf("❌ Failed to disable server: %v\n", err)
176
+ return
177
+ }
178
+
179
+ fmt.Printf("✅ Disabled MCP server: %s\n", id)
180
+ },
181
+ }
182
+
183
+ func init() {
184
+ rootCmd.AddCommand(mcpCmd)
185
+
186
+ // Add subcommands
187
+ mcpCmd.AddCommand(mcpListCmd)
188
+ mcpCmd.AddCommand(mcpAddCmd)
189
+ mcpCmd.AddCommand(mcpRemoveCmd)
190
+ mcpCmd.AddCommand(mcpEnableCmd)
191
+ mcpCmd.AddCommand(mcpDisableCmd)
192
+
193
+ // Add flags
194
+ mcpAddCmd.Flags().String("name", "", "Server name")
195
+ mcpAddCmd.Flags().String("id", "", "Server ID (auto-generated if not provided)")
196
+ }
package/cmd/patch.go ADDED
@@ -0,0 +1,19 @@
1
+ package cmd
2
+
3
+ import (
4
+ "fmt"
5
+ "github.com/spf13/cobra"
6
+ )
7
+
8
+ var patchCmd = &cobra.Command{
9
+ Use: "patch",
10
+ Short: "Generate or apply patches",
11
+ RunE: func(cmd *cobra.Command, args []string) error {
12
+ fmt.Println("Patch operations - coming soon!")
13
+ return nil
14
+ },
15
+ }
16
+
17
+ func init() {
18
+ rootCmd.AddCommand(patchCmd)
19
+ }