Skip to content

Upstream sync: Port 39 new commits from copilot-sdk (2026-03-24)#20

Merged
edburns merged 16 commits intomainfrom
copilot/sync-upstream-39-new-commits
Mar 25, 2026
Merged

Upstream sync: Port 39 new commits from copilot-sdk (2026-03-24)#20
edburns merged 16 commits intomainfrom
copilot/sync-upstream-39-new-commits

Conversation

Copy link
Contributor

Copilot AI commented Mar 24, 2026

Ports 39 upstream commits (062b61c → 40887393) from the official Copilot SDK to the Java SDK.


Before the change?

  • Unknown session event types from newer CLI versions were silently dropped (returned null from parser)
  • No way to have a permission handler abstain from answering (multi-client scenarios)
  • No way to mark a tool as safe/skip-permission
  • System message customization was limited to full replace or append — no section-level control
  • setModel() had no reasoning effort parameter
  • No inline binary (blob) attachment support
  • No OpenTelemetry configuration support
  • autoRestart option was still active (upstream removed it)

After the change?

Forward compatibility

  • Unknown event types now return UnknownSessionEvent (preserves id/timestamp/parentId) instead of null, so handlers receive all events from newer CLI versions

Permission handling

  • PermissionRequestResultKind.NO_RESULT — handler abstains, leaving the request for another client; SDK skips the RPC response in both v2 and v3 protocol paths

Tool definitions

  • ToolDefinition.skipPermission field + createSkipPermission() factory — CLI bypasses permission prompt for the tool

System message fine-grained customization (SystemMessageMode.CUSTOMIZE)

  • SectionOverrideAction enum (replace, remove, append, prepend, transform)
  • SectionOverride class — per-section override with optional async transform callback
  • SystemPromptSections — well-known section identifier constants
  • SystemMessageConfig.setSections(Map<String, SectionOverride>) — section-level overrides
  • systemMessage.transform RPC handler registered automatically when transform callbacks are present
new SessionConfig()
    .setSystemMessage(new SystemMessageConfig()
        .setMode(SystemMessageMode.CUSTOMIZE)
        .setSections(Map.of(
            SystemPromptSections.TONE,
                new SectionOverride().setAction(SectionOverrideAction.REPLACE)
                                     .setContent("Be concise and formal."),
            SystemPromptSections.IDENTITY,
                new SectionOverride().setTransform(content ->
                    CompletableFuture.completedFuture(content + "\nAlways end with DONE."))
        )))

Model switching

  • CopilotSession.setModel(String model, String reasoningEffort) — new overload; existing setModel(String) delegates to it

Attachments — type-safe polymorphic hierarchy

  • MessageAttachment sealed interface — Java equivalent of the .NET SDK's UserMessageDataAttachmentsItem polymorphic base class, with Jackson @JsonTypeInfo/@JsonSubTypes annotations for polymorphic serialization
  • Attachment record now implements MessageAttachment (with getType() bridge method)
  • BlobAttachmentfinal class implementing MessageAttachment for inline base64-encoded binary (e.g. images)
  • MessageOptions.setAttachments(List<? extends MessageAttachment>) — accepts List<Attachment>, List<BlobAttachment>, or List<MessageAttachment> with full compile-time safety
  • SendMessageRequest uses List<MessageAttachment> internally
// Single-type list (type inferred)
new MessageOptions().setAttachments(List.of(
    new Attachment("file", "/path/to/file.java", "Source")));

// Mixed list (explicit type hint)
new MessageOptions().setAttachments(List.<MessageAttachment>of(
    new Attachment("file", "/path/to/file.java", "Source"),
    new BlobAttachment().setData(base64Data).setMimeType("image/png")));

Observability

  • TelemetryConfig class + CopilotClientOptions.setTelemetry(TelemetryConfig) — sets COPILOT_OTEL_* env vars on CLI process startup

Deprecations

  • CopilotClientOptions.autoRestart — marked @Deprecated, no-op

Bug fixes

  • Fixed compilation errors in NO_RESULT permission handling: PermissionRequestResultKind is a string-backed value class (not an enum), so replaced valueOf() with constructor call in CopilotSession and .name() with .getValue() in RpcHandlerDispatcher

