mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package providers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"sync"
|
|
|
|
copilot "github.com/github/copilot-sdk/go"
|
|
)
|
|
|
|
type GitHubCopilotProvider struct {
|
|
uri string
|
|
connectMode string // "stdio" or "grpc"
|
|
|
|
client *copilot.Client
|
|
session *copilot.Session
|
|
|
|
mu sync.Mutex
|
|
}
|
|
|
|
func NewGitHubCopilotProvider(uri string, connectMode string, model string) (*GitHubCopilotProvider, error) {
|
|
if connectMode == "" {
|
|
connectMode = "grpc"
|
|
}
|
|
|
|
switch connectMode {
|
|
case "stdio":
|
|
// TODO:
|
|
return nil, fmt.Errorf("stdio mode not implemented")
|
|
case "grpc":
|
|
client := copilot.NewClient(&copilot.ClientOptions{
|
|
CLIUrl: uri,
|
|
})
|
|
if err := client.Start(context.Background()); err != nil {
|
|
return nil, fmt.Errorf("can't connect to Github Copilot: %w; `https://github.com/github/copilot-sdk/blob/main/docs/getting-started.md#connecting-to-an-external-cli-server` for details", err)
|
|
}
|
|
|
|
session, err := client.CreateSession(context.Background(), &copilot.SessionConfig{
|
|
Model: model,
|
|
Hooks: &copilot.SessionHooks{},
|
|
})
|
|
if err != nil {
|
|
|
|
client.Stop()
|
|
return nil, fmt.Errorf("create session failed: %w", err)
|
|
}
|
|
|
|
return &GitHubCopilotProvider{
|
|
uri: uri,
|
|
connectMode: connectMode,
|
|
client: client,
|
|
session: session,
|
|
}, nil
|
|
default:
|
|
return nil, fmt.Errorf("unknown connect mode: %s", connectMode)
|
|
}
|
|
}
|
|
|
|
func (p *GitHubCopilotProvider) Close() {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
if p.client != nil {
|
|
p.client.Stop()
|
|
p.client = nil
|
|
p.session = nil
|
|
}
|
|
}
|
|
|
|
func (p *GitHubCopilotProvider) Chat(ctx context.Context, messages []Message, tools []ToolDefinition, model string, options map[string]interface{}) (*LLMResponse, error) {
|
|
type tempMessage struct {
|
|
Role string `json:"role"`
|
|
Content string `json:"content"`
|
|
}
|
|
out := make([]tempMessage, 0, len(messages))
|
|
for _, msg := range messages {
|
|
out = append(out, tempMessage{
|
|
Role: msg.Role,
|
|
Content: msg.Content,
|
|
})
|
|
}
|
|
|
|
fullcontent, err := json.Marshal(out)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("marshal messages: %w", err)
|
|
}
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
|
|
resp, err := p.session.SendAndWait(ctx, copilot.MessageOptions{
|
|
Prompt: string(fullcontent),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var content string
|
|
if resp != nil && resp.Data.Content != nil {
|
|
content = *resp.Data.Content
|
|
}
|
|
|
|
return &LLMResponse{
|
|
FinishReason: "stop",
|
|
Content: content,
|
|
}, nil
|
|
}
|
|
func (p *GitHubCopilotProvider) GetDefaultModel() string {
|
|
|
|
return "gpt-4.1"
|
|
}
|