From 5eb7adb376cb8be40fc03b6d6595cdde7bd3b9d6 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 11 Feb 2026 06:06:37 -0800 Subject: [PATCH] Fix Go cookbook recipes to use correct SDK API All 5 Go recipes and their markdown docs used incorrect API patterns that don't match the real github.com/github/copilot-sdk/go v0.1.23: - copilot.NewClient() -> copilot.NewClient(nil) (*ClientOptions param) - client.Start() -> client.Start(ctx) (context.Context required) - copilot.SessionConfig -> &copilot.SessionConfig (pointer required) - session.On(func(event copilot.Event)) -> session.On(func(event copilot.SessionEvent)) - Type assertions -> event.Type string check + *event.Data.Content deref - session.WaitForIdle() -> session.SendAndWait(ctx, ...) (WaitForIdle doesn't exist) - copilot.SystemMessage -> copilot.SystemMessageConfig All 5 recipes verified to compile against SDK v0.1.23. --- cookbook/copilot-sdk/go/error-handling.md | 98 ++++++++--------- .../copilot-sdk/go/managing-local-files.md | 42 ++++--- cookbook/copilot-sdk/go/multiple-sessions.md | 32 +++--- .../copilot-sdk/go/persisting-sessions.md | 31 +++--- cookbook/copilot-sdk/go/pr-visualization.md | 38 ++++--- .../copilot-sdk/go/recipe/error-handling.go | 31 ++---- .../go/recipe/managing-local-files.go | 38 ++++--- .../go/recipe/multiple-sessions.go | 26 +++-- .../go/recipe/persisting-sessions.go | 104 +++++++++--------- .../copilot-sdk/go/recipe/pr-visualization.go | 38 ++++--- 10 files changed, 246 insertions(+), 232 deletions(-) diff --git a/cookbook/copilot-sdk/go/error-handling.md b/cookbook/copilot-sdk/go/error-handling.md index 658613a9..462d2706 100644 --- a/cookbook/copilot-sdk/go/error-handling.md +++ b/cookbook/copilot-sdk/go/error-handling.md @@ -18,24 +18,22 @@ You need to handle various error conditions like connection failures, timeouts, package main import ( + "context" "fmt" "log" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { - client := copilot.NewClient() + ctx := context.Background() + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { log.Fatalf("Failed to start client: %v", err) } - defer func() { - if err := client.Stop(); err != nil { - log.Printf("Error stopping client: %v", err) - } - }() + defer client.Stop() - session, err := client.CreateSession(copilot.SessionConfig{ + session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5", }) if err != nil { @@ -43,19 +41,15 @@ func main() { } defer session.Destroy() - responseChan := make(chan string, 1) - session.On(func(event copilot.Event) { - if msg, ok := event.(copilot.AssistantMessageEvent); ok { - responseChan <- msg.Data.Content - } - }) - - if err := session.Send(copilot.MessageOptions{Prompt: "Hello!"}); err != nil { + result, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"}) + if err != nil { log.Printf("Failed to send message: %v", err) + return } - response := <-responseChan - fmt.Println(response) + if result != nil && result.Data.Content != nil { + fmt.Println(*result.Data.Content) + } } ``` @@ -63,14 +57,17 @@ func main() { ```go import ( + "context" "errors" + "fmt" "os/exec" + copilot "github.com/github/copilot-sdk/go" ) -func startClient() error { - client := copilot.NewClient() +func startClient(ctx context.Context) error { + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { var execErr *exec.Error if errors.As(err, &execErr) { return fmt.Errorf("Copilot CLI not found. Please install it first: %w", err) @@ -90,48 +87,41 @@ func startClient() error { ```go import ( "context" + "errors" + "fmt" "time" + copilot "github.com/github/copilot-sdk/go" ) func sendWithTimeout(session *copilot.Session) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - responseChan := make(chan string, 1) - errChan := make(chan error, 1) - - session.On(func(event copilot.Event) { - if msg, ok := event.(copilot.AssistantMessageEvent); ok { - responseChan <- msg.Data.Content + result, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Complex question..."}) + if err != nil { + if errors.Is(err, context.DeadlineExceeded) { + return fmt.Errorf("request timed out") } - }) - - if err := session.Send(copilot.MessageOptions{Prompt: "Complex question..."}); err != nil { return err } - select { - case response := <-responseChan: - fmt.Println(response) - return nil - case err := <-errChan: - return err - case <-ctx.Done(): - return fmt.Errorf("request timed out") + if result != nil && result.Data.Content != nil { + fmt.Println(*result.Data.Content) } + return nil } ``` ## Aborting a request ```go -func abortAfterDelay(session *copilot.Session) { - // Start a request - session.Send(copilot.MessageOptions{Prompt: "Write a very long story..."}) +func abortAfterDelay(ctx context.Context, session *copilot.Session) { + // Start a request (non-blocking send) + session.Send(ctx, copilot.MessageOptions{Prompt: "Write a very long story..."}) // Abort it after some condition time.AfterFunc(5*time.Second, func() { - if err := session.Abort(); err != nil { + if err := session.Abort(ctx); err != nil { log.Printf("Failed to abort: %v", err) } fmt.Println("Request aborted") @@ -143,13 +133,18 @@ func abortAfterDelay(session *copilot.Session) { ```go import ( + "context" + "fmt" + "log" "os" "os/signal" "syscall" + copilot "github.com/github/copilot-sdk/go" ) func main() { - client := copilot.NewClient() + ctx := context.Background() + client := copilot.NewClient(nil) // Set up signal handling sigChan := make(chan os.Signal, 1) @@ -158,15 +153,11 @@ func main() { go func() { <-sigChan fmt.Println("\nShutting down...") - - if err := client.Stop(); err != nil { - log.Printf("Cleanup errors: %v", err) - } - + client.Stop() os.Exit(0) }() - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { log.Fatal(err) } @@ -178,14 +169,15 @@ func main() { ```go func doWork() error { - client := copilot.NewClient() + ctx := context.Background() + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { return fmt.Errorf("failed to start: %w", err) } defer client.Stop() - session, err := client.CreateSession(copilot.SessionConfig{Model: "gpt-5"}) + session, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: "gpt-5"}) if err != nil { return fmt.Errorf("failed to create session: %w", err) } diff --git a/cookbook/copilot-sdk/go/managing-local-files.md b/cookbook/copilot-sdk/go/managing-local-files.md index 1e5a2999..f86871a5 100644 --- a/cookbook/copilot-sdk/go/managing-local-files.md +++ b/cookbook/copilot-sdk/go/managing-local-files.md @@ -18,23 +18,26 @@ You have a folder with many files and want to organize them into subfolders base package main import ( + "context" "fmt" "log" "os" "path/filepath" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { + ctx := context.Background() + // Create and start client - client := copilot.NewClient() - if err := client.Start(); err != nil { + client := copilot.NewClient(nil) + if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() // Create session - session, err := client.CreateSession(copilot.SessionConfig{ + session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5", }) if err != nil { @@ -43,14 +46,20 @@ func main() { defer session.Destroy() // Event handler - session.On(func(event copilot.Event) { - switch e := event.(type) { - case copilot.AssistantMessageEvent: - fmt.Printf("\nCopilot: %s\n", e.Data.Content) - case copilot.ToolExecutionStartEvent: - fmt.Printf(" → Running: %s\n", e.Data.ToolName) - case copilot.ToolExecutionCompleteEvent: - fmt.Printf(" āœ“ Completed: %s\n", e.Data.ToolName) + session.On(func(event copilot.SessionEvent) { + switch event.Type { + case "assistant.message": + if event.Data.Content != nil { + fmt.Printf("\nCopilot: %s\n", *event.Data.Content) + } + case "tool.execution_start": + if event.Data.ToolName != nil { + fmt.Printf(" → Running: %s\n", *event.Data.ToolName) + } + case "tool.execution_complete": + if event.Data.ToolName != nil { + fmt.Printf(" āœ“ Completed: %s\n", *event.Data.ToolName) + } } }) @@ -69,11 +78,10 @@ Analyze the files in "%s" and organize them into subfolders. Please confirm before moving any files. `, targetFolder) - if err := session.Send(copilot.MessageOptions{Prompt: prompt}); err != nil { + _, err = session.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt}) + if err != nil { log.Fatal(err) } - - session.WaitForIdle() } ``` @@ -116,7 +124,7 @@ Analyze files in "%s" and show me how you would organize them by file type. DO NOT move any files - just show me the plan. `, targetFolder) -session.Send(copilot.MessageOptions{Prompt: prompt}) +session.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt}) ``` ## Custom grouping with AI analysis @@ -134,7 +142,7 @@ Consider: Propose folder names that are descriptive and useful. `, targetFolder) -session.Send(copilot.MessageOptions{Prompt: prompt}) +session.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt}) ``` ## Safety considerations diff --git a/cookbook/copilot-sdk/go/multiple-sessions.md b/cookbook/copilot-sdk/go/multiple-sessions.md index 66261961..82d8bf50 100644 --- a/cookbook/copilot-sdk/go/multiple-sessions.md +++ b/cookbook/copilot-sdk/go/multiple-sessions.md @@ -18,47 +18,49 @@ You need to run multiple conversations in parallel, each with its own context an package main import ( + "context" "fmt" "log" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { - client := copilot.NewClient() + ctx := context.Background() + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() // Create multiple independent sessions - session1, err := client.CreateSession(copilot.SessionConfig{Model: "gpt-5"}) + session1, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: "gpt-5"}) if err != nil { log.Fatal(err) } defer session1.Destroy() - session2, err := client.CreateSession(copilot.SessionConfig{Model: "gpt-5"}) + session2, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: "gpt-5"}) if err != nil { log.Fatal(err) } defer session2.Destroy() - session3, err := client.CreateSession(copilot.SessionConfig{Model: "claude-sonnet-4.5"}) + session3, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: "claude-sonnet-4.5"}) if err != nil { log.Fatal(err) } defer session3.Destroy() // Each session maintains its own conversation history - session1.Send(copilot.MessageOptions{Prompt: "You are helping with a Python project"}) - session2.Send(copilot.MessageOptions{Prompt: "You are helping with a TypeScript project"}) - session3.Send(copilot.MessageOptions{Prompt: "You are helping with a Go project"}) + session1.Send(ctx, copilot.MessageOptions{Prompt: "You are helping with a Python project"}) + session2.Send(ctx, copilot.MessageOptions{Prompt: "You are helping with a TypeScript project"}) + session3.Send(ctx, copilot.MessageOptions{Prompt: "You are helping with a Go project"}) // Follow-up messages stay in their respective contexts - session1.Send(copilot.MessageOptions{Prompt: "How do I create a virtual environment?"}) - session2.Send(copilot.MessageOptions{Prompt: "How do I set up tsconfig?"}) - session3.Send(copilot.MessageOptions{Prompt: "How do I initialize a module?"}) + session1.Send(ctx, copilot.MessageOptions{Prompt: "How do I create a virtual environment?"}) + session2.Send(ctx, copilot.MessageOptions{Prompt: "How do I set up tsconfig?"}) + session3.Send(ctx, copilot.MessageOptions{Prompt: "How do I initialize a module?"}) } ``` @@ -67,7 +69,7 @@ func main() { Use custom IDs for easier tracking: ```go -session, err := client.CreateSession(copilot.SessionConfig{ +session, err := client.CreateSession(ctx, &copilot.SessionConfig{ SessionID: "user-123-chat", Model: "gpt-5", }) @@ -81,7 +83,7 @@ fmt.Println(session.SessionID) // "user-123-chat" ## Listing sessions ```go -sessions, err := client.ListSessions() +sessions, err := client.ListSessions(ctx) if err != nil { log.Fatal(err) } @@ -95,7 +97,7 @@ for _, sessionInfo := range sessions { ```go // Delete a specific session -if err := client.DeleteSession("user-123-chat"); err != nil { +if err := client.DeleteSession(ctx, "user-123-chat"); err != nil { log.Printf("Failed to delete session: %v", err) } ``` diff --git a/cookbook/copilot-sdk/go/persisting-sessions.md b/cookbook/copilot-sdk/go/persisting-sessions.md index 8587b978..ea13b7ab 100644 --- a/cookbook/copilot-sdk/go/persisting-sessions.md +++ b/cookbook/copilot-sdk/go/persisting-sessions.md @@ -19,22 +19,24 @@ You want users to be able to continue a conversation even after closing and reop package main import ( + "context" "fmt" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { - client := copilot.NewClient() - client.Start() + ctx := context.Background() + client := copilot.NewClient(nil) + client.Start(ctx) defer client.Stop() // Create session with a memorable ID - session, _ := client.CreateSession(copilot.SessionConfig{ + session, _ := client.CreateSession(ctx, &copilot.SessionConfig{ SessionID: "user-123-conversation", Model: "gpt-5", }) - session.Send(copilot.MessageOptions{Prompt: "Let's discuss TypeScript generics"}) + session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Let's discuss TypeScript generics"}) // Session ID is preserved fmt.Println(session.SessionID) @@ -47,15 +49,16 @@ func main() { ### Resuming a session ```go -client := copilot.NewClient() -client.Start() +ctx := context.Background() +client := copilot.NewClient(nil) +client.Start(ctx) defer client.Stop() // Resume the previous session -session, _ := client.ResumeSession("user-123-conversation") +session, _ := client.ResumeSession(ctx, "user-123-conversation") // Previous context is restored -session.Send(copilot.MessageOptions{Prompt: "What were we discussing?"}) +session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "What were we discussing?"}) session.Destroy() ``` @@ -63,7 +66,7 @@ session.Destroy() ### Listing available sessions ```go -sessions, _ := client.ListSessions() +sessions, _ := client.ListSessions(ctx) for _, s := range sessions { fmt.Println("Session:", s.SessionID) } @@ -73,15 +76,17 @@ for _, s := range sessions { ```go // Remove session and all its data from disk -client.DeleteSession("user-123-conversation") +client.DeleteSession(ctx, "user-123-conversation") ``` ### Getting session history ```go -messages, _ := session.GetMessages() +messages, _ := session.GetMessages(ctx) for _, msg := range messages { - fmt.Printf("[%s] %v\n", msg.Type, msg.Data) + if msg.Data.Content != nil { + fmt.Printf("[%s] %s\n", msg.Type, *msg.Data.Content) + } } ``` diff --git a/cookbook/copilot-sdk/go/pr-visualization.md b/cookbook/copilot-sdk/go/pr-visualization.md index e8046733..b0c7c0b3 100644 --- a/cookbook/copilot-sdk/go/pr-visualization.md +++ b/cookbook/copilot-sdk/go/pr-visualization.md @@ -39,6 +39,7 @@ package main import ( "bufio" + "context" "flag" "fmt" "log" @@ -46,7 +47,7 @@ import ( "os/exec" "regexp" "strings" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) // ============================================================================ @@ -94,6 +95,7 @@ func promptForRepo() string { // ============================================================================ func main() { + ctx := context.Background() repoFlag := flag.String("repo", "", "GitHub repository (owner/repo)") flag.Parse() @@ -126,18 +128,18 @@ func main() { parts := strings.SplitN(repo, "/", 2) owner, repoName := parts[0], parts[1] - // Create Copilot client - no custom tools needed! - client := copilot.NewClient(copilot.ClientConfig{LogLevel: "error"}) + // Create Copilot client + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() cwd, _ := os.Getwd() - session, err := client.CreateSession(copilot.SessionConfig{ + session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5", - SystemMessage: copilot.SystemMessage{ + SystemMessage: &copilot.SystemMessageConfig{ Content: fmt.Sprintf(` You are analyzing pull requests for the GitHub repository: %s/%s @@ -159,12 +161,16 @@ The current working directory is: %s defer session.Destroy() // Set up event handling - session.On(func(event copilot.Event) { - switch e := event.(type) { - case copilot.AssistantMessageEvent: - fmt.Printf("\nšŸ¤– %s\n\n", e.Data.Content) - case copilot.ToolExecutionStartEvent: - fmt.Printf(" āš™ļø %s\n", e.Data.ToolName) + session.On(func(event copilot.SessionEvent) { + switch event.Type { + case "assistant.message": + if event.Data.Content != nil { + fmt.Printf("\nšŸ¤– %s\n\n", *event.Data.Content) + } + case "tool.execution_start": + if event.Data.ToolName != nil { + fmt.Printf(" āš™ļø %s\n", *event.Data.ToolName) + } } }) @@ -180,12 +186,10 @@ The current working directory is: %s Finally, summarize the PR health - average age, oldest PR, and how many might be considered stale. `, owner, repoName) - if err := session.Send(copilot.MessageOptions{Prompt: prompt}); err != nil { + if _, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt}); err != nil { log.Fatal(err) } - session.WaitForIdle() - // Interactive loop fmt.Println("\nšŸ’” Ask follow-up questions or type \"exit\" to quit.\n") fmt.Println("Examples:") @@ -209,11 +213,9 @@ The current working directory is: %s break } - if err := session.Send(copilot.MessageOptions{Prompt: input}); err != nil { + if _, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: input}); err != nil { log.Printf("Error: %v", err) } - - session.WaitForIdle() } } ``` diff --git a/cookbook/copilot-sdk/go/recipe/error-handling.go b/cookbook/copilot-sdk/go/recipe/error-handling.go index 32edd9f9..3fc0fcdc 100644 --- a/cookbook/copilot-sdk/go/recipe/error-handling.go +++ b/cookbook/copilot-sdk/go/recipe/error-handling.go @@ -1,25 +1,23 @@ package main import ( + "context" "fmt" "log" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { - client := copilot.NewClient() + ctx := context.Background() + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { log.Fatalf("Failed to start client: %v", err) } - defer func() { - if err := client.Stop(); err != nil { - log.Printf("Error stopping client: %v", err) - } - }() + defer client.Stop() - session, err := client.CreateSession(copilot.SessionConfig{ + session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5", }) if err != nil { @@ -27,18 +25,13 @@ func main() { } defer session.Destroy() - responseChan := make(chan string, 1) - session.On(func(event copilot.Event) { - if msg, ok := event.(copilot.AssistantMessageEvent); ok { - responseChan <- msg.Data.Content - } - }) - - if err := session.Send(copilot.MessageOptions{Prompt: "Hello!"}); err != nil { + result, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"}) + if err != nil { log.Printf("Failed to send message: %v", err) return } - response := <-responseChan - fmt.Println(response) + if result != nil && result.Data.Content != nil { + fmt.Println(*result.Data.Content) + } } diff --git a/cookbook/copilot-sdk/go/recipe/managing-local-files.go b/cookbook/copilot-sdk/go/recipe/managing-local-files.go index f1582669..dc3dfd84 100644 --- a/cookbook/copilot-sdk/go/recipe/managing-local-files.go +++ b/cookbook/copilot-sdk/go/recipe/managing-local-files.go @@ -1,24 +1,27 @@ package main import ( + "context" "fmt" "log" "os" "path/filepath" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { + ctx := context.Background() + // Create and start client - client := copilot.NewClient() - if err := client.Start(); err != nil { + client := copilot.NewClient(nil) + if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() // Create session - session, err := client.CreateSession(copilot.SessionConfig{ + session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5", }) if err != nil { @@ -27,14 +30,20 @@ func main() { defer session.Destroy() // Event handler - session.On(func(event copilot.Event) { - switch e := event.(type) { - case copilot.AssistantMessageEvent: - fmt.Printf("\nCopilot: %s\n", e.Data.Content) - case copilot.ToolExecutionStartEvent: - fmt.Printf(" → Running: %s\n", e.Data.ToolName) - case copilot.ToolExecutionCompleteEvent: - fmt.Printf(" āœ“ Completed: %s\n", e.Data.ToolName) + session.On(func(event copilot.SessionEvent) { + switch event.Type { + case "assistant.message": + if event.Data.Content != nil { + fmt.Printf("\nCopilot: %s\n", *event.Data.Content) + } + case "tool.execution_start": + if event.Data.ToolName != nil { + fmt.Printf(" → Running: %s\n", *event.Data.ToolName) + } + case "tool.execution_complete": + if event.Data.ToolName != nil { + fmt.Printf(" āœ“ Completed: %s\n", *event.Data.ToolName) + } } }) @@ -54,9 +63,8 @@ Analyze the files in "%s" and organize them into subfolders. Please confirm before moving any files. `, targetFolder) - if err := session.Send(copilot.MessageOptions{Prompt: prompt}); err != nil { + _, err = session.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt}) + if err != nil { log.Fatal(err) } - - session.WaitForIdle() } diff --git a/cookbook/copilot-sdk/go/recipe/multiple-sessions.go b/cookbook/copilot-sdk/go/recipe/multiple-sessions.go index 0fb3325c..9b99fcd2 100644 --- a/cookbook/copilot-sdk/go/recipe/multiple-sessions.go +++ b/cookbook/copilot-sdk/go/recipe/multiple-sessions.go @@ -1,34 +1,36 @@ package main import ( + "context" "fmt" "log" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { - client := copilot.NewClient() + ctx := context.Background() + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() // Create multiple independent sessions - session1, err := client.CreateSession(copilot.SessionConfig{Model: "gpt-5"}) + session1, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: "gpt-5"}) if err != nil { log.Fatal(err) } defer session1.Destroy() - session2, err := client.CreateSession(copilot.SessionConfig{Model: "gpt-5"}) + session2, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: "gpt-5"}) if err != nil { log.Fatal(err) } defer session2.Destroy() - session3, err := client.CreateSession(copilot.SessionConfig{Model: "claude-sonnet-4.5"}) + session3, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: "claude-sonnet-4.5"}) if err != nil { log.Fatal(err) } @@ -37,16 +39,16 @@ func main() { fmt.Println("Created 3 independent sessions") // Each session maintains its own conversation history - session1.Send(copilot.MessageOptions{Prompt: "You are helping with a Python project"}) - session2.Send(copilot.MessageOptions{Prompt: "You are helping with a TypeScript project"}) - session3.Send(copilot.MessageOptions{Prompt: "You are helping with a Go project"}) + session1.Send(ctx, copilot.MessageOptions{Prompt: "You are helping with a Python project"}) + session2.Send(ctx, copilot.MessageOptions{Prompt: "You are helping with a TypeScript project"}) + session3.Send(ctx, copilot.MessageOptions{Prompt: "You are helping with a Go project"}) fmt.Println("Sent initial context to all sessions") // Follow-up messages stay in their respective contexts - session1.Send(copilot.MessageOptions{Prompt: "How do I create a virtual environment?"}) - session2.Send(copilot.MessageOptions{Prompt: "How do I set up tsconfig?"}) - session3.Send(copilot.MessageOptions{Prompt: "How do I initialize a module?"}) + session1.Send(ctx, copilot.MessageOptions{Prompt: "How do I create a virtual environment?"}) + session2.Send(ctx, copilot.MessageOptions{Prompt: "How do I set up tsconfig?"}) + session3.Send(ctx, copilot.MessageOptions{Prompt: "How do I initialize a module?"}) fmt.Println("Sent follow-up questions to each session") fmt.Println("All sessions will be destroyed on exit") diff --git a/cookbook/copilot-sdk/go/recipe/persisting-sessions.go b/cookbook/copilot-sdk/go/recipe/persisting-sessions.go index 11ee7ad0..471e5757 100644 --- a/cookbook/copilot-sdk/go/recipe/persisting-sessions.go +++ b/cookbook/copilot-sdk/go/recipe/persisting-sessions.go @@ -1,68 +1,68 @@ package main import ( - "fmt" - "log" + "context" + "fmt" + "log" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) func main() { - client := copilot.NewClient() - if err := client.Start(); err != nil { - log.Fatal(err) - } - defer client.Stop() + ctx := context.Background() + client := copilot.NewClient(nil) + if err := client.Start(ctx); err != nil { + log.Fatal(err) + } + defer client.Stop() - // Create session with a memorable ID - session, err := client.CreateSession(copilot.SessionConfig{ - SessionID: "user-123-conversation", - Model: "gpt-5", - }) - if err != nil { - log.Fatal(err) - } + // Create session with a memorable ID + session, err := client.CreateSession(ctx, &copilot.SessionConfig{ + SessionID: "user-123-conversation", + Model: "gpt-5", + }) + if err != nil { + log.Fatal(err) + } - if err := session.Send(copilot.MessageOptions{Prompt: "Let's discuss TypeScript generics"}); err != nil { - log.Fatal(err) - } - fmt.Printf("Session created: %s\n", session.SessionID) + _, err = session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Let's discuss TypeScript generics"}) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Session created: %s\n", session.SessionID) - // Destroy session but keep data on disk - if err := session.Destroy(); err != nil { - log.Fatal(err) - } - fmt.Println("Session destroyed (state persisted)") + // Destroy session but keep data on disk + session.Destroy() + fmt.Println("Session destroyed (state persisted)") - // Resume the previous session - resumed, err := client.ResumeSession("user-123-conversation") - if err != nil { - log.Fatal(err) - } - fmt.Printf("Resumed: %s\n", resumed.SessionID) + // Resume the previous session + resumed, err := client.ResumeSession(ctx, "user-123-conversation") + if err != nil { + log.Fatal(err) + } + fmt.Printf("Resumed: %s\n", resumed.SessionID) - if err := resumed.Send(copilot.MessageOptions{Prompt: "What were we discussing?"}); err != nil { - log.Fatal(err) - } + _, err = resumed.SendAndWait(ctx, copilot.MessageOptions{Prompt: "What were we discussing?"}) + if err != nil { + log.Fatal(err) + } - // List sessions - sessions, err := client.ListSessions() - if err != nil { - log.Fatal(err) - } - ids := make([]string, 0, len(sessions)) - for _, s := range sessions { - ids = append(ids, s.SessionID) - } - fmt.Printf("Sessions: %v\n", ids) + // List sessions + sessions, err := client.ListSessions(ctx) + if err != nil { + log.Fatal(err) + } + ids := make([]string, 0, len(sessions)) + for _, s := range sessions { + ids = append(ids, s.SessionID) + } + fmt.Printf("Sessions: %v\n", ids) - // Delete session permanently - if err := client.DeleteSession("user-123-conversation"); err != nil { - log.Fatal(err) - } - fmt.Println("Session deleted") + // Delete session permanently + if err := client.DeleteSession(ctx, "user-123-conversation"); err != nil { + log.Fatal(err) + } + fmt.Println("Session deleted") - if err := resumed.Destroy(); err != nil { - log.Fatal(err) - } + resumed.Destroy() } diff --git a/cookbook/copilot-sdk/go/recipe/pr-visualization.go b/cookbook/copilot-sdk/go/recipe/pr-visualization.go index abea027b..54178eec 100644 --- a/cookbook/copilot-sdk/go/recipe/pr-visualization.go +++ b/cookbook/copilot-sdk/go/recipe/pr-visualization.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "context" "flag" "fmt" "log" @@ -10,7 +11,7 @@ import ( "regexp" "strings" - "github.com/github/copilot-sdk/go" + copilot "github.com/github/copilot-sdk/go" ) // ============================================================================ @@ -58,6 +59,7 @@ func promptForRepo() string { // ============================================================================ func main() { + ctx := context.Background() repoFlag := flag.String("repo", "", "GitHub repository (owner/repo)") flag.Parse() @@ -90,18 +92,18 @@ func main() { parts := strings.SplitN(repo, "/", 2) owner, repoName := parts[0], parts[1] - // Create Copilot client - no custom tools needed! - client := copilot.NewClient(copilot.ClientConfig{LogLevel: "error"}) + // Create Copilot client + client := copilot.NewClient(nil) - if err := client.Start(); err != nil { + if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() cwd, _ := os.Getwd() - session, err := client.CreateSession(copilot.SessionConfig{ + session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5", - SystemMessage: copilot.SystemMessage{ + SystemMessage: &copilot.SystemMessageConfig{ Content: fmt.Sprintf(` You are analyzing pull requests for the GitHub repository: %s/%s @@ -123,12 +125,16 @@ The current working directory is: %s defer session.Destroy() // Set up event handling - session.On(func(event copilot.Event) { - switch e := event.(type) { - case copilot.AssistantMessageEvent: - fmt.Printf("\nšŸ¤– %s\n\n", e.Data.Content) - case copilot.ToolExecutionStartEvent: - fmt.Printf(" āš™ļø %s\n", e.Data.ToolName) + session.On(func(event copilot.SessionEvent) { + switch event.Type { + case "assistant.message": + if event.Data.Content != nil { + fmt.Printf("\nšŸ¤– %s\n\n", *event.Data.Content) + } + case "tool.execution_start": + if event.Data.ToolName != nil { + fmt.Printf(" āš™ļø %s\n", *event.Data.ToolName) + } } }) @@ -144,12 +150,10 @@ The current working directory is: %s Finally, summarize the PR health - average age, oldest PR, and how many might be considered stale. `, owner, repoName) - if err := session.Send(copilot.MessageOptions{Prompt: prompt}); err != nil { + if _, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt}); err != nil { log.Fatal(err) } - session.WaitForIdle() - // Interactive loop fmt.Println("\nšŸ’” Ask follow-up questions or type \"exit\" to quit.\n") fmt.Println("Examples:") @@ -173,10 +177,8 @@ The current working directory is: %s break } - if err := session.Send(copilot.MessageOptions{Prompt: input}); err != nil { + if _, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: input}); err != nil { log.Printf("Error: %v", err) } - - session.WaitForIdle() } }