Pull request checklist

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been reviewed and added / updated if needed (for bug fixes / features)
  • mvn spotless:apply has been run to format the code
  • mvn clean verify passes locally

Does this introduce a breaking change?

  • Yes
  • No

Attachment now implements the new MessageAttachment sealed interface and MessageOptions.setAttachments accepts List<? extends MessageAttachment>. All existing caller code compiles unchanged: List.of(new Attachment(...)) infers List<Attachment> which matches List<? extends MessageAttachment>. No casts required.



💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

Copilot AI linked an issue Mar 24, 2026 that may be closed by this pull request
…ission, blob, CUSTOMIZE mode, TelemetryConfig

Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/copilot-sdk-java/sessions/405da6c3-54b8-42e2-9577-e4959467224f
Copilot AI changed the title [WIP] Sync upstream with 39 new commits from official Copilot SDK Upstream sync: Port 39 new commits from copilot-sdk (2026-03-24) Mar 24, 2026
Copilot AI requested a review from edburns March 24, 2026 01:25
@edburns
Copy link
Collaborator

edburns commented Mar 24, 2026

@copilot I have added checkstyle.org to the allow list. Please re-run that aspect of the checks.

Copy link
Contributor Author

Copilot AI commented Mar 24, 2026

@copilot I have added checkstyle.org to the allow list. Please re-run that aspect of the checks.

Checkstyle passes with 0 violations — mvn checkstyle:check exits successfully.

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
edburns and others added 3 commits March 23, 2026 23:14
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@edburns
Copy link
Collaborator

edburns commented Mar 24, 2026

@copilot investigate and push additional commits to fix this failure in the "Build & Test" workflow: https://github.com/github/copilot-sdk-java/actions/runs/23471384285/job/68294676620?pr=20

Copy link
Contributor Author

Copilot AI commented Mar 24, 2026

@copilot investigate and push additional commits to fix this failure in the "Build & Test" workflow: https://github.com/github/copilot-sdk-java/actions/runs/23471384285/job/68294676620...

Fixed in a912420. The two compilation errors were caused by treating PermissionRequestResultKind as an enum when it's actually a class with string constants:

  • CopilotSession.java:713 — replaced PermissionRequestResultKind.valueOf(...) with new PermissionRequestResultKind(...)
  • RpcHandlerDispatcher.java:196 — replaced NO_RESULT.name() with NO_RESULT.getValue()

Build passes: 448 tests, 0 failures.

@edburns
Copy link
Collaborator

edburns commented Mar 24, 2026

Prompt

The current state of this branch copilot-pr-20 tracks this PR #20. Use the gh cli if you need to interact with the PR.

I am a human reviewer reviewing this PR.

I have a worktree branch checked out at

D:/workareas/copilot-sdk-java-00-main cbf43621f [main]

Compare this branch with the main branch and help me understand the changes.

Rank them from most controversial or risky to least.

Response

Author: copilot-swe-agent | +1448 / -37 across 27 files | Self-declares a breaking change


1. BREAKING: MessageOptions.setAttachments(List<?>) type erasure — HIGH RISK

MessageOptions.java changes the field from List<Attachment> to List<Object>, and the setter from List<Attachment> to List<?>. SendMessageRequest.java mirrors this with List<Object>.

Concerns:

  • Type safety is gone. Callers can now pass any object in the list, with no compile-time check. A typo or wrong type won't fail until Jackson serialization—or worse, silently produce bad JSON.
  • The upstream .NET SDK likely uses a polymorphic union type or interface. The Java port should consider introducing a marker interface (e.g., MessageAttachment) that both Attachment and BlobAttachment implement, keeping compile-time safety while supporting both types. List<?> / List<Object> is a crude workaround.
  • The PR body admits this is a breaking change for callers storing getAttachments() as List<Attachment>.

2. SessionRequestBuilder.extractTransformCallbacks returns Object[] — MEDIUM-HIGH RISK

SessionRequestBuilder.java returns Object[] with positional semantics ([0] = wire config, [1] = callbacks). Callers in CopilotClient.java must cast with @SuppressWarnings("unchecked").

Concerns:

  • Fragile and error-prone. A simple record record ExtractedTransforms(SystemMessageConfig wireConfig, Map<...> callbacks) would be much cleaner.
  • The same extraction + registration block is duplicated in both createSession and resumeSession in CopilotClient. Should be a shared helper.

