From 35b52624a69f04ae99e6b519a3d88428e77657b0 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 10 Jun 2026 15:08:17 +0100 Subject: [PATCH 01/10] Add E2E test for session.providerEndpoint.get Validates the new shared API exposed by copilot-agent-runtime (see github/copilot-sdk-internal#133) end-to-end from the Node SDK. Covers both BYOK (returns provider config + headers) and CAPI (returns the resolved CAPI base URL). Regenerates rpc.ts and session-events.ts against the runtime schema that adds the providerEndpoint RPC. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- nodejs/src/generated/rpc.ts | 89 +++++++++++++++++++ nodejs/test/e2e/provider_endpoint.e2e.test.ts | 86 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 nodejs/test/e2e/provider_endpoint.e2e.test.ts diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index c17a21d21..c45c8ccba 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -1011,6 +1011,20 @@ export type ProviderConfigWireApi = | "completions" /** OpenAI Responses API wire format. */ | "responses"; +/** + * Wire protocol the caller must speak to `baseUrl`. Tells the caller which LLM client library to instantiate. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ProviderWireProtocol". + */ +/** @experimental */ +export type ProviderWireProtocol = + /** OpenAI Chat Completions wire format (`/chat/completions`). Use the `openai` client library. */ + | "openai-completions" + /** OpenAI Responses wire format (`/responses`). Use the `openai` client library. */ + | "openai-responses" + /** Anthropic Messages wire format (`/v1/messages`). Use the `@anthropic-ai/sdk` client library. */ + | "anthropic"; /** * Schema for the `PushAttachment` type. * @@ -7809,6 +7823,69 @@ export interface ProviderConfigAzure { */ apiVersion?: string; } +/** + * A snapshot of the provider endpoint the session is currently configured to talk to, with enough information for an external caller to make inference calls directly against the same backend using the OpenAI or Anthropic client libraries. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ProviderEndpoint". + */ +/** @experimental */ +export interface ProviderEndpoint { + protocol: ProviderWireProtocol; + /** + * Base URL the caller should pass to the LLM client library (e.g. `new OpenAI({ baseURL })` or `new Anthropic({ baseURL })`). + */ + baseUrl: string; + /** + * Credential for the LLM client constructor (e.g. `new OpenAI({ apiKey })` or `new Anthropic({ apiKey })`). The OpenAI / Anthropic client libraries turn this into the appropriate auth header (typically `Authorization: Bearer …`). Omitted only when the endpoint accepts unauthenticated requests (e.g. a local model server). + */ + apiKey?: string; + /** + * Static HTTP headers the caller must include on every outbound request. Does NOT include the `Authorization` header (the LLM client library adds that from `apiKey`) and does NOT include the `sessionToken` header (sent separately). + */ + headers: { + [k: string]: string | undefined; + }; + sessionToken?: ProviderSessionToken; +} +/** + * Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ProviderSessionToken". + */ +/** @experimental */ +export interface ProviderSessionToken { + /** + * The short-lived token value. + */ + token: string; + /** + * HTTP header name the token must be sent under. + */ + header: string; + /** + * The model the token is bound to, when applicable. When set, the token is only valid for requests against this model. + */ + model?: string; + /** + * When the token expires. Callers should refresh by calling `get` again before this time, or reactively on any 401/403 response from `baseUrl`. + */ + expiresAt: string; +} +/** + * Optional model identifier to scope the endpoint snapshot to. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ProviderEndpointGetRequest". + */ +/** @experimental */ +export interface ProviderEndpointGetRequest { + /** + * Model identifier the caller intends to use against the returned endpoint. Used to pick the wire protocol (Anthropic Messages vs. OpenAI Responses vs. OpenAI Chat Completions) and to scope any returned `sessionToken` to that model. When omitted, the session's currently active model is used. Ignored when the session uses a custom provider that doesn't vary by model. + */ + modelId?: string; +} /** * File attachment * @@ -13911,6 +13988,18 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.plugins.reload", { sessionId, ...params }), }, /** @experimental */ + providerEndpoint: { + /** + * Returns the provider endpoint and credentials the session is currently configured to talk to, so the caller can make inference calls directly against the same backend the session uses. May throw for sessions whose authentication scheme is not yet supported. + * + * @param params Optional model identifier to scope the endpoint snapshot to. + * + * @returns A snapshot of the provider endpoint the session is currently configured to talk to, with enough information for an external caller to make inference calls directly against the same backend using the OpenAI or Anthropic client libraries. + */ + get: async (params?: ProviderEndpointGetRequest): Promise => + connection.sendRequest("session.providerEndpoint.get", { sessionId, ...params }), + }, + /** @experimental */ options: { /** * Patches the genuinely-mutable subset of session options. diff --git a/nodejs/test/e2e/provider_endpoint.e2e.test.ts b/nodejs/test/e2e/provider_endpoint.e2e.test.ts new file mode 100644 index 000000000..b21124c83 --- /dev/null +++ b/nodejs/test/e2e/provider_endpoint.e2e.test.ts @@ -0,0 +1,86 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +import { describe, expect, it } from "vitest"; +import { approveAll } from "../../src/index.js"; +import { createSdkTestContext } from "./harness/sdkTestContext.js"; + +describe("session.providerEndpoint.get RPC", async () => { + const { copilotClient: client } = await createSdkTestContext(); + + it("returns the BYOK provider endpoint when a custom provider is configured", async () => { + const session = await client.createSession({ + onPermissionRequest: approveAll, + provider: { + type: "openai", + wireApi: "completions", + baseUrl: "https://api.example.test/v1", + apiKey: "byok-secret", + headers: { "X-Custom-Header": "byok-yes" }, + }, + }); + + try { + const endpoint = await session.rpc.providerEndpoint.get({}); + + expect(endpoint.protocol).toBe("openai-completions"); + expect(endpoint.baseUrl).toBe("https://api.example.test/v1"); + expect(endpoint.apiKey).toBe("byok-secret"); + expect(endpoint.headers).toMatchObject({ "X-Custom-Header": "byok-yes" }); + // Auth and per-request session-token headers should not appear here. + expect(endpoint.headers).not.toHaveProperty("Authorization"); + expect(endpoint.headers).not.toHaveProperty("Copilot-Session-Token"); + // BYOK sessions never issue a CAPI session token. + expect(endpoint.sessionToken).toBeUndefined(); + } finally { + try { + await session.disconnect(); + } catch { + // disconnect may fail since the BYOK provider URL is fake + } + } + }); + + it("returns the CAPI provider endpoint for an OAuth-authenticated session", async () => { + const session = await client.createSession({ + onPermissionRequest: approveAll, + }); + + try { + const endpoint = await session.rpc.providerEndpoint.get({}); + + // Wire protocol defaults to openai-completions when no model picks + // an alternative endpoint set. + expect(["openai-completions", "openai-responses", "anthropic"]).toContain(endpoint.protocol); + + // CAPI baseUrl is the (proxy) Copilot API URL injected by the harness. + expect(endpoint.baseUrl).toMatch(/^https?:\/\//); + + // For CAPI OAuth sessions the apiKey is the resolved GitHub bearer. + expect(endpoint.apiKey).toBeTypeOf("string"); + expect(endpoint.apiKey!.length).toBeGreaterThan(0); + + // Standard CAPI headers should be present, and the Authorization / + // session-token headers must not be in `headers` (they're carried + // by `apiKey` and `sessionToken` respectively). + expect(endpoint.headers["Copilot-Integration-Id"]).toBeTypeOf("string"); + expect(endpoint.headers["User-Agent"]).toMatch(/Copilot/i); + expect(endpoint.headers["X-GitHub-Api-Version"]).toBeTypeOf("string"); + expect(endpoint.headers["X-Interaction-Id"]).toMatch(/[0-9a-f-]{8,}/); + expect(endpoint.headers).not.toHaveProperty("Authorization"); + expect(endpoint.headers).not.toHaveProperty("Copilot-Session-Token"); + + // If a session token came back, it must use the documented header + // name and an ISO 8601 expiry. The harness proxy may decline to + // issue one — in that case the field is simply omitted. + if (endpoint.sessionToken) { + expect(endpoint.sessionToken.header).toBe("Copilot-Session-Token"); + expect(endpoint.sessionToken.token.length).toBeGreaterThan(0); + expect(Date.parse(endpoint.sessionToken.expiresAt)).not.toBeNaN(); + } + } finally { + await session.disconnect(); + } + }); +}); From f21594882bfe2f7b0a07b563f8ad34d933a77c6b Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 11 Jun 2026 12:18:45 +0100 Subject: [PATCH 02/10] Update e2e test for renamed provider.getEndpoint API Runtime renamed session.providerEndpoint.get -> session.provider.getEndpoint and split the wire protocol into separate type+wireApi fields. Regenerated rpc.ts/session-events.ts against the runtime schema and updated the test assertions to match. Both BYOK and CAPI cases pass against the real harness CapiProxy. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- nodejs/src/generated/rpc.ts | 77 +++++++++++++------ nodejs/src/generated/session-events.ts | 28 +++---- nodejs/test/e2e/provider_endpoint.e2e.test.ts | 28 ++++--- 3 files changed, 86 insertions(+), 47 deletions(-) diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index c45c8ccba..c1120c1b7 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -1012,19 +1012,31 @@ export type ProviderConfigWireApi = /** OpenAI Responses API wire format. */ | "responses"; /** - * Wire protocol the caller must speak to `baseUrl`. Tells the caller which LLM client library to instantiate. + * Provider family. Matches the `type` field of a BYOK provider config. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ProviderWireProtocol". + * via the `definition` "ProviderEndpointType". */ /** @experimental */ -export type ProviderWireProtocol = - /** OpenAI Chat Completions wire format (`/chat/completions`). Use the `openai` client library. */ - | "openai-completions" - /** OpenAI Responses wire format (`/responses`). Use the `openai` client library. */ - | "openai-responses" - /** Anthropic Messages wire format (`/v1/messages`). Use the `@anthropic-ai/sdk` client library. */ +export type ProviderEndpointType = + /** OpenAI-compatible endpoint (use the OpenAI client library). */ + | "openai" + /** Azure OpenAI endpoint (use the OpenAI client library with the Azure base URL). */ + | "azure" + /** Anthropic endpoint (use the Anthropic client library). */ | "anthropic"; +/** + * Wire API to be used, when required for the provider type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ProviderEndpointWireApi". + */ +/** @experimental */ +export type ProviderEndpointWireApi = + /** Classic chat-completions request shape. */ + | "completions" + /** Newer responses request shape. */ + | "responses"; /** * Schema for the `PushAttachment` type. * @@ -2854,6 +2866,10 @@ export interface SlashCommandInfo { * Whether the command is experimental */ experimental?: boolean; + /** + * Whether the command may be the target of `/every` / `/after` schedules. Resolution happens at every tick, so only set this when the command is safe to re-invoke and produces an agent prompt. + */ + schedulable?: boolean; } /** * Optional unstructured input hint @@ -5397,6 +5413,19 @@ export interface McpUnregisterExternalClientRequest { */ serverName: string; } +/** + * Memory configuration for this session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "MemoryConfiguration". + */ +/** @experimental */ +export interface MemoryConfiguration { + /** + * Whether memory is enabled for the session. + */ + enabled: boolean; +} /** * Model identifier and token limits used to compute the context-info breakdown. * @@ -7824,24 +7853,25 @@ export interface ProviderConfigAzure { apiVersion?: string; } /** - * A snapshot of the provider endpoint the session is currently configured to talk to, with enough information for an external caller to make inference calls directly against the same backend using the OpenAI or Anthropic client libraries. + * A snapshot of the provider endpoint the session is currently configured to talk to. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "ProviderEndpoint". */ /** @experimental */ export interface ProviderEndpoint { - protocol: ProviderWireProtocol; + type: ProviderEndpointType; + wireApi?: ProviderEndpointWireApi; /** - * Base URL the caller should pass to the LLM client library (e.g. `new OpenAI({ baseURL })` or `new Anthropic({ baseURL })`). + * Base URL to pass to the LLM client library. */ baseUrl: string; /** - * Credential for the LLM client constructor (e.g. `new OpenAI({ apiKey })` or `new Anthropic({ apiKey })`). The OpenAI / Anthropic client libraries turn this into the appropriate auth header (typically `Authorization: Bearer …`). Omitted only when the endpoint accepts unauthenticated requests (e.g. a local model server). + * Long-lived credential to pass to the LLM client. Omitted only when the endpoint accepts unauthenticated requests. */ apiKey?: string; /** - * Static HTTP headers the caller must include on every outbound request. Does NOT include the `Authorization` header (the LLM client library adds that from `apiKey`) and does NOT include the `sessionToken` header (sent separately). + * HTTP headers the caller must include on every outbound request. Does NOT include the `Authorization` header (the LLM client library adds that from `apiKey`) and does NOT include the `sessionToken` header (sent separately). */ headers: { [k: string]: string | undefined; @@ -7869,20 +7899,20 @@ export interface ProviderSessionToken { */ model?: string; /** - * When the token expires. Callers should refresh by calling `get` again before this time, or reactively on any 401/403 response from `baseUrl`. + * When the token expires, if known. Callers should refresh by calling `getEndpoint` again before this time, or reactively on any 401/403 response from `baseUrl`. */ - expiresAt: string; + expiresAt?: string; } /** * Optional model identifier to scope the endpoint snapshot to. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ProviderEndpointGetRequest". + * via the `definition` "ProviderGetEndpointRequest". */ /** @experimental */ -export interface ProviderEndpointGetRequest { +export interface ProviderGetEndpointRequest { /** - * Model identifier the caller intends to use against the returned endpoint. Used to pick the wire protocol (Anthropic Messages vs. OpenAI Responses vs. OpenAI Chat Completions) and to scope any returned `sessionToken` to that model. When omitted, the session's currently active model is used. Ignored when the session uses a custom provider that doesn't vary by model. + * Model identifier the caller intends to use against the returned endpoint. Used to pick the correct wire shape. Omit to use whichever model the session is currently using — that path also surfaces an auto-mode `sessionToken` when applicable, preserving auto-mode billing. When `modelId` is supplied, the response never includes a `sessionToken` and the caller must authorize requests with `apiKey` alone. */ modelId?: string; } @@ -9813,6 +9843,7 @@ export interface SessionOpenOptions { * @experimental */ additionalContentExclusionPolicies?: SessionOpenOptionsAdditionalContentExclusionPolicy[]; + memory?: MemoryConfiguration; /** * Capabilities enabled for this session. */ @@ -13988,16 +14019,16 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.plugins.reload", { sessionId, ...params }), }, /** @experimental */ - providerEndpoint: { + provider: { /** - * Returns the provider endpoint and credentials the session is currently configured to talk to, so the caller can make inference calls directly against the same backend the session uses. May throw for sessions whose authentication scheme is not yet supported. + * Returns the provider endpoint and credentials the session is currently configured to talk to, so the caller can make inference calls directly against the same backend the session uses. * * @param params Optional model identifier to scope the endpoint snapshot to. * - * @returns A snapshot of the provider endpoint the session is currently configured to talk to, with enough information for an external caller to make inference calls directly against the same backend using the OpenAI or Anthropic client libraries. + * @returns A snapshot of the provider endpoint the session is currently configured to talk to. */ - get: async (params?: ProviderEndpointGetRequest): Promise => - connection.sendRequest("session.providerEndpoint.get", { sessionId, ...params }), + getEndpoint: async (params?: ProviderGetEndpointRequest): Promise => + connection.sendRequest("session.provider.getEndpoint", { sessionId, ...params }), }, /** @experimental */ options: { diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts index a4fba8f33..e219371d3 100644 --- a/nodejs/src/generated/session-events.ts +++ b/nodejs/src/generated/session-events.ts @@ -2653,18 +2653,6 @@ export interface AssistantMessageEvent { * Assistant response containing text content, optional tool requests, and interaction metadata */ export interface AssistantMessageData { - /** - * Raw Anthropic content array with advisor blocks (server_tool_use, advisor_tool_result) for verbatim round-tripping - * - * @experimental - */ - anthropicAdvisorBlocks?: unknown[]; - /** - * Anthropic advisor model ID used for this response, for timeline display on replay - * - * @experimental - */ - anthropicAdvisorModel?: string; /** * Provider's completion / response identifier; shared across all chunks of a single API call. Used to group multi-chunk assistant utterances. */ @@ -2714,6 +2702,7 @@ export interface AssistantMessageData { * GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs */ requestId?: string; + serverTools?: AssistantMessageServerTools; /** * Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation */ @@ -2727,6 +2716,19 @@ export interface AssistantMessageData { */ turnId?: string; } +/** + * Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping + */ +/** @experimental */ +export interface AssistantMessageServerTools { + advisorModel?: string; + functionCallNamespaces?: { + [k: string]: string | undefined; + }; + items?: unknown[]; + provider: string; + rawContentBlocks?: unknown[]; +} /** * A tool invocation request from the assistant */ @@ -3862,7 +3864,7 @@ export interface SkillInvokedData { */ pluginVersion?: string; /** - * Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), personal-claude (~/.claude/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill) + * Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill) */ source?: string; trigger?: SkillInvokedTrigger; diff --git a/nodejs/test/e2e/provider_endpoint.e2e.test.ts b/nodejs/test/e2e/provider_endpoint.e2e.test.ts index b21124c83..ee74117d4 100644 --- a/nodejs/test/e2e/provider_endpoint.e2e.test.ts +++ b/nodejs/test/e2e/provider_endpoint.e2e.test.ts @@ -6,7 +6,7 @@ import { describe, expect, it } from "vitest"; import { approveAll } from "../../src/index.js"; import { createSdkTestContext } from "./harness/sdkTestContext.js"; -describe("session.providerEndpoint.get RPC", async () => { +describe("session.provider.getEndpoint RPC", async () => { const { copilotClient: client } = await createSdkTestContext(); it("returns the BYOK provider endpoint when a custom provider is configured", async () => { @@ -22,9 +22,10 @@ describe("session.providerEndpoint.get RPC", async () => { }); try { - const endpoint = await session.rpc.providerEndpoint.get({}); + const endpoint = await session.rpc.provider.getEndpoint({}); - expect(endpoint.protocol).toBe("openai-completions"); + expect(endpoint.type).toBe("openai"); + expect(endpoint.wireApi).toBe("completions"); expect(endpoint.baseUrl).toBe("https://api.example.test/v1"); expect(endpoint.apiKey).toBe("byok-secret"); expect(endpoint.headers).toMatchObject({ "X-Custom-Header": "byok-yes" }); @@ -48,11 +49,13 @@ describe("session.providerEndpoint.get RPC", async () => { }); try { - const endpoint = await session.rpc.providerEndpoint.get({}); + const endpoint = await session.rpc.provider.getEndpoint({}); - // Wire protocol defaults to openai-completions when no model picks - // an alternative endpoint set. - expect(["openai-completions", "openai-responses", "anthropic"]).toContain(endpoint.protocol); + expect(["openai", "azure", "anthropic"]).toContain(endpoint.type); + // wireApi is omitted for anthropic; otherwise one of the OpenAI shapes. + if (endpoint.type !== "anthropic") { + expect(["completions", "responses"]).toContain(endpoint.wireApi); + } // CAPI baseUrl is the (proxy) Copilot API URL injected by the harness. expect(endpoint.baseUrl).toMatch(/^https?:\/\//); @@ -71,13 +74,16 @@ describe("session.providerEndpoint.get RPC", async () => { expect(endpoint.headers).not.toHaveProperty("Authorization"); expect(endpoint.headers).not.toHaveProperty("Copilot-Session-Token"); - // If a session token came back, it must use the documented header - // name and an ISO 8601 expiry. The harness proxy may decline to - // issue one — in that case the field is simply omitted. + // When the omit-modelId path returned an auto-mode session token, it + // must use the documented header name and an ISO 8601 expiry. The + // harness may have a non-auto model selected, in which case the + // field is simply omitted. if (endpoint.sessionToken) { expect(endpoint.sessionToken.header).toBe("Copilot-Session-Token"); expect(endpoint.sessionToken.token.length).toBeGreaterThan(0); - expect(Date.parse(endpoint.sessionToken.expiresAt)).not.toBeNaN(); + if (endpoint.sessionToken.expiresAt !== undefined) { + expect(Date.parse(endpoint.sessionToken.expiresAt)).not.toBeNaN(); + } } } finally { await session.disconnect(); From 75321558461ae9c453a1f6fdb52029921d3dde1e Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 11 Jun 2026 12:24:19 +0100 Subject: [PATCH 03/10] Pass COPILOT_ALLOW_GET_PROVIDER_ENDPOINT through the harness env The API is gated by env var, so set it on the harness env object (which is the same one passed to the CLI subprocess) instead of requiring callers to export it in their own environment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- nodejs/test/e2e/provider_endpoint.e2e.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nodejs/test/e2e/provider_endpoint.e2e.test.ts b/nodejs/test/e2e/provider_endpoint.e2e.test.ts index ee74117d4..e31984793 100644 --- a/nodejs/test/e2e/provider_endpoint.e2e.test.ts +++ b/nodejs/test/e2e/provider_endpoint.e2e.test.ts @@ -7,7 +7,12 @@ import { approveAll } from "../../src/index.js"; import { createSdkTestContext } from "./harness/sdkTestContext.js"; describe("session.provider.getEndpoint RPC", async () => { - const { copilotClient: client } = await createSdkTestContext(); + const { copilotClient: client, env } = await createSdkTestContext(); + + // The provider endpoint API is gated behind an opt-in env var; the harness + // env object is the same one passed to the CLI subprocess, so mutating it + // here enables the API for this test file's client. + env.COPILOT_ALLOW_GET_PROVIDER_ENDPOINT = "true"; it("returns the BYOK provider endpoint when a custom provider is configured", async () => { const session = await client.createSession({ From 9aaed3f608cb02fc580f56b1036aaa5203a315b5 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 11 Jun 2026 13:18:42 +0100 Subject: [PATCH 04/10] Update e2e for Authorization pass-through in provider endpoint The runtime now surfaces Authorization in the headers map (consistent with BYOK pass-through) rather than stripping it. Update the e2e to assert the new contract and regen the RPC bindings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- nodejs/src/generated/rpc.ts | 4 ++-- nodejs/test/e2e/provider_endpoint.e2e.test.ts | 11 +++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index c1120c1b7..d71e64134 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -7871,7 +7871,7 @@ export interface ProviderEndpoint { */ apiKey?: string; /** - * HTTP headers the caller must include on every outbound request. Does NOT include the `Authorization` header (the LLM client library adds that from `apiKey`) and does NOT include the `sessionToken` header (sent separately). + * HTTP headers the caller must include on every outbound request. */ headers: { [k: string]: string | undefined; @@ -7912,7 +7912,7 @@ export interface ProviderSessionToken { /** @experimental */ export interface ProviderGetEndpointRequest { /** - * Model identifier the caller intends to use against the returned endpoint. Used to pick the correct wire shape. Omit to use whichever model the session is currently using — that path also surfaces an auto-mode `sessionToken` when applicable, preserving auto-mode billing. When `modelId` is supplied, the response never includes a `sessionToken` and the caller must authorize requests with `apiKey` alone. + * Model identifier the caller intends to use against the returned endpoint. Used to pick the correct wire shape. Omit to use whichever model the session is currently using. */ modelId?: string; } diff --git a/nodejs/test/e2e/provider_endpoint.e2e.test.ts b/nodejs/test/e2e/provider_endpoint.e2e.test.ts index e31984793..1bac76253 100644 --- a/nodejs/test/e2e/provider_endpoint.e2e.test.ts +++ b/nodejs/test/e2e/provider_endpoint.e2e.test.ts @@ -34,9 +34,6 @@ describe("session.provider.getEndpoint RPC", async () => { expect(endpoint.baseUrl).toBe("https://api.example.test/v1"); expect(endpoint.apiKey).toBe("byok-secret"); expect(endpoint.headers).toMatchObject({ "X-Custom-Header": "byok-yes" }); - // Auth and per-request session-token headers should not appear here. - expect(endpoint.headers).not.toHaveProperty("Authorization"); - expect(endpoint.headers).not.toHaveProperty("Copilot-Session-Token"); // BYOK sessions never issue a CAPI session token. expect(endpoint.sessionToken).toBeUndefined(); } finally { @@ -69,15 +66,13 @@ describe("session.provider.getEndpoint RPC", async () => { expect(endpoint.apiKey).toBeTypeOf("string"); expect(endpoint.apiKey!.length).toBeGreaterThan(0); - // Standard CAPI headers should be present, and the Authorization / - // session-token headers must not be in `headers` (they're carried - // by `apiKey` and `sessionToken` respectively). + // Standard CAPI headers should be present, and Authorization is + // surfaced as the runtime sends it (`Bearer `). expect(endpoint.headers["Copilot-Integration-Id"]).toBeTypeOf("string"); expect(endpoint.headers["User-Agent"]).toMatch(/Copilot/i); expect(endpoint.headers["X-GitHub-Api-Version"]).toBeTypeOf("string"); expect(endpoint.headers["X-Interaction-Id"]).toMatch(/[0-9a-f-]{8,}/); - expect(endpoint.headers).not.toHaveProperty("Authorization"); - expect(endpoint.headers).not.toHaveProperty("Copilot-Session-Token"); + expect(endpoint.headers.Authorization).toBe(`Bearer ${endpoint.apiKey}`); // When the omit-modelId path returned an auto-mode session token, it // must use the documented header name and an ISO 8601 expiry. The From ecadd884d8b291536b4bf4e9bcb1988264c67961 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 11 Jun 2026 18:21:07 +0100 Subject: [PATCH 05/10] Regen SDK bindings for trimmed apiKey description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- nodejs/src/generated/rpc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index d71e64134..7cca2fa10 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -7867,7 +7867,7 @@ export interface ProviderEndpoint { */ baseUrl: string; /** - * Long-lived credential to pass to the LLM client. Omitted only when the endpoint accepts unauthenticated requests. + * A credential the caller should use with this endpoint. Omitted only when the endpoint accepts unauthenticated requests. */ apiKey?: string; /** From c21c13582e38ab3af6cd60a454a0fec8a4197718 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 12 Jun 2026 12:01:57 +0100 Subject: [PATCH 06/10] Add C# E2E coverage for session.provider.getEndpoint Mirrors the existing nodejs e2e test pair: - BYOK provider returns the configured endpoint and headers verbatim - CAPI/OAuth session returns the proxied baseUrl, bearer apiKey, required CAPI headers, and (when present) a Copilot-Session-Token Regenerates dotnet bindings (Rpc.cs, SessionEvents.cs) from the runtime schema to pick up ProviderApi/ProviderEndpoint/ProviderSessionToken. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 242 ++++++++++++++++++++ dotnet/src/Generated/SessionEvents.cs | 50 ++-- dotnet/test/E2E/ProviderEndpointE2ETests.cs | 117 ++++++++++ 3 files changed, 396 insertions(+), 13 deletions(-) create mode 100644 dotnet/test/E2E/ProviderEndpointE2ETests.cs diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 4b6cdab93..7738a3395 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -5607,6 +5607,80 @@ internal sealed class PluginsReloadRequestWithSession public string SessionId { get; set; } = string.Empty; } +/// Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. +[Experimental(Diagnostics.Experimental)] +public sealed class ProviderSessionToken +{ + /// When the token expires, if known. Callers should refresh by calling `getEndpoint` again before this time, or reactively on any 401/403 response from `baseUrl`. + [JsonPropertyName("expiresAt")] + public DateTimeOffset? ExpiresAt { get; set; } + + /// HTTP header name the token must be sent under. + [JsonPropertyName("header")] + public string Header { get; set; } = string.Empty; + + /// The model the token is bound to, when applicable. When set, the token is only valid for requests against this model. + [JsonPropertyName("model")] + public string? Model { get; set; } + + /// The short-lived token value. + [JsonPropertyName("token")] + public string Token { get; set; } = string.Empty; +} + +/// A snapshot of the provider endpoint the session is currently configured to talk to. +[Experimental(Diagnostics.Experimental)] +public sealed class ProviderEndpoint +{ + /// A credential the caller should use with this endpoint. Omitted only when the endpoint accepts unauthenticated requests. + [JsonPropertyName("apiKey")] + public string? ApiKey { get; set; } + + /// Base URL to pass to the LLM client library. + [Url] + [StringSyntax(StringSyntaxAttribute.Uri)] + [JsonPropertyName("baseUrl")] + public string BaseUrl { get; set; } = string.Empty; + + /// HTTP headers the caller must include on every outbound request. + [JsonPropertyName("headers")] + public IDictionary Headers { get => field ??= new Dictionary(); set; } + + /// Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. + [JsonPropertyName("sessionToken")] + public ProviderSessionToken? SessionToken { get; set; } + + /// Provider family. Matches the `type` field of a BYOK provider config. + [JsonPropertyName("type")] + public ProviderEndpointType Type { get; set; } + + /// Wire API to be used, when required for the provider type. + [JsonPropertyName("wireApi")] + public ProviderEndpointWireApi? WireApi { get; set; } +} + +/// Optional model identifier to scope the endpoint snapshot to. +[Experimental(Diagnostics.Experimental)] +public sealed class ProviderGetEndpointRequest +{ + /// Model identifier the caller intends to use against the returned endpoint. Used to pick the correct wire shape. Omit to use whichever model the session is currently using. + [JsonPropertyName("modelId")] + public string? ModelId { get; set; } +} + +/// Optional model identifier to scope the endpoint snapshot to. +[Experimental(Diagnostics.Experimental)] +internal sealed class ProviderGetEndpointRequestWithSession +{ + /// Model identifier the caller intends to use against the returned endpoint. Used to pick the correct wire shape. Omit to use whichever model the session is currently using. + [JsonPropertyName("modelId")] + public string? ModelId { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + /// Indicates whether the session options patch was applied successfully. [Experimental(Diagnostics.Experimental)] public sealed class SessionUpdateOptionsResult @@ -6539,6 +6613,10 @@ public sealed class SlashCommandInfo /// Canonical command name without a leading slash. [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; + + /// Whether the command may be the target of `/every` / `/after` schedules. Resolution happens at every tick, so only set this when the command is safe to re-invoke and produces an agent prompt. + [JsonPropertyName("schedulable")] + public bool? Schedulable { get; set; } } /// Slash commands available in the session, after applying any include/exclude filters. @@ -12995,6 +13073,135 @@ public override void Write(Utf8JsonWriter writer, McpAppsHostContextDetailsTheme } +/// Provider family. Matches the `type` field of a BYOK provider config. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ProviderEndpointType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ProviderEndpointType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// OpenAI-compatible endpoint (use the OpenAI client library). + public static ProviderEndpointType Openai { get; } = new("openai"); + + /// Azure OpenAI endpoint (use the OpenAI client library with the Azure base URL). + public static ProviderEndpointType Azure { get; } = new("azure"); + + /// Anthropic endpoint (use the Anthropic client library). + public static ProviderEndpointType Anthropic { get; } = new("anthropic"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ProviderEndpointType left, ProviderEndpointType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ProviderEndpointType left, ProviderEndpointType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ProviderEndpointType other && Equals(other); + + /// + public bool Equals(ProviderEndpointType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ProviderEndpointType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ProviderEndpointType value, JsonSerializerOptions options) + { + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ProviderEndpointType)); + } + } +} + + +/// Wire API to be used, when required for the provider type. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ProviderEndpointWireApi : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ProviderEndpointWireApi(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Classic chat-completions request shape. + public static ProviderEndpointWireApi Completions { get; } = new("completions"); + + /// Newer responses request shape. + public static ProviderEndpointWireApi Responses { get; } = new("responses"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ProviderEndpointWireApi left, ProviderEndpointWireApi right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ProviderEndpointWireApi left, ProviderEndpointWireApi right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ProviderEndpointWireApi other && Equals(other); + + /// + public bool Equals(ProviderEndpointWireApi other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ProviderEndpointWireApi Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ProviderEndpointWireApi value, JsonSerializerOptions options) + { + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ProviderEndpointWireApi)); + } + } +} + + /// Allowed values for the `OptionsUpdateAdditionalContentExclusionPolicyScope` enumeration. [Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] @@ -16279,6 +16486,12 @@ internal SessionRpc(CopilotSession session) Interlocked.CompareExchange(ref field, new(_session), null) ?? field; + /// Provider APIs. + public ProviderApi Provider => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + /// Options APIs. public OptionsApi Options => field ?? @@ -17668,6 +17881,30 @@ public async Task ReloadAsync(PluginsReloadRequest? request = null, Cancellation } } +/// Provides session-scoped Provider APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class ProviderApi +{ + private readonly CopilotSession _session; + + internal ProviderApi(CopilotSession session) + { + _session = session; + } + + /// Returns the provider endpoint and credentials the session is currently configured to talk to, so the caller can make inference calls directly against the same backend the session uses. + /// Optional model identifier to scope the endpoint snapshot to. + /// The to monitor for cancellation requests. The default is . + /// A snapshot of the provider endpoint the session is currently configured to talk to. + public async Task GetEndpointAsync(ProviderGetEndpointRequest? request = null, CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var rpcRequest = new ProviderGetEndpointRequestWithSession { SessionId = _session.SessionId, ModelId = request?.ModelId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.provider.getEndpoint", [rpcRequest], cancellationToken); + } +} + /// Provides session-scoped Options APIs. [Experimental(Diagnostics.Experimental)] public sealed class OptionsApi @@ -19176,6 +19413,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, FuncAssistant response containing text content, optional tool requests, and interaction metadata. public sealed partial class AssistantMessageData { - /// Raw Anthropic content array with advisor blocks (server_tool_use, advisor_tool_result) for verbatim round-tripping. - [Experimental(Diagnostics.Experimental)] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("anthropicAdvisorBlocks")] - public JsonElement[]? AnthropicAdvisorBlocks { get; set; } - - /// Anthropic advisor model ID used for this response, for timeline display on replay. - [Experimental(Diagnostics.Experimental)] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("anthropicAdvisorModel")] - public string? AnthropicAdvisorModel { get; set; } - /// Provider's completion / response identifier; shared across all chunks of a single API call. Used to group multi-chunk assistant utterances. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("apiCallId")] @@ -2253,6 +2241,11 @@ public sealed partial class AssistantMessageData [JsonPropertyName("requestId")] public string? RequestId { get; set; } + /// Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("serverTools")] + public AssistantMessageServerTools? ServerTools { get; set; } + /// Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("serviceRequestId")] @@ -2661,7 +2654,7 @@ public sealed partial class SkillInvokedData [JsonPropertyName("pluginVersion")] public string? PluginVersion { get; set; } - /// Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), personal-claude (~/.claude/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill). + /// Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("source")] public string? Source { get; set; } @@ -3953,6 +3946,36 @@ public partial class Attachment } +/// Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping. +/// Nested data type for AssistantMessageServerTools. +[Experimental(Diagnostics.Experimental)] +public sealed partial class AssistantMessageServerTools +{ + /// Gets or sets the advisorModel value. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("advisorModel")] + public string? AdvisorModel { get; set; } + + /// Gets or sets the functionCallNamespaces value. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("functionCallNamespaces")] + public IDictionary? FunctionCallNamespaces { get; set; } + + /// Gets or sets the items value. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("items")] + public JsonElement[]? Items { get; set; } + + /// Gets or sets the provider value. + [JsonPropertyName("provider")] + public required string Provider { get; set; } + + /// Gets or sets the rawContentBlocks value. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("rawContentBlocks")] + public JsonElement[]? RawContentBlocks { get; set; } +} + /// A tool invocation request from the assistant. /// Nested data type for AssistantMessageToolRequest. public sealed partial class AssistantMessageToolRequest @@ -8283,6 +8306,7 @@ public override void Write(Utf8JsonWriter writer, CanvasOpenedAvailability value [JsonSerializable(typeof(AssistantMessageDeltaData))] [JsonSerializable(typeof(AssistantMessageDeltaEvent))] [JsonSerializable(typeof(AssistantMessageEvent))] +[JsonSerializable(typeof(AssistantMessageServerTools))] [JsonSerializable(typeof(AssistantMessageStartData))] [JsonSerializable(typeof(AssistantMessageStartEvent))] [JsonSerializable(typeof(AssistantMessageToolRequest))] diff --git a/dotnet/test/E2E/ProviderEndpointE2ETests.cs b/dotnet/test/E2E/ProviderEndpointE2ETests.cs new file mode 100644 index 000000000..d11e85303 --- /dev/null +++ b/dotnet/test/E2E/ProviderEndpointE2ETests.cs @@ -0,0 +1,117 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; +using System.Text.RegularExpressions; +using Xunit; +using Xunit.Abstractions; + +namespace GitHub.Copilot.Test.E2E; + +public class ProviderEndpointE2ETests(E2ETestFixture fixture, ITestOutputHelper output) + : E2ETestBase(fixture, "provider-endpoint", output) +{ + /// + /// Creates a client with the provider-endpoint API opt-in env var set. The + /// runtime gates `session.provider.getEndpoint` behind + /// COPILOT_ALLOW_GET_PROVIDER_ENDPOINT so callers don't depend on it + /// accidentally while the API is still experimental. + /// + private CopilotClient CreateProviderEndpointClient() + { + var env = new Dictionary(Ctx.GetEnvironment()) + { + ["COPILOT_ALLOW_GET_PROVIDER_ENDPOINT"] = "true", + }; + return Ctx.CreateClient(options: new CopilotClientOptions { Environment = env }); + } + + [Fact] + public async Task ShouldReturnByokProviderEndpointWhenCustomProviderIsConfigured() + { + var client = CreateProviderEndpointClient(); + + var session = await client.CreateSessionAsync(new SessionConfig + { + OnPermissionRequest = PermissionHandler.ApproveAll, + Provider = new ProviderConfig + { + Type = "openai", + WireApi = "completions", + BaseUrl = "https://api.example.test/v1", + ApiKey = "byok-secret", + Headers = new Dictionary { ["X-Custom-Header"] = "byok-yes" }, + }, + }); + + try + { + var endpoint = await session.Rpc.Provider.GetEndpointAsync(); + + Assert.Equal(ProviderEndpointType.Openai, endpoint.Type); + Assert.Equal(ProviderEndpointWireApi.Completions, endpoint.WireApi); + Assert.Equal("https://api.example.test/v1", endpoint.BaseUrl); + Assert.Equal("byok-secret", endpoint.ApiKey); + Assert.Equal("byok-yes", endpoint.Headers["X-Custom-Header"]); + // BYOK sessions never issue a CAPI session token. + Assert.Null(endpoint.SessionToken); + } + finally + { + try { await session.DisposeAsync(); } + catch { /* disconnect may fail since the BYOK provider URL is fake */ } + } + } + + [Fact] + public async Task ShouldReturnCapiProviderEndpointForOAuthAuthenticatedSession() + { + var client = CreateProviderEndpointClient(); + + await using var session = await client.CreateSessionAsync(new SessionConfig + { + OnPermissionRequest = PermissionHandler.ApproveAll, + }); + + var endpoint = await session.Rpc.Provider.GetEndpointAsync(); + + Assert.True( + endpoint.Type == ProviderEndpointType.Openai + || endpoint.Type == ProviderEndpointType.Azure + || endpoint.Type == ProviderEndpointType.Anthropic, + $"unexpected endpoint.Type {endpoint.Type}"); + // wireApi is omitted for anthropic; otherwise one of the OpenAI shapes. + if (endpoint.Type != ProviderEndpointType.Anthropic) + { + Assert.True( + endpoint.WireApi == ProviderEndpointWireApi.Completions + || endpoint.WireApi == ProviderEndpointWireApi.Responses, + $"unexpected endpoint.WireApi {endpoint.WireApi}"); + } + + // CAPI baseUrl is the (proxy) Copilot API URL injected by the harness. + Assert.Matches(@"^https?://", endpoint.BaseUrl); + + // For CAPI OAuth sessions the apiKey is the resolved GitHub bearer. + Assert.False(string.IsNullOrEmpty(endpoint.ApiKey)); + + // Standard CAPI headers should be present, and Authorization is + // surfaced as the runtime sends it (`Bearer `). + Assert.False(string.IsNullOrEmpty(endpoint.Headers["Copilot-Integration-Id"])); + Assert.Matches(new Regex("Copilot", RegexOptions.IgnoreCase), endpoint.Headers["User-Agent"]); + Assert.False(string.IsNullOrEmpty(endpoint.Headers["X-GitHub-Api-Version"])); + Assert.Matches(@"[0-9a-f-]{8,}", endpoint.Headers["X-Interaction-Id"]); + Assert.Equal($"Bearer {endpoint.ApiKey}", endpoint.Headers["Authorization"]); + + // When the omit-modelId path returned an auto-mode session token, it + // must use the documented header name. The harness may have a non-auto + // model selected, in which case the field is simply omitted. + if (endpoint.SessionToken != null) + { + Assert.Equal("Copilot-Session-Token", endpoint.SessionToken.Header); + Assert.False(string.IsNullOrEmpty(endpoint.SessionToken.Token)); + } + } +} From b55455371a49e64ba45e241dc5d8a87f4da5f4e4 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 12 Jun 2026 12:22:08 +0100 Subject: [PATCH 07/10] Regen Go/Python/Rust bindings for session.provider.getEndpoint Picks up the new ProviderEndpoint type and session.provider.getEndpoint RPC from the runtime schema. Generated by scripts/codegen/{go,python,rust}.ts against the runtime worktree exposing the API. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/zrpc.go | 123 +++++++++++ go/rpc/zrpc_encoding.go | 2 + go/rpc/zsession_events.go | 20 +- go/zsession_events.go | 1 + python/copilot/generated/rpc.py | 234 +++++++++++++++++++-- python/copilot/generated/session_events.py | 58 +++-- rust/src/generated/api_types.rs | 165 +++++++++++++++ rust/src/generated/rpc.rs | 73 +++++++ rust/src/generated/session_events.rs | 47 +++-- rust/src/types.rs | 2 + 10 files changed, 665 insertions(+), 60 deletions(-) diff --git a/go/rpc/zrpc.go b/go/rpc/zrpc.go index b1d9df103..24f6507aa 100644 --- a/go/rpc/zrpc.go +++ b/go/rpc/zrpc.go @@ -2715,6 +2715,14 @@ type MCPUnregisterExternalClientRequest struct { ServerName string `json:"serverName"` } +// Memory configuration for this session. +// Experimental: MemoryConfiguration is part of an experimental API and may change or be +// removed. +type MemoryConfiguration struct { + // Whether memory is enabled for the session. + Enabled bool `json:"enabled"` +} + // Model identifier and token limits used to compute the context-info breakdown. // Experimental: MetadataContextInfoRequest is part of an experimental API and may change or // be removed. @@ -4552,6 +4560,52 @@ type ProviderConfigAzure struct { APIVersion *string `json:"apiVersion,omitempty"` } +// A snapshot of the provider endpoint the session is currently configured to talk to. +// Experimental: ProviderEndpoint is part of an experimental API and may change or be +// removed. +type ProviderEndpoint struct { + // A credential the caller should use with this endpoint. Omitted only when the endpoint + // accepts unauthenticated requests. + APIKey *string `json:"apiKey,omitempty"` + // Base URL to pass to the LLM client library. + BaseURL string `json:"baseUrl"` + // HTTP headers the caller must include on every outbound request. + Headers map[string]string `json:"headers"` + // Short-lived, rotating credential the caller must send on every request, in addition to + // `apiKey` if one is present. Omitted when the endpoint does not require one. + SessionToken *ProviderSessionToken `json:"sessionToken,omitempty"` + // Provider family. Matches the `type` field of a BYOK provider config. + Type ProviderEndpointType `json:"type"` + // Wire API to be used, when required for the provider type. + WireAPI *ProviderEndpointWireAPI `json:"wireApi,omitempty"` +} + +// Optional model identifier to scope the endpoint snapshot to. +// Experimental: ProviderGetEndpointRequest is part of an experimental API and may change or +// be removed. +type ProviderGetEndpointRequest struct { + // Model identifier the caller intends to use against the returned endpoint. Used to pick + // the correct wire shape. Omit to use whichever model the session is currently using. + ModelID *string `json:"modelId,omitempty"` +} + +// Short-lived, rotating credential the caller must send on every request, in addition to +// `apiKey` if one is present. Omitted when the endpoint does not require one. +// Experimental: ProviderSessionToken is part of an experimental API and may change or be +// removed. +type ProviderSessionToken struct { + // When the token expires, if known. Callers should refresh by calling `getEndpoint` again + // before this time, or reactively on any 401/403 response from `baseUrl`. + ExpiresAt *time.Time `json:"expiresAt,omitempty"` + // HTTP header name the token must be sent under. + Header string `json:"header"` + // The model the token is bound to, when applicable. When set, the token is only valid for + // requests against this model. + Model *string `json:"model,omitempty"` + // The short-lived token value. + Token string `json:"token"` +} + // Schema for the `PushAttachment` type. // Experimental: PushAttachment is part of an experimental API and may change or be removed. type PushAttachment interface { @@ -6020,6 +6074,8 @@ type SessionOpenOptions struct { LogInteractiveShells *bool `json:"logInteractiveShells,omitempty"` // Identifier sent to LSP-style integrations. LspClientName *string `json:"lspClientName,omitempty"` + // Memory configuration for this session. + Memory *MemoryConfiguration `json:"memory,omitempty"` // Initial model identifier. Model *string `json:"model,omitempty"` // Initial model capability overrides. @@ -7086,6 +7142,10 @@ type SlashCommandInfo struct { Kind SlashCommandKind `json:"kind"` // Canonical command name without a leading slash Name string `json:"name"` + // Whether the command may be the target of `/every` / `/after` schedules. Resolution + // happens at every tick, so only set this when the command is safe to re-invoke and + // produces an agent prompt. + Schedulable *bool `json:"schedulable,omitempty"` } // Optional unstructured input hint @@ -9377,6 +9437,32 @@ const ( ProviderConfigWireAPIResponses ProviderConfigWireAPI = "responses" ) +// Provider family. Matches the `type` field of a BYOK provider config. +// Experimental: ProviderEndpointType is part of an experimental API and may change or be +// removed. +type ProviderEndpointType string + +const ( + // Anthropic endpoint (use the Anthropic client library). + ProviderEndpointTypeAnthropic ProviderEndpointType = "anthropic" + // Azure OpenAI endpoint (use the OpenAI client library with the Azure base URL). + ProviderEndpointTypeAzure ProviderEndpointType = "azure" + // OpenAI-compatible endpoint (use the OpenAI client library). + ProviderEndpointTypeOpenai ProviderEndpointType = "openai" +) + +// Wire API to be used, when required for the provider type. +// Experimental: ProviderEndpointWireAPI is part of an experimental API and may change or be +// removed. +type ProviderEndpointWireAPI string + +const ( + // Classic chat-completions request shape. + ProviderEndpointWireAPICompletions ProviderEndpointWireAPI = "completions" + // Newer responses request shape. + ProviderEndpointWireAPIResponses ProviderEndpointWireAPI = "responses" +) + // Type of GitHub reference // Experimental: PushAttachmentGitHubReferenceType is part of an experimental API and may // change or be removed. @@ -14020,6 +14106,41 @@ func (a *PluginsAPI) Reload(ctx context.Context, params ...*PluginsReloadRequest return &result, nil } +// Experimental: ProviderAPI contains experimental APIs that may change or be removed. +type ProviderAPI sessionAPI + +// GetEndpoint returns the provider endpoint and credentials the session is currently +// configured to talk to, so the caller can make inference calls directly against the same +// backend the session uses. +// +// RPC method: session.provider.getEndpoint. +// +// Parameters: Optional model identifier to scope the endpoint snapshot to. +// +// Returns: A snapshot of the provider endpoint the session is currently configured to talk +// to. +func (a *ProviderAPI) GetEndpoint(ctx context.Context, params ...*ProviderGetEndpointRequest) (*ProviderEndpoint, error) { + var requestParams *ProviderGetEndpointRequest + if len(params) > 0 { + requestParams = params[0] + } + req := map[string]any{"sessionId": a.sessionID} + if requestParams != nil { + if requestParams.ModelID != nil { + req["modelId"] = *requestParams.ModelID + } + } + raw, err := a.client.Request("session.provider.getEndpoint", req) + if err != nil { + return nil, err + } + var result ProviderEndpoint + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // Experimental: QueueAPI contains experimental APIs that may change or be removed. type QueueAPI sessionAPI @@ -15251,6 +15372,7 @@ type SessionRPC struct { Permissions *PermissionsAPI Plan *PlanAPI Plugins *PluginsAPI + Provider *ProviderAPI Queue *QueueAPI Remote *RemoteAPI Schedule *ScheduleAPI @@ -15461,6 +15583,7 @@ func NewSessionRPC(client *jsonrpc2.Client, sessionID string) *SessionRPC { r.Permissions = (*PermissionsAPI)(&r.common) r.Plan = (*PlanAPI)(&r.common) r.Plugins = (*PluginsAPI)(&r.common) + r.Provider = (*ProviderAPI)(&r.common) r.Queue = (*QueueAPI)(&r.common) r.Remote = (*RemoteAPI)(&r.common) r.Schedule = (*ScheduleAPI)(&r.common) diff --git a/go/rpc/zrpc_encoding.go b/go/rpc/zrpc_encoding.go index bf455dc7e..82a0ca1d0 100644 --- a/go/rpc/zrpc_encoding.go +++ b/go/rpc/zrpc_encoding.go @@ -2700,6 +2700,7 @@ func (r *SessionOpenOptions) UnmarshalJSON(data []byte) error { IsExperimentalMode *bool `json:"isExperimentalMode,omitempty"` LogInteractiveShells *bool `json:"logInteractiveShells,omitempty"` LspClientName *string `json:"lspClientName,omitempty"` + Memory *MemoryConfiguration `json:"memory,omitempty"` Model *string `json:"model,omitempty"` ModelCapabilitiesOverrides *ModelCapabilitiesOverride `json:"modelCapabilitiesOverrides,omitempty"` Name *string `json:"name,omitempty"` @@ -2759,6 +2760,7 @@ func (r *SessionOpenOptions) UnmarshalJSON(data []byte) error { r.IsExperimentalMode = raw.IsExperimentalMode r.LogInteractiveShells = raw.LogInteractiveShells r.LspClientName = raw.LspClientName + r.Memory = raw.Memory r.Model = raw.Model r.ModelCapabilitiesOverrides = raw.ModelCapabilitiesOverrides r.Name = raw.Name diff --git a/go/rpc/zsession_events.go b/go/rpc/zsession_events.go index 98d008256..14d6c983f 100644 --- a/go/rpc/zsession_events.go +++ b/go/rpc/zsession_events.go @@ -177,12 +177,6 @@ func (*AssistantReasoningData) Type() SessionEventType { return SessionEventType // Assistant response containing text content, optional tool requests, and interaction metadata type AssistantMessageData struct { - // Raw Anthropic content array with advisor blocks (server_tool_use, advisor_tool_result) for verbatim round-tripping - // Experimental: AnthropicAdvisorBlocks is part of an experimental API and may change or be removed. - AnthropicAdvisorBlocks []any `json:"anthropicAdvisorBlocks,omitzero"` - // Anthropic advisor model ID used for this response, for timeline display on replay - // Experimental: AnthropicAdvisorModel is part of an experimental API and may change or be removed. - AnthropicAdvisorModel *string `json:"anthropicAdvisorModel,omitempty"` // Provider's completion / response identifier; shared across all chunks of a single API call. Used to group multi-chunk assistant utterances. APICallID *string `json:"apiCallId,omitempty"` // The assistant's text response content @@ -208,6 +202,8 @@ type AssistantMessageData struct { ReasoningText *string `json:"reasoningText,omitempty"` // GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs RequestID *string `json:"requestId,omitempty"` + // Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping + ServerTools *AssistantMessageServerTools `json:"serverTools,omitempty"` // Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation ServiceRequestID *string `json:"serviceRequestId,omitempty"` // Tool invocations requested by the assistant in this message @@ -1258,7 +1254,7 @@ type SkillInvokedData struct { PluginName *string `json:"pluginName,omitempty"` // Version of the plugin this skill originated from, when applicable PluginVersion *string `json:"pluginVersion,omitempty"` - // Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), personal-claude (~/.claude/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill) + // Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill) Source *string `json:"source,omitempty"` // What triggered the skill invocation: `user-invoked` (explicit user action, such as via a slash command or UI affordance), `agent-invoked` (agent requested the skill), or `context-load` (loaded as part of another context, such as preloading skills configured on a custom agent or subagent) Trigger *SkillInvokedTrigger `json:"trigger,omitempty"` @@ -1627,6 +1623,16 @@ func (*SessionWorkspaceFileChangedData) Type() SessionEventType { return SessionEventTypeSessionWorkspaceFileChanged } +// Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping +// Experimental: AssistantMessageServerTools is part of an experimental API and may change or be removed. +type AssistantMessageServerTools struct { + AdvisorModel *string `json:"advisorModel,omitempty"` + FunctionCallNamespaces map[string]string `json:"functionCallNamespaces,omitzero"` + Items []any `json:"items,omitzero"` + Provider string `json:"provider"` + RawContentBlocks []any `json:"rawContentBlocks,omitzero"` +} + // A tool invocation request from the assistant type AssistantMessageToolRequest struct { // Arguments to pass to the tool, format depends on the tool diff --git a/go/zsession_events.go b/go/zsession_events.go index 5a8962efd..936193cf6 100644 --- a/go/zsession_events.go +++ b/go/zsession_events.go @@ -12,6 +12,7 @@ type ( AssistantIntentData = rpc.AssistantIntentData AssistantMessageData = rpc.AssistantMessageData AssistantMessageDeltaData = rpc.AssistantMessageDeltaData + AssistantMessageServerTools = rpc.AssistantMessageServerTools AssistantMessageStartData = rpc.AssistantMessageStartData AssistantMessageToolRequest = rpc.AssistantMessageToolRequest AssistantMessageToolRequestType = rpc.AssistantMessageToolRequestType diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index 69bf16007..be0584223 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -2809,6 +2809,25 @@ def to_dict(self) -> dict: result["serverName"] = from_str(self.server_name) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MemoryConfiguration: + """Memory configuration for this session.""" + + enabled: bool + """Whether memory is enabled for the session.""" + + @staticmethod + def from_dict(obj: Any) -> 'MemoryConfiguration': + assert isinstance(obj, dict) + enabled = from_bool(obj.get("enabled")) + return MemoryConfiguration(enabled) + + def to_dict(self) -> dict: + result: dict = {} + result["enabled"] = from_bool(self.enabled) + return result + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionContextInfo: @@ -4594,20 +4613,64 @@ def to_dict(self) -> dict: return result # Experimental: this type is part of an experimental API and may change or be removed. -class ProviderConfigType(Enum): - """Provider type. Defaults to "openai" for generic OpenAI-compatible APIs.""" +class ProviderType(Enum): + """Provider type. Defaults to "openai" for generic OpenAI-compatible APIs. + Provider family. Matches the `type` field of a BYOK provider config. + """ ANTHROPIC = "anthropic" AZURE = "azure" OPENAI = "openai" # Experimental: this type is part of an experimental API and may change or be removed. -class ProviderConfigWireAPI(Enum): - """Wire API format (openai/azure only). Defaults to "completions".""" +class ProviderWireAPI(Enum): + """Wire API format (openai/azure only). Defaults to "completions". + Wire API to be used, when required for the provider type. + """ COMPLETIONS = "completions" RESPONSES = "responses" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class ProviderSessionToken: + """Short-lived, rotating credential the caller must send on every request, in addition to + `apiKey` if one is present. Omitted when the endpoint does not require one. + """ + header: str + """HTTP header name the token must be sent under.""" + + token: str + """The short-lived token value.""" + + expires_at: datetime | None = None + """When the token expires, if known. Callers should refresh by calling `getEndpoint` again + before this time, or reactively on any 401/403 response from `baseUrl`. + """ + model: str | None = None + """The model the token is bound to, when applicable. When set, the token is only valid for + requests against this model. + """ + + @staticmethod + def from_dict(obj: Any) -> 'ProviderSessionToken': + assert isinstance(obj, dict) + header = from_str(obj.get("header")) + token = from_str(obj.get("token")) + expires_at = from_union([from_datetime, from_none], obj.get("expiresAt")) + model = from_union([from_str, from_none], obj.get("model")) + return ProviderSessionToken(header, token, expires_at, model) + + def to_dict(self) -> dict: + result: dict = {} + result["header"] = from_str(self.header) + result["token"] = from_str(self.token) + if self.expires_at is not None: + result["expiresAt"] = from_union([lambda x: x.isoformat(), from_none], self.expires_at) + if self.model is not None: + result["model"] = from_union([from_str, from_none], self.model) + return result + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class PushAttachmentFileLineRange: @@ -12226,10 +12289,10 @@ class ProviderConfig: """Well-known model ID used for capability lookup. When set, agent behavior config and token limits are inferred from this model. """ - type: ProviderConfigType | None = None + type: ProviderType | None = None """Provider type. Defaults to "openai" for generic OpenAI-compatible APIs.""" - wire_api: ProviderConfigWireAPI | None = None + wire_api: ProviderWireAPI | None = None """Wire API format (openai/azure only). Defaults to "completions".""" wire_model: str | None = None @@ -12249,8 +12312,8 @@ def from_dict(obj: Any) -> 'ProviderConfig': max_output_tokens = from_union([from_float, from_none], obj.get("maxOutputTokens")) max_prompt_tokens = from_union([from_float, from_none], obj.get("maxPromptTokens")) model_id = from_union([from_str, from_none], obj.get("modelId")) - type = from_union([ProviderConfigType, from_none], obj.get("type")) - wire_api = from_union([ProviderConfigWireAPI, from_none], obj.get("wireApi")) + type = from_union([ProviderType, from_none], obj.get("type")) + wire_api = from_union([ProviderWireAPI, from_none], obj.get("wireApi")) wire_model = from_union([from_str, from_none], obj.get("wireModel")) return ProviderConfig(base_url, api_key, azure, bearer_token, headers, max_context_window_tokens, max_output_tokens, max_prompt_tokens, model_id, type, wire_api, wire_model) @@ -12274,13 +12337,62 @@ def to_dict(self) -> dict: if self.model_id is not None: result["modelId"] = from_union([from_str, from_none], self.model_id) if self.type is not None: - result["type"] = from_union([lambda x: to_enum(ProviderConfigType, x), from_none], self.type) + result["type"] = from_union([lambda x: to_enum(ProviderType, x), from_none], self.type) if self.wire_api is not None: - result["wireApi"] = from_union([lambda x: to_enum(ProviderConfigWireAPI, x), from_none], self.wire_api) + result["wireApi"] = from_union([lambda x: to_enum(ProviderWireAPI, x), from_none], self.wire_api) if self.wire_model is not None: result["wireModel"] = from_union([from_str, from_none], self.wire_model) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class ProviderEndpoint: + """A snapshot of the provider endpoint the session is currently configured to talk to.""" + + base_url: str + """Base URL to pass to the LLM client library.""" + + headers: dict[str, str] + """HTTP headers the caller must include on every outbound request.""" + + type: ProviderType + """Provider family. Matches the `type` field of a BYOK provider config.""" + + api_key: str | None = None + """A credential the caller should use with this endpoint. Omitted only when the endpoint + accepts unauthenticated requests. + """ + session_token: ProviderSessionToken | None = None + """Short-lived, rotating credential the caller must send on every request, in addition to + `apiKey` if one is present. Omitted when the endpoint does not require one. + """ + wire_api: ProviderWireAPI | None = None + """Wire API to be used, when required for the provider type.""" + + @staticmethod + def from_dict(obj: Any) -> 'ProviderEndpoint': + assert isinstance(obj, dict) + base_url = from_str(obj.get("baseUrl")) + headers = from_dict(from_str, obj.get("headers")) + type = ProviderType(obj.get("type")) + api_key = from_union([from_str, from_none], obj.get("apiKey")) + session_token = from_union([ProviderSessionToken.from_dict, from_none], obj.get("sessionToken")) + wire_api = from_union([ProviderWireAPI, from_none], obj.get("wireApi")) + return ProviderEndpoint(base_url, headers, type, api_key, session_token, wire_api) + + def to_dict(self) -> dict: + result: dict = {} + result["baseUrl"] = from_str(self.base_url) + result["headers"] = from_dict(from_str, self.headers) + result["type"] = to_enum(ProviderType, self.type) + if self.api_key is not None: + result["apiKey"] = from_union([from_str, from_none], self.api_key) + if self.session_token is not None: + result["sessionToken"] = from_union([lambda x: to_class(ProviderSessionToken, x), from_none], self.session_token) + if self.wire_api is not None: + result["wireApi"] = from_union([lambda x: to_enum(ProviderWireAPI, x), from_none], self.wire_api) + return result + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class PushAttachmentSelectionDetails: @@ -14418,6 +14530,12 @@ class SlashCommandInfo: input: SlashCommandInput | None = None """Optional unstructured input hint""" + schedulable: bool | None = None + """Whether the command may be the target of `/every` / `/after` schedules. Resolution + happens at every tick, so only set this when the command is safe to re-invoke and + produces an agent prompt. + """ + @staticmethod def from_dict(obj: Any) -> 'SlashCommandInfo': assert isinstance(obj, dict) @@ -14428,7 +14546,8 @@ def from_dict(obj: Any) -> 'SlashCommandInfo': aliases = from_union([lambda x: from_list(from_str, x), from_none], obj.get("aliases")) experimental = from_union([from_bool, from_none], obj.get("experimental")) input = from_union([SlashCommandInput.from_dict, from_none], obj.get("input")) - return SlashCommandInfo(allow_during_agent_execution, description, kind, name, aliases, experimental, input) + schedulable = from_union([from_bool, from_none], obj.get("schedulable")) + return SlashCommandInfo(allow_during_agent_execution, description, kind, name, aliases, experimental, input, schedulable) def to_dict(self) -> dict: result: dict = {} @@ -14442,6 +14561,8 @@ def to_dict(self) -> dict: result["experimental"] = from_union([from_bool, from_none], self.experimental) if self.input is not None: result["input"] = from_union([lambda x: to_class(SlashCommandInput, x), from_none], self.input) + if self.schedulable is not None: + result["schedulable"] = from_union([from_bool, from_none], self.schedulable) return result # Experimental: this type is part of an experimental API and may change or be removed. @@ -17751,6 +17872,9 @@ class SessionOpenOptions: lsp_client_name: str | None = None """Identifier sent to LSP-style integrations.""" + memory: MemoryConfiguration | None = None + """Memory configuration for this session.""" + model: str | None = None """Initial model identifier.""" @@ -17842,6 +17966,7 @@ def from_dict(obj: Any) -> 'SessionOpenOptions': is_experimental_mode = from_union([from_bool, from_none], obj.get("isExperimentalMode")) log_interactive_shells = from_union([from_bool, from_none], obj.get("logInteractiveShells")) lsp_client_name = from_union([from_str, from_none], obj.get("lspClientName")) + memory = from_union([MemoryConfiguration.from_dict, from_none], obj.get("memory")) model = from_union([from_str, from_none], obj.get("model")) model_capabilities_overrides = from_union([ModelCapabilitiesOverride.from_dict, from_none], obj.get("modelCapabilitiesOverrides")) name = from_union([from_str, from_none], obj.get("name")) @@ -17862,7 +17987,7 @@ def from_dict(obj: Any) -> 'SessionOpenOptions': trajectory_file = from_union([from_str, from_none], obj.get("trajectoryFile")) working_directory = from_union([from_str, from_none], obj.get("workingDirectory")) working_directory_context = from_union([SessionContext.from_dict, from_none], obj.get("workingDirectoryContext")) - return SessionOpenOptions(additional_content_exclusion_policies, agent_context, ask_user_disabled, auth_info, available_tools, client_kind, client_name, coauthor_enabled, config_dir, continue_on_auto_mode, copilot_url, custom_agents_local_only, detached_from_spawning_parent_engagement_id, detached_from_spawning_parent_session_id, disabled_instruction_sources, disabled_skills, enable_on_demand_instruction_discovery, enable_script_safety, enable_streaming, env_value_mode, events_log_directory, excluded_tools, feature_flags, installed_plugins, integration_id, is_experimental_mode, log_interactive_shells, lsp_client_name, model, model_capabilities_overrides, name, provider, reasoning_effort, reasoning_summary, remote_defaulted_on, remote_exporting, remote_steerable, running_in_interactive_mode, sandbox_config, session_capabilities, session_id, shell_init_profile, shell_process_flags, skill_directories, skip_custom_instructions, trajectory_file, working_directory, working_directory_context) + return SessionOpenOptions(additional_content_exclusion_policies, agent_context, ask_user_disabled, auth_info, available_tools, client_kind, client_name, coauthor_enabled, config_dir, continue_on_auto_mode, copilot_url, custom_agents_local_only, detached_from_spawning_parent_engagement_id, detached_from_spawning_parent_session_id, disabled_instruction_sources, disabled_skills, enable_on_demand_instruction_discovery, enable_script_safety, enable_streaming, env_value_mode, events_log_directory, excluded_tools, feature_flags, installed_plugins, integration_id, is_experimental_mode, log_interactive_shells, lsp_client_name, memory, model, model_capabilities_overrides, name, provider, reasoning_effort, reasoning_summary, remote_defaulted_on, remote_exporting, remote_steerable, running_in_interactive_mode, sandbox_config, session_capabilities, session_id, shell_init_profile, shell_process_flags, skill_directories, skip_custom_instructions, trajectory_file, working_directory, working_directory_context) def to_dict(self) -> dict: result: dict = {} @@ -17922,6 +18047,8 @@ def to_dict(self) -> dict: result["logInteractiveShells"] = from_union([from_bool, from_none], self.log_interactive_shells) if self.lsp_client_name is not None: result["lspClientName"] = from_union([from_str, from_none], self.lsp_client_name) + if self.memory is not None: + result["memory"] = from_union([lambda x: to_class(MemoryConfiguration, x), from_none], self.memory) if self.model is not None: result["model"] = from_union([from_str, from_none], self.model) if self.model_capabilities_overrides is not None: @@ -19102,6 +19229,28 @@ def to_dict(self) -> dict: result["source"] = from_union([lambda x: to_enum(PermissionsSetAAllSource, x), from_none], self.source) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class ProviderGetEndpointRequest: + """Optional model identifier to scope the endpoint snapshot to.""" + + model_id: str | None = None + """Model identifier the caller intends to use against the returned endpoint. Used to pick + the correct wire shape. Omit to use whichever model the session is currently using. + """ + + @staticmethod + def from_dict(obj: Any) -> 'ProviderGetEndpointRequest': + assert isinstance(obj, dict) + model_id = from_union([from_str, from_none], obj.get("modelId")) + return ProviderGetEndpointRequest(model_id) + + def to_dict(self) -> dict: + result: dict = {} + if self.model_id is not None: + result["modelId"] = from_union([from_str, from_none], self.model_id) + return result + # Experimental: this type is part of an experimental API and may change or be removed. # Internal: this type is an internal SDK API and is not part of the public surface. @dataclass @@ -19508,6 +19657,7 @@ class RPC: mcp_stop_server_request: MCPStopServerRequest mcp_tools: MCPTools mcp_unregister_external_client_request: MCPUnregisterExternalClientRequest + memory_configuration: MemoryConfiguration metadata_context_info_request: MetadataContextInfoRequest metadata_context_info_result: MetadataContextInfoResult metadata_is_processing_result: MetadataIsProcessingResult @@ -19679,8 +19829,13 @@ class RPC: poll_spawned_sessions_result: PollSpawnedSessionsResult provider_config: ProviderConfig provider_config_azure: ProviderConfigAzure - provider_config_type: ProviderConfigType - provider_config_wire_api: ProviderConfigWireAPI + provider_config_type: ProviderType + provider_config_wire_api: ProviderWireAPI + provider_endpoint: ProviderEndpoint + provider_endpoint_type: ProviderType + provider_endpoint_wire_api: ProviderWireAPI + provider_get_endpoint_request: ProviderGetEndpointRequest + provider_session_token: ProviderSessionToken push_attachment: PushAttachment push_attachment_blob: PushAttachmentBlob push_attachment_directory: PushAttachmentDirectory @@ -20221,6 +20376,7 @@ def from_dict(obj: Any) -> 'RPC': mcp_stop_server_request = MCPStopServerRequest.from_dict(obj.get("McpStopServerRequest")) mcp_tools = MCPTools.from_dict(obj.get("McpTools")) mcp_unregister_external_client_request = MCPUnregisterExternalClientRequest.from_dict(obj.get("McpUnregisterExternalClientRequest")) + memory_configuration = MemoryConfiguration.from_dict(obj.get("MemoryConfiguration")) metadata_context_info_request = MetadataContextInfoRequest.from_dict(obj.get("MetadataContextInfoRequest")) metadata_context_info_result = MetadataContextInfoResult.from_dict(obj.get("MetadataContextInfoResult")) metadata_is_processing_result = MetadataIsProcessingResult.from_dict(obj.get("MetadataIsProcessingResult")) @@ -20392,8 +20548,13 @@ def from_dict(obj: Any) -> 'RPC': poll_spawned_sessions_result = PollSpawnedSessionsResult.from_dict(obj.get("PollSpawnedSessionsResult")) provider_config = ProviderConfig.from_dict(obj.get("ProviderConfig")) provider_config_azure = ProviderConfigAzure.from_dict(obj.get("ProviderConfigAzure")) - provider_config_type = ProviderConfigType(obj.get("ProviderConfigType")) - provider_config_wire_api = ProviderConfigWireAPI(obj.get("ProviderConfigWireApi")) + provider_config_type = ProviderType(obj.get("ProviderConfigType")) + provider_config_wire_api = ProviderWireAPI(obj.get("ProviderConfigWireApi")) + provider_endpoint = ProviderEndpoint.from_dict(obj.get("ProviderEndpoint")) + provider_endpoint_type = ProviderType(obj.get("ProviderEndpointType")) + provider_endpoint_wire_api = ProviderWireAPI(obj.get("ProviderEndpointWireApi")) + provider_get_endpoint_request = ProviderGetEndpointRequest.from_dict(obj.get("ProviderGetEndpointRequest")) + provider_session_token = ProviderSessionToken.from_dict(obj.get("ProviderSessionToken")) push_attachment = _load_PushAttachment(obj.get("PushAttachment")) push_attachment_blob = PushAttachmentBlob.from_dict(obj.get("PushAttachmentBlob")) push_attachment_directory = PushAttachmentDirectory.from_dict(obj.get("PushAttachmentDirectory")) @@ -20703,7 +20864,7 @@ def from_dict(obj: Any) -> 'RPC': session_context_info = from_union([SessionContextInfo.from_dict, from_none], obj.get("SessionContextInfo")) task_progress = from_union([TaskProgress.from_dict, from_none], obj.get("TaskProgress")) workspace_summary = from_union([WorkspaceSummary.from_dict, from_none], obj.get("WorkspaceSummary")) - return RPC(abort_request, abort_result, account_get_quota_request, account_get_quota_result, account_quota_snapshot, agent_get_current_result, agent_info, agent_info_source, agent_list, agent_registry_live_target_entry, agent_registry_live_target_entry_attention_kind, agent_registry_live_target_entry_kind, agent_registry_live_target_entry_last_terminal_event, agent_registry_live_target_entry_status, agent_registry_log_capture, agent_registry_log_capture_open_error_reason, agent_registry_spawn_error, agent_registry_spawn_permission_mode, agent_registry_spawn_registry_timeout, agent_registry_spawn_request, agent_registry_spawn_result, agent_registry_spawn_spawned, agent_registry_spawn_validation_error, agent_registry_spawn_validation_error_field, agent_registry_spawn_validation_error_reason, agent_reload_result, agents_discover_request, agent_select_request, agent_select_result, allow_all_permission_set_result, allow_all_permission_state, api_key_auth_info, auth_info, auth_info_type, cancel_user_requested_shell_command_result, canvas_action, canvas_action_invoke_request, canvas_action_invoke_result, canvas_close_request, canvas_host_context, canvas_host_context_capabilities, canvas_instance_availability, canvas_json_schema, canvas_list, canvas_list_open_result, canvas_open_request, canvas_provider_close_request, canvas_provider_invoke_action_request, canvas_provider_open_request, canvas_provider_open_result, canvas_session_context, command_list, commands_handle_pending_command_request, commands_handle_pending_command_result, commands_invoke_request, commands_list_request, commands_respond_to_queued_command_request, commands_respond_to_queued_command_result, configure_session_extensions_params, connected_remote_session_metadata, connected_remote_session_metadata_kind, connected_remote_session_metadata_repository, connect_remote_session_params, connect_request, connect_result, content_filter_mode, copilot_api_token_auth_info, copilot_user_response, copilot_user_response_endpoints, copilot_user_response_quota_snapshots, copilot_user_response_quota_snapshots_chat, copilot_user_response_quota_snapshots_completions, copilot_user_response_quota_snapshots_premium_interactions, current_model, current_tool_metadata, discovered_canvas, discovered_mcp_server, discovered_mcp_server_type, enqueue_command_params, enqueue_command_result, env_auth_info, event_log_read_request, event_log_release_interest_result, event_log_tail_result, event_log_types, events_agent_scope, events_cursor_status, events_read_result, execute_command_params, execute_command_result, extension, extension_context_push_input, extension_list, extensions_disable_request, extensions_enable_request, extension_source, extension_status, external_tool_result, external_tool_text_result_for_llm, external_tool_text_result_for_llm_binary_results_for_llm, external_tool_text_result_for_llm_binary_results_for_llm_type, external_tool_text_result_for_llm_content, external_tool_text_result_for_llm_content_audio, external_tool_text_result_for_llm_content_image, external_tool_text_result_for_llm_content_resource, external_tool_text_result_for_llm_content_resource_details, external_tool_text_result_for_llm_content_resource_link, external_tool_text_result_for_llm_content_resource_link_icon, external_tool_text_result_for_llm_content_resource_link_icon_theme, external_tool_text_result_for_llm_content_terminal, external_tool_text_result_for_llm_content_text, filter_mapping, fleet_start_request, fleet_start_result, folder_trust_add_params, folder_trust_check_params, folder_trust_check_result, gh_cli_auth_info, handle_pending_tool_call_request, handle_pending_tool_call_result, history_abort_manual_compaction_result, history_cancel_background_compaction_result, history_compact_context_window, history_compact_request, history_compact_result, history_summarize_for_handoff_result, history_truncate_request, history_truncate_result, hmac_auth_info, installed_plugin, installed_plugin_info, installed_plugin_source, installed_plugin_source_git_hub, installed_plugin_source_local, installed_plugin_source_url, instructions_discover_request, instructions_get_sources_result, instruction_source, instruction_source_location, instruction_source_type, local_session_metadata_value, log_request, log_result, lsp_initialize_request, marketplace_add_result, marketplace_browse_result, marketplace_info, marketplace_list_result, marketplace_plugin_info, marketplace_refresh_entry, marketplace_refresh_result, marketplace_remove_result, mcp_allowed_server, mcp_apps_call_tool_request, mcp_apps_diagnose_capability, mcp_apps_diagnose_request, mcp_apps_diagnose_result, mcp_apps_diagnose_server, mcp_apps_host_context, mcp_apps_host_context_details, mcp_apps_host_context_details_available_display_mode, mcp_apps_host_context_details_display_mode, mcp_apps_host_context_details_platform, mcp_apps_host_context_details_theme, mcp_apps_list_tools_request, mcp_apps_list_tools_result, mcp_apps_read_resource_request, mcp_apps_read_resource_result, mcp_apps_resource_content, mcp_apps_set_host_context_details, mcp_apps_set_host_context_details_available_display_mode, mcp_apps_set_host_context_details_display_mode, mcp_apps_set_host_context_details_platform, mcp_apps_set_host_context_details_theme, mcp_apps_set_host_context_request, mcp_cancel_sampling_execution_params, mcp_cancel_sampling_execution_result, mcp_config_add_request, mcp_config_disable_request, mcp_config_enable_request, mcp_config_list, mcp_config_remove_request, mcp_config_update_request, mcp_configure_git_hub_request, mcp_configure_git_hub_result, mcp_disable_request, mcp_discover_request, mcp_discover_result, mcp_enable_request, mcp_execute_sampling_params, mcp_execute_sampling_request, mcp_execute_sampling_result, mcp_filtered_server, mcp_host_state, mcp_is_server_running_request, mcp_is_server_running_result, mcp_list_tools_request, mcp_list_tools_result, mcp_oauth_login_request, mcp_oauth_login_result, mcp_oauth_respond_request, mcp_oauth_respond_result, mcp_register_external_client_request, mcp_reload_with_config_request, mcp_remove_git_hub_result, mcp_restart_server_request, mcp_sampling_execution_action, mcp_sampling_execution_result, mcp_server, mcp_server_auth_config, mcp_server_auth_config_redirect_port, mcp_server_config, mcp_server_config_http, mcp_server_config_http_oauth_grant_type, mcp_server_config_http_type, mcp_server_config_stdio, mcp_server_failure_info, mcp_server_list, mcp_server_needs_auth_info, mcp_set_env_value_mode_details, mcp_set_env_value_mode_params, mcp_set_env_value_mode_result, mcp_start_server_request, mcp_start_servers_result, mcp_stop_server_request, mcp_tools, mcp_unregister_external_client_request, metadata_context_info_request, metadata_context_info_result, metadata_is_processing_result, metadata_recompute_context_tokens_request, metadata_recompute_context_tokens_result, metadata_record_context_change_request, metadata_record_context_change_result, metadata_set_working_directory_request, metadata_set_working_directory_result, metadata_snapshot_current_mode, metadata_snapshot_remote_metadata, metadata_snapshot_remote_metadata_repository, metadata_snapshot_remote_metadata_task_type, model, model_billing, model_billing_token_prices, model_billing_token_prices_long_context, model_capabilities, model_capabilities_limits, model_capabilities_limits_vision, model_capabilities_override, model_capabilities_override_limits, model_capabilities_override_limits_vision, model_capabilities_override_supports, model_capabilities_supports, model_list, model_list_request, model_picker_category, model_picker_price_category, model_policy, model_policy_state, model_set_reasoning_effort_request, model_set_reasoning_effort_result, models_list_request, model_switch_to_request, model_switch_to_result, mode_set_request, name_get_result, name_set_auto_request, name_set_auto_result, name_set_request, open_canvas_instance, options_update_additional_content_exclusion_policy, options_update_additional_content_exclusion_policy_rule, options_update_additional_content_exclusion_policy_rule_source, options_update_additional_content_exclusion_policy_scope, options_update_context_tier, options_update_env_value_mode, options_update_reasoning_summary, options_update_tool_filter_precedence, pending_permission_request, pending_permission_request_list, permission_decision, permission_decision_approved, permission_decision_approved_for_location, permission_decision_approved_for_session, permission_decision_approve_for_location, permission_decision_approve_for_location_approval, permission_decision_approve_for_location_approval_commands, permission_decision_approve_for_location_approval_custom_tool, permission_decision_approve_for_location_approval_extension_management, permission_decision_approve_for_location_approval_extension_permission_access, permission_decision_approve_for_location_approval_mcp, permission_decision_approve_for_location_approval_mcp_sampling, permission_decision_approve_for_location_approval_memory, permission_decision_approve_for_location_approval_read, permission_decision_approve_for_location_approval_write, permission_decision_approve_for_session, permission_decision_approve_for_session_approval, permission_decision_approve_for_session_approval_commands, permission_decision_approve_for_session_approval_custom_tool, permission_decision_approve_for_session_approval_extension_management, permission_decision_approve_for_session_approval_extension_permission_access, permission_decision_approve_for_session_approval_mcp, permission_decision_approve_for_session_approval_mcp_sampling, permission_decision_approve_for_session_approval_memory, permission_decision_approve_for_session_approval_read, permission_decision_approve_for_session_approval_write, permission_decision_approve_once, permission_decision_approve_permanently, permission_decision_cancelled, permission_decision_denied_by_content_exclusion_policy, permission_decision_denied_by_permission_request_hook, permission_decision_denied_by_rules, permission_decision_denied_interactively_by_user, permission_decision_denied_no_approval_rule_and_could_not_request_from_user, permission_decision_reject, permission_decision_request, permission_decision_user_not_available, permission_location_add_tool_approval_params, permission_location_apply_params, permission_location_apply_result, permission_location_resolve_params, permission_location_resolve_result, permission_location_type, permission_paths_add_params, permission_paths_allowed_check_params, permission_paths_allowed_check_result, permission_paths_config, permission_paths_list, permission_paths_update_primary_params, permission_paths_workspace_check_params, permission_paths_workspace_check_result, permission_prompt_shown_notification, permission_request_result, permission_rules_set, permissions_configure_additional_content_exclusion_policy, permissions_configure_additional_content_exclusion_policy_rule, permissions_configure_additional_content_exclusion_policy_rule_source, permissions_configure_additional_content_exclusion_policy_scope, permissions_configure_params, permissions_configure_result, permissions_folder_trust_add_trusted_result, permissions_get_allow_all_request, permissions_locations_add_tool_approval_details, permissions_locations_add_tool_approval_details_commands, permissions_locations_add_tool_approval_details_custom_tool, permissions_locations_add_tool_approval_details_extension_management, permissions_locations_add_tool_approval_details_extension_permission_access, permissions_locations_add_tool_approval_details_mcp, permissions_locations_add_tool_approval_details_mcp_sampling, permissions_locations_add_tool_approval_details_memory, permissions_locations_add_tool_approval_details_read, permissions_locations_add_tool_approval_details_write, permissions_locations_add_tool_approval_result, permissions_modify_rules_params, permissions_modify_rules_result, permissions_modify_rules_scope, permissions_notify_prompt_shown_result, permissions_paths_add_result, permissions_paths_list_request, permissions_paths_update_primary_result, permissions_pending_requests_request, permissions_reset_session_approvals_request, permissions_reset_session_approvals_result, permissions_set_allow_all_request, permissions_set_allow_all_source, permissions_set_approve_all_request, permissions_set_approve_all_result, permissions_set_approve_all_source, permissions_set_required_request, permissions_set_required_result, permissions_urls_set_unrestricted_mode_result, permission_urls_config, permission_urls_set_unrestricted_mode_params, ping_request, ping_result, plan_read_result, plan_read_sql_todos_result, plan_sql_todos_row, plan_update_request, plugin, plugin_install_result, plugin_list, plugin_list_result, plugins_disable_request, plugins_enable_request, plugins_install_request, plugins_marketplaces_add_request, plugins_marketplaces_browse_request, plugins_marketplaces_refresh_request, plugins_marketplaces_remove_request, plugins_reload_request, plugins_uninstall_request, plugins_update_request, plugin_update_all_entry, plugin_update_all_result, plugin_update_result, poll_spawned_sessions_result, provider_config, provider_config_azure, provider_config_type, provider_config_wire_api, push_attachment, push_attachment_blob, push_attachment_directory, push_attachment_file, push_attachment_file_line_range, push_attachment_git_hub_reference, push_attachment_git_hub_reference_type, push_attachment_selection, push_attachment_selection_details, push_attachment_selection_details_end, push_attachment_selection_details_start, queued_command_handled, queued_command_not_handled, queued_command_result, queue_pending_items, queue_pending_items_kind, queue_pending_items_result, queue_remove_most_recent_result, register_event_interest_params, register_event_interest_result, register_extension_tools_params, register_extension_tools_result, release_event_interest_params, remote_control_config, remote_control_config_existing_mc_session, remote_control_status, remote_control_status_active, remote_control_status_connecting, remote_control_status_error, remote_control_status_off, remote_control_status_result, remote_control_stop_result, remote_control_transfer_result, remote_enable_request, remote_enable_result, remote_notify_steerable_changed_request, remote_notify_steerable_changed_result, remote_session_connection_result, remote_session_metadata_repository, remote_session_metadata_task_type, remote_session_metadata_value, remote_session_mode, remote_session_repository, sandbox_config, sandbox_config_user_policy, sandbox_config_user_policy_experimental, sandbox_config_user_policy_experimental_seatbelt, sandbox_config_user_policy_filesystem, sandbox_config_user_policy_network, schedule_entry, schedule_list, schedule_stop_request, schedule_stop_result, secrets_add_filter_values_request, secrets_add_filter_values_result, send_agent_mode, send_attachments_to_message_params, send_mode, send_request, send_result, server_agent_list, server_instruction_source_list, server_skill, server_skill_list, session_activity, session_auth_status, session_bulk_delete_result, session_capability, session_context, session_context_host_type, session_enrich_metadata_result, session_fs_append_file_request, session_fs_error, session_fs_error_code, session_fs_exists_request, session_fs_exists_result, session_fs_mkdir_request, session_fs_readdir_request, session_fs_readdir_result, session_fs_readdir_with_types_entry, session_fs_readdir_with_types_entry_type, session_fs_readdir_with_types_request, session_fs_readdir_with_types_result, session_fs_read_file_request, session_fs_read_file_result, session_fs_rename_request, session_fs_rm_request, session_fs_set_provider_capabilities, session_fs_set_provider_conventions, session_fs_set_provider_request, session_fs_set_provider_result, session_fs_sqlite_exists_request, session_fs_sqlite_exists_result, session_fs_sqlite_query_request, session_fs_sqlite_query_result, session_fs_sqlite_query_type, session_fs_stat_request, session_fs_stat_result, session_fs_write_file_request, session_installed_plugin, session_installed_plugin_source, session_installed_plugin_source_git_hub, session_installed_plugin_source_local, session_installed_plugin_source_url, session_list, session_list_entry, session_list_filter, session_load_deferred_repo_hooks_result, session_log_level, session_mcp_apps_call_tool_result, session_metadata_snapshot, session_mode, session_model_list, session_open_options, session_open_options_additional_content_exclusion_policy, session_open_options_additional_content_exclusion_policy_rule, session_open_options_additional_content_exclusion_policy_rule_source, session_open_options_additional_content_exclusion_policy_scope, session_open_options_env_value_mode, session_open_options_reasoning_summary, session_open_params, session_open_result, session_prune_result, sessions_bulk_delete_request, sessions_check_in_use_request, sessions_check_in_use_result, sessions_close_request, sessions_close_result, sessions_enrich_metadata_request, session_set_credentials_params, session_set_credentials_result, sessions_find_by_prefix_request, sessions_find_by_prefix_result, sessions_find_by_task_id_request, sessions_find_by_task_id_result, sessions_fork_request, sessions_fork_result, sessions_get_board_entry_count_request, sessions_get_board_entry_count_result, sessions_get_event_file_path_request, sessions_get_event_file_path_result, sessions_get_last_for_context_request, sessions_get_last_for_context_result, sessions_get_persisted_remote_steerable_request, sessions_get_persisted_remote_steerable_result, session_sizes, sessions_list_request, sessions_load_deferred_repo_hooks_request, sessions_open_attach, sessions_open_cloud, sessions_open_create, sessions_open_handoff, sessions_open_handoff_task_type, sessions_open_progress, sessions_open_progress_status, sessions_open_progress_step, sessions_open_remote, sessions_open_resume, sessions_open_resume_last, sessions_open_status, session_source, sessions_poll_spawned_sessions_event, sessions_poll_spawned_sessions_request, sessions_prune_old_request, sessions_register_extension_tools_on_session_options, sessions_release_lock_request, sessions_release_lock_result, sessions_reload_plugin_hooks_request, sessions_reload_plugin_hooks_result, sessions_save_request, sessions_save_result, sessions_set_additional_plugins_request, sessions_set_additional_plugins_result, sessions_set_remote_control_steering_request, sessions_start_remote_control_request, sessions_stop_remote_control_request, sessions_transfer_remote_control_request, session_telemetry_engagement, session_update_options_params, session_update_options_result, session_working_directory_context, session_working_directory_context_host_type, shell_cancel_user_requested_request, shell_exec_request, shell_exec_result, shell_execute_user_requested_request, shell_kill_request, shell_kill_result, shell_kill_signal, shutdown_request, skill, skill_list, skills_config_set_disabled_skills_request, skills_disable_request, skills_discover_request, skills_enable_request, skills_get_invoked_result, skills_invoked_skill, skills_load_diagnostics, slash_command_agent_prompt_result, slash_command_completed_result, slash_command_info, slash_command_input, slash_command_input_completion, slash_command_invocation_result, slash_command_kind, slash_command_select_subcommand_option, slash_command_select_subcommand_result, slash_command_text_result, task_agent_info, task_agent_progress, task_execution_mode, task_info, task_list, task_progress_line, tasks_cancel_request, tasks_cancel_result, tasks_get_current_promotable_result, tasks_get_progress_request, tasks_get_progress_result, task_shell_info, task_shell_info_attachment_mode, task_shell_progress, tasks_promote_current_to_background_result, tasks_promote_to_background_request, tasks_promote_to_background_result, tasks_refresh_result, tasks_remove_request, tasks_remove_result, tasks_send_message_request, tasks_send_message_result, tasks_start_agent_request, tasks_start_agent_result, task_status, tasks_wait_for_pending_result, telemetry_set_feature_overrides_request, token_auth_info, tool, tool_list, tools_get_current_metadata_result, tools_initialize_and_validate_result, tools_list_request, ui_auto_mode_switch_response, ui_elicitation_array_any_of_field, ui_elicitation_array_any_of_field_items, ui_elicitation_array_any_of_field_items_any_of, ui_elicitation_array_enum_field, ui_elicitation_array_enum_field_items, ui_elicitation_field_value, ui_elicitation_request, ui_elicitation_response, ui_elicitation_response_action, ui_elicitation_response_content, ui_elicitation_result, ui_elicitation_schema, ui_elicitation_schema_property, ui_elicitation_schema_property_boolean, ui_elicitation_schema_property_number, ui_elicitation_schema_property_number_type, ui_elicitation_schema_property_string, ui_elicitation_schema_property_string_format, ui_elicitation_string_enum_field, ui_elicitation_string_one_of_field, ui_elicitation_string_one_of_field_one_of, ui_ephemeral_query_request, ui_ephemeral_query_result, ui_exit_plan_mode_action, ui_exit_plan_mode_response, ui_handle_pending_auto_mode_switch_request, ui_handle_pending_elicitation_request, ui_handle_pending_exit_plan_mode_request, ui_handle_pending_result, ui_handle_pending_sampling_request, ui_handle_pending_sampling_response, ui_handle_pending_user_input_request, ui_register_direct_auto_mode_switch_handler_result, ui_unregister_direct_auto_mode_switch_handler_request, ui_unregister_direct_auto_mode_switch_handler_result, ui_user_input_response, usage_get_metrics_result, usage_metrics_code_changes, usage_metrics_model_metric, usage_metrics_model_metric_requests, usage_metrics_model_metric_token_detail, usage_metrics_model_metric_usage, usage_metrics_token_detail, user_auth_info, user_requested_shell_command_result, workspace_diff_file_change, workspace_diff_file_change_type, workspace_diff_mode, workspace_diff_result, workspaces_checkpoints, workspaces_create_file_request, workspaces_diff_request, workspaces_get_workspace_result, workspaces_list_checkpoints_result, workspaces_list_files_result, workspaces_read_checkpoint_request, workspaces_read_checkpoint_result, workspaces_read_file_request, workspaces_read_file_result, workspaces_save_large_paste_request, workspaces_save_large_paste_result, workspace_summary_host_type, workspaces_workspace_details_host_type, session_context_info, task_progress, workspace_summary) + return RPC(abort_request, abort_result, account_get_quota_request, account_get_quota_result, account_quota_snapshot, agent_get_current_result, agent_info, agent_info_source, agent_list, agent_registry_live_target_entry, agent_registry_live_target_entry_attention_kind, agent_registry_live_target_entry_kind, agent_registry_live_target_entry_last_terminal_event, agent_registry_live_target_entry_status, agent_registry_log_capture, agent_registry_log_capture_open_error_reason, agent_registry_spawn_error, agent_registry_spawn_permission_mode, agent_registry_spawn_registry_timeout, agent_registry_spawn_request, agent_registry_spawn_result, agent_registry_spawn_spawned, agent_registry_spawn_validation_error, agent_registry_spawn_validation_error_field, agent_registry_spawn_validation_error_reason, agent_reload_result, agents_discover_request, agent_select_request, agent_select_result, allow_all_permission_set_result, allow_all_permission_state, api_key_auth_info, auth_info, auth_info_type, cancel_user_requested_shell_command_result, canvas_action, canvas_action_invoke_request, canvas_action_invoke_result, canvas_close_request, canvas_host_context, canvas_host_context_capabilities, canvas_instance_availability, canvas_json_schema, canvas_list, canvas_list_open_result, canvas_open_request, canvas_provider_close_request, canvas_provider_invoke_action_request, canvas_provider_open_request, canvas_provider_open_result, canvas_session_context, command_list, commands_handle_pending_command_request, commands_handle_pending_command_result, commands_invoke_request, commands_list_request, commands_respond_to_queued_command_request, commands_respond_to_queued_command_result, configure_session_extensions_params, connected_remote_session_metadata, connected_remote_session_metadata_kind, connected_remote_session_metadata_repository, connect_remote_session_params, connect_request, connect_result, content_filter_mode, copilot_api_token_auth_info, copilot_user_response, copilot_user_response_endpoints, copilot_user_response_quota_snapshots, copilot_user_response_quota_snapshots_chat, copilot_user_response_quota_snapshots_completions, copilot_user_response_quota_snapshots_premium_interactions, current_model, current_tool_metadata, discovered_canvas, discovered_mcp_server, discovered_mcp_server_type, enqueue_command_params, enqueue_command_result, env_auth_info, event_log_read_request, event_log_release_interest_result, event_log_tail_result, event_log_types, events_agent_scope, events_cursor_status, events_read_result, execute_command_params, execute_command_result, extension, extension_context_push_input, extension_list, extensions_disable_request, extensions_enable_request, extension_source, extension_status, external_tool_result, external_tool_text_result_for_llm, external_tool_text_result_for_llm_binary_results_for_llm, external_tool_text_result_for_llm_binary_results_for_llm_type, external_tool_text_result_for_llm_content, external_tool_text_result_for_llm_content_audio, external_tool_text_result_for_llm_content_image, external_tool_text_result_for_llm_content_resource, external_tool_text_result_for_llm_content_resource_details, external_tool_text_result_for_llm_content_resource_link, external_tool_text_result_for_llm_content_resource_link_icon, external_tool_text_result_for_llm_content_resource_link_icon_theme, external_tool_text_result_for_llm_content_terminal, external_tool_text_result_for_llm_content_text, filter_mapping, fleet_start_request, fleet_start_result, folder_trust_add_params, folder_trust_check_params, folder_trust_check_result, gh_cli_auth_info, handle_pending_tool_call_request, handle_pending_tool_call_result, history_abort_manual_compaction_result, history_cancel_background_compaction_result, history_compact_context_window, history_compact_request, history_compact_result, history_summarize_for_handoff_result, history_truncate_request, history_truncate_result, hmac_auth_info, installed_plugin, installed_plugin_info, installed_plugin_source, installed_plugin_source_git_hub, installed_plugin_source_local, installed_plugin_source_url, instructions_discover_request, instructions_get_sources_result, instruction_source, instruction_source_location, instruction_source_type, local_session_metadata_value, log_request, log_result, lsp_initialize_request, marketplace_add_result, marketplace_browse_result, marketplace_info, marketplace_list_result, marketplace_plugin_info, marketplace_refresh_entry, marketplace_refresh_result, marketplace_remove_result, mcp_allowed_server, mcp_apps_call_tool_request, mcp_apps_diagnose_capability, mcp_apps_diagnose_request, mcp_apps_diagnose_result, mcp_apps_diagnose_server, mcp_apps_host_context, mcp_apps_host_context_details, mcp_apps_host_context_details_available_display_mode, mcp_apps_host_context_details_display_mode, mcp_apps_host_context_details_platform, mcp_apps_host_context_details_theme, mcp_apps_list_tools_request, mcp_apps_list_tools_result, mcp_apps_read_resource_request, mcp_apps_read_resource_result, mcp_apps_resource_content, mcp_apps_set_host_context_details, mcp_apps_set_host_context_details_available_display_mode, mcp_apps_set_host_context_details_display_mode, mcp_apps_set_host_context_details_platform, mcp_apps_set_host_context_details_theme, mcp_apps_set_host_context_request, mcp_cancel_sampling_execution_params, mcp_cancel_sampling_execution_result, mcp_config_add_request, mcp_config_disable_request, mcp_config_enable_request, mcp_config_list, mcp_config_remove_request, mcp_config_update_request, mcp_configure_git_hub_request, mcp_configure_git_hub_result, mcp_disable_request, mcp_discover_request, mcp_discover_result, mcp_enable_request, mcp_execute_sampling_params, mcp_execute_sampling_request, mcp_execute_sampling_result, mcp_filtered_server, mcp_host_state, mcp_is_server_running_request, mcp_is_server_running_result, mcp_list_tools_request, mcp_list_tools_result, mcp_oauth_login_request, mcp_oauth_login_result, mcp_oauth_respond_request, mcp_oauth_respond_result, mcp_register_external_client_request, mcp_reload_with_config_request, mcp_remove_git_hub_result, mcp_restart_server_request, mcp_sampling_execution_action, mcp_sampling_execution_result, mcp_server, mcp_server_auth_config, mcp_server_auth_config_redirect_port, mcp_server_config, mcp_server_config_http, mcp_server_config_http_oauth_grant_type, mcp_server_config_http_type, mcp_server_config_stdio, mcp_server_failure_info, mcp_server_list, mcp_server_needs_auth_info, mcp_set_env_value_mode_details, mcp_set_env_value_mode_params, mcp_set_env_value_mode_result, mcp_start_server_request, mcp_start_servers_result, mcp_stop_server_request, mcp_tools, mcp_unregister_external_client_request, memory_configuration, metadata_context_info_request, metadata_context_info_result, metadata_is_processing_result, metadata_recompute_context_tokens_request, metadata_recompute_context_tokens_result, metadata_record_context_change_request, metadata_record_context_change_result, metadata_set_working_directory_request, metadata_set_working_directory_result, metadata_snapshot_current_mode, metadata_snapshot_remote_metadata, metadata_snapshot_remote_metadata_repository, metadata_snapshot_remote_metadata_task_type, model, model_billing, model_billing_token_prices, model_billing_token_prices_long_context, model_capabilities, model_capabilities_limits, model_capabilities_limits_vision, model_capabilities_override, model_capabilities_override_limits, model_capabilities_override_limits_vision, model_capabilities_override_supports, model_capabilities_supports, model_list, model_list_request, model_picker_category, model_picker_price_category, model_policy, model_policy_state, model_set_reasoning_effort_request, model_set_reasoning_effort_result, models_list_request, model_switch_to_request, model_switch_to_result, mode_set_request, name_get_result, name_set_auto_request, name_set_auto_result, name_set_request, open_canvas_instance, options_update_additional_content_exclusion_policy, options_update_additional_content_exclusion_policy_rule, options_update_additional_content_exclusion_policy_rule_source, options_update_additional_content_exclusion_policy_scope, options_update_context_tier, options_update_env_value_mode, options_update_reasoning_summary, options_update_tool_filter_precedence, pending_permission_request, pending_permission_request_list, permission_decision, permission_decision_approved, permission_decision_approved_for_location, permission_decision_approved_for_session, permission_decision_approve_for_location, permission_decision_approve_for_location_approval, permission_decision_approve_for_location_approval_commands, permission_decision_approve_for_location_approval_custom_tool, permission_decision_approve_for_location_approval_extension_management, permission_decision_approve_for_location_approval_extension_permission_access, permission_decision_approve_for_location_approval_mcp, permission_decision_approve_for_location_approval_mcp_sampling, permission_decision_approve_for_location_approval_memory, permission_decision_approve_for_location_approval_read, permission_decision_approve_for_location_approval_write, permission_decision_approve_for_session, permission_decision_approve_for_session_approval, permission_decision_approve_for_session_approval_commands, permission_decision_approve_for_session_approval_custom_tool, permission_decision_approve_for_session_approval_extension_management, permission_decision_approve_for_session_approval_extension_permission_access, permission_decision_approve_for_session_approval_mcp, permission_decision_approve_for_session_approval_mcp_sampling, permission_decision_approve_for_session_approval_memory, permission_decision_approve_for_session_approval_read, permission_decision_approve_for_session_approval_write, permission_decision_approve_once, permission_decision_approve_permanently, permission_decision_cancelled, permission_decision_denied_by_content_exclusion_policy, permission_decision_denied_by_permission_request_hook, permission_decision_denied_by_rules, permission_decision_denied_interactively_by_user, permission_decision_denied_no_approval_rule_and_could_not_request_from_user, permission_decision_reject, permission_decision_request, permission_decision_user_not_available, permission_location_add_tool_approval_params, permission_location_apply_params, permission_location_apply_result, permission_location_resolve_params, permission_location_resolve_result, permission_location_type, permission_paths_add_params, permission_paths_allowed_check_params, permission_paths_allowed_check_result, permission_paths_config, permission_paths_list, permission_paths_update_primary_params, permission_paths_workspace_check_params, permission_paths_workspace_check_result, permission_prompt_shown_notification, permission_request_result, permission_rules_set, permissions_configure_additional_content_exclusion_policy, permissions_configure_additional_content_exclusion_policy_rule, permissions_configure_additional_content_exclusion_policy_rule_source, permissions_configure_additional_content_exclusion_policy_scope, permissions_configure_params, permissions_configure_result, permissions_folder_trust_add_trusted_result, permissions_get_allow_all_request, permissions_locations_add_tool_approval_details, permissions_locations_add_tool_approval_details_commands, permissions_locations_add_tool_approval_details_custom_tool, permissions_locations_add_tool_approval_details_extension_management, permissions_locations_add_tool_approval_details_extension_permission_access, permissions_locations_add_tool_approval_details_mcp, permissions_locations_add_tool_approval_details_mcp_sampling, permissions_locations_add_tool_approval_details_memory, permissions_locations_add_tool_approval_details_read, permissions_locations_add_tool_approval_details_write, permissions_locations_add_tool_approval_result, permissions_modify_rules_params, permissions_modify_rules_result, permissions_modify_rules_scope, permissions_notify_prompt_shown_result, permissions_paths_add_result, permissions_paths_list_request, permissions_paths_update_primary_result, permissions_pending_requests_request, permissions_reset_session_approvals_request, permissions_reset_session_approvals_result, permissions_set_allow_all_request, permissions_set_allow_all_source, permissions_set_approve_all_request, permissions_set_approve_all_result, permissions_set_approve_all_source, permissions_set_required_request, permissions_set_required_result, permissions_urls_set_unrestricted_mode_result, permission_urls_config, permission_urls_set_unrestricted_mode_params, ping_request, ping_result, plan_read_result, plan_read_sql_todos_result, plan_sql_todos_row, plan_update_request, plugin, plugin_install_result, plugin_list, plugin_list_result, plugins_disable_request, plugins_enable_request, plugins_install_request, plugins_marketplaces_add_request, plugins_marketplaces_browse_request, plugins_marketplaces_refresh_request, plugins_marketplaces_remove_request, plugins_reload_request, plugins_uninstall_request, plugins_update_request, plugin_update_all_entry, plugin_update_all_result, plugin_update_result, poll_spawned_sessions_result, provider_config, provider_config_azure, provider_config_type, provider_config_wire_api, provider_endpoint, provider_endpoint_type, provider_endpoint_wire_api, provider_get_endpoint_request, provider_session_token, push_attachment, push_attachment_blob, push_attachment_directory, push_attachment_file, push_attachment_file_line_range, push_attachment_git_hub_reference, push_attachment_git_hub_reference_type, push_attachment_selection, push_attachment_selection_details, push_attachment_selection_details_end, push_attachment_selection_details_start, queued_command_handled, queued_command_not_handled, queued_command_result, queue_pending_items, queue_pending_items_kind, queue_pending_items_result, queue_remove_most_recent_result, register_event_interest_params, register_event_interest_result, register_extension_tools_params, register_extension_tools_result, release_event_interest_params, remote_control_config, remote_control_config_existing_mc_session, remote_control_status, remote_control_status_active, remote_control_status_connecting, remote_control_status_error, remote_control_status_off, remote_control_status_result, remote_control_stop_result, remote_control_transfer_result, remote_enable_request, remote_enable_result, remote_notify_steerable_changed_request, remote_notify_steerable_changed_result, remote_session_connection_result, remote_session_metadata_repository, remote_session_metadata_task_type, remote_session_metadata_value, remote_session_mode, remote_session_repository, sandbox_config, sandbox_config_user_policy, sandbox_config_user_policy_experimental, sandbox_config_user_policy_experimental_seatbelt, sandbox_config_user_policy_filesystem, sandbox_config_user_policy_network, schedule_entry, schedule_list, schedule_stop_request, schedule_stop_result, secrets_add_filter_values_request, secrets_add_filter_values_result, send_agent_mode, send_attachments_to_message_params, send_mode, send_request, send_result, server_agent_list, server_instruction_source_list, server_skill, server_skill_list, session_activity, session_auth_status, session_bulk_delete_result, session_capability, session_context, session_context_host_type, session_enrich_metadata_result, session_fs_append_file_request, session_fs_error, session_fs_error_code, session_fs_exists_request, session_fs_exists_result, session_fs_mkdir_request, session_fs_readdir_request, session_fs_readdir_result, session_fs_readdir_with_types_entry, session_fs_readdir_with_types_entry_type, session_fs_readdir_with_types_request, session_fs_readdir_with_types_result, session_fs_read_file_request, session_fs_read_file_result, session_fs_rename_request, session_fs_rm_request, session_fs_set_provider_capabilities, session_fs_set_provider_conventions, session_fs_set_provider_request, session_fs_set_provider_result, session_fs_sqlite_exists_request, session_fs_sqlite_exists_result, session_fs_sqlite_query_request, session_fs_sqlite_query_result, session_fs_sqlite_query_type, session_fs_stat_request, session_fs_stat_result, session_fs_write_file_request, session_installed_plugin, session_installed_plugin_source, session_installed_plugin_source_git_hub, session_installed_plugin_source_local, session_installed_plugin_source_url, session_list, session_list_entry, session_list_filter, session_load_deferred_repo_hooks_result, session_log_level, session_mcp_apps_call_tool_result, session_metadata_snapshot, session_mode, session_model_list, session_open_options, session_open_options_additional_content_exclusion_policy, session_open_options_additional_content_exclusion_policy_rule, session_open_options_additional_content_exclusion_policy_rule_source, session_open_options_additional_content_exclusion_policy_scope, session_open_options_env_value_mode, session_open_options_reasoning_summary, session_open_params, session_open_result, session_prune_result, sessions_bulk_delete_request, sessions_check_in_use_request, sessions_check_in_use_result, sessions_close_request, sessions_close_result, sessions_enrich_metadata_request, session_set_credentials_params, session_set_credentials_result, sessions_find_by_prefix_request, sessions_find_by_prefix_result, sessions_find_by_task_id_request, sessions_find_by_task_id_result, sessions_fork_request, sessions_fork_result, sessions_get_board_entry_count_request, sessions_get_board_entry_count_result, sessions_get_event_file_path_request, sessions_get_event_file_path_result, sessions_get_last_for_context_request, sessions_get_last_for_context_result, sessions_get_persisted_remote_steerable_request, sessions_get_persisted_remote_steerable_result, session_sizes, sessions_list_request, sessions_load_deferred_repo_hooks_request, sessions_open_attach, sessions_open_cloud, sessions_open_create, sessions_open_handoff, sessions_open_handoff_task_type, sessions_open_progress, sessions_open_progress_status, sessions_open_progress_step, sessions_open_remote, sessions_open_resume, sessions_open_resume_last, sessions_open_status, session_source, sessions_poll_spawned_sessions_event, sessions_poll_spawned_sessions_request, sessions_prune_old_request, sessions_register_extension_tools_on_session_options, sessions_release_lock_request, sessions_release_lock_result, sessions_reload_plugin_hooks_request, sessions_reload_plugin_hooks_result, sessions_save_request, sessions_save_result, sessions_set_additional_plugins_request, sessions_set_additional_plugins_result, sessions_set_remote_control_steering_request, sessions_start_remote_control_request, sessions_stop_remote_control_request, sessions_transfer_remote_control_request, session_telemetry_engagement, session_update_options_params, session_update_options_result, session_working_directory_context, session_working_directory_context_host_type, shell_cancel_user_requested_request, shell_exec_request, shell_exec_result, shell_execute_user_requested_request, shell_kill_request, shell_kill_result, shell_kill_signal, shutdown_request, skill, skill_list, skills_config_set_disabled_skills_request, skills_disable_request, skills_discover_request, skills_enable_request, skills_get_invoked_result, skills_invoked_skill, skills_load_diagnostics, slash_command_agent_prompt_result, slash_command_completed_result, slash_command_info, slash_command_input, slash_command_input_completion, slash_command_invocation_result, slash_command_kind, slash_command_select_subcommand_option, slash_command_select_subcommand_result, slash_command_text_result, task_agent_info, task_agent_progress, task_execution_mode, task_info, task_list, task_progress_line, tasks_cancel_request, tasks_cancel_result, tasks_get_current_promotable_result, tasks_get_progress_request, tasks_get_progress_result, task_shell_info, task_shell_info_attachment_mode, task_shell_progress, tasks_promote_current_to_background_result, tasks_promote_to_background_request, tasks_promote_to_background_result, tasks_refresh_result, tasks_remove_request, tasks_remove_result, tasks_send_message_request, tasks_send_message_result, tasks_start_agent_request, tasks_start_agent_result, task_status, tasks_wait_for_pending_result, telemetry_set_feature_overrides_request, token_auth_info, tool, tool_list, tools_get_current_metadata_result, tools_initialize_and_validate_result, tools_list_request, ui_auto_mode_switch_response, ui_elicitation_array_any_of_field, ui_elicitation_array_any_of_field_items, ui_elicitation_array_any_of_field_items_any_of, ui_elicitation_array_enum_field, ui_elicitation_array_enum_field_items, ui_elicitation_field_value, ui_elicitation_request, ui_elicitation_response, ui_elicitation_response_action, ui_elicitation_response_content, ui_elicitation_result, ui_elicitation_schema, ui_elicitation_schema_property, ui_elicitation_schema_property_boolean, ui_elicitation_schema_property_number, ui_elicitation_schema_property_number_type, ui_elicitation_schema_property_string, ui_elicitation_schema_property_string_format, ui_elicitation_string_enum_field, ui_elicitation_string_one_of_field, ui_elicitation_string_one_of_field_one_of, ui_ephemeral_query_request, ui_ephemeral_query_result, ui_exit_plan_mode_action, ui_exit_plan_mode_response, ui_handle_pending_auto_mode_switch_request, ui_handle_pending_elicitation_request, ui_handle_pending_exit_plan_mode_request, ui_handle_pending_result, ui_handle_pending_sampling_request, ui_handle_pending_sampling_response, ui_handle_pending_user_input_request, ui_register_direct_auto_mode_switch_handler_result, ui_unregister_direct_auto_mode_switch_handler_request, ui_unregister_direct_auto_mode_switch_handler_result, ui_user_input_response, usage_get_metrics_result, usage_metrics_code_changes, usage_metrics_model_metric, usage_metrics_model_metric_requests, usage_metrics_model_metric_token_detail, usage_metrics_model_metric_usage, usage_metrics_token_detail, user_auth_info, user_requested_shell_command_result, workspace_diff_file_change, workspace_diff_file_change_type, workspace_diff_mode, workspace_diff_result, workspaces_checkpoints, workspaces_create_file_request, workspaces_diff_request, workspaces_get_workspace_result, workspaces_list_checkpoints_result, workspaces_list_files_result, workspaces_read_checkpoint_request, workspaces_read_checkpoint_result, workspaces_read_file_request, workspaces_read_file_result, workspaces_save_large_paste_request, workspaces_save_large_paste_result, workspace_summary_host_type, workspaces_workspace_details_host_type, session_context_info, task_progress, workspace_summary) def to_dict(self) -> dict: result: dict = {} @@ -20934,6 +21095,7 @@ def to_dict(self) -> dict: result["McpStopServerRequest"] = to_class(MCPStopServerRequest, self.mcp_stop_server_request) result["McpTools"] = to_class(MCPTools, self.mcp_tools) result["McpUnregisterExternalClientRequest"] = to_class(MCPUnregisterExternalClientRequest, self.mcp_unregister_external_client_request) + result["MemoryConfiguration"] = to_class(MemoryConfiguration, self.memory_configuration) result["MetadataContextInfoRequest"] = to_class(MetadataContextInfoRequest, self.metadata_context_info_request) result["MetadataContextInfoResult"] = to_class(MetadataContextInfoResult, self.metadata_context_info_result) result["MetadataIsProcessingResult"] = to_class(MetadataIsProcessingResult, self.metadata_is_processing_result) @@ -21105,8 +21267,13 @@ def to_dict(self) -> dict: result["PollSpawnedSessionsResult"] = to_class(PollSpawnedSessionsResult, self.poll_spawned_sessions_result) result["ProviderConfig"] = to_class(ProviderConfig, self.provider_config) result["ProviderConfigAzure"] = to_class(ProviderConfigAzure, self.provider_config_azure) - result["ProviderConfigType"] = to_enum(ProviderConfigType, self.provider_config_type) - result["ProviderConfigWireApi"] = to_enum(ProviderConfigWireAPI, self.provider_config_wire_api) + result["ProviderConfigType"] = to_enum(ProviderType, self.provider_config_type) + result["ProviderConfigWireApi"] = to_enum(ProviderWireAPI, self.provider_config_wire_api) + result["ProviderEndpoint"] = to_class(ProviderEndpoint, self.provider_endpoint) + result["ProviderEndpointType"] = to_enum(ProviderType, self.provider_endpoint_type) + result["ProviderEndpointWireApi"] = to_enum(ProviderWireAPI, self.provider_endpoint_wire_api) + result["ProviderGetEndpointRequest"] = to_class(ProviderGetEndpointRequest, self.provider_get_endpoint_request) + result["ProviderSessionToken"] = to_class(ProviderSessionToken, self.provider_session_token) result["PushAttachment"] = (self.push_attachment).to_dict() result["PushAttachmentBlob"] = to_class(PushAttachmentBlob, self.push_attachment_blob) result["PushAttachmentDirectory"] = to_class(PushAttachmentDirectory, self.push_attachment_directory) @@ -21659,6 +21826,10 @@ def _load_TaskInfo(obj: Any) -> "TaskInfo": PermissionsConfigureAdditionalContentExclusionPolicyScope = AdditionalContentExclusionPolicyScope PermissionsSetAllowAllSource = PermissionsSetAAllSource PermissionsSetApproveAllSource = PermissionsSetAAllSource +ProviderConfigType = ProviderType +ProviderConfigWireApi = ProviderWireAPI +ProviderEndpointType = ProviderType +ProviderEndpointWireApi = ProviderWireAPI RemoteSessionMetadataTaskType = TaskType SessionContextHostType = HostType SessionMcpAppsCallToolResult = dict @@ -22631,6 +22802,19 @@ async def reload(self, params: PluginsReloadRequest | None = None, *, timeout: f await self._client.request("session.plugins.reload", params_dict, **_timeout_kwargs(timeout)) +# Experimental: this API group is experimental and may change or be removed. +class ProviderApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def get_endpoint(self, params: ProviderGetEndpointRequest | None = None, *, timeout: float | None = None) -> ProviderEndpoint: + "Returns the provider endpoint and credentials the session is currently configured to talk to, so the caller can make inference calls directly against the same backend the session uses.\n\nArgs:\n params: Optional model identifier to scope the endpoint snapshot to.\n\nReturns:\n A snapshot of the provider endpoint the session is currently configured to talk to." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} if params is not None else {} + params_dict["sessionId"] = self._session_id + return ProviderEndpoint.from_dict(await self._client.request("session.provider.getEndpoint", params_dict, **_timeout_kwargs(timeout))) + + # Experimental: this API group is experimental and may change or be removed. class OptionsApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -23210,6 +23394,7 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self.skills = SkillsApi(client, session_id) self.mcp = McpApi(client, session_id) self.plugins = PluginsApi(client, session_id) + self.provider = ProviderApi(client, session_id) self.options = OptionsApi(client, session_id) self.lsp = LspApi(client, session_id) self.extensions = ExtensionsApi(client, session_id) @@ -23753,6 +23938,7 @@ async def handle_canvas_action_invoke(params: dict) -> dict | None: "McpExecuteSamplingResult", "McpOauthApi", "McpServerAuthConfig", + "MemoryConfiguration", "MetadataApi", "MetadataContextInfoRequest", "MetadataContextInfoResult", @@ -23961,10 +24147,18 @@ async def handle_canvas_action_invoke(params: dict) -> dict | None: "PluginsUninstallRequest", "PluginsUpdateRequest", "PollSpawnedSessionsResult", + "ProviderApi", "ProviderConfig", "ProviderConfigAzure", "ProviderConfigType", - "ProviderConfigWireAPI", + "ProviderConfigWireApi", + "ProviderEndpoint", + "ProviderEndpointType", + "ProviderEndpointWireApi", + "ProviderGetEndpointRequest", + "ProviderSessionToken", + "ProviderType", + "ProviderWireAPI", "PurpleSource", "PushAttachment", "PushAttachmentBlob", diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py index f2e155f49..3b192890f 100644 --- a/python/copilot/generated/session_events.py +++ b/python/copilot/generated/session_events.py @@ -285,6 +285,46 @@ def to_dict(self) -> dict: return {_compat_to_json_key(key): _compat_to_json_value(value) for key, value in self._values.items() if value is not None} +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class AssistantMessageServerTools: + "Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping" + provider: str + advisor_model: str | None = None + function_call_namespaces: dict[str, str] | None = None + items: list[Any] | None = None + raw_content_blocks: list[Any] | None = None + + @staticmethod + def from_dict(obj: Any) -> "AssistantMessageServerTools": + assert isinstance(obj, dict) + provider = from_str(obj.get("provider")) + advisor_model = from_union([from_none, from_str], obj.get("advisorModel")) + function_call_namespaces = from_union([from_none, lambda x: from_dict(from_str, x)], obj.get("functionCallNamespaces")) + items = from_union([from_none, lambda x: from_list(lambda x: x, x)], obj.get("items")) + raw_content_blocks = from_union([from_none, lambda x: from_list(lambda x: x, x)], obj.get("rawContentBlocks")) + return AssistantMessageServerTools( + provider=provider, + advisor_model=advisor_model, + function_call_namespaces=function_call_namespaces, + items=items, + raw_content_blocks=raw_content_blocks, + ) + + def to_dict(self) -> dict: + result: dict = {} + result["provider"] = from_str(self.provider) + if self.advisor_model is not None: + result["advisorModel"] = from_union([from_none, from_str], self.advisor_model) + if self.function_call_namespaces is not None: + result["functionCallNamespaces"] = from_union([from_none, lambda x: from_dict(from_str, x)], self.function_call_namespaces) + if self.items is not None: + result["items"] = from_union([from_none, lambda x: from_list(lambda x: x, x)], self.items) + if self.raw_content_blocks is not None: + result["rawContentBlocks"] = from_union([from_none, lambda x: from_list(lambda x: x, x)], self.raw_content_blocks) + return result + + @dataclass class AbortData: "Turn abort information including the reason for termination" @@ -328,10 +368,6 @@ class AssistantMessageData: "Assistant response containing text content, optional tool requests, and interaction metadata" content: str message_id: str - # Experimental: this field is part of an experimental API and may change or be removed. - anthropic_advisor_blocks: list[Any] | None = None - # Experimental: this field is part of an experimental API and may change or be removed. - anthropic_advisor_model: str | None = None api_call_id: str | None = None encrypted_content: str | None = None interaction_id: str | None = None @@ -343,6 +379,7 @@ class AssistantMessageData: reasoning_opaque: str | None = None reasoning_text: str | None = None request_id: str | None = None + server_tools: AssistantMessageServerTools | None = None service_request_id: str | None = None tool_requests: list[AssistantMessageToolRequest] | None = None turn_id: str | None = None @@ -352,8 +389,6 @@ def from_dict(obj: Any) -> "AssistantMessageData": assert isinstance(obj, dict) content = from_str(obj.get("content")) message_id = from_str(obj.get("messageId")) - anthropic_advisor_blocks = from_union([from_none, lambda x: from_list(lambda x: x, x)], obj.get("anthropicAdvisorBlocks")) - anthropic_advisor_model = from_union([from_none, from_str], obj.get("anthropicAdvisorModel")) api_call_id = from_union([from_none, from_str], obj.get("apiCallId")) encrypted_content = from_union([from_none, from_str], obj.get("encryptedContent")) interaction_id = from_union([from_none, from_str], obj.get("interactionId")) @@ -364,14 +399,13 @@ def from_dict(obj: Any) -> "AssistantMessageData": reasoning_opaque = from_union([from_none, from_str], obj.get("reasoningOpaque")) reasoning_text = from_union([from_none, from_str], obj.get("reasoningText")) request_id = from_union([from_none, from_str], obj.get("requestId")) + server_tools = from_union([from_none, AssistantMessageServerTools.from_dict], obj.get("serverTools")) service_request_id = from_union([from_none, from_str], obj.get("serviceRequestId")) tool_requests = from_union([from_none, lambda x: from_list(AssistantMessageToolRequest.from_dict, x)], obj.get("toolRequests")) turn_id = from_union([from_none, from_str], obj.get("turnId")) return AssistantMessageData( content=content, message_id=message_id, - anthropic_advisor_blocks=anthropic_advisor_blocks, - anthropic_advisor_model=anthropic_advisor_model, api_call_id=api_call_id, encrypted_content=encrypted_content, interaction_id=interaction_id, @@ -382,6 +416,7 @@ def from_dict(obj: Any) -> "AssistantMessageData": reasoning_opaque=reasoning_opaque, reasoning_text=reasoning_text, request_id=request_id, + server_tools=server_tools, service_request_id=service_request_id, tool_requests=tool_requests, turn_id=turn_id, @@ -391,10 +426,6 @@ def to_dict(self) -> dict: result: dict = {} result["content"] = from_str(self.content) result["messageId"] = from_str(self.message_id) - if self.anthropic_advisor_blocks is not None: - result["anthropicAdvisorBlocks"] = from_union([from_none, lambda x: from_list(lambda x: x, x)], self.anthropic_advisor_blocks) - if self.anthropic_advisor_model is not None: - result["anthropicAdvisorModel"] = from_union([from_none, from_str], self.anthropic_advisor_model) if self.api_call_id is not None: result["apiCallId"] = from_union([from_none, from_str], self.api_call_id) if self.encrypted_content is not None: @@ -415,6 +446,8 @@ def to_dict(self) -> dict: result["reasoningText"] = from_union([from_none, from_str], self.reasoning_text) if self.request_id is not None: result["requestId"] = from_union([from_none, from_str], self.request_id) + if self.server_tools is not None: + result["serverTools"] = from_union([from_none, lambda x: to_class(AssistantMessageServerTools, x)], self.server_tools) if self.service_request_id is not None: result["serviceRequestId"] = from_union([from_none, from_str], self.service_request_id) if self.tool_requests is not None: @@ -7331,6 +7364,7 @@ def session_event_to_dict(x: SessionEvent) -> Any: "AssistantIntentData", "AssistantMessageData", "AssistantMessageDeltaData", + "AssistantMessageServerTools", "AssistantMessageStartData", "AssistantMessageToolRequest", "AssistantMessageToolRequestType", diff --git a/rust/src/generated/api_types.rs b/rust/src/generated/api_types.rs index f52c06651..55c092128 100644 --- a/rust/src/generated/api_types.rs +++ b/rust/src/generated/api_types.rs @@ -310,6 +310,8 @@ pub mod rpc_methods { pub const SESSION_PLUGINS_LIST: &str = "session.plugins.list"; /// `session.plugins.reload` pub const SESSION_PLUGINS_RELOAD: &str = "session.plugins.reload"; + /// `session.provider.getEndpoint` + pub const SESSION_PROVIDER_GETENDPOINT: &str = "session.provider.getEndpoint"; /// `session.options.update` pub const SESSION_OPTIONS_UPDATE: &str = "session.options.update"; /// `session.lsp.initialize` @@ -1878,6 +1880,9 @@ pub struct SlashCommandInfo { pub kind: SlashCommandKind, /// Canonical command name without a leading slash pub name: String, + /// Whether the command may be the target of `/every` / `/after` schedules. Resolution happens at every tick, so only set this when the command is safe to re-invoke and produces an agent prompt. + #[serde(skip_serializing_if = "Option::is_none")] + pub schedulable: Option, } /// Slash commands available in the session, after applying any include/exclude filters. @@ -4464,6 +4469,21 @@ pub(crate) struct McpUnregisterExternalClientRequest { pub server_name: String, } +/// Memory configuration for this session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MemoryConfiguration { + /// Whether memory is enabled for the session. + pub enabled: bool, +} + /// Model identifier and token limits used to compute the context-info breakdown. /// ///
@@ -7134,6 +7154,73 @@ pub struct ProviderConfig { pub wire_model: Option, } +/// Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ProviderSessionToken { + /// When the token expires, if known. Callers should refresh by calling `getEndpoint` again before this time, or reactively on any 401/403 response from `baseUrl`. + #[serde(skip_serializing_if = "Option::is_none")] + pub expires_at: Option, + /// HTTP header name the token must be sent under. + pub header: String, + /// The model the token is bound to, when applicable. When set, the token is only valid for requests against this model. + #[serde(skip_serializing_if = "Option::is_none")] + pub model: Option, + /// The short-lived token value. + pub token: String, +} + +/// A snapshot of the provider endpoint the session is currently configured to talk to. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ProviderEndpoint { + /// A credential the caller should use with this endpoint. Omitted only when the endpoint accepts unauthenticated requests. + #[serde(skip_serializing_if = "Option::is_none")] + pub api_key: Option, + /// Base URL to pass to the LLM client library. + pub base_url: String, + /// HTTP headers the caller must include on every outbound request. + pub headers: HashMap, + /// Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. + #[serde(skip_serializing_if = "Option::is_none")] + pub session_token: Option, + /// Provider family. Matches the `type` field of a BYOK provider config. + pub r#type: ProviderEndpointType, + /// Wire API to be used, when required for the provider type. + #[serde(skip_serializing_if = "Option::is_none")] + pub wire_api: Option, +} + +/// Optional model identifier to scope the endpoint snapshot to. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ProviderGetEndpointRequest { + /// Model identifier the caller intends to use against the returned endpoint. Used to pick the correct wire shape. Omit to use whichever model the session is currently using. + #[serde(skip_serializing_if = "Option::is_none")] + pub model_id: Option, +} + /// Blob attachment with inline base64-encoded data /// ///
@@ -9129,6 +9216,9 @@ pub struct SessionOpenOptions { /// Identifier sent to LSP-style integrations. #[serde(skip_serializing_if = "Option::is_none")] pub lsp_client_name: Option, + /// Memory configuration for this session. + #[serde(skip_serializing_if = "Option::is_none")] + pub memory: Option, /// Initial model identifier. #[serde(skip_serializing_if = "Option::is_none")] pub model: Option, @@ -14275,6 +14365,34 @@ pub struct SessionPluginsListResult { pub plugins: Vec, } +/// A snapshot of the provider endpoint the session is currently configured to talk to. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionProviderGetEndpointResult { + /// A credential the caller should use with this endpoint. Omitted only when the endpoint accepts unauthenticated requests. + #[serde(skip_serializing_if = "Option::is_none")] + pub api_key: Option, + /// Base URL to pass to the LLM client library. + pub base_url: String, + /// HTTP headers the caller must include on every outbound request. + pub headers: HashMap, + /// Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. + #[serde(skip_serializing_if = "Option::is_none")] + pub session_token: Option, + /// Provider family. Matches the `type` field of a BYOK provider config. + pub r#type: ProviderEndpointType, + /// Wire API to be used, when required for the provider type. + #[serde(skip_serializing_if = "Option::is_none")] + pub wire_api: Option, +} + /// Indicates whether the session options patch was applied successfully. /// ///
@@ -17853,6 +17971,53 @@ pub enum ProviderConfigWireApi { Unknown, } +/// Provider family. Matches the `type` field of a BYOK provider config. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum ProviderEndpointType { + /// OpenAI-compatible endpoint (use the OpenAI client library). + #[serde(rename = "openai")] + Openai, + /// Azure OpenAI endpoint (use the OpenAI client library with the Azure base URL). + #[serde(rename = "azure")] + Azure, + /// Anthropic endpoint (use the Anthropic client library). + #[serde(rename = "anthropic")] + Anthropic, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Wire API to be used, when required for the provider type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum ProviderEndpointWireApi { + /// Classic chat-completions request shape. + #[serde(rename = "completions")] + Completions, + /// Newer responses request shape. + #[serde(rename = "responses")] + Responses, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + /// Attachment type discriminator #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum PushAttachmentBlobType { diff --git a/rust/src/generated/rpc.rs b/rust/src/generated/rpc.rs index cd5132f48..e75ef9e35 100644 --- a/rust/src/generated/rpc.rs +++ b/rust/src/generated/rpc.rs @@ -2209,6 +2209,13 @@ impl<'a> SessionRpc<'a> { } } + /// `session.provider.*` sub-namespace. + pub fn provider(&self) -> SessionRpcProvider<'a> { + SessionRpcProvider { + session: self.session, + } + } + /// `session.queue.*` sub-namespace. pub fn queue(&self) -> SessionRpcQueue<'a> { SessionRpcQueue { @@ -5944,6 +5951,72 @@ impl<'a> SessionRpcPlugins<'a> { } } +/// `session.provider.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcProvider<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcProvider<'a> { + /// Returns the provider endpoint and credentials the session is currently configured to talk to, so the caller can make inference calls directly against the same backend the session uses. + /// + /// Wire method: `session.provider.getEndpoint`. + /// + /// # Returns + /// + /// A snapshot of the provider endpoint the session is currently configured to talk to. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_endpoint(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_PROVIDER_GETENDPOINT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Returns the provider endpoint and credentials the session is currently configured to talk to, so the caller can make inference calls directly against the same backend the session uses. + /// + /// Wire method: `session.provider.getEndpoint`. + /// + /// # Parameters + /// + /// * `params` - Optional model identifier to scope the endpoint snapshot to. + /// + /// # Returns + /// + /// A snapshot of the provider endpoint the session is currently configured to talk to. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_endpoint_with_params( + &self, + params: ProviderGetEndpointRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_PROVIDER_GETENDPOINT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + /// `session.queue.*` RPCs. #[derive(Clone, Copy)] pub struct SessionRpcQueue<'a> { diff --git a/rust/src/generated/session_events.rs b/rust/src/generated/session_events.rs index e20d7d6ef..6b4f83325 100644 --- a/rust/src/generated/session_events.rs +++ b/rust/src/generated/session_events.rs @@ -1210,6 +1210,28 @@ pub struct AssistantStreamingDeltaData { pub total_response_size_bytes: i64, } +/// Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AssistantMessageServerTools { + #[serde(skip_serializing_if = "Option::is_none")] + pub advisor_model: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub function_call_namespaces: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub items: Option>, + pub provider: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub raw_content_blocks: Option>, +} + /// A tool invocation request from the assistant #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -1242,26 +1264,6 @@ pub struct AssistantMessageToolRequest { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AssistantMessageData { - /// Raw Anthropic content array with advisor blocks (server_tool_use, advisor_tool_result) for verbatim round-tripping - /// - ///
- /// - /// **Experimental.** This type is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. - /// - ///
- #[serde(skip_serializing_if = "Option::is_none")] - pub anthropic_advisor_blocks: Option>, - /// Anthropic advisor model ID used for this response, for timeline display on replay - /// - ///
- /// - /// **Experimental.** This type is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. - /// - ///
- #[serde(skip_serializing_if = "Option::is_none")] - pub anthropic_advisor_model: Option, /// Provider's completion / response identifier; shared across all chunks of a single API call. Used to group multi-chunk assistant utterances. #[serde(skip_serializing_if = "Option::is_none")] pub api_call_id: Option, @@ -1298,6 +1300,9 @@ pub struct AssistantMessageData { /// GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs #[serde(skip_serializing_if = "Option::is_none")] pub request_id: Option, + /// Neutral provider-tagged server-side tool-use payload (tool search, advisor) for verbatim round-tripping + #[serde(skip_serializing_if = "Option::is_none")] + pub server_tools: Option, /// Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation #[serde(skip_serializing_if = "Option::is_none")] pub service_request_id: Option, @@ -1930,7 +1935,7 @@ pub struct SkillInvokedData { /// Version of the plugin this skill originated from, when applicable #[serde(skip_serializing_if = "Option::is_none")] pub plugin_version: Option, - /// Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), personal-claude (~/.claude/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill) + /// Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill) #[serde(skip_serializing_if = "Option::is_none")] pub source: Option, /// What triggered the skill invocation: `user-invoked` (explicit user action, such as via a slash command or UI affordance), `agent-invoked` (agent requested the skill), or `context-load` (loaded as part of another context, such as preloading skills configured on a custom agent or subagent) diff --git a/rust/src/types.rs b/rust/src/types.rs index 8b9b5960a..765c28bed 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -4173,6 +4173,8 @@ pub use crate::generated::api_types::{ Model, ModelBilling, ModelCapabilities, ModelCapabilitiesLimits, ModelCapabilitiesLimitsVision, ModelCapabilitiesSupports, ModelList, ModelPolicy, PermissionDecision, PermissionDecisionApproveOnce, PermissionDecisionReject, PermissionDecisionUserNotAvailable, + ProviderEndpoint, ProviderEndpointType, ProviderEndpointWireApi, ProviderGetEndpointRequest, + ProviderSessionToken, }; /// Permission categories the CLI may request approval for. From 1fd5534c00cdac45a0f9fe318a2d9f48552b4376 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 12 Jun 2026 12:22:15 +0100 Subject: [PATCH 08/10] Add Go/Python/Rust E2E coverage for session.provider.getEndpoint Mirrors the existing nodejs provider_endpoint.e2e.test.ts in the three remaining language SDKs, covering both the BYOK and CAPI branches. Also drops a speculative phrase from the existing .NET test's XML doc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/E2E/ProviderEndpointE2ETests.cs | 6 +- go/internal/e2e/provider_endpoint_e2e_test.go | 144 ++++++++++++ python/e2e/test_provider_endpoint_e2e.py | 112 +++++++++ rust/tests/e2e.rs | 2 + rust/tests/e2e/provider_endpoint.rs | 219 ++++++++++++++++++ 5 files changed, 479 insertions(+), 4 deletions(-) create mode 100644 go/internal/e2e/provider_endpoint_e2e_test.go create mode 100644 python/e2e/test_provider_endpoint_e2e.py create mode 100644 rust/tests/e2e/provider_endpoint.rs diff --git a/dotnet/test/E2E/ProviderEndpointE2ETests.cs b/dotnet/test/E2E/ProviderEndpointE2ETests.cs index d11e85303..5f90ccdb6 100644 --- a/dotnet/test/E2E/ProviderEndpointE2ETests.cs +++ b/dotnet/test/E2E/ProviderEndpointE2ETests.cs @@ -14,10 +14,8 @@ public class ProviderEndpointE2ETests(E2ETestFixture fixture, ITestOutputHelper : E2ETestBase(fixture, "provider-endpoint", output) { /// - /// Creates a client with the provider-endpoint API opt-in env var set. The - /// runtime gates `session.provider.getEndpoint` behind - /// COPILOT_ALLOW_GET_PROVIDER_ENDPOINT so callers don't depend on it - /// accidentally while the API is still experimental. + /// Creates a client with the provider-endpoint API opt-in env var + /// (COPILOT_ALLOW_GET_PROVIDER_ENDPOINT) set on the CLI subprocess. /// private CopilotClient CreateProviderEndpointClient() { diff --git a/go/internal/e2e/provider_endpoint_e2e_test.go b/go/internal/e2e/provider_endpoint_e2e_test.go new file mode 100644 index 000000000..d5d9c019d --- /dev/null +++ b/go/internal/e2e/provider_endpoint_e2e_test.go @@ -0,0 +1,144 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +package e2e + +import ( + "regexp" + "strings" + "testing" + + copilot "github.com/github/copilot-sdk/go" + "github.com/github/copilot-sdk/go/internal/e2e/testharness" + "github.com/github/copilot-sdk/go/rpc" +) + +// session.provider.getEndpoint is gated behind COPILOT_ALLOW_GET_PROVIDER_ENDPOINT; +// the harness env passed to the CLI subprocess opts in for this test file. +func TestProviderEndpointE2E(t *testing.T) { + ctx := testharness.NewTestContext(t) + + client := ctx.NewClient(func(opts *copilot.ClientOptions) { + opts.Env = append(opts.Env, "COPILOT_ALLOW_GET_PROVIDER_ENDPOINT=true") + }) + t.Cleanup(func() { client.ForceStop() }) + + t.Run("returns the BYOK provider endpoint when a custom provider is configured", func(t *testing.T) { + ctx.ConfigureForTest(t) + session, err := client.CreateSession(t.Context(), &copilot.SessionConfig{ + OnPermissionRequest: copilot.PermissionHandler.ApproveAll, + Provider: &copilot.ProviderConfig{ + Type: "openai", + WireAPI: "completions", + BaseURL: "https://api.example.test/v1", + APIKey: "byok-secret", + Headers: map[string]string{"X-Custom-Header": "byok-yes"}, + }, + }) + if err != nil { + t.Fatalf("create session: %v", err) + } + // disconnect may fail since the BYOK provider URL is fake. + defer func() { _ = session.Disconnect() }() + + endpoint, err := session.RPC.Provider.GetEndpoint(t.Context()) + if err != nil { + t.Fatalf("getEndpoint: %v", err) + } + + if endpoint.Type != rpc.ProviderEndpointTypeOpenai { + t.Errorf("Type: want %q, got %q", rpc.ProviderEndpointTypeOpenai, endpoint.Type) + } + if endpoint.WireAPI == nil || *endpoint.WireAPI != rpc.ProviderEndpointWireAPICompletions { + t.Errorf("WireAPI: want %q, got %v", rpc.ProviderEndpointWireAPICompletions, endpoint.WireAPI) + } + if endpoint.BaseURL != "https://api.example.test/v1" { + t.Errorf("BaseURL: got %q", endpoint.BaseURL) + } + if endpoint.APIKey == nil || *endpoint.APIKey != "byok-secret" { + t.Errorf("APIKey: got %v", endpoint.APIKey) + } + if got := endpoint.Headers["X-Custom-Header"]; got != "byok-yes" { + t.Errorf("X-Custom-Header: got %q", got) + } + // BYOK sessions never issue a CAPI session token. + if endpoint.SessionToken != nil { + t.Errorf("SessionToken: expected nil, got %+v", endpoint.SessionToken) + } + }) + + t.Run("returns the CAPI provider endpoint for an OAuth-authenticated session", func(t *testing.T) { + ctx.ConfigureForTest(t) + session, err := client.CreateSession(t.Context(), &copilot.SessionConfig{ + OnPermissionRequest: copilot.PermissionHandler.ApproveAll, + }) + if err != nil { + t.Fatalf("create session: %v", err) + } + defer func() { + if err := session.Disconnect(); err != nil { + t.Errorf("disconnect: %v", err) + } + }() + + endpoint, err := session.RPC.Provider.GetEndpoint(t.Context()) + if err != nil { + t.Fatalf("getEndpoint: %v", err) + } + + switch endpoint.Type { + case rpc.ProviderEndpointTypeOpenai, rpc.ProviderEndpointTypeAzure, rpc.ProviderEndpointTypeAnthropic: + default: + t.Errorf("unexpected Type %q", endpoint.Type) + } + // wireApi is omitted for anthropic; otherwise one of the OpenAI shapes. + if endpoint.Type != rpc.ProviderEndpointTypeAnthropic { + if endpoint.WireAPI == nil || + (*endpoint.WireAPI != rpc.ProviderEndpointWireAPICompletions && + *endpoint.WireAPI != rpc.ProviderEndpointWireAPIResponses) { + t.Errorf("unexpected WireAPI %v for type %q", endpoint.WireAPI, endpoint.Type) + } + } + + // CAPI baseUrl is the (proxy) Copilot API URL injected by the harness. + if !strings.HasPrefix(endpoint.BaseURL, "http://") && !strings.HasPrefix(endpoint.BaseURL, "https://") { + t.Errorf("BaseURL not an http(s) URL: %q", endpoint.BaseURL) + } + + // For CAPI OAuth sessions the apiKey is the resolved GitHub bearer. + if endpoint.APIKey == nil || len(*endpoint.APIKey) == 0 { + t.Fatalf("APIKey should be a non-empty string, got %v", endpoint.APIKey) + } + + // Standard CAPI headers must be present, and Authorization is surfaced + // as the runtime sends it (`Bearer `). + if endpoint.Headers["Copilot-Integration-Id"] == "" { + t.Errorf("Copilot-Integration-Id header missing") + } + if ua := endpoint.Headers["User-Agent"]; !regexp.MustCompile(`(?i)Copilot`).MatchString(ua) { + t.Errorf("User-Agent should mention Copilot, got %q", ua) + } + if endpoint.Headers["X-GitHub-Api-Version"] == "" { + t.Errorf("X-GitHub-Api-Version header missing") + } + if !regexp.MustCompile(`[0-9a-f-]{8,}`).MatchString(endpoint.Headers["X-Interaction-Id"]) { + t.Errorf("X-Interaction-Id should match interaction-id format, got %q", endpoint.Headers["X-Interaction-Id"]) + } + if want, got := "Bearer "+*endpoint.APIKey, endpoint.Headers["Authorization"]; want != got { + t.Errorf("Authorization: want %q, got %q", want, got) + } + + // When the omit-modelId path returned an auto-mode session token, it + // must use the documented header name. The harness may have a non-auto + // model selected, in which case the field is simply omitted. + if endpoint.SessionToken != nil { + if endpoint.SessionToken.Header != "Copilot-Session-Token" { + t.Errorf("SessionToken.Header: got %q", endpoint.SessionToken.Header) + } + if endpoint.SessionToken.Token == "" { + t.Errorf("SessionToken.Token should be non-empty") + } + } + }) +} diff --git a/python/e2e/test_provider_endpoint_e2e.py b/python/e2e/test_provider_endpoint_e2e.py new file mode 100644 index 000000000..7496e381f --- /dev/null +++ b/python/e2e/test_provider_endpoint_e2e.py @@ -0,0 +1,112 @@ +"""E2E tests for session.provider.getEndpoint.""" + +# session.provider.getEndpoint is gated behind COPILOT_ALLOW_GET_PROVIDER_ENDPOINT; +# the harness env passed to the CLI subprocess opts in for this test file. + +import re + +import pytest + +from copilot.client import CopilotClient, RuntimeConnection +from copilot.generated.rpc import ProviderType, ProviderWireAPI +from copilot.session import PermissionHandler + +from .testharness import E2ETestContext + +pytestmark = pytest.mark.asyncio(loop_scope="module") + + +@pytest.fixture(scope="module") +async def provider_ctx(ctx: E2ETestContext): + env = {**ctx.get_env(), "COPILOT_ALLOW_GET_PROVIDER_ENDPOINT": "true"} + client = CopilotClient( + connection=RuntimeConnection.for_stdio(path=ctx.cli_path), + working_directory=ctx.work_dir, + env=env, + github_token=env["GITHUB_TOKEN"], + ) + try: + yield ctx, client + finally: + await client.stop() + + +class TestProviderEndpoint: + async def test_returns_byok_provider_endpoint_when_custom_provider_is_configured( + self, provider_ctx: tuple[E2ETestContext, CopilotClient] + ): + _, client = provider_ctx + session = await client.create_session( + on_permission_request=PermissionHandler.approve_all, + provider={ + "type": "openai", + "wire_api": "completions", + "base_url": "https://api.example.test/v1", + "api_key": "byok-secret", + "headers": {"X-Custom-Header": "byok-yes"}, + }, + ) + + try: + endpoint = await session.rpc.provider.get_endpoint() + + assert endpoint.type == ProviderType.OPENAI + assert endpoint.wire_api == ProviderWireAPI.COMPLETIONS + assert endpoint.base_url == "https://api.example.test/v1" + assert endpoint.api_key == "byok-secret" + assert endpoint.headers["X-Custom-Header"] == "byok-yes" + # BYOK sessions never issue a CAPI session token. + assert endpoint.session_token is None + finally: + try: + await session.disconnect() + except Exception: + pass # disconnect may fail since the BYOK provider URL is fake + + async def test_returns_capi_provider_endpoint_for_oauth_authenticated_session( + self, provider_ctx: tuple[E2ETestContext, CopilotClient] + ): + _, client = provider_ctx + session = await client.create_session( + on_permission_request=PermissionHandler.approve_all, + ) + + try: + endpoint = await session.rpc.provider.get_endpoint() + + assert endpoint.type in ( + ProviderType.OPENAI, + ProviderType.AZURE, + ProviderType.ANTHROPIC, + ) + # wire_api is omitted for anthropic; otherwise one of the OpenAI shapes. + if endpoint.type != ProviderType.ANTHROPIC: + assert endpoint.wire_api in ( + ProviderWireAPI.COMPLETIONS, + ProviderWireAPI.RESPONSES, + ) + + # CAPI baseUrl is the (proxy) Copilot API URL injected by the harness. + assert re.match(r"^https?://", endpoint.base_url) + + # For CAPI OAuth sessions the api_key is the resolved GitHub bearer. + assert isinstance(endpoint.api_key, str) + assert len(endpoint.api_key) > 0 + + # Standard CAPI headers must be present, and Authorization is + # surfaced as the runtime sends it (`Bearer `). + assert isinstance(endpoint.headers["Copilot-Integration-Id"], str) + assert re.search(r"Copilot", endpoint.headers["User-Agent"], re.IGNORECASE) + assert isinstance(endpoint.headers["X-GitHub-Api-Version"], str) + assert re.search(r"[0-9a-f-]{8,}", endpoint.headers["X-Interaction-Id"]) + assert endpoint.headers["Authorization"] == f"Bearer {endpoint.api_key}" + + # When the omit-model_id path returned an auto-mode session token, + # it must use the documented header name. The harness may have a + # non-auto model selected, in which case the field is simply + # omitted. + if endpoint.session_token is not None: + assert endpoint.session_token.header == "Copilot-Session-Token" + assert len(endpoint.session_token.token) > 0 + finally: + await session.disconnect() diff --git a/rust/tests/e2e.rs b/rust/tests/e2e.rs index 40bb5adb7..29137d13d 100644 --- a/rust/tests/e2e.rs +++ b/rust/tests/e2e.rs @@ -51,6 +51,8 @@ mod per_session_auth; mod permissions; #[path = "e2e/pre_mcp_tool_call_hook.rs"] mod pre_mcp_tool_call_hook; +#[path = "e2e/provider_endpoint.rs"] +mod provider_endpoint; #[path = "e2e/rpc_additional_edge_cases.rs"] mod rpc_additional_edge_cases; #[path = "e2e/rpc_agent.rs"] diff --git a/rust/tests/e2e/provider_endpoint.rs b/rust/tests/e2e/provider_endpoint.rs new file mode 100644 index 000000000..5937f8fcd --- /dev/null +++ b/rust/tests/e2e/provider_endpoint.rs @@ -0,0 +1,219 @@ +use std::collections::HashMap; +use std::ffi::OsString; +use std::sync::Arc; + +use github_copilot_sdk::handler::ApproveAllHandler; +use github_copilot_sdk::{ + ProviderConfig, ProviderEndpointType, ProviderEndpointWireApi, SessionConfig, +}; + +use super::support::{DEFAULT_TEST_TOKEN, with_e2e_context}; + +// session.provider.getEndpoint is gated behind COPILOT_ALLOW_GET_PROVIDER_ENDPOINT; +// the harness env passed to the CLI subprocess opts in for these tests. +fn opt_in_env() -> (OsString, OsString) { + ( + "COPILOT_ALLOW_GET_PROVIDER_ENDPOINT".into(), + "true".into(), + ) +} + +#[tokio::test] +async fn byok_provider_endpoint_returns_configured_endpoint() { + with_e2e_context( + "provider-endpoint", + "byok_provider_endpoint_returns_configured_endpoint", + |ctx| { + Box::pin(async move { + let mut options = ctx.client_options(); + options.env.push(opt_in_env()); + let client = github_copilot_sdk::Client::start(options) + .await + .expect("start client"); + + let mut headers = HashMap::new(); + headers.insert("X-Custom-Header".to_string(), "byok-yes".to_string()); + + let session = client + .create_session( + SessionConfig::default() + .with_permission_handler(Arc::new(ApproveAllHandler)) + .with_provider( + ProviderConfig::new("https://api.example.test/v1") + .with_provider_type("openai") + .with_wire_api("completions") + .with_api_key("byok-secret") + .with_headers(headers), + ), + ) + .await + .expect("create session"); + + let endpoint = session + .rpc() + .provider() + .get_endpoint() + .await + .expect("get_endpoint"); + + assert!( + matches!(endpoint.r#type, ProviderEndpointType::Openai), + "expected type=openai, got {:?}", + endpoint.r#type, + ); + assert!( + matches!(endpoint.wire_api, Some(ProviderEndpointWireApi::Completions)), + "expected wireApi=completions, got {:?}", + endpoint.wire_api, + ); + assert_eq!(endpoint.base_url, "https://api.example.test/v1"); + assert_eq!(endpoint.api_key.as_deref(), Some("byok-secret")); + assert_eq!( + endpoint.headers.get("X-Custom-Header").map(String::as_str), + Some("byok-yes"), + ); + assert!( + endpoint.session_token.is_none(), + "BYOK sessions never issue a CAPI session token", + ); + + // disconnect may fail since the BYOK provider URL is fake + let _ = session.disconnect().await; + client.stop().await.expect("stop client"); + }) + }, + ) + .await; +} + +#[tokio::test] +async fn capi_provider_endpoint_returns_resolved_credentials() { + with_e2e_context( + "provider-endpoint", + "capi_provider_endpoint_returns_resolved_credentials", + |ctx| { + Box::pin(async move { + ctx.set_default_copilot_user(); + let mut options = ctx.client_options().with_github_token(DEFAULT_TEST_TOKEN); + options.env.push(opt_in_env()); + let client = github_copilot_sdk::Client::start(options) + .await + .expect("start client"); + + let session = client + .create_session( + SessionConfig::default() + .with_permission_handler(Arc::new(ApproveAllHandler)), + ) + .await + .expect("create session"); + + let endpoint = session + .rpc() + .provider() + .get_endpoint() + .await + .expect("get_endpoint"); + + assert!( + matches!( + endpoint.r#type, + ProviderEndpointType::Openai + | ProviderEndpointType::Azure + | ProviderEndpointType::Anthropic + ), + "expected type in {{openai, azure, anthropic}}, got {:?}", + endpoint.r#type, + ); + if !matches!(endpoint.r#type, ProviderEndpointType::Anthropic) { + assert!( + matches!( + endpoint.wire_api, + Some(ProviderEndpointWireApi::Completions) + | Some(ProviderEndpointWireApi::Responses) + ), + "expected wireApi in {{completions, responses}}, got {:?}", + endpoint.wire_api, + ); + } + + assert!( + endpoint.base_url.starts_with("http://") + || endpoint.base_url.starts_with("https://"), + "expected http(s) baseUrl, got {}", + endpoint.base_url, + ); + + let api_key = endpoint + .api_key + .as_deref() + .expect("CAPI OAuth session must surface apiKey"); + assert!(!api_key.is_empty(), "apiKey must be non-empty"); + + let integration_id = endpoint + .headers + .get("Copilot-Integration-Id") + .expect("Copilot-Integration-Id header"); + assert!( + !integration_id.is_empty(), + "Copilot-Integration-Id must be non-empty", + ); + + let user_agent = endpoint + .headers + .get("User-Agent") + .expect("User-Agent header"); + assert!( + user_agent.to_ascii_lowercase().contains("copilot"), + "expected User-Agent to mention Copilot, got {user_agent}", + ); + + let api_version = endpoint + .headers + .get("X-GitHub-Api-Version") + .expect("X-GitHub-Api-Version header"); + assert!( + !api_version.is_empty(), + "X-GitHub-Api-Version must be non-empty", + ); + + let interaction_id = endpoint + .headers + .get("X-Interaction-Id") + .expect("X-Interaction-Id header"); + let hex_count = interaction_id + .chars() + .filter(|c| c.is_ascii_hexdigit() || *c == '-') + .count(); + assert!( + hex_count >= 8, + "expected X-Interaction-Id to look like a hex/uuid value, got {interaction_id}", + ); + + let authorization = endpoint + .headers + .get("Authorization") + .expect("Authorization header"); + assert_eq!(authorization, &format!("Bearer {api_key}")); + + if let Some(session_token) = endpoint.session_token.as_ref() { + assert_eq!(session_token.header, "Copilot-Session-Token"); + assert!( + !session_token.token.is_empty(), + "session token must be non-empty", + ); + if let Some(expires_at) = session_token.expires_at.as_deref() { + assert!( + !expires_at.is_empty(), + "expected non-empty expiresAt", + ); + } + } + + session.disconnect().await.expect("disconnect session"); + client.stop().await.expect("stop client"); + }) + }, + ) + .await; +} From 0437b5733848012222e5b10cb66b6de4df8c3b20 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 12 Jun 2026 12:39:36 +0100 Subject: [PATCH 09/10] Add Java E2E coverage for session.provider.getEndpoint Adds the generated bindings for the new session.provider.getEndpoint RPC (spliced into the bundled api.schema.json so unrelated regen drift is excluded) and mirrors the existing nodejs/.NET/Go/Python/Rust provider endpoint E2E tests in Java, covering both the BYOK and CAPI branches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../generated/rpc/ProviderEndpointType.java | 37 +++++ .../rpc/ProviderEndpointWireApi.java | 35 ++++ .../generated/rpc/ProviderSessionToken.java | 34 ++++ .../generated/rpc/SessionProviderApi.java | 42 +++++ .../rpc/SessionProviderGetEndpointParams.java | 30 ++++ .../rpc/SessionProviderGetEndpointResult.java | 41 +++++ .../copilot/generated/rpc/SessionRpc.java | 3 + .../copilot/ProviderEndpointE2ETest.java | 153 ++++++++++++++++++ 8 files changed, 375 insertions(+) create mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java create mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java create mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java create mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java create mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java create mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java create mode 100644 java/src/test/java/com/github/copilot/ProviderEndpointE2ETest.java diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java new file mode 100644 index 000000000..1d4c377bb --- /dev/null +++ b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED FILE - DO NOT EDIT +// Generated from: api.schema.json + +package com.github.copilot.generated.rpc; + +import javax.annotation.processing.Generated; + +/** + * Provider family. Matches the `type` field of a BYOK provider config. + * + * @since 1.0.0 + */ +@javax.annotation.processing.Generated("copilot-sdk-codegen") +public enum ProviderEndpointType { + /** The {@code openai} variant. */ + OPENAI("openai"), + /** The {@code azure} variant. */ + AZURE("azure"), + /** The {@code anthropic} variant. */ + ANTHROPIC("anthropic"); + + private final String value; + ProviderEndpointType(String value) { this.value = value; } + @com.fasterxml.jackson.annotation.JsonValue + public String getValue() { return value; } + @com.fasterxml.jackson.annotation.JsonCreator + public static ProviderEndpointType fromValue(String value) { + for (ProviderEndpointType v : values()) { + if (v.value.equals(value)) return v; + } + throw new IllegalArgumentException("Unknown ProviderEndpointType value: " + value); + } +} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java new file mode 100644 index 000000000..72a5c4d61 --- /dev/null +++ b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED FILE - DO NOT EDIT +// Generated from: api.schema.json + +package com.github.copilot.generated.rpc; + +import javax.annotation.processing.Generated; + +/** + * Wire API to be used, when required for the provider type. + * + * @since 1.0.0 + */ +@javax.annotation.processing.Generated("copilot-sdk-codegen") +public enum ProviderEndpointWireApi { + /** The {@code completions} variant. */ + COMPLETIONS("completions"), + /** The {@code responses} variant. */ + RESPONSES("responses"); + + private final String value; + ProviderEndpointWireApi(String value) { this.value = value; } + @com.fasterxml.jackson.annotation.JsonValue + public String getValue() { return value; } + @com.fasterxml.jackson.annotation.JsonCreator + public static ProviderEndpointWireApi fromValue(String value) { + for (ProviderEndpointWireApi v : values()) { + if (v.value.equals(value)) return v; + } + throw new IllegalArgumentException("Unknown ProviderEndpointWireApi value: " + value); + } +} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java new file mode 100644 index 000000000..0ca81941a --- /dev/null +++ b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED FILE - DO NOT EDIT +// Generated from: api.schema.json + +package com.github.copilot.generated.rpc; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.OffsetDateTime; +import javax.annotation.processing.Generated; + +/** + * Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. + * + * @since 1.0.0 + */ +@javax.annotation.processing.Generated("copilot-sdk-codegen") +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public record ProviderSessionToken( + /** The short-lived token value. */ + @JsonProperty("token") String token, + /** HTTP header name the token must be sent under. */ + @JsonProperty("header") String header, + /** The model the token is bound to, when applicable. When set, the token is only valid for requests against this model. */ + @JsonProperty("model") String model, + /** When the token expires, if known. Callers should refresh by calling `getEndpoint` again before this time, or reactively on any 401/403 response from `baseUrl`. */ + @JsonProperty("expiresAt") OffsetDateTime expiresAt +) { +} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java new file mode 100644 index 000000000..428f916ae --- /dev/null +++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED FILE - DO NOT EDIT +// Generated from: api.schema.json + +package com.github.copilot.generated.rpc; + +import com.github.copilot.CopilotExperimental; +import java.util.concurrent.CompletableFuture; +import javax.annotation.processing.Generated; + +/** + * API methods for the {@code provider} namespace. + * + * @since 1.0.0 + */ +@javax.annotation.processing.Generated("copilot-sdk-codegen") +public final class SessionProviderApi { + + private final RpcCaller caller; + private final String sessionId; + + /** @param caller the RPC transport function */ + SessionProviderApi(RpcCaller caller, String sessionId) { + this.caller = caller; + this.sessionId = sessionId; + } + + /** + * Optional model identifier to scope the endpoint snapshot to. + * + * @apiNote This method is experimental and may change in a future version. + * @since 1.0.0 + */ + @CopilotExperimental + public CompletableFuture getEndpoint() { + return caller.invoke("session.provider.getEndpoint", java.util.Map.of("sessionId", this.sessionId), SessionProviderGetEndpointResult.class); + } + +} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java new file mode 100644 index 000000000..09e992a78 --- /dev/null +++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED FILE - DO NOT EDIT +// Generated from: api.schema.json + +package com.github.copilot.generated.rpc; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.copilot.CopilotExperimental; +import javax.annotation.processing.Generated; + +/** + * Optional model identifier to scope the endpoint snapshot to. + * + * @apiNote This method is experimental and may change in a future version. + * @since 1.0.0 + */ +@CopilotExperimental +@javax.annotation.processing.Generated("copilot-sdk-codegen") +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public record SessionProviderGetEndpointParams( + /** Target session identifier */ + @JsonProperty("sessionId") String sessionId +) { +} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java new file mode 100644 index 000000000..344af3a82 --- /dev/null +++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED FILE - DO NOT EDIT +// Generated from: api.schema.json + +package com.github.copilot.generated.rpc; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.copilot.CopilotExperimental; +import java.util.Map; +import javax.annotation.processing.Generated; + +/** + * A snapshot of the provider endpoint the session is currently configured to talk to. + * + * @apiNote This method is experimental and may change in a future version. + * @since 1.0.0 + */ +@CopilotExperimental +@javax.annotation.processing.Generated("copilot-sdk-codegen") +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public record SessionProviderGetEndpointResult( + /** Provider family. Matches the `type` field of a BYOK provider config. */ + @JsonProperty("type") ProviderEndpointType type, + /** Wire API to be used, when required for the provider type. */ + @JsonProperty("wireApi") ProviderEndpointWireApi wireApi, + /** Base URL to pass to the LLM client library. */ + @JsonProperty("baseUrl") String baseUrl, + /** A credential the caller should use with this endpoint. Omitted only when the endpoint accepts unauthenticated requests. */ + @JsonProperty("apiKey") String apiKey, + /** HTTP headers the caller must include on every outbound request. */ + @JsonProperty("headers") Map headers, + /** Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. */ + @JsonProperty("sessionToken") ProviderSessionToken sessionToken +) { +} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java index bc87f7989..9fa1c1560 100644 --- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java +++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java @@ -89,6 +89,8 @@ public final class SessionRpc { public final SessionRemoteApi remote; /** API methods for the {@code schedule} namespace. */ public final SessionScheduleApi schedule; + /** API methods for the {@code provider} namespace. */ + public final SessionProviderApi provider; /** * Creates a new session RPC client. @@ -129,6 +131,7 @@ public SessionRpc(RpcCaller caller, String sessionId) { this.usage = new SessionUsageApi(caller, sessionId); this.remote = new SessionRemoteApi(caller, sessionId); this.schedule = new SessionScheduleApi(caller, sessionId); + this.provider = new SessionProviderApi(caller, sessionId); } /** diff --git a/java/src/test/java/com/github/copilot/ProviderEndpointE2ETest.java b/java/src/test/java/com/github/copilot/ProviderEndpointE2ETest.java new file mode 100644 index 000000000..08ae25444 --- /dev/null +++ b/java/src/test/java/com/github/copilot/ProviderEndpointE2ETest.java @@ -0,0 +1,153 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +package com.github.copilot; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import com.github.copilot.generated.rpc.ProviderEndpointType; +import com.github.copilot.generated.rpc.ProviderEndpointWireApi; +import com.github.copilot.generated.rpc.ProviderSessionToken; +import com.github.copilot.generated.rpc.SessionProviderGetEndpointResult; +import com.github.copilot.rpc.CopilotClientOptions; +import com.github.copilot.rpc.PermissionHandler; +import com.github.copilot.rpc.ProviderConfig; +import com.github.copilot.rpc.SessionConfig; + +/** + * Tests for the {@code session.provider.getEndpoint} RPC, which surfaces the + * resolved provider endpoint and credentials for either a BYOK or CAPI session. + */ +public class ProviderEndpointE2ETest { + + private static E2ETestContext ctx; + + @BeforeAll + static void setup() throws Exception { + ctx = E2ETestContext.create(); + } + + @AfterAll + static void teardown() throws Exception { + if (ctx != null) { + ctx.close(); + } + } + + // session.provider.getEndpoint is gated behind COPILOT_ALLOW_GET_PROVIDER_ENDPOINT; + // the harness env passed to the CLI subprocess opts in for these tests. + private CopilotClient createProviderEndpointClient() { + Map env = new HashMap<>(ctx.getEnvironment()); + env.put("COPILOT_ALLOW_GET_PROVIDER_ENDPOINT", "true"); + return ctx.createClient(new CopilotClientOptions().setEnvironment(env)); + } + + @Test + void shouldReturnByokProviderEndpointWhenCustomProviderConfigured() throws Exception { + try (CopilotClient client = createProviderEndpointClient()) { + Map customHeaders = new HashMap<>(); + customHeaders.put("X-Custom-Header", "byok-yes"); + + ProviderConfig provider = new ProviderConfig().setType("openai").setWireApi("completions") + .setBaseUrl("https://api.example.test/v1").setApiKey("byok-secret").setHeaders(customHeaders); + + CopilotSession session = client.createSession( + new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL).setProvider(provider)) + .get(); + + try { + SessionProviderGetEndpointResult endpoint = session.getRpc().provider.getEndpoint().get(); + + assertEquals(ProviderEndpointType.OPENAI, endpoint.type()); + assertEquals(ProviderEndpointWireApi.COMPLETIONS, endpoint.wireApi()); + assertEquals("https://api.example.test/v1", endpoint.baseUrl()); + assertEquals("byok-secret", endpoint.apiKey()); + assertEquals("byok-yes", endpoint.headers().get("X-Custom-Header")); + // BYOK sessions never issue a CAPI session token. + assertNull(endpoint.sessionToken(), "BYOK session should not have a session token"); + } finally { + try { + session.close(); + } catch (Exception ignored) { + // disconnect may fail since the BYOK provider URL is fake + } + } + } + } + + @Test + void shouldReturnCapiProviderEndpointForOAuthAuthenticatedSession() throws Exception { + ctx.initializeProxy(); + ctx.setCopilotUserByToken("fake-token-for-e2e-tests", "e2e-user", "individual_pro", ctx.getProxyUrl(), + "https://localhost:1/telemetry", "e2e-tracking-id"); + + try (CopilotClient client = createProviderEndpointClient()) { + CopilotSession session = client + .createSession(new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get(); + + try { + SessionProviderGetEndpointResult endpoint = session.getRpc().provider.getEndpoint().get(); + + assertNotNull(endpoint.type(), "CAPI endpoint should have a provider type"); + assertTrue(endpoint.type() == ProviderEndpointType.OPENAI + || endpoint.type() == ProviderEndpointType.AZURE + || endpoint.type() == ProviderEndpointType.ANTHROPIC, + "expected type in {openai, azure, anthropic}, got " + endpoint.type()); + // wireApi is omitted for anthropic; otherwise one of the OpenAI shapes. + if (endpoint.type() != ProviderEndpointType.ANTHROPIC) { + assertTrue(endpoint.wireApi() == ProviderEndpointWireApi.COMPLETIONS + || endpoint.wireApi() == ProviderEndpointWireApi.RESPONSES, + "expected wireApi in {completions, responses}, got " + endpoint.wireApi()); + } + + // CAPI baseUrl is the (proxy) Copilot API URL injected by the harness. + assertTrue(endpoint.baseUrl().startsWith("http://") || endpoint.baseUrl().startsWith("https://"), + "expected http(s) baseUrl, got " + endpoint.baseUrl()); + + // For CAPI OAuth sessions the apiKey is the resolved GitHub bearer. + assertNotNull(endpoint.apiKey(), "CAPI OAuth session must surface apiKey"); + assertFalse(endpoint.apiKey().isEmpty(), "apiKey must be non-empty"); + + Map headers = endpoint.headers(); + String integrationId = headers.get("Copilot-Integration-Id"); + assertNotNull(integrationId, "Copilot-Integration-Id header must be present"); + assertFalse(integrationId.isEmpty(), "Copilot-Integration-Id must be non-empty"); + + String userAgent = headers.get("User-Agent"); + assertNotNull(userAgent, "User-Agent header must be present"); + assertTrue(userAgent.toLowerCase().contains("copilot"), + "expected User-Agent to mention Copilot, got " + userAgent); + + String apiVersion = headers.get("X-GitHub-Api-Version"); + assertNotNull(apiVersion, "X-GitHub-Api-Version header must be present"); + assertFalse(apiVersion.isEmpty(), "X-GitHub-Api-Version must be non-empty"); + + String interactionId = headers.get("X-Interaction-Id"); + assertNotNull(interactionId, "X-Interaction-Id header must be present"); + assertTrue(interactionId.matches(".*[0-9a-f-]{8,}.*"), + "expected X-Interaction-Id to look like a hex/uuid value, got " + interactionId); + + String authorization = headers.get("Authorization"); + assertEquals("Bearer " + endpoint.apiKey(), authorization); + + ProviderSessionToken sessionToken = endpoint.sessionToken(); + if (sessionToken != null) { + assertEquals("Copilot-Session-Token", sessionToken.header()); + assertFalse(sessionToken.token().isEmpty(), "session token must be non-empty"); + // expiresAt is optional; when present it parses as OffsetDateTime so no + // additional validation is needed. + } + } finally { + session.close(); + } + } + } +} From 283e23daf5e38d126bf3fd08ed817a3d73164660 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 11:40:10 +0000 Subject: [PATCH 10/10] Regenerate Java codegen output Auto-committed by java-codegen-check workflow. --- .../generated/rpc/ProviderEndpointType.java | 37 ---------------- .../rpc/ProviderEndpointWireApi.java | 35 ---------------- .../generated/rpc/ProviderSessionToken.java | 34 --------------- .../generated/rpc/SessionProviderApi.java | 42 ------------------- .../rpc/SessionProviderGetEndpointParams.java | 30 ------------- .../rpc/SessionProviderGetEndpointResult.java | 41 ------------------ .../copilot/generated/rpc/SessionRpc.java | 3 -- 7 files changed, 222 deletions(-) delete mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java delete mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java delete mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java delete mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java delete mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java delete mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java deleted file mode 100644 index 1d4c377bb..000000000 --- a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointType.java +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -// AUTO-GENERATED FILE - DO NOT EDIT -// Generated from: api.schema.json - -package com.github.copilot.generated.rpc; - -import javax.annotation.processing.Generated; - -/** - * Provider family. Matches the `type` field of a BYOK provider config. - * - * @since 1.0.0 - */ -@javax.annotation.processing.Generated("copilot-sdk-codegen") -public enum ProviderEndpointType { - /** The {@code openai} variant. */ - OPENAI("openai"), - /** The {@code azure} variant. */ - AZURE("azure"), - /** The {@code anthropic} variant. */ - ANTHROPIC("anthropic"); - - private final String value; - ProviderEndpointType(String value) { this.value = value; } - @com.fasterxml.jackson.annotation.JsonValue - public String getValue() { return value; } - @com.fasterxml.jackson.annotation.JsonCreator - public static ProviderEndpointType fromValue(String value) { - for (ProviderEndpointType v : values()) { - if (v.value.equals(value)) return v; - } - throw new IllegalArgumentException("Unknown ProviderEndpointType value: " + value); - } -} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java deleted file mode 100644 index 72a5c4d61..000000000 --- a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderEndpointWireApi.java +++ /dev/null @@ -1,35 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -// AUTO-GENERATED FILE - DO NOT EDIT -// Generated from: api.schema.json - -package com.github.copilot.generated.rpc; - -import javax.annotation.processing.Generated; - -/** - * Wire API to be used, when required for the provider type. - * - * @since 1.0.0 - */ -@javax.annotation.processing.Generated("copilot-sdk-codegen") -public enum ProviderEndpointWireApi { - /** The {@code completions} variant. */ - COMPLETIONS("completions"), - /** The {@code responses} variant. */ - RESPONSES("responses"); - - private final String value; - ProviderEndpointWireApi(String value) { this.value = value; } - @com.fasterxml.jackson.annotation.JsonValue - public String getValue() { return value; } - @com.fasterxml.jackson.annotation.JsonCreator - public static ProviderEndpointWireApi fromValue(String value) { - for (ProviderEndpointWireApi v : values()) { - if (v.value.equals(value)) return v; - } - throw new IllegalArgumentException("Unknown ProviderEndpointWireApi value: " + value); - } -} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java b/java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java deleted file mode 100644 index 0ca81941a..000000000 --- a/java/src/generated/java/com/github/copilot/generated/rpc/ProviderSessionToken.java +++ /dev/null @@ -1,34 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -// AUTO-GENERATED FILE - DO NOT EDIT -// Generated from: api.schema.json - -package com.github.copilot.generated.rpc; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.time.OffsetDateTime; -import javax.annotation.processing.Generated; - -/** - * Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. - * - * @since 1.0.0 - */ -@javax.annotation.processing.Generated("copilot-sdk-codegen") -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown = true) -public record ProviderSessionToken( - /** The short-lived token value. */ - @JsonProperty("token") String token, - /** HTTP header name the token must be sent under. */ - @JsonProperty("header") String header, - /** The model the token is bound to, when applicable. When set, the token is only valid for requests against this model. */ - @JsonProperty("model") String model, - /** When the token expires, if known. Callers should refresh by calling `getEndpoint` again before this time, or reactively on any 401/403 response from `baseUrl`. */ - @JsonProperty("expiresAt") OffsetDateTime expiresAt -) { -} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java deleted file mode 100644 index 428f916ae..000000000 --- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderApi.java +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -// AUTO-GENERATED FILE - DO NOT EDIT -// Generated from: api.schema.json - -package com.github.copilot.generated.rpc; - -import com.github.copilot.CopilotExperimental; -import java.util.concurrent.CompletableFuture; -import javax.annotation.processing.Generated; - -/** - * API methods for the {@code provider} namespace. - * - * @since 1.0.0 - */ -@javax.annotation.processing.Generated("copilot-sdk-codegen") -public final class SessionProviderApi { - - private final RpcCaller caller; - private final String sessionId; - - /** @param caller the RPC transport function */ - SessionProviderApi(RpcCaller caller, String sessionId) { - this.caller = caller; - this.sessionId = sessionId; - } - - /** - * Optional model identifier to scope the endpoint snapshot to. - * - * @apiNote This method is experimental and may change in a future version. - * @since 1.0.0 - */ - @CopilotExperimental - public CompletableFuture getEndpoint() { - return caller.invoke("session.provider.getEndpoint", java.util.Map.of("sessionId", this.sessionId), SessionProviderGetEndpointResult.class); - } - -} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java deleted file mode 100644 index 09e992a78..000000000 --- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointParams.java +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -// AUTO-GENERATED FILE - DO NOT EDIT -// Generated from: api.schema.json - -package com.github.copilot.generated.rpc; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.github.copilot.CopilotExperimental; -import javax.annotation.processing.Generated; - -/** - * Optional model identifier to scope the endpoint snapshot to. - * - * @apiNote This method is experimental and may change in a future version. - * @since 1.0.0 - */ -@CopilotExperimental -@javax.annotation.processing.Generated("copilot-sdk-codegen") -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown = true) -public record SessionProviderGetEndpointParams( - /** Target session identifier */ - @JsonProperty("sessionId") String sessionId -) { -} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java deleted file mode 100644 index 344af3a82..000000000 --- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionProviderGetEndpointResult.java +++ /dev/null @@ -1,41 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -// AUTO-GENERATED FILE - DO NOT EDIT -// Generated from: api.schema.json - -package com.github.copilot.generated.rpc; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.github.copilot.CopilotExperimental; -import java.util.Map; -import javax.annotation.processing.Generated; - -/** - * A snapshot of the provider endpoint the session is currently configured to talk to. - * - * @apiNote This method is experimental and may change in a future version. - * @since 1.0.0 - */ -@CopilotExperimental -@javax.annotation.processing.Generated("copilot-sdk-codegen") -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown = true) -public record SessionProviderGetEndpointResult( - /** Provider family. Matches the `type` field of a BYOK provider config. */ - @JsonProperty("type") ProviderEndpointType type, - /** Wire API to be used, when required for the provider type. */ - @JsonProperty("wireApi") ProviderEndpointWireApi wireApi, - /** Base URL to pass to the LLM client library. */ - @JsonProperty("baseUrl") String baseUrl, - /** A credential the caller should use with this endpoint. Omitted only when the endpoint accepts unauthenticated requests. */ - @JsonProperty("apiKey") String apiKey, - /** HTTP headers the caller must include on every outbound request. */ - @JsonProperty("headers") Map headers, - /** Short-lived, rotating credential the caller must send on every request, in addition to `apiKey` if one is present. Omitted when the endpoint does not require one. */ - @JsonProperty("sessionToken") ProviderSessionToken sessionToken -) { -} diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java index 9fa1c1560..bc87f7989 100644 --- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java +++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionRpc.java @@ -89,8 +89,6 @@ public final class SessionRpc { public final SessionRemoteApi remote; /** API methods for the {@code schedule} namespace. */ public final SessionScheduleApi schedule; - /** API methods for the {@code provider} namespace. */ - public final SessionProviderApi provider; /** * Creates a new session RPC client. @@ -131,7 +129,6 @@ public SessionRpc(RpcCaller caller, String sessionId) { this.usage = new SessionUsageApi(caller, sessionId); this.remote = new SessionRemoteApi(caller, sessionId); this.schedule = new SessionScheduleApi(caller, sessionId); - this.provider = new SessionProviderApi(caller, sessionId); } /**