diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index bc28a29fb..7112a3f51 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -124,7 +124,7 @@ session.createSession(new SessionConfig() Sessions emit typed events via `session.on()`: ```java -session.on(AssistantMessageEvent.class, msg -> System.out.println(msg.getData().getContent())); +session.on(AssistantMessageEvent.class, msg -> System.out.println(msg.getData().content())); session.on(SessionIdleEvent.class, idle -> done.complete(null)); ``` diff --git a/.gitignore b/.gitignore index 5f035eaa5..f6b0681d3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ examples-test/ .merge-env blog-copilotsdk/ .claude/worktrees +smoke-test diff --git a/CHANGELOG.md b/CHANGELOG.md index 29e6b6281..1404ba336 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). > **Upstream sync:** [`github/copilot-sdk@062b61c`](https://github.com/github/copilot-sdk/commit/062b61c8aa63b9b5d45fa1d7b01723e6660ffa83) +### Notice + +- **This repository is now archived.** The official GitHub Copilot SDK for Java is maintained at [github/copilot-sdk-java](https://github.com/github/copilot-sdk-java). No further changes or releases will be made in this repository. + ## [1.0.11] - 2026-03-12 > **Upstream sync:** [`github/copilot-sdk@062b61c`](https://github.com/github/copilot-sdk/commit/062b61c8aa63b9b5d45fa1d7b01723e6660ffa83) diff --git a/README.md b/README.md index 4d31e5b33..d4b0a54ab 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Copilot SDK for Java +> 🚨 **This repository is archived.** The official GitHub Copilot SDK for Java is now maintained at **[github/copilot-sdk-java](https://github.com/github/copilot-sdk-java)**. No further changes or releases will be made here. Please use the official SDK going forward. + [![Build](https://github.com/copilot-community-sdk/copilot-sdk-java/actions/workflows/build-test.yml/badge.svg)](https://github.com/copilot-community-sdk/copilot-sdk-java/actions/workflows/build-test.yml) [![Site](https://github.com/copilot-community-sdk/copilot-sdk-java/actions/workflows/deploy-site.yml/badge.svg)](https://github.com/copilot-community-sdk/copilot-sdk-java/actions/workflows/deploy-site.yml) [![Coverage](.github/badges/jacoco.svg)](https://copilot-community-sdk.github.io/copilot-sdk-java/snapshot/jacoco/index.html) @@ -16,8 +18,6 @@ ## Background -> āš ļø **Disclaimer:** This is an **unofficial, community-driven SDK** and is **not supported or endorsed by GitHub**. This SDK may change in breaking ways. Use at your own risk. - Java SDK for programmatic control of GitHub Copilot CLI, enabling you to build AI-powered applications and agentic workflows. ## Installation @@ -63,16 +63,16 @@ public class CopilotSDK { // Handle assistant message events session.on(AssistantMessageEvent.class, msg -> { - System.out.println(msg.getData().getContent()); + System.out.println(msg.getData().content()); }); // Handle session usage info events session.on(SessionUsageInfoEvent.class, usage -> { var data = usage.getData(); System.out.println("\n--- Usage Metrics ---"); - System.out.println("Current tokens: " + (int) data.getCurrentTokens()); - System.out.println("Token limit: " + (int) data.getTokenLimit()); - System.out.println("Messages count: " + (int) data.getMessagesLength()); + System.out.println("Current tokens: " + (int) data.currentTokens()); + System.out.println("Token limit: " + (int) data.tokenLimit()); + System.out.println("Messages count: " + (int) data.messagesLength()); }); // Send a message diff --git a/pom.xml b/pom.xml index 51c08825f..cea1f9575 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ io.github.copilot-community-sdk copilot-sdk - 1.0.11 + 1.0.12-SNAPSHOT jar GitHub Copilot Community SDK :: Java @@ -33,7 +33,7 @@ scm:git:https://github.com/copilot-community-sdk/copilot-sdk-java.git scm:git:https://github.com/copilot-community-sdk/copilot-sdk-java.git https://github.com/copilot-community-sdk/copilot-sdk-java - v1.0.11 + HEAD @@ -108,6 +108,18 @@ maven-compiler-plugin 3.14.1 + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + + com.github.copilot.sdk.java + + + + org.apache.maven.plugins diff --git a/src/site/markdown/advanced.md b/src/site/markdown/advanced.md index 42b2c8964..926df5d72 100644 --- a/src/site/markdown/advanced.md +++ b/src/site/markdown/advanced.md @@ -1,6 +1,6 @@ # Advanced Usage -> āš ļø **Disclaimer:** This is an **unofficial, community-driven SDK** and is **not supported or endorsed by GitHub**. Use at your own risk. +> 🚨 **This repository is archived.** The official GitHub Copilot SDK for Java is now maintained at **[github/copilot-sdk-java](https://github.com/github/copilot-sdk-java)**. No further changes or releases will be made here. Please use the official SDK going forward. This guide covers advanced scenarios for extending and customizing your Copilot integration. @@ -339,8 +339,8 @@ session.on(SessionCompactionStartEvent.class, start -> { }); session.on(SessionCompactionCompleteEvent.class, complete -> { var data = complete.getData(); - System.out.println("Compaction completed - success: " + data.isSuccess() - + ", tokens removed: " + data.getTokensRemoved()); + System.out.println("Compaction completed - success: " + data.success() + + ", tokens removed: " + data.tokensRemoved()); }); ``` @@ -856,7 +856,7 @@ session.on(AssistantMessageEvent.class, msg -> { session.on(AssistantMessageEvent.class, msg -> { // This handler executes normally despite the exception above - System.out.println(msg.getData().getContent()); + System.out.println(msg.getData().content()); }); ``` diff --git a/src/site/markdown/cookbook/error-handling.md b/src/site/markdown/cookbook/error-handling.md index db1a173f5..1e44e702f 100644 --- a/src/site/markdown/cookbook/error-handling.md +++ b/src/site/markdown/cookbook/error-handling.md @@ -44,7 +44,7 @@ public class BasicErrorHandling { new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL).setModel("gpt-5")).get(); session.on(AssistantMessageEvent.class, msg -> { - System.out.println(msg.getData().getContent()); + System.out.println(msg.getData().content()); }); session.sendAndWait(new MessageOptions() @@ -110,7 +110,7 @@ public class TimeoutHandling { public static void sendWithTimeout(CopilotSession session) { try { session.on(AssistantMessageEvent.class, msg -> { - System.out.println(msg.getData().getContent()); + System.out.println(msg.getData().content()); }); // Wait up to 30 seconds for response @@ -209,7 +209,7 @@ public class TryWithResources { new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL).setModel("gpt-5")).get()) { session.on(AssistantMessageEvent.class, msg -> { - System.out.println(msg.getData().getContent()); + System.out.println(msg.getData().content()); }); session.sendAndWait(new MessageOptions() @@ -254,7 +254,7 @@ public class ToolErrorHandling { new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL).setTools(List.of(errorTool))).get(); session.on(AssistantMessageEvent.class, msg -> { - System.out.println(msg.getData().getContent()); + System.out.println(msg.getData().content()); }); // Session continues even when tool fails diff --git a/src/site/markdown/cookbook/managing-local-files.md b/src/site/markdown/cookbook/managing-local-files.md index 941cbdded..c978ccbad 100644 --- a/src/site/markdown/cookbook/managing-local-files.md +++ b/src/site/markdown/cookbook/managing-local-files.md @@ -54,15 +54,15 @@ public class ManagingLocalFiles { var done = new CountDownLatch(1); session.on(AssistantMessageEvent.class, msg -> - System.out.println("\nCopilot: " + msg.getData().getContent()) + System.out.println("\nCopilot: " + msg.getData().content()) ); session.on(ToolExecutionStartEvent.class, evt -> - System.out.println(" → Running: " + evt.getData().getToolName()) + System.out.println(" → Running: " + evt.getData().toolName()) ); session.on(ToolExecutionCompleteEvent.class, evt -> - System.out.println(" āœ“ Completed: " + evt.getData().getToolCallId()) + System.out.println(" āœ“ Completed: " + evt.getData().toolCallId()) ); session.on(SessionIdleEvent.class, evt -> done.countDown()); @@ -171,7 +171,7 @@ public class InteractiveFileOrganizer { new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL).setModel("gpt-5")).get(); session.on(AssistantMessageEvent.class, msg -> - System.out.println("\nCopilot: " + msg.getData().getContent()) + System.out.println("\nCopilot: " + msg.getData().content()) ); System.out.print("Enter folder path to organize: "); diff --git a/src/site/markdown/cookbook/multiple-sessions.md b/src/site/markdown/cookbook/multiple-sessions.md index ff7441255..b03c69c2c 100644 --- a/src/site/markdown/cookbook/multiple-sessions.md +++ b/src/site/markdown/cookbook/multiple-sessions.md @@ -50,11 +50,11 @@ public class MultipleSessions { // Set up event handlers for each session session1.on(AssistantMessageEvent.class, msg -> - System.out.println("Session 1: " + msg.getData().getContent())); + System.out.println("Session 1: " + msg.getData().content())); session2.on(AssistantMessageEvent.class, msg -> - System.out.println("Session 2: " + msg.getData().getContent())); + System.out.println("Session 2: " + msg.getData().content())); session3.on(AssistantMessageEvent.class, msg -> - System.out.println("Session 3: " + msg.getData().getContent())); + System.out.println("Session 3: " + msg.getData().content())); // Each session maintains its own conversation history session1.send(new MessageOptions() diff --git a/src/site/markdown/cookbook/persisting-sessions.md b/src/site/markdown/cookbook/persisting-sessions.md index a281c88f3..a3191005d 100644 --- a/src/site/markdown/cookbook/persisting-sessions.md +++ b/src/site/markdown/cookbook/persisting-sessions.md @@ -48,7 +48,7 @@ public class PersistingSessions { ).get(); session.on(AssistantMessageEvent.class, msg -> - System.out.println(msg.getData().getContent()) + System.out.println(msg.getData().content()) ); session.sendAndWait(new MessageOptions() @@ -76,7 +76,7 @@ public class ResumeSession { var session = client.resumeSession("user-123-conversation", new ResumeSessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get(); session.on(AssistantMessageEvent.class, msg -> - System.out.println(msg.getData().getContent()) + System.out.println(msg.getData().content()) ); // Previous context is restored @@ -141,7 +141,7 @@ public class SessionHistory { for (var event : messages) { // Print different event types appropriately if (event instanceof AssistantMessageEvent msg) { - System.out.printf("[assistant] %s%n", msg.getData().getContent()); + System.out.printf("[assistant] %s%n", msg.getData().content()); } else if (event instanceof UserMessageEvent userMsg) { System.out.printf("[user] %s%n", userMsg.getData().content()); } else { @@ -218,7 +218,7 @@ public class SessionManager { if (session != null) { session.on(AssistantMessageEvent.class, msg -> - System.out.println("\nCopilot: " + msg.getData().getContent()) + System.out.println("\nCopilot: " + msg.getData().content()) ); // Interactive conversation loop diff --git a/src/site/markdown/cookbook/pr-visualization.md b/src/site/markdown/cookbook/pr-visualization.md index dfe9db85f..6fabf5c35 100644 --- a/src/site/markdown/cookbook/pr-visualization.md +++ b/src/site/markdown/cookbook/pr-visualization.md @@ -101,11 +101,11 @@ public class PRVisualization { // Set up event handling session.on(AssistantMessageEvent.class, msg -> - System.out.println("\nšŸ¤– " + msg.getData().getContent() + "\n") + System.out.println("\nšŸ¤– " + msg.getData().content() + "\n") ); session.on(ToolExecutionStartEvent.class, evt -> - System.out.println(" āš™ļø " + evt.getData().getToolName()) + System.out.println(" āš™ļø " + evt.getData().toolName()) ); // Initial prompt - let Copilot figure out the details diff --git a/src/site/markdown/documentation.md b/src/site/markdown/documentation.md index 5e6913dbd..366b04627 100644 --- a/src/site/markdown/documentation.md +++ b/src/site/markdown/documentation.md @@ -1,6 +1,6 @@ # Copilot SDK for Java - Documentation -> āš ļø **Disclaimer:** This is an **unofficial, community-driven SDK** and is **not supported or endorsed by GitHub**. Use at your own risk. +> 🚨 **This repository is archived.** The official GitHub Copilot SDK for Java is now maintained at **[github/copilot-sdk-java](https://github.com/github/copilot-sdk-java)**. No further changes or releases will be made here. Please use the official SDK going forward. This guide covers common use cases for the Copilot SDK for Java. For complete API details, see the [Javadoc](apidocs/index.html). @@ -40,7 +40,7 @@ try (var client = new CopilotClient()) { ).get(); var response = session.sendAndWait("Explain Java records in one sentence").get(); - System.out.println(response.getData().getContent()); + System.out.println(response.getData().content()); session.close(); } @@ -58,7 +58,7 @@ For straightforward interactions, use `sendAndWait()`: ```java var response = session.sendAndWait("What is the capital of France?").get(); -System.out.println(response.getData().getContent()); +System.out.println(response.getData().content()); ``` ### Event-Based Processing @@ -103,7 +103,7 @@ var done = new CompletableFuture(); // Type-safe event handlers (recommended) session.on(AssistantMessageEvent.class, msg -> { - System.out.println("Response: " + msg.getData().getContent()); + System.out.println("Response: " + msg.getData().content()); }); session.on(SessionErrorEvent.class, err -> { @@ -124,7 +124,7 @@ You can also use a single handler for all events: session.on(event -> { switch (event) { case AssistantMessageEvent msg -> - System.out.println("Response: " + msg.getData().getContent()); + System.out.println("Response: " + msg.getData().content()); case SessionErrorEvent err -> System.err.println("Error: " + err.getData().message()); case SessionIdleEvent idle -> @@ -299,11 +299,11 @@ var history = session.getMessages().get(); for (var event : history) { switch (event) { case UserMessageEvent user -> - System.out.println("User: " + user.getData().getContent()); + System.out.println("User: " + user.getData().content()); case AssistantMessageEvent assistant -> - System.out.println("Assistant: " + assistant.getData().getContent()); + System.out.println("Assistant: " + assistant.getData().content()); case ToolExecutionCompleteEvent tool -> - System.out.println("Tool: " + tool.getData().getToolName()); + System.out.println("Tool: " + tool.getData().toolCallId()); default -> { } } } @@ -596,8 +596,8 @@ var session2 = client.createSession( var future1 = session1.sendAndWait("Summarize REST APIs"); var future2 = session2.sendAndWait("Summarize GraphQL"); -System.out.println("GPT: " + future1.get().getData().getContent()); -System.out.println("Claude: " + future2.get().getData().getContent()); +System.out.println("GPT: " + future1.get().getData().content()); +System.out.println("Claude: " + future2.get().getData().content()); ``` ### Resume a Previous Session diff --git a/src/site/markdown/getting-started.md b/src/site/markdown/getting-started.md index 49281a4fc..cbbad8d46 100644 --- a/src/site/markdown/getting-started.md +++ b/src/site/markdown/getting-started.md @@ -81,7 +81,7 @@ public class HelloCopilot { new MessageOptions().setPrompt("What is 2 + 2?") ).get(); - System.out.println(response.getData().getContent()); + System.out.println(response.getData().content()); } } } diff --git a/src/site/markdown/hooks.md b/src/site/markdown/hooks.md index 11df1d6e9..4dde96fdd 100644 --- a/src/site/markdown/hooks.md +++ b/src/site/markdown/hooks.md @@ -1,6 +1,6 @@ # Session Hooks -> āš ļø **Disclaimer:** This is an **unofficial, community-driven SDK** and is **not supported or endorsed by GitHub**. Use at your own risk. +> 🚨 **This repository is archived.** The official GitHub Copilot SDK for Java is now maintained at **[github/copilot-sdk-java](https://github.com/github/copilot-sdk-java)**. No further changes or releases will be made here. Please use the official SDK going forward. Session hooks allow you to intercept and modify tool execution, user prompts, and session lifecycle events. Use hooks to implement custom logic like logging, security controls, or context injection. @@ -339,7 +339,7 @@ public class HooksExample { ).get(); var response = session.sendAndWait("List files in /tmp").get(); - System.out.println(response.getData().getContent()); + System.out.println(response.getData().content()); session.close(); } diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index 27abc27c0..83a589824 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -1,6 +1,6 @@ # Copilot SDK for Java -> āš ļø **Disclaimer:** This is an **unofficial, community-driven SDK** and is **not supported or endorsed by GitHub**. Use at your own risk. +> 🚨 **This repository is archived.** The official GitHub Copilot SDK for Java is now maintained at **[github/copilot-sdk-java](https://github.com/github/copilot-sdk-java)**. No further changes or releases will be made here. Please use the official SDK going forward. Welcome to the documentation for the **Copilot SDK for Java** — a Java SDK for programmatic control of GitHub Copilot CLI, enabling you to build AI-powered applications and agentic workflows. @@ -52,7 +52,7 @@ public class Example { var done = new CompletableFuture(); session.on(AssistantMessageEvent.class, msg -> { - System.out.println(msg.getData().getContent()); + System.out.println(msg.getData().content()); }); session.on(SessionIdleEvent.class, idle -> done.complete(null)); @@ -96,7 +96,7 @@ class hello { var session = client.createSession(new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get(); var done = new CompletableFuture(); session.on(AssistantMessageEvent.class, msg -> { - System.out.print(msg.getData().getContent()); + System.out.print(msg.getData().content()); }); session.on(SessionIdleEvent.class, idle -> done.complete(null)); session.send(new MessageOptions().setPrompt("Say hello!")).get(); diff --git a/src/site/markdown/mcp.md b/src/site/markdown/mcp.md index 68df0db87..8f830da57 100644 --- a/src/site/markdown/mcp.md +++ b/src/site/markdown/mcp.md @@ -22,7 +22,7 @@ var session = client.createSession( ).get(); var result = session.sendAndWait("List files in the directory").get(); -System.out.println(result.getData().getContent()); +System.out.println(result.getData().content()); ``` > **Tip:** Browse the [MCP Servers Directory](https://github.com/modelcontextprotocol/servers) for community servers like GitHub, SQLite, and Puppeteer. diff --git a/src/test/prompts/PROMPT-smoke-test.md b/src/test/prompts/PROMPT-smoke-test.md new file mode 100644 index 000000000..4013002ac --- /dev/null +++ b/src/test/prompts/PROMPT-smoke-test.md @@ -0,0 +1,135 @@ +# Prompt: Generate and Run the copilot-sdk-java Smoke Test + +## Objective + +Create a Maven project that acts as a smoke test for `copilot-sdk-java`. The project must compile, build, and run to completion with exit code 0 as the definition of success. + +## Step 1 — Read the source README + +Read the file `README.md` at the top level of this repository. You will need two sections from it: + +- **"Snapshot Builds"** — provides the Maven GAV (groupId, artifactId, version) and the Maven Central Snapshots repository configuration to use for the dependency under test. +- **"Quick Start"** — provides the exact Java source code for the smoke test program. Use this code verbatim. Do not modify it, fix it, or improve it. If it does not compile or run correctly against the artifact under test, that is itself a smoke test failure and must be reported as such rather than silently corrected. + +## Step 2 — Create the Maven project + +Create the following file layout in a subdirectory named `smoke-test/` at the top level of this repository: + +``` +smoke-test/ + pom.xml + src/main/java/(Class name taken from the code in the "Quick Start" section in the README).java ← verbatim from README "Quick Start" +``` + +### `pom.xml` requirements + +- **groupId**: `com.github` (or any reasonable value) +- **artifactId**: `copilot-sdk-smoketest` +- **version**: `1.0-SNAPSHOT` +- **packaging**: `jar` +- **Java source/target**: (taken from the "Requirements" section in the README) (via `maven.compiler.source` and `maven.compiler.target` properties) +- **`mainClass` property**: (taken from the "Quick Start" section in the README) (the class is in the default package) + +#### Snapshot repository + +Configure the Maven Central Snapshots repository exactly as specified in the "Snapshot Builds" section of `README.md`, and add `always` inside the `` block so that every build fetches the latest snapshot without requiring `-U`: + +```xml + + central-snapshots + https://central.sonatype.com/repository/maven-snapshots/ + + true + always + + +``` + +#### Dependency + +Use the GAV from the "Snapshot Builds" section of `README.md` verbatim — do not substitute the release version from the "Maven" section. + +#### Plugins — REQUIRED configuration + +**Do not use `maven-shade-plugin`.** Use the `Class-Path` manifest approach instead: + +1. **`maven-jar-plugin`** (version **3.4.1** — pin explicitly to suppress Maven version warnings): + + ```xml + + org.apache.maven.plugins + maven-jar-plugin + 3.4.1 + + + + ${mainClass} + true + lib/ + false + + + + + ``` + + **Critical**: `false` is mandatory. Without it, the manifest `Class-Path:` entry uses the timestamped SNAPSHOT filename (e.g. `copilot-sdk-java-0.1.33-20260312.125508-3.jar`) while `copy-dependencies` writes the base SNAPSHOT filename (`copilot-sdk-java-0.1.33-SNAPSHOT.jar`), causing `NoClassDefFoundError` at runtime. + +2. **`maven-dependency-plugin`** (version **3.6.1**): + + ```xml + + org.apache.maven.plugins + maven-dependency-plugin + 3.6.1 + + + copy-dependencies + package + copy-dependencies + + ${project.build.directory}/lib + + + + + ``` + + This copies all runtime dependency JARs into `target/lib/`, which is where the manifest `Class-Path:` points. + +## Step 3 — Build + +```bash +mvn -U clean package +``` + +The `-U` flag forces a fresh snapshot metadata check regardless of local cache. The `always` already handles this for normal invocations, but `-U` is the safest choice for CI. + +Build must succeed with `BUILD SUCCESS` before proceeding. + +## Step 4 — Run + +```bash +java -jar ./target/copilot-sdk-smoketest-1.0-SNAPSHOT.jar +``` + +The JAR must be run from the `smoke-test/` directory so that the relative `lib/` path in the manifest resolves correctly. Do not use `-cp` or `-classpath` — the test specifically validates that `java -jar` works with the manifest `Class-Path:` approach. + +## Step 5 — Verify success + +The smoke test passes if and only if the process exits with code **0**. + +The "Quick Start" code in `README.md` already contains the exit-code logic: it captures the last assistant message and calls `System.exit(0)` if it contains `"4"` (the expected answer to "What is 2+2?"), or `System.exit(-1)` otherwise. + +Check the exit code: +```bash +echo "Exit code: $?" +``` + +Expected: `Exit code: 0` + +## Important API notes (do not apply these as fixes — they are here for diagnostic context only) + +If the build fails with compilation errors such as `cannot find symbol` on methods like `getContent()`, `getCurrentTokens()`, `getTokenLimit()`, or `getMessagesLength()`, this indicates a mismatch between the Quick Start code and the SDK implementation. **Do not silently fix the code.** Report the failure. The purpose of this smoke test is precisely to catch such regressions. + +For reference: the data classes in `copilot-sdk-java` are Java **records**. Record accessor methods have no `get` prefix — they are named `content()`, `currentTokens()`, `tokenLimit()`, and `messagesLength()`. If the README Quick Start uses `getContent()` etc., that is a bug in the README that must be surfaced, not silently corrected.