@github/copilot-sdk 1.0.14 → 1.0.15-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/session.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createSessionRpc } from "./generated/rpc.js";
2
2
  import type { ModelSwitchAutoTierResult } from "./generated/rpc.js";
3
3
  import type { OpenCanvasInstance } from "./generated/rpc.js";
4
- import type { MessageOptions, ContextTier, ReasoningEffort, ReasoningSummary, AutoTier, ModelCapabilitiesOverride, SessionCapabilities, SessionEvent, SessionEventHandler, SessionEventType, SessionUiApi, TypedSessionEventHandler } from "./types.js";
4
+ import type { MessageOptions, ResponseSchema, ContextTier, ReasoningEffort, ReasoningSummary, AutoTier, ModelCapabilitiesOverride, SessionCapabilities, SessionEvent, SessionEventHandler, SessionEventType, SessionUiApi, TypedSessionEventHandler } from "./types.js";
5
5
  import { type SessionFactoryApi } from "./factory.js";
6
6
  /** Assistant message event - the final response from the assistant. */
7
7
  export type AssistantMessageEvent = Extract<SessionEvent, {
@@ -65,6 +65,7 @@ export declare class CopilotSession {
65
65
  private _capabilities;
66
66
  private openCanvasInstances;
67
67
  private disconnected;
68
+ private readonly pendingStructuredWaits;
68
69
  private disconnecting;
69
70
  private onDisconnected?;
70
71
  /**
@@ -122,13 +123,14 @@ export declare class CopilotSession {
122
123
  */
123
124
  get ui(): SessionUiApi;
124
125
  /**
125
- * Sends a message to this session and waits for the response.
126
+ * Sends a message to this session and returns once it is admitted.
126
127
  *
127
128
  * The message is processed asynchronously. Subscribe to events via {@link on}
128
129
  * to receive streaming responses and other session events.
129
130
  *
130
131
  * @param options - The message options including the prompt and optional attachments
131
- * @returns A promise that resolves with the message ID of the response
132
+ * @returns The submitted user message's ID, not an assistant response ID.
133
+ * When this send starts a run, root assistant messages carry it as originatingMessageId.
132
134
  * @throws Error if the session has been disconnected or the connection fails
133
135
  *
134
136
  * @example
@@ -149,6 +151,9 @@ export declare class CopilotSession {
149
151
  * assistant has finished processing the message.
150
152
  *
151
153
  * Events are still delivered to handlers registered via {@link on} while waiting.
154
+ * With a schema as the second argument, returns its parsed, validated result.
155
+ * Structured waits select only root-agent output originating from this send;
156
+ * other queued work may delay session.idle but cannot replace the result.
152
157
  *
153
158
  * @param options - The message options including the prompt and optional attachments
154
159
  * @param timeout - Timeout in milliseconds (default: 60000). Controls how long to wait; does not abort in-flight agent work.
@@ -165,7 +170,9 @@ export declare class CopilotSession {
165
170
  * ```
166
171
  */
167
172
  sendAndWait(prompt: string, timeout?: number): Promise<AssistantMessageEvent | undefined>;
173
+ sendAndWait<TResult>(options: MessageOptions | string, responseSchema: ResponseSchema<TResult>, timeout?: number): Promise<TResult>;
168
174
  sendAndWait(options: MessageOptions, timeout?: number): Promise<AssistantMessageEvent | undefined>;
175
+ private sendAndWaitForStructuredMessage;
169
176
  /**
170
177
  * Subscribes to events from this session.
171
178
  *
package/dist/session.js CHANGED
@@ -3,6 +3,7 @@ import { ConnectionError, ErrorCodes, ResponseError } from "vscode-jsonrpc/node.
3
3
  import { createInternalSessionRpc, createSessionRpc } from "./generated/rpc.js";
4
4
  import { CanvasError } from "./canvas.js";
5
5
  import { getTraceContext } from "./telemetry.js";
6
+ import { isResponseSchema, toJsonSchema } from "./schema.js";
6
7
  import { isAttributedPermissionResult } from "./types.js";
7
8
  import {
8
9
  FACTORY_AGENT_OPTION_KEYS,
@@ -259,6 +260,7 @@ class CopilotSession {
259
260
  _capabilities = {};
260
261
  openCanvasInstances = [];
261
262
  disconnected = false;
263
+ pendingStructuredWaits = /* @__PURE__ */ new Set();
262
264
  disconnecting = false;
263
265
  onDisconnected;
264
266
  /** @internal Client session API handlers, populated by CopilotClient during create/resume. */
@@ -475,13 +477,54 @@ class CopilotSession {
475
477
  attachments: options.attachments,
476
478
  mode: options.mode,
477
479
  agentMode: options.agentMode,
478
- requestHeaders: options.requestHeaders
480
+ requestHeaders: options.requestHeaders,
481
+ ...options.responseSchema ? {
482
+ responseFormat: {
483
+ type: "json_schema",
484
+ jsonSchema: {
485
+ name: "response",
486
+ strict: true,
487
+ schema: toJsonSchema(options.responseSchema)
488
+ }
489
+ }
490
+ } : {}
479
491
  });
480
492
  return response.messageId;
481
493
  }
