@github/copilot-sdk 1.0.29-preview.8 → 1.0.29

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
@@ -64,6 +64,7 @@ By default the callback authenticates only requests made for sessions this clien
64
64
  `startAhpHost()` requires `authentication`: `github`, or direct-only `none` / `custom`
65
65
  (`requireIdentity` and a validator returning `{identity,expiresAt}` or `null`):
66
66
 
67
+ <!-- docs-validate: strict -->
67
68
  ```typescript
68
69
  import { CopilotClient } from "@github/copilot-sdk";
69
70
 
@@ -134,6 +135,7 @@ by the SDK. Published sessions remain discoverable after hosting stops.
134
135
 
135
136
  Supply `createSession` to materialize fresh AHP sessions in your application:
136
137
 
138
+ <!-- docs-validate: strict -->
137
139
  ```typescript
138
140
  import { approveAll, CopilotClient, defineTool } from "@github/copilot-sdk";
139
141
 
@@ -286,7 +288,7 @@ new CopilotClient(options?: CopilotClientOptions)
286
288
  - `RuntimeConnection.forStdio({ path?, args?, env? })` (default) — spawn the runtime and communicate over its stdin/stdout.
287
289
  - `RuntimeConnection.forTcp({ port?, connectionToken?, path?, args?, env? })` — spawn the runtime as a TCP server.
288
290
  - `RuntimeConnection.forUri(url, { connectionToken? })` — connect to an already-running runtime (mutually exclusive with `gitHubToken`/`useLoggedInUser`). There is no top-level `cliUrl` shortcut; use this factory for URL-based connections.
289
- - `RuntimeConnection.forInProcess()` — host the runtime in-process over its native C ABI (FFI). **Experimental.** Because the runtime shares this process, `env`, `telemetry`, and `workingDirectory` are rejected with this transport; set them on the host process instead.
291
+ - `RuntimeConnection.forInProcess()` — host the runtime in-process over its native C ABI (FFI). **Experimental.** Client-level `env`, `telemetry`, and `workingDirectory` are rejected; use supported typed options and configure working directories per session.
290
292
  - The child-process transports (`forStdio`/`forTcp`) also accept a per-connection `env`. Set it there or via the top-level `env` option — not both (setting both throws).
291
293
  - Managed child-process connections materialize the bundled `copilot-runtime` and adjacent `runtime.node`, then launch the wrapper by default. An explicit connection `path` or `COPILOT_CLI_PATH` overrides the bundled runtime.
292
294
  - `mode?: "empty" | "copilot-cli"` - Defaulting strategy. Use `"empty"` for multi-user server mode; defaults to `"copilot-cli"`.
@@ -421,6 +423,20 @@ Create a new conversation session.
421
423
  - `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.
422
424
  - `skillProvider?: SkillProvider` - **Experimental.** Serves skills from host storage instead of skill directories. Not persisted; pass it again on resume. See [Skill providers](#skill-providers-experimental).
423
425
 
426
+ <!-- docs-validate: strict -->
427
+ <!-- docs-validate: hidden -->
428
+ ```typescript
429
+ declare function acquireTokenForHost(host: string): Promise<string>;
430
+
431
+ const session = await client.createSession({
432
+ gitHubTokenProvider: async ({ host }) => ({
433
+ kind: "token",
434
+ accessToken: await acquireTokenForHost(host),
435
+ expiresIn: 8 * 60 * 60,
436
+ }),
437
+ });
438
+ ```
439
+ <!-- /docs-validate: hidden -->
424
440
  ```typescript
