From 9b7d10082d4eb90d6ea03ed9b38a1f2b0a477f2a Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Tue, 17 Mar 2026 00:49:25 -0700 Subject: [PATCH 1/6] Add Copilot SDK Java instructions file Add instructions/copilot-sdk-java.instructions.md modeled after the C# equivalent in github/awesome-copilot. Covers client initialization, session management, event handling, streaming, custom tools, BYOK, permissions, and common usage patterns for Java developers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- instructions/copilot-sdk-java.instructions.md | 762 ++++++++++++++++++ 1 file changed, 762 insertions(+) create mode 100644 instructions/copilot-sdk-java.instructions.md diff --git a/instructions/copilot-sdk-java.instructions.md b/instructions/copilot-sdk-java.instructions.md new file mode 100644 index 000000000..fe358b3b1 --- /dev/null +++ b/instructions/copilot-sdk-java.instructions.md @@ -0,0 +1,762 @@ +--- +applyTo: '**.java, **/pom.xml' +description: 'This file provides guidance on building Java applications using GitHub Copilot SDK for Java.' +name: 'GitHub Copilot SDK Java Instructions' +--- + +## Core Principles + +- The SDK is in technical preview and may have breaking changes +- Requires Java 17 or later +- Requires GitHub Copilot CLI installed and in PATH +- Uses `CompletableFuture` for all async operations +- Implements `AutoCloseable` for resource cleanup (try-with-resources) + +## Installation + +### Maven + +```xml + + com.github.copilot + copilot-sdk-java + LATEST + +``` + +### Gradle + +```groovy +implementation 'com.github.copilot:copilot-sdk-java:LATEST' +``` + +## Client Initialization + +### Basic Client Setup + +```java +try (var client = new CopilotClient()) { + client.start().get(); + // Use client... +} +``` + +### Client Configuration Options + +When creating a CopilotClient, use `CopilotClientOptions`: + +- `cliPath` - Path to CLI executable (default: "copilot" from PATH) +- `cliArgs` - Extra arguments prepended before SDK-managed flags +- `cliUrl` - URL of existing CLI server (e.g., "localhost:8080"). When provided, client won't spawn a process +- `port` - Server port (default: 0 for random, only when `useStdio` is false) +- `useStdio` - Use stdio transport instead of TCP (default: true) +- `logLevel` - Log level: "error", "warn", "info", "debug", "trace" (default: "info") +- `autoStart` - Auto-start server on first request (default: true) +- `autoRestart` - Auto-restart on crash (default: true) +- `cwd` - Working directory for the CLI process +- `environment` - Environment variables for the CLI process +- `gitHubToken` - GitHub token for authentication +- `useLoggedInUser` - Use logged-in `gh` CLI auth (default: true unless token provided) +- `onListModels` - Custom model list handler for BYOK scenarios + +```java +var options = new CopilotClientOptions() + .setCliPath("/path/to/copilot") + .setLogLevel("debug") + .setAutoStart(true) + .setAutoRestart(true) + .setGitHubToken(System.getenv("GITHUB_TOKEN")); + +try (var client = new CopilotClient(options)) { + client.start().get(); + // Use client... +} +``` + +### Manual Server Control + +For explicit control: +```java +var client = new CopilotClient(new CopilotClientOptions().setAutoStart(false)); +client.start().get(); +// Use client... +client.stop().get(); +``` + +Use `forceStop()` when `stop()` takes too long. + +## Session Management + +### Creating Sessions + +Use `SessionConfig` for configuration. The permission handler is **required**: + +```java +var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setStreaming(true) + .setTools(List.of(...)) + .setSystemMessage(new SystemMessageConfig() + .setMode(SystemMessageMode.APPEND) + .setContent("Custom instructions")) + .setAvailableTools(List.of("tool1", "tool2")) + .setExcludedTools(List.of("tool3")) + .setProvider(new ProviderConfig().setType("openai")) + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); +``` + +### Session Config Options + +- `sessionId` - Custom session ID +- `clientName` - Application name +- `model` - Model name ("gpt-5", "claude-sonnet-4.5", etc.) +- `reasoningEffort` - "low", "medium", "high", "xhigh" +- `tools` - Custom tools exposed to the CLI +- `systemMessage` - System message customization +- `availableTools` - Allowlist of tool names +- `excludedTools` - Blocklist of tool names +- `provider` - Custom API provider configuration (BYOK) +- `streaming` - Enable streaming response chunks (default: false) +- `workingDirectory` - Session working directory +- `mcpServers` - MCP server configurations +- `customAgents` - Custom agent configurations +- `agent` - Pre-select agent by name +- `infiniteSessions` - Infinite sessions configuration +- `skillDirectories` - Skill SKILL.md directories +- `disabledSkills` - Skills to disable +- `configDir` - Config directory path +- `hooks` - Session lifecycle hooks +- `onPermissionRequest` - **REQUIRED** permission handler +- `onUserInputRequest` - User input handler +- `onEvent` - Event handler registered before session creation + +All setters return `SessionConfig` for method chaining. + +### Resuming Sessions + +```java +var session = client.resumeSession(sessionId, new ResumeSessionConfig() + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); +``` + +### Session Operations + +- `session.getSessionId()` - Get session identifier +- `session.send(prompt)` / `session.send(MessageOptions)` - Send message, returns message ID +- `session.sendAndWait(prompt)` / `session.sendAndWait(MessageOptions)` - Send and wait for response (60s timeout) +- `session.sendAndWait(options, timeoutMs)` - Send and wait with custom timeout +- `session.abort()` - Abort current processing +- `session.getMessages()` - Get all events/messages +- `session.setModel(modelId)` - Switch to a different model +- `session.log(message)` / `session.logWarning(message)` / `session.logError(message)` - Log to session timeline +- `session.close()` - Clean up resources + +## Event Handling + +### Event Subscription Pattern + +Use `CompletableFuture` for waiting on session events: + +```java +var done = new CompletableFuture(); + +session.on(event -> { + if (event instanceof AssistantMessageEvent msg) { + System.out.println(msg.getData().content()); + } else if (event instanceof SessionIdleEvent) { + done.complete(null); + } +}); + +session.send(new MessageOptions().setPrompt("Hello")); +done.get(); +``` + +### Type-Safe Event Handling + +Use the typed `on()` overload for compile-time safety: + +```java +session.on(AssistantMessageEvent.class, msg -> { + System.out.println(msg.getData().content()); +}); + +session.on(SessionIdleEvent.class, idle -> { + done.complete(null); +}); +``` + +### Unsubscribing from Events + +The `on()` method returns a `Closeable`: + +```java +var subscription = session.on(event -> { /* handler */ }); +// Later... +subscription.close(); +``` + +### Event Types + +Use pattern matching (Java 17+) for event handling: + +```java +session.on(event -> { + switch (event) { + case UserMessageEvent userMsg -> + // Handle user message + {} + case AssistantMessageEvent assistantMsg -> + System.out.println(assistantMsg.getData().content()); + case AssistantMessageDeltaEvent delta -> + System.out.print(delta.getData().deltaContent()); + case ToolExecutionStartEvent toolStart -> + // Tool execution started + {} + case ToolExecutionCompleteEvent toolComplete -> + // Tool execution completed + {} + case SessionStartEvent start -> + // Session started + {} + case SessionIdleEvent idle -> + // Session is idle (processing complete) + {} + case SessionErrorEvent error -> + System.err.println("Error: " + error.getData().message()); + default -> { } + } +}); +``` + +### Event Error Handling + +Control how errors in event handlers are handled: + +```java +// Set a custom error handler +session.setEventErrorHandler(ex -> { + logger.error("Event handler error", ex); +}); + +// Or set the error propagation policy +session.setEventErrorPolicy(EventErrorPolicy.SUPPRESS_AND_LOG_ERRORS); +``` + +## Streaming Responses + +### Enabling Streaming + +Set `streaming(true)` in SessionConfig: + +```java +var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setStreaming(true) + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); +``` + +### Handling Streaming Events + +Handle both delta events (incremental) and final events: + +```java +var done = new CompletableFuture(); + +session.on(event -> { + switch (event) { + case AssistantMessageDeltaEvent delta -> + // Incremental text chunk + System.out.print(delta.getData().deltaContent()); + case AssistantReasoningDeltaEvent reasoningDelta -> + // Incremental reasoning chunk (model-dependent) + System.out.print(reasoningDelta.getData().deltaContent()); + case AssistantMessageEvent msg -> + // Final complete message + System.out.println("\n--- Final ---\n" + msg.getData().content()); + case AssistantReasoningEvent reasoning -> + // Final reasoning content + System.out.println("--- Reasoning ---\n" + reasoning.getData().content()); + case SessionIdleEvent idle -> + done.complete(null); + default -> { } + } +}); + +session.send(new MessageOptions().setPrompt("Tell me a story")); +done.get(); +``` + +Note: Final events (`AssistantMessageEvent`, `AssistantReasoningEvent`) are ALWAYS sent regardless of streaming setting. + +## Custom Tools + +### Defining Tools + +Use `ToolDefinition.create()` with JSON Schema parameters and a `ToolHandler`: + +```java +var tool = ToolDefinition.create( + "get_weather", + "Get weather for a location", + Map.of( + "type", "object", + "properties", Map.of( + "location", Map.of("type", "string", "description", "City name") + ), + "required", List.of("location") + ), + invocation -> { + String location = (String) invocation.getArguments().get("location"); + return CompletableFuture.completedFuture("Sunny in " + location); + } +); + +var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setTools(List.of(tool)) + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); +``` + +### Type-Safe Tool Arguments + +Use `getArgumentsAs()` for deserialization into a typed record or class: + +```java +record WeatherArgs(String location, String unit) {} + +var tool = ToolDefinition.create( + "get_weather", + "Get weather for a location", + Map.of( + "type", "object", + "properties", Map.of( + "location", Map.of("type", "string"), + "unit", Map.of("type", "string", "enum", List.of("celsius", "fahrenheit")) + ), + "required", List.of("location") + ), + invocation -> { + var args = invocation.getArgumentsAs(WeatherArgs.class); + return CompletableFuture.completedFuture( + Map.of("temp", 72, "unit", args.unit(), "location", args.location()) + ); + } +); +``` + +### Overriding Built-In Tools + +```java +var override = ToolDefinition.createOverride( + "built_in_tool_name", + "Custom description", + Map.of("type", "object", "properties", Map.of(...)), + invocation -> CompletableFuture.completedFuture("custom result") +); +``` + +### Tool Return Types + +- Return any JSON-serializable value (String, Map, List, record, POJO) +- The SDK automatically serializes the return value and sends it back to the CLI + +### Tool Execution Flow + +When Copilot invokes a tool, the client automatically: +1. Deserializes the arguments +2. Runs your handler function +3. Serializes the return value +4. Responds to the CLI + +## Permission Handling + +### Required Permission Handler + +A permission handler is **mandatory** when creating or resuming sessions: + +```java +// Approve all requests (for development/testing) +new SessionConfig() + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) + +// Custom permission logic +new SessionConfig() + .setOnPermissionRequest((request, invocation) -> { + if ("dangerous-action".equals(request.getKind())) { + return CompletableFuture.completedFuture( + new PermissionRequestResult().setKind("user-denied") + ); + } + return CompletableFuture.completedFuture( + new PermissionRequestResult().setKind("user-approved") + ); + }) +``` + +## User Input Handling + +Handle user input requests from the agent: + +```java +new SessionConfig() + .setOnUserInputRequest((request, invocation) -> { + System.out.println("Agent asks: " + request.getQuestion()); + String answer = scanner.nextLine(); + return CompletableFuture.completedFuture( + new UserInputResponse() + .setAnswer(answer) + .setWasFreeform(true) + ); + }) +``` + +## System Message Customization + +### Append Mode (Default - Preserves Guardrails) + +```java +var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setSystemMessage(new SystemMessageConfig() + .setMode(SystemMessageMode.APPEND) + .setContent(""" + + - Always check for security vulnerabilities + - Suggest performance improvements when applicable + + """)) + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); +``` + +### Replace Mode (Full Control - Removes Guardrails) + +```java +var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setSystemMessage(new SystemMessageConfig() + .setMode(SystemMessageMode.REPLACE) + .setContent("You are a helpful assistant.")) + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); +``` + +## File Attachments + +Attach files to messages using `Attachment`: + +```java +session.send(new MessageOptions() + .setPrompt("Analyze this file") + .setAttachments(List.of( + new Attachment("file", "/path/to/file.java", "My File") + )) +); +``` + +## Message Delivery Modes + +Use the `mode` property in `MessageOptions`: + +- `"enqueue"` - Queue message for processing (default) +- `"immediate"` - Process message immediately + +```java +session.send(new MessageOptions() + .setPrompt("...") + .setMode("enqueue") +); +``` + +## Convenience: Send and Wait + +Use `sendAndWait()` to send a message and block until the assistant responds: + +```java +// With default 60-second timeout +AssistantMessageEvent response = session.sendAndWait("What is 2+2?").get(); +System.out.println(response.getData().content()); + +// With custom timeout +AssistantMessageEvent response = session.sendAndWait( + new MessageOptions().setPrompt("Write a long story"), + 120_000 // 120 seconds +).get(); +``` + +## Multiple Sessions + +Sessions are independent and can run concurrently: + +```java +var session1 = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); + +var session2 = client.createSession(new SessionConfig() + .setModel("claude-sonnet-4.5") + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); + +session1.send(new MessageOptions().setPrompt("Hello from session 1")); +session2.send(new MessageOptions().setPrompt("Hello from session 2")); +``` + +## Bring Your Own Key (BYOK) + +Use custom API providers via `ProviderConfig`: + +```java +// OpenAI +var session = client.createSession(new SessionConfig() + .setProvider(new ProviderConfig() + .setType("openai") + .setBaseUrl("https://api.openai.com/v1") + .setApiKey("sk-...")) + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); + +// Azure OpenAI +var session = client.createSession(new SessionConfig() + .setProvider(new ProviderConfig() + .setType("azure") + .setAzure(new AzureOptions() + .setEndpoint("https://my-resource.openai.azure.com") + .setDeployment("gpt-4")) + .setBearerToken("...")) + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) +).get(); +``` + +## Session Lifecycle Management + +### Listing Sessions + +```java +var sessions = client.listSessions().get(); +for (var metadata : sessions) { + System.out.println("Session: " + metadata.getSessionId()); +} +``` + +### Deleting Sessions + +```java +client.deleteSession(sessionId).get(); +``` + +### Checking Connection State + +```java +var state = client.getState(); +``` + +### Lifecycle Event Subscription + +```java +AutoCloseable subscription = client.onLifecycle(event -> { + System.out.println("Lifecycle event: " + event); +}); +// Later... +subscription.close(); +``` + +## Error Handling + +### Standard Exception Handling + +```java +try { + var session = client.createSession(new SessionConfig() + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) + ).get(); + session.sendAndWait("Hello").get(); +} catch (ExecutionException ex) { + Throwable cause = ex.getCause(); + System.err.println("Error: " + cause.getMessage()); +} catch (Exception ex) { + System.err.println("Error: " + ex.getMessage()); +} +``` + +### Session Error Events + +Monitor `SessionErrorEvent` for runtime errors: + +```java +session.on(SessionErrorEvent.class, error -> { + System.err.println("Session Error: " + error.getData().message()); +}); +``` + +## Connectivity Testing + +Use `ping()` to verify server connectivity: + +```java +var response = client.ping("test message").get(); +``` + +## Status and Authentication + +```java +// Get CLI version and protocol info +var status = client.getStatus().get(); + +// Check authentication status +var authStatus = client.getAuthStatus().get(); + +// List available models +var models = client.listModels().get(); +``` + +## Resource Cleanup + +### Automatic Cleanup with try-with-resources + +ALWAYS use try-with-resources for automatic disposal: + +```java +try (var client = new CopilotClient()) { + client.start().get(); + try (var session = client.createSession(new SessionConfig() + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get()) { + // Use session... + } +} +// Resources automatically cleaned up +``` + +### Manual Cleanup + +If not using try-with-resources: + +```java +var client = new CopilotClient(); +try { + client.start().get(); + // Use client... +} finally { + client.stop().get(); +} +``` + +## Best Practices + +1. **Always use try-with-resources** for `CopilotClient` and `CopilotSession` +2. **Always provide a permission handler** - it is required for `createSession` and `resumeSession` +3. **Use `CompletableFuture`** properly - call `.get()` to block, or chain with `.thenApply()`/`.thenCompose()` +4. **Use `sendAndWait()`** for simple request-response patterns instead of manual event handling +5. **Handle `SessionErrorEvent`** for robust error handling +6. **Use pattern matching** (switch with sealed types) for event handling +7. **Enable streaming** for better UX in interactive scenarios +8. **Close event subscriptions** (`Closeable`) when no longer needed +9. **Use `SystemMessageMode.APPEND`** to preserve safety guardrails +10. **Provide descriptive tool names and descriptions** for better model understanding +11. **Handle both delta and final events** when streaming is enabled +12. **Use `getArgumentsAs()`** for type-safe tool argument deserialization + +## Common Patterns + +### Simple Query-Response + +```java +try (var client = new CopilotClient()) { + client.start().get(); + + try (var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get()) { + + var response = session.sendAndWait("What is 2+2?").get(); + System.out.println(response.getData().content()); + } +} +``` + +### Event-Driven Conversation + +```java +try (var client = new CopilotClient()) { + client.start().get(); + + try (var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get()) { + + var done = new CompletableFuture(); + + session.on(AssistantMessageEvent.class, msg -> + System.out.println(msg.getData().content())); + + session.on(SessionIdleEvent.class, idle -> + done.complete(null)); + + session.send(new MessageOptions().setPrompt("What is 2+2?")); + done.get(); + } +} +``` + +### Multi-Turn Conversation + +```java +try (var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get()) { + + var response1 = session.sendAndWait("What is the capital of France?").get(); + System.out.println(response1.getData().content()); + + var response2 = session.sendAndWait("What is its population?").get(); + System.out.println(response2.getData().content()); +} +``` + +### Tool with Complex Return Type + +```java +record UserInfo(String id, String name, String email, String role) {} + +var tool = ToolDefinition.create( + "get_user", + "Retrieve user information", + Map.of( + "type", "object", + "properties", Map.of( + "userId", Map.of("type", "string", "description", "User ID") + ), + "required", List.of("userId") + ), + invocation -> { + String userId = (String) invocation.getArguments().get("userId"); + return CompletableFuture.completedFuture( + new UserInfo(userId, "John Doe", "john@example.com", "Developer") + ); + } +); +``` + +### Session Hooks + +```java +var session = client.createSession(new SessionConfig() + .setModel("gpt-5") + .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) + .setHooks(new SessionHooks() + .setOnPreToolUse(hook -> { + System.out.println("About to execute tool: " + hook); + return CompletableFuture.completedFuture(null); + }) + .setOnPostToolUse(hook -> { + System.out.println("Tool execution complete: " + hook); + return CompletableFuture.completedFuture(null); + })) +).get(); +``` From bafc419573f4c0cc49f9ed2ed753456da3af6313 Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Tue, 17 Mar 2026 09:11:07 -0700 Subject: [PATCH 2/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- instructions/copilot-sdk-java.instructions.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/instructions/copilot-sdk-java.instructions.md b/instructions/copilot-sdk-java.instructions.md index fe358b3b1..0ceaa2063 100644 --- a/instructions/copilot-sdk-java.instructions.md +++ b/instructions/copilot-sdk-java.instructions.md @@ -18,16 +18,16 @@ name: 'GitHub Copilot SDK Java Instructions' ```xml - com.github.copilot + com.github copilot-sdk-java - LATEST + ${copilot-sdk-java.version} ``` ### Gradle ```groovy -implementation 'com.github.copilot:copilot-sdk-java:LATEST' +implementation "com.github:copilot-sdk-java:${copilotSdkJavaVersion}" ``` ## Client Initialization From 8c58fc91d485285a1fbdb61b62ce175ae239698c Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Tue, 17 Mar 2026 09:11:23 -0700 Subject: [PATCH 3/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- instructions/copilot-sdk-java.instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instructions/copilot-sdk-java.instructions.md b/instructions/copilot-sdk-java.instructions.md index 0ceaa2063..a10fe7ea9 100644 --- a/instructions/copilot-sdk-java.instructions.md +++ b/instructions/copilot-sdk-java.instructions.md @@ -150,7 +150,7 @@ var session = client.resumeSession(sessionId, new ResumeSessionConfig() - `session.abort()` - Abort current processing - `session.getMessages()` - Get all events/messages - `session.setModel(modelId)` - Switch to a different model -- `session.log(message)` / `session.logWarning(message)` / `session.logError(message)` - Log to session timeline +- `session.log(message)` / `session.log(message, "warning", false)` / `session.log(message, "error", false)` - Log to session timeline with level `"info"`, `"warning"`, or `"error"` - `session.close()` - Clean up resources ## Event Handling From a5f998b45e973fcc6577ea2c2191541c8b680d05 Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Tue, 17 Mar 2026 09:12:17 -0700 Subject: [PATCH 4/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- instructions/copilot-sdk-java.instructions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instructions/copilot-sdk-java.instructions.md b/instructions/copilot-sdk-java.instructions.md index a10fe7ea9..682e64fcb 100644 --- a/instructions/copilot-sdk-java.instructions.md +++ b/instructions/copilot-sdk-java.instructions.md @@ -389,11 +389,11 @@ new SessionConfig() .setOnPermissionRequest((request, invocation) -> { if ("dangerous-action".equals(request.getKind())) { return CompletableFuture.completedFuture( - new PermissionRequestResult().setKind("user-denied") + new PermissionRequestResult().setKind(PermissionRequestResultKind.DENIED) ); } return CompletableFuture.completedFuture( - new PermissionRequestResult().setKind("user-approved") + new PermissionRequestResult().setKind(PermissionRequestResultKind.APPROVED) ); }) ``` From 166a2e15470db42c8fcb8af8d70379ccfe622062 Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Tue, 17 Mar 2026 09:12:38 -0700 Subject: [PATCH 5/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- instructions/copilot-sdk-java.instructions.md | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/instructions/copilot-sdk-java.instructions.md b/instructions/copilot-sdk-java.instructions.md index 682e64fcb..4e6f01e9d 100644 --- a/instructions/copilot-sdk-java.instructions.md +++ b/instructions/copilot-sdk-java.instructions.md @@ -204,29 +204,22 @@ Use pattern matching (Java 17+) for event handling: ```java session.on(event -> { - switch (event) { - case UserMessageEvent userMsg -> - // Handle user message - {} - case AssistantMessageEvent assistantMsg -> - System.out.println(assistantMsg.getData().content()); - case AssistantMessageDeltaEvent delta -> - System.out.print(delta.getData().deltaContent()); - case ToolExecutionStartEvent toolStart -> - // Tool execution started - {} - case ToolExecutionCompleteEvent toolComplete -> - // Tool execution completed - {} - case SessionStartEvent start -> - // Session started - {} - case SessionIdleEvent idle -> - // Session is idle (processing complete) - {} - case SessionErrorEvent error -> - System.err.println("Error: " + error.getData().message()); - default -> { } + if (event instanceof UserMessageEvent userMsg) { + // Handle user message + } else if (event instanceof AssistantMessageEvent assistantMsg) { + System.out.println(assistantMsg.getData().content()); + } else if (event instanceof AssistantMessageDeltaEvent delta) { + System.out.print(delta.getData().deltaContent()); + } else if (event instanceof ToolExecutionStartEvent toolStart) { + // Tool execution started + } else if (event instanceof ToolExecutionCompleteEvent toolComplete) { + // Tool execution completed + } else if (event instanceof SessionStartEvent start) { + // Session started + } else if (event instanceof SessionIdleEvent idle) { + // Session is idle (processing complete) + } else if (event instanceof SessionErrorEvent error) { + System.err.println("Error: " + error.getData().message()); } }); ``` From f4c5c26c62a19b4f2b00280db6365f117e23fffa Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Tue, 17 Mar 2026 09:12:52 -0700 Subject: [PATCH 6/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- instructions/copilot-sdk-java.instructions.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/instructions/copilot-sdk-java.instructions.md b/instructions/copilot-sdk-java.instructions.md index 4e6f01e9d..bf18a3c5a 100644 --- a/instructions/copilot-sdk-java.instructions.md +++ b/instructions/copilot-sdk-java.instructions.md @@ -743,12 +743,13 @@ var session = client.createSession(new SessionConfig() .setModel("gpt-5") .setOnPermissionRequest(PermissionHandler.APPROVE_ALL) .setHooks(new SessionHooks() - .setOnPreToolUse(hook -> { - System.out.println("About to execute tool: " + hook); - return CompletableFuture.completedFuture(null); + .setOnPreToolUse((input, invocation) -> { + System.out.println("About to execute tool: " + input); + var decision = new PreToolUseHookOutput().setKind("allow"); + return CompletableFuture.completedFuture(decision); }) - .setOnPostToolUse(hook -> { - System.out.println("Tool execution complete: " + hook); + .setOnPostToolUse((output, invocation) -> { + System.out.println("Tool execution complete: " + output); return CompletableFuture.completedFuture(null); })) ).get();