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
21 changes: 13 additions & 8 deletions dotnet/src/Generated/SessionEvents.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions dotnet/test/ForwardCompatibilityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public void FromJson_KnownEventType_DeserializesNormally()
"id": "00000000-0000-0000-0000-000000000001",
"timestamp": "2026-01-01T00:00:00Z",
"parentId": null,
"agentId": "agent-1",
"type": "user.message",
"data": {
"content": "Hello"
Expand All @@ -31,6 +32,7 @@ public void FromJson_KnownEventType_DeserializesNormally()

Assert.IsType<UserMessageEvent>(result);
Assert.Equal("user.message", result.Type);
Assert.Equal("agent-1", result.AgentId);
}

[Fact]
Expand All @@ -41,6 +43,7 @@ public void FromJson_UnknownEventType_ReturnsBaseSessionEvent()
"id": "12345678-1234-1234-1234-123456789abc",
"timestamp": "2026-06-15T10:30:00Z",
"parentId": "abcdefab-abcd-abcd-abcd-abcdefabcdef",
"agentId": "future-agent",
"type": "future.feature_from_server",
"data": { "key": "value" }
}
Expand All @@ -50,6 +53,7 @@ public void FromJson_UnknownEventType_ReturnsBaseSessionEvent()

Assert.IsType<SessionEvent>(result);
Assert.Equal("unknown", result.Type);
Assert.Equal("future-agent", result.AgentId);
}

[Fact]
Expand Down
2 changes: 2 additions & 0 deletions dotnet/test/SessionEventSerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class SessionEventSerializationTests
Id = Guid.Parse("11111111-1111-1111-1111-111111111111"),
Timestamp = DateTimeOffset.Parse("2026-03-15T21:26:02.642Z"),
ParentId = Guid.Parse("22222222-2222-2222-2222-222222222222"),
AgentId = "agent-1",
Data = new AssistantMessageData
{
MessageId = "msg-1",
Expand Down Expand Up @@ -134,6 +135,7 @@ public void SessionEvent_ToJson_RoundTrips_JsonElementBackedPayloads(SessionEven
switch (expectedType)
{
case "assistant.message":
Assert.Equal("agent-1", root.GetProperty("agentId").GetString());
Assert.Equal(
"README.md",
root.GetProperty("data")
Expand Down
34 changes: 20 additions & 14 deletions go/generated_session_events.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 78 additions & 0 deletions go/session_event_serialization_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package copilot

import (
"encoding/json"
"testing"
)

func TestSessionEventAgentIDRoundTripsKnownEvent(t *testing.T) {
event, err := UnmarshalSessionEvent([]byte(`{
"id": "00000000-0000-0000-0000-000000000001",
"timestamp": "2026-01-01T00:00:00Z",
"parentId": null,
"agentId": "agent-1",
"type": "user.message",
"data": {
"content": "Hello"
}
}`))
if err != nil {
t.Fatalf("failed to unmarshal session event: %v", err)
}

if event.AgentID == nil || *event.AgentID != "agent-1" {
t.Fatalf("expected agent ID to round-trip, got %v", event.AgentID)
}
if _, ok := event.Data.(*UserMessageData); !ok {
t.Fatalf("expected user message data, got %T", event.Data)
}

data, err := event.Marshal()
if err != nil {
t.Fatalf("failed to marshal session event: %v", err)
}

var serialized map[string]any
if err := json.Unmarshal(data, &serialized); err != nil {
t.Fatalf("failed to unmarshal serialized session event: %v", err)
}
if serialized["agentId"] != "agent-1" {
t.Fatalf("expected serialized agentId to round-trip, got %v", serialized["agentId"])
}
}

func TestSessionEventAgentIDRoundTripsUnknownEvent(t *testing.T) {
event, err := UnmarshalSessionEvent([]byte(`{
"id": "00000000-0000-0000-0000-000000000002",
"timestamp": "2026-01-01T00:00:00Z",
"parentId": null,
"agentId": "future-agent",
"type": "future.feature_from_server",
"data": {
"key": "value"
}
}`))
if err != nil {
t.Fatalf("failed to unmarshal session event: %v", err)
}

if event.AgentID == nil || *event.AgentID != "future-agent" {
t.Fatalf("expected agent ID to round-trip, got %v", event.AgentID)
}
if _, ok := event.Data.(*RawSessionEventData); !ok {
t.Fatalf("expected raw session event data, got %T", event.Data)
}

data, err := event.Marshal()
if err != nil {
t.Fatalf("failed to marshal session event: %v", err)
}

var serialized map[string]any
if err := json.Unmarshal(data, &serialized); err != nil {
t.Fatalf("failed to unmarshal serialized session event: %v", err)
}
if serialized["agentId"] != "future-agent" {
t.Fatalf("expected serialized agentId to round-trip, got %v", serialized["agentId"])
}
}
15 changes: 10 additions & 5 deletions python/copilot/generated/session_events.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions python/test_event_forward_compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
UserMessageAgentMode,
UserMessageAttachmentGithubReferenceType,
session_event_from_dict,
session_event_to_dict,
)


Expand All @@ -47,6 +48,39 @@ def test_unknown_event_type_maps_to_unknown(self):
event = session_event_from_dict(unknown_event)
assert event.type == SessionEventType.UNKNOWN, f"Expected UNKNOWN, got {event.type}"

def test_known_event_preserves_top_level_agent_id(self):
"""Known events should preserve the top-level sub-agent envelope ID."""
known_event = {
"id": str(uuid4()),
"timestamp": datetime.now().isoformat(),
"parentId": None,
"agentId": "agent-1",
"type": "user.message",
"data": {"content": "Hello"},
}

event = session_event_from_dict(known_event)
assert event.agent_id == "agent-1"
assert session_event_to_dict(event)["agentId"] == "agent-1"

def test_unknown_event_preserves_top_level_agent_id(self):
"""Unknown events should preserve the top-level sub-agent envelope ID."""
unknown_event = {
"id": str(uuid4()),
"timestamp": datetime.now().isoformat(),
"parentId": None,
"agentId": "future-agent",
"type": "session.future_feature_from_server",
"data": {"key": "value"},
}

event = session_event_from_dict(unknown_event)
assert event.type == SessionEventType.UNKNOWN
assert event.agent_id == "future-agent"
serialized = session_event_to_dict(event)
assert serialized["agentId"] == "future-agent"
assert serialized["type"] == "session.future_feature_from_server"

def test_malformed_uuid_raises_error(self):
"""Malformed UUIDs should raise ValueError for visibility, not be suppressed."""
malformed_event = {
Expand Down
Loading
Loading