482
- async sendAndWait(optionsOrPrompt, timeout) {
494
+ async sendAndWait(optionsOrPrompt, schemaOrTimeout, timeout) {
483
495
  const options = typeof optionsOrPrompt === "string" ? { prompt: optionsOrPrompt } : optionsOrPrompt;
484
- const effectiveTimeout = timeout ?? 6e4;
496
+ const typedSchema = isResponseSchema(schemaOrTimeout) ? schemaOrTimeout : void 0;
497
+ if (schemaOrTimeout !== void 0 && typeof schemaOrTimeout !== "number" && !typedSchema) {
498
+ throw new TypeError(
499
+ "The second argument must be a timeout or a schema with toJSONSchema() and parse(). Pass raw JSON Schema in options.responseSchema instead."
500
+ );
501
+ }
502
+ const effectiveTimeout = (typeof schemaOrTimeout === "number" ? schemaOrTimeout : timeout) ?? 6e4;
503
+ if (typedSchema && options.responseSchema) {
504
+ throw new Error(
505
+ "Do not specify responseSchema in options when requesting a typed response."
506
+ );
507
+ }
508
+ if (typedSchema && options.mode === "immediate") {
509
+ throw new Error(
510
+ "Structured output cannot be requested on an immediate steering message."
511
+ );
512
+ }
513
+ if (typedSchema || options.responseSchema) {
514
+ const message = await this.sendAndWaitForStructuredMessage(
515
+ typedSchema ? { ...options, responseSchema: typedSchema } : options,
516
+ effectiveTimeout
517
+ );
518
+ if (typedSchema) {
519
+ if (!message) {
520
+ throw new Error(
521
+ "The requested run completed without a structured assistant response."
522
+ );
523
+ }
524
+ return typedSchema.parse(JSON.parse(message.data.content));
525
+ }
526
+ return message;
527
+ }
485
528
  let resolveOutcome;
486
529
  const outcomePromise = new Promise((resolve) => {
487
530
  resolveOutcome = resolve;
@@ -523,12 +566,95 @@ class CopilotSession {
523
566
  unsubscribe();
524
567
  }
525
568
  }
569
+ async sendAndWaitForStructuredMessage(options, timeout) {
570
+ if (this.disconnected) {
571
+ throw new Error("Session is disconnected");
572
+ }
573
+ let resolveOutcome;
574
+ const outcomePromise = new Promise((resolve) => {
575
+ resolveOutcome = resolve;
576
+ });
577
+ const fail = (error) => resolveOutcome({ kind: "error", error });
578
+ let messageId;
579
+ let consumed = false;
580
+ let lastMessage;
581
+ const buffered = [];
582
+ const observe = (event) => {
583
+ if (event.agentId) return;
584
+ if (event.type === "user.message" && event.data.messageId === messageId) {
585
+ consumed = true;
586
+ } else if (event.type === "assistant.message" && event.data.originatingMessageId === messageId) {
587
+ consumed = true;
588
+ lastMessage = event.data.toolRequests?.length ? void 0 : event;
589
+ } else if (consumed && event.type === "session.idle" && event.data.mode !== "autopilot") {
590
+ if (event.data.aborted) {
591
+ fail(
592
+ new Error(
593
+ "The requested run was aborted before a structured result was completed."
594
+ )
595
+ );
596
+ } else {
597
+ resolveOutcome({ kind: "idle", message: lastMessage });
598
+ }
599
+ } else if (consumed && event.type === "session.error") {
600
+ const error = new Error(event.data.message);
601
+ error.stack = event.data.stack;
602
+ fail(error);
603
+ }
604
+ };
605
+ const unsubscribe = this.on((event) => {
606
+ if (event.type !== "user.message" && event.type !== "assistant.message" && event.type !== "session.idle" && event.type !== "session.error") {
607
+ return;
608
+ }
609
+ if (messageId === void 0) {
610
+ buffered.push(event);
611
+ } else {
612
+ observe(event);
613
+ }
614
+ });
615
+ this.pendingStructuredWaits.add(fail);
616
+ const timer = setTimeout(
617
+ () => fail(new Error(`Timeout after ${timeout}ms waiting for the structured response`)),
618
+ timeout
619
+ );
620
+ try {
621
+ const sendOutcome = this.send(options).then(
622
+ (id) => {
623
+ if (!id) {
624
+ throw new Error(
625
+ "The runtime did not return a message ID for the structured send."
626
+ );
627
+ }
628
+ messageId = id;
629
+ for (const event of buffered) observe(event);
630
+ buffered.length = 0;
631
+ return outcomePromise;
632
+ },
633
+ (error) => ({
634
+ kind: "error",
635
+ error: error instanceof Error ? error : new Error(String(error))
636
+ })
637
+ );
638
+ const outcome = await Promise.race([sendOutcome, outcomePromise]);
639
+ if (outcome.kind === "error") throw outcome.error;
640
+ return outcome.message;
641
+ } finally {
642
+ clearTimeout(timer);
643
+ buffered.length = 0;
644
+ unsubscribe();
645
+ this.pendingStructuredWaits.delete(fail);
646
+ }
647
+ }
526
648
  /** @internal */
527
649
  _markDisconnected() {
528
650
  if (this.disconnected) {
529
651
  return;
530
652
  }
531
653
  this.disconnected = true;
654
+ for (const fail of this.pendingStructuredWaits) {
655
+ fail(new Error("Session disconnected while waiting for a structured response"));
656
+ }
657
+ this.pendingStructuredWaits.clear();
532
658
  for (const controller of this.pendingExternalTools.values()) {
533
659
  controller.abort();
534
660
  }
package/dist/types.d.ts CHANGED
@@ -4,14 +4,14 @@
4
4
  import type { Canvas } from "./canvas.js";
5
5
  import type { SessionFsProvider } from "./sessionFsProvider.js";
6
6
  import type { CopilotRequestHandler } from "./copilotRequestHandler.js";
7
- import type { AutoTier, PermissionRequest as GeneratedPermissionRequest, PermissionRequestedData as GeneratedPermissionRequestedData, PermissionRequestedEvent as GeneratedPermissionRequestedEvent, ReasoningSummary, SessionLimitsConfig, SessionEvent as GeneratedSessionEvent } from "./generated/session-events.js";
7
+ import type { AttachmentExtensionContext as GeneratedExtensionContextAttachment, AutoTier, PermissionRequest as GeneratedPermissionRequest, PermissionRequestedData as GeneratedPermissionRequestedData, PermissionRequestedEvent as GeneratedPermissionRequestedEvent, ReasoningSummary, SessionLimitsConfig, SessionEvent as GeneratedSessionEvent } from "./generated/session-events.js";
8
8
  import type { CopilotSession } from "./session.js";
9
9
  import type { FactoryJsonSchema, JsonValue } from "./factory.js";
10
- import type { GitHubTokenAcquireRequest, GitHubTokenAcquireResult, GitHubTelemetryNotification, ModelBillingTokenPrices, OpenCanvasInstance, RemoteSessionMode, CurrentToolMetadata } from "./generated/rpc.js";
10
+ import type { ExtensionLaunchProviderHandler as GeneratedExtensionLaunchProvider, GitHubTokenAcquireRequest, GitHubTokenAcquireResult, GitHubTelemetryNotification, ModelBillingTokenPrices, OpenCanvasInstance, RemoteSessionMode, CurrentToolMetadata } from "./generated/rpc.js";
11
11
  import type { ToolSet } from "./toolSet.js";
12
12
  export type { RemoteSessionMode } from "./generated/rpc.js";
13
13
  export type { CurrentToolMetadata } from "./generated/rpc.js";
14
- export type { GitHubTokenAcquireReason, GitHubTokenAcquireResult, GitHubTelemetryNotification, GitHubTelemetryEvent, GitHubTelemetryClientInfo, } from "./generated/rpc.js";
14
+ export type { ExtensionLaunchProfile, ExtensionLaunchProviderResolveRequest, ExtensionLaunchProviderResolveResult, GitHubTokenAcquireReason, GitHubTokenAcquireResult, GitHubTelemetryNotification, GitHubTelemetryEvent, GitHubTelemetryClientInfo, } from "./generated/rpc.js";
15
15
  /**
16
16
  * Arguments passed to a session's {@link GitHubTokenProvider}.
17
17
  *
@@ -282,6 +282,14 @@ export interface CopilotClientOptions {
282
282
  * startup before any sessions can be created.
283
283
  */
284
284
  builtinPluginDirectories?: readonly string[];
285
+ /**
286
+ * Connection-level extension launch profile provider.
287
+ * When set, the client registers the provider during startup before any
288
+ * session can be created.
289
+ *
290
+ * @experimental
291
+ */
292
+ extensionLaunchProvider?: ExtensionLaunchProvider;
285
293
  /**
286
294
  * Log level for the Copilot runtime. When omitted, the runtime uses its
287
295
  * own default (currently `"info"`).
@@ -409,6 +417,8 @@ export interface CopilotClientOptions {
409
417
  */
410
418
  clientInfo?: CopilotClientInfo;
411
419
  }
420
+ /** Resolves launch profiles for extension entrypoints discovered by the runtime. */
421
+ export type ExtensionLaunchProvider = GeneratedExtensionLaunchProvider;
412
422
  /**
413
423
  * Configuration for creating a session
414
424
  */
@@ -510,6 +520,13 @@ export interface ZodSchema<T = unknown> {
510
520
  _output: T;
511
521
  toJSONSchema(): Record<string, unknown>;
512
522
  }
523
+ /**
524
+ * A Zod-compatible output schema that both describes and parses a typed result.
525
+ * TypeScript types are erased at runtime, so typed output requires a schema value.
526
+ */
527
+ export interface ResponseSchema<T = unknown> extends ZodSchema<T> {
528
+ parse(value: unknown): T;
529
+ }
513
530
  /**
514
531
  * Tool definition. Parameters can be either:
515
532
  * - A Zod schema (provides type inference for handler)
@@ -2740,6 +2757,8 @@ export interface ProviderModelConfig {
2740
2757
  * Message provenance, independent of delivery mode.
2741
2758
  */
2742
2759
  export type MessageSource = "user" | "system" | `agent-${string}`;
2760
+ /** Structured context contributed by an extension. */
2761
+ export type ExtensionContextAttachment = GeneratedExtensionContextAttachment;
2743
2762
  export interface MessageOptions {
2744
2763
  /**
2745
2764
  * The prompt/message to send
@@ -2752,7 +2771,7 @@ export interface MessageOptions {
2752
2771
  */
2753
2772
  source?: MessageSource;
2754
2773
  /**
2755
- * File, directory, selection, or blob attachments
2774
+ * File, directory, selection, blob, or extension context attachments
2756
2775
  */
2757
2776
  attachments?: Array<{
2758
2777
  type: "file";
@@ -2782,7 +2801,7 @@ export interface MessageOptions {
2782
2801
  data: string;
2783
2802
  mimeType: string;
2784
2803
  displayName?: string;
2785
- }>;
2804
+ } | ExtensionContextAttachment>;
2786
2805
  /**
2787
2806
  * Message delivery mode
2788
2807
  * - "enqueue": Add to queue (default)
@@ -2802,6 +2821,19 @@ export interface MessageOptions {
2802
2821
  * If provided, this is shown in the timeline instead of `prompt`.
2803
2822
  */
2804
2823
  displayPrompt?: string;
2824
+ /**
2825
+ * JSON Schema or a Zod schema for this run's output, including requests after tool calls.
2826
+ * Independent sends do not inherit it. Ordinary immediate steering retains the active
2827
+ * schema and origin, even when promoted to a follow-up after the model request finishes.
2828
+ * Specifying a schema with mode "immediate" is rejected, even while idle.
2829
+ * This is not a persisted session default and does not survive a context reset.
2830
+ *
2831
+ * sendAndWait still returns an assistant message event. For a typed result, pass a
2832
+ * Zod-compatible schema as sendAndWait's second argument instead.
2833
+ * Streaming events remain text and may include intermediate messages.
2834
+ * Use rpc.send's responseFormat for provider-specific name, description and strict options.
2835
+ */
2836
+ responseSchema?: ZodSchema | Record<string, unknown>;
2805
2837
  }
2806
2838
  /**
2807
2839
  * All possible event type strings from SessionEvent
package/package.json CHANGED
@@ -4,8 +4,8 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/github/copilot-sdk.git"
6
6
  },
7
- "version": "1.0.14",
8
- "copilotCliVersion": "1.0.85",
7
+ "version": "1.0.15-preview.0",
8
+ "copilotCliVersion": "1.0.87-0",
9
9
  "description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC",
10
10
  "main": "./dist/cjs/index.js",
11
11
  "types": "./dist/index.d.ts",
@@ -37,7 +37,8 @@
37
37
  "clean": "rimraf --glob dist *.tgz",
38
38
  "build": "tsx esbuild-copilotsdk-nodejs.ts",
39
39
  "acquire:runtime-packages": "tsx scripts/runtime-package-acquisition.ts",
40
- "pack:release": "tsx scripts/package-sdk.ts",
40
+ "pack:release": "npm run verify:dependency-policy && tsx scripts/package-sdk.ts",
41
+ "verify:dependency-policy": "tsx scripts/verify-dependency-policy.ts",
41
42
  "verify:release-packages": "tsx scripts/verify-release-packages.ts",
42
43
  "release:manifest": "tsx scripts/release-manifest.ts",
43
44
  "prepare:runtime": "tsx scripts/prepare-runtime.ts",
@@ -64,13 +65,14 @@
64
65
  "author": "GitHub",
65
66
  "license": "MIT",
66
67
  "dependencies": {
67
- "koffi": "^3.2.1",
68
- "vscode-jsonrpc": "^8.2.1",
69
- "zod": "^4.3.6"
68
+ "koffi": "3.2.1",
69
+ "vscode-jsonrpc": "8.2.1",
70
+ "zod": "4.3.6"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@platformatic/vfs": "^0.3.0",
73
74
  "@types/node": "^25.2.0",
75
+ "@types/semver": "7.8.0",
74
76
  "@types/ws": "^8.18.1",
75
77
  "@typescript-eslint/eslint-plugin": "^8.54.0",
76
78
  "@typescript-eslint/parser": "^8.54.0",
@@ -98,13 +100,13 @@
98
100
  "README.md"
99
101
  ],
100
102
  "optionalDependencies": {
101
- "@github/copilot-sdk-darwin-arm64": "1.0.14",
102
- "@github/copilot-sdk-darwin-x64": "1.0.14",
103
- "@github/copilot-sdk-linux-arm64": "1.0.14",
104
- "@github/copilot-sdk-linux-x64": "1.0.14",
105
- "@github/copilot-sdk-linuxmusl-arm64": "1.0.14",
106
- "@github/copilot-sdk-linuxmusl-x64": "1.0.14",
107
- "@github/copilot-sdk-win32-arm64": "1.0.14",
108
- "@github/copilot-sdk-win32-x64": "1.0.14"
103
+ "@github/copilot-sdk-darwin-arm64": "1.0.15-preview.0",
104
+ "@github/copilot-sdk-darwin-x64": "1.0.15-preview.0",
105
+ "@github/copilot-sdk-linux-arm64": "1.0.15-preview.0",
106
+ "@github/copilot-sdk-linux-x64": "1.0.15-preview.0",
107
+ "@github/copilot-sdk-linuxmusl-arm64": "1.0.15-preview.0",
108
+ "@github/copilot-sdk-linuxmusl-x64": "1.0.15-preview.0",
109
+ "@github/copilot-sdk-win32-arm64": "1.0.15-preview.0",
110
+ "@github/copilot-sdk-win32-x64": "1.0.15-preview.0"
109
111
  }
110
112
  }