3. systemMessage.transform RPC handler — concurrency model — MEDIUM RISK

CopilotSession.handleSystemMessageTransform() uses synchronized (result) on a LinkedHashMap to collect futures. RpcHandlerDispatcher wraps the handler in CompletableFuture.runAsync() (default ForkJoinPool).

Concerns:

  • The synchronized block works but is coarse-grained. Since futures are collected with allOf, the map is only written-to from thenAccept callbacks which could interleave. The synchronization is correct but worth verifying there are no deadlock scenarios.
  • CompletableFuture.runAsync() in the dispatcher uses the common pool. Transform callbacks are user-provided and could block. A custom executor would be safer.
  • No test covers the concurrent multi-section transform case.

4. ToolDefinition record gains a 6th component — MEDIUM RISK

ToolDefinition.java adds skipPermission to the record, changing the canonical constructor from 5 to 6 parameters.

Concerns:

  • Any existing code using the canonical constructor new ToolDefinition(name, desc, params, handler, overrides) will fail to compile. The factory methods are updated, but direct constructor usage in tests or downstream code would break.
  • The record is getting large. If more fields are needed, migration to a builder or class may be warranted.

5. NO_RESULT permission handling — silent no-op — MEDIUM RISK

Both CopilotSession.java (v2 path) and RpcHandlerDispatcher.java (v3 path) check for NO_RESULT and simply return without sending an RPC response.

Concerns:

  • This means the CLI will wait indefinitely for a response that never comes (by design, for multi-client scenarios). For single-client use, returning NO_RESULT would leave the permission request hanging forever. This should be documented prominently as a footgun.
  • No test verifies this end-to-end behavior.

6. autoRestart deprecation — field default change — LOW-MEDIUM RISK

CopilotClientOptions.java changes autoRestart default from true to uninitialized (false). It's marked @Deprecated.

Concerns:

  • Any code that was relying on isAutoRestart() returning true by default will now get false. Even though it's a no-op, callers doing conditional logic on it could change behavior.

7. UnknownSessionEvent forward compatibility — LOW RISK

UnknownSessionEvent.java is added to the sealed hierarchy in AbstractSessionEvent.java. SessionEventParser.java returns it instead of null.

Concerns:

  • Any existing code with exhaustive switch on the sealed type will need to add a case for UnknownSessionEvent. However, the sealed class already had many variants, so callers likely have a default branch.
  • Behavioral change: previously null was returned (and presumably filtered), now a non-null event is dispatched to handlers. This is good but could surprise handlers that don't expect it.
  • Well-tested in ForwardCompatibilityTest.java and updated SessionEventParserTest.java.

8. New DTO classes — SectionOverride, SectionOverrideAction, SystemPromptSections, BlobAttachment, TelemetryConfig — LOW RISK

All are additive, well-documented, and don't modify existing APIs. Standard Jackson-annotated DTOs following existing project conventions.


9. CopilotSession.setModel(String, String) overload and log(...) URL parameter — LOW RISK

Additive overloads. Existing setModel(String) now delegates to the new method. The log() 3-arg version delegates to the 4-arg version.

Minor note: The existing log(String, String, Boolean) method signature change is technically source-compatible since it delegates, but the new 4-arg version is the "real" implementation now.


10. TelemetryConfig → env vars in CliServerManager — LOW RISK

