package api import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "git.x2erp.com/qdy/go-base/ctx" "git.x2erp.com/qdy/go-base/model/response" opencode "git.x2erp.com/qdy/go-base/sdk/opencode" "git.x2erp.com/qdy/go-svc-code/internal/opencode/container" ) // CreateSessionHandler 创建OpenCode会话 // 路由: POST /api/opencode/projects/:id/sessions func CreateSessionHandler(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("创建OpenCode会话请求: 项目ID=%s, 请求参数=%v", id, req) // 获取实例 instance := manager.GetInstance(id) if instance == nil { return ErrorResponse(fmt.Errorf("项目 %s 的OpenCode实例未启动", id)) } if instance.Status != container.StatusRunning { return ErrorResponse(fmt.Errorf("项目 %s 的OpenCode实例不在运行状态", id)) } // 创建OpenCode客户端 serverURL := fmt.Sprintf("http://localhost:%d", instance.Port) client, err := opencode.NewClient(serverURL) if err != nil { return ErrorResponse(fmt.Errorf("创建OpenCode客户端失败: %v", err)) } // 准备请求体 var parentID *string if pid, ok := req["parent_id"].(string); ok && pid != "" { parentID = &pid } var title *string if t, ok := req["title"].(string); ok && t != "" { title = &t } // 创建认证请求编辑器 var requestEditors []opencode.RequestEditorFn if instance.Token != "" { requestEditors = append(requestEditors, func(ctx context.Context, req *http.Request) error { req.Header.Set("Authorization", "Bearer "+instance.Token) return nil }) } // 调用OpenCode API创建会话 resp, err := client.SessionCreate( context.Background(), &opencode.SessionCreateParams{}, opencode.SessionCreateJSONRequestBody{ ParentID: parentID, Title: title, }, requestEditors..., ) if err != nil { return ErrorResponse(fmt.Errorf("请求OpenCode API失败: %v", err)) } defer resp.Body.Close() // 读取响应 body, err := io.ReadAll(resp.Body) if err != nil { return ErrorResponse(fmt.Errorf("读取响应失败: %v", err)) } // 检查HTTP状态码 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { return ErrorResponse(fmt.Errorf("OpenCode API返回错误: 状态码=%d, 响应=%s", resp.StatusCode, string(body))) } // 解析响应 var opencodeResponse map[string]interface{} if err := json.Unmarshal(body, &opencodeResponse); err != nil { return ErrorResponse(fmt.Errorf("解析OpenCode响应失败: %v", err)) } log.Printf("OpenCode会话创建成功: 项目=%s, 响应=%v", id, opencodeResponse) return SuccessResponseWithMessage(opencodeResponse, "会话创建成功") } }