@github/copilot-sdk 1.0.11 → 1.0.12-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.
@@ -217,9 +217,9 @@ function getBundledCliPath() {
217
217
  if (typeof import_meta.resolve === "function") {
218
218
  for (const packageName of packageNames) {
219
219
  try {
220
- const sdkUrl = import_meta.resolve(`${packageName}/sdk`);
221
- const sdkPath = (0, import_node_url.fileURLToPath)(sdkUrl);
222
- return (0, import_node_path.join)((0, import_node_path.dirname)((0, import_node_path.dirname)(sdkPath)), "index.js");
220
+ const packageEntryUrl = import_meta.resolve(packageName);
221
+ const packageEntryPath = (0, import_node_url.fileURLToPath)(packageEntryUrl);
222
+ return (0, import_node_path.join)((0, import_node_path.dirname)(packageEntryPath), "index.js");
223
223
  } catch {
224
224
  }
225
225
  }
@@ -1119,7 +1119,7 @@ class CopilotClient {
1119
1119
  canvasProvider: config.canvasProvider,
1120
1120
  commands: config.commands?.map((cmd) => ({
1121
1121
  name: cmd.name,
1122
- description: cmd.description
1122
+ description: cmd.description ?? ""
1123
1123
  })),
1124
1124
  systemMessage: wireSystemMessage,
1125
1125
  availableTools: toolFilterOptions.availableTools,
@@ -1242,10 +1242,10 @@ class CopilotClient {
1242
1242
  return this.resumeSessionInternal(sessionId, config);
1243
1243
  }
1244
1244
  /** @internal */
1245
- async resumeSessionForExtension(sessionId, config, factories) {
1246
- return this.resumeSessionInternal(sessionId, config, factories);
1245
+ async resumeSessionForExtension(sessionId, config, factories, extensionOptions) {
1246
+ return this.resumeSessionInternal(sessionId, config, factories, extensionOptions);
1247
1247
  }
1248
- async resumeSessionInternal(sessionId, config, factories) {
1248
+ async resumeSessionInternal(sessionId, config, factories, extensionOptions) {
1249
1249
  if (!this.connection) {
1250
1250
  await this.start();
1251
1251
  }
@@ -1342,7 +1342,7 @@ class CopilotClient {
1342
1342
  canvasProvider: config.canvasProvider,
1343
1343
  commands: config.commands?.map((cmd) => ({
1344
1344
  name: cmd.name,
1345
- description: cmd.description
1345
+ description: cmd.description ?? ""
1346
1346
  })),
1347
1347
  provider: bearerWireProvider,
1348
1348
  capi: config.capi,
@@ -1394,12 +1394,30 @@ class CopilotClient {
1394
1394
  openCanvases: config.openCanvases,
1395
1395
  expAssignments: config.expAssignments,
1396
1396
  enableManagedSettings: config.enableManagedSettings,
1397
- managedSettings: config.managedSettings
1397
+ managedSettings: config.managedSettings,
1398
+ ...extensionOptions?.requestedEnvironmentVariables ? {
1399
+ requestedEnvironmentVariables: extensionOptions.requestedEnvironmentVariables
1400
+ } : {}
1398
1401
  });
1402
+ if (extensionOptions?.requestedEnvironmentVariables) {
1403
+ const requested = new Set(extensionOptions.requestedEnvironmentVariables);
1404
+ const { grantedEnvironmentVariables } = response;
1405
+ for (const [name, value] of Object.entries(grantedEnvironmentVariables ?? {})) {
1406
+ if (requested.has(name)) {
1407
+ process.env[name] = value;
1408
+ }
1409
+ }
1410
+ }
1399
1411
  const { workspacePath, capabilities, openCanvases } = response;
1400
1412
  session["_workspacePath"] = workspacePath;
1401
1413
  session.setCapabilities(capabilities);
1402
1414
  session.setOpenCanvases(openCanvases ?? []);
1415
+ if (config.mcpServers) {
1416
+ await this.connection.sendRequest("session.mcp.reloadWithConfig", {
1417
+ sessionId,
1418
+ config: { mcpServers: toWireMcpServers(config.mcpServers) }
1419
+ });
1420
+ }
1403
1421
  if (config.onMcpAuthRequest) {
1404
1422
  await this.connection.sendRequest("session.eventLog.registerInterest", {
1405
1423
  sessionId,
@@ -42,6 +42,7 @@ async function joinSession(config = {}) {
42
42
  const {
43
43
  extensionSdkPath: _stripped,
44
44
  factories,
45
+ requestedEnvironmentVariables,
45
46
  ...rest
46
47
  } = config;
47
48
  void _stripped;
@@ -52,7 +53,8 @@ async function joinSession(config = {}) {
52
53
  onPermissionRequest: config.onPermissionRequest ?? import_types.defaultJoinSessionPermissionHandler,
53
54
  suppressResumeEvent: config.suppressResumeEvent ?? true
54
55
  },
55
- factories
56
+ factories,
57
+ requestedEnvironmentVariables?.length ? { requestedEnvironmentVariables } : void 0
56
58
  );
57
59
  }
58
60
  // Annotate the CommonJS export names for ESM import in node:
@@ -43,7 +43,7 @@ function createServerRpc(connection) {
43
43
  /**
44
44
  * Lists Copilot models available to the authenticated user.
45
45
  *
46
- * @param params Optional GitHub token used to list models for a specific user instead of the global auth context.
46
+ * @param params Optional opaque account selection or compatibility GitHub token used to list models.
47
47
  *
48
48
  * @returns List of Copilot models available to the resolved user, including capabilities and billing metadata.
49
49
  */
@@ -69,9 +69,9 @@ function createServerRpc(connection) {
69
69
  /** @experimental */
70
70
  account: {
71
71
  /**
72
- * Gets Copilot quota usage for the authenticated user or supplied GitHub token.
72
+ * Gets Copilot quota usage for the current or opaquely selected authenticated user.
73
73
  *
74
- * @param params Optional GitHub token used to look up quota for a specific user instead of the global auth context.
74
+ * @param params Optional opaque account selection or compatibility GitHub token used to look up quota.
75
75
  *
76
76
  * @returns Quota usage snapshots for the resolved user, keyed by quota type.
77
77
  */
@@ -168,7 +168,15 @@ function createServerRpc(connection) {
168
168
  *
169
169
  * @returns MCP servers discovered from user, workspace, plugin, and built-in sources.
170
170
  */
171
- discover: async (params) => connection.sendRequest("mcp.discover", params)
171
+ discover: async (params) => connection.sendRequest("mcp.discover", params),
172
+ /**
173
+ * Requests a side-effect-free MCP install plan from a catalog candidate handle or a caller-supplied card. This host-implemented server method is available through SDK/TUI hosts; standalone and C-ABI runtimes whose host does not implement server-method dispatch return JSON-RPC MethodNotFound. A runtime with planning available returns a normalised plan and opaque single-use plan handle; a runtime without it returns the typed planning-unavailable result. A completed plan reports resource identity, provenance, eligible transport choices, the user-scope target, required typed values and secret placeholders, the policy result, the configuration changes installing would make, and whether a reload would be needed. Planning never writes configuration, stores a secret, or reloads MCP servers, so abandoning a plan needs no call and leaves nothing behind.
174
+ *
175
+ * @param params A side-effect-free request for an MCP install plan. Computing a plan never writes configuration, stores a secret, or reloads MCP servers.
176
+ *
177
+ * @returns Outcome of an mcp.planInstall call: either a normalised plan, or one typed refusal. Nothing is written in either case.
178
+ */
179
+ planInstall: async (params) => connection.sendRequest("mcp.planInstall", params)
172
180
  },
173
181
  /** @experimental */
174
182
  extensions: {
@@ -198,6 +206,17 @@ function createServerRpc(connection) {
198
206
  */
199
207
  registerExtensionLaunchProvider: async () => connection.sendRequest("registerExtensionLaunchProvider", {}),
200
208
  /** @experimental */
209
+ catalog: {
210
+ /**
211
+ * Requests a bounded catalog search. This host-implemented server method is available through SDK/TUI hosts; standalone and C-ABI runtimes whose host does not implement server-method dispatch return JSON-RPC MethodNotFound. A runtime with search available returns inert candidate summaries, each with an opaque single-use handle scoped to this runtime instance; a runtime without it returns the typed search-unavailable result. Public authorities may be searched anonymously, while an authority that requires credentials yields the typed authentication-required result. All returned text, URLs, and package metadata are untrusted external data and can never trigger instructions, tools, or installation. Read-only: nothing is installed, configured, or persisted.
212
+ *
213
+ * @param params A bounded catalog search. Both the query length and the result count are capped by the schema so a caller cannot request an unbounded scan.
214
+ *
215
+ * @returns Outcome of a catalog.search call: either bounded inert candidates, or one typed refusal. Never a partial success.
216
+ */
217
+ search: async (params) => connection.sendRequest("catalog.search", params)
218
+ },
219
+ /** @experimental */
201
220
  plugins: {
202
221
  /**
203
222
  * Lists plugins installed in user/global state.
@@ -246,6 +265,15 @@ function createServerRpc(connection) {
246
265
  */
247
266
  disable: async (params) => connection.sendRequest("plugins.disable", params),
248
267
  /** @experimental */
268
+ builtin: {
269
+ /**
270
+ * Replaces this server's trusted built-in plugin directories while no sessions are active.
271
+ *
272
+ * @param params Trusted built-in plugin directories to use for this runtime process.
273
+ */
274
+ set: async (params) => connection.sendRequest("plugins.builtin.set", params)
275
+ },
276
+ /** @experimental */
249
277
  marketplaces: {
250
278
  /**
251
279
  * Lists all registered marketplaces (defaults + user-added).
@@ -296,7 +324,13 @@ function createServerRpc(connection) {
296
324
  *
297
325
  * @param params Skill names to mark as disabled in global configuration, replacing any previous list.
298
326
  */
299
- setDisabledSkills: async (params) => connection.sendRequest("skills.config.setDisabledSkills", params)
327
+ setDisabledSkills: async (params) => connection.sendRequest("skills.config.setDisabledSkills", params),
328
+ /**
329
+ * Atomically adds or removes one skill from the disabled list.
330
+ *
331
+ * @param params Adds or removes a single skill from the global disabled list, leaving every other entry untouched.
332
+ */
333
+ setSkillDisabled: async (params) => connection.sendRequest("skills.config.setSkillDisabled", params)
300
334
  },
301
335
  /**
302
336
  * Discovers skills across global and project sources.
@@ -639,7 +673,7 @@ function createInternalServerRpc(connection) {
639
673
  /**
640
674
  * Performs the SDK server connection handshake and validates the optional connection token. Marked internal because this is JSON-RPC transport plumbing invoked automatically by an SDK client's own `connect()` wrapper, not a user-facing method. Stays internal as long as the SDK client owns the handshake; would only become public if the SDK ever exposed the raw schema surface to consumers without a connection wrapper.
641
675
  *
642
- * @param params Parameters for the `server.connect` handshake: an optional connection token and optional connection-level opt-ins (e.g. GitHub telemetry forwarding).
676
+ * @param params Connection-level opt-ins for the `server.connect` handshake. Transport authentication is consumed by the native protocol boundary before dispatch.
643
677
  *
644
678
  * @returns Handshake result reporting the server's protocol version and package version on success.
645
679
  *
@@ -982,6 +1016,8 @@ function createSessionRpc(connection, sessionId) {
982
1016
  * Sets the current agent interaction mode.
983
1017
  *
984
1018
  * @param params Agent interaction mode to apply to the session.
1019
+ *
1020
+ * @returns Outcome of a session mode change, including any model switch it triggered and follow-up the host must perform.
985
1021
  */
986
1022
  set: async (params) => connection.sendRequest("session.mode.set", { sessionId, ...params })
987
1023
  },
@@ -1384,6 +1420,12 @@ function createSessionRpc(connection, sessionId) {
1384
1420
  * Reloads MCP server connections for the session.
1385
1421
  */
1386
1422
  reload: async () => connection.sendRequest("session.mcp.reload", { sessionId }),
1423
+ /**
1424
+ * Releases any turns waiting on an in-flight MCP load without cancelling the load, letting the agent proceed while MCP servers finish connecting in the background. No-op when no MCP load is in flight or waiting turns were already released.
1425
+ *
1426
+ * @returns Result of moving in-flight MCP loading to the background.
1427
+ */
1428
+ moveLoadingToBackground: async () => connection.sendRequest("session.mcp.moveLoadingToBackground", { sessionId }),
1387
1429
  /**
1388
1430
  * Runs an MCP sampling inference on behalf of an MCP server.
1389
1431
  *
@@ -1464,6 +1506,14 @@ function createSessionRpc(connection, sessionId) {
1464
1506
  * @returns OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server.
1465
1507
  */
1466
1508
  login: async (params) => connection.sendRequest("session.mcp.oauth.login", { sessionId, ...params }),
1509
+ /**
1510
+ * Passively probes a configured remote MCP server to classify whether OAuth is required or a cached/override token is accepted. Does not start OAuth, emit pending OAuth requests, or mutate MCP connection state.
1511
+ *
1512
+ * @param params Remote MCP server name for a passive OAuth status probe.
1513
+ *
1514
+ * @returns Passive MCP OAuth probe result. `authenticated` means the server accepted the probe request while an OAuth-origin access token was attached; it does not prove the server required or independently validated that token. The probe does not make a second unauthenticated request. Failed is an expected probe-domain outcome; JSON-RPC errors are reserved for API-call failures.
1515
+ */
1516
+ probe: async (params) => connection.sendRequest("session.mcp.oauth.probe", { sessionId, ...params }),
1467
1517
  /**
1468
1518
  * Responds to a pending MCP OAuth authorization request by its request id.
1469
1519
  *
@@ -1646,6 +1696,30 @@ function createSessionRpc(connection, sessionId) {
1646
1696
  },
1647
1697
  /** @experimental */
1648
1698
  tools: {
1699
+ /**
1700
+ * Executes one tool from the session's currently offered tool set through the native invocation pipeline.
1701
+ *
1702
+ * @param params A tool name and arguments to execute through the session's native invocation pipeline.
1703
+ *
1704
+ * @returns Canonical result returned by a session tool.
1705
+ */
1706
+ execute: async (params) => connection.sendRequest("session.tools.execute", { sessionId, ...params }),
1707
+ /**
1708
+ * Returns the Rust-owned built-in tool descriptors used to construct the session's offered tool set.
1709
+ *
1710
+ * @param params Options controlling how Rust-owned built-in tool descriptors are materialized.
1711
+ *
1712
+ * @returns Rust-owned built-in tool descriptors for the session.
1713
+ */
1714
+ getBuiltinDescriptors: async (params) => connection.sendRequest("session.tools.getBuiltinDescriptors", { sessionId, ...params }),
1715
+ /**
1716
+ * Projects a completed task_complete tool call into its label-safe session event payload.
1717
+ *
1718
+ * @param params Task-completion tool arguments and final result used to build a label-safe session event payload.
1719
+ *
1720
+ * @returns Task completion notification with summary from the agent
1721
+ */
1722
+ taskCompleteEventData: async (params) => connection.sendRequest("session.tools.taskCompleteEventData", { sessionId, ...params }),
1649
1723
  /**
1650
1724
  * Provides the result for a pending external tool call.
1651
1725
  *
@@ -1666,6 +1740,14 @@ function createSessionRpc(connection, sessionId) {
1666
1740
  * @returns Current lightweight tool metadata snapshot for the session.
1667
1741
  */
1668
1742
  getCurrentMetadata: async () => connection.sendRequest("session.tools.getCurrentMetadata", { sessionId }),
1743
+ /**
1744
+ * Atomically replaces the complete externally implemented tool list supplied by the calling connection. Built-in, MCP/plugin, extension-discovered, subagent, and tools supplied by other connections remain unchanged.
1745
+ *
1746
+ * @param params Complete externally implemented tool list for the calling connection. An empty list removes every tool previously supplied by that connection.
1747
+ *
1748
+ * @returns Empty result after replacing the calling connection's externally implemented tools.
1749
+ */
1750
+ set: async (params) => connection.sendRequest("session.tools.set", { sessionId, ...params }),
1669
1751
  /**
1670
1752
  * Updates the current session's live subagent settings after user settings change. The persisted user settings remain the source of truth for future sessions.
1671
1753
  *
@@ -1748,7 +1830,7 @@ function createSessionRpc(connection, sessionId) {
1748
1830
  *
1749
1831
  * @param params Transient question to answer without adding it to conversation history.
1750
1832
  *
1751
- * @returns Transient answer generated from current conversation context.
1833
+ * @returns Completed transient query. Ordered chunks and the terminal outcome are also delivered through `ui.ephemeral_query` session events while it runs.
1752
1834
  */
1753
1835
  ephemeralQuery: async (params) => connection.sendRequest("session.ui.ephemeralQuery", { sessionId, ...params }),
1754
1836
  /**
@@ -1855,19 +1937,19 @@ function createSessionRpc(connection, sessionId) {
1855
1937
  */
1856
1938
  setApproveAll: async (params) => connection.sendRequest("session.permissions.setApproveAll", { sessionId, ...params }),
1857
1939
  /**
1858
- * Sets the allow-all permission mode for the session. Used by attach-mode clients (e.g. LocalRpcSession's `/allow-all` forwarder) to flip the target session's permission state. The `on` mode swaps in unrestricted path and URL managers and emits `session.permissions_changed` on transition; the `auto` mode keeps normal prompt paths active while attaching LLM safety recommendations. The result returns the authoritative post-mutation state so callers can update their local mirrors without racing the `session.permissions_changed` notification on the same wire.
1940
+ * Sets the permission mode for the session. `manual` follows the normal approval flow, `assisted` attaches LLM safety recommendations, and `allow-all` automatically approves permission requests. The result returns the authoritative post-mutation mode so callers can update local state without racing the `session.permissions_changed` notification.
1859
1941
  *
1860
- * @param params Allow-all mode to apply for the session.
1942
+ * @param params Permission mode to apply for the session.
1861
1943
  *
1862
- * @returns Indicates whether the operation succeeded and reports the post-mutation state.
1944
+ * @returns Indicates whether the requested permission mode was applied and reports the authoritative post-mutation mode.
1863
1945
  */
1864
- setAllowAll: async (params) => connection.sendRequest("session.permissions.setAllowAll", { sessionId, ...params }),
1946
+ setMode: async (params) => connection.sendRequest("session.permissions.setMode", { sessionId, ...params }),
1865
1947
  /**
1866
- * Returns the current allow-all permission mode for the session.
1948
+ * Returns the current permission mode for the session.
1867
1949
  *
1868
- * @returns Current allow-all permission mode.
1950
+ * @returns Current permission mode.
1869
1951
  */
1870
- getAllowAll: async () => connection.sendRequest("session.permissions.getAllowAll", { sessionId }),
1952
+ getMode: async () => connection.sendRequest("session.permissions.getMode", { sessionId }),
1871
1953
  /**
1872
1954
  * Adds or removes session-scoped or location-scoped permission rules.
1873
1955
  *
@@ -2385,6 +2467,90 @@ function createInternalSessionRpc(connection, sessionId) {
2385
2467
  */
2386
2468
  sendSystemNotification: async (params) => connection.sendRequest("session.sendSystemNotification", { sessionId, ...params }),
2387
2469
  /** @experimental */
2470
+ gitHubAuth: {
2471
+ /**
2472
+ * Gets the current authentication information for internal session hosts.
2473
+ *
2474
+ * @returns Current authentication information, or null when no authentication is active.
2475
+ */
2476
+ getCurrentAuthInfo: async () => connection.sendRequest("session.gitHubAuth.getCurrentAuthInfo", { sessionId }),
2477
+ /**
2478
+ * Gets all authentication accounts available to the internal session host.
2479
+ *
2480
+ * @returns Authentication accounts available to the internal session host.
2481
+ */
2482
+ getAllAuthAvailable: async () => connection.sendRequest("session.gitHubAuth.getAllAuthAvailable", { sessionId }),
2483
+ /**
2484
+ * Refreshes Copilot account metadata for the current authentication.
2485
+ *
2486
+ * @returns Current authentication information, or null when no authentication is active.
2487
+ */
2488
+ refreshCopilotUser: async () => connection.sendRequest("session.gitHubAuth.refreshCopilotUser", { sessionId }),
2489
+ /**
2490
+ * Logs in a GitHub user through the internal session host.
2491
+ *
2492
+ * @param params Internal GitHub login parameters.
2493
+ *
2494
+ * @returns Authentication credentials accepted only at native protocol ingress. Runtime outputs use credential-free `AuthIdentity` metadata.
2495
+ */
2496
+ login: async (params) => connection.sendRequest("session.gitHubAuth.login", { sessionId, ...params }),
2497
+ /**
2498
+ * Switches the session to another available authentication.
2499
+ *
2500
+ * @param params Parameters for switching the session's active authentication.
2501
+ */
2502
+ switchToAuth: async (params) => connection.sendRequest("session.gitHubAuth.switchToAuth", { sessionId, ...params }),
2503
+ /**
2504
+ * Logs out the session's current GitHub authentication.
2505
+ *
2506
+ * @returns Whether the current authentication was logged out.
2507
+ */
2508
+ logout: async () => connection.sendRequest("session.gitHubAuth.logout", { sessionId }),
2509
+ /**
2510
+ * Logs out a specific GitHub authentication.
2511
+ *
2512
+ * @param params Parameters identifying a GitHub authentication to log out.
2513
+ *
2514
+ * @returns Whether the requested authentication was logged out.
2515
+ */
2516
+ logoutUser: async (params) => connection.sendRequest("session.gitHubAuth.logoutUser", { sessionId, ...params }),
2517
+ /**
2518
+ * Gets validation errors from the most recent authentication attempt.
2519
+ *
2520
+ * @returns Validation errors from the most recent authentication attempt.
2521
+ */
2522
+ lastAuthErrors: async () => connection.sendRequest("session.gitHubAuth.lastAuthErrors", { sessionId })
2523
+ },
2524
+ /** @experimental */
2525
+ canvas: {
2526
+ /** @experimental */
2527
+ provider: {
2528
+ /**
2529
+ * Registers an internal canvas provider connection and its contributions.
2530
+ *
2531
+ * @param params Internal canvas provider registration parameters.
2532
+ */
2533
+ register: async (params) => connection.sendRequest("session.canvas.provider.register", { sessionId, ...params }),
2534
+ /**
2535
+ * Unregisters an internal canvas provider connection.
2536
+ *
2537
+ * @param params Internal canvas provider unregistration parameters.
2538
+ */
2539
+ unregister: async (params) => connection.sendRequest("session.canvas.provider.unregister", { sessionId, ...params })
2540
+ }
2541
+ },
2542
+ /** @experimental */
2543
+ model: {
2544
+ /**
2545
+ * Resolves and applies organization-managed and repository model overlays.
2546
+ *
2547
+ * @param params Managed, repository, and CLI model overrides to overlay onto the session at startup.
2548
+ *
2549
+ * @returns The model identifier active on the session after the switch.
2550
+ */
2551
+ applyStartupOverlay: async (params) => connection.sendRequest("session.model.applyStartupOverlay", { sessionId, ...params })
2552
+ },
2553
+ /** @experimental */
2388
2554
  mcp: {
2389
2555
  /**
2390
2556
  * Reloads MCP server connections for the session with an explicit host-provided configuration.
@@ -2397,7 +2563,7 @@ function createInternalSessionRpc(connection, sessionId) {
2397
2563
  /**
2398
2564
  * Configures the built-in GitHub MCP server for the session's current auth context.
2399
2565
  *
2400
- * @param params Opaque auth info used to configure GitHub MCP.
2566
+ * @param params Credential-free authentication identity used to configure GitHub MCP.
2401
2567
  *
2402
2568
  * @returns Result of configuring GitHub MCP.
2403
2569
  */
@@ -2416,6 +2582,17 @@ function createInternalSessionRpc(connection, sessionId) {
2416
2582
  unregisterExternalClient: async (params) => connection.sendRequest("session.mcp.unregisterExternalClient", { sessionId, ...params })
2417
2583
  },
2418
2584
  /** @experimental */
2585
+ commands: {
2586
+ /**
2587
+ * Finalizes persistence associated with a client-applied slash-command effect.
2588
+ *
2589
+ * @param params The pending slash-command invocation effect to finalize, plus whether the host applied or cancelled it.
2590
+ *
2591
+ * @returns Whether finalizing the invocation effect succeeded, and the failure reason when it did not.
2592
+ */
2593
+ finalizeInvocationEffect: async (params) => connection.sendRequest("session.commands.finalizeInvocationEffect", { sessionId, ...params })
2594
+ },
2595
+ /** @experimental */
2419
2596
  settings: {
2420
2597
  /**
2421
2598
  * Returns a redacted snapshot of session runtime settings, with secrets and raw feature flags excluded. Internal: the runtime settings shape is a runtime-internal surface and is deliberately kept out of the public SDK, because consumers should not depend on the runtime's internal settings layout. It remains callable in-process and is expected to be reworked as the runtime internals are consolidated.
@@ -1174,7 +1174,13 @@ class CopilotSession {
1174
1174
  }
1175
1175
  try {
1176
1176
  const result = await this.elicitationHandler(context);
1177
- await this.rpc.ui.handlePendingElicitation({ requestId, result });
1177
+ await this.rpc.ui.handlePendingElicitation({
1178
+ requestId,
1179
+ result: {
1180
+ action: result.action,
1181
+ ...result.content ? { content: result.content } : {}
1182
+ }
1183
+ });
1178
1184
  } catch {
1179
1185
  try {
1180
1186
  await this.rpc.ui.handlePendingElicitation({
package/dist/client.js CHANGED
@@ -194,9 +194,9 @@ function getBundledCliPath() {
194
194
  if (typeof import.meta.resolve === "function") {
195
195
  for (const packageName of packageNames) {
196
196
  try {
197
- const sdkUrl = import.meta.resolve(`${packageName}/sdk`);
198
- const sdkPath = fileURLToPath(sdkUrl);
199
- return join(dirname(dirname(sdkPath)), "index.js");
197
+ const packageEntryUrl = import.meta.resolve(packageName);
198
+ const packageEntryPath = fileURLToPath(packageEntryUrl);
199
+ return join(dirname(packageEntryPath), "index.js");
200
200
  } catch {
201
201
  }
202
202
  }
@@ -1096,7 +1096,7 @@ class CopilotClient {
1096
1096
  canvasProvider: config.canvasProvider,
1097
1097
  commands: config.commands?.map((cmd) => ({
1098
1098
  name: cmd.name,
1099
- description: cmd.description
1099
+ description: cmd.description ?? ""
1100
1100
  })),
1101
1101
  systemMessage: wireSystemMessage,
1102
1102
  availableTools: toolFilterOptions.availableTools,
@@ -1219,10 +1219,10 @@ class CopilotClient {
1219
1219
  return this.resumeSessionInternal(sessionId, config);
1220
1220
  }
1221
1221
  /** @internal */
1222
- async resumeSessionForExtension(sessionId, config, factories) {
1223
- return this.resumeSessionInternal(sessionId, config, factories);
1222
+ async resumeSessionForExtension(sessionId, config, factories, extensionOptions) {
1223
+ return this.resumeSessionInternal(sessionId, config, factories, extensionOptions);
1224
1224
  }
1225
- async resumeSessionInternal(sessionId, config, factories) {
1225
+ async resumeSessionInternal(sessionId, config, factories, extensionOptions) {
1226
1226
  if (!this.connection) {
1227
1227
  await this.start();
1228
1228
  }
@@ -1319,7 +1319,7 @@ class CopilotClient {
1319
1319
  canvasProvider: config.canvasProvider,
1320
1320
  commands: config.commands?.map((cmd) => ({
1321
1321
  name: cmd.name,
1322
- description: cmd.description
1322
+ description: cmd.description ?? ""
1323
1323
  })),
1324
1324
  provider: bearerWireProvider,
1325
1325
  capi: config.capi,
@@ -1371,12 +1371,30 @@ class CopilotClient {
1371
1371
  openCanvases: config.openCanvases,
1372
1372
  expAssignments: config.expAssignments,
1373
1373
  enableManagedSettings: config.enableManagedSettings,
1374
- managedSettings: config.managedSettings
1374
+ managedSettings: config.managedSettings,
1375
+ ...extensionOptions?.requestedEnvironmentVariables ? {
1376
+ requestedEnvironmentVariables: extensionOptions.requestedEnvironmentVariables
1377
+ } : {}
1375
1378
  });
1379
+ if (extensionOptions?.requestedEnvironmentVariables) {
1380
+ const requested = new Set(extensionOptions.requestedEnvironmentVariables);
1381
+ const { grantedEnvironmentVariables } = response;
1382
+ for (const [name, value] of Object.entries(grantedEnvironmentVariables ?? {})) {
1383
+ if (requested.has(name)) {
1384
+ process.env[name] = value;
1385
+ }
1386
+ }
1387
+ }
1376
1388
  const { workspacePath, capabilities, openCanvases } = response;
1377
1389
  session["_workspacePath"] = workspacePath;
1378
1390
  session.setCapabilities(capabilities);
1379
1391
  session.setOpenCanvases(openCanvases ?? []);
1392
+ if (config.mcpServers) {
1393
+ await this.connection.sendRequest("session.mcp.reloadWithConfig", {
1394
+ sessionId,
1395
+ config: { mcpServers: toWireMcpServers(config.mcpServers) }
1396
+ });
1397
+ }
1380
1398
  if (config.onMcpAuthRequest) {
1381
1399
  await this.connection.sendRequest("session.eventLog.registerInterest", {
1382
1400
  sessionId,
@@ -4,6 +4,35 @@ import type { FactoryHandle } from "./factory.js";
4
4
  export { Canvas, CanvasError, createCanvas, type CanvasAction, type CanvasDeclaration, type CanvasHostContext, type CanvasJsonSchema, type CanvasOptions, } from "./canvas.js";
5
5
  export type JoinSessionConfig = Omit<ResumeSessionConfig, "onPermissionRequest" | "extensionSdkPath"> & {
6
6
  onPermissionRequest?: PermissionHandler;
7
+ /**
8
+ * Names of sensitive environment variables this extension needs, such as
9
+ * `"GITHUB_TOKEN"`.
10
+ *
11
+ * The Copilot CLI strips sensitive variables from every extension process
12
+ * before it starts, so an extension that needs one must ask for it by name.
13
+ * The CLI prompts the user with the extension's name and the exact list of
14
+ * variables requested. On approval the granted values are written into this
15
+ * process's `process.env` before {@link joinSession} resolves, so they are
16
+ * readable afterwards. On denial the join rejects and the extension does not
17
+ * load, so its tools never reach the model.
18
+ *
19
+ * An approval is remembered against the exact set of names the user saw, so
20
+ * asking for an additional variable later prompts again. Names that are unset
21
+ * or that the CLI does not filter from extensions are not prompted for. An
22
+ * empty list means the same as omitting the option: nothing is requested.
23
+ *
24
+ * Requires a Copilot CLI that supports extension environment access; older
25
+ * CLIs ignore the request and grant nothing.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const session = await joinSession({
30
+ * requestedEnvironmentVariables: ["GITHUB_TOKEN"],
31
+ * });
32
+ * const token = process.env.GITHUB_TOKEN;
33
+ * ```
34
+ */
35
+ requestedEnvironmentVariables?: string[];
7
36
  /**
8
37
  * Factory handles to register when the extension joins the session.
9
38
  *
package/dist/extension.js CHANGED
@@ -23,6 +23,7 @@ async function joinSession(config = {}) {
23
23
  const {
24
24
  extensionSdkPath: _stripped,
25
25
  factories,
26
+ requestedEnvironmentVariables,
26
27
  ...rest
27
28
  } = config;
28
29
  void _stripped;
@@ -33,7 +34,8 @@ async function joinSession(config = {}) {
33
34
  onPermissionRequest: config.onPermissionRequest ?? defaultJoinSessionPermissionHandler,
34
35
  suppressResumeEvent: config.suppressResumeEvent ?? true
35
36
  },
36
- factories
37
+ factories,
38
+ requestedEnvironmentVariables?.length ? { requestedEnvironmentVariables } : void 0
37
39
  );
38
40
  }
39
41
  export {