Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dotnet/src/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
hasHooks ? true : null,
config.WorkingDirectory,
config.Streaming is true ? true : null,
config.IncludeSubAgentStreamingEvents,
config.McpServers,
"direct",
config.CustomAgents,
Expand Down Expand Up @@ -622,6 +623,7 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
config.EnableConfigDiscovery,
config.DisableResume is true ? true : null,
config.Streaming is true ? true : null,
config.IncludeSubAgentStreamingEvents,
config.McpServers,
"direct",
config.CustomAgents,
Expand Down Expand Up @@ -1636,6 +1638,7 @@ internal record CreateSessionRequest(
bool? Hooks,
string? WorkingDirectory,
bool? Streaming,
bool? IncludeSubAgentStreamingEvents,
IDictionary<string, McpServerConfig>? McpServers,
string? EnvValueMode,
IList<CustomAgentConfig>? CustomAgents,
Expand Down Expand Up @@ -1691,6 +1694,7 @@ internal record ResumeSessionRequest(
bool? EnableConfigDiscovery,
bool? DisableResume,
bool? Streaming,
bool? IncludeSubAgentStreamingEvents,
IDictionary<string, McpServerConfig>? McpServers,
string? EnvValueMode,
IList<CustomAgentConfig>? CustomAgents,
Expand Down
24 changes: 24 additions & 0 deletions dotnet/src/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,7 @@ protected SessionConfig(SessionConfig? other)
SessionId = other.SessionId;
SkillDirectories = other.SkillDirectories is not null ? [.. other.SkillDirectories] : null;
Streaming = other.Streaming;
IncludeSubAgentStreamingEvents = other.IncludeSubAgentStreamingEvents;
SystemMessage = other.SystemMessage;
Tools = other.Tools is not null ? [.. other.Tools] : null;
WorkingDirectory = other.WorkingDirectory;
Expand Down Expand Up @@ -1848,6 +1849,17 @@ protected SessionConfig(SessionConfig? other)
/// </summary>
public bool Streaming { get; set; }

/// <summary>
/// Include sub-agent streaming events in the event stream. When true, streaming
/// delta events from sub-agents (e.g., <c>assistant.message_delta</c>,
/// <c>assistant.reasoning_delta</c>, <c>assistant.streaming_delta</c> with
/// <c>agentId</c> set) are forwarded to this connection. When false, only
/// non-streaming sub-agent events and <c>subagent.*</c> lifecycle events are
/// forwarded; streaming deltas from sub-agents are suppressed.
/// Default: true.
/// </summary>
public bool IncludeSubAgentStreamingEvents { get; set; } = true;

Comment thread
stephentoub marked this conversation as resolved.
/// <summary>
/// MCP server configurations for the session.
/// Keys are server names, values are server configurations (<see cref="McpStdioServerConfig"/> or <see cref="McpHttpServerConfig"/>).
Expand Down Expand Up @@ -1961,6 +1973,7 @@ protected ResumeSessionConfig(ResumeSessionConfig? other)
CreateSessionFsHandler = other.CreateSessionFsHandler;
SkillDirectories = other.SkillDirectories is not null ? [.. other.SkillDirectories] : null;
Streaming = other.Streaming;
IncludeSubAgentStreamingEvents = other.IncludeSubAgentStreamingEvents;
SystemMessage = other.SystemMessage;
Tools = other.Tools is not null ? [.. other.Tools] : null;
WorkingDirectory = other.WorkingDirectory;
Expand Down Expand Up @@ -2082,6 +2095,17 @@ protected ResumeSessionConfig(ResumeSessionConfig? other)
/// </summary>
public bool Streaming { get; set; }

/// <summary>
/// Include sub-agent streaming events in the event stream. When true, streaming
/// delta events from sub-agents (e.g., <c>assistant.message_delta</c>,
/// <c>assistant.reasoning_delta</c>, <c>assistant.streaming_delta</c> with
/// <c>agentId</c> set) are forwarded to this connection. When false, only
/// non-streaming sub-agent events and <c>subagent.*</c> lifecycle events are
/// forwarded; streaming deltas from sub-agents are suppressed.
/// Default: true.
/// </summary>
public bool IncludeSubAgentStreamingEvents { get; set; } = true;

Comment thread
stephentoub marked this conversation as resolved.
/// <summary>
/// MCP server configurations for the session.
/// Keys are server names, values are server configurations (<see cref="McpStdioServerConfig"/> or <see cref="McpHttpServerConfig"/>).
Expand Down
26 changes: 26 additions & 0 deletions dotnet/test/CloneTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public void SessionConfig_Clone_CopiesAllProperties()
ExcludedTools = ["tool3"],
WorkingDirectory = "/workspace",
Streaming = true,
IncludeSubAgentStreamingEvents = false,
McpServers = new Dictionary<string, McpServerConfig> { ["server1"] = new McpStdioServerConfig { Command = "echo" } },
CustomAgents = [new CustomAgentConfig { Name = "agent1" }],
Agent = "agent1",
Expand All @@ -104,6 +105,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.IncludeSubAgentStreamingEvents, clone.IncludeSubAgentStreamingEvents);
Assert.Equal(original.McpServers.Count, clone.McpServers!.Count);
Assert.Equal(original.CustomAgents.Count, clone.CustomAgents!.Count);
Assert.Equal(original.Agent, clone.Agent);
Expand Down Expand Up @@ -243,6 +245,7 @@ public void Clone_WithNullCollections_ReturnsNullCollections()
Assert.Null(clone.SkillDirectories);
Assert.Null(clone.DisabledSkills);
Assert.Null(clone.Tools);
Assert.True(clone.IncludeSubAgentStreamingEvents);
}

