Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f57dc91
Regenerate RPC bindings for managedSettings.clearCache
joshspicer Aug 28, 2026
7947421
Regenerate Java codegen output
github-actions[bot] Aug 28, 2026
02b459d
Merge branch 'main' into agents/managed-settings-clear-cache
joshspicer Sep 1, 2026
3e2059c
Regenerate Java managed settings clear-cache binding
joshspicer Sep 1, 2026
52bbe78
Regenerate Java codegen output
github-actions[bot] Sep 1, 2026
cb3f640
Merge remote-tracking branch 'refs/remotes/origin/pr-2438' into agent…
joshspicer Sep 2, 2026
ddaaf2d
Regenerate clear-cache bindings from runtime schema
joshspicer Sep 2, 2026
de4bc72
Regenerate Java codegen output
github-actions[bot] Sep 2, 2026
c7e6d3d
Merge remote-tracking branch 'origin/main' into agents/update-pr-runt…
joshspicer Sep 3, 2026
21c0885
Regenerate Java managed settings clear-cache binding
joshspicer Sep 3, 2026
497aa9e
Regenerate Java codegen output
github-actions[bot] Sep 3, 2026
1e3db79
Merge remote-tracking branch 'origin/main' into agents/update-pr-runt…
joshspicer Sep 3, 2026
e53c1fe
Update Copilot CLI to 1.0.83-4
github-actions[bot] Sep 3, 2026
9bfebad
Update Copilot CLI to 1.0.83-4
Copilot Sep 3, 2026
60da1d8
Add managed settings clear-cache E2E coverage
joshspicer Sep 3, 2026
8ee5f13
Merge remote-tracking branch 'origin/agents/managed-settings-clear-ca…
joshspicer Sep 3, 2026
5273796
Keep clear-cache E2E on default transport
joshspicer Sep 3, 2026
da13441
Merge remote-tracking branch 'origin/main' into agents/update-pr-runt…
joshspicer Sep 3, 2026
2c59364
Merge main into managed-settings-clear-cache
Copilot Sep 4, 2026
7e3ed43
Regenerate Java codegen output
github-actions[bot] Sep 4, 2026
0d85463
Fix duplicate Rust MCP config field
Copilot Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions dotnet/test/E2E/RpcServerE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ public async Task Should_Call_Rpc_Ping_With_Typed_Params_And_Result()
Assert.NotEqual(default, result.Timestamp);
}

[Fact]
[Trait(E2ETestTraits.Backend, E2ETestTraits.CapiOnly)]
public async Task Should_Clear_The_Managed_Settings_Cache()
{
await Client.StartAsync();

await Client.Rpc.ManagedSettings.ClearCacheAsync();
}

