Skip to content

Commit aef4bd9

Browse files
stephentoubCopilot
andcommitted
Fix expanded protocol integrations
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 3807b3f commit aef4bd9

14 files changed

Lines changed: 87 additions & 55 deletions

File tree

java/scripts/codegen/java.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ interface JavaTypeResult {
232232
// Set before each schema generation pass; used by schemaTypeToJava and helpers.
233233
let currentDefinitions: Record<string, JSONSchema7> = {};
234234
const pendingStandaloneTypes = new Map<string, JSONSchema7>();
235+
const generatedSessionEventTypeNames = new Set<string>();
235236

236237
// Cross-schema definitions: keyed by schema filename (e.g. "session-events.schema.json"),
237238
// value is the definitions map from that schema. Populated by generateRpcTypes so that
@@ -573,13 +574,15 @@ function schemaTypeToJava(
573574
if (crossSchemaMatch) {
574575
const [, schemaFile, typeName] = crossSchemaMatch;
575576
const externalDefs = crossSchemaDefinitions.get(schemaFile);
576-
if (schemaFile === "session-events.schema.json" && externalDefs?.[typeName]) {
577+
if (
578+
schemaFile === "session-events.schema.json"
579+
&& externalDefs?.[typeName]
580+
&& generatedSessionEventTypeNames.has(typeName)
581+
) {
577582
imports.add(`com.github.copilot.generated.${typeName}`);
578583
return { javaType: typeName, imports };
579584
}
580-
// Fallback: extract just the type name and warn
581-
console.warn(`[codegen] Unresolved cross-schema $ref: ${schema.$ref}`);
582-
return { javaType: typeName, imports };
585+
return { javaType: "Object", imports };
583586
}
584587

585588
const name = schema.$ref.replace(/^#\/definitions\//, "");
@@ -784,6 +787,13 @@ async function generateSessionEvents(schemaPath: string): Promise<void> {
784787
// Generate standalone types discovered via $ref resolution
785788
await generatePendingStandaloneTypes(packageName, packageDir, GENERATED_FROM_SESSION_EVENTS);
786789

790+
generatedSessionEventTypeNames.clear();
791+
for (const entry of await fs.readdir(path.join(REPO_ROOT, packageDir), { withFileTypes: true })) {
792+
if (entry.isFile() && entry.name.endsWith(".java")) {
793+
generatedSessionEventTypeNames.add(path.basename(entry.name, ".java"));
794+
}
795+
}
796+
787797
console.log(`✅ Generated ${variants.length + 1} session event files`);
788798
}
789799

java/sdk/src/generated/java/com/github/copilot/generated/rpc/PendingPermissionRequest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
1111
import com.fasterxml.jackson.annotation.JsonInclude;
1212
import com.fasterxml.jackson.annotation.JsonProperty;
13-
import com.github.copilot.generated.PermissionPromptRequest;
1413
import javax.annotation.processing.Generated;
1514

1615
/**
@@ -25,6 +24,6 @@ public record PendingPermissionRequest(
2524
/** Unique identifier for the pending permission request */
2625
@JsonProperty("requestId") String requestId,
2726
/** The user-facing permission prompt details (commands, write, read, mcp, url, memory, custom-tool, path, hook) */
28-
@JsonProperty("request") PermissionPromptRequest request
27+
@JsonProperty("request") Object request
2928
) {
3029
}

java/sdk/src/main/java/com/github/copilot/CopilotSession.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ private void executeToolAndRespondAsync(String requestId, String toolName, Strin
10011001
* future completes exceptionally.
10021002
*/
10031003
private SessionUiHandlePendingElicitationParams buildElicitationCancelParams(String requestId) {
1004-
var cancelResult = new UIElicitationResponse(UIElicitationResponseAction.CANCEL, null);
1004+
var cancelResult = new UIElicitationResponse(UIElicitationResponseAction.CANCEL, null, null);
10051005
return new SessionUiHandlePendingElicitationParams(sessionId, requestId, cancelResult);
10061006
}
10071007

@@ -1213,7 +1213,7 @@ private void handleElicitationRequestAsync(ElicitationContext context, String re
12131213
? result.getAction().getValue()
12141214
: ElicitationResultAction.CANCEL.getValue();
12151215
var parsedAction = UIElicitationResponseAction.fromValue(actionStr);
1216-
var elicitationResult = new UIElicitationResponse(parsedAction, result.getContent());
1216+
var elicitationResult = new UIElicitationResponse(parsedAction, result.getContent(), null);
12171217
getRpc().ui.handlePendingElicitation(
12181218
new SessionUiHandlePendingElicitationParams(sessionId, requestId, elicitationResult));
12191219
} catch (Exception e) {
@@ -1268,10 +1268,10 @@ private final class SessionUiApiImpl implements SessionUiApi {
12681268
@Override
12691269
public CompletableFuture<ElicitationResult> elicitation(ElicitationParams params) {
12701270
assertElicitation();
1271-
return getRpc().ui.elicitation(new SessionUiElicitationParams(sessionId, params.getMessage(),
1271+
return getRpc().ui.elicitation(new SessionUiElicitationParams(sessionId, null, params.getMessage(),
12721272
new UIElicitationSchema(params.getRequestedSchema().getType(),
1273-
params.getRequestedSchema().getProperties(), params.getRequestedSchema().getRequired())))
1274-
.thenApply(resp -> {
1273+
params.getRequestedSchema().getProperties(), params.getRequestedSchema().getRequired()),
1274+
null, null)).thenApply(resp -> {
12751275
var result = new ElicitationResult();
12761276
if (resp.action() != null) {
12771277
for (ElicitationResultAction a : ElicitationResultAction.values()) {
@@ -1293,8 +1293,9 @@ public CompletableFuture<ElicitationResult> elicitation(ElicitationParams params
12931293
public CompletableFuture<Boolean> confirm(String message) {
12941294
assertElicitation();
12951295
var field = Map.of("type", "boolean", "default", (Object) true);
1296-
return getRpc().ui.elicitation(new SessionUiElicitationParams(sessionId, message,
1297-
new UIElicitationSchema("object", Map.of("confirmed", (Object) field), List.of("confirmed"))))
1296+
return getRpc().ui
1297+
.elicitation(new SessionUiElicitationParams(sessionId, null, message, new UIElicitationSchema(
1298+
"object", Map.of("confirmed", (Object) field), List.of("confirmed")), null, null))
12981299
.thenApply(resp -> {
12991300
if (resp.action() == UIElicitationResponseAction.ACCEPT && resp.content() != null) {
13001301
Object val = resp.content().get("confirmed");
@@ -1316,8 +1317,9 @@ public CompletableFuture<Boolean> confirm(String message) {
13161317
public CompletableFuture<String> select(String message, String[] options) {
13171318
assertElicitation();
13181319
var field = Map.of("type", (Object) "string", "enum", (Object) options);
1319-
return getRpc().ui.elicitation(new SessionUiElicitationParams(sessionId, message,
1320-
new UIElicitationSchema("object", Map.of("selection", (Object) field), List.of("selection"))))
1320+
return getRpc().ui
1321+
.elicitation(new SessionUiElicitationParams(sessionId, null, message, new UIElicitationSchema(
1322+
"object", Map.of("selection", (Object) field), List.of("selection")), null, null))
13211323
.thenApply(resp -> {
13221324
if (resp.action() == UIElicitationResponseAction.ACCEPT && resp.content() != null) {
13231325
Object val = resp.content().get("selection");
@@ -1346,9 +1348,8 @@ public CompletableFuture<String> input(String message, InputOptions options) {
13461348
if (options.getDefaultValue() != null)
13471349
field.put("default", options.getDefaultValue());
13481350
}
1349-
return getRpc().ui
1350-
.elicitation(new SessionUiElicitationParams(sessionId, message,
1351-
new UIElicitationSchema("object", Map.of("value", (Object) field), List.of("value"))))
1351+
return getRpc().ui.elicitation(new SessionUiElicitationParams(sessionId, null, message,
1352+
new UIElicitationSchema("object", Map.of("value", (Object) field), List.of("value")), null, null))
13521353
.thenApply(resp -> {
13531354
if (resp.action() == UIElicitationResponseAction.ACCEPT && resp.content() != null) {
13541355
Object val = resp.content().get("value");
@@ -1994,10 +1995,8 @@ public CompletableFuture<Void> abort() {
19941995
*/
19951996
public CompletableFuture<Void> setModel(String model, String reasoningEffort) {
19961997
ensureNotTerminated();
1997-
return getRpc().model
1998-
.switchTo(
1999-
new SessionModelSwitchToParams(sessionId, model, reasoningEffort, null, null, null, null, null))
2000-
.thenApply(r -> null);
1998+
return getRpc().model.switchTo(new SessionModelSwitchToParams(sessionId, model, reasoningEffort, null, null,
1999+
null, null, null, null, null, null, null, null, null, null)).thenApply(r -> null);
20012000
}
20022001

20032002
/**
@@ -2077,8 +2076,10 @@ public CompletableFuture<Void> setModel(String model, String reasoningEffort, St
20772076
var generatedReasoningSummary = reasoningSummary == null
20782077
? null
20792078
: com.github.copilot.generated.rpc.ReasoningSummary.fromValue(reasoningSummary);
2080-
return getRpc().model.switchTo(new SessionModelSwitchToParams(sessionId, model, reasoningEffort,
2081-
generatedReasoningSummary, null, generatedCapabilities, null, null)).thenApply(r -> null);
2079+
return getRpc().model
2080+
.switchTo(new SessionModelSwitchToParams(sessionId, model, reasoningEffort, generatedReasoningSummary,
2081+
null, generatedCapabilities, null, null, null, null, null, null, null, null, null))
2082+
.thenApply(r -> null);
20822083
}
20832084

20842085
/**

python/copilot/copilot_request_handler.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,12 @@ async def write_response(self, data: str | bytes) -> None:
458458
raise RuntimeError("Copilot request response write() called before start().")
459459
if self.finished:
460460
raise RuntimeError("Copilot request response write() called after end()/error().")
461-
is_binary = isinstance(data, bytes)
462-
payload = base64.b64encode(data).decode("ascii") if is_binary else data
461+
if isinstance(data, bytes):
462+
payload = base64.b64encode(data).decode("ascii")
463+
is_binary = True
464+
else:
465+
payload = data
466+
is_binary = False
463467
await self._require_rpc().http_response_chunk(
464468
LlmInferenceHTTPResponseChunkRequest(
465469
data=payload,

python/copilot/generated/session_events.py

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python/copilot/session.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,11 @@
2727
from ._telemetry import get_trace_context, trace_context
2828
from .canvas import CanvasError, CanvasHandler, OpenCanvasInstance
2929
from .generated.rpc import (
30-
CanvasHandler as RpcCanvasHandler,
31-
)
32-
from .generated.rpc import (
30+
BuiltinToolInputSchemaType,
3331
CanvasProviderCloseRequest,
3432
CanvasProviderInvokeActionRequest,
3533
CanvasProviderOpenRequest,
3634
CanvasProviderOpenResult,
37-
BuiltinToolInputSchemaType,
3835
ClientSessionApiHandlers,
3936
CommandsHandlePendingCommandRequest,
4037
HandlePendingToolCallRequest,
@@ -60,6 +57,9 @@
6057
UIElicitationSchemaPropertyType,
6158
UIHandlePendingElicitationRequest,
6259
)
60+
from .generated.rpc import (
61+
CanvasHandler as RpcCanvasHandler,
62+
)
6363
from .generated.rpc import (
6464
ContextTier as _RpcContextTier,
6565
)

rust/tests/e2e/commands.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ async fn session_commands_invoke_known_builtin_returns_expected_result() {
105105
.invoke(CommandsInvokeRequest {
106106
name: "context".to_string(),
107107
input: None,
108+
..Default::default()
108109
})
109110
.await
110111
.expect("invoke context");

rust/tests/e2e/mode_handlers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ async fn should_invoke_exit_plan_mode_handler_when_model_uses_tool() {
118118
.mode()
119119
.set(ModeSetRequest {
120120
mode: SessionMode::Plan,
121+
..Default::default()
121122
})
122123
.await
123124
.expect("set plan mode");

rust/tests/e2e/rpc_additional_edge_cases.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ async fn mode_set_to_same_value_multiple_times_stays_stable() {
277277
.mode()
278278
.set(ModeSetRequest {
279279
mode: SessionMode::Plan,
280+
..Default::default()
280281
})
281282
.await
282283
.expect("set mode");

rust/tests/e2e/rpc_event_side_effects.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ async fn should_emit_mode_changed_event_when_mode_set() {
4040
.mode()
4141
.set(ModeSetRequest {
4242
mode: SessionMode::Plan,
43+
..Default::default()
4344
})
4445
.await
4546
.expect("set mode");

0 commit comments

Comments
 (0)