Skip to content

Commit d4dc83d

Browse files
authored
Merge pull request #131 from copilot-community-sdk/copilot/create-cookbooks-dotnet-go
Add cookbook with 5 practical recipes for common SDK usage patterns
2 parents c5a8b2d + 758151b commit d4dc83d

10 files changed

Lines changed: 1250 additions & 1 deletion

File tree

.github/workflows/publish-maven.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,13 @@ jobs:
116116
# Update version in jbang-example.java
117117
sed -i "s|copilot-sdk:[0-9]*\.[0-9]*\.[0-9]*|copilot-sdk:${VERSION}|g" jbang-example.java
118118
119+
# Update version in cookbook files (Maven will filter ${project.version} during site generation,
120+
# but we also need the actual version for direct JBang usage)
121+
find src/site/markdown/cookbook -name "*.md" -type f -exec \
122+
sed -i "s|\${project.version}|${VERSION}|g" {} \;
123+
119124
# Commit the documentation changes before release:prepare (requires clean working directory)
120-
git add CHANGELOG.md README.md jbang-example.java
125+
git add CHANGELOG.md README.md jbang-example.java src/site/markdown/cookbook/
121126
git commit -m "docs: update version references to ${VERSION}"
122127
123128
# Save the commit SHA for potential rollback

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
1212
1313
### Added
1414

15+
#### Cookbook with Practical Recipes
16+
17+
Added a comprehensive cookbook with 5 practical recipes demonstrating common SDK usage patterns. All examples are JBang-compatible and can be run directly without a full Maven project setup.
18+
19+
**Recipes:**
20+
- **Error Handling** - Connection failures, timeouts, cleanup patterns, tool errors
21+
- **Multiple Sessions** - Parallel conversations, custom session IDs, lifecycle management
22+
- **Managing Local Files** - AI-powered file organization with grouping strategies
23+
- **PR Visualization** - Interactive CLI tool for analyzing PR age distribution via GitHub MCP Server
24+
- **Persisting Sessions** - Save and resume conversations across restarts
25+
26+
**Location:** `src/site/markdown/cookbook/`
27+
28+
**Usage:**
29+
```bash
30+
jbang BasicErrorHandling.java
31+
jbang MultipleSessions.java
32+
jbang PRVisualization.java github/copilot-sdk
33+
```
34+
35+
Each recipe includes JBang prerequisites, usage instructions, and best practices.
36+
1537
#### Session Context and Filtering
1638

