From 3a239dcf8df295984d580f857725ed0d49c159d6 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 17 Mar 2026 11:31:12 -0400 Subject: [PATCH 1/7] Add experimental API annotations from schema stability markers Read the 'stability' field from api.schema.json and propagate it to generated code in all four SDK languages. APIs marked as experimental in the schema (fleet, agent, compaction) now carry appropriate annotations in the generated output. Changes to codegen scripts (scripts/codegen/): - utils.ts: Add stability field to RpcMethod; add isNodeFullyExperimental helper - csharp.ts: Emit [Experimental(Diagnostics.Experimental)] on types and API classes - typescript.ts: Emit /** @experimental */ JSDoc on types and groups - python.ts: Emit # Experimental comments on types and API classes, docstrings on methods - go.ts: Emit // Experimental: comments on types and API structs Design decisions: - When all methods in a group are experimental, the group/class is annotated and individual methods are not (annotation is inherited) - Data types (request/result) for experimental methods are also annotated - C# uses a Diagnostics.Experimental const ("GHCP001") referenced by all attributes - SDK csproj suppresses GHCP001 internally; consumers still see warnings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 23 + dotnet/src/GitHub.Copilot.SDK.csproj | 4 + dotnet/test/GitHub.Copilot.SDK.Test.csproj | 1 + go/rpc/generated_rpc.go | 1016 +++++++++----------- nodejs/src/generated/rpc.ts | 15 + python/copilot/generated/rpc.py | 11 + scripts/codegen/csharp.ts | 55 +- scripts/codegen/go.ts | 35 +- scripts/codegen/python.ts | 35 +- scripts/codegen/typescript.ts | 18 +- scripts/codegen/utils.ts | 16 + 11 files changed, 643 insertions(+), 586 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index f6ca0382f..6fc593c12 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -5,12 +5,20 @@ // AUTO-GENERATED FILE - DO NOT EDIT // Generated from: api.schema.json +using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; using StreamJsonRpc; namespace GitHub.Copilot.SDK.Rpc; +/// Diagnostic IDs for the Copilot SDK. +internal static class Diagnostics +{ + /// Indicates an experimental API that may change or be removed. + internal const string Experimental = "GHCP001"; +} + /// RPC data type for Ping operations. public class PingResult { @@ -427,6 +435,7 @@ internal class SessionWorkspaceCreateFileRequest } /// RPC data type for SessionFleetStart operations. +[Experimental(Diagnostics.Experimental)] public class SessionFleetStartResult { /// Whether fleet mode was successfully activated. @@ -435,6 +444,7 @@ public class SessionFleetStartResult } /// RPC data type for SessionFleetStart operations. +[Experimental(Diagnostics.Experimental)] internal class SessionFleetStartRequest { /// Target session identifier. @@ -463,6 +473,7 @@ public class Agent } /// RPC data type for SessionAgentList operations. +[Experimental(Diagnostics.Experimental)] public class SessionAgentListResult { /// Available custom agents. @@ -471,6 +482,7 @@ public class SessionAgentListResult } /// RPC data type for SessionAgentList operations. +[Experimental(Diagnostics.Experimental)] internal class SessionAgentListRequest { /// Target session identifier. @@ -495,6 +507,7 @@ public class SessionAgentGetCurrentResultAgent } /// RPC data type for SessionAgentGetCurrent operations. +[Experimental(Diagnostics.Experimental)] public class SessionAgentGetCurrentResult { /// Currently selected custom agent, or null if using the default agent. @@ -503,6 +516,7 @@ public class SessionAgentGetCurrentResult } /// RPC data type for SessionAgentGetCurrent operations. +[Experimental(Diagnostics.Experimental)] internal class SessionAgentGetCurrentRequest { /// Target session identifier. @@ -527,6 +541,7 @@ public class SessionAgentSelectResultAgent } /// RPC data type for SessionAgentSelect operations. +[Experimental(Diagnostics.Experimental)] public class SessionAgentSelectResult { /// The newly selected custom agent. @@ -535,6 +550,7 @@ public class SessionAgentSelectResult } /// RPC data type for SessionAgentSelect operations. +[Experimental(Diagnostics.Experimental)] internal class SessionAgentSelectRequest { /// Target session identifier. @@ -547,11 +563,13 @@ internal class SessionAgentSelectRequest } /// RPC data type for SessionAgentDeselect operations. +[Experimental(Diagnostics.Experimental)] public class SessionAgentDeselectResult { } /// RPC data type for SessionAgentDeselect operations. +[Experimental(Diagnostics.Experimental)] internal class SessionAgentDeselectRequest { /// Target session identifier. @@ -560,6 +578,7 @@ internal class SessionAgentDeselectRequest } /// RPC data type for SessionCompactionCompact operations. +[Experimental(Diagnostics.Experimental)] public class SessionCompactionCompactResult { /// Whether compaction completed successfully. @@ -576,6 +595,7 @@ public class SessionCompactionCompactResult } /// RPC data type for SessionCompactionCompact operations. +[Experimental(Diagnostics.Experimental)] internal class SessionCompactionCompactRequest { /// Target session identifier. @@ -1000,6 +1020,7 @@ public async Task CreateFileAsync(string path, } /// Provides session-scoped Fleet APIs. +[Experimental(Diagnostics.Experimental)] public class FleetApi { private readonly JsonRpc _rpc; @@ -1020,6 +1041,7 @@ public async Task StartAsync(string? prompt = null, Can } /// Provides session-scoped Agent APIs. +[Experimental(Diagnostics.Experimental)] public class AgentApi { private readonly JsonRpc _rpc; @@ -1061,6 +1083,7 @@ public async Task DeselectAsync(CancellationToken ca } /// Provides session-scoped Compaction APIs. +[Experimental(Diagnostics.Experimental)] public class CompactionApi { private readonly JsonRpc _rpc; diff --git a/dotnet/src/GitHub.Copilot.SDK.csproj b/dotnet/src/GitHub.Copilot.SDK.csproj index 5d2502c87..38eb0cf3a 100644 --- a/dotnet/src/GitHub.Copilot.SDK.csproj +++ b/dotnet/src/GitHub.Copilot.SDK.csproj @@ -20,6 +20,10 @@ true + + $(NoWarn);GHCP001 + + true diff --git a/dotnet/test/GitHub.Copilot.SDK.Test.csproj b/dotnet/test/GitHub.Copilot.SDK.Test.csproj index fbc9f17c3..8e0dbf6b7 100644 --- a/dotnet/test/GitHub.Copilot.SDK.Test.csproj +++ b/dotnet/test/GitHub.Copilot.SDK.Test.csproj @@ -2,6 +2,7 @@ false + $(NoWarn);GHCP001 diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index ffe87455e..c06b59796 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -4,283 +4,291 @@ package rpc import ( - "context" - "encoding/json" + "context" + "encoding/json" - "github.com/github/copilot-sdk/go/internal/jsonrpc2" + "github.com/github/copilot-sdk/go/internal/jsonrpc2" ) type PingResult struct { - // Echoed message (or default greeting) - Message string `json:"message"` - // Server protocol version number - ProtocolVersion float64 `json:"protocolVersion"` - // Server timestamp in milliseconds - Timestamp float64 `json:"timestamp"` + // Echoed message (or default greeting) + Message string `json:"message"` + // Server protocol version number + ProtocolVersion float64 `json:"protocolVersion"` + // Server timestamp in milliseconds + Timestamp float64 `json:"timestamp"` } type PingParams struct { - // Optional message to echo back - Message *string `json:"message,omitempty"` + // Optional message to echo back + Message *string `json:"message,omitempty"` } type ModelsListResult struct { - // List of available models with full metadata - Models []Model `json:"models"` + // List of available models with full metadata + Models []Model `json:"models"` } type Model struct { - // Billing information - Billing *Billing `json:"billing,omitempty"` - // Model capabilities and limits - Capabilities Capabilities `json:"capabilities"` - // Default reasoning effort level (only present if model supports reasoning effort) - DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` - // Model identifier (e.g., "claude-sonnet-4.5") - ID string `json:"id"` - // Display name - Name string `json:"name"` - // Policy state (if applicable) - Policy *Policy `json:"policy,omitempty"` - // Supported reasoning effort levels (only present if model supports reasoning effort) - SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` + // Billing information + Billing *Billing `json:"billing,omitempty"` + // Model capabilities and limits + Capabilities Capabilities `json:"capabilities"` + // Default reasoning effort level (only present if model supports reasoning effort) + DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` + // Model identifier (e.g., "claude-sonnet-4.5") + ID string `json:"id"` + // Display name + Name string `json:"name"` + // Policy state (if applicable) + Policy *Policy `json:"policy,omitempty"` + // Supported reasoning effort levels (only present if model supports reasoning effort) + SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` } // Billing information type Billing struct { - // Billing cost multiplier relative to the base rate - Multiplier float64 `json:"multiplier"` + // Billing cost multiplier relative to the base rate + Multiplier float64 `json:"multiplier"` } // Model capabilities and limits type Capabilities struct { - // Token limits for prompts, outputs, and context window - Limits Limits `json:"limits"` - // Feature flags indicating what the model supports - Supports Supports `json:"supports"` + // Token limits for prompts, outputs, and context window + Limits Limits `json:"limits"` + // Feature flags indicating what the model supports + Supports Supports `json:"supports"` } // Token limits for prompts, outputs, and context window type Limits struct { - // Maximum total context window size in tokens - MaxContextWindowTokens float64 `json:"max_context_window_tokens"` - // Maximum number of output/completion tokens - MaxOutputTokens *float64 `json:"max_output_tokens,omitempty"` - // Maximum number of prompt/input tokens - MaxPromptTokens *float64 `json:"max_prompt_tokens,omitempty"` + // Maximum total context window size in tokens + MaxContextWindowTokens float64 `json:"max_context_window_tokens"` + // Maximum number of output/completion tokens + MaxOutputTokens *float64 `json:"max_output_tokens,omitempty"` + // Maximum number of prompt/input tokens + MaxPromptTokens *float64 `json:"max_prompt_tokens,omitempty"` } // Feature flags indicating what the model supports type Supports struct { - // Whether this model supports reasoning effort configuration - ReasoningEffort *bool `json:"reasoningEffort,omitempty"` - // Whether this model supports vision/image input - Vision *bool `json:"vision,omitempty"` + // Whether this model supports reasoning effort configuration + ReasoningEffort *bool `json:"reasoningEffort,omitempty"` + // Whether this model supports vision/image input + Vision *bool `json:"vision,omitempty"` } // Policy state (if applicable) type Policy struct { - // Current policy state for this model - State string `json:"state"` - // Usage terms or conditions for this model - Terms string `json:"terms"` + // Current policy state for this model + State string `json:"state"` + // Usage terms or conditions for this model + Terms string `json:"terms"` } type ToolsListResult struct { - // List of available built-in tools with metadata - Tools []Tool `json:"tools"` + // List of available built-in tools with metadata + Tools []Tool `json:"tools"` } type Tool struct { - // Description of what the tool does - Description string `json:"description"` - // Optional instructions for how to use this tool effectively - Instructions *string `json:"instructions,omitempty"` - // Tool identifier (e.g., "bash", "grep", "str_replace_editor") - Name string `json:"name"` - // Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP - // tools) - NamespacedName *string `json:"namespacedName,omitempty"` - // JSON Schema for the tool's input parameters - Parameters map[string]interface{} `json:"parameters,omitempty"` + // Description of what the tool does + Description string `json:"description"` + // Optional instructions for how to use this tool effectively + Instructions *string `json:"instructions,omitempty"` + // Tool identifier (e.g., "bash", "grep", "str_replace_editor") + Name string `json:"name"` + // Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP + // tools) + NamespacedName *string `json:"namespacedName,omitempty"` + // JSON Schema for the tool's input parameters + Parameters map[string]interface{} `json:"parameters,omitempty"` } type ToolsListParams struct { - // Optional model ID — when provided, the returned tool list reflects model-specific - // overrides - Model *string `json:"model,omitempty"` + // Optional model ID — when provided, the returned tool list reflects model-specific + // overrides + Model *string `json:"model,omitempty"` } type AccountGetQuotaResult struct { - // Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) - QuotaSnapshots map[string]QuotaSnapshot `json:"quotaSnapshots"` + // Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) + QuotaSnapshots map[string]QuotaSnapshot `json:"quotaSnapshots"` } type QuotaSnapshot struct { - // Number of requests included in the entitlement - EntitlementRequests float64 `json:"entitlementRequests"` - // Number of overage requests made this period - Overage float64 `json:"overage"` - // Whether pay-per-request usage is allowed when quota is exhausted - OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` - // Percentage of entitlement remaining - RemainingPercentage float64 `json:"remainingPercentage"` - // Date when the quota resets (ISO 8601) - ResetDate *string `json:"resetDate,omitempty"` - // Number of requests used so far this period - UsedRequests float64 `json:"usedRequests"` + // Number of requests included in the entitlement + EntitlementRequests float64 `json:"entitlementRequests"` + // Number of overage requests made this period + Overage float64 `json:"overage"` + // Whether pay-per-request usage is allowed when quota is exhausted + OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` + // Percentage of entitlement remaining + RemainingPercentage float64 `json:"remainingPercentage"` + // Date when the quota resets (ISO 8601) + ResetDate *string `json:"resetDate,omitempty"` + // Number of requests used so far this period + UsedRequests float64 `json:"usedRequests"` } type SessionModelGetCurrentResult struct { - // Currently active model identifier - ModelID *string `json:"modelId,omitempty"` + // Currently active model identifier + ModelID *string `json:"modelId,omitempty"` } type SessionModelSwitchToResult struct { - // Currently active model identifier after the switch - ModelID *string `json:"modelId,omitempty"` + // Currently active model identifier after the switch + ModelID *string `json:"modelId,omitempty"` } type SessionModelSwitchToParams struct { - // Model identifier to switch to - ModelID string `json:"modelId"` - // Reasoning effort level to use for the model - ReasoningEffort *string `json:"reasoningEffort,omitempty"` + // Model identifier to switch to + ModelID string `json:"modelId"` + // Reasoning effort level to use for the model + ReasoningEffort *string `json:"reasoningEffort,omitempty"` } type SessionModeGetResult struct { - // The current agent mode. - Mode Mode `json:"mode"` + // The current agent mode. + Mode Mode `json:"mode"` } type SessionModeSetResult struct { - // The agent mode after switching. - Mode Mode `json:"mode"` + // The agent mode after switching. + Mode Mode `json:"mode"` } type SessionModeSetParams struct { - // The mode to switch to. Valid values: "interactive", "plan", "autopilot". - Mode Mode `json:"mode"` + // The mode to switch to. Valid values: "interactive", "plan", "autopilot". + Mode Mode `json:"mode"` } type SessionPlanReadResult struct { - // The content of the plan file, or null if it does not exist - Content *string `json:"content"` - // Whether the plan file exists in the workspace - Exists bool `json:"exists"` - // Absolute file path of the plan file, or null if workspace is not enabled - Path *string `json:"path"` + // The content of the plan file, or null if it does not exist + Content *string `json:"content"` + // Whether the plan file exists in the workspace + Exists bool `json:"exists"` + // Absolute file path of the plan file, or null if workspace is not enabled + Path *string `json:"path"` } type SessionPlanUpdateResult struct { } type SessionPlanUpdateParams struct { - // The new content for the plan file - Content string `json:"content"` + // The new content for the plan file + Content string `json:"content"` } type SessionPlanDeleteResult struct { } type SessionWorkspaceListFilesResult struct { - // Relative file paths in the workspace files directory - Files []string `json:"files"` + // Relative file paths in the workspace files directory + Files []string `json:"files"` } type SessionWorkspaceReadFileResult struct { - // File content as a UTF-8 string - Content string `json:"content"` + // File content as a UTF-8 string + Content string `json:"content"` } type SessionWorkspaceReadFileParams struct { - // Relative path within the workspace files directory - Path string `json:"path"` + // Relative path within the workspace files directory + Path string `json:"path"` } type SessionWorkspaceCreateFileResult struct { } type SessionWorkspaceCreateFileParams struct { - // File content to write as a UTF-8 string - Content string `json:"content"` - // Relative path within the workspace files directory - Path string `json:"path"` + // File content to write as a UTF-8 string + Content string `json:"content"` + // Relative path within the workspace files directory + Path string `json:"path"` } +// Experimental: SessionFleetStartResult is part of an experimental API and may change or be removed. type SessionFleetStartResult struct { - // Whether fleet mode was successfully activated - Started bool `json:"started"` + // Whether fleet mode was successfully activated + Started bool `json:"started"` } +// Experimental: SessionFleetStartParams is part of an experimental API and may change or be removed. type SessionFleetStartParams struct { - // Optional user prompt to combine with fleet instructions - Prompt *string `json:"prompt,omitempty"` + // Optional user prompt to combine with fleet instructions + Prompt *string `json:"prompt,omitempty"` } +// Experimental: SessionAgentListResult is part of an experimental API and may change or be removed. type SessionAgentListResult struct { - // Available custom agents - Agents []AgentElement `json:"agents"` + // Available custom agents + Agents []AgentElement `json:"agents"` } type AgentElement struct { - // Description of the agent's purpose - Description string `json:"description"` - // Human-readable display name - DisplayName string `json:"displayName"` - // Unique identifier of the custom agent - Name string `json:"name"` + // Description of the agent's purpose + Description string `json:"description"` + // Human-readable display name + DisplayName string `json:"displayName"` + // Unique identifier of the custom agent + Name string `json:"name"` } +// Experimental: SessionAgentGetCurrentResult is part of an experimental API and may change or be removed. type SessionAgentGetCurrentResult struct { - // Currently selected custom agent, or null if using the default agent - Agent *SessionAgentGetCurrentResultAgent `json:"agent"` + // Currently selected custom agent, or null if using the default agent + Agent *SessionAgentGetCurrentResultAgent `json:"agent"` } type SessionAgentGetCurrentResultAgent struct { - // Description of the agent's purpose - Description string `json:"description"` - // Human-readable display name - DisplayName string `json:"displayName"` - // Unique identifier of the custom agent - Name string `json:"name"` + // Description of the agent's purpose + Description string `json:"description"` + // Human-readable display name + DisplayName string `json:"displayName"` + // Unique identifier of the custom agent + Name string `json:"name"` } +// Experimental: SessionAgentSelectResult is part of an experimental API and may change or be removed. type SessionAgentSelectResult struct { - // The newly selected custom agent - Agent SessionAgentSelectResultAgent `json:"agent"` + // The newly selected custom agent + Agent SessionAgentSelectResultAgent `json:"agent"` } // The newly selected custom agent type SessionAgentSelectResultAgent struct { - // Description of the agent's purpose - Description string `json:"description"` - // Human-readable display name - DisplayName string `json:"displayName"` - // Unique identifier of the custom agent - Name string `json:"name"` + // Description of the agent's purpose + Description string `json:"description"` + // Human-readable display name + DisplayName string `json:"displayName"` + // Unique identifier of the custom agent + Name string `json:"name"` } +// Experimental: SessionAgentSelectParams is part of an experimental API and may change or be removed. type SessionAgentSelectParams struct { - // Name of the custom agent to select - Name string `json:"name"` + // Name of the custom agent to select + Name string `json:"name"` } +// Experimental: SessionAgentDeselectResult is part of an experimental API and may change or be removed. type SessionAgentDeselectResult struct { } +// Experimental: SessionCompactionCompactResult is part of an experimental API and may change or be removed. type SessionCompactionCompactResult struct { - // Number of messages removed during compaction - MessagesRemoved float64 `json:"messagesRemoved"` - // Whether compaction completed successfully - Success bool `json:"success"` - // Number of tokens freed by compaction - TokensRemoved float64 `json:"tokensRemoved"` + // Number of messages removed during compaction + MessagesRemoved float64 `json:"messagesRemoved"` + // Whether compaction completed successfully + Success bool `json:"success"` + // Number of tokens freed by compaction + TokensRemoved float64 `json:"tokensRemoved"` } type SessionToolsHandlePendingToolCallResult struct { - // Whether the tool call result was handled successfully - Success bool `json:"success"` + // Whether the tool call result was handled successfully + Success bool `json:"success"` } type SessionToolsHandlePendingToolCallParams struct { @@ -297,8 +305,8 @@ type ResultResult struct { } type SessionPermissionsHandlePendingPermissionRequestResult struct { - // Whether the permission request was handled successfully - Success bool `json:"success"` + // Whether the permission request was handled successfully + Success bool `json:"success"` } type SessionPermissionsHandlePendingPermissionRequestParams struct { @@ -315,44 +323,44 @@ type SessionPermissionsHandlePendingPermissionRequestParamsResult struct { } type SessionLogResult struct { - // The unique identifier of the emitted session event - EventID string `json:"eventId"` + // The unique identifier of the emitted session event + EventID string `json:"eventId"` } type SessionLogParams struct { - // When true, the message is transient and not persisted to the session event log on disk - Ephemeral *bool `json:"ephemeral,omitempty"` - // Log severity level. Determines how the message is displayed in the timeline. Defaults to - // "info". - Level *Level `json:"level,omitempty"` - // Human-readable message - Message string `json:"message"` + // When true, the message is transient and not persisted to the session event log on disk + Ephemeral *bool `json:"ephemeral,omitempty"` + // Log severity level. Determines how the message is displayed in the timeline. Defaults to + // "info". + Level *Level `json:"level,omitempty"` + // Human-readable message + Message string `json:"message"` } type SessionShellExecResult struct { - // Unique identifier for tracking streamed output - ProcessID string `json:"processId"` + // Unique identifier for tracking streamed output + ProcessID string `json:"processId"` } type SessionShellExecParams struct { - // Shell command to execute - Command string `json:"command"` - // Working directory (defaults to session working directory) - Cwd *string `json:"cwd,omitempty"` - // Timeout in milliseconds (default: 30000) - Timeout *float64 `json:"timeout,omitempty"` + // Shell command to execute + Command string `json:"command"` + // Working directory (defaults to session working directory) + Cwd *string `json:"cwd,omitempty"` + // Timeout in milliseconds (default: 30000) + Timeout *float64 `json:"timeout,omitempty"` } type SessionShellKillResult struct { - // Whether the signal was sent successfully - Killed bool `json:"killed"` + // Whether the signal was sent successfully + Killed bool `json:"killed"` } type SessionShellKillParams struct { - // Process identifier returned by shell.exec - ProcessID string `json:"processId"` - // Signal to send (default: SIGTERM) - Signal *Signal `json:"signal,omitempty"` + // Process identifier returned by shell.exec + ProcessID string `json:"processId"` + // Signal to send (default: SIGTERM) + Signal *Signal `json:"signal,omitempty"` } // The current agent mode. @@ -402,490 +410,364 @@ type ResultUnion struct { String *string } -type ServerModelsRpcApi struct{ client *jsonrpc2.Client } + +type ServerModelsRpcApi struct { client *jsonrpc2.Client } func (a *ServerModelsRpcApi) List(ctx context.Context) (*ModelsListResult, error) { - raw, err := a.client.Request("models.list", map[string]interface{}{}) - if err != nil { - return nil, err - } - var result ModelsListResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + raw, err := a.client.Request("models.list", map[string]interface{}{}) + if err != nil { return nil, err } + var result ModelsListResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } -type ServerToolsRpcApi struct{ client *jsonrpc2.Client } +type ServerToolsRpcApi struct { client *jsonrpc2.Client } func (a *ServerToolsRpcApi) List(ctx context.Context, params *ToolsListParams) (*ToolsListResult, error) { - raw, err := a.client.Request("tools.list", params) - if err != nil { - return nil, err - } - var result ToolsListResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + raw, err := a.client.Request("tools.list", params) + if err != nil { return nil, err } + var result ToolsListResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } -type ServerAccountRpcApi struct{ client *jsonrpc2.Client } +type ServerAccountRpcApi struct { client *jsonrpc2.Client } func (a *ServerAccountRpcApi) GetQuota(ctx context.Context) (*AccountGetQuotaResult, error) { - raw, err := a.client.Request("account.getQuota", map[string]interface{}{}) - if err != nil { - return nil, err - } - var result AccountGetQuotaResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + raw, err := a.client.Request("account.getQuota", map[string]interface{}{}) + if err != nil { return nil, err } + var result AccountGetQuotaResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } // ServerRpc provides typed server-scoped RPC methods. type ServerRpc struct { - client *jsonrpc2.Client - Models *ServerModelsRpcApi - Tools *ServerToolsRpcApi - Account *ServerAccountRpcApi + client *jsonrpc2.Client + Models *ServerModelsRpcApi + Tools *ServerToolsRpcApi + Account *ServerAccountRpcApi } func (a *ServerRpc) Ping(ctx context.Context, params *PingParams) (*PingResult, error) { - raw, err := a.client.Request("ping", params) - if err != nil { - return nil, err - } - var result PingResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + raw, err := a.client.Request("ping", params) + if err != nil { return nil, err } + var result PingResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func NewServerRpc(client *jsonrpc2.Client) *ServerRpc { - return &ServerRpc{client: client, - Models: &ServerModelsRpcApi{client: client}, - Tools: &ServerToolsRpcApi{client: client}, - Account: &ServerAccountRpcApi{client: client}, - } + return &ServerRpc{client: client, + Models: &ServerModelsRpcApi{client: client}, + Tools: &ServerToolsRpcApi{client: client}, + Account: &ServerAccountRpcApi{client: client}, + } } -type ModelRpcApi struct { - client *jsonrpc2.Client - sessionID string -} +type ModelRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ModelRpcApi) GetCurrent(ctx context.Context) (*SessionModelGetCurrentResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.model.getCurrent", req) - if err != nil { - return nil, err - } - var result SessionModelGetCurrentResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.model.getCurrent", req) + if err != nil { return nil, err } + var result SessionModelGetCurrentResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *ModelRpcApi) SwitchTo(ctx context.Context, params *SessionModelSwitchToParams) (*SessionModelSwitchToResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["modelId"] = params.ModelID - if params.ReasoningEffort != nil { - req["reasoningEffort"] = *params.ReasoningEffort - } - } - raw, err := a.client.Request("session.model.switchTo", req) - if err != nil { - return nil, err - } - var result SessionModelSwitchToResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil -} - -type ModeRpcApi struct { - client *jsonrpc2.Client - sessionID string -} + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["modelId"] = params.ModelID + if params.ReasoningEffort != nil { + req["reasoningEffort"] = *params.ReasoningEffort + } + } + raw, err := a.client.Request("session.model.switchTo", req) + if err != nil { return nil, err } + var result SessionModelSwitchToResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil +} + +type ModeRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ModeRpcApi) Get(ctx context.Context) (*SessionModeGetResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.mode.get", req) - if err != nil { - return nil, err - } - var result SessionModeGetResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.mode.get", req) + if err != nil { return nil, err } + var result SessionModeGetResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *ModeRpcApi) Set(ctx context.Context, params *SessionModeSetParams) (*SessionModeSetResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["mode"] = params.Mode - } - raw, err := a.client.Request("session.mode.set", req) - if err != nil { - return nil, err - } - var result SessionModeSetResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil -} - -type PlanRpcApi struct { - client *jsonrpc2.Client - sessionID string + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["mode"] = params.Mode + } + raw, err := a.client.Request("session.mode.set", req) + if err != nil { return nil, err } + var result SessionModeSetResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } +type PlanRpcApi struct { client *jsonrpc2.Client; sessionID string } + func (a *PlanRpcApi) Read(ctx context.Context) (*SessionPlanReadResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.plan.read", req) - if err != nil { - return nil, err - } - var result SessionPlanReadResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.plan.read", req) + if err != nil { return nil, err } + var result SessionPlanReadResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *PlanRpcApi) Update(ctx context.Context, params *SessionPlanUpdateParams) (*SessionPlanUpdateResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["content"] = params.Content - } - raw, err := a.client.Request("session.plan.update", req) - if err != nil { - return nil, err - } - var result SessionPlanUpdateResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["content"] = params.Content + } + raw, err := a.client.Request("session.plan.update", req) + if err != nil { return nil, err } + var result SessionPlanUpdateResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *PlanRpcApi) Delete(ctx context.Context) (*SessionPlanDeleteResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.plan.delete", req) - if err != nil { - return nil, err - } - var result SessionPlanDeleteResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.plan.delete", req) + if err != nil { return nil, err } + var result SessionPlanDeleteResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } -type WorkspaceRpcApi struct { - client *jsonrpc2.Client - sessionID string -} +type WorkspaceRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *WorkspaceRpcApi) ListFiles(ctx context.Context) (*SessionWorkspaceListFilesResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.workspace.listFiles", req) - if err != nil { - return nil, err - } - var result SessionWorkspaceListFilesResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.workspace.listFiles", req) + if err != nil { return nil, err } + var result SessionWorkspaceListFilesResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *WorkspaceRpcApi) ReadFile(ctx context.Context, params *SessionWorkspaceReadFileParams) (*SessionWorkspaceReadFileResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["path"] = params.Path - } - raw, err := a.client.Request("session.workspace.readFile", req) - if err != nil { - return nil, err - } - var result SessionWorkspaceReadFileResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["path"] = params.Path + } + raw, err := a.client.Request("session.workspace.readFile", req) + if err != nil { return nil, err } + var result SessionWorkspaceReadFileResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *WorkspaceRpcApi) CreateFile(ctx context.Context, params *SessionWorkspaceCreateFileParams) (*SessionWorkspaceCreateFileResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["path"] = params.Path - req["content"] = params.Content - } - raw, err := a.client.Request("session.workspace.createFile", req) - if err != nil { - return nil, err - } - var result SessionWorkspaceCreateFileResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil -} - -type FleetRpcApi struct { - client *jsonrpc2.Client - sessionID string + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["path"] = params.Path + req["content"] = params.Content + } + raw, err := a.client.Request("session.workspace.createFile", req) + if err != nil { return nil, err } + var result SessionWorkspaceCreateFileResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } +// Experimental: FleetRpcApi contains experimental APIs that may change or be removed. +type FleetRpcApi struct { client *jsonrpc2.Client; sessionID string } + func (a *FleetRpcApi) Start(ctx context.Context, params *SessionFleetStartParams) (*SessionFleetStartResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - if params.Prompt != nil { - req["prompt"] = *params.Prompt - } - } - raw, err := a.client.Request("session.fleet.start", req) - if err != nil { - return nil, err - } - var result SessionFleetStartResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil -} - -type AgentRpcApi struct { - client *jsonrpc2.Client - sessionID string -} + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + if params.Prompt != nil { + req["prompt"] = *params.Prompt + } + } + raw, err := a.client.Request("session.fleet.start", req) + if err != nil { return nil, err } + var result SessionFleetStartResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil +} + +// Experimental: AgentRpcApi contains experimental APIs that may change or be removed. +type AgentRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *AgentRpcApi) List(ctx context.Context) (*SessionAgentListResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.list", req) - if err != nil { - return nil, err - } - var result SessionAgentListResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.agent.list", req) + if err != nil { return nil, err } + var result SessionAgentListResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *AgentRpcApi) GetCurrent(ctx context.Context) (*SessionAgentGetCurrentResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.getCurrent", req) - if err != nil { - return nil, err - } - var result SessionAgentGetCurrentResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.agent.getCurrent", req) + if err != nil { return nil, err } + var result SessionAgentGetCurrentResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *AgentRpcApi) Select(ctx context.Context, params *SessionAgentSelectParams) (*SessionAgentSelectResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["name"] = params.Name - } - raw, err := a.client.Request("session.agent.select", req) - if err != nil { - return nil, err - } - var result SessionAgentSelectResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["name"] = params.Name + } + raw, err := a.client.Request("session.agent.select", req) + if err != nil { return nil, err } + var result SessionAgentSelectResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *AgentRpcApi) Deselect(ctx context.Context) (*SessionAgentDeselectResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.deselect", req) - if err != nil { - return nil, err - } - var result SessionAgentDeselectResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.agent.deselect", req) + if err != nil { return nil, err } + var result SessionAgentDeselectResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } -type CompactionRpcApi struct { - client *jsonrpc2.Client - sessionID string -} +// Experimental: CompactionRpcApi contains experimental APIs that may change or be removed. +type CompactionRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *CompactionRpcApi) Compact(ctx context.Context) (*SessionCompactionCompactResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.compaction.compact", req) - if err != nil { - return nil, err - } - var result SessionCompactionCompactResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.compaction.compact", req) + if err != nil { return nil, err } + var result SessionCompactionCompactResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } -type ToolsRpcApi struct { - client *jsonrpc2.Client - sessionID string -} +type ToolsRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ToolsRpcApi) HandlePendingToolCall(ctx context.Context, params *SessionToolsHandlePendingToolCallParams) (*SessionToolsHandlePendingToolCallResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["requestId"] = params.RequestID - if params.Result != nil { - req["result"] = *params.Result - } - if params.Error != nil { - req["error"] = *params.Error - } - } - raw, err := a.client.Request("session.tools.handlePendingToolCall", req) - if err != nil { - return nil, err - } - var result SessionToolsHandlePendingToolCallResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil -} - -type PermissionsRpcApi struct { - client *jsonrpc2.Client - sessionID string -} + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + if params.Result != nil { + req["result"] = *params.Result + } + if params.Error != nil { + req["error"] = *params.Error + } + } + raw, err := a.client.Request("session.tools.handlePendingToolCall", req) + if err != nil { return nil, err } + var result SessionToolsHandlePendingToolCallResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil +} + +type PermissionsRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *PermissionsRpcApi) HandlePendingPermissionRequest(ctx context.Context, params *SessionPermissionsHandlePendingPermissionRequestParams) (*SessionPermissionsHandlePendingPermissionRequestResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["requestId"] = params.RequestID - req["result"] = params.Result - } - raw, err := a.client.Request("session.permissions.handlePendingPermissionRequest", req) - if err != nil { - return nil, err - } - var result SessionPermissionsHandlePendingPermissionRequestResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil -} - -type ShellRpcApi struct { - client *jsonrpc2.Client - sessionID string + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + req["result"] = params.Result + } + raw, err := a.client.Request("session.permissions.handlePendingPermissionRequest", req) + if err != nil { return nil, err } + var result SessionPermissionsHandlePendingPermissionRequestResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } +type ShellRpcApi struct { client *jsonrpc2.Client; sessionID string } + func (a *ShellRpcApi) Exec(ctx context.Context, params *SessionShellExecParams) (*SessionShellExecResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["command"] = params.Command - if params.Cwd != nil { - req["cwd"] = *params.Cwd - } - if params.Timeout != nil { - req["timeout"] = *params.Timeout - } - } - raw, err := a.client.Request("session.shell.exec", req) - if err != nil { - return nil, err - } - var result SessionShellExecResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["command"] = params.Command + if params.Cwd != nil { + req["cwd"] = *params.Cwd + } + if params.Timeout != nil { + req["timeout"] = *params.Timeout + } + } + raw, err := a.client.Request("session.shell.exec", req) + if err != nil { return nil, err } + var result SessionShellExecResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *ShellRpcApi) Kill(ctx context.Context, params *SessionShellKillParams) (*SessionShellKillResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["processId"] = params.ProcessID - if params.Signal != nil { - req["signal"] = *params.Signal - } - } - raw, err := a.client.Request("session.shell.kill", req) - if err != nil { - return nil, err - } - var result SessionShellKillResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["processId"] = params.ProcessID + if params.Signal != nil { + req["signal"] = *params.Signal + } + } + raw, err := a.client.Request("session.shell.kill", req) + if err != nil { return nil, err } + var result SessionShellKillResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } // SessionRpc provides typed session-scoped RPC methods. type SessionRpc struct { - client *jsonrpc2.Client - sessionID string - Model *ModelRpcApi - Mode *ModeRpcApi - Plan *PlanRpcApi - Workspace *WorkspaceRpcApi - Fleet *FleetRpcApi - Agent *AgentRpcApi - Compaction *CompactionRpcApi - Tools *ToolsRpcApi - Permissions *PermissionsRpcApi - Shell *ShellRpcApi + client *jsonrpc2.Client + sessionID string + Model *ModelRpcApi + Mode *ModeRpcApi + Plan *PlanRpcApi + Workspace *WorkspaceRpcApi + Fleet *FleetRpcApi + Agent *AgentRpcApi + Compaction *CompactionRpcApi + Tools *ToolsRpcApi + Permissions *PermissionsRpcApi + Shell *ShellRpcApi } func (a *SessionRpc) Log(ctx context.Context, params *SessionLogParams) (*SessionLogResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["message"] = params.Message - if params.Level != nil { - req["level"] = *params.Level - } - if params.Ephemeral != nil { - req["ephemeral"] = *params.Ephemeral - } - } - raw, err := a.client.Request("session.log", req) - if err != nil { - return nil, err - } - var result SessionLogResult - if err := json.Unmarshal(raw, &result); err != nil { - return nil, err - } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["message"] = params.Message + if params.Level != nil { + req["level"] = *params.Level + } + if params.Ephemeral != nil { + req["ephemeral"] = *params.Ephemeral + } + } + raw, err := a.client.Request("session.log", req) + if err != nil { return nil, err } + var result SessionLogResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc { - return &SessionRpc{client: client, sessionID: sessionID, - Model: &ModelRpcApi{client: client, sessionID: sessionID}, - Mode: &ModeRpcApi{client: client, sessionID: sessionID}, - Plan: &PlanRpcApi{client: client, sessionID: sessionID}, - Workspace: &WorkspaceRpcApi{client: client, sessionID: sessionID}, - Fleet: &FleetRpcApi{client: client, sessionID: sessionID}, - Agent: &AgentRpcApi{client: client, sessionID: sessionID}, - Compaction: &CompactionRpcApi{client: client, sessionID: sessionID}, - Tools: &ToolsRpcApi{client: client, sessionID: sessionID}, - Permissions: &PermissionsRpcApi{client: client, sessionID: sessionID}, - Shell: &ShellRpcApi{client: client, sessionID: sessionID}, - } + return &SessionRpc{client: client, sessionID: sessionID, + Model: &ModelRpcApi{client: client, sessionID: sessionID}, + Mode: &ModeRpcApi{client: client, sessionID: sessionID}, + Plan: &PlanRpcApi{client: client, sessionID: sessionID}, + Workspace: &WorkspaceRpcApi{client: client, sessionID: sessionID}, + Fleet: &FleetRpcApi{client: client, sessionID: sessionID}, + Agent: &AgentRpcApi{client: client, sessionID: sessionID}, + Compaction: &CompactionRpcApi{client: client, sessionID: sessionID}, + Tools: &ToolsRpcApi{client: client, sessionID: sessionID}, + Permissions: &PermissionsRpcApi{client: client, sessionID: sessionID}, + Shell: &ShellRpcApi{client: client, sessionID: sessionID}, + } } diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index e5ba9ad4c..16907fdba 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -340,6 +340,7 @@ export interface SessionWorkspaceCreateFileParams { content: string; } +/** @experimental */ export interface SessionFleetStartResult { /** * Whether fleet mode was successfully activated @@ -347,6 +348,7 @@ export interface SessionFleetStartResult { started: boolean; } +/** @experimental */ export interface SessionFleetStartParams { /** * Target session identifier @@ -358,6 +360,7 @@ export interface SessionFleetStartParams { prompt?: string; } +/** @experimental */ export interface SessionAgentListResult { /** * Available custom agents @@ -378,6 +381,7 @@ export interface SessionAgentListResult { }[]; } +/** @experimental */ export interface SessionAgentListParams { /** * Target session identifier @@ -385,6 +389,7 @@ export interface SessionAgentListParams { sessionId: string; } +/** @experimental */ export interface SessionAgentGetCurrentResult { /** * Currently selected custom agent, or null if using the default agent @@ -405,6 +410,7 @@ export interface SessionAgentGetCurrentResult { } | null; } +/** @experimental */ export interface SessionAgentGetCurrentParams { /** * Target session identifier @@ -412,6 +418,7 @@ export interface SessionAgentGetCurrentParams { sessionId: string; } +/** @experimental */ export interface SessionAgentSelectResult { /** * The newly selected custom agent @@ -432,6 +439,7 @@ export interface SessionAgentSelectResult { }; } +/** @experimental */ export interface SessionAgentSelectParams { /** * Target session identifier @@ -443,8 +451,10 @@ export interface SessionAgentSelectParams { name: string; } +/** @experimental */ export interface SessionAgentDeselectResult {} +/** @experimental */ export interface SessionAgentDeselectParams { /** * Target session identifier @@ -452,6 +462,7 @@ export interface SessionAgentDeselectParams { sessionId: string; } +/** @experimental */ export interface SessionCompactionCompactResult { /** * Whether compaction completed successfully @@ -467,6 +478,7 @@ export interface SessionCompactionCompactResult { messagesRemoved: number; } +/** @experimental */ export interface SessionCompactionCompactParams { /** * Target session identifier @@ -660,10 +672,12 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin createFile: async (params: Omit): Promise => connection.sendRequest("session.workspace.createFile", { sessionId, ...params }), }, + /** @experimental */ fleet: { start: async (params: Omit): Promise => connection.sendRequest("session.fleet.start", { sessionId, ...params }), }, + /** @experimental */ agent: { list: async (): Promise => connection.sendRequest("session.agent.list", { sessionId }), @@ -674,6 +688,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin deselect: async (): Promise => connection.sendRequest("session.agent.deselect", { sessionId }), }, + /** @experimental */ compaction: { compact: async (): Promise => connection.sendRequest("session.compaction.compact", { sessionId }), diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index 29b7463df..564ccf64e 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -724,6 +724,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionFleetStartResult: started: bool @@ -741,6 +742,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionFleetStartParams: prompt: str | None = None @@ -786,6 +788,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionAgentListResult: agents: list[AgentElement] @@ -830,6 +833,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionAgentGetCurrentResult: agent: SessionAgentGetCurrentResultAgent | None = None @@ -876,6 +880,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionAgentSelectResult: agent: SessionAgentSelectResultAgent @@ -893,6 +898,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionAgentSelectParams: name: str @@ -910,6 +916,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionAgentDeselectResult: @staticmethod @@ -922,6 +929,7 @@ def to_dict(self) -> dict: return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionCompactionCompactResult: messages_removed: float @@ -1666,6 +1674,7 @@ async def create_file(self, params: SessionWorkspaceCreateFileParams, *, timeout return SessionWorkspaceCreateFileResult.from_dict(await self._client.request("session.workspace.createFile", params_dict, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. class FleetApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client @@ -1677,6 +1686,7 @@ async def start(self, params: SessionFleetStartParams, *, timeout: float | None return SessionFleetStartResult.from_dict(await self._client.request("session.fleet.start", params_dict, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. class AgentApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client @@ -1697,6 +1707,7 @@ async def deselect(self, *, timeout: float | None = None) -> SessionAgentDeselec return SessionAgentDeselectResult.from_dict(await self._client.request("session.agent.deselect", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. class CompactionApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 3aeb0eef3..57e8fcbcb 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -16,6 +16,7 @@ import { getApiSchemaPath, writeGeneratedFile, isRpcMethod, + isNodeFullyExperimental, EXCLUDED_EVENT_TYPES, REPO_ROOT, type ApiSchema, @@ -594,6 +595,7 @@ export async function generateSessionEvents(schemaPath?: string): Promise // ══════════════════════════════════════════════════════════════════════════════ let emittedRpcClasses = new Set(); +let experimentalRpcTypes = new Set(); let rpcKnownTypes = new Map(); let rpcEnumOutput: string[] = []; @@ -651,6 +653,9 @@ function emitRpcClass(className: string, schema: JSONSchema7, visibility: "publi const requiredSet = new Set(schema.required || []); const lines: string[] = []; lines.push(...xmlDocComment(schema.description || `RPC data type for ${className.replace(/Request$/, "").replace(/Result$/, "")} operations.`, "")); + if (experimentalRpcTypes.has(className)) { + lines.push(`[Experimental(Diagnostics.Experimental)]`); + } lines.push(`${visibility} class ${className}`, `{`); const props = Object.entries(schema.properties || {}); @@ -712,7 +717,7 @@ function emitServerRpcClasses(node: Record, classes: string[]): // Top-level methods (like ping) for (const [key, value] of topLevelMethods) { if (!isRpcMethod(value)) continue; - emitServerInstanceMethod(key, value, srLines, classes, " "); + emitServerInstanceMethod(key, value, srLines, classes, " ", false); } // Group properties @@ -737,6 +742,10 @@ function emitServerApiClass(className: string, node: Record, cl const lines: string[] = []; const displayName = className.replace(/^Server/, "").replace(/Api$/, ""); lines.push(`/// Provides server-scoped ${displayName} APIs.`); + const groupExperimental = isNodeFullyExperimental(node); + if (groupExperimental) { + lines.push(`[Experimental(Diagnostics.Experimental)]`); + } lines.push(`public class ${className}`); lines.push(`{`); lines.push(` private readonly JsonRpc _rpc;`); @@ -748,7 +757,7 @@ function emitServerApiClass(className: string, node: Record, cl for (const [key, value] of Object.entries(node)) { if (!isRpcMethod(value)) continue; - emitServerInstanceMethod(key, value, lines, classes, " "); + emitServerInstanceMethod(key, value, lines, classes, " ", groupExperimental); } lines.push(`}`); @@ -757,13 +766,17 @@ function emitServerApiClass(className: string, node: Record, cl function emitServerInstanceMethod( name: string, - method: { rpcMethod: string; params: JSONSchema7 | null; result: JSONSchema7 }, + method: RpcMethod, lines: string[], classes: string[], - indent: string + indent: string, + groupExperimental: boolean ): void { const methodName = toPascalCase(name); const resultClassName = `${typeToClassName(method.rpcMethod)}Result`; + if (method.stability === "experimental") { + experimentalRpcTypes.add(resultClassName); + } const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); if (resultClass) classes.push(resultClass); @@ -773,12 +786,18 @@ function emitServerInstanceMethod( let requestClassName: string | null = null; if (paramEntries.length > 0) { requestClassName = `${typeToClassName(method.rpcMethod)}Request`; + if (method.stability === "experimental") { + experimentalRpcTypes.add(requestClassName); + } const reqClass = emitRpcClass(requestClassName, method.params!, "internal", classes); if (reqClass) classes.push(reqClass); } lines.push(""); lines.push(`${indent}/// Calls "${method.rpcMethod}".`); + if (method.stability === "experimental" && !groupExperimental) { + lines.push(`${indent}[Experimental(Diagnostics.Experimental)]`); + } const sigParams: string[] = []; const bodyAssignments: string[] = []; @@ -817,7 +836,7 @@ function emitSessionRpcClasses(node: Record, classes: string[]) // Emit top-level session RPC methods directly on the SessionRpc class const topLevelLines: string[] = []; for (const [key, value] of topLevelMethods) { - emitSessionMethod(key, value as RpcMethod, topLevelLines, classes, " "); + emitSessionMethod(key, value as RpcMethod, topLevelLines, classes, " ", false); } srLines.push(...topLevelLines); @@ -830,9 +849,12 @@ function emitSessionRpcClasses(node: Record, classes: string[]) return result; } -function emitSessionMethod(key: string, method: RpcMethod, lines: string[], classes: string[], indent: string): void { +function emitSessionMethod(key: string, method: RpcMethod, lines: string[], classes: string[], indent: string, groupExperimental: boolean): void { const methodName = toPascalCase(key); const resultClassName = `${typeToClassName(method.rpcMethod)}Result`; + if (method.stability === "experimental") { + experimentalRpcTypes.add(resultClassName); + } const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); if (resultClass) classes.push(resultClass); @@ -847,12 +869,18 @@ function emitSessionMethod(key: string, method: RpcMethod, lines: string[], clas }); const requestClassName = `${typeToClassName(method.rpcMethod)}Request`; + if (method.stability === "experimental") { + experimentalRpcTypes.add(requestClassName); + } if (method.params) { const reqClass = emitRpcClass(requestClassName, method.params, "internal", classes); if (reqClass) classes.push(reqClass); } lines.push("", `${indent}/// Calls "${method.rpcMethod}".`); + if (method.stability === "experimental" && !groupExperimental) { + lines.push(`${indent}[Experimental(Diagnostics.Experimental)]`); + } const sigParams: string[] = []; const bodyAssignments = [`SessionId = _sessionId`]; @@ -872,12 +900,14 @@ function emitSessionMethod(key: string, method: RpcMethod, lines: string[], clas function emitSessionApiClass(className: string, node: Record, classes: string[]): string { const displayName = className.replace(/Api$/, ""); - const lines = [`/// Provides session-scoped ${displayName} APIs.`, `public class ${className}`, `{`, ` private readonly JsonRpc _rpc;`, ` private readonly string _sessionId;`, ""]; + const groupExperimental = isNodeFullyExperimental(node); + const experimentalAttr = groupExperimental ? `[Experimental(Diagnostics.Experimental)]\n` : ""; + const lines = [`/// Provides session-scoped ${displayName} APIs.`, `${experimentalAttr}public class ${className}`, `{`, ` private readonly JsonRpc _rpc;`, ` private readonly string _sessionId;`, ""]; lines.push(` internal ${className}(JsonRpc rpc, string sessionId)`, ` {`, ` _rpc = rpc;`, ` _sessionId = sessionId;`, ` }`); for (const [key, value] of Object.entries(node)) { if (!isRpcMethod(value)) continue; - emitSessionMethod(key, value, lines, classes, " "); + emitSessionMethod(key, value, lines, classes, " ", groupExperimental); } lines.push(`}`); return lines.join("\n"); @@ -885,6 +915,7 @@ function emitSessionApiClass(className: string, node: Record, c function generateRpcCode(schema: ApiSchema): string { emittedRpcClasses.clear(); + experimentalRpcTypes.clear(); rpcKnownTypes.clear(); rpcEnumOutput = []; generatedEnums.clear(); // Clear shared enum deduplication map @@ -902,11 +933,19 @@ function generateRpcCode(schema: ApiSchema): string { // AUTO-GENERATED FILE - DO NOT EDIT // Generated from: api.schema.json +using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; using StreamJsonRpc; namespace GitHub.Copilot.SDK.Rpc; + +/// Diagnostic IDs for the Copilot SDK. +internal static class Diagnostics +{ + /// Indicates an experimental API that may change or be removed. + internal const string Experimental = "GHCP001"; +} `); for (const cls of classes) if (cls) lines.push(cls, ""); diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 1ebc50797..a1acf17f2 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -17,6 +17,7 @@ import { postProcessSchema, writeGeneratedFile, isRpcMethod, + isNodeFullyExperimental, type ApiSchema, type RpcMethod, } from "./utils.js"; @@ -168,9 +169,24 @@ async function generateRpc(schemaPath?: string): Promise { lines.push(`)`); lines.push(``); - // Add quicktype-generated types (skip package line) - const qtLines = qtResult.lines.filter((l) => !l.startsWith("package ")); - lines.push(...qtLines); + // Add quicktype-generated types (skip package line), annotating experimental types + const experimentalTypeNames = new Set(); + for (const method of allMethods) { + if (method.stability !== "experimental") continue; + experimentalTypeNames.add(toPascalCase(method.rpcMethod) + "Result"); + const baseName = toPascalCase(method.rpcMethod); + if (combinedSchema.definitions![baseName + "Params"]) { + experimentalTypeNames.add(baseName + "Params"); + } + } + let qtCode = qtResult.lines.filter((l) => !l.startsWith("package ")).join("\n"); + for (const typeName of experimentalTypeNames) { + qtCode = qtCode.replace( + new RegExp(`^(type ${typeName} struct)`, "m"), + `// Experimental: ${typeName} is part of an experimental API and may change or be removed.\n$1` + ); + } + lines.push(qtCode); lines.push(``); // Emit ServerRpc @@ -201,11 +217,15 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio const prefix = isSession ? "" : "Server"; const apiName = prefix + toPascalCase(groupName) + apiSuffix; const fields = isSession ? "client *jsonrpc2.Client; sessionID string" : "client *jsonrpc2.Client"; + const groupExperimental = isNodeFullyExperimental(groupNode as Record); + if (groupExperimental) { + lines.push(`// Experimental: ${apiName} contains experimental APIs that may change or be removed.`); + } lines.push(`type ${apiName} struct { ${fields} }`); lines.push(``); for (const [key, value] of Object.entries(groupNode as Record)) { if (!isRpcMethod(value)) continue; - emitMethod(lines, apiName, key, value, isSession); + emitMethod(lines, apiName, key, value, isSession, groupExperimental); } } @@ -224,7 +244,7 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio // Top-level methods (server only) for (const [key, value] of topLevelMethods) { if (!isRpcMethod(value)) continue; - emitMethod(lines, wrapperName, key, value, isSession); + emitMethod(lines, wrapperName, key, value, isSession, false); } // Constructor @@ -244,7 +264,7 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio lines.push(``); } -function emitMethod(lines: string[], receiver: string, name: string, method: RpcMethod, isSession: boolean): void { +function emitMethod(lines: string[], receiver: string, name: string, method: RpcMethod, isSession: boolean, groupExperimental = false): void { const methodName = toPascalCase(name); const resultType = toPascalCase(method.rpcMethod) + "Result"; @@ -254,6 +274,9 @@ function emitMethod(lines: string[], receiver: string, name: string, method: Rpc const hasParams = isSession ? nonSessionParams.length > 0 : Object.keys(paramProps).length > 0; const paramsType = hasParams ? toPascalCase(method.rpcMethod) + "Params" : ""; + if (method.stability === "experimental" && !groupExperimental) { + lines.push(`// Experimental: ${methodName} is an experimental API and may change or be removed in future versions.`); + } const sig = hasParams ? `func (a *${receiver}) ${methodName}(ctx context.Context, params *${paramsType}) (*${resultType}, error)` : `func (a *${receiver}) ${methodName}(ctx context.Context) (*${resultType}, error)`; diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts index 65563d741..3dfa52535 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -15,6 +15,7 @@ import { postProcessSchema, writeGeneratedFile, isRpcMethod, + isNodeFullyExperimental, type ApiSchema, type RpcMethod, } from "./utils.js"; @@ -215,6 +216,23 @@ async function generateRpc(schemaPath?: string): Promise { // Modernize to Python 3.11+ syntax typesCode = modernizePython(typesCode); + // Annotate experimental data types + const experimentalTypeNames = new Set(); + for (const method of allMethods) { + if (method.stability !== "experimental") continue; + experimentalTypeNames.add(toPascalCase(method.rpcMethod) + "Result"); + const baseName = toPascalCase(method.rpcMethod); + if (combinedSchema.definitions![baseName + "Params"]) { + experimentalTypeNames.add(baseName + "Params"); + } + } + for (const typeName of experimentalTypeNames) { + typesCode = typesCode.replace( + new RegExp(`^(@dataclass\\n)?class ${typeName}[:(]`, "m"), + (match) => `# Experimental: this type is part of an experimental API and may change or be removed.\n${match}` + ); + } + const lines: string[] = []; lines.push(`""" AUTO-GENERATED FILE - DO NOT EDIT @@ -259,12 +277,19 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio for (const [groupName, groupNode] of groups) { const prefix = isSession ? "" : "Server"; const apiName = prefix + toPascalCase(groupName) + "Api"; + const groupExperimental = isNodeFullyExperimental(groupNode as Record); if (isSession) { + if (groupExperimental) { + lines.push(`# Experimental: this API group is experimental and may change or be removed.`); + } lines.push(`class ${apiName}:`); lines.push(` def __init__(self, client: "JsonRpcClient", session_id: str):`); lines.push(` self._client = client`); lines.push(` self._session_id = session_id`); } else { + if (groupExperimental) { + lines.push(`# Experimental: this API group is experimental and may change or be removed.`); + } lines.push(`class ${apiName}:`); lines.push(` def __init__(self, client: "JsonRpcClient"):`); lines.push(` self._client = client`); @@ -272,7 +297,7 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio lines.push(``); for (const [key, value] of Object.entries(groupNode as Record)) { if (!isRpcMethod(value)) continue; - emitMethod(lines, key, value, isSession); + emitMethod(lines, key, value, isSession, groupExperimental); } lines.push(``); } @@ -301,12 +326,12 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio // Top-level methods for (const [key, value] of topLevelMethods) { if (!isRpcMethod(value)) continue; - emitMethod(lines, key, value, isSession); + emitMethod(lines, key, value, isSession, false); } lines.push(``); } -function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: boolean): void { +function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: boolean, groupExperimental = false): void { const methodName = toSnakeCase(name); const resultType = toPascalCase(method.rpcMethod) + "Result"; @@ -322,6 +347,10 @@ function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: lines.push(sig); + if (method.stability === "experimental" && !groupExperimental) { + lines.push(` """.. warning:: This API is experimental and may change or be removed in future versions."""`); + } + // Build request body with proper serialization/deserialization if (isSession) { if (hasParams) { diff --git a/scripts/codegen/typescript.ts b/scripts/codegen/typescript.ts index 77c31019a..8d23b428f 100644 --- a/scripts/codegen/typescript.ts +++ b/scripts/codegen/typescript.ts @@ -15,6 +15,7 @@ import { postProcessSchema, writeGeneratedFile, isRpcMethod, + isNodeFullyExperimental, type ApiSchema, type RpcMethod, } from "./utils.js"; @@ -91,6 +92,9 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js"; bannerComment: "", additionalProperties: false, }); + if (method.stability === "experimental") { + lines.push("/** @experimental */"); + } lines.push(compiled.trim()); lines.push(""); @@ -99,6 +103,9 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js"; bannerComment: "", additionalProperties: false, }); + if (method.stability === "experimental") { + lines.push("/** @experimental */"); + } lines.push(paramsCompiled.trim()); lines.push(""); } @@ -129,7 +136,7 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js"; console.log(` ✓ ${outPath}`); } -function emitGroup(node: Record, indent: string, isSession: boolean): string[] { +function emitGroup(node: Record, indent: string, isSession: boolean, parentExperimental = false): string[] { const lines: string[] = []; for (const [key, value] of Object.entries(node)) { if (isRpcMethod(value)) { @@ -160,11 +167,18 @@ function emitGroup(node: Record, indent: string, isSession: boo } } + if ((value as RpcMethod).stability === "experimental" && !parentExperimental) { + lines.push(`${indent}/** @experimental */`); + } lines.push(`${indent}${key}: async (${sigParams.join(", ")}): Promise<${resultType}> =>`); lines.push(`${indent} connection.sendRequest("${rpcMethod}", ${bodyArg}),`); } else if (typeof value === "object" && value !== null) { + const groupExperimental = isNodeFullyExperimental(value as Record); + if (groupExperimental) { + lines.push(`${indent}/** @experimental */`); + } lines.push(`${indent}${key}: {`); - lines.push(...emitGroup(value as Record, indent + " ", isSession)); + lines.push(...emitGroup(value as Record, indent + " ", isSession, groupExperimental)); lines.push(`${indent}},`); } } diff --git a/scripts/codegen/utils.ts b/scripts/codegen/utils.ts index 88ca68de8..2c13b1d96 100644 --- a/scripts/codegen/utils.ts +++ b/scripts/codegen/utils.ts @@ -126,6 +126,7 @@ export interface RpcMethod { rpcMethod: string; params: JSONSchema7 | null; result: JSONSchema7; + stability?: string; } export interface ApiSchema { @@ -136,3 +137,18 @@ export interface ApiSchema { export function isRpcMethod(node: unknown): node is RpcMethod { return typeof node === "object" && node !== null && "rpcMethod" in node; } + +/** Returns true when every leaf RPC method inside `node` is marked experimental. */ +export function isNodeFullyExperimental(node: Record): boolean { + const methods: RpcMethod[] = []; + (function collect(n: Record) { + for (const value of Object.values(n)) { + if (isRpcMethod(value)) { + methods.push(value); + } else if (typeof value === "object" && value !== null) { + collect(value as Record); + } + } + })(node); + return methods.length > 0 && methods.every(m => m.stability === "experimental"); +} From d869f2193989927ecdc8a9ff4ef521aaaebfcb87 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 17 Mar 2026 11:44:19 -0400 Subject: [PATCH 2/7] Strip trailing whitespace from Go quicktype output Address review feedback: quicktype generates comments with trailing whitespace which fails gofmt checks. Add a post-processing step to strip trailing whitespace from the quicktype output before writing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/generated_rpc.go | 172 ++++++++++++++++++++-------------------- scripts/codegen/go.ts | 2 + 2 files changed, 88 insertions(+), 86 deletions(-) diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index c06b59796..4f8e50e5b 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -11,164 +11,164 @@ import ( ) type PingResult struct { - // Echoed message (or default greeting) + // Echoed message (or default greeting) Message string `json:"message"` - // Server protocol version number + // Server protocol version number ProtocolVersion float64 `json:"protocolVersion"` - // Server timestamp in milliseconds + // Server timestamp in milliseconds Timestamp float64 `json:"timestamp"` } type PingParams struct { - // Optional message to echo back + // Optional message to echo back Message *string `json:"message,omitempty"` } type ModelsListResult struct { - // List of available models with full metadata + // List of available models with full metadata Models []Model `json:"models"` } type Model struct { - // Billing information + // Billing information Billing *Billing `json:"billing,omitempty"` - // Model capabilities and limits + // Model capabilities and limits Capabilities Capabilities `json:"capabilities"` - // Default reasoning effort level (only present if model supports reasoning effort) + // Default reasoning effort level (only present if model supports reasoning effort) DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` - // Model identifier (e.g., "claude-sonnet-4.5") + // Model identifier (e.g., "claude-sonnet-4.5") ID string `json:"id"` - // Display name + // Display name Name string `json:"name"` - // Policy state (if applicable) + // Policy state (if applicable) Policy *Policy `json:"policy,omitempty"` - // Supported reasoning effort levels (only present if model supports reasoning effort) + // Supported reasoning effort levels (only present if model supports reasoning effort) SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` } // Billing information type Billing struct { - // Billing cost multiplier relative to the base rate + // Billing cost multiplier relative to the base rate Multiplier float64 `json:"multiplier"` } // Model capabilities and limits type Capabilities struct { - // Token limits for prompts, outputs, and context window + // Token limits for prompts, outputs, and context window Limits Limits `json:"limits"` - // Feature flags indicating what the model supports + // Feature flags indicating what the model supports Supports Supports `json:"supports"` } // Token limits for prompts, outputs, and context window type Limits struct { - // Maximum total context window size in tokens + // Maximum total context window size in tokens MaxContextWindowTokens float64 `json:"max_context_window_tokens"` - // Maximum number of output/completion tokens + // Maximum number of output/completion tokens MaxOutputTokens *float64 `json:"max_output_tokens,omitempty"` - // Maximum number of prompt/input tokens + // Maximum number of prompt/input tokens MaxPromptTokens *float64 `json:"max_prompt_tokens,omitempty"` } // Feature flags indicating what the model supports type Supports struct { - // Whether this model supports reasoning effort configuration + // Whether this model supports reasoning effort configuration ReasoningEffort *bool `json:"reasoningEffort,omitempty"` - // Whether this model supports vision/image input + // Whether this model supports vision/image input Vision *bool `json:"vision,omitempty"` } // Policy state (if applicable) type Policy struct { - // Current policy state for this model + // Current policy state for this model State string `json:"state"` - // Usage terms or conditions for this model + // Usage terms or conditions for this model Terms string `json:"terms"` } type ToolsListResult struct { - // List of available built-in tools with metadata + // List of available built-in tools with metadata Tools []Tool `json:"tools"` } type Tool struct { - // Description of what the tool does + // Description of what the tool does Description string `json:"description"` - // Optional instructions for how to use this tool effectively + // Optional instructions for how to use this tool effectively Instructions *string `json:"instructions,omitempty"` - // Tool identifier (e.g., "bash", "grep", "str_replace_editor") + // Tool identifier (e.g., "bash", "grep", "str_replace_editor") Name string `json:"name"` - // Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP - // tools) + // Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP + // tools) NamespacedName *string `json:"namespacedName,omitempty"` - // JSON Schema for the tool's input parameters + // JSON Schema for the tool's input parameters Parameters map[string]interface{} `json:"parameters,omitempty"` } type ToolsListParams struct { - // Optional model ID — when provided, the returned tool list reflects model-specific - // overrides + // Optional model ID — when provided, the returned tool list reflects model-specific + // overrides Model *string `json:"model,omitempty"` } type AccountGetQuotaResult struct { - // Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) + // Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) QuotaSnapshots map[string]QuotaSnapshot `json:"quotaSnapshots"` } type QuotaSnapshot struct { - // Number of requests included in the entitlement + // Number of requests included in the entitlement EntitlementRequests float64 `json:"entitlementRequests"` - // Number of overage requests made this period + // Number of overage requests made this period Overage float64 `json:"overage"` - // Whether pay-per-request usage is allowed when quota is exhausted + // Whether pay-per-request usage is allowed when quota is exhausted OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` - // Percentage of entitlement remaining + // Percentage of entitlement remaining RemainingPercentage float64 `json:"remainingPercentage"` - // Date when the quota resets (ISO 8601) + // Date when the quota resets (ISO 8601) ResetDate *string `json:"resetDate,omitempty"` - // Number of requests used so far this period + // Number of requests used so far this period UsedRequests float64 `json:"usedRequests"` } type SessionModelGetCurrentResult struct { - // Currently active model identifier + // Currently active model identifier ModelID *string `json:"modelId,omitempty"` } type SessionModelSwitchToResult struct { - // Currently active model identifier after the switch + // Currently active model identifier after the switch ModelID *string `json:"modelId,omitempty"` } type SessionModelSwitchToParams struct { - // Model identifier to switch to + // Model identifier to switch to ModelID string `json:"modelId"` - // Reasoning effort level to use for the model + // Reasoning effort level to use for the model ReasoningEffort *string `json:"reasoningEffort,omitempty"` } type SessionModeGetResult struct { - // The current agent mode. + // The current agent mode. Mode Mode `json:"mode"` } type SessionModeSetResult struct { - // The agent mode after switching. + // The agent mode after switching. Mode Mode `json:"mode"` } type SessionModeSetParams struct { - // The mode to switch to. Valid values: "interactive", "plan", "autopilot". + // The mode to switch to. Valid values: "interactive", "plan", "autopilot". Mode Mode `json:"mode"` } type SessionPlanReadResult struct { - // The content of the plan file, or null if it does not exist + // The content of the plan file, or null if it does not exist Content *string `json:"content"` - // Whether the plan file exists in the workspace + // Whether the plan file exists in the workspace Exists bool `json:"exists"` - // Absolute file path of the plan file, or null if workspace is not enabled + // Absolute file path of the plan file, or null if workspace is not enabled Path *string `json:"path"` } @@ -176,7 +176,7 @@ type SessionPlanUpdateResult struct { } type SessionPlanUpdateParams struct { - // The new content for the plan file + // The new content for the plan file Content string `json:"content"` } @@ -184,17 +184,17 @@ type SessionPlanDeleteResult struct { } type SessionWorkspaceListFilesResult struct { - // Relative file paths in the workspace files directory + // Relative file paths in the workspace files directory Files []string `json:"files"` } type SessionWorkspaceReadFileResult struct { - // File content as a UTF-8 string + // File content as a UTF-8 string Content string `json:"content"` } type SessionWorkspaceReadFileParams struct { - // Relative path within the workspace files directory + // Relative path within the workspace files directory Path string `json:"path"` } @@ -202,73 +202,73 @@ type SessionWorkspaceCreateFileResult struct { } type SessionWorkspaceCreateFileParams struct { - // File content to write as a UTF-8 string + // File content to write as a UTF-8 string Content string `json:"content"` - // Relative path within the workspace files directory + // Relative path within the workspace files directory Path string `json:"path"` } // Experimental: SessionFleetStartResult is part of an experimental API and may change or be removed. type SessionFleetStartResult struct { - // Whether fleet mode was successfully activated + // Whether fleet mode was successfully activated Started bool `json:"started"` } // Experimental: SessionFleetStartParams is part of an experimental API and may change or be removed. type SessionFleetStartParams struct { - // Optional user prompt to combine with fleet instructions + // Optional user prompt to combine with fleet instructions Prompt *string `json:"prompt,omitempty"` } // Experimental: SessionAgentListResult is part of an experimental API and may change or be removed. type SessionAgentListResult struct { - // Available custom agents + // Available custom agents Agents []AgentElement `json:"agents"` } type AgentElement struct { - // Description of the agent's purpose + // Description of the agent's purpose Description string `json:"description"` - // Human-readable display name + // Human-readable display name DisplayName string `json:"displayName"` - // Unique identifier of the custom agent + // Unique identifier of the custom agent Name string `json:"name"` } // Experimental: SessionAgentGetCurrentResult is part of an experimental API and may change or be removed. type SessionAgentGetCurrentResult struct { - // Currently selected custom agent, or null if using the default agent + // Currently selected custom agent, or null if using the default agent Agent *SessionAgentGetCurrentResultAgent `json:"agent"` } type SessionAgentGetCurrentResultAgent struct { - // Description of the agent's purpose + // Description of the agent's purpose Description string `json:"description"` - // Human-readable display name + // Human-readable display name DisplayName string `json:"displayName"` - // Unique identifier of the custom agent + // Unique identifier of the custom agent Name string `json:"name"` } // Experimental: SessionAgentSelectResult is part of an experimental API and may change or be removed. type SessionAgentSelectResult struct { - // The newly selected custom agent + // The newly selected custom agent Agent SessionAgentSelectResultAgent `json:"agent"` } // The newly selected custom agent type SessionAgentSelectResultAgent struct { - // Description of the agent's purpose + // Description of the agent's purpose Description string `json:"description"` - // Human-readable display name + // Human-readable display name DisplayName string `json:"displayName"` - // Unique identifier of the custom agent + // Unique identifier of the custom agent Name string `json:"name"` } // Experimental: SessionAgentSelectParams is part of an experimental API and may change or be removed. type SessionAgentSelectParams struct { - // Name of the custom agent to select + // Name of the custom agent to select Name string `json:"name"` } @@ -278,16 +278,16 @@ type SessionAgentDeselectResult struct { // Experimental: SessionCompactionCompactResult is part of an experimental API and may change or be removed. type SessionCompactionCompactResult struct { - // Number of messages removed during compaction + // Number of messages removed during compaction MessagesRemoved float64 `json:"messagesRemoved"` - // Whether compaction completed successfully + // Whether compaction completed successfully Success bool `json:"success"` - // Number of tokens freed by compaction + // Number of tokens freed by compaction TokensRemoved float64 `json:"tokensRemoved"` } type SessionToolsHandlePendingToolCallResult struct { - // Whether the tool call result was handled successfully + // Whether the tool call result was handled successfully Success bool `json:"success"` } @@ -305,7 +305,7 @@ type ResultResult struct { } type SessionPermissionsHandlePendingPermissionRequestResult struct { - // Whether the permission request was handled successfully + // Whether the permission request was handled successfully Success bool `json:"success"` } @@ -323,43 +323,43 @@ type SessionPermissionsHandlePendingPermissionRequestParamsResult struct { } type SessionLogResult struct { - // The unique identifier of the emitted session event + // The unique identifier of the emitted session event EventID string `json:"eventId"` } type SessionLogParams struct { - // When true, the message is transient and not persisted to the session event log on disk + // When true, the message is transient and not persisted to the session event log on disk Ephemeral *bool `json:"ephemeral,omitempty"` - // Log severity level. Determines how the message is displayed in the timeline. Defaults to - // "info". + // Log severity level. Determines how the message is displayed in the timeline. Defaults to + // "info". Level *Level `json:"level,omitempty"` - // Human-readable message + // Human-readable message Message string `json:"message"` } type SessionShellExecResult struct { - // Unique identifier for tracking streamed output + // Unique identifier for tracking streamed output ProcessID string `json:"processId"` } type SessionShellExecParams struct { - // Shell command to execute + // Shell command to execute Command string `json:"command"` - // Working directory (defaults to session working directory) + // Working directory (defaults to session working directory) Cwd *string `json:"cwd,omitempty"` - // Timeout in milliseconds (default: 30000) + // Timeout in milliseconds (default: 30000) Timeout *float64 `json:"timeout,omitempty"` } type SessionShellKillResult struct { - // Whether the signal was sent successfully + // Whether the signal was sent successfully Killed bool `json:"killed"` } type SessionShellKillParams struct { - // Process identifier returned by shell.exec + // Process identifier returned by shell.exec ProcessID string `json:"processId"` - // Signal to send (default: SIGTERM) + // Signal to send (default: SIGTERM) Signal *Signal `json:"signal,omitempty"` } diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index a1acf17f2..554ab793f 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -180,6 +180,8 @@ async function generateRpc(schemaPath?: string): Promise { } } let qtCode = qtResult.lines.filter((l) => !l.startsWith("package ")).join("\n"); + // Strip trailing whitespace from quicktype output (gofmt requirement) + qtCode = qtCode.replace(/[ \t]+$/gm, ""); for (const typeName of experimentalTypeNames) { qtCode = qtCode.replace( new RegExp(`^(type ${typeName} struct)`, "m"), From a54582157d2fefb929f6b85803c5f3d34161952a Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 17 Mar 2026 11:54:26 -0400 Subject: [PATCH 3/7] fix: use tabs for Go indentation and column-align struct fields gofmt requires tab indentation (not spaces) and column-aligns struct field declarations and composite literal keys. Updated the Go codegen to emit tabs for all indentation and compute proper padding for field alignment in wrapper structs and constructors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/generated_rpc.go | 492 ++++++++++++++++++++-------------------- scripts/codegen/go.ts | 54 +++-- 2 files changed, 278 insertions(+), 268 deletions(-) diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 4f8e50e5b..9a12f6668 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -4,10 +4,10 @@ package rpc import ( - "context" - "encoding/json" + "context" + "encoding/json" - "github.com/github/copilot-sdk/go/internal/jsonrpc2" + "github.com/github/copilot-sdk/go/internal/jsonrpc2" ) type PingResult struct { @@ -414,360 +414,360 @@ type ResultUnion struct { type ServerModelsRpcApi struct { client *jsonrpc2.Client } func (a *ServerModelsRpcApi) List(ctx context.Context) (*ModelsListResult, error) { - raw, err := a.client.Request("models.list", map[string]interface{}{}) - if err != nil { return nil, err } - var result ModelsListResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + raw, err := a.client.Request("models.list", map[string]interface{}{}) + if err != nil { return nil, err } + var result ModelsListResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type ServerToolsRpcApi struct { client *jsonrpc2.Client } func (a *ServerToolsRpcApi) List(ctx context.Context, params *ToolsListParams) (*ToolsListResult, error) { - raw, err := a.client.Request("tools.list", params) - if err != nil { return nil, err } - var result ToolsListResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + raw, err := a.client.Request("tools.list", params) + if err != nil { return nil, err } + var result ToolsListResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type ServerAccountRpcApi struct { client *jsonrpc2.Client } func (a *ServerAccountRpcApi) GetQuota(ctx context.Context) (*AccountGetQuotaResult, error) { - raw, err := a.client.Request("account.getQuota", map[string]interface{}{}) - if err != nil { return nil, err } - var result AccountGetQuotaResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + raw, err := a.client.Request("account.getQuota", map[string]interface{}{}) + if err != nil { return nil, err } + var result AccountGetQuotaResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } // ServerRpc provides typed server-scoped RPC methods. type ServerRpc struct { - client *jsonrpc2.Client - Models *ServerModelsRpcApi - Tools *ServerToolsRpcApi - Account *ServerAccountRpcApi + client *jsonrpc2.Client + Models *ServerModelsRpcApi + Tools *ServerToolsRpcApi + Account *ServerAccountRpcApi } func (a *ServerRpc) Ping(ctx context.Context, params *PingParams) (*PingResult, error) { - raw, err := a.client.Request("ping", params) - if err != nil { return nil, err } - var result PingResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + raw, err := a.client.Request("ping", params) + if err != nil { return nil, err } + var result PingResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func NewServerRpc(client *jsonrpc2.Client) *ServerRpc { - return &ServerRpc{client: client, - Models: &ServerModelsRpcApi{client: client}, - Tools: &ServerToolsRpcApi{client: client}, - Account: &ServerAccountRpcApi{client: client}, - } + return &ServerRpc{client: client, + Models: &ServerModelsRpcApi{client: client}, + Tools: &ServerToolsRpcApi{client: client}, + Account: &ServerAccountRpcApi{client: client}, + } } type ModelRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ModelRpcApi) GetCurrent(ctx context.Context) (*SessionModelGetCurrentResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.model.getCurrent", req) - if err != nil { return nil, err } - var result SessionModelGetCurrentResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.model.getCurrent", req) + if err != nil { return nil, err } + var result SessionModelGetCurrentResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *ModelRpcApi) SwitchTo(ctx context.Context, params *SessionModelSwitchToParams) (*SessionModelSwitchToResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["modelId"] = params.ModelID - if params.ReasoningEffort != nil { - req["reasoningEffort"] = *params.ReasoningEffort - } - } - raw, err := a.client.Request("session.model.switchTo", req) - if err != nil { return nil, err } - var result SessionModelSwitchToResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["modelId"] = params.ModelID + if params.ReasoningEffort != nil { + req["reasoningEffort"] = *params.ReasoningEffort + } + } + raw, err := a.client.Request("session.model.switchTo", req) + if err != nil { return nil, err } + var result SessionModelSwitchToResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type ModeRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ModeRpcApi) Get(ctx context.Context) (*SessionModeGetResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.mode.get", req) - if err != nil { return nil, err } - var result SessionModeGetResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.mode.get", req) + if err != nil { return nil, err } + var result SessionModeGetResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *ModeRpcApi) Set(ctx context.Context, params *SessionModeSetParams) (*SessionModeSetResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["mode"] = params.Mode - } - raw, err := a.client.Request("session.mode.set", req) - if err != nil { return nil, err } - var result SessionModeSetResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["mode"] = params.Mode + } + raw, err := a.client.Request("session.mode.set", req) + if err != nil { return nil, err } + var result SessionModeSetResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type PlanRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *PlanRpcApi) Read(ctx context.Context) (*SessionPlanReadResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.plan.read", req) - if err != nil { return nil, err } - var result SessionPlanReadResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.plan.read", req) + if err != nil { return nil, err } + var result SessionPlanReadResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *PlanRpcApi) Update(ctx context.Context, params *SessionPlanUpdateParams) (*SessionPlanUpdateResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["content"] = params.Content - } - raw, err := a.client.Request("session.plan.update", req) - if err != nil { return nil, err } - var result SessionPlanUpdateResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["content"] = params.Content + } + raw, err := a.client.Request("session.plan.update", req) + if err != nil { return nil, err } + var result SessionPlanUpdateResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *PlanRpcApi) Delete(ctx context.Context) (*SessionPlanDeleteResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.plan.delete", req) - if err != nil { return nil, err } - var result SessionPlanDeleteResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.plan.delete", req) + if err != nil { return nil, err } + var result SessionPlanDeleteResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type WorkspaceRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *WorkspaceRpcApi) ListFiles(ctx context.Context) (*SessionWorkspaceListFilesResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.workspace.listFiles", req) - if err != nil { return nil, err } - var result SessionWorkspaceListFilesResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.workspace.listFiles", req) + if err != nil { return nil, err } + var result SessionWorkspaceListFilesResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *WorkspaceRpcApi) ReadFile(ctx context.Context, params *SessionWorkspaceReadFileParams) (*SessionWorkspaceReadFileResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["path"] = params.Path - } - raw, err := a.client.Request("session.workspace.readFile", req) - if err != nil { return nil, err } - var result SessionWorkspaceReadFileResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["path"] = params.Path + } + raw, err := a.client.Request("session.workspace.readFile", req) + if err != nil { return nil, err } + var result SessionWorkspaceReadFileResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *WorkspaceRpcApi) CreateFile(ctx context.Context, params *SessionWorkspaceCreateFileParams) (*SessionWorkspaceCreateFileResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["path"] = params.Path - req["content"] = params.Content - } - raw, err := a.client.Request("session.workspace.createFile", req) - if err != nil { return nil, err } - var result SessionWorkspaceCreateFileResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["path"] = params.Path + req["content"] = params.Content + } + raw, err := a.client.Request("session.workspace.createFile", req) + if err != nil { return nil, err } + var result SessionWorkspaceCreateFileResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } // Experimental: FleetRpcApi contains experimental APIs that may change or be removed. type FleetRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *FleetRpcApi) Start(ctx context.Context, params *SessionFleetStartParams) (*SessionFleetStartResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - if params.Prompt != nil { - req["prompt"] = *params.Prompt - } - } - raw, err := a.client.Request("session.fleet.start", req) - if err != nil { return nil, err } - var result SessionFleetStartResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + if params.Prompt != nil { + req["prompt"] = *params.Prompt + } + } + raw, err := a.client.Request("session.fleet.start", req) + if err != nil { return nil, err } + var result SessionFleetStartResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } // Experimental: AgentRpcApi contains experimental APIs that may change or be removed. type AgentRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *AgentRpcApi) List(ctx context.Context) (*SessionAgentListResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.list", req) - if err != nil { return nil, err } - var result SessionAgentListResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.agent.list", req) + if err != nil { return nil, err } + var result SessionAgentListResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *AgentRpcApi) GetCurrent(ctx context.Context) (*SessionAgentGetCurrentResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.getCurrent", req) - if err != nil { return nil, err } - var result SessionAgentGetCurrentResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.agent.getCurrent", req) + if err != nil { return nil, err } + var result SessionAgentGetCurrentResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *AgentRpcApi) Select(ctx context.Context, params *SessionAgentSelectParams) (*SessionAgentSelectResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["name"] = params.Name - } - raw, err := a.client.Request("session.agent.select", req) - if err != nil { return nil, err } - var result SessionAgentSelectResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["name"] = params.Name + } + raw, err := a.client.Request("session.agent.select", req) + if err != nil { return nil, err } + var result SessionAgentSelectResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *AgentRpcApi) Deselect(ctx context.Context) (*SessionAgentDeselectResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.deselect", req) - if err != nil { return nil, err } - var result SessionAgentDeselectResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.agent.deselect", req) + if err != nil { return nil, err } + var result SessionAgentDeselectResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } // Experimental: CompactionRpcApi contains experimental APIs that may change or be removed. type CompactionRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *CompactionRpcApi) Compact(ctx context.Context) (*SessionCompactionCompactResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - raw, err := a.client.Request("session.compaction.compact", req) - if err != nil { return nil, err } - var result SessionCompactionCompactResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + raw, err := a.client.Request("session.compaction.compact", req) + if err != nil { return nil, err } + var result SessionCompactionCompactResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type ToolsRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ToolsRpcApi) HandlePendingToolCall(ctx context.Context, params *SessionToolsHandlePendingToolCallParams) (*SessionToolsHandlePendingToolCallResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["requestId"] = params.RequestID - if params.Result != nil { - req["result"] = *params.Result - } - if params.Error != nil { - req["error"] = *params.Error - } - } - raw, err := a.client.Request("session.tools.handlePendingToolCall", req) - if err != nil { return nil, err } - var result SessionToolsHandlePendingToolCallResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + if params.Result != nil { + req["result"] = *params.Result + } + if params.Error != nil { + req["error"] = *params.Error + } + } + raw, err := a.client.Request("session.tools.handlePendingToolCall", req) + if err != nil { return nil, err } + var result SessionToolsHandlePendingToolCallResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type PermissionsRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *PermissionsRpcApi) HandlePendingPermissionRequest(ctx context.Context, params *SessionPermissionsHandlePendingPermissionRequestParams) (*SessionPermissionsHandlePendingPermissionRequestResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["requestId"] = params.RequestID - req["result"] = params.Result - } - raw, err := a.client.Request("session.permissions.handlePendingPermissionRequest", req) - if err != nil { return nil, err } - var result SessionPermissionsHandlePendingPermissionRequestResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + req["result"] = params.Result + } + raw, err := a.client.Request("session.permissions.handlePendingPermissionRequest", req) + if err != nil { return nil, err } + var result SessionPermissionsHandlePendingPermissionRequestResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } type ShellRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ShellRpcApi) Exec(ctx context.Context, params *SessionShellExecParams) (*SessionShellExecResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["command"] = params.Command - if params.Cwd != nil { - req["cwd"] = *params.Cwd - } - if params.Timeout != nil { - req["timeout"] = *params.Timeout - } - } - raw, err := a.client.Request("session.shell.exec", req) - if err != nil { return nil, err } - var result SessionShellExecResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["command"] = params.Command + if params.Cwd != nil { + req["cwd"] = *params.Cwd + } + if params.Timeout != nil { + req["timeout"] = *params.Timeout + } + } + raw, err := a.client.Request("session.shell.exec", req) + if err != nil { return nil, err } + var result SessionShellExecResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func (a *ShellRpcApi) Kill(ctx context.Context, params *SessionShellKillParams) (*SessionShellKillResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["processId"] = params.ProcessID - if params.Signal != nil { - req["signal"] = *params.Signal - } - } - raw, err := a.client.Request("session.shell.kill", req) - if err != nil { return nil, err } - var result SessionShellKillResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["processId"] = params.ProcessID + if params.Signal != nil { + req["signal"] = *params.Signal + } + } + raw, err := a.client.Request("session.shell.kill", req) + if err != nil { return nil, err } + var result SessionShellKillResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } // SessionRpc provides typed session-scoped RPC methods. type SessionRpc struct { - client *jsonrpc2.Client - sessionID string - Model *ModelRpcApi - Mode *ModeRpcApi - Plan *PlanRpcApi - Workspace *WorkspaceRpcApi - Fleet *FleetRpcApi - Agent *AgentRpcApi - Compaction *CompactionRpcApi - Tools *ToolsRpcApi - Permissions *PermissionsRpcApi - Shell *ShellRpcApi + client *jsonrpc2.Client + sessionID string + Model *ModelRpcApi + Mode *ModeRpcApi + Plan *PlanRpcApi + Workspace *WorkspaceRpcApi + Fleet *FleetRpcApi + Agent *AgentRpcApi + Compaction *CompactionRpcApi + Tools *ToolsRpcApi + Permissions *PermissionsRpcApi + Shell *ShellRpcApi } func (a *SessionRpc) Log(ctx context.Context, params *SessionLogParams) (*SessionLogResult, error) { - req := map[string]interface{}{"sessionId": a.sessionID} - if params != nil { - req["message"] = params.Message - if params.Level != nil { - req["level"] = *params.Level - } - if params.Ephemeral != nil { - req["ephemeral"] = *params.Ephemeral - } - } - raw, err := a.client.Request("session.log", req) - if err != nil { return nil, err } - var result SessionLogResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return &result, nil + req := map[string]interface{}{"sessionId": a.sessionID} + if params != nil { + req["message"] = params.Message + if params.Level != nil { + req["level"] = *params.Level + } + if params.Ephemeral != nil { + req["ephemeral"] = *params.Ephemeral + } + } + raw, err := a.client.Request("session.log", req) + if err != nil { return nil, err } + var result SessionLogResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + return &result, nil } func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc { - return &SessionRpc{client: client, sessionID: sessionID, - Model: &ModelRpcApi{client: client, sessionID: sessionID}, - Mode: &ModeRpcApi{client: client, sessionID: sessionID}, - Plan: &PlanRpcApi{client: client, sessionID: sessionID}, - Workspace: &WorkspaceRpcApi{client: client, sessionID: sessionID}, - Fleet: &FleetRpcApi{client: client, sessionID: sessionID}, - Agent: &AgentRpcApi{client: client, sessionID: sessionID}, - Compaction: &CompactionRpcApi{client: client, sessionID: sessionID}, - Tools: &ToolsRpcApi{client: client, sessionID: sessionID}, - Permissions: &PermissionsRpcApi{client: client, sessionID: sessionID}, - Shell: &ShellRpcApi{client: client, sessionID: sessionID}, - } + return &SessionRpc{client: client, sessionID: sessionID, + Model: &ModelRpcApi{client: client, sessionID: sessionID}, + Mode: &ModeRpcApi{client: client, sessionID: sessionID}, + Plan: &PlanRpcApi{client: client, sessionID: sessionID}, + Workspace: &WorkspaceRpcApi{client: client, sessionID: sessionID}, + Fleet: &FleetRpcApi{client: client, sessionID: sessionID}, + Agent: &AgentRpcApi{client: client, sessionID: sessionID}, + Compaction: &CompactionRpcApi{client: client, sessionID: sessionID}, + Tools: &ToolsRpcApi{client: client, sessionID: sessionID}, + Permissions: &PermissionsRpcApi{client: client, sessionID: sessionID}, + Shell: &ShellRpcApi{client: client, sessionID: sessionID}, + } } diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 554ab793f..157001203 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -162,10 +162,10 @@ async function generateRpc(schemaPath?: string): Promise { lines.push(`package rpc`); lines.push(``); lines.push(`import (`); - lines.push(` "context"`); - lines.push(` "encoding/json"`); + lines.push(`\t"context"`); + lines.push(`\t"encoding/json"`); lines.push(``); - lines.push(` "github.com/github/copilot-sdk/go/internal/jsonrpc2"`); + lines.push(`\t"github.com/github/copilot-sdk/go/internal/jsonrpc2"`); lines.push(`)`); lines.push(``); @@ -231,14 +231,20 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio } } + // Compute field name lengths for gofmt-compatible column alignment + const groupPascalNames = groups.map(([g]) => toPascalCase(g)); + const allFieldNames = isSession ? ["client", "sessionID", ...groupPascalNames] : ["client", ...groupPascalNames]; + const maxFieldLen = Math.max(...allFieldNames.map((n) => n.length)); + const pad = (name: string) => name.padEnd(maxFieldLen); + // Emit wrapper struct lines.push(`// ${wrapperName} provides typed ${isSession ? "session" : "server"}-scoped RPC methods.`); lines.push(`type ${wrapperName} struct {`); - lines.push(` client *jsonrpc2.Client`); - if (isSession) lines.push(` sessionID string`); + lines.push(`\t${pad("client")} *jsonrpc2.Client`); + if (isSession) lines.push(`\t${pad("sessionID")} string`); for (const [groupName] of groups) { const prefix = isSession ? "" : "Server"; - lines.push(` ${toPascalCase(groupName)} *${prefix}${toPascalCase(groupName)}${apiSuffix}`); + lines.push(`\t${pad(toPascalCase(groupName))} *${prefix}${toPascalCase(groupName)}${apiSuffix}`); } lines.push(`}`); lines.push(``); @@ -249,19 +255,23 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio emitMethod(lines, wrapperName, key, value, isSession, false); } + // Compute key alignment for constructor composite literal (gofmt aligns key: value) + const maxKeyLen = Math.max(...groupPascalNames.map((n) => n.length + 1)); // +1 for colon + const padKey = (name: string) => (name + ":").padEnd(maxKeyLen + 1); // +1 for min trailing space + // Constructor const ctorParams = isSession ? "client *jsonrpc2.Client, sessionID string" : "client *jsonrpc2.Client"; const ctorFields = isSession ? "client: client, sessionID: sessionID," : "client: client,"; lines.push(`func New${wrapperName}(${ctorParams}) *${wrapperName} {`); - lines.push(` return &${wrapperName}{${ctorFields}`); + lines.push(`\treturn &${wrapperName}{${ctorFields}`); for (const [groupName] of groups) { const prefix = isSession ? "" : "Server"; const apiInit = isSession ? `&${toPascalCase(groupName)}${apiSuffix}{client: client, sessionID: sessionID}` : `&${prefix}${toPascalCase(groupName)}${apiSuffix}{client: client}`; - lines.push(` ${toPascalCase(groupName)}: ${apiInit},`); + lines.push(`\t\t${padKey(toPascalCase(groupName))}${apiInit},`); } - lines.push(` }`); + lines.push(`\t}`); lines.push(`}`); lines.push(``); } @@ -286,33 +296,33 @@ function emitMethod(lines: string[], receiver: string, name: string, method: Rpc lines.push(sig + ` {`); if (isSession) { - lines.push(` req := map[string]interface{}{"sessionId": a.sessionID}`); + lines.push(`\treq := map[string]interface{}{"sessionId": a.sessionID}`); if (hasParams) { - lines.push(` if params != nil {`); + lines.push(`\tif params != nil {`); for (const pName of nonSessionParams) { const goField = toGoFieldName(pName); const isOptional = !requiredParams.has(pName); if (isOptional) { // Optional fields are pointers - only add when non-nil and dereference - lines.push(` if params.${goField} != nil {`); - lines.push(` req["${pName}"] = *params.${goField}`); - lines.push(` }`); + lines.push(`\t\tif params.${goField} != nil {`); + lines.push(`\t\t\treq["${pName}"] = *params.${goField}`); + lines.push(`\t\t}`); } else { - lines.push(` req["${pName}"] = params.${goField}`); + lines.push(`\t\treq["${pName}"] = params.${goField}`); } } - lines.push(` }`); + lines.push(`\t}`); } - lines.push(` raw, err := a.client.Request("${method.rpcMethod}", req)`); + lines.push(`\traw, err := a.client.Request("${method.rpcMethod}", req)`); } else { const arg = hasParams ? "params" : "map[string]interface{}{}"; - lines.push(` raw, err := a.client.Request("${method.rpcMethod}", ${arg})`); + lines.push(`\traw, err := a.client.Request("${method.rpcMethod}", ${arg})`); } - lines.push(` if err != nil { return nil, err }`); - lines.push(` var result ${resultType}`); - lines.push(` if err := json.Unmarshal(raw, &result); err != nil { return nil, err }`); - lines.push(` return &result, nil`); + lines.push(`\tif err != nil { return nil, err }`); + lines.push(`\tvar result ${resultType}`); + lines.push(`\tif err := json.Unmarshal(raw, &result); err != nil { return nil, err }`); + lines.push(`\treturn &result, nil`); lines.push(`}`); lines.push(``); } From dae6767ddebca83f4a5b53364a237ea8936731cd Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 17 Mar 2026 12:04:34 -0400 Subject: [PATCH 4/7] fix: use multi-line if-return blocks for gofmt compatibility gofmt expands single-line 'if err != nil { return nil, err }' into multi-line blocks. Updated Go codegen to emit the multi-line form directly, avoiding the gofmt diff. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/generated_rpc.go | 200 ++++++++++++++++++++++++++++++---------- scripts/codegen/go.ts | 8 +- 2 files changed, 156 insertions(+), 52 deletions(-) diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 9a12f6668..1e7d3757f 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -415,9 +415,13 @@ type ServerModelsRpcApi struct { client *jsonrpc2.Client } func (a *ServerModelsRpcApi) List(ctx context.Context) (*ModelsListResult, error) { raw, err := a.client.Request("models.list", map[string]interface{}{}) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result ModelsListResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -425,9 +429,13 @@ type ServerToolsRpcApi struct { client *jsonrpc2.Client } func (a *ServerToolsRpcApi) List(ctx context.Context, params *ToolsListParams) (*ToolsListResult, error) { raw, err := a.client.Request("tools.list", params) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result ToolsListResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -435,9 +443,13 @@ type ServerAccountRpcApi struct { client *jsonrpc2.Client } func (a *ServerAccountRpcApi) GetQuota(ctx context.Context) (*AccountGetQuotaResult, error) { raw, err := a.client.Request("account.getQuota", map[string]interface{}{}) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result AccountGetQuotaResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -451,9 +463,13 @@ type ServerRpc struct { func (a *ServerRpc) Ping(ctx context.Context, params *PingParams) (*PingResult, error) { raw, err := a.client.Request("ping", params) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result PingResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -470,9 +486,13 @@ type ModelRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ModelRpcApi) GetCurrent(ctx context.Context) (*SessionModelGetCurrentResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.model.getCurrent", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionModelGetCurrentResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -485,9 +505,13 @@ func (a *ModelRpcApi) SwitchTo(ctx context.Context, params *SessionModelSwitchTo } } raw, err := a.client.Request("session.model.switchTo", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionModelSwitchToResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -496,9 +520,13 @@ type ModeRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *ModeRpcApi) Get(ctx context.Context) (*SessionModeGetResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.mode.get", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionModeGetResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -508,9 +536,13 @@ func (a *ModeRpcApi) Set(ctx context.Context, params *SessionModeSetParams) (*Se req["mode"] = params.Mode } raw, err := a.client.Request("session.mode.set", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionModeSetResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -519,9 +551,13 @@ type PlanRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *PlanRpcApi) Read(ctx context.Context) (*SessionPlanReadResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.plan.read", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionPlanReadResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -531,18 +567,26 @@ func (a *PlanRpcApi) Update(ctx context.Context, params *SessionPlanUpdateParams req["content"] = params.Content } raw, err := a.client.Request("session.plan.update", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionPlanUpdateResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } func (a *PlanRpcApi) Delete(ctx context.Context) (*SessionPlanDeleteResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.plan.delete", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionPlanDeleteResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -551,9 +595,13 @@ type WorkspaceRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *WorkspaceRpcApi) ListFiles(ctx context.Context) (*SessionWorkspaceListFilesResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.workspace.listFiles", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionWorkspaceListFilesResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -563,9 +611,13 @@ func (a *WorkspaceRpcApi) ReadFile(ctx context.Context, params *SessionWorkspace req["path"] = params.Path } raw, err := a.client.Request("session.workspace.readFile", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionWorkspaceReadFileResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -576,9 +628,13 @@ func (a *WorkspaceRpcApi) CreateFile(ctx context.Context, params *SessionWorkspa req["content"] = params.Content } raw, err := a.client.Request("session.workspace.createFile", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionWorkspaceCreateFileResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -593,9 +649,13 @@ func (a *FleetRpcApi) Start(ctx context.Context, params *SessionFleetStartParams } } raw, err := a.client.Request("session.fleet.start", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionFleetStartResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -605,18 +665,26 @@ type AgentRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *AgentRpcApi) List(ctx context.Context) (*SessionAgentListResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.agent.list", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionAgentListResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } func (a *AgentRpcApi) GetCurrent(ctx context.Context) (*SessionAgentGetCurrentResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.agent.getCurrent", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionAgentGetCurrentResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -626,18 +694,26 @@ func (a *AgentRpcApi) Select(ctx context.Context, params *SessionAgentSelectPara req["name"] = params.Name } raw, err := a.client.Request("session.agent.select", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionAgentSelectResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } func (a *AgentRpcApi) Deselect(ctx context.Context) (*SessionAgentDeselectResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.agent.deselect", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionAgentDeselectResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -647,9 +723,13 @@ type CompactionRpcApi struct { client *jsonrpc2.Client; sessionID string } func (a *CompactionRpcApi) Compact(ctx context.Context) (*SessionCompactionCompactResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} raw, err := a.client.Request("session.compaction.compact", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionCompactionCompactResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -667,9 +747,13 @@ func (a *ToolsRpcApi) HandlePendingToolCall(ctx context.Context, params *Session } } raw, err := a.client.Request("session.tools.handlePendingToolCall", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionToolsHandlePendingToolCallResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -682,9 +766,13 @@ func (a *PermissionsRpcApi) HandlePendingPermissionRequest(ctx context.Context, req["result"] = params.Result } raw, err := a.client.Request("session.permissions.handlePendingPermissionRequest", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionPermissionsHandlePendingPermissionRequestResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -702,9 +790,13 @@ func (a *ShellRpcApi) Exec(ctx context.Context, params *SessionShellExecParams) } } raw, err := a.client.Request("session.shell.exec", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionShellExecResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -717,9 +809,13 @@ func (a *ShellRpcApi) Kill(ctx context.Context, params *SessionShellKillParams) } } raw, err := a.client.Request("session.shell.kill", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionShellKillResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } @@ -751,9 +847,13 @@ func (a *SessionRpc) Log(ctx context.Context, params *SessionLogParams) (*Sessio } } raw, err := a.client.Request("session.log", req) - if err != nil { return nil, err } + if err != nil { + return nil, err + } var result SessionLogResult - if err := json.Unmarshal(raw, &result); err != nil { return nil, err } + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } return &result, nil } diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 157001203..72a9deef2 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -319,9 +319,13 @@ function emitMethod(lines: string[], receiver: string, name: string, method: Rpc lines.push(`\traw, err := a.client.Request("${method.rpcMethod}", ${arg})`); } - lines.push(`\tif err != nil { return nil, err }`); + lines.push(`\tif err != nil {`); + lines.push(`\t\treturn nil, err`); + lines.push(`\t}`); lines.push(`\tvar result ${resultType}`); - lines.push(`\tif err := json.Unmarshal(raw, &result); err != nil { return nil, err }`); + lines.push(`\tif err := json.Unmarshal(raw, &result); err != nil {`); + lines.push(`\t\treturn nil, err`); + lines.push(`\t}`); lines.push(`\treturn &result, nil`); lines.push(`}`); lines.push(``); From f1ae76d262244b0f075791fcc04e889ab6a229fc Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 17 Mar 2026 12:28:38 -0400 Subject: [PATCH 5/7] fix: expand single-line struct defs to multi-line for gofmt gofmt expands single-line struct definitions with semicolons into multi-line format. Updated the Go codegen to emit API struct definitions in multi-line format directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/generated_rpc.go | 62 ++++++++++++++++++++++++++++++++--------- scripts/codegen/go.ts | 10 +++++-- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 1e7d3757f..91112559d 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -411,7 +411,9 @@ type ResultUnion struct { } -type ServerModelsRpcApi struct { client *jsonrpc2.Client } +type ServerModelsRpcApi struct { + client *jsonrpc2.Client +} func (a *ServerModelsRpcApi) List(ctx context.Context) (*ModelsListResult, error) { raw, err := a.client.Request("models.list", map[string]interface{}{}) @@ -425,7 +427,9 @@ func (a *ServerModelsRpcApi) List(ctx context.Context) (*ModelsListResult, error return &result, nil } -type ServerToolsRpcApi struct { client *jsonrpc2.Client } +type ServerToolsRpcApi struct { + client *jsonrpc2.Client +} func (a *ServerToolsRpcApi) List(ctx context.Context, params *ToolsListParams) (*ToolsListResult, error) { raw, err := a.client.Request("tools.list", params) @@ -439,7 +443,9 @@ func (a *ServerToolsRpcApi) List(ctx context.Context, params *ToolsListParams) ( return &result, nil } -type ServerAccountRpcApi struct { client *jsonrpc2.Client } +type ServerAccountRpcApi struct { + client *jsonrpc2.Client +} func (a *ServerAccountRpcApi) GetQuota(ctx context.Context) (*AccountGetQuotaResult, error) { raw, err := a.client.Request("account.getQuota", map[string]interface{}{}) @@ -481,7 +487,10 @@ func NewServerRpc(client *jsonrpc2.Client) *ServerRpc { } } -type ModelRpcApi struct { client *jsonrpc2.Client; sessionID string } +type ModelRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *ModelRpcApi) GetCurrent(ctx context.Context) (*SessionModelGetCurrentResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -515,7 +524,10 @@ func (a *ModelRpcApi) SwitchTo(ctx context.Context, params *SessionModelSwitchTo return &result, nil } -type ModeRpcApi struct { client *jsonrpc2.Client; sessionID string } +type ModeRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *ModeRpcApi) Get(ctx context.Context) (*SessionModeGetResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -546,7 +558,10 @@ func (a *ModeRpcApi) Set(ctx context.Context, params *SessionModeSetParams) (*Se return &result, nil } -type PlanRpcApi struct { client *jsonrpc2.Client; sessionID string } +type PlanRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *PlanRpcApi) Read(ctx context.Context) (*SessionPlanReadResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -590,7 +605,10 @@ func (a *PlanRpcApi) Delete(ctx context.Context) (*SessionPlanDeleteResult, erro return &result, nil } -type WorkspaceRpcApi struct { client *jsonrpc2.Client; sessionID string } +type WorkspaceRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *WorkspaceRpcApi) ListFiles(ctx context.Context) (*SessionWorkspaceListFilesResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -639,7 +657,10 @@ func (a *WorkspaceRpcApi) CreateFile(ctx context.Context, params *SessionWorkspa } // Experimental: FleetRpcApi contains experimental APIs that may change or be removed. -type FleetRpcApi struct { client *jsonrpc2.Client; sessionID string } +type FleetRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *FleetRpcApi) Start(ctx context.Context, params *SessionFleetStartParams) (*SessionFleetStartResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -660,7 +681,10 @@ func (a *FleetRpcApi) Start(ctx context.Context, params *SessionFleetStartParams } // Experimental: AgentRpcApi contains experimental APIs that may change or be removed. -type AgentRpcApi struct { client *jsonrpc2.Client; sessionID string } +type AgentRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *AgentRpcApi) List(ctx context.Context) (*SessionAgentListResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -718,7 +742,10 @@ func (a *AgentRpcApi) Deselect(ctx context.Context) (*SessionAgentDeselectResult } // Experimental: CompactionRpcApi contains experimental APIs that may change or be removed. -type CompactionRpcApi struct { client *jsonrpc2.Client; sessionID string } +type CompactionRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *CompactionRpcApi) Compact(ctx context.Context) (*SessionCompactionCompactResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -733,7 +760,10 @@ func (a *CompactionRpcApi) Compact(ctx context.Context) (*SessionCompactionCompa return &result, nil } -type ToolsRpcApi struct { client *jsonrpc2.Client; sessionID string } +type ToolsRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *ToolsRpcApi) HandlePendingToolCall(ctx context.Context, params *SessionToolsHandlePendingToolCallParams) (*SessionToolsHandlePendingToolCallResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -757,7 +787,10 @@ func (a *ToolsRpcApi) HandlePendingToolCall(ctx context.Context, params *Session return &result, nil } -type PermissionsRpcApi struct { client *jsonrpc2.Client; sessionID string } +type PermissionsRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *PermissionsRpcApi) HandlePendingPermissionRequest(ctx context.Context, params *SessionPermissionsHandlePendingPermissionRequestParams) (*SessionPermissionsHandlePendingPermissionRequestResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} @@ -776,7 +809,10 @@ func (a *PermissionsRpcApi) HandlePendingPermissionRequest(ctx context.Context, return &result, nil } -type ShellRpcApi struct { client *jsonrpc2.Client; sessionID string } +type ShellRpcApi struct { + client *jsonrpc2.Client + sessionID string +} func (a *ShellRpcApi) Exec(ctx context.Context, params *SessionShellExecParams) (*SessionShellExecResult, error) { req := map[string]interface{}{"sessionId": a.sessionID} diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 72a9deef2..e92d741e5 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -218,12 +218,18 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio for (const [groupName, groupNode] of groups) { const prefix = isSession ? "" : "Server"; const apiName = prefix + toPascalCase(groupName) + apiSuffix; - const fields = isSession ? "client *jsonrpc2.Client; sessionID string" : "client *jsonrpc2.Client"; const groupExperimental = isNodeFullyExperimental(groupNode as Record); if (groupExperimental) { lines.push(`// Experimental: ${apiName} contains experimental APIs that may change or be removed.`); } - lines.push(`type ${apiName} struct { ${fields} }`); + lines.push(`type ${apiName} struct {`); + if (isSession) { + lines.push(`\tclient *jsonrpc2.Client`); + lines.push(`\tsessionID string`); + } else { + lines.push(`\tclient *jsonrpc2.Client`); + } + lines.push(`}`); lines.push(``); for (const [key, value] of Object.entries(groupNode as Record)) { if (!isRpcMethod(value)) continue; From 13450150dcb62024a48f07f3b866c6c6e38868a6 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 17 Mar 2026 12:35:39 -0400 Subject: [PATCH 6/7] fix: collapse quicktype column alignment for gofmt compatibility quicktype emits wide-spaced struct fields for column alignment, but gofmt doesn't column-align when fields have interleaved comments. Added post-processing to collapse excessive spacing in quicktype struct field lines and remove trailing blank lines from quicktype output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/generated_rpc.go | 215 ++++++++++++++++++++-------------------- scripts/codegen/go.ts | 7 ++ 2 files changed, 114 insertions(+), 108 deletions(-) diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 91112559d..9a05f5711 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -12,164 +12,164 @@ import ( type PingResult struct { // Echoed message (or default greeting) - Message string `json:"message"` + Message string `json:"message"` // Server protocol version number - ProtocolVersion float64 `json:"protocolVersion"` + ProtocolVersion float64 `json:"protocolVersion"` // Server timestamp in milliseconds - Timestamp float64 `json:"timestamp"` + Timestamp float64 `json:"timestamp"` } type PingParams struct { // Optional message to echo back - Message *string `json:"message,omitempty"` + Message *string `json:"message,omitempty"` } type ModelsListResult struct { // List of available models with full metadata - Models []Model `json:"models"` + Models []Model `json:"models"` } type Model struct { // Billing information - Billing *Billing `json:"billing,omitempty"` + Billing *Billing `json:"billing,omitempty"` // Model capabilities and limits - Capabilities Capabilities `json:"capabilities"` + Capabilities Capabilities `json:"capabilities"` // Default reasoning effort level (only present if model supports reasoning effort) - DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` + DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` // Model identifier (e.g., "claude-sonnet-4.5") - ID string `json:"id"` + ID string `json:"id"` // Display name - Name string `json:"name"` + Name string `json:"name"` // Policy state (if applicable) - Policy *Policy `json:"policy,omitempty"` + Policy *Policy `json:"policy,omitempty"` // Supported reasoning effort levels (only present if model supports reasoning effort) - SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` + SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` } // Billing information type Billing struct { // Billing cost multiplier relative to the base rate - Multiplier float64 `json:"multiplier"` + Multiplier float64 `json:"multiplier"` } // Model capabilities and limits type Capabilities struct { // Token limits for prompts, outputs, and context window - Limits Limits `json:"limits"` + Limits Limits `json:"limits"` // Feature flags indicating what the model supports - Supports Supports `json:"supports"` + Supports Supports `json:"supports"` } // Token limits for prompts, outputs, and context window type Limits struct { // Maximum total context window size in tokens - MaxContextWindowTokens float64 `json:"max_context_window_tokens"` + MaxContextWindowTokens float64 `json:"max_context_window_tokens"` // Maximum number of output/completion tokens - MaxOutputTokens *float64 `json:"max_output_tokens,omitempty"` + MaxOutputTokens *float64 `json:"max_output_tokens,omitempty"` // Maximum number of prompt/input tokens - MaxPromptTokens *float64 `json:"max_prompt_tokens,omitempty"` + MaxPromptTokens *float64 `json:"max_prompt_tokens,omitempty"` } // Feature flags indicating what the model supports type Supports struct { // Whether this model supports reasoning effort configuration - ReasoningEffort *bool `json:"reasoningEffort,omitempty"` + ReasoningEffort *bool `json:"reasoningEffort,omitempty"` // Whether this model supports vision/image input - Vision *bool `json:"vision,omitempty"` + Vision *bool `json:"vision,omitempty"` } // Policy state (if applicable) type Policy struct { // Current policy state for this model - State string `json:"state"` + State string `json:"state"` // Usage terms or conditions for this model - Terms string `json:"terms"` + Terms string `json:"terms"` } type ToolsListResult struct { // List of available built-in tools with metadata - Tools []Tool `json:"tools"` + Tools []Tool `json:"tools"` } type Tool struct { // Description of what the tool does - Description string `json:"description"` + Description string `json:"description"` // Optional instructions for how to use this tool effectively - Instructions *string `json:"instructions,omitempty"` + Instructions *string `json:"instructions,omitempty"` // Tool identifier (e.g., "bash", "grep", "str_replace_editor") - Name string `json:"name"` + Name string `json:"name"` // Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP // tools) - NamespacedName *string `json:"namespacedName,omitempty"` + NamespacedName *string `json:"namespacedName,omitempty"` // JSON Schema for the tool's input parameters - Parameters map[string]interface{} `json:"parameters,omitempty"` + Parameters map[string]interface{} `json:"parameters,omitempty"` } type ToolsListParams struct { // Optional model ID — when provided, the returned tool list reflects model-specific // overrides - Model *string `json:"model,omitempty"` + Model *string `json:"model,omitempty"` } type AccountGetQuotaResult struct { // Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) - QuotaSnapshots map[string]QuotaSnapshot `json:"quotaSnapshots"` + QuotaSnapshots map[string]QuotaSnapshot `json:"quotaSnapshots"` } type QuotaSnapshot struct { // Number of requests included in the entitlement - EntitlementRequests float64 `json:"entitlementRequests"` + EntitlementRequests float64 `json:"entitlementRequests"` // Number of overage requests made this period - Overage float64 `json:"overage"` + Overage float64 `json:"overage"` // Whether pay-per-request usage is allowed when quota is exhausted - OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` + OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` // Percentage of entitlement remaining - RemainingPercentage float64 `json:"remainingPercentage"` + RemainingPercentage float64 `json:"remainingPercentage"` // Date when the quota resets (ISO 8601) - ResetDate *string `json:"resetDate,omitempty"` + ResetDate *string `json:"resetDate,omitempty"` // Number of requests used so far this period - UsedRequests float64 `json:"usedRequests"` + UsedRequests float64 `json:"usedRequests"` } type SessionModelGetCurrentResult struct { // Currently active model identifier - ModelID *string `json:"modelId,omitempty"` + ModelID *string `json:"modelId,omitempty"` } type SessionModelSwitchToResult struct { // Currently active model identifier after the switch - ModelID *string `json:"modelId,omitempty"` + ModelID *string `json:"modelId,omitempty"` } type SessionModelSwitchToParams struct { // Model identifier to switch to - ModelID string `json:"modelId"` + ModelID string `json:"modelId"` // Reasoning effort level to use for the model - ReasoningEffort *string `json:"reasoningEffort,omitempty"` + ReasoningEffort *string `json:"reasoningEffort,omitempty"` } type SessionModeGetResult struct { // The current agent mode. - Mode Mode `json:"mode"` + Mode Mode `json:"mode"` } type SessionModeSetResult struct { // The agent mode after switching. - Mode Mode `json:"mode"` + Mode Mode `json:"mode"` } type SessionModeSetParams struct { // The mode to switch to. Valid values: "interactive", "plan", "autopilot". - Mode Mode `json:"mode"` + Mode Mode `json:"mode"` } type SessionPlanReadResult struct { // The content of the plan file, or null if it does not exist - Content *string `json:"content"` + Content *string `json:"content"` // Whether the plan file exists in the workspace - Exists bool `json:"exists"` + Exists bool `json:"exists"` // Absolute file path of the plan file, or null if workspace is not enabled - Path *string `json:"path"` + Path *string `json:"path"` } type SessionPlanUpdateResult struct { @@ -177,7 +177,7 @@ type SessionPlanUpdateResult struct { type SessionPlanUpdateParams struct { // The new content for the plan file - Content string `json:"content"` + Content string `json:"content"` } type SessionPlanDeleteResult struct { @@ -185,17 +185,17 @@ type SessionPlanDeleteResult struct { type SessionWorkspaceListFilesResult struct { // Relative file paths in the workspace files directory - Files []string `json:"files"` + Files []string `json:"files"` } type SessionWorkspaceReadFileResult struct { // File content as a UTF-8 string - Content string `json:"content"` + Content string `json:"content"` } type SessionWorkspaceReadFileParams struct { // Relative path within the workspace files directory - Path string `json:"path"` + Path string `json:"path"` } type SessionWorkspaceCreateFileResult struct { @@ -203,73 +203,73 @@ type SessionWorkspaceCreateFileResult struct { type SessionWorkspaceCreateFileParams struct { // File content to write as a UTF-8 string - Content string `json:"content"` + Content string `json:"content"` // Relative path within the workspace files directory - Path string `json:"path"` + Path string `json:"path"` } // Experimental: SessionFleetStartResult is part of an experimental API and may change or be removed. type SessionFleetStartResult struct { // Whether fleet mode was successfully activated - Started bool `json:"started"` + Started bool `json:"started"` } // Experimental: SessionFleetStartParams is part of an experimental API and may change or be removed. type SessionFleetStartParams struct { // Optional user prompt to combine with fleet instructions - Prompt *string `json:"prompt,omitempty"` + Prompt *string `json:"prompt,omitempty"` } // Experimental: SessionAgentListResult is part of an experimental API and may change or be removed. type SessionAgentListResult struct { // Available custom agents - Agents []AgentElement `json:"agents"` + Agents []AgentElement `json:"agents"` } type AgentElement struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } // Experimental: SessionAgentGetCurrentResult is part of an experimental API and may change or be removed. type SessionAgentGetCurrentResult struct { // Currently selected custom agent, or null if using the default agent - Agent *SessionAgentGetCurrentResultAgent `json:"agent"` + Agent *SessionAgentGetCurrentResultAgent `json:"agent"` } type SessionAgentGetCurrentResultAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } // Experimental: SessionAgentSelectResult is part of an experimental API and may change or be removed. type SessionAgentSelectResult struct { // The newly selected custom agent - Agent SessionAgentSelectResultAgent `json:"agent"` + Agent SessionAgentSelectResultAgent `json:"agent"` } // The newly selected custom agent type SessionAgentSelectResultAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } // Experimental: SessionAgentSelectParams is part of an experimental API and may change or be removed. type SessionAgentSelectParams struct { // Name of the custom agent to select - Name string `json:"name"` + Name string `json:"name"` } // Experimental: SessionAgentDeselectResult is part of an experimental API and may change or be removed. @@ -279,88 +279,88 @@ type SessionAgentDeselectResult struct { // Experimental: SessionCompactionCompactResult is part of an experimental API and may change or be removed. type SessionCompactionCompactResult struct { // Number of messages removed during compaction - MessagesRemoved float64 `json:"messagesRemoved"` + MessagesRemoved float64 `json:"messagesRemoved"` // Whether compaction completed successfully - Success bool `json:"success"` + Success bool `json:"success"` // Number of tokens freed by compaction - TokensRemoved float64 `json:"tokensRemoved"` + TokensRemoved float64 `json:"tokensRemoved"` } type SessionToolsHandlePendingToolCallResult struct { // Whether the tool call result was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } type SessionToolsHandlePendingToolCallParams struct { - Error *string `json:"error,omitempty"` - RequestID string `json:"requestId"` - Result *ResultUnion `json:"result"` + Error *string `json:"error,omitempty"` + RequestID string `json:"requestId"` + Result *ResultUnion `json:"result"` } type ResultResult struct { - Error *string `json:"error,omitempty"` - ResultType *string `json:"resultType,omitempty"` - TextResultForLlm string `json:"textResultForLlm"` - ToolTelemetry map[string]interface{} `json:"toolTelemetry,omitempty"` + Error *string `json:"error,omitempty"` + ResultType *string `json:"resultType,omitempty"` + TextResultForLlm string `json:"textResultForLlm"` + ToolTelemetry map[string]interface{} `json:"toolTelemetry,omitempty"` } type SessionPermissionsHandlePendingPermissionRequestResult struct { // Whether the permission request was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } type SessionPermissionsHandlePendingPermissionRequestParams struct { - RequestID string `json:"requestId"` - Result SessionPermissionsHandlePendingPermissionRequestParamsResult `json:"result"` + RequestID string `json:"requestId"` + Result SessionPermissionsHandlePendingPermissionRequestParamsResult `json:"result"` } type SessionPermissionsHandlePendingPermissionRequestParamsResult struct { - Kind Kind `json:"kind"` - Rules []interface{} `json:"rules,omitempty"` - Feedback *string `json:"feedback,omitempty"` - Message *string `json:"message,omitempty"` - Path *string `json:"path,omitempty"` + Kind Kind `json:"kind"` + Rules []interface{} `json:"rules,omitempty"` + Feedback *string `json:"feedback,omitempty"` + Message *string `json:"message,omitempty"` + Path *string `json:"path,omitempty"` } type SessionLogResult struct { // The unique identifier of the emitted session event - EventID string `json:"eventId"` + EventID string `json:"eventId"` } type SessionLogParams struct { // When true, the message is transient and not persisted to the session event log on disk - Ephemeral *bool `json:"ephemeral,omitempty"` + Ephemeral *bool `json:"ephemeral,omitempty"` // Log severity level. Determines how the message is displayed in the timeline. Defaults to // "info". - Level *Level `json:"level,omitempty"` + Level *Level `json:"level,omitempty"` // Human-readable message - Message string `json:"message"` + Message string `json:"message"` } type SessionShellExecResult struct { // Unique identifier for tracking streamed output - ProcessID string `json:"processId"` + ProcessID string `json:"processId"` } type SessionShellExecParams struct { // Shell command to execute - Command string `json:"command"` + Command string `json:"command"` // Working directory (defaults to session working directory) - Cwd *string `json:"cwd,omitempty"` + Cwd *string `json:"cwd,omitempty"` // Timeout in milliseconds (default: 30000) - Timeout *float64 `json:"timeout,omitempty"` + Timeout *float64 `json:"timeout,omitempty"` } type SessionShellKillResult struct { // Whether the signal was sent successfully - Killed bool `json:"killed"` + Killed bool `json:"killed"` } type SessionShellKillParams struct { // Process identifier returned by shell.exec - ProcessID string `json:"processId"` + ProcessID string `json:"processId"` // Signal to send (default: SIGTERM) - Signal *Signal `json:"signal,omitempty"` + Signal *Signal `json:"signal,omitempty"` } // The current agent mode. @@ -371,18 +371,18 @@ type SessionShellKillParams struct { type Mode string const ( - Autopilot Mode = "autopilot" + Autopilot Mode = "autopilot" Interactive Mode = "interactive" - Plan Mode = "plan" + Plan Mode = "plan" ) type Kind string const ( - Approved Kind = "approved" - DeniedByContentExclusionPolicy Kind = "denied-by-content-exclusion-policy" - DeniedByRules Kind = "denied-by-rules" - DeniedInteractivelyByUser Kind = "denied-interactively-by-user" + Approved Kind = "approved" + DeniedByContentExclusionPolicy Kind = "denied-by-content-exclusion-policy" + DeniedByRules Kind = "denied-by-rules" + DeniedInteractivelyByUser Kind = "denied-interactively-by-user" DeniedNoApprovalRuleAndCouldNotRequestFromUser Kind = "denied-no-approval-rule-and-could-not-request-from-user" ) @@ -391,8 +391,8 @@ const ( type Level string const ( - Error Level = "error" - Info Level = "info" + Error Level = "error" + Info Level = "info" Warning Level = "warning" ) @@ -400,17 +400,16 @@ const ( type Signal string const ( - Sigint Signal = "SIGINT" + Sigint Signal = "SIGINT" Sigkill Signal = "SIGKILL" Sigterm Signal = "SIGTERM" ) type ResultUnion struct { ResultResult *ResultResult - String *string + String *string } - type ServerModelsRpcApi struct { client *jsonrpc2.Client } diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index e92d741e5..db408f4b7 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -182,12 +182,19 @@ async function generateRpc(schemaPath?: string): Promise { let qtCode = qtResult.lines.filter((l) => !l.startsWith("package ")).join("\n"); // Strip trailing whitespace from quicktype output (gofmt requirement) qtCode = qtCode.replace(/[ \t]+$/gm, ""); + // Collapse quicktype's column-aligned struct fields to single-space separation. + // gofmt doesn't column-align fields that have comments between them, so the wide + // padding quicktype emits causes a gofmt diff. Apply to all capitalized field lines + // (only in quicktype output — hand-written code is emitted separately). + qtCode = qtCode.replace(/^(\t[A-Z].*)/gm, (_, line) => line.replace(/ +/g, " ")); for (const typeName of experimentalTypeNames) { qtCode = qtCode.replace( new RegExp(`^(type ${typeName} struct)`, "m"), `// Experimental: ${typeName} is part of an experimental API and may change or be removed.\n$1` ); } + // Remove trailing blank lines from quicktype output before appending + qtCode = qtCode.replace(/\n+$/, ""); lines.push(qtCode); lines.push(``); From 67fe227fd5764337d544c5e8b925571faa06a1fa Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 17 Mar 2026 12:44:28 -0400 Subject: [PATCH 7/7] fix: regenerate Go output with gofmt for proper formatting Removed manual quicktype column-alignment workaround and regenerated with Go installed locally so formatGoFile() runs gofmt properly. This ensures the committed output exactly matches what CI produces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/generated_rpc.go | 48 ++++++++++++++++++++--------------------- scripts/codegen/go.ts | 5 ----- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 9a05f5711..401f38305 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -292,16 +292,16 @@ type SessionToolsHandlePendingToolCallResult struct { } type SessionToolsHandlePendingToolCallParams struct { - Error *string `json:"error,omitempty"` - RequestID string `json:"requestId"` - Result *ResultUnion `json:"result"` + Error *string `json:"error,omitempty"` + RequestID string `json:"requestId"` + Result *ResultUnion `json:"result"` } type ResultResult struct { - Error *string `json:"error,omitempty"` - ResultType *string `json:"resultType,omitempty"` - TextResultForLlm string `json:"textResultForLlm"` - ToolTelemetry map[string]interface{} `json:"toolTelemetry,omitempty"` + Error *string `json:"error,omitempty"` + ResultType *string `json:"resultType,omitempty"` + TextResultForLlm string `json:"textResultForLlm"` + ToolTelemetry map[string]interface{} `json:"toolTelemetry,omitempty"` } type SessionPermissionsHandlePendingPermissionRequestResult struct { @@ -310,16 +310,16 @@ type SessionPermissionsHandlePendingPermissionRequestResult struct { } type SessionPermissionsHandlePendingPermissionRequestParams struct { - RequestID string `json:"requestId"` - Result SessionPermissionsHandlePendingPermissionRequestParamsResult `json:"result"` + RequestID string `json:"requestId"` + Result SessionPermissionsHandlePendingPermissionRequestParamsResult `json:"result"` } type SessionPermissionsHandlePendingPermissionRequestParamsResult struct { - Kind Kind `json:"kind"` - Rules []interface{} `json:"rules,omitempty"` - Feedback *string `json:"feedback,omitempty"` - Message *string `json:"message,omitempty"` - Path *string `json:"path,omitempty"` + Kind Kind `json:"kind"` + Rules []interface{} `json:"rules,omitempty"` + Feedback *string `json:"feedback,omitempty"` + Message *string `json:"message,omitempty"` + Path *string `json:"path,omitempty"` } type SessionLogResult struct { @@ -371,18 +371,18 @@ type SessionShellKillParams struct { type Mode string const ( - Autopilot Mode = "autopilot" + Autopilot Mode = "autopilot" Interactive Mode = "interactive" - Plan Mode = "plan" + Plan Mode = "plan" ) type Kind string const ( - Approved Kind = "approved" - DeniedByContentExclusionPolicy Kind = "denied-by-content-exclusion-policy" - DeniedByRules Kind = "denied-by-rules" - DeniedInteractivelyByUser Kind = "denied-interactively-by-user" + Approved Kind = "approved" + DeniedByContentExclusionPolicy Kind = "denied-by-content-exclusion-policy" + DeniedByRules Kind = "denied-by-rules" + DeniedInteractivelyByUser Kind = "denied-interactively-by-user" DeniedNoApprovalRuleAndCouldNotRequestFromUser Kind = "denied-no-approval-rule-and-could-not-request-from-user" ) @@ -391,8 +391,8 @@ const ( type Level string const ( - Error Level = "error" - Info Level = "info" + Error Level = "error" + Info Level = "info" Warning Level = "warning" ) @@ -400,14 +400,14 @@ const ( type Signal string const ( - Sigint Signal = "SIGINT" + Sigint Signal = "SIGINT" Sigkill Signal = "SIGKILL" Sigterm Signal = "SIGTERM" ) type ResultUnion struct { ResultResult *ResultResult - String *string + String *string } type ServerModelsRpcApi struct { diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index db408f4b7..c467761d0 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -182,11 +182,6 @@ async function generateRpc(schemaPath?: string): Promise { let qtCode = qtResult.lines.filter((l) => !l.startsWith("package ")).join("\n"); // Strip trailing whitespace from quicktype output (gofmt requirement) qtCode = qtCode.replace(/[ \t]+$/gm, ""); - // Collapse quicktype's column-aligned struct fields to single-space separation. - // gofmt doesn't column-align fields that have comments between them, so the wide - // padding quicktype emits causes a gofmt diff. Apply to all capitalized field lines - // (only in quicktype output — hand-written code is emitted separately). - qtCode = qtCode.replace(/^(\t[A-Z].*)/gm, (_, line) => line.replace(/ +/g, " ")); for (const typeName of experimentalTypeNames) { qtCode = qtCode.replace( new RegExp(`^(type ${typeName} struct)`, "m"),