@github/copilot-sdk 1.0.14 → 1.0.15-unstable.35393089353.gfc44743

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
@@ -305,6 +305,87 @@ Send a message and wait until the session becomes idle.
305
305
 
306
306
  Returns the final assistant message event, or undefined if none was received.
307
307
 
308
+ ##### Structured output (preview)
309
+
310
+ Requires a runtime build with `responseFormat` and `originatingMessageId` support.
311
+ Pass a raw JSON Schema or a Zod schema as `responseSchema` to `send` or
312
+ `sendAndWait`. As with custom tool parameters, the SDK converts Zod schemas to
313
+ JSON Schema before sending them:
314
+
315
+ ```typescript
316
+ import { z } from "zod";
317
+
318
+ const answerSchema = z.object({ answer: z.number().int() });
319
+ const message = await session.sendAndWait({
320
+ prompt: "What is 19 + 23?",
321
+ responseSchema: answerSchema,
322
+ });
323
+ console.log(message?.data.content); // JSON text
324
+ ```
325
+
326
+ For a typed result, pass the Zod schema as the **second argument** instead:
327
+
328
+ ```typescript
329
+ const answer = await session.sendAndWait("What is 19 + 23?", answerSchema);
330
+ console.log(answer.answer); // number; TResult is inferred from answerSchema
331
+ ```
332
+
333
+ `sendAndWait<TResult>(options, schema, timeout?)` generates the JSON Schema from
334
+ the schema value, parses the final JSON, and validates it with the schema's
335
+ `parse` method. TypeScript cannot derive a runtime schema from an erased type
336
+ parameter alone. Invalid JSON, a schema mismatch, or a completed run without a
337
+ matching assistant message throws. Do not also set `options.responseSchema` when
338
+ using the typed overload.
339
+
340
+ The schema belongs to the submitted run, including its tool-call iterations.
341
+ Internally generated stop-hook corrections retain the schema and originating
342
+ message ID, so the wait returns the corrected answer. Independent subsequent
343
+ sends do not inherit it. Ordinary immediate steering inherits the active schema
344
+ and originating message ID, even when it arrives too late for the current model
345
+ request and is promoted into a follow-up run. Specifying a schema with
346
+ `mode: "immediate"` is rejected, even while idle.
347
+ The generated `session.rpc.send` and `session.rpc.sendMessages` wrappers expose
348
+ the full `responseFormat` contract when you need to set its name, description,
349
+ or strict option rather than using the convenience defaults (`name: "response"`,
350
+ `strict: true`).
351
+ Each batch starts one run: the final returned message ID is its origin, preceding
352
+ messages are context, and an empty batch has no origin. An immediate batch
353
+ steers the active run instead and retains its origin.
354
+ The schema is not a persisted session default: autonomous resume-pending work
355
+ after a restart does not restore it. A terminal tool that clears context ends
356
+ the old run; its fresh seed does not inherit the schema or origin. Such a run
357
+ can finish without a structured result, in which case the typed wait throws.
358
+ After a successful terminal tool, the runtime disables tools while the model
359
+ produces the structured result. Stop-hook corrections remain supported.
360
+ Remote sessions and known HydraFusion routes reject response formats before
361
+ admission. Schemas larger than 32 MiB when JSON-encoded are also rejected before
362
+ admission, using the runtime's existing request-size ceiling. This does not
363
+ guarantee the schema plus conversation and tools fits the provider's budget.
364
+
365
+ Structured waits select the last root-agent message whose `originatingMessageId`
366
+ matches the ID returned by their send, then return at a non-autopilot
367
+ `session.idle`. Other queued work can delay that idle, but cannot replace the
368
+ selected result. The existing unformatted overload retains its session-wide
369
+ behavior. `turnId` identifies an individual model/tool iteration, not the whole
370
+ run; telemetry interaction IDs are not unique run identifiers.
371
+
372
+ For event-driven consumption with `send`, subscribe before sending and collect
373
+ root `assistant.message` events whose `data.originatingMessageId` matches the ID
374
+ returned by `send`; events may arrive before that acknowledgement. Wait for
375
+ `session.idle`, then parse the last matching message without tool requests.
376
+ An earlier response may be superseded by a stop-hook correction. Handle
377
+ `session.error` and aborted idle events rather than returning a partial result.
378
+
379
+ Streaming still delivers ordinary text events, including intermediate messages
380
+ and tool calls. Only the final selected message is parsed by the typed overload;
381
+ not every event is necessarily a complete schema-conforming JSON document.
382
+ Provider errors, refusals, cancellation, truncation, session errors, and timeouts
383
+ can prevent a typed result. A timeout stops waiting, not the runtime's work.
384
+ Use a model and endpoint that support native structured output. An API-compatible
385
+ gateway may ignore format fields even when it accepts the request; for example,
386
+ the Claude Chat-completions compatibility route is not equivalent to Anthropic's
387
+ native `output_config.format` endpoint.
388
+
308
389
  ##### `on(eventType: string, handler: TypedSessionEventHandler): () => void`