[Fact]
Expand Down Expand Up @@ -272,4 +275,27 @@ public void ResumeSessionConfig_Clone_CopiesAgentProperty()

Assert.Equal("test-agent", clone.Agent);
}

[Fact]
public void ResumeSessionConfig_Clone_CopiesIncludeSubAgentStreamingEvents()
{
var original = new ResumeSessionConfig
{
IncludeSubAgentStreamingEvents = false,
};

var clone = original.Clone();

Assert.False(clone.IncludeSubAgentStreamingEvents);
}

[Fact]
public void ResumeSessionConfig_Clone_PreservesIncludeSubAgentStreamingEventsDefault()
{
var original = new ResumeSessionConfig();

var clone = original.Clone();

Assert.True(clone.IncludeSubAgentStreamingEvents);
}
}
10 changes: 10 additions & 0 deletions go/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,11 @@ func (c *Client) CreateSession(ctx context.Context, config *SessionConfig) (*Ses
if config.Streaming {
req.Streaming = Bool(true)
}
if config.IncludeSubAgentStreamingEvents != nil {
req.IncludeSubAgentStreamingEvents = config.IncludeSubAgentStreamingEvents
} else {
req.IncludeSubAgentStreamingEvents = Bool(true)
}
Comment thread
stephentoub marked this conversation as resolved.
if config.OnUserInputRequest != nil {
req.RequestUserInput = Bool(true)
}
Expand Down Expand Up @@ -744,6 +749,11 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
if config.Streaming {
req.Streaming = Bool(true)
}
if config.IncludeSubAgentStreamingEvents != nil {
req.IncludeSubAgentStreamingEvents = config.IncludeSubAgentStreamingEvents
} else {
req.IncludeSubAgentStreamingEvents = Bool(true)
}
Comment thread
stephentoub marked this conversation as resolved.
if config.OnUserInputRequest != nil {
req.RequestUserInput = Bool(true)
}
Expand Down
74 changes: 74 additions & 0 deletions go/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,80 @@ func TestResumeSessionRequest_RequestElicitation(t *testing.T) {
})
}

func TestCreateSessionRequest_IncludeSubAgentStreamingEvents(t *testing.T) {
t.Run("defaults to true when nil", func(t *testing.T) {
req := createSessionRequest{
IncludeSubAgentStreamingEvents: Bool(true),
}
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["includeSubAgentStreamingEvents"] != true {
t.Errorf("Expected includeSubAgentStreamingEvents to be true, got %v", m["includeSubAgentStreamingEvents"])
}
})

t.Run("preserves explicit false", func(t *testing.T) {
req := createSessionRequest{
IncludeSubAgentStreamingEvents: 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["includeSubAgentStreamingEvents"] != false {
t.Errorf("Expected includeSubAgentStreamingEvents to be false, got %v", m["includeSubAgentStreamingEvents"])
}
})
}

func TestResumeSessionRequest_IncludeSubAgentStreamingEvents(t *testing.T) {
t.Run("defaults to true when nil", func(t *testing.T) {
req := resumeSessionRequest{
SessionID: "s1",
IncludeSubAgentStreamingEvents: Bool(true),
}
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["includeSubAgentStreamingEvents"] != true {
t.Errorf("Expected includeSubAgentStreamingEvents to be true, got %v", m["includeSubAgentStreamingEvents"])
}
})

t.Run("preserves explicit false", func(t *testing.T) {
req := resumeSessionRequest{
SessionID: "s1",
IncludeSubAgentStreamingEvents: 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["includeSubAgentStreamingEvents"] != false {
t.Errorf("Expected includeSubAgentStreamingEvents to be false, got %v", m["includeSubAgentStreamingEvents"])
}
})
}

func TestCreateSessionResponse_Capabilities(t *testing.T) {
t.Run("reads capabilities from session.create response", func(t *testing.T) {
responseJSON := `{"sessionId":"s1","workspacePath":"/tmp","capabilities":{"ui":{"elicitation":true}}}`
Expand Down
Loading
Loading