@github/copilot-sdk 1.0.13-preview.1 → 1.0.13-preview.2

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/README.md CHANGED
@@ -137,12 +137,25 @@ Create a new conversation session.
137
137
  - `infiniteSessions?: InfiniteSessionConfig` - Configure automatic context compaction (see below)
138
138
  - `workingDirectory?: string` - Working directory for the session (default: runtime process cwd).
139
139
  - `enableSessionStore?: boolean` - Enables the cross-session store for search and retrieval across sessions. When unset in `"copilot-cli"` mode, the runtime default applies (enabled). In `"empty"` mode, defaults to disabled.
140
+ - `gitHubTokenProvider?: GitHubTokenProvider` - Acquires rotating, session-scoped GitHub tokens. Token results require a positive `expiresIn` value in seconds remaining when the callback completes; production tokens typically last eight hours. Cannot be combined with `gitHubToken`.
140
141
  - `provider?: ProviderConfig` - Custom API provider configuration (BYOK - Bring Your Own Key). See [Custom Providers](#custom-providers) section.
141
142
  - `onPermissionRequest?: PermissionHandler` - Optional handler called before each tool execution to approve or deny it. When omitted, permission requests are emitted as events and left pending for manual resolution. `approveAll` approves requests when managed settings are disabled and throws when `enableManagedSettings` is true. Custom handlers can inspect `managedApprovalRequired` for human-facing confirmation logic. See [Permission Handling](#permission-handling) section.
142
143
  - `onUserInputRequest?: UserInputHandler` - Handler for user input requests from the agent. Enables the `ask_user` tool. See [User Input Requests](#user-input-requests) section.
143
144
  - `onElicitationRequest?: ElicitationHandler` - Handler for elicitation requests dispatched by the server. Enables this client to present form-based UI dialogs on behalf of the agent or other session participants. See [Elicitation Requests](#elicitation-requests) section.
144
145
  - `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.
145
146
 
147
+ ```typescript
148
+ const session = await client.createSession({
149
+ gitHubTokenProvider: async ({ host }) => ({
150
+ kind: "token",
151
+ accessToken: await acquireTokenForHost(host),
152
+ expiresIn: 8 * 60 * 60,
153
+ }),
154
+ });
155
+ ```
156
+
157
+ Initial acquisition runs during session creation or resume. Cancellation, provider errors, and invalid token responses reject that operation instead of falling back to ambient authentication. Idle sessions refresh only before their next credential-consuming operation; there is no background refresh timer.
158
+
146
159
  ##### `resumeSession(sessionId: string, config?: ResumeSessionConfig): Promise<CopilotSession>`
147
160
 
148
161
  Resume an existing session. Returns the session with `workspacePath` populated if infinite sessions were enabled.
@@ -294,6 +294,7 @@ class CopilotClient {
294
294
  builtinPluginDirectories = [];
295
295
  onGitHubTelemetry;
296
296
  clientGlobalHandlers = {};
297
+ githubTokenProviders = /* @__PURE__ */ new Map();
297
298
  /**
298
299
  * Typed server-scoped RPC methods.
299
300
  * @throws Error if the client is not connected
@@ -551,8 +552,53 @@ class CopilotClient {
551
552
  }
552
553
  };
553
554
  }
555
+ handlers.gitHubToken = {
556
+ getToken: (params) => this.acquireGitHubToken(params)
557
+ };
554
558
  this.clientGlobalHandlers = handlers;
555
559
  }
560
+ async acquireGitHubToken(params) {
561
+ const registration = this.githubTokenProviders.get(params.registrationId);
562
+ if (!registration) {
563
+ throw new Error(
564
+ `No GitHub token provider registered for registration ID "${params.registrationId}"`
565
+ );
566
+ }
567
+ return await registration.provider({
568
+ host: params.host,
569
+ sessionId: params.sessionId ?? registration.sessionId,
570
+ reason: params.reason
571
+ });
572
+ }
573
+ registerGitHubTokenProvider(provider, sessionId) {
574
+ if (!provider) {
575
+ return void 0;
576
+ }
577
+ const registrationId = (0, import_node_crypto.randomUUID)();
578
+ this.githubTokenProviders.set(registrationId, { provider, sessionId, committed: false });
579
+ return registrationId;
580
+ }
581
+ assignGitHubTokenProvider(registrationId, sessionId) {
582
+ if (!registrationId) {
583
+ return;
584
+ }
585
+ const registration = this.githubTokenProviders.get(registrationId);
586
+ if (registration) {
587
+ registration.sessionId = sessionId;
588
+ }
589
+ }
590
+ commitGitHubTokenProvider(sessionId, registrationId) {
591
+ for (const [candidateId, registration2] of this.githubTokenProviders) {
592
+ if (registration2.sessionId === sessionId && registration2.committed) {
593
+ this.githubTokenProviders.delete(candidateId);
594
+ }
595
+ }
596
+ const registration = registrationId ? this.githubTokenProviders.get(registrationId) : void 0;
597
+ if (registration) {
598
+ registration.sessionId = sessionId;
599
+ registration.committed = true;
600
+ }
601
+ }
556
602
  /**
557
603
  * Starts the CLI server and establishes a connection.
558
604
  *
@@ -669,6 +715,7 @@ class CopilotClient {
669
715
  session._markDisconnected();
670
716
  }
671
717
  this.sessions.clear();
718
+ this.githubTokenProviders.clear();
672
719
  if (this.connection && (this.cliProcess || this.ffiHost) && !this.isExternalServer) {
673
720
  const runtimeShutdownStart = Date.now();
674
721
  const shutdownPromise = this.rpc.runtime.shutdown();
@@ -823,6 +870,7 @@ class CopilotClient {
823
870
  session._markDisconnected();
824
871
  }
825
872
  this.sessions.clear();
873
+ this.githubTokenProviders.clear();
826
874
  if (this.messageWriter) {
827
875
  this.messageWriter.suppressWriteErrors = true;
828
876
  }
@@ -1026,6 +1074,9 @@ class CopilotClient {
1026
1074
  }
1027
1075
  }
1028
1076
  async createSession(config) {
1077
+ if (config.gitHubToken !== void 0 && config.gitHubTokenProvider !== void 0) {
1078
+ throw new Error("gitHubToken and gitHubTokenProvider are mutually exclusive");
1079
+ }
1029
1080
  if (!this.connection) {
1030
1081
  await this.start();
1031
1082
  }
@@ -1036,6 +1087,11 @@ class CopilotClient {
1036
1087
  const callerSessionId = config.sessionId;
1037
1088
  const useServerGeneratedId = config.cloud != null && callerSessionId == null;
1038
1089
  const localSessionId = useServerGeneratedId ? void 0 : callerSessionId ?? (0, import_node_crypto.randomUUID)();
1090
+ const toolFilterOptions = this.resolveToolFilterOptions(config);
1091
+ const gitHubTokenProviderRegistrationId = this.registerGitHubTokenProvider(
1092
+ config.gitHubTokenProvider,
1093
+ localSessionId
1094
+ );
1039
1095
  const {
1040
1096
  wireProvider: bearerWireProvider,
1041
1097
  wireProviders: bearerWireProviders,
@@ -1052,7 +1108,10 @@ class CopilotClient {
1052
1108
  this.onGetTraceContext,
1053
1109
  {
1054
1110
  mcpAuthHandler: config.onMcpAuthRequest,
1055
- managedSettingsEnabled: config.enableManagedSettings === true || config.managedSettings !== void 0
1111
+ managedSettingsEnabled: config.enableManagedSettings === true || config.managedSettings !== void 0,
1112
+ onDisconnected: gitHubTokenProviderRegistrationId === void 0 ? void 0 : () => this.githubTokenProviders.delete(
1113
+ gitHubTokenProviderRegistrationId
1114
+ )
1056
1115
  }
1057
1116
  );
1058
1117
  s.registerTools(config.tools);
@@ -1090,10 +1149,16 @@ class CopilotClient {
1090
1149
  let session;
1091
1150
  let registeredId;
1092
1151
  if (localSessionId !== void 0) {
1093
- session = initializeSession(localSessionId);
1094
- registeredId = localSessionId;
1152
+ try {
1153
+ session = initializeSession(localSessionId);
1154
+ registeredId = localSessionId;
1155
+ } catch (error) {
1156
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1157
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1158
+ }
1159
+ throw error;
1160
+ }
1095
1161
  }
1096
- const toolFilterOptions = this.resolveToolFilterOptions(config);
1097
1162
  try {
1098
1163
  const response = await this.connection.sendRequest("session.create", {
1099
1164
  ...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
@@ -1178,6 +1243,7 @@ class CopilotClient {
1178
1243
  infiniteSessions: config.infiniteSessions,
1179
1244
  memory: config.memory,
1180
1245
  gitHubToken: config.gitHubToken,
1246
+ gitHubTokenProviderRegistrationId,
1181
1247
  remoteSession: config.remoteSession,
1182
1248
  cloud: config.cloud,
1183
1249
  expAssignments: config.expAssignments,
@@ -1201,6 +1267,7 @@ class CopilotClient {
1201
1267
  session = initializeSession(returnedSessionId);
1202
1268
  registeredId = returnedSessionId;
1203
1269
  }
1270
+ this.assignGitHubTokenProvider(gitHubTokenProviderRegistrationId, returnedSessionId);
1204
1271
  if (config.onMcpAuthRequest) {
1205
1272
  await this.connection.sendRequest("session.eventLog.registerInterest", {
1206
1273
  sessionId: returnedSessionId,
@@ -1210,10 +1277,14 @@ class CopilotClient {
1210
1277
  session["_workspacePath"] = workspacePath;
1211
1278
  session.setCapabilities(capabilities);
1212
1279
  await this.updateSessionOptionsForMode(session, config);
1280
+ this.commitGitHubTokenProvider(returnedSessionId, gitHubTokenProviderRegistrationId);
1213
1281
  } catch (e) {
1214
1282
  if (registeredId !== void 0) {
1215
1283
  this.sessions.delete(registeredId);
1216
1284
  }
1285
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1286
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1287
+ }
1217
1288
  throw e;
1218
1289
  }
1219
1290
  return session;
@@ -1250,6 +1321,9 @@ class CopilotClient {
1250
1321
  return this.resumeSessionInternal(sessionId, config, factories, extensionOptions);
1251
1322
  }
1252
1323
  async resumeSessionInternal(sessionId, config, factories, extensionOptions) {
1324
+ if (config.gitHubToken !== void 0 && config.gitHubTokenProvider !== void 0) {
1325
+ throw new Error("gitHubToken and gitHubTokenProvider are mutually exclusive");
1326
+ }
1253
1327
  if (!this.connection) {
1254
1328
  await this.start();
1255
1329
  }
@@ -1307,6 +1381,15 @@ class CopilotClient {
1307
1381
  this.sessions.set(sessionId, session);
1308
1382
  this.setupSessionFs(session, config);
1309
1383
  const toolFilterOptions = this.resolveToolFilterOptions(config);
1384
+ const gitHubTokenProviderRegistrationId = this.registerGitHubTokenProvider(
1385
+ config.gitHubTokenProvider,
1386
+ sessionId
1387
+ );
1388
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1389
+ session._setOnDisconnected(
1390
+ () => this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId)
1391
+ );
1392
+ }
1310
1393
  try {
1311
1394
  const response = await this.connection.sendRequest("session.resume", {
1312
1395
  ...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
@@ -1394,6 +1477,7 @@ class CopilotClient {
1394
1477
  disableResume: config.suppressResumeEvent,
1395
1478
  continuePendingWork: config.continuePendingWork,
1396
1479
  gitHubToken: config.gitHubToken,
1480
+ gitHubTokenProviderRegistrationId,
1397
1481
  remoteSession: config.remoteSession,
1398
1482
  openCanvases: config.openCanvases,
1399
1483
  expAssignments: config.expAssignments,
@@ -1423,8 +1507,12 @@ class CopilotClient {
1423
1507
  });
1424
1508
  }
1425
1509
  await this.updateSessionOptionsForMode(session, config);
1510
+ this.commitGitHubTokenProvider(sessionId, gitHubTokenProviderRegistrationId);
1426
1511
  } catch (e) {
1427
1512
  this.sessions.delete(sessionId);
1513
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1514
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1515
+ }
1428
1516
  throw e;
1429
1517
  }
1430
1518
  return session;
@@ -1613,7 +1701,9 @@ class CopilotClient {
1613
1701
  if (!success) {
1614
1702
  throw new Error(`Failed to delete session ${sessionId}: ${error || "Unknown error"}`);
1615
1703
  }
1704
+ const session = this.sessions.get(sessionId);
1616
1705
  this.sessions.delete(sessionId);
1706
+ session?._runOnDisconnected();
1617
1707
  }
1618
1708
  /**
1619
1709
  * List all available sessions.
@@ -2161,6 +2251,7 @@ stderr: ${stderrOutput}`
2161
2251
  );
2162
2252
  this.connection.onClose(() => {
2163
2253
  this.state = "disconnected";
2254
+ this.githubTokenProviders.clear();
2164
2255
  });
2165
2256
  this.connection.onError((_error) => {
2166
2257
  this.state = "disconnected";
@@ -2540,6 +2540,25 @@ function createInternalSessionRpc(connection, sessionId) {
2540
2540
  }
2541
2541
  },
2542
2542
  /** @experimental */
2543
+ factory: {
2544
+ /**
2545
+ * Internal tool-originated factory invocation.
2546
+ *
2547
+ * @param params Internal parameters for invoking a registered factory from a tool.
2548
+ *
2549
+ * @returns Complete current or terminal factory run envelope.
2550
+ */
2551
+ runFromTool: async (params) => connection.sendRequest("session.factory.runFromTool", { sessionId, ...params }),
2552
+ /**
2553
+ * Internal tool-originated factory resume.
2554
+ *
2555
+ * @param params Internal parameters for resuming a factory run from a tool.
2556
+ *
2557
+ * @returns Resolved persisted factory identity and resumed run envelope.
2558
+ */
2559
+ resumeFromTool: async (params) => connection.sendRequest("session.factory.resumeFromTool", { sessionId, ...params })
2560
+ },
2561
+ /** @experimental */
2543
2562
  model: {
2544
2563
  /**
2545
2564
  * Resolves and applies organization-managed and repository model overlays.
@@ -241,6 +241,7 @@ class CopilotSession {
241
241
  this.traceContextProvider = traceContextProvider;
242
242
  this.mcpAuthHandler = options?.mcpAuthHandler;
243
243
  this.managedSettingsEnabled = options?.managedSettingsEnabled === true;
244
+ this.onDisconnected = options?.onDisconnected;
244
245
  }
245
246
  sessionId;
246
247
  connection;
@@ -267,6 +268,7 @@ class CopilotSession {
267
268
  _capabilities = {};
268
269
  openCanvasInstances = [];
269
270
  disconnected = false;
271
+ onDisconnected;
270
272
  /** @internal Client session API handlers, populated by CopilotClient during create/resume. */
271
273
  clientSessionApis = {};
272
274
  /**
@@ -475,7 +477,7 @@ class CopilotSession {
475
477
  const unsubscribe = this.on((event) => {
476
478
  if (event.type === "assistant.message") {
477
479
  lastAssistantMessage = event;
478
- } else if (event.type === "session.idle") {
480
+ } else if (event.type === "session.idle" && event.data.mode !== "autopilot") {
479
481
  resolveOutcome({ kind: "idle" });
480
482
  } else if (event.type === "session.error") {
481
483
  const error = new Error(event.data.message);
@@ -510,7 +512,11 @@ class CopilotSession {
510
512
  }
511
513
  /** @internal */
512
514
  _markDisconnected() {
515
+ if (this.disconnected) {
516
+ return;
517
+ }
513
518
  this.disconnected = true;
519
+ this._runOnDisconnected();
514
520
  this.eventHandlers.clear();
515
521
  this.typedEventHandlers.clear();
516
522
  this.toolHandlers.clear();
@@ -530,6 +536,15 @@ class CopilotSession {
530
536
  this.factoryAbortControllers.clear();
531
537
  this.transformCallbacks?.clear();
532
538
  }
539
+ /** @internal */
540
+ _runOnDisconnected() {
541
+ this.onDisconnected?.();
542
+ this.onDisconnected = void 0;
543
+ }
544
+ /** @internal */
545
+ _setOnDisconnected(callback) {
546
+ this.onDisconnected = callback;
547
+ }
533
548
  on(eventTypeOrHandler, handler) {
534
549
  if (typeof eventTypeOrHandler === "string" && handler) {
535
550
  const eventType = eventTypeOrHandler;
package/dist/client.d.ts CHANGED
@@ -40,6 +40,7 @@ export declare class CopilotClient {
40
40
  private builtinPluginDirectories;
41
41
  private onGitHubTelemetry?;
42
42
  private clientGlobalHandlers;
43
+ private githubTokenProviders;
43
44
  /**
44
45
  * Typed server-scoped RPC methods.
45
46
  * @throws Error if the client is not connected
@@ -96,6 +97,10 @@ export declare class CopilotClient {
96
97
  private validateSessionFsConfig;
97
98
  private setupSessionFs;
98
99
  private setupClientGlobalHandlers;
100
+ private acquireGitHubToken;
101
+ private registerGitHubTokenProvider;
102
+ private assignGitHubTokenProvider;
103
+ private commitGitHubTokenProvider;
99
104
  /**
100
105
  * Starts the CLI server and establishes a connection.
101
106
  *
package/dist/client.js CHANGED
@@ -271,6 +271,7 @@ class CopilotClient {
271
271
  builtinPluginDirectories = [];
272
272
  onGitHubTelemetry;
273
273
  clientGlobalHandlers = {};
274
+ githubTokenProviders = /* @__PURE__ */ new Map();
274
275
  /**
275
276
  * Typed server-scoped RPC methods.
276
277
  * @throws Error if the client is not connected
@@ -528,8 +529,53 @@ class CopilotClient {
528
529
  }
529
530
  };
530
531
  }
532
+ handlers.gitHubToken = {
533
+ getToken: (params) => this.acquireGitHubToken(params)
534
+ };
531
535
  this.clientGlobalHandlers = handlers;
532
536
  }
537
+ async acquireGitHubToken(params) {
538
+ const registration = this.githubTokenProviders.get(params.registrationId);
539
+ if (!registration) {
540
+ throw new Error(
541
+ `No GitHub token provider registered for registration ID "${params.registrationId}"`
542
+ );
543
+ }
544
+ return await registration.provider({
545
+ host: params.host,
546
+ sessionId: params.sessionId ?? registration.sessionId,
547
+ reason: params.reason
548
+ });
549
+ }
550
+ registerGitHubTokenProvider(provider, sessionId) {
551
+ if (!provider) {
552
+ return void 0;
553
+ }
554
+ const registrationId = randomUUID();
555
+ this.githubTokenProviders.set(registrationId, { provider, sessionId, committed: false });
556
+ return registrationId;
557
+ }
558
+ assignGitHubTokenProvider(registrationId, sessionId) {
559
+ if (!registrationId) {
560
+ return;
561
+ }
562
+ const registration = this.githubTokenProviders.get(registrationId);
563
+ if (registration) {
564
+ registration.sessionId = sessionId;
565
+ }
566
+ }
567
+ commitGitHubTokenProvider(sessionId, registrationId) {
568
+ for (const [candidateId, registration2] of this.githubTokenProviders) {
569
+ if (registration2.sessionId === sessionId && registration2.committed) {
570
+ this.githubTokenProviders.delete(candidateId);
571
+ }
572
+ }
573
+ const registration = registrationId ? this.githubTokenProviders.get(registrationId) : void 0;
574
+ if (registration) {
575
+ registration.sessionId = sessionId;
576
+ registration.committed = true;
577
+ }
578
+ }
533
579
  /**
534
580
  * Starts the CLI server and establishes a connection.
535
581
  *
@@ -646,6 +692,7 @@ class CopilotClient {
646
692
  session._markDisconnected();
647
693
  }
648
694
  this.sessions.clear();
695
+ this.githubTokenProviders.clear();
649
696
  if (this.connection && (this.cliProcess || this.ffiHost) && !this.isExternalServer) {
650
697
  const runtimeShutdownStart = Date.now();
651
698
  const shutdownPromise = this.rpc.runtime.shutdown();
@@ -800,6 +847,7 @@ class CopilotClient {
800
847
  session._markDisconnected();
801
848
  }
802
849
  this.sessions.clear();
850
+ this.githubTokenProviders.clear();
803
851
  if (this.messageWriter) {
804
852
  this.messageWriter.suppressWriteErrors = true;
805
853
  }
@@ -1003,6 +1051,9 @@ class CopilotClient {
1003
1051
  }
1004
1052
  }
1005
1053
  async createSession(config) {
1054
+ if (config.gitHubToken !== void 0 && config.gitHubTokenProvider !== void 0) {
1055
+ throw new Error("gitHubToken and gitHubTokenProvider are mutually exclusive");
1056
+ }
1006
1057
  if (!this.connection) {
1007
1058
  await this.start();
1008
1059
  }
@@ -1013,6 +1064,11 @@ class CopilotClient {
1013
1064
  const callerSessionId = config.sessionId;
1014
1065
  const useServerGeneratedId = config.cloud != null && callerSessionId == null;
1015
1066
  const localSessionId = useServerGeneratedId ? void 0 : callerSessionId ?? randomUUID();
1067
+ const toolFilterOptions = this.resolveToolFilterOptions(config);
1068
+ const gitHubTokenProviderRegistrationId = this.registerGitHubTokenProvider(
1069
+ config.gitHubTokenProvider,
1070
+ localSessionId
1071
+ );
1016
1072
  const {
1017
1073
  wireProvider: bearerWireProvider,
1018
1074
  wireProviders: bearerWireProviders,
@@ -1029,7 +1085,10 @@ class CopilotClient {
1029
1085
  this.onGetTraceContext,
1030
1086
  {
1031
1087
  mcpAuthHandler: config.onMcpAuthRequest,
1032
- managedSettingsEnabled: config.enableManagedSettings === true || config.managedSettings !== void 0
1088
+ managedSettingsEnabled: config.enableManagedSettings === true || config.managedSettings !== void 0,
1089
+ onDisconnected: gitHubTokenProviderRegistrationId === void 0 ? void 0 : () => this.githubTokenProviders.delete(
1090
+ gitHubTokenProviderRegistrationId
1091
+ )
1033
1092
  }
1034
1093
  );
1035
1094
  s.registerTools(config.tools);
@@ -1067,10 +1126,16 @@ class CopilotClient {
1067
1126
  let session;
1068
1127
  let registeredId;
1069
1128
  if (localSessionId !== void 0) {
1070
- session = initializeSession(localSessionId);
1071
- registeredId = localSessionId;
1129
+ try {
1130
+ session = initializeSession(localSessionId);
1131
+ registeredId = localSessionId;
1132
+ } catch (error) {
1133
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1134
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1135
+ }
1136
+ throw error;
1137
+ }
1072
1138
  }
1073
- const toolFilterOptions = this.resolveToolFilterOptions(config);
1074
1139
  try {
1075
1140
  const response = await this.connection.sendRequest("session.create", {
1076
1141
  ...await getTraceContext(this.onGetTraceContext),
@@ -1155,6 +1220,7 @@ class CopilotClient {
1155
1220
  infiniteSessions: config.infiniteSessions,
1156
1221
  memory: config.memory,
1157
1222
  gitHubToken: config.gitHubToken,
1223
+ gitHubTokenProviderRegistrationId,
1158
1224
  remoteSession: config.remoteSession,
1159
1225
  cloud: config.cloud,
1160
1226
  expAssignments: config.expAssignments,
@@ -1178,6 +1244,7 @@ class CopilotClient {
1178
1244
  session = initializeSession(returnedSessionId);
1179
1245
  registeredId = returnedSessionId;
1180
1246
  }
1247
+ this.assignGitHubTokenProvider(gitHubTokenProviderRegistrationId, returnedSessionId);
1181
1248
  if (config.onMcpAuthRequest) {
1182
1249
  await this.connection.sendRequest("session.eventLog.registerInterest", {
1183
1250
  sessionId: returnedSessionId,
@@ -1187,10 +1254,14 @@ class CopilotClient {
1187
1254
  session["_workspacePath"] = workspacePath;
1188
1255
  session.setCapabilities(capabilities);
1189
1256
  await this.updateSessionOptionsForMode(session, config);
1257
+ this.commitGitHubTokenProvider(returnedSessionId, gitHubTokenProviderRegistrationId);
1190
1258
  } catch (e) {
1191
1259
  if (registeredId !== void 0) {
1192
1260
  this.sessions.delete(registeredId);
1193
1261
  }
1262
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1263
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1264
+ }
1194
1265
  throw e;
1195
1266
  }
1196
1267
  return session;
@@ -1227,6 +1298,9 @@ class CopilotClient {
1227
1298
  return this.resumeSessionInternal(sessionId, config, factories, extensionOptions);
1228
1299
  }
1229
1300
  async resumeSessionInternal(sessionId, config, factories, extensionOptions) {
1301
+ if (config.gitHubToken !== void 0 && config.gitHubTokenProvider !== void 0) {
1302
+ throw new Error("gitHubToken and gitHubTokenProvider are mutually exclusive");
1303
+ }
1230
1304
  if (!this.connection) {
1231
1305
  await this.start();
1232
1306
  }
@@ -1284,6 +1358,15 @@ class CopilotClient {
1284
1358
  this.sessions.set(sessionId, session);
1285
1359
  this.setupSessionFs(session, config);
1286
1360
  const toolFilterOptions = this.resolveToolFilterOptions(config);
1361
+ const gitHubTokenProviderRegistrationId = this.registerGitHubTokenProvider(
1362
+ config.gitHubTokenProvider,
1363
+ sessionId
1364
+ );
1365
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1366
+ session._setOnDisconnected(
1367
+ () => this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId)
1368
+ );
1369
+ }
1287
1370
  try {
1288
1371
  const response = await this.connection.sendRequest("session.resume", {
1289
1372
  ...await getTraceContext(this.onGetTraceContext),
@@ -1371,6 +1454,7 @@ class CopilotClient {
1371
1454
  disableResume: config.suppressResumeEvent,
1372
1455
  continuePendingWork: config.continuePendingWork,
1373
1456
  gitHubToken: config.gitHubToken,
1457
+ gitHubTokenProviderRegistrationId,
1374
1458
  remoteSession: config.remoteSession,
1375
1459
  openCanvases: config.openCanvases,
1376
1460
  expAssignments: config.expAssignments,
@@ -1400,8 +1484,12 @@ class CopilotClient {
1400
1484
  });
1401
1485
  }
1402
1486
  await this.updateSessionOptionsForMode(session, config);
1487
+ this.commitGitHubTokenProvider(sessionId, gitHubTokenProviderRegistrationId);
1403
1488
  } catch (e) {
1404
1489
  this.sessions.delete(sessionId);
1490
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1491
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1492
+ }
1405
1493
  throw e;
1406
1494
  }
1407
1495
  return session;
@@ -1590,7 +1678,9 @@ class CopilotClient {
1590
1678
  if (!success) {
1591
1679
  throw new Error(`Failed to delete session ${sessionId}: ${error || "Unknown error"}`);
1592
1680
  }
1681
+ const session = this.sessions.get(sessionId);
1593
1682
  this.sessions.delete(sessionId);
1683
+ session?._runOnDisconnected();
1594
1684
  }
1595
1685
  /**
1596
1686
  * List all available sessions.
@@ -2138,6 +2228,7 @@ stderr: ${stderrOutput}`
2138
2228
  );
2139
2229
  this.connection.onClose(() => {
2140
2230
  this.state = "disconnected";
2231
+ this.githubTokenProviders.clear();
2141
2232
  });
2142
2233
  this.connection.onError((_error) => {
2143
2234
  this.state = "disconnected";