@dcode-dev/dcode-cli 1.0.1 ā 1.0.3
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.
- package/bin/dcode-bin +0 -0
- package/cmd/agent_v2.go +53 -1
- package/cmd/model.go +159 -0
- package/cmd/switch.go +5 -13
- package/internal/config/config.go +67 -14
- package/package.json +1 -1
package/bin/dcode-bin
CHANGED
|
Binary file
|
package/cmd/agent_v2.go
CHANGED
|
@@ -79,7 +79,7 @@ func runAgentV2(cmd *cobra.Command, args []string) error {
|
|
|
79
79
|
// Set default models
|
|
80
80
|
switch provider {
|
|
81
81
|
case "gemini":
|
|
82
|
-
cfg.Model.Model = "gemini-2.
|
|
82
|
+
cfg.Model.Model = "gemini-2.5-flash"
|
|
83
83
|
case "openai":
|
|
84
84
|
cfg.Model.Model = "gpt-4"
|
|
85
85
|
case "copilot":
|
|
@@ -365,6 +365,7 @@ func handleCommand(input string, agentManager *agents.AgentManager, toolRegistry
|
|
|
365
365
|
fmt.Println("\nAvailable Commands:")
|
|
366
366
|
fmt.Println(" /help, /h - Show this help")
|
|
367
367
|
fmt.Println(" /agent - List and switch agents")
|
|
368
|
+
fmt.Println(" /model - Change AI model")
|
|
368
369
|
fmt.Println(" /tools - List available tools")
|
|
369
370
|
fmt.Println(" /auth - Show authentication status")
|
|
370
371
|
fmt.Println(" /clear - Clear conversation history")
|
|
@@ -402,6 +403,57 @@ func handleCommand(input string, agentManager *agents.AgentManager, toolRegistry
|
|
|
402
403
|
}
|
|
403
404
|
fmt.Println()
|
|
404
405
|
return true, true
|
|
406
|
+
|
|
407
|
+
case "/model":
|
|
408
|
+
// Show current model and allow changing
|
|
409
|
+
cfg, err := config.LoadConfig()
|
|
410
|
+
if err != nil {
|
|
411
|
+
fmt.Printf("ā Error loading config: %v\n", err)
|
|
412
|
+
return true, true
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
provider := cfg.Model.Provider
|
|
416
|
+
currentModel := cfg.Model.Model
|
|
417
|
+
|
|
418
|
+
fmt.Printf("\nš¤ Current: %s (%s)\n\n", currentModel, provider)
|
|
419
|
+
|
|
420
|
+
// Show available models
|
|
421
|
+
models := map[string][]string{
|
|
422
|
+
"gemini": {"gemini-2.5-flash", "gemini-2.0-flash-exp", "gemini-1.5-pro", "gemini-1.5-flash"},
|
|
423
|
+
"openai": {"gpt-4", "gpt-4-turbo", "gpt-4o", "gpt-4o-mini", "gpt-3.5-turbo", "o1-preview", "o1-mini"},
|
|
424
|
+
"copilot": {"gpt-4", "gpt-4-turbo", "gpt-4o", "gpt-4o-mini", "gpt-3.5-turbo", "o1-preview", "o1-mini", "claude-3.5-sonnet"},
|
|
425
|
+
"claude": {"claude-3-5-sonnet-20241022", "claude-3-5-haiku-20241022", "claude-3-opus-20240229"},
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if availableModels, ok := models[provider]; ok {
|
|
429
|
+
fmt.Println("Available models:")
|
|
430
|
+
for i, model := range availableModels {
|
|
431
|
+
marker := " "
|
|
432
|
+
if model == currentModel {
|
|
433
|
+
marker = "āø"
|
|
434
|
+
}
|
|
435
|
+
fmt.Printf(" %s %d. %s\n", marker, i+1, model)
|
|
436
|
+
}
|
|
437
|
+
fmt.Print("\nEnter number to switch (or press Enter to keep current): ")
|
|
438
|
+
|
|
439
|
+
var choice string
|
|
440
|
+
fmt.Scanln(&choice)
|
|
441
|
+
|
|
442
|
+
if choice != "" {
|
|
443
|
+
var num int
|
|
444
|
+
if _, err := fmt.Sscanf(choice, "%d", &num); err == nil && num >= 1 && num <= len(availableModels) {
|
|
445
|
+
cfg.Model.Model = availableModels[num-1]
|
|
446
|
+
if err := config.SaveConfig(cfg); err != nil {
|
|
447
|
+
fmt.Printf("ā Error saving: %v\n", err)
|
|
448
|
+
} else {
|
|
449
|
+
fmt.Printf("ā
Switched to: %s\n", cfg.Model.Model)
|
|
450
|
+
fmt.Println("ā ļø Restart dcode for changes to take effect")
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
fmt.Println()
|
|
456
|
+
return true, true
|
|
405
457
|
|
|
406
458
|
case "/clear":
|
|
407
459
|
agent, _ := agentManager.GetCurrentAgent()
|
package/cmd/model.go
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
package cmd
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"strconv"
|
|
6
|
+
|
|
7
|
+
"github.com/ddhanush1/dcode/internal/config"
|
|
8
|
+
"github.com/spf13/cobra"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
var modelCmd = &cobra.Command{
|
|
12
|
+
Use: "model [model-name]",
|
|
13
|
+
Short: "Select AI model for current provider",
|
|
14
|
+
Long: `Select which AI model to use with the current provider.
|
|
15
|
+
|
|
16
|
+
If no model name is provided, shows available models for current provider.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
dcode model # List available models
|
|
20
|
+
dcode model gpt-4 # Use GPT-4
|
|
21
|
+
dcode model gpt-3.5-turbo # Use GPT-3.5 Turbo`,
|
|
22
|
+
RunE: selectModel,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func init() {
|
|
26
|
+
rootCmd.AddCommand(modelCmd)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Available models for each provider
|
|
30
|
+
var providerModels = map[string][]string{
|
|
31
|
+
"gemini": {
|
|
32
|
+
"gemini-2.5-flash",
|
|
33
|
+
"gemini-2.0-flash-exp",
|
|
34
|
+
"gemini-1.5-pro",
|
|
35
|
+
"gemini-1.5-flash",
|
|
36
|
+
"gemini-pro",
|
|
37
|
+
},
|
|
38
|
+
"openai": {
|
|
39
|
+
"gpt-4",
|
|
40
|
+
"gpt-4-turbo",
|
|
41
|
+
"gpt-4o",
|
|
42
|
+
"gpt-4o-mini",
|
|
43
|
+
"gpt-3.5-turbo",
|
|
44
|
+
"o1-preview",
|
|
45
|
+
"o1-mini",
|
|
46
|
+
},
|
|
47
|
+
"copilot": {
|
|
48
|
+
"gpt-4",
|
|
49
|
+
"gpt-4-turbo",
|
|
50
|
+
"gpt-4o",
|
|
51
|
+
"gpt-4o-mini",
|
|
52
|
+
"gpt-3.5-turbo",
|
|
53
|
+
"o1-preview",
|
|
54
|
+
"o1-mini",
|
|
55
|
+
"claude-3.5-sonnet",
|
|
56
|
+
},
|
|
57
|
+
"claude": {
|
|
58
|
+
"claude-3-5-sonnet-20241022",
|
|
59
|
+
"claude-3-5-haiku-20241022",
|
|
60
|
+
"claude-3-opus-20240229",
|
|
61
|
+
"claude-3-sonnet-20240229",
|
|
62
|
+
"claude-3-haiku-20240307",
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
func selectModel(cmd *cobra.Command, args []string) error {
|
|
67
|
+
// Load config
|
|
68
|
+
cfg, err := config.LoadConfig()
|
|
69
|
+
if err != nil {
|
|
70
|
+
return fmt.Errorf("failed to load config: %w", err)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
provider := cfg.Model.Provider
|
|
74
|
+
if provider == "" {
|
|
75
|
+
return fmt.Errorf("no provider set. Use 'dcode switch <provider>' first")
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
availableModels, ok := providerModels[provider]
|
|
79
|
+
if !ok {
|
|
80
|
+
return fmt.Errorf("unknown provider: %s", provider)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// If model name provided, set it directly
|
|
84
|
+
if len(args) > 0 {
|
|
85
|
+
modelName := args[0]
|
|
86
|
+
|
|
87
|
+
// Validate model
|
|
88
|
+
valid := false
|
|
89
|
+
for _, m := range availableModels {
|
|
90
|
+
if m == modelName {
|
|
91
|
+
valid = true
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if !valid {
|
|
97
|
+
fmt.Printf("ā ļø Warning: '%s' is not in the list of known models\n", modelName)
|
|
98
|
+
fmt.Printf("Setting it anyway... (custom models are supported)\n\n")
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
cfg.Model.Model = modelName
|
|
102
|
+
if err := config.SaveConfig(cfg); err != nil {
|
|
103
|
+
return fmt.Errorf("failed to save config: %w", err)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fmt.Printf("ā
Model set to: %s\n", modelName)
|
|
107
|
+
fmt.Printf(" Provider: %s\n", provider)
|
|
108
|
+
return nil
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Interactive selection
|
|
112
|
+
fmt.Printf("\nš¤ Available models for %s:\n\n", provider)
|
|
113
|
+
for i, model := range availableModels {
|
|
114
|
+
current := ""
|
|
115
|
+
if model == cfg.Model.Model {
|
|
116
|
+
current = " (current)"
|
|
117
|
+
}
|
|
118
|
+
fmt.Printf(" %d. %s%s\n", i+1, model, current)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fmt.Printf("\n 0. Enter custom model name\n")
|
|
122
|
+
fmt.Print("\nSelect model (0-" + strconv.Itoa(len(availableModels)) + "): ")
|
|
123
|
+
|
|
124
|
+
var choice int
|
|
125
|
+
fmt.Scanf("%d", &choice)
|
|
126
|
+
|
|
127
|
+
if choice == 0 {
|
|
128
|
+
// Custom model
|
|
129
|
+
fmt.Print("Enter custom model name: ")
|
|
130
|
+
var customModel string
|
|
131
|
+
fmt.Scanln(&customModel)
|
|
132
|
+
|
|
133
|
+
if customModel != "" {
|
|
134
|
+
cfg.Model.Model = customModel
|
|
135
|
+
if err := config.SaveConfig(cfg); err != nil {
|
|
136
|
+
return fmt.Errorf("failed to save config: %w", err)
|
|
137
|
+
}
|
|
138
|
+
fmt.Printf("\nā
Model set to: %s\n", customModel)
|
|
139
|
+
}
|
|
140
|
+
return nil
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if choice < 1 || choice > len(availableModels) {
|
|
144
|
+
return fmt.Errorf("invalid choice: %d", choice)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
selectedModel := availableModels[choice-1]
|
|
148
|
+
cfg.Model.Model = selectedModel
|
|
149
|
+
|
|
150
|
+
if err := config.SaveConfig(cfg); err != nil {
|
|
151
|
+
return fmt.Errorf("failed to save config: %w", err)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fmt.Printf("\nā
Model set to: %s\n", selectedModel)
|
|
155
|
+
fmt.Printf(" Provider: %s\n", provider)
|
|
156
|
+
fmt.Println("\nYou can now run: dcode")
|
|
157
|
+
|
|
158
|
+
return nil
|
|
159
|
+
}
|
package/cmd/switch.go
CHANGED
|
@@ -86,24 +86,16 @@ func switchProvider(cmd *cobra.Command, args []string) error {
|
|
|
86
86
|
cfg.Auth.Provider = provider
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
// Set default models
|
|
89
|
+
// Set default models (ALWAYS update model when switching provider)
|
|
90
90
|
switch provider {
|
|
91
91
|
case "gemini":
|
|
92
|
-
|
|
93
|
-
cfg.Model.Model = "gemini-2.0-flash-exp"
|
|
94
|
-
}
|
|
92
|
+
cfg.Model.Model = "gemini-2.5-flash"
|
|
95
93
|
case "openai":
|
|
96
|
-
|
|
97
|
-
cfg.Model.Model = "gpt-4"
|
|
98
|
-
}
|
|
94
|
+
cfg.Model.Model = "gpt-4"
|
|
99
95
|
case "claude":
|
|
100
|
-
|
|
101
|
-
cfg.Model.Model = "claude-3-5-sonnet-20241022"
|
|
102
|
-
}
|
|
96
|
+
cfg.Model.Model = "claude-3-5-sonnet-20241022"
|
|
103
97
|
case "copilot":
|
|
104
|
-
|
|
105
|
-
cfg.Model.Model = "gpt-4"
|
|
106
|
-
}
|
|
98
|
+
cfg.Model.Model = "gpt-4"
|
|
107
99
|
}
|
|
108
100
|
|
|
109
101
|
// Save config
|
|
@@ -209,38 +209,89 @@ func GetConfigDir() (string, error) {
|
|
|
209
209
|
|
|
210
210
|
// LoadConfig loads configuration from file and environment
|
|
211
211
|
func LoadConfig() (*Config, error) {
|
|
212
|
-
cfg := DefaultConfig()
|
|
213
|
-
|
|
214
|
-
// Check environment for provider override first
|
|
215
|
-
if provider := os.Getenv("AI_PROVIDER"); provider != "" {
|
|
216
|
-
cfg.Model.Provider = provider
|
|
217
|
-
cfg.Auth.Provider = provider
|
|
218
|
-
}
|
|
219
|
-
|
|
220
212
|
// Load from settings.toml if it exists
|
|
221
213
|
configDir, err := GetConfigDir()
|
|
222
214
|
if err != nil {
|
|
223
215
|
return nil, err
|
|
224
216
|
}
|
|
225
217
|
|
|
218
|
+
homeDir, _ := os.UserHomeDir()
|
|
226
219
|
settingsPath := filepath.Join(configDir, "settings.toml")
|
|
220
|
+
var cfg *Config
|
|
221
|
+
|
|
227
222
|
if _, err := os.Stat(settingsPath); err == nil {
|
|
223
|
+
// File exists - load it WITHOUT defaults to avoid env-based auto-detection
|
|
224
|
+
cfg = &Config{
|
|
225
|
+
// Set ONLY structural defaults, no provider detection
|
|
226
|
+
Agent: AgentConfig{
|
|
227
|
+
DefaultAgent: "generalist",
|
|
228
|
+
EnabledAgents: []string{"generalist"},
|
|
229
|
+
AgentDirectory: filepath.Join(homeDir, ".dcode", "agents"),
|
|
230
|
+
MaxTurns: 50,
|
|
231
|
+
EnableSubAgents: true,
|
|
232
|
+
},
|
|
233
|
+
Tool: ToolConfig{
|
|
234
|
+
ToolDirectory: filepath.Join(homeDir, ".dcode", "tools"),
|
|
235
|
+
ShellTimeout: 300,
|
|
236
|
+
WebSearchEnabled: false,
|
|
237
|
+
ToolSettings: make(map[string]string),
|
|
238
|
+
},
|
|
239
|
+
Server: ServerConfig{
|
|
240
|
+
Host: "localhost",
|
|
241
|
+
Port: 8080,
|
|
242
|
+
A2APort: 41242,
|
|
243
|
+
},
|
|
244
|
+
Telemetry: TelemetryConfig{
|
|
245
|
+
SampleRate: 1.0,
|
|
246
|
+
EnableLogging: true,
|
|
247
|
+
LogLevel: "info",
|
|
248
|
+
},
|
|
249
|
+
}
|
|
250
|
+
|
|
228
251
|
data, err := os.ReadFile(settingsPath)
|
|
229
252
|
if err != nil {
|
|
230
253
|
return nil, fmt.Errorf("failed to read settings file: %w", err)
|
|
231
254
|
}
|
|
232
255
|
|
|
256
|
+
// This will override the structural defaults with saved values
|
|
233
257
|
if err := toml.Unmarshal(data, cfg); err != nil {
|
|
234
258
|
return nil, fmt.Errorf("failed to parse settings file: %w", err)
|
|
235
259
|
}
|
|
260
|
+
|
|
261
|
+
// DEBUG: Print what was loaded
|
|
262
|
+
// fmt.Printf("DEBUG: Loaded provider=%s model=%s\n", cfg.Model.Provider, cfg.Model.Model)
|
|
263
|
+
} else {
|
|
264
|
+
// No file, use full defaults (with env detection)
|
|
265
|
+
cfg = DefaultConfig()
|
|
236
266
|
}
|
|
237
267
|
|
|
238
|
-
//
|
|
239
|
-
|
|
268
|
+
// ONLY override if AI_PROVIDER is explicitly set in environment
|
|
269
|
+
if provider := os.Getenv("AI_PROVIDER"); provider != "" {
|
|
270
|
+
cfg.Model.Provider = provider
|
|
271
|
+
cfg.Auth.Provider = provider
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Apply other environment overrides
|
|
275
|
+
if val := os.Getenv("AI_MODEL"); val != "" {
|
|
276
|
+
cfg.Model.Model = val
|
|
277
|
+
}
|
|
240
278
|
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
279
|
+
// Set API keys for current provider
|
|
280
|
+
switch cfg.Auth.Provider {
|
|
281
|
+
case "openai":
|
|
282
|
+
if val := os.Getenv("OPENAI_API_KEY"); val != "" {
|
|
283
|
+
cfg.Auth.APIKey = val
|
|
284
|
+
}
|
|
285
|
+
case "gemini":
|
|
286
|
+
if val := os.Getenv("GEMINI_API_KEY"); val != "" {
|
|
287
|
+
cfg.Auth.APIKey = val
|
|
288
|
+
} else if val := os.Getenv("GOOGLE_API_KEY"); val != "" {
|
|
289
|
+
cfg.Auth.APIKey = val
|
|
290
|
+
}
|
|
291
|
+
case "claude":
|
|
292
|
+
if val := os.Getenv("ANTHROPIC_API_KEY"); val != "" {
|
|
293
|
+
cfg.Auth.APIKey = val
|
|
294
|
+
}
|
|
244
295
|
}
|
|
245
296
|
|
|
246
297
|
return cfg, nil
|
|
@@ -265,11 +316,13 @@ func (c *Config) ApplyEnvironment() {
|
|
|
265
316
|
c.mu.Lock()
|
|
266
317
|
defer c.mu.Unlock()
|
|
267
318
|
|
|
268
|
-
//
|
|
319
|
+
// ONLY override provider if AI_PROVIDER env var is explicitly set
|
|
269
320
|
if val := os.Getenv("AI_PROVIDER"); val != "" {
|
|
270
321
|
c.Auth.Provider = val
|
|
271
322
|
c.Model.Provider = val
|
|
272
323
|
}
|
|
324
|
+
|
|
325
|
+
// Set API keys based on current provider
|
|
273
326
|
if val := os.Getenv("OPENAI_API_KEY"); val != "" && c.Auth.Provider == "openai" {
|
|
274
327
|
c.Auth.APIKey = val
|
|
275
328
|
}
|