425
441
  const session = await client.createSession({
426
442
  gitHubTokenProvider: async ({ host }) => ({
@@ -495,6 +511,7 @@ Request the TUI to switch to displaying the specified session. Only available in
495
511
 
496
512
  Subscribe to a specific session lifecycle event type. Returns an unsubscribe function.
497
513
 
514
+ <!-- docs-validate: strict -->
498
515
  ```typescript
499
516
  const unsubscribe = client.onLifecycle("session.foreground", (event) => {
500
517
  console.log(`Session ${event.sessionId} is now in foreground`);
@@ -505,6 +522,7 @@ const unsubscribe = client.onLifecycle("session.foreground", (event) => {
505
522
 
506
523
  Subscribe to all session lifecycle events. Returns an unsubscribe function.
507
524
 
525
+ <!-- docs-validate: strict -->
508
526
  ```typescript
509
527
  const unsubscribe = client.onLifecycle((event) => {
510
528
  console.log(`${event.type}: ${event.sessionId}`);
@@ -552,12 +570,32 @@ Returns the message ID.
552
570
 
553
571
  Use `source: "system"` for automated messages from your application:
554
572
 
573
+ <!-- docs-validate: strict -->
574
+ <!-- docs-validate: hidden -->
575
+ ```typescript
576
+ import type { CopilotSession } from "@github/copilot-sdk";
577
+
578
+ declare const session: CopilotSession;
579
+
580
+ await session.send({ prompt: "Context updated", source: "system" });
581
+ ```
582
+ <!-- /docs-validate: hidden -->
555
583
  ```typescript
556
584
  await session.send({ prompt: "Context updated", source: "system" });
557
585
  ```
558
586
 
559
587
  For a message from another agent, use its trusted sender ID:
560
588
 
589
+ <!-- docs-validate: strict -->
590
+ <!-- docs-validate: hidden -->
591
+ ```typescript
592
+ import type { CopilotSession } from "@github/copilot-sdk";
593
+
594
+ declare const session: CopilotSession;
595
+
596
+ await session.send({ prompt: "Review complete", source: "agent-reviewer-id" });
597
+ ```
598
+ <!-- /docs-validate: hidden -->
561
599
  ```typescript
562
600
  await session.send({ prompt: "Review complete", source: "agent-reviewer-id" });
563
601
  ```
@@ -590,6 +628,23 @@ Pass a raw JSON Schema or a Zod schema as `responseSchema` to `send` or
590
628
  `sendAndWait`. As with custom tool parameters, the SDK converts Zod schemas to
591
629
  JSON Schema before sending them:
592
630
 
631
+ <!-- docs-validate: strict -->
632
+ <!-- docs-validate: hidden -->
633
+ ```typescript
634
+ import type { CopilotSession } from "@github/copilot-sdk";
635
+
636
+ declare const session: CopilotSession;
637
+
638
+ import { z } from "zod";
639
+
640
+ const answerSchema = z.object({ answer: z.number().int() });
641
+ const message = await session.sendAndWait({
642
+ prompt: "What is 19 + 23?",
643
+ responseSchema: answerSchema,
644
+ });
645
+ console.log(message?.data.content); // JSON text
646
+ ```
647
+ <!-- /docs-validate: hidden -->
593
648
  ```typescript
594
649
  import { z } from "zod";
595
650
 
@@ -603,6 +658,20 @@ console.log(message?.data.content); // JSON text
603
658
 
604
659
  For a typed result, pass the Zod schema as the **second argument** instead:
605
660
 
661
+ <!-- docs-validate: strict -->
662
+ <!-- docs-validate: hidden -->
663
+ ```typescript
664
+ import type { CopilotSession } from "@github/copilot-sdk";
665
+
666
+ declare const session: CopilotSession;
667
+ import { z } from "zod";
668
+
669
+ const answerSchema = z.object({ answer: z.number().int() });
670
+
671
+ const answer = await session.sendAndWait("What is 19 + 23?", answerSchema);
672
+ console.log(answer.answer); // number; TResult is inferred from answerSchema
673
+ ```
674
+ <!-- /docs-validate: hidden -->
606
675
  ```typescript
607
676
  const answer = await session.sendAndWait("What is 19 + 23?", answerSchema);
608
677
  console.log(answer.answer); // number; TResult is inferred from answerSchema
@@ -675,6 +744,28 @@ native `output_config.format` endpoint.
675
744
 
676
745
  Subscribe to a specific event type. The handler receives properly typed events.
677
746
 
747
+ <!-- docs-validate: strict -->
748
+ <!-- docs-validate: hidden -->
749
+ ```typescript
750
+ import type { CopilotSession } from "@github/copilot-sdk";
751
+
752
+ declare const session: CopilotSession;
753
+
754
+ // Listen for specific event types with full type inference
755
+ session.on("assistant.message", (event) => {
756
+ console.log(event.data.content); // TypeScript knows about event.data.content
757
+ });
758
+
759
+ session.on("session.idle", () => {
760
+ console.log("Session is idle");
761
+ });
762
+
763
+ // Listen to streaming events
764
+ session.on("assistant.message_delta", (event) => {
765
+ process.stdout.write(event.data.deltaContent);
766
+ });
767
+ ```
768
+ <!-- /docs-validate: hidden -->
678
769
  ```typescript
679
770
  // Listen for specific event types with full type inference
680
771
  session.on("assistant.message", (event) => {
@@ -695,6 +786,22 @@ session.on("assistant.message_delta", (event) => {
695
786
 
696
787
  Subscribe to all session events. Returns an unsubscribe function.
697
788
 
789
+ <!-- docs-validate: strict -->
790
+ <!-- docs-validate: hidden -->
791
+ ```typescript
792
+ import type { CopilotSession } from "@github/copilot-sdk";
793
+
794
+ declare const session: CopilotSession;
795
+
796
+ const unsubscribe = session.on((event) => {
797
+ // Handle any event type
798
+ console.log(event.type, event);
799
+ });
800
+
801
+ // Later...
802
+ unsubscribe();
803
+ ```
804
+ <!-- /docs-validate: hidden -->
698
805
  ```typescript
699
806
  const unsubscribe = session.on((event) => {
700
807
  // Handle any event type
@@ -722,6 +829,19 @@ The runtime does not apply the preference immediately. It records the request an
722
829
 
723
830
  Watch for the outcome through the `session.model_change` event on success or the ephemeral `session.auto_tier_switch_failed` event on failure. A failed activation leaves the incumbent effective tier unchanged. Read the authoritative state at any time with `session.rpc.model.getCurrent()`.
724
831
 
832
+ <!-- docs-validate: strict -->
833
+ <!-- docs-validate: hidden -->
834
+ ```typescript
835
+ import type { CopilotSession } from "@github/copilot-sdk";
836
+
837
+ declare const session: CopilotSession;
838
+
839
+ const result = await session.setAutoTier("intelligence");
840
+ if (result.status === "pending") {
841
+ // Accepted, but not yet in effect.
842
+ }
843
+ ```
844
+ <!-- /docs-validate: hidden -->
725
845
  ```typescript
726
846
  const result = await session.setAutoTier("intelligence");
727
847
  if (result.status === "pending") {
@@ -735,6 +855,23 @@ See [Auto tier persistence](../docs/features/session-persistence.md#auto-tier-pe
735
855
 
736
856
  Read the current model's reasoning-summary presentation policy without changing session state. Call `session.rpc.model.list()` first to load the model catalog; otherwise the result may have `ready: false`. The request and result types are exported from `@github/copilot-sdk`.
737
857
 
858
+ <!-- docs-validate: strict -->
859
+ <!-- docs-validate: hidden -->
860
+ ```typescript
861
+ import type { CopilotSession } from "@github/copilot-sdk";
862
+
863
+ declare const session: CopilotSession;
864
+
865
+ import type {
866
+ ModelGetReasoningSummariesRequest,
867
+ ModelGetReasoningSummariesResult,
868
+ } from "@github/copilot-sdk";
869
+
870
+ const presentation: ModelGetReasoningSummariesRequest = { summariesVisible: false };
871
+ const policy: ModelGetReasoningSummariesResult =
872
+ await session.rpc.model.getReasoningSummaries(presentation);
873
+ ```
874
+ <!-- /docs-validate: hidden -->
738
875
  ```typescript
739
876
  import type {
740
877
  ModelGetReasoningSummariesRequest,
@@ -754,6 +891,26 @@ Replace the tools this client supplies to the session, together with the handler
754
891
 
755
892
  Once the runtime accepts the replacement, every tool call this session dispatches uses the new handlers; calls already running finish on their original handlers. If the runtime rejects it, the promise rejects and the previous tools and handlers stay in place. Concurrent calls are applied one at a time, in call order.
756
893
 
894
+ <!-- docs-validate: strict -->
895
+ <!-- docs-validate: hidden -->
896
+ ```typescript
897
+ import type { CopilotSession } from "@github/copilot-sdk";
898
+
899
+ declare const session: CopilotSession;
900
+ import { defineTool } from "@github/copilot-sdk";
901
+ import { z } from "zod";
902
+
903
+ declare function searchIssues(query: string): Promise<string>;
904
+
905
+ await session.setTools([
906
+ defineTool("search_issues", {
907
+ description: "Search the issues shown on the current page",
908
+ parameters: z.object({ query: z.string() }),
909
+ handler: async ({ query }) => searchIssues(query),
910
+ }),
911
+ ]);
912
+ ```
913
+ <!-- /docs-validate: hidden -->
757
914
  ```typescript
758
915
  await session.setTools([
759
916
  defineTool("search_issues", {
@@ -782,6 +939,18 @@ Disconnect the session and free resources. Session data on disk is preserved for
782
939
 
783
940
  Host capabilities reported when the session was created or resumed. Use this to check feature support before calling capability-gated APIs.
784
941
 
942
+ <!-- docs-validate: strict -->
943
+ <!-- docs-validate: hidden -->
944
+ ```typescript
945
+ import type { CopilotSession } from "@github/copilot-sdk";
946
+
947
+ declare const session: CopilotSession;
948
+
949
+ if (session.capabilities.ui?.elicitation) {
950
+ const ok = await session.ui.confirm("Deploy?");
951
+ }
952
+ ```
953
+ <!-- /docs-validate: hidden -->
785
954
  ```typescript
786
955
  if (session.capabilities.ui?.elicitation) {
787
956
  const ok = await session.ui.confirm("Deploy?");
@@ -1427,7 +1596,7 @@ console.log(session.workspacePath);
1427
1596
  // => ~/.copilot/session-state/{sessionId}/
1428
1597
 
1429
1598
  // Custom thresholds
1430
- const session = await client.createSession({
1599
+ const tuned = await client.createSession({
1431
1600
  model: "gpt-5",
1432
1601
  infiniteSessions: {
1433
1602
  enabled: true,
@@ -1437,7 +1606,7 @@ const session = await client.createSession({
1437
1606
  });
1438
1607
 
1439
1608
  // Disable infinite sessions
1440
- const session = await client.createSession({
1609
+ const disabled = await client.createSession({
1441
1610
  model: "gpt-5",
1442
1611
  infiniteSessions: { enabled: false },
1443
1612
  });
@@ -1475,13 +1644,13 @@ const disabled = await client.createSession({
1475
1644
  <!-- /docs-validate: hidden -->
1476
1645
  ```typescript
1477
1646
  // Enable memory for a session
1478
- const session = await client.createSession({
1647
+ const enabled = await client.createSession({
1479
1648
  model: "gpt-5",
1480
1649
  memory: { enabled: true },
1481
1650
  });
1482
1651
 
1483
1652
  // Disable memory for a session
1484
- const session = await client.createSession({
1653
+ const disabled = await client.createSession({
1485
1654
  model: "gpt-5",
1486
1655
  memory: { enabled: false },
1487
1656
  });
@@ -22,7 +22,7 @@ __export(cliVersion_exports, {
22
22
  COPILOT_CLI_VERSION: () => COPILOT_CLI_VERSION
23
23
  });
24
24
  module.exports = __toCommonJS(cliVersion_exports);
25
- const COPILOT_CLI_VERSION = "1.0.106-9";
25
+ const COPILOT_CLI_VERSION = "1.0.107";
26
26
  const COPILOT_CLI_USE_NPM_PACKAGE = false;
27
27
  // Annotate the CommonJS export names for ESM import in node:
28
28
  0 && (module.exports = {
@@ -301,6 +301,10 @@ function getNodeExecPath() {
301
301
  function getBundledRuntimePath() {
302
302
  return (0, import_runtimeArtifacts.ensureRuntimeBundle)(import_cliVersion.COPILOT_CLI_VERSION);
303
303
  }
304
+ async function getSpawnableBundledRuntimePath() {
305
+ const runtimePath = await getBundledRuntimePath();
306
+ return process.platform === "win32" ? import_node_path.win32.toNamespacedPath(runtimePath) : runtimePath;
307
+ }
304
308
  class TeardownResilientStreamMessageWriter extends import_node.StreamMessageWriter {
305
309
  suppressWriteErrors = false;
306
310
  constructor(writable) {
@@ -466,19 +470,22 @@ class CopilotClient {
466
470
  */
467
471
  constructor(options = {}) {
468
472
  const conn = options._internalConnection ?? options.connection ?? CopilotClient.resolveDefaultConnection();
473
+ if ((conn.kind === "uri" || conn.kind === "parent-process") && options.internalTestOptions !== void 0) {
474
+ throw new Error("internalTestOptions requires a runtime owned by this client");
475
+ }
469
476
  if (conn.kind === "uri" && (options.gitHubToken !== void 0 || options.useLoggedInUser !== void 0)) {
470
477
  throw new Error(
471
478
  "gitHubToken and useLoggedInUser cannot be used with RuntimeConnection.forUri (external server manages its own auth)"
472
479
  );
473
480
  }
474
- if (conn.kind === "inprocess" && options.workingDirectory !== void 0) {
481
+ if (conn.kind === "inprocess" && options.env !== void 0) {
475
482
  throw new Error(
476
- "workingDirectory is not supported with RuntimeConnection.forInProcess(): the in-process transport hosts the runtime in this process, so honoring it would require mutating the shared process-global cwd. Change the host process's working directory before constructing the client instead."
483
+ "env is not supported with RuntimeConnection.forInProcess(): environment variables belong to the shared host process. Use typed client/session options or a child-process transport."
477
484
  );
478
485
  }
479
- if (conn.kind === "inprocess" && options.env !== void 0) {
486
+ if (conn.kind === "inprocess" && options.workingDirectory !== void 0) {
480
487
  throw new Error(
481
- "env is not supported with RuntimeConnection.forInProcess(): the in-process transport loads the native runtime into the shared host process, whose single environment block cannot carry per-client values. Set the variables on the host process environment instead."
488
+ "workingDirectory is not supported with RuntimeConnection.forInProcess(): the in-process transport hosts the runtime in this process, so honoring it would require mutating the shared process-global cwd. Set SessionConfig.workingDirectory instead."
482
489
  );
483
490
  }
484
491
  if (conn.kind === "inprocess" && options.telemetry !== void 0) {
@@ -544,6 +551,7 @@ class CopilotClient {
544
551
  const connArgs = conn.kind === "stdio" || conn.kind === "tcp" ? conn.args ?? [] : [];
545
552
  this.connectionExtraArgs = [...connArgs];
546
553
  this.options = {
554
+ internalTestOptions: options.internalTestOptions,
547
555
  entra: options.entra ? { ...options.entra, tokenProvider: options.entra.tokenProvider } : void 0,
548
556
  workingDirectory: options.workingDirectory ?? process.cwd(),
549
557
  logLevel: options.logLevel,
@@ -1164,7 +1172,7 @@ class CopilotClient {
1164
1172
  * // Session with model and tools
1165
1173
  * const session = await client.createSession({
1166
1174
  * onPermissionRequest: approveAll,
1167
- * model: "gpt-4",
1175
+ * model: "gpt-5.4",
1168
1176
  * tools: [{
1169
1177
  * name: "get_weather",
1170
1178
  * description: "Get weather for a location",
@@ -2429,15 +2437,40 @@ class CopilotClient {
2429
2437
  };
2430
2438
  }
2431
2439
  /**
2432
- * Builds the environment for the spawned runtime child process (stdio/TCP): applies
2433
- * the auth token, connection token, `COPILOT_HOME`, keychain setting, and telemetry
2434
- * variables on top of the effective env. Not used by the in-process (FFI) transport,
2435
- * whose worker inherits the host process's ambient environment
2436
- * (see {@link CopilotClient.startInProcessFfi}).
2440
+ * Builds runtime configuration for child processes and the per-host FFI snapshot.
2441
+ * Typed auth, home, keychain, and telemetry options override the effective env.
2437
2442
  */
2438
2443
  buildRuntimeEnv() {
2439
- const env = { ...this.resolvedEnv };
2444
+ const env = process.platform === "win32" ? Object.fromEntries(
2445
+ Object.entries(this.resolvedEnv).map(([key, value]) => [
2446
+ key.toUpperCase(),
2447
+ value
2448
+ ])
2449
+ ) : { ...this.resolvedEnv };
2440
2450
  delete env.NODE_DEBUG;
2451
+ const test = this.options.internalTestOptions;
2452
+ if (test) {
2453
+ const overrides = {
2454
+ COPILOT_API_URL: test.copilotApiUrl,
2455
+ COPILOT_DEBUG_GITHUB_API_URL: test.githubApiUrl,
2456
+ HTTP_PROXY: test.proxyUrl,
2457
+ HTTPS_PROXY: test.proxyUrl,
2458
+ http_proxy: test.proxyUrl,
2459
+ https_proxy: test.proxyUrl,
2460
+ NO_PROXY: test.noProxy,
2461
+ no_proxy: test.noProxy,
2462
+ NODE_EXTRA_CA_CERTS: test.caCertificatePath,
2463
+ SSL_CERT_FILE: test.caCertificatePath,
2464
+ REQUESTS_CA_BUNDLE: test.caCertificatePath,
2465
+ CURL_CA_BUNDLE: test.caCertificatePath,
2466
+ GIT_SSL_CAINFO: test.caCertificatePath
2467
+ };
2468
+ for (const [key, value] of Object.entries(overrides)) {
2469
+ if (value !== void 0) {
2470
+ env[process.platform === "win32" ? key.toUpperCase() : key] = value;
2471
+ }
2472
+ }
2473
+ }
2441
2474
  if (this.options.gitHubToken) {
2442
2475
  env.COPILOT_SDK_AUTH_TOKEN = this.options.gitHubToken;
2443
2476
  }
@@ -2446,6 +2479,9 @@ class CopilotClient {
2446
2479
  }
2447
2480
  if (this.options.baseDirectory) {
2448
2481
  env.COPILOT_HOME = this.options.baseDirectory;
2482
+ if (this.connectionConfig.kind === "inprocess") {
2483
+ env.COPILOT_CACHE_HOME = (0, import_node_path.join)(this.options.baseDirectory, "cache");
2484
+ }
2449
2485
  }
2450
2486
  if (this.options.mode === "empty") {
2451
2487
  env.COPILOT_DISABLE_KEYTAR = "1";
@@ -2472,7 +2508,7 @@ class CopilotClient {
2472
2508
  * Start the CLI server process
2473
2509
  */
2474
2510
  async startCLIServer() {
2475
- this.resolvedCliPath ??= await getBundledRuntimePath();
2511
+ this.resolvedCliPath ??= await getSpawnableBundledRuntimePath();
2476
2512
  return new Promise((resolve2, reject) => {
2477
2513
  this.stderrBuffer = "";
2478
2514
  const args = [...this.connectionExtraArgs, "--headless", "--no-auto-update"];
@@ -2510,6 +2546,22 @@ class CopilotClient {
2510
2546
  `Copilot CLI not found at ${this.resolvedCliPath}. Set COPILOT_CLI_PATH to use a custom installation.`
2511
2547
  );
2512
2548
  }
2549
+ const workingDirectory = this.options.workingDirectory;
2550
+ let workingDirectoryProblem;
2551
+ try {
2552
+ workingDirectoryProblem = (0, import_node_fs.statSync)(workingDirectory).isDirectory() ? void 0 : "does not exist or is not a directory";
2553
+ if (!workingDirectoryProblem) {
2554
+ (0, import_node_fs.accessSync)(workingDirectory, import_node_fs.constants.X_OK);
2555
+ }
2556
+ } catch (error) {
2557
+ const code = error.code;
2558
+ workingDirectoryProblem = code === "ENOENT" || code === "ENOTDIR" ? "does not exist or is not a directory" : `cannot be entered: ${error instanceof Error ? error.message : String(error)}`;
2559
+ }
2560
+ if (workingDirectoryProblem) {
2561
+ throw new Error(
2562
+ `Working directory ${workingDirectory} ${workingDirectoryProblem}.`
2563
+ );
2564
+ }
2513
2565
  const stdioConfig = this.connectionConfig.kind === "stdio" ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
2514
2566
  const isJsFile = this.resolvedCliPath.endsWith(".js");
2515
2567
  if (isJsFile) {
@@ -2661,16 +2713,7 @@ stderr: ${this.stderrBuffer.trim().slice(-8192) || "(empty)"}`
2661
2713
  runtimeLibrary = (0, import_node_path.join)((0, import_node_path.dirname)(bundledRuntimePath), "runtime.node");
2662
2714
  }
2663
2715
  const { FfiRuntimeHost } = await import("./ffiRuntimeHost.js");
2664
- const environment = {};
2665
- if (this.options.gitHubToken) {
2666
- environment.COPILOT_SDK_AUTH_TOKEN = this.options.gitHubToken;
2667
- }
2668
- if (this.options.baseDirectory) {
2669
- environment.COPILOT_HOME = this.options.baseDirectory;
2670
- }
2671
- if (this.options.mode === "empty") {
2672
- environment.COPILOT_DISABLE_KEYTAR = "1";
2673
- }
2716
+ const environment = this.buildRuntimeEnv();
2674
2717
  const args = [];
2675
2718
  if (this.options.logLevel) {
2676
2719
  args.push("--log-level", this.options.logLevel);
@@ -2628,7 +2628,7 @@ function createSessionRpc(connection, sessionId) {
2628
2628
  /** @experimental */
2629
2629
  login: {
2630
2630
  /**
2631
- * Begin an interactive login flow for a provider kind (dispatch is kind-only) and return its opaque flow id and first step.
2631
+ * Begin an interactive login flow for a provider kind, optionally selecting how to authorize (`method`: `web` by default, or `device-code`), and return its opaque flow id and first step.
2632
2632
  *
2633
2633
  * @param params Begin an interactive login flow for a provider kind, optionally reusing a cached base identity or explicitly requesting provider account selection.
2634
2634
  *
@@ -2640,7 +2640,7 @@ function createSessionRpc(connection, sessionId) {
2640
2640
  *
2641
2641
  * @param params Advance an in-flight login flow, optionally fulfilling an input-required step.
2642
2642
  *
2643
- * @returns One step in an interactive login flow. The consumer acts on the step and calls advance to proceed. Browser-open is encoded as two distinct steps by design: `open-url` is CONSUMER-driven (the provider surfaces the authorize URL and the consumer opens it — github.com/GHEC web), while `needs-interaction` is PROVIDER-driven (the provider opens the browser or broker UI itself and does not surface a URL — Entra).
2643
+ * @returns One step in an interactive login flow. The consumer acts on the step and calls advance to proceed. Browser-open is encoded as two distinct steps by design: `open-url` is CONSUMER-driven (the provider surfaces the authorize URL and the consumer opens it — github.com/GHEC web), while `needs-interaction` is PROVIDER-driven (the provider opens the browser or broker UI itself and does not surface a URL — Entra). A device-code flow surfaces its one-time code as `device-code`; the consumer shows the code, may open the verification URI, and calls advance, which resolves once the user has authorized the device.
2644
2644
  */
2645
2645
  advance: async (params) => connection.sendRequest("session.accounts.login.advance", { ...params, sessionId }),
2646
2646
  /**
@@ -4500,6 +4500,12 @@ function createSessionRpc(connection, sessionId) {
4500
4500
  * @returns Indicates whether an in-progress background compaction was cancelled.
4501
4501
  */
4502
4502
  cancelBackgroundCompaction: async () => connection.sendRequest("session.history.cancelBackgroundCompaction", { sessionId }),
4503
+ /**
4504
+ * Replaces this local session's compaction settings: the model, prompt and reasoning effort its automatic and manual compactions use. Each call replaces all three: an omitted field returns to its default. Settings are held in memory only, so re-apply them after resuming the session in a new process. A change applies to compactions that start afterwards, except that automatic compactions keep the model the running turn already chose for them until that turn ends; a compaction already in progress may still pick up a new reasoning effort. Rejects on a remote session.
4505
+ *
4506
+ * @param params Compaction settings for this session. Each call replaces the previous settings: an omitted field returns to its default. Settings live in memory until the session ends; re-apply them after resuming a session in a new process.
4507
+ */
4508
+ setCompactionConfig: async (params) => connection.sendRequest("session.history.setCompactionConfig", { ...params, sessionId }),
4503
4509
  /**
4504
4510
  * Aborts any in-progress manual compaction on a local session.
4505
4511
  *
@@ -4837,6 +4843,15 @@ function createInternalSessionRpc(connection, sessionId) {
4837
4843
  }
4838
4844
  },
4839
4845
  /** @experimental */
4846
+ canvasSource: {
4847
+ /**
4848
+ * Closes a canvas through its original session source. Requires the privately admitted in-process CLI host.
4849
+ *
4850
+ * @param params Closes a canvas through its original owned or attached session namespace.
4851
+ */
4852
+ close: async (params) => connection.sendRequest("session.canvasSource.close", { ...params, sessionId })
4853
+ },
4854
+ /** @experimental */
4840
4855
  workflow: {
4841
4856
  /**
4842
4857
  * Internal tool-originated dynamic workflow invocation.
@@ -1177,6 +1177,13 @@ class CopilotSession {
1177
1177
  } else if (typeof rawResult === "string") {
1178
1178
  result = rawResult;
1179
1179
  } else if (isToolResultObject(rawResult)) {
1180
+ try {
1181
+ JSON.stringify(rawResult.toolTelemetry);
1182
+ } catch (error) {
1183
+ const message = error instanceof Error ? error.message : String(error);
1184
+ throw new Error(`failed to serialize tool telemetry: ${message}`);
1185
+ }
1186
+ JSON.stringify(rawResult);
1180
1187
  result = rawResult;
1181
1188
  } else {
1182
1189
  result = JSON.stringify(rawResult);
@@ -1189,7 +1196,10 @@ class CopilotSession {
1189
1196
  if (!this._claimExternalTool(requestId, controller)) {
1190
1197
  return;
1191
1198
  }
1192
- const message = error instanceof Error ? error.message : String(error);
1199
+ let message = error instanceof Error ? error.message : String(error);
1200
+ if (!message) {
1201
+ message = error instanceof Error && error.name || "Error";
1202
+ }
1193
1203
  try {
1194
1204
  await this.rpc.tools.handlePendingToolCall({ requestId, error: message });
1195
1205
  } catch (rpcError) {
package/dist/cjs/types.js CHANGED
@@ -71,11 +71,9 @@ const RuntimeConnection = {
71
71
  /**
72
72
  * Host the runtime in-process over the native runtime library's C ABI (FFI).
73
73
  *
74
- * @experimental Per-client options lowered to environment variables (`env`,
75
- * `telemetry`, `gitHubToken`, `baseDirectory`) are **not** honored in-process;
76
- * the worker inherits the host process's ambient environment. Set the
77
- * corresponding environment variables on the host process instead. See
78
- * https://github.com/github/copilot-sdk/issues/1934.
74
+ * @experimental Runtime configuration from `gitHubToken` and
75
+ * `baseDirectory` is scoped to this host, not the process environment.
76
+ * Client-level `env`, `telemetry` and `workingDirectory` are unsupported.
79
77
  */
80
78
  forInProcess(options = {}) {
81
79
  return { kind: "inprocess", ...options };
@@ -1,2 +1,2 @@
1
- export declare const COPILOT_CLI_VERSION = "1.0.106-9";
1
+ export declare const COPILOT_CLI_VERSION = "1.0.107";
2
2
  export declare const COPILOT_CLI_USE_NPM_PACKAGE = false;
@@ -1,4 +1,4 @@
1
- const COPILOT_CLI_VERSION = "1.0.106-9";
1
+ const COPILOT_CLI_VERSION = "1.0.107";
2
2
  const COPILOT_CLI_USE_NPM_PACKAGE = false;
3
3
  export {
4
4
  COPILOT_CLI_USE_NPM_PACKAGE,
package/dist/client.d.ts CHANGED
@@ -474,11 +474,8 @@ export declare class CopilotClient {
474
474
  */
475
475
  onLifecycle(handler: SessionLifecycleHandler): () => void;
476
476
  /**
477
- * Builds the environment for the spawned runtime child process (stdio/TCP): applies
478
- * the auth token, connection token, `COPILOT_HOME`, keychain setting, and telemetry
479
- * variables on top of the effective env. Not used by the in-process (FFI) transport,
480
- * whose worker inherits the host process's ambient environment
481
- * (see {@link CopilotClient.startInProcessFfi}).
477
+ * Builds runtime configuration for child processes and the per-host FFI snapshot.
478
+ * Typed auth, home, keychain, and telemetry options override the effective env.
482
479
  */
483
480
  private buildRuntimeEnv;
484
481
  /**