diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs
index 0bea6e8db..342d35c25 100644
--- a/dotnet/src/Generated/Rpc.cs
+++ b/dotnet/src/Generated/Rpc.cs
@@ -493,6 +493,37 @@ internal sealed class ModeSetRequest
public SessionMode Mode { get; set; }
}
+/// RPC data type for NameGet operations.
+public sealed class NameGetResult
+{
+ /// The session name, falling back to the auto-generated summary, or null if neither exists.
+ [JsonPropertyName("name")]
+ public string? Name { get; set; }
+}
+
+/// RPC data type for SessionNameGet operations.
+internal sealed class SessionNameGetRequest
+{
+ /// Target session identifier.
+ [JsonPropertyName("sessionId")]
+ public string SessionId { get; set; } = string.Empty;
+}
+
+/// RPC data type for NameSet operations.
+internal sealed class NameSetRequest
+{
+ /// Target session identifier.
+ [JsonPropertyName("sessionId")]
+ public string SessionId { get; set; } = string.Empty;
+
+ /// New session name (1–100 characters, trimmed of leading/trailing whitespace).
+ [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")]
+ [MinLength(1)]
+ [MaxLength(100)]
+ [JsonPropertyName("name")]
+ public string Name { get; set; } = string.Empty;
+}
+
/// RPC data type for PlanRead operations.
public sealed class PlanReadResult
{
@@ -537,32 +568,113 @@ internal sealed class SessionPlanDeleteRequest
public string SessionId { get; set; } = string.Empty;
}
-/// RPC data type for WorkspaceListFiles operations.
-public sealed class WorkspaceListFilesResult
+/// RPC data type for WorkspacesGetWorkspaceResultWorkspace operations.
+public sealed class WorkspacesGetWorkspaceResultWorkspace
+{
+ /// Gets or sets the id value.
+ [JsonPropertyName("id")]
+ public Guid Id { get; set; }
+
+ /// Gets or sets the cwd value.
+ [JsonPropertyName("cwd")]
+ public string? Cwd { get; set; }
+
+ /// Gets or sets the git_root value.
+ [JsonPropertyName("git_root")]
+ public string? GitRoot { get; set; }
+
+ /// Gets or sets the repository value.
+ [JsonPropertyName("repository")]
+ public string? Repository { get; set; }
+
+ /// Gets or sets the host_type value.
+ [JsonPropertyName("host_type")]
+ public WorkspacesGetWorkspaceResultWorkspaceHostType? HostType { get; set; }
+
+ /// Gets or sets the branch value.
+ [JsonPropertyName("branch")]
+ public string? Branch { get; set; }
+
+ /// Gets or sets the summary value.
+ [JsonPropertyName("summary")]
+ public string? Summary { get; set; }
+
+ /// Gets or sets the name value.
+ [JsonPropertyName("name")]
+ public string? Name { get; set; }
+
+ /// Gets or sets the summary_count value.
+ [Range((double)0, (double)long.MaxValue)]
+ [JsonPropertyName("summary_count")]
+ public long? SummaryCount { get; set; }
+
+ /// Gets or sets the created_at value.
+ [JsonPropertyName("created_at")]
+ public DateTimeOffset? CreatedAt { get; set; }
+
+ /// Gets or sets the updated_at value.
+ [JsonPropertyName("updated_at")]
+ public DateTimeOffset? UpdatedAt { get; set; }
+
+ /// Gets or sets the mc_task_id value.
+ [JsonPropertyName("mc_task_id")]
+ public string? McTaskId { get; set; }
+
+ /// Gets or sets the mc_session_id value.
+ [JsonPropertyName("mc_session_id")]
+ public string? McSessionId { get; set; }
+
+ /// Gets or sets the mc_last_event_id value.
+ [JsonPropertyName("mc_last_event_id")]
+ public string? McLastEventId { get; set; }
+
+ /// Gets or sets the session_sync_level value.
+ [JsonPropertyName("session_sync_level")]
+ public WorkspacesGetWorkspaceResultWorkspaceSessionSyncLevel? SessionSyncLevel { get; set; }
+}
+
+/// RPC data type for WorkspacesGetWorkspace operations.
+public sealed class WorkspacesGetWorkspaceResult
+{
+ /// Current workspace metadata, or null if not available.
+ [JsonPropertyName("workspace")]
+ public WorkspacesGetWorkspaceResultWorkspace? Workspace { get; set; }
+}
+
+/// RPC data type for SessionWorkspacesGetWorkspace operations.
+internal sealed class SessionWorkspacesGetWorkspaceRequest
+{
+ /// Target session identifier.
+ [JsonPropertyName("sessionId")]
+ public string SessionId { get; set; } = string.Empty;
+}
+
+/// RPC data type for WorkspacesListFiles operations.
+public sealed class WorkspacesListFilesResult
{
/// Relative file paths in the workspace files directory.
[JsonPropertyName("files")]
public IList Files { get => field ??= []; set; }
}
-/// RPC data type for SessionWorkspaceListFiles operations.
-internal sealed class SessionWorkspaceListFilesRequest
+/// RPC data type for SessionWorkspacesListFiles operations.
+internal sealed class SessionWorkspacesListFilesRequest
{
/// Target session identifier.
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = string.Empty;
}
-/// RPC data type for WorkspaceReadFile operations.
-public sealed class WorkspaceReadFileResult
+/// RPC data type for WorkspacesReadFile operations.
+public sealed class WorkspacesReadFileResult
{
/// File content as a UTF-8 string.
[JsonPropertyName("content")]
public string Content { get; set; } = string.Empty;
}
-/// RPC data type for WorkspaceReadFile operations.
-internal sealed class WorkspaceReadFileRequest
+/// RPC data type for WorkspacesReadFile operations.
+internal sealed class WorkspacesReadFileRequest
{
/// Target session identifier.
[JsonPropertyName("sessionId")]
@@ -573,8 +685,8 @@ internal sealed class WorkspaceReadFileRequest
public string Path { get; set; } = string.Empty;
}
-/// RPC data type for WorkspaceCreateFile operations.
-internal sealed class WorkspaceCreateFileRequest
+/// RPC data type for WorkspacesCreateFile operations.
+internal sealed class WorkspacesCreateFileRequest
{
/// Target session identifier.
[JsonPropertyName("sessionId")]
@@ -1754,6 +1866,35 @@ public enum SessionMode
}
+/// Defines the allowed values.
+[JsonConverter(typeof(JsonStringEnumConverter))]
+public enum WorkspacesGetWorkspaceResultWorkspaceHostType
+{
+ /// The github variant.
+ [JsonStringEnumMemberName("github")]
+ Github,
+ /// The ado variant.
+ [JsonStringEnumMemberName("ado")]
+ Ado,
+}
+
+
+/// Defines the allowed values.
+[JsonConverter(typeof(JsonStringEnumConverter))]
+public enum WorkspacesGetWorkspaceResultWorkspaceSessionSyncLevel
+{
+ /// The local variant.
+ [JsonStringEnumMemberName("local")]
+ Local,
+ /// The user variant.
+ [JsonStringEnumMemberName("user")]
+ User,
+ /// The repo_and_user variant.
+ [JsonStringEnumMemberName("repo_and_user")]
+ RepoAndUser,
+}
+
+
/// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum McpServerStatus
@@ -2036,8 +2177,9 @@ internal SessionRpc(JsonRpc rpc, string sessionId)
_sessionId = sessionId;
Model = new ModelApi(rpc, sessionId);
Mode = new ModeApi(rpc, sessionId);
+ Name = new NameApi(rpc, sessionId);
Plan = new PlanApi(rpc, sessionId);
- Workspace = new WorkspaceApi(rpc, sessionId);
+ Workspaces = new WorkspacesApi(rpc, sessionId);
Fleet = new FleetApi(rpc, sessionId);
Agent = new AgentApi(rpc, sessionId);
Skills = new SkillsApi(rpc, sessionId);
@@ -2059,11 +2201,14 @@ internal SessionRpc(JsonRpc rpc, string sessionId)
/// Mode APIs.
public ModeApi Mode { get; }
+ /// Name APIs.
+ public NameApi Name { get; }
+
/// Plan APIs.
public PlanApi Plan { get; }
- /// Workspace APIs.
- public WorkspaceApi Workspace { get; }
+ /// Workspaces APIs.
+ public WorkspacesApi Workspaces { get; }
/// Fleet APIs.
public FleetApi Fleet { get; }
@@ -2166,6 +2311,33 @@ public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken
}
}
+/// Provides session-scoped Name APIs.
+public sealed class NameApi
+{
+ private readonly JsonRpc _rpc;
+ private readonly string _sessionId;
+
+ internal NameApi(JsonRpc rpc, string sessionId)
+ {
+ _rpc = rpc;
+ _sessionId = sessionId;
+ }
+
+ /// Calls "session.name.get".
+ public async Task GetAsync(CancellationToken cancellationToken = default)
+ {
+ var request = new SessionNameGetRequest { SessionId = _sessionId };
+ return await CopilotClient.InvokeRpcAsync(_rpc, "session.name.get", [request], cancellationToken);
+ }
+
+ /// Calls "session.name.set".
+ public async Task SetAsync(string name, CancellationToken cancellationToken = default)
+ {
+ var request = new NameSetRequest { SessionId = _sessionId, Name = name };
+ await CopilotClient.InvokeRpcAsync(_rpc, "session.name.set", [request], cancellationToken);
+ }
+}
+
/// Provides session-scoped Plan APIs.
public sealed class PlanApi
{
@@ -2200,37 +2372,44 @@ public async Task DeleteAsync(CancellationToken cancellationToken = default)
}
}
-/// Provides session-scoped Workspace APIs.
-public sealed class WorkspaceApi
+/// Provides session-scoped Workspaces APIs.
+public sealed class WorkspacesApi
{
private readonly JsonRpc _rpc;
private readonly string _sessionId;
- internal WorkspaceApi(JsonRpc rpc, string sessionId)
+ internal WorkspacesApi(JsonRpc rpc, string sessionId)
{
_rpc = rpc;
_sessionId = sessionId;
}
- /// Calls "session.workspace.listFiles".
- public async Task ListFilesAsync(CancellationToken cancellationToken = default)
+ /// Calls "session.workspaces.getWorkspace".
+ public async Task GetWorkspaceAsync(CancellationToken cancellationToken = default)
+ {
+ var request = new SessionWorkspacesGetWorkspaceRequest { SessionId = _sessionId };
+ return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspaces.getWorkspace", [request], cancellationToken);
+ }
+
+ /// Calls "session.workspaces.listFiles".
+ public async Task ListFilesAsync(CancellationToken cancellationToken = default)
{
- var request = new SessionWorkspaceListFilesRequest { SessionId = _sessionId };
- return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.listFiles", [request], cancellationToken);
+ var request = new SessionWorkspacesListFilesRequest { SessionId = _sessionId };
+ return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspaces.listFiles", [request], cancellationToken);
}
- /// Calls "session.workspace.readFile".
- public async Task ReadFileAsync(string path, CancellationToken cancellationToken = default)
+ /// Calls "session.workspaces.readFile".
+ public async Task ReadFileAsync(string path, CancellationToken cancellationToken = default)
{
- var request = new WorkspaceReadFileRequest { SessionId = _sessionId, Path = path };
- return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.readFile", [request], cancellationToken);
+ var request = new WorkspacesReadFileRequest { SessionId = _sessionId, Path = path };
+ return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspaces.readFile", [request], cancellationToken);
}
- /// Calls "session.workspace.createFile".
+ /// Calls "session.workspaces.createFile".
public async Task CreateFileAsync(string path, string content, CancellationToken cancellationToken = default)
{
- var request = new WorkspaceCreateFileRequest { SessionId = _sessionId, Path = path, Content = content };
- await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.createFile", [request], cancellationToken);
+ var request = new WorkspacesCreateFileRequest { SessionId = _sessionId, Path = path, Content = content };
+ await CopilotClient.InvokeRpcAsync(_rpc, "session.workspaces.createFile", [request], cancellationToken);
}
}
@@ -2812,6 +2991,8 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func f.Contains("nested.txt"));
}
diff --git a/go/internal/e2e/rpc_test.go b/go/internal/e2e/rpc_test.go
index 5a79a7509..819e8ccca 100644
--- a/go/internal/e2e/rpc_test.go
+++ b/go/internal/e2e/rpc_test.go
@@ -307,7 +307,7 @@ func TestSessionRpc(t *testing.T) {
}
// Initially no files
- initialFiles, err := session.RPC.Workspace.ListFiles(t.Context())
+ initialFiles, err := session.RPC.Workspaces.ListFiles(t.Context())
if err != nil {
t.Fatalf("Failed to list files: %v", err)
}
@@ -317,7 +317,7 @@ func TestSessionRpc(t *testing.T) {
// Create a file
fileContent := "Hello, workspace!"
- _, err = session.RPC.Workspace.CreateFile(t.Context(), &rpc.WorkspaceCreateFileRequest{
+ _, err = session.RPC.Workspaces.CreateFile(t.Context(), &rpc.WorkspacesCreateFileRequest{
Path: "test.txt",
Content: fileContent,
})
@@ -326,7 +326,7 @@ func TestSessionRpc(t *testing.T) {
}
// List files
- afterCreate, err := session.RPC.Workspace.ListFiles(t.Context())
+ afterCreate, err := session.RPC.Workspaces.ListFiles(t.Context())
if err != nil {
t.Fatalf("Failed to list files after create: %v", err)
}
@@ -335,7 +335,7 @@ func TestSessionRpc(t *testing.T) {
}
// Read file
- readResult, err := session.RPC.Workspace.ReadFile(t.Context(), &rpc.WorkspaceReadFileRequest{
+ readResult, err := session.RPC.Workspaces.ReadFile(t.Context(), &rpc.WorkspacesReadFileRequest{
Path: "test.txt",
})
if err != nil {
@@ -346,7 +346,7 @@ func TestSessionRpc(t *testing.T) {
}
// Create nested file
- _, err = session.RPC.Workspace.CreateFile(t.Context(), &rpc.WorkspaceCreateFileRequest{
+ _, err = session.RPC.Workspaces.CreateFile(t.Context(), &rpc.WorkspacesCreateFileRequest{
Path: "subdir/nested.txt",
Content: "Nested content",
})
@@ -354,7 +354,7 @@ func TestSessionRpc(t *testing.T) {
t.Fatalf("Failed to create nested file: %v", err)
}
- afterNested, err := session.RPC.Workspace.ListFiles(t.Context())
+ afterNested, err := session.RPC.Workspaces.ListFiles(t.Context())
if err != nil {
t.Fatalf("Failed to list files after nested: %v", err)
}
diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go
index 75660a0e0..39478b0c4 100644
--- a/go/rpc/generated_rpc.go
+++ b/go/rpc/generated_rpc.go
@@ -344,6 +344,19 @@ type ModeSetRequest struct {
Mode SessionMode `json:"mode"`
}
+type NameGetResult struct {
+ // The session name, falling back to the auto-generated summary, or null if neither exists
+ Name *string `json:"name"`
+}
+
+type NameSetResult struct {
+}
+
+type NameSetRequest struct {
+ // New session name (1–100 characters, trimmed of leading/trailing whitespace)
+ Name string `json:"name"`
+}
+
type PlanReadResult struct {
// The content of the plan file, or null if it does not exist
Content *string `json:"content"`
@@ -364,25 +377,48 @@ type PlanUpdateRequest struct {
type PlanDeleteResult struct {
}
-type WorkspaceListFilesResult struct {
+type WorkspacesGetWorkspaceResult struct {
+ // Current workspace metadata, or null if not available
+ Workspace *WorkspaceClass `json:"workspace"`
+}
+
+type WorkspaceClass struct {
+ Branch *string `json:"branch,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ Cwd *string `json:"cwd,omitempty"`
+ GitRoot *string `json:"git_root,omitempty"`
+ HostType *HostType `json:"host_type,omitempty"`
+ ID string `json:"id"`
+ McLastEventID *string `json:"mc_last_event_id,omitempty"`
+ McSessionID *string `json:"mc_session_id,omitempty"`
+ McTaskID *string `json:"mc_task_id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Repository *string `json:"repository,omitempty"`
+ SessionSyncLevel *SessionSyncLevel `json:"session_sync_level,omitempty"`
+ Summary *string `json:"summary,omitempty"`
+ SummaryCount *int64 `json:"summary_count,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+}
+
+type WorkspacesListFilesResult struct {
// Relative file paths in the workspace files directory
Files []string `json:"files"`
}
-type WorkspaceReadFileResult struct {
+type WorkspacesReadFileResult struct {
// File content as a UTF-8 string
Content string `json:"content"`
}
-type WorkspaceReadFileRequest struct {
+type WorkspacesReadFileRequest struct {
// Relative path within the workspace files directory
Path string `json:"path"`
}
-type WorkspaceCreateFileResult struct {
+type WorkspacesCreateFileResult struct {
}
-type WorkspaceCreateFileRequest struct {
+type WorkspacesCreateFileRequest struct {
// File content to write as a UTF-8 string
Content string `json:"content"`
// Relative path within the workspace files directory
@@ -1058,8 +1094,8 @@ const (
type MCPConfigType string
const (
- MCPConfigTypeLocal MCPConfigType = "local"
MCPConfigTypeHTTP MCPConfigType = "http"
+ MCPConfigTypeLocal MCPConfigType = "local"
MCPConfigTypeSSE MCPConfigType = "sse"
MCPConfigTypeStdio MCPConfigType = "stdio"
)
@@ -1103,6 +1139,21 @@ const (
SessionModePlan SessionMode = "plan"
)
+type HostType string
+
+const (
+ HostTypeAdo HostType = "ado"
+ HostTypeGithub HostType = "github"
+)
+
+type SessionSyncLevel string
+
+const (
+ SessionSyncLevelRepoAndUser SessionSyncLevel = "repo_and_user"
+ SessionSyncLevelLocal SessionSyncLevel = "local"
+ SessionSyncLevelUser SessionSyncLevel = "user"
+)
+
// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
type MCPServerStatus string
@@ -1427,6 +1478,37 @@ func (a *ModeApi) Set(ctx context.Context, params *ModeSetRequest) (*ModeSetResu
return &result, nil
}
+type NameApi sessionApi
+
+func (a *NameApi) Get(ctx context.Context) (*NameGetResult, error) {
+ req := map[string]any{"sessionId": a.sessionID}
+ raw, err := a.client.Request("session.name.get", req)
+ if err != nil {
+ return nil, err
+ }
+ var result NameGetResult
+ if err := json.Unmarshal(raw, &result); err != nil {
+ return nil, err
+ }
+ return &result, nil
+}
+
+func (a *NameApi) Set(ctx context.Context, params *NameSetRequest) (*NameSetResult, error) {
+ req := map[string]any{"sessionId": a.sessionID}
+ if params != nil {
+ req["name"] = params.Name
+ }
+ raw, err := a.client.Request("session.name.set", req)
+ if err != nil {
+ return nil, err
+ }
+ var result NameSetResult
+ if err := json.Unmarshal(raw, &result); err != nil {
+ return nil, err
+ }
+ return &result, nil
+}
+
type PlanApi sessionApi
func (a *PlanApi) Read(ctx context.Context) (*PlanReadResult, error) {
@@ -1471,48 +1553,61 @@ func (a *PlanApi) Delete(ctx context.Context) (*PlanDeleteResult, error) {
return &result, nil
}
-type WorkspaceApi sessionApi
+type WorkspacesApi sessionApi
+
+func (a *WorkspacesApi) GetWorkspace(ctx context.Context) (*WorkspacesGetWorkspaceResult, error) {
+ req := map[string]any{"sessionId": a.sessionID}
+ raw, err := a.client.Request("session.workspaces.getWorkspace", req)
+ if err != nil {
+ return nil, err
+ }
+ var result WorkspacesGetWorkspaceResult
+ if err := json.Unmarshal(raw, &result); err != nil {
+ return nil, err
+ }
+ return &result, nil
+}
-func (a *WorkspaceApi) ListFiles(ctx context.Context) (*WorkspaceListFilesResult, error) {
+func (a *WorkspacesApi) ListFiles(ctx context.Context) (*WorkspacesListFilesResult, error) {
req := map[string]any{"sessionId": a.sessionID}
- raw, err := a.client.Request("session.workspace.listFiles", req)
+ raw, err := a.client.Request("session.workspaces.listFiles", req)
if err != nil {
return nil, err
}
- var result WorkspaceListFilesResult
+ var result WorkspacesListFilesResult
if err := json.Unmarshal(raw, &result); err != nil {
return nil, err
}
return &result, nil
}
-func (a *WorkspaceApi) ReadFile(ctx context.Context, params *WorkspaceReadFileRequest) (*WorkspaceReadFileResult, error) {
+func (a *WorkspacesApi) ReadFile(ctx context.Context, params *WorkspacesReadFileRequest) (*WorkspacesReadFileResult, error) {
req := map[string]any{"sessionId": a.sessionID}
if params != nil {
req["path"] = params.Path
}
- raw, err := a.client.Request("session.workspace.readFile", req)
+ raw, err := a.client.Request("session.workspaces.readFile", req)
if err != nil {
return nil, err
}
- var result WorkspaceReadFileResult
+ var result WorkspacesReadFileResult
if err := json.Unmarshal(raw, &result); err != nil {
return nil, err
}
return &result, nil
}
-func (a *WorkspaceApi) CreateFile(ctx context.Context, params *WorkspaceCreateFileRequest) (*WorkspaceCreateFileResult, error) {
+func (a *WorkspacesApi) CreateFile(ctx context.Context, params *WorkspacesCreateFileRequest) (*WorkspacesCreateFileResult, error) {
req := map[string]any{"sessionId": a.sessionID}
if params != nil {
req["path"] = params.Path
req["content"] = params.Content
}
- raw, err := a.client.Request("session.workspace.createFile", req)
+ raw, err := a.client.Request("session.workspaces.createFile", req)
if err != nil {
return nil, err
}
- var result WorkspaceCreateFileResult
+ var result WorkspacesCreateFileResult
if err := json.Unmarshal(raw, &result); err != nil {
return nil, err
}
@@ -2007,8 +2102,9 @@ type SessionRpc struct {
Model *ModelApi
Mode *ModeApi
+ Name *NameApi
Plan *PlanApi
- Workspace *WorkspaceApi
+ Workspaces *WorkspacesApi
Fleet *FleetApi
Agent *AgentApi
Skills *SkillsApi
@@ -2054,8 +2150,9 @@ func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc {
r.common = sessionApi{client: client, sessionID: sessionID}
r.Model = (*ModelApi)(&r.common)
r.Mode = (*ModeApi)(&r.common)
+ r.Name = (*NameApi)(&r.common)
r.Plan = (*PlanApi)(&r.common)
- r.Workspace = (*WorkspaceApi)(&r.common)
+ r.Workspaces = (*WorkspacesApi)(&r.common)
r.Fleet = (*FleetApi)(&r.common)
r.Agent = (*AgentApi)(&r.common)
r.Skills = (*SkillsApi)(&r.common)
diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json
index cc4407bbb..1c84c1d71 100644
--- a/nodejs/package-lock.json
+++ b/nodejs/package-lock.json
@@ -9,7 +9,7 @@
"version": "0.1.8",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.26-0",
+ "@github/copilot": "^1.0.26",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
@@ -663,26 +663,26 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.26-0",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.26-0.tgz",
- "integrity": "sha512-MHeddlLZCi5OFeuzKRtj7kmJVm1o/teNwgrL5/FHU9x0H6VioG+KGlY6gd1H/cTJ763dtYQyACMPYFUNVVY52g==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.26.tgz",
+ "integrity": "sha512-F7P6yimFzjvWxOF/A0F6k//vcpSVcVusQjaybb3IKyrEDhnd/LOv2tD+x6W0IoxCftGDDhkzBA2aon3rL9lPhQ==",
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.26-0",
- "@github/copilot-darwin-x64": "1.0.26-0",
- "@github/copilot-linux-arm64": "1.0.26-0",
- "@github/copilot-linux-x64": "1.0.26-0",
- "@github/copilot-win32-arm64": "1.0.26-0",
- "@github/copilot-win32-x64": "1.0.26-0"
+ "@github/copilot-darwin-arm64": "1.0.26",
+ "@github/copilot-darwin-x64": "1.0.26",
+ "@github/copilot-linux-arm64": "1.0.26",
+ "@github/copilot-linux-x64": "1.0.26",
+ "@github/copilot-win32-arm64": "1.0.26",
+ "@github/copilot-win32-x64": "1.0.26"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.26-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.26-0.tgz",
- "integrity": "sha512-C1GP4qrKjCjPoKr485o0IbcP3n1q/4LxKwAhpga0V+9ZHlvggZ58YB9AaUFySJ+Alpu1vBlw/FFpD9amroasvw==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.26.tgz",
+ "integrity": "sha512-eV+jDMj4vnjdGcG+c4zg11zZKVAp94Hm4sK4f9LnyWw8MumTfS5F2Yyse9zt7A3oGlegyczmJopKwuwZbQd4ww==",
"cpu": [
"arm64"
],
@@ -696,9 +696,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.26-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.26-0.tgz",
- "integrity": "sha512-A/HSuoCe8i5+yc5yCi4ZMi6PQfOOExA0wwpN13zFKwmqDwdNdogb4/wX42DoGr7JwuOGhZSzXCEZirt/lqqxjQ==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.26.tgz",
+ "integrity": "sha512-2AAgu19F3scDlYhsiHxCn0cz4ZkINq8gxnqW0an8VQn6p15lDcah6PqHw+RJ+12qiYX5L5NNACty9UOkIK7Kzg==",
"cpu": [
"x64"
],
@@ -712,9 +712,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.26-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.26-0.tgz",
- "integrity": "sha512-goMPZkMi5dCqA1JHbgsxaUKOmtZ6juBAeUfVomtKmdKee1KC74TFXlEuP8qJMGkeug2yivPOptAfQQXSyJJnHw==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.26.tgz",
+ "integrity": "sha512-SnM7+TGAZ/i9dim5FfHM7+ii01hdpHJzzh8vnnA1Fa7RPFJaQ2KTOdTDJFgfv6e/jLhKXZEelYIidgCA3vSQCQ==",
"cpu": [
"arm64"
],
@@ -728,9 +728,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.26-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.26-0.tgz",
- "integrity": "sha512-oK6uQ0Q0ZUO9IM3B+KJb9wyRHG5ZGP5qoTOOTN7JcC+p8ZveNSGCAHUAtzLSflUREJUFYfRZauUKcfV31/Y2LA==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.26.tgz",
+ "integrity": "sha512-x76vcwVbi0j03hFMhiQs+Eqefd9Xmc4qJoaj44YA2VsJuDbZw2Yv7ZBq7Vyxd/shJwJZjaKv36MHcx5bVUMBJQ==",
"cpu": [
"x64"
],
@@ -744,9 +744,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.26-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.26-0.tgz",
- "integrity": "sha512-VXwm8xryO3cUHydVkzmSzb0M3WonwGDHCcgwI2GGS2YkHB9VjmRbdpVeLYeDB5EzmyZLSd7Nr4+i2X0gsU93ow==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.26.tgz",
+ "integrity": "sha512-enVRcy7W9RD1bwYkF+mcxR+biXsG/X5m46XBaD0opvfDeiBHceDnI8hEI0O1A5PYvRo88AZFvDEmEW3Gdj6+rQ==",
"cpu": [
"arm64"
],
@@ -760,9 +760,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.26-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.26-0.tgz",
- "integrity": "sha512-+4IFUZbYSg5jxchEFdgVEgSDJzDE/P3nRDtEBcIhpYlVb7/zAw2JCkCJr+i4Aruo4zysJnEybL0wM3TpcWTt/g==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.26.tgz",
+ "integrity": "sha512-DpJF6C1x4+sYIXUx5+vWCu6cFAbD2YlrXQ/BRttf2MMdc0DHwdgJxrttBBF2qCvmpfzjSE8cr5G0kt5EUk7FGw==",
"cpu": [
"x64"
],
diff --git a/nodejs/package.json b/nodejs/package.json
index f4a3a2188..ca2e0afe7 100644
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -56,7 +56,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.26-0",
+ "@github/copilot": "^1.0.26",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json
index 3c5ebfd97..d85bc1e5e 100644
--- a/nodejs/samples/package-lock.json
+++ b/nodejs/samples/package-lock.json
@@ -18,7 +18,7 @@
"version": "0.1.8",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.22",
+ "@github/copilot": "^1.0.26",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts
index 8214dec4e..9b70619f8 100644
--- a/nodejs/src/generated/rpc.ts
+++ b/nodejs/src/generated/rpc.ts
@@ -595,6 +595,20 @@ export interface ModeSetRequest {
mode: SessionMode;
}
+export interface NameGetResult {
+ /**
+ * The session name, falling back to the auto-generated summary, or null if neither exists
+ */
+ name: string | null;
+}
+
+export interface NameSetRequest {
+ /**
+ * New session name (1–100 characters, trimmed of leading/trailing whitespace)
+ */
+ name: string;
+}
+
export interface PlanReadResult {
/**
* Whether the plan file exists in the workspace
@@ -617,28 +631,51 @@ export interface PlanUpdateRequest {
content: string;
}
-export interface WorkspaceListFilesResult {
+export interface WorkspacesGetWorkspaceResult {
+ /**
+ * Current workspace metadata, or null if not available
+ */
+ workspace: {
+ id: string;
+ cwd?: string;
+ git_root?: string;
+ repository?: string;
+ host_type?: "github" | "ado";
+ branch?: string;
+ summary?: string;
+ name?: string;
+ summary_count?: number;
+ created_at?: string;
+ updated_at?: string;
+ mc_task_id?: string;
+ mc_session_id?: string;
+ mc_last_event_id?: string;
+ session_sync_level?: "local" | "user" | "repo_and_user";
+ } | null;
+}
+
+export interface WorkspacesListFilesResult {
/**
* Relative file paths in the workspace files directory
*/
files: string[];
}
-export interface WorkspaceReadFileResult {
+export interface WorkspacesReadFileResult {
/**
* File content as a UTF-8 string
*/
content: string;
}
-export interface WorkspaceReadFileRequest {
+export interface WorkspacesReadFileRequest {
/**
* Relative path within the workspace files directory
*/
path: string;
}
-export interface WorkspaceCreateFileRequest {
+export interface WorkspacesCreateFileRequest {
/**
* Relative path within the workspace files directory
*/
@@ -1593,6 +1630,12 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin
set: async (params: Omit): Promise =>
connection.sendRequest("session.mode.set", { sessionId, ...params }),
},
+ name: {
+ get: async (): Promise =>
+ connection.sendRequest("session.name.get", { sessionId }),
+ set: async (params: Omit): Promise =>
+ connection.sendRequest("session.name.set", { sessionId, ...params }),
+ },
plan: {
read: async (): Promise =>
connection.sendRequest("session.plan.read", { sessionId }),
@@ -1601,13 +1644,15 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin
delete: async (): Promise =>
connection.sendRequest("session.plan.delete", { sessionId }),
},
- workspace: {
- listFiles: async (): Promise =>
- connection.sendRequest("session.workspace.listFiles", { sessionId }),
- readFile: async (params: Omit): Promise =>
- connection.sendRequest("session.workspace.readFile", { sessionId, ...params }),
- createFile: async (params: Omit): Promise =>
- connection.sendRequest("session.workspace.createFile", { sessionId, ...params }),
+ workspaces: {
+ getWorkspace: async (): Promise =>
+ connection.sendRequest("session.workspaces.getWorkspace", { sessionId }),
+ listFiles: async (): Promise =>
+ connection.sendRequest("session.workspaces.listFiles", { sessionId }),
+ readFile: async (params: Omit): Promise =>
+ connection.sendRequest("session.workspaces.readFile", { sessionId, ...params }),
+ createFile: async (params: Omit): Promise =>
+ connection.sendRequest("session.workspaces.createFile", { sessionId, ...params }),
},
/** @experimental */
fleet: {
diff --git a/nodejs/test/e2e/rpc.test.ts b/nodejs/test/e2e/rpc.test.ts
index bca4e8cd7..a4c333139 100644
--- a/nodejs/test/e2e/rpc.test.ts
+++ b/nodejs/test/e2e/rpc.test.ts
@@ -156,28 +156,28 @@ describe("Session RPC", async () => {
const session = await client.createSession({ onPermissionRequest: approveAll });
// Initially no files
- const initialFiles = await session.rpc.workspace.listFiles();
+ const initialFiles = await session.rpc.workspaces.listFiles();
expect(initialFiles.files).toEqual([]);
// Create a file
const fileContent = "Hello, workspace!";
- await session.rpc.workspace.createFile({ path: "test.txt", content: fileContent });
+ await session.rpc.workspaces.createFile({ path: "test.txt", content: fileContent });
// List files
- const afterCreate = await session.rpc.workspace.listFiles();
+ const afterCreate = await session.rpc.workspaces.listFiles();
expect(afterCreate.files).toContain("test.txt");
// Read file
- const readResult = await session.rpc.workspace.readFile({ path: "test.txt" });
+ const readResult = await session.rpc.workspaces.readFile({ path: "test.txt" });
expect(readResult.content).toBe(fileContent);
// Create nested file
- await session.rpc.workspace.createFile({
+ await session.rpc.workspaces.createFile({
path: "subdir/nested.txt",
content: "Nested content",
});
- const afterNested = await session.rpc.workspace.listFiles();
+ const afterNested = await session.rpc.workspaces.listFiles();
expect(afterNested.files).toContain("test.txt");
expect(afterNested.files.some((f) => f.includes("nested.txt"))).toBe(true);
});
diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py
index b24f74e51..a4f15d9e2 100644
--- a/python/copilot/generated/rpc.py
+++ b/python/copilot/generated/rpc.py
@@ -10,19 +10,17 @@
from collections.abc import Callable
from dataclasses import dataclass
-from typing import Protocol
-
-
-from dataclasses import dataclass
-from typing import Any, TypeVar, Callable, cast
from datetime import datetime
from enum import Enum
+from typing import Any, Protocol, TypeVar, cast
from uuid import UUID
+
import dateutil.parser
T = TypeVar("T")
EnumT = TypeVar("EnumT", bound=Enum)
+
def from_str(x: Any) -> str:
assert isinstance(x, str)
return x
@@ -766,7 +764,7 @@ def to_dict(self) -> dict:
class MCPServerSource(Enum):
"""Configuration source
-
+
Configuration source: user, workspace, plugin, or builtin
"""
BUILTIN = "builtin"
@@ -1130,6 +1128,38 @@ def to_dict(self) -> dict:
result["mode"] = to_enum(SessionMode, self.mode)
return result
+@dataclass
+class NameGetResult:
+ name: str | None = None
+ """The session name, falling back to the auto-generated summary, or null if neither exists"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'NameGetResult':
+ assert isinstance(obj, dict)
+ name = from_union([from_none, from_str], obj.get("name"))
+ return NameGetResult(name)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["name"] = from_union([from_none, from_str], self.name)
+ return result
+
+@dataclass
+class NameSetRequest:
+ name: str
+ """New session name (1–100 characters, trimmed of leading/trailing whitespace)"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'NameSetRequest':
+ assert isinstance(obj, dict)
+ name = from_str(obj.get("name"))
+ return NameSetRequest(name)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["name"] = from_str(self.name)
+ return result
+
@dataclass
class PlanReadResult:
exists: bool
@@ -1172,16 +1202,112 @@ def to_dict(self) -> dict:
result["content"] = from_str(self.content)
return result
+class HostType(Enum):
+ ADO = "ado"
+ GITHUB = "github"
+
+class SessionSyncLevel(Enum):
+ LOCAL = "local"
+ REPO_AND_USER = "repo_and_user"
+ USER = "user"
+
@dataclass
-class WorkspaceListFilesResult:
+class Workspace:
+ id: UUID
+ branch: str | None = None
+ created_at: datetime | None = None
+ cwd: str | None = None
+ git_root: str | None = None
+ host_type: HostType | None = None
+ mc_last_event_id: str | None = None
+ mc_session_id: str | None = None
+ mc_task_id: str | None = None
+ name: str | None = None
+ repository: str | None = None
+ session_sync_level: SessionSyncLevel | None = None
+ summary: str | None = None
+ summary_count: int | None = None
+ updated_at: datetime | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'Workspace':
+ assert isinstance(obj, dict)
+ id = UUID(obj.get("id"))
+ branch = from_union([from_str, from_none], obj.get("branch"))
+ created_at = from_union([from_datetime, from_none], obj.get("created_at"))
+ cwd = from_union([from_str, from_none], obj.get("cwd"))
+ git_root = from_union([from_str, from_none], obj.get("git_root"))
+ host_type = from_union([HostType, from_none], obj.get("host_type"))
+ mc_last_event_id = from_union([from_str, from_none], obj.get("mc_last_event_id"))
+ mc_session_id = from_union([from_str, from_none], obj.get("mc_session_id"))
+ mc_task_id = from_union([from_str, from_none], obj.get("mc_task_id"))
+ name = from_union([from_str, from_none], obj.get("name"))
+ repository = from_union([from_str, from_none], obj.get("repository"))
+ session_sync_level = from_union([SessionSyncLevel, from_none], obj.get("session_sync_level"))
+ summary = from_union([from_str, from_none], obj.get("summary"))
+ summary_count = from_union([from_int, from_none], obj.get("summary_count"))
+ updated_at = from_union([from_datetime, from_none], obj.get("updated_at"))
+ return Workspace(id, branch, created_at, cwd, git_root, host_type, mc_last_event_id, mc_session_id, mc_task_id, name, repository, session_sync_level, summary, summary_count, updated_at)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["id"] = str(self.id)
+ if self.branch is not None:
+ result["branch"] = from_union([from_str, from_none], self.branch)
+ if self.created_at is not None:
+ result["created_at"] = from_union([lambda x: x.isoformat(), from_none], self.created_at)
+ if self.cwd is not None:
+ result["cwd"] = from_union([from_str, from_none], self.cwd)
+ if self.git_root is not None:
+ result["git_root"] = from_union([from_str, from_none], self.git_root)
+ if self.host_type is not None:
+ result["host_type"] = from_union([lambda x: to_enum(HostType, x), from_none], self.host_type)
+ if self.mc_last_event_id is not None:
+ result["mc_last_event_id"] = from_union([from_str, from_none], self.mc_last_event_id)
+ if self.mc_session_id is not None:
+ result["mc_session_id"] = from_union([from_str, from_none], self.mc_session_id)
+ if self.mc_task_id is not None:
+ result["mc_task_id"] = from_union([from_str, from_none], self.mc_task_id)
+ if self.name is not None:
+ result["name"] = from_union([from_str, from_none], self.name)
+ if self.repository is not None:
+ result["repository"] = from_union([from_str, from_none], self.repository)
+ if self.session_sync_level is not None:
+ result["session_sync_level"] = from_union([lambda x: to_enum(SessionSyncLevel, x), from_none], self.session_sync_level)
+ if self.summary is not None:
+ result["summary"] = from_union([from_str, from_none], self.summary)
+ if self.summary_count is not None:
+ result["summary_count"] = from_union([from_int, from_none], self.summary_count)
+ if self.updated_at is not None:
+ result["updated_at"] = from_union([lambda x: x.isoformat(), from_none], self.updated_at)
+ return result
+
+@dataclass
+class WorkspacesGetWorkspaceResult:
+ workspace: Workspace | None = None
+ """Current workspace metadata, or null if not available"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'WorkspacesGetWorkspaceResult':
+ assert isinstance(obj, dict)
+ workspace = from_union([Workspace.from_dict, from_none], obj.get("workspace"))
+ return WorkspacesGetWorkspaceResult(workspace)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["workspace"] = from_union([lambda x: to_class(Workspace, x), from_none], self.workspace)
+ return result
+
+@dataclass
+class WorkspacesListFilesResult:
files: list[str]
"""Relative file paths in the workspace files directory"""
@staticmethod
- def from_dict(obj: Any) -> 'WorkspaceListFilesResult':
+ def from_dict(obj: Any) -> 'WorkspacesListFilesResult':
assert isinstance(obj, dict)
files = from_list(from_str, obj.get("files"))
- return WorkspaceListFilesResult(files)
+ return WorkspacesListFilesResult(files)
def to_dict(self) -> dict:
result: dict = {}
@@ -1189,15 +1315,15 @@ def to_dict(self) -> dict:
return result
@dataclass
-class WorkspaceReadFileResult:
+class WorkspacesReadFileResult:
content: str
"""File content as a UTF-8 string"""
@staticmethod
- def from_dict(obj: Any) -> 'WorkspaceReadFileResult':
+ def from_dict(obj: Any) -> 'WorkspacesReadFileResult':
assert isinstance(obj, dict)
content = from_str(obj.get("content"))
- return WorkspaceReadFileResult(content)
+ return WorkspacesReadFileResult(content)
def to_dict(self) -> dict:
result: dict = {}
@@ -1205,15 +1331,15 @@ def to_dict(self) -> dict:
return result
@dataclass
-class WorkspaceReadFileRequest:
+class WorkspacesReadFileRequest:
path: str
"""Relative path within the workspace files directory"""
@staticmethod
- def from_dict(obj: Any) -> 'WorkspaceReadFileRequest':
+ def from_dict(obj: Any) -> 'WorkspacesReadFileRequest':
assert isinstance(obj, dict)
path = from_str(obj.get("path"))
- return WorkspaceReadFileRequest(path)
+ return WorkspacesReadFileRequest(path)
def to_dict(self) -> dict:
result: dict = {}
@@ -1221,7 +1347,7 @@ def to_dict(self) -> dict:
return result
@dataclass
-class WorkspaceCreateFileRequest:
+class WorkspacesCreateFileRequest:
content: str
"""File content to write as a UTF-8 string"""
@@ -1229,11 +1355,11 @@ class WorkspaceCreateFileRequest:
"""Relative path within the workspace files directory"""
@staticmethod
- def from_dict(obj: Any) -> 'WorkspaceCreateFileRequest':
+ def from_dict(obj: Any) -> 'WorkspacesCreateFileRequest':
assert isinstance(obj, dict)
content = from_str(obj.get("content"))
path = from_str(obj.get("path"))
- return WorkspaceCreateFileRequest(content, path)
+ return WorkspacesCreateFileRequest(content, path)
def to_dict(self) -> dict:
result: dict = {}
@@ -2216,15 +2342,15 @@ class Kind(Enum):
class PermissionDecision:
kind: Kind
"""The permission request was approved
-
+
Denied because approval rules explicitly blocked it
-
+
Denied because no approval rule matched and user confirmation was unavailable
-
+
Denied by the user during an interactive prompt
-
+
Denied by the organization's content exclusion policy
-
+
Denied by a permission request hook registered by an extension or plugin
"""
rules: list[Any] | None = None
@@ -2235,7 +2361,7 @@ class PermissionDecision:
message: str | None = None
"""Human-readable explanation of why the path was excluded
-
+
Optional message from the hook explaining the denial
"""
path: str | None = None
@@ -3235,6 +3361,18 @@ def mode_set_request_from_dict(s: Any) -> ModeSetRequest:
def mode_set_request_to_dict(x: ModeSetRequest) -> Any:
return to_class(ModeSetRequest, x)
+def name_get_result_from_dict(s: Any) -> NameGetResult:
+ return NameGetResult.from_dict(s)
+
+def name_get_result_to_dict(x: NameGetResult) -> Any:
+ return to_class(NameGetResult, x)
+
+def name_set_request_from_dict(s: Any) -> NameSetRequest:
+ return NameSetRequest.from_dict(s)
+
+def name_set_request_to_dict(x: NameSetRequest) -> Any:
+ return to_class(NameSetRequest, x)
+
def plan_read_result_from_dict(s: Any) -> PlanReadResult:
return PlanReadResult.from_dict(s)
@@ -3247,29 +3385,35 @@ def plan_update_request_from_dict(s: Any) -> PlanUpdateRequest:
def plan_update_request_to_dict(x: PlanUpdateRequest) -> Any:
return to_class(PlanUpdateRequest, x)
-def workspace_list_files_result_from_dict(s: Any) -> WorkspaceListFilesResult:
- return WorkspaceListFilesResult.from_dict(s)
+def workspaces_get_workspace_result_from_dict(s: Any) -> WorkspacesGetWorkspaceResult:
+ return WorkspacesGetWorkspaceResult.from_dict(s)
+
+def workspaces_get_workspace_result_to_dict(x: WorkspacesGetWorkspaceResult) -> Any:
+ return to_class(WorkspacesGetWorkspaceResult, x)
-def workspace_list_files_result_to_dict(x: WorkspaceListFilesResult) -> Any:
- return to_class(WorkspaceListFilesResult, x)
+def workspaces_list_files_result_from_dict(s: Any) -> WorkspacesListFilesResult:
+ return WorkspacesListFilesResult.from_dict(s)
-def workspace_read_file_result_from_dict(s: Any) -> WorkspaceReadFileResult:
- return WorkspaceReadFileResult.from_dict(s)
+def workspaces_list_files_result_to_dict(x: WorkspacesListFilesResult) -> Any:
+ return to_class(WorkspacesListFilesResult, x)
-def workspace_read_file_result_to_dict(x: WorkspaceReadFileResult) -> Any:
- return to_class(WorkspaceReadFileResult, x)
+def workspaces_read_file_result_from_dict(s: Any) -> WorkspacesReadFileResult:
+ return WorkspacesReadFileResult.from_dict(s)
-def workspace_read_file_request_from_dict(s: Any) -> WorkspaceReadFileRequest:
- return WorkspaceReadFileRequest.from_dict(s)
+def workspaces_read_file_result_to_dict(x: WorkspacesReadFileResult) -> Any:
+ return to_class(WorkspacesReadFileResult, x)
-def workspace_read_file_request_to_dict(x: WorkspaceReadFileRequest) -> Any:
- return to_class(WorkspaceReadFileRequest, x)
+def workspaces_read_file_request_from_dict(s: Any) -> WorkspacesReadFileRequest:
+ return WorkspacesReadFileRequest.from_dict(s)
-def workspace_create_file_request_from_dict(s: Any) -> WorkspaceCreateFileRequest:
- return WorkspaceCreateFileRequest.from_dict(s)
+def workspaces_read_file_request_to_dict(x: WorkspacesReadFileRequest) -> Any:
+ return to_class(WorkspacesReadFileRequest, x)
-def workspace_create_file_request_to_dict(x: WorkspaceCreateFileRequest) -> Any:
- return to_class(WorkspaceCreateFileRequest, x)
+def workspaces_create_file_request_from_dict(s: Any) -> WorkspacesCreateFileRequest:
+ return WorkspacesCreateFileRequest.from_dict(s)
+
+def workspaces_create_file_request_to_dict(x: WorkspacesCreateFileRequest) -> Any:
+ return to_class(WorkspacesCreateFileRequest, x)
def fleet_start_result_from_dict(s: Any) -> FleetStartResult:
return FleetStartResult.from_dict(s)
@@ -3709,6 +3853,20 @@ async def set(self, params: ModeSetRequest, *, timeout: float | None = None) ->
await self._client.request("session.mode.set", params_dict, **_timeout_kwargs(timeout))
+class NameApi:
+ def __init__(self, client: "JsonRpcClient", session_id: str):
+ self._client = client
+ self._session_id = session_id
+
+ async def get(self, *, timeout: float | None = None) -> NameGetResult:
+ return NameGetResult.from_dict(await self._client.request("session.name.get", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)))
+
+ async def set(self, params: NameSetRequest, *, timeout: float | None = None) -> None:
+ params_dict = {k: v for k, v in params.to_dict().items() if v is not None}
+ params_dict["sessionId"] = self._session_id
+ await self._client.request("session.name.set", params_dict, **_timeout_kwargs(timeout))
+
+
class PlanApi:
def __init__(self, client: "JsonRpcClient", session_id: str):
self._client = client
@@ -3726,23 +3884,26 @@ async def delete(self, *, timeout: float | None = None) -> None:
await self._client.request("session.plan.delete", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))
-class WorkspaceApi:
+class WorkspacesApi:
def __init__(self, client: "JsonRpcClient", session_id: str):
self._client = client
self._session_id = session_id
- async def list_files(self, *, timeout: float | None = None) -> WorkspaceListFilesResult:
- return WorkspaceListFilesResult.from_dict(await self._client.request("session.workspace.listFiles", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)))
+ async def get_workspace(self, *, timeout: float | None = None) -> WorkspacesGetWorkspaceResult:
+ return WorkspacesGetWorkspaceResult.from_dict(await self._client.request("session.workspaces.getWorkspace", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)))
+
+ async def list_files(self, *, timeout: float | None = None) -> WorkspacesListFilesResult:
+ return WorkspacesListFilesResult.from_dict(await self._client.request("session.workspaces.listFiles", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)))
- async def read_file(self, params: WorkspaceReadFileRequest, *, timeout: float | None = None) -> WorkspaceReadFileResult:
+ async def read_file(self, params: WorkspacesReadFileRequest, *, timeout: float | None = None) -> WorkspacesReadFileResult:
params_dict = {k: v for k, v in params.to_dict().items() if v is not None}
params_dict["sessionId"] = self._session_id
- return WorkspaceReadFileResult.from_dict(await self._client.request("session.workspace.readFile", params_dict, **_timeout_kwargs(timeout)))
+ return WorkspacesReadFileResult.from_dict(await self._client.request("session.workspaces.readFile", params_dict, **_timeout_kwargs(timeout)))
- async def create_file(self, params: WorkspaceCreateFileRequest, *, timeout: float | None = None) -> None:
+ async def create_file(self, params: WorkspacesCreateFileRequest, *, timeout: float | None = None) -> None:
params_dict = {k: v for k, v in params.to_dict().items() if v is not None}
params_dict["sessionId"] = self._session_id
- await self._client.request("session.workspace.createFile", params_dict, **_timeout_kwargs(timeout))
+ await self._client.request("session.workspaces.createFile", params_dict, **_timeout_kwargs(timeout))
# Experimental: this API group is experimental and may change or be removed.
@@ -3957,8 +4118,9 @@ def __init__(self, client: "JsonRpcClient", session_id: str):
self._session_id = session_id
self.model = ModelApi(client, session_id)
self.mode = ModeApi(client, session_id)
+ self.name = NameApi(client, session_id)
self.plan = PlanApi(client, session_id)
- self.workspace = WorkspaceApi(client, session_id)
+ self.workspaces = WorkspacesApi(client, session_id)
self.fleet = FleetApi(client, session_id)
self.agent = AgentApi(client, session_id)
self.skills = SkillsApi(client, session_id)
diff --git a/python/e2e/test_rpc.py b/python/e2e/test_rpc.py
index 0d9f9a4eb..c5e9a7b79 100644
--- a/python/e2e/test_rpc.py
+++ b/python/e2e/test_rpc.py
@@ -187,8 +187,8 @@ async def test_read_update_and_delete_plan(self):
async def test_create_list_and_read_workspace_files(self):
"""Test creating, listing, and reading workspace files"""
from copilot.generated.rpc import (
- WorkspaceCreateFileRequest,
- WorkspaceReadFileRequest,
+ WorkspacesCreateFileRequest,
+ WorkspacesReadFileRequest,
)
client = CopilotClient(SubprocessConfig(cli_path=CLI_PATH, use_stdio=True))
@@ -200,31 +200,31 @@ async def test_create_list_and_read_workspace_files(self):
)
# Initially no files
- initial_files = await session.rpc.workspace.list_files()
+ initial_files = await session.rpc.workspaces.list_files()
assert initial_files.files == []
# Create a file
file_content = "Hello, workspace!"
- await session.rpc.workspace.create_file(
- WorkspaceCreateFileRequest(content=file_content, path="test.txt")
+ await session.rpc.workspaces.create_file(
+ WorkspacesCreateFileRequest(content=file_content, path="test.txt")
)
# List files
- after_create = await session.rpc.workspace.list_files()
+ after_create = await session.rpc.workspaces.list_files()
assert "test.txt" in after_create.files
# Read file
- read_result = await session.rpc.workspace.read_file(
- WorkspaceReadFileRequest(path="test.txt")
+ read_result = await session.rpc.workspaces.read_file(
+ WorkspacesReadFileRequest(path="test.txt")
)
assert read_result.content == file_content
# Create nested file
- await session.rpc.workspace.create_file(
- WorkspaceCreateFileRequest(content="Nested content", path="subdir/nested.txt")
+ await session.rpc.workspaces.create_file(
+ WorkspacesCreateFileRequest(content="Nested content", path="subdir/nested.txt")
)
- after_nested = await session.rpc.workspace.list_files()
+ after_nested = await session.rpc.workspaces.list_files()
assert "test.txt" in after_nested.files
assert any("nested.txt" in f for f in after_nested.files)
diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts
index 9e63b68ea..243047fb6 100644
--- a/scripts/codegen/csharp.ts
+++ b/scripts/codegen/csharp.ts
@@ -258,6 +258,11 @@ function emitDataAnnotations(schema: JSONSchema7, indent: string): string[] {
}
// [MinLength] / [MaxLength] for string constraints
+ if (typeof schema.minLength === "number" || typeof schema.maxLength === "number") {
+ attrs.push(
+ `${indent}[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")]`
+ );
+ }
if (typeof schema.minLength === "number") {
attrs.push(`${indent}[MinLength(${schema.minLength})]`);
}
diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts
index 62b53e1e6..46d11de83 100644
--- a/scripts/codegen/python.ts
+++ b/scripts/codegen/python.ts
@@ -1454,6 +1454,14 @@ async function generateRpc(schemaPath?: string): Promise {
typesCode = modernizePython(typesCode);
typesCode = collapsePlaceholderPythonDataclasses(typesCode);
+ // Strip quicktype's import block and preamble — we provide our own unified header.
+ // The preamble ends just before the first helper function (e.g. "def from_str")
+ // or class definition.
+ typesCode = typesCode.replace(/^[\s\S]*?(?=^(?:def |@dataclass|class )\w)/m, "");
+
+ // Strip trailing whitespace from blank lines (e.g. inside multi-line docstrings)
+ typesCode = typesCode.replace(/^\s+$/gm, "");
+
// Annotate experimental data types
const experimentalTypeNames = new Set();
for (const method of allMethods) {
@@ -1494,7 +1502,15 @@ if TYPE_CHECKING:
from collections.abc import Callable
from dataclasses import dataclass
-from typing import Protocol
+from datetime import datetime
+from enum import Enum
+from typing import Any, Protocol, TypeVar, cast
+from uuid import UUID
+
+import dateutil.parser
+
+T = TypeVar("T")
+EnumT = TypeVar("EnumT", bound=Enum)
`);
lines.push(typesCode);
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index 691d66bf9..ba4ed7d10 100644
--- a/test/harness/package-lock.json
+++ b/test/harness/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
- "@github/copilot": "^1.0.22",
+ "@github/copilot": "^1.0.26",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"openai": "^6.17.0",
@@ -462,27 +462,27 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.22",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.22.tgz",
- "integrity": "sha512-BR9oTJ1tQ51RV81xcxmlZe0zB3Tf8i/vFsKSTm2f5wRLJgtuVl2LgaFStoI/peTFcmgtZbhrqsnWTu5GkEPK5Q==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.26.tgz",
+ "integrity": "sha512-F7P6yimFzjvWxOF/A0F6k//vcpSVcVusQjaybb3IKyrEDhnd/LOv2tD+x6W0IoxCftGDDhkzBA2aon3rL9lPhQ==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.22",
- "@github/copilot-darwin-x64": "1.0.22",
- "@github/copilot-linux-arm64": "1.0.22",
- "@github/copilot-linux-x64": "1.0.22",
- "@github/copilot-win32-arm64": "1.0.22",
- "@github/copilot-win32-x64": "1.0.22"
+ "@github/copilot-darwin-arm64": "1.0.26",
+ "@github/copilot-darwin-x64": "1.0.26",
+ "@github/copilot-linux-arm64": "1.0.26",
+ "@github/copilot-linux-x64": "1.0.26",
+ "@github/copilot-win32-arm64": "1.0.26",
+ "@github/copilot-win32-x64": "1.0.26"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.22",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.22.tgz",
- "integrity": "sha512-cK42uX+oz46Cjsb7z+rdPw+DIGczfVSFWlc1WDcdVlwBW4cEfV0pzFXExpN1r1z179TFgAaVMbhkgLqhOZ/PeQ==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.26.tgz",
+ "integrity": "sha512-eV+jDMj4vnjdGcG+c4zg11zZKVAp94Hm4sK4f9LnyWw8MumTfS5F2Yyse9zt7A3oGlegyczmJopKwuwZbQd4ww==",
"cpu": [
"arm64"
],
@@ -497,9 +497,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.22",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.22.tgz",
- "integrity": "sha512-Pmw0ipF+yeLbP6JctsEoMS2LUCpVdC2r557BnCoe48BN8lO8i9JLnkpuDDrJ1AZuCk1VjnujFKEQywOOdfVlpA==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.26.tgz",
+ "integrity": "sha512-2AAgu19F3scDlYhsiHxCn0cz4ZkINq8gxnqW0an8VQn6p15lDcah6PqHw+RJ+12qiYX5L5NNACty9UOkIK7Kzg==",
"cpu": [
"x64"
],
@@ -514,9 +514,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.22",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.22.tgz",
- "integrity": "sha512-WVgG67VmZgHoD7GMlkTxEVe1qK8k9Ek9A02/Da7obpsDdtBInt3nJTwBEgm4cNDM4XaenQH17/jmwVtTwXB6lw==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.26.tgz",
+ "integrity": "sha512-SnM7+TGAZ/i9dim5FfHM7+ii01hdpHJzzh8vnnA1Fa7RPFJaQ2KTOdTDJFgfv6e/jLhKXZEelYIidgCA3vSQCQ==",
"cpu": [
"arm64"
],
@@ -531,9 +531,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.22",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.22.tgz",
- "integrity": "sha512-XRkHVFmdC7FMrczXOdPjbNKiknMr13asKtwJoErJO/Xdy4cmzKQHSvNsBk8VNrr7oyWrUcB1F6mbIxb2LFxPOw==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.26.tgz",
+ "integrity": "sha512-x76vcwVbi0j03hFMhiQs+Eqefd9Xmc4qJoaj44YA2VsJuDbZw2Yv7ZBq7Vyxd/shJwJZjaKv36MHcx5bVUMBJQ==",
"cpu": [
"x64"
],
@@ -548,9 +548,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.22",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.22.tgz",
- "integrity": "sha512-Ao6gv1f2ZV+HVlkB1MV7YFdCuaB3NcFCnNu0a6/WLl2ypsfP1vWosPPkIB32jQJeBkT9ku3exOZLRj+XC0P3Mg==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.26.tgz",
+ "integrity": "sha512-enVRcy7W9RD1bwYkF+mcxR+biXsG/X5m46XBaD0opvfDeiBHceDnI8hEI0O1A5PYvRo88AZFvDEmEW3Gdj6+rQ==",
"cpu": [
"arm64"
],
@@ -565,9 +565,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.22",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.22.tgz",
- "integrity": "sha512-EppcL+3TpxC+X/eQEIYtkN0PaA3/cvtI9UJqldLIkKDPXNYk/0mw877Ru9ypRcBWBWokDN6iKIWk5IxYH+JIvg==",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.26.tgz",
+ "integrity": "sha512-DpJF6C1x4+sYIXUx5+vWCu6cFAbD2YlrXQ/BRttf2MMdc0DHwdgJxrttBBF2qCvmpfzjSE8cr5G0kt5EUk7FGw==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index def9f09cf..527c036b7 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -11,7 +11,7 @@
"test": "vitest run"
},
"devDependencies": {
- "@github/copilot": "^1.0.22",
+ "@github/copilot": "^1.0.26",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"openai": "^6.17.0",