-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmain.go
More file actions
153 lines (126 loc) · 4.42 KB
/
Copy pathmain.go
File metadata and controls
153 lines (126 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
"context"
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
"charm.land/fantasy"
"charm.land/fantasy/providers/openaicompat"
"github.com/joho/godotenv"
"github.com/JiayuXu0/MiniCode/internal/config"
"github.com/JiayuXu0/MiniCode/internal/permission"
"github.com/JiayuXu0/MiniCode/tools"
"github.com/JiayuXu0/MiniCode/tui"
)
const systemPrompt = `你是工控智科的大模型,是一个有帮助的编码与问题解决助手,具备文件系统工具能力。
Available tools:
- glob: Find files by pattern
- view: Read file contents
- grep: Search file contents
- bash: Execute shell commands
- write: Write content to files
- edit: Edit files by replacing text
When asked about code or files, use tools to gather information.
You may need multiple tool calls. Respond in the user's language.
Do not make up facts. If you are unsure or lack information, say so clearly and ask for the needed details.`
func main() {
_ = godotenv.Load() // 忽略 .env 不存在的情况
// 加载配置
cfg, err := config.Load()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
os.Exit(1)
}
ctx := context.Background()
// 从配置创建 model
model, err := createModel(ctx, cfg)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating model: %v\n", err)
os.Exit(1)
}
// 创建权限服务
permService := permission.NewService()
agent := fantasy.NewAgent(model,
fantasy.WithSystemPrompt(systemPrompt),
fantasy.WithTools(
tools.NewGlobTool(),
tools.NewViewTool(),
tools.NewGrepTool(),
tools.NewBashTool(permService),
tools.NewWriteTool(permService),
tools.NewEditTool(permService),
),
)
m := tui.New(agent, permService, cfg.GetDefaultModel())
p := tea.NewProgram(m, tea.WithAltScreen(), tea.WithMouseCellMotion())
// 设置 Program 引用
m.SetProgram(p)
permService.SetProgram(p)
if _, err := p.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Runtime error: %v\n", err)
os.Exit(1)
}
}
// createModel 根据配置创建语言模型
func createModel(ctx context.Context, cfg *config.Config) (fantasy.LanguageModel, error) {
modelName := cfg.GetDefaultModel()
// 按优先级尝试不同的 provider
providers := []string{"zhipu", "openrouter", "bailian", "openai"}
for _, providerName := range providers {
if providerCfg, ok := cfg.GetProvider(providerName); ok {
switch providerName {
case "zhipu":
return createOpenAICompatModel(ctx, providerCfg, modelName, "https://open.bigmodel.cn/api/coding/paas/v4", "zai")
case "openrouter":
return createOpenAICompatModel(ctx, providerCfg, modelName, "https://openrouter.ai/api/v1", "openrouter")
case "bailian":
return createOpenAICompatModel(ctx, providerCfg, modelName, "https://dashscope.aliyuncs.com/compatible-mode/v1", "bailian")
case "openai":
return createOpenAICompatModel(ctx, providerCfg, modelName, "https://api.openai.com/v1", "openai")
}
}
}
// 回退到环境变量
apiKey := os.Getenv("OPENAI_API_KEY")
if apiKey == "" {
return nil, fmt.Errorf("no API key found. Add a provider in minicode.json or set OPENAI_API_KEY env var")
}
// 使用默认配置创建智谱模型
providerCfg := config.ProviderConfig{
APIKey: apiKey,
BaseURL: "https://open.bigmodel.cn/api/coding/paas/v4",
Name: "zai",
}
return createOpenAICompatModel(ctx, providerCfg, modelName, "https://open.bigmodel.cn/api/coding/paas/v4", "zai")
}
// createOpenAICompatModel 创建 OpenAI 兼容的模型
// 支持:智谱 GLM、OpenRouter、百炼、OpenAI 等
func createOpenAICompatModel(ctx context.Context, providerCfg config.ProviderConfig, modelName, defaultBaseURL, defaultName string) (fantasy.LanguageModel, error) {
if providerCfg.APIKey == "" {
return nil, fmt.Errorf("API key is required")
}
// 使用配置的 base_url,如果没有则使用默认值
baseURL := providerCfg.BaseURL
if baseURL == "" {
baseURL = defaultBaseURL
}
// 使用配置的 name,如果没有则使用默认值
name := providerCfg.Name
if name == "" {
name = defaultName
}
// 创建 openaicompat provider
provider, err := openaicompat.New(
openaicompat.WithBaseURL(baseURL),
openaicompat.WithAPIKey(providerCfg.APIKey),
openaicompat.WithName(name),
)
if err != nil {
return nil, fmt.Errorf("failed to create provider: %w", err)
}
model, err := provider.LanguageModel(ctx, modelName)
if err != nil {
return nil, fmt.Errorf("failed to get model %s: %w", modelName, err)
}
return model, nil
}