diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 3ba14bebe..cb724b130 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -568,6 +568,7 @@ public async Task CreateSessionAsync(SessionConfig config, Cance config.AvailableTools, config.ExcludedTools, config.Provider, + config.EnableSessionTelemetry, (bool?)true, config.OnUserInputRequest != null ? true : null, hasHooks ? true : null, @@ -694,6 +695,7 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes config.AvailableTools, config.ExcludedTools, config.Provider, + config.EnableSessionTelemetry, (bool?)true, config.OnUserInputRequest != null ? true : null, hasHooks ? true : null, @@ -1781,6 +1783,7 @@ internal record CreateSessionRequest( IList? AvailableTools, IList? ExcludedTools, ProviderConfig? Provider, + bool? EnableSessionTelemetry, bool? RequestPermission, bool? RequestUserInput, bool? Hooks, @@ -1837,6 +1840,7 @@ internal record ResumeSessionRequest( IList? AvailableTools, IList? ExcludedTools, ProviderConfig? Provider, + bool? EnableSessionTelemetry, bool? RequestPermission, bool? RequestUserInput, bool? Hooks, diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 0a09d32b7..7ab7417fb 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -1849,6 +1849,7 @@ protected SessionConfig(SessionConfig? other) OnPermissionRequest = other.OnPermissionRequest; OnUserInputRequest = other.OnUserInputRequest; Provider = other.Provider; + EnableSessionTelemetry = other.EnableSessionTelemetry; ReasoningEffort = other.ReasoningEffort; CreateSessionFsHandler = other.CreateSessionFsHandler; GitHubToken = other.GitHubToken; @@ -1930,6 +1931,17 @@ protected SessionConfig(SessionConfig? other) /// public ProviderConfig? Provider { get; set; } + /// + /// Enables or disables internal session telemetry for this session. + /// When false, disables session telemetry. When null (the default) or true, + /// telemetry is enabled for GitHub-authenticated sessions. + /// When a custom (BYOK) is configured, session telemetry is + /// always disabled regardless of this setting. + /// This is independent of , which configures + /// OpenTelemetry export for observability. + /// + public bool? EnableSessionTelemetry { get; set; } + /// /// Handler for permission requests from the server. /// When provided, the server will call this handler to request permission for operations. @@ -2114,6 +2126,7 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) OnPermissionRequest = other.OnPermissionRequest; OnUserInputRequest = other.OnUserInputRequest; Provider = other.Provider; + EnableSessionTelemetry = other.EnableSessionTelemetry; ReasoningEffort = other.ReasoningEffort; CreateSessionFsHandler = other.CreateSessionFsHandler; GitHubToken = other.GitHubToken; @@ -2164,6 +2177,17 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// public ProviderConfig? Provider { get; set; } + /// + /// Enables or disables internal session telemetry for this session. + /// When false, disables session telemetry. When null (the default) or true, + /// telemetry is enabled for GitHub-authenticated sessions. + /// When a custom (BYOK) is configured, session telemetry is + /// always disabled regardless of this setting. + /// This is independent of , which configures + /// OpenTelemetry export for observability. + /// + public bool? EnableSessionTelemetry { get; set; } + /// /// Reasoning effort level for models that support it. /// Valid values: "low", "medium", "high", "xhigh". diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index 31627f5a3..14263de79 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -159,6 +159,63 @@ public async Task Should_Propagate_Process_Options_To_Spawned_Cli() await session.DisposeAsync(); } + [Fact] + public async Task Should_Forward_EnableSessionTelemetry_In_Wire_Request() + { + var (cliPath, capturePath) = await CreateFakeCliCaptureAsync(); + + await using var client = Ctx.CreateClient(options: new CopilotClientOptions + { + AutoStart = false, + CliPath = cliPath, + CliArgs = ["--capture-file", capturePath], + UseLoggedInUser = false, + }); + + await client.StartAsync(); + + // When explicitly set to false, it should appear in the wire request + var session = await client.CreateSessionAsync(new SessionConfig + { + EnableSessionTelemetry = false, + OnPermissionRequest = PermissionHandler.ApproveAll, + }); + + using var capture = JsonDocument.Parse(await File.ReadAllTextAsync(capturePath)); + var createRequest = GetCapturedRequestParams(capture.RootElement, "session.create"); + Assert.False(createRequest.GetProperty("enableSessionTelemetry").GetBoolean()); + + await session.DisposeAsync(); + } + + [Fact] + public async Task Should_Omit_EnableSessionTelemetry_When_Not_Set() + { + var (cliPath, capturePath) = await CreateFakeCliCaptureAsync(); + + await using var client = Ctx.CreateClient(options: new CopilotClientOptions + { + AutoStart = false, + CliPath = cliPath, + CliArgs = ["--capture-file", capturePath], + UseLoggedInUser = false, + }); + + await client.StartAsync(); + + // When omitted (null/default), the field should not be present in the wire request + var session = await client.CreateSessionAsync(new SessionConfig + { + OnPermissionRequest = PermissionHandler.ApproveAll, + }); + + using var capture = JsonDocument.Parse(await File.ReadAllTextAsync(capturePath)); + var createRequest = GetCapturedRequestParams(capture.RootElement, "session.create"); + Assert.False(createRequest.TryGetProperty("enableSessionTelemetry", out _)); + + await session.DisposeAsync(); + } + [Fact] public async Task Should_Propagate_Activity_TraceContext_To_Session_Create_And_Send() { diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 10e0bbf45..055d53302 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -90,6 +90,7 @@ public void SessionConfig_Clone_CopiesAllProperties() ExcludedTools = ["tool3"], WorkingDirectory = "/workspace", Streaming = true, + EnableSessionTelemetry = false, IncludeSubAgentStreamingEvents = false, McpServers = new Dictionary { ["server1"] = new McpStdioServerConfig { Command = "echo" } }, CustomAgents = [new CustomAgentConfig { Name = "agent1" }], @@ -111,6 +112,7 @@ public void SessionConfig_Clone_CopiesAllProperties() Assert.Equal(original.ExcludedTools, clone.ExcludedTools); Assert.Equal(original.WorkingDirectory, clone.WorkingDirectory); Assert.Equal(original.Streaming, clone.Streaming); + Assert.Equal(original.EnableSessionTelemetry, clone.EnableSessionTelemetry); Assert.Equal(original.IncludeSubAgentStreamingEvents, clone.IncludeSubAgentStreamingEvents); Assert.Equal(original.McpServers.Count, clone.McpServers!.Count); Assert.Equal(original.CustomAgents.Count, clone.CustomAgents!.Count); @@ -315,6 +317,19 @@ public void ResumeSessionConfig_Clone_PreservesIncludeSubAgentStreamingEventsDef Assert.True(clone.IncludeSubAgentStreamingEvents); } + [Fact] + public void ResumeSessionConfig_Clone_CopiesEnableSessionTelemetry() + { + var original = new ResumeSessionConfig + { + EnableSessionTelemetry = false, + }; + + var clone = original.Clone(); + + Assert.False(clone.EnableSessionTelemetry); + } + [Fact] public void ResumeSessionConfig_Clone_CopiesContinuePendingWork() { @@ -337,4 +352,24 @@ public void ResumeSessionConfig_Clone_PreservesContinuePendingWorkDefault() Assert.Null(clone.ContinuePendingWork); } + + [Fact] + public void SessionConfig_Clone_PreservesEnableSessionTelemetryDefault() + { + var original = new SessionConfig(); + + var clone = original.Clone(); + + Assert.Null(clone.EnableSessionTelemetry); + } + + [Fact] + public void ResumeSessionConfig_Clone_PreservesEnableSessionTelemetryDefault() + { + var original = new ResumeSessionConfig(); + + var clone = original.Clone(); + + Assert.Null(clone.EnableSessionTelemetry); + } } diff --git a/dotnet/test/Unit/SerializationTests.cs b/dotnet/test/Unit/SerializationTests.cs index e58b256f4..713c46abd 100644 --- a/dotnet/test/Unit/SerializationTests.cs +++ b/dotnet/test/Unit/SerializationTests.cs @@ -126,6 +126,38 @@ public void ResumeSessionRequest_CanSerializeInstructionDirectories_WithSdkOptio Assert.Equal("C:\\resume-instructions", root.GetProperty("instructionDirectories")[0].GetString()); } + [Fact] + public void CreateSessionRequest_CanSerializeEnableSessionTelemetry_WithSdkOptions() + { + var options = GetSerializerOptions(); + var requestType = GetNestedType(typeof(CopilotClient), "CreateSessionRequest"); + var request = CreateInternalRequest( + requestType, + ("SessionId", "session-id"), + ("EnableSessionTelemetry", false)); + + var json = JsonSerializer.Serialize(request, requestType, options); + using var document = JsonDocument.Parse(json); + var root = document.RootElement; + Assert.False(root.GetProperty("enableSessionTelemetry").GetBoolean()); + } + + [Fact] + public void ResumeSessionRequest_CanSerializeEnableSessionTelemetry_WithSdkOptions() + { + var options = GetSerializerOptions(); + var requestType = GetNestedType(typeof(CopilotClient), "ResumeSessionRequest"); + var request = CreateInternalRequest( + requestType, + ("SessionId", "session-id"), + ("EnableSessionTelemetry", false)); + + var json = JsonSerializer.Serialize(request, requestType, options); + using var document = JsonDocument.Parse(json); + var root = document.RootElement; + Assert.False(root.GetProperty("enableSessionTelemetry").GetBoolean()); + } + [Fact] public void McpHttpServerConfig_CanSerializeOauthOptions_WithSdkOptions() { diff --git a/go/client.go b/go/client.go index 851dcf4e2..92a00c083 100644 --- a/go/client.go +++ b/go/client.go @@ -630,6 +630,7 @@ func (c *Client) CreateSession(ctx context.Context, config *SessionConfig) (*Ses req.AvailableTools = config.AvailableTools req.ExcludedTools = config.ExcludedTools req.Provider = config.Provider + req.EnableSessionTelemetry = config.EnableSessionTelemetry req.ModelCapabilities = config.ModelCapabilities req.WorkingDirectory = config.WorkingDirectory req.MCPServers = config.MCPServers @@ -789,6 +790,7 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string, req.SystemMessage = wireSystemMessage req.Tools = config.Tools req.Provider = config.Provider + req.EnableSessionTelemetry = config.EnableSessionTelemetry req.ModelCapabilities = config.ModelCapabilities req.AvailableTools = config.AvailableTools req.ExcludedTools = config.ExcludedTools diff --git a/go/client_test.go b/go/client_test.go index a2dccab33..28b44086e 100644 --- a/go/client_test.go +++ b/go/client_test.go @@ -990,6 +990,35 @@ func TestResumeSessionRequest_ContinuePendingWork(t *testing.T) { }) } +func TestCreateSessionRequest_EnableSessionTelemetry(t *testing.T) { + t.Run("forwards enableSessionTelemetry when false", func(t *testing.T) { + req := createSessionRequest{ + EnableSessionTelemetry: Bool(false), + } + data, err := json.Marshal(req) + if err != nil { + t.Fatalf("Failed to marshal: %v", err) + } + var m map[string]any + if err := json.Unmarshal(data, &m); err != nil { + t.Fatalf("Failed to unmarshal: %v", err) + } + if m["enableSessionTelemetry"] != false { + t.Errorf("Expected enableSessionTelemetry to be false, got %v", m["enableSessionTelemetry"]) + } + }) + + t.Run("omits enableSessionTelemetry when not set", func(t *testing.T) { + req := createSessionRequest{} + data, _ := json.Marshal(req) + var m map[string]any + json.Unmarshal(data, &m) + if _, ok := m["enableSessionTelemetry"]; ok { + t.Error("Expected enableSessionTelemetry to be omitted when not set") + } + }) +} + func TestCreateSessionRequest_IncludeSubAgentStreamingEvents(t *testing.T) { t.Run("defaults to true when nil", func(t *testing.T) { req := createSessionRequest{ @@ -1026,6 +1055,36 @@ func TestCreateSessionRequest_IncludeSubAgentStreamingEvents(t *testing.T) { }) } +func TestResumeSessionRequest_EnableSessionTelemetry(t *testing.T) { + t.Run("forwards enableSessionTelemetry when false", func(t *testing.T) { + req := resumeSessionRequest{ + SessionID: "s1", + EnableSessionTelemetry: Bool(false), + } + data, err := json.Marshal(req) + if err != nil { + t.Fatalf("Failed to marshal: %v", err) + } + var m map[string]any + if err := json.Unmarshal(data, &m); err != nil { + t.Fatalf("Failed to unmarshal: %v", err) + } + if m["enableSessionTelemetry"] != false { + t.Errorf("Expected enableSessionTelemetry to be false, got %v", m["enableSessionTelemetry"]) + } + }) + + t.Run("omits enableSessionTelemetry when not set", func(t *testing.T) { + req := resumeSessionRequest{SessionID: "s1"} + data, _ := json.Marshal(req) + var m map[string]any + json.Unmarshal(data, &m) + if _, ok := m["enableSessionTelemetry"]; ok { + t.Error("Expected enableSessionTelemetry to be omitted when not set") + } + }) +} + func TestResumeSessionRequest_IncludeSubAgentStreamingEvents(t *testing.T) { t.Run("defaults to true when nil", func(t *testing.T) { req := resumeSessionRequest{ diff --git a/go/types.go b/go/types.go index dd3ffbbe3..152f809c8 100644 --- a/go/types.go +++ b/go/types.go @@ -570,6 +570,13 @@ type SessionConfig struct { IncludeSubAgentStreamingEvents *bool // Provider configures a custom model provider (BYOK) Provider *ProviderConfig + // EnableSessionTelemetry enables or disables internal session telemetry. + // When false, disables session telemetry. When nil (the default) or true, + // telemetry is enabled for GitHub-authenticated sessions. When a custom + // Provider (BYOK) is configured, session telemetry is always disabled + // regardless of this setting. This is independent of the OpenTelemetry + // configuration in CopilotClientOptions. + EnableSessionTelemetry *bool // ModelCapabilities overrides individual model capabilities resolved by the runtime. // Only non-nil fields are applied over the runtime-resolved capabilities. ModelCapabilities *rpc.ModelCapabilitiesOverride @@ -760,6 +767,13 @@ type ResumeSessionConfig struct { ExcludedTools []string // Provider configures a custom model provider Provider *ProviderConfig + // EnableSessionTelemetry enables or disables internal session telemetry. + // When false, disables session telemetry. When nil (the default) or true, + // telemetry is enabled for GitHub-authenticated sessions. When a custom + // Provider (BYOK) is configured, session telemetry is always disabled + // regardless of this setting. This is independent of the OpenTelemetry + // configuration in CopilotClientOptions. + EnableSessionTelemetry *bool // ModelCapabilities overrides individual model capabilities resolved by the runtime. // Only non-nil fields are applied over the runtime-resolved capabilities. ModelCapabilities *rpc.ModelCapabilitiesOverride @@ -1039,6 +1053,7 @@ type createSessionRequest struct { AvailableTools []string `json:"availableTools"` ExcludedTools []string `json:"excludedTools,omitempty"` Provider *ProviderConfig `json:"provider,omitempty"` + EnableSessionTelemetry *bool `json:"enableSessionTelemetry,omitempty"` ModelCapabilities *rpc.ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"` RequestPermission *bool `json:"requestPermission,omitempty"` RequestUserInput *bool `json:"requestUserInput,omitempty"` @@ -1088,6 +1103,7 @@ type resumeSessionRequest struct { AvailableTools []string `json:"availableTools"` ExcludedTools []string `json:"excludedTools,omitempty"` Provider *ProviderConfig `json:"provider,omitempty"` + EnableSessionTelemetry *bool `json:"enableSessionTelemetry,omitempty"` ModelCapabilities *rpc.ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"` RequestPermission *bool `json:"requestPermission,omitempty"` RequestUserInput *bool `json:"requestUserInput,omitempty"` diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts index b1b6b4f46..ac7334859 100644 --- a/nodejs/src/client.ts +++ b/nodejs/src/client.ts @@ -801,6 +801,7 @@ export class CopilotClient { availableTools: config.availableTools, excludedTools: config.excludedTools, provider: config.provider ? toWireProviderConfig(config.provider) : undefined, + enableSessionTelemetry: config.enableSessionTelemetry, modelCapabilities: config.modelCapabilities, requestPermission: true, requestUserInput: !!config.onUserInputRequest, @@ -932,6 +933,7 @@ export class CopilotClient { systemMessage: wireSystemMessage, availableTools: config.availableTools, excludedTools: config.excludedTools, + enableSessionTelemetry: config.enableSessionTelemetry, tools: config.tools?.map((tool) => ({ name: tool.name, description: tool.description, diff --git a/nodejs/src/types.ts b/nodejs/src/types.ts index 59dff3d82..ef954c85f 100644 --- a/nodejs/src/types.ts +++ b/nodejs/src/types.ts @@ -1273,6 +1273,16 @@ export interface SessionConfig { */ provider?: ProviderConfig; + /** + * Enables or disables session telemetry for this session. + * When `false`, disables session telemetry. When omitted (the default) or `true`, + * telemetry is enabled for GitHub-authenticated sessions. + * When a custom {@link provider} (BYOK) is configured, session telemetry is always + * disabled regardless of this setting. + * This is independent of the OpenTelemetry configuration in {@link CopilotClientOptions.telemetry}. + */ + enableSessionTelemetry?: boolean; + /** * Handler for permission requests from the server. * When provided, the server will call this handler to request permission for operations. @@ -1415,6 +1425,7 @@ export type ResumeSessionConfig = Pick< | "availableTools" | "excludedTools" | "provider" + | "enableSessionTelemetry" | "modelCapabilities" | "streaming" | "includeSubAgentStreamingEvents" diff --git a/nodejs/test/client.test.ts b/nodejs/test/client.test.ts index b2fe998ee..7328ebc1e 100644 --- a/nodejs/test/client.test.ts +++ b/nodejs/test/client.test.ts @@ -98,6 +98,47 @@ describe("CopilotClient", () => { spy.mockRestore(); }); + it("forwards enableSessionTelemetry in session.create request", async () => { + const client = new CopilotClient(); + await client.start(); + onTestFinished(() => client.forceStop()); + + const spy = vi.spyOn((client as any).connection!, "sendRequest"); + await client.createSession({ + enableSessionTelemetry: false, + onPermissionRequest: approveAll, + }); + + expect(spy).toHaveBeenCalledWith( + "session.create", + expect.objectContaining({ enableSessionTelemetry: false }) + ); + }); + + it("forwards enableSessionTelemetry in session.resume request", async () => { + const client = new CopilotClient(); + await client.start(); + onTestFinished(() => client.forceStop()); + + const session = await client.createSession({ onPermissionRequest: approveAll }); + const spy = vi + .spyOn((client as any).connection!, "sendRequest") + .mockImplementation(async (method: string, params: any) => { + if (method === "session.resume") return { sessionId: params.sessionId }; + throw new Error(`Unexpected method: ${method}`); + }); + await client.resumeSession(session.sessionId, { + enableSessionTelemetry: false, + onPermissionRequest: approveAll, + }); + + expect(spy).toHaveBeenCalledWith( + "session.resume", + expect.objectContaining({ enableSessionTelemetry: false, sessionId: session.sessionId }) + ); + spy.mockRestore(); + }); + it("defaults includeSubAgentStreamingEvents to true in session.create when not specified", async () => { const client = new CopilotClient(); await client.start(); diff --git a/python/copilot/client.py b/python/copilot/client.py index 0e03dcbf7..34eb988cc 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -1239,6 +1239,7 @@ async def create_session( hooks: SessionHooks | None = None, working_directory: str | None = None, provider: ProviderConfig | None = None, + enable_session_telemetry: bool | None = None, model_capabilities: ModelCapabilitiesOverride | None = None, streaming: bool | None = None, include_sub_agent_streaming_events: bool | None = None, @@ -1287,6 +1288,8 @@ async def create_session( hooks: Lifecycle hooks for the session. working_directory: Working directory for the session. provider: Provider configuration for Azure or custom endpoints. + enable_session_telemetry: When False, disables internal session telemetry + for this session. model_capabilities: Override individual model capabilities resolved by the runtime. streaming: Whether to enable streaming responses. include_sub_agent_streaming_events: Whether to include sub-agent streaming @@ -1421,6 +1424,9 @@ async def create_session( if provider: payload["provider"] = self._convert_provider_to_wire_format(provider) + if enable_session_telemetry is not None: + payload["enableSessionTelemetry"] = enable_session_telemetry + # Add model capabilities override if provided if model_capabilities: payload["modelCapabilities"] = _capabilities_to_dict(model_capabilities) @@ -1545,6 +1551,7 @@ async def resume_session( hooks: SessionHooks | None = None, working_directory: str | None = None, provider: ProviderConfig | None = None, + enable_session_telemetry: bool | None = None, model_capabilities: ModelCapabilitiesOverride | None = None, streaming: bool | None = None, include_sub_agent_streaming_events: bool | None = None, @@ -1594,6 +1601,8 @@ async def resume_session( hooks: Lifecycle hooks for the session. working_directory: Working directory for the session. provider: Provider configuration for Azure or custom endpoints. + enable_session_telemetry: When False, disables internal session telemetry + for this session. model_capabilities: Override individual model capabilities resolved by the runtime. streaming: Whether to enable streaming responses. include_sub_agent_streaming_events: Whether to include sub-agent streaming @@ -1690,6 +1699,8 @@ async def resume_session( payload["excludedTools"] = excluded_tools if provider: payload["provider"] = self._convert_provider_to_wire_format(provider) + if enable_session_telemetry is not None: + payload["enableSessionTelemetry"] = enable_session_telemetry if model_capabilities: payload["modelCapabilities"] = _capabilities_to_dict(model_capabilities) if streaming is not None: diff --git a/python/copilot/session.py b/python/copilot/session.py index 97a505c25..e2a5e534e 100644 --- a/python/copilot/session.py +++ b/python/copilot/session.py @@ -882,6 +882,12 @@ class SessionConfig(TypedDict, total=False): working_directory: str # Custom provider configuration (BYOK - Bring Your Own Key) provider: ProviderConfig + # Enables or disables internal session telemetry. When False, disables session + # telemetry. When omitted (the default) or True, telemetry is enabled for + # GitHub-authenticated sessions. When a custom provider (BYOK) is configured, + # session telemetry is always disabled regardless of this setting. + # This is independent of the OpenTelemetry configuration in CopilotClientOptions. + enable_session_telemetry: bool # Enable streaming of assistant message and reasoning chunks # When True, assistant.message_delta and assistant.reasoning_delta events # with delta_content are sent as the response is generated @@ -950,6 +956,12 @@ class ResumeSessionConfig(TypedDict, total=False): # registered via tools=. Ignored if available_tools is set. excluded_tools: list[str] provider: ProviderConfig + # Enables or disables internal session telemetry. When False, disables session + # telemetry. When omitted (the default) or True, telemetry is enabled for + # GitHub-authenticated sessions. When a custom provider (BYOK) is configured, + # session telemetry is always disabled regardless of this setting. + # This is independent of the OpenTelemetry configuration in CopilotClientOptions. + enable_session_telemetry: bool # Reasoning effort level for models that support it. reasoning_effort: ReasoningEffort on_permission_request: _PermissionHandlerFn diff --git a/python/test_client.py b/python/test_client.py index a890ca12e..26de29287 100644 --- a/python/test_client.py +++ b/python/test_client.py @@ -543,6 +543,57 @@ async def mock_request(method, params): finally: await client.force_stop() + @pytest.mark.asyncio + async def test_create_session_forwards_enable_session_telemetry(self): + client = CopilotClient(SubprocessConfig(cli_path=CLI_PATH)) + await client.start() + + try: + captured = {} + original_request = client._client.request + + async def mock_request(method, params): + captured[method] = params + return await original_request(method, params) + + client._client.request = mock_request + await client.create_session( + on_permission_request=PermissionHandler.approve_all, + enable_session_telemetry=False, + ) + assert captured["session.create"]["enableSessionTelemetry"] is False + finally: + await client.force_stop() + + @pytest.mark.asyncio + async def test_resume_session_forwards_enable_session_telemetry(self): + client = CopilotClient(SubprocessConfig(cli_path=CLI_PATH)) + await client.start() + + try: + session = await client.create_session( + on_permission_request=PermissionHandler.approve_all + ) + + captured = {} + original_request = client._client.request + + async def mock_request(method, params): + captured[method] = params + if method == "session.resume": + return {"sessionId": session.session_id} + return await original_request(method, params) + + client._client.request = mock_request + await client.resume_session( + session.session_id, + on_permission_request=PermissionHandler.approve_all, + enable_session_telemetry=False, + ) + assert captured["session.resume"]["enableSessionTelemetry"] is False + finally: + await client.force_stop() + @pytest.mark.asyncio async def test_create_session_forwards_provider_headers(self): client = CopilotClient(SubprocessConfig(cli_path=CLI_PATH))