CliServerManager.java sets COPILOT_OTEL_* env vars. Straightforward, no security concerns (it's local process configuration).


11. Documentation and CHANGELOG — MINIMAL RISK

advanced.md and CHANGELOG.md are thorough and well-structured.


Summary of key review questions

  1. Should List<?> / List<Object> be replaced with a marker interface? This is the most important design decision.
  2. Should Object[] return type be replaced with a proper record? Low effort, high readability.
  3. Should NO_RESULT behavior be documented with a warning for single-client scenarios?
  4. Is the ToolDefinition record sustainable at 6 fields, or time for a builder?

…w-failure

Fix compilation errors from PermissionRequestResultKind enum-to-class refactor
@edburns
Copy link
Collaborator

edburns commented Mar 24, 2026

@copilot Consider this change you made:

MessageOptions.java changes the field from List<Attachment> to List<Object>, and the setter from List<Attachment> to List<?>. SendMessageRequest.java mirrors this with List<Object>.

Now consider this statement about the reference implementation.

The .NET SDK uses a polymorphic base class UserMessageDataAttachmentsItem with a type discriminator. All 5 attachment variants (file, directory, selection, github_reference, blob) extend it. The attachments list is typed List<UserMessageDataAttachmentsItem> — fully type-safe.

The Java PR currently uses List<Object> / List<?>, which loses all compile-time safety.

I do not accept this loss of type safety.

Here's the minimal type-safe alternative that mirrors the .NET approach using Java idioms. Analyze and think about these suggestions in the context of your PR. I want you to apply these changes. Update and/or add tests to cover and assert correctness for your changes.

1. New sealed interface: MessageAttachment

package com.github.copilot.sdk.json;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

/**
 * Marker interface for all attachment types that can be included in a message.
 * <p>
 * This is the Java equivalent of the .NET SDK's
 * {@code UserMessageDataAttachmentsItem} polymorphic base class.
 *
 * @see Attachment
 * @see BlobAttachment
 * @see MessageOptions#setAttachments(java.util.List)
 * @since 1.2.0
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Attachment.class, name = "file"),
    @JsonSubTypes.Type(value = BlobAttachment.class, name = "blob")
})
public sealed interface MessageAttachment permits Attachment, BlobAttachment {

    /** Returns the attachment type discriminator (e.g., "file", "blob"). */
    String getType();
}

2. Attachment implements it

Attachment is currently a record. It already has type() from the record component. It needs to implement MessageAttachment and add the getType() bridge:

public record Attachment(
    @JsonProperty("type") String type,
    @JsonProperty("path") String path,
    @JsonProperty("displayName") String displayName
) implements MessageAttachment {

    @Override
    public String getType() {
        return type;
    }
}

(Records generate an accessor for each component named after the component — type() — but the interface requires getType(), so the explicit override is needed.)

3. BlobAttachment implements it

Just add implements MessageAttachment to the class declaration — it already has getType():

public class BlobAttachment implements MessageAttachment {
    // ... existing code unchanged ...
}

4. MessageOptions restores type safety

// Field:
private List<MessageAttachment> attachments;

// Getter:
public List<MessageAttachment> getAttachments() {
    return attachments == null ? null : Collections.unmodifiableList(attachments);
}

// Setter:
public MessageOptions setAttachments(List<? extends MessageAttachment> attachments) {
    this.attachments = attachments != null ? new ArrayList<>(attachments) : null;
    return this;
}

Using List<? extends MessageAttachment> in the setter means callers can pass List<Attachment>, List<BlobAttachment>, or List<MessageAttachment> — all work without casts.

5. SendMessageRequest matches

private List<MessageAttachment> attachments;

public List<MessageAttachment> getAttachments() { ... }
public void setAttachments(List<MessageAttachment> attachments) { ... }

Impact

  • All existing caller code compiles unchanged: List.of(new Attachment(...)) infers List<Attachment> which matches List<? extends MessageAttachment>.
  • List.of(new BlobAttachment(...)) also works — same inference.
  • Mixed lists work: List.<MessageAttachment>of(new Attachment(...), new BlobAttachment(...)) — callers need the explicit type hint only for mixed lists, which is standard Java.
  • No breaking change if MessageAttachment is introduced alongside this PR, since the pre-PR type was List<Attachment> and Attachment would now implement MessageAttachment.
  • The Jackson @JsonTypeInfo/@JsonSubTypes annotations on the interface handle polymorphic deserialization correctly, matching what the .NET SDK's [JsonPolymorphic] does.