309
390
 
310
391
  Subscribe to a specific event type. The handler receives properly typed events.
@@ -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.85";
25
+ const COPILOT_CLI_VERSION = "1.0.85-unstable.r35379093703.g3514c9a";
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 = {
@@ -45,13 +45,11 @@ var import_cliVersion = require("./cliVersion.js");
45
45
  var import_sessionFsProvider = require("./sessionFsProvider.js");
46
46
  var import_copilotRequestHandler = require("./copilotRequestHandler.js");
47
47
  var import_telemetry = require("./telemetry.js");
48
+ var import_schema = require("./schema.js");
48
49
  var import_toolSet = require("./toolSet.js");
49
50
  var import_types = require("./types.js");
50
51
  const MIN_PROTOCOL_VERSION = 3;
51
52
  const RUNTIME_SHUTDOWN_TIMEOUT_MS = 1e4;
52
- function isZodSchema(value) {
53
- return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
54
- }
55
53
  async function withTimeout(promise, timeoutMs, message) {
56
54
  let timeout;
57
55
  try {
@@ -96,13 +94,6 @@ async function waitForChildExit(child, timeoutMs) {
96
94
  }
97
95
  });
98
96
  }
99
- function toJsonSchema(parameters) {
100
- if (!parameters) return void 0;
101
- if (isZodSchema(parameters)) {
102
- return parameters.toJSONSchema();
103
- }
104
- return parameters;
105
- }
106
97
  const DEFAULT_PROVIDER_NAME = "default";
