@github/copilot-sdk 1.0.13-preview.0 → 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
  }
@@ -988,7 +1036,8 @@ class CopilotClient {
988
1036
  *
989
1037
  * In empty mode, defaults the four overridable feature flags to safe values
990
1038
  * (caller values from `config` win). `installedPlugins=[]` is unconditional
991
- * in empty mode — apps that need custom plugins should switch modes.
1039
+ * in empty mode. `includedBuiltinSkills` defaults to `[]`, but callers can
1040
+ * explicitly allow selected runtime-bundled skills.
992
1041
  */
993
1042
  async updateSessionOptionsForMode(session, config) {
994
1043
  const patch = {};
@@ -998,6 +1047,7 @@ class CopilotClient {
998
1047
  patch.coauthorEnabled = config.coauthorEnabled ?? false;
999
1048
  patch.manageScheduleEnabled = config.manageScheduleEnabled ?? false;
1000
1049
  patch.installedPlugins = [];
1050
+ patch.includedBuiltinSkills = config.includedBuiltinSkills ?? [];
1001
1051
  } else {
1002
1052
  if (config.skipCustomInstructions !== void 0)
1003
1053
  patch.skipCustomInstructions = config.skipCustomInstructions;
@@ -1007,6 +1057,8 @@ class CopilotClient {
1007
1057
  patch.coauthorEnabled = config.coauthorEnabled;
1008
1058
  if (config.manageScheduleEnabled !== void 0)
1009
1059
  patch.manageScheduleEnabled = config.manageScheduleEnabled;
1060
+ if (config.includedBuiltinSkills !== void 0)
1061
+ patch.includedBuiltinSkills = config.includedBuiltinSkills;
1010
1062
  }
1011
1063
  if (Object.keys(patch).length === 0) {
1012
1064
  return;
@@ -1022,6 +1074,9 @@ class CopilotClient {
1022
1074
  }
1023
1075
  }
1024
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
+ }
1025
1080
  if (!this.connection) {
1026
1081
  await this.start();
1027
1082
  }
@@ -1032,6 +1087,11 @@ class CopilotClient {
1032
1087
  const callerSessionId = config.sessionId;
1033
1088
  const useServerGeneratedId = config.cloud != null && callerSessionId == null;
1034
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
+ );
1035
1095
  const {
1036
1096
  wireProvider: bearerWireProvider,
1037
1097
  wireProviders: bearerWireProviders,
@@ -1048,7 +1108,10 @@ class CopilotClient {
1048
1108
  this.onGetTraceContext,
1049
1109
  {
1050
1110
  mcpAuthHandler: config.onMcpAuthRequest,
1051
- 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
+ )
1052
1115
  }
1053
1116
  );
1054
1117
  s.registerTools(config.tools);
@@ -1086,10 +1149,16 @@ class CopilotClient {
1086
1149
  let session;
1087
1150
  let registeredId;
1088
1151
  if (localSessionId !== void 0) {
1089
- session = initializeSession(localSessionId);
1090
- 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
+ }
1091
1161
  }
1092
- const toolFilterOptions = this.resolveToolFilterOptions(config);
1093
1162
  try {
1094
1163
  const response = await this.connection.sendRequest("session.create", {
1095
1164
  ...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
@@ -1174,6 +1243,7 @@ class CopilotClient {
1174
1243
  infiniteSessions: config.infiniteSessions,
1175
1244
  memory: config.memory,
1176
1245
  gitHubToken: config.gitHubToken,
1246
+ gitHubTokenProviderRegistrationId,
1177
1247
  remoteSession: config.remoteSession,
1178
1248
  cloud: config.cloud,
1179
1249
  expAssignments: config.expAssignments,
@@ -1197,6 +1267,7 @@ class CopilotClient {
1197
1267
  session = initializeSession(returnedSessionId);
1198
1268
  registeredId = returnedSessionId;
1199
1269
  }
1270
+ this.assignGitHubTokenProvider(gitHubTokenProviderRegistrationId, returnedSessionId);
1200
1271
  if (config.onMcpAuthRequest) {
1201
1272
  await this.connection.sendRequest("session.eventLog.registerInterest", {
1202
1273
  sessionId: returnedSessionId,
@@ -1206,10 +1277,14 @@ class CopilotClient {
1206
1277
  session["_workspacePath"] = workspacePath;
1207
1278
  session.setCapabilities(capabilities);
1208
1279
  await this.updateSessionOptionsForMode(session, config);
1280
+ this.commitGitHubTokenProvider(returnedSessionId, gitHubTokenProviderRegistrationId);
1209
1281
  } catch (e) {
1210
1282
  if (registeredId !== void 0) {
1211
1283
  this.sessions.delete(registeredId);
1212
1284
  }
1285
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1286
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1287
+ }
1213
1288
  throw e;
1214
1289
  }
1215
1290
  return session;
@@ -1246,6 +1321,9 @@ class CopilotClient {
1246
1321
  return this.resumeSessionInternal(sessionId, config, factories, extensionOptions);
1247
1322
  }
1248
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
+ }
1249
1327
  if (!this.connection) {
1250
1328
  await this.start();
1251
1329
  }
@@ -1303,6 +1381,15 @@ class CopilotClient {
1303
1381
  this.sessions.set(sessionId, session);
1304
1382
  this.setupSessionFs(session, config);
1305
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
+ }
1306
1393
  try {
1307
1394
  const response = await this.connection.sendRequest("session.resume", {
1308
1395
  ...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
@@ -1390,6 +1477,7 @@ class CopilotClient {
1390
1477
  disableResume: config.suppressResumeEvent,
1391
1478
  continuePendingWork: config.continuePendingWork,
1392
1479
  gitHubToken: config.gitHubToken,
1480
+ gitHubTokenProviderRegistrationId,
1393
1481
  remoteSession: config.remoteSession,
1394
1482
  openCanvases: config.openCanvases,
1395
1483
  expAssignments: config.expAssignments,
@@ -1419,8 +1507,12 @@ class CopilotClient {
1419
1507
  });
1420
1508
  }
1421
1509
  await this.updateSessionOptionsForMode(session, config);
1510
+ this.commitGitHubTokenProvider(sessionId, gitHubTokenProviderRegistrationId);
1422
1511
  } catch (e) {
1423
1512
  this.sessions.delete(sessionId);
1513
+ if (gitHubTokenProviderRegistrationId !== void 0) {
1514
+ this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1515
+ }
1424
1516
  throw e;
1425
1517
  }
1426
1518
  return session;
@@ -1609,7 +1701,9 @@ class CopilotClient {
1609
1701
  if (!success) {
1610
1702
  throw new Error(`Failed to delete session ${sessionId}: ${error || "Unknown error"}`);
1611
1703
  }
1704
+ const session = this.sessions.get(sessionId);
1612
1705
  this.sessions.delete(sessionId);
1706
+ session?._runOnDisconnected();
1613
1707
  }
1614
1708
  /**
1615
1709
  * List all available sessions.
@@ -2157,6 +2251,7 @@ stderr: ${stderrOutput}`
2157
2251
  );
2158
2252
  this.connection.onClose(() => {
2159
2253
  this.state = "disconnected";
2254
+ this.githubTokenProviders.clear();
2160
2255
  });
2161
2256
  this.connection.onError((_error) => {
2162
2257
  this.state = "disconnected";
@@ -1991,7 +1991,7 @@ function createSessionRpc(connection, sessionId) {
1991
1991
  */
1992
1992
  list: async () => connection.sendRequest("session.permissions.paths.list", { sessionId }),
1993
1993
  /**
1994
- * Adds a directory to the session's allow-list.
1994
+ * Adds a directory to the session's allow-list and activates conventional skill and agent definitions under it.
1995
1995
  *
1996
1996
  * @param params Directory path to add to the session's allowed directories.
1997
1997
  *
@@ -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.
@@ -2837,6 +2856,11 @@ function registerClientGlobalApiHandlers(connection, handlers) {
2837
2856
  if (!handler) return;
2838
2857
  await handler.event(params);
2839
2858
  });
2859
+ connection.onRequest("gitHubToken.getToken", async (params) => {
2860
+ const handler = handlers.gitHubToken;
2861
+ if (!handler) throw new Error("No gitHubToken client-global handler registered");
2862
+ return handler.getToken(params);
2863
+ });
2840
2864
  }
2841
2865
  // Annotate the CommonJS export names for ESM import in node:
2842
2866
  0 && (module.exports = {
package/dist/cjs/index.js CHANGED
@@ -27,6 +27,7 @@ __export(index_exports, {
27
27
  CopilotWebSocketCloseStatus: () => import_types2.CopilotWebSocketCloseStatus,
28
28
  CopilotWebSocketForwarder: () => import_types2.CopilotWebSocketForwarder,
29
29
  CopilotWebSocketHandler: () => import_types2.CopilotWebSocketHandler,
30
+ DisableBypassPermissionsModes: () => import_types.DisableBypassPermissionsModes,
30
31
  FactoryResumeError: () => import_factory.FactoryResumeError,
31
32
  RuntimeConnection: () => import_types.RuntimeConnection,
32
33
  SYSTEM_MESSAGE_SECTIONS: () => import_types2.SYSTEM_MESSAGE_SECTIONS,
@@ -60,6 +61,7 @@ var import_types2 = require("./types.js");
60
61
  CopilotWebSocketCloseStatus,
61
62
  CopilotWebSocketForwarder,
62
63
  CopilotWebSocketHandler,
64
+ DisableBypassPermissionsModes,
63
65
  FactoryResumeError,
64
66
  RuntimeConnection,
65
67
  SYSTEM_MESSAGE_SECTIONS,
@@ -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/cjs/types.js CHANGED
@@ -22,6 +22,7 @@ __export(types_exports, {
22
22
  CopilotWebSocketCloseStatus: () => import_copilotRequestHandler.CopilotWebSocketCloseStatus,
23
23
  CopilotWebSocketForwarder: () => import_copilotRequestHandler.CopilotWebSocketForwarder,
24
24
  CopilotWebSocketHandler: () => import_copilotRequestHandler.CopilotWebSocketHandler,
25
+ DisableBypassPermissionsModes: () => DisableBypassPermissionsModes,
25
26
  RuntimeConnection: () => RuntimeConnection,
26
27
  SYSTEM_MESSAGE_SECTIONS: () => SYSTEM_MESSAGE_SECTIONS,
27
28
  SessionFsSqliteTransactionFailure: () => import_sessionFsProvider2.SessionFsSqliteTransactionFailure,
@@ -165,12 +166,19 @@ const approveAll = (request, invocation) => {
165
166
  const defaultJoinSessionPermissionHandler = () => ({
166
167
  kind: "no-result"
167
168
  });
169
+ const DisableBypassPermissionsModes = {
170
+ /** Turn off bypass-permissions mode entirely. */
171
+ Disable: "disable",
172
+ /** Permit automatic bypass but block full allow-all. */
173
+ AllowAutoOnly: "allow-auto-only"
174
+ };
168
175
  // Annotate the CommonJS export names for ESM import in node:
169
176
  0 && (module.exports = {
170
177
  CopilotRequestHandler,
171
178
  CopilotWebSocketCloseStatus,
172
179
  CopilotWebSocketForwarder,
173
180
  CopilotWebSocketHandler,
181
+ DisableBypassPermissionsModes,
174
182
  RuntimeConnection,
175
183
  SYSTEM_MESSAGE_SECTIONS,
176
184
  SessionFsSqliteTransactionFailure,
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
  *
@@ -198,7 +203,8 @@ export declare class CopilotClient {
198
203
  *
199
204
  * In empty mode, defaults the four overridable feature flags to safe values
200
205
  * (caller values from `config` win). `installedPlugins=[]` is unconditional
201
- * in empty mode — apps that need custom plugins should switch modes.
206
+ * in empty mode. `includedBuiltinSkills` defaults to `[]`, but callers can
207
+ * explicitly allow selected runtime-bundled skills.
202
208
  */
203
209
  private updateSessionOptionsForMode;
204
210
  createSession(config: SessionConfig): Promise<CopilotSession>;