Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

start_instance.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package api
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "os"
  7. "git.x2erp.com/qdy/go-base/ctx"
  8. "git.x2erp.com/qdy/go-base/model/response"
  9. "git.x2erp.com/qdy/go-svc-code/internal/opencode/container"
  10. )
  11. // StartInstanceHandler 启动项目OpenCode实例
  12. // 路由: POST /api/opencode/projects/:id/start
  13. func StartInstanceHandler(manager *container.InstanceManager) func(string, map[string]interface{}, *ctx.RequestContext) (*response.QueryResult[interface{}], error) {
  14. return func(id string, req map[string]interface{}, reqCtx *ctx.RequestContext) (*response.QueryResult[interface{}], error) {
  15. log.Printf("启动项目实例请求: 项目ID=%s, 请求参数=%v, 请求参数类型: %T", id, req, req)
  16. log.Printf("RequestContext: %+v", reqCtx)
  17. // 获取租户ID
  18. tenantID, _ := GetRequestContext(reqCtx)
  19. if tenantID == "" {
  20. tenantID = "default"
  21. log.Printf("使用默认租户ID: %s", tenantID)
  22. }
  23. // 如果请求参数为空,尝试从opencode.json读取token
  24. token := ""
  25. toolURL := ""
  26. // 首先尝试从请求参数读取
  27. if len(req) > 0 {
  28. toolURL, _ = req["tool_url"].(string)
  29. token, _ = req["token"].(string)
  30. }
  31. // 如果token为空,从opencode.json读取
  32. if token == "" {
  33. token = readTokenFromOpenCodeConfig()
  34. if token != "" {
  35. log.Printf("从opencode.json读取token: %s...", token[:min(20, len(token))])
  36. }
  37. }
  38. // 如果tool_url为空,使用默认值
  39. if toolURL == "" {
  40. toolURL = "http://localhost:9060/api/dbtools/"
  41. log.Printf("使用默认tool_url: %s", toolURL)
  42. }
  43. // 验证参数
  44. if toolURL == "" {
  45. return ErrorResponse(fmt.Errorf("tool_url参数必须提供且为非空字符串"))
  46. }
  47. if token == "" {
  48. log.Printf("警告: token为空,某些功能可能受限")
  49. // 允许token为空,某些工具可能不需要认证
  50. }
  51. // 启动实例
  52. instance, err := manager.StartInstance(id, tenantID, toolURL, token)
  53. if err != nil {
  54. log.Printf("启动实例失败: 项目=%s, 错误=%v", id, err)
  55. return ErrorResponse(fmt.Errorf("启动实例失败: %v", err))
  56. }
  57. // 构建响应数据
  58. instanceInfo := InstanceInfo{
  59. ProjectID: instance.ProjectID,
  60. Port: instance.Port,
  61. PID: instance.PID,
  62. Status: string(instance.Status),
  63. ConfigPath: instance.ConfigPath,
  64. WorkDir: instance.WorkDir,
  65. APIBase: fmt.Sprintf("http://localhost:%d", instance.Port),
  66. ToolURL: instance.ToolURL,
  67. }
  68. log.Printf("实例启动成功: 项目=%s, 端口=%d, PID=%d", id, instance.Port, instance.PID)
  69. return SuccessResponseWithMessage(instanceInfo, "实例启动成功")
  70. }
  71. }
  72. // min 返回两个整数中的最小值
  73. func min(a, b int) int {
  74. if a < b {
  75. return a
  76. }
  77. return b
  78. }
  79. // readTokenFromOpenCodeConfig 从.opencode/opencode.json读取token
  80. func readTokenFromOpenCodeConfig() string {
  81. configPath := "./.opencode/opencode.json"
  82. data, err := os.ReadFile(configPath)
  83. if err != nil {
  84. log.Printf("读取opencode.json失败: %v", err)
  85. return ""
  86. }
  87. var config map[string]interface{}
  88. if err := json.Unmarshal(data, &config); err != nil {
  89. log.Printf("解析opencode.json失败: %v", err)
  90. return ""
  91. }
  92. if token, ok := config["token"].(string); ok {
  93. return token
  94. }
  95. log.Printf("opencode.json中未找到token字段")
  96. return ""
  97. }