[Fact]
public async Task Should_Reject_Llm_Inference_Response_Frames_For_Missing_Request()
{
Expand Down
29 changes: 29 additions & 0 deletions dotnet/test/Unit/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,35 @@ public void QueuePendingItems_MessageId_UsesCamelCaseAndIsOptional(string? messa
}
#pragma warning restore GHCP001

[Fact]
public void ModelSwitchRequests_DistinguishRequiredNullFromOmittedOptionalValue()
{
var options = GetSerializerOptions();
var assembly = typeof(CopilotClient).Assembly;

var switchAutoTierType = assembly.GetType("GitHub.Copilot.Rpc.ModelSwitchAutoTierRequest");
Assert.NotNull(switchAutoTierType);
var switchAutoTierRequest = CreateInternalRequest(
switchAutoTierType!,
("SessionId", "session-id"),
("AutoTier", null));
using var switchAutoTierDocument = JsonDocument.Parse(
JsonSerializer.Serialize(switchAutoTierRequest, switchAutoTierType!, options));
Assert.True(switchAutoTierDocument.RootElement.TryGetProperty("autoTier", out var requiredAutoTier));
Assert.Equal(JsonValueKind.Null, requiredAutoTier.ValueKind);

var switchToType = assembly.GetType("GitHub.Copilot.Rpc.ModelSwitchToRequest");
Assert.NotNull(switchToType);
var switchToRequest = CreateInternalRequest(
switchToType!,
("SessionId", "session-id"),
("ModelId", "auto"),
("AutoTier", null));
using var switchToDocument = JsonDocument.Parse(
JsonSerializer.Serialize(switchToRequest, switchToType!, options));
Assert.False(switchToDocument.RootElement.TryGetProperty("autoTier", out _));
}

private static JsonSerializerOptions GetSerializerOptions()
{
var prop = typeof(CopilotClient)
Expand Down
15 changes: 15 additions & 0 deletions go/internal/e2e/rpc_server_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ import (
// Mirrors dotnet/test/RpcServerTests.cs (snapshot category "rpc_server").
// Tests server-scoped (non-session) RPCs.
func TestRPCServerE2E(t *testing.T) {
t.Run("should clear the managed settings cache", func(t *testing.T) {
ctx := testharness.NewTestContext(t)
ctx.ConfigureForTest(t)
client := ctx.NewClient()
t.Cleanup(func() { client.ForceStop() })

if err := client.Start(t.Context()); err != nil {
t.Fatalf("Start failed: %v", err)
}

if _, err := client.RPC.ManagedSettings.ClearCache(t.Context()); err != nil {
t.Fatalf("ManagedSettings.ClearCache failed: %v", err)
}
})

t.Run("should call rpc ping with typed params and result", func(t *testing.T) {
ctx := testharness.NewTestContext(t)
ctx.ConfigureForTest(t)
Expand Down
24 changes: 23 additions & 1 deletion java/scripts/codegen/java.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,18 @@ function rpcMethodToClassName(rpcMethod: string): string {
return rpcMethod.split(/[._-]/).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
}

function schemaAllowsNull(schema: JSONSchema7): boolean {
if (schema.type === "null" || (Array.isArray(schema.type) && schema.type.includes("null"))) {
return true;
}
if (schema.const === null || schema.enum?.includes(null)) {
return true;
}
return [...(schema.anyOf || []), ...(schema.oneOf || [])].some(
(variant) => typeof variant === "object" && schemaAllowsNull(variant)
);
}

/** Generate a Java record for a JSON Schema object type. Returns the class content. */
function generateRpcClass(
className: string,
Expand All @@ -1340,13 +1352,20 @@ function generateRpcClass(
const visModifier = visibility === "public" ? "public " : "";

const properties = Object.entries(schema.properties || {});
const required = new Set(schema.required || []);
const fields = properties.flatMap(([propName, propSchema]) => {
if (typeof propSchema !== "object") return [];
const prop = propSchema as JSONSchema7;
// Record components are always boxed (nullable by design).
const result = schemaTypeToJava(prop, false, className, propName, localNestedTypes);
for (const imp of result.imports) imports.add(imp);
return [{ propName, javaName: toCamelCase(propName), javaType: result.javaType, description: prop.description }];
return [{
propName,
javaName: toCamelCase(propName),
javaType: result.javaType,
description: prop.description,
includeNull: required.has(propName) && schemaAllowsNull(prop),
}];
});

lines.push(`@JsonInclude(JsonInclude.Include.NON_NULL)`);
Expand All @@ -1361,6 +1380,9 @@ function generateRpcClass(
if (f.description) {
lines.push(` /** ${f.description} */`);
}
if (f.includeNull) {
lines.push(` @JsonInclude(JsonInclude.Include.ALWAYS)`);
}
lines.push(` @JsonProperty("${f.propName}") ${f.javaType} ${f.javaName}${comma}`);
}
lines.push(`) {`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public record CustomAgentsUpdatedAgent(
/** Source location: user, project, inherited, remote, or plugin */
@JsonProperty("source") String source,
/** List of tool names available to this agent, or null when all tools are available */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("tools") List<String> tools,
/** Whether the agent can be selected by the user */
@JsonProperty("userInvocable") Boolean userInvocable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,21 @@ public record BuiltinToolDescriptor(
/** Stable name used to invoke the built-in tool. */
@JsonProperty("name") String name,
/** Optional human-readable title for the tool. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("title") String title,
/** Model-facing description of the tool's behavior. */
@JsonProperty("description") String description,
/** JSON Schema for the tool input, or null when the tool uses a custom format. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("inputSchema") BuiltinToolInputSchema inputSchema,
/** Optional supplemental usage instructions for the tool. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("instructions") String instructions,
/** Optional tool category discriminator. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("type") String type,
/** Optional custom input format used instead of a JSON Schema. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("format") BuiltinToolFormat format,
/** Policy describing which tool metadata may be recorded without obfuscation. */
@JsonProperty("safeForTelemetry") Object safeForTelemetry,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public record FactoryAgentSummary(
/** Owning factory run identifier. */
@JsonProperty("runId") String runId,
/** Phase identifier active when the agent was launched, or null. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("phaseId") String phaseId,
/** Friendly, non-unique name intended for display */
@JsonProperty("label") String label,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public record FactoryCurrentPhase(
/** Current phase identifier. */
@JsonProperty("id") String id,
/** Zero-based declared phase ordinal, or null for an undeclared phase. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("ordinal") Long ordinal
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public record FactoryPhaseObservation(
/** Phase identifier. */
@JsonProperty("id") String id,
/** Zero-based declared phase ordinal, or null for an undeclared phase. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("ordinal") Long ordinal,
/** Human-readable phase title. */
@JsonProperty("title") String title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public record FactoryProgressLine(
/** Resume attempt that emitted this record. */
@JsonProperty("attempt") Long attempt,
/** Phase active when the record was emitted, or null before any phase. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("phaseId") String phaseId,
/** Epoch milliseconds when the record was persisted. */
@JsonProperty("recordedAt") Long recordedAt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ public record FactoryProgressPage(
/** Progress records in sequence order. */
@JsonProperty("records") List<FactoryProgressLine> records,
/** Oldest sequence number in this page, or null when empty. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("oldestSeq") Long oldestSeq,
/** Newest sequence number in this page, or null when empty. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("newestSeq") Long newestSeq,
/** Whether progress records older than this page exist. */
@JsonProperty("hasMoreOlder") Boolean hasMoreOlder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,15 @@ public record FactoryRunSummary(
/** Epoch milliseconds when the run was created. */
@JsonProperty("createdAt") Long createdAt,
/** Epoch milliseconds when execution first started, or null before start. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("startedAt") Long startedAt,
/** Epoch milliseconds when the durable run was last updated. */
@JsonProperty("updatedAt") Long updatedAt,
/** Epoch milliseconds when the run completed, or null while nonterminal. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("completedAt") Long completedAt,
/** Current phase identity, or null before any phase is entered. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("currentPhase") FactoryCurrentPhase currentPhase,
/** Number of phases declared by the factory. */
@JsonProperty("declaredPhaseCount") Long declaredPhaseCount,
Expand All @@ -52,12 +55,15 @@ public record FactoryRunSummary(
/** Resource ceilings declared by the factory. */
@JsonProperty("declaredLimits") FactoryDeclaredLimits declaredLimits,
/** Approved effective resource ceilings, or null until approved. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("approved") FactoryDeclaredLimits approved,
/** Epoch milliseconds when this live-overlay snapshot was observed. */
@JsonProperty("observedAt") Long observedAt,
/** Epoch milliseconds when the current active segment started, or null while inactive. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("activeSegmentStartedAt") Long activeSegmentStartedAt,
/** Terminal run outcome, or null while nonterminal. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("terminal") FactoryRunTerminal terminal
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public record PermissionRule(
/** The rule kind, such as Shell or GitHubMCP */
@JsonProperty("kind") String kind,
/** Argument value matched against the request, or null when the rule kind has no argument (e.g. 'read', 'write', 'memory'). */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("argument") String argument
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ public record SessionFactoryGetRunDetailResult(
/** Epoch milliseconds when the run was created. */
@JsonProperty("createdAt") Long createdAt,
/** Epoch milliseconds when execution first started, or null before start. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("startedAt") Long startedAt,
/** Epoch milliseconds when the durable run was last updated. */
@JsonProperty("updatedAt") Long updatedAt,
/** Epoch milliseconds when the run completed, or null while nonterminal. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("completedAt") Long completedAt,
/** Current phase identity, or null before any phase is entered. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("currentPhase") FactoryCurrentPhase currentPhase,
/** Number of phases declared by the factory. */
@JsonProperty("declaredPhaseCount") Long declaredPhaseCount,
Expand All @@ -56,12 +59,15 @@ public record SessionFactoryGetRunDetailResult(
/** Resource ceilings declared by the factory. */
@JsonProperty("declaredLimits") FactoryDeclaredLimits declaredLimits,
/** Approved effective resource ceilings, or null until approved. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("approved") FactoryDeclaredLimits approved,
/** Epoch milliseconds when this live-overlay snapshot was observed. */
@JsonProperty("observedAt") Long observedAt,
/** Epoch milliseconds when the current active segment started, or null while inactive. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("activeSegmentStartedAt") Long activeSegmentStartedAt,
/** Terminal run outcome, or null while nonterminal. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("terminal") FactoryRunTerminal terminal,
/** Lifecycle and timing observations for each factory phase. */
@JsonProperty("phases") List<FactoryPhaseObservation> phases,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ public record SessionFactoryGetRunProgressResult(
/** Progress records in sequence order. */
@JsonProperty("records") List<FactoryProgressLine> records,
/** Oldest sequence number in this page, or null when empty. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("oldestSeq") Long oldestSeq,
/** Newest sequence number in this page, or null when empty. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("newestSeq") Long newestSeq,
/** Whether progress records older than this page exist. */
@JsonProperty("hasMoreOlder") Boolean hasMoreOlder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public record SessionMetadataSnapshotResult(
/** True when the session was detected to be in use by another process at construction time. Local consumers may surface a confirmation prompt before fully attaching. Always false for new sessions. */
@JsonProperty("alreadyInUse") Boolean alreadyInUse,
/** Absolute path to the session's workspace directory on disk, or null if the session has no associated workspace */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("workspacePath") String workspacePath,
/** User-provided name supplied at session construction (via `--name`), if any. Immutable after construction. */
@JsonProperty("initialName") String initialName,
Expand All @@ -52,6 +53,7 @@ public record SessionMetadataSnapshotResult(
/** Currently selected model identifier, if any */
@JsonProperty("selectedModel") String selectedModel,
/** Current session limits, or null when no limits are active */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("sessionLimits") SessionLimitsConfig sessionLimits,
/** Public-facing workspace metadata for this session, or null if the session has no associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, internal flags). */
@JsonProperty("workspace") SessionMetadataSnapshotResultWorkspace workspace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public record SessionModelSwitchAutoTierParams(
/** Target session identifier */
@JsonProperty("sessionId") String sessionId,
/** Auto preference to activate when a future user turn using the `auto` model safely mints a replacement model and token pair. Pass null to return to provider-default Auto routing. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("autoTier") AutoTier autoTier,
/** Origin to record on the effective `session.model_change` event. Defaults to `sdk` when omitted. */
@JsonProperty("source") ModelChangeSource source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionNameGetResult(
/** The session name (user-set or auto-generated), or null if not yet set */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("name") String name
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ public record SessionPlanReadResult(
/** Whether the plan file exists in the workspace */
@JsonProperty("exists") Boolean exists,
/** The content of the plan file, or null if it does not exist */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("content") String content,
/** Absolute file path of the plan file, or null if workspace is not enabled */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("path") String path
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionToolsGetCurrentMetadataResult(
/** Current tool metadata, or null when tools have not been initialized yet */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("tools") List<CurrentToolMetadata> tools
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionWorkspacesEnsureResult(
/** Current workspace metadata, or null if not available */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("workspace") SessionWorkspacesEnsureResultWorkspace workspace,
/** Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). */
@JsonProperty("path") String path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionWorkspacesGetWorkspaceResult(
/** Current workspace metadata, or null if not available */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("workspace") SessionWorkspacesGetWorkspaceResultWorkspace workspace,
/** Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). */
@JsonProperty("path") String path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionWorkspacesReadAutopilotObjectiveResult(
/** Autopilot objective file content, or null when missing. */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("content") String content
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionWorkspacesReadCheckpointResult(
/** Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("content") String content
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionWorkspacesSaveLargePasteResult(
/** Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, non-infinite sessions, remote sessions) */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("saved") SessionWorkspacesSaveLargePasteResultSaved saved
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionWorkspacesTruncateSummariesResult(
/** Current workspace metadata, or null if not available */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("workspace") SessionWorkspacesTruncateSummariesResultWorkspace workspace,
/** Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). */
@JsonProperty("path") String path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionWorkspacesUpdateMetadataResult(
/** Current workspace metadata, or null if not available */
@JsonInclude(JsonInclude.Include.ALWAYS)
@JsonProperty("workspace") SessionWorkspacesUpdateMetadataResultWorkspace workspace,
/** Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). */
@JsonProperty("path") String path
Expand Down
Loading