| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- package api
-
- import (
- "encoding/json"
- "fmt"
- "log"
- "os"
-
- "git.x2erp.com/qdy/go-base/ctx"
- "git.x2erp.com/qdy/go-base/model/response"
- "git.x2erp.com/qdy/go-svc-code/internal/opencode/container"
- )
-
- // StartInstanceHandler 启动项目OpenCode实例
- // 路由: POST /api/opencode/projects/:id/start
- func StartInstanceHandler(manager *container.InstanceManager) func(string, map[string]interface{}, *ctx.RequestContext) (*response.QueryResult[interface{}], error) {
- return func(id string, req map[string]interface{}, reqCtx *ctx.RequestContext) (*response.QueryResult[interface{}], error) {
- log.Printf("启动项目实例请求: 项目ID=%s, 请求参数=%v, 请求参数类型: %T", id, req, req)
- log.Printf("RequestContext: %+v", reqCtx)
-
- // 获取租户ID
- tenantID, _ := GetRequestContext(reqCtx)
- if tenantID == "" {
- tenantID = "default"
- log.Printf("使用默认租户ID: %s", tenantID)
- }
-
- // 如果请求参数为空,尝试从opencode.json读取token
- token := ""
- toolURL := ""
-
- // 首先尝试从请求参数读取
- if len(req) > 0 {
- toolURL, _ = req["tool_url"].(string)
- token, _ = req["token"].(string)
- }
-
- // 如果token为空,从opencode.json读取
- if token == "" {
- token = readTokenFromOpenCodeConfig()
- if token != "" {
- log.Printf("从opencode.json读取token: %s...", token[:min(20, len(token))])
- }
- }
-
- // 如果tool_url为空,使用默认值
- if toolURL == "" {
- toolURL = "http://localhost:9060/api/dbtools/"
- log.Printf("使用默认tool_url: %s", toolURL)
- }
-
- // 验证参数
- if toolURL == "" {
- return ErrorResponse(fmt.Errorf("tool_url参数必须提供且为非空字符串"))
- }
-
- if token == "" {
- log.Printf("警告: token为空,某些功能可能受限")
- // 允许token为空,某些工具可能不需要认证
- }
-
- // 启动实例
- instance, err := manager.StartInstance(id, tenantID, toolURL, token)
- if err != nil {
- log.Printf("启动实例失败: 项目=%s, 错误=%v", id, err)
- return ErrorResponse(fmt.Errorf("启动实例失败: %v", err))
- }
-
- // 构建响应数据
- instanceInfo := InstanceInfo{
- ProjectID: instance.ProjectID,
- Port: instance.Port,
- PID: instance.PID,
- Status: string(instance.Status),
- ConfigPath: instance.ConfigPath,
- WorkDir: instance.WorkDir,
- APIBase: fmt.Sprintf("http://localhost:%d", instance.Port),
- ToolURL: instance.ToolURL,
- }
-
- log.Printf("实例启动成功: 项目=%s, 端口=%d, PID=%d", id, instance.Port, instance.PID)
- return SuccessResponseWithMessage(instanceInfo, "实例启动成功")
- }
- }
-
- // min 返回两个整数中的最小值
- func min(a, b int) int {
- if a < b {
- return a
- }
- return b
- }
-
- // readTokenFromOpenCodeConfig 从.opencode/opencode.json读取token
- func readTokenFromOpenCodeConfig() string {
- configPath := "./.opencode/opencode.json"
- data, err := os.ReadFile(configPath)
- if err != nil {
- log.Printf("读取opencode.json失败: %v", err)
- return ""
- }
-
- var config map[string]interface{}
- if err := json.Unmarshal(data, &config); err != nil {
- log.Printf("解析opencode.json失败: %v", err)
- return ""
- }
-
- if token, ok := config["token"].(string); ok {
- return token
- }
-
- log.Printf("opencode.json中未找到token字段")
- return ""
- }
|