diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs
index ea9b3e2d..4e059b70 100644
--- a/dotnet/src/Generated/SessionEvents.cs
+++ b/dotnet/src/Generated/SessionEvents.cs
@@ -6,7 +6,7 @@
//
// Generated from: @github/copilot/session-events.schema.json
// Generated by: scripts/generate-session-types.ts
-// Generated at: 2026-01-22T14:30:57.371Z
+// Generated at: 2026-01-26T18:08:34.014Z
//
// To update these types:
// 1. Update the schema in copilot-agent-runtime
@@ -43,6 +43,7 @@ namespace GitHub.Copilot.SDK;
[JsonDerivedType(typeof(SessionInfoEvent), "session.info")]
[JsonDerivedType(typeof(SessionModelChangeEvent), "session.model_change")]
[JsonDerivedType(typeof(SessionResumeEvent), "session.resume")]
+[JsonDerivedType(typeof(SessionSnapshotRewindEvent), "session.snapshot_rewind")]
[JsonDerivedType(typeof(SessionStartEvent), "session.start")]
[JsonDerivedType(typeof(SessionTruncationEvent), "session.truncation")]
[JsonDerivedType(typeof(SessionUsageInfoEvent), "session.usage_info")]
@@ -181,6 +182,18 @@ public partial class SessionTruncationEvent : SessionEvent
public required SessionTruncationData Data { get; set; }
}
+///
+/// Event: session.snapshot_rewind
+///
+public partial class SessionSnapshotRewindEvent : SessionEvent
+{
+ [JsonIgnore]
+ public override string Type => "session.snapshot_rewind";
+
+ [JsonPropertyName("data")]
+ public required SessionSnapshotRewindData Data { get; set; }
+}
+
///
/// Event: session.usage_info
///
@@ -620,6 +633,15 @@ public partial class SessionTruncationData
public required string PerformedBy { get; set; }
}
+public partial class SessionSnapshotRewindData
+{
+ [JsonPropertyName("upToEventId")]
+ public required string UpToEventId { get; set; }
+
+ [JsonPropertyName("eventsRemoved")]
+ public required double EventsRemoved { get; set; }
+}
+
public partial class SessionUsageInfoData
{
[JsonPropertyName("tokenLimit")]
@@ -844,6 +866,14 @@ public partial class ToolExecutionStartData
[JsonPropertyName("arguments")]
public object? Arguments { get; set; }
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("mcpServerName")]
+ public string? McpServerName { get; set; }
+
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("mcpToolName")]
+ public string? McpToolName { get; set; }
+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("parentToolCallId")]
public string? ParentToolCallId { get; set; }
@@ -1055,10 +1085,22 @@ public partial class SessionCompactionCompleteDataCompactionTokensUsed
public required double CachedInput { get; set; }
}
-public partial class UserMessageDataAttachmentsItem
+public partial class UserMessageDataAttachmentsItemFile : UserMessageDataAttachmentsItem
{
- [JsonPropertyName("type")]
- public required UserMessageDataAttachmentsItemType Type { get; set; }
+ [JsonIgnore]
+ public override string Type => "file";
+
+ [JsonPropertyName("path")]
+ public required string Path { get; set; }
+
+ [JsonPropertyName("displayName")]
+ public required string DisplayName { get; set; }
+}
+
+public partial class UserMessageDataAttachmentsItemDirectory : UserMessageDataAttachmentsItem
+{
+ [JsonIgnore]
+ public override string Type => "directory";
[JsonPropertyName("path")]
public required string Path { get; set; }
@@ -1067,6 +1109,64 @@ public partial class UserMessageDataAttachmentsItem
public required string DisplayName { get; set; }
}
+public partial class UserMessageDataAttachmentsItemSelectionSelectionStart
+{
+ [JsonPropertyName("line")]
+ public required double Line { get; set; }
+
+ [JsonPropertyName("character")]
+ public required double Character { get; set; }
+}
+
+public partial class UserMessageDataAttachmentsItemSelectionSelectionEnd
+{
+ [JsonPropertyName("line")]
+ public required double Line { get; set; }
+
+ [JsonPropertyName("character")]
+ public required double Character { get; set; }
+}
+
+public partial class UserMessageDataAttachmentsItemSelectionSelection
+{
+ [JsonPropertyName("start")]
+ public required UserMessageDataAttachmentsItemSelectionSelectionStart Start { get; set; }
+
+ [JsonPropertyName("end")]
+ public required UserMessageDataAttachmentsItemSelectionSelectionEnd End { get; set; }
+}
+
+public partial class UserMessageDataAttachmentsItemSelection : UserMessageDataAttachmentsItem
+{
+ [JsonIgnore]
+ public override string Type => "selection";
+
+ [JsonPropertyName("filePath")]
+ public required string FilePath { get; set; }
+
+ [JsonPropertyName("displayName")]
+ public required string DisplayName { get; set; }
+
+ [JsonPropertyName("text")]
+ public required string Text { get; set; }
+
+ [JsonPropertyName("selection")]
+ public required UserMessageDataAttachmentsItemSelectionSelection Selection { get; set; }
+}
+
+[JsonPolymorphic(
+ TypeDiscriminatorPropertyName = "type",
+ UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
+[JsonDerivedType(typeof(UserMessageDataAttachmentsItemFile), "file")]
+[JsonDerivedType(typeof(UserMessageDataAttachmentsItemDirectory), "directory")]
+[JsonDerivedType(typeof(UserMessageDataAttachmentsItemSelection), "selection")]
+public partial class UserMessageDataAttachmentsItem
+{
+ [JsonPropertyName("type")]
+ public virtual string Type { get; set; } = string.Empty;
+}
+
+
public partial class AssistantMessageDataToolRequestsItem
{
[JsonPropertyName("toolCallId")]
@@ -1088,6 +1188,10 @@ public partial class ToolExecutionCompleteDataResult
{
[JsonPropertyName("content")]
public required string Content { get; set; }
+
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("detailedContent")]
+ public string? DetailedContent { get; set; }
}
public partial class ToolExecutionCompleteDataError
@@ -1130,15 +1234,6 @@ public enum SessionHandoffDataSourceType
Local,
}
-[JsonConverter(typeof(JsonStringEnumConverter))]
-public enum UserMessageDataAttachmentsItemType
-{
- [JsonStringEnumMemberName("file")]
- File,
- [JsonStringEnumMemberName("directory")]
- Directory,
-}
-
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum AssistantMessageDataToolRequestsItemType
{
@@ -1208,6 +1303,8 @@ public enum SystemMessageDataRole
[JsonSerializable(typeof(SessionResumeData))]
[JsonSerializable(typeof(SessionResumeDataContext))]
[JsonSerializable(typeof(SessionResumeEvent))]
+[JsonSerializable(typeof(SessionSnapshotRewindData))]
+[JsonSerializable(typeof(SessionSnapshotRewindEvent))]
[JsonSerializable(typeof(SessionStartData))]
[JsonSerializable(typeof(SessionStartDataContext))]
[JsonSerializable(typeof(SessionStartEvent))]
@@ -1240,5 +1337,11 @@ public enum SystemMessageDataRole
[JsonSerializable(typeof(ToolUserRequestedEvent))]
[JsonSerializable(typeof(UserMessageData))]
[JsonSerializable(typeof(UserMessageDataAttachmentsItem))]
+[JsonSerializable(typeof(UserMessageDataAttachmentsItemDirectory))]
+[JsonSerializable(typeof(UserMessageDataAttachmentsItemFile))]
+[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelection))]
+[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelectionSelection))]
+[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelectionSelectionEnd))]
+[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelectionSelectionStart))]
[JsonSerializable(typeof(UserMessageEvent))]
internal partial class SessionEventsJsonContext : JsonSerializerContext;
\ No newline at end of file
diff --git a/go/generated_session_events.go b/go/generated_session_events.go
index 64feeade..98af62b5 100644
--- a/go/generated_session_events.go
+++ b/go/generated_session_events.go
@@ -2,7 +2,7 @@
//
// Generated from: @github/copilot/session-events.schema.json
// Generated by: scripts/generate-session-types.ts
-// Generated at: 2026-01-22T04:11:05.365Z
+// Generated at: 2026-01-26T18:08:33.950Z
//
// To update these types:
// 1. Update the schema in copilot-agent-runtime
@@ -70,6 +70,8 @@ type Data struct {
PreTruncationTokensInMessages *float64 `json:"preTruncationTokensInMessages,omitempty"`
TokenLimit *float64 `json:"tokenLimit,omitempty"`
TokensRemovedDuringTruncation *float64 `json:"tokensRemovedDuringTruncation,omitempty"`
+ EventsRemoved *float64 `json:"eventsRemoved,omitempty"`
+ UpToEventID *string `json:"upToEventId,omitempty"`
CurrentTokens *float64 `json:"currentTokens,omitempty"`
MessagesLength *float64 `json:"messagesLength,omitempty"`
CompactionTokensUsed *CompactionTokensUsed `json:"compactionTokensUsed,omitempty"`
@@ -108,6 +110,8 @@ type Data struct {
Arguments interface{} `json:"arguments"`
ToolCallID *string `json:"toolCallId,omitempty"`
ToolName *string `json:"toolName,omitempty"`
+ MCPServerName *string `json:"mcpServerName,omitempty"`
+ MCPToolName *string `json:"mcpToolName,omitempty"`
PartialOutput *string `json:"partialOutput,omitempty"`
ProgressMessage *string `json:"progressMessage,omitempty"`
IsUserRequested *bool `json:"isUserRequested,omitempty"`
@@ -127,9 +131,27 @@ type Data struct {
}
type Attachment struct {
- DisplayName string `json:"displayName"`
- Path string `json:"path"`
- Type AttachmentType `json:"type"`
+ DisplayName string `json:"displayName"`
+ Path *string `json:"path,omitempty"`
+ Type AttachmentType `json:"type"`
+ FilePath *string `json:"filePath,omitempty"`
+ Selection *SelectionClass `json:"selection,omitempty"`
+ Text *string `json:"text,omitempty"`
+}
+
+type SelectionClass struct {
+ End End `json:"end"`
+ Start Start `json:"start"`
+}
+
+type End struct {
+ Character float64 `json:"character"`
+ Line float64 `json:"line"`
+}
+
+type Start struct {
+ Character float64 `json:"character"`
+ Line float64 `json:"line"`
}
type CompactionTokensUsed struct {
@@ -174,7 +196,8 @@ type Repository struct {
}
type Result struct {
- Content string `json:"content"`
+ Content string `json:"content"`
+ DetailedContent *string `json:"detailedContent,omitempty"`
}
type ToolRequest struct {
@@ -189,6 +212,7 @@ type AttachmentType string
const (
Directory AttachmentType = "directory"
File AttachmentType = "file"
+ Selection AttachmentType = "selection"
)
type Role string
@@ -235,6 +259,7 @@ const (
SessionInfo SessionEventType = "session.info"
SessionModelChange SessionEventType = "session.model_change"
SessionResume SessionEventType = "session.resume"
+ SessionSnapshotRewind SessionEventType = "session.snapshot_rewind"
SessionStart SessionEventType = "session.start"
SessionTruncation SessionEventType = "session.truncation"
SessionUsageInfo SessionEventType = "session.usage_info"
diff --git a/nodejs/scripts/generate-csharp-session-types.ts b/nodejs/scripts/generate-csharp-session-types.ts
index 722737b6..cf295117 100644
--- a/nodejs/scripts/generate-csharp-session-types.ts
+++ b/nodejs/scripts/generate-csharp-session-types.ts
@@ -345,6 +345,166 @@ function generateNestedClass(
return lines.join("\n");
}
+/**
+ * Find a discriminator property shared by all variants in an anyOf.
+ * Returns the property name and the mapping of const values to variant schemas.
+ */
+function findDiscriminator(variants: JSONSchema7[]): { property: string; mapping: Map } | null {
+ if (variants.length === 0) return null;
+
+ // Look for a property with a const value in all variants
+ const firstVariant = variants[0];
+ if (!firstVariant.properties) return null;
+
+ for (const [propName, propSchema] of Object.entries(firstVariant.properties)) {
+ if (typeof propSchema !== "object") continue;
+ const schema = propSchema as JSONSchema7;
+ if (schema.const === undefined) continue;
+
+ // Check if all variants have this property with a const value
+ const mapping = new Map();
+ let isValidDiscriminator = true;
+
+ for (const variant of variants) {
+ if (!variant.properties) {
+ isValidDiscriminator = false;
+ break;
+ }
+ const variantProp = variant.properties[propName];
+ if (typeof variantProp !== "object") {
+ isValidDiscriminator = false;
+ break;
+ }
+ const variantSchema = variantProp as JSONSchema7;
+ if (variantSchema.const === undefined) {
+ isValidDiscriminator = false;
+ break;
+ }
+ mapping.set(String(variantSchema.const), variant);
+ }
+
+ if (isValidDiscriminator && mapping.size === variants.length) {
+ return { property: propName, mapping };
+ }
+ }
+
+ return null;
+}
+
+/**
+ * Generate a polymorphic base class and derived classes for a discriminated union.
+ */
+function generatePolymorphicClasses(
+ baseClassName: string,
+ discriminatorProperty: string,
+ variants: JSONSchema7[],
+ knownTypes: Map,
+ nestedClasses: Map,
+ enumOutput: string[]
+): string {
+ const lines: string[] = [];
+ const discriminatorInfo = findDiscriminator(variants)!;
+
+ // Generate base class with JsonPolymorphic attribute
+ lines.push(`[JsonPolymorphic(`);
+ lines.push(` TypeDiscriminatorPropertyName = "${discriminatorProperty}",`);
+ lines.push(` UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]`);
+
+ // Add JsonDerivedType attributes for each variant
+ for (const [constValue] of discriminatorInfo.mapping) {
+ const derivedClassName = `${baseClassName}${toPascalCase(constValue)}`;
+ lines.push(`[JsonDerivedType(typeof(${derivedClassName}), "${constValue}")]`);
+ }
+
+ lines.push(`public partial class ${baseClassName}`);
+ lines.push(`{`);
+ lines.push(` [JsonPropertyName("${discriminatorProperty}")]`);
+ lines.push(` public virtual string ${toPascalCase(discriminatorProperty)} { get; set; } = string.Empty;`);
+ lines.push(`}`);
+ lines.push("");
+
+ // Generate derived classes
+ for (const [constValue, variant] of discriminatorInfo.mapping) {
+ const derivedClassName = `${baseClassName}${toPascalCase(constValue)}`;
+ const derivedCode = generateDerivedClass(
+ derivedClassName,
+ baseClassName,
+ discriminatorProperty,
+ constValue,
+ variant,
+ knownTypes,
+ nestedClasses,
+ enumOutput
+ );
+ nestedClasses.set(derivedClassName, derivedCode);
+ }
+
+ return lines.join("\n");
+}
+
+/**
+ * Generate a derived class for a discriminated union variant.
+ */
+function generateDerivedClass(
+ className: string,
+ baseClassName: string,
+ discriminatorProperty: string,
+ discriminatorValue: string,
+ schema: JSONSchema7,
+ knownTypes: Map,
+ nestedClasses: Map,
+ enumOutput: string[]
+): string {
+ const lines: string[] = [];
+ const required = new Set(schema.required || []);
+
+ lines.push(`public partial class ${className} : ${baseClassName}`);
+ lines.push(`{`);
+
+ // Override the discriminator property
+ lines.push(` [JsonIgnore]`);
+ lines.push(` public override string ${toPascalCase(discriminatorProperty)} => "${discriminatorValue}";`);
+ lines.push("");
+
+ if (schema.properties) {
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
+ if (typeof propSchema !== "object") continue;
+ // Skip the discriminator property (already in base class)
+ if (propName === discriminatorProperty) continue;
+
+ const isRequired = required.has(propName);
+ const csharpName = toPascalCase(propName);
+ const csharpType = resolvePropertyType(
+ propSchema as JSONSchema7,
+ className,
+ csharpName,
+ isRequired,
+ knownTypes,
+ nestedClasses,
+ enumOutput
+ );
+
+ if (!isRequired) {
+ lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`);
+ }
+ lines.push(` [JsonPropertyName("${propName}")]`);
+
+ const isNullableType = csharpType.endsWith("?");
+ const requiredModifier = isRequired && !isNullableType ? "required " : "";
+ lines.push(` public ${requiredModifier}${csharpType} ${csharpName} { get; set; }`);
+ lines.push("");
+ }
+ }
+
+ // Remove trailing empty line
+ if (lines[lines.length - 1] === "") {
+ lines.pop();
+ }
+
+ lines.push(`}`);
+ return lines.join("\n");
+}
+
/**
* Resolve the C# type for a property, generating nested classes as needed.
* Handles objects and arrays of objects.
@@ -411,6 +571,26 @@ function resolvePropertyType(
if (propSchema.type === "array" && propSchema.items) {
const items = propSchema.items as JSONSchema7;
+ // Array of discriminated union (anyOf with shared discriminator)
+ if (items.anyOf && Array.isArray(items.anyOf)) {
+ const variants = items.anyOf.filter((v): v is JSONSchema7 => typeof v === "object");
+ const discriminatorInfo = findDiscriminator(variants);
+
+ if (discriminatorInfo) {
+ const baseClassName = `${parentClassName}${propName}Item`;
+ const polymorphicCode = generatePolymorphicClasses(
+ baseClassName,
+ discriminatorInfo.property,
+ variants,
+ knownTypes,
+ nestedClasses,
+ enumOutput
+ );
+ nestedClasses.set(baseClassName, polymorphicCode);
+ return isRequired ? `${baseClassName}[]` : `${baseClassName}[]?`;
+ }
+ }
+
// Array of objects with properties
if (items.type === "object" && items.properties) {
const itemClassName = `${parentClassName}${propName}Item`;
diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts
index b86e97d5..7b799f8a 100644
--- a/nodejs/src/generated/session-events.ts
+++ b/nodejs/src/generated/session-events.ts
@@ -3,7 +3,7 @@
*
* Generated from: @github/copilot/session-events.schema.json
* Generated by: scripts/generate-session-types.ts
- * Generated at: 2026-01-22T04:11:04.988Z
+ * Generated at: 2026-01-26T18:08:33.710Z
*
* To update these types:
* 1. Update the schema in copilot-agent-runtime
@@ -127,6 +127,17 @@ export type SessionEvent =
performedBy: string;
};
}
+ | {
+ id: string;
+ timestamp: string;
+ parentId: string | null;
+ ephemeral: true;
+ type: "session.snapshot_rewind";
+ data: {
+ upToEventId: string;
+ eventsRemoved: number;
+ };
+ }
| {
id: string;
timestamp: string;
@@ -178,11 +189,34 @@ export type SessionEvent =
data: {
content: string;
transformedContent?: string;
- attachments?: {
- type: "file" | "directory";
- path: string;
- displayName: string;
- }[];
+ attachments?: (
+ | {
+ type: "file";
+ path: string;
+ displayName: string;
+ }
+ | {
+ type: "directory";
+ path: string;
+ displayName: string;
+ }
+ | {
+ type: "selection";
+ filePath: string;
+ displayName: string;
+ text: string;
+ selection: {
+ start: {
+ line: number;
+ character: number;
+ };
+ end: {
+ line: number;
+ character: number;
+ };
+ };
+ }
+ )[];
source?: string;
};
}
@@ -340,6 +374,8 @@ export type SessionEvent =
toolCallId: string;
toolName: string;
arguments?: unknown;
+ mcpServerName?: string;
+ mcpToolName?: string;
parentToolCallId?: string;
};
}
@@ -377,6 +413,7 @@ export type SessionEvent =
isUserRequested?: boolean;
result?: {
content: string;
+ detailedContent?: string;
};
error?: {
message: string;
diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py
index f8d8f4f2..ba473c7f 100644
--- a/python/copilot/generated/session_events.py
+++ b/python/copilot/generated/session_events.py
@@ -3,16 +3,16 @@
Generated from: @github/copilot/session-events.schema.json
Generated by: scripts/generate-session-types.ts
-Generated at: 2026-01-22T04:11:05.267Z
+Generated at: 2026-01-26T18:08:33.907Z
To update these types:
1. Update the schema in copilot-agent-runtime
2. Run: npm run generate:session-types
"""
-from enum import Enum
from dataclasses import dataclass
-from typing import Any, Optional, Dict, Union, List, TypeVar, Type, Callable, cast
+from typing import Any, Optional, Dict, Union, List, TypeVar, Type, cast, Callable
+from enum import Enum
from datetime import datetime
from uuid import UUID
import dateutil.parser
@@ -22,16 +22,6 @@
EnumT = TypeVar("EnumT", bound=Enum)
-def from_str(x: Any) -> str:
- assert isinstance(x, str)
- return x
-
-
-def to_enum(c: Type[EnumT], x: Any) -> EnumT:
- assert isinstance(x, c)
- return x.value
-
-
def from_float(x: Any) -> float:
assert isinstance(x, (float, int)) and not isinstance(x, bool)
return float(x)
@@ -42,6 +32,16 @@ def to_float(x: Any) -> float:
return x
+def to_class(c: Type[T], x: Any) -> dict:
+ assert isinstance(x, c)
+ return cast(Any, x).to_dict()
+
+
+def from_str(x: Any) -> str:
+ assert isinstance(x, str)
+ return x
+
+
def from_none(x: Any) -> Any:
assert x is None
return x
@@ -56,6 +56,11 @@ def from_union(fs, x):
assert False
+def to_enum(c: Type[EnumT], x: Any) -> EnumT:
+ assert isinstance(x, c)
+ return x.value
+
+
def from_dict(f: Callable[[Any], T], x: Any) -> Dict[str, T]:
assert isinstance(x, dict)
return { k: f(v) for (k, v) in x.items() }
@@ -75,35 +80,101 @@ def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
return [f(y) for y in x]
-def to_class(c: Type[T], x: Any) -> dict:
- assert isinstance(x, c)
- return cast(Any, x).to_dict()
+@dataclass
+class End:
+ character: float
+ line: float
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'End':
+ assert isinstance(obj, dict)
+ character = from_float(obj.get("character"))
+ line = from_float(obj.get("line"))
+ return End(character, line)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["character"] = to_float(self.character)
+ result["line"] = to_float(self.line)
+ return result
+
+
+@dataclass
+class Start:
+ character: float
+ line: float
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'Start':
+ assert isinstance(obj, dict)
+ character = from_float(obj.get("character"))
+ line = from_float(obj.get("line"))
+ return Start(character, line)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["character"] = to_float(self.character)
+ result["line"] = to_float(self.line)
+ return result
+
+
+@dataclass
+class Selection:
+ end: End
+ start: Start
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'Selection':
+ assert isinstance(obj, dict)
+ end = End.from_dict(obj.get("end"))
+ start = Start.from_dict(obj.get("start"))
+ return Selection(end, start)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["end"] = to_class(End, self.end)
+ result["start"] = to_class(Start, self.start)
+ return result
class AttachmentType(Enum):
DIRECTORY = "directory"
FILE = "file"
+ SELECTION = "selection"
@dataclass
class Attachment:
display_name: str
- path: str
type: AttachmentType
+ path: Optional[str] = None
+ file_path: Optional[str] = None
+ selection: Optional[Selection] = None
+ text: Optional[str] = None
@staticmethod
def from_dict(obj: Any) -> 'Attachment':
assert isinstance(obj, dict)
display_name = from_str(obj.get("displayName"))
- path = from_str(obj.get("path"))
type = AttachmentType(obj.get("type"))
- return Attachment(display_name, path, type)
+ path = from_union([from_str, from_none], obj.get("path"))
+ file_path = from_union([from_str, from_none], obj.get("filePath"))
+ selection = from_union([Selection.from_dict, from_none], obj.get("selection"))
+ text = from_union([from_str, from_none], obj.get("text"))
+ return Attachment(display_name, type, path, file_path, selection, text)
def to_dict(self) -> dict:
result: dict = {}
result["displayName"] = from_str(self.display_name)
- result["path"] = from_str(self.path)
result["type"] = to_enum(AttachmentType, self.type)
+ if self.path is not None:
+ result["path"] = from_union([from_str, from_none], self.path)
+ if self.file_path is not None:
+ result["filePath"] = from_union([from_str, from_none], self.file_path)
+ if self.selection is not None:
+ result["selection"] = from_union([lambda x: to_class(Selection, x), from_none], self.selection)
+ if self.text is not None:
+ result["text"] = from_union([from_str, from_none], self.text)
return result
@@ -266,16 +337,20 @@ def to_dict(self) -> dict:
@dataclass
class Result:
content: str
+ detailed_content: Optional[str] = None
@staticmethod
def from_dict(obj: Any) -> 'Result':
assert isinstance(obj, dict)
content = from_str(obj.get("content"))
- return Result(content)
+ detailed_content = from_union([from_str, from_none], obj.get("detailedContent"))
+ return Result(content, detailed_content)
def to_dict(self) -> dict:
result: dict = {}
result["content"] = from_str(self.content)
+ if self.detailed_content is not None:
+ result["detailedContent"] = from_union([from_str, from_none], self.detailed_content)
return result
@@ -351,6 +426,8 @@ class Data:
pre_truncation_tokens_in_messages: Optional[float] = None
token_limit: Optional[float] = None
tokens_removed_during_truncation: Optional[float] = None
+ events_removed: Optional[float] = None
+ up_to_event_id: Optional[str] = None
current_tokens: Optional[float] = None
messages_length: Optional[float] = None
compaction_tokens_used: Optional[CompactionTokensUsed] = None
@@ -389,6 +466,8 @@ class Data:
arguments: Any = None
tool_call_id: Optional[str] = None
tool_name: Optional[str] = None
+ mcp_server_name: Optional[str] = None
+ mcp_tool_name: Optional[str] = None
partial_output: Optional[str] = None
progress_message: Optional[str] = None
is_user_requested: Optional[bool] = None
@@ -437,6 +516,8 @@ def from_dict(obj: Any) -> 'Data':
pre_truncation_tokens_in_messages = from_union([from_float, from_none], obj.get("preTruncationTokensInMessages"))
token_limit = from_union([from_float, from_none], obj.get("tokenLimit"))
tokens_removed_during_truncation = from_union([from_float, from_none], obj.get("tokensRemovedDuringTruncation"))
+ events_removed = from_union([from_float, from_none], obj.get("eventsRemoved"))
+ up_to_event_id = from_union([from_str, from_none], obj.get("upToEventId"))
current_tokens = from_union([from_float, from_none], obj.get("currentTokens"))
messages_length = from_union([from_float, from_none], obj.get("messagesLength"))
compaction_tokens_used = from_union([CompactionTokensUsed.from_dict, from_none], obj.get("compactionTokensUsed"))
@@ -475,6 +556,8 @@ def from_dict(obj: Any) -> 'Data':
arguments = obj.get("arguments")
tool_call_id = from_union([from_str, from_none], obj.get("toolCallId"))
tool_name = from_union([from_str, from_none], obj.get("toolName"))
+ mcp_server_name = from_union([from_str, from_none], obj.get("mcpServerName"))
+ mcp_tool_name = from_union([from_str, from_none], obj.get("mcpToolName"))
partial_output = from_union([from_str, from_none], obj.get("partialOutput"))
progress_message = from_union([from_str, from_none], obj.get("progressMessage"))
is_user_requested = from_union([from_bool, from_none], obj.get("isUserRequested"))
@@ -491,7 +574,7 @@ def from_dict(obj: Any) -> 'Data':
metadata = from_union([Metadata.from_dict, from_none], obj.get("metadata"))
name = from_union([from_str, from_none], obj.get("name"))
role = from_union([Role, from_none], obj.get("role"))
- return Data(context, copilot_version, producer, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, stack, info_type, new_model, previous_model, handoff_time, remote_session_id, repository, source_type, summary, messages_removed_during_truncation, performed_by, post_truncation_messages_length, post_truncation_tokens_in_messages, pre_truncation_messages_length, pre_truncation_tokens_in_messages, token_limit, tokens_removed_during_truncation, current_tokens, messages_length, compaction_tokens_used, error, messages_removed, post_compaction_tokens, pre_compaction_messages_length, pre_compaction_tokens, success, summary_content, tokens_removed, attachments, content, source, transformed_content, turn_id, intent, reasoning_id, delta_content, message_id, parent_tool_call_id, tool_requests, total_response_size_bytes, api_call_id, cache_read_tokens, cache_write_tokens, cost, duration, initiator, input_tokens, model, output_tokens, provider_call_id, quota_snapshots, reason, arguments, tool_call_id, tool_name, partial_output, progress_message, is_user_requested, result, tool_telemetry, agent_description, agent_display_name, agent_name, tools, hook_invocation_id, hook_type, input, output, metadata, name, role)
+ return Data(context, copilot_version, producer, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, stack, info_type, new_model, previous_model, handoff_time, remote_session_id, repository, source_type, summary, messages_removed_during_truncation, performed_by, post_truncation_messages_length, post_truncation_tokens_in_messages, pre_truncation_messages_length, pre_truncation_tokens_in_messages, token_limit, tokens_removed_during_truncation, events_removed, up_to_event_id, current_tokens, messages_length, compaction_tokens_used, error, messages_removed, post_compaction_tokens, pre_compaction_messages_length, pre_compaction_tokens, success, summary_content, tokens_removed, attachments, content, source, transformed_content, turn_id, intent, reasoning_id, delta_content, message_id, parent_tool_call_id, tool_requests, total_response_size_bytes, api_call_id, cache_read_tokens, cache_write_tokens, cost, duration, initiator, input_tokens, model, output_tokens, provider_call_id, quota_snapshots, reason, arguments, tool_call_id, tool_name, mcp_server_name, mcp_tool_name, partial_output, progress_message, is_user_requested, result, tool_telemetry, agent_description, agent_display_name, agent_name, tools, hook_invocation_id, hook_type, input, output, metadata, name, role)
def to_dict(self) -> dict:
result: dict = {}
@@ -551,6 +634,10 @@ def to_dict(self) -> dict:
result["tokenLimit"] = from_union([to_float, from_none], self.token_limit)
if self.tokens_removed_during_truncation is not None:
result["tokensRemovedDuringTruncation"] = from_union([to_float, from_none], self.tokens_removed_during_truncation)
+ if self.events_removed is not None:
+ result["eventsRemoved"] = from_union([to_float, from_none], self.events_removed)
+ if self.up_to_event_id is not None:
+ result["upToEventId"] = from_union([from_str, from_none], self.up_to_event_id)
if self.current_tokens is not None:
result["currentTokens"] = from_union([to_float, from_none], self.current_tokens)
if self.messages_length is not None:
@@ -627,6 +714,10 @@ def to_dict(self) -> dict:
result["toolCallId"] = from_union([from_str, from_none], self.tool_call_id)
if self.tool_name is not None:
result["toolName"] = from_union([from_str, from_none], self.tool_name)
+ if self.mcp_server_name is not None:
+ result["mcpServerName"] = from_union([from_str, from_none], self.mcp_server_name)
+ if self.mcp_tool_name is not None:
+ result["mcpToolName"] = from_union([from_str, from_none], self.mcp_tool_name)
if self.partial_output is not None:
result["partialOutput"] = from_union([from_str, from_none], self.partial_output)
if self.progress_message is not None:
@@ -683,6 +774,7 @@ class SessionEventType(Enum):
SESSION_INFO = "session.info"
SESSION_MODEL_CHANGE = "session.model_change"
SESSION_RESUME = "session.resume"
+ SESSION_SNAPSHOT_REWIND = "session.snapshot_rewind"
SESSION_START = "session.start"
SESSION_TRUNCATION = "session.truncation"
SESSION_USAGE_INFO = "session.usage_info"
diff --git a/test/snapshots/session/should_abort_a_session.yaml b/test/snapshots/session/should_abort_a_session.yaml
index 4c7093ad..5f524344 100644
--- a/test/snapshots/session/should_abort_a_session.yaml
+++ b/test/snapshots/session/should_abort_a_session.yaml
@@ -5,7 +5,9 @@ conversations:
- role: system
content: ${system}
- role: user
- content: run the shell command 'sleep 100' (works on bash and PowerShell)
+ content: run the shell command 'sleep 100' (note this works on both bash and PowerShell)
+ - role: assistant
+ content: I'll run the sleep command for 100 seconds.
- role: assistant
tool_calls:
- id: toolcall_0
@@ -19,13 +21,14 @@ conversations:
type: function
function:
name: ${shell}
- arguments: '{"command":"sleep 100","description":"Run sleep 100 command","mode":"sync","initial_wait":30}'
+ arguments: '{"command":"sleep 100","description":"Run sleep 100 command","mode":"sync","initial_wait":105}'
- messages:
- role: system
content: ${system}
- role: user
- content: run the shell command 'sleep 100' (works on bash and PowerShell)
+ content: run the shell command 'sleep 100' (note this works on both bash and PowerShell)
- role: assistant
+ content: I'll run the sleep command for 100 seconds.
tool_calls:
- id: toolcall_0
type: function
@@ -36,7 +39,7 @@ conversations:
type: function
function:
name: ${shell}
- arguments: '{"command":"sleep 100","description":"Run sleep 100 command","mode":"sync","initial_wait":30}'
+ arguments: '{"command":"sleep 100","description":"Run sleep 100 command","mode":"sync","initial_wait":105}'
- role: tool
tool_call_id: toolcall_0
content: Intent logged
@@ -46,4 +49,4 @@ conversations:
- role: user
content: What is 2+2?
- role: assistant
- content: 2 + 2 = 4
+ content: 2+2 equals 4.