|
| 1 | +# Copilot SDK for Java - Documentation |
| 2 | + |
| 3 | +This document provides detailed API reference and usage examples for the Copilot SDK for Java. |
| 4 | + |
| 5 | +## Table of Contents |
| 6 | + |
| 7 | +- [API Reference](#api-reference) |
| 8 | + - [CopilotClient](#copilotclient) |
| 9 | + - [CopilotSession](#copilotsession) |
| 10 | +- [Event Types](#event-types) |
| 11 | +- [Streaming](#streaming) |
| 12 | +- [Advanced Usage](#advanced-usage) |
| 13 | + - [Manual Server Control](#manual-server-control) |
| 14 | + - [Tools](#tools) |
| 15 | + - [System Message Customization](#system-message-customization) |
| 16 | + - [Multiple Sessions](#multiple-sessions) |
| 17 | + - [File Attachments](#file-attachments) |
| 18 | + - [Bring Your Own Key (BYOK)](#bring-your-own-key-byok) |
| 19 | + - [Permission Handling](#permission-handling) |
| 20 | +- [Error Handling](#error-handling) |
| 21 | + |
| 22 | +## API Reference |
| 23 | + |
| 24 | +### CopilotClient |
| 25 | + |
| 26 | +#### Constructor |
| 27 | + |
| 28 | +```java |
| 29 | +new CopilotClient() |
| 30 | +new CopilotClient(CopilotClientOptions options) |
| 31 | +``` |
| 32 | + |
| 33 | +**Options:** |
| 34 | + |
| 35 | +- `cliPath` - Path to CLI executable (default: "copilot" from PATH) |
| 36 | +- `cliArgs` - Extra arguments prepended before SDK-managed flags |
| 37 | +- `cliUrl` - URL of existing CLI server to connect to (e.g., `"localhost:8080"`). When provided, the client will not spawn a CLI process. |
| 38 | +- `port` - Server port (default: 0 for random) |
| 39 | +- `useStdio` - Use stdio transport instead of TCP (default: true) |
| 40 | +- `logLevel` - Log level (default: "info") |
| 41 | +- `autoStart` - Auto-start server (default: true) |
| 42 | +- `autoRestart` - Auto-restart on crash (default: true) |
| 43 | +- `cwd` - Working directory for the CLI process |
| 44 | +- `environment` - Environment variables to pass to the CLI process |
| 45 | + |
| 46 | +#### Methods |
| 47 | + |
| 48 | +##### `start(): CompletableFuture<Void>` |
| 49 | + |
| 50 | +Start the CLI server and establish connection. |
| 51 | + |
| 52 | +##### `stop(): CompletableFuture<Void>` |
| 53 | + |
| 54 | +Stop the server and close all sessions. |
| 55 | + |
| 56 | +##### `forceStop(): CompletableFuture<Void>` |
| 57 | + |
| 58 | +Force stop the CLI server without graceful cleanup. |
| 59 | + |
| 60 | +##### `createSession(SessionConfig config): CompletableFuture<CopilotSession>` |
| 61 | + |
| 62 | +Create a new conversation session. |
| 63 | + |
| 64 | +**Config:** |
| 65 | + |
| 66 | +- `sessionId` - Custom session ID |
| 67 | +- `model` - Model to use ("gpt-5", "claude-sonnet-4.5", etc.) |
| 68 | +- `tools` - Custom tools exposed to the CLI |
| 69 | +- `systemMessage` - System message customization |
| 70 | +- `availableTools` - List of tool names to allow |
| 71 | +- `excludedTools` - List of tool names to disable |
| 72 | +- `provider` - Custom API provider configuration (BYOK) |
| 73 | +- `streaming` - Enable streaming of response chunks (default: false) |
| 74 | +- `mcpServers` - MCP server configurations |
| 75 | +- `customAgents` - Custom agent configurations |
| 76 | +- `onPermissionRequest` - Handler for permission requests |
| 77 | + |
| 78 | +##### `resumeSession(String sessionId, ResumeSessionConfig config): CompletableFuture<CopilotSession>` |
| 79 | + |
| 80 | +Resume an existing session. |
| 81 | + |
| 82 | +##### `ping(String message): CompletableFuture<PingResponse>` |
| 83 | + |
| 84 | +Ping the server to check connectivity. |
| 85 | + |
| 86 | +##### `getState(): ConnectionState` |
| 87 | + |
| 88 | +Get current connection state. Returns one of: `DISCONNECTED`, `CONNECTING`, `CONNECTED`, `ERROR`. |
| 89 | + |
| 90 | +##### `listSessions(): CompletableFuture<List<SessionMetadata>>` |
| 91 | + |
| 92 | +List all available sessions. |
| 93 | + |
| 94 | +##### `deleteSession(String sessionId): CompletableFuture<Void>` |
| 95 | + |
| 96 | +Delete a session and its data from disk. |
| 97 | + |
| 98 | +##### `getLastSessionId(): CompletableFuture<String>` |
| 99 | + |
| 100 | +Get the ID of the most recently used session. |
| 101 | + |
| 102 | +--- |
| 103 | + |
| 104 | +### CopilotSession |
| 105 | + |
| 106 | +Represents a single conversation session. |
| 107 | + |
| 108 | +#### Properties |
| 109 | + |
| 110 | +- `getSessionId()` - The unique identifier for this session |
| 111 | + |
| 112 | +#### Methods |
| 113 | + |
| 114 | +##### `send(MessageOptions options): CompletableFuture<String>` |
| 115 | + |
| 116 | +Send a message to the session. |
| 117 | + |
| 118 | +**Options:** |
| 119 | + |
| 120 | +- `prompt` - The message/prompt to send |
| 121 | +- `attachments` - File attachments |
| 122 | +- `mode` - Delivery mode ("enqueue" or "immediate") |
| 123 | + |
| 124 | +Returns the message ID. |
| 125 | + |
| 126 | +##### `sendAndWait(MessageOptions options, long timeoutMs): CompletableFuture<AssistantMessageEvent>` |
| 127 | + |
| 128 | +Send a message and wait for the session to become idle. Default timeout is 60 seconds. |
| 129 | + |
| 130 | +##### `on(Consumer<AbstractSessionEvent> handler): Closeable` |
| 131 | + |
| 132 | +Subscribe to session events. Returns a `Closeable` to unsubscribe. |
| 133 | + |
| 134 | +```java |
| 135 | +var subscription = session.on(evt -> { |
| 136 | + System.out.println("Event: " + evt.getType()); |
| 137 | +}); |
| 138 | + |
| 139 | +// Later... |
| 140 | +subscription.close(); |
| 141 | +``` |
| 142 | + |
| 143 | +##### `abort(): CompletableFuture<Void>` |
| 144 | + |
| 145 | +Abort the currently processing message in this session. |
| 146 | + |
| 147 | +##### `getMessages(): CompletableFuture<List<AbstractSessionEvent>>` |
| 148 | + |
| 149 | +Get all events/messages from this session. |
| 150 | + |
| 151 | +##### `close()` |
| 152 | + |
| 153 | +Dispose the session and free resources. |
| 154 | + |
| 155 | +--- |
| 156 | + |
| 157 | +## Event Types |
| 158 | + |
| 159 | +Sessions emit various events during processing. Each event type extends `AbstractSessionEvent`: |
| 160 | + |
| 161 | +- `UserMessageEvent` - User message added |
| 162 | +- `AssistantMessageEvent` - Assistant response |
| 163 | +- `AssistantMessageDeltaEvent` - Streaming response chunk |
| 164 | +- `ToolExecutionStartEvent` - Tool execution started |
| 165 | +- `ToolExecutionCompleteEvent` - Tool execution completed |
| 166 | +- `SessionStartEvent` - Session started |
| 167 | +- `SessionIdleEvent` - Session is idle |
| 168 | +- `SessionErrorEvent` - Session error occurred |
| 169 | +- `SessionResumeEvent` - Session was resumed |
| 170 | +- And more... |
| 171 | + |
| 172 | +Use pattern matching (Java 21+) to handle specific event types: |
| 173 | + |
| 174 | +```java |
| 175 | +session.on(evt -> { |
| 176 | + if (evt instanceof AssistantMessageEvent msg) { |
| 177 | + System.out.println(msg.getData().getContent()); |
| 178 | + } else if (evt instanceof SessionErrorEvent err) { |
| 179 | + System.out.println("Error: " + err.getData().getMessage()); |
| 180 | + } |
| 181 | +}); |
| 182 | +``` |
| 183 | + |
| 184 | +## Streaming |
| 185 | + |
| 186 | +Enable streaming to receive assistant response chunks as they're generated: |
| 187 | + |
| 188 | +```java |
| 189 | +var session = client.createSession( |
| 190 | + new SessionConfig() |
| 191 | + .setModel("gpt-5") |
| 192 | + .setStreaming(true) |
| 193 | +).get(); |
| 194 | + |
| 195 | +var done = new CompletableFuture<Void>(); |
| 196 | + |
| 197 | +session.on(evt -> { |
| 198 | + if (evt instanceof AssistantMessageDeltaEvent delta) { |
| 199 | + // Streaming message chunk - print incrementally |
| 200 | + System.out.print(delta.getData().getDeltaContent()); |
| 201 | + } else if (evt instanceof AssistantMessageEvent msg) { |
| 202 | + // Final message - complete content |
| 203 | + System.out.println("\n--- Final message ---"); |
| 204 | + System.out.println(msg.getData().getContent()); |
| 205 | + } else if (evt instanceof SessionIdleEvent) { |
| 206 | + done.complete(null); |
| 207 | + } |
| 208 | +}); |
| 209 | + |
| 210 | +session.send(new MessageOptions().setPrompt("Tell me a short story")).get(); |
| 211 | +done.get(); |
| 212 | +``` |
| 213 | + |
| 214 | +## Advanced Usage |
| 215 | + |
| 216 | +### Manual Server Control |
| 217 | + |
| 218 | +```java |
| 219 | +var client = new CopilotClient( |
| 220 | + new CopilotClientOptions().setAutoStart(false) |
| 221 | +); |
| 222 | + |
| 223 | +// Start manually |
| 224 | +client.start().get(); |
| 225 | + |
| 226 | +// Use client... |
| 227 | + |
| 228 | +// Stop manually |
| 229 | +client.stop().get(); |
| 230 | +``` |
| 231 | + |
| 232 | +### Tools |
| 233 | + |
| 234 | +You can let the CLI call back into your process when the model needs capabilities you own: |
| 235 | + |
| 236 | +```java |
| 237 | +var lookupTool = ToolDefinition.create( |
| 238 | + "lookup_issue", |
| 239 | + "Fetch issue details from our tracker", |
| 240 | + Map.of( |
| 241 | + "type", "object", |
| 242 | + "properties", Map.of( |
| 243 | + "id", Map.of("type", "string", "description", "Issue identifier") |
| 244 | + ), |
| 245 | + "required", List.of("id") |
| 246 | + ), |
| 247 | + invocation -> { |
| 248 | + String id = ((Map<String, Object>) invocation.getArguments()).get("id").toString(); |
| 249 | + return CompletableFuture.completedFuture(fetchIssue(id)); |
| 250 | + } |
| 251 | +); |
| 252 | + |
| 253 | +var session = client.createSession( |
| 254 | + new SessionConfig() |
| 255 | + .setModel("gpt-5") |
| 256 | + .setTools(List.of(lookupTool)) |
| 257 | +).get(); |
| 258 | +``` |
| 259 | + |
| 260 | +### System Message Customization |
| 261 | + |
| 262 | +Control the system prompt using `SystemMessageConfig` in session config: |
| 263 | + |
| 264 | +```java |
| 265 | +var session = client.createSession( |
| 266 | + new SessionConfig() |
| 267 | + .setModel("gpt-5") |
| 268 | + .setSystemMessage(new SystemMessageConfig() |
| 269 | + .setMode(SystemMessageMode.APPEND) |
| 270 | + .setContent(""" |
| 271 | + <workflow_rules> |
| 272 | + - Always check for security vulnerabilities |
| 273 | + - Suggest performance improvements when applicable |
| 274 | + </workflow_rules> |
| 275 | + """)) |
| 276 | +).get(); |
| 277 | +``` |
| 278 | + |
| 279 | +For full control (removes all guardrails), use `REPLACE` mode: |
| 280 | + |
| 281 | +```java |
| 282 | +var session = client.createSession( |
| 283 | + new SessionConfig() |
| 284 | + .setModel("gpt-5") |
| 285 | + .setSystemMessage(new SystemMessageConfig() |
| 286 | + .setMode(SystemMessageMode.REPLACE) |
| 287 | + .setContent("You are a helpful assistant.")) |
| 288 | +).get(); |
| 289 | +``` |
| 290 | + |
| 291 | +### Multiple Sessions |
| 292 | + |
| 293 | +```java |
| 294 | +var session1 = client.createSession( |
| 295 | + new SessionConfig().setModel("gpt-5") |
| 296 | +).get(); |
| 297 | + |
| 298 | +var session2 = client.createSession( |
| 299 | + new SessionConfig().setModel("claude-sonnet-4.5") |
| 300 | +).get(); |
| 301 | + |
| 302 | +// Both sessions are independent |
| 303 | +session1.send(new MessageOptions().setPrompt("Hello from session 1")).get(); |
| 304 | +session2.send(new MessageOptions().setPrompt("Hello from session 2")).get(); |
| 305 | +``` |
| 306 | + |
| 307 | +### File Attachments |
| 308 | + |
| 309 | +```java |
| 310 | +session.send(new MessageOptions() |
| 311 | + .setPrompt("Analyze this file") |
| 312 | + .setAttachments(List.of( |
| 313 | + new Attachment() |
| 314 | + .setType("file") |
| 315 | + .setPath("/path/to/file.java") |
| 316 | + .setDisplayName("My File") |
| 317 | + )) |
| 318 | +).get(); |
| 319 | +``` |
| 320 | + |
| 321 | +### Bring Your Own Key (BYOK) |
| 322 | + |
| 323 | +Use a custom API provider: |
| 324 | + |
| 325 | +```java |
| 326 | +var session = client.createSession( |
| 327 | + new SessionConfig() |
| 328 | + .setProvider(new ProviderConfig() |
| 329 | + .setType("openai") |
| 330 | + .setBaseUrl("https://api.openai.com/v1") |
| 331 | + .setApiKey("your-api-key")) |
| 332 | +).get(); |
| 333 | +``` |
| 334 | + |
| 335 | +### Permission Handling |
| 336 | + |
| 337 | +Handle permission requests from the CLI: |
| 338 | + |
| 339 | +```java |
| 340 | +var session = client.createSession( |
| 341 | + new SessionConfig() |
| 342 | + .setModel("gpt-5") |
| 343 | + .setOnPermissionRequest((request, invocation) -> { |
| 344 | + // Approve or deny the permission request |
| 345 | + var result = new PermissionRequestResult(); |
| 346 | + result.setKind("user-approved"); |
| 347 | + return CompletableFuture.completedFuture(result); |
| 348 | + }) |
| 349 | +).get(); |
| 350 | +``` |
| 351 | + |
| 352 | +## Error Handling |
| 353 | + |
| 354 | +```java |
| 355 | +try { |
| 356 | + var session = client.createSession().get(); |
| 357 | + session.send(new MessageOptions().setPrompt("Hello")).get(); |
| 358 | +} catch (ExecutionException ex) { |
| 359 | + Throwable cause = ex.getCause(); |
| 360 | + System.err.println("Error: " + cause.getMessage()); |
| 361 | +} |
| 362 | +``` |
0 commit comments