package llm import ( "bufio" "fmt" "io" "net/http" "strings" "yunion.io/x/onecloud/cmd/climc/shell" "yunion.io/x/onecloud/pkg/mcclient" modules "yunion.io/x/onecloud/pkg/mcclient/modules/llm" base_options "yunion.io/x/onecloud/pkg/mcclient/options" options "yunion.io/x/onecloud/pkg/mcclient/options/llm" ) func init() { cmd := shell.NewResourceCmd(&modules.MCPAgent) cmd.List(new(options.MCPAgentListOptions)) cmd.Show(new(options.MCPAgentShowOptions)) cmd.Create(new(options.MCPAgentCreateOptions)) cmd.Update(new(options.MCPAgentUpdateOptions)) cmd.Delete(new(options.MCPAgentDeleteOptions)) cmd.Perform("public", &base_options.BasePublicOptions{}) cmd.Perform("private", &base_options.BaseIdOptions{}) cmd.Get("mcp-tools", new(options.MCPAgentIdOptions)) cmd.Get("tool-request", new(options.MCPAgentToolRequestOptions)) // cmd.Get("chat-test", new(options.MCPAgentChatTestOptions)) cmd.Get("request", new(options.MCPAgentMCPAgentRequestOptions)) shell.R(&options.MCPAgentMCPAgentRequestOptions{}, "mcp-agent-chat", "Chat with MCP Agent (Stream)", chatStream) shell.R(&options.MCPAgentDefaultChatOptions{}, "mcp-agent-chat-default", "Chat with default MCP Agent (Stream, no ID required)", chatStreamDefault) } func chatStream(s *mcclient.ClientSession, args *options.MCPAgentMCPAgentRequestOptions) error { id, err := modules.MCPAgent.GetId(s, args.ID, nil) if err != nil { return err } bodyJSON, err := args.Params() if err != nil { return fmt.Errorf("failed to build request params: %v", err) } headers := http.Header{} headers.Set("Content-Type", "application/json") body := strings.NewReader(bodyJSON.String()) path := fmt.Sprintf("/mcp_agents/%s/chat-stream", id) resp, err := s.RawVersionRequest( modules.MCPAgent.ServiceType(), modules.MCPAgent.EndpointType(), "POST", path, headers, body, ) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { // Read error body body, _ := io.ReadAll(resp.Body) return fmt.Errorf("Error: %s %s", resp.Status, string(body)) } scanner := bufio.NewScanner(resp.Body) var eventData []string for scanner.Scan() { line := scanner.Text() if line == "" { if len(eventData) > 0 { fmt.Print(strings.Join(eventData, "\n")) eventData = nil } continue } if after, found := strings.CutPrefix(line, "data: "); found { eventData = append(eventData, after) } } if err := scanner.Err(); err != nil { return err } fmt.Println() return nil } func chatStreamDefault(s *mcclient.ClientSession, args *options.MCPAgentDefaultChatOptions) error { bodyJSON, err := args.Params() if err != nil { return fmt.Errorf("failed to build request params: %v", err) } headers := http.Header{} headers.Set("Content-Type", "application/json") body := strings.NewReader(bodyJSON.String()) path := "/mcp_agents/default/chat-stream" resp, err := s.RawVersionRequest( modules.MCPAgent.ServiceType(), modules.MCPAgent.EndpointType(), "POST", path, headers, body, ) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { respBody, _ := io.ReadAll(resp.Body) return fmt.Errorf("Error: %s %s", resp.Status, string(respBody)) } scanner := bufio.NewScanner(resp.Body) var eventData []string for scanner.Scan() { line := scanner.Text() if line == "" { if len(eventData) > 0 { fmt.Print(strings.Join(eventData, "\n")) eventData = nil } continue } if after, found := strings.CutPrefix(line, "data: "); found { eventData = append(eventData, after) } } if err := scanner.Err(); err != nil { return err } fmt.Println() return nil }