{"repo": "cciisiaicat/goagent", "files": {"agent/deepseek/client.go": {"b328d24267f1ceab4bc1d5706c36394f96ad5267": {"t": 1785746080.1518505, "n": 3911, "h": "cfec2314ce7bc020", "c": "package deepseek\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// Config DeepSeek配置\ntype Config struct {\n\tAPIKey string\n\tBaseURL string\n\tModel string\n}\n\n// Client DeepSeek客户端\ntype Client struct {\n\tconfig *Config\n\thttpClient *http.Client\n}\n\n// NewClient 创建DeepSeek客户端\nfunc NewClient(config *Config) *Client {\n\tif config.BaseURL == \"\" {\n\t\tconfig.BaseURL = \"https://api.deepseek.com/v1\"\n\t}\n\tif config.Model == \"\" {\n\t\tconfig.Model = \"deepseek-chat\"\n\t}\n\t\n\treturn &Client{\n\t\tconfig: config,\n\t\thttpClient: &http.Client{},\n\t}\n}\n\n// GetProvider 获取提供商名称\nfunc (c *Client) GetProvider() string {\n\treturn \"deepseek\"\n}\n\n// ValidateRequest 验证请求参数\nfunc (c *Client) ValidateRequest(req interface{}) error {\n\t// 可以添加特定的验证逻辑\n\treturn nil\n}\n\n// Chat 发送聊天请求\nfunc (c *Client) Chat(ctx context.Context, req interface{}) (interface{}, error) {\n\tdeepseekReq, err := ToDeepSeekRequest(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"convert to deepseek request failed: %w\", err)\n\t}\n\t\n\t// 设置默认模型\n\tif deepseekReq.Model == \"\" {\n\t\tdeepseekReq.Model = c.config.Model\n\t}\n\t\n\treqBody, err := json.Marshal(deepseekReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal request failed: %w\", err)\n\t}\n\t\n\t// 调试输出已移除\n\t\n\thttpReq, err := http.NewRequestWithContext(ctx, \"POST\", c.config.BaseURL+\"/chat/completions\", bytes.NewReader(reqBody))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create http request failed: %w\", err)\n\t}\n\t\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\thttpReq.Header.Set(\"Authorization\", \"Bearer \"+c.config.APIKey)\n\t\n\tresp, err := c.httpClient.Do(httpReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"http request failed: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\tif resp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\treturn nil, fmt.Errorf(\"api request failed with status %d: %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar deepseekResp DeepSeekChatResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&deepseekResp); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode response failed: %w\", err)\n\t}\n\t\n\treturn FromDeepSeekResponse(&deepseekResp), nil\n}\n\n// ChatStream 发送流式聊天请求\nfunc (c *Client) ChatStream(ctx context.Context, req interface{}) (<-chan interface{}, error) {\n\tdeepseekReq, err := ToDeepSeekRequest(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"convert to deepseek request failed: %w\", err)\n\t}\n\t\n\t// 启用流式模式\n\tdeepseekReq.Stream = true\n\t\n\t// 设置默认模型\n\tif deepseekReq.Model == \"\" {\n\t\tdeepseekReq.Model = c.config.Model\n\t}\n\t\n\treqBody, err := json.Marshal(deepseekReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal request failed: %w\", err)\n\t}\n\t\n\thttpReq, err := http.NewRequestWithContext(ctx, \"POST\", c.config.BaseURL+\"/chat/completions\", bytes.NewReader(reqBody))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create http request failed: %w\", err)\n\t}\n\t\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\thttpReq.Header.Set(\"Authorization\", \"Bearer \"+c.config.APIKey)\n\thttpReq.Header.Set(\"Accept\", \"text/event-stream\")\n\t\n\tresp, err := c.httpClient.Do(httpReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"http request failed: %w\", err)\n\t}\n\t\n\tif resp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\tresp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"api request failed with status %d: %s\", resp.StatusCode, string(body))\n\t}\n\t\n\tch := make(chan interface{}, 10)\n\t\n\tgo func() {\n\t\tdefer resp.Body.Close()\n\t\tdefer close(ch)\n\t\t\n\t\tscanner := bufio.NewScanner(resp.Body)\n\t\tfor scanner.Scan() {\n\t\t\tline := scanner.Text()\n\t\t\t\n\t\t\tif !strings.HasPrefix(line, \"data: \") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t\n\t\t\tdata := strings.TrimPrefix(line, \"data: \")\n\t\t\tif data == \"[DONE]\" {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t\n\t\t\tvar streamResp DeepSeekStreamResponse\n\t\t\tif err := json.Unmarshal([]byte(data), &streamResp); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t\n\t\t\t// 转换为统一格式\n\t\t\tselect {\n\t\t\tcase ch <- streamResp:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}()\n\t\n\treturn ch, nil\n}"}, "8f80af4ab77f5bc5c942a9e8b6177f3fd1a7ebe6": {"t": 1785759650.455883, "n": 3911, "h": "cfec2314ce7bc020", "c": "package deepseek\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// Config DeepSeek配置\ntype Config struct {\n\tAPIKey string\n\tBaseURL string\n\tModel string\n}\n\n// Client DeepSeek客户端\ntype Client struct {\n\tconfig *Config\n\thttpClient *http.Client\n}\n\n// NewClient 创建DeepSeek客户端\nfunc NewClient(config *Config) *Client {\n\tif config.BaseURL == \"\" {\n\t\tconfig.BaseURL = \"https://api.deepseek.com/v1\"\n\t}\n\tif config.Model == \"\" {\n\t\tconfig.Model = \"deepseek-chat\"\n\t}\n\t\n\treturn &Client{\n\t\tconfig: config,\n\t\thttpClient: &http.Client{},\n\t}\n}\n\n// GetProvider 获取提供商名称\nfunc (c *Client) GetProvider() string {\n\treturn \"deepseek\"\n}\n\n// ValidateRequest 验证请求参数\nfunc (c *Client) ValidateRequest(req interface{}) error {\n\t// 可以添加特定的验证逻辑\n\treturn nil\n}\n\n// Chat 发送聊天请求\nfunc (c *Client) Chat(ctx context.Context, req interface{}) (interface{}, error) {\n\tdeepseekReq, err := ToDeepSeekRequest(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"convert to deepseek request failed: %w\", err)\n\t}\n\t\n\t// 设置默认模型\n\tif deepseekReq.Model == \"\" {\n\t\tdeepseekReq.Model = c.config.Model\n\t}\n\t\n\treqBody, err := json.Marshal(deepseekReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal request failed: %w\", err)\n\t}\n\t\n\t// 调试输出已移除\n\t\n\thttpReq, err := http.NewRequestWithContext(ctx, \"POST\", c.config.BaseURL+\"/chat/completions\", bytes.NewReader(reqBody))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create http request failed: %w\", err)\n\t}\n\t\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\thttpReq.Header.Set(\"Authorization\", \"Bearer \"+c.config.APIKey)\n\t\n\tresp, err := c.httpClient.Do(httpReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"http request failed: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\tif resp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\treturn nil, fmt.Errorf(\"api request failed with status %d: %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar deepseekResp DeepSeekChatResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&deepseekResp); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode response failed: %w\", err)\n\t}\n\t\n\treturn FromDeepSeekResponse(&deepseekResp), nil\n}\n\n// ChatStream 发送流式聊天请求\nfunc (c *Client) ChatStream(ctx context.Context, req interface{}) (<-chan interface{}, error) {\n\tdeepseekReq, err := ToDeepSeekRequest(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"convert to deepseek request failed: %w\", err)\n\t}\n\t\n\t// 启用流式模式\n\tdeepseekReq.Stream = true\n\t\n\t// 设置默认模型\n\tif deepseekReq.Model == \"\" {\n\t\tdeepseekReq.Model = c.config.Model\n\t}\n\t\n\treqBody, err := json.Marshal(deepseekReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal request failed: %w\", err)\n\t}\n\t\n\thttpReq, err := http.NewRequestWithContext(ctx, \"POST\", c.config.BaseURL+\"/chat/completions\", bytes.NewReader(reqBody))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create http request failed: %w\", err)\n\t}\n\t\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\thttpReq.Header.Set(\"Authorization\", \"Bearer \"+c.config.APIKey)\n\thttpReq.Header.Set(\"Accept\", \"text/event-stream\")\n\t\n\tresp, err := c.httpClient.Do(httpReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"http request failed: %w\", err)\n\t}\n\t\n\tif resp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\tresp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"api request failed with status %d: %s\", resp.StatusCode, string(body))\n\t}\n\t\n\tch := make(chan interface{}, 10)\n\t\n\tgo func() {\n\t\tdefer resp.Body.Close()\n\t\tdefer close(ch)\n\t\t\n\t\tscanner := bufio.NewScanner(resp.Body)\n\t\tfor scanner.Scan() {\n\t\t\tline := scanner.Text()\n\t\t\t\n\t\t\tif !strings.HasPrefix(line, \"data: \") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t\n\t\t\tdata := strings.TrimPrefix(line, \"data: \")\n\t\t\tif data == \"[DONE]\" {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t\n\t\t\tvar streamResp DeepSeekStreamResponse\n\t\t\tif err := json.Unmarshal([]byte(data), &streamResp); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t\n\t\t\t// 转换为统一格式\n\t\t\tselect {\n\t\t\tcase ch <- streamResp:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}()\n\t\n\treturn ch, nil\n}"}}}}