@github/copilot-sdk 1.0.13-preview.6 → 1.0.13

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.
package/dist/session.js CHANGED
@@ -231,6 +231,7 @@ class CopilotSession {
231
231
  eventHandlers = /* @__PURE__ */ new Set();
232
232
  typedEventHandlers = /* @__PURE__ */ new Map();
233
233
  toolHandlers = /* @__PURE__ */ new Map();
234
+ pendingExternalTools = /* @__PURE__ */ new Map();
234
235
  canvases = /* @__PURE__ */ new Map();
235
236
  bearerTokenProviders = /* @__PURE__ */ new Map();
236
237
  commandHandlers = /* @__PURE__ */ new Map();
@@ -250,6 +251,7 @@ class CopilotSession {
250
251
  _capabilities = {};
251
252
  openCanvasInstances = [];
252
253
  disconnected = false;
254
+ disconnecting = false;
253
255
  onDisconnected;
254
256
  /** @internal Client session API handlers, populated by CopilotClient during create/resume. */
255
257
  clientSessionApis = {};
@@ -507,6 +509,10 @@ class CopilotSession {
507
509
  return;
508
510
  }
509
511
  this.disconnected = true;
512
+ for (const controller of this.pendingExternalTools.values()) {
513
+ controller.abort();
514
+ }
515
+ this.pendingExternalTools.clear();
510
516
  this._runOnDisconnected();
511
517
  this.eventHandlers.clear();
512
518
  this.typedEventHandlers.clear();
@@ -610,6 +616,15 @@ class CopilotSession {
610
616
  tracestate
611
617
  );
612
618
  }
619
+ } else if (event.type === "external_tool.completed") {
620
+ const { requestId } = event.data;
621
+ if (requestId) {
622
+ const controller = this.pendingExternalTools.get(requestId);
623
+ if (controller) {
624
+ this.pendingExternalTools.delete(requestId);
625
+ controller.abort();
626
+ }
627
+ }
613
628
  } else if (event.type === "permission.requested") {
614
629
  const { requestId, permissionRequest, resolvedByHook } = event.data;
615
630
  if (resolvedByHook) {
@@ -690,16 +705,35 @@ class CopilotSession {
690
705
  * @internal
691
706
  */
692
707
  async _executeToolAndRespond(requestId, toolName, toolCallId, args, handler, traceparent, tracestate) {
708
+ const controller = new AbortController();
709
+ if (this.disconnected || this.pendingExternalTools.has(requestId)) {
710
+ return;
711
+ }
712
+ this.pendingExternalTools.set(requestId, controller);
693
713
  try {
694
714
  let availableTools;
695
715
  if (toolName === TOOL_SEARCH_TOOL_NAME) {
716
+ if (controller.signal.aborted) {
717
+ return;
718
+ }
719
+ const aborted = new Promise((resolve) => {
720
+ controller.signal.addEventListener("abort", () => resolve(void 0), {
721
+ once: true
722
+ });
723
+ });
696
724
  try {
697
- const metadata = await this.rpc.tools.getCurrentMetadata();
698
- availableTools = metadata.tools ?? void 0;
725
+ const metadata = await Promise.race([
726
+ this.rpc.tools.getCurrentMetadata(),
727
+ aborted
728
+ ]);
729
+ availableTools = metadata?.tools ?? void 0;
699
730
  } catch {
700
731
  availableTools = void 0;
701
732
  }
702
733
  }
734
+ if (controller.signal.aborted) {
735
+ return;
736
+ }
703
737
  const rawResult = await handler(args, {
704
738
  sessionId: this.sessionId,
705
739
  toolCallId,
@@ -707,7 +741,8 @@ class CopilotSession {
707
741
  arguments: args,
708
742
  availableTools,
709
743
  traceparent,
710
- tracestate
744
+ tracestate,
745
+ signal: controller.signal
711
746
  });
712
747
  let result;
713
748
  if (rawResult == null) {
@@ -719,12 +754,12 @@ class CopilotSession {
719
754
  } else {
720
755
  result = JSON.stringify(rawResult);
721
756
  }
722
- if (this.disconnected) {
757
+ if (!this._claimExternalTool(requestId, controller)) {
723
758
  return;
724
759
  }
725
760
  await this.rpc.tools.handlePendingToolCall({ requestId, result });
726
761
  } catch (error) {
727
- if (this.disconnected) {
762
+ if (!this._claimExternalTool(requestId, controller)) {
728
763
  return;
729
764
  }
730
765
  const message = error instanceof Error ? error.message : String(error);
@@ -735,7 +770,19 @@ class CopilotSession {
735
770
  throw rpcError;
736
771
  }
737
772
  }
773
+ } finally {
774
+ if (this.pendingExternalTools.get(requestId) === controller) {
775
+ this.pendingExternalTools.delete(requestId);
776
+ }
777
+ controller.abort();
778
+ }
779
+ }
780
+ _claimExternalTool(requestId, controller) {
781
+ if (this.disconnected || this.pendingExternalTools.get(requestId) !== controller) {
782
+ return false;
738
783
  }
784
+ this.pendingExternalTools.delete(requestId);
785
+ return true;
739
786
  }
740
787
  /**
741
788
  * Executes a permission handler and sends the result back via RPC.
@@ -1489,13 +1536,27 @@ class CopilotSession {
1489
1536
  * ```
1490
1537
  */
1491
1538
  async disconnect() {
1492
- if (this.disconnected) {
1539
+ if (this.disconnected || this.disconnecting) {
1493
1540
  return;
1494
1541
  }
1495
- await this.connection.sendRequest("session.destroy", {
1496
- sessionId: this.sessionId
1497
- });
1498
- this._markDisconnected();
1542
+ this.disconnecting = true;
1543
+ try {
1544
+ let response = { success: false };
1545
+ for (let attempt = 0; attempt < 2 && !response.success; attempt++) {
1546
+ response = await this.connection.sendRequest("session.detach", {
1547
+ sessionId: this.sessionId
1548
+ });
1549
+ }
1550
+ if (!response.success) {
1551
+ throw new Error(
1552
+ `Failed to disconnect session ${this.sessionId}: ${response.error || "Unknown error"}`
1553
+ );
1554
+ }
1555
+ this._markDisconnected();
1556
+ } catch (error) {
1557
+ this.disconnecting = false;
1558
+ throw error;
1559
+ }
1499
1560
  }
1500
1561
  /** Enables `await using session = ...` syntax for automatic cleanup. */
1501
1562
  async [Symbol.asyncDispose]() {
@@ -1537,11 +1598,48 @@ class CopilotSession {
1537
1598
  * ```typescript
1538
1599
  * await session.setModel("gpt-5.4");
1539
1600
  * await session.setModel("claude-sonnet-4.6", { reasoningEffort: "high" });
1601
+ *
1602
+ * // Select the Auto model and its routing preference in one call.
1603
+ * await session.setModel("auto", { autoTier: "intelligence" });
1540
1604
  * ```
1541
1605
  */
1542
1606
  async setModel(model, options) {
1543
1607
  await this.rpc.model.switchTo({ modelId: model, ...options });
1544
1608
  }
1609
+ /**
1610
+ * Change the Auto routing preference without changing the selected model.
1611
+ *
1612
+ * The runtime does not apply the preference immediately. It records the
1613
+ * request and commits it only when a later user turn using the `auto` model
1614
+ * successfully obtains a usable model from the provider. A `pending` status
1615
+ * therefore confirms that the request was accepted, not that it took effect.
1616
+ *
1617
+ * Watch for the outcome through the `session.model_change` event on success,
1618
+ * or the ephemeral `session.auto_tier_switch_failed` event on failure. You
1619
+ * can also read the current committed and in-flight state at any time with
1620
+ * `session.rpc.model.getCurrent()`.
1621
+ *
1622
+ * Only the most recent request survives: issuing a new request replaces any
1623
+ * earlier one that has not yet been claimed by a turn.
1624
+ *
1625
+ * @param autoTier - Routing preference to activate, or `null` to return to
1626
+ * the provider's default Auto routing
1627
+ * @returns The runtime's immediate acknowledgement and Auto preference snapshot
1628
+ *
1629
+ * @experimental Part of an experimental Auto routing surface and may change
1630
+ * or be removed in a future release.
1631
+ *
1632
+ * @example
1633
+ * ```typescript
1634
+ * const result = await session.setAutoTier("intelligence");
1635
+ * if (result.status === "pending") {
1636
+ * // Takes effect on a later turn that uses the `auto` model.
1637
+ * }
1638
+ * ```
1639
+ */
1640
+ async setAutoTier(autoTier) {
1641
+ return await this.rpc.model.switchAutoTier({ autoTier });
1642
+ }
1545
1643
  /**
1546
1644
  * Log a message to the session timeline.
1547
1645
  * The message appears in the session event stream and is visible to SDK consumers
package/dist/types.d.ts CHANGED
@@ -35,6 +35,7 @@ export type SessionEvent = Exclude<GeneratedSessionEvent, {
35
35
  type: "permission.requested";
36
36
  }> | PermissionRequestedEvent;
37
37
  export type { AutoTier, ReasoningSummary } from "./generated/session-events.js";
38
+ export type { CurrentModel, ModelSwitchAutoTierResult, ModelSwitchAutoTierStatus, } from "./generated/rpc.js";
38
39
  export type { SessionFsProvider } from "./sessionFsProvider.js";
39
40
  export { createSessionFsAdapter } from "./sessionFsProvider.js";
40
41
  export type { SessionFsFileInfo } from "./sessionFsProvider.js";
@@ -496,6 +497,8 @@ export interface ToolInvocation {
496
497
  traceparent?: string;
497
498
  /** W3C Trace Context tracestate from the CLI's execute_tool span. */
498
499
  tracestate?: string;
500
+ /** Aborted when the runtime completes this request or the session disconnects. */
501
+ signal?: AbortSignal;
499
502
  }
500
503
  export type ToolHandler<TArgs = unknown> = (args: TArgs, invocation: ToolInvocation) => Promise<unknown> | unknown;
501
504
  /**
@@ -1746,9 +1749,13 @@ export interface CapiSessionOptions {
1746
1749
  * Requires a runtime with Auto tier support and V2 Auto routing.
1747
1750
  *
1748
1751
  * When omitted on create, the runtime uses its default routing behavior.
1749
- * The runtime persists this preference across cold resume; an explicit tier
1750
- * on cold resume overrides the persisted value. For an already-resident
1751
- * session, omission preserves the current tier and a different tier is rejected.
1752
+ * The runtime persists this preference across cold resume; when omitted on
1753
+ * cold resume, it restores the last committed preference. On resident
1754
+ * resume, a different tier requests a safe switch that takes effect after
1755
+ * resume succeeds, and never disturbs a turn that is already running.
1756
+ *
1757
+ * To change the preference on a live session, call
1758
+ * {@link CopilotSession.setAutoTier} instead.
1752
1759
  */
1753
1760
  autoTier?: AutoTier;
1754
1761
  /**
package/package.json CHANGED
@@ -4,8 +4,8 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/github/copilot-sdk.git"
6
6
  },
7
- "version": "1.0.13-preview.6",
8
- "copilotCliVersion": "1.0.83-3",
7
+ "version": "1.0.13",
8
+ "copilotCliVersion": "1.0.83",
9
9
  "description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC",
10
10
  "main": "./dist/cjs/index.js",
11
11
  "types": "./dist/index.d.ts",
@@ -95,13 +95,13 @@
95
95
  "README.md"
96
96
  ],
97
97
  "optionalDependencies": {
98
- "@github/copilot-sdk-darwin-arm64": "1.0.13-preview.6",
99
- "@github/copilot-sdk-darwin-x64": "1.0.13-preview.6",
100
- "@github/copilot-sdk-linux-arm64": "1.0.13-preview.6",
101
- "@github/copilot-sdk-linux-x64": "1.0.13-preview.6",
102
- "@github/copilot-sdk-linuxmusl-arm64": "1.0.13-preview.6",
103
- "@github/copilot-sdk-linuxmusl-x64": "1.0.13-preview.6",
104
- "@github/copilot-sdk-win32-arm64": "1.0.13-preview.6",
105
- "@github/copilot-sdk-win32-x64": "1.0.13-preview.6"
98
+ "@github/copilot-sdk-darwin-arm64": "1.0.13",
99
+ "@github/copilot-sdk-darwin-x64": "1.0.13",
100
+ "@github/copilot-sdk-linux-arm64": "1.0.13",
101
+ "@github/copilot-sdk-linux-x64": "1.0.13",
102
+ "@github/copilot-sdk-linuxmusl-arm64": "1.0.13",
103
+ "@github/copilot-sdk-linuxmusl-x64": "1.0.13",
104
+ "@github/copilot-sdk-win32-arm64": "1.0.13",
105
+ "@github/copilot-sdk-win32-x64": "1.0.13"
106
106
  }
107
107
  }