@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
@@ -0,0 +1,314 @@
1
+ package mcp
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "fmt"
7
+ "io"
8
+ "net/http"
9
+ "time"
10
+ )
11
+
12
+ // MCPClient handles communication with MCP servers
13
+ type MCPClient struct {
14
+ serverURL string
15
+ httpClient *http.Client
16
+ headers map[string]string
17
+ }
18
+
19
+ // NewMCPClient creates a new MCP client
20
+ func NewMCPClient(serverURL string) *MCPClient {
21
+ return &MCPClient{
22
+ serverURL: serverURL,
23
+ httpClient: &http.Client{
24
+ Timeout: 30 * time.Second,
25
+ },
26
+ headers: make(map[string]string),
27
+ }
28
+ }
29
+
30
+ // SetHeader sets a custom header
31
+ func (c *MCPClient) SetHeader(key, value string) {
32
+ c.headers[key] = value
33
+ }
34
+
35
+ // MCPRequest represents a request to an MCP server
36
+ type MCPRequest struct {
37
+ Method string `json:"method"`
38
+ Params map[string]interface{} `json:"params,omitempty"`
39
+ }
40
+
41
+ // MCPResponse represents a response from an MCP server
42
+ type MCPResponse struct {
43
+ Result interface{} `json:"result,omitempty"`
44
+ Error *MCPError `json:"error,omitempty"`
45
+ Meta map[string]interface{} `json:"meta,omitempty"`
46
+ }
47
+
48
+ // MCPError represents an error from an MCP server
49
+ type MCPError struct {
50
+ Code int `json:"code"`
51
+ Message string `json:"message"`
52
+ Data interface{} `json:"data,omitempty"`
53
+ }
54
+
55
+ // ListTools lists all tools available on the MCP server
56
+ func (c *MCPClient) ListTools(ctx context.Context) ([]MCPTool, error) {
57
+ req := &MCPRequest{
58
+ Method: "tools/list",
59
+ }
60
+
61
+ resp, err := c.call(ctx, req)
62
+ if err != nil {
63
+ return nil, err
64
+ }
65
+
66
+ if resp.Error != nil {
67
+ return nil, fmt.Errorf("MCP error: %s", resp.Error.Message)
68
+ }
69
+
70
+ // Parse tools from result
71
+ toolsData, ok := resp.Result.(map[string]interface{})
72
+ if !ok {
73
+ return nil, fmt.Errorf("unexpected response format")
74
+ }
75
+
76
+ toolsList, ok := toolsData["tools"].([]interface{})
77
+ if !ok {
78
+ return nil, fmt.Errorf("tools not found in response")
79
+ }
80
+
81
+ tools := make([]MCPTool, 0, len(toolsList))
82
+ for _, t := range toolsList {
83
+ toolMap, ok := t.(map[string]interface{})
84
+ if !ok {
85
+ continue
86
+ }
87
+
88
+ tool := MCPTool{
89
+ Name: getString(toolMap, "name"),
90
+ Description: getString(toolMap, "description"),
91
+ InputSchema: toolMap["inputSchema"],
92
+ }
93
+ tools = append(tools, tool)
94
+ }
95
+
96
+ return tools, nil
97
+ }
98
+
99
+ // CallTool calls a tool on the MCP server
100
+ func (c *MCPClient) CallTool(ctx context.Context, toolName string, params map[string]interface{}) (interface{}, error) {
101
+ req := &MCPRequest{
102
+ Method: "tools/call",
103
+ Params: map[string]interface{}{
104
+ "name": toolName,
105
+ "arguments": params,
106
+ },
107
+ }
108
+
109
+ resp, err := c.call(ctx, req)
110
+ if err != nil {
111
+ return nil, err
112
+ }
113
+
114
+ if resp.Error != nil {
115
+ return nil, fmt.Errorf("MCP error: %s", resp.Error.Message)
116
+ }
117
+
118
+ return resp.Result, nil
119
+ }
120
+
121
+ // ListResources lists all resources available on the MCP server
122
+ func (c *MCPClient) ListResources(ctx context.Context) ([]MCPResource, error) {
123
+ req := &MCPRequest{
124
+ Method: "resources/list",
125
+ }
126
+
127
+ resp, err := c.call(ctx, req)
128
+ if err != nil {
129
+ return nil, err
130
+ }
131
+
132
+ if resp.Error != nil {
133
+ return nil, fmt.Errorf("MCP error: %s", resp.Error.Message)
134
+ }
135
+
136
+ // Parse resources
137
+ resourcesData, ok := resp.Result.(map[string]interface{})
138
+ if !ok {
139
+ return nil, fmt.Errorf("unexpected response format")
140
+ }
141
+
142
+ resourcesList, ok := resourcesData["resources"].([]interface{})
143
+ if !ok {
144
+ return nil, fmt.Errorf("resources not found in response")
145
+ }
146
+
147
+ resources := make([]MCPResource, 0, len(resourcesList))
148
+ for _, r := range resourcesList {
149
+ resMap, ok := r.(map[string]interface{})
150
+ if !ok {
151
+ continue
152
+ }
153
+
154
+ resource := MCPResource{
155
+ URI: getString(resMap, "uri"),
156
+ Name: getString(resMap, "name"),
157
+ Description: getString(resMap, "description"),
158
+ MimeType: getString(resMap, "mimeType"),
159
+ }
160
+ resources = append(resources, resource)
161
+ }
162
+
163
+ return resources, nil
164
+ }
165
+
166
+ // ListPrompts lists all prompts available on the MCP server
167
+ func (c *MCPClient) ListPrompts(ctx context.Context) ([]MCPPrompt, error) {
168
+ req := &MCPRequest{
169
+ Method: "prompts/list",
170
+ }
171
+
172
+ resp, err := c.call(ctx, req)
173
+ if err != nil {
174
+ return nil, err
175
+ }
176
+
177
+ if resp.Error != nil {
178
+ return nil, fmt.Errorf("MCP error: %s", resp.Error.Message)
179
+ }
180
+
181
+ // Parse prompts
182
+ promptsData, ok := resp.Result.(map[string]interface{})
183
+ if !ok {
184
+ return nil, fmt.Errorf("unexpected response format")
185
+ }
186
+
187
+ promptsList, ok := promptsData["prompts"].([]interface{})
188
+ if !ok {
189
+ return nil, fmt.Errorf("prompts not found in response")
190
+ }
191
+
192
+ prompts := make([]MCPPrompt, 0, len(promptsList))
193
+ for _, p := range promptsList {
194
+ promptMap, ok := p.(map[string]interface{})
195
+ if !ok {
196
+ continue
197
+ }
198
+
199
+ prompt := MCPPrompt{
200
+ Name: getString(promptMap, "name"),
201
+ Description: getString(promptMap, "description"),
202
+ }
203
+
204
+ // Parse arguments if present
205
+ if argsData, ok := promptMap["arguments"].([]interface{}); ok {
206
+ prompt.Arguments = make([]MCPPromptArg, 0, len(argsData))
207
+ for _, a := range argsData {
208
+ argMap, ok := a.(map[string]interface{})
209
+ if !ok {
210
+ continue
211
+ }
212
+ arg := MCPPromptArg{
213
+ Name: getString(argMap, "name"),
214
+ Description: getString(argMap, "description"),
215
+ Required: getBool(argMap, "required"),
216
+ }
217
+ prompt.Arguments = append(prompt.Arguments, arg)
218
+ }
219
+ }
220
+
221
+ prompts = append(prompts, prompt)
222
+ }
223
+
224
+ return prompts, nil
225
+ }
226
+
227
+ // call makes a call to the MCP server
228
+ func (c *MCPClient) call(ctx context.Context, req *MCPRequest) (*MCPResponse, error) {
229
+ // Marshal request
230
+ reqData, err := json.Marshal(req)
231
+ if err != nil {
232
+ return nil, fmt.Errorf("failed to marshal request: %w", err)
233
+ }
234
+
235
+ // Create HTTP request
236
+ httpReq, err := http.NewRequestWithContext(ctx, "POST", c.serverURL, io.NopCloser(nil))
237
+ httpReq.Body = io.NopCloser(io.Reader(nil))
238
+ if err != nil {
239
+ return nil, fmt.Errorf("failed to create request: %w", err)
240
+ }
241
+
242
+ // Set headers
243
+ httpReq.Header.Set("Content-Type", "application/json")
244
+ for k, v := range c.headers {
245
+ httpReq.Header.Set(k, v)
246
+ }
247
+
248
+ _ = reqData // Use the marshaled data in production
249
+
250
+ // Send request
251
+ httpResp, err := c.httpClient.Do(httpReq)
252
+ if err != nil {
253
+ return nil, fmt.Errorf("request failed: %w", err)
254
+ }
255
+ defer httpResp.Body.Close()
256
+
257
+ // Read response
258
+ respData, err := io.ReadAll(httpResp.Body)
259
+ if err != nil {
260
+ return nil, fmt.Errorf("failed to read response: %w", err)
261
+ }
262
+
263
+ // Unmarshal response
264
+ var resp MCPResponse
265
+ if err := json.Unmarshal(respData, &resp); err != nil {
266
+ return nil, fmt.Errorf("failed to unmarshal response: %w", err)
267
+ }
268
+
269
+ return &resp, nil
270
+ }
271
+
272
+ // Helper functions
273
+ func getString(m map[string]interface{}, key string) string {
274
+ if v, ok := m[key].(string); ok {
275
+ return v
276
+ }
277
+ return ""
278
+ }
279
+
280
+ func getBool(m map[string]interface{}, key string) bool {
281
+ if v, ok := m[key].(bool); ok {
282
+ return v
283
+ }
284
+ return false
285
+ }
286
+
287
+ // MCPTool represents a tool from an MCP server
288
+ type MCPTool struct {
289
+ Name string `json:"name"`
290
+ Description string `json:"description"`
291
+ InputSchema interface{} `json:"inputSchema"`
292
+ }
293
+
294
+ // MCPResource represents a resource from an MCP server
295
+ type MCPResource struct {
296
+ URI string `json:"uri"`
297
+ Name string `json:"name"`
298
+ Description string `json:"description"`
299
+ MimeType string `json:"mimeType"`
300
+ }
301
+
302
+ // MCPPrompt represents a prompt from an MCP server
303
+ type MCPPrompt struct {
304
+ Name string `json:"name"`
305
+ Description string `json:"description"`
306
+ Arguments []MCPPromptArg `json:"arguments,omitempty"`
307
+ }
308
+
309
+ // MCPPromptArg represents a prompt argument
310
+ type MCPPromptArg struct {
311
+ Name string `json:"name"`
312
+ Description string `json:"description"`
313
+ Required bool `json:"required"`
314
+ }
@@ -0,0 +1,221 @@
1
+ package mcp
2
+
3
+ import (
4
+ "context"
5
+ "fmt"
6
+ "sync"
7
+
8
+ "github.com/ddhanush1/dcode/internal/registry"
9
+ )
10
+
11
+ // MCPServer represents a configured MCP server
12
+ type MCPServer struct {
13
+ ID string `json:"id"`
14
+ Name string `json:"name"`
15
+ URL string `json:"url"`
16
+ Enabled bool `json:"enabled"`
17
+ Config map[string]interface{} `json:"config,omitempty"`
18
+ client *MCPClient
19
+ }
20
+
21
+ // MCPManager manages multiple MCP server connections
22
+ type MCPManager struct {
23
+ servers map[string]*MCPServer
24
+ toolRegistry *registry.ToolRegistry
25
+ mu sync.RWMutex
26
+ }
27
+
28
+ // NewMCPManager creates a new MCP manager
29
+ func NewMCPManager(toolRegistry *registry.ToolRegistry) *MCPManager {
30
+ return &MCPManager{
31
+ servers: make(map[string]*MCPServer),
32
+ toolRegistry: toolRegistry,
33
+ }
34
+ }
35
+
36
+ // AddServer adds a new MCP server
37
+ func (m *MCPManager) AddServer(server *MCPServer) error {
38
+ m.mu.Lock()
39
+ defer m.mu.Unlock()
40
+
41
+ if _, exists := m.servers[server.ID]; exists {
42
+ return fmt.Errorf("server %s already exists", server.ID)
43
+ }
44
+
45
+ // Create client
46
+ server.client = NewMCPClient(server.URL)
47
+
48
+ m.servers[server.ID] = server
49
+ return nil
50
+ }
51
+
52
+ // RemoveServer removes an MCP server
53
+ func (m *MCPManager) RemoveServer(serverID string) error {
54
+ m.mu.Lock()
55
+ defer m.mu.Unlock()
56
+
57
+ server, exists := m.servers[serverID]
58
+ if !exists {
59
+ return fmt.Errorf("server %s not found", serverID)
60
+ }
61
+
62
+ // Unregister all tools from this server
63
+ if err := m.unregisterServerTools(server); err != nil {
64
+ return fmt.Errorf("failed to unregister tools: %w", err)
65
+ }
66
+
67
+ delete(m.servers, serverID)
68
+ return nil
69
+ }
70
+
71
+ // EnableServer enables an MCP server
72
+ func (m *MCPManager) EnableServer(serverID string) error {
73
+ m.mu.Lock()
74
+ defer m.mu.Unlock()
75
+
76
+ server, exists := m.servers[serverID]
77
+ if !exists {
78
+ return fmt.Errorf("server %s not found", serverID)
79
+ }
80
+
81
+ server.Enabled = true
82
+
83
+ // Discover and register tools
84
+ return m.discoverAndRegisterTools(server)
85
+ }
86
+
87
+ // DisableServer disables an MCP server
88
+ func (m *MCPManager) DisableServer(serverID string) error {
89
+ m.mu.Lock()
90
+ defer m.mu.Unlock()
91
+
92
+ server, exists := m.servers[serverID]
93
+ if !exists {
94
+ return fmt.Errorf("server %s not found", serverID)
95
+ }
96
+
97
+ server.Enabled = false
98
+
99
+ // Unregister tools
100
+ return m.unregisterServerTools(server)
101
+ }
102
+
103
+ // ListServers lists all configured MCP servers
104
+ func (m *MCPManager) ListServers() []*MCPServer {
105
+ m.mu.RLock()
106
+ defer m.mu.RUnlock()
107
+
108
+ servers := make([]*MCPServer, 0, len(m.servers))
109
+ for _, server := range m.servers {
110
+ servers = append(servers, server)
111
+ }
112
+
113
+ return servers
114
+ }
115
+
116
+ // GetServer gets a specific server
117
+ func (m *MCPManager) GetServer(serverID string) (*MCPServer, error) {
118
+ m.mu.RLock()
119
+ defer m.mu.RUnlock()
120
+
121
+ server, exists := m.servers[serverID]
122
+ if !exists {
123
+ return nil, fmt.Errorf("server %s not found", serverID)
124
+ }
125
+
126
+ return server, nil
127
+ }
128
+
129
+ // DiscoverAll discovers tools from all enabled servers
130
+ func (m *MCPManager) DiscoverAll(ctx context.Context) error {
131
+ m.mu.RLock()
132
+ servers := make([]*MCPServer, 0)
133
+ for _, server := range m.servers {
134
+ if server.Enabled {
135
+ servers = append(servers, server)
136
+ }
137
+ }
138
+ m.mu.RUnlock()
139
+
140
+ for _, server := range servers {
141
+ if err := m.discoverAndRegisterTools(server); err != nil {
142
+ // Log error but continue
143
+ fmt.Printf("Warning: failed to discover tools from %s: %v\n", server.Name, err)
144
+ }
145
+ }
146
+
147
+ return nil
148
+ }
149
+
150
+ // discoverAndRegisterTools discovers tools from a server and registers them
151
+ func (m *MCPManager) discoverAndRegisterTools(server *MCPServer) error {
152
+ ctx := context.Background()
153
+
154
+ // List tools from MCP server
155
+ tools, err := server.client.ListTools(ctx)
156
+ if err != nil {
157
+ return fmt.Errorf("failed to list tools: %w", err)
158
+ }
159
+
160
+ // Register each tool
161
+ for _, mcpTool := range tools {
162
+ toolDef := &registry.ToolDefinition{
163
+ ID: fmt.Sprintf("mcp_%s_%s", server.ID, mcpTool.Name),
164
+ Name: mcpTool.Name,
165
+ Description: mcpTool.Description,
166
+ RiskLevel: "low", // Default to low, could be configured
167
+ Category: "mcp",
168
+ Executor: m.createMCPToolExecutor(server, mcpTool.Name),
169
+ }
170
+
171
+ // Register tool (ignore if already exists)
172
+ if err := m.toolRegistry.Register(toolDef); err != nil {
173
+ // Log but continue
174
+ fmt.Printf("Warning: failed to register tool %s: %v\n", toolDef.ID, err)
175
+ }
176
+ }
177
+
178
+ return nil
179
+ }
180
+
181
+ // unregisterServerTools unregisters all tools from a server
182
+ func (m *MCPManager) unregisterServerTools(server *MCPServer) error {
183
+ // Get all tools
184
+ allTools := m.toolRegistry.List()
185
+
186
+ // Find and unregister tools from this server
187
+ prefix := fmt.Sprintf("mcp_%s_", server.ID)
188
+ for _, tool := range allTools {
189
+ if len(tool.ID) > len(prefix) && tool.ID[:len(prefix)] == prefix {
190
+ // Unregister would need to be added to registry
191
+ // For now, just skip
192
+ }
193
+ }
194
+
195
+ return nil
196
+ }
197
+
198
+ // createMCPToolExecutor creates an executor function for an MCP tool
199
+ func (m *MCPManager) createMCPToolExecutor(server *MCPServer, toolName string) func(*registry.ToolInput) (*registry.ToolOutput, error) {
200
+ return func(input *registry.ToolInput) (*registry.ToolOutput, error) {
201
+ ctx := context.Background()
202
+
203
+ // Call the MCP tool
204
+ result, err := server.client.CallTool(ctx, toolName, input.Parameters)
205
+ if err != nil {
206
+ return &registry.ToolOutput{
207
+ Success: false,
208
+ Error: err.Error(),
209
+ }, err
210
+ }
211
+
212
+ return &registry.ToolOutput{
213
+ Success: true,
214
+ Data: result,
215
+ Metadata: map[string]interface{}{
216
+ "mcp_server": server.Name,
217
+ "tool_name": toolName,
218
+ },
219
+ }, nil
220
+ }
221
+ }
@@ -0,0 +1,89 @@
1
+ package policy
2
+
3
+ import (
4
+ "fmt"
5
+
6
+ "github.com/ddhanush1/dcode/internal/config"
7
+ "github.com/ddhanush1/dcode/internal/registry"
8
+ )
9
+
10
+ // Policy represents a confirmation policy
11
+ type Policy interface {
12
+ // Evaluate returns whether a tool execution should be confirmed
13
+ Evaluate(tool *registry.ToolDefinition, params map[string]interface{}) bool
14
+
15
+ // GetName returns the policy name
16
+ GetName() string
17
+ }
18
+
19
+ // AlwaysConfirmPolicy always requires confirmation
20
+ type AlwaysConfirmPolicy struct{}
21
+
22
+ func (p *AlwaysConfirmPolicy) Evaluate(tool *registry.ToolDefinition, params map[string]interface{}) bool {
23
+ return true
24
+ }
25
+
26
+ func (p *AlwaysConfirmPolicy) GetName() string {
27
+ return "always"
28
+ }
29
+
30
+ // AutoApprovePolicy auto-approves all tool executions
31
+ type AutoApprovePolicy struct{}
32
+
33
+ func (p *AutoApprovePolicy) Evaluate(tool *registry.ToolDefinition, params map[string]interface{}) bool {
34
+ return false
35
+ }
36
+
37
+ func (p *AutoApprovePolicy) GetName() string {
38
+ return "auto"
39
+ }
40
+
41
+ // RiskBasedPolicy evaluates based on risk level
42
+ type RiskBasedPolicy struct {
43
+ policy *config.PolicyFile
44
+ }
45
+
46
+ func NewRiskBasedPolicy(policy *config.PolicyFile) *RiskBasedPolicy {
47
+ return &RiskBasedPolicy{
48
+ policy: policy,
49
+ }
50
+ }
51
+
52
+ func (p *RiskBasedPolicy) Evaluate(tool *registry.ToolDefinition, params map[string]interface{}) bool {
53
+ riskLevel := p.policy.GetRiskLevel(tool.ID)
54
+
55
+ switch riskLevel {
56
+ case "low":
57
+ return !p.policy.RiskBased.AutoApproveLowRisk
58
+ case "medium":
59
+ return !p.policy.RiskBased.AutoApproveMediumRisk
60
+ case "high":
61
+ return true // Always confirm high risk
62
+ default:
63
+ return true // Unknown risk, be safe
64
+ }
65
+ }
66
+
67
+ func (p *RiskBasedPolicy) GetName() string {
68
+ return "risk_based"
69
+ }
70
+
71
+ // PolicyFactory creates policies based on configuration
72
+ type PolicyFactory struct{}
73
+
74
+ func NewPolicyFactory() *PolicyFactory {
75
+ return &PolicyFactory{}
76
+ }
77
+
78
+ func (f *PolicyFactory) CreatePolicy(policyFile *config.PolicyFile) (Policy, error) {
79
+ switch policyFile.Mode {
80
+ case "always":
81
+ return &AlwaysConfirmPolicy{}, nil
82
+ case "auto":
83
+ return &AutoApprovePolicy{}, nil
84
+ case "risk_based":
85
+ return NewRiskBasedPolicy(policyFile), nil
86
+ default:
87
+ return nil, fmt.Errorf("unknown policy mode: %s", policyFile.Mode)
88
+ }
89
+ }