@github/copilot-sdk 1.0.11-preview.2 → 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.
package/dist/client.js CHANGED
@@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto";
3
3
  import { existsSync } from "node:fs";
4
4
  import { createRequire } from "node:module";
5
5
  import { Socket } from "node:net";
6
- import { dirname, join } from "node:path";
6
+ import { dirname, isAbsolute, join } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import {
9
9
  createMessageConnection,
@@ -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
  }
@@ -268,6 +268,7 @@ class CopilotClient {
268
268
  /** Connection-level session filesystem config, set via constructor option. */
269
269
  sessionFsConfig = null;
270
270
  requestHandler = null;
271
+ builtinPluginDirectories = [];
271
272
  onGitHubTelemetry;
272
273
  clientGlobalHandlers = {};
273
274
  /**
@@ -396,6 +397,16 @@ class CopilotClient {
396
397
  if (options.sessionFs) {
397
398
  this.validateSessionFsConfig(options.sessionFs);
398
399
  }
400
+ if (options.builtinPluginDirectories) {
401
+ for (const path of options.builtinPluginDirectories) {
402
+ if (!isAbsolute(path)) {
403
+ throw new Error(
404
+ `builtinPluginDirectories must contain only absolute paths: ${path}`
405
+ );
406
+ }
407
+ }
408
+ this.builtinPluginDirectories = [...options.builtinPluginDirectories];
409
+ }
399
410
  if (conn.kind === "uri") {
400
411
  const { host, port } = this.parseCliUrl(conn.url);
401
412
  this.actualHost = host;
@@ -550,6 +561,16 @@ class CopilotClient {
550
561
  }
551
562
  await this.connectToServer();
552
563
  await this.verifyProtocolVersion();
564
+ if (this.builtinPluginDirectories.length > 0) {
565
+ try {
566
+ await this.connection.sendRequest("plugins.builtin.set", {
567
+ paths: this.builtinPluginDirectories
568
+ });
569
+ } catch (error) {
570
+ await this.forceStop();
571
+ throw error;
572
+ }
573
+ }
553
574
  if (this.sessionFsConfig) {
554
575
  await this.connection.sendRequest("sessionFs.setProvider", {
555
576
  initialCwd: this.sessionFsConfig.initialCwd,
@@ -1075,7 +1096,7 @@ class CopilotClient {
1075
1096
  canvasProvider: config.canvasProvider,
1076
1097
  commands: config.commands?.map((cmd) => ({
1077
1098
  name: cmd.name,
1078
- description: cmd.description
1099
+ description: cmd.description ?? ""
1079
1100
  })),
1080
1101
  systemMessage: wireSystemMessage,
1081
1102
  availableTools: toolFilterOptions.availableTools,
@@ -1198,10 +1219,10 @@ class CopilotClient {
1198
1219
  return this.resumeSessionInternal(sessionId, config);
1199
1220
  }
1200
1221
  /** @internal */
1201
- async resumeSessionForExtension(sessionId, config, factories) {
1202
- return this.resumeSessionInternal(sessionId, config, factories);
1222
+ async resumeSessionForExtension(sessionId, config, factories, extensionOptions) {
1223
+ return this.resumeSessionInternal(sessionId, config, factories, extensionOptions);
1203
1224
  }
1204
- async resumeSessionInternal(sessionId, config, factories) {
1225
+ async resumeSessionInternal(sessionId, config, factories, extensionOptions) {
1205
1226
  if (!this.connection) {
1206
1227
  await this.start();
1207
1228
  }
@@ -1298,7 +1319,7 @@ class CopilotClient {
1298
1319
  canvasProvider: config.canvasProvider,
1299
1320
  commands: config.commands?.map((cmd) => ({
1300
1321
  name: cmd.name,
1301
- description: cmd.description
1322
+ description: cmd.description ?? ""
1302
1323
  })),
1303
1324
  provider: bearerWireProvider,
1304
1325
  capi: config.capi,
@@ -1350,12 +1371,30 @@ class CopilotClient {
1350
1371
  openCanvases: config.openCanvases,
1351
1372
  expAssignments: config.expAssignments,
1352
1373
  enableManagedSettings: config.enableManagedSettings,
1353
- managedSettings: config.managedSettings
1374
+ managedSettings: config.managedSettings,
1375
+ ...extensionOptions?.requestedEnvironmentVariables ? {
1376
+ requestedEnvironmentVariables: extensionOptions.requestedEnvironmentVariables
1377
+ } : {}
1354
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
+ }
1355
1388
  const { workspacePath, capabilities, openCanvases } = response;
1356
1389
  session["_workspacePath"] = workspacePath;
1357
1390
  session.setCapabilities(capabilities);
1358
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
+ }
1359
1398
  if (config.onMcpAuthRequest) {
1360
1399
  await this.connection.sendRequest("session.eventLog.registerInterest", {
1361
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 {
package/dist/factory.d.ts CHANGED
@@ -17,12 +17,16 @@ export type JsonValue = null | boolean | number | string | JsonValue[] | {
17
17
  [key: string]: JsonValue;
18
18
  };
19
19
  /**
20
- * Conservative JSON shape language accepted for structured factory agent output.
20
+ * Conservative JSON shape language accepted by the Agent Factories surface, for
21
+ * both structured factory agent output and a factory's declared `argsSchema`.
21
22
  *
22
- * This is a best-effort structural guard used to decide whether a subagent's
23
- * structured output should be accepted or retried — **not** a full JSON Schema
23
+ * This is a best-effort structural guard — used to decide whether a subagent's
24
+ * structured output should be accepted or retried, and whether a caller's
25
+ * factory `args` match the declared shape — **not** a full JSON Schema
24
26
  * validator. Only these keywords are honored: `type`, `required`, `enum`,
25
- * `const`, recursive `properties`/`items`, and `anyOf`/`oneOf`/`allOf`.
27
+ * `const`, recursive `properties`/`items`, and `anyOf`/`oneOf`/`allOf`. A `type`
28
+ * is one of `null`, `boolean`, `integer`, `number`, `string`, `array`, or
29
+ * `object`, or a non-empty array of those (for example `["object", "null"]`).
26
30
  *
27
31
  * Everything else is **ignored, not enforced**. In particular, string
28
32
  * constraints (`pattern`, `minLength`, `maxLength`, `format`), numeric ranges