[java] Add linux-x64 implementation of in process Copilot CLI - #2295
[java] Add linux-x64 implementation of in process Copilot CLI#2295edburns wants to merge 1042 commits into
Conversation
* Update @github/copilot to 1.0.71-0 - Updated nodejs and test harness dependencies - Re-ran code generators - Formatted generated code * Fix Java billing coverage test Exercise the new promotion field when constructing ModelBilling. Generated by Copilot Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 93b921d6-55b4-4fdc-9583-17a69ad39d54 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Stephen Toub <stoub@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Tool search configuration support * Fix ResumeSessionConfig * Fix spotless check * Fix Copilot comments * Fetch available tools for tool search * Addressing CI and alerts * Addressing review comments * Fix formatting * Fix spotless check
PR #1952 updated sample code from gpt-4.1 to gpt-5.4 but left behind references in source code docstrings/comments across all SDKs. This updates the remaining occurrences in SetModel/setModel/set_model API documentation. Co-authored-by: j-zhangyiyuan <j-zhangyiyuan@microsoft.com>
Apply the docs style guide (.github/instructions/docs-style.instructions.md): - Replace 'etc.' with 'and more' (4 occurrences across 3 files) - Replace 'e.g.' with 'For example' (1 occurrence in code comment) - Remove trailing whitespace (3 occurrences across 3 files) Only safe files with no open PR conflicts were modified. Co-authored-by: j-zhangyiyuan <j-zhangyiyuan@microsoft.com>
* Update @github/copilot to 1.0.71-2 - Updated nodejs and test harness dependencies - Re-ran code generators - Formatted generated code * Address generated SDK review feedback Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 217cbb68-9e90-4cf7-a02a-45e93f6938dd --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Stephen Toub <stoub@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The HMAC key auth method (CAPI_HMAC_KEY / COPILOT_HMAC_KEY) should not be documented publicly; it was re-added by doc automation. Removes it from the authentication priority list in authenticate.md and the summary in README.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add opaque metadata passthrough to SDK tool definitions
Add an optional, opaque `metadata` bag to tool definitions across all SDK
languages and forward it verbatim over the session.create/resume RPC. This
lets hosts attach namespaced metadata to tools without expanding the typed
public contract; the runtime may recognize specific keys to inform
host-specific behavior. Unknown keys are round-tripped untouched.
Languages: nodejs (Tool.metadata + defineTool), python (Tool.metadata +
define_tool), go (Tool.Metadata), rust (Tool.metadata + with_metadata),
java (ToolDefinition.metadata + createWithMetadata), dotnet
(CopilotToolOptions.Metadata + wire ToolDefinition.Metadata). Tests added
per language for wire/serialization forwarding and omission when unset.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback on tool metadata passthrough
- dotnet: change Metadata value type to IDictionary<string, JsonNode?> for
NativeAOT-safe serialization (CopilotToolOptions + wire ToolDefinition,
FromAIFunction cast, unit test); drop redundant [JsonPropertyName("metadata")]
since the Web camelCase policy already maps it; remove the <remarks> block
from the Metadata property.
- Reword metadata doc comments across nodejs/python/go/rust/java to describe
the bag opaquely without the SDK-vs-runtime/CLI distinction.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bf2bf0dd-ec9f-42f5-a6e1-4f2a9e562d5f
* Java: enable tool metadata for @copilotTool + compat constructor
Address Java SME feedback so annotation-based tools reach parity with the
programmatic API and existing constructor call sites keep compiling.
- ToolDefinition: add a backward-compatible 7-arg constructor delegating to
the canonical 8-arg with metadata=null.
- CopilotTool: add metadata() plus nested MetadataEntry/MetadataValue/
MetadataFlag annotations (@target({})) with a shallow bool|str|flag-map
representation, documenting the programmatic API for richer values.
- CopilotToolProcessor: generate the metadata constructor argument
(Map.<String, Object>of(...) with an explicit type witness) instead of a
hardcoded null; null when no metadata is present.
- Tests: processor generation cases (nested flags, absent, combined flags),
ToolDefinition 7-arg/.metadata(...) copy/flag-chaining cases, and a
fromObject metadata assertion; extend the SimpleTools fixture pair to emit
a safeForTelemetry metadata map.
- ADR-005: update the generated snippet to the 8-arg shape and document the
@copilotTool(metadata = ...) syntax and emitted shape.
Note: mvn verify / spotless:apply not run locally (no JDK/Maven in the dev
environment); relies on PR CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bf2bf0dd-ec9f-42f5-a6e1-4f2a9e562d5f
* Apply spotless formatting to Java metadata changes
Reflow javadoc and wrap annotation/constructor args per the Eclipse
formatter (mvn spotless:apply). No behavioral change.
Verified locally: mvn spotless:check clean; ToolDefinitionTest (8),
ToolDefinitionFromObjectTest (31), CopilotToolProcessorTest (37) all pass on
JDK 26.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bf2bf0dd-ec9f-42f5-a6e1-4f2a9e562d5f
* test: assert null metadata arg in generated tool definition
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ab2c14cd-d2e1-4524-a6dc-e9c10899343c
* docs: describe the metadata-less ToolDefinition overload by its steady state
Reword the 7-arg constructor's Javadoc to describe what the overload is (a
convenience constructor equivalent to the canonical one with metadata=null)
rather than its relationship to a specific change ("backward-compatible",
"retained so ... keep compiling after metadata was added"), which is only
meaningful in the context of the PR that introduced it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bf2bf0dd-ec9f-42f5-a6e1-4f2a9e562d5f
* rust: use IndexMap for tool metadata to serialize deterministically
HashMap serializes keys in a randomized order, unlike the sibling `parameters`
field (IndexMap) and the other SDKs (nodejs/python insertion order, Go sorted).
Switch the tool `metadata` bag to IndexMap<String, Value> so key order is
deterministic and consistent, avoiding non-reproducible wire output. No new
dependency; indexmap is already used by this struct.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bf2bf0dd-ec9f-42f5-a6e1-4f2a9e562d5f
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Ed Burns <edburns@microsoft.com>
* Instrument Node in-process test stalls Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Trace runtime and proxy during Node stalls Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Create focused Windows in-process stress run Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Measure Windows test resource pressure Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Preserve runtime diagnostics on failure Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Trace Windows session database locks Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Avoid perturbing runtime lock timing Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Avoid Windows in-process teardown deadlock Do not retry removal of the in-process runtime's session home while its Vitest worker still owns a locked session database. Retrying until the hook timeout prevents the worker from exiting and releasing the lock. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 * Clarify Windows teardown deadlock Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e902b9a-5527-4a32-a5a3-e0bf5bfef3f7 --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Update @github/copilot to 1.0.71
- Updated nodejs and test harness dependencies
- Re-ran code generators
- Formatted generated code
* Route Python hooks.invoke through generated client-global handler
CLI 1.0.71 promoted hooks.invoke to a client-global RPC method with a
generated HooksHandler interface. The handwritten SDK still registered its
own hooks.invoke handler, which only avoided colliding with the generated
one because global handlers were skipped when no LLM/telemetry adapter was
set.
Make the wiring intentional: add _HooksAdapter implementing the generated
HooksHandler protocol (routing HookInvokeRequest.sessionId to the matching
session's dispatcher), always register the client-global handlers with the
hooks adapter, and remove the redundant handwritten hooks.invoke
registrations and dead client-level handler.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ae226b7f-caf9-46f3-b8c5-b9a21c5d7951
* Route Node hooks.invoke through generated client-global handler
CLI 1.0.71 promoted hooks.invoke to a client-global RPC method with a
generated HooksHandler interface. The handwritten SDK registered its own
hooks.invoke handler on the connection, which the generated
registerClientGlobalApiHandlers then shadowed with an unwired handler that
threw "No hooks client-global handler registered" — so hooks never fired.
Wire the existing handleHooksInvoke routing into the generated
clientGlobalHandlers.hooks slot and drop the redundant handwritten
connection.onRequest("hooks.invoke") registration. Behavior is unchanged;
the dispatcher and its payload validation are reused as-is.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ae226b7f-caf9-46f3-b8c5-b9a21c5d7951
* Route Go hooks.invoke through generated client-global handler
CLI 1.0.71 promoted hooks.invoke to a client-global RPC method whose
generated registration installs a hooks.invoke handler that rejects all
invocations unless the Hooks slot is populated. Whenever an LLM inference
or telemetry adapter was configured, that generated handler overrode the
handwritten hooks.invoke registration and hooks stopped firing (e.g. the
sub-agent hook test).
Always register the client-global handlers with a hooksAdapter that
delegates to the existing per-session dispatcher, and drop the redundant
handwritten hooks.invoke registration.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ae226b7f-caf9-46f3-b8c5-b9a21c5d7951
* Fix Rust hook input deserialization for float timestamps
The Copilot CLI serializes hook input `timestamp` as a JSON float
(e.g. `1784203878038.0`). Rust's hand-authored hook input structs typed
`timestamp` as `i64`, so `serde_json::from_value` rejected the float,
`dispatch_hook` returned an error, and the session handler fell back to
an empty `{ "output": {} }` response. Hooks therefore never fired: e.g. a
preToolUse deny was dropped, the CLI executed the tool, and the replayed
conversation diverged ("No cached response" -> 500).
Other SDKs tolerate this incidentally (Go decodes `input` into `any` and
re-marshals, dropping the `.0`); Rust decodes strictly. Type the hook
input `timestamp` fields as `f64` to match the shape the runtime sends.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ae226b7f-caf9-46f3-b8c5-b9a21c5d7951
* Fix .NET build break and float hook timestamps for hooks.invoke
CLI 1.0.71 promoted hooks.invoke to an internal client-global RPC method.
The C# codegen still emitted its internal request/result DTOs behind a public
IHooksHandler surface, producing CS0050/CS0051 inconsistent-accessibility
errors that broke the entire .NET build. It also registered a second, unwired
hooks.invoke handler that would shadow the working handwritten one.
Filter internal client-global and client-session methods in the C# code
generator so no generated interface, handler property, or RPC registration is
emitted for internal methods like hooks.invoke. The handwritten
SetLocalRpcMethod(hooks.invoke, ...) registration continues to serve hooks.
This mirrors, for .NET's static typing, the routing fixes already applied to
Node, Python, and Go.
Also tolerate hook timestamp epoch milliseconds encoded as either JSON
integers or floats in UnixMillisecondsDateTimeOffsetConverter, covering the
CLI 1.0.71 float serialization (matching the Rust fix).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 94a20428-6b0e-4733-a354-0abf2d186320
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Steve Sanderson <SteveSandersonMS@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Enable issue intents on issue-triage workflow
Recompile issue-triage.lock.yml with gh-aw v0.82.1 to wire
GH_AW_RUNTIME_FEATURES=${{ vars.GH_AW_RUNTIME_FEATURES }}, enabling native
issue intents (rationale/confidence) for the workflow's add-labels safe
output. No behavior change: the trigger, permissions, prompt, and safe
outputs are unchanged, and the source .md is untouched.
The actions-lock.json pin bump (github/gh-aw-actions/setup v0.82.1) is
required by the recompiled lock.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Bump verify-compiled gh-aw pin to v0.82.1 and recompile locks
The verify-compiled workflow pinned gh-aw v0.77.5 while issue-triage.lock.yml
was compiled with v0.82.1, so CI recompiled at v0.77.5 and the byte diff failed
the check. Bump the pin to v0.82.1 to match, and recompile all lock files at
v0.82.1 so they are consistent with the pinned compiler.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* chore(aw): upgrade aw workflows with latest pre-release
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(ci): align verify workflow gh-aw toolchain
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add generated agentics-maintenance workflow (gh-aw v0.82.10)
`gh aw compile` with the v0.82.10 toolchain introduced by this PR emits
`.github/workflows/agentics-maintenance.yml`. Commit the generated file
so it is tracked alongside the recompiled locks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 004ba78d-3cf4-41ab-8647-180e683460f0
* Enable org billing (copilot-requests) for agentic workflows
Add `permissions.copilot-requests: write` to all 11 agentic (gh-aw)
workflows so their Copilot usage is billed to the org, and recompile the
lock files. The compiled workflows now authenticate the Copilot CLI with
the GitHub Actions token and set S2STOKENS=true.
Authored by adding `features.copilot-requests: true`, migrating it with
`gh aw fix --write` (the deprecated flag maps to the permission), and
recompiling with gh-aw v0.82.10.
Rebased onto #1880 (issue-intents), which bumps the pinned gh-aw CLI to
v0.82.10.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 004ba78d-3cf4-41ab-8647-180e683460f0
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Steve Sanderson <SteveSandersonMS@users.noreply.github.com>
When a model calls a nonexistent tool, the runtime replies with
"Available tools that can be called are <list>." The E2E replay proxy
embedded that literal enumeration in ~54 snapshots, so any change to the
built-in tool set (e.g. the new write_agent tool) broke snapshot matching
and caused the copilot-agent-runtime C# SDK canary to retry forever until
the 45m timeout.
Collapse the entire enumeration to a stable ${available_tools} placeholder
on both the live-request side (normalizeAvailableToolNames) and the stored
snapshot side (new normalizeStoredToolMessages applied at load time), so
snapshots keep matching as the built-in tool set evolves across runtime
versions and platforms.
Copilot-Session: fa431f41-c7dc-4580-9cba-274170ee64df
Co-authored-by: TestUser <test@example.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add custom agent reasoning effort Expose an optional per-agent reasoning effort across every SDK binding while preserving omission semantics and the reasoningEffort wire name. Add focused serialization, cloning, builder, and DTO coverage plus custom-agent documentation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 32727fc4-2ac8-41eb-a68a-e74674ecf155 * Clarify custom agent effort inheritance Document that omitted per-agent reasoning effort inherits an explicit parent session effort, while omission at both levels leaves the backend to choose. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 32727fc4-2ac8-41eb-a68a-e74674ecf155 * Clarify custom agent effort API docs Align every binding's CustomAgentConfig description with runtime inheritance semantics for omitted reasoning effort. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 32727fc4-2ac8-41eb-a68a-e74674ecf155 * Test custom agent effort through client Capture session.create requests through the public .NET client path instead of reflecting into private serializer options. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 32727fc4-2ac8-41eb-a68a-e74674ecf155 * Clarify custom agent effort omission Document that omitted per-agent reasoning effort sends no override and lets the backend choose its default rather than inheriting the parent session effort. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 32727fc4-2ac8-41eb-a68a-e74674ecf155
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bumps the java-codegen-deps group with 1 update in the /java/scripts/codegen directory: [tsx](https://github.com/privatenumber/tsx). Updates `tsx` from 4.22.4 to 4.23.1 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](privatenumber/tsx@v4.22.4...v4.23.1) --- updated-dependencies: - dependency-name: tsx dependency-version: 4.23.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: java-codegen-deps ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Update SDK E2E tests for canonical exit_plan_mode action order The runtime now canonicalizes the exit_plan_mode action menu to [autopilot, interactive, exit_only] regardless of the order the model passes in the tool call. Update the mode_handlers E2E assertions in all five SDK suites (C#, Go, Node, Python, Rust) to expect the canonical order so the shared snapshot test passes against the current runtime. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e36340e-3d37-46ed-ac6f-3989fea57dc7 * Update mode_handlers snapshot to canonical exit_plan_mode action order The E2E tests were updated to expect the canonical action order [autopilot, interactive, exit_only], but the replay snapshot still supplied [interactive, autopilot, exit_only] as the model's exit_plan_mode tool-call arguments, which the CLI forwards verbatim to the SDK handler. Align the snapshot with the tests so request.actions matches across all language SDKs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 446b10a1-29f6-4155-bf3a-ac1241c742f3 --------- Co-authored-by: TestUser <test@example.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add .NET BYOK E2E coverage Reuse conceptual replay snapshots across Anthropic Messages, OpenAI Responses, and OpenAI Chat Completions, and add three Ubuntu in-process CI legs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Normalize Anthropic adjacent user turns Collapse runtime-specific blank-line expansion so conceptual replay snapshots match recovery turns consistently. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Document potential BYOK E2E gaps Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Restore workflow path quoting Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Preserve the .NET test matrix Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Clarify replay harness test leg Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Use existing replay harness test coverage Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Simplify BYOK replay harness Make non-CAPI replay explicitly read-only so provider response parsing and SSE aggregation are unnecessary. Keep protocol-complete forward rendering, clarify backend trait naming, and rename the .NET proxy wrapper to reflect its protocol-neutral role. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Unify replay protocol paths Select a protocol descriptor once per backend so CAPI and BYOK share routing, canonical matching, errors, JSON/SSE responses, and exchange inspection. Replay compaction directly from canonical snapshots instead of synthesizing provider-specific responses. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c * Fix Responses replay stream lifecycle Keep initial Responses events in progress and empty until their matching delta and done events, and use the isolated E2E context when injecting a BYOK provider. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 85a40918-bd95-440b-b6e9-97c757a71f8c
* Harden MCP OAuth cancel E2E tests against create/interest race The MCP OAuth "cancel" E2E tests sampled the host auth callback the instant the server reached `needs-auth`, which is racy: `session.create` kicks off the MCP connection, but the SDK only registers its `mcp.oauth_required` event interest after create returns. When the server's initial 401 wins that race, the runtime records `needs-auth` without invoking the host callback, so the callback observation was intermittently empty (e.g. the flaky C# CI leg in copilot-agent-runtime). Wait for the callback to be invoked (bounded, reusing each suite's existing wait-for-condition helper) instead of sampling it immediately. A later runtime auth retry fires the callback with the same `initial` reason, so the assertions stay valid. Applied uniformly to C#, Go, Python, Java, and Rust; the Go change also guards the observed request with a mutex to fix a latent data race. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7849882-a2a2-4587-a602-da7718889a8c * Use TaskCompletionSource for thread-safe callback wait in C# cancel test Addresses review feedback: the previous poll read observedRequest (written by the callback thread) from the test continuation without synchronization. Switch to the TaskCompletionSource pattern already used by the direct-RPC test in this file, so the callback result is handed off safely and awaited with a timeout. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7849882-a2a2-4587-a602-da7718889a8c --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Mirror Node SDK releases internally Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b6e76edd-7acc-4681-a884-56d16967c048 * Simplify release retry handling Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b6e76edd-7acc-4681-a884-56d16967c048 * Handle Azure feed conflict prefix Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b6e76edd-7acc-4681-a884-56d16967c048 * Fix Windows release helper parsing Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b6e76edd-7acc-4681-a884-56d16967c048 --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Strongly type expAssignments session config across all SDKs
Replace the opaque JSON typing of the internal `expAssignments`
session-config field with a strongly-typed `CopilotExpAssignmentResponse`
(plus `ExpConfigEntry`) in every SDK, mirroring the runtime contract.
Wire keys remain PascalCase (Features, Flights, Configs, Id, Parameters,
...), optional fields are omitted when null, and the field keeps its
internal/hidden posture in each language.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43d7a02b-08ff-4e7d-a8c0-afa6dfbe94b0
* Address review: normalize required exp-assignment fields
- Go: add MarshalJSON to CopilotExpAssignmentResponse/ExpConfigEntry so
nil Features/Flights/Configs/Parameters serialize as []/{} instead of
null, matching the Python/Rust/.NET reference behavior; add a test.
- Java: default AssignmentContext to "" so the required field is not
dropped by NON_NULL when unset.
- .NET: tighten ExpConfigEntry.Parameters value type from JsonNode? to
JsonValue? to constrain values to JSON scalars.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43d7a02b-08ff-4e7d-a8c0-afa6dfbe94b0
* Default ExpConfigEntry.Id to "" in Java
The Id field is required by the wire contract, but defaulting to null let
class-level NON_NULL drop the key for a zero-value entry. Default it to ""
so the required key is always emitted, matching the Go and .NET defaults.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43d7a02b-08ff-4e7d-a8c0-afa6dfbe94b0
* Fix stale "opaque JSON" comment in Python exp wiring
The expAssignments path now serializes a concrete CopilotExpAssignmentResponse,
so drop the outdated "opaque JSON" wording from the adjacent comments.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43d7a02b-08ff-4e7d-a8c0-afa6dfbe94b0
* Fix nightly rustfmt import grouping in types.rs tests
Move `use std::collections::HashMap;` into the std import block so
`cargo fmt --check` with the nightly group_imports config passes in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43d7a02b-08ff-4e7d-a8c0-afa6dfbe94b0
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update @github/copilot to 1.0.72 - Updated nodejs and test harness dependencies - Re-ran code generators - Formatted generated code * Fix Copilot 1.0.72 E2E compatibility Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b518a351-2110-47a8-98be-371b1e8e5608 * Fix abort recovery E2E tests Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b518a351-2110-47a8-98be-371b1e8e5608 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Mackinnon Buck <mackinnon.buck@gmail.com>
The WebSocket protocol (RFC 6455 §4.2.2) mandates SHA-1 for computing the Sec-WebSocket-Accept header. This is not used for security purposes. Added both @SuppressWarnings and lgtm suppression comments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c4e523e3-9d39-4598-90ec-54d959c44ce8
The java-sdk-inprocess CI job set COPILOT_SDK_DEFAULT_CONNECTION=inprocess as a step-level environment variable, which leaked into surefire unit tests. The Maven inprocess profile already configures this env var only in failsafe's <environmentVariables>, per the design: 'Leave Surefire on its standard transport; only Failsafe ITs use InProcess.' Removing the redundant step-level env var fixes all 195 surefire test errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c4e523e3-9d39-4598-90ec-54d959c44ce8
Use absolute paths for system commands (cat → /usr/bin/cat, cmd → COMSPEC env var) and resolve npx via PATH search in CapiProxy to avoid executing commands with relative paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c4e523e3-9d39-4598-90ec-54d959c44ce8
- JnaNativeBinding.trackedCallbacks: suppress with @SuppressWarnings; this is a GC-root pattern — values are intentionally never read, the map exists solely to prevent garbage collection of JNA callback function pointers while native code holds them. - ErrorHandlingTest: access errorEvents via LOG.info after session close (events may or may not be emitted depending on CLI version/scenario). - SessionEventsE2ETest: add assertTrue on usageEvents.size() to access the collected list (events are backend-dependent). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c4e523e3-9d39-4598-90ec-54d959c44ce8
- SessionEventsE2ETest: replace trivially-true size >= 0 assertion with conditional content access (getData() assertion when events present). - InProcessEnvGuard: suppress StringEquality warning on intentional identity comparison with ABSENT_SENTINEL (unique instance used as a null-alternative sentinel to distinguish absent vs empty env vars). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c4e523e3-9d39-4598-90ec-54d959c44ce8
The lgtm[java/reference-equality-on-strings] comment suppresses CodeQL for the ABSENT_SENTINEL identity check. Java's @SuppressWarnings is not honored by CodeQL's analysis engine. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c4e523e3-9d39-4598-90ec-54d959c44ce8
Use .equals() instead of == for the sentinel check. The sentinel value contains null bytes that cannot appear in real environment variables, making .equals() safe and eliminating the CodeQL string-identity alert. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c4e523e3-9d39-4598-90ec-54d959c44ce8
Author: Ed Burns <edburns@microsoft.com>
Date: Fri Aug 7 17:29:06 2026 +0000
Fix Java in-process test lifecycle and parity
Prevent the Java in-process test profile from corrupting Surefire control
streams or poisoning later tests through the runtime's process-global LLM
provider registration. Preserve explicit subprocess and TCP transport choices,
sanitize process-only options before constructing in-process clients, and run
request-handler tests over their required isolated stdio runtime.
Fix the remaining test-contract issues by making fake socket RPC handler
registration atomic with reader startup, honoring the configured CLI
entrypoint when runtime.node is in a prebuilds directory, and isolating the
streaming model-cache scenario. Remove in-process skip annotations from tests
that already exercise an explicit subprocess transport.
The complete `mvn clean verify -Pinprocess` run now finishes successfully
without hangs, transport timeouts, provider-ownership failures, or Surefire
stream corruption.
File-by-file manifest:
- `java/sdk/pom.xml`: use Surefire's TCP fork channel for unit and integration
tests so native runtime output cannot corrupt Maven's process-pipe protocol.
- `java/sdk/src/main/java/com/github/copilot/CopilotClient.java`: preserve
explicitly selected TCP options when the default connection environment
requests in-process transport.
- `java/sdk/src/main/java/com/github/copilot/JsonRpcClient.java`: add a socket
construction hook that registers handlers before the reader thread starts.
- `java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java`:
resolve the configured Copilot executable separately from runtime.node when
the native library uses the package's prebuilds layout.
- `java/sdk/src/main/java/com/github/copilot/rpc/CopilotClientOptions.java`:
allow `setCwd(null)` to clear a previously configured working directory.
- `java/sdk/src/test/java/com/github/copilot/ClientOptionsE2ETest.java`: run
explicit fake-stdio option forwarding tests under the in-process profile.
- `java/sdk/src/test/java/com/github/copilot/ConfigCloneTest.java`: cover
clearing a configured working directory.
- `java/sdk/src/test/java/com/github/copilot/CopilotClientTest.java`: remove
obsolete in-process skips from explicit subprocess and TCP lifecycle tests.
- `java/sdk/src/test/java/com/github/copilot/CopilotClientTransportTest.java`:
test explicit transport precedence, in-process option sanitization, and TCP
token selection under the profile default.
- `java/sdk/src/test/java/com/github/copilot/CopilotRequestTestSupport.java`:
explicitly select stdio for request-handler tests that register the
process-global LLM inference provider.
- `java/sdk/src/test/java/com/github/copilot/E2ETestContext.java`: honor
explicit transports, route request-handler clients to subprocess isolation,
and clear environment, cwd, and CLI arguments before in-process client
construction.
- `java/sdk/src/test/java/com/github/copilot/GitHubTelemetryTest.java`: register
fake runtime RPC handlers before socket message processing begins.
- `java/sdk/src/test/java/com/github/copilot/MetadataApiTest.java`: run explicit
stdio metadata tests instead of skipping them under the profile.
- `java/sdk/src/test/java/com/github/copilot/PerSessionAuthTest.java`: run the
explicit subprocess unauthenticated case under the profile.
- `java/sdk/src/test/java/com/github/copilot/RpcServerMiscE2ETest.java`: run the
explicit subprocess account lifecycle case under the profile.
- `java/sdk/src/test/java/com/github/copilot/StreamingFidelityTest.java`: give
the gpt-5.4 reasoning/streaming scenario an isolated proxy and runtime model
cache.
- `java/sdk/src/test/java/com/github/copilot/ffi/FfiRuntimeHostTest.java`: cover
failed connection-open cleanup followed by successful sequential startup.
- `java/sdk/src/test/java/com/github/copilot/ffi/NativeRuntimeLoaderTest.java`:
cover resolving a configured CLI beside a prebuilds runtime.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e03c4e94-97b0-41ad-9f4e-c01633dc0bf7
This comment has been minimized.
This comment has been minimized.
…Connection APIs as @CopilotExperimental - Move GPG signing release profile from sdk/pom.xml to parent pom.xml so all reactor modules (sdk + copilot-native) are signed on publish. - Move README.md from java/sdk/ to java/ top level and fix relative paths. - Add in-process mode (experimental) section to README documenting the copilot-sdk-java-runtime classifier dependency and RuntimeConnection usage. - Annotate RuntimeConnection, StdioRuntimeConnection, TcpRuntimeConnection, UriRuntimeConnection, and CopilotClientOptions.get/setConnection() with @CopilotExperimental. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 35ff58dd-bfec-40bc-981d-d3c82174511d
This comment has been minimized.
This comment has been minimized.
The README was moved from java/sdk/ to java/ but the test still resolved it relative to the sdk module directory. Update the path to ../README.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 35ff58dd-bfec-40bc-981d-d3c82174511d
This comment has been minimized.
This comment has been minimized.
NativeRuntimeLoader.resolveEntrypoint() handles COPILOT_CLI_PATH resolution internally, making the CopilotClientOptions parameter redundant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 35ff58dd-bfec-40bc-981d-d3c82174511d
Cross-SDK Consistency Review ✅This PR adds Java in-process FFI support ( Status across SDKs:
No consistency issues found. The Java API naming follows Java conventions (camelCase methods, PascalCase types) and is semantically parallel to all other SDK implementations. The The multi-module Maven restructure (
|
e27e834 to
d66ea1a
Compare
This PR is the roll up of the agentic work done in the subtasks of #2166 . At each step of those subtasks, the CI was clean and all reviews were applied as appropriate.
PR 2295 — Reviewer's guide: In-process FFI runtime for the Java SDK
TL;DR
This PR does for the Java SDK what #1901 did for .NET and #1915 did for Rust: it adds an in-process connection mode that loads the Copilot runtime (
runtime.nodecdylib) as a native library via JNA, eliminating the need for a separate CLI child process. Currently scoped to linux-x64 only; the entire in-process API surface is marked@CopilotExperimental.The PR also restructures the Java Maven project from a single module into a multi-module reactor to support publishing the native runtime binaries as separate classifier JARs alongside the existing SDK JAR.
What's in the native binary, where does it come from, and how is it loaded?
The binary:
runtime.nodeDespite the
.nodeextension (a napi-rs naming convention),runtime.nodeis an ordinary platform-specific shared library (.soon Linux). It is a Rustcdylibproduced by thesrc/runtimecrate ingithub/copilot-agent-runtime. It exposes two front doors:extern "C"lifecycle/transport entry points callable by any language via FFI without Node.js.The 5 C ABI entry points are:
copilot_runtime_host_startcopilot_runtime_host_shutdowncopilot_runtime_connection_openon_outboundcallback for runtime→SDK data delivery.copilot_runtime_connection_writecopilot_runtime_connection_closeAll JSON-RPC methods travel as data through this fixed 5-function transport; the export surface never changes as the method set grows.
Where it comes from (build-time)
The
copilot-nativeMaven module's build fetches the binary from npm duringgenerate-resources:fetch-native.mjsreads the pinned version and SHA-512 integrity hash for@github/copilot-linux-x64fromnodejs/package-lock.json.npm packto download the exact tarball, verifies it against the integrity hash.runtime.nodeand thecopilotCLI executable into a staging directory.maven-jar-pluginpackages them into a classifier JAR (copilot-sdk-java-runtime-<version>-linux-x64.jar) with the layoutnative/linux-x64/runtime.node.How it's loaded (runtime)
PlatformDetector(303 lines) determines the classifier usingos.name,os.arch, and on Linux, ELF PT_INTERP parsing to distinguish glibc vs musl — no subprocesses, no heuristics.NativeRuntimeLoader(466 lines) resolves the binary in this order:COPILOT_CLI_PATHenv var → checks forruntime.nodealongside the CLI.native/<classifier>/runtime.node→ extracts atomically to~/.copilot/runtime-cache/<version>/<classifier>/runtime.node.runtime.nodealongside the bundledcopilotexecutable.JnaNativeBinding(253 lines) loads the library by absolute path via JNA and maps each C ABI export. Enforces a one-library-per-process invariant (library handle isstatic, never unloaded). Duplicate loads from the same path are silently accepted; different paths are rejected.FfiRuntimeHost(349 lines) orchestrates the lifecycle: starts the host, opens a connection, bridges the bidirectional JSON-RPC transport. Theon_outboundcallback (invoked by native threads) feeds received data into aQueueInputStreamthat the SDK's existingJsonRpcClientreads from.Structural changes
Multi-module Maven reactor
The single-module
java/pom.xmlis now a parent POM (pompackaging) with two submodules:java/pom.xmlcopilot-sdk-java-parentmaven.deploy.skip=true). Holds thereleaseprofile (GPG signing) inherited by all submodules.java/sdk/copilot-sdk-javajava/src/→java/sdk/src/.java/copilot-native/copilot-sdk-java-runtimelinux-x64only, ~20-26 MB).Consumer dependency declaration
Consumer usage
New public API surface (all
@CopilotExperimental)RuntimeConnection(sealed class)forStdio(),forTcp(),forUri(String),forInProcess().StdioRuntimeConnectionTcpRuntimeConnectionUriRuntimeConnectionInProcessRuntimeConnectionCopilotClientOptions.setConnection()/getConnection()The
RuntimeConnectionAPI replaces the previous pattern of settingcliUrl,cliPath,useStdio,port, andtcpConnectionTokenindividually. When aRuntimeConnectionis set, it takes precedence; conflicting legacy options causeIllegalArgumentException.New internal packages
com.github.copilot.ffi(9 classes, ~1,752 lines)FfiRuntimeHostJnaNativeBindingNativeBindingNativeRuntimeLoaderruntime.node: env var → classpath → cache. Atomic extraction with file locking.PlatformDetectorQueueInputStreamFfiOutputStreamconnection_write.OutboundCallbackon_outbound.ReaderThreadFactoryTests for FFI (6 files, ~2,054 lines)
FfiRuntimeHostTestJnaNativeBindingTestNativeRuntimeLoaderTestPlatformDetectorTestQueueInputStreamTestInProcessTransportITCI/workflow changes
java-sdk-inprocessinjava-sdk-tests.yml: runsmvn clean verify -Pinprocesson ubuntu-latest (linux-x64). Usescontinue-on-error: truewhile experimental.java/target/→java/sdk/target/for surefire/failsafe reports and coverage data.-pl sdkto restrict to the SDK module (the native module requires JDK 25 build tools).java/sdk/module layout.✅ Note that the existing java publishing jobs will continue to work as currently written.
Key design decisions (from ADR-007)
JNA over Panama FFM: JNA supports the Java 17 baseline with zero consumer configuration. Panama FFM requires Java 22+ and
--enable-native-accessflags. Performance difference is irrelevant (JSON-RPC I/O dominates).Per-platform classifier JARs over monolithic JAR: A monolithic JAR with all 6 common platforms would be ~132 MB. Classifier JARs let consumers pull only their target platform (~20-26 MB each). An uber-JAR can be assembled via
maven-assembly-pluginif needed.Library-never-unloads pattern: The loaded native library is held in a
staticfield and never released. Native worker threads outlive any individualFfiRuntimeHostinstance; unloading would crash.One library per process: Enforced by a process-wide guard, consistent with Rust, .NET, Go, and Python SDK implementations.
Diff statistics
java/src/→java/sdk/src/)copilot-native/pom.xml(214 lines),fetch-native.mjs(114 lines)Recommended review order
java/docs/adr/adr-007-native-bundling-strategy.md— context, options considered, decision rationale.rpc/RuntimeConnection.java,rpc/InProcessRuntimeConnection.java, andrpc/CopilotClientOptions.java(thesetConnection/getConnectionmethods).NativeBinding.java→JnaNativeBinding.java→FfiRuntimeHost.java→NativeRuntimeLoader.java→PlatformDetector.java.copilot-native/pom.xmlandcopilot-native/scripts/fetch-native.mjs.java/pom.xml(parent) andjava/sdk/pom.xml(child)..github/workflows/java-sdk-tests.yml(new inprocess job, path updates).ffi/test package ande2e/InProcessTransportIT.java.Implementation details.
Implemented agentically using https://aka.ms/coreai/shepherd-task/slides .