107
98
  function extractBearerTokenProviders(provider, providers) {
108
99
  const callbacks = /* @__PURE__ */ new Map();
@@ -1188,7 +1179,7 @@ class CopilotClient {
1188
1179
  tools: config.tools?.map((tool) => ({
1189
1180
  name: tool.name,
1190
1181
  description: tool.description,
1191
- parameters: toJsonSchema(tool.parameters),
1182
+ parameters: (0, import_schema.toJsonSchema)(tool.parameters),
1192
1183
  overridesBuiltInTool: tool.overridesBuiltInTool,
1193
1184
  skipPermission: tool.skipPermission,
1194
1185
  defer: tool.defer,
@@ -1432,7 +1423,7 @@ class CopilotClient {
1432
1423
  tools: config.tools?.map((tool) => ({
1433
1424
  name: tool.name,
1434
1425
  description: tool.description,
1435
- parameters: toJsonSchema(tool.parameters),
1426
+ parameters: (0, import_schema.toJsonSchema)(tool.parameters),
1436
1427
  overridesBuiltInTool: tool.overridesBuiltInTool,
1437
1428
  skipPermission: tool.skipPermission,
1438
1429
  defer: tool.defer,
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var schema_exports = {};
20
+ __export(schema_exports, {
21
+ isResponseSchema: () => isResponseSchema,
22
+ isZodSchema: () => isZodSchema,
23
+ toJsonSchema: () => toJsonSchema
24
+ });
25
+ module.exports = __toCommonJS(schema_exports);
26
+ function isZodSchema(value) {
27
+ return typeof value === "object" && value !== null && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
28
+ }
29
+ function toJsonSchema(schema) {
30
+ return isZodSchema(schema) ? schema.toJSONSchema() : schema;
31
+ }
32
+ function isResponseSchema(value) {
33
+ return isZodSchema(value) && "parse" in value && typeof value.parse === "function";
34
+ }
35
+ // Annotate the CommonJS export names for ESM import in node:
36
+ 0 && (module.exports = {
37
+ isResponseSchema,
38
+ isZodSchema,
39
+ toJsonSchema
40
+ });
@@ -26,6 +26,7 @@ var import_node = require("vscode-jsonrpc/node.js");
26
26
  var import_rpc = require("./generated/rpc.js");
27
27
  var import_canvas = require("./canvas.js");
28
28
  var import_telemetry = require("./telemetry.js");
29
+ var import_schema = require("./schema.js");
29
30
  var import_types = require("./types.js");
30
31
  var import_factory = require("./factory.js");
31
32
  function isFactoryResumeErrorCode(value) {
@@ -277,6 +278,7 @@ class CopilotSession {
277
278
  _capabilities = {};
278
279
  openCanvasInstances = [];
279
280
  disconnected = false;
281
+ pendingStructuredWaits = /* @__PURE__ */ new Set();
280
282
  disconnecting = false;
281
283
  onDisconnected;
282
284
  /** @internal Client session API handlers, populated by CopilotClient during create/resume. */
@@ -493,13 +495,54 @@ class CopilotSession {
493
495
  attachments: options.attachments,
494
496
  mode: options.mode,
495
497
  agentMode: options.agentMode,
496
- requestHeaders: options.requestHeaders
498
+ requestHeaders: options.requestHeaders,
499
+ ...options.responseSchema ? {
500
+ responseFormat: {
501
+ type: "json_schema",
502
+ jsonSchema: {
503
+ name: "response",
504
+ strict: true,
505
+ schema: (0, import_schema.toJsonSchema)(options.responseSchema)
506
+ }
507
+ }
508
+ } : {}
497
509
  });
498
510
  return response.messageId;
499
511
  }
500
- async sendAndWait(optionsOrPrompt, timeout) {
512
+ async sendAndWait(optionsOrPrompt, schemaOrTimeout, timeout) {
501
513
  const options = typeof optionsOrPrompt === "string" ? { prompt: optionsOrPrompt } : optionsOrPrompt;
502
- const effectiveTimeout = timeout ?? 6e4;
514
+ const typedSchema = (0, import_schema.isResponseSchema)(schemaOrTimeout) ? schemaOrTimeout : void 0;
515
+ if (schemaOrTimeout !== void 0 && typeof schemaOrTimeout !== "number" && !typedSchema) {
516
+ throw new TypeError(
517
+ "The second argument must be a timeout or a schema with toJSONSchema() and parse(). Pass raw JSON Schema in options.responseSchema instead."
518
+ );
519
+ }
520
+ const effectiveTimeout = (typeof schemaOrTimeout === "number" ? schemaOrTimeout : timeout) ?? 6e4;
521
+ if (typedSchema && options.responseSchema) {
522
+ throw new Error(
523
+ "Do not specify responseSchema in options when requesting a typed response."
524
+ );
525
+ }
526
+ if (typedSchema && options.mode === "immediate") {
527
+ throw new Error(
528
+ "Structured output cannot be requested on an immediate steering message."
529
+ );
530
+ }
531
+ if (typedSchema || options.responseSchema) {
532
+ const message = await this.sendAndWaitForStructuredMessage(
533
+ typedSchema ? { ...options, responseSchema: typedSchema } : options,
534
+ effectiveTimeout
535
+ );
536
+ if (typedSchema) {
537
+ if (!message) {
538
+ throw new Error(
539
+ "The requested run completed without a structured assistant response."
540
+ );
541
+ }
542
+ return typedSchema.parse(JSON.parse(message.data.content));
543
+ }
544
+ return message;
545
+ }
503
546
  let resolveOutcome;
504
547
  const outcomePromise = new Promise((resolve) => {
505
548
  resolveOutcome = resolve;
@@ -541,12 +584,95 @@ class CopilotSession {
541
584
  unsubscribe();
542
585
  }
543
586
  }
587
+ async sendAndWaitForStructuredMessage(options, timeout) {
588
+ if (this.disconnected) {
589
+ throw new Error("Session is disconnected");
590
+ }
591
+ let resolveOutcome;
592
+ const outcomePromise = new Promise((resolve) => {
593
+ resolveOutcome = resolve;
594
+ });
595
+ const fail = (error) => resolveOutcome({ kind: "error", error });
596
+ let messageId;
597
+ let consumed = false;
598
+ let lastMessage;
599
+ const buffered = [];
600
+ const observe = (event) => {
601
+ if (event.agentId) return;
602
+ if (event.type === "user.message" && event.data.messageId === messageId) {
603
+ consumed = true;
604
+ } else if (event.type === "assistant.message" && event.data.originatingMessageId === messageId) {
605
+ consumed = true;
606
+ lastMessage = event.data.toolRequests?.length ? void 0 : event;
607
+ } else if (consumed && event.type === "session.idle" && event.data.mode !== "autopilot") {
608
+ if (event.data.aborted) {
609
+ fail(
610
+ new Error(
611
+ "The requested run was aborted before a structured result was completed."
612
+ )
613
+ );
614
+ } else {
615
+ resolveOutcome({ kind: "idle", message: lastMessage });
616
+ }
617
+ } else if (consumed && event.type === "session.error") {
618
+ const error = new Error(event.data.message);
619
+ error.stack = event.data.stack;
620
+ fail(error);
621
+ }
622
+ };
623
+ const unsubscribe = this.on((event) => {
624
+ if (event.type !== "user.message" && event.type !== "assistant.message" && event.type !== "session.idle" && event.type !== "session.error") {
625
+ return;
626
+ }
627
+ if (messageId === void 0) {
628
+ buffered.push(event);
629
+ } else {
630
+ observe(event);
631
+ }
632
+ });
633
+ this.pendingStructuredWaits.add(fail);
634
+ const timer = setTimeout(
635
+ () => fail(new Error(`Timeout after ${timeout}ms waiting for the structured response`)),
636
+ timeout
637
+ );
638
+ try {
639
+ const sendOutcome = this.send(options).then(
640
+ (id) => {
641
+ if (!id) {
642
+ throw new Error(
643
+ "The runtime did not return a message ID for the structured send."
644
+ );
645
+ }
646
+ messageId = id;
647
+ for (const event of buffered) observe(event);
648
+ buffered.length = 0;
649
+ return outcomePromise;
650
+ },
651
+ (error) => ({
652
+ kind: "error",
653
+ error: error instanceof Error ? error : new Error(String(error))
654
+ })
655
+ );
656
+ const outcome = await Promise.race([sendOutcome, outcomePromise]);
657
+ if (outcome.kind === "error") throw outcome.error;
658
+ return outcome.message;
659
+ } finally {
660
+ clearTimeout(timer);
661
+ buffered.length = 0;
662
+ unsubscribe();
663
+ this.pendingStructuredWaits.delete(fail);
664
+ }
665
+ }
544
666
  /** @internal */
545
667
  _markDisconnected() {
546
668
  if (this.disconnected) {
547
669
  return;
548
670
  }
549
671
  this.disconnected = true;
672
+ for (const fail of this.pendingStructuredWaits) {
673
+ fail(new Error("Session disconnected while waiting for a structured response"));
674
+ }
675
+ this.pendingStructuredWaits.clear();
550
676
  for (const controller of this.pendingExternalTools.values()) {
551
677
  controller.abort();
552
678
  }
@@ -1,2 +1,2 @@
1
- export declare const COPILOT_CLI_VERSION = "1.0.85";
1
+ export declare const COPILOT_CLI_VERSION = "1.0.85-unstable.r35379093703.g3514c9a";
2
2
  export declare const COPILOT_CLI_USE_NPM_PACKAGE = false;
@@ -1,4 +1,4 @@
1
- const COPILOT_CLI_VERSION = "1.0.85";
1
+ const COPILOT_CLI_VERSION = "1.0.85-unstable.r35379093703.g3514c9a";
2
2
  const COPILOT_CLI_USE_NPM_PACKAGE = false;
3
3
  export {
4
4
  COPILOT_CLI_USE_NPM_PACKAGE,
package/dist/client.js CHANGED
@@ -23,13 +23,11 @@ import { COPILOT_CLI_VERSION } from "./cliVersion.js";
23
23
  import { createSessionFsAdapter } from "./sessionFsProvider.js";
24
24
  import { createCopilotRequestAdapter } from "./copilotRequestHandler.js";
25
25
  import { getTraceContext } from "./telemetry.js";
26
+ import { toJsonSchema } from "./schema.js";
26
27
  import { ToolSet } from "./toolSet.js";
27
28
  import { defaultJoinSessionPermissionHandler } from "./types.js";
28
29
  const MIN_PROTOCOL_VERSION = 3;
29
30
  const RUNTIME_SHUTDOWN_TIMEOUT_MS = 1e4;
30
- function isZodSchema(value) {
31
- return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
32
- }
33
31
  async function withTimeout(promise, timeoutMs, message) {
34
32
  let timeout;
35
33
  try {
@@ -74,13 +72,6 @@ async function waitForChildExit(child, timeoutMs) {
74
72
  }
75
73
  });
76
74
  }
77
- function toJsonSchema(parameters) {
78
- if (!parameters) return void 0;
79
- if (isZodSchema(parameters)) {
80
- return parameters.toJSONSchema();
81
- }
82
- return parameters;
83
- }
84
75
  const DEFAULT_PROVIDER_NAME = "default";
85
76
  function extractBearerTokenProviders(provider, providers) {
86
77
  const callbacks = /* @__PURE__ */ new Map();
package/dist/index.d.ts CHANGED
@@ -11,5 +11,5 @@ export { defineFactory, FactoryResumeError, isFactoryRunTerminal } from "./facto
11
11
  export { Canvas, CanvasError, createCanvas, type CanvasAction, type CanvasDeclaration, type CanvasHostContext, type CanvasHostContextCapabilities, type CanvasJsonSchema, type CanvasOptions, } from "./canvas.js";
12
12
  export { defineTool, approveAll, createAttributedPermissionResult, convertMcpCallToolResult, createSessionFsAdapter, CopilotRequestHandler, CopilotWebSocketHandler, CopilotWebSocketCloseStatus, CopilotWebSocketForwarder, SessionFsSqliteTransactionFailure, SYSTEM_MESSAGE_SECTIONS, } from "./types.js";
13
13
  export type * from "./generated/session-events.js";
14
- export type { AskUserVariant, CommandContext, CommandDefinition, CommandHandler, CanvasProviderIdentity, CloudSessionOptions, CloudSessionRepository, AutoModeSwitchHandler, AutoModeSwitchRequest, AutoModeSwitchResponse, AgentStopHandler, AgentStopHookInput, AgentStopHookOutput, UserPromptTransformedHandler, UserPromptTransformedHookInput, UserPromptTransformedHookOutput, CopilotClientInfo, CopilotClientMode, CopilotClientOptions, CopilotExpAssignmentResponse, StdioRuntimeConnection, InProcessRuntimeConnection, TcpRuntimeConnection, UriRuntimeConnection, ChildProcessRuntimeConnection, CustomAgentConfig, ElicitationFieldValue, ElicitationHandler, ElicitationParams, ElicitationContext, ElicitationResult, ElicitationSchema, ElicitationSchemaField, ExpConfigEntry, ExpFlagValue, ExitPlanModeHandler, ExitPlanModeRequest, ExitPlanModeResult, ExtensionInfo, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, GitHubMcpToolConfig, GitHubTelemetryNotification, GitHubTelemetryEvent, GitHubTelemetryClientInfo, GitHubTokenAcquireReason, GitHubTokenAcquireResult, GitHubTokenProvider, GitHubTokenProviderArgs, GitHubTokenProviderResult, InfiniteSessionConfig, LargeToolOutputConfig, MemoryConfiguration, UiInputOptions, FactoryLimits, FactoryMeta, MCPStdioServerConfig, MCPHTTPServerConfig, MCPServerConfig, DefaultAgentConfig, BearerTokenProvider, MessageOptions, MessageSource, ManagedSettings, ManagedSettingsPermissions, ModelBilling, ModelBillingTokenPrices, ModelBillingTokenPricesLongContext, AutoTier, CapiSessionOptions, CurrentModel, ModelSwitchAutoTierResult, ModelSwitchAutoTierStatus, ModelCapabilities, ModelCapabilitiesOverride, ModelInfo, ModelPolicy, NamedProviderConfig, PermissionHandler, PermissionRequest, PermissionRequestedData, PermissionRequestedEvent, PermissionRequestResult, AttributedPermissionResult, PermissionDecisionContext, PermissionDecisionOutcome, PermissionDecisionSource, PermissionDecisionSurface, PermissionResponseCapability, ProviderConfig, ProviderModelConfig, ProviderTokenArgs, RemoteSessionMode, ResumeSessionConfig, SectionOverride, SectionOverrideAction, SectionTransformFn, SessionCapabilities, SessionConfig, SessionConfigBase, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventMetadata, SessionLifecycleEventType, SessionLifecycleHandler, SessionHooks, SessionCreatedEvent, SessionDeletedEvent, SessionUpdatedEvent, SessionForegroundEvent, SessionBackgroundEvent, SessionContext, SessionListFilter, SessionMetadata, SessionUiApi, SessionFsConfig, SessionFsProvider, SessionFsFileInfo, SessionFsSqliteQueryResult, SessionFsSqliteQueryType, SessionFsSqliteProvider, SessionFsSqliteStatement, SessionFsSqliteTransactionErrorClass, CopilotRequestContext, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageCustomizeConfig, SystemMessageReplaceConfig, SystemMessageSection, TelemetryConfig, TraceContext, TraceContextProvider, Tool, ToolHandler, ToolInvocation, CurrentToolMetadata, ToolTelemetry, ToolResultObject, ToolSearchConfig, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js";
14
+ export type { AskUserVariant, CommandContext, CommandDefinition, CommandHandler, CanvasProviderIdentity, CloudSessionOptions, CloudSessionRepository, AutoModeSwitchHandler, AutoModeSwitchRequest, AutoModeSwitchResponse, AgentStopHandler, AgentStopHookInput, AgentStopHookOutput, UserPromptTransformedHandler, UserPromptTransformedHookInput, UserPromptTransformedHookOutput, CopilotClientInfo, CopilotClientMode, CopilotClientOptions, CopilotExpAssignmentResponse, StdioRuntimeConnection, InProcessRuntimeConnection, TcpRuntimeConnection, UriRuntimeConnection, ChildProcessRuntimeConnection, CustomAgentConfig, ElicitationFieldValue, ElicitationHandler, ElicitationParams, ElicitationContext, ElicitationResult, ElicitationSchema, ElicitationSchemaField, ExpConfigEntry, ExpFlagValue, ExitPlanModeHandler, ExitPlanModeRequest, ExitPlanModeResult, ExtensionInfo, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, GitHubMcpToolConfig, GitHubTelemetryNotification, GitHubTelemetryEvent, GitHubTelemetryClientInfo, GitHubTokenAcquireReason, GitHubTokenAcquireResult, GitHubTokenProvider, GitHubTokenProviderArgs, GitHubTokenProviderResult, InfiniteSessionConfig, LargeToolOutputConfig, MemoryConfiguration, UiInputOptions, FactoryLimits, FactoryMeta, MCPStdioServerConfig, MCPHTTPServerConfig, MCPServerConfig, DefaultAgentConfig, BearerTokenProvider, MessageOptions, ResponseSchema, MessageSource, ManagedSettings, ManagedSettingsPermissions, ModelBilling, ModelBillingTokenPrices, ModelBillingTokenPricesLongContext, AutoTier, CapiSessionOptions, CurrentModel, ModelSwitchAutoTierResult, ModelSwitchAutoTierStatus, ModelCapabilities, ModelCapabilitiesOverride, ModelInfo, ModelPolicy, NamedProviderConfig, PermissionHandler, PermissionRequest, PermissionRequestedData, PermissionRequestedEvent, PermissionRequestResult, AttributedPermissionResult, PermissionDecisionContext, PermissionDecisionOutcome, PermissionDecisionSource, PermissionDecisionSurface, PermissionResponseCapability, ProviderConfig, ProviderModelConfig, ProviderTokenArgs, RemoteSessionMode, ResumeSessionConfig, SectionOverride, SectionOverrideAction, SectionTransformFn, SessionCapabilities, SessionConfig, SessionConfigBase, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventMetadata, SessionLifecycleEventType, SessionLifecycleHandler, SessionHooks, SessionCreatedEvent, SessionDeletedEvent, SessionUpdatedEvent, SessionForegroundEvent, SessionBackgroundEvent, SessionContext, SessionListFilter, SessionMetadata, SessionUiApi, SessionFsConfig, SessionFsProvider, SessionFsFileInfo, SessionFsSqliteQueryResult, SessionFsSqliteQueryType, SessionFsSqliteProvider, SessionFsSqliteStatement, SessionFsSqliteTransactionErrorClass, CopilotRequestContext, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageCustomizeConfig, SystemMessageReplaceConfig, SystemMessageSection, TelemetryConfig, TraceContext, TraceContextProvider, Tool, ToolHandler, ToolInvocation, CurrentToolMetadata, ToolTelemetry, ToolResultObject, ToolSearchConfig, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js";
15
15
  export type { RunOptions, ResumeOptions, FactoryLimitOverrides, FactoryResumeErrorCode, SessionFactoryApi, FactoryAgentOptions, FactoryContext, FactoryDefinition, FactoryHandle, FactoryJsonSchema, JsonValue, FactoryPipelineStage, FactoryStepOptions, FactoryRunResult, FactoryRunStatus, FactoryRunSummary, FactoryListRunsOptions, FactoryRunsPage, FactoryRunDetail, FactoryProgressPage, FactoryProgressLine, FactoryPhaseObservation, FactoryPhaseStatus, FactoryAgentSummary, } from "./factory.js";
@@ -0,0 +1,4 @@
1
+ import type { ResponseSchema, ZodSchema } from "./types.js";
2
+ export declare function isZodSchema(value: unknown): value is ZodSchema;
3
+ export declare function toJsonSchema(schema: ZodSchema | Record<string, unknown> | undefined): Record<string, unknown> | undefined;
4
+ export declare function isResponseSchema(value: unknown): value is ResponseSchema;
package/dist/schema.js ADDED
@@ -0,0 +1,14 @@
1
+ function isZodSchema(value) {
2
+ return typeof value === "object" && value !== null && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
3
+ }
4
+ function toJsonSchema(schema) {
5
+ return isZodSchema(schema) ? schema.toJSONSchema() : schema;
6
+ }
7
+ function isResponseSchema(value) {
8
+ return isZodSchema(value) && "parse" in value && typeof value.parse === "function";
9
+ }
10
+ export {
11
+ isResponseSchema,
12
+ isZodSchema,
13
+ toJsonSchema
14
+ };
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
@@ -510,6 +510,13 @@ export interface ZodSchema<T = unknown> {
510
510
  _output: T;
511
511
  toJSONSchema(): Record<string, unknown>;
512
512
  }
513
+ /**
514
+ * A Zod-compatible output schema that both describes and parses a typed result.
515
+ * TypeScript types are erased at runtime, so typed output requires a schema value.
516
+ */
517
+ export interface ResponseSchema<T = unknown> extends ZodSchema<T> {
518
+ parse(value: unknown): T;
519
+ }
513
520
  /**
514
521
  * Tool definition. Parameters can be either:
515
522
  * - A Zod schema (provides type inference for handler)
@@ -2802,6 +2809,19 @@ export interface MessageOptions {
2802
2809
  * If provided, this is shown in the timeline instead of `prompt`.
2803
2810
  */
2804
2811
  displayPrompt?: string;
2812
+ /**
2813
+ * JSON Schema or a Zod schema for this run's output, including requests after tool calls.
2814
+ * Independent sends do not inherit it. Ordinary immediate steering retains the active
2815
+ * schema and origin, even when promoted to a follow-up after the model request finishes.
2816
+ * Specifying a schema with mode "immediate" is rejected, even while idle.
2817
+ * This is not a persisted session default and does not survive a context reset.
2818
+ *
2819
+ * sendAndWait still returns an assistant message event. For a typed result, pass a
2820
+ * Zod-compatible schema as sendAndWait's second argument instead.
2821
+ * Streaming events remain text and may include intermediate messages.
2822
+ * Use rpc.send's responseFormat for provider-specific name, description and strict options.
2823
+ */
2824
+ responseSchema?: ZodSchema | Record<string, unknown>;
2805
2825
  }
2806
2826
  /**
2807
2827
  * 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-unstable.35393089353.gfc44743",
8
+ "copilotCliVersion": "1.0.85-unstable.r35379093703.g3514c9a",
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-unstable.35393089353.gfc44743",
104
+ "@github/copilot-sdk-darwin-x64": "1.0.15-unstable.35393089353.gfc44743",
105
+ "@github/copilot-sdk-linux-arm64": "1.0.15-unstable.35393089353.gfc44743",
106
+ "@github/copilot-sdk-linux-x64": "1.0.15-unstable.35393089353.gfc44743",
107
+ "@github/copilot-sdk-linuxmusl-arm64": "1.0.15-unstable.35393089353.gfc44743",
108
+ "@github/copilot-sdk-linuxmusl-x64": "1.0.15-unstable.35393089353.gfc44743",
109
+ "@github/copilot-sdk-win32-arm64": "1.0.15-unstable.35393089353.gfc44743",
110
+ "@github/copilot-sdk-win32-x64": "1.0.15-unstable.35393089353.gfc44743"
109
111
  }
110
112
  }