1739
Added session context tracking and filtering capabilities to help manage multiple Copilot sessions across different repositories and working directories.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ jbang https://github.com/copilot-community-sdk/copilot-sdk-java/blob/latest/jban
105105
- [Getting Started](https://copilot-community-sdk.github.io/copilot-sdk-java/documentation.html)
106106
- [Javadoc API Reference](https://copilot-community-sdk.github.io/copilot-sdk-java/apidocs/)
107107
- [MCP Servers Integration](https://copilot-community-sdk.github.io/copilot-sdk-java/mcp.html)
108+
- [Cookbook](src/site/markdown/cookbook/) — Practical recipes for common use cases
108109

109110
## Projects Using This SDK
110111

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# GitHub Copilot SDK Cookbook — Java
2+
3+
This folder hosts short, practical recipes for using the GitHub Copilot SDK with Java. Each recipe is concise, copy‑pasteable, and points to fuller examples and tests.
4+
5+
## Prerequisites
6+
7+
All cookbook examples can be run directly using [JBang](https://www.jbang.dev/), which allows you to run Java code without a full project setup.
8+
9+
**Install JBang:**
10+
11+
```bash
12+
# macOS (using Homebrew)
13+
brew install jbangdev/tap/jbang
14+
15+
# Linux/macOS (using curl)
16+
curl -Ls https://sh.jbang.dev | bash -s - app setup
17+
18+
# Windows (using Scoop)
19+
scoop install jbang
20+
```
21+
22+
For other installation methods, see the [JBang installation guide](https://www.jbang.dev/download/).
23+
24+
## Recipes
25+
26+
- [Error Handling](error-handling.md): Handle errors gracefully including connection failures, timeouts, and cleanup.
27+
- [Multiple Sessions](multiple-sessions.md): Manage multiple independent conversations simultaneously.
28+
- [Managing Local Files](managing-local-files.md): Organize files by metadata using AI-powered grouping strategies.
29+
- [PR Visualization](pr-visualization.md): Generate interactive PR age charts using GitHub MCP Server.
30+
- [Persisting Sessions](persisting-sessions.md): Save and resume sessions across restarts.
31+
32+
## Contributing
33+
34+
Add a new recipe by creating a markdown file in this folder and linking it above. Follow repository guidance in the [main README](https://github.com/github/copilot-sdk-java#contributing).
35+
36+
## Status
37+
38+
These recipes are complete, practical examples and can be used directly or adapted for your own projects.
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
# Error Handling Patterns
2+
3+
Handle errors gracefully in your Copilot SDK applications.
4+
5+
## Prerequisites
6+
7+
Install [JBang](https://www.jbang.dev/) to run these examples:
8+
9+
```bash
10+
# macOS (using Homebrew)
11+
brew install jbangdev/tap/jbang
12+
13+
# Linux/macOS (using curl)
14+
curl -Ls https://sh.jbang.dev | bash -s - app setup
15+
16+
# Windows (using Scoop)
17+
scoop install jbang
18+
```
19+
20+
## Example scenario
21+
22+
You need to handle various error conditions like connection failures, timeouts, and invalid responses.
23+
24+
## Basic error handling
25+
26+
**Usage:**
27+
```bash
28+
jbang BasicErrorHandling.java
29+
```
30+
31+
**Code:**
32+
```java
33+
//DEPS io.github.copilot-community-sdk:copilot-sdk:${project.version}
34+
import com.github.copilot.sdk.*;
35+
import com.github.copilot.sdk.events.*;
36+
import com.github.copilot.sdk.json.*;
37+
38+
public class BasicErrorHandling {
39+
public static void main(String[] args) {
40+
try (var client = new CopilotClient()) {
41+
client.start().get();
42+
43+
var session = client.createSession(
44+
new SessionConfig().setModel("gpt-5")).get();
45+
46+
session.on(AssistantMessageEvent.class, msg -> {
47+
System.out.println(msg.getData().getContent());
48+
});
49+
50+
session.sendAndWait(new MessageOptions()
51+
.setPrompt("Hello!")).get();
52+
53+
session.close();
54+
} catch (Exception ex) {
55+
System.err.println("Error: " + ex.getMessage());
56+
ex.printStackTrace();
57+
}
58+
}
59+
}
60+
```
61+
62+
## Handling specific error types
63+
64+
```java
65+
//DEPS io.github.copilot-community-sdk:copilot-sdk:${project.version}
66+
import com.github.copilot.sdk.*;
67+
import com.github.copilot.sdk.events.*;
68+
import com.github.copilot.sdk.json.*;
69+
import java.util.concurrent.ExecutionException;
70+
71+
public class SpecificErrorHandling {
72+
public static void startClient() {
73+
try (var client = new CopilotClient()) {
74+
client.start().get();
75+
// ... use client ...
76+
} catch (ExecutionException ex) {
77+
Throwable cause = ex.getCause();
78+
if (cause instanceof java.io.IOException) {
79+
System.err.println("Copilot CLI not found. Please install it first.");
80+
System.err.println("Details: " + cause.getMessage());
81+
} else if (cause instanceof java.util.concurrent.TimeoutException) {
82+
System.err.println("Could not connect to Copilot CLI server.");
83+
System.err.println("Details: " + cause.getMessage());
84+
} else {
85+
System.err.println("Unexpected error: " + cause.getMessage());
86+
cause.printStackTrace();
87+
}
88+
} catch (InterruptedException ex) {
89+
Thread.currentThread().interrupt();
90+
System.err.println("Operation interrupted: " + ex.getMessage());
91+
} catch (Exception ex) {
92+
System.err.println("Unexpected error: " + ex.getMessage());
93+
ex.printStackTrace();
94+
}
95+
}
96+
}
97+
```
98+
99+
## Timeout handling
100+
101+
```java
102+
//DEPS io.github.copilot-community-sdk:copilot-sdk:${project.version}
103+
import com.github.copilot.sdk.*;
104+
import com.github.copilot.sdk.events.*;
105+
import com.github.copilot.sdk.json.*;
106+
import java.util.concurrent.TimeUnit;
107+
import java.util.concurrent.TimeoutException;
108+
109+
public class TimeoutHandling {
110+
public static void sendWithTimeout(CopilotSession session) {
111+
try {
112+
session.on(AssistantMessageEvent.class, msg -> {
113+
System.out.println(msg.getData().getContent());
114+
});
115+
116+
// Wait up to 30 seconds for response
117+
session.sendAndWait(new MessageOptions()
118+
.setPrompt("Complex question..."))
119+
.get(30, TimeUnit.SECONDS);
120+
121+
} catch (TimeoutException ex) {
122+
System.err.println("Request timed out");
123+
} catch (Exception ex) {
124+
System.err.println("Error: " + ex.getMessage());
125+
}
126+
}
127+
}
128+
```
129+
130+
## Aborting a request
131+
132+
```java
133+
//DEPS io.github.copilot-community-sdk:copilot-sdk:${project.version}
134+
import com.github.copilot.sdk.*;
135+
import com.github.copilot.sdk.events.*;
136+
import com.github.copilot.sdk.json.*;
137+
import java.util.concurrent.Executors;
138+
import java.util.concurrent.ScheduledExecutorService;
139+
import java.util.concurrent.TimeUnit;
140+
141+
public class AbortRequest {
142+
public static void abortAfterDelay(CopilotSession session) {
143+
// Start a request (non-blocking)
144+
session.send(new MessageOptions()
145+
.setPrompt("Write a very long story..."));
146+
147+
// Schedule abort after 5 seconds
148+
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
149+
scheduler.schedule(() -> {
150+
try {
151+
session.abort().get();
152+
System.out.println("Request aborted");
153+
} catch (Exception ex) {
154+
System.err.println("Failed to abort: " + ex.getMessage());
155+
} finally {
156+
scheduler.shutdown();
157+
}
158+
}, 5, TimeUnit.SECONDS);
159+
}
160+
}
161+
```
162+
163+
## Graceful shutdown
164+
165+
```java
166+
//DEPS io.github.copilot-community-sdk:copilot-sdk:${project.version}
167+
import com.github.copilot.sdk.*;
168+
import com.github.copilot.sdk.events.*;
169+
import com.github.copilot.sdk.json.*;
170+
171+
public class GracefulShutdown {
172+
public static void main(String[] args) {
173+
var client = new CopilotClient();
174+
175+
// Set up shutdown hook
176+
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
177+
System.out.println("\nShutting down...");
178+
try {
179+
client.close();
180+
} catch (Exception ex) {
181+
System.err.println("Error during shutdown: " + ex.getMessage());
182+
}
183+
}));
184+
185+
try {
186+
client.start().get();
187+
// ... do work ...
188+
} catch (Exception ex) {
189+
ex.printStackTrace();
190+
}
191+
}
192+
}
193+
```
194+
195+
## Try-with-resources pattern
196+
197+
```java
198+
//DEPS io.github.copilot-community-sdk:copilot-sdk:${project.version}
199+
import com.github.copilot.sdk.*;
200+
import com.github.copilot.sdk.events.*;
201+
import com.github.copilot.sdk.json.*;
202+
203+
public class TryWithResources {
204+
public static void doWork() throws Exception {
205+
try (var client = new CopilotClient()) {
206+
client.start().get();
207+
208+
try (var session = client.createSession(
209+
new SessionConfig().setModel("gpt-5")).get()) {
210+
211+
session.on(AssistantMessageEvent.class, msg -> {
212+
System.out.println(msg.getData().getContent());
213+
});
214+
215+
session.sendAndWait(new MessageOptions()
216+
.setPrompt("Hello!")).get();
217+
218+
// Session and client are automatically closed
219+
}
220+
}
221+
}
222+
}
223+
```
224+
225+
## Handling tool errors
226+
227+
```java
228+
//DEPS io.github.copilot-community-sdk:copilot-sdk:${project.version}
229+
import com.github.copilot.sdk.*;
230+
import com.github.copilot.sdk.events.*;
231+
import com.github.copilot.sdk.json.*;
232+
import java.util.Map;
233+
import java.util.List;
234+
import java.util.concurrent.CompletableFuture;
235+
236+
public class ToolErrorHandling {
237+
public static void handleToolErrors() throws Exception {
238+
var errorTool = ToolDefinition.create(
239+
"get_user_location",
240+
"Gets the user's location",
241+
Map.of("type", "object", "properties", Map.of()),
242+
invocation -> {
243+
// Return an error result
244+
return CompletableFuture.completedFuture(
245+
ToolResultObject.error("Location service unavailable")
246+
);
247+
}
248+
);
249+
250+
try (var client = new CopilotClient()) {
251+
client.start().get();
252+
253+
var session = client.createSession(
254+
new SessionConfig().setTools(List.of(errorTool))).get();
255+
256+
session.on(AssistantMessageEvent.class, msg -> {
257+
System.out.println(msg.getData().getContent());
258+
});
259+
260+
// Session continues even when tool fails
261+
session.sendAndWait(new MessageOptions()
262+
.setPrompt("What is my location? If you can't find out, just say 'unknown'."))
263+
.get();
264+
265+
session.close();
266+
}
267+
}
268+
}
269+
```
270+
271+
## Best practices
272+
273+
1. **Always clean up**: Use try-with-resources to ensure `close()` is called
274+
2. **Handle connection errors**: The CLI might not be installed or running
275+
3. **Set appropriate timeouts**: Use `get(timeout, TimeUnit)` for long-running requests
276+
4. **Log errors**: Capture error details for debugging
277+
5. **Wrap operations**: Consider wrapping SDK operations in methods that handle common errors
278+
6. **Check error causes**: Use `ExecutionException.getCause()` to get the actual error from `CompletableFuture`

0 commit comments

Comments
 (0)