diff --git a/ai/copilot/client.go b/ai/copilot/client.go index 8a29675e..00ee44d3 100644 --- a/ai/copilot/client.go +++ b/ai/copilot/client.go @@ -147,6 +147,17 @@ func (c *Client) createSession(ctx context.Context) (SessionWrapper, error) { return session, nil } +func assistantMessageText(resp *copilot.SessionEvent) (string, bool) { + if resp == nil { + return "", false + } + data, ok := resp.Data.(*copilot.AssistantMessageData) + if !ok { + return "", false + } + return data.Content, true +} + // GenerateWorkflow creates a workflow config from a natural language request. func (c *Client) GenerateWorkflow(ctx context.Context, req ai.GenerateRequest) (*ai.GenerateResponse, error) { session, err := c.createSession(ctx) @@ -162,11 +173,11 @@ func (c *Client) GenerateWorkflow(ctx context.Context, req ai.GenerateRequest) ( return nil, fmt.Errorf("copilot request failed: %w", err) } - if resp == nil || resp.Data.Content == nil { + text, ok := assistantMessageText(resp) + if !ok { return nil, fmt.Errorf("empty response from Copilot") } - text := *resp.Data.Content jsonStr := aillm.ExtractJSON(text) if jsonStr == "" { return nil, fmt.Errorf("no JSON found in Copilot response") @@ -194,11 +205,12 @@ func (c *Client) GenerateComponent(ctx context.Context, spec ai.ComponentSpec) ( return "", fmt.Errorf("copilot request failed: %w", err) } - if resp == nil || resp.Data.Content == nil { + text, ok := assistantMessageText(resp) + if !ok { return "", fmt.Errorf("empty response from Copilot") } - return aillm.ExtractCode(*resp.Data.Content), nil + return aillm.ExtractCode(text), nil } // SuggestWorkflow returns workflow suggestions for a use case. @@ -216,11 +228,11 @@ func (c *Client) SuggestWorkflow(ctx context.Context, useCase string) ([]ai.Work return nil, fmt.Errorf("copilot request failed: %w", err) } - if resp == nil || resp.Data.Content == nil { + text, ok := assistantMessageText(resp) + if !ok { return nil, fmt.Errorf("empty response from Copilot") } - text := *resp.Data.Content jsonStr := aillm.ExtractJSON(text) if jsonStr == "" { return nil, fmt.Errorf("no JSON found in Copilot response") @@ -253,11 +265,11 @@ func (c *Client) IdentifyMissingComponents(ctx context.Context, cfg *config.Work return nil, fmt.Errorf("copilot request failed: %w", err) } - if resp == nil || resp.Data.Content == nil { + text, ok := assistantMessageText(resp) + if !ok { return nil, fmt.Errorf("empty response from Copilot") } - text := *resp.Data.Content jsonStr := aillm.ExtractJSON(text) if jsonStr == "" { return nil, nil // no missing components diff --git a/ai/copilot/client_test.go b/ai/copilot/client_test.go index 3f645850..5da596d8 100644 --- a/ai/copilot/client_test.go +++ b/ai/copilot/client_test.go @@ -47,7 +47,7 @@ func newTestClient(wrapper ClientWrapper) *Client { // Helper to create a SessionEvent with the given text content. func sessionEventWithContent(text string) *copilot.SessionEvent { return &copilot.SessionEvent{ - Data: copilot.Data{Content: &text}, + Data: &copilot.AssistantMessageData{Content: text}, } } @@ -220,9 +220,9 @@ func TestGenerateWorkflow_EmptyResponse(t *testing.T) { } } -func TestGenerateWorkflow_NilContent(t *testing.T) { +func TestGenerateWorkflow_NonAssistantResponse(t *testing.T) { event := &copilot.SessionEvent{ - Data: copilot.Data{Content: nil}, + Data: nil, } wrapper := mockWrapperWithResponse(event, nil) client := newTestClient(wrapper) diff --git a/go.mod b/go.mod index 6b584b8c..8da81d16 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/docker/docker v28.5.2+incompatible github.com/expr-lang/expr v1.17.8 github.com/fsnotify/fsnotify v1.9.0 - github.com/github/copilot-sdk/go v0.2.0 + github.com/github/copilot-sdk/go v0.3.0 github.com/golang-jwt/jwt/v5 v5.3.1 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 diff --git a/go.sum b/go.sum index ad13a711..19bf5a1b 100644 --- a/go.sum +++ b/go.sum @@ -207,8 +207,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78= github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= -github.com/github/copilot-sdk/go v0.2.0 h1:RnrIIirmtp4wGgqSQFJ2k9phbeveIxOtYZqDogoNEa0= -github.com/github/copilot-sdk/go v0.2.0/go.mod h1:uGWkjVYcp2DV9DgtqYihh5tEoJjNqxIFaUNnrwY4FxM= +github.com/github/copilot-sdk/go v0.3.0 h1:LPMpoJzUTfrPbr/5e7s5QKvi66PMmREnbZ9kRxPe6ls= +github.com/github/copilot-sdk/go v0.3.0/go.mod h1:uGWkjVYcp2DV9DgtqYihh5tEoJjNqxIFaUNnrwY4FxM= github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=