What this does NOT do (and shouldn't)

The .NET SDK has 5 subtypes (file, directory, selection, github_reference, blob). The Java SDK currently only has Attachment (maps to "file") and BlobAttachment (maps to "blob"). The other 3 types can be added later as the SDK evolves — the sealed interface can be extended when needed. No need to add them preemptively.

Copy link
Contributor Author

Copilot AI commented Mar 24, 2026

@copilot Consider this change you made:

MessageOptions.java changes the field from List<Attachment> to List<Object>, and the setter from List<Attachment> to List<?>. SendM...

Applied in 727e767. Introduced MessageAttachment sealed interface with @JsonTypeInfo/@JsonSubTypes for polymorphic serialization:

  • Attachment record now implements MessageAttachment with getType() bridge
  • BlobAttachment is now final class ... implements MessageAttachment
  • MessageOptions.setAttachments(List<? extends MessageAttachment>) — accepts List<Attachment>, List<BlobAttachment>, or List<MessageAttachment>
  • SendMessageRequest uses List<MessageAttachment> internally
  • 12 new tests covering type safety, Jackson serialization, mixed lists, clone behavior, and null handling

460 tests pass, 0 failures. No breaking change — existing List.of(new Attachment(...)) callers compile unchanged.

edburns and others added 3 commits March 24, 2026 16:28
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…formCallbacks` returns `Object[]`** — MEDIUM-HIGH RISK"

Your branch is up to date with 'upstream/copilot/sync-upstream-39-new-commits'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .gitignore
	modified:   src/main/java/com/github/copilot/sdk/CopilotClient.java
	modified:   src/main/java/com/github/copilot/sdk/SessionRequestBuilder.java
	modified:   src/test/java/com/github/copilot/sdk/SessionRequestBuilderTest.java

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	src/main/java/com/github/copilot/sdk/ExtractedTransforms.java

no changes added to commit (use "git add" and/or "git commit -a")
…g — silent no-op** — MEDIUM RISK"

modified:   .gitignore
	modified:   src/main/java/com/github/copilot/sdk/RpcHandlerDispatcher.java
	modified:   src/main/java/com/github/copilot/sdk/json/PermissionRequestResultKind.java
	modified:   src/test/java/com/github/copilot/sdk/RpcHandlerDispatcherTest.java
	modified:   src/test/java/com/github/copilot/sdk/SessionHandlerTest.java
@edburns
Copy link
Collaborator

edburns commented Mar 24, 2026

@copilot I observe that https://github.com/github/copilot-sdk-java/actions/runs/23513530134/job/68440337356?pr=20 had Spotless check failures. Please re-run spotless, fix those failures and push commits, and ensure the "Build & Test" check has passed. If not, keep working until you have a clean run.

Copy link
Contributor Author

Copilot AI commented Mar 24, 2026

@copilot I observe that https://github.com/github/copilot-sdk-java/actions/runs/23513530134/job/68440337356?pr=20 had Spotless check failures. Please re-run spotless, fix those failure...

Fixed in 698da99. The Spotless failure was a line-ending mismatch (\r\n vs \n) in the new ExtractedTransforms.java file. Ran mvn spotless:apply, verified mvn spotless:check passes, and confirmed the full build succeeds: 462 tests, 0 failures.

@edburns edburns marked this pull request as ready for review March 25, 2026 01:37
Copilot AI review requested due to automatic review settings March 25, 2026 01:37
@edburns edburns merged commit 33c081f into main Mar 25, 2026
8 checks passed
@edburns edburns deleted the copilot/sync-upstream-39-new-commits branch March 25, 2026 01:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ports 39 upstream commits from the official github/copilot-sdk into the Java SDK to improve forward compatibility, expand system message customization, add new attachment and telemetry capabilities, and align protocol behavior changes.

Changes:

  • Add forward-compatible UnknownSessionEvent handling so unknown CLI event types are dispatched instead of dropped.
  • Introduce SystemMessageMode.CUSTOMIZE with per-section overrides + optional async transform callbacks wired through systemMessage.transform.
  • Expand SDK surface with NO_RESULT permission abstention (v3), tool skipPermission, blob attachments, model reasoning-effort overload, and OpenTelemetry CLI startup configuration.

Reviewed changes

Copilot reviewed 33 out of 34 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/test/java/com/github/copilot/sdk/SessionRequestBuilderTest.java Adds unit tests for extracting system message transform callbacks.
src/test/java/com/github/copilot/sdk/SessionHandlerTest.java Adds test coverage for v3 NO_RESULT permission handling behavior.
src/test/java/com/github/copilot/sdk/SessionEventParserTest.java Updates expectations for unknown event types to return UnknownSessionEvent.
src/test/java/com/github/copilot/sdk/RpcHandlerDispatcherTest.java Adds coverage for v2 behavior when handler returns NO_RESULT.
src/test/java/com/github/copilot/sdk/PermissionRequestResultKindTest.java Extends kind/value and JSON round-trip tests to include NO_RESULT.
src/test/java/com/github/copilot/sdk/MessageAttachmentTest.java Introduces tests for MessageAttachment polymorphism and attachment list type-safety.
src/test/java/com/github/copilot/sdk/ForwardCompatibilityTest.java Adds focused tests for unknown event forward-compat behavior and metadata preservation.
src/site/markdown/advanced.md Documents new safe-tool skipping, CUSTOMIZE system messages, blob attachments, and telemetry.
src/main/java/com/github/copilot/sdk/json/ToolDefinition.java Adds skipPermission field and createSkipPermission() factory.
src/main/java/com/github/copilot/sdk/json/TelemetryConfig.java Adds telemetry configuration DTO for CLI startup env var wiring.
src/main/java/com/github/copilot/sdk/json/SystemPromptSections.java Adds constants for well-known system prompt section identifiers.
src/main/java/com/github/copilot/sdk/json/SystemMessageConfig.java Adds sections map for CUSTOMIZE mode section-level overrides.
src/main/java/com/github/copilot/sdk/json/SendMessageRequest.java Updates request DTO to use List<MessageAttachment> for attachments.
src/main/java/com/github/copilot/sdk/json/SectionOverrideAction.java Adds enum describing section override operations including transform.
src/main/java/com/github/copilot/sdk/json/SectionOverride.java Adds per-section override type with optional async transform callback (SDK-local).
src/main/java/com/github/copilot/sdk/json/PermissionRequestResultKind.java Adds NO_RESULT constant and documentation for abstention behavior.
src/main/java/com/github/copilot/sdk/json/MessageOptions.java Updates attachments API to accept polymorphic MessageAttachment and copy lists defensively.
src/main/java/com/github/copilot/sdk/json/MessageAttachment.java Introduces sealed interface + Jackson polymorphic annotations for attachments.
src/main/java/com/github/copilot/sdk/json/CopilotClientOptions.java Deprecates autoRestart (no-op) and adds telemetry configuration property.
src/main/java/com/github/copilot/sdk/json/BlobAttachment.java Adds inline base64 blob attachment type.
src/main/java/com/github/copilot/sdk/json/Attachment.java Updates file attachment record to implement MessageAttachment.
src/main/java/com/github/copilot/sdk/events/UnknownSessionEvent.java Adds forward-compat placeholder event type retaining base metadata + original type.
src/main/java/com/github/copilot/sdk/events/SessionEventParser.java Returns UnknownSessionEvent for unknown types instead of null.
src/main/java/com/github/copilot/sdk/events/AbstractSessionEvent.java Permits UnknownSessionEvent in the sealed event hierarchy.
src/main/java/com/github/copilot/sdk/SystemMessageMode.java Adds CUSTOMIZE enum value.
src/main/java/com/github/copilot/sdk/SessionRequestBuilder.java Adds transform-callback extraction producing a wire-safe system message config.
src/main/java/com/github/copilot/sdk/RpcHandlerDispatcher.java Registers systemMessage.transform and enforces v2 NO_RESULT rejection behavior.
src/main/java/com/github/copilot/sdk/ExtractedTransforms.java Adds small carrier type for wire config + extracted transform callbacks.
src/main/java/com/github/copilot/sdk/CopilotSession.java Implements transform callback registry/handler, v3 permission abstention, model + log overloads.
src/main/java/com/github/copilot/sdk/CopilotClient.java Wires transform callback extraction + registration into session create/resume flows.
src/main/java/com/github/copilot/sdk/CliServerManager.java Sets CLI OpenTelemetry-related environment variables at process startup.
CHANGELOG.md Updates upstream sync hash and documents newly added/changed/deprecated features.
.lastmerge Updates the recorded upstream merge commit hash.
.gitignore Adds ignore entries for temporary prompt artifacts.
Comments suppressed due to low confidence (1)

src/site/markdown/advanced.md:49

  • The table of contents lists “OpenTelemetry” twice (also appears earlier). Remove this duplicate TOC line to avoid repeated entries.
- [OpenTelemetry](#OpenTelemetry)

});
futures.add(f);
} else {
result.put(sectionId, Map.of("content", content));
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleSystemMessageTransform() writes to result from async completion handlers (synchronized) but also writes to result in the else branch without synchronization. If any transform callback completes on another thread while iteration is still running, this can cause concurrent modification of the non-thread-safe LinkedHashMap (and nondeterministic output). Consider synchronizing all writes to result (including the else branch) or using a concurrent map / collecting results after all futures complete.

Suggested change
result.put(sectionId, Map.of("content", content));
synchronized (result) {
result.put(sectionId, Map.of("content", content));
}

Copilot uses AI. Check for mistakes.
- [Fine-grained Customization](#Fine-grained_Customization)
- [File Attachments](#File_Attachments)
- [Inline Blob Attachments](#Inline_Blob_Attachments)
- [OpenTelemetry](#OpenTelemetry)
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table of contents lists “OpenTelemetry” twice, which will create duplicate entries/anchors in the rendered docs. Remove one of the duplicate TOC lines.

This issue also appears on line 49 of the same file.

Copilot uses AI. Check for mistakes.
@JsonProperty("overridesBuiltInTool") Boolean overridesBuiltInTool,
@JsonProperty("skipPermission") Boolean skipPermission) {

/**
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding skipPermission as a new record component changes the canonical constructor signature, which is source-breaking for any callers doing new ToolDefinition(...). To preserve source compatibility, consider adding an overloaded 5-arg constructor delegating to the 6-arg canonical one (defaulting skipPermission to null) while still keeping the factories.

Suggested change
/**
/**
* Backwards-compatible constructor that matches the original 5-argument
* signature before {@code skipPermission} was added as a record component.
* <p>
* This constructor delegates to the canonical 6-argument constructor with
* {@code skipPermission} defaulted to {@code null}.
*
* @param name
* the unique name of the tool
* @param description
* a description of what the tool does
* @param parameters
* the JSON Schema defining the tool's parameters
* @param handler
* the handler function to execute when invoked
* @param overridesBuiltInTool
* when {@code true}, indicates that this tool intentionally
* overrides a built-in CLI tool with the same name
*/
public ToolDefinition(String name, String description, Object parameters, ToolHandler handler,
Boolean overridesBuiltInTool) {
this(name, description, parameters, handler, overridesBuiltInTool, null);
}
/**

Copilot uses AI. Check for mistakes.
Comment on lines +82 to 87
* <li>{@link Attachment} — file, directory, code selection, or GitHub
* reference</li>
* <li>{@link BlobAttachment} — inline base64-encoded binary data (e.g. images)
* </li>
* </ul>
*
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Javadoc claims Attachment supports “directory, code selection, or GitHub reference”, but Attachment only has path/displayName and the polymorphic mapping in MessageAttachment only registers it under the type id "file". Either narrow the docs to the supported attachment types/values, or expand the attachment model + subtype mapping to actually support the additional kinds.

Suggested change
* <li>{@link Attachment} — file, directory, code selection, or GitHub
* reference</li>
* <li>{@link BlobAttachment} — inline base64-encoded binary data (e.g. images)
* </li>
* </ul>
*
* <li>{@link Attachment} — file reference (path-based file attachment)</li>
* <li>{@link BlobAttachment} — inline base64-encoded binary data (e.g. images)
* </li>
* </ul>
*
*

Copilot uses AI. Check for mistakes.
Comment on lines +63 to +65
* (broadcast permission model). When connected to a protocol v2 server, the SDK
* will throw {@link IllegalStateException} because v2 expects exactly one
* response per permission request.
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PermissionRequestResultKind.NO_RESULT Javadoc says the SDK will throw IllegalStateException when connected to a protocol v2 server, but the v2 dispatcher path converts this into a denied response instead. Update the Javadoc to match the actual behavior (e.g., treated as denied / cannot be used with v2).

Suggested change
* (broadcast permission model). When connected to a protocol v2 server, the SDK
* will throw {@link IllegalStateException} because v2 expects exactly one
* response per permission request.
* (broadcast permission model). When connected to a protocol v2 server, this
* kind cannot be honored and will be treated as a denied response instead,
* because v2 expects exactly one concrete outcome per permission request.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upstream sync: 39 new commits (2026-03-24)

3 participants