(
+ SessionEvent.FromJson(mixedJson));
+ Assert.Equal(ManagedSettingsResolvedSource.Mixed, mixedEvent.Data.Source);
+ Assert.Null(mixedEvent.Data.ClientManaged);
+ using var mixedDocument = JsonDocument.Parse(mixedEvent.ToJson());
+ Assert.False(mixedDocument.RootElement.GetProperty("data").TryGetProperty("clientManaged", out _));
+ }
}
diff --git a/go/client.go b/go/client.go
index d2c43c26bd..856e933ea2 100644
--- a/go/client.go
+++ b/go/client.go
@@ -750,6 +750,10 @@ func extractTransformCallbacks(config *SystemMessageConfig) (*SystemMessageConfi
return wireConfig, callbacks
}
+func hasManagedSettings(enableManagedSettings *bool, managedSettings *ManagedSettings) bool {
+ return (enableManagedSettings != nil && *enableManagedSettings) || managedSettings != nil
+}
+
func (c *Client) CreateSession(ctx context.Context, config *SessionConfig) (*Session, error) {
if config == nil {
config = &SessionConfig{}
@@ -833,6 +837,7 @@ func (c *Client) CreateSession(ctx context.Context, config *SessionConfig) (*Ses
req.ExtensionInfo = config.ExtensionInfo
req.ExpAssignments = config.ExpAssignments
req.EnableManagedSettings = config.EnableManagedSettings
+ req.ManagedSettings = config.ManagedSettings
if len(config.Commands) > 0 {
cmds := make([]wireCommand, 0, len(config.Commands))
@@ -917,7 +922,7 @@ func (c *Client) CreateSession(ctx context.Context, config *SessionConfig) (*Ses
sessionID,
c.client,
"",
- config.EnableManagedSettings != nil && *config.EnableManagedSettings,
+ hasManagedSettings(config.EnableManagedSettings, config.ManagedSettings),
)
s.registerTools(config.Tools)
@@ -1215,6 +1220,7 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
req.ExtensionInfo = config.ExtensionInfo
req.ExpAssignments = config.ExpAssignments
req.EnableManagedSettings = config.EnableManagedSettings
+ req.ManagedSettings = config.ManagedSettings
if config.OnPermissionRequest != nil {
req.RequestPermission = Bool(true)
}
@@ -1250,7 +1256,7 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
sessionID,
c.client,
"",
- config.EnableManagedSettings != nil && *config.EnableManagedSettings,
+ hasManagedSettings(config.EnableManagedSettings, config.ManagedSettings),
)
session.registerTools(config.Tools)
diff --git a/go/client_test.go b/go/client_test.go
index b5274cfda0..3322d77412 100644
--- a/go/client_test.go
+++ b/go/client_test.go
@@ -3563,3 +3563,162 @@ func TestIsTerminal(t *testing.T) {
}
})
}
+
+func TestSessionRequests_ManagedSettings(t *testing.T) {
+ settings := &ManagedSettings{
+ Permissions: &ManagedSettingsPermissions{
+ DisableBypassPermissionsMode: DisableBypassPermissionsModeDisable,
+ Deny: []string{"Shell(git push)"},
+ Ask: []string{"Domain(publish.example)"},
+ Allow: []string{"Read(**)"},
+ },
+ }
+
+ expectedPermissions := map[string]any{
+ "disableBypassPermissionsMode": "disable",
+ "deny": []any{"Shell(git push)"},
+ "ask": []any{"Domain(publish.example)"},
+ "allow": []any{"Read(**)"},
+ }
+
+ t.Run("direct injection enables managed safeguards", func(t *testing.T) {
+ if !hasManagedSettings(nil, settings) {
+ t.Fatal("expected injected managed settings to enable managed safeguards")
+ }
+ if hasManagedSettings(nil, nil) {
+ t.Fatal("expected an ordinary session to remain unmanaged")
+ }
+ })
+
+ t.Run("includes managedSettings on create when set", func(t *testing.T) {
+ req := createSessionRequest{EnableManagedSettings: Bool(true), ManagedSettings: settings}
+ data, err := json.Marshal(req)
+ if err != nil {
+ t.Fatalf("Failed to marshal: %v", err)
+ }
+ var m map[string]any
+ if err := json.Unmarshal(data, &m); err != nil {
+ t.Fatalf("Failed to unmarshal: %v", err)
+ }
+ if m["enableManagedSettings"] != true {
+ t.Errorf("Expected enableManagedSettings true, got %v", m["enableManagedSettings"])
+ }
+ ms, ok := m["managedSettings"].(map[string]any)
+ if !ok {
+ t.Fatalf("Expected managedSettings object, got %v", m["managedSettings"])
+ }
+ perms, ok := ms["permissions"].(map[string]any)
+ if !ok {
+ t.Fatalf("Expected permissions object, got %v", ms["permissions"])
+ }
+ if !reflect.DeepEqual(perms, expectedPermissions) {
+ t.Errorf("permissions mismatch:\n got: %#v\nwant: %#v", perms, expectedPermissions)
+ }
+ })
+
+ t.Run("includes managedSettings on resume when set", func(t *testing.T) {
+ req := resumeSessionRequest{SessionID: "s1", ManagedSettings: settings}
+ data, err := json.Marshal(req)
+ if err != nil {
+ t.Fatalf("Failed to marshal: %v", err)
+ }
+ var m map[string]any
+ if err := json.Unmarshal(data, &m); err != nil {
+ t.Fatalf("Failed to unmarshal: %v", err)
+ }
+ if _, ok := m["managedSettings"].(map[string]any); !ok {
+ t.Fatalf("Expected managedSettings object, got %v", m["managedSettings"])
+ }
+ })
+
+ t.Run("omits managedSettings when nil", func(t *testing.T) {
+ req := createSessionRequest{}
+ data, _ := json.Marshal(req)
+ var m map[string]any
+ json.Unmarshal(data, &m)
+ if _, ok := m["managedSettings"]; ok {
+ t.Error("Expected managedSettings to be omitted when nil")
+ }
+ })
+
+ t.Run("preserves explicit empty permission arrays", func(t *testing.T) {
+ // A non-nil empty allow list is restrictive: it admits no operations.
+ // Preserve field presence while still omitting nil slices.
+ req := createSessionRequest{ManagedSettings: &ManagedSettings{
+ Permissions: &ManagedSettingsPermissions{
+ DisableBypassPermissionsMode: DisableBypassPermissionsModeDisable,
+ Deny: []string{},
+ Ask: []string{},
+ Allow: []string{},
+ },
+ }}
+ data, err := json.Marshal(req)
+ if err != nil {
+ t.Fatalf("Failed to marshal: %v", err)
+ }
+ var m map[string]any
+ json.Unmarshal(data, &m)
+ perms := m["managedSettings"].(map[string]any)["permissions"].(map[string]any)
+ if perms["disableBypassPermissionsMode"] != "disable" {
+ t.Errorf("Expected disableBypassPermissionsMode preserved, got %v", perms["disableBypassPermissionsMode"])
+ }
+ for _, key := range []string{"deny", "ask", "allow"} {
+ if value, ok := perms[key].([]any); !ok || len(value) != 0 {
+ t.Errorf("Expected %s to be an explicit empty array, got %v", key, perms[key])
+ }
+ }
+ })
+
+ t.Run("distinguishes explicit empty allow from an absent allow", func(t *testing.T) {
+ // Security-critical: a present empty allow list admits nothing, while an
+ // absent allow list imposes no allow restriction. The wire output must
+ // tell these apart per-field, so an explicit empty slice serializes as
+ // `[]` while a nil slice is omitted entirely.
+ req := createSessionRequest{ManagedSettings: &ManagedSettings{
+ Permissions: &ManagedSettingsPermissions{
+ Allow: []string{}, // present but empty: admit nothing
+ // Deny and Ask left nil: no such restriction supplied.
+ },
+ }}
+ data, err := json.Marshal(req)
+ if err != nil {
+ t.Fatalf("Failed to marshal: %v", err)
+ }
+ var m map[string]any
+ json.Unmarshal(data, &m)
+ perms := m["managedSettings"].(map[string]any)["permissions"].(map[string]any)
+
+ allow, ok := perms["allow"].([]any)
+ if !ok || len(allow) != 0 {
+ t.Errorf("Expected allow to be an explicit empty array, got %v", perms["allow"])
+ }
+ if _, present := perms["deny"]; present {
+ t.Errorf("Expected deny to be omitted when nil, got %v", perms["deny"])
+ }
+ if _, present := perms["ask"]; present {
+ t.Errorf("Expected ask to be omitted when nil, got %v", perms["ask"])
+ }
+ })
+
+ t.Run("distinguishes explicit empty arrays on resume", func(t *testing.T) {
+ req := resumeSessionRequest{SessionID: "s1", ManagedSettings: &ManagedSettings{
+ Permissions: &ManagedSettingsPermissions{
+ Deny: []string{},
+ Ask: []string{},
+ Allow: []string{},
+ },
+ }}
+ data, err := json.Marshal(req)
+ if err != nil {
+ t.Fatalf("Failed to marshal: %v", err)
+ }
+ var m map[string]any
+ json.Unmarshal(data, &m)
+ perms := m["managedSettings"].(map[string]any)["permissions"].(map[string]any)
+ for _, key := range []string{"deny", "ask", "allow"} {
+ if value, ok := perms[key].([]any); !ok || len(value) != 0 {
+ t.Errorf("Expected %s to be an explicit empty array on resume, got %v", key, perms[key])
+ }
+ }
+ })
+}
diff --git a/go/session_event_serialization_test.go b/go/session_event_serialization_test.go
index bd47fdfbe2..ee9258b225 100644
--- a/go/session_event_serialization_test.go
+++ b/go/session_event_serialization_test.go
@@ -189,3 +189,69 @@ func TestRawSessionEventDataWithNilRawMarshalsAsNull(t *testing.T) {
t.Fatalf("expected missing raw data to marshal as null, got %v", serialized["data"])
}
}
+
+func TestManagedSettingsResolvedProvenanceRoundTrips(t *testing.T) {
+ sources := []ManagedSettingsResolvedSource{
+ ManagedSettingsResolvedSourceServer,
+ ManagedSettingsResolvedSourceDevice,
+ ManagedSettingsResolvedSourceClient,
+ ManagedSettingsResolvedSourceMixed,
+ ManagedSettingsResolvedSourceNone,
+ }
+ expectedSources := []string{"server", "device", "client", "mixed", "none"}
+ for i, source := range sources {
+ if string(source) != expectedSources[i] {
+ t.Fatalf("expected source %q, got %q", expectedSources[i], source)
+ }
+ }
+
+ clientManaged := true
+ resolved := SessionManagedSettingsResolvedData{
+ BypassPermissionsDisabled: true,
+ ClientManaged: &clientManaged,
+ DeviceManaged: false,
+ FailClosed: false,
+ ManagedKeys: []string{"permissions"},
+ ServerManaged: false,
+ Source: ManagedSettingsResolvedSourceClient,
+ }
+ data, err := json.Marshal(resolved)
+ if err != nil {
+ t.Fatalf("failed to marshal managed settings resolution: %v", err)
+ }
+
+ var serialized map[string]any
+ if err := json.Unmarshal(data, &serialized); err != nil {
+ t.Fatalf("failed to inspect managed settings resolution: %v", err)
+ }
+ if serialized["source"] != "client" || serialized["clientManaged"] != true {
+ t.Fatalf("expected client provenance, got %v", serialized)
+ }
+
+ var roundTripped SessionManagedSettingsResolvedData
+ if err := json.Unmarshal(data, &roundTripped); err != nil {
+ t.Fatalf("failed to round-trip managed settings resolution: %v", err)
+ }
+ if roundTripped.Source != ManagedSettingsResolvedSourceClient ||
+ roundTripped.ClientManaged == nil ||
+ !*roundTripped.ClientManaged {
+ t.Fatalf("expected client provenance to round-trip, got %#v", roundTripped)
+ }
+
+ resolved.Source = ManagedSettingsResolvedSourceMixed
+ resolved.ClientManaged = nil
+ data, err = json.Marshal(resolved)
+ if err != nil {
+ t.Fatalf("failed to marshal mixed managed settings resolution: %v", err)
+ }
+ serialized = nil
+ if err := json.Unmarshal(data, &serialized); err != nil {
+ t.Fatalf("failed to inspect mixed managed settings resolution: %v", err)
+ }
+ if serialized["source"] != "mixed" {
+ t.Fatalf("expected mixed provenance, got %v", serialized["source"])
+ }
+ if _, ok := serialized["clientManaged"]; ok {
+ t.Fatalf("expected absent clientManaged to be omitted, got %v", serialized)
+ }
+}
diff --git a/go/types.go b/go/types.go
index 6669564bf4..6d6a877d30 100644
--- a/go/types.go
+++ b/go/types.go
@@ -1498,6 +1498,51 @@ type SessionConfig struct {
// be set; if omitted, the runtime is expected to reject session creation
// (fail-closed). Unset behaves exactly as before.
EnableManagedSettings *bool
+ // ManagedSettings supplies host-injected enterprise managed settings for
+ // the session. Unlike EnableManagedSettings (which asks the runtime to
+ // self-fetch account/org and device policy), this provides the managed
+ // policy directly. The runtime validates it with the same
+ // managed-permission parser it uses for fetched policy and composes it
+ // restrictively with any self-fetched (server) and device-managed (MDM)
+ // layers. It is startup-only and not persisted: re-supply it on resume,
+ // where it replaces the prior injected layer (omitting it clears the
+ // layer). It may be combined with EnableManagedSettings. Requires a runtime
+ // whose RPC schema includes managedSettings.
+ ManagedSettings *ManagedSettings
+}
+
+// ManagedSettings is host-injected enterprise managed settings for a session.
+// The first supported contract is permissions-only; unknown sibling keys are
+// rejected by the runtime. Serialized on the wire as managedSettings.
+type ManagedSettings struct {
+ // Permissions is the managed permission policy for the session.
+ Permissions *ManagedSettingsPermissions `json:"permissions,omitempty"`
+}
+
+// DisableBypassPermissionsMode is the managed bypass-permissions policy.
+type DisableBypassPermissionsMode = rpc.DisableBypassPermissionsMode
+
+const (
+ // DisableBypassPermissionsModeDisable turns off bypass-permissions mode.
+ DisableBypassPermissionsModeDisable = rpc.DisableBypassPermissionsModeDisable
+)
+
+// ManagedSettingsPermissions is the permissions-only managed policy injected
+// via ManagedSettings. Rule strings use the same vocabulary the runtime
+// accepts for fetched managed policy (e.g. "Read(**)", "Shell(git push *)");
+// malformed rules are rejected by the runtime at session creation.
+type ManagedSettingsPermissions struct {
+ // DisableBypassPermissionsMode, when set to "disable", turns off
+ // bypass-permissions ("yolo") mode for the session. Deny-wins: no other
+ // layer can re-enable it.
+ DisableBypassPermissionsMode DisableBypassPermissionsMode `json:"disableBypassPermissionsMode,omitempty"`
+ // Deny lists operations that must always be denied. Unioned across layers.
+ Deny []string `json:"deny,omitzero"`
+ // Ask lists operations that must prompt for approval. Unioned across layers.
+ Ask []string `json:"ask,omitzero"`
+ // Allow lists operations permitted without prompting. Every declared allow
+ // list across managed layers must admit an operation for it to be allowed.
+ Allow []string `json:"allow,omitzero"`
}
// ToolDefer controls whether a tool may be deferred (loaded lazily via tool
@@ -1961,6 +2006,11 @@ type ResumeSessionConfig struct {
// SessionConfig.EnableManagedSettings. Re-supply on resume so the runtime
// re-applies the managed-settings self-fetch after a CLI process restart.
EnableManagedSettings *bool
+ // ManagedSettings re-injects host-provided managed settings on resume. See
+ // SessionConfig.ManagedSettings. It must be re-supplied on resume: it
+ // replaces the prior injected layer, and omitting it clears that layer so
+ // warm and cold resume behave identically.
+ ManagedSettings *ManagedSettings
}
// ProviderTokenArgs carries the context passed to a [BearerTokenProvider] callback
@@ -2423,6 +2473,7 @@ type createSessionRequest struct {
CanvasProvider *CanvasProviderIdentity `json:"canvasProvider,omitempty"`
ExpAssignments *CopilotExpAssignmentResponse `json:"expAssignments,omitempty"`
EnableManagedSettings *bool `json:"enableManagedSettings,omitempty"`
+ ManagedSettings *ManagedSettings `json:"managedSettings,omitempty"`
Traceparent string `json:"traceparent,omitempty"`
Tracestate string `json:"tracestate,omitempty"`
}
@@ -2519,6 +2570,7 @@ type resumeSessionRequest struct {
CanvasProvider *CanvasProviderIdentity `json:"canvasProvider,omitempty"`
ExpAssignments *CopilotExpAssignmentResponse `json:"expAssignments,omitempty"`
EnableManagedSettings *bool `json:"enableManagedSettings,omitempty"`
+ ManagedSettings *ManagedSettings `json:"managedSettings,omitempty"`
Traceparent string `json:"traceparent,omitempty"`
Tracestate string `json:"tracestate,omitempty"`
}
diff --git a/java/src/main/java/com/github/copilot/SessionRequestBuilder.java b/java/src/main/java/com/github/copilot/SessionRequestBuilder.java
index add4a79b66..23e4f77b41 100644
--- a/java/src/main/java/com/github/copilot/SessionRequestBuilder.java
+++ b/java/src/main/java/com/github/copilot/SessionRequestBuilder.java
@@ -201,6 +201,7 @@ static CreateSessionRequest buildCreateRequest(SessionConfig config, String sess
request.setCloud(config.getCloud());
request.setExpAssignments(config.getExpAssignments());
config.getEnableManagedSettings().ifPresent(request::setEnableManagedSettings);
+ request.setManagedSettings(config.getManagedSettings());
return request;
}
@@ -337,6 +338,7 @@ static ResumeSessionRequest buildResumeRequest(String sessionId, ResumeSessionCo
request.setRemoteSession(config.getRemoteSession());
request.setExpAssignments(config.getExpAssignments());
config.getEnableManagedSettings().ifPresent(request::setEnableManagedSettings);
+ request.setManagedSettings(config.getManagedSettings());
return request;
}
@@ -374,7 +376,8 @@ static void configureSession(CopilotSession session, SessionConfig config) {
if (config.getOnPermissionRequest() != null) {
session.registerPermissionHandler(config.getOnPermissionRequest());
}
- session.setManagedSettingsEnabled(config.getEnableManagedSettings().orElse(false));
+ session.setManagedSettingsEnabled(
+ config.getEnableManagedSettings().orElse(false) || config.getManagedSettings() != null);
if (config.getOnMcpAuthRequest() != null) {
session.registerMcpAuthHandler(config.getOnMcpAuthRequest());
}
@@ -425,7 +428,8 @@ static void configureSession(CopilotSession session, ResumeSessionConfig config)
if (config.getOnPermissionRequest() != null) {
session.registerPermissionHandler(config.getOnPermissionRequest());
}
- session.setManagedSettingsEnabled(config.getEnableManagedSettings().orElse(false));
+ session.setManagedSettingsEnabled(
+ config.getEnableManagedSettings().orElse(false) || config.getManagedSettings() != null);
if (config.getOnMcpAuthRequest() != null) {
session.registerMcpAuthHandler(config.getOnMcpAuthRequest());
}
diff --git a/java/src/main/java/com/github/copilot/rpc/CreateSessionRequest.java b/java/src/main/java/com/github/copilot/rpc/CreateSessionRequest.java
index 46f59a28cd..4c74e38ac2 100644
--- a/java/src/main/java/com/github/copilot/rpc/CreateSessionRequest.java
+++ b/java/src/main/java/com/github/copilot/rpc/CreateSessionRequest.java
@@ -234,6 +234,10 @@ public final class CreateSessionRequest {
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean enableManagedSettings;
+ @JsonProperty("managedSettings")
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private ManagedSettings managedSettings;
+
/** Gets the model name. @return the model */
public String getModel() {
return model;
@@ -1095,4 +1099,17 @@ public void setEnableManagedSettings(boolean enableManagedSettings) {
public void clearEnableManagedSettings() {
this.enableManagedSettings = null;
}
+
+ /** @return host-injected managed settings, or {@code null} when unset */
+ public ManagedSettings getManagedSettings() {
+ return managedSettings;
+ }
+
+ /**
+ * @param managedSettings
+ * host-injected managed settings
+ */
+ public void setManagedSettings(ManagedSettings managedSettings) {
+ this.managedSettings = managedSettings;
+ }
}
diff --git a/java/src/main/java/com/github/copilot/rpc/ManagedSettings.java b/java/src/main/java/com/github/copilot/rpc/ManagedSettings.java
new file mode 100644
index 0000000000..39e8fcf55a
--- /dev/null
+++ b/java/src/main/java/com/github/copilot/rpc/ManagedSettings.java
@@ -0,0 +1,34 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *--------------------------------------------------------------------------------------------*/
+package com.github.copilot.rpc;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Managed settings an SDK host may inject at session create or resume.
+ *
+ *
+ * The initial public contract is permissions-only.
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public final class ManagedSettings {
+ @JsonProperty("permissions")
+ private ManagedSettingsPermissions permissions;
+
+ /** @return the managed permission policy, or {@code null} when unset */
+ public ManagedSettingsPermissions getPermissions() {
+ return permissions;
+ }
+
+ /**
+ * @param permissions
+ * managed permission policy
+ * @return this settings object
+ */
+ public ManagedSettings setPermissions(ManagedSettingsPermissions permissions) {
+ this.permissions = permissions;
+ return this;
+ }
+}
diff --git a/java/src/main/java/com/github/copilot/rpc/ManagedSettingsPermissions.java b/java/src/main/java/com/github/copilot/rpc/ManagedSettingsPermissions.java
new file mode 100644
index 0000000000..0923cea54a
--- /dev/null
+++ b/java/src/main/java/com/github/copilot/rpc/ManagedSettingsPermissions.java
@@ -0,0 +1,90 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *--------------------------------------------------------------------------------------------*/
+package com.github.copilot.rpc;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.github.copilot.generated.rpc.DisableBypassPermissionsMode;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enterprise permission policy injected by an SDK host at session startup.
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public final class ManagedSettingsPermissions {
+ @JsonProperty("disableBypassPermissionsMode")
+ private DisableBypassPermissionsMode disableBypassPermissionsMode;
+
+ @JsonProperty("deny")
+ private List deny;
+
+ @JsonProperty("ask")
+ private List ask;
+
+ @JsonProperty("allow")
+ private List allow;
+
+ /** @return the bypass-permissions policy, or {@code null} when unset */
+ public DisableBypassPermissionsMode getDisableBypassPermissionsMode() {
+ return disableBypassPermissionsMode;
+ }
+
+ /**
+ * Disables bypass/allow-all permission modes.
+ *
+ * @param value
+ * bypass-permissions policy
+ * @return this policy
+ */
+ public ManagedSettingsPermissions setDisableBypassPermissionsMode(DisableBypassPermissionsMode value) {
+ this.disableBypassPermissionsMode = value;
+ return this;
+ }
+
+ /** @return rules that deny matching operations, or {@code null} when unset */
+ public List getDeny() {
+ return deny;
+ }
+
+ /**
+ * @param rules
+ * deny rules
+ * @return this policy
+ */
+ public ManagedSettingsPermissions setDeny(List rules) {
+ this.deny = rules == null ? null : new ArrayList<>(rules);
+ return this;
+ }
+
+ /** @return rules that require approval, or {@code null} when unset */
+ public List getAsk() {
+ return ask;
+ }
+
+ /**
+ * @param rules
+ * ask rules
+ * @return this policy
+ */
+ public ManagedSettingsPermissions setAsk(List rules) {
+ this.ask = rules == null ? null : new ArrayList<>(rules);
+ return this;
+ }
+
+ /** @return rules that allow matching operations, or {@code null} when unset */
+ public List getAllow() {
+ return allow;
+ }
+
+ /**
+ * @param rules
+ * allow rules
+ * @return this policy
+ */
+ public ManagedSettingsPermissions setAllow(List rules) {
+ this.allow = rules == null ? null : new ArrayList<>(rules);
+ return this;
+ }
+}
diff --git a/java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java b/java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java
index 1e32ec847d..10641157b6 100644
--- a/java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java
+++ b/java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java
@@ -107,6 +107,7 @@ public class ResumeSessionConfig {
private String remoteSession;
private CopilotExpAssignmentResponse expAssignments;
private Boolean enableManagedSettings;
+ private ManagedSettings managedSettings;
/**
* Gets the AI model to use.
@@ -1910,6 +1911,24 @@ public ResumeSessionConfig setEnableManagedSettings(boolean enableManagedSetting
return this;
}
+ /** @return host-injected managed settings, or {@code null} when unset */
+ public ManagedSettings getManagedSettings() {
+ return managedSettings;
+ }
+
+ /**
+ * Supplies permissions-only managed settings for this resume. The value
+ * replaces the prior injected layer and is not persisted.
+ *
+ * @param managedSettings
+ * the host-injected managed settings
+ * @return this config for method chaining
+ */
+ public ResumeSessionConfig setManagedSettings(ManagedSettings managedSettings) {
+ this.managedSettings = managedSettings;
+ return this;
+ }
+
/**
* Creates a shallow clone of this {@code ResumeSessionConfig} instance.
*
@@ -1992,6 +2011,7 @@ public ResumeSessionConfig clone() {
copy.remoteSession = this.remoteSession;
copy.expAssignments = this.expAssignments;
copy.enableManagedSettings = this.enableManagedSettings;
+ copy.managedSettings = this.managedSettings;
return copy;
}
}
diff --git a/java/src/main/java/com/github/copilot/rpc/ResumeSessionRequest.java b/java/src/main/java/com/github/copilot/rpc/ResumeSessionRequest.java
index 3fe17b182a..8c9d03ede2 100644
--- a/java/src/main/java/com/github/copilot/rpc/ResumeSessionRequest.java
+++ b/java/src/main/java/com/github/copilot/rpc/ResumeSessionRequest.java
@@ -236,6 +236,10 @@ public final class ResumeSessionRequest {
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean enableManagedSettings;
+ @JsonProperty("managedSettings")
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private ManagedSettings managedSettings;
+
/** Gets the session ID. @return the session ID */
public String getSessionId() {
return sessionId;
@@ -1110,4 +1114,17 @@ public void setEnableManagedSettings(boolean enableManagedSettings) {
public void clearEnableManagedSettings() {
this.enableManagedSettings = null;
}
+
+ /** @return host-injected managed settings, or {@code null} when unset */
+ public ManagedSettings getManagedSettings() {
+ return managedSettings;
+ }
+
+ /**
+ * @param managedSettings
+ * host-injected managed settings
+ */
+ public void setManagedSettings(ManagedSettings managedSettings) {
+ this.managedSettings = managedSettings;
+ }
}
diff --git a/java/src/main/java/com/github/copilot/rpc/SessionConfig.java b/java/src/main/java/com/github/copilot/rpc/SessionConfig.java
index ad62551fd8..3ccda690f0 100644
--- a/java/src/main/java/com/github/copilot/rpc/SessionConfig.java
+++ b/java/src/main/java/com/github/copilot/rpc/SessionConfig.java
@@ -108,6 +108,7 @@ public class SessionConfig {
private CloudSessionOptions cloud;
private CopilotExpAssignmentResponse expAssignments;
private Boolean enableManagedSettings;
+ private ManagedSettings managedSettings;
/**
* Gets the custom session ID.
@@ -2041,6 +2042,29 @@ public SessionConfig setEnableManagedSettings(boolean enableManagedSettings) {
return this;
}
+ /**
+ * Gets host-injected managed settings for this session.
+ *
+ * @return the managed settings, or {@code null} when unset
+ */
+ public ManagedSettings getManagedSettings() {
+ return managedSettings;
+ }
+
+ /**
+ * Supplies permissions-only managed settings at session startup. The runtime
+ * validates and composes this policy restrictively with self-fetched and device
+ * policy. Re-supply it on resume because it is not persisted.
+ *
+ * @param managedSettings
+ * the host-injected managed settings
+ * @return this config instance for method chaining
+ */
+ public SessionConfig setManagedSettings(ManagedSettings managedSettings) {
+ this.managedSettings = managedSettings;
+ return this;
+ }
+
/**
* Creates a shallow clone of this {@code SessionConfig} instance.
*
@@ -2128,6 +2152,7 @@ public SessionConfig clone() {
copy.cloud = this.cloud;
copy.expAssignments = this.expAssignments;
copy.enableManagedSettings = this.enableManagedSettings;
+ copy.managedSettings = this.managedSettings;
return copy;
}
}
diff --git a/java/src/test/java/com/github/copilot/ManagedSettingsTest.java b/java/src/test/java/com/github/copilot/ManagedSettingsTest.java
new file mode 100644
index 0000000000..dbd19f3c97
--- /dev/null
+++ b/java/src/test/java/com/github/copilot/ManagedSettingsTest.java
@@ -0,0 +1,90 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *--------------------------------------------------------------------------------------------*/
+package com.github.copilot;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.copilot.generated.rpc.DisableBypassPermissionsMode;
+import com.github.copilot.rpc.ManagedSettings;
+import com.github.copilot.rpc.ManagedSettingsPermissions;
+import com.github.copilot.rpc.PermissionRequestResult;
+import com.github.copilot.rpc.ResumeSessionConfig;
+import com.github.copilot.rpc.SessionConfig;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.jupiter.api.Test;
+
+class ManagedSettingsTest {
+ @Test
+ void forwardsManagedSettingsOnCreateAndResume() throws Exception {
+ var permissions = new ManagedSettingsPermissions()
+ .setDisableBypassPermissionsMode(DisableBypassPermissionsMode.DISABLE).setDeny(List.of("Shell(rm *)"))
+ .setAsk(List.of("Domain(publish.example)")).setAllow(List.of("Read(**)"));
+ var managedSettings = new ManagedSettings().setPermissions(permissions);
+
+ var create = SessionRequestBuilder.buildCreateRequest(
+ new SessionConfig().setEnableManagedSettings(true).setManagedSettings(managedSettings),
+ "managed-create");
+ var resume = SessionRequestBuilder.buildResumeRequest("managed-resume",
+ new ResumeSessionConfig().setEnableManagedSettings(true).setManagedSettings(managedSettings));
+
+ assertEquals(managedSettings, create.getManagedSettings());
+ assertEquals(managedSettings, resume.getManagedSettings());
+ var json = new ObjectMapper().writeValueAsString(create);
+ assertTrue(json.contains("\"enableManagedSettings\":true"));
+ assertTrue(json.contains("\"managedSettings\":{\"permissions\""));
+ assertTrue(json.contains("\"disableBypassPermissionsMode\":\"disable\""));
+ }
+
+ @Test
+ void preservesExplicitEmptyPermissionArrays() throws Exception {
+ // Security-critical: a present empty allow list admits nothing, while an
+ // absent (null) list imposes no such restriction. Jackson NON_NULL must
+ // emit an explicit empty array as `[]` and omit null fields, so the two
+ // remain distinguishable on the wire.
+ var permissions = new ManagedSettingsPermissions().setDeny(List.of()).setAsk(List.of()).setAllow(List.of());
+ var managedSettings = new ManagedSettings().setPermissions(permissions);
+ var create = SessionRequestBuilder.buildCreateRequest(new SessionConfig().setManagedSettings(managedSettings),
+ "managed-empty");
+
+ var json = new ObjectMapper().writeValueAsString(create);
+ assertTrue(json.contains("\"deny\":[]"), json);
+ assertTrue(json.contains("\"ask\":[]"), json);
+ assertTrue(json.contains("\"allow\":[]"), json);
+ }
+
+ @Test
+ void distinguishesExplicitEmptyAllowFromAbsentAllow() throws Exception {
+ // Present empty allow admits nothing; the null deny/ask must be omitted.
+ var permissions = new ManagedSettingsPermissions().setAllow(List.of());
+ var managedSettings = new ManagedSettings().setPermissions(permissions);
+ var create = SessionRequestBuilder.buildCreateRequest(new SessionConfig().setManagedSettings(managedSettings),
+ "managed-mixed");
+
+ var json = new ObjectMapper().writeValueAsString(create);
+ assertTrue(json.contains("\"allow\":[]"), json);
+ assertFalse(json.contains("\"deny\""), json);
+ assertFalse(json.contains("\"ask\""), json);
+ }
+
+ @Test
+ void directInjectionEnablesManagedSafeguards() throws Exception {
+ var session = new CopilotSession("session-1", null);
+ var settings = new ManagedSettings().setPermissions(new ManagedSettingsPermissions());
+ var managedSettingsEnabled = new AtomicBoolean();
+ var config = new SessionConfig().setManagedSettings(settings).setOnPermissionRequest((request, invocation) -> {
+ managedSettingsEnabled.set(invocation.isManagedSettingsEnabled());
+ return CompletableFuture.completedFuture(PermissionRequestResult.noResult());
+ });
+
+ SessionRequestBuilder.configureSession(session, config);
+ session.handlePermissionRequest(new ObjectMapper().readTree("{\"kind\":\"read\"}")).get();
+
+ assertTrue(managedSettingsEnabled.get());
+ }
+}
diff --git a/java/src/test/java/com/github/copilot/SessionEventDeserializationTest.java b/java/src/test/java/com/github/copilot/SessionEventDeserializationTest.java
index fc978ed65b..8d9b70a348 100644
--- a/java/src/test/java/com/github/copilot/SessionEventDeserializationTest.java
+++ b/java/src/test/java/com/github/copilot/SessionEventDeserializationTest.java
@@ -113,6 +113,54 @@ void testParseSessionIdleEvent() throws Exception {
assertEquals("session.idle", event.getType());
}
+ @Test
+ void testManagedSettingsResolvedClientProvenance() throws Exception {
+ assertEquals("server", ManagedSettingsResolvedSource.SERVER.getValue());
+ assertEquals("device", ManagedSettingsResolvedSource.DEVICE.getValue());
+ assertEquals("client", ManagedSettingsResolvedSource.CLIENT.getValue());
+ assertEquals("mixed", ManagedSettingsResolvedSource.MIXED.getValue());
+ assertEquals("none", ManagedSettingsResolvedSource.NONE.getValue());
+
+ String clientJson = """
+ {
+ "type": "session.managed_settings_resolved",
+ "data": {
+ "source": "client",
+ "serverManaged": false,
+ "deviceManaged": false,
+ "clientManaged": true,
+ "failClosed": false,
+ "bypassPermissionsDisabled": true,
+ "managedKeys": ["permissions"]
+ }
+ }
+ """;
+
+ var clientEvent = assertInstanceOf(SessionManagedSettingsResolvedEvent.class, parseJson(clientJson));
+ assertEquals(ManagedSettingsResolvedSource.CLIENT, clientEvent.getData().source());
+ assertEquals(Boolean.TRUE, clientEvent.getData().clientManaged());
+ assertTrue(MAPPER.writeValueAsString(clientEvent).contains("\"clientManaged\":true"));
+
+ String mixedJson = """
+ {
+ "type": "session.managed_settings_resolved",
+ "data": {
+ "source": "mixed",
+ "serverManaged": true,
+ "deviceManaged": true,
+ "failClosed": false,
+ "bypassPermissionsDisabled": true,
+ "managedKeys": ["permissions"]
+ }
+ }
+ """;
+
+ var mixedEvent = assertInstanceOf(SessionManagedSettingsResolvedEvent.class, parseJson(mixedJson));
+ assertEquals(ManagedSettingsResolvedSource.MIXED, mixedEvent.getData().source());
+ assertNull(mixedEvent.getData().clientManaged());
+ assertFalse(MAPPER.writeValueAsString(mixedEvent).contains("\"clientManaged\""));
+ }
+
@Test
void testParseSessionInfoEvent() throws Exception {
String json = """
@@ -897,15 +945,16 @@ void testParseEmptyJson() throws Exception {
@Test
void testParseAllEventTypes() throws Exception {
String[] types = {"session.start", "session.resume", "session.error", "session.idle", "session.info",
- "session.model_change", "session.mode_changed", "session.plan_changed",
- "session.workspace_file_changed", "session.handoff", "session.truncation", "session.snapshot_rewind",
- "session.usage_info", "session.compaction_start", "session.compaction_complete", "user.message",
- "pending_messages.modified", "assistant.turn_start", "assistant.intent", "assistant.reasoning",
- "assistant.reasoning_delta", "assistant.message", "assistant.message_delta", "assistant.turn_end",
- "assistant.usage", "abort", "tool.user_requested", "tool.execution_start",
- "tool.execution_partial_result", "tool.execution_progress", "tool.execution_complete",
- "subagent.started", "subagent.completed", "subagent.failed", "subagent.selected", "hook.start",
- "hook.end", "system.message", "session.shutdown", "skill.invoked"};
+ "session.model_change", "session.mode_changed", "session.managed_settings_resolved",
+ "session.managed_settings_enforced", "session.plan_changed", "session.workspace_file_changed",
+ "session.handoff", "session.truncation", "session.snapshot_rewind", "session.usage_info",
+ "session.compaction_start", "session.compaction_complete", "user.message", "pending_messages.modified",
+ "assistant.turn_start", "assistant.intent", "assistant.reasoning", "assistant.reasoning_delta",
+ "assistant.message", "assistant.message_delta", "assistant.turn_end", "assistant.usage", "abort",
+ "tool.user_requested", "tool.execution_start", "tool.execution_partial_result",
+ "tool.execution_progress", "tool.execution_complete", "subagent.started", "subagent.completed",
+ "subagent.failed", "subagent.selected", "hook.start", "hook.end", "system.message", "session.shutdown",
+ "skill.invoked"};
for (String type : types) {
String json = """
diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts
index 4ed139be70..c30b2207b8 100644
--- a/nodejs/src/client.ts
+++ b/nodejs/src/client.ts
@@ -1467,7 +1467,9 @@ export class CopilotClient {
this.onGetTraceContext,
{
mcpAuthHandler: config.onMcpAuthRequest,
- managedSettingsEnabled: config.enableManagedSettings,
+ managedSettingsEnabled:
+ config.enableManagedSettings === true ||
+ config.managedSettings !== undefined,
}
);
s.registerTools(config.tools);
@@ -1608,6 +1610,7 @@ export class CopilotClient {
cloud: config.cloud,
expAssignments: config.expAssignments,
enableManagedSettings: config.enableManagedSettings,
+ managedSettings: config.managedSettings,
});
const {
@@ -1708,7 +1711,8 @@ export class CopilotClient {
this.onGetTraceContext,
{
mcpAuthHandler: config.onMcpAuthRequest,
- managedSettingsEnabled: config.enableManagedSettings,
+ managedSettingsEnabled:
+ config.enableManagedSettings === true || config.managedSettings !== undefined,
}
);
session.registerTools(config.tools);
@@ -1855,6 +1859,7 @@ export class CopilotClient {
openCanvases: config.openCanvases,
expAssignments: config.expAssignments,
enableManagedSettings: config.enableManagedSettings,
+ managedSettings: config.managedSettings,
});
const { workspacePath, capabilities, openCanvases } = response as {
diff --git a/nodejs/src/index.ts b/nodejs/src/index.ts
index f915a8707e..5ab53471a6 100644
--- a/nodejs/src/index.ts
+++ b/nodejs/src/index.ts
@@ -107,6 +107,8 @@ export type {
DefaultAgentConfig,
BearerTokenProvider,
MessageOptions,
+ ManagedSettings,
+ ManagedSettingsPermissions,
ModelBilling,
ModelBillingTokenPrices,
ModelBillingTokenPricesLongContext,
diff --git a/nodejs/src/types.ts b/nodejs/src/types.ts
index d77a3a97cf..4ff2791898 100644
--- a/nodejs/src/types.ts
+++ b/nodejs/src/types.ts
@@ -2088,6 +2088,45 @@ export interface GitHubMcpToolConfig {
disableFormDeferral?: boolean;
}
+/**
+ * Permissions-only managed policy injected by the host via
+ * {@link SessionConfigBase.managedSettings}.
+ *
+ * Rule strings use the same vocabulary the runtime accepts for fetched managed
+ * policy (e.g. `"Read(**)"`, `"Shell(git push *)"`); malformed rules are
+ * rejected at session creation.
+ */
+export interface ManagedSettingsPermissions {
+ /**
+ * When set to `"disable"`, bypass-permissions ("yolo") mode is turned off
+ * for the session. This is deny-wins: it cannot be re-enabled by any other
+ * layer.
+ */
+ disableBypassPermissionsMode?: "disable";
+ /** Operations that must always be denied. Unioned across managed layers. */
+ deny?: string[];
+ /**
+ * Operations that must prompt for approval. Unioned across managed layers.
+ */
+ ask?: string[];
+ /**
+ * Operations permitted without prompting. Every declared `allow` list
+ * (across managed layers) must admit an operation for it to be allowed.
+ */
+ allow?: string[];
+}
+
+/**
+ * Host-injected enterprise managed settings. The first supported contract is
+ * permissions-only; unknown sibling keys are rejected by the runtime.
+ *
+ * @see {@link SessionConfigBase.managedSettings}
+ */
+export interface ManagedSettings {
+ /** Managed permission policy for the session. */
+ permissions?: ManagedSettingsPermissions;
+}
+
/**
* Shared configuration fields used by both {@link SessionConfig} (for
* creating a new session) and {@link ResumeSessionConfig} (for resuming
@@ -2586,6 +2625,31 @@ export interface SessionConfigBase {
*/
enableManagedSettings?: boolean;
+ /**
+ * Host-injected enterprise managed settings for this session.
+ *
+ * Unlike {@link SessionConfigBase.enableManagedSettings} — which asks the
+ * runtime to *self-fetch* account/org and device policy — this field lets
+ * the host supply the managed policy directly. The runtime validates it
+ * with the same managed-permission parser it uses for fetched policy and
+ * composes it restrictively with any self-fetched (server) and
+ * device-managed (MDM) layers: `deny`/`ask` rules are unioned, every
+ * declared `allow` list must admit an operation, and
+ * `disableBypassPermissionsMode: "disable"` is deny-wins.
+ *
+ * This is startup-only. It is **not** persisted: it must be re-supplied on
+ * {@link CopilotClient.resumeSession | resume}, where it replaces the prior
+ * injected layer (omitting it clears the layer, so warm and cold resume
+ * behave identically). It may be combined with `enableManagedSettings`;
+ * when both are supplied the injected, server, and device restrictions all
+ * apply.
+ *
+ * Requires a Copilot runtime whose RPC schema includes `managedSettings`.
+ * Older runtimes may ignore this additive field, so hosts must not rely on
+ * injected policy until they ship a compatible runtime.
+ */
+ managedSettings?: ManagedSettings;
+
/**
* When true, skips embedding-based retrieval for this session.
* Use in multitenant deployments to prevent cross-session information leakage
diff --git a/nodejs/test/client.test.ts b/nodejs/test/client.test.ts
index 962d90970e..01a97e9800 100644
--- a/nodejs/test/client.test.ts
+++ b/nodejs/test/client.test.ts
@@ -3659,3 +3659,101 @@ describe("CopilotClient", () => {
});
});
});
+
+describe("managedSettings serialization", () => {
+ async function captureCreateParams(config: Record): Promise {
+ const client = new CopilotClient();
+ await client.start();
+ onTestFinished(() => stopClient(client));
+ const spy = vi
+ .spyOn((client as any).connection!, "sendRequest")
+ .mockImplementation(async (method: string, params: any) => {
+ if (method === "session.create") return { sessionId: params.sessionId };
+ throw new Error(`Unexpected method: ${method}`);
+ });
+ await client.createSession({ onPermissionRequest: approveAll, ...config });
+ const call = spy.mock.calls.find(([method]) => method === "session.create");
+ return call![1];
+ }
+
+ it("forwards the full permissions object on session.create", async () => {
+ const params = await captureCreateParams({
+ managedSettings: {
+ permissions: {
+ disableBypassPermissionsMode: "disable",
+ deny: ["Shell(git push)"],
+ ask: ["Domain(publish.example)"],
+ allow: ["Read(**)"],
+ },
+ },
+ });
+ expect(params.managedSettings).toEqual({
+ permissions: {
+ disableBypassPermissionsMode: "disable",
+ deny: ["Shell(git push)"],
+ ask: ["Domain(publish.example)"],
+ allow: ["Read(**)"],
+ },
+ });
+ });
+
+ it("marks directly injected sessions as managed", async () => {
+ const client = new CopilotClient();
+ await client.start();
+ onTestFinished(() => stopClient(client));
+ vi.spyOn((client as any).connection!, "sendRequest").mockImplementation(
+ async (method: string, params: any) => {
+ if (method === "session.create") return { sessionId: params.sessionId };
+ throw new Error(`Unexpected method: ${method}`);
+ }
+ );
+
+ const session = await client.createSession({
+ onPermissionRequest: approveAll,
+ managedSettings: { permissions: { deny: ["Edit(/secrets/**)"] } },
+ });
+
+ expect((session as any).managedSettingsEnabled).toBe(true);
+ });
+
+ it("omits managedSettings when not supplied", async () => {
+ const params = await captureCreateParams({});
+ expect(params.managedSettings).toBeUndefined();
+ });
+
+ it("coexists with enableManagedSettings", async () => {
+ const params = await captureCreateParams({
+ enableManagedSettings: true,
+ managedSettings: { permissions: { deny: ["Edit(/secrets/**)"] } },
+ });
+ expect(params.enableManagedSettings).toBe(true);
+ expect(params.managedSettings).toEqual({ permissions: { deny: ["Edit(/secrets/**)"] } });
+ });
+
+ it("preserves empty arrays in the permissions object", async () => {
+ const params = await captureCreateParams({
+ managedSettings: { permissions: { deny: [], ask: [], allow: [] } },
+ });
+ expect(params.managedSettings).toEqual({ permissions: { deny: [], ask: [], allow: [] } });
+ });
+
+ it("forwards managedSettings on session.resume", async () => {
+ const client = new CopilotClient();
+ await client.start();
+ onTestFinished(() => stopClient(client));
+ const spy = vi
+ .spyOn((client as any).connection!, "sendRequest")
+ .mockImplementation(async (method: string, params: any) => {
+ if (method === "session.resume") return { sessionId: params.sessionId };
+ throw new Error(`Unexpected method: ${method}`);
+ });
+ await client.resumeSession("session-1", {
+ onPermissionRequest: approveAll,
+ managedSettings: { permissions: { ask: ["Domain(publish.example)"] } },
+ });
+ const call = spy.mock.calls.find(([method]) => method === "session.resume");
+ expect(call![1].managedSettings).toEqual({
+ permissions: { ask: ["Domain(publish.example)"] },
+ });
+ });
+});
diff --git a/nodejs/test/session-event-types.test.ts b/nodejs/test/session-event-types.test.ts
index fef7acdb2b..5a8f2ca521 100644
--- a/nodejs/test/session-event-types.test.ts
+++ b/nodejs/test/session-event-types.test.ts
@@ -22,6 +22,9 @@ import type {
PermissionRequest,
PermissionRequestedData,
PermissionRequestedEvent,
+ ManagedSettingsResolvedData,
+ ManagedSettingsResolvedEvent,
+ ManagedSettingsResolvedSource,
// *Data payload types from the v0.3.0 generated session-event schema.
AssistantMessageData,
@@ -163,6 +166,45 @@ describe("Session event type exports (#1156)", () => {
expect(permissionEvent.data.permissionRequest.managedApprovalRequired).toBe(true);
});
+ it("exposes managed settings client and mixed provenance", () => {
+ const sources: ManagedSettingsResolvedSource[] = [
+ "server",
+ "device",
+ "client",
+ "mixed",
+ "none",
+ ];
+ expect(sources).toEqual(["server", "device", "client", "mixed", "none"]);
+
+ const clientData: ManagedSettingsResolvedData = {
+ bypassPermissionsDisabled: true,
+ clientManaged: true,
+ deviceManaged: false,
+ failClosed: false,
+ managedKeys: ["permissions"],
+ serverManaged: false,
+ source: "client",
+ };
+ const clientEvent: ManagedSettingsResolvedEvent = {
+ ephemeral: true,
+ id: "evt-managed-1",
+ parentId: null,
+ timestamp: "2026-01-01T00:00:00.000Z",
+ type: "session.managed_settings_resolved",
+ data: clientData,
+ };
+ expect(clientEvent.data.source).toBe("client");
+ expect(clientEvent.data.clientManaged).toBe(true);
+
+ const { clientManaged: _, ...withoutClientManaged } = clientData;
+ const mixedData: ManagedSettingsResolvedData = {
+ ...withoutClientManaged,
+ source: "mixed",
+ };
+ expect(mixedData.source).toBe("mixed");
+ expect("clientManaged" in mixedData).toBe(false);
+ });
+
it("rejects approveAll in managed settings sessions", () => {
expect(() =>
approveAll(
@@ -260,6 +302,7 @@ describe("Session event type exports (#1156)", () => {
assertImportable();
assertImportable();
assertImportable();
+ assertImportable();
assertImportable();
assertImportable();
@@ -270,6 +313,8 @@ describe("Session event type exports (#1156)", () => {
assertImportable();
assertImportable();
assertImportable();
+ assertImportable();
+ assertImportable();
// Supporting auxiliary types referenced by the *Data shapes — these
// must round-trip through the package root too, otherwise consumers
diff --git a/python/copilot/__init__.py b/python/copilot/__init__.py
index 678fffbf14..a7366db543 100644
--- a/python/copilot/__init__.py
+++ b/python/copilot/__init__.py
@@ -41,6 +41,8 @@
GetStatusResponse,
InProcessRuntimeConnection,
LogLevel,
+ ManagedSettings,
+ ManagedSettingsPermissions,
ModelBilling,
ModelCapabilities,
ModelInfo,
@@ -272,6 +274,8 @@
"McpAuthStaticClientConfig",
"McpAuthToken",
"McpAuthWwwAuthenticateParams",
+ "ManagedSettings",
+ "ManagedSettingsPermissions",
"ModelBilling",
"ModelBillingTokenPrices",
"ModelBillingTokenPricesLongContext",
diff --git a/python/copilot/client.py b/python/copilot/client.py
index 7c273bd010..21ceb6eee1 100644
--- a/python/copilot/client.py
+++ b/python/copilot/client.py
@@ -247,6 +247,63 @@ def _capi_session_options_to_wire(options: CapiSessionOptions) -> dict[str, Any]
return wire
+@dataclass
+class ManagedSettingsPermissions:
+ """Permissions-only managed policy injected via :class:`ManagedSettings`.
+
+ Rule strings use the same vocabulary the runtime accepts for fetched
+ managed policy (e.g. ``"Read(**)"``, ``"Shell(git push *)"``); malformed
+ rules are rejected by the runtime at session creation.
+ """
+
+ disable_bypass_permissions_mode: Literal["disable"] | None = None
+ """When ``"disable"``, turns off bypass-permissions ("yolo") mode for the
+ session. Deny-wins: no other layer can re-enable it. Sent on the wire as
+ ``disableBypassPermissionsMode``."""
+ deny: list[str] | None = None
+ """Operations that must always be denied. Unioned across managed layers."""
+ ask: list[str] | None = None
+ """Operations that must prompt for approval. Unioned across managed layers."""
+ allow: list[str] | None = None
+ """Operations permitted without prompting. Every declared ``allow`` list
+ across managed layers must admit an operation for it to be allowed."""
+
+
+@dataclass
+class ManagedSettings:
+ """Host-injected enterprise managed settings for a session.
+
+ Unlike ``enable_managed_settings`` — which asks the runtime to *self-fetch*
+ account/org and device policy — this supplies the managed policy directly.
+ The runtime validates it with the same managed-permission parser it uses
+ for fetched policy and composes it restrictively with any self-fetched
+ (server) and device-managed (MDM) layers.
+
+ The first supported contract is permissions-only; unknown sibling keys are
+ rejected by the runtime. Serialized on the wire as ``managedSettings``.
+ """
+
+ permissions: ManagedSettingsPermissions | None = None
+ """Managed permission policy for the session."""
+
+
+def _managed_settings_to_dict(settings: ManagedSettings) -> dict[str, Any]:
+ wire: dict[str, Any] = {}
+ permissions = settings.permissions
+ if permissions is not None:
+ perms: dict[str, Any] = {}
+ if permissions.disable_bypass_permissions_mode is not None:
+ perms["disableBypassPermissionsMode"] = permissions.disable_bypass_permissions_mode
+ if permissions.deny is not None:
+ perms["deny"] = list(permissions.deny)
+ if permissions.ask is not None:
+ perms["ask"] = list(permissions.ask)
+ if permissions.allow is not None:
+ perms["allow"] = list(permissions.allow)
+ wire["permissions"] = perms
+ return wire
+
+
# Implicit provider name for the singular, whole-session ``provider`` config.
# Named providers are keyed by their own ``name``.
_DEFAULT_BEARER_TOKEN_PROVIDER_NAME = "default"
@@ -2090,6 +2147,7 @@ async def create_session(
exp_assignments: CopilotExpAssignmentResponse | None = None,
enable_managed_settings: bool | None = None,
github_mcp_tool_config: GitHubMcpToolConfig | None = None,
+ managed_settings: ManagedSettings | None = None,
) -> CopilotSession:
"""
Create a new conversation session with the Copilot CLI.
@@ -2241,6 +2299,15 @@ async def create_session(
expected to reject session creation (fail-closed). When unset,
behaves exactly as before. Sent on the wire as
``enableManagedSettings``.
+ managed_settings: Host-injected enterprise managed settings for the
+ session. Supplies managed policy directly instead of
+ self-fetching; the runtime validates it and composes it
+ restrictively with any self-fetched (server) and device-managed
+ layers. Startup-only and not persisted: re-supply on
+ :meth:`resume_session` (omitting it clears the injected layer).
+ May be combined with ``enable_managed_settings``. Requires a
+ runtime whose RPC schema includes ``managedSettings``. Sent on
+ the wire as ``managedSettings``.
Returns:
A :class:`CopilotSession` instance for the new session.
@@ -2389,6 +2456,10 @@ async def create_session(
if enable_managed_settings is not None:
payload["enableManagedSettings"] = enable_managed_settings
+ # Host-injected managed settings (permissions-only contract)
+ if managed_settings is not None:
+ payload["managedSettings"] = _managed_settings_to_dict(managed_settings)
+
# Add working directory if provided
if working_directory:
payload["workingDirectory"] = working_directory
@@ -2575,7 +2646,8 @@ def _initialize_session(sid: str) -> CopilotSession:
sid,
self._client,
workspace_path=None,
- managed_settings_enabled=enable_managed_settings is True,
+ managed_settings_enabled=enable_managed_settings is True
+ or managed_settings is not None,
)
if self._session_fs_config:
if create_session_fs_handler is None:
@@ -2799,6 +2871,7 @@ async def resume_session(
exp_assignments: CopilotExpAssignmentResponse | None = None,
enable_managed_settings: bool | None = None,
github_mcp_tool_config: GitHubMcpToolConfig | None = None,
+ managed_settings: ManagedSettings | None = None,
) -> CopilotSession:
"""
Resume an existing conversation session by its ID.
@@ -2951,6 +3024,11 @@ async def resume_session(
expected to reject session creation (fail-closed). When unset,
behaves exactly as before. Sent on the wire as
``enableManagedSettings``.
+ managed_settings: Host-injected enterprise managed settings for the
+ session. Must be re-supplied on resume; it replaces the prior
+ injected layer, and omitting it clears that layer so warm and
+ cold resume behave identically. See :meth:`create_session`. Sent
+ on the wire as ``managedSettings``.
Returns:
A :class:`CopilotSession` instance for the resumed session.
@@ -3122,6 +3200,10 @@ async def resume_session(
if enable_managed_settings is not None:
payload["enableManagedSettings"] = enable_managed_settings
+ # Host-injected managed settings (permissions-only contract)
+ if managed_settings is not None:
+ payload["managedSettings"] = _managed_settings_to_dict(managed_settings)
+
if working_directory:
payload["workingDirectory"] = working_directory
if additional_directories:
@@ -3234,7 +3316,8 @@ async def resume_session(
session_id,
self._client,
workspace_path=None,
- managed_settings_enabled=enable_managed_settings is True,
+ managed_settings_enabled=enable_managed_settings is True
+ or managed_settings is not None,
)
if self._session_fs_config:
if create_session_fs_handler is None:
diff --git a/python/test_client.py b/python/test_client.py
index f101fc3968..2375bc98a9 100644
--- a/python/test_client.py
+++ b/python/test_client.py
@@ -28,6 +28,8 @@
CloudSessionRepository,
CopilotExpAssignmentResponse,
ExpConfigEntry,
+ ManagedSettings,
+ ManagedSettingsPermissions,
ModelBilling,
ModelCapabilities,
ModelInfo,
@@ -651,6 +653,61 @@ async def mock_request(method, params, **kwargs):
finally:
await client.force_stop()
+ @pytest.mark.asyncio
+ async def test_create_and_resume_session_forward_managed_settings(self):
+ client = CopilotClient(connection=RuntimeConnection.for_stdio(path=CLI_PATH))
+ await client.start()
+ try:
+ captured = {}
+
+ async def mock_request(method, params, **kwargs):
+ captured[method] = params
+ if method in ("session.create", "session.resume"):
+ result = {"sessionId": params.get("sessionId") or "session-1"}
+ callback = kwargs.get("on_response_inline")
+ if callback is not None:
+ callback(result)
+ return result
+ return {}
+
+ client._client.request = mock_request
+ session = await client.create_session(
+ on_permission_request=PermissionHandler.approve_all,
+ enable_managed_settings=True,
+ managed_settings=ManagedSettings(
+ permissions=ManagedSettingsPermissions(
+ disable_bypass_permissions_mode="disable",
+ deny=["Shell(git push)"],
+ ask=["Domain(publish.example)"],
+ allow=["Read(**)"],
+ )
+ ),
+ )
+ resumed_session = await client.resume_session(
+ session.session_id,
+ on_permission_request=PermissionHandler.approve_all,
+ managed_settings=ManagedSettings(
+ permissions=ManagedSettingsPermissions(ask=["Domain(publish.example)"])
+ ),
+ )
+
+ assert session._managed_settings_enabled is True
+ assert resumed_session._managed_settings_enabled is True
+ assert captured["session.create"]["enableManagedSettings"] is True
+ assert captured["session.create"]["managedSettings"] == {
+ "permissions": {
+ "disableBypassPermissionsMode": "disable",
+ "deny": ["Shell(git push)"],
+ "ask": ["Domain(publish.example)"],
+ "allow": ["Read(**)"],
+ }
+ }
+ assert captured["session.resume"]["managedSettings"] == {
+ "permissions": {"ask": ["Domain(publish.example)"]}
+ }
+ finally:
+ await client.force_stop()
+
@pytest.mark.asyncio
async def test_create_and_resume_session_default_enable_experimental_mode_by_mode(self):
with TemporaryDirectory() as base_directory:
@@ -691,6 +748,7 @@ async def mock_request(method, params, **kwargs):
finally:
await client.force_stop()
+ async def test_managed_settings_omitted_when_not_supplied(self):
client = CopilotClient(connection=RuntimeConnection.for_stdio(path=CLI_PATH))
await client.start()
try:
@@ -698,7 +756,7 @@ async def mock_request(method, params, **kwargs):
async def mock_request(method, params, **kwargs):
captured[method] = params
- if method in ("session.create", "session.resume"):
+ if method == "session.create":
result = {"sessionId": params.get("sessionId") or "session-1"}
callback = kwargs.get("on_response_inline")
if callback is not None:
@@ -707,16 +765,42 @@ async def mock_request(method, params, **kwargs):
return {}
client._client.request = mock_request
- session = await client.create_session(
+ await client.create_session(
on_permission_request=PermissionHandler.approve_all,
)
- await client.resume_session(
- session.session_id,
+
+ assert "managedSettings" not in captured["session.create"]
+ finally:
+ await client.force_stop()
+
+ @pytest.mark.asyncio
+ async def test_managed_settings_preserves_empty_arrays(self):
+ client = CopilotClient(connection=RuntimeConnection.for_stdio(path=CLI_PATH))
+ await client.start()
+ try:
+ captured = {}
+
+ async def mock_request(method, params, **kwargs):
+ captured[method] = params
+ if method == "session.create":
+ result = {"sessionId": params.get("sessionId") or "session-1"}
+ callback = kwargs.get("on_response_inline")
+ if callback is not None:
+ callback(result)
+ return result
+ return {}
+
+ client._client.request = mock_request
+ await client.create_session(
on_permission_request=PermissionHandler.approve_all,
+ managed_settings=ManagedSettings(
+ permissions=ManagedSettingsPermissions(deny=[], ask=[], allow=[])
+ ),
)
- assert "isExperimentalMode" not in captured["session.create"]
- assert "isExperimentalMode" not in captured["session.resume"]
+ assert captured["session.create"]["managedSettings"] == {
+ "permissions": {"deny": [], "ask": [], "allow": []}
+ }
finally:
await client.force_stop()
diff --git a/python/test_event_forward_compatibility.py b/python/test_event_forward_compatibility.py
index 1ffbd59c54..2e8015a97d 100644
--- a/python/test_event_forward_compatibility.py
+++ b/python/test_event_forward_compatibility.py
@@ -18,10 +18,12 @@
ElicitationCompletedAction,
ElicitationRequestedMode,
ElicitationRequestedSchema,
+ ManagedSettingsResolvedSource,
PermissionPromptRequestMemory,
PermissionRequestMemory,
PermissionRequestMemoryAction,
SessionEventType,
+ SessionManagedSettingsResolvedData,
SessionTaskCompleteData,
UserMessageAgentMode,
session_event_from_dict,
@@ -136,6 +138,42 @@ def test_explicit_generated_symbols_remain_available(self):
)
assert schema.to_dict()["type"] == "object"
+ def test_managed_settings_client_provenance_round_trips(self):
+ """Managed settings events should preserve truthful client provenance."""
+ assert [source.value for source in ManagedSettingsResolvedSource] == [
+ "server",
+ "device",
+ "client",
+ "mixed",
+ "none",
+ ]
+
+ client = SessionManagedSettingsResolvedData(
+ bypass_permissions_disabled=True,
+ client_managed=True,
+ device_managed=False,
+ fail_closed=False,
+ managed_keys=["permissions"],
+ server_managed=False,
+ source=ManagedSettingsResolvedSource.CLIENT,
+ )
+ serialized = client.to_dict()
+ assert serialized["source"] == "client"
+ assert serialized["clientManaged"] is True
+ assert SessionManagedSettingsResolvedData.from_dict(serialized) == client
+
+ mixed = SessionManagedSettingsResolvedData(
+ bypass_permissions_disabled=True,
+ device_managed=True,
+ fail_closed=False,
+ managed_keys=["permissions"],
+ server_managed=True,
+ source=ManagedSettingsResolvedSource.MIXED,
+ )
+ serialized = mixed.to_dict()
+ assert serialized["source"] == "mixed"
+ assert "clientManaged" not in serialized
+
def test_data_shim_preserves_raw_mapping_values(self):
"""Compatibility Data should keep arbitrary nested mappings as plain dicts."""
parsed = Data.from_dict(
diff --git a/rust/src/session.rs b/rust/src/session.rs
index d505541a50..c6c806b1c1 100644
--- a/rust/src/session.rs
+++ b/rust/src/session.rs
@@ -66,6 +66,13 @@ pub(crate) struct SessionHandlers {
pub tools: Arc>>,
}
+fn has_managed_settings(
+ enable_managed_settings: Option,
+ managed_settings: Option<&crate::types::ManagedSettings>,
+) -> bool {
+ enable_managed_settings == Some(true) || managed_settings.is_some()
+}
+
/// Shared state between a [`Session`] and its event loop, used by [`Session::send_and_wait`].
struct IdleWaiter {
tx: oneshot::Sender, Error>>,
@@ -899,7 +906,10 @@ impl Client {
);
let handlers = SessionHandlers {
permission: permission_handler,
- managed_settings_enabled: wire.enable_managed_settings == Some(true),
+ managed_settings_enabled: has_managed_settings(
+ wire.enable_managed_settings,
+ wire.managed_settings.as_ref(),
+ ),
elicitation: runtime.elicitation_handler.take(),
mcp_auth: runtime.mcp_auth_handler.take(),
user_input: runtime.user_input_handler.take(),
@@ -1169,7 +1179,10 @@ impl Client {
);
let handlers = SessionHandlers {
permission: permission_handler,
- managed_settings_enabled: wire.enable_managed_settings == Some(true),
+ managed_settings_enabled: has_managed_settings(
+ wire.enable_managed_settings,
+ wire.managed_settings.as_ref(),
+ ),
elicitation: runtime.elicitation_handler.take(),
mcp_auth: runtime.mcp_auth_handler.take(),
user_input: runtime.user_input_handler.take(),
@@ -2550,9 +2563,16 @@ fn inject_transform_sections_resume(
mod tests {
use serde_json::json;
- use super::{notification_permission_payload, permission_request_data};
+ use super::{has_managed_settings, notification_permission_payload, permission_request_data};
use crate::handler::PermissionResult;
+ #[test]
+ fn direct_injection_enables_managed_safeguards() {
+ let settings = crate::types::ManagedSettings::default();
+ assert!(has_managed_settings(None, Some(&settings)));
+ assert!(!has_managed_settings(None, None));
+ }
+
#[test]
fn notification_payload_suppresses_no_result() {
assert!(notification_permission_payload(&PermissionResult::NoResult).is_none());
diff --git a/rust/src/types.rs b/rust/src/types.rs
index 37d3b248bf..d3c4faa16b 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -1763,6 +1763,99 @@ pub struct CopilotExpAssignmentResponse {
pub assignment_context: String,
}
+/// Controls whether bypass-permissions mode is available in a managed session.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+#[non_exhaustive]
+pub enum DisableBypassPermissionsMode {
+ /// Turn off bypass-permissions mode.
+ Disable,
+}
+
+/// Permission rules injected as a managed-settings layer at session bootstrap.
+///
+/// All fields are optional; an omitted field imposes no constraint from this
+/// layer. This layer composes restrictively with any server- or device-level
+/// managed settings: [`deny`](Self::deny) and [`ask`](Self::ask) rules are
+/// unioned across layers, every present [`allow`](Self::allow) list must admit a
+/// tool for it to be allowed, and
+/// [`disable_bypass_permissions_mode`](Self::disable_bypass_permissions_mode) is
+/// honored if any layer sets it (deny-wins).
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[non_exhaustive]
+pub struct ManagedSettingsPermissions {
+ /// When set to `"disable"`, bypass-permissions mode is turned off for the
+ /// session regardless of other layers. Serialized as
+ /// `disableBypassPermissionsMode`.
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub disable_bypass_permissions_mode: Option,
+ /// Tool-permission patterns that are always denied.
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub deny: Option>,
+ /// Tool-permission patterns that require an explicit ask.
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub ask: Option>,
+ /// Tool-permission patterns that are allowed without prompting.
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub allow: Option>,
+}
+
+impl ManagedSettingsPermissions {
+ /// Sets the bypass-permissions policy for this managed layer.
+ pub fn with_disable_bypass_permissions_mode(
+ mut self,
+ value: DisableBypassPermissionsMode,
+ ) -> Self {
+ self.disable_bypass_permissions_mode = Some(value);
+ self
+ }
+
+ /// Sets the rules that are always denied.
+ pub fn with_deny(mut self, rules: Vec) -> Self {
+ self.deny = Some(rules);
+ self
+ }
+
+ /// Sets the rules that require explicit approval.
+ pub fn with_ask(mut self, rules: Vec) -> Self {
+ self.ask = Some(rules);
+ self
+ }
+
+ /// Sets the rules that are allowed without prompting.
+ pub fn with_allow(mut self, rules: Vec) -> Self {
+ self.allow = Some(rules);
+ self
+ }
+}
+
+/// Managed-settings layer injected at session startup. Currently carries only a
+/// [`permissions`](Self::permissions) object.
+///
+/// This layer is startup-only and is not persisted with the session. It must be
+/// re-supplied on resume to remain in effect; omitting it on resume clears the
+/// previously injected layer. It can be combined with
+/// [`SessionConfig::enable_managed_settings`]. Older runtimes may ignore this
+/// additive field, so hosts must not rely on injected policy until they ship a
+/// compatible runtime.
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[non_exhaustive]
+pub struct ManagedSettings {
+ /// Permission rules for this managed-settings layer.
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub permissions: Option,
+}
+
+impl ManagedSettings {
+ /// Sets the permissions-only managed policy.
+ pub fn with_permissions(mut self, permissions: ManagedSettingsPermissions) -> Self {
+ self.permissions = Some(permissions);
+ self
+ }
+}
+
/// Configuration for creating a new session via the `session.create` RPC.
///
/// All fields are optional — the CLI applies sensible defaults.
@@ -2055,6 +2148,15 @@ pub struct SessionConfig {
/// (fail-closed). When `None`, behaves exactly as before. Set via
/// [`with_enable_managed_settings`](Self::with_enable_managed_settings).
pub enable_managed_settings: Option,
+ /// Optional managed-settings layer injected at session bootstrap. Currently
+ /// carries a [`permissions`](ManagedSettingsPermissions) object that composes
+ /// restrictively with any server- or device-level managed settings. This
+ /// layer is startup-only and is not persisted: it must be re-supplied on
+ /// resume to remain in effect. Can be combined with
+ /// [`enable_managed_settings`](Self::enable_managed_settings). Serialized on
+ /// the wire as `managedSettings`. Set via
+ /// [`with_managed_settings`](Self::with_managed_settings).
+ pub managed_settings: Option,
/// Custom session filesystem provider for this session. Required when
/// the [`Client`](crate::Client) was started with
/// [`ClientOptions::session_fs`](crate::ClientOptions::session_fs) set.
@@ -2201,6 +2303,7 @@ impl std::fmt::Debug for SessionConfig {
.field("exp_assignments", &self.exp_assignments)
.field("enable_managed_settings", &self.enable_managed_settings)
.field("enable_experimental_mode", &self.enable_experimental_mode)
+ .field("managed_settings", &self.managed_settings)
.field(
"session_fs_provider",
&self.session_fs_provider.as_ref().map(|_| ""),
@@ -2312,6 +2415,7 @@ impl Default for SessionConfig {
commands: None,
exp_assignments: None,
enable_managed_settings: None,
+ managed_settings: None,
session_fs_provider: None,
permission_handler: None,
elicitation_handler: None,
@@ -2477,6 +2581,7 @@ impl SessionConfig {
exp_assignments: self.exp_assignments,
enable_managed_settings: self.enable_managed_settings,
is_experimental_mode: self.enable_experimental_mode,
+ managed_settings: self.managed_settings,
};
let runtime = SessionConfigRuntime {
@@ -3100,6 +3205,15 @@ impl SessionConfig {
self.enable_managed_settings = Some(enabled);
self
}
+
+ /// Inject a managed-settings layer (currently permission rules) at session
+ /// bootstrap. This layer is startup-only and is not persisted, so it must be
+ /// re-supplied on resume to remain in effect. Can be combined with
+ /// [`with_enable_managed_settings`](Self::with_enable_managed_settings).
+ pub fn with_managed_settings(mut self, managed_settings: ManagedSettings) -> Self {
+ self.managed_settings = Some(managed_settings);
+ self
+ }
}
///
/// See [`SessionConfig`] for the construction patterns (chained `with_*`
@@ -3292,6 +3406,12 @@ pub struct ResumeSessionConfig {
/// process restart. Set via
/// [`with_enable_managed_settings`](Self::with_enable_managed_settings).
pub enable_managed_settings: Option,
+ /// Optional managed-settings layer injected on resume. See
+ /// [`SessionConfig::managed_settings`]. This layer is not persisted, so it
+ /// must be re-supplied on resume to remain in effect; omitting it clears the
+ /// previously injected layer. Serialized on the wire as `managedSettings`.
+ /// Set via [`with_managed_settings`](Self::with_managed_settings).
+ pub managed_settings: Option,
/// Custom session filesystem provider. Required on resume when the
/// [`Client`](crate::Client) was started with
/// [`ClientOptions::session_fs`](crate::ClientOptions::session_fs).
@@ -3431,6 +3551,7 @@ impl std::fmt::Debug for ResumeSessionConfig {
.field("exp_assignments", &self.exp_assignments)
.field("enable_managed_settings", &self.enable_managed_settings)
.field("enable_experimental_mode", &self.enable_experimental_mode)
+ .field("managed_settings", &self.managed_settings)
.field(
"session_fs_provider",
&self.session_fs_provider.as_ref().map(|_| ""),
@@ -3588,6 +3709,7 @@ impl ResumeSessionConfig {
exp_assignments: self.exp_assignments,
enable_managed_settings: self.enable_managed_settings,
is_experimental_mode: self.enable_experimental_mode,
+ managed_settings: self.managed_settings,
suppress_resume_event: self.suppress_resume_event,
continue_pending_work: self.continue_pending_work,
};
@@ -3681,6 +3803,7 @@ impl ResumeSessionConfig {
commands: None,
exp_assignments: None,
enable_managed_settings: None,
+ managed_settings: None,
session_fs_provider: None,
suppress_resume_event: None,
continue_pending_work: None,
@@ -4285,6 +4408,14 @@ impl ResumeSessionConfig {
self.enable_managed_settings = Some(enabled);
self
}
+
+ /// Inject a managed-settings layer (currently permission rules) on resume.
+ /// See [`SessionConfig::with_managed_settings`]. Must be re-supplied on
+ /// resume; omitting it clears the previously injected layer.
+ pub fn with_managed_settings(mut self, managed_settings: ManagedSettings) -> Self {
+ self.managed_settings = Some(managed_settings);
+ self
+ }
}
/// Controls how the system message is constructed.
diff --git a/rust/src/wire.rs b/rust/src/wire.rs
index 3e19063fcc..53ea1c4480 100644
--- a/rust/src/wire.rs
+++ b/rust/src/wire.rs
@@ -186,6 +186,8 @@ pub(crate) struct SessionCreateWire {
pub enable_managed_settings: Option,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_experimental_mode: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub managed_settings: Option,
}
/// The exact JSON shape sent on the `session.resume` JSON-RPC request.
@@ -335,4 +337,6 @@ pub(crate) struct SessionResumeWire {
pub enable_managed_settings: Option,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_experimental_mode: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub managed_settings: Option,
}
diff --git a/rust/tests/session_test.rs b/rust/tests/session_test.rs
index 41cae3e950..727911081d 100644
--- a/rust/tests/session_test.rs
+++ b/rust/tests/session_test.rs
@@ -17,12 +17,14 @@ use github_copilot_sdk::rpc::{
OpenCanvasInstance,
};
use github_copilot_sdk::session_events::{
- McpOauthRequiredData, ReasoningSummary, SessionLimitsConfig,
+ ManagedSettingsResolvedSource, McpOauthRequiredData, ReasoningSummary, SessionLimitsConfig,
+ SessionManagedSettingsResolvedData,
};
use github_copilot_sdk::types::{
CanvasProviderIdentity, CloudSessionOptions, CloudSessionRepository, CommandContext,
- CommandDefinition, CommandHandler, DeliveryMode, ElicitationRequest, ElicitationResult,
- ExitPlanModeData, ExtensionInfo, MessageOptions, RequestId, SessionConfig, SessionId,
+ CommandDefinition, CommandHandler, DeliveryMode, DisableBypassPermissionsMode,
+ ElicitationRequest, ElicitationResult, ExitPlanModeData, ExtensionInfo, ManagedSettings,
+ ManagedSettingsPermissions, MessageOptions, RequestId, SessionConfig, SessionId,
SetModelOptions, Tool, ToolInvocation, ToolResult,
};
use github_copilot_sdk::{Client, ContextTier, ErrorKind, ProtocolErrorKind, tool};
@@ -763,6 +765,135 @@ async fn create_session_sends_canvas_wire_fields() {
timeout(TIMEOUT, create_handle).await.unwrap().unwrap();
}
+#[tokio::test]
+async fn create_and_resume_send_managed_settings_permissions() {
+ use github_copilot_sdk::types::ResumeSessionConfig;
+
+ let (client, mut server_read, mut server_write) = make_client();
+
+ let managed = ManagedSettings::default().with_permissions(
+ ManagedSettingsPermissions::default()
+ .with_disable_bypass_permissions_mode(DisableBypassPermissionsMode::Disable)
+ .with_deny(vec!["shell(rm*)".to_string()])
+ .with_ask(vec!["write".to_string()])
+ .with_allow(vec![]),
+ );
+
+ let create_handle = tokio::spawn({
+ let client = client.clone();
+ let managed = managed.clone();
+ async move {
+ client
+ .create_session(
+ SessionConfig::default()
+ .with_enable_managed_settings(true)
+ .with_managed_settings(managed),
+ )
+ .await
+ .unwrap()
+ }
+ });
+
+ let request = read_framed(&mut server_read).await;
+ assert_eq!(request["method"], "session.create");
+ assert_eq!(request["params"]["enableManagedSettings"], true);
+ let perms = &request["params"]["managedSettings"]["permissions"];
+ assert_eq!(perms["disableBypassPermissionsMode"], "disable");
+ assert_eq!(perms["deny"][0], "shell(rm*)");
+ assert_eq!(perms["ask"][0], "write");
+ assert_eq!(perms["allow"], serde_json::json!([]));
+
+ let id = request["id"].as_u64().unwrap();
+ let session_id = requested_session_id(&request).to_string();
+ let response = serde_json::json!({
+ "jsonrpc": "2.0",
+ "id": id,
+ "result": { "sessionId": session_id.clone() },
+ });
+ write_framed(&mut server_write, &serde_json::to_vec(&response).unwrap()).await;
+ timeout(TIMEOUT, create_handle).await.unwrap().unwrap();
+
+ let resume_handle = tokio::spawn({
+ let client = client.clone();
+ let session_id = session_id.clone();
+ async move {
+ client
+ .resume_session(
+ ResumeSessionConfig::new(SessionId::from(session_id))
+ .with_managed_settings(managed),
+ )
+ .await
+ .unwrap()
+ }
+ });
+
+ let request = read_framed(&mut server_read).await;
+ assert_eq!(request["method"], "session.resume");
+ assert_eq!(
+ request["params"]["managedSettings"]["permissions"]["deny"][0],
+ "shell(rm*)"
+ );
+
+ let id = request["id"].as_u64().unwrap();
+ let response = serde_json::json!({
+ "jsonrpc": "2.0",
+ "id": id,
+ "result": { "sessionId": session_id },
+ });
+ write_framed(&mut server_write, &serde_json::to_vec(&response).unwrap()).await;
+
+ let reload = read_framed(&mut server_read).await;
+ assert_eq!(reload["method"], "session.skills.reload");
+ let id = reload["id"].as_u64().unwrap();
+ let response = serde_json::json!({ "jsonrpc": "2.0", "id": id, "result": {} });
+ write_framed(&mut server_write, &serde_json::to_vec(&response).unwrap()).await;
+
+ timeout(TIMEOUT, resume_handle).await.unwrap().unwrap();
+}
+
+#[test]
+fn managed_settings_resolved_event_preserves_client_provenance() {
+ let sources = [
+ (ManagedSettingsResolvedSource::Server, "server"),
+ (ManagedSettingsResolvedSource::Device, "device"),
+ (ManagedSettingsResolvedSource::Client, "client"),
+ (ManagedSettingsResolvedSource::Mixed, "mixed"),
+ (ManagedSettingsResolvedSource::None, "none"),
+ ];
+ for (source, wire_value) in sources {
+ assert_eq!(
+ serde_json::to_value(source).unwrap(),
+ serde_json::json!(wire_value)
+ );
+ }
+
+ let with_client = SessionManagedSettingsResolvedData {
+ bypass_permissions_disabled: true,
+ client_managed: Some(true),
+ managed_keys: vec!["permissions".to_string()],
+ source: ManagedSettingsResolvedSource::Client,
+ ..Default::default()
+ };
+ let serialized = serde_json::to_value(&with_client).unwrap();
+ assert_eq!(serialized["source"], "client");
+ assert_eq!(serialized["clientManaged"], true);
+
+ let round_tripped: SessionManagedSettingsResolvedData =
+ serde_json::from_value(serialized).unwrap();
+ assert_eq!(round_tripped.source, ManagedSettingsResolvedSource::Client);
+ assert_eq!(round_tripped.client_managed, Some(true));
+
+ let without_client = SessionManagedSettingsResolvedData {
+ bypass_permissions_disabled: true,
+ managed_keys: vec!["permissions".to_string()],
+ source: ManagedSettingsResolvedSource::Mixed,
+ ..Default::default()
+ };
+ let serialized = serde_json::to_value(&without_client).unwrap();
+ assert_eq!(serialized["source"], "mixed");
+ assert!(serialized.get("clientManaged").is_none());
+}
+
fn make_client_with_telemetry(
callback: github_copilot_sdk::github_telemetry::GitHubTelemetryCallback,
) -> (Client, tokio::io::DuplexStream, tokio::io::DuplexStream) {
From 89f126b0c53692047838d46299806787acdf74e0 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Fri, 7 Aug 2026 14:06:51 +0000
Subject: [PATCH 05/51] docs: update version references to 1.0.10-preview.0
---
java/README.md | 8 ++++----
java/jbang-example.java | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/java/README.md b/java/README.md
index 94f2de4102..8001d87d80 100644
--- a/java/README.md
+++ b/java/README.md
@@ -32,14 +32,14 @@ Replace `${copilot.sdk.version}` with the latest release from Maven Central.
com.github
copilot-sdk-java
- 1.0.9
+ 1.0.10-preview.0
```
### Gradle
```groovy
-implementation 'com.github:copilot-sdk-java:1.0.9'
+implementation 'com.github:copilot-sdk-java:1.0.10-preview.0'
```
#### Snapshot Builds
@@ -58,7 +58,7 @@ Snapshot builds of the next development version are published to Maven Central S
com.github
copilot-sdk-java
- 1.0.10-SNAPSHOT
+ 1.0.11-preview.0-SNAPSHOT
```
@@ -67,7 +67,7 @@ Snapshot builds of the next development version are published to Maven Central S
Replace `${copilot.sdk.version}` with the latest release from Maven Central.
```groovy
-implementation 'com.github:copilot-sdk-java:1.0.10-SNAPSHOT'
+implementation 'com.github:copilot-sdk-java:1.0.11-preview.0-SNAPSHOT'
```
## Quick Start
diff --git a/java/jbang-example.java b/java/jbang-example.java
index bea647ae9d..39d64ad4ad 100644
--- a/java/jbang-example.java
+++ b/java/jbang-example.java
@@ -1,5 +1,5 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS com.github:copilot-sdk-java:1.0.9
+//DEPS com.github:copilot-sdk-java:1.0.10-preview.0
import com.github.copilot.CopilotClient;
import com.github.copilot.generated.AssistantMessageEvent;
import com.github.copilot.generated.SessionUsageInfoEvent;
From db84f1063be79751f0d0188814ec9c2fc191f8fd Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Fri, 7 Aug 2026 14:07:18 +0000
Subject: [PATCH 06/51] [maven-release-plugin] prepare release
java/v1.0.10-preview.0
---
java/pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/java/pom.xml b/java/pom.xml
index ea468a75e2..7113e926e8 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -7,7 +7,7 @@
com.github
copilot-sdk-java
- 1.0.10-SNAPSHOT
+ 1.0.10-preview.0
jar
GitHub Copilot SDK :: Java
@@ -33,7 +33,7 @@
scm:git:https://github.com/github/copilot-sdk.git
scm:git:https://github.com/github/copilot-sdk.git
https://github.com/github/copilot-sdk
- HEAD
+ java/v1.0.10-preview.0
From 25c0beab6095def6881bb12ddd8d36f21dcbd3d6 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Fri, 7 Aug 2026 14:07:22 +0000
Subject: [PATCH 07/51] [maven-release-plugin] prepare for next development
iteration
---
java/pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/java/pom.xml b/java/pom.xml
index 7113e926e8..3a235705ff 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -7,7 +7,7 @@
com.github
copilot-sdk-java
- 1.0.10-preview.0
+ 1.0.11-preview.0-SNAPSHOT
jar
GitHub Copilot SDK :: Java
@@ -33,7 +33,7 @@
scm:git:https://github.com/github/copilot-sdk.git
scm:git:https://github.com/github/copilot-sdk.git
https://github.com/github/copilot-sdk
- java/v1.0.10-preview.0
+ HEAD
From 243ca395b64a47d892ced939fb1884ea82a2c839 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Sun, 9 Aug 2026 08:11:55 -0400
Subject: [PATCH 08/51] Skip untyped internal C# RPC properties (#2298)
Remove internal properties without a representable schema shape before C# RPC generation, while preserving typed internal properties and strict failures for public schemas.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 510b87fe-e424-4389-a811-2a4c3a2181ff
---
scripts/codegen/csharp.ts | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts
index 2d68e68e27..4fb71cd0ca 100644
--- a/scripts/codegen/csharp.ts
+++ b/scripts/codegen/csharp.ts
@@ -355,6 +355,41 @@ function failUnmappable(context: string, schema: JSONSchema7): never {
);
}
+function omitUntypedInternalProperties(value: unknown): void {
+ if (!value || typeof value !== "object") return;
+ if (Array.isArray(value)) {
+ value.forEach(omitUntypedInternalProperties);
+ return;
+ }
+
+ const node = value as Record;
+ const properties = node.properties;
+ if (properties && typeof properties === "object" && !Array.isArray(properties)) {
+ for (const [name, property] of Object.entries(properties)) {
+ if (!property || typeof property !== "object" || Array.isArray(property)) continue;
+ const schema = property as JSONSchema7;
+ const hasType =
+ schema.type !== undefined ||
+ schema.$ref !== undefined ||
+ schema.anyOf !== undefined ||
+ schema.oneOf !== undefined ||
+ schema.allOf !== undefined ||
+ schema.enum !== undefined ||
+ schema.const !== undefined ||
+ isOpaqueJson(schema);
+ if (isSchemaInternal(schema) && !hasType) {
+ delete (properties as Record)[name];
+ } else {
+ omitUntypedInternalProperties(property);
+ }
+ }
+ }
+
+ for (const [name, child] of Object.entries(node)) {
+ if (name !== "properties") omitUntypedInternalProperties(child);
+ }
+}
+
function requiresArgumentNullCheck(typeName: string, isRequired: boolean): boolean {
return isRequired && !typeName.endsWith("?") && !isNonNullableCSharpValueType(typeName);
}
@@ -2568,6 +2603,8 @@ function generateRpcCode(
externalJsonSerializableRefs: Map> = new Map(),
externalValueTypes: Set = new Set()
): string {
+ schema = cloneSchemaForCodegen(schema);
+ omitUntypedInternalProperties(schema);
emittedRpcClassSchemas.clear();
emittedRpcEnumResultTypes.clear();
experimentalRpcTypes.clear();
From 8d0a9cc63391cb5d820bd092726c811f1225c4b9 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Sun, 9 Aug 2026 10:28:18 -0400
Subject: [PATCH 09/51] Update @github/copilot to 1.0.79-9 (#2299)
* Update @github/copilot to 1.0.79-9
- Updated nodejs and test harness dependencies
- Re-ran code generators
- Formatted generated code
* Fix factory run listing after CLI update
Pass the generated RPC client's required paging request while preserving the SDK's existing listRuns API and wire behavior.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Bound in-process .NET test cleanup
Fall back to ForceStopAsync when graceful in-process fixture cleanup stalls so a hung session.destroy cannot hold the macOS runner indefinitely. Cover the concurrent graceful/forced shutdown path with a lifetime regression test.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 781f5380-c114-40eb-a599-378b3f15cbea
* Stabilize .NET CLI startup error test
Use a deterministic failing JavaScript CLI fixture instead of relying on the bundled CLI to parse an invalid flag within the TCP startup timeout on loaded Windows runners.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 781f5380-c114-40eb-a599-378b3f15cbea
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Stephen Toub
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 781f5380-c114-40eb-a599-378b3f15cbea
---
dotnet/src/Generated/Rpc.cs | 201 +++++++++---------
dotnet/src/Generated/SessionEvents.cs | 5 +
dotnet/test/E2E/ClientE2ETests.cs | 10 +-
dotnet/test/Harness/E2ETestContext.cs | 18 +-
.../test/Unit/ClientSessionLifetimeTests.cs | 21 ++
go/rpc/zrpc.go | 87 ++++++--
go/rpc/zrpc_encoding.go | 17 ++
go/rpc/zsession_events.go | 2 +
java/pom.xml | 2 +-
java/scripts/codegen/package-lock.json | 72 +++----
java/scripts/codegen/package.json | 2 +-
.../generated/SubagentCompletedEvent.java | 4 +-
.../generated/rpc/FactoryAgentOptions.java | 8 +-
.../copilot/generated/rpc/SandboxConfig.java | 6 +-
.../generated/rpc/SandboxConfigAuth.java | 29 +++
.../generated/rpc/SessionFactoryApi.java | 11 +-
.../rpc/SessionFactoryListRunsParams.java | 10 +-
.../rpc/SessionFactoryListRunsResult.java | 12 +-
nodejs/package-lock.json | 72 +++----
nodejs/package.json | 2 +-
nodejs/samples/package-lock.json | 2 +-
nodejs/src/generated/rpc.ts | 89 ++++++--
nodejs/src/generated/session-events.ts | 4 +
nodejs/src/session.ts | 2 +-
python/copilot/generated/rpc.py | 152 ++++++++++---
python/copilot/generated/session_events.py | 5 +
rust/src/generated/api_types.rs | 79 ++++++-
rust/src/generated/rpc.rs | 14 +-
rust/src/generated/session_events.rs | 3 +
test/harness/package-lock.json | 72 +++----
test/harness/package.json | 2 +-
31 files changed, 712 insertions(+), 303 deletions(-)
create mode 100644 java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfigAuth.java
diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs
index 604ed09600..71d49d5262 100644
--- a/dotnet/src/Generated/Rpc.cs
+++ b/dotnet/src/Generated/Rpc.cs
@@ -2314,11 +2314,6 @@ public sealed class SessionOpenResult
[JsonPropertyName("remoteSessionId")]
public string? RemoteSessionId { get; set; }
- /// In-process SessionClientApi handle for the opened session, returned to CLI callers as a transitional shortcut. Marked internal so the public SDK surface does not expose it; SDK consumers should construct per-session clients from `sessionId` instead.
- [JsonInclude]
- [JsonPropertyName("sessionApi")]
- internal JsonElement? SessionApi { get; set; }
-
/// Opened session ID. Omitted when status is `not_found`.
[JsonPropertyName("sessionId")]
public string? SessionId { get; set; }
@@ -3110,12 +3105,6 @@ public partial class RemoteControlStatusActive : RemoteControlStatus
/// Whether the MC session may steer this session.
[JsonPropertyName("isSteerable")]
public required bool IsSteerable { get; set; }
-
- /// In-process prompt-manager handle (CLI-only optimization). Marked internal: this field is excluded from the public SDK surface. When the CLI migrates to a process-separated SDK, the same bidirectional prompt-routing handshake is expressed via dedicated remote-control RPCs (register/resolve) rather than a shared in-process object.
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [JsonInclude]
- [JsonPropertyName("promptManager")]
- internal JsonElement? PromptManager { get; set; }
}
/// The last setup attempt failed. The singleton is otherwise off.
@@ -3266,31 +3255,18 @@ internal sealed class SessionsStopRemoteControlRequest
[Experimental(Diagnostics.Experimental)]
internal sealed class RegisterExtensionToolsResult
{
- /// In-process unsubscribe function (CLI-only optimization). Marked internal: replaced by an explicit `extensions.unregister` RPC in the SDK migration.
- [JsonInclude]
- [JsonPropertyName("unsubscribe")]
- internal JsonElement Unsubscribe { get; set; }
}
/// Optional registration options.
[Experimental(Diagnostics.Experimental)]
public sealed class SessionsRegisterExtensionToolsOnSessionOptions
{
- /// In-process `() => boolean` gating callback (CLI-only optimization). Marked internal: replaced by runtime-side enable/disable RPCs in the SDK migration.
- [JsonInclude]
- [JsonPropertyName("enabled")]
- internal JsonElement? Enabled { get; set; }
}
/// Params to attach an extension loader's tools to a session.
[Experimental(Diagnostics.Experimental)]
internal sealed class RegisterExtensionToolsParams
{
- /// In-process ExtensionLoader handle (CLI-only optimization). Marked internal: this field is excluded from the public SDK surface. When the CLI migrates to a process-separated SDK, extension discovery/launch moves entirely into the runtime — the CLI passes pure config (search paths, disabled ids) via SessionOptions instead.
- [JsonInclude]
- [JsonPropertyName("loader")]
- internal JsonElement Loader { get; set; }
-
/// Optional registration options.
[JsonPropertyName("options")]
public SessionsRegisterExtensionToolsOnSessionOptions? Options { get; set; }
@@ -3304,11 +3280,6 @@ internal sealed class RegisterExtensionToolsParams
[Experimental(Diagnostics.Experimental)]
internal sealed class ConfigureSessionExtensionsParams
{
- /// In-process ExtensionController delegate (CLI-only optimization). Marked internal: this field is excluded from the public SDK surface. The post-SDK extension surface exposes list/enable/disable/reload via dedicated RPCs served by the runtime.
- [JsonInclude]
- [JsonPropertyName("controller")]
- internal JsonElement? Controller { get; set; }
-
/// Session to attach the extension controller delegate to.
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = string.Empty;
@@ -4309,6 +4280,7 @@ internal sealed class CanvasActionInvokeRequest
[JsonDerivedType(typeof(FactoryRunFailureFactoryLimitReached), "factory_limit_reached")]
[JsonDerivedType(typeof(FactoryRunFailureFactoryResumeDeclined), "factory_resume_declined")]
[JsonDerivedType(typeof(FactoryRunFailureFactoryDurableFailure), "factory_durable_failure")]
+[JsonDerivedType(typeof(FactoryRunFailureFactoryAccountingIncomplete), "factory_accounting_incomplete")]
public partial class FactoryRunFailure
{
/// The type discriminator.
@@ -4376,6 +4348,24 @@ public partial class FactoryRunFailureFactoryDurableFailure : FactoryRunFailure
public required string RunId { get; set; }
}
+/// The run stopped because its usage accounting could not be completed.
+/// The factory_accounting_incomplete variant of .
+[Experimental(Diagnostics.Experimental)]
+public partial class FactoryRunFailureFactoryAccountingIncomplete : FactoryRunFailure
+{
+ ///
+ [JsonIgnore]
+ public override string Type => "factory_accounting_incomplete";
+
+ /// Confirmed usage in nano-AIU, representing the floor of what the run spent.
+ [JsonPropertyName("drainedNanoAiu")]
+ public required long DrainedNanoAiu { get; set; }
+
+ /// Factory run identifier.
+ [JsonPropertyName("runId")]
+ public required string RunId { get; set; }
+}
+
/// Complete current or terminal factory run envelope.
[Experimental(Diagnostics.Experimental)]
public sealed class FactoryRunResult
@@ -4660,19 +4650,47 @@ public sealed class FactoryRunSummary
public long UpdatedAt { get; set; }
}
-/// Factory runs in durable creation order.
+/// A page of factory runs in durable creation order.
[Experimental(Diagnostics.Experimental)]
public sealed class FactoryListRunsResult
{
+ /// Whether terminal runs newer than this page exist.
+ [JsonPropertyName("hasMoreNewer")]
+ public bool? HasMoreNewer { get; set; }
+
+ /// Newest terminal-run cursor in this page, or null when the terminal window is empty.
+ [JsonPropertyName("newestSeq")]
+ public long? NewestSeq { get; set; }
+
+ /// Oldest terminal-run cursor in this page, or null when the terminal window is empty.
+ [JsonPropertyName("oldestSeq")]
+ public long? OldestSeq { get; set; }
+
+ /// Number of terminal runs older than this page.
+ [JsonPropertyName("omittedOlder")]
+ public long? OmittedOlder { get; set; }
+
/// Gets or sets the runs value.
[JsonPropertyName("runs")]
public IList Runs { get => field ??= []; set; }
}
-/// Empty parameters for listing factory runs.
+/// Parameters for paging factory runs.
[Experimental(Diagnostics.Experimental)]
internal sealed class FactoryListRunsRequest
{
+ /// Exclusive forward cursor.
+ [JsonPropertyName("afterSeq")]
+ public long? AfterSeq { get; set; }
+
+ /// Exclusive backward cursor.
+ [JsonPropertyName("beforeSeq")]
+ public long? BeforeSeq { get; set; }
+
+ /// Maximum terminal runs to return. Defaults to 200 and is capped at 500.
+ [JsonPropertyName("limit")]
+ public int? Limit { get; set; }
+
/// Target session identifier.
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = string.Empty;
@@ -5042,6 +5060,14 @@ public sealed class FactoryAgentResult
[Experimental(Diagnostics.Experimental)]
public sealed class FactoryAgentOptions
{
+ /// Optional custom agent name for the subagent. This field is accepted but not yet honored.
+ [JsonPropertyName("agent")]
+ public string? Agent { get; set; }
+
+ /// Optional context tier for the subagent. This field is accepted but not yet honored.
+ [JsonPropertyName("contextTier")]
+ public ContextTier? ContextTier { get; set; }
+
/// Optional label distinguishing otherwise identical memoized agent calls.
[JsonPropertyName("label")]
public string? Label { get; set; }
@@ -5050,6 +5076,10 @@ public sealed class FactoryAgentOptions
[JsonPropertyName("model")]
public string? Model { get; set; }
+ /// Optional reasoning effort for the subagent. This field is accepted but not yet honored.
+ [JsonPropertyName("reasoningEffort")]
+ public string? ReasoningEffort { get; set; }
+
/// Optional JSON Schema for structured agent output.
[JsonPropertyName("schema")]
public JsonElement? Schema { get; set; }
@@ -7162,11 +7192,6 @@ internal sealed class McpStartServersResult
[Experimental(Diagnostics.Experimental)]
internal sealed class McpReloadWithConfigRequest
{
- /// Opaque runtime MCP reload configuration. Marked internal: an in-process runtime shape (reloadMcpServers throws over the wire).
- [JsonInclude]
- [JsonPropertyName("config")]
- internal JsonElement Config { get; set; }
-
/// Target session identifier.
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = string.Empty;
@@ -7301,11 +7326,6 @@ internal sealed class McpConfigureGitHubResult
[Experimental(Diagnostics.Experimental)]
internal sealed class McpConfigureGitHubRequest
{
- /// Opaque runtime auth info for GitHub MCP configuration. Marked internal: an in-process runtime shape (configureGitHubMcp is a no-op over the wire).
- [JsonInclude]
- [JsonPropertyName("authInfo")]
- internal JsonElement AuthInfo { get; set; }
-
/// Target session identifier.
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = string.Empty;
@@ -7362,16 +7382,6 @@ internal sealed class McpStopServerRequest
[Experimental(Diagnostics.Experimental)]
internal sealed class McpRegisterExternalClientRequest
{
- /// In-process MCP Client instance. Marked internal: cannot be serialized across the JSON-RPC boundary.
- [JsonInclude]
- [JsonPropertyName("client")]
- internal JsonElement Client { get; set; }
-
- /// In-process server config (MCPServerConfig) paired with the in-process client/transport. Marked internal alongside its companions.
- [JsonInclude]
- [JsonPropertyName("config")]
- internal JsonElement Config { get; set; }
-
/// Logical server name for the external client.
[JsonPropertyName("serverName")]
public string ServerName { get; set; } = string.Empty;
@@ -7379,11 +7389,6 @@ internal sealed class McpRegisterExternalClientRequest
/// Target session identifier.
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = string.Empty;
-
- /// In-process MCP Transport instance. Marked internal: cannot be serialized across the JSON-RPC boundary.
- [JsonInclude]
- [JsonPropertyName("transport")]
- internal JsonElement Transport { get; set; }
}
/// Server name identifying the external client to remove.
@@ -8649,6 +8654,19 @@ public sealed class ProviderConfig
public string? WireModel { get; set; }
}
+/// Credential-injection capability flags applied while the sandbox is enabled.
+[Experimental(Diagnostics.Experimental)]
+public sealed class SandboxConfigAuth
+{
+ /// Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in).
+ [JsonPropertyName("gh")]
+ public bool? Gh { get; set; }
+
+ /// Whether to inject git credentials as an `http.<url>.extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. github.com is served by the Copilot token; every other forge (Azure DevOps, GitHub Enterprise Server, GitLab, ...) by a credential the host resolves from the user's own helper before the sandbox is applied. Default: false (opt-in).
+ [JsonPropertyName("git")]
+ public bool? Git { get; set; }
+}
+
/// macOS seatbelt experimental options.
[Experimental(Diagnostics.Experimental)]
public sealed class SandboxConfigUserPolicyExperimentalSeatbelt
@@ -8764,18 +8782,14 @@ public sealed class SandboxConfig
[JsonPropertyName("allowDevToolAccess")]
public bool? AllowDevToolAccess { get; set; }
+ /// Credential-injection capability flags.
+ [JsonPropertyName("auth")]
+ public SandboxConfigAuth? Auth { get; set; }
+
/// Whether sandboxing is enabled for the session.
[JsonPropertyName("enabled")]
public bool Enabled { get; set; }
- /// Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in).
- [JsonPropertyName("ghAuth")]
- public bool? GhAuth { get; set; }
-
- /// Whether to inject the Copilot GitHub token as an `http.<host>.extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. Default: false (opt-in).
- [JsonPropertyName("gitAuth")]
- public bool? GitAuth { get; set; }
-
/// User-managed sandbox policy fragment merged into the auto-discovered base policy.
[JsonPropertyName("userPolicy")]
public SandboxConfigUserPolicy? UserPolicy { get; set; }
@@ -10193,16 +10207,6 @@ public sealed class UIEphemeralQueryResult
[Experimental(Diagnostics.Experimental)]
internal sealed class UIEphemeralQueryRequest
{
- /// In-process `AbortSignal` forwarded to the model client to cancel an in-flight request. Marked internal: excluded from the public SDK surface. Replaced by an explicit cancellation token + cancel RPC in the SDK migration.
- [JsonInclude]
- [JsonPropertyName("abortSignal")]
- internal JsonElement? AbortSignal { get; set; }
-
- /// In-process streaming callback `(text) => void` invoked with each token as the model emits it. Marked internal: excluded from the public SDK surface. In a process-separated SDK this is replaced by a streaming RPC that yields chunks and a final answer.
- [JsonInclude]
- [JsonPropertyName("onChunk")]
- internal JsonElement? OnChunk { get; set; }
-
/// Question to answer from the current conversation context.
[JsonPropertyName("question")]
public string Question { get; set; } = string.Empty;
@@ -24646,28 +24650,25 @@ public async Task GetRemoteControlStatusAsync(Cancell
/// Registers extension-provided tools on the given session, gated by an optional `enabled` callback. Returns an opaque unsubscribe function the caller must invoke to deregister the tools when the extension is torn down. Marked internal because `loader`, `enabled`, and the returned `unsubscribe` are in-process handles that cannot cross the JSON-RPC boundary. Disappears once extension discovery / launch / tool registration are owned by the runtime: SDK consumers will pass pure config (search paths, disabled ids) via `SessionOptions` and the runtime will resolve, launch, register, and tear down extensions itself.
/// Session to register extension tools on.
- /// In-process ExtensionLoader handle (CLI-only optimization). Marked internal: this field is excluded from the public SDK surface. When the CLI migrates to a process-separated SDK, extension discovery/launch moves entirely into the runtime — the CLI passes pure config (search paths, disabled ids) via SessionOptions instead.
/// Optional registration options.
/// The to monitor for cancellation requests. The default is .
/// Handle for releasing the extension tool registration.
- internal async Task RegisterExtensionToolsOnSessionAsync(string sessionId, object loader, SessionsRegisterExtensionToolsOnSessionOptions? options = null, CancellationToken cancellationToken = default)
+ internal async Task RegisterExtensionToolsOnSessionAsync(string sessionId, SessionsRegisterExtensionToolsOnSessionOptions? options = null, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(sessionId);
- ArgumentNullException.ThrowIfNull(loader);
- var request = new RegisterExtensionToolsParams { SessionId = sessionId, Loader = CopilotClient.ToJsonElementForWire(loader)!.Value, Options = options };
+ var request = new RegisterExtensionToolsParams { SessionId = sessionId, Options = options };
return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.registerExtensionToolsOnSession", [request], cancellationToken);
}
/// Attaches (or detaches) an in-process ExtensionController delegate for the given session, used by shared-API surfaces that need to query or modify the session's extension state. Pass `controller: undefined` to detach. Marked internal because the controller is an in-process object that cannot cross the JSON-RPC boundary. Disappears alongside `registerExtensionToolsOnSession`: once the runtime owns extension management, the public surface exposes list/enable/disable/reload as dedicated RPCs served by the runtime.
/// Session to attach the extension controller delegate to.
- /// In-process ExtensionController delegate (CLI-only optimization). Marked internal: this field is excluded from the public SDK surface. The post-SDK extension surface exposes list/enable/disable/reload via dedicated RPCs served by the runtime.
/// The to monitor for cancellation requests. The default is .
- internal async Task ConfigureSessionExtensionsAsync(string sessionId, object? controller = null, CancellationToken cancellationToken = default)
+ internal async Task ConfigureSessionExtensionsAsync(string sessionId, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(sessionId);
- var request = new ConfigureSessionExtensionsParams { SessionId = sessionId, Controller = CopilotClient.ToJsonElementForWire(controller) };
+ var request = new ConfigureSessionExtensionsParams { SessionId = sessionId };
await CopilotClient.InvokeRpcAsync(_rpc, "sessions.configureSessionExtensions", [request], cancellationToken);
}
}
@@ -25299,13 +25300,16 @@ public async Task GetRunAsync(string runId, CancellationToken
}
/// Lists durable factory runs for this session in creation order.
+ /// Exclusive forward cursor.
+ /// Exclusive backward cursor.
+ /// Maximum terminal runs to return. Defaults to 200 and is capped at 500.
/// The to monitor for cancellation requests. The default is .
- /// Factory runs in durable creation order.
- public async Task ListRunsAsync(CancellationToken cancellationToken = default)
+ /// A page of factory runs in durable creation order.
+ public async Task ListRunsAsync(long? afterSeq = null, long? beforeSeq = null, int? limit = null, CancellationToken cancellationToken = default)
{
_session.ThrowIfDisposed();
- var request = new FactoryListRunsRequest { SessionId = _session.SessionId };
+ var request = new FactoryListRunsRequest { SessionId = _session.SessionId, AfterSeq = afterSeq, BeforeSeq = beforeSeq, Limit = limit };
return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.factory.listRuns", [request], cancellationToken);
}
@@ -26337,15 +26341,13 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default)
}
/// Reloads MCP server connections for the session with an explicit host-provided configuration.
- /// Opaque runtime MCP reload configuration. Marked internal: an in-process runtime shape (reloadMcpServers throws over the wire).
/// The to monitor for cancellation requests. The default is .
/// MCP server startup filtering result.
- internal async Task ReloadWithConfigAsync(object config, CancellationToken cancellationToken = default)
+ internal async Task ReloadWithConfigAsync(CancellationToken cancellationToken = default)
{
- ArgumentNullException.ThrowIfNull(config);
_session.ThrowIfDisposed();
- var request = new McpReloadWithConfigRequest { SessionId = _session.SessionId, Config = CopilotClient.ToJsonElementForWire(config)!.Value };
+ var request = new McpReloadWithConfigRequest { SessionId = _session.SessionId };
return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.reloadWithConfig", [request], cancellationToken);
}
@@ -26405,15 +26407,13 @@ public async Task RemoveGitHubAsync(CancellationToken can
}
/// Configures the built-in GitHub MCP server for the session's current auth context.
- /// Opaque runtime auth info for GitHub MCP configuration. Marked internal: an in-process runtime shape (configureGitHubMcp is a no-op over the wire).
/// The to monitor for cancellation requests. The default is .
/// Result of configuring GitHub MCP.
- internal async Task ConfigureGitHubAsync(object authInfo, CancellationToken cancellationToken = default)
+ internal async Task ConfigureGitHubAsync(CancellationToken cancellationToken = default)
{
- ArgumentNullException.ThrowIfNull(authInfo);
_session.ThrowIfDisposed();
- var request = new McpConfigureGitHubRequest { SessionId = _session.SessionId, AuthInfo = CopilotClient.ToJsonElementForWire(authInfo)!.Value };
+ var request = new McpConfigureGitHubRequest { SessionId = _session.SessionId };
return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.configureGitHub", [request], cancellationToken);
}
@@ -26457,19 +26457,13 @@ public async Task StopServerAsync(string serverName, CancellationToken cancellat
/// Registers a pre-connected external MCP client (e.g. IDE) on the session's host. The caller retains lifecycle ownership of the client and transport. Marked internal because the `client` and `transport` arguments are in-process MCP SDK instances that cannot be serialized across the JSON-RPC boundary; once the CLI moves on top of the SDK, external clients will be expressed as transport configs the runtime can construct itself.
/// Logical server name for the external client.
- /// In-process MCP Client instance. Marked internal: cannot be serialized across the JSON-RPC boundary.
- /// In-process MCP Transport instance. Marked internal: cannot be serialized across the JSON-RPC boundary.
- /// In-process server config (MCPServerConfig) paired with the in-process client/transport. Marked internal alongside its companions.
/// The to monitor for cancellation requests. The default is .
- internal async Task RegisterExternalClientAsync(string serverName, object client, object transport, object config, CancellationToken cancellationToken = default)
+ internal async Task RegisterExternalClientAsync(string serverName, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(serverName);
- ArgumentNullException.ThrowIfNull(client);
- ArgumentNullException.ThrowIfNull(transport);
- ArgumentNullException.ThrowIfNull(config);
_session.ThrowIfDisposed();
- var request = new McpRegisterExternalClientRequest { SessionId = _session.SessionId, ServerName = serverName, Client = CopilotClient.ToJsonElementForWire(client)!.Value, Transport = CopilotClient.ToJsonElementForWire(transport)!.Value, Config = CopilotClient.ToJsonElementForWire(config)!.Value };
+ var request = new McpRegisterExternalClientRequest { SessionId = _session.SessionId, ServerName = serverName };
await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.registerExternalClient", [request], cancellationToken);
}
@@ -27223,16 +27217,14 @@ internal UiApi(CopilotSession session)
/// Runs a transient no-tools model query against the current conversation context.
/// Question to answer from the current conversation context.
- /// In-process streaming callback `(text) => void` invoked with each token as the model emits it. Marked internal: excluded from the public SDK surface. In a process-separated SDK this is replaced by a streaming RPC that yields chunks and a final answer.
- /// In-process `AbortSignal` forwarded to the model client to cancel an in-flight request. Marked internal: excluded from the public SDK surface. Replaced by an explicit cancellation token + cancel RPC in the SDK migration.
/// The to monitor for cancellation requests. The default is .
/// Transient answer generated from current conversation context.
- public async Task EphemeralQueryAsync(string question, object? onChunk = null, object? abortSignal = null, CancellationToken cancellationToken = default)
+ public async Task EphemeralQueryAsync(string question, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(question);
_session.ThrowIfDisposed();
- var request = new UIEphemeralQueryRequest { SessionId = _session.SessionId, Question = question, OnChunk = CopilotClient.ToJsonElementForWire(onChunk), AbortSignal = CopilotClient.ToJsonElementForWire(abortSignal) };
+ var request = new UIEphemeralQueryRequest { SessionId = _session.SessionId, Question = question };
return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.ephemeralQuery", [request], cancellationToken);
}
@@ -29818,6 +29810,7 @@ public static void RegisterClientGlobalApiHandlers(JsonRpc rpc, ClientGlobalApiH
[JsonSerializable(typeof(RemoteSessionMetadataValue))]
[JsonSerializable(typeof(RunOptions))]
[JsonSerializable(typeof(SandboxConfig))]
+[JsonSerializable(typeof(SandboxConfigAuth))]
[JsonSerializable(typeof(SandboxConfigUserPolicy))]
[JsonSerializable(typeof(SandboxConfigUserPolicyExperimental))]
[JsonSerializable(typeof(SandboxConfigUserPolicyExperimentalSeatbelt))]
diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs
index 47c13846fb..90eb08263d 100644
--- a/dotnet/src/Generated/SessionEvents.cs
+++ b/dotnet/src/Generated/SessionEvents.cs
@@ -3553,6 +3553,11 @@ public sealed partial class SubagentCompletedData
[JsonPropertyName("agentName")]
public required string AgentName { get; set; }
+ /// Whether the sub-agent was torn down by cancellation - its own abort, or an ancestor being killed - instead of finishing its work. Cancellation is not a failure, so the run still reports completion; this distinguishes a torn-down sub-agent from one that ran to the end.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("cancelled")]
+ public bool? Cancelled { get; set; }
+
/// Wall-clock duration of the sub-agent execution in milliseconds.
[JsonConverter(typeof(MillisecondsTimeSpanConverter))]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
diff --git a/dotnet/test/E2E/ClientE2ETests.cs b/dotnet/test/E2E/ClientE2ETests.cs
index d166223d65..b6bdfd90fd 100644
--- a/dotnet/test/E2E/ClientE2ETests.cs
+++ b/dotnet/test/E2E/ClientE2ETests.cs
@@ -11,6 +11,9 @@ namespace GitHub.Copilot.Test.E2E;
// Other test classes should instead inherit from E2ETestBase
public class ClientE2ETests(E2ETestFixture fixture) : IClassFixture
{
+ private const string FailingCliScript =
+ "process.stderr.write('nonexistent test flag on stderr\\n'); process.exit(1);";
+
private E2ETestContext Ctx => fixture.Ctx;
[Theory]
@@ -177,11 +180,14 @@ public async Task Should_Not_Throw_When_Disposing_Session_After_Stopping_Client(
[InlineData(false)] // TCP transport
public async Task Should_Report_Error_With_Stderr_When_CLI_Fails_To_Start(bool useStdio)
{
+ var cliPath = Path.Join(Ctx.WorkDir, $"failing-cli-{Guid.NewGuid():N}.js");
+ await File.WriteAllTextAsync(cliPath, FailingCliScript);
+
var client = new CopilotClient(new CopilotClientOptions
{
Connection = useStdio
- ? RuntimeConnection.ForStdio(args: ["--nonexistent-flag-for-testing"])
- : RuntimeConnection.ForTcp(args: ["--nonexistent-flag-for-testing"])
+ ? RuntimeConnection.ForStdio(path: cliPath)
+ : RuntimeConnection.ForTcp(path: cliPath)
});
var ex = await Assert.ThrowsAsync(() => client.StartAsync());
diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs
index af34de6ec7..1c88d809b1 100644
--- a/dotnet/test/Harness/E2ETestContext.cs
+++ b/dotnet/test/Harness/E2ETestContext.cs
@@ -13,6 +13,7 @@ namespace GitHub.Copilot.Test.Harness;
public sealed class E2ETestContext : IAsyncDisposable
{
private const string DefaultGitHubToken = "fake-token-for-e2e-tests";
+ private static readonly TimeSpan s_gracefulClientStopTimeout = TimeSpan.FromSeconds(30);
public string HomeDir { get; }
public string WorkDir { get; }
@@ -549,7 +550,6 @@ private static bool IsInProcess(RuntimeConnection? connection)
return false;
}
- // Inproc holds the session-store SQLite handle in-process; graceful StopAsync releases it so the temp-dir delete succeeds on Windows.
private static async Task StopClientForCleanupAsync(CopilotClient client)
{
var isInProcess = string.Equals(
@@ -558,7 +558,21 @@ private static async Task StopClientForCleanupAsync(CopilotClient client)
StringComparison.OrdinalIgnoreCase);
if (isInProcess)
{
- await client.StopAsync();
+ var gracefulStop = client.StopAsync();
+ try
+ {
+ await gracefulStop.WaitAsync(s_gracefulClientStopTimeout);
+ }
+ catch (TimeoutException)
+ {
+ Console.Error.WriteLine(
+ $"Graceful in-process client cleanup exceeded {s_gracefulClientStopTimeout}; forcing shutdown.");
+ await client.ForceStopAsync();
+
+ // Disposing the connection completes any session.destroy RPC that
+ // blocked graceful cleanup. Observe that task before continuing.
+ await gracefulStop.WaitAsync(s_gracefulClientStopTimeout);
+ }
}
else
{
diff --git a/dotnet/test/Unit/ClientSessionLifetimeTests.cs b/dotnet/test/Unit/ClientSessionLifetimeTests.cs
index d4b4100b4c..da04ff38bb 100644
--- a/dotnet/test/Unit/ClientSessionLifetimeTests.cs
+++ b/dotnet/test/Unit/ClientSessionLifetimeTests.cs
@@ -183,6 +183,27 @@ public async Task StopAsync_Keeps_Session_Rooted_Until_Destroy_Completes()
AssertSessionCount(client, sessions: 0);
}
+ [Fact]
+ public async Task ForceStopAsync_Unblocks_StopAsync_When_Session_Destroy_Hangs()
+ {
+ await using var server = await FakeCopilotServer.StartAsync();
+ server.DelayDestroy();
+ await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) });
+
+ _ = await client.CreateSessionAsync(new SessionConfig
+ {
+ OnPermissionRequest = PermissionHandler.ApproveAll
+ });
+
+ var stopTask = client.StopAsync();
+ await server.DestroyStarted;
+
+ await client.ForceStopAsync();
+ await stopTask.WaitAsync(TimeSpan.FromSeconds(5));
+
+ AssertSessionCount(client, sessions: 0);
+ }
+
[Fact]
public async Task ResumeSessionAsync_Throws_When_Same_Client_Already_Tracks_Session()
{
diff --git a/go/rpc/zrpc.go b/go/rpc/zrpc.go
index 6de48d06c1..622c7a0cbc 100644
--- a/go/rpc/zrpc.go
+++ b/go/rpc/zrpc.go
@@ -2452,10 +2452,16 @@ type FactoryAckResult struct {
// Experimental: FactoryAgentOptions is part of an experimental API and may change or be
// removed.
type FactoryAgentOptions struct {
+ // Optional custom agent name for the subagent. This field is accepted but not yet honored.
+ Agent *string `json:"agent,omitempty"`
+ // Optional context tier for the subagent. This field is accepted but not yet honored.
+ ContextTier *ContextTier `json:"contextTier,omitempty"`
// Optional label distinguishing otherwise identical memoized agent calls.
Label *string `json:"label,omitempty"`
// Optional model identifier for the subagent.
Model *string `json:"model,omitempty"`
+ // Optional reasoning effort for the subagent. This field is accepted but not yet honored.
+ ReasoningEffort *string `json:"reasoningEffort,omitempty"`
// Optional JSON Schema for structured agent output.
Schema any `json:"schema,omitempty"`
}
@@ -2611,17 +2617,31 @@ type FactoryJournalPutRequest struct {
RunID string `json:"runId"`
}
-// Empty parameters for listing factory runs.
+// Parameters for paging factory runs.
// Experimental: FactoryListRunsRequest is part of an experimental API and may change or be
// removed.
type FactoryListRunsRequest struct {
+ // Exclusive forward cursor.
+ AfterSeq *int64 `json:"afterSeq,omitempty"`
+ // Exclusive backward cursor.
+ BeforeSeq *int64 `json:"beforeSeq,omitempty"`
+ // Maximum terminal runs to return. Defaults to 200 and is capped at 500.
+ Limit *int32 `json:"limit,omitempty"`
}
-// Factory runs in durable creation order.
+// A page of factory runs in durable creation order.
// Experimental: FactoryListRunsResult is part of an experimental API and may change or be
// removed.
type FactoryListRunsResult struct {
- Runs []FactoryRunSummary `json:"runs"`
+ // Whether terminal runs newer than this page exist.
+ HasMoreNewer *bool `json:"hasMoreNewer,omitempty"`
+ // Newest terminal-run cursor in this page, or null when the terminal window is empty.
+ NewestSeq *int64 `json:"newestSeq,omitempty"`
+ // Oldest terminal-run cursor in this page, or null when the terminal window is empty.
+ OldestSeq *int64 `json:"oldestSeq,omitempty"`
+ // Number of terminal runs older than this page.
+ OmittedOlder *int64 `json:"omittedOlder,omitempty"`
+ Runs []FactoryRunSummary `json:"runs"`
}
// One ordered factory progress line.
@@ -2772,6 +2792,19 @@ func (r RawFactoryRunFailureData) Type() FactoryRunFailureType {
return r.Discriminator
}
+// The run stopped because its usage accounting could not be completed.
+type FactoryRunFailureFactoryAccountingIncomplete struct {
+ // Confirmed usage in nano-AIU, representing the floor of what the run spent.
+ DrainedNanoAiu int64 `json:"drainedNanoAiu"`
+ // Factory run identifier.
+ RunID string `json:"runId"`
+}
+
+func (FactoryRunFailureFactoryAccountingIncomplete) factoryRunFailure() {}
+func (FactoryRunFailureFactoryAccountingIncomplete) Type() FactoryRunFailureType {
+ return FactoryRunFailureTypeFactoryAccountingIncomplete
+}
+
type FactoryRunFailureFactoryDurableFailure struct {
// Stable failure code.
Code string `json:"code"`
@@ -8208,19 +8241,29 @@ type SandboxConfig struct {
// Cargo lock files granted read-write. Default: true (enabled by default; set to false to
// opt out).
AllowDevToolAccess *bool `json:"allowDevToolAccess,omitempty"`
+ // Credential-injection capability flags.
+ Auth *SandboxConfigAuth `json:"auth,omitempty"`
// Whether sandboxing is enabled for the session.
Enabled bool `json:"enabled"`
- // Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the
- // OS keyring the sandbox blocks. Default: false (opt-in).
- GhAuth *bool `json:"ghAuth,omitempty"`
- // Whether to inject the Copilot GitHub token as an `http..extraheader` so
- // authenticated HTTPS git works inside the sandbox without the shell-based credential
- // helper the sandbox blocks. Default: false (opt-in).
- GitAuth *bool `json:"gitAuth,omitempty"`
// User-managed sandbox policy fragment merged into the auto-discovered base policy.
UserPolicy *SandboxConfigUserPolicy `json:"userPolicy,omitempty"`
}
+// Credential-injection capability flags applied while the sandbox is enabled.
+// Experimental: SandboxConfigAuth is part of an experimental API and may change or be
+// removed.
+type SandboxConfigAuth struct {
+ // Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the
+ // OS keyring the sandbox blocks. Default: false (opt-in).
+ Gh *bool `json:"gh,omitempty"`
+ // Whether to inject git credentials as an `http..extraheader` so authenticated HTTPS
+ // git works inside the sandbox without the shell-based credential helper the sandbox
+ // blocks. github.com is served by the Copilot token; every other forge (Azure DevOps,
+ // GitHub Enterprise Server, GitLab, ...) by a credential the host resolves from the user's
+ // own helper before the sandbox is applied. Default: false (opt-in).
+ Git *bool `json:"git,omitempty"`
+}
+
// User-managed sandbox policy fragment merged into the auto-discovered base policy.
// Experimental: SandboxConfigUserPolicy is part of an experimental API and may change or be
// removed.
@@ -13525,9 +13568,10 @@ const (
type FactoryRunFailureType string
const (
- FactoryRunFailureTypeFactoryDurableFailure FactoryRunFailureType = "factory_durable_failure"
- FactoryRunFailureTypeFactoryLimitReached FactoryRunFailureType = "factory_limit_reached"
- FactoryRunFailureTypeFactoryResumeDeclined FactoryRunFailureType = "factory_resume_declined"
+ FactoryRunFailureTypeFactoryAccountingIncomplete FactoryRunFailureType = "factory_accounting_incomplete"
+ FactoryRunFailureTypeFactoryDurableFailure FactoryRunFailureType = "factory_durable_failure"
+ FactoryRunFailureTypeFactoryLimitReached FactoryRunFailureType = "factory_limit_reached"
+ FactoryRunFailureTypeFactoryResumeDeclined FactoryRunFailureType = "factory_resume_declined"
)
// Current or terminal state of a factory run.
@@ -18218,9 +18262,22 @@ func (a *FactoryAPI) GetRunProgress(ctx context.Context, params *FactoryGetRunPr
//
// RPC method: session.factory.listRuns.
//
-// Returns: Factory runs in durable creation order.
-func (a *FactoryAPI) ListRuns(ctx context.Context) (*FactoryListRunsResult, error) {
+// Parameters: Parameters for paging factory runs.
+//
+// Returns: A page of factory runs in durable creation order.
+func (a *FactoryAPI) ListRuns(ctx context.Context, params *FactoryListRunsRequest) (*FactoryListRunsResult, error) {
req := map[string]any{"sessionId": a.sessionID}
+ if params != nil {
+ if params.AfterSeq != nil {
+ req["afterSeq"] = *params.AfterSeq
+ }
+ if params.BeforeSeq != nil {
+ req["beforeSeq"] = *params.BeforeSeq
+ }
+ if params.Limit != nil {
+ req["limit"] = *params.Limit
+ }
+ }
raw, err := a.client.Request(ctx, "session.factory.listRuns", req)
if err != nil {
return nil, err
diff --git a/go/rpc/zrpc_encoding.go b/go/rpc/zrpc_encoding.go
index 8b69c28c2a..29c253e1cc 100644
--- a/go/rpc/zrpc_encoding.go
+++ b/go/rpc/zrpc_encoding.go
@@ -1075,6 +1075,12 @@ func unmarshalFactoryRunFailure(data []byte) (FactoryRunFailure, error) {
}
switch raw.Type {
+ case FactoryRunFailureTypeFactoryAccountingIncomplete:
+ var d FactoryRunFailureFactoryAccountingIncomplete
+ if err := json.Unmarshal(data, &d); err != nil {
+ return nil, err
+ }
+ return &d, nil
case FactoryRunFailureTypeFactoryDurableFailure:
var d FactoryRunFailureFactoryDurableFailure
if err := json.Unmarshal(data, &d); err != nil {
@@ -1109,6 +1115,17 @@ func (r RawFactoryRunFailureData) MarshalJSON() ([]byte, error) {
})
}
+func (r FactoryRunFailureFactoryAccountingIncomplete) MarshalJSON() ([]byte, error) {
+ type alias FactoryRunFailureFactoryAccountingIncomplete
+ return json.Marshal(struct {
+ Type FactoryRunFailureType `json:"type"`
+ alias
+ }{
+ Type: r.Type(),
+ alias: alias(r),
+ })
+}
+
func (r FactoryRunFailureFactoryDurableFailure) MarshalJSON() ([]byte, error) {
type alias FactoryRunFailureFactoryDurableFailure
return json.Marshal(struct {
diff --git a/go/rpc/zsession_events.go b/go/rpc/zsession_events.go
index 0034af6a7f..05c8fd5489 100644
--- a/go/rpc/zsession_events.go
+++ b/go/rpc/zsession_events.go
@@ -1882,6 +1882,8 @@ type SubagentCompletedData struct {
AgentDisplayName string `json:"agentDisplayName"`
// Internal name of the sub-agent
AgentName string `json:"agentName"`
+ // Whether the sub-agent was torn down by cancellation - its own abort, or an ancestor being killed - instead of finishing its work. Cancellation is not a failure, so the run still reports completion; this distinguishes a torn-down sub-agent from one that ran to the end.
+ Cancelled *bool `json:"cancelled,omitempty"`
// Wall-clock duration of the sub-agent execution in milliseconds
DurationMs *int64 `json:"durationMs,omitempty"`
// Model used by the sub-agent
diff --git a/java/pom.xml b/java/pom.xml
index 3a235705ff..c5e9f62ad6 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -88,7 +88,7 @@
DO NOT EDIT MANUALLY. Updated by the update-copilot-dependency
workflow.
-->
- ^1.0.79-6
+ ^1.0.79-9
diff --git a/java/scripts/codegen/package-lock.json b/java/scripts/codegen/package-lock.json
index 5b3197f6f2..d4824febaf 100644
--- a/java/scripts/codegen/package-lock.json
+++ b/java/scripts/codegen/package-lock.json
@@ -6,7 +6,7 @@
"": {
"name": "copilot-sdk-java-codegen",
"dependencies": {
- "@github/copilot": "^1.0.79-6",
+ "@github/copilot": "^1.0.79-9",
"json-schema": "^0.4.0",
"tsx": "^4.23.1"
}
@@ -428,9 +428,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-6.tgz",
- "integrity": "sha512-per2cqu8WYuRXXvdU38cYZ7lUSQP5uBDY2QfFZow9FgGOyOToEWz+ykw2NYVKMnx0u1gIiI20Ovl4zec9Dob6w==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-9.tgz",
+ "integrity": "sha512-1QRRV3z1HA8sr3JUo4e2l+zFVbIGIOqnmTwzdJ+ilfr+mkmC7LYWkJxV3+j+zN0nq8JAgusSL/Schc43MPIqug==",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"detect-libc": "^2.1.2"
@@ -439,20 +439,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.79-6",
- "@github/copilot-darwin-x64": "1.0.79-6",
- "@github/copilot-linux-arm64": "1.0.79-6",
- "@github/copilot-linux-x64": "1.0.79-6",
- "@github/copilot-linuxmusl-arm64": "1.0.79-6",
- "@github/copilot-linuxmusl-x64": "1.0.79-6",
- "@github/copilot-win32-arm64": "1.0.79-6",
- "@github/copilot-win32-x64": "1.0.79-6"
+ "@github/copilot-darwin-arm64": "1.0.79-9",
+ "@github/copilot-darwin-x64": "1.0.79-9",
+ "@github/copilot-linux-arm64": "1.0.79-9",
+ "@github/copilot-linux-x64": "1.0.79-9",
+ "@github/copilot-linuxmusl-arm64": "1.0.79-9",
+ "@github/copilot-linuxmusl-x64": "1.0.79-9",
+ "@github/copilot-win32-arm64": "1.0.79-9",
+ "@github/copilot-win32-x64": "1.0.79-9"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-6.tgz",
- "integrity": "sha512-22aYilTJsiZX4w55DPXHvJFHSNwZWGip4DcQCQTvzzVIGc8MjlCQVModE9B6ElGs18hUaM3NH4piTYYT0HqNGQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-DBTtv06Lpka1R+bkYfCWH38838b66bTLvsRsNjSuQV9AzgMPHjIn+Q2wAmU89rUyw5ej9iCIL5ppps+roi7qRw==",
"cpu": [
"arm64"
],
@@ -466,9 +466,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-6.tgz",
- "integrity": "sha512-1ESqmLenOGkfD4KwgxtUZh+Wt5+qKwtLHGpfpRl+d/BSKj4cNo9FUO2vFEmF3zQefpmady3vmDURSdi65hlC+w==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-9.tgz",
+ "integrity": "sha512-j+XOqtVWa0EZ8lBR+xIsPVI7ErpDepgr3WuSfUCkC9fOdvnVJ1rbyBY3gCM/urY4wJNdbHc4t1vN9MjtRNpTGA==",
"cpu": [
"x64"
],
@@ -482,9 +482,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-6.tgz",
- "integrity": "sha512-R8ZmfoJuOj1CT0zamAnRJi7nxhUPRFi3vo3dWlzSkto0Uwez+j2IJmyGIZEZbN65BJJJMD2/kg0GZQG+l+PmUA==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-eYsJlokogYeXo2tCwqoDW+rELbLs0ht7b3R1nrl9odO6U6ZabIm6BilSLSxjWCtE1ZpqDLmdJbOV0/6cQwjvlA==",
"cpu": [
"arm64"
],
@@ -498,9 +498,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-6.tgz",
- "integrity": "sha512-P8Dgq59MIoiWKTRUGLrzzQ+NX54sqsHQFAoTJPis2K0N1O7BUTN4RDl8aPN3v4c1MCkbH9YzjmT8ns1JPeIUuQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-9.tgz",
+ "integrity": "sha512-KknlE4hT3rw/Ne1aL+F1KEQrq40d4I8aGfxAEuahmn3NaM7CSBikDVIsAvkmTq7e2vHzaLytpclc8+gcEAIK6Q==",
"cpu": [
"x64"
],
@@ -514,9 +514,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-6.tgz",
- "integrity": "sha512-6CS4YuL1x8YwoEfr/dPcq+ZQYTJQTukO/Uuv88eZ9/RWGdhcls14j/WWPcte8LLk2EFJXchM9WPmkOmZppPkwQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-Wrk+vpzg9ho/uC7ajNgIEjPShtB+pGlaJV+8rvYcHeQG6Gyx8YrPMI+OMdYou6RI9firqIaywT0UPuy9PUzoOg==",
"cpu": [
"arm64"
],
@@ -530,9 +530,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-6.tgz",
- "integrity": "sha512-y+fX6P4oXKADqXsEWCTqWFmLECTm2jVmxkCEC6C1TGqHDzN0+X2pJQd/LTSOZFmtlgxVjusL93eCk1mwa2MapQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-9.tgz",
+ "integrity": "sha512-ERULakTfCb4KYK4hGcMPRp5qm5K7KqKFHhGrAdn1VLrm8QsXDYzl2vUO4tIU/TxRW5VA9pmWh30JpCjQScSnDA==",
"cpu": [
"x64"
],
@@ -546,9 +546,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-6.tgz",
- "integrity": "sha512-E/JxBAA4Dqy7d81mCBfZ1L9XJH7eK1DBQn2Jlur5oBvA3qluX05kXcGTlmGkGVA2mkM9rD5zaSC8yZ5grq40HQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-XAe2calnhhiAVdIb2jUn4Bh961nu4zz3N5tcrb5CNjDSbjEE2LQf8CaNV4h/QhHjjpcmqFIfMQBMYxW1+9xixg==",
"cpu": [
"arm64"
],
@@ -562,9 +562,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-6.tgz",
- "integrity": "sha512-7Hlfb438QNqU34OhhRiJiElWoyP7xED5iZunU1vC00L1RbrsTXDeC41y2oAxYiXa/bX60TV4x/oWuGli/0no6A==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-9.tgz",
+ "integrity": "sha512-/nK1IR5Vho2r6vuzq9xziVWwlgan41eL62Oo0feu7RaMvhS+f40l4jZCjuWLbeysh/we642qCyRjK8gkv730lA==",
"cpu": [
"x64"
],
diff --git a/java/scripts/codegen/package.json b/java/scripts/codegen/package.json
index bb8936e752..5e3630ec07 100644
--- a/java/scripts/codegen/package.json
+++ b/java/scripts/codegen/package.json
@@ -7,7 +7,7 @@
"generate:java": "tsx java.ts"
},
"dependencies": {
- "@github/copilot": "^1.0.79-6",
+ "@github/copilot": "^1.0.79-9",
"json-schema": "^0.4.0",
"tsx": "^4.23.1"
}
diff --git a/java/src/generated/java/com/github/copilot/generated/SubagentCompletedEvent.java b/java/src/generated/java/com/github/copilot/generated/SubagentCompletedEvent.java
index f32613579d..f7300ddbf4 100644
--- a/java/src/generated/java/com/github/copilot/generated/SubagentCompletedEvent.java
+++ b/java/src/generated/java/com/github/copilot/generated/SubagentCompletedEvent.java
@@ -47,7 +47,9 @@ public record SubagentCompletedEventData(
/** Total tokens (input + output) consumed by the sub-agent */
@JsonProperty("totalTokens") Long totalTokens,
/** Wall-clock duration of the sub-agent execution in milliseconds */
- @JsonProperty("durationMs") Long durationMs
+ @JsonProperty("durationMs") Long durationMs,
+ /** Whether the sub-agent was torn down by cancellation - its own abort, or an ancestor being killed - instead of finishing its work. Cancellation is not a failure, so the run still reports completion; this distinguishes a torn-down sub-agent from one that ran to the end. */
+ @JsonProperty("cancelled") Boolean cancelled
) {
}
}
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/FactoryAgentOptions.java b/java/src/generated/java/com/github/copilot/generated/rpc/FactoryAgentOptions.java
index 675e715e85..9910d4f7f5 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/FactoryAgentOptions.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/FactoryAgentOptions.java
@@ -26,6 +26,12 @@ public record FactoryAgentOptions(
/** Optional JSON Schema for structured agent output. */
@JsonProperty("schema") Object schema,
/** Optional model identifier for the subagent. */
- @JsonProperty("model") String model
+ @JsonProperty("model") String model,
+ /** Optional reasoning effort for the subagent. This field is accepted but not yet honored. */
+ @JsonProperty("reasoningEffort") String reasoningEffort,
+ /** Optional context tier for the subagent. This field is accepted but not yet honored. */
+ @JsonProperty("contextTier") ContextTier contextTier,
+ /** Optional custom agent name for the subagent. This field is accepted but not yet honored. */
+ @JsonProperty("agent") String agent
) {
}
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfig.java b/java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfig.java
index cfb2c23fff..d9130eb819 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfig.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfig.java
@@ -27,10 +27,8 @@ public record SandboxConfig(
@JsonProperty("userPolicy") SandboxConfigUserPolicy userPolicy,
/** Whether to auto-add the current working directory to readwritePaths. Default: true. */
@JsonProperty("addCurrentWorkingDirectory") Boolean addCurrentWorkingDirectory,
- /** Whether to inject the Copilot GitHub token as an `http..extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. Default: false (opt-in). */
- @JsonProperty("gitAuth") Boolean gitAuth,
- /** Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in). */
- @JsonProperty("ghAuth") Boolean ghAuth,
+ /** Credential-injection capability flags. */
+ @JsonProperty("auth") SandboxConfigAuth auth,
/** Whether to auto-grant read access to common developer-tool caches, registries, and toolchains in their default home locations (cargo, go, npm, Maven, and more), plus read-write access to (and, on Unix, up-front creation of) the scratch caches builds write on every run (go-build, ccache, sccache, Gradle caches, Cargo lock/tracker files), so builds work without extra configuration; a relocated CARGO_HOME additionally gets its Cargo lock files granted read-write. Default: true (enabled by default; set to false to opt out). */
@JsonProperty("allowDevToolAccess") Boolean allowDevToolAccess
) {
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfigAuth.java b/java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfigAuth.java
new file mode 100644
index 0000000000..4a3612e0b6
--- /dev/null
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SandboxConfigAuth.java
@@ -0,0 +1,29 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *--------------------------------------------------------------------------------------------*/
+
+// AUTO-GENERATED FILE - DO NOT EDIT
+// Generated from: api.schema.json
+
+package com.github.copilot.generated.rpc;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.processing.Generated;
+
+/**
+ * Credential-injection capability flags applied while the sandbox is enabled.
+ *
+ * @since 1.0.0
+ */
+@javax.annotation.processing.Generated("copilot-sdk-codegen")
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public record SandboxConfigAuth(
+ /** Whether to inject git credentials as an `http..extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. github.com is served by the Copilot token; every other forge (Azure DevOps, GitHub Enterprise Server, GitLab, ...) by a credential the host resolves from the user's own helper before the sandbox is applied. Default: false (opt-in). */
+ @JsonProperty("git") Boolean git,
+ /** Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in). */
+ @JsonProperty("gh") Boolean gh
+) {
+}
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryApi.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryApi.java
index 6d15ac17c3..e0628ea3dc 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryApi.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryApi.java
@@ -83,14 +83,19 @@ public CompletableFuture getRun(SessionFactoryGetRun
}
/**
- * Empty parameters for listing factory runs.
+ * Parameters for paging factory runs.
+ *
+ * Note: the {@code sessionId} field in the params record is overridden
+ * by the session-scoped wrapper; any value provided is ignored.
*
* @apiNote This method is experimental and may change in a future version.
* @since 1.0.0
*/
@CopilotExperimental
- public CompletableFuture listRuns() {
- return caller.invoke("session.factory.listRuns", java.util.Map.of("sessionId", this.sessionId), SessionFactoryListRunsResult.class);
+ public CompletableFuture listRuns(SessionFactoryListRunsParams params) {
+ com.fasterxml.jackson.databind.node.ObjectNode _p = MAPPER.valueToTree(params);
+ _p.put("sessionId", this.sessionId);
+ return caller.invoke("session.factory.listRuns", _p, SessionFactoryListRunsResult.class);
}
/**
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsParams.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsParams.java
index e3b90f07f7..41de4ae4a6 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsParams.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsParams.java
@@ -14,7 +14,7 @@
import javax.annotation.processing.Generated;
/**
- * Empty parameters for listing factory runs.
+ * Parameters for paging factory runs.
*
* @apiNote This method is experimental and may change in a future version.
* @since 1.0.0
@@ -25,6 +25,12 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionFactoryListRunsParams(
/** Target session identifier */
- @JsonProperty("sessionId") String sessionId
+ @JsonProperty("sessionId") String sessionId,
+ /** Exclusive forward cursor. */
+ @JsonProperty("afterSeq") Long afterSeq,
+ /** Exclusive backward cursor. */
+ @JsonProperty("beforeSeq") Long beforeSeq,
+ /** Maximum terminal runs to return. Defaults to 200 and is capped at 500. */
+ @JsonProperty("limit") Long limit
) {
}
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsResult.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsResult.java
index 7d1ac45a9e..3a23bc369a 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsResult.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionFactoryListRunsResult.java
@@ -15,7 +15,7 @@
import javax.annotation.processing.Generated;
/**
- * Factory runs in durable creation order.
+ * A page of factory runs in durable creation order.
*
* @apiNote This method is experimental and may change in a future version.
* @since 1.0.0
@@ -25,6 +25,14 @@
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public record SessionFactoryListRunsResult(
- @JsonProperty("runs") List runs
+ @JsonProperty("runs") List runs,
+ /** Oldest terminal-run cursor in this page, or null when the terminal window is empty. */
+ @JsonProperty("oldestSeq") Long oldestSeq,
+ /** Newest terminal-run cursor in this page, or null when the terminal window is empty. */
+ @JsonProperty("newestSeq") Long newestSeq,
+ /** Whether terminal runs newer than this page exist. */
+ @JsonProperty("hasMoreNewer") Boolean hasMoreNewer,
+ /** Number of terminal runs older than this page. */
+ @JsonProperty("omittedOlder") Long omittedOlder
) {
}
diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json
index cd571ced14..39fa8b6fa8 100644
--- a/nodejs/package-lock.json
+++ b/nodejs/package-lock.json
@@ -9,7 +9,7 @@
"version": "0.0.0-dev",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.79-6",
+ "@github/copilot": "^1.0.79-9",
"koffi": "^3.1.0",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
@@ -700,9 +700,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-6.tgz",
- "integrity": "sha512-per2cqu8WYuRXXvdU38cYZ7lUSQP5uBDY2QfFZow9FgGOyOToEWz+ykw2NYVKMnx0u1gIiI20Ovl4zec9Dob6w==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-9.tgz",
+ "integrity": "sha512-1QRRV3z1HA8sr3JUo4e2l+zFVbIGIOqnmTwzdJ+ilfr+mkmC7LYWkJxV3+j+zN0nq8JAgusSL/Schc43MPIqug==",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"detect-libc": "^2.1.2"
@@ -711,20 +711,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.79-6",
- "@github/copilot-darwin-x64": "1.0.79-6",
- "@github/copilot-linux-arm64": "1.0.79-6",
- "@github/copilot-linux-x64": "1.0.79-6",
- "@github/copilot-linuxmusl-arm64": "1.0.79-6",
- "@github/copilot-linuxmusl-x64": "1.0.79-6",
- "@github/copilot-win32-arm64": "1.0.79-6",
- "@github/copilot-win32-x64": "1.0.79-6"
+ "@github/copilot-darwin-arm64": "1.0.79-9",
+ "@github/copilot-darwin-x64": "1.0.79-9",
+ "@github/copilot-linux-arm64": "1.0.79-9",
+ "@github/copilot-linux-x64": "1.0.79-9",
+ "@github/copilot-linuxmusl-arm64": "1.0.79-9",
+ "@github/copilot-linuxmusl-x64": "1.0.79-9",
+ "@github/copilot-win32-arm64": "1.0.79-9",
+ "@github/copilot-win32-x64": "1.0.79-9"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-6.tgz",
- "integrity": "sha512-22aYilTJsiZX4w55DPXHvJFHSNwZWGip4DcQCQTvzzVIGc8MjlCQVModE9B6ElGs18hUaM3NH4piTYYT0HqNGQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-DBTtv06Lpka1R+bkYfCWH38838b66bTLvsRsNjSuQV9AzgMPHjIn+Q2wAmU89rUyw5ej9iCIL5ppps+roi7qRw==",
"cpu": [
"arm64"
],
@@ -738,9 +738,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-6.tgz",
- "integrity": "sha512-1ESqmLenOGkfD4KwgxtUZh+Wt5+qKwtLHGpfpRl+d/BSKj4cNo9FUO2vFEmF3zQefpmady3vmDURSdi65hlC+w==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-9.tgz",
+ "integrity": "sha512-j+XOqtVWa0EZ8lBR+xIsPVI7ErpDepgr3WuSfUCkC9fOdvnVJ1rbyBY3gCM/urY4wJNdbHc4t1vN9MjtRNpTGA==",
"cpu": [
"x64"
],
@@ -754,9 +754,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-6.tgz",
- "integrity": "sha512-R8ZmfoJuOj1CT0zamAnRJi7nxhUPRFi3vo3dWlzSkto0Uwez+j2IJmyGIZEZbN65BJJJMD2/kg0GZQG+l+PmUA==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-eYsJlokogYeXo2tCwqoDW+rELbLs0ht7b3R1nrl9odO6U6ZabIm6BilSLSxjWCtE1ZpqDLmdJbOV0/6cQwjvlA==",
"cpu": [
"arm64"
],
@@ -770,9 +770,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-6.tgz",
- "integrity": "sha512-P8Dgq59MIoiWKTRUGLrzzQ+NX54sqsHQFAoTJPis2K0N1O7BUTN4RDl8aPN3v4c1MCkbH9YzjmT8ns1JPeIUuQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-9.tgz",
+ "integrity": "sha512-KknlE4hT3rw/Ne1aL+F1KEQrq40d4I8aGfxAEuahmn3NaM7CSBikDVIsAvkmTq7e2vHzaLytpclc8+gcEAIK6Q==",
"cpu": [
"x64"
],
@@ -786,9 +786,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-6.tgz",
- "integrity": "sha512-6CS4YuL1x8YwoEfr/dPcq+ZQYTJQTukO/Uuv88eZ9/RWGdhcls14j/WWPcte8LLk2EFJXchM9WPmkOmZppPkwQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-Wrk+vpzg9ho/uC7ajNgIEjPShtB+pGlaJV+8rvYcHeQG6Gyx8YrPMI+OMdYou6RI9firqIaywT0UPuy9PUzoOg==",
"cpu": [
"arm64"
],
@@ -802,9 +802,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-6.tgz",
- "integrity": "sha512-y+fX6P4oXKADqXsEWCTqWFmLECTm2jVmxkCEC6C1TGqHDzN0+X2pJQd/LTSOZFmtlgxVjusL93eCk1mwa2MapQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-9.tgz",
+ "integrity": "sha512-ERULakTfCb4KYK4hGcMPRp5qm5K7KqKFHhGrAdn1VLrm8QsXDYzl2vUO4tIU/TxRW5VA9pmWh30JpCjQScSnDA==",
"cpu": [
"x64"
],
@@ -818,9 +818,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-6.tgz",
- "integrity": "sha512-E/JxBAA4Dqy7d81mCBfZ1L9XJH7eK1DBQn2Jlur5oBvA3qluX05kXcGTlmGkGVA2mkM9rD5zaSC8yZ5grq40HQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-XAe2calnhhiAVdIb2jUn4Bh961nu4zz3N5tcrb5CNjDSbjEE2LQf8CaNV4h/QhHjjpcmqFIfMQBMYxW1+9xixg==",
"cpu": [
"arm64"
],
@@ -834,9 +834,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-6.tgz",
- "integrity": "sha512-7Hlfb438QNqU34OhhRiJiElWoyP7xED5iZunU1vC00L1RbrsTXDeC41y2oAxYiXa/bX60TV4x/oWuGli/0no6A==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-9.tgz",
+ "integrity": "sha512-/nK1IR5Vho2r6vuzq9xziVWwlgan41eL62Oo0feu7RaMvhS+f40l4jZCjuWLbeysh/we642qCyRjK8gkv730lA==",
"cpu": [
"x64"
],
diff --git a/nodejs/package.json b/nodejs/package.json
index 5becc3d3c3..a4160cd2c3 100644
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -56,7 +56,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.79-6",
+ "@github/copilot": "^1.0.79-9",
"koffi": "^3.1.0",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json
index 5794a0032b..ad84030026 100644
--- a/nodejs/samples/package-lock.json
+++ b/nodejs/samples/package-lock.json
@@ -18,7 +18,7 @@
"version": "0.0.0-dev",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.79-6",
+ "@github/copilot": "^1.0.79-9",
"koffi": "^3.1.0",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts
index 7a8c66909d..042a7d0bb7 100644
--- a/nodejs/src/generated/rpc.ts
+++ b/nodejs/src/generated/rpc.ts
@@ -686,6 +686,17 @@ export type FactoryRunFailure =
*/
runId: string;
type: "factory_durable_failure";
+ }
+ | {
+ /**
+ * Factory run identifier.
+ */
+ runId: string;
+ /**
+ * Confirmed usage in nano-AIU, representing the floor of what the run spent.
+ */
+ drainedNanoAiu: number;
+ type: "factory_accounting_incomplete";
};
/**
* Cumulative resource ceiling that stopped a factory run.
@@ -5733,6 +5744,15 @@ export interface FactoryAgentOptions {
* Optional model identifier for the subagent.
*/
model?: string;
+ /**
+ * Optional reasoning effort for the subagent. This field is accepted but not yet honored.
+ */
+ reasoningEffort?: string;
+ contextTier?: ContextTier;
+ /**
+ * Optional custom agent name for the subagent. This field is accepted but not yet honored.
+ */
+ agent?: string;
}
/**
* Parameters for one factory-scoped subagent call.
@@ -5986,15 +6006,28 @@ export interface FactoryJournalPutRequest {
};
}
/**
- * Empty parameters for listing factory runs.
+ * Parameters for paging factory runs.
*
* This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
* via the `definition` "FactoryListRunsRequest".
*/
/** @experimental */
-export interface FactoryListRunsRequest {}
+export interface FactoryListRunsRequest {
+ /**
+ * Exclusive forward cursor.
+ */
+ afterSeq?: number;
+ /**
+ * Exclusive backward cursor.
+ */
+ beforeSeq?: number;
+ /**
+ * Maximum terminal runs to return. Defaults to 200 and is capped at 500.
+ */
+ limit?: number;
+}
/**
- * Factory runs in durable creation order.
+ * A page of factory runs in durable creation order.
*
* This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
* via the `definition` "FactoryListRunsResult".
@@ -6002,6 +6035,22 @@ export interface FactoryListRunsRequest {}
/** @experimental */
export interface FactoryListRunsResult {
runs: FactoryRunSummary[];
+ /**
+ * Oldest terminal-run cursor in this page, or null when the terminal window is empty.
+ */
+ oldestSeq?: number | null;
+ /**
+ * Newest terminal-run cursor in this page, or null when the terminal window is empty.
+ */
+ newestSeq?: number | null;
+ /**
+ * Whether terminal runs newer than this page exist.
+ */
+ hasMoreNewer?: boolean;
+ /**
+ * Number of terminal runs older than this page.
+ */
+ omittedOlder?: number;
}
/**
* Durable factory run summary with read-time live overlays.
@@ -13240,14 +13289,7 @@ export interface SandboxConfig {
* Whether to auto-add the current working directory to readwritePaths. Default: true.
*/
addCurrentWorkingDirectory?: boolean;
- /**
- * Whether to inject the Copilot GitHub token as an `http..extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. Default: false (opt-in).
- */
- gitAuth?: boolean;
- /**
- * Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in).
- */
- ghAuth?: boolean;
+ auth?: SandboxConfigAuth;
/**
* Whether to auto-grant read access to common developer-tool caches, registries, and toolchains in their default home locations (cargo, go, npm, Maven, and more), plus read-write access to (and, on Unix, up-front creation of) the scratch caches builds write on every run (go-build, ccache, sccache, Gradle caches, Cargo lock/tracker files), so builds work without extra configuration; a relocated CARGO_HOME additionally gets its Cargo lock files granted read-write. Default: true (enabled by default; set to false to opt out).
*/
@@ -13366,6 +13408,23 @@ export interface SandboxConfigUserPolicyExperimentalSeatbelt {
*/
keychainAccess?: boolean;
}
+/**
+ * Credential-injection capability flags applied while the sandbox is enabled.
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "SandboxConfigAuth".
+ */
+/** @experimental */
+export interface SandboxConfigAuth {
+ /**
+ * Whether to inject git credentials as an `http..extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. github.com is served by the Copilot token; every other forge (Azure DevOps, GitHub Enterprise Server, GitLab, ...) by a credential the host resolves from the user's own helper before the sandbox is applied. Default: false (opt-in).
+ */
+ git?: boolean;
+ /**
+ * Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in).
+ */
+ gh?: boolean;
+}
/**
* Register an absolute-time scheduled prompt.
*
@@ -19726,10 +19785,12 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin
/**
* Lists durable factory runs for this session in creation order.
*
- * @returns Factory runs in durable creation order.
+ * @param params Parameters for paging factory runs.
+ *
+ * @returns A page of factory runs in durable creation order.
*/
- listRuns: async (): Promise =>
- connection.sendRequest("session.factory.listRuns", { sessionId }),
+ listRuns: async (params: FactoryListRunsRequest): Promise =>
+ connection.sendRequest("session.factory.listRuns", { sessionId, ...params }),
/**
* Gets durable and live observability detail for one factory run.
*
diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts
index 19d044d6d1..db24fc23e9 100644
--- a/nodejs/src/generated/session-events.ts
+++ b/nodejs/src/generated/session-events.ts
@@ -5561,6 +5561,10 @@ export interface SubagentCompletedData {
* Internal name of the sub-agent
*/
agentName: string;
+ /**
+ * Whether the sub-agent was torn down by cancellation - its own abort, or an ancestor being killed - instead of finishing its work. Cancellation is not a failure, so the run still reports completion; this distinguishes a torn-down sub-agent from one that ran to the end.
+ */
+ cancelled?: boolean;
/**
* Wall-clock duration of the sub-agent execution in milliseconds
*/
diff --git a/nodejs/src/session.ts b/nodejs/src/session.ts
index ed575a5154..5cc49fb758 100644
--- a/nodejs/src/session.ts
+++ b/nodejs/src/session.ts
@@ -487,7 +487,7 @@ export class CopilotSession {
}) as SessionFactoryApi["resume"],
getRun: async (runId) => toPublicFactoryRunResult(await this.rpc.factory.getRun({ runId })),
waitForRun: (runId, options) => this.waitForFactoryRun(runId, options?.signal),
- listRuns: async () => (await this.rpc.factory.listRuns()).runs,
+ listRuns: async () => (await this.rpc.factory.listRuns({})).runs,
getRunDetail: (runId) => this.rpc.factory.getRunDetail({ runId }),
getRunProgress: (runId, options = {}) =>
this.rpc.factory.getRunProgress({ runId, ...options }),
diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py
index a9511540cc..103149088d 100644
--- a/python/copilot/generated/rpc.py
+++ b/python/copilot/generated/rpc.py
@@ -2284,29 +2284,47 @@ class FactoryAgentOptions:
Subagent execution options.
"""
+ agent: str | None = None
+ """Optional custom agent name for the subagent. This field is accepted but not yet honored."""
+
+ context_tier: ContextTier | None = None
+ """Optional context tier for the subagent. This field is accepted but not yet honored."""
+
label: str | None = None
"""Optional label distinguishing otherwise identical memoized agent calls."""
model: str | None = None
"""Optional model identifier for the subagent."""
+ reasoning_effort: str | None = None
+ """Optional reasoning effort for the subagent. This field is accepted but not yet honored."""
+
schema: Any = None
"""Optional JSON Schema for structured agent output."""
@staticmethod
def from_dict(obj: Any) -> 'FactoryAgentOptions':
assert isinstance(obj, dict)
+ agent = from_union([from_str, from_none], obj.get("agent"))
+ context_tier = from_union([ContextTier, from_none], obj.get("contextTier"))
label = from_union([from_str, from_none], obj.get("label"))
model = from_union([from_str, from_none], obj.get("model"))
+ reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort"))
schema = obj.get("schema")
- return FactoryAgentOptions(label, model, schema)
+ return FactoryAgentOptions(agent, context_tier, label, model, reasoning_effort, schema)
def to_dict(self) -> dict:
result: dict = {}
+ if self.agent is not None:
+ result["agent"] = from_union([from_str, from_none], self.agent)
+ if self.context_tier is not None:
+ result["contextTier"] = from_union([lambda x: to_enum(ContextTier, x), from_none], self.context_tier)
if self.label is not None:
result["label"] = from_union([from_str, from_none], self.label)
if self.model is not None:
result["model"] = from_union([from_str, from_none], self.model)
+ if self.reasoning_effort is not None:
+ result["reasoningEffort"] = from_union([from_str, from_none], self.reasoning_effort)
if self.schema is not None:
result["schema"] = self.schema
return result
@@ -2690,14 +2708,33 @@ def to_dict(self) -> dict:
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
class FactoryListRunsRequest:
- """Empty parameters for listing factory runs."""
+ """Parameters for paging factory runs."""
+
+ after_seq: int | None = None
+ """Exclusive forward cursor."""
+
+ before_seq: int | None = None
+ """Exclusive backward cursor."""
+
+ limit: int | None = None
+ """Maximum terminal runs to return. Defaults to 200 and is capped at 500."""
+
@staticmethod
def from_dict(obj: Any) -> 'FactoryListRunsRequest':
assert isinstance(obj, dict)
- return FactoryListRunsRequest()
+ after_seq = from_union([from_int, from_none], obj.get("afterSeq"))
+ before_seq = from_union([from_int, from_none], obj.get("beforeSeq"))
+ limit = from_union([from_int, from_none], obj.get("limit"))
+ return FactoryListRunsRequest(after_seq, before_seq, limit)
def to_dict(self) -> dict:
result: dict = {}
+ if self.after_seq is not None:
+ result["afterSeq"] = from_union([from_int, from_none], self.after_seq)
+ if self.before_seq is not None:
+ result["beforeSeq"] = from_union([from_int, from_none], self.before_seq)
+ if self.limit is not None:
+ result["limit"] = from_union([from_int, from_none], self.limit)
return result
# Experimental: this type is part of an experimental API and may change or be removed.
@@ -2748,6 +2785,7 @@ class FactoryRunFailureKind(Enum):
TIMEOUT_SECONDS = "timeoutSeconds"
class FactoryRunFailureType(Enum):
+ FACTORY_ACCOUNTING_INCOMPLETE = "factory_accounting_incomplete"
FACTORY_DURABLE_FAILURE = "factory_durable_failure"
FACTORY_LIMIT_REACHED = "factory_limit_reached"
FACTORY_RESUME_DECLINED = "factory_resume_declined"
@@ -8102,6 +8140,40 @@ def to_dict(self) -> dict:
result["branch"] = from_union([from_str, from_none], self.branch)
return result
+# Experimental: this type is part of an experimental API and may change or be removed.
+@dataclass
+class SandboxConfigAuth:
+ """Credential-injection capability flags.
+
+ Credential-injection capability flags applied while the sandbox is enabled.
+ """
+ gh: bool | None = None
+ """Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the
+ OS keyring the sandbox blocks. Default: false (opt-in).
+ """
+ git: bool | None = None
+ """Whether to inject git credentials as an `http..extraheader` so authenticated HTTPS
+ git works inside the sandbox without the shell-based credential helper the sandbox
+ blocks. github.com is served by the Copilot token; every other forge (Azure DevOps,
+ GitHub Enterprise Server, GitLab, ...) by a credential the host resolves from the user's
+ own helper before the sandbox is applied. Default: false (opt-in).
+ """
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SandboxConfigAuth':
+ assert isinstance(obj, dict)
+ gh = from_union([from_bool, from_none], obj.get("gh"))
+ git = from_union([from_bool, from_none], obj.get("git"))
+ return SandboxConfigAuth(gh, git)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ if self.gh is not None:
+ result["gh"] = from_union([from_bool, from_none], self.gh)
+ if self.git is not None:
+ result["git"] = from_union([from_bool, from_none], self.git)
+ return result
+
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
class SandboxConfigUserPolicyExperimentalSeatbelt:
@@ -14079,6 +14151,8 @@ class FactoryRunFailure:
"""Machine-readable factory run failure.
Machine-readable failure details for an errored run.
+
+ The run stopped because its usage accounting could not be completed.
"""
run_id: str
"""Factory run identifier.
@@ -14101,6 +14175,9 @@ class FactoryRunFailure:
operation: FactoryDurableOperation | None = None
"""Execution-critical durable operation that failed."""
+ drained_nano_aiu: int | None = None
+ """Confirmed usage in nano-AIU, representing the floor of what the run spent."""
+
@staticmethod
def from_dict(obj: Any) -> 'FactoryRunFailure':
assert isinstance(obj, dict)
@@ -14111,7 +14188,8 @@ def from_dict(obj: Any) -> 'FactoryRunFailure':
reason = from_union([from_str, from_none], obj.get("reason"))
code = from_union([from_str, from_none], obj.get("code"))
operation = from_union([FactoryDurableOperation, from_none], obj.get("operation"))
- return FactoryRunFailure(run_id, type, kind, value, reason, code, operation)
+ drained_nano_aiu = from_union([from_int, from_none], obj.get("drainedNanoAiu"))
+ return FactoryRunFailure(run_id, type, kind, value, reason, code, operation, drained_nano_aiu)
def to_dict(self) -> dict:
result: dict = {}
@@ -14127,6 +14205,8 @@ def to_dict(self) -> dict:
result["code"] = from_union([from_str, from_none], self.code)
if self.operation is not None:
result["operation"] = from_union([lambda x: to_enum(FactoryDurableOperation, x), from_none], self.operation)
+ if self.drained_nano_aiu is not None:
+ result["drainedNanoAiu"] = from_union([from_int, from_none], self.drained_nano_aiu)
return result
# Experimental: this type is part of an experimental API and may change or be removed.
@@ -25647,15 +25727,9 @@ class SandboxConfig:
Cargo lock files granted read-write. Default: true (enabled by default; set to false to
opt out).
"""
- gh_auth: bool | None = None
- """Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the
- OS keyring the sandbox blocks. Default: false (opt-in).
- """
- git_auth: bool | None = None
- """Whether to inject the Copilot GitHub token as an `http..extraheader` so
- authenticated HTTPS git works inside the sandbox without the shell-based credential
- helper the sandbox blocks. Default: false (opt-in).
- """
+ auth: SandboxConfigAuth | None = None
+ """Credential-injection capability flags."""
+
user_policy: SandboxConfigUserPolicy | None = None
"""User-managed sandbox policy fragment merged into the auto-discovered base policy."""
@@ -25665,10 +25739,9 @@ def from_dict(obj: Any) -> 'SandboxConfig':
enabled = from_bool(obj.get("enabled"))
add_current_working_directory = from_union([from_bool, from_none], obj.get("addCurrentWorkingDirectory"))
allow_dev_tool_access = from_union([from_bool, from_none], obj.get("allowDevToolAccess"))
- gh_auth = from_union([from_bool, from_none], obj.get("ghAuth"))
- git_auth = from_union([from_bool, from_none], obj.get("gitAuth"))
+ auth = from_union([SandboxConfigAuth.from_dict, from_none], obj.get("auth"))
user_policy = from_union([SandboxConfigUserPolicy.from_dict, from_none], obj.get("userPolicy"))
- return SandboxConfig(enabled, add_current_working_directory, allow_dev_tool_access, gh_auth, git_auth, user_policy)
+ return SandboxConfig(enabled, add_current_working_directory, allow_dev_tool_access, auth, user_policy)
def to_dict(self) -> dict:
result: dict = {}
@@ -25677,10 +25750,8 @@ def to_dict(self) -> dict:
result["addCurrentWorkingDirectory"] = from_union([from_bool, from_none], self.add_current_working_directory)
if self.allow_dev_tool_access is not None:
result["allowDevToolAccess"] = from_union([from_bool, from_none], self.allow_dev_tool_access)
- if self.gh_auth is not None:
- result["ghAuth"] = from_union([from_bool, from_none], self.gh_auth)
- if self.git_auth is not None:
- result["gitAuth"] = from_union([from_bool, from_none], self.git_auth)
+ if self.auth is not None:
+ result["auth"] = from_union([lambda x: to_class(SandboxConfigAuth, x), from_none], self.auth)
if self.user_policy is not None:
result["userPolicy"] = from_union([lambda x: to_class(SandboxConfigUserPolicy, x), from_none], self.user_policy)
return result
@@ -25759,19 +25830,42 @@ def to_dict(self) -> dict:
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
class FactoryListRunsResult:
- """Factory runs in durable creation order."""
+ """A page of factory runs in durable creation order."""
runs: list[FactoryRunSummary]
+ has_more_newer: bool | None = None
+ """Whether terminal runs newer than this page exist."""
+
+ newest_seq: int | None = None
+ """Newest terminal-run cursor in this page, or null when the terminal window is empty."""
+
+ oldest_seq: int | None = None
+ """Oldest terminal-run cursor in this page, or null when the terminal window is empty."""
+
+ omitted_older: int | None = None
+ """Number of terminal runs older than this page."""
@staticmethod
def from_dict(obj: Any) -> 'FactoryListRunsResult':
assert isinstance(obj, dict)
runs = from_list(FactoryRunSummary.from_dict, obj.get("runs"))
- return FactoryListRunsResult(runs)
+ has_more_newer = from_union([from_bool, from_none], obj.get("hasMoreNewer"))
+ newest_seq = from_union([from_int, from_none], obj.get("newestSeq"))
+ oldest_seq = from_union([from_int, from_none], obj.get("oldestSeq"))
+ omitted_older = from_union([from_int, from_none], obj.get("omittedOlder"))
+ return FactoryListRunsResult(runs, has_more_newer, newest_seq, oldest_seq, omitted_older)
def to_dict(self) -> dict:
result: dict = {}
result["runs"] = from_list(lambda x: to_class(FactoryRunSummary, x), self.runs)
+ if self.has_more_newer is not None:
+ result["hasMoreNewer"] = from_union([from_bool, from_none], self.has_more_newer)
+ if self.newest_seq is not None:
+ result["newestSeq"] = from_union([from_int, from_none], self.newest_seq)
+ if self.oldest_seq is not None:
+ result["oldestSeq"] = from_union([from_int, from_none], self.oldest_seq)
+ if self.omitted_older is not None:
+ result["omittedOlder"] = from_union([from_int, from_none], self.omitted_older)
return result
# Experimental: this type is part of an experimental API and may change or be removed.
@@ -29380,6 +29474,7 @@ class RPC:
remote_session_repository: RemoteSessionRepository
run_options: RunOptions
sandbox_config: SandboxConfig
+ sandbox_config_auth: SandboxConfigAuth
sandbox_config_user_policy: SandboxConfigUserPolicy
sandbox_config_user_policy_experimental: SandboxConfigUserPolicyExperimental
sandbox_config_user_policy_experimental_seatbelt: SandboxConfigUserPolicyExperimentalSeatbelt
@@ -30392,6 +30487,7 @@ def from_dict(obj: Any) -> 'RPC':
remote_session_repository = RemoteSessionRepository.from_dict(obj.get("RemoteSessionRepository"))
run_options = RunOptions.from_dict(obj.get("RunOptions"))
sandbox_config = SandboxConfig.from_dict(obj.get("SandboxConfig"))
+ sandbox_config_auth = SandboxConfigAuth.from_dict(obj.get("SandboxConfigAuth"))
sandbox_config_user_policy = SandboxConfigUserPolicy.from_dict(obj.get("SandboxConfigUserPolicy"))
sandbox_config_user_policy_experimental = SandboxConfigUserPolicyExperimental.from_dict(obj.get("SandboxConfigUserPolicyExperimental"))
sandbox_config_user_policy_experimental_seatbelt = SandboxConfigUserPolicyExperimentalSeatbelt.from_dict(obj.get("SandboxConfigUserPolicyExperimentalSeatbelt"))
@@ -30745,7 +30841,7 @@ def from_dict(obj: Any) -> 'RPC':
subagent_settings = from_union([SubagentSettings.from_dict, from_none], obj.get("SubagentSettings"))
task_progress = from_union([TaskProgress.from_dict, from_none], obj.get("TaskProgress"))
workspace_summary = from_union([WorkspaceSummary.from_dict, from_none], obj.get("WorkspaceSummary"))
- return RPC(abort_request, abort_result, account_all_users, account_get_all_users_result, account_get_current_auth_result, account_get_quota_request, account_get_quota_result, account_login_request, account_login_result, account_logout_request, account_logout_result, account_quota_snapshot, adaptive_thinking_support, agent_discovery_path, agent_discovery_path_list, agent_discovery_path_scope, agent_get_current_result, agent_info, agent_info_source, agent_list, agent_list_request, agent_registry_live_target_entry, agent_registry_live_target_entry_attention_kind, agent_registry_live_target_entry_kind, agent_registry_live_target_entry_last_terminal_event, agent_registry_live_target_entry_status, agent_registry_log_capture, agent_registry_log_capture_open_error_reason, agent_registry_spawn_error, agent_registry_spawn_permission_mode, agent_registry_spawn_registry_timeout, agent_registry_spawn_request, agent_registry_spawn_result, agent_registry_spawn_spawned, agent_registry_spawn_validation_error, agent_registry_spawn_validation_error_field, agent_registry_spawn_validation_error_reason, agent_reload_result, agents_discover_request, agent_select_request, agent_select_result, agent_set_prompt_request, agents_get_discovery_paths_request, allow_all_permission_set_result, allow_all_permission_state, api_key_auth_info, auth_info, auth_info_type, built_in_model_catalog, built_in_model_catalog_entry, cancel_user_requested_shell_command_result, canvas_action, canvas_action_invoke_request, canvas_action_invoke_result, canvas_close_request, canvas_host_context, canvas_host_context_capabilities, canvas_json_schema, canvas_list, canvas_list_open_result, canvas_open_request, canvas_provider_close_request, canvas_provider_invoke_action_request, canvas_provider_open_request, canvas_provider_open_result, canvas_session_context, capi_session_options, command_list, commands_handle_pending_command_request, commands_handle_pending_command_result, commands_invoke_request, commands_list_request, commands_respond_to_queued_command_request, commands_respond_to_queued_command_result, completions_get_trigger_characters_result, completions_request_request, completions_request_result, configure_session_extensions_params, connected_remote_session_metadata, connected_remote_session_metadata_kind, connected_remote_session_metadata_repository, connect_remote_session_params, connect_request, connect_result, content_exclusion_check_paths_request, content_exclusion_check_paths_result, content_exclusion_path_check, content_filter_mode, context_heaviest_message, copilot_api_token_auth_info, copilot_user_response, copilot_user_response_endpoints, copilot_user_response_quota_snapshots, copilot_user_response_quota_snapshots_chat, copilot_user_response_quota_snapshots_completions, copilot_user_response_quota_snapshots_premium_interactions, current_model, current_tool_metadata, debug_collect_logs_collected_entry, debug_collect_logs_destination, debug_collect_logs_entry, debug_collect_logs_entry_kind, debug_collect_logs_include, debug_collect_logs_redaction, debug_collect_logs_request, debug_collect_logs_result, debug_collect_logs_result_kind, debug_collect_logs_skipped_entry, debug_collect_logs_source, disable_bypass_permissions_mode, discovered_canvas, discovered_extension, discovered_extension_mode, discovered_extension_plugin, discovered_extensions, discovered_extensions_disable_request, discovered_extensions_enable_request, discovered_extension_source, discovered_mcp_server, discovered_mcp_server_type, enqueue_command_params, enqueue_command_result, env_auth_info, event_log_read_request, event_log_release_interest_result, event_log_tail_result, event_log_types, events_agent_scope, events_cursor_status, events_read_direction, events_read_result, execute_command_params, execute_command_result, extension, extension_context_push_input, extension_launch_profile, extension_launch_provider_resolve_request, extension_launch_provider_resolve_result, extension_list, extensions_disable_request, extensions_enable_request, extension_source, extension_status, external_tool_result, external_tool_text_result_for_llm, external_tool_text_result_for_llm_binary_results_for_llm, external_tool_text_result_for_llm_binary_results_for_llm_type, external_tool_text_result_for_llm_content, external_tool_text_result_for_llm_content_audio, external_tool_text_result_for_llm_content_image, external_tool_text_result_for_llm_content_resource, external_tool_text_result_for_llm_content_resource_details, external_tool_text_result_for_llm_content_resource_link, external_tool_text_result_for_llm_content_resource_link_icon, external_tool_text_result_for_llm_content_resource_link_icon_theme, external_tool_text_result_for_llm_content_shell_exit, external_tool_text_result_for_llm_content_terminal, external_tool_text_result_for_llm_content_text, factory_abort_request, factory_ack_result, factory_agent_options, factory_agent_request, factory_agent_result, factory_agent_summary, factory_cancel_request, factory_current_phase, factory_declared_limits, factory_durable_operation, factory_execute_request, factory_execute_result, factory_get_run_progress_request, factory_get_run_request, factory_journal_get_request, factory_journal_get_result, factory_journal_put_request, factory_list_runs_request, factory_list_runs_result, factory_log_line, factory_log_line_kind, factory_log_request, factory_phase_observation, factory_phase_status, factory_progress_line, factory_progress_page, factory_resume_request, factory_resume_result, factory_run_consumed, factory_run_detail, factory_run_failure, factory_run_failure_kind, factory_run_limits, factory_run_request, factory_run_result, factory_run_status, factory_run_summary, factory_run_terminal, filter_mapping, fleet_start_request, fleet_start_result, folder_trust_add_params, folder_trust_check_params, folder_trust_check_result, gh_cli_auth_info, git_hub_telemetry_client_info, git_hub_telemetry_event, git_hub_telemetry_notification, handle_pending_tool_call_request, handle_pending_tool_call_result, history_abort_manual_compaction_result, history_cancel_background_compaction_result, history_clear_context_request, history_clear_context_result, history_compact_context_window, history_compact_request, history_compact_result, history_file_restore_skip_reason, history_list_rewind_points_result, history_preview_rewind_request, history_preview_rewind_result, history_rewind_change_type, history_rewind_file_preview, history_rewind_mode, history_rewind_outcome, history_rewind_point, history_rewind_request, history_rewind_result, history_rewind_unavailable_reason, history_skipped_file_restore, history_summarize_for_handoff_result, history_truncate_request, history_truncate_result, hmac_auth_info, hook_invoke_request, hook_invoke_response, hook_type, installed_plugin, installed_plugin_info, installed_plugin_source, installed_plugin_source_git_hub, installed_plugin_source_local, installed_plugin_source_url, instruction_discovery_path, instruction_discovery_path_kind, instruction_discovery_path_list, instruction_discovery_path_location, instructions_discover_request, instructions_get_discovery_paths_request, instructions_get_sources_result, instruction_source, instruction_source_location, instruction_source_type, interrupt_main_turn_request, interrupt_main_turn_result, llm_inference_headers, llm_inference_http_request_chunk_request, llm_inference_http_request_chunk_result, llm_inference_http_request_start_request, llm_inference_http_request_start_result, llm_inference_http_request_start_transport, llm_inference_http_response_chunk_error, llm_inference_http_response_chunk_request, llm_inference_http_response_chunk_result, llm_inference_http_response_start_request, llm_inference_http_response_start_result, llm_inference_set_provider_result, local_session_metadata_value, log_request, log_result, lsp_initialize_request, managed_settings_read_result, marketplace_add_result, marketplace_browse_result, marketplace_info, marketplace_list_result, marketplace_plugin_info, marketplace_refresh_entry, marketplace_refresh_result, marketplace_remove_result, mcp_allowed_server, mcp_apps_call_tool_request, mcp_apps_diagnose_capability, mcp_apps_diagnose_request, mcp_apps_diagnose_result, mcp_apps_diagnose_server, mcp_apps_host_context, mcp_apps_host_context_details, mcp_apps_host_context_details_available_display_mode, mcp_apps_host_context_details_display_mode, mcp_apps_host_context_details_platform, mcp_apps_host_context_details_theme, mcp_apps_list_tools_request, mcp_apps_list_tools_result, mcp_apps_read_resource_request, mcp_apps_read_resource_result, mcp_apps_resource_content, mcp_apps_set_host_context_details, mcp_apps_set_host_context_details_available_display_mode, mcp_apps_set_host_context_details_display_mode, mcp_apps_set_host_context_details_platform, mcp_apps_set_host_context_details_theme, mcp_apps_set_host_context_request, mcp_cancel_sampling_execution_params, mcp_cancel_sampling_execution_result, mcp_config_add_request, mcp_config_disable_request, mcp_config_enable_request, mcp_config_list, mcp_config_remove_request, mcp_config_update_request, mcp_configure_git_hub_request, mcp_configure_git_hub_result, mcp_disable_request, mcp_discover_request, mcp_discover_result, mcp_enable_request, mcp_execute_sampling_params, mcp_execute_sampling_request, mcp_execute_sampling_result, mcp_filtered_server, mcp_headers_handle_pending_headers_refresh_request, mcp_headers_handle_pending_headers_refresh_request_request, mcp_headers_handle_pending_headers_refresh_request_result, mcp_host_state, mcp_is_server_running_request, mcp_is_server_running_result, mcp_list_tools_request, mcp_list_tools_result, mcp_oauth_authentication_state_changed_request, mcp_oauth_handle_pending_request, mcp_oauth_handle_pending_result, mcp_oauth_login_grant_type, mcp_oauth_login_request, mcp_oauth_login_result, mcp_oauth_pending_request_response, mcp_oauth_respond_request, mcp_oauth_respond_result, mcp_register_external_client_request, mcp_reload_with_config_request, mcp_remove_git_hub_result, mcp_resource, mcp_resource_annotations, mcp_resource_content, mcp_resource_icon, mcp_resources_list_request, mcp_resources_list_result, mcp_resources_list_templates_request, mcp_resources_list_templates_result, mcp_resources_read_request, mcp_resources_read_result, mcp_resource_template, mcp_restart_server_request, mcp_sampling_execution_action, mcp_sampling_execution_result, mcp_server, mcp_server_auth_config, mcp_server_auth_config_redirect_port, mcp_server_config, mcp_server_config_defer_tools, mcp_server_config_http, mcp_server_config_http_oauth_grant_type, mcp_server_config_http_type, mcp_server_config_stdio, mcp_server_failure_info, mcp_server_list, mcp_server_needs_auth_info, mcp_set_env_value_mode_details, mcp_set_env_value_mode_params, mcp_set_env_value_mode_result, mcp_start_server_request, mcp_start_servers_result, mcp_stop_server_request, mcp_tools, mcp_tool_ui, mcp_tool_ui_visibility, mcp_unregister_external_client_request, memory_configuration, metadata_context_attribution_result, metadata_context_heaviest_messages_request, metadata_context_heaviest_messages_result, metadata_context_info_request, metadata_context_info_result, metadata_is_processing_result, metadata_recompute_context_tokens_request, metadata_recompute_context_tokens_result, metadata_record_context_change_request, metadata_record_context_change_result, metadata_set_working_directory_request, metadata_set_working_directory_result, metadata_snapshot_current_mode, metadata_snapshot_remote_metadata, metadata_snapshot_remote_metadata_repository, metadata_snapshot_remote_metadata_task_type, model, model_billing, model_billing_promo, model_billing_token_prices, model_billing_token_prices_long_context, model_capabilities, model_capabilities_limits, model_capabilities_limits_vision, model_capabilities_override, model_capabilities_override_limits, model_capabilities_override_limits_vision, model_capabilities_override_supports, model_capabilities_supports, model_list, model_list_request, model_picker_category, model_picker_price_category, model_policy, model_policy_state, model_set_reasoning_effort_request, model_set_reasoning_effort_result, models_list_request, model_switch_to_request, model_switch_to_result, mode_set_request, named_provider_config, name_get_result, name_set_auto_request, name_set_auto_result, name_set_request, open_canvas_instance, options_update_additional_content_exclusion_policy, options_update_additional_content_exclusion_policy_rule, options_update_additional_content_exclusion_policy_rule_source, options_update_additional_content_exclusion_policy_scope, options_update_context_tier, options_update_env_value_mode, options_update_reasoning_summary, options_update_tool_filter_precedence, pending_permission_request, pending_permission_request_list, permission_decision, permission_decision_approved, permission_decision_approved_for_location, permission_decision_approved_for_session, permission_decision_approve_for_location, permission_decision_approve_for_location_approval, permission_decision_approve_for_location_approval_commands, permission_decision_approve_for_location_approval_custom_tool, permission_decision_approve_for_location_approval_extension_management, permission_decision_approve_for_location_approval_extension_permission_access, permission_decision_approve_for_location_approval_factory, permission_decision_approve_for_location_approval_mcp, permission_decision_approve_for_location_approval_mcp_sampling, permission_decision_approve_for_location_approval_memory, permission_decision_approve_for_location_approval_read, permission_decision_approve_for_location_approval_write, permission_decision_approve_for_session, permission_decision_approve_for_session_approval, permission_decision_approve_for_session_approval_commands, permission_decision_approve_for_session_approval_custom_tool, permission_decision_approve_for_session_approval_extension_management, permission_decision_approve_for_session_approval_extension_permission_access, permission_decision_approve_for_session_approval_factory, permission_decision_approve_for_session_approval_mcp, permission_decision_approve_for_session_approval_mcp_sampling, permission_decision_approve_for_session_approval_memory, permission_decision_approve_for_session_approval_read, permission_decision_approve_for_session_approval_write, permission_decision_approve_once, permission_decision_approve_permanently, permission_decision_cancelled, permission_decision_context, permission_decision_denied_by_content_exclusion_policy, permission_decision_denied_by_permission_request_hook, permission_decision_denied_by_rules, permission_decision_denied_interactively_by_user, permission_decision_denied_no_approval_rule_and_could_not_request_from_user, permission_decision_outcome, permission_decision_reject, permission_decision_request, permission_decision_source, permission_decision_surface, permission_decision_user_not_available, permission_location_add_tool_approval_params, permission_location_apply_params, permission_location_apply_result, permission_location_resolve_params, permission_location_resolve_result, permission_location_type, permission_paths_add_params, permission_paths_allowed_check_params, permission_paths_allowed_check_result, permission_paths_config, permission_paths_list, permission_paths_update_primary_params, permission_paths_workspace_check_params, permission_paths_workspace_check_result, permission_prompt_shown_notification, permission_request_result, permission_rules_set, permissions_allow_all_mode, permissions_configure_additional_content_exclusion_policy, permissions_configure_additional_content_exclusion_policy_rule, permissions_configure_additional_content_exclusion_policy_rule_source, permissions_configure_additional_content_exclusion_policy_scope, permissions_configure_params, permissions_configure_result, permissions_folder_trust_add_trusted_result, permissions_get_allow_all_request, permissions_locations_add_tool_approval_details, permissions_locations_add_tool_approval_details_commands, permissions_locations_add_tool_approval_details_custom_tool, permissions_locations_add_tool_approval_details_extension_management, permissions_locations_add_tool_approval_details_extension_permission_access, permissions_locations_add_tool_approval_details_factory, permissions_locations_add_tool_approval_details_mcp, permissions_locations_add_tool_approval_details_mcp_sampling, permissions_locations_add_tool_approval_details_memory, permissions_locations_add_tool_approval_details_read, permissions_locations_add_tool_approval_details_write, permissions_locations_add_tool_approval_result, permissions_modify_rules_params, permissions_modify_rules_result, permissions_modify_rules_scope, permissions_notify_prompt_shown_result, permissions_paths_add_result, permissions_paths_list_request, permissions_paths_update_primary_result, permissions_pending_requests_request, permissions_reset_session_approvals_request, permissions_reset_session_approvals_result, permissions_set_allow_all_request, permissions_set_allow_all_source, permissions_set_approve_all_request, permissions_set_approve_all_result, permissions_set_approve_all_source, permissions_set_required_request, permissions_set_required_result, permissions_urls_set_unrestricted_mode_result, permission_urls_config, permission_urls_set_unrestricted_mode_params, ping_request, ping_result, plan_read_result, plan_read_sql_todos_result, plan_read_sql_todos_with_dependencies_result, plan_sql_todo_dependency, plan_sql_todos_row, plan_update_request, plugin, plugin_install_result, plugin_list, plugin_list_result, plugins_disable_request, plugins_enable_request, plugins_install_request, plugins_marketplaces_add_request, plugins_marketplaces_browse_request, plugins_marketplaces_refresh_request, plugins_marketplaces_remove_request, plugins_reload_request, plugins_uninstall_request, plugins_update_request, plugin_update_all_entry, plugin_update_all_result, plugin_update_result, provider_add_request, provider_add_result, provider_config, provider_config_azure, provider_config_transport, provider_config_type, provider_config_wire_api, provider_endpoint, provider_endpoint_transport, provider_endpoint_type, provider_endpoint_wire_api, provider_get_endpoint_request, provider_model_config, provider_session_token, provider_token_acquire_request, provider_token_acquire_result, push_attachment, push_attachment_blob, push_attachment_directory, push_attachment_file, push_attachment_file_line_range, push_attachment_git_hub_actions_job, push_attachment_git_hub_commit, push_attachment_git_hub_file, push_attachment_git_hub_file_diff, push_attachment_git_hub_file_diff_side, push_attachment_git_hub_reference, push_attachment_git_hub_reference_type, push_attachment_git_hub_release, push_attachment_git_hub_repository, push_attachment_git_hub_snippet, push_attachment_git_hub_tree_comparison, push_attachment_git_hub_tree_comparison_side, push_attachment_git_hub_url, push_attachment_selection, push_attachment_selection_details, push_attachment_selection_details_end, push_attachment_selection_details_start, push_git_hub_repo_ref, queue_begin_deferred_idle_drain_request, queue_begin_deferred_idle_drain_result, queue_consume_system_notifications_request, queued_command_handled, queued_command_not_handled, queued_command_result, queue_defer_session_idle_request, queue_duplicate_at_request, queue_duplicate_at_result, queue_enqueue_resume_pending_result, queue_finish_deferred_idle_drain_request, queue_finish_deferred_idle_drain_result, queue_has_pending_result, queue_insert_at_request, queue_insert_at_result, queue_insert_message, queue_move_item_request, queue_move_item_result, queue_pending_items, queue_pending_items_kind, queue_pending_items_result, queue_remove_at_request, queue_remove_at_result, queue_remove_most_recent_result, queue_send_now_request, queue_send_now_result, queue_set_drain_paused_request, queue_snapshot_result, queue_update_text_request, queue_update_text_result, register_event_interest_params, register_event_interest_result, register_extension_tools_params, register_extension_tools_result, release_event_interest_params, remote_control_config, remote_control_config_existing_mc_session, remote_control_status, remote_control_status_active, remote_control_status_connecting, remote_control_status_error, remote_control_status_off, remote_control_status_result, remote_control_stop_result, remote_control_transfer_result, remote_enable_request, remote_enable_result, remote_notify_steerable_changed_request, remote_notify_steerable_changed_result, remote_session_connection_result, remote_session_metadata_repository, remote_session_metadata_task_type, remote_session_metadata_value, remote_session_mode, remote_session_repository, run_options, sandbox_config, sandbox_config_user_policy, sandbox_config_user_policy_experimental, sandbox_config_user_policy_experimental_seatbelt, sandbox_config_user_policy_filesystem, sandbox_config_user_policy_network, sandbox_config_user_policy_network_proxy, sandbox_config_user_policy_seatbelt, schedule_add_at_request, schedule_add_cron_request, schedule_add_request, schedule_add_result, schedule_add_self_paced_request, schedule_entry, schedule_has_self_paced_result, schedule_list, schedule_rearm_self_paced_request, schedule_stop_request, schedule_stop_result, secrets_add_filter_values_request, secrets_add_filter_values_result, send_agent_mode, send_attachments_to_message_params, send_message_item, send_messages_request, send_messages_result, send_mode, send_request, send_result, send_system_notification_request, server_agent_list, server_instruction_source_list, server_skill, server_skill_list, session_activity, session_agent_list_request, session_auth_status, session_bulk_delete_result, session_cancel_all_background_agents_result, session_capability, session_commands_list_request, session_completion_item, session_context, session_context_host_type, session_enrich_metadata_result, session_fs_append_file_request, session_fs_error, session_fs_error_code, session_fs_exists_request, session_fs_exists_result, session_fs_mkdir_request, session_fs_readdir_request, session_fs_readdir_result, session_fs_readdir_with_types_entry, session_fs_readdir_with_types_entry_type, session_fs_readdir_with_types_request, session_fs_readdir_with_types_result, session_fs_read_file_request, session_fs_read_file_result, session_fs_rename_request, session_fs_rm_request, session_fs_set_provider_capabilities, session_fs_set_provider_conventions, session_fs_set_provider_request, session_fs_set_provider_result, session_fs_sqlite_exists_request, session_fs_sqlite_exists_result, session_fs_sqlite_query_request, session_fs_sqlite_query_result, session_fs_sqlite_query_type, session_fs_sqlite_transaction_error, session_fs_sqlite_transaction_error_class, session_fs_sqlite_transaction_request, session_fs_sqlite_transaction_result, session_fs_sqlite_transaction_statement, session_fs_stat_request, session_fs_stat_result, session_fs_write_file_request, session_history_compact_request, session_installed_plugin, session_installed_plugin_source, session_installed_plugin_source_git_hub, session_installed_plugin_source_local, session_installed_plugin_source_url, session_limit_prediction_baseline_data, session_limit_prediction_client_type, session_limit_prediction_details, session_limit_prediction_predict_request, session_limit_prediction_request, session_limit_prediction_result, session_limit_prediction_source, session_limit_prediction_tier, session_limit_prediction_tier_option, session_limit_prediction_unavailable_reason, session_list, session_list_entry, session_list_filter, session_load_deferred_repo_hooks_result, session_log_level, session_managed_permissions, session_managed_settings, session_mcp_apps_call_tool_result, session_metadata_snapshot, session_mode, session_model_list, session_model_list_request, session_model_price_category, session_open_options, session_open_options_additional_content_exclusion_policy, session_open_options_additional_content_exclusion_policy_rule, session_open_options_additional_content_exclusion_policy_rule_source, session_open_options_additional_content_exclusion_policy_scope, session_open_options_env_value_mode, session_open_options_reasoning_summary, session_open_params, session_open_result, session_plugins_reload_request, session_provider_get_endpoint_request, session_prune_result, sessions_bulk_delete_request, sessions_check_in_use_request, sessions_check_in_use_result, sessions_close_request, sessions_close_result, sessions_delete_request, sessions_enrich_metadata_request, session_set_credentials_params, session_set_credentials_result, session_settings_built_in_tool_availability_snapshot, session_settings_evaluate_predicate_request, session_settings_evaluate_predicate_result, session_settings_job_snapshot, session_settings_model_snapshot, session_settings_online_evaluation_snapshot, session_settings_predicate_name, session_settings_repo_snapshot, session_settings_snapshot, session_settings_validation_snapshot, sessions_find_by_prefix_request, sessions_find_by_prefix_result, sessions_find_by_task_id_request, sessions_find_by_task_id_result, sessions_fork_request, sessions_fork_result, sessions_get_board_entry_count_request, sessions_get_board_entry_count_result, sessions_get_event_file_path_request, sessions_get_event_file_path_result, sessions_get_last_for_context_request, sessions_get_last_for_context_result, sessions_get_metadata_request, sessions_get_metadata_result, sessions_get_persisted_remote_steerable_request, sessions_get_persisted_remote_steerable_result, session_sizes, sessions_list_non_empty_session_ids_request, sessions_list_non_empty_session_ids_result, sessions_list_request, sessions_load_deferred_repo_hooks_request, sessions_open_attach, sessions_open_cloud, sessions_open_create, sessions_open_handoff, sessions_open_handoff_task_type, sessions_open_progress, sessions_open_progress_status, sessions_open_progress_step, sessions_open_remote, sessions_open_resume, sessions_open_resume_last, sessions_open_status, session_source, sessions_prune_old_request, sessions_register_extension_tools_on_session_options, sessions_release_lock_request, sessions_release_lock_result, sessions_reload_plugin_hooks_request, sessions_reload_plugin_hooks_result, sessions_save_request, sessions_save_result, sessions_set_additional_plugins_request, sessions_set_additional_plugins_result, sessions_set_remote_control_steering_request, sessions_start_remote_control_request, sessions_stop_remote_control_request, sessions_transfer_remote_control_request, session_telemetry_engagement, session_update_options_params, session_update_options_result, session_visibility_status, session_working_directory_context, session_working_directory_context_host_type, shell_cancel_user_requested_request, shell_exec_request, shell_exec_result, shell_execute_user_requested_request, shell_init_profile, shell_init_script, shell_init_script_shell, shell_kill_request, shell_kill_result, shell_kill_signal, shell_options, shutdown_request, skill, skill_discovery_path, skill_discovery_path_list, skill_discovery_scope, skill_list, skills_config_set_disabled_skills_request, skills_disable_request, skills_discover_request, skills_enable_request, skills_get_discovery_paths_request, skills_get_invoked_result, skills_invoked_skill, skills_load_diagnostics, slash_command_agent_prompt_result, slash_command_completed_result, slash_command_info, slash_command_input, slash_command_input_choice, slash_command_input_completion, slash_command_invocation_result, slash_command_kind, slash_command_select_subcommand_option, slash_command_select_subcommand_result, slash_command_text_result, subagent_settings_entry, subagent_settings_entry_context_tier, task_agent_info, task_agent_progress, task_execution_mode, task_info, task_list, task_progress_line, tasks_cancel_request, tasks_cancel_result, tasks_get_current_promotable_result, tasks_get_progress_request, tasks_get_progress_result, task_shell_info, task_shell_info_attachment_mode, task_shell_progress, tasks_promote_current_to_background_result, tasks_promote_to_background_request, tasks_promote_to_background_result, tasks_refresh_result, tasks_remove_request, tasks_remove_result, tasks_send_message_request, tasks_send_message_result, tasks_start_agent_request, tasks_start_agent_result, task_status, tasks_wait_for_pending_result, telemetry_set_feature_overrides_request, token_auth_info, tool, tool_list, tools_get_current_metadata_result, tools_initialize_and_validate_result, tools_list_request, tools_update_subagent_settings_result, ui_auto_mode_switch_response, ui_elicitation_array_any_of_field, ui_elicitation_array_any_of_field_items, ui_elicitation_array_any_of_field_items_any_of, ui_elicitation_array_enum_field, ui_elicitation_array_enum_field_items, ui_elicitation_field_value, ui_elicitation_request, ui_elicitation_response, ui_elicitation_response_action, ui_elicitation_response_content, ui_elicitation_result, ui_elicitation_schema, ui_elicitation_schema_property, ui_elicitation_schema_property_boolean, ui_elicitation_schema_property_number, ui_elicitation_schema_property_number_type, ui_elicitation_schema_property_string, ui_elicitation_schema_property_string_format, ui_elicitation_string_enum_field, ui_elicitation_string_one_of_field, ui_elicitation_string_one_of_field_one_of, ui_ephemeral_query_request, ui_ephemeral_query_result, ui_exit_plan_mode_action, ui_exit_plan_mode_response, ui_handle_pending_auto_mode_switch_request, ui_handle_pending_elicitation_request, ui_handle_pending_exit_plan_mode_request, ui_handle_pending_result, ui_handle_pending_sampling_request, ui_handle_pending_sampling_response, ui_handle_pending_session_limits_exhausted_request, ui_handle_pending_user_input_request, ui_register_direct_auto_mode_switch_handler_result, ui_session_limits_exhausted_response, ui_session_limits_exhausted_response_action, ui_unregister_direct_auto_mode_switch_handler_request, ui_unregister_direct_auto_mode_switch_handler_result, ui_user_input_response, update_subagent_settings_request, usage_get_metrics_result, usage_metrics_code_changes, usage_metrics_model_metric, usage_metrics_model_metric_requests, usage_metrics_model_metric_token_detail, usage_metrics_model_metric_usage, usage_metrics_token_detail, user_auth_info, user_requested_shell_command_result, user_setting_metadata, user_settings_get_result, user_settings_set_request, user_settings_set_result, visibility_get_result, visibility_set_request, visibility_set_result, workspace_diff_file_change, workspace_diff_file_change_type, workspace_diff_mode, workspace_diff_result, workspaces_add_summary_request, workspaces_add_summary_result, workspaces_autopilot_objective_exists_result, workspaces_checkpoints, workspaces_create_file_request, workspaces_delete_autopilot_objective_result, workspaces_diff_request, workspaces_ensure_request, workspaces_get_workspace_result, workspaces_list_checkpoints_result, workspaces_list_files_result, workspaces_read_autopilot_objective_result, workspaces_read_checkpoint_request, workspaces_read_checkpoint_result, workspaces_read_file_request, workspaces_read_file_result, workspaces_save_large_paste_request, workspaces_save_large_paste_result, workspaces_truncate_summaries_request, workspace_summary_host_type, workspaces_update_metadata_request, workspaces_workspace_details_host_type, workspaces_write_autopilot_objective_request, workspaces_write_autopilot_objective_result, session_context_attribution, session_context_info, subagent_settings, task_progress, workspace_summary)
+ return RPC(abort_request, abort_result, account_all_users, account_get_all_users_result, account_get_current_auth_result, account_get_quota_request, account_get_quota_result, account_login_request, account_login_result, account_logout_request, account_logout_result, account_quota_snapshot, adaptive_thinking_support, agent_discovery_path, agent_discovery_path_list, agent_discovery_path_scope, agent_get_current_result, agent_info, agent_info_source, agent_list, agent_list_request, agent_registry_live_target_entry, agent_registry_live_target_entry_attention_kind, agent_registry_live_target_entry_kind, agent_registry_live_target_entry_last_terminal_event, agent_registry_live_target_entry_status, agent_registry_log_capture, agent_registry_log_capture_open_error_reason, agent_registry_spawn_error, agent_registry_spawn_permission_mode, agent_registry_spawn_registry_timeout, agent_registry_spawn_request, agent_registry_spawn_result, agent_registry_spawn_spawned, agent_registry_spawn_validation_error, agent_registry_spawn_validation_error_field, agent_registry_spawn_validation_error_reason, agent_reload_result, agents_discover_request, agent_select_request, agent_select_result, agent_set_prompt_request, agents_get_discovery_paths_request, allow_all_permission_set_result, allow_all_permission_state, api_key_auth_info, auth_info, auth_info_type, built_in_model_catalog, built_in_model_catalog_entry, cancel_user_requested_shell_command_result, canvas_action, canvas_action_invoke_request, canvas_action_invoke_result, canvas_close_request, canvas_host_context, canvas_host_context_capabilities, canvas_json_schema, canvas_list, canvas_list_open_result, canvas_open_request, canvas_provider_close_request, canvas_provider_invoke_action_request, canvas_provider_open_request, canvas_provider_open_result, canvas_session_context, capi_session_options, command_list, commands_handle_pending_command_request, commands_handle_pending_command_result, commands_invoke_request, commands_list_request, commands_respond_to_queued_command_request, commands_respond_to_queued_command_result, completions_get_trigger_characters_result, completions_request_request, completions_request_result, configure_session_extensions_params, connected_remote_session_metadata, connected_remote_session_metadata_kind, connected_remote_session_metadata_repository, connect_remote_session_params, connect_request, connect_result, content_exclusion_check_paths_request, content_exclusion_check_paths_result, content_exclusion_path_check, content_filter_mode, context_heaviest_message, copilot_api_token_auth_info, copilot_user_response, copilot_user_response_endpoints, copilot_user_response_quota_snapshots, copilot_user_response_quota_snapshots_chat, copilot_user_response_quota_snapshots_completions, copilot_user_response_quota_snapshots_premium_interactions, current_model, current_tool_metadata, debug_collect_logs_collected_entry, debug_collect_logs_destination, debug_collect_logs_entry, debug_collect_logs_entry_kind, debug_collect_logs_include, debug_collect_logs_redaction, debug_collect_logs_request, debug_collect_logs_result, debug_collect_logs_result_kind, debug_collect_logs_skipped_entry, debug_collect_logs_source, disable_bypass_permissions_mode, discovered_canvas, discovered_extension, discovered_extension_mode, discovered_extension_plugin, discovered_extensions, discovered_extensions_disable_request, discovered_extensions_enable_request, discovered_extension_source, discovered_mcp_server, discovered_mcp_server_type, enqueue_command_params, enqueue_command_result, env_auth_info, event_log_read_request, event_log_release_interest_result, event_log_tail_result, event_log_types, events_agent_scope, events_cursor_status, events_read_direction, events_read_result, execute_command_params, execute_command_result, extension, extension_context_push_input, extension_launch_profile, extension_launch_provider_resolve_request, extension_launch_provider_resolve_result, extension_list, extensions_disable_request, extensions_enable_request, extension_source, extension_status, external_tool_result, external_tool_text_result_for_llm, external_tool_text_result_for_llm_binary_results_for_llm, external_tool_text_result_for_llm_binary_results_for_llm_type, external_tool_text_result_for_llm_content, external_tool_text_result_for_llm_content_audio, external_tool_text_result_for_llm_content_image, external_tool_text_result_for_llm_content_resource, external_tool_text_result_for_llm_content_resource_details, external_tool_text_result_for_llm_content_resource_link, external_tool_text_result_for_llm_content_resource_link_icon, external_tool_text_result_for_llm_content_resource_link_icon_theme, external_tool_text_result_for_llm_content_shell_exit, external_tool_text_result_for_llm_content_terminal, external_tool_text_result_for_llm_content_text, factory_abort_request, factory_ack_result, factory_agent_options, factory_agent_request, factory_agent_result, factory_agent_summary, factory_cancel_request, factory_current_phase, factory_declared_limits, factory_durable_operation, factory_execute_request, factory_execute_result, factory_get_run_progress_request, factory_get_run_request, factory_journal_get_request, factory_journal_get_result, factory_journal_put_request, factory_list_runs_request, factory_list_runs_result, factory_log_line, factory_log_line_kind, factory_log_request, factory_phase_observation, factory_phase_status, factory_progress_line, factory_progress_page, factory_resume_request, factory_resume_result, factory_run_consumed, factory_run_detail, factory_run_failure, factory_run_failure_kind, factory_run_limits, factory_run_request, factory_run_result, factory_run_status, factory_run_summary, factory_run_terminal, filter_mapping, fleet_start_request, fleet_start_result, folder_trust_add_params, folder_trust_check_params, folder_trust_check_result, gh_cli_auth_info, git_hub_telemetry_client_info, git_hub_telemetry_event, git_hub_telemetry_notification, handle_pending_tool_call_request, handle_pending_tool_call_result, history_abort_manual_compaction_result, history_cancel_background_compaction_result, history_clear_context_request, history_clear_context_result, history_compact_context_window, history_compact_request, history_compact_result, history_file_restore_skip_reason, history_list_rewind_points_result, history_preview_rewind_request, history_preview_rewind_result, history_rewind_change_type, history_rewind_file_preview, history_rewind_mode, history_rewind_outcome, history_rewind_point, history_rewind_request, history_rewind_result, history_rewind_unavailable_reason, history_skipped_file_restore, history_summarize_for_handoff_result, history_truncate_request, history_truncate_result, hmac_auth_info, hook_invoke_request, hook_invoke_response, hook_type, installed_plugin, installed_plugin_info, installed_plugin_source, installed_plugin_source_git_hub, installed_plugin_source_local, installed_plugin_source_url, instruction_discovery_path, instruction_discovery_path_kind, instruction_discovery_path_list, instruction_discovery_path_location, instructions_discover_request, instructions_get_discovery_paths_request, instructions_get_sources_result, instruction_source, instruction_source_location, instruction_source_type, interrupt_main_turn_request, interrupt_main_turn_result, llm_inference_headers, llm_inference_http_request_chunk_request, llm_inference_http_request_chunk_result, llm_inference_http_request_start_request, llm_inference_http_request_start_result, llm_inference_http_request_start_transport, llm_inference_http_response_chunk_error, llm_inference_http_response_chunk_request, llm_inference_http_response_chunk_result, llm_inference_http_response_start_request, llm_inference_http_response_start_result, llm_inference_set_provider_result, local_session_metadata_value, log_request, log_result, lsp_initialize_request, managed_settings_read_result, marketplace_add_result, marketplace_browse_result, marketplace_info, marketplace_list_result, marketplace_plugin_info, marketplace_refresh_entry, marketplace_refresh_result, marketplace_remove_result, mcp_allowed_server, mcp_apps_call_tool_request, mcp_apps_diagnose_capability, mcp_apps_diagnose_request, mcp_apps_diagnose_result, mcp_apps_diagnose_server, mcp_apps_host_context, mcp_apps_host_context_details, mcp_apps_host_context_details_available_display_mode, mcp_apps_host_context_details_display_mode, mcp_apps_host_context_details_platform, mcp_apps_host_context_details_theme, mcp_apps_list_tools_request, mcp_apps_list_tools_result, mcp_apps_read_resource_request, mcp_apps_read_resource_result, mcp_apps_resource_content, mcp_apps_set_host_context_details, mcp_apps_set_host_context_details_available_display_mode, mcp_apps_set_host_context_details_display_mode, mcp_apps_set_host_context_details_platform, mcp_apps_set_host_context_details_theme, mcp_apps_set_host_context_request, mcp_cancel_sampling_execution_params, mcp_cancel_sampling_execution_result, mcp_config_add_request, mcp_config_disable_request, mcp_config_enable_request, mcp_config_list, mcp_config_remove_request, mcp_config_update_request, mcp_configure_git_hub_request, mcp_configure_git_hub_result, mcp_disable_request, mcp_discover_request, mcp_discover_result, mcp_enable_request, mcp_execute_sampling_params, mcp_execute_sampling_request, mcp_execute_sampling_result, mcp_filtered_server, mcp_headers_handle_pending_headers_refresh_request, mcp_headers_handle_pending_headers_refresh_request_request, mcp_headers_handle_pending_headers_refresh_request_result, mcp_host_state, mcp_is_server_running_request, mcp_is_server_running_result, mcp_list_tools_request, mcp_list_tools_result, mcp_oauth_authentication_state_changed_request, mcp_oauth_handle_pending_request, mcp_oauth_handle_pending_result, mcp_oauth_login_grant_type, mcp_oauth_login_request, mcp_oauth_login_result, mcp_oauth_pending_request_response, mcp_oauth_respond_request, mcp_oauth_respond_result, mcp_register_external_client_request, mcp_reload_with_config_request, mcp_remove_git_hub_result, mcp_resource, mcp_resource_annotations, mcp_resource_content, mcp_resource_icon, mcp_resources_list_request, mcp_resources_list_result, mcp_resources_list_templates_request, mcp_resources_list_templates_result, mcp_resources_read_request, mcp_resources_read_result, mcp_resource_template, mcp_restart_server_request, mcp_sampling_execution_action, mcp_sampling_execution_result, mcp_server, mcp_server_auth_config, mcp_server_auth_config_redirect_port, mcp_server_config, mcp_server_config_defer_tools, mcp_server_config_http, mcp_server_config_http_oauth_grant_type, mcp_server_config_http_type, mcp_server_config_stdio, mcp_server_failure_info, mcp_server_list, mcp_server_needs_auth_info, mcp_set_env_value_mode_details, mcp_set_env_value_mode_params, mcp_set_env_value_mode_result, mcp_start_server_request, mcp_start_servers_result, mcp_stop_server_request, mcp_tools, mcp_tool_ui, mcp_tool_ui_visibility, mcp_unregister_external_client_request, memory_configuration, metadata_context_attribution_result, metadata_context_heaviest_messages_request, metadata_context_heaviest_messages_result, metadata_context_info_request, metadata_context_info_result, metadata_is_processing_result, metadata_recompute_context_tokens_request, metadata_recompute_context_tokens_result, metadata_record_context_change_request, metadata_record_context_change_result, metadata_set_working_directory_request, metadata_set_working_directory_result, metadata_snapshot_current_mode, metadata_snapshot_remote_metadata, metadata_snapshot_remote_metadata_repository, metadata_snapshot_remote_metadata_task_type, model, model_billing, model_billing_promo, model_billing_token_prices, model_billing_token_prices_long_context, model_capabilities, model_capabilities_limits, model_capabilities_limits_vision, model_capabilities_override, model_capabilities_override_limits, model_capabilities_override_limits_vision, model_capabilities_override_supports, model_capabilities_supports, model_list, model_list_request, model_picker_category, model_picker_price_category, model_policy, model_policy_state, model_set_reasoning_effort_request, model_set_reasoning_effort_result, models_list_request, model_switch_to_request, model_switch_to_result, mode_set_request, named_provider_config, name_get_result, name_set_auto_request, name_set_auto_result, name_set_request, open_canvas_instance, options_update_additional_content_exclusion_policy, options_update_additional_content_exclusion_policy_rule, options_update_additional_content_exclusion_policy_rule_source, options_update_additional_content_exclusion_policy_scope, options_update_context_tier, options_update_env_value_mode, options_update_reasoning_summary, options_update_tool_filter_precedence, pending_permission_request, pending_permission_request_list, permission_decision, permission_decision_approved, permission_decision_approved_for_location, permission_decision_approved_for_session, permission_decision_approve_for_location, permission_decision_approve_for_location_approval, permission_decision_approve_for_location_approval_commands, permission_decision_approve_for_location_approval_custom_tool, permission_decision_approve_for_location_approval_extension_management, permission_decision_approve_for_location_approval_extension_permission_access, permission_decision_approve_for_location_approval_factory, permission_decision_approve_for_location_approval_mcp, permission_decision_approve_for_location_approval_mcp_sampling, permission_decision_approve_for_location_approval_memory, permission_decision_approve_for_location_approval_read, permission_decision_approve_for_location_approval_write, permission_decision_approve_for_session, permission_decision_approve_for_session_approval, permission_decision_approve_for_session_approval_commands, permission_decision_approve_for_session_approval_custom_tool, permission_decision_approve_for_session_approval_extension_management, permission_decision_approve_for_session_approval_extension_permission_access, permission_decision_approve_for_session_approval_factory, permission_decision_approve_for_session_approval_mcp, permission_decision_approve_for_session_approval_mcp_sampling, permission_decision_approve_for_session_approval_memory, permission_decision_approve_for_session_approval_read, permission_decision_approve_for_session_approval_write, permission_decision_approve_once, permission_decision_approve_permanently, permission_decision_cancelled, permission_decision_context, permission_decision_denied_by_content_exclusion_policy, permission_decision_denied_by_permission_request_hook, permission_decision_denied_by_rules, permission_decision_denied_interactively_by_user, permission_decision_denied_no_approval_rule_and_could_not_request_from_user, permission_decision_outcome, permission_decision_reject, permission_decision_request, permission_decision_source, permission_decision_surface, permission_decision_user_not_available, permission_location_add_tool_approval_params, permission_location_apply_params, permission_location_apply_result, permission_location_resolve_params, permission_location_resolve_result, permission_location_type, permission_paths_add_params, permission_paths_allowed_check_params, permission_paths_allowed_check_result, permission_paths_config, permission_paths_list, permission_paths_update_primary_params, permission_paths_workspace_check_params, permission_paths_workspace_check_result, permission_prompt_shown_notification, permission_request_result, permission_rules_set, permissions_allow_all_mode, permissions_configure_additional_content_exclusion_policy, permissions_configure_additional_content_exclusion_policy_rule, permissions_configure_additional_content_exclusion_policy_rule_source, permissions_configure_additional_content_exclusion_policy_scope, permissions_configure_params, permissions_configure_result, permissions_folder_trust_add_trusted_result, permissions_get_allow_all_request, permissions_locations_add_tool_approval_details, permissions_locations_add_tool_approval_details_commands, permissions_locations_add_tool_approval_details_custom_tool, permissions_locations_add_tool_approval_details_extension_management, permissions_locations_add_tool_approval_details_extension_permission_access, permissions_locations_add_tool_approval_details_factory, permissions_locations_add_tool_approval_details_mcp, permissions_locations_add_tool_approval_details_mcp_sampling, permissions_locations_add_tool_approval_details_memory, permissions_locations_add_tool_approval_details_read, permissions_locations_add_tool_approval_details_write, permissions_locations_add_tool_approval_result, permissions_modify_rules_params, permissions_modify_rules_result, permissions_modify_rules_scope, permissions_notify_prompt_shown_result, permissions_paths_add_result, permissions_paths_list_request, permissions_paths_update_primary_result, permissions_pending_requests_request, permissions_reset_session_approvals_request, permissions_reset_session_approvals_result, permissions_set_allow_all_request, permissions_set_allow_all_source, permissions_set_approve_all_request, permissions_set_approve_all_result, permissions_set_approve_all_source, permissions_set_required_request, permissions_set_required_result, permissions_urls_set_unrestricted_mode_result, permission_urls_config, permission_urls_set_unrestricted_mode_params, ping_request, ping_result, plan_read_result, plan_read_sql_todos_result, plan_read_sql_todos_with_dependencies_result, plan_sql_todo_dependency, plan_sql_todos_row, plan_update_request, plugin, plugin_install_result, plugin_list, plugin_list_result, plugins_disable_request, plugins_enable_request, plugins_install_request, plugins_marketplaces_add_request, plugins_marketplaces_browse_request, plugins_marketplaces_refresh_request, plugins_marketplaces_remove_request, plugins_reload_request, plugins_uninstall_request, plugins_update_request, plugin_update_all_entry, plugin_update_all_result, plugin_update_result, provider_add_request, provider_add_result, provider_config, provider_config_azure, provider_config_transport, provider_config_type, provider_config_wire_api, provider_endpoint, provider_endpoint_transport, provider_endpoint_type, provider_endpoint_wire_api, provider_get_endpoint_request, provider_model_config, provider_session_token, provider_token_acquire_request, provider_token_acquire_result, push_attachment, push_attachment_blob, push_attachment_directory, push_attachment_file, push_attachment_file_line_range, push_attachment_git_hub_actions_job, push_attachment_git_hub_commit, push_attachment_git_hub_file, push_attachment_git_hub_file_diff, push_attachment_git_hub_file_diff_side, push_attachment_git_hub_reference, push_attachment_git_hub_reference_type, push_attachment_git_hub_release, push_attachment_git_hub_repository, push_attachment_git_hub_snippet, push_attachment_git_hub_tree_comparison, push_attachment_git_hub_tree_comparison_side, push_attachment_git_hub_url, push_attachment_selection, push_attachment_selection_details, push_attachment_selection_details_end, push_attachment_selection_details_start, push_git_hub_repo_ref, queue_begin_deferred_idle_drain_request, queue_begin_deferred_idle_drain_result, queue_consume_system_notifications_request, queued_command_handled, queued_command_not_handled, queued_command_result, queue_defer_session_idle_request, queue_duplicate_at_request, queue_duplicate_at_result, queue_enqueue_resume_pending_result, queue_finish_deferred_idle_drain_request, queue_finish_deferred_idle_drain_result, queue_has_pending_result, queue_insert_at_request, queue_insert_at_result, queue_insert_message, queue_move_item_request, queue_move_item_result, queue_pending_items, queue_pending_items_kind, queue_pending_items_result, queue_remove_at_request, queue_remove_at_result, queue_remove_most_recent_result, queue_send_now_request, queue_send_now_result, queue_set_drain_paused_request, queue_snapshot_result, queue_update_text_request, queue_update_text_result, register_event_interest_params, register_event_interest_result, register_extension_tools_params, register_extension_tools_result, release_event_interest_params, remote_control_config, remote_control_config_existing_mc_session, remote_control_status, remote_control_status_active, remote_control_status_connecting, remote_control_status_error, remote_control_status_off, remote_control_status_result, remote_control_stop_result, remote_control_transfer_result, remote_enable_request, remote_enable_result, remote_notify_steerable_changed_request, remote_notify_steerable_changed_result, remote_session_connection_result, remote_session_metadata_repository, remote_session_metadata_task_type, remote_session_metadata_value, remote_session_mode, remote_session_repository, run_options, sandbox_config, sandbox_config_auth, sandbox_config_user_policy, sandbox_config_user_policy_experimental, sandbox_config_user_policy_experimental_seatbelt, sandbox_config_user_policy_filesystem, sandbox_config_user_policy_network, sandbox_config_user_policy_network_proxy, sandbox_config_user_policy_seatbelt, schedule_add_at_request, schedule_add_cron_request, schedule_add_request, schedule_add_result, schedule_add_self_paced_request, schedule_entry, schedule_has_self_paced_result, schedule_list, schedule_rearm_self_paced_request, schedule_stop_request, schedule_stop_result, secrets_add_filter_values_request, secrets_add_filter_values_result, send_agent_mode, send_attachments_to_message_params, send_message_item, send_messages_request, send_messages_result, send_mode, send_request, send_result, send_system_notification_request, server_agent_list, server_instruction_source_list, server_skill, server_skill_list, session_activity, session_agent_list_request, session_auth_status, session_bulk_delete_result, session_cancel_all_background_agents_result, session_capability, session_commands_list_request, session_completion_item, session_context, session_context_host_type, session_enrich_metadata_result, session_fs_append_file_request, session_fs_error, session_fs_error_code, session_fs_exists_request, session_fs_exists_result, session_fs_mkdir_request, session_fs_readdir_request, session_fs_readdir_result, session_fs_readdir_with_types_entry, session_fs_readdir_with_types_entry_type, session_fs_readdir_with_types_request, session_fs_readdir_with_types_result, session_fs_read_file_request, session_fs_read_file_result, session_fs_rename_request, session_fs_rm_request, session_fs_set_provider_capabilities, session_fs_set_provider_conventions, session_fs_set_provider_request, session_fs_set_provider_result, session_fs_sqlite_exists_request, session_fs_sqlite_exists_result, session_fs_sqlite_query_request, session_fs_sqlite_query_result, session_fs_sqlite_query_type, session_fs_sqlite_transaction_error, session_fs_sqlite_transaction_error_class, session_fs_sqlite_transaction_request, session_fs_sqlite_transaction_result, session_fs_sqlite_transaction_statement, session_fs_stat_request, session_fs_stat_result, session_fs_write_file_request, session_history_compact_request, session_installed_plugin, session_installed_plugin_source, session_installed_plugin_source_git_hub, session_installed_plugin_source_local, session_installed_plugin_source_url, session_limit_prediction_baseline_data, session_limit_prediction_client_type, session_limit_prediction_details, session_limit_prediction_predict_request, session_limit_prediction_request, session_limit_prediction_result, session_limit_prediction_source, session_limit_prediction_tier, session_limit_prediction_tier_option, session_limit_prediction_unavailable_reason, session_list, session_list_entry, session_list_filter, session_load_deferred_repo_hooks_result, session_log_level, session_managed_permissions, session_managed_settings, session_mcp_apps_call_tool_result, session_metadata_snapshot, session_mode, session_model_list, session_model_list_request, session_model_price_category, session_open_options, session_open_options_additional_content_exclusion_policy, session_open_options_additional_content_exclusion_policy_rule, session_open_options_additional_content_exclusion_policy_rule_source, session_open_options_additional_content_exclusion_policy_scope, session_open_options_env_value_mode, session_open_options_reasoning_summary, session_open_params, session_open_result, session_plugins_reload_request, session_provider_get_endpoint_request, session_prune_result, sessions_bulk_delete_request, sessions_check_in_use_request, sessions_check_in_use_result, sessions_close_request, sessions_close_result, sessions_delete_request, sessions_enrich_metadata_request, session_set_credentials_params, session_set_credentials_result, session_settings_built_in_tool_availability_snapshot, session_settings_evaluate_predicate_request, session_settings_evaluate_predicate_result, session_settings_job_snapshot, session_settings_model_snapshot, session_settings_online_evaluation_snapshot, session_settings_predicate_name, session_settings_repo_snapshot, session_settings_snapshot, session_settings_validation_snapshot, sessions_find_by_prefix_request, sessions_find_by_prefix_result, sessions_find_by_task_id_request, sessions_find_by_task_id_result, sessions_fork_request, sessions_fork_result, sessions_get_board_entry_count_request, sessions_get_board_entry_count_result, sessions_get_event_file_path_request, sessions_get_event_file_path_result, sessions_get_last_for_context_request, sessions_get_last_for_context_result, sessions_get_metadata_request, sessions_get_metadata_result, sessions_get_persisted_remote_steerable_request, sessions_get_persisted_remote_steerable_result, session_sizes, sessions_list_non_empty_session_ids_request, sessions_list_non_empty_session_ids_result, sessions_list_request, sessions_load_deferred_repo_hooks_request, sessions_open_attach, sessions_open_cloud, sessions_open_create, sessions_open_handoff, sessions_open_handoff_task_type, sessions_open_progress, sessions_open_progress_status, sessions_open_progress_step, sessions_open_remote, sessions_open_resume, sessions_open_resume_last, sessions_open_status, session_source, sessions_prune_old_request, sessions_register_extension_tools_on_session_options, sessions_release_lock_request, sessions_release_lock_result, sessions_reload_plugin_hooks_request, sessions_reload_plugin_hooks_result, sessions_save_request, sessions_save_result, sessions_set_additional_plugins_request, sessions_set_additional_plugins_result, sessions_set_remote_control_steering_request, sessions_start_remote_control_request, sessions_stop_remote_control_request, sessions_transfer_remote_control_request, session_telemetry_engagement, session_update_options_params, session_update_options_result, session_visibility_status, session_working_directory_context, session_working_directory_context_host_type, shell_cancel_user_requested_request, shell_exec_request, shell_exec_result, shell_execute_user_requested_request, shell_init_profile, shell_init_script, shell_init_script_shell, shell_kill_request, shell_kill_result, shell_kill_signal, shell_options, shutdown_request, skill, skill_discovery_path, skill_discovery_path_list, skill_discovery_scope, skill_list, skills_config_set_disabled_skills_request, skills_disable_request, skills_discover_request, skills_enable_request, skills_get_discovery_paths_request, skills_get_invoked_result, skills_invoked_skill, skills_load_diagnostics, slash_command_agent_prompt_result, slash_command_completed_result, slash_command_info, slash_command_input, slash_command_input_choice, slash_command_input_completion, slash_command_invocation_result, slash_command_kind, slash_command_select_subcommand_option, slash_command_select_subcommand_result, slash_command_text_result, subagent_settings_entry, subagent_settings_entry_context_tier, task_agent_info, task_agent_progress, task_execution_mode, task_info, task_list, task_progress_line, tasks_cancel_request, tasks_cancel_result, tasks_get_current_promotable_result, tasks_get_progress_request, tasks_get_progress_result, task_shell_info, task_shell_info_attachment_mode, task_shell_progress, tasks_promote_current_to_background_result, tasks_promote_to_background_request, tasks_promote_to_background_result, tasks_refresh_result, tasks_remove_request, tasks_remove_result, tasks_send_message_request, tasks_send_message_result, tasks_start_agent_request, tasks_start_agent_result, task_status, tasks_wait_for_pending_result, telemetry_set_feature_overrides_request, token_auth_info, tool, tool_list, tools_get_current_metadata_result, tools_initialize_and_validate_result, tools_list_request, tools_update_subagent_settings_result, ui_auto_mode_switch_response, ui_elicitation_array_any_of_field, ui_elicitation_array_any_of_field_items, ui_elicitation_array_any_of_field_items_any_of, ui_elicitation_array_enum_field, ui_elicitation_array_enum_field_items, ui_elicitation_field_value, ui_elicitation_request, ui_elicitation_response, ui_elicitation_response_action, ui_elicitation_response_content, ui_elicitation_result, ui_elicitation_schema, ui_elicitation_schema_property, ui_elicitation_schema_property_boolean, ui_elicitation_schema_property_number, ui_elicitation_schema_property_number_type, ui_elicitation_schema_property_string, ui_elicitation_schema_property_string_format, ui_elicitation_string_enum_field, ui_elicitation_string_one_of_field, ui_elicitation_string_one_of_field_one_of, ui_ephemeral_query_request, ui_ephemeral_query_result, ui_exit_plan_mode_action, ui_exit_plan_mode_response, ui_handle_pending_auto_mode_switch_request, ui_handle_pending_elicitation_request, ui_handle_pending_exit_plan_mode_request, ui_handle_pending_result, ui_handle_pending_sampling_request, ui_handle_pending_sampling_response, ui_handle_pending_session_limits_exhausted_request, ui_handle_pending_user_input_request, ui_register_direct_auto_mode_switch_handler_result, ui_session_limits_exhausted_response, ui_session_limits_exhausted_response_action, ui_unregister_direct_auto_mode_switch_handler_request, ui_unregister_direct_auto_mode_switch_handler_result, ui_user_input_response, update_subagent_settings_request, usage_get_metrics_result, usage_metrics_code_changes, usage_metrics_model_metric, usage_metrics_model_metric_requests, usage_metrics_model_metric_token_detail, usage_metrics_model_metric_usage, usage_metrics_token_detail, user_auth_info, user_requested_shell_command_result, user_setting_metadata, user_settings_get_result, user_settings_set_request, user_settings_set_result, visibility_get_result, visibility_set_request, visibility_set_result, workspace_diff_file_change, workspace_diff_file_change_type, workspace_diff_mode, workspace_diff_result, workspaces_add_summary_request, workspaces_add_summary_result, workspaces_autopilot_objective_exists_result, workspaces_checkpoints, workspaces_create_file_request, workspaces_delete_autopilot_objective_result, workspaces_diff_request, workspaces_ensure_request, workspaces_get_workspace_result, workspaces_list_checkpoints_result, workspaces_list_files_result, workspaces_read_autopilot_objective_result, workspaces_read_checkpoint_request, workspaces_read_checkpoint_result, workspaces_read_file_request, workspaces_read_file_result, workspaces_save_large_paste_request, workspaces_save_large_paste_result, workspaces_truncate_summaries_request, workspace_summary_host_type, workspaces_update_metadata_request, workspaces_workspace_details_host_type, workspaces_write_autopilot_objective_request, workspaces_write_autopilot_objective_result, session_context_attribution, session_context_info, subagent_settings, task_progress, workspace_summary)
def to_dict(self) -> dict:
result: dict = {}
@@ -31404,6 +31500,7 @@ def to_dict(self) -> dict:
result["RemoteSessionRepository"] = to_class(RemoteSessionRepository, self.remote_session_repository)
result["RunOptions"] = to_class(RunOptions, self.run_options)
result["SandboxConfig"] = to_class(SandboxConfig, self.sandbox_config)
+ result["SandboxConfigAuth"] = to_class(SandboxConfigAuth, self.sandbox_config_auth)
result["SandboxConfigUserPolicy"] = to_class(SandboxConfigUserPolicy, self.sandbox_config_user_policy)
result["SandboxConfigUserPolicyExperimental"] = to_class(SandboxConfigUserPolicyExperimental, self.sandbox_config_user_policy_experimental)
result["SandboxConfigUserPolicyExperimentalSeatbelt"] = to_class(SandboxConfigUserPolicyExperimentalSeatbelt, self.sandbox_config_user_policy_experimental_seatbelt)
@@ -32766,9 +32863,11 @@ async def get_run(self, params: FactoryGetRunRequest, *, timeout: float | None =
params_dict["sessionId"] = self._session_id
return FactoryRunResult.from_dict(await self._client.request("session.factory.getRun", params_dict, **_timeout_kwargs(timeout)))
- async def list_runs(self, *, timeout: float | None = None) -> FactoryListRunsResult:
- "Lists durable factory runs for this session in creation order.\n\nReturns:\n Factory runs in durable creation order."
- return FactoryListRunsResult.from_dict(await self._client.request("session.factory.listRuns", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)))
+ async def list_runs(self, params: FactoryListRunsRequest, *, timeout: float | None = None) -> FactoryListRunsResult:
+ "Lists durable factory runs for this session in creation order.\n\nArgs:\n params: Parameters for paging factory runs.\n\nReturns:\n A page of factory runs in durable creation order."
+ params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None}
+ params_dict["sessionId"] = self._session_id
+ return FactoryListRunsResult.from_dict(await self._client.request("session.factory.listRuns", params_dict, **_timeout_kwargs(timeout)))
async def get_run_detail(self, params: FactoryGetRunRequest, *, timeout: float | None = None) -> FactoryRunDetail:
"Gets durable and live observability detail for one factory run.\n\nArgs:\n params: Parameters for retrieving a factory run.\n\nReturns:\n Full factory run observability detail."
@@ -35404,6 +35503,7 @@ async def handle_git_hub_telemetry_event(params: dict) -> None:
"RemoteSessionRepository",
"RunOptions",
"SandboxConfig",
+ "SandboxConfigAuth",
"SandboxConfigUserPolicy",
"SandboxConfigUserPolicyExperimental",
"SandboxConfigUserPolicyExperimentalSeatbelt",
diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py
index d11317a82b..4c3a53e539 100644
--- a/python/copilot/generated/session_events.py
+++ b/python/copilot/generated/session_events.py
@@ -7836,6 +7836,7 @@ class SubagentCompletedData:
agent_display_name: str
agent_name: str
tool_call_id: str
+ cancelled: bool | None = None
duration: timedelta | None = None
model: str | None = None
total_tokens: int | None = None
@@ -7847,6 +7848,7 @@ def from_dict(obj: Any) -> "SubagentCompletedData":
agent_display_name = from_str(obj.get("agentDisplayName"))
agent_name = from_str(obj.get("agentName"))
tool_call_id = from_str(obj.get("toolCallId"))
+ cancelled = from_union([from_none, from_bool], obj.get("cancelled"))
duration = from_union([from_none, from_timedelta], obj.get("durationMs"))
model = from_union([from_none, from_str], obj.get("model"))
total_tokens = from_union([from_none, from_int], obj.get("totalTokens"))
@@ -7855,6 +7857,7 @@ def from_dict(obj: Any) -> "SubagentCompletedData":
agent_display_name=agent_display_name,
agent_name=agent_name,
tool_call_id=tool_call_id,
+ cancelled=cancelled,
duration=duration,
model=model,
total_tokens=total_tokens,
@@ -7866,6 +7869,8 @@ def to_dict(self) -> dict:
result["agentDisplayName"] = from_str(self.agent_display_name)
result["agentName"] = from_str(self.agent_name)
result["toolCallId"] = from_str(self.tool_call_id)
+ if self.cancelled is not None:
+ result["cancelled"] = from_union([from_none, from_bool], self.cancelled)
if self.duration is not None:
result["durationMs"] = from_union([from_none, to_timedelta_int], self.duration)
if self.model is not None:
diff --git a/rust/src/generated/api_types.rs b/rust/src/generated/api_types.rs
index c93f34cf64..caf9457a87 100644
--- a/rust/src/generated/api_types.rs
+++ b/rust/src/generated/api_types.rs
@@ -4093,12 +4093,21 @@ pub struct FactoryAckResult {}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FactoryAgentOptions {
+ /// Optional custom agent name for the subagent. This field is accepted but not yet honored.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub agent: Option,
+ /// Optional context tier for the subagent. This field is accepted but not yet honored.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub context_tier: Option,
/// Optional label distinguishing otherwise identical memoized agent calls.
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option,
/// Optional model identifier for the subagent.
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option,
+ /// Optional reasoning effort for the subagent. This field is accepted but not yet honored.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub reasoning_effort: Option,
/// Optional JSON Schema for structured agent output.
#[serde(skip_serializing_if = "Option::is_none")]
pub schema: Option,
@@ -4362,7 +4371,7 @@ pub struct FactoryJournalPutRequest {
pub run_id: String,
}
-/// Empty parameters for listing factory runs.
+/// Parameters for paging factory runs.
///
///
///
@@ -4372,7 +4381,17 @@ pub struct FactoryJournalPutRequest {
///
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
-pub struct FactoryListRunsRequest {}
+pub struct FactoryListRunsRequest {
+ /// Exclusive forward cursor.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub after_seq: Option,
+ /// Exclusive backward cursor.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub before_seq: Option,
+ /// Maximum terminal runs to return. Defaults to 200 and is capped at 500.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub limit: Option,
+}
/// Durable factory resource consumption.
///
@@ -4443,7 +4462,7 @@ pub struct FactoryRunSummary {
pub updated_at: i64,
}
-/// Factory runs in durable creation order.
+/// A page of factory runs in durable creation order.
///
///
///
@@ -4454,6 +4473,18 @@ pub struct FactoryRunSummary {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FactoryListRunsResult {
+ /// Whether terminal runs newer than this page exist.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub has_more_newer: Option
,
+ /// Newest terminal-run cursor in this page, or null when the terminal window is empty.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub newest_seq: Option,
+ /// Oldest terminal-run cursor in this page, or null when the terminal window is empty.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub oldest_seq: Option,
+ /// Number of terminal runs older than this page.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub omitted_older: Option,
pub runs: Vec,
}
@@ -12317,6 +12348,25 @@ pub struct RemoteSessionRepository {
pub owner: String,
}
+/// Credential-injection capability flags applied while the sandbox is enabled.
+///
+///
+///
+/// **Experimental.** This type is part of an experimental wire-protocol surface
+/// and may change or be removed in future SDK or CLI releases.
+///
+///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SandboxConfigAuth {
+ /// Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in).
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub gh: Option,
+ /// Whether to inject git credentials as an `http..extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. github.com is served by the Copilot token; every other forge (Azure DevOps, GitHub Enterprise Server, GitLab, ...) by a credential the host resolves from the user's own helper before the sandbox is applied. Default: false (opt-in).
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub git: Option,
+}
+
/// macOS seatbelt experimental options.
///
///
@@ -12475,14 +12525,11 @@ pub struct SandboxConfig {
/// Whether to auto-grant read access to common developer-tool caches, registries, and toolchains in their default home locations (cargo, go, npm, Maven, and more), plus read-write access to (and, on Unix, up-front creation of) the scratch caches builds write on every run (go-build, ccache, sccache, Gradle caches, Cargo lock/tracker files), so builds work without extra configuration; a relocated CARGO_HOME additionally gets its Cargo lock files granted read-write. Default: true (enabled by default; set to false to opt out).
#[serde(skip_serializing_if = "Option::is_none")]
pub allow_dev_tool_access: Option
,
+ /// Credential-injection capability flags.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub auth: Option,
/// Whether sandboxing is enabled for the session.
pub enabled: bool,
- /// Whether to export `GH_TOKEN` so the `gh` CLI authenticates inside the sandbox without the OS keyring the sandbox blocks. Default: false (opt-in).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub gh_auth: Option,
- /// Whether to inject the Copilot GitHub token as an `http..extraheader` so authenticated HTTPS git works inside the sandbox without the shell-based credential helper the sandbox blocks. Default: false (opt-in).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub git_auth: Option,
/// User-managed sandbox policy fragment merged into the auto-discovered base policy.
#[serde(skip_serializing_if = "Option::is_none")]
pub user_policy: Option,
@@ -19359,7 +19406,7 @@ pub struct SessionFactoryGetRunResult {
pub status: FactoryRunStatus,
}
-/// Factory runs in durable creation order.
+/// A page of factory runs in durable creation order.
///
///
///
@@ -19370,6 +19417,18 @@ pub struct SessionFactoryGetRunResult {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SessionFactoryListRunsResult {
+ /// Whether terminal runs newer than this page exist.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub has_more_newer: Option
,
+ /// Newest terminal-run cursor in this page, or null when the terminal window is empty.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub newest_seq: Option,
+ /// Oldest terminal-run cursor in this page, or null when the terminal window is empty.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub oldest_seq: Option,
+ /// Number of terminal runs older than this page.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub omitted_older: Option,
pub runs: Vec,
}
diff --git a/rust/src/generated/rpc.rs b/rust/src/generated/rpc.rs
index db69aa1e84..fae4d7e168 100644
--- a/rust/src/generated/rpc.rs
+++ b/rust/src/generated/rpc.rs
@@ -4511,9 +4511,13 @@ impl<'a> SessionRpcFactory<'a> {
///
/// Wire method: `session.factory.listRuns`.
///
+ /// # Parameters
+ ///
+ /// * `params` - Parameters for paging factory runs.
+ ///
/// # Returns
///
- /// Factory runs in durable creation order.
+ /// A page of factory runs in durable creation order.
///
///
///
@@ -4522,8 +4526,12 @@ impl<'a> SessionRpcFactory<'a> {
/// SDK and CLI versions if your code depends on it.
///
///
- pub async fn list_runs(&self) -> Result {
- let wire_params = serde_json::json!({ "sessionId": self.session.id() });
+ pub async fn list_runs(
+ &self,
+ params: FactoryListRunsRequest,
+ ) -> Result {
+ let mut wire_params = serde_json::to_value(params)?;
+ wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string());
let _value = self
.session
.client()
diff --git a/rust/src/generated/session_events.rs b/rust/src/generated/session_events.rs
index f5bfab83f4..913499a6f7 100644
--- a/rust/src/generated/session_events.rs
+++ b/rust/src/generated/session_events.rs
@@ -2860,6 +2860,9 @@ pub struct SubagentCompletedData {
pub agent_display_name: String,
/// Internal name of the sub-agent
pub agent_name: String,
+ /// Whether the sub-agent was torn down by cancellation - its own abort, or an ancestor being killed - instead of finishing its work. Cancellation is not a failure, so the run still reports completion; this distinguishes a torn-down sub-agent from one that ran to the end.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub cancelled: Option,
/// Wall-clock duration of the sub-agent execution in milliseconds
#[serde(skip_serializing_if = "Option::is_none")]
pub duration_ms: Option,
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index b55238c179..1a73bb053c 100644
--- a/test/harness/package-lock.json
+++ b/test/harness/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
- "@github/copilot": "^1.0.79-6",
+ "@github/copilot": "^1.0.79-9",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
@@ -501,9 +501,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-6.tgz",
- "integrity": "sha512-per2cqu8WYuRXXvdU38cYZ7lUSQP5uBDY2QfFZow9FgGOyOToEWz+ykw2NYVKMnx0u1gIiI20Ovl4zec9Dob6w==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-9.tgz",
+ "integrity": "sha512-1QRRV3z1HA8sr3JUo4e2l+zFVbIGIOqnmTwzdJ+ilfr+mkmC7LYWkJxV3+j+zN0nq8JAgusSL/Schc43MPIqug==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
@@ -513,20 +513,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.79-6",
- "@github/copilot-darwin-x64": "1.0.79-6",
- "@github/copilot-linux-arm64": "1.0.79-6",
- "@github/copilot-linux-x64": "1.0.79-6",
- "@github/copilot-linuxmusl-arm64": "1.0.79-6",
- "@github/copilot-linuxmusl-x64": "1.0.79-6",
- "@github/copilot-win32-arm64": "1.0.79-6",
- "@github/copilot-win32-x64": "1.0.79-6"
+ "@github/copilot-darwin-arm64": "1.0.79-9",
+ "@github/copilot-darwin-x64": "1.0.79-9",
+ "@github/copilot-linux-arm64": "1.0.79-9",
+ "@github/copilot-linux-x64": "1.0.79-9",
+ "@github/copilot-linuxmusl-arm64": "1.0.79-9",
+ "@github/copilot-linuxmusl-x64": "1.0.79-9",
+ "@github/copilot-win32-arm64": "1.0.79-9",
+ "@github/copilot-win32-x64": "1.0.79-9"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-6.tgz",
- "integrity": "sha512-22aYilTJsiZX4w55DPXHvJFHSNwZWGip4DcQCQTvzzVIGc8MjlCQVModE9B6ElGs18hUaM3NH4piTYYT0HqNGQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-DBTtv06Lpka1R+bkYfCWH38838b66bTLvsRsNjSuQV9AzgMPHjIn+Q2wAmU89rUyw5ej9iCIL5ppps+roi7qRw==",
"cpu": [
"arm64"
],
@@ -541,9 +541,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-6.tgz",
- "integrity": "sha512-1ESqmLenOGkfD4KwgxtUZh+Wt5+qKwtLHGpfpRl+d/BSKj4cNo9FUO2vFEmF3zQefpmady3vmDURSdi65hlC+w==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-9.tgz",
+ "integrity": "sha512-j+XOqtVWa0EZ8lBR+xIsPVI7ErpDepgr3WuSfUCkC9fOdvnVJ1rbyBY3gCM/urY4wJNdbHc4t1vN9MjtRNpTGA==",
"cpu": [
"x64"
],
@@ -558,9 +558,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-6.tgz",
- "integrity": "sha512-R8ZmfoJuOj1CT0zamAnRJi7nxhUPRFi3vo3dWlzSkto0Uwez+j2IJmyGIZEZbN65BJJJMD2/kg0GZQG+l+PmUA==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-eYsJlokogYeXo2tCwqoDW+rELbLs0ht7b3R1nrl9odO6U6ZabIm6BilSLSxjWCtE1ZpqDLmdJbOV0/6cQwjvlA==",
"cpu": [
"arm64"
],
@@ -575,9 +575,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-6.tgz",
- "integrity": "sha512-P8Dgq59MIoiWKTRUGLrzzQ+NX54sqsHQFAoTJPis2K0N1O7BUTN4RDl8aPN3v4c1MCkbH9YzjmT8ns1JPeIUuQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-9.tgz",
+ "integrity": "sha512-KknlE4hT3rw/Ne1aL+F1KEQrq40d4I8aGfxAEuahmn3NaM7CSBikDVIsAvkmTq7e2vHzaLytpclc8+gcEAIK6Q==",
"cpu": [
"x64"
],
@@ -592,9 +592,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-6.tgz",
- "integrity": "sha512-6CS4YuL1x8YwoEfr/dPcq+ZQYTJQTukO/Uuv88eZ9/RWGdhcls14j/WWPcte8LLk2EFJXchM9WPmkOmZppPkwQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-Wrk+vpzg9ho/uC7ajNgIEjPShtB+pGlaJV+8rvYcHeQG6Gyx8YrPMI+OMdYou6RI9firqIaywT0UPuy9PUzoOg==",
"cpu": [
"arm64"
],
@@ -609,9 +609,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-6.tgz",
- "integrity": "sha512-y+fX6P4oXKADqXsEWCTqWFmLECTm2jVmxkCEC6C1TGqHDzN0+X2pJQd/LTSOZFmtlgxVjusL93eCk1mwa2MapQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-9.tgz",
+ "integrity": "sha512-ERULakTfCb4KYK4hGcMPRp5qm5K7KqKFHhGrAdn1VLrm8QsXDYzl2vUO4tIU/TxRW5VA9pmWh30JpCjQScSnDA==",
"cpu": [
"x64"
],
@@ -626,9 +626,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-6.tgz",
- "integrity": "sha512-E/JxBAA4Dqy7d81mCBfZ1L9XJH7eK1DBQn2Jlur5oBvA3qluX05kXcGTlmGkGVA2mkM9rD5zaSC8yZ5grq40HQ==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-9.tgz",
+ "integrity": "sha512-XAe2calnhhiAVdIb2jUn4Bh961nu4zz3N5tcrb5CNjDSbjEE2LQf8CaNV4h/QhHjjpcmqFIfMQBMYxW1+9xixg==",
"cpu": [
"arm64"
],
@@ -643,9 +643,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.79-6",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-6.tgz",
- "integrity": "sha512-7Hlfb438QNqU34OhhRiJiElWoyP7xED5iZunU1vC00L1RbrsTXDeC41y2oAxYiXa/bX60TV4x/oWuGli/0no6A==",
+ "version": "1.0.79-9",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-9.tgz",
+ "integrity": "sha512-/nK1IR5Vho2r6vuzq9xziVWwlgan41eL62Oo0feu7RaMvhS+f40l4jZCjuWLbeysh/we642qCyRjK8gkv730lA==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index efb64a56d2..3b9d8e289c 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -14,7 +14,7 @@
"node": "^20.19.0 || >=22.12.0"
},
"devDependencies": {
- "@github/copilot": "^1.0.79-6",
+ "@github/copilot": "^1.0.79-9",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
From 3108e8ce26286043afa52f12781331460628baa0 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 10 Aug 2026 16:14:53 -0400
Subject: [PATCH 10/51] Update @github/copilot to 1.0.79 (#2306)
* Update @github/copilot to 1.0.79
- Updated nodejs and test harness dependencies
- Re-ran code generators
- Formatted generated code
* Fix flaky Node cleanup test
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Stephen Toub
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
java/pom.xml | 2 +-
java/scripts/codegen/package-lock.json | 72 +++++++++++++-------------
java/scripts/codegen/package.json | 2 +-
nodejs/package-lock.json | 72 +++++++++++++-------------
nodejs/package.json | 2 +-
nodejs/samples/package-lock.json | 2 +-
nodejs/test/e2e/client.e2e.test.ts | 9 +++-
test/harness/package-lock.json | 72 +++++++++++++-------------
test/harness/package.json | 2 +-
9 files changed, 120 insertions(+), 115 deletions(-)
diff --git a/java/pom.xml b/java/pom.xml
index c5e9f62ad6..796051891b 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -88,7 +88,7 @@
DO NOT EDIT MANUALLY. Updated by the update-copilot-dependency
workflow.
-->
- ^1.0.79-9
+ ^1.0.79
diff --git a/java/scripts/codegen/package-lock.json b/java/scripts/codegen/package-lock.json
index d4824febaf..527eef03e7 100644
--- a/java/scripts/codegen/package-lock.json
+++ b/java/scripts/codegen/package-lock.json
@@ -6,7 +6,7 @@
"": {
"name": "copilot-sdk-java-codegen",
"dependencies": {
- "@github/copilot": "^1.0.79-9",
+ "@github/copilot": "^1.0.79",
"json-schema": "^0.4.0",
"tsx": "^4.23.1"
}
@@ -428,9 +428,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-9.tgz",
- "integrity": "sha512-1QRRV3z1HA8sr3JUo4e2l+zFVbIGIOqnmTwzdJ+ilfr+mkmC7LYWkJxV3+j+zN0nq8JAgusSL/Schc43MPIqug==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79.tgz",
+ "integrity": "sha512-uHBm2BYbKJgyfiKp1WokX7QUNHGvzEX0zaGeb3qM3CybP06rsJrX3JgQe95qwwma6vQz0ah9gV68ERW2JqaKRA==",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"detect-libc": "^2.1.2"
@@ -439,20 +439,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.79-9",
- "@github/copilot-darwin-x64": "1.0.79-9",
- "@github/copilot-linux-arm64": "1.0.79-9",
- "@github/copilot-linux-x64": "1.0.79-9",
- "@github/copilot-linuxmusl-arm64": "1.0.79-9",
- "@github/copilot-linuxmusl-x64": "1.0.79-9",
- "@github/copilot-win32-arm64": "1.0.79-9",
- "@github/copilot-win32-x64": "1.0.79-9"
+ "@github/copilot-darwin-arm64": "1.0.79",
+ "@github/copilot-darwin-x64": "1.0.79",
+ "@github/copilot-linux-arm64": "1.0.79",
+ "@github/copilot-linux-x64": "1.0.79",
+ "@github/copilot-linuxmusl-arm64": "1.0.79",
+ "@github/copilot-linuxmusl-x64": "1.0.79",
+ "@github/copilot-win32-arm64": "1.0.79",
+ "@github/copilot-win32-x64": "1.0.79"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-9.tgz",
- "integrity": "sha512-DBTtv06Lpka1R+bkYfCWH38838b66bTLvsRsNjSuQV9AzgMPHjIn+Q2wAmU89rUyw5ej9iCIL5ppps+roi7qRw==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79.tgz",
+ "integrity": "sha512-rsw7JoMvlcxXb0yx08oIeEc0x2hUEwKSfhX9ESKfdMVt0Ckrzm4OEvNUyzOpOnLJ9+l3h/aI+u1w5g2ZU2K7UA==",
"cpu": [
"arm64"
],
@@ -466,9 +466,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-9.tgz",
- "integrity": "sha512-j+XOqtVWa0EZ8lBR+xIsPVI7ErpDepgr3WuSfUCkC9fOdvnVJ1rbyBY3gCM/urY4wJNdbHc4t1vN9MjtRNpTGA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79.tgz",
+ "integrity": "sha512-D983e2lXYnq+KhjA8mTZXonY1+LGfJN9BM195J73shUvx49nRJmibDHWLvVtGeYc+43evGUOAQrOqOspAhhWPQ==",
"cpu": [
"x64"
],
@@ -482,9 +482,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-9.tgz",
- "integrity": "sha512-eYsJlokogYeXo2tCwqoDW+rELbLs0ht7b3R1nrl9odO6U6ZabIm6BilSLSxjWCtE1ZpqDLmdJbOV0/6cQwjvlA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79.tgz",
+ "integrity": "sha512-qqaNkvi92Wg+4OZk/kTWC2nUG72G0vV6eRAo5+PnKaPmjdX1GsI0a+lPxXPEbzX0zYLi/8yrUyANwyyNEsGgXA==",
"cpu": [
"arm64"
],
@@ -498,9 +498,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-9.tgz",
- "integrity": "sha512-KknlE4hT3rw/Ne1aL+F1KEQrq40d4I8aGfxAEuahmn3NaM7CSBikDVIsAvkmTq7e2vHzaLytpclc8+gcEAIK6Q==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79.tgz",
+ "integrity": "sha512-wzotZfvHkItutciLFMXZT2k9Qiii4Ta8tsVDCMQ7CP8hPxV91FyJ1yf3+FFSSfPvWrfYM6BOAiqIuX+LjgRuiw==",
"cpu": [
"x64"
],
@@ -514,9 +514,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-9.tgz",
- "integrity": "sha512-Wrk+vpzg9ho/uC7ajNgIEjPShtB+pGlaJV+8rvYcHeQG6Gyx8YrPMI+OMdYou6RI9firqIaywT0UPuy9PUzoOg==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79.tgz",
+ "integrity": "sha512-INtRSARl7DdNm2MXnn4GJuK+Y7QD24ANox02uH8htNQwRlNvdvg+YGS1V/mYgLDXFepeUjMjzTNC+i70+kh5uw==",
"cpu": [
"arm64"
],
@@ -530,9 +530,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-9.tgz",
- "integrity": "sha512-ERULakTfCb4KYK4hGcMPRp5qm5K7KqKFHhGrAdn1VLrm8QsXDYzl2vUO4tIU/TxRW5VA9pmWh30JpCjQScSnDA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79.tgz",
+ "integrity": "sha512-LxJAIfPP6Ok/9qpXGZuhnAft3W9JVcK9tbO3jWXcGDJT3v+2NtutyjmP/A7/cDXdTruXVQ4MybwAgacN8Gj/sg==",
"cpu": [
"x64"
],
@@ -546,9 +546,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-9.tgz",
- "integrity": "sha512-XAe2calnhhiAVdIb2jUn4Bh961nu4zz3N5tcrb5CNjDSbjEE2LQf8CaNV4h/QhHjjpcmqFIfMQBMYxW1+9xixg==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79.tgz",
+ "integrity": "sha512-5wg/ayCBTVy4g4FdO/9BJZRVARY0sgjAn9rBkw5BSJMv4u7Mvxg5Sftlift+V5UWxTyCSHAELZ5IHKvox4Yi8w==",
"cpu": [
"arm64"
],
@@ -562,9 +562,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-9.tgz",
- "integrity": "sha512-/nK1IR5Vho2r6vuzq9xziVWwlgan41eL62Oo0feu7RaMvhS+f40l4jZCjuWLbeysh/we642qCyRjK8gkv730lA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79.tgz",
+ "integrity": "sha512-FTpThWwwCDYnLdE0pfdo5zpAQLLVg36kmC2IKyVMuCYv9iPe7rE1mz7ng/UITN9M3TAMBrwHSvCV3pITvw4W8Q==",
"cpu": [
"x64"
],
diff --git a/java/scripts/codegen/package.json b/java/scripts/codegen/package.json
index 5e3630ec07..b1393f40b6 100644
--- a/java/scripts/codegen/package.json
+++ b/java/scripts/codegen/package.json
@@ -7,7 +7,7 @@
"generate:java": "tsx java.ts"
},
"dependencies": {
- "@github/copilot": "^1.0.79-9",
+ "@github/copilot": "^1.0.79",
"json-schema": "^0.4.0",
"tsx": "^4.23.1"
}
diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json
index 39fa8b6fa8..0fe7660f81 100644
--- a/nodejs/package-lock.json
+++ b/nodejs/package-lock.json
@@ -9,7 +9,7 @@
"version": "0.0.0-dev",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.79-9",
+ "@github/copilot": "^1.0.79",
"koffi": "^3.1.0",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
@@ -700,9 +700,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-9.tgz",
- "integrity": "sha512-1QRRV3z1HA8sr3JUo4e2l+zFVbIGIOqnmTwzdJ+ilfr+mkmC7LYWkJxV3+j+zN0nq8JAgusSL/Schc43MPIqug==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79.tgz",
+ "integrity": "sha512-uHBm2BYbKJgyfiKp1WokX7QUNHGvzEX0zaGeb3qM3CybP06rsJrX3JgQe95qwwma6vQz0ah9gV68ERW2JqaKRA==",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"detect-libc": "^2.1.2"
@@ -711,20 +711,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.79-9",
- "@github/copilot-darwin-x64": "1.0.79-9",
- "@github/copilot-linux-arm64": "1.0.79-9",
- "@github/copilot-linux-x64": "1.0.79-9",
- "@github/copilot-linuxmusl-arm64": "1.0.79-9",
- "@github/copilot-linuxmusl-x64": "1.0.79-9",
- "@github/copilot-win32-arm64": "1.0.79-9",
- "@github/copilot-win32-x64": "1.0.79-9"
+ "@github/copilot-darwin-arm64": "1.0.79",
+ "@github/copilot-darwin-x64": "1.0.79",
+ "@github/copilot-linux-arm64": "1.0.79",
+ "@github/copilot-linux-x64": "1.0.79",
+ "@github/copilot-linuxmusl-arm64": "1.0.79",
+ "@github/copilot-linuxmusl-x64": "1.0.79",
+ "@github/copilot-win32-arm64": "1.0.79",
+ "@github/copilot-win32-x64": "1.0.79"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-9.tgz",
- "integrity": "sha512-DBTtv06Lpka1R+bkYfCWH38838b66bTLvsRsNjSuQV9AzgMPHjIn+Q2wAmU89rUyw5ej9iCIL5ppps+roi7qRw==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79.tgz",
+ "integrity": "sha512-rsw7JoMvlcxXb0yx08oIeEc0x2hUEwKSfhX9ESKfdMVt0Ckrzm4OEvNUyzOpOnLJ9+l3h/aI+u1w5g2ZU2K7UA==",
"cpu": [
"arm64"
],
@@ -738,9 +738,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-9.tgz",
- "integrity": "sha512-j+XOqtVWa0EZ8lBR+xIsPVI7ErpDepgr3WuSfUCkC9fOdvnVJ1rbyBY3gCM/urY4wJNdbHc4t1vN9MjtRNpTGA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79.tgz",
+ "integrity": "sha512-D983e2lXYnq+KhjA8mTZXonY1+LGfJN9BM195J73shUvx49nRJmibDHWLvVtGeYc+43evGUOAQrOqOspAhhWPQ==",
"cpu": [
"x64"
],
@@ -754,9 +754,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-9.tgz",
- "integrity": "sha512-eYsJlokogYeXo2tCwqoDW+rELbLs0ht7b3R1nrl9odO6U6ZabIm6BilSLSxjWCtE1ZpqDLmdJbOV0/6cQwjvlA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79.tgz",
+ "integrity": "sha512-qqaNkvi92Wg+4OZk/kTWC2nUG72G0vV6eRAo5+PnKaPmjdX1GsI0a+lPxXPEbzX0zYLi/8yrUyANwyyNEsGgXA==",
"cpu": [
"arm64"
],
@@ -770,9 +770,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-9.tgz",
- "integrity": "sha512-KknlE4hT3rw/Ne1aL+F1KEQrq40d4I8aGfxAEuahmn3NaM7CSBikDVIsAvkmTq7e2vHzaLytpclc8+gcEAIK6Q==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79.tgz",
+ "integrity": "sha512-wzotZfvHkItutciLFMXZT2k9Qiii4Ta8tsVDCMQ7CP8hPxV91FyJ1yf3+FFSSfPvWrfYM6BOAiqIuX+LjgRuiw==",
"cpu": [
"x64"
],
@@ -786,9 +786,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-9.tgz",
- "integrity": "sha512-Wrk+vpzg9ho/uC7ajNgIEjPShtB+pGlaJV+8rvYcHeQG6Gyx8YrPMI+OMdYou6RI9firqIaywT0UPuy9PUzoOg==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79.tgz",
+ "integrity": "sha512-INtRSARl7DdNm2MXnn4GJuK+Y7QD24ANox02uH8htNQwRlNvdvg+YGS1V/mYgLDXFepeUjMjzTNC+i70+kh5uw==",
"cpu": [
"arm64"
],
@@ -802,9 +802,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-9.tgz",
- "integrity": "sha512-ERULakTfCb4KYK4hGcMPRp5qm5K7KqKFHhGrAdn1VLrm8QsXDYzl2vUO4tIU/TxRW5VA9pmWh30JpCjQScSnDA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79.tgz",
+ "integrity": "sha512-LxJAIfPP6Ok/9qpXGZuhnAft3W9JVcK9tbO3jWXcGDJT3v+2NtutyjmP/A7/cDXdTruXVQ4MybwAgacN8Gj/sg==",
"cpu": [
"x64"
],
@@ -818,9 +818,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-9.tgz",
- "integrity": "sha512-XAe2calnhhiAVdIb2jUn4Bh961nu4zz3N5tcrb5CNjDSbjEE2LQf8CaNV4h/QhHjjpcmqFIfMQBMYxW1+9xixg==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79.tgz",
+ "integrity": "sha512-5wg/ayCBTVy4g4FdO/9BJZRVARY0sgjAn9rBkw5BSJMv4u7Mvxg5Sftlift+V5UWxTyCSHAELZ5IHKvox4Yi8w==",
"cpu": [
"arm64"
],
@@ -834,9 +834,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-9.tgz",
- "integrity": "sha512-/nK1IR5Vho2r6vuzq9xziVWwlgan41eL62Oo0feu7RaMvhS+f40l4jZCjuWLbeysh/we642qCyRjK8gkv730lA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79.tgz",
+ "integrity": "sha512-FTpThWwwCDYnLdE0pfdo5zpAQLLVg36kmC2IKyVMuCYv9iPe7rE1mz7ng/UITN9M3TAMBrwHSvCV3pITvw4W8Q==",
"cpu": [
"x64"
],
diff --git a/nodejs/package.json b/nodejs/package.json
index a4160cd2c3..437a77a01b 100644
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -56,7 +56,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.79-9",
+ "@github/copilot": "^1.0.79",
"koffi": "^3.1.0",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json
index ad84030026..66b4df4708 100644
--- a/nodejs/samples/package-lock.json
+++ b/nodejs/samples/package-lock.json
@@ -18,7 +18,7 @@
"version": "0.0.0-dev",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.79-9",
+ "@github/copilot": "^1.0.79",
"koffi": "^3.1.0",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
diff --git a/nodejs/test/e2e/client.e2e.test.ts b/nodejs/test/e2e/client.e2e.test.ts
index 89489f78e6..35e7440766 100644
--- a/nodejs/test/e2e/client.e2e.test.ts
+++ b/nodejs/test/e2e/client.e2e.test.ts
@@ -1,5 +1,5 @@
import { ChildProcess } from "child_process";
-import { describe, expect, it, onTestFinished } from "vitest";
+import { describe, expect, it, onTestFinished, vi } from "vitest";
import { approveAll, CopilotClient, RuntimeConnection } from "../../src/index.js";
import { isInProcessTransport } from "./harness/sdkTestContext.js";
@@ -95,7 +95,12 @@ describe("Client", () => {
const cliProcess = (client as any).cliProcess as ChildProcess;
expect(cliProcess).toBeDefined();
cliProcess.kill("SIGKILL");
- await new Promise((resolve) => setTimeout(resolve, 100));
+ await vi.waitFor(
+ () => {
+ expect((client as unknown as { state: string }).state).toBe("disconnected");
+ },
+ { timeout: 10_000 }
+ );
const errors = await client.stop();
if (errors.length > 0) {
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index 1a73bb053c..17a839f0d5 100644
--- a/test/harness/package-lock.json
+++ b/test/harness/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
- "@github/copilot": "^1.0.79-9",
+ "@github/copilot": "^1.0.79",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
@@ -501,9 +501,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79-9.tgz",
- "integrity": "sha512-1QRRV3z1HA8sr3JUo4e2l+zFVbIGIOqnmTwzdJ+ilfr+mkmC7LYWkJxV3+j+zN0nq8JAgusSL/Schc43MPIqug==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.79.tgz",
+ "integrity": "sha512-uHBm2BYbKJgyfiKp1WokX7QUNHGvzEX0zaGeb3qM3CybP06rsJrX3JgQe95qwwma6vQz0ah9gV68ERW2JqaKRA==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
@@ -513,20 +513,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.79-9",
- "@github/copilot-darwin-x64": "1.0.79-9",
- "@github/copilot-linux-arm64": "1.0.79-9",
- "@github/copilot-linux-x64": "1.0.79-9",
- "@github/copilot-linuxmusl-arm64": "1.0.79-9",
- "@github/copilot-linuxmusl-x64": "1.0.79-9",
- "@github/copilot-win32-arm64": "1.0.79-9",
- "@github/copilot-win32-x64": "1.0.79-9"
+ "@github/copilot-darwin-arm64": "1.0.79",
+ "@github/copilot-darwin-x64": "1.0.79",
+ "@github/copilot-linux-arm64": "1.0.79",
+ "@github/copilot-linux-x64": "1.0.79",
+ "@github/copilot-linuxmusl-arm64": "1.0.79",
+ "@github/copilot-linuxmusl-x64": "1.0.79",
+ "@github/copilot-win32-arm64": "1.0.79",
+ "@github/copilot-win32-x64": "1.0.79"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79-9.tgz",
- "integrity": "sha512-DBTtv06Lpka1R+bkYfCWH38838b66bTLvsRsNjSuQV9AzgMPHjIn+Q2wAmU89rUyw5ej9iCIL5ppps+roi7qRw==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.79.tgz",
+ "integrity": "sha512-rsw7JoMvlcxXb0yx08oIeEc0x2hUEwKSfhX9ESKfdMVt0Ckrzm4OEvNUyzOpOnLJ9+l3h/aI+u1w5g2ZU2K7UA==",
"cpu": [
"arm64"
],
@@ -541,9 +541,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79-9.tgz",
- "integrity": "sha512-j+XOqtVWa0EZ8lBR+xIsPVI7ErpDepgr3WuSfUCkC9fOdvnVJ1rbyBY3gCM/urY4wJNdbHc4t1vN9MjtRNpTGA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.79.tgz",
+ "integrity": "sha512-D983e2lXYnq+KhjA8mTZXonY1+LGfJN9BM195J73shUvx49nRJmibDHWLvVtGeYc+43evGUOAQrOqOspAhhWPQ==",
"cpu": [
"x64"
],
@@ -558,9 +558,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79-9.tgz",
- "integrity": "sha512-eYsJlokogYeXo2tCwqoDW+rELbLs0ht7b3R1nrl9odO6U6ZabIm6BilSLSxjWCtE1ZpqDLmdJbOV0/6cQwjvlA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.79.tgz",
+ "integrity": "sha512-qqaNkvi92Wg+4OZk/kTWC2nUG72G0vV6eRAo5+PnKaPmjdX1GsI0a+lPxXPEbzX0zYLi/8yrUyANwyyNEsGgXA==",
"cpu": [
"arm64"
],
@@ -575,9 +575,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79-9.tgz",
- "integrity": "sha512-KknlE4hT3rw/Ne1aL+F1KEQrq40d4I8aGfxAEuahmn3NaM7CSBikDVIsAvkmTq7e2vHzaLytpclc8+gcEAIK6Q==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.79.tgz",
+ "integrity": "sha512-wzotZfvHkItutciLFMXZT2k9Qiii4Ta8tsVDCMQ7CP8hPxV91FyJ1yf3+FFSSfPvWrfYM6BOAiqIuX+LjgRuiw==",
"cpu": [
"x64"
],
@@ -592,9 +592,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79-9.tgz",
- "integrity": "sha512-Wrk+vpzg9ho/uC7ajNgIEjPShtB+pGlaJV+8rvYcHeQG6Gyx8YrPMI+OMdYou6RI9firqIaywT0UPuy9PUzoOg==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.79.tgz",
+ "integrity": "sha512-INtRSARl7DdNm2MXnn4GJuK+Y7QD24ANox02uH8htNQwRlNvdvg+YGS1V/mYgLDXFepeUjMjzTNC+i70+kh5uw==",
"cpu": [
"arm64"
],
@@ -609,9 +609,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79-9.tgz",
- "integrity": "sha512-ERULakTfCb4KYK4hGcMPRp5qm5K7KqKFHhGrAdn1VLrm8QsXDYzl2vUO4tIU/TxRW5VA9pmWh30JpCjQScSnDA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.79.tgz",
+ "integrity": "sha512-LxJAIfPP6Ok/9qpXGZuhnAft3W9JVcK9tbO3jWXcGDJT3v+2NtutyjmP/A7/cDXdTruXVQ4MybwAgacN8Gj/sg==",
"cpu": [
"x64"
],
@@ -626,9 +626,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79-9.tgz",
- "integrity": "sha512-XAe2calnhhiAVdIb2jUn4Bh961nu4zz3N5tcrb5CNjDSbjEE2LQf8CaNV4h/QhHjjpcmqFIfMQBMYxW1+9xixg==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.79.tgz",
+ "integrity": "sha512-5wg/ayCBTVy4g4FdO/9BJZRVARY0sgjAn9rBkw5BSJMv4u7Mvxg5Sftlift+V5UWxTyCSHAELZ5IHKvox4Yi8w==",
"cpu": [
"arm64"
],
@@ -643,9 +643,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.79-9",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79-9.tgz",
- "integrity": "sha512-/nK1IR5Vho2r6vuzq9xziVWwlgan41eL62Oo0feu7RaMvhS+f40l4jZCjuWLbeysh/we642qCyRjK8gkv730lA==",
+ "version": "1.0.79",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79.tgz",
+ "integrity": "sha512-FTpThWwwCDYnLdE0pfdo5zpAQLLVg36kmC2IKyVMuCYv9iPe7rE1mz7ng/UITN9M3TAMBrwHSvCV3pITvw4W8Q==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index 3b9d8e289c..7903a8f4ef 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -14,7 +14,7 @@
"node": "^20.19.0 || >=22.12.0"
},
"devDependencies": {
- "@github/copilot": "^1.0.79-9",
+ "@github/copilot": "^1.0.79",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
From e2cd7adbdc617c665d5fd67d08ebb6f69f280d29 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Tue, 11 Aug 2026 10:31:19 -0400
Subject: [PATCH 11/51] Consolidate SDK GitHub releases (#2305)
* Consolidate SDK GitHub releases
Create one shared GitHub Release for all SDK languages while retaining scoped Rust and Java source tags.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 01a9d0e3-0073-48f2-afae-de0398986669
* Gate releases on Maven publication
Expose Maven publication success from the reusable Java workflow so documentation deployment failures do not suppress the shared SDK release.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 01a9d0e3-0073-48f2-afae-de0398986669
* Clarify unified release guidance
Document the Node-only unstable channel and align changelog examples with the six-language release policy.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 01a9d0e3-0073-48f2-afae-de0398986669
---------
Copilot-Session: 01a9d0e3-0073-48f2-afae-de0398986669
---
.github/workflows/java-publish-maven.yml | 100 ++-----------------
.github/workflows/java.notes.template | 29 ------
.github/workflows/publish.yml | 32 +-----
.github/workflows/release-changelog.lock.yml | 4 +-
.github/workflows/release-changelog.md | 29 +++---
docs/developer-docs/secrets.md | 2 +-
rust/README.md | 2 +-
rust/RELEASING.md | 35 +++----
8 files changed, 44 insertions(+), 189 deletions(-)
delete mode 100644 .github/workflows/java.notes.template
diff --git a/.github/workflows/java-publish-maven.yml b/.github/workflows/java-publish-maven.yml
index e293d91271..f80b38f761 100644
--- a/.github/workflows/java-publish-maven.yml
+++ b/.github/workflows/java-publish-maven.yml
@@ -37,6 +37,10 @@ on:
type: boolean
required: false
default: false
+ outputs:
+ mavenPublished:
+ description: "Whether the Java package was published to Maven Central"
+ value: ${{ jobs.publish-maven.outputs.published }}
secrets:
JAVA_RELEASE_TOKEN:
required: true
@@ -80,39 +84,6 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.JAVA_RELEASE_TOKEN }}
- - name: Verify JAVA_RELEASE_GITHUB_TOKEN can trigger workflows
- run: |
- # JAVA_RELEASE_GITHUB_TOKEN is used for:
- # - gh workflow run release-changelog.lock.yml (requires actions:write)
- # Check the token's OAuth scopes for 'workflow' (classic PAT) or
- # attempt a workflow dispatch with a non-existent ref to verify write access
- # (fine-grained PAT — these don't expose scopes via X-OAuth-Scopes).
- SCOPES=$(gh api -i user 2>&1 | grep -i '^x-oauth-scopes:' | tr '[:upper:]' '[:lower:]' || true)
- if echo "$SCOPES" | grep -q 'workflow'; then
- echo "JAVA_RELEASE_GITHUB_TOKEN has 'workflow' scope (classic PAT)"
- elif [ -z "$SCOPES" ]; then
- # Fine-grained PAT: no X-OAuth-Scopes header returned.
- # Attempt a workflow dispatch against a non-existent ref. If the token
- # has actions:write, the API returns 422 (validation failed on ref).
- # If it lacks the permission, the API returns 403.
- HTTP_CODE=$(gh api -X POST \
- "repos/${{ github.repository }}/actions/workflows/release-changelog.lock.yml/dispatches" \
- -f ref="preflight-check-nonexistent-ref" \
- -f 'inputs[tag]=preflight-check' \
- --silent -i 2>&1 | head -1 | grep -oE '[0-9]{3}' || echo "000")
- if [ "$HTTP_CODE" = "403" ] || [ "$HTTP_CODE" = "000" ]; then
- echo "::error::JAVA_RELEASE_GITHUB_TOKEN lacks actions:write permission on ${{ github.repository }}. It cannot trigger the changelog generation workflow."
- exit 1
- fi
- # 422 = has write access but ref doesn't exist (expected), 204 would mean it dispatched (shouldn't happen with fake ref)
- echo "JAVA_RELEASE_GITHUB_TOKEN actions:write access OK (fine-grained PAT, dispatch returned HTTP ${HTTP_CODE})"
- else
- echo "::error::JAVA_RELEASE_GITHUB_TOKEN lacks 'workflow' scope. Found scopes: ${SCOPES}. It needs this scope to trigger changelog generation via gh workflow run."
- exit 1
- fi
- env:
- GITHUB_TOKEN: ${{ secrets.JAVA_RELEASE_GITHUB_TOKEN }}
-
publish-maven:
name: Publish Java SDK to Maven Central
needs: preflight
@@ -123,6 +94,7 @@ jobs:
working-directory: ./java
outputs:
version: ${{ steps.versions.outputs.release_version }}
+ published: ${{ steps.publish-maven.outcome == 'success' }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -227,6 +199,7 @@ jobs:
JAVA_GPG_PASSPHRASE: ${{ secrets.JAVA_GPG_PASSPHRASE }}
- name: Perform Release and Deploy to Maven Central
+ id: publish-maven
working-directory: ./java
run: |
mvn -B release:perform \
@@ -248,68 +221,9 @@ jobs:
# Also run Maven release:rollback to clean up any partial release state
mvn -B release:rollback || true
- github-release:
- name: Create GitHub Release
- needs: [preflight, publish-maven]
- if: github.ref == 'refs/heads/main'
- runs-on: ubuntu-latest
- defaults:
- run:
- shell: bash
- working-directory: ./java
- steps:
- - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- with:
- fetch-depth: 0
- - name: Create GitHub Release
- run: |
- VERSION="${{ needs.publish-maven.outputs.version }}"
- GROUP_ID="com.github"
- ARTIFACT_ID="copilot-sdk-java"
- CURRENT_TAG="java/v${VERSION}"
-
- if gh release view "${CURRENT_TAG}" >/dev/null 2>&1; then
- echo "Release ${CURRENT_TAG} already exists. Skipping creation."
- exit 0
- fi
-
- # Generate release notes from template
- export VERSION GROUP_ID ARTIFACT_ID
- RELEASE_NOTES=$(envsubst < $GITHUB_WORKSPACE/.github/workflows/java.notes.template)
-
- # Get the previous tag for generating notes
- # grep returns exit 1 when no lines match (first release), so
- # append "|| true" to prevent pipefail from aborting the script.
- PREV_TAG=$(git tag --list 'java/v*' --sort=-version:refname \
- | grep -Fxv "${CURRENT_TAG}" \
- | head -n 1 || true)
-
- echo "Current tag: ${CURRENT_TAG}"
- echo "Previous tag: ${PREV_TAG}"
-
- # Build the gh release command
- GH_ARGS=("${CURRENT_TAG}")
- GH_ARGS+=("--title" "GitHub Copilot SDK for Java ${VERSION}")
- GH_ARGS+=("--notes" "${RELEASE_NOTES}")
- GH_ARGS+=("--generate-notes")
-
- if [ -n "$PREV_TAG" ]; then
- GH_ARGS+=("--notes-start-tag" "$PREV_TAG")
- fi
-
- ${{ inputs.prerelease == true && 'GH_ARGS+=("--prerelease")' || '' }}
-
- gh release create "${GH_ARGS[@]}"
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - name: Trigger changelog generation
- run: gh workflow run release-changelog.lock.yml -f tag="java/v${{ needs.publish-maven.outputs.version }}"
- env:
- GITHUB_TOKEN: ${{ secrets.JAVA_RELEASE_GITHUB_TOKEN }}
-
deploy-site:
name: Deploy Documentation Site
- needs: [preflight, publish-maven, github-release]
+ needs: [preflight, publish-maven]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
diff --git a/.github/workflows/java.notes.template b/.github/workflows/java.notes.template
deleted file mode 100644
index e209a110b6..0000000000
--- a/.github/workflows/java.notes.template
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-# Installation
-
-⚠️ **Artifact versioning plan:** Releases of this implementation track releases of the reference implementation. For each release of the reference implementation, there may follow a corresponding release of this implementation with the same number as the reference implementation. Release identifiers of the reference implementation are in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding maven version for the release will be `Maj.Min.Micro-java.N`, where `Maj`, `Min` and `Micro` are the corresponding numbers for the reference implementation release, and `N` is a monotonically increasing sequence number starting with 0 for each release. See the corresponding architectural decision record for more information in the `docs/adr` directory of the source code.
-
-📦 [View on Maven Central](https://central.sonatype.com/artifact/${GROUP_ID}/${ARTIFACT_ID}/${VERSION})
-
-📖 [Documentation](https://github.github.io/copilot-sdk-java/${VERSION}/) · [Javadoc](https://github.github.io/copilot-sdk-java/${VERSION}/apidocs/index.html)
-
-
-## Maven
-```xml
-
- ${GROUP_ID}
- ${ARTIFACT_ID}
- ${VERSION}
-
-```
-
-## Gradle (Kotlin DSL)
-```kotlin
-implementation("${GROUP_ID}:${ARTIFACT_ID}:${VERSION}")
-```
-
-## Gradle (Groovy DSL)
-```groovy
-implementation '${GROUP_ID}:${ARTIFACT_ID}:${VERSION}'
-```
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index b44fd582a2..98bf236900 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -379,7 +379,8 @@ jobs:
needs.publish-nodejs.result == 'success' &&
needs.publish-dotnet.result == 'success' &&
needs.publish-python.result == 'success' &&
- needs.publish-rust.result == 'success'
+ needs.publish-rust.result == 'success' &&
+ needs.publish-java.outputs.mavenPublished == 'true'
runs-on: ubuntu-latest
permissions:
actions: write
@@ -434,11 +435,9 @@ jobs:
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - name: Tag Rust SDK and create Rust GitHub Release
- # Rust gets its own version-scoped GitHub Release with notes
- # derived from PR titles since the previous Rust tag. The
- # cross-language `vX.Y.Z` release above still exists; this one
- # is the canonical reference for Rust users.
+ - name: Tag Rust SDK
+ # Keep a language-scoped source tag for traceability. Rust is
+ # included in the cross-language `vX.Y.Z` GitHub Release.
if: github.event.inputs.dist-tag == 'latest' || github.event.inputs.dist-tag == 'prerelease'
run: |
set -e
@@ -453,26 +452,5 @@ jobs:
else
echo "Tag $TAG_NAME already exists, skipping tag push"
fi
- # Find the previous Rust tag for note generation. Prefer rust/v*,
- # fall back to the historical rust-v* tags from the release-plz era.
- PREV_TAG=$(git tag --list 'rust/v*' --sort=-v:refname | grep -vFx "$TAG_NAME" | head -n1)
- if [ -z "$PREV_TAG" ]; then
- PREV_TAG=$(git tag --list 'rust-v*' --sort=-v:refname | head -n1)
- fi
- NOTES_FLAG=""
- if [ -n "$PREV_TAG" ]; then
- NOTES_FLAG="--notes-start-tag $PREV_TAG"
- echo "Generating notes from $PREV_TAG..$TAG_NAME"
- else
- echo "No previous Rust tag found; generating notes from full history"
- fi
- PRERELEASE_FLAG=""
- if [ "${{ github.event.inputs.dist-tag }}" = "prerelease" ]; then
- PRERELEASE_FLAG="--prerelease"
- fi
- gh release create "$TAG_NAME" \
- --title "$TAG_NAME" \
- --generate-notes $NOTES_FLAG $PRERELEASE_FLAG \
- --target ${{ github.sha }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/release-changelog.lock.yml b/.github/workflows/release-changelog.lock.yml
index 781f41b22b..23b19d9b82 100644
--- a/.github/workflows/release-changelog.lock.yml
+++ b/.github/workflows/release-changelog.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"9342b428009e6a3b47258c08b78735a89fc72714b73a44b72c4714e310d60006","body_hash":"89e26ed929f440bd6af57d1da92b06dbf1739b4a1d34b9923286919d00f272d1","compiler_version":"v0.83.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.73"}}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a4a0859e0103be270433c7fe1926a346c46271b4b530b2c08fa5d606d0ab75c4","body_hash":"490b25b529910b1b087df624fd59eaef52e142e84b9503ca1cf87631f4c36b53","compiler_version":"v0.83.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.73"}}
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"8bdba8075360648fe6802302a5b4e016361dc6ac","version":"v0.83.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.38","digest":"sha256:cb928eb62d9139a013c2d278dab19af232d35a2d83dca71a3d98eb431f786243","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.38@sha256:cb928eb62d9139a013c2d278dab19af232d35a2d83dca71a3d98eb431f786243"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.38","digest":"sha256:cd6145620d96acee46e1ede25180a13aa36002467e663db0caa453a8bc8eb60c","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.38@sha256:cd6145620d96acee46e1ede25180a13aa36002467e663db0caa453a8bc8eb60c"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.38","digest":"sha256:6c19094d95aad5f9f128ad5e583f0f2b894b158aa66c3b86dd9bcc90970a2917","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.38@sha256:6c19094d95aad5f9f128ad5e583f0f2b894b158aa66c3b86dd9bcc90970a2917"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.3","digest":"sha256:3c744710ea275cd5ee65db92a1099e0d980754bd9fafda9ce67704c67004dc83","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.3@sha256:3c744710ea275cd5ee65db92a1099e0d980754bd9fafda9ce67704c67004dc83"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.6.0","digest":"sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3","pinned_image":"ghcr.io/github/github-mcp-server:v1.6.0@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3"}]}
# This file was automatically generated by gh-aw (v0.83.1). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
#
@@ -62,7 +62,7 @@ on:
required: false
type: string
tag:
- description: Release tag to generate changelog for (e.g., v0.1.30, /v1.0.0)
+ description: Release tag to generate changelog for (e.g., v1.0.0)
required: true
type: string
diff --git a/.github/workflows/release-changelog.md b/.github/workflows/release-changelog.md
index 7a682c56dd..c846b0dd32 100644
--- a/.github/workflows/release-changelog.md
+++ b/.github/workflows/release-changelog.md
@@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
tag:
- description: "Release tag to generate changelog for (e.g., v0.1.30, /v1.0.0)"
+ description: "Release tag to generate changelog for (e.g., v1.0.0)"
required: true
type: string
permissions:
@@ -55,9 +55,8 @@ Use the GitHub API to fetch the release corresponding to `${{ github.event.input
2. The **new version** is the release tag: `${{ github.event.inputs.tag }}`
3. Fetch the release metadata to determine if this is a **stable** or **prerelease** release.
4. Determine the **previous version** to diff against:
- - **Scoped tags**: If the tag has a language prefix (e.g., `java/v1.0.0` or `rust/v0.2.0`), the previous tag must use the **same prefix**. List tags matching that prefix (e.g., `java/v*` or `rust/v*`) sorted by version and pick the one immediately before the current tag. Only compare within the same scope.
- - **For stable releases**: find the previous **stable** release (skip prereleases). Check `CHANGELOG.md` for the most recent version heading matching this scope (`## [vX.Y.Z](...)` for unscoped, `## [java/vX.Y.Z](...)` for Java, `## [rust/vX.Y.Z](...)` for Rust), or fall back to listing releases via the API. This means stable changelogs include ALL changes since the last stable release, even if some were already mentioned in prerelease notes.
- - **For prerelease releases**: find the most recent release of **any kind** (stable or prerelease) that precedes this one within the same tag scope. This way prerelease notes only cover what's new since the last release.
+ - **For stable releases**: find the previous **stable** release (skip prereleases). Check `CHANGELOG.md` for the most recent `## [vX.Y.Z](...)` heading, or fall back to listing releases via the API. This means stable changelogs include ALL changes since the last stable release, even if some were already mentioned in prerelease notes.
+ - **For prerelease releases**: find the most recent release of **any kind** (stable or prerelease) that precedes this one. This way prerelease notes only cover what's new since the last release.
5. If no previous release exists at all, use the first commit in the repo as the starting point.
6. After identifying the range, verify it by listing the commits in `PREVIOUS_TAG..NEW_TAG`. If the local result still looks suspiciously small or inconsistent, do **not** proceed based on local git alone — use the GitHub tools as the source of truth for the commits and PRs in the release.
@@ -68,8 +67,7 @@ Use the GitHub API to fetch the release corresponding to `${{ github.event.input
- PR number and title
- The PR author
- Which SDK(s) were affected (look for prefixes like `[C#]`, `[Python]`, `[Go]`, `[Node]`, `[Java]`, `[Rust]` in the title, or infer from changed files)
-3. **For scoped tags** (e.g., `java/v*`, `rust/v*`): only include changes that touch the corresponding language directory (`java/`, `rust/`). Ignore changes to other languages unless they directly affect the scoped SDK.
-4. Ignore:
+3. Ignore:
- Dependabot/bot PRs that only bump internal dependencies (like `Update @github/copilot to ...`) unless they bring user-facing changes
- Merge commits with no meaningful content
- Preview/prerelease-only changes that were already documented
@@ -81,6 +79,10 @@ Separate the changes into two groups:
1. **Highlighted features**: Any interesting new feature or significant improvement that deserves its own section with a description and code snippet(s). Read the PR diff and source code to understand the feature well enough to write about it.
2. **Other changes**: Bug fixes, minor improvements, and smaller features that can be summarized in a single bullet each.
+**Format for each highlighted feature** — use an `### Feature:` or `### Fix:` heading, a 1-2 sentence description explaining what it does and why it matters, and at least one short code snippet (max 3 lines). Cover all six SDKs—TypeScript, C#, Go, Python, Java, and Rust—in the combined release notes. Show code examples in the languages whose APIs best illustrate the change, and ensure every user-visible language-specific change appears either as a highlighted feature or under other changes.
+
+**Format for other changes** — use a single `### Other changes` section with a flat bulleted list. Each bullet has a lowercase prefix (`feature:`, `bugfix:`, `improvement:`) and a one-line description linking to the PR. **However, if there are no highlighted features above it, omit the `### Other changes` heading.**
+
Only include changes that are **user-visible in the published SDK packages**. Skip anything that only affects docs, CI, build tooling, GitHub workflows, test infrastructure, or other internal-only concerns.
Additionally, identify **new contributors** — anyone whose first merged PR to this repo falls within this release range. You can determine this by checking whether the author has any earlier merged PRs in the repository.
@@ -90,11 +92,7 @@ Additionally, identify **new contributors** — anyone whose first merged PR to
**Skip this step entirely for prerelease releases.**
1. Read the current `CHANGELOG.md` file.
-2. Add the new version entry **at the top** of the file, right after the title/header. Use the **full tag** as the version in the heading — e.g., `## [v0.2.3](...)` for unscoped tags, `## [java/v1.0.0](...)` for Java-scoped tags, `## [rust/v0.2.3](...)` for Rust-scoped tags.
-
-**Format for each highlighted feature** — use an `### Feature:` or `### Fix:` heading, a 1-2 sentence description explaining what it does and why it matters, and at least one short code snippet (max 3 lines). For unscoped releases, focus on **TypeScript** and **C#** as the primary languages; only show Go/Python when giving a list of one-liner equivalents across all languages, or when their usage pattern is meaningfully different. For **scoped releases** (e.g., `java/v*`), show code snippets in the scoped language only (e.g., Java for `java/v*`, Rust for `rust/v*`).
-
-**Format for other changes** — a single `### Other changes` section with a flat bulleted list. Each bullet has a lowercase prefix (`feature:`, `bugfix:`, `improvement:`) and a one-line description linking to the PR. **However, if there are no highlighted features above it, omit the `### Other changes` heading entirely** — just list the bullets directly under the version heading.
+2. Add the new version entry **at the top** of the file, right after the title/header. Use the full tag as the version in the heading, for example `## [v1.0.0](...)`.
3. Use the release's publish date (from the GitHub Release metadata), not today's date. For `workflow_dispatch` runs, fetch the release by tag to get the date.
4. If there are new contributors, add a `### New contributors` section at the end listing each with a link to their first PR:
@@ -118,11 +116,6 @@ Use the `create-pull-request` output to submit your changes. The PR should:
Use the `update-release` output to replace the auto-generated release notes with your nicely formatted changelog. **Do not include the version heading** (`## [vX.Y.Z](...) (date)`) in the release notes — the release already has a title showing the version. Start directly with the feature sections or other changes list.
-**IMPORTANT — Preserving the Installation section:**
-The release body may contain an Installation section delimited by `` and `` HTML comments. In the case of Java, this section includes Maven/Gradle dependency snippets and a "View on Maven Central" link. You **MUST** preserve this entire section (from the opening comment through the closing comment, inclusive) exactly as it appears in the existing release body. Place your generated changelog content **after** the Installation section.
-
-**URL reconstruction:** If the Maven Central URL in the Installation section appears corrupted or contains the word "redacted", reconstruct it. Extract the version from the release tag (e.g., `java/v1.0.0` → `1.0.0`), and rebuild the URL as: `https://central.sonatype.com/artifact/com.github/copilot-sdk-java/{VERSION}`. The `` HTML comment in the section contains the intended URL pattern.
-
## Example Output
Here is an example of what a changelog entry should look like, based on real commits from this repo. **Follow this style exactly.**
@@ -154,6 +147,8 @@ While `session.rpc.models.setModel()` already worked, there is now a convenience
- C#: `session.SetModel("gpt-4o")`
- Python: `session.set_model("gpt-4o")`
- Go: `session.SetModel("gpt-4o")`
+- Java: `session.setModel("gpt-4o").get()`
+- Rust: `session.set_model("gpt-4o", None).await?`
### Other changes
@@ -171,7 +166,7 @@ While `session.rpc.models.setModel()` already worked, there is now a convenience
**Key rules visible in the example:**
- Highlighted features get their own `### Feature:` heading, a short description, and code snippets
-- Code snippets are TypeScript and C# primarily; Go/Python only when listing one-liner equivalents or when meaningfully different
+- Code snippets use whichever of TypeScript, C#, Go, Python, Java, and Rust best illustrate the change; list all affected languages when showing equivalents
- The `### Other changes` section is a flat bulleted list with lowercase `bugfix:` / `feature:` / `improvement:` prefixes
- PR numbers are linked inline, not at the end with author attribution (keep it clean)
diff --git a/docs/developer-docs/secrets.md b/docs/developer-docs/secrets.md
index 15788bbe56..573f4f22e1 100644
--- a/docs/developer-docs/secrets.md
+++ b/docs/developer-docs/secrets.md
@@ -50,7 +50,7 @@ These secrets are used by the Java SDK Maven Central publishing workflow (`java-
* **`JAVA_RELEASE_TOKEN`**: GitHub token with **push** permission on the repository. Used by the release workflow for `actions/checkout`, pushing release commits and tags to `main`, and running `mvn release:prepare -DpushChanges=true`.
* Workflows: `java-publish-maven.yml`
-* **`JAVA_RELEASE_GITHUB_TOKEN`**: GitHub token with **workflow dispatch** (actions:write) permission on this repository and `github/copilot-sdk-java`. Used to trigger the `release-changelog.lock.yml` workflow and the documentation site deployment after a release is published.
+* **`JAVA_RELEASE_GITHUB_TOKEN`**: GitHub token with **workflow dispatch** (actions:write) permission on `github/copilot-sdk-java`. Used to trigger the documentation site deployment after a release is published.
* Workflows: `java-publish-maven.yml`
## Rust publishing secret
diff --git a/rust/README.md b/rust/README.md
index 3140900447..29fe673558 100644
--- a/rust/README.md
+++ b/rust/README.md
@@ -4,7 +4,7 @@ A Rust SDK for programmatic access to the GitHub Copilot CLI.
See [github/copilot-sdk](https://github.com/github/copilot-sdk) for the equivalent SDKs in TypeScript, Python, Go, .NET, and Java. The Rust SDK seeks parity with those SDKs; see [Differences From Other SDKs](#differences-from-other-sdks) below for the small set of intentional divergences.
-**Releases:** [github.com/github/copilot-sdk/releases?q=rust%2F](https://github.com/github/copilot-sdk/releases?q=rust%2F) — per-version release notes for the Rust crate.
+**Releases:** [github.com/github/copilot-sdk/releases](https://github.com/github/copilot-sdk/releases) — combined release notes for all SDK languages.
## Prerequisites
diff --git a/rust/RELEASING.md b/rust/RELEASING.md
index de0252de8b..06e362f54e 100644
--- a/rust/RELEASING.md
+++ b/rust/RELEASING.md
@@ -1,8 +1,7 @@
# Releasing `github-copilot-sdk`
-The Rust crate ships through the same unified `publish.yml` workflow
-as the Node, .NET, and Python SDKs. There is no Rust-specific release
-workflow.
+The Rust crate ships through the unified `publish.yml` workflow
+alongside the other SDKs. There is no Rust-specific release workflow.
## TL;DR
@@ -16,9 +15,11 @@ workflow.
prerelease version requirement to install it.
- `unstable` — skipped for Rust (Cargo doesn't have a clean
equivalent of npm's `unstable` dist-tag).
-4. The workflow publishes all four SDKs at the shared computed
- version, tags `rust/vX.Y.Z`, and creates a Rust-scoped GitHub
- Release with auto-generated notes since the previous Rust tag.
+4. For `latest` and `prerelease`, the workflow publishes all SDKs at
+ the shared computed version, tags `rust/vX.Y.Z` for source
+ traceability, and creates one combined `vX.Y.Z` GitHub Release.
+ The `unstable` channel publishes only the Node.js SDK and does not
+ create a GitHub Release.
## Version, tag, and release notes
@@ -26,14 +27,11 @@ workflow.
as a placeholder. CI overrides it at publish time with the version
computed by `publish.yml` (or an explicit `version` workflow input).
- **Tag:** `rust/vX.Y.Z` (matches the `go/vX.Y.Z` style used elsewhere
- in this repo). The historical `rust-v0.1.0` tag from the
- release-plz era stays valid as a starting point for auto-generated
- release notes.
-- **Release notes:** auto-generated by `gh release --generate-notes`
- from PR titles between the previous Rust tag and the new one.
- Write descriptive PR titles for any change that touches the Rust
- surface; that's the only place those changes will be visible to
- Rust users.
+ in this repo). The tag identifies the source used for that crate
+ version.
+- **Release notes:** generated for the combined `vX.Y.Z` GitHub
+ Release. Write descriptive PR titles for changes that touch the Rust
+ surface so they are represented accurately in the shared notes.
## Cargo prerelease semantics
@@ -59,8 +57,8 @@ cargo yank --version X.Y.Z github-copilot-sdk
Yanking does *not* delete the version — existing `Cargo.lock` files
keep working — but it stops new resolutions from picking it. Follow
-up with a patch release that fixes the bug, and add a note to the
-yanked version's GitHub Release explaining why.
+up with a patch release that fixes the bug, and update the combined
+GitHub Release notes to explain why.
Reverse with `cargo yank --undo --version X.Y.Z github-copilot-sdk`
if the yank was a mistake.
@@ -90,6 +88,5 @@ git push origin rust/vX.Y.Z
perl -i -pe 's/^version = ".*"$/version = "0.0.0-dev"/' Cargo.toml
```
-Manual publishes skip the auto-generated GitHub Release. Run
-`gh release create rust/vX.Y.Z --generate-notes` after pushing the
-tag.
+Manual publishes skip the combined GitHub Release. Create or update the
+matching `vX.Y.Z` release after pushing the tag.
From f75d222117d99acf50db95fab8bb2cbf1d5148d8 Mon Sep 17 00:00:00 2001
From: Matthew Rayermann
Date: Tue, 11 Aug 2026 09:31:27 -0700
Subject: [PATCH 12/51] [SDK/Factories] Make The Agent Factories Surface Match
The Wire Contract (#2309)
* [SDK/Factories] Make The Agent Factories Surface Match The Wire Contract
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* [SDK/Codegen] Map Both Opaque Schema Markers In The TypeScript Generator
A bare x-opaque-json node now renders as JsonValue and a bare x-opaque-in-process node as OpaqueInProcessValue, instead of both collapsing to an object index signature. Nodes that also carry a real constraint keep it, so declarations like ExternalToolResult and McpServerConfig retain their unions.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* [SDK/Factories] Drop The FactoryRunResult Override And The Factory Casts
The regenerated wire types now type the factory result and argument fields as JsonValue, so the hand-written FactoryRunResult override, the toPublicFactoryRunResult boundary helper, and four casts are all unnecessary. A compile-time assertion pins the result type so the override cannot creep back.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* [SDK/Factories] Refuse A Factory Run Started From Inside A Factory Body
A factory body could start a second top-level run through any session reference it could reach, escaping the limits the user approved. An AsyncLocalStorage guard now refuses factory.run and factory.resume on the body's call path, before the RPC is dispatched, so no durable run row is created. The guard is per-call-path, so an unrelated concurrent run started elsewhere in the extension still succeeds.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* [SDK/Factories] Correct The Factory Resume Error Code Union
The union exported two codes no runtime path raises and omitted five it does, so a caller could branch on a dead code and receive a raw RpcResponseError for a real one. It now names exactly the codes execute_resume raises before a resumed run starts. permission_denied is deliberately excluded: an SDK-initiated resume dispatches with RunOrigin::default(), so the approval branch never runs and the code is unreachable from this path.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* [SDK/Factories] Forward Every Declared Subagent Option From ctx.agent
The hand-written FactoryAgentOptions declared only label, schema and model, and the agent implementation rebuilt the request from those three, so agent, reasoningEffort and contextTier were dropped before the request was sent. The options are now declared once as a key tuple and copied from it, and two compile-time assertions pin that tuple to both the public and the wire interface, so a future wire option fails the build instead of being silently dropped. Undeclared keys are still filtered out, because the wire schema forbids them.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* [SDK/Factories] Stop A Latched Progress Flush Error From Downgrading A Run
A background progress flush that failed earlier latched its error, and close() rethrew it from the factory execute finally block, so a factory body that succeeded settled as an error. The latched error is now best effort and warns, matching the treatment the final send already had. A mid-body flush failure stays fatal, because a running body that cannot record progress must not continue.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* [SDK/Factories] Correct The Factories Guide And Published API Comments
The guide and four JSDoc comments described behavior that does not exist: a declined SDK-initiated run resolving as cancelled, a single-active-run limit, two error codes no runtime path raises, an unpaginated listRuns, and a three-option ctx.agent. They now match the shipped surface, including that the SDK forwards agent, reasoningEffort and contextTier while the current runtime does not yet honor them. File-content assertions guard both files, which nothing else covers.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* Add changelog entry for the Agent Factories wire-contract corrections
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* Drop the transient runtime-support caveat from the factories docs
The claim that the runtime does not yet honor agent, reasoningEffort and contextTier is a point-in-time fact about another repository. It rots as soon as the runtime lands support, so the SDK docs no longer carry it. Also wraps three over-length test assertions that the prettier check flagged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* Simplify factory docs so they do not encode transient facts
- Describe ctx.session by what it omits, and point at the extensions_manage guide
- Drop the hardcoded active-run limit, which will become a setting
- Drop the listRuns paging parenthetical
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* Stop the subagent-option E2E from waiting on a model response
The factory awaited its subagent to completion, so the test hung wherever no cached model response exists and timed out at 30s on CI. Only the runtime's acceptance of the option payload is under test, and a refused request rejects before a subagent starts. The factory now races the call against a short timer and returns as soon as the request is accepted.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* Describe ctx.session by how it behaves, not by what it lacks
The context session is a full CopilotSession, so factory.run and factory.resume are present and callable. Saying the APIs are absent contradicted the exported type. The guide and the published comment now say the session refuses those calls.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
* Drop the hand-written changelog entry
The changelog is generated at release time, so an entry added by hand in a feature PR does not fit the file's convention.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
---------
Copilot-Session: 5ece6b29-8b10-47aa-ab17-b64c47f5fdcd
---
nodejs/docs/factories.md | 8 +-
nodejs/src/factory.ts | 72 ++--
nodejs/src/generated/rpc.ts | 268 +++++---------
nodejs/src/generated/session-events.ts | 149 +++-----
nodejs/src/index.ts | 9 +-
nodejs/src/session.ts | 97 ++---
nodejs/src/types.ts | 3 +-
nodejs/test/e2e/factory.e2e.test.ts | 297 +++++++++++++--
.../test/e2e/fixtures/factory-extension.mjs | 154 +++++++-
nodejs/test/factory.test.ts | 347 +++++++++++++++++-
nodejs/test/session-event-types.test.ts | 19 +
nodejs/test/typescript-codegen.test.ts | 122 ++++++
scripts/codegen/typescript.ts | 83 ++++-
scripts/codegen/utils.ts | 28 ++
14 files changed, 1245 insertions(+), 411 deletions(-)
diff --git a/nodejs/docs/factories.md b/nodejs/docs/factories.md
index 0c1f0f09a0..a227679054 100644
--- a/nodejs/docs/factories.md
+++ b/nodejs/docs/factories.md
@@ -53,7 +53,7 @@ The `run()` context provides:
- `ctx.runId`: Stable ID reused across resumed attempts.
- `ctx.args`: Invocation arguments, forwarded verbatim. When the caller omits `args`, this is `{}` rather than `undefined`.
-- `ctx.agent(prompt, options?)`: Runs one factory-owned subagent. Options are exactly `label`, `schema`, and `model`. See [Subagent calls](#subagent-calls).
+- `ctx.agent(prompt, options?)`: Runs one factory-owned subagent. Options are exactly `label`, `schema`, `model`, `agent`, `reasoningEffort`, and `contextTier`. See [Subagent calls](#subagent-calls).
- `ctx.parallel(thunks)`: Runs thunks concurrently and awaits all of them (a barrier). A thunk that throws becomes `null` in the result array, so one failed item does not lose the rest. Cancellation and hard runtime failures (`ResponseError`, `ConnectionError`) are the exception — those propagate and reject the whole call, because they mean the run itself is in trouble rather than one item having failed. Handle them at run level; do not assume every failure arrives as a `null`. Rejects above 4096 items.
- `ctx.pipeline(items, ...stages)`: Flows each item through every stage without a barrier between stages, so one item can be in a later stage while another is still in an earlier one. Each stage is called as `(previous, item, index)`, where `previous` is the prior stage's result and `item` is the original input. A stage that throws drops that item to `null` and skips its remaining stages, with the same exception for cancellation and hard runtime failures. Rejects above 4096 items.
- `ctx.phase(title)`: Starts a named progress phase. This sets a single run-global value, so calling it from inside concurrent `parallel`/`pipeline` stages races. Call it at run-level transitions and distinguish concurrent work by `label` instead.
@@ -61,7 +61,7 @@ The `run()` context provides:
- `ctx.step(key, producer, options?)`: Journals the producer's JSON result under a stable key so a resume replays it without re-running the producer. A journaled (default) producer must return a JSON-serializable value; `undefined` or a non-JSON value is rejected. Pass `{ volatile: true }` to bypass the journal and run the producer every time.
The key is the *sole* identity: neither the producer body nor its inputs contribute to it. A resume replays the cached value for a matching key even if the producer has since changed, so version the key (`"scan-v2"`) whenever its inputs or meaning change. Journaled producers are best-effort at-least-once and may run again across crashes or concurrent same-key callers, so keep side effects idempotent.
-- `ctx.session`: The full session returned by `joinSession`.
+- `ctx.session`: The session returned by `joinSession`. It refuses calls that start or resume a factory run. Call `extensions_manage` with `operation: "guide"` to read more about the session APIs.
- `ctx.signal`: Cooperative cancellation signal for extension work and subprocesses.
- `ctx.factory(...)`: Always rejects because nested factories are not supported.
@@ -156,7 +156,7 @@ session.factory.resume(
): Promise;
```
-Both resolve with the run envelope (`FactoryRunResult`) for **every** outcome — `completed`, `error`, `halted`, and `cancelled` alike. Inspect `status` and read `result` only when the run completed; a limit breach carries a typed `failure`. A declined fresh run is not a pre-execution failure: the run row already exists by the time the prompt is answered, so it resolves with a terminal `cancelled` envelope carrying the run ID. Only failures that occur *before* a run exists reject: an unknown factory name or an already-active session. Pre-execution resume failures, including a declined reapproval, throw `FactoryResumeError`, whose `code` is one of `not_found`, `non_resumable`, `already_active`, `reapproval_declined`, or `no_approval_provider`.
+Both resolve with the run envelope (`FactoryRunResult`) for **every** outcome — `completed`, `error`, `halted`, and `cancelled` alike. Inspect `status` and read `result` only when the run completed; a limit breach carries a typed `failure`. SDK-initiated `run` and `resume` do not request permission, so they have no declined outcome. The model's `run_factory` tool requests permission before the durable row exists; declining it creates no run row. An SDK-initiated run is refused only when the session already has its maximum number of active top-level runs. Pre-execution resume failures throw `FactoryResumeError`, whose `code` is one of `not_found`, `non_resumable`, `already_active`, `factory_already_running`, `factory_limits_invalid`, `factory_session_disposed`, `factory_storage_unavailable`, or `factory_storage_corrupt`.
An agent that no longer has a prior run's ID in context can recover it with `factories_manage` and `operation: "runs"`, which lists the session's factory runs with their IDs and statuses. This matters for resume: a run that reached a limit keeps its journal, so resuming it replays completed work for free, while restarting it from scratch pays for that work twice.
@@ -210,7 +210,7 @@ const page = await session.factory.getRunProgress(runId, {
});
```
-- `listRuns()` returns summaries in durable creation order.
+- `listRuns()` returns the newest default page of this session's durable factory runs.
- `getRunDetail(runId)` returns phases, prompt-safe agent summaries, and the latest progress page.
- `getRunProgress(runId, options?)` pages progress forward, backward, by phase, or from the latest tail.
diff --git a/nodejs/src/factory.ts b/nodejs/src/factory.ts
index 53c0aeca82..8ad1c7acbc 100644
--- a/nodejs/src/factory.ts
+++ b/nodejs/src/factory.ts
@@ -6,38 +6,15 @@ import type {
FactoryGetRunProgressRequest,
FactoryProgressPage,
FactoryRunDetail,
- FactoryRunResult as WireFactoryRunResult,
+ FactoryRunResult,
FactoryRunStatus,
FactoryRunSummary,
} from "./generated/rpc.js";
+import type { ContextTier } from "./generated/session-events.js";
import type { CopilotSession } from "./session.js";
import type { FactoryLimits, FactoryMeta } from "./types.js";
-/**
- * The envelope describing a factory run: its identity, status, and — once it
- * has completed — its result. `getRun` returns this for an in-flight run too,
- * so `status` may be `pending` or `running` and the outcome fields absent.
- *
- * `result` is re-typed here rather than taken from the generated wire type. The
- * runtime returns any JSON value — including `null`, a string, a number, or an
- * array — but the schema models the field as an opaque node, which the
- * generator renders as an object. Narrowing the correction to this surface
- * keeps the `x-opaque-json` handling unchanged for every other consumer.
- *
- * This override is temporary. Once the schema distinguishes an opaque JSON
- * value from an opaque in-process value and that ships in a CLI release,
- * regenerating produces the right type directly, and this declaration, the
- * `toPublicFactoryRunResult` boundary helper, and the casts around it should
- * all be deleted. Tracked by github/copilot-agent-runtime#14122.
- *
- * @experimental Part of the experimental Agent Factories surface and may
- * change or be removed in future SDK or CLI releases.
- */
-export type FactoryRunResult = Omit & {
- /** Completed factory result. */
- result?: JsonValue;
-};
-
+export type { FactoryRunResult };
export type {
FactoryAgentSummary,
FactoryPhaseStatus,
@@ -115,8 +92,20 @@ export interface FactoryAgentOptions {
label?: string;
schema?: FactoryJsonSchema;
model?: string;
+ reasoningEffort?: string;
+ contextTier?: ContextTier;
+ agent?: string;
}
+export const FACTORY_AGENT_OPTION_KEYS = [
+ "label",
+ "schema",
+ "model",
+ "reasoningEffort",
+ "contextTier",
+ "agent",
+] as const;
+
/**
* Options for a durable factory step.
*
@@ -185,7 +174,10 @@ export interface FactoryContext {
factory(name: string, args?: JsonValue): Promise;
/** Caller-supplied input, forwarded verbatim. */
args: TArgs;
- /** The same full session instance returned by `joinSession`. */
+ /**
+ * The session instance returned by `joinSession`. It refuses calls that
+ * start or resume a factory run.
+ */
session: CopilotSession;
/** Cooperative cancellation signal for the current factory run. */
signal: AbortSignal;
@@ -275,8 +267,11 @@ export type FactoryResumeErrorCode =
| "not_found"
| "non_resumable"
| "already_active"
- | "reapproval_declined"
- | "no_approval_provider";
+ | "factory_already_running"
+ | "factory_limits_invalid"
+ | "factory_session_disposed"
+ | "factory_storage_unavailable"
+ | "factory_storage_corrupt";
/**
* Friendly factory API exposed on a session.
@@ -290,9 +285,12 @@ export interface SessionFactoryApi {
*
* The envelope is returned for every outcome, including `error`, `halted`,
* and `cancelled` — inspect `status` and read `result` only when the run
- * completed. A declined fresh run resolves with a terminal `cancelled`
- * envelope. Failures that occur before a run exists (such as an unknown
- * factory or an already-active session) still reject.
+ * completed. SDK-initiated runs do not request permission, so they have no
+ * declined outcome. The model's `run_factory` tool requests permission
+ * before a durable row exists; declining it creates no run row. Failures
+ * that occur before a run exists (such as an unknown factory or attempting
+ * to start a run while the session is at its active top-level run limit)
+ * still reject.
*/
run(name: string, options?: RunOptions): Promise;
run(
@@ -302,9 +300,9 @@ export interface SessionFactoryApi {
/**
* Resume a run from its persisted factory name, arguments, journal, and accounting.
*
- * Resolves with the run envelope like {@link SessionFactoryApi.run}. A
- * pre-execution failure, including declined reapproval, rejects with
- * {@link FactoryResumeError}.
+ * Resolves with the run envelope like {@link SessionFactoryApi.run}.
+ * SDK-initiated resumes do not request permission. A pre-execution failure
+ * with a documented resume code rejects with {@link FactoryResumeError}.
*/
resume(runId: string, options?: ResumeOptions): Promise;
/** Read the latest durable envelope for a factory run. */
@@ -324,7 +322,9 @@ export interface SessionFactoryApi {
* {@link SessionFactoryApi.cancel} to actually stop it.
*/
waitForRun(runId: string, options?: { signal?: AbortSignal }): Promise;
- /** List this session's durable factory runs in creation order. */
+ /**
+ * List the newest default page of this session's durable factory runs.
+ */
listRuns(): Promise;
/** Read durable phases, direct agents, and the latest progress tail for a run. */
getRunDetail(runId: string): Promise;
diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts
index 042a7d0bb7..cefc8ef4df 100644
--- a/nodejs/src/generated/rpc.ts
+++ b/nodejs/src/generated/rpc.ts
@@ -7,6 +7,16 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js";
import type { AbortReason, Attachment, ContextTier, EmbeddedBlobResourceContents, EmbeddedTextResourceContents, McpServerSource, McpServerStatus, PermissionPromptRequest, PermissionRule, ReasoningSummary, SessionEvent, SessionLimitsConfig, SessionMode, ShutdownType, SkillSource, UserToolSessionApproval, Verbosity } from "./session-events.js";
+/** A value that can be represented losslessly on the SDK JSON wire. */
+export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
+
+/**
+ * A value that lives only in this process and never crosses the JSON-RPC
+ * boundary, such as a callback or a host object handle.
+ * @internal
+ */
+export type OpaqueInProcessValue = unknown;
+
/**
* Initial authentication info for the session.
*
@@ -259,6 +269,22 @@ export type AuthInfoType =
| "token"
/** Authentication from a Copilot API token. */
| "copilot-api-token";
+/**
+ * JSON Schema for canvas open input
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "CanvasJsonSchema".
+ */
+/** @experimental */
+export type CanvasJsonSchema = JsonValue;
+/**
+ * Provider-supplied action result.
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "CanvasActionInvokeResult".
+ */
+/** @experimental */
+export type CanvasActionInvokeResult = JsonValue;
/**
* Coarse command category for grouping and behavior: runtime built-in, skill-backed command, or SDK/client-owned command
*
@@ -3605,7 +3631,7 @@ export interface AgentInfo {
* @experimental
*/
mcpServers?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Skill names preloaded into this agent's context. Omitted means none.
@@ -4009,16 +4035,6 @@ export interface CanvasAction {
description?: string;
inputSchema?: CanvasJsonSchema;
}
-/**
- * JSON Schema for canvas open input
- *
- * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
- * via the `definition` "CanvasJsonSchema".
- */
-/** @experimental */
-export interface CanvasJsonSchema {
- [k: string]: unknown | undefined;
-}
/**
* Canvas action invocation parameters.
*
@@ -4038,19 +4054,7 @@ export interface CanvasActionInvokeRequest {
/**
* Action input
*/
- input?: {
- [k: string]: unknown | undefined;
- };
-}
-/**
- * Provider-supplied action result.
- *
- * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
- * via the `definition` "CanvasActionInvokeResult".
- */
-/** @experimental */
-export interface CanvasActionInvokeResult {
- [k: string]: unknown | undefined;
+ input?: JsonValue;
}
/**
* Canvas close parameters.
@@ -4195,9 +4199,7 @@ export interface OpenCanvasInstance {
/**
* Input supplied when the instance was opened
*/
- input?: {
- [k: string]: unknown | undefined;
- };
+ input?: JsonValue;
}
/**
* Canvas open parameters.
@@ -4222,9 +4224,7 @@ export interface CanvasOpenRequest {
/**
* Canvas open input
*/
- input?: {
- [k: string]: unknown | undefined;
- };
+ input?: JsonValue;
}
/**
* Canvas close parameters sent to the provider.
@@ -4297,9 +4297,7 @@ export interface CanvasProviderInvokeActionRequest {
/**
* Action input
*/
- input?: {
- [k: string]: unknown | undefined;
- };
+ input?: JsonValue;
host?: CanvasHostContext;
session?: CanvasSessionContext;
}
@@ -4330,9 +4328,7 @@ export interface CanvasProviderOpenRequest {
/**
* Canvas open input
*/
- input?: {
- [k: string]: unknown | undefined;
- };
+ input?: JsonValue;
host?: CanvasHostContext;
session?: CanvasSessionContext;
}
@@ -4657,9 +4653,7 @@ export interface ConfigureSessionExtensionsParams {
*
* @internal
*/
- controller?: {
- [k: string]: unknown | undefined;
- };
+ controller?: OpaqueInProcessValue;
}
/**
* Metadata for a connected remote session.
@@ -4904,7 +4898,7 @@ export interface CurrentToolMetadata {
* JSON Schema for tool input
*/
input_schema?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Whether the tool is loaded on demand via tool search
@@ -5334,9 +5328,7 @@ export interface ExtensionContextPushInput {
/**
* Caller-supplied JSON payload (required, may be null but not undefined)
*/
- payload: {
- [k: string]: unknown | undefined;
- };
+ payload: JsonValue;
}
/**
* Opaque integrator-owned process launch profile for one extension entrypoint.
@@ -5460,7 +5452,7 @@ export interface ExternalToolTextResultForLlm {
* Optional tool-specific telemetry
*/
toolTelemetry?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Base64-encoded binary results returned to the model
@@ -5500,7 +5492,7 @@ export interface ExternalToolTextResultForLlmBinaryResultsForLlm {
* Optional metadata from the producing tool.
*/
metadata?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -5737,9 +5729,7 @@ export interface FactoryAgentOptions {
/**
* Optional JSON Schema for structured agent output.
*/
- schema?: {
- [k: string]: unknown | undefined;
- };
+ schema?: JsonValue;
/**
* Optional model identifier for the subagent.
*/
@@ -5787,9 +5777,7 @@ export interface FactoryAgentResult {
/**
* Agent result, omitted when the agent produced no result.
*/
- result?: {
- [k: string]: unknown | undefined;
- };
+ result?: JsonValue;
}
/**
* Prompt-safe durable identity and live status for a direct factory agent.
@@ -5877,9 +5865,7 @@ export interface FactoryExecuteRequest {
/**
* Factory input value.
*/
- args: {
- [k: string]: unknown | undefined;
- };
+ args: JsonValue;
}
/**
* Result returned by an extension factory closure.
@@ -5892,9 +5878,7 @@ export interface FactoryExecuteResult {
/**
* Factory result value.
*/
- result?: {
- [k: string]: unknown | undefined;
- };
+ result?: JsonValue;
}
/**
* Parameters for paging factory progress.
@@ -5974,9 +5958,7 @@ export interface FactoryJournalGetResult {
/**
* Cached JSON result. The hit field distinguishes a cached JSON null from a miss.
*/
- resultJson?: {
- [k: string]: unknown | undefined;
- };
+ resultJson?: JsonValue;
}
/**
* Parameters for storing a factory journal entry.
@@ -6001,9 +5983,7 @@ export interface FactoryJournalPutRequest {
/**
* JSON result to memoize.
*/
- resultJson: {
- [k: string]: unknown | undefined;
- };
+ resultJson: JsonValue;
}
/**
* Parameters for paging factory runs.
@@ -6283,9 +6263,7 @@ export interface FactoryRunResult {
/**
* Completed factory result.
*/
- result?: {
- [k: string]: unknown | undefined;
- };
+ result?: JsonValue;
/**
* Error message for an errored run.
*/
@@ -6298,9 +6276,7 @@ export interface FactoryRunResult {
/**
* Partial journal and progress snapshot for a halted, cancelled, or errored run.
*/
- snapshot?: {
- [k: string]: unknown | undefined;
- };
+ snapshot?: JsonValue;
}
/**
* Full factory run observability detail.
@@ -6348,9 +6324,7 @@ export interface FactoryRunRequest {
/**
* Factory input value.
*/
- args: {
- [k: string]: unknown | undefined;
- };
+ args: JsonValue;
options?: RunOptions;
}
/**
@@ -6925,7 +6899,7 @@ export interface HistoryTruncateResult {
export interface HookInvokeRequest {
sessionId: string;
hookType: HookType;
- input: unknown;
+ input: JsonValue;
}
/**
* Optional output returned by an SDK callback hook.
@@ -6936,7 +6910,7 @@ export interface HookInvokeRequest {
/** @experimental */
/** @internal */
export interface HookInvokeResponse {
- output?: unknown;
+ output?: JsonValue;
}
/**
* Installed plugin record from global state, with marketplace, version, install time, enabled state, cache path, and source.
@@ -7568,9 +7542,7 @@ export interface ManagedSettingsReadResult {
/**
* Validated, canonical managed-settings JSON. Omitted when no managed settings were discovered or when discovered settings failed validation.
*/
- settingsJson?: {
- [k: string]: unknown | undefined;
- };
+ settingsJson?: JsonValue;
/**
* Discovery or validation error text when managed settings could not be read safely.
*/
@@ -7741,7 +7713,7 @@ export interface McpAppsCallToolRequest {
* Tool arguments
*/
arguments?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* **Required.** Server whose ui:// view issued the request. Per SEP-1865 ('callable by the app from this server only'), the call is rejected when this differs from `serverName`, and rejected outright when missing.
@@ -7886,7 +7858,7 @@ export interface McpAppsListToolsResult {
* App-callable tools from the server
*/
tools: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
}[];
}
/**
@@ -7947,7 +7919,7 @@ export interface McpAppsResourceContent {
* Resource-level metadata (CSP, permissions, etc.)
*/
_meta?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -8220,9 +8192,7 @@ export interface McpConfigureGitHubRequest {
*
* @internal
*/
- authInfo: {
- [k: string]: unknown | undefined;
- };
+ authInfo: OpaqueInProcessValue;
}
/**
* Result of configuring GitHub MCP.
@@ -8308,9 +8278,7 @@ export interface McpExecuteSamplingParams {
/**
* The original MCP JSON-RPC request ID (string or number). Used by the runtime to correlate the inference with the originating MCP request for telemetry; this is distinct from `requestId` (which is the schema-level cancellation handle).
*/
- mcpRequestId: {
- [k: string]: unknown | undefined;
- };
+ mcpRequestId: JsonValue;
request: McpExecuteSamplingRequest;
}
/**
@@ -8683,25 +8651,19 @@ export interface McpRegisterExternalClientRequest {
*
* @internal
*/
- client: {
- [k: string]: unknown | undefined;
- };
+ client: OpaqueInProcessValue;
/**
* In-process MCP Transport instance. Marked internal: cannot be serialized across the JSON-RPC boundary.
*
* @internal
*/
- transport: {
- [k: string]: unknown | undefined;
- };
+ transport: OpaqueInProcessValue;
/**
* In-process server config (MCPServerConfig) paired with the in-process client/transport. Marked internal alongside its companions.
*
* @internal
*/
- config: {
- [k: string]: unknown | undefined;
- };
+ config: OpaqueInProcessValue;
}
/**
* Opaque MCP reload configuration.
@@ -8717,9 +8679,7 @@ export interface McpReloadWithConfigRequest {
*
* @internal
*/
- config: {
- [k: string]: unknown | undefined;
- };
+ config: OpaqueInProcessValue;
}
/**
* Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove).
@@ -8775,13 +8735,13 @@ export interface McpResource {
* Resource-level metadata
*/
_meta?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Server-provided non-standard descriptor fields preserved from the MCP response
*/
additionalProperties?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -8812,7 +8772,7 @@ export interface McpResourceIcon {
* Server-provided non-standard icon fields preserved from the MCP response
*/
additionalProperties?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -8839,7 +8799,7 @@ export interface McpResourceAnnotations {
* Server-provided non-standard annotation fields preserved from the MCP response
*/
additionalProperties?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -8870,7 +8830,7 @@ export interface McpResourceContent {
* Resource-level metadata (CSP, permissions, etc.)
*/
_meta?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -8978,13 +8938,13 @@ export interface McpResourceTemplate {
* Resource-template-level metadata
*/
_meta?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Server-provided non-standard descriptor fields preserved from the MCP response
*/
additionalProperties?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -9947,7 +9907,7 @@ export interface NameSetRequest {
/** @experimental */
export interface OptionsUpdateAdditionalContentExclusionPolicy {
rules: OptionsUpdateAdditionalContentExclusionPolicyRule[];
- last_updated_at: unknown;
+ last_updated_at: JsonValue;
scope: OptionsUpdateAdditionalContentExclusionPolicyScope;
}
/**
@@ -11025,7 +10985,7 @@ export interface PermissionRulesSet {
/** @experimental */
export interface PermissionsConfigureAdditionalContentExclusionPolicy {
rules: PermissionsConfigureAdditionalContentExclusionPolicyRule[];
- last_updated_at: unknown;
+ last_updated_at: JsonValue;
scope: PermissionsConfigureAdditionalContentExclusionPolicyScope;
}
/**
@@ -11836,7 +11796,7 @@ export interface ProviderAddResult {
/**
* Synthesized selectable model entries for the newly added BYOK models, each under its provider-qualified selection id (`provider/id`). Empty when only providers were added.
*/
- models: unknown[];
+ models: JsonValue[];
}
/**
* Custom model-provider configuration (BYOK).
@@ -12471,9 +12431,7 @@ export interface QueueConsumeSystemNotificationsRequest {
/**
* Opaque runtime-owned filter object.
*/
- filter: {
- [k: string]: unknown | undefined;
- };
+ filter: JsonValue;
}
/**
* Inputs for marking session.idle deferred in native state.
@@ -12882,9 +12840,7 @@ export interface RegisterExtensionToolsParams {
*
* @internal
*/
- loader: {
- [k: string]: unknown | undefined;
- };
+ loader: OpaqueInProcessValue;
options?: SessionsRegisterExtensionToolsOnSessionOptions;
}
/**
@@ -12900,9 +12856,7 @@ export interface SessionsRegisterExtensionToolsOnSessionOptions {
*
* @internal
*/
- enabled?: {
- [k: string]: unknown | undefined;
- };
+ enabled?: OpaqueInProcessValue;
}
/**
* Handle for releasing the extension tool registration.
@@ -12920,9 +12874,7 @@ export interface RegisterExtensionToolsResult {
*
* @internal
*/
- unsubscribe: {
- [k: string]: unknown | undefined;
- };
+ unsubscribe: OpaqueInProcessValue;
}
/**
* Opaque handle previously returned by `registerInterest` to release.
@@ -13043,9 +12995,7 @@ export interface RemoteControlStatusActive {
*
* @internal
*/
- promptManager?: {
- [k: string]: unknown | undefined;
- };
+ promptManager?: OpaqueInProcessValue;
/**
* True while a read-only/session-sync export is deferred, awaiting the first `user.message` before its MC session exists. Marked internal: this field is excluded from the public SDK surface and is populated only on the CLI in-process path.
*
@@ -13867,15 +13817,11 @@ export interface SendSystemNotificationRequest {
/**
* Optional structured notification kind.
*/
- kind?: {
- [k: string]: unknown | undefined;
- };
+ kind?: JsonValue;
/**
* Internal delivery options, including passive policy.
*/
- options?: {
- [k: string]: unknown | undefined;
- };
+ options?: JsonValue;
}
/**
* Agents discovered across user, project, plugin, and remote sources.
@@ -14363,7 +14309,7 @@ export interface SessionFsSqliteQueryRequest {
* Optional named bind parameters
*/
params?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -14378,7 +14324,7 @@ export interface SessionFsSqliteQueryResult {
* For SELECT: array of row objects. For others: empty array.
*/
rows: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
}[];
/**
* Column names from the result set
@@ -14436,7 +14382,7 @@ export interface SessionFsSqliteTransactionStatement {
* Optional named bind parameters.
*/
params?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -14839,7 +14785,7 @@ export interface SessionModelList {
/**
* Available models, ordered with the most preferred default first. Includes both Copilot (CAPI) models and any registry BYOK models; a BYOK model appears under its provider-qualified selection id (`provider/id`).
*/
- list: unknown[];
+ list: JsonValue[];
/**
* Cost categories for the full CAPI catalog, including picker-disabled models that Auto may select. Metadata only; entries absent from `list` are not manually selectable.
*/
@@ -14848,7 +14794,7 @@ export interface SessionModelList {
* Per-quota snapshots returned alongside the model list, keyed by quota type.
*/
quotaSnapshots?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -14909,9 +14855,7 @@ export interface SessionOpenOptions {
*
* @internal
*/
- expAssignments?: {
- [k: string]: unknown | undefined;
- };
+ expAssignments?: JsonValue;
/**
* Opt-in: self-fetch and enforce enterprise managed settings at session bootstrap.
*/
@@ -15166,7 +15110,7 @@ export interface ShellInitScript {
/** @experimental */
export interface SessionOpenOptionsAdditionalContentExclusionPolicy {
rules: SessionOpenOptionsAdditionalContentExclusionPolicyRule[];
- last_updated_at: unknown;
+ last_updated_at: JsonValue;
scope: SessionOpenOptionsAdditionalContentExclusionPolicyScope;
}
/**
@@ -15315,9 +15259,7 @@ export interface SessionsOpenCloud {
*
* @internal
*/
- onTaskCreated?: {
- [k: string]: unknown | undefined;
- };
+ onTaskCreated?: OpaqueInProcessValue;
}
/**
* Parameters for fetching a remote session and handing it off to a new local session.
@@ -15339,17 +15281,13 @@ export interface SessionsOpenHandoff {
*
* @internal
*/
- onProgress?: {
- [k: string]: unknown | undefined;
- };
+ onProgress?: OpaqueInProcessValue;
/**
* In-process confirmation callback `(request) => boolean | Promise` invoked when the handoff needs the caller to confirm a non-fatal blocker (e.g. a repository mismatch between the current working directory and the remote session). Returning `true` proceeds with the handoff; returning `false` (or omitting the callback) aborts it. Marked internal because a function reference cannot cross the JSON-RPC boundary, for the same reasons as `onProgress`.
*
* @internal
*/
- onConfirm?: {
- [k: string]: unknown | undefined;
- };
+ onConfirm?: OpaqueInProcessValue;
}
/**
* Result of opening a session.
@@ -15371,9 +15309,7 @@ export interface SessionOpenResult {
*
* @internal
*/
- sessionApi?: {
- [k: string]: unknown | undefined;
- };
+ sessionApi?: OpaqueInProcessValue;
/**
* Startup prompts queued by user-level hook configs at session creation. Only populated when status is `created`; resumed sessions return an empty array.
*/
@@ -17316,7 +17252,7 @@ export interface Tool {
* JSON Schema for the tool's input parameters
*/
parameters?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Optional instructions for how to use this tool effectively
@@ -17749,17 +17685,13 @@ export interface UIEphemeralQueryRequest {
*
* @internal
*/
- onChunk?: {
- [k: string]: unknown | undefined;
- };
+ onChunk?: OpaqueInProcessValue;
/**
* In-process `AbortSignal` forwarded to the model client to cancel an in-flight request. Marked internal: excluded from the public SDK surface. Replaced by an explicit cancellation token + cancel RPC in the SDK migration.
*
* @internal
*/
- abortSignal?: {
- [k: string]: unknown | undefined;
- };
+ abortSignal?: OpaqueInProcessValue;
}
/**
* Transient answer generated from current conversation context.
@@ -18210,15 +18142,11 @@ export interface UserSettingMetadata {
/**
* The effective value: the user's value if set, otherwise the default.
*/
- value: {
- [k: string]: unknown | undefined;
- };
+ value: JsonValue;
/**
* The centrally-known default for this setting (null when no default is registered).
*/
- default: {
- [k: string]: unknown | undefined;
- };
+ default: JsonValue;
/**
* True when the user has not set an explicit value for this setting (i.e. it is left at its default). Reflects whether the user has overridden the key, not whether the effective value happens to equal the default — a key explicitly set to a value identical to the default still reports false.
*/
@@ -18250,9 +18178,7 @@ export interface UserSettingsSetRequest {
/**
* Partial user settings to write, as a free-form object keyed by setting name
*/
- settings: {
- [k: string]: unknown | undefined;
- };
+ settings: JsonValue;
}
/**
* Outcome of writing user settings.
@@ -18481,9 +18407,7 @@ export interface WorkspacesEnsureRequest {
/**
* Opaque workspace context supplied by the session host.
*/
- context?: {
- [k: string]: unknown | undefined;
- };
+ context?: JsonValue;
}
/**
* Current workspace metadata for the session, including its absolute filesystem path when available.
@@ -18674,9 +18598,7 @@ export interface WorkspacesUpdateMetadataRequest {
/**
* Opaque workspace context supplied by the session host.
*/
- context?: {
- [k: string]: unknown | undefined;
- };
+ context?: JsonValue;
/**
* Optional workspace display name override.
*/
@@ -18736,7 +18658,7 @@ export interface SessionAgentListRequest {
*/
/** @experimental */
export interface SessionMcpAppsCallToolResult {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
}
/** @experimental */
diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts
index db24fc23e9..4bdfa19946 100644
--- a/nodejs/src/generated/session-events.ts
+++ b/nodejs/src/generated/session-events.ts
@@ -3,6 +3,9 @@
* Generated from: session-events.schema.json
*/
+/** A value that can be represented losslessly on the SDK JSON wire. */
+export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
+
/**
* Union of all session event variants emitted by the Copilot CLI runtime.
*/
@@ -669,6 +672,10 @@ export type ElicitationCompletedAction =
| "decline"
/** The user dismissed the request. */
| "cancel";
+/**
+ * Opaque JSON value submitted for one field in accepted `elicitation.completed` form content.
+ */
+export type ElicitationCompletedContent = JsonValue | undefined;
/**
* Reason the runtime is requesting host-provided MCP OAuth credentials
*/
@@ -709,6 +716,10 @@ export type McpHeadersRefreshCompletedOutcome =
| "none"
/** No response arrived within the bounded window. */
| "timeout";
+/**
+ * Source-defined JSON payload for the custom notification
+ */
+export type CustomNotificationPayload = JsonValue;
/**
* The user's auto-mode-switch choice
*/
@@ -3269,9 +3280,7 @@ export interface AttachmentExtensionContext {
/**
* Caller-supplied JSON payload
*/
- payload?: {
- [k: string]: unknown | undefined;
- };
+ payload?: JsonValue;
/**
* Human-readable composer pill label
*/
@@ -3810,9 +3819,7 @@ export interface CitationReference {
/**
* Provider-native citation correlation data (e.g. Anthropic search_result_index / document_index), passed through opaquely for debugging and forward compatibility.
*/
- providerMetadata?: {
- [k: string]: unknown | undefined;
- };
+ providerMetadata?: JsonValue;
/**
* Identifier of the CitationSource this reference points to (CitationSource.id).
*/
@@ -3881,9 +3888,9 @@ export interface AssistantMessageServerTools {
functionCallNamespaces?: {
[k: string]: string | undefined;
};
- items?: unknown[];
+ items?: JsonValue[];
provider: string;
- rawContentBlocks?: unknown[];
+ rawContentBlocks?: JsonValue[];
}
/**
* A tool invocation request from the assistant
@@ -3892,9 +3899,7 @@ export interface AssistantMessageToolRequest {
/**
* Arguments to pass to the tool, format depends on the tool
*/
- arguments?: {
- [k: string]: unknown | undefined;
- };
+ arguments?: JsonValue;
/**
* Resolved intention summary describing what this specific call does
*/
@@ -4573,9 +4578,7 @@ export interface ToolUserRequestedData {
/**
* Arguments for the tool invocation
*/
- arguments?: {
- [k: string]: unknown | undefined;
- };
+ arguments?: JsonValue;
/**
* Unique identifier for this tool call
*/
@@ -4622,9 +4625,7 @@ export interface ToolExecutionStartData {
/**
* Arguments passed to the tool
*/
- arguments?: {
- [k: string]: unknown | undefined;
- };
+ arguments?: JsonValue;
/**
* When true, the tool output should be displayed expanded (verbatim) in the CLI timeline
*/
@@ -4848,9 +4849,7 @@ export interface ToolExecutionCompleteData {
*
* @experimental
*/
- mcpMeta?: {
- [k: string]: unknown | undefined;
- };
+ mcpMeta?: JsonValue;
/**
* Model identifier that generated this tool call
*/
@@ -4879,7 +4878,7 @@ export interface ToolExecutionCompleteData {
* Tool-specific telemetry data (e.g., CodeQL check counts, grep match counts)
*/
toolTelemetry?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Identifier for the agent loop turn this tool was invoked in, matching the corresponding assistant.turn_start event
@@ -4932,15 +4931,11 @@ export interface ToolExecutionCompleteResult {
*
* @experimental
*/
- mcpMeta?: {
- [k: string]: unknown | undefined;
- };
+ mcpMeta?: JsonValue;
/**
* Structured content (arbitrary JSON) returned verbatim by the MCP tool
*/
- structuredContent?: {
- [k: string]: unknown | undefined;
- };
+ structuredContent?: JsonValue;
uiResource?: ToolExecutionCompleteUIResource;
}
/**
@@ -4959,7 +4954,7 @@ export interface PersistedBinaryImage {
* Optional metadata from the producing tool.
*/
metadata?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* MIME type of the binary data
@@ -4984,7 +4979,7 @@ export interface OmittedBinaryResult {
* Optional metadata from the producing tool.
*/
metadata?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* MIME type of the omitted binary data
@@ -5014,7 +5009,7 @@ export interface BinaryAssetReference {
* Optional metadata from the producing tool.
*/
metadata?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* MIME type of the referenced binary data
@@ -5779,9 +5774,7 @@ export interface HookStartData {
/**
* Input data passed to the hook
*/
- input?: {
- [k: string]: unknown | undefined;
- };
+ input?: JsonValue;
}
/**
* Session event "hook.end". Hook invocation completion details including output, success status, and error information
@@ -5829,9 +5822,7 @@ export interface HookEndData {
/**
* Output data produced by the hook
*/
- output?: {
- [k: string]: unknown | undefined;
- };
+ output?: JsonValue;
/**
* Whether the hook completed successfully
*/
@@ -5952,7 +5943,7 @@ export interface BinaryAssetData {
* Optional metadata from the producing tool.
*/
metadata?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* MIME type of the binary asset
@@ -6021,7 +6012,7 @@ export interface SystemMessageMetadata {
* Template variables used when constructing the prompt
*/
variables?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
}
/**
@@ -6226,9 +6217,7 @@ export interface SystemNotificationFactoryCompleted {
/**
* Machine-readable terminal failure details, when present.
*/
- failure?: {
- [k: string]: unknown | undefined;
- };
+ failure?: JsonValue;
/**
* Bounded prompt-safe preview of the completed result.
*/
@@ -6254,9 +6243,7 @@ export interface SystemNotificationUnclassified {
/**
* Opaque metadata supplied by the external host, when present.
*/
- metadata?: {
- [k: string]: unknown | undefined;
- };
+ metadata?: JsonValue;
/**
* Type discriminator. Always "unclassified".
*/
@@ -6309,9 +6296,7 @@ export interface PermissionRequestedData {
/**
* Neutral risk metadata supplied by the tool host. Consumers may display this value but must not use it to bypass the permission decision.
*/
- riskAssessment?: {
- [k: string]: unknown | undefined;
- };
+ riskAssessment?: JsonValue;
}
/**
* Shell command permission request
@@ -6494,9 +6479,7 @@ export interface PermissionRequestMcp {
/**
* Arguments to pass to the MCP tool
*/
- args?: {
- [k: string]: unknown | undefined;
- };
+ args?: JsonValue;
/**
* Permission kind discriminator
*/
@@ -6597,9 +6580,7 @@ export interface PermissionRequestCustomTool {
/**
* Arguments to pass to the custom tool
*/
- args?: {
- [k: string]: unknown | undefined;
- };
+ args?: JsonValue;
/**
* Permission kind discriminator
*/
@@ -6632,9 +6613,7 @@ export interface PermissionRequestHook {
/**
* Arguments of the tool call being gated
*/
- toolArgs?: {
- [k: string]: unknown | undefined;
- };
+ toolArgs?: JsonValue;
/**
* Tool call ID that triggered this permission request
*/
@@ -6893,9 +6872,7 @@ export interface PermissionPromptRequestMcp {
/**
* Arguments to pass to the MCP tool
*/
- args?: {
- [k: string]: unknown | undefined;
- };
+ args?: JsonValue;
/**
* Auto-approval judge information for this request; present only when auto mode is enabled.
*
@@ -7010,9 +6987,7 @@ export interface PermissionPromptRequestCustomTool {
/**
* Arguments to pass to the custom tool
*/
- args?: {
- [k: string]: unknown | undefined;
- };
+ args?: JsonValue;
/**
* Auto-approval judge information for this request; present only when auto mode is enabled.
*
@@ -7081,9 +7056,7 @@ export interface PermissionPromptRequestHook {
/**
* Arguments of the tool call being gated
*/
- toolArgs?: {
- [k: string]: unknown | undefined;
- };
+ toolArgs?: JsonValue;
/**
* Tool call ID that triggered this permission request
*/
@@ -7663,7 +7636,7 @@ export interface ElicitationRequestedSchema {
* Form field definitions, keyed by field name
*/
properties: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* List of required field names
@@ -7720,12 +7693,6 @@ export interface ElicitationCompletedData {
*/
requestId: string;
}
-/**
- * Opaque JSON value submitted for one field in accepted `elicitation.completed` form content.
- */
-export interface ElicitationCompletedContent {
- [k: string]: unknown | undefined;
-}
/**
* Session event "sampling.requested". Sampling request from an MCP server; contains the server name and a requestId for correlation
*/
@@ -7763,9 +7730,7 @@ export interface SamplingRequestedData {
/**
* The JSON-RPC request ID from the MCP protocol
*/
- mcpRequestId: {
- [k: string]: unknown | undefined;
- };
+ mcpRequestId: JsonValue;
/**
* Unique identifier for this sampling request; used to respond via session.respondToSampling()
*/
@@ -8114,12 +8079,6 @@ export interface CustomNotificationData {
*/
version?: number;
}
-/**
- * Source-defined JSON payload for the custom notification
- */
-export interface CustomNotificationPayload {
- [k: string]: unknown | undefined;
-}
/**
* Optional source-defined string identifiers describing the payload subject
*/
@@ -8163,9 +8122,7 @@ export interface ExternalToolRequestedData {
/**
* Arguments to pass to the external tool
*/
- arguments?: {
- [k: string]: unknown | undefined;
- };
+ arguments?: JsonValue;
/**
* Unique identifier for this request; used to respond via session.respondToExternalTool()
*/
@@ -8718,9 +8675,7 @@ export interface ManagedSettingsResolvedData {
/**
* The effective (resolved) managed settings values, so clients can render exactly what is enforced. Absent when no managed policy is in force.
*/
- settings?: {
- [k: string]: unknown | undefined;
- };
+ settings?: JsonValue;
source: ManagedSettingsResolvedSource;
}
/**
@@ -9570,9 +9525,7 @@ export interface CanvasOpenedData {
/**
* Input supplied when the instance was opened
*/
- input?: {
- [k: string]: unknown | undefined;
- };
+ input?: JsonValue;
/**
* Stable caller-supplied canvas instance identifier
*/
@@ -9667,9 +9620,7 @@ export interface CanvasRegistryChangedCanvas {
/**
* JSON Schema for canvas open input
*/
- inputSchema?: {
- [k: string]: unknown | undefined;
- };
+ inputSchema?: JsonValue;
}
/**
* A single action within a canvas declaration, with its name, optional description, and optional input schema.
@@ -9683,9 +9634,7 @@ export interface CanvasRegistryChangedCanvasAction {
/**
* JSON Schema for action input
*/
- inputSchema?: {
- [k: string]: unknown | undefined;
- };
+ inputSchema?: JsonValue;
/**
* Action name
*/
@@ -9836,9 +9785,7 @@ export interface CanvasRecordedData {
/**
* Input supplied when the instance was opened
*/
- input?: {
- [k: string]: unknown | undefined;
- };
+ input?: JsonValue;
/**
* Stable caller-supplied canvas instance identifier
*/
@@ -9974,7 +9921,7 @@ export interface McpAppToolCallCompleteData {
* Arguments passed to the tool by the app view, if any
*/
arguments?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Wall-clock duration of the underlying tools/call in milliseconds
@@ -9985,7 +9932,7 @@ export interface McpAppToolCallCompleteData {
* Standard MCP CallToolResult returned by the server. Present whether or not the call set isError.
*/
result?: {
- [k: string]: unknown | undefined;
+ [k: string]: JsonValue | undefined;
};
/**
* Name of the MCP server hosting the tool
diff --git a/nodejs/src/index.ts b/nodejs/src/index.ts
index 5ab53471a6..622fd38b5a 100644
--- a/nodejs/src/index.ts
+++ b/nodejs/src/index.ts
@@ -41,14 +41,15 @@ export {
// consumers can import them directly from "@github/copilot-sdk" instead of
// reaching into the package's internal dist layout. See issue #1156.
//
-// Five names from this file are also explicitly exported elsewhere in this
+// Six names from this file are also explicitly exported elsewhere in this
// module — `SessionEvent` (re-exported below from `./types.js`),
// `PermissionRequest` (re-exported below from `./types.js`),
// `PermissionRequestedData`/`PermissionRequestedEvent` (also re-exported below
-// from `./types.js`), and `AssistantMessageEvent` (re-exported above from
-// `./session.js`). Per the ECMAScript module spec, the explicit named re-exports
+// from `./types.js`), `AssistantMessageEvent` (re-exported above from
+// `./session.js`), and `JsonValue` (re-exported below from `./factory.js`).
+// Per the ECMAScript module spec, the explicit named re-exports
// shadow the names arriving via `export type *`, so the hand-authored public API
-// surface for those five identifiers is preserved unchanged.
+// surface for those six identifiers is preserved unchanged.
export type * from "./generated/session-events.js";
export type {
CommandContext,
diff --git a/nodejs/src/session.ts b/nodejs/src/session.ts
index 5cc49fb758..42e30d6f34 100644
--- a/nodejs/src/session.ts
+++ b/nodejs/src/session.ts
@@ -7,6 +7,7 @@
* @module session
*/
+import { AsyncLocalStorage } from "node:async_hooks";
import type { MessageConnection } from "vscode-jsonrpc/node.js";
import { ConnectionError, ErrorCodes, ResponseError } from "vscode-jsonrpc/node.js";
import { createSessionRpc } from "./generated/rpc.js";
@@ -16,9 +17,6 @@ import type {
CurrentToolMetadata,
McpOauthPendingRequestResponse,
FactoryLogLine,
- FactoryRunRequest,
- FactoryExecuteResult,
- FactoryJournalPutRequest,
FactoryRunResult as WireFactoryRunResult,
} from "./generated/rpc.js";
import { type Canvas, CanvasError } from "./canvas.js";
@@ -66,11 +64,13 @@ import type {
UserInputResponse,
} from "./types.js";
import {
+ FACTORY_AGENT_OPTION_KEYS,
getFactoryDefinition,
FactoryResumeError,
isFactoryRunTerminal,
type FactoryResumeErrorCode,
type FactoryRunResult,
+ type FactoryAgentOptions,
type RunOptions,
type SessionFactoryApi,
type FactoryContext,
@@ -84,11 +84,35 @@ function isFactoryResumeErrorCode(value: unknown): value is FactoryResumeErrorCo
value === "not_found" ||
value === "non_resumable" ||
value === "already_active" ||
- value === "reapproval_declined" ||
- value === "no_approval_provider"
+ value === "factory_already_running" ||
+ value === "factory_limits_invalid" ||
+ value === "factory_session_disposed" ||
+ value === "factory_storage_unavailable" ||
+ value === "factory_storage_corrupt"
);
}
+function copyDefinedFactoryAgentOption(
+ source: FactoryAgentOptions,
+ target: FactoryAgentOptions,
+ key: TKey
+): void {
+ const value = source[key];
+ if (value !== undefined) {
+ target[key] = value;
+ }
+}
+
+const factoryExecutionStore = new AsyncLocalStorage<{ active: boolean }>();
+
+function throwIfFactoryExecutionIsActive(): void {
+ if (factoryExecutionStore.getStore()?.active) {
+ throw new Error(
+ "factory.run and factory.resume are not allowed while a factory body is running on this call path."
+ );
+ }
+}
+
/**
* Convert a raw hook input received over the wire into its public-facing shape.
* This deserializes the numeric Unix-ms `timestamp` field on BaseHookInput
@@ -255,7 +279,10 @@ class FactoryProgressBuffer {
const lines = this.pending.splice(0);
await this.flushTail;
if (this.flushFailed) {
- throw this.flushError;
+ console.warn(
+ "Ignoring a background factory progress flush failure after the factory body settled",
+ this.flushError
+ );
}
if (lines.length > 0) {
try {
@@ -288,24 +315,6 @@ class FactoryProgressBuffer {
}
}
-/**
- * Reconcile the generated envelope with the public one.
- *
- * The two are identical at runtime. They differ only in how `result` is typed:
- * the runtime returns any JSON value, but the schema models the field as an
- * opaque node, which the generator renders as an object. {@link FactoryRunResult}
- * corrects that for the factory surface without changing `x-opaque-json`
- * handling for any other consumer, so the boundary needs a cast rather than a
- * conversion.
- *
- * Delete this along with the {@link FactoryRunResult} override once the schema
- * distinguishes opaque JSON values from opaque in-process values —
- * github/copilot-agent-runtime#14122.
- */
-function toPublicFactoryRunResult(envelope: WireFactoryRunResult): FactoryRunResult {
- return envelope as FactoryRunResult;
-}
-
async function awaitFactoryOperation(
operation: () => Promise,
signal: AbortSignal
@@ -442,6 +451,7 @@ export class CopilotSession {
nameOrHandle: string | FactoryHandle,
options?: RunOptions
): Promise