@github/copilot-sdk-darwin-arm64 1.0.16-preview.0 → 1.0.17-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ export declare class CopilotClient {
10
10
  private requestAdapter;
11
11
  private messageWriter;
12
12
  private connectionClosed;
13
+ private connectionEpoch;
13
14
  private socket;
14
15
  private runtimePort;
15
16
  private actualHost;
@@ -3876,7 +3876,7 @@ var init_ffiRuntimeHost = __esm({
3876
3876
  );
3877
3877
  if (!this.connectionId) {
3878
3878
  this.unregisterCallback();
3879
- this.lib.hostShutdown(this.serverId);
3879
+ await this.shutdownHost();
3880
3880
  this.serverId = 0;
3881
3881
  throw new Error("copilot_runtime_connection_open failed.");
3882
3882
  }
@@ -3885,7 +3885,7 @@ var init_ffiRuntimeHost = __esm({
3885
3885
  } finally {
3886
3886
  this.starting = false;
3887
3887
  if (this.disposed) {
3888
- void this.tryFinalizeCleanup();
3888
+ await this.tryFinalizeCleanup();
3889
3889
  }
3890
3890
  }
3891
3891
  }
@@ -3924,6 +3924,17 @@ var init_ffiRuntimeHost = __esm({
3924
3924
  );
3925
3925
  }
3926
3926
  }
3927
+ shutdownHost() {
3928
+ return new Promise((resolvePromise, rejectPromise) => {
3929
+ this.lib.hostShutdown.async(this.serverId, (error, result) => {
3930
+ if (error) {
3931
+ rejectPromise(error);
3932
+ } else {
3933
+ resolvePromise(result);
3934
+ }
3935
+ });
3936
+ });
3937
+ }
3927
3938
  unregisterCallback() {
3928
3939
  if (this.outboundCallback === void 0) {
3929
3940
  return true;
@@ -3996,7 +4007,7 @@ var init_ffiRuntimeHost = __esm({
3996
4007
  }
3997
4008
  if (this.serverId) {
3998
4009
  try {
3999
- if (!this.lib.hostShutdown(this.serverId)) {
4010
+ if (!await this.shutdownHost()) {
4000
4011
  console.error(
4001
4012
  `In-process FFI host shutdown did not recognize server ${this.serverId}.`
4002
4013
  );
@@ -4660,15 +4671,45 @@ function createServerRpc(connection) {
4660
4671
  /** @experimental */
4661
4672
  managedSettings: {
4662
4673
  /**
4663
- * Discovers device-managed settings from production MDM and managed-file sources, validates them against the runtime-owned managed-settings schema, and returns the canonical JSON without requiring a session.
4674
+ * Discovers device-managed settings from production MDM and managed-file sources, validates them against the runtime-owned managed-settings schema, and returns the canonical JSON without requiring a session. `managedSettings.resolve` returns the same device settings together with the account's server policy.
4664
4675
  *
4665
4676
  * @returns Validated device-managed settings discovered before a session exists.
4666
4677
  */
4667
4678
  read: async () => connection.sendRequest("managedSettings.read", {}),
4668
4679
  /**
4669
- * Force-refreshes enterprise managed settings for every account: wipes the persistent server-policy cache (the whole `<cacheHome>/managed-settings` directory) and drops this runtime process's in-memory retained server policy. It does not itself fetch policy — the effect is that the next time a session resolves managed settings for an account, that resolution re-fetches the account's org policy from the network instead of serving a cached response. Note that `managedSettings.read` returns only device/MDM settings and never triggers the account server-policy fetch, so a host implementing "sync account policy" should start a fresh session resolution rather than treat a subsequent `managedSettings.read` as the refreshed org policy. Mirrors the invalidation a sign-out performs, broadened from the one signing-out account to all of them; device/MDM layers describe the machine, not the account, and are left untouched. Rejects if the on-disk cache cannot be removed.
4680
+ * Force-refreshes enterprise managed settings for every account: wipes the persistent server-policy cache (the whole `<cacheHome>/managed-settings` directory) and drops this runtime process's in-memory retained server policy. It does not itself fetch policy — the effect is that the next time a session resolves managed settings for an account, that resolution re-fetches the account's org policy from the network instead of serving a cached response. Note that `managedSettings.read` returns only device/MDM settings and never triggers the account server-policy fetch, so a host implementing "sync account policy" should call `managedSettings.resolve` or start a fresh session resolution rather than treat a subsequent `managedSettings.read` as the refreshed org policy. Mirrors the invalidation a sign-out performs, broadened from the one signing-out account to all of them; device/MDM layers describe the machine, not the account, and are left untouched. Rejects if the on-disk cache cannot be removed.
4681
+ */
4682
+ clearCache: async () => connection.sendRequest("managedSettings.clearCache", {}),
4683
+ /**
4684
+ * Resolves the effective enterprise managed settings without a session, from the device channel and, when an account is available, the account's server policy through the same per-account cache sessions use. A cached server policy less than an hour old is used without a fetch; otherwise the policy is fetched, and when the fetch fails a cached policy up to 24 hours old is used instead, unless `forceRemoteSettingsRefresh` requires a live fetch. With no account requested or signed in, it reports device policy only; signing out removes the account's cached policy. It can fetch server policy over the network when the cache is stale, so call it off latency-critical paths such as startup rather than before listing models. The policy helper is not run. `layers` lists each channel's document before merging, and `values` and `meta` carry typed effective values and their lock state for the keys typed so far.
4685
+ *
4686
+ * @param params Optional opaque account selection or GitHub token whose managed settings are resolved.
4687
+ *
4688
+ * @returns Effective enterprise managed settings for an account, resolved without a session.
4689
+ */
4690
+ resolve: async (params) => connection.sendRequest("managedSettings.resolve", params),
4691
+ /**
4692
+ * Returns the managed-settings authoring JSON schema with descriptive `x-composition` annotations aligned with the shared settings-engine vocabulary. These annotations are not a complete runtime composition contract: model, effortLevel, and contextTier remain coupled. Use `managedSettings.compose` for the runtime's effective result. Performs no I/O.
4693
+ *
4694
+ * @returns The authoring JSON schema for managed settings recognized by this runtime.
4695
+ */
4696
+ schema: async () => connection.sendRequest("managedSettings.schema", {}),
4697
+ /**
4698
+ * Validates a candidate managed-settings document the way the runtime validates delivered policy, without applying it. Reports errors that would reject the document, warnings for content the runtime ignores, and the canonical document it would apply. Document text nested more than 64 levels deep is rejected. Performs no I/O.
4699
+ *
4700
+ * @param params A candidate managed-settings document to validate without applying it.
4701
+ *
4702
+ * @returns Result of validating a managed-settings document.
4703
+ */
4704
+ validate: async (params) => connection.sendRequest("managedSettings.validate", params),
4705
+ /**
4706
+ * Merges candidate managed-settings documents for the device, server, and policy-helper channels into the effective settings the runtime would enforce on this host, using the same precedence and composition rules as live resolution, without applying them. Like live resolution, a server's advisory sandbox force-enable is declined on a host that cannot run the sandbox. Does not fetch policy or read policy files, but may perform blocking OS or subprocess probes for sandbox support. Preview documents are limited to 1 MiB and 64 levels of nesting.
4707
+ *
4708
+ * @param params Candidate managed-settings documents to merge without applying them.
4709
+ *
4710
+ * @returns The effective managed settings the runtime would enforce for the given documents, in the same shape `managedSettings.resolve` returns.
4670
4711
  */
4671
- clearCache: async () => connection.sendRequest("managedSettings.clearCache", {})
4712
+ compose: async (params) => connection.sendRequest("managedSettings.compose", params)
4672
4713
  },
4673
4714
  /** @experimental */
4674
4715
  runtime: {
@@ -6116,6 +6157,12 @@ function createSessionRpc(connection, sessionId) {
6116
6157
  * @returns Feature detection and hard polling limits for the EXPERIMENTAL session connector API.
6117
6158
  */
6118
6159
  getCapabilities: async () => connection.sendRequest("session.connectors.getCapabilities", { sessionId }),
6160
+ /**
6161
+ * Returns the session account selection, or null.
6162
+ *
6163
+ * @returns Session account selection, or null.
6164
+ */
6165
+ getAccount: async () => connection.sendRequest("session.connectors.getAccount", { sessionId }),
6119
6166
  /**
6120
6167
  * Returns authoritative session Connector state from current availability, pinned account selection, cached catalog, and live MCP projection without performing a Connector service request.
6121
6168
  *
@@ -6184,7 +6231,7 @@ function createSessionRpc(connection, sessionId) {
6184
6231
  /**
6185
6232
  * Waits for the live session's in-flight managed-settings application, then returns the retained effective snapshot used by runtime enforcement and by `session.managed_settings_resolved`. It does not perform another account, device, or server resolution, and rejects when resolution has not produced a snapshot.
6186
6233
  *
6187
- * @returns Enterprise managed-settings resolution: the effective managed settings the session applied and which channels contributed, so SDK clients can show users what is enterprise-managed. Fires whenever managed policy is (re)applied — at session start, on resume, and on account switch. This is an ephemeral live snapshot (delivered to subscribers but not persisted to the session event log), because at session start it resolves before `session.start` is emitted. Device values take precedence over server values, then the policy helper, per ordinary key, while permissions compose restrictively across device, server, policy-helper, and SDK-client layers. The account-scoped `getManagedSettings()` API does not include session-local client injection. Marked experimental while the managed-settings surface stabilizes.
6234
+ * @returns Effective enterprise managed settings and contributing channels. Session events report applied policy; sessionless resolve reports an account/device snapshot, and compose reports a non-applying preview of candidate documents. Device values take precedence over server values, then the policy helper, per ordinary key, while permissions compose restrictively. Session-local SDK-client policy is included only in session results. Marked experimental while the managed-settings surface stabilizes.
6188
6235
  */
6189
6236
  get: async () => connection.sendRequest("session.managedSettings.get", { sessionId })
6190
6237
  },
@@ -8926,6 +8973,7 @@ var CopilotSession = class {
8926
8973
  sessionId;
8927
8974
  connection;
8928
8975
  _workspacePath;
8976
+ _transcriptRecovery;
8929
8977
  eventHandlers = /* @__PURE__ */ new Set();
8930
8978
  typedEventHandlers = /* @__PURE__ */ new Map();
8931
8979
  toolHandlers = /* @__PURE__ */ new Map();
@@ -9115,6 +9163,14 @@ var CopilotSession = class {
9115
9163
  get workspacePath() {
9116
9164
  return this._workspacePath;
9117
9165
  }
9166
+ /** Recovery observed while loading this session; undefined on a clean resume. */
9167
+ get transcriptRecovery() {
9168
+ return this._transcriptRecovery;
9169
+ }
9170
+ /** @internal */
9171
+ setTranscriptRecovery(recovery) {
9172
+ this._transcriptRecovery = recovery;
9173
+ }
9118
9174
  /**
9119
9175
  * Host capabilities reported when the session was created or resumed.
9120
9176
  * Use this to check feature support before calling capability-gated APIs.
@@ -11294,6 +11350,7 @@ var CopilotClient = class _CopilotClient {
11294
11350
  requestAdapter = null;
11295
11351
  messageWriter = null;
11296
11352
  connectionClosed = false;
11353
+ connectionEpoch = 0;
11297
11354
  socket = null;
11298
11355
  runtimePort = null;
11299
11356
  actualHost = "localhost";
@@ -11703,6 +11760,7 @@ var CopilotClient = class _CopilotClient {
11703
11760
  }
11704
11761
  async doStart() {
11705
11762
  this.forceStopping = false;
11763
+ this.connectionEpoch++;
11706
11764
  this.connectionClosed = false;
11707
11765
  this.processTransportError = null;
11708
11766
  this.state = "connecting";
@@ -11738,6 +11796,9 @@ var CopilotClient = class _CopilotClient {
11738
11796
  if (this.requestHandler) {
11739
11797
  await this.connection.sendRequest("llmInference.setProvider", {});
11740
11798
  }
11799
+ if (this.connectionClosed) {
11800
+ throw new Error("CLI server connection closed during startup");
11801
+ }
11741
11802
  this.state = "connected";
11742
11803
  } catch (error) {
11743
11804
  const startupError = this.processTransportError ?? error;
@@ -11857,10 +11918,23 @@ var CopilotClient = class _CopilotClient {
11857
11918
  this.socket = null;
11858
11919
  try {
11859
11920
  if (!socket.destroyed) {
11860
- await new Promise((resolve22) => {
11861
- socket.once("close", () => resolve22());
11862
- socket.end();
11863
- });
11921
+ let timeout;
11922
+ try {
11923
+ await new Promise((resolve22) => {
11924
+ socket.once("close", () => resolve22());
11925
+ if (this.connectionClosed) {
11926
+ socket.destroy();
11927
+ } else {
11928
+ timeout = setTimeout(
11929
+ () => socket.destroy(),
11930
+ RUNTIME_SHUTDOWN_TIMEOUT_MS
11931
+ );
11932
+ socket.end();
11933
+ }
11934
+ });
11935
+ } finally {
11936
+ if (timeout !== void 0) clearTimeout(timeout);
11937
+ }
11864
11938
  }
11865
11939
  } catch (error) {
11866
11940
  errors.push(
@@ -12523,6 +12597,7 @@ var CopilotClient = class _CopilotClient {
12523
12597
  allowedModels: config.allowedModels,
12524
12598
  ...await getTraceContext(this.onGetTraceContext),
12525
12599
  sessionId,
12600
+ allowTranscriptRecovery: config.allowTranscriptRecovery,
12526
12601
  clientName: config.clientName,
12527
12602
  model: config.model,
12528
12603
  reasoningEffort: config.reasoningEffort,
@@ -12629,10 +12704,11 @@ var CopilotClient = class _CopilotClient {
12629
12704
  }
12630
12705
  }
12631
12706
  }
12632
- const { workspacePath, capabilities, openCanvases } = response;
12707
+ const { workspacePath, capabilities, openCanvases, transcriptRecovery } = response;
12633
12708
  session["_workspacePath"] = workspacePath;
12634
12709
  session.setCapabilities(capabilities);
12635
12710
  session.setOpenCanvases(openCanvases ?? []);
12711
+ session.setTranscriptRecovery(transcriptRecovery);
12636
12712
  if (config.onMcpAuthRequest) {
12637
12713
  await this.connection.sendRequest("session.eventLog.registerInterest", {
12638
12714
  sessionId,
@@ -13621,8 +13697,13 @@ stderr: ${stderrOutput}` : ""}`
13621
13697
  );
13622
13698
  const connection = this.connection;
13623
13699
  const messageWriter = this.messageWriter;
13700
+ const cliProcess = this.isExternalServer ? null : this.cliProcess;
13701
+ const connectionEpoch = this.connectionEpoch;
13702
+ const isCurrentConnection = () => connectionEpoch === this.connectionEpoch && this.connection === connection && (cliProcess === null || this.cliProcess === cliProcess);
13703
+ let disconnecting = false;
13704
+ let exitFallback;
13624
13705
  const markDisconnected = () => {
13625
- if (this.connection !== connection) {
13706
+ if (!isCurrentConnection()) {
13626
13707
  connection.dispose();
13627
13708
  return;
13628
13709
  }
@@ -13636,13 +13717,48 @@ stderr: ${stderrOutput}` : ""}`
13636
13717
  this.githubTokenProviders.clear();
13637
13718
  this.requestAdapter?.cancelPending();
13638
13719
  connection.dispose();
13720
+ this.socket?.destroy();
13721
+ this.connection = null;
13722
+ this.messageWriter = null;
13723
+ this._rpc = null;
13724
+ this._internalRpc = null;
13725
+ this.modelsCache = null;
13639
13726
  };
13640
- this.connection.onClose(() => {
13727
+ const disconnectAfterDrain = () => {
13728
+ if (exitFallback !== void 0) {
13729
+ clearTimeout(exitFallback);
13730
+ exitFallback = void 0;
13731
+ }
13732
+ if (!isCurrentConnection()) {
13733
+ connection.dispose();
13734
+ return;
13735
+ }
13736
+ if (disconnecting) return;
13737
+ disconnecting = true;
13738
+ this.connectionClosed = true;
13641
13739
  if (messageWriter) messageWriter.suppressWriteErrors = true;
13642
13740
  void connection.drain().then(markDisconnected);
13643
- });
13741
+ };
13742
+ this.connection.onClose(disconnectAfterDrain);
13743
+ if (cliProcess) {
13744
+ cliProcess.once("exit", () => {
13745
+ if (!isCurrentConnection()) {
13746
+ connection.dispose();
13747
+ return;
13748
+ }
13749
+ if (disconnecting) return;
13750
+ if (this.socket) {
13751
+ disconnectAfterDrain();
13752
+ return;
13753
+ }
13754
+ this.connectionClosed = true;
13755
+ if (messageWriter) messageWriter.suppressWriteErrors = true;
13756
+ exitFallback = setTimeout(disconnectAfterDrain, RUNTIME_SHUTDOWN_TIMEOUT_MS);
13757
+ exitFallback.unref();
13758
+ });
13759
+ }
13644
13760
  this.connection.onError(() => {
13645
- if (this.connection === connection) {
13761
+ if (connectionEpoch === this.connectionEpoch && this.connection === connection) {
13646
13762
  this.state = "disconnected";
13647
13763
  }
13648
13764
  });
@@ -33,6 +33,7 @@ export declare class FfiRuntimeHost {
33
33
  * bytes are copied out before returning.
34
34
  */
35
35
  private feedInbound;
36
+ private shutdownHost;
36
37
  private unregisterCallback;
37
38
  private scheduleCleanupRetry;
38
39
  private tryFinalizeCleanup;