@github/copilot-sdk 1.0.0-beta.6 → 1.0.0-beta.8

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.
@@ -18,14 +18,13 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var session_exports = {};
20
20
  __export(session_exports, {
21
- CopilotSession: () => CopilotSession,
22
- NO_RESULT_PERMISSION_V2_ERROR: () => NO_RESULT_PERMISSION_V2_ERROR
21
+ CopilotSession: () => CopilotSession
23
22
  });
24
23
  module.exports = __toCommonJS(session_exports);
25
24
  var import_node = require("vscode-jsonrpc/node.js");
26
25
  var import_rpc = require("./generated/rpc.js");
26
+ var import_canvas = require("./canvas.js");
27
27
  var import_telemetry = require("./telemetry.js");
28
- const NO_RESULT_PERMISSION_V2_ERROR = "Permission handlers cannot return 'no-result' when connected to a protocol v2 server.";
29
28
  function deserializeHookInput(raw) {
30
29
  if (!raw || typeof raw !== "object" || typeof raw.timestamp !== "number") {
31
30
  return raw;
@@ -53,6 +52,7 @@ class CopilotSession {
53
52
  eventHandlers = /* @__PURE__ */ new Set();
54
53
  typedEventHandlers = /* @__PURE__ */ new Map();
55
54
  toolHandlers = /* @__PURE__ */ new Map();
55
+ canvases = /* @__PURE__ */ new Map();
56
56
  commandHandlers = /* @__PURE__ */ new Map();
57
57
  permissionHandler;
58
58
  userInputHandler;
@@ -64,6 +64,7 @@ class CopilotSession {
64
64
  _rpc = null;
65
65
  traceContextProvider;
66
66
  _capabilities = {};
67
+ openCanvasInstances = [];
67
68
  /** @internal Client session API handlers, populated by CopilotClient during create/resume. */
68
69
  clientSessionApis = {};
69
70
  /**
@@ -393,6 +394,61 @@ class CopilotSession {
393
394
  getToolHandler(name) {
394
395
  return this.toolHandlers.get(name);
395
396
  }
397
+ /**
398
+ * Registers canvas declarations and handlers for this session.
399
+ *
400
+ * @param canvases - Canvases created via `createCanvas`, or undefined to clear all canvases
401
+ * @internal Called by the SDK when creating/resuming a session with `canvases`.
402
+ */
403
+ registerCanvases(canvases) {
404
+ this.canvases.clear();
405
+ if (!canvases || canvases.length === 0) {
406
+ delete this.clientSessionApis.canvas;
407
+ return;
408
+ }
409
+ for (const canvas of canvases) {
410
+ this.canvases.set(canvas.declaration.id, canvas);
411
+ }
412
+ const self = this;
413
+ this.clientSessionApis.canvas = {
414
+ async open(params) {
415
+ const canvas = self.canvases.get(params.canvasId);
416
+ if (!canvas) throw new Error(`No canvas registered with id "${params.canvasId}"`);
417
+ try {
418
+ return await canvas.open(params) ?? {};
419
+ } catch (error) {
420
+ throw toCanvasRpcError(error);
421
+ }
422
+ },
423
+ async close(params) {
424
+ const canvas = self.canvases.get(params.canvasId);
425
+ if (!canvas) throw new Error(`No canvas registered with id "${params.canvasId}"`);
426
+ try {
427
+ if (canvas.onClose) {
428
+ await canvas.onClose(params);
429
+ }
430
+ } catch (error) {
431
+ throw toCanvasRpcError(error);
432
+ }
433
+ },
434
+ async invokeAction(params) {
435
+ const canvas = self.canvases.get(params.canvasId);
436
+ if (!canvas) throw new Error(`No canvas registered with id "${params.canvasId}"`);
437
+ const handler = canvas.actionHandlers.get(params.actionName);
438
+ if (!handler) {
439
+ throw new import_canvas.CanvasError(
440
+ "canvas_action_no_handler",
441
+ "No handler implemented for this canvas action"
442
+ );
443
+ }
444
+ try {
445
+ return await handler(params);
446
+ } catch (error) {
447
+ throw toCanvasRpcError(error);
448
+ }
449
+ }
450
+ };
451
+ }
396
452
  /**
397
453
  * Registers command handlers for this session.
398
454
  *
@@ -489,6 +545,24 @@ class CopilotSession {
489
545
  setCapabilities(capabilities) {
490
546
  this._capabilities = capabilities ?? {};
491
547
  }
548
+ /**
549
+ * Snapshot of canvas instances that were already open when the session was
550
+ * resumed. Populated from the `session.resume` response; empty for freshly
551
+ * created sessions. Returns a defensive copy — mutating the returned array
552
+ * has no effect on the session.
553
+ */
554
+ get openCanvases() {
555
+ return [...this.openCanvasInstances];
556
+ }
557
+ /**
558
+ * Sets the open-canvas snapshot for this session.
559
+ *
560
+ * @param instances - The `openCanvases` array from the `session.resume` response.
561
+ * @internal This method is typically called internally when resuming a session.
562
+ */
563
+ setOpenCanvases(instances) {
564
+ this.openCanvasInstances = [...instances];
565
+ }
492
566
  assertElicitation() {
493
567
  if (!this._capabilities.ui?.elicitation) {
494
568
  throw new Error(
@@ -628,33 +702,6 @@ class CopilotSession {
628
702
  }
629
703
  return { sections: result };
630
704
  }
631
- /**
632
- * Handles a permission request in the v2 protocol format (synchronous RPC).
633
- * Used as a back-compat adapter when connected to a v2 server.
634
- *
635
- * @param request - The permission request data from the CLI
636
- * @returns A promise that resolves with the permission decision
637
- * @internal This method is for internal use by the SDK.
638
- */
639
- async _handlePermissionRequestV2(request) {
640
- if (!this.permissionHandler) {
641
- return { kind: "user-not-available" };
642
- }
643
- try {
644
- const result = await this.permissionHandler(request, {
645
- sessionId: this.sessionId
646
- });
647
- if (result.kind === "no-result") {
648
- throw new Error(NO_RESULT_PERMISSION_V2_ERROR);
649
- }
650
- return result;
651
- } catch (error) {
652
- if (error instanceof Error && error.message === NO_RESULT_PERMISSION_V2_ERROR) {
653
- throw error;
654
- }
655
- return { kind: "user-not-available" };
656
- }
657
- }
658
705
  /**
659
706
  * Handles a user input request from the Copilot CLI.
660
707
  *
@@ -851,8 +898,13 @@ function isToolResultObject(value) {
851
898
  ];
852
899
  return allowedResultTypes.includes(value.resultType);
853
900
  }
901
+ function toCanvasRpcError(error) {
902
+ if (error instanceof import_node.ResponseError) return error;
903
+ const code = error instanceof import_canvas.CanvasError ? error.code : "canvas_handler_error";
904
+ const message = error instanceof Error ? error.message : String(error);
905
+ return new import_node.ResponseError(import_node.ErrorCodes.InternalError, message, { code, message });
906
+ }
854
907
  // Annotate the CommonJS export names for ESM import in node:
855
908
  0 && (module.exports = {
856
- CopilotSession,
857
- NO_RESULT_PERMISSION_V2_ERROR
909
+ CopilotSession
858
910
  });
package/dist/cjs/types.js CHANGED
@@ -19,7 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var types_exports = {};
20
20
  __export(types_exports, {
21
21
  RuntimeConnection: () => RuntimeConnection,
22
- SYSTEM_PROMPT_SECTIONS: () => SYSTEM_PROMPT_SECTIONS,
22
+ SYSTEM_MESSAGE_SECTIONS: () => SYSTEM_MESSAGE_SECTIONS,
23
23
  approveAll: () => approveAll,
24
24
  convertMcpCallToolResult: () => convertMcpCallToolResult,
25
25
  createSessionFsAdapter: () => import_sessionFsProvider.createSessionFsAdapter,
@@ -101,7 +101,7 @@ function convertMcpCallToolResult(callResult) {
101
101
  function defineTool(name, config) {
102
102
  return { name, ...config };
103
103
  }
104
- const SYSTEM_PROMPT_SECTIONS = {
104
+ const SYSTEM_MESSAGE_SECTIONS = {
105
105
  identity: { description: "Agent identity preamble and mode statement" },
106
106
  tone: { description: "Response style, conciseness rules, output formatting preferences" },
107
107
  tool_efficiency: { description: "Tool usage patterns, parallel calling, batching guidelines" },
@@ -111,6 +111,9 @@ const SYSTEM_PROMPT_SECTIONS = {
111
111
  safety: { description: "Environment limitations, prohibited actions, security policies" },
112
112
  tool_instructions: { description: "Per-tool usage instructions" },
113
113
  custom_instructions: { description: "Repository and organization custom instructions" },
114
+ runtime_instructions: {
115
+ description: "Runtime-provided context and instructions (e.g. system notifications, memories, workspace context, mode-specific instructions, content-exclusion policy)"
116
+ },
114
117
  last_instructions: {
115
118
  description: "End-of-prompt instructions: parallel tool calling, persistence, task completion"
116
119
  }
@@ -122,7 +125,7 @@ const defaultJoinSessionPermissionHandler = () => ({
122
125
  // Annotate the CommonJS export names for ESM import in node:
123
126
  0 && (module.exports = {
124
127
  RuntimeConnection,
125
- SYSTEM_PROMPT_SECTIONS,
128
+ SYSTEM_MESSAGE_SECTIONS,
126
129
  approveAll,
127
130
  convertMcpCallToolResult,
128
131
  createSessionFsAdapter,
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createServerRpc } from "./generated/rpc.js";
2
2
  import { CopilotSession } from "./session.js";
3
- import type { ConnectionState, CopilotClientOptions, GetAuthStatusResponse, GetStatusResponse, ModelInfo, ResumeSessionConfig, SessionConfig, SessionLifecycleEventType, SessionLifecycleHandler, SessionListFilter, SessionMetadata, TypedSessionLifecycleHandler } from "./types.js";
3
+ import type { CopilotClientOptions, GetAuthStatusResponse, GetStatusResponse, ModelInfo, ResumeSessionConfig, SessionConfig, SessionLifecycleEventType, SessionLifecycleHandler, SessionListFilter, SessionMetadata, TypedSessionLifecycleHandler } from "./types.js";
4
4
  /**
5
5
  * Main client for interacting with the Copilot CLI.
6
6
  *
@@ -244,19 +244,6 @@ export declare class CopilotClient {
244
244
  * ```
245
245
  */
246
246
  resumeSession(sessionId: string, config: ResumeSessionConfig): Promise<CopilotSession>;
247
- /**
248
- * Gets the current connection state of the client.
249
- *
250
- * @returns The current connection state: "disconnected", "connecting", "connected", or "error"
251
- *
252
- * @example
253
- * ```typescript
254
- * if (client.getState() === "connected") {
255
- * const session = await client.createSession({ onPermissionRequest: approveAll });
256
- * }
257
- * ```
258
- */
259
- getState(): ConnectionState;
260
247
  /**
261
248
  * Sends a ping request to the server to verify connectivity.
262
249
  *
@@ -480,16 +467,4 @@ export declare class CopilotClient {
480
467
  private handleAutoModeSwitchRequest;
481
468
  private handleHooksInvoke;
482
469
  private handleSystemMessageTransform;
483
- /**
484
- * Handles a v2-style tool.call RPC request from the server.
485
- * Looks up the session and tool handler, executes it, and returns the result
486
- * in the v2 response format.
487
- */
488
- private handleToolCallRequestV2;
489
- /**
490
- * Handles a v2-style permission.request RPC request from the server.
491
- */
492
- private handlePermissionRequestV2;
493
- private normalizeToolResultV2;
494
- private isToolResultObject;
495
470
  }
package/dist/client.js CHANGED
@@ -18,11 +18,11 @@ import {
18
18
  registerClientSessionApiHandlers
19
19
  } from "./generated/rpc.js";
20
20
  import { getSdkProtocolVersion } from "./sdkProtocolVersion.js";
21
- import { CopilotSession, NO_RESULT_PERMISSION_V2_ERROR } from "./session.js";
21
+ import { CopilotSession } from "./session.js";
22
22
  import { createSessionFsAdapter } from "./sessionFsProvider.js";
23
23
  import { getTraceContext } from "./telemetry.js";
24
24
  import { defaultJoinSessionPermissionHandler } from "./types.js";
25
- const MIN_PROTOCOL_VERSION = 2;
25
+ const MIN_PROTOCOL_VERSION = 3;
26
26
  function isZodSchema(value) {
27
27
  return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
28
28
  }
@@ -558,6 +558,7 @@ class CopilotClient {
558
558
  this.onGetTraceContext
559
559
  );
560
560
  session.registerTools(config.tools);
561
+ session.registerCanvases(config.canvases);
561
562
  session.registerCommands(config.commands);
562
563
  session.registerPermissionHandler(config.onPermissionRequest);
563
564
  if (config.onUserInputRequest) {
@@ -600,6 +601,10 @@ class CopilotClient {
600
601
  overridesBuiltInTool: tool.overridesBuiltInTool,
601
602
  skipPermission: tool.skipPermission
602
603
  })),
604
+ canvases: config.canvases?.map((canvas) => canvas.declaration),
605
+ requestCanvasRenderer: config.requestCanvasRenderer,
606
+ requestExtensions: config.requestExtensions,
607
+ extensionInfo: config.extensionInfo,
603
608
  commands: config.commands?.map((cmd) => ({
604
609
  name: cmd.name,
605
610
  description: cmd.description
@@ -610,7 +615,7 @@ class CopilotClient {
610
615
  provider: config.provider,
611
616
  enableSessionTelemetry: config.enableSessionTelemetry,
612
617
  modelCapabilities: config.modelCapabilities,
613
- requestPermission: true,
618
+ requestPermission: !!config.onPermissionRequest,
614
619
  requestUserInput: !!config.onUserInputRequest,
615
620
  requestElicitation: !!config.onElicitationRequest,
616
621
  requestExitPlanMode: !!config.onExitPlanModeRequest,
@@ -678,6 +683,7 @@ class CopilotClient {
678
683
  this.onGetTraceContext
679
684
  );
680
685
  session.registerTools(config.tools);
686
+ session.registerCanvases(config.canvases);
681
687
  session.registerCommands(config.commands);
682
688
  session.registerPermissionHandler(config.onPermissionRequest);
683
689
  if (config.onUserInputRequest) {
@@ -724,6 +730,10 @@ class CopilotClient {
724
730
  overridesBuiltInTool: tool.overridesBuiltInTool,
725
731
  skipPermission: tool.skipPermission
726
732
  })),
733
+ canvases: config.canvases?.map((canvas) => canvas.declaration),
734
+ requestCanvasRenderer: config.requestCanvasRenderer,
735
+ requestExtensions: config.requestExtensions,
736
+ extensionInfo: config.extensionInfo,
727
737
  commands: config.commands?.map((cmd) => ({
728
738
  name: cmd.name,
729
739
  description: cmd.description
@@ -753,32 +763,19 @@ class CopilotClient {
753
763
  suppressResumeEvent: config.suppressResumeEvent,
754
764
  continuePendingWork: config.continuePendingWork,
755
765
  gitHubToken: config.gitHubToken,
756
- remoteSession: config.remoteSession
766
+ remoteSession: config.remoteSession,
767
+ openCanvases: config.openCanvases
757
768
  });
758
- const { workspacePath, capabilities } = response;
769
+ const { workspacePath, capabilities, openCanvases } = response;
759
770
  session["_workspacePath"] = workspacePath;
760
771
  session.setCapabilities(capabilities);
772
+ session.setOpenCanvases(openCanvases ?? []);
761
773
  } catch (e) {
762
774
  this.sessions.delete(sessionId);
763
775
  throw e;
764
776
  }
765
777
  return session;
766
778
  }
767
- /**
768
- * Gets the current connection state of the client.
769
- *
770
- * @returns The current connection state: "disconnected", "connecting", "connected", or "error"
771
- *
772
- * @example
773
- * ```typescript
774
- * if (client.getState() === "connected") {
775
- * const session = await client.createSession({ onPermissionRequest: approveAll });
776
- * }
777
- * ```
778
- */
779
- getState() {
780
- return this.state;
781
- }
782
779
  /**
783
780
  * Sends a ping request to the server to verify connectivity.
784
781
  *
@@ -1367,14 +1364,6 @@ stderr: ${stderrOutput}`
1367
1364
  this.connection.onNotification("session.lifecycle", (notification) => {
1368
1365
  this.handleSessionLifecycleNotification(notification);
1369
1366
  });
1370
- this.connection.onRequest(
1371
- "tool.call",
1372
- async (params) => await this.handleToolCallRequestV2(params)
1373
- );
1374
- this.connection.onRequest(
1375
- "permission.request",
1376
- async (params) => await this.handlePermissionRequestV2(params)
1377
- );
1378
1367
  this.connection.onRequest(
1379
1368
  "userInput.request",
1380
1369
  async (params) => await this.handleUserInputRequest(params)
@@ -1516,105 +1505,6 @@ stderr: ${stderrOutput}`
1516
1505
  }
1517
1506
  return await session._handleSystemMessageTransform(params.sections);
1518
1507
  }
1519
- // ========================================================================
1520
- // Protocol v2 backward-compatibility adapters
1521
- // ========================================================================
1522
- /**
1523
- * Handles a v2-style tool.call RPC request from the server.
1524
- * Looks up the session and tool handler, executes it, and returns the result
1525
- * in the v2 response format.
1526
- */
1527
- async handleToolCallRequestV2(params) {
1528
- if (!params || typeof params.sessionId !== "string" || typeof params.toolCallId !== "string" || typeof params.toolName !== "string") {
1529
- throw new Error("Invalid tool call payload");
1530
- }
1531
- const session = this.sessions.get(params.sessionId);
1532
- if (!session) {
1533
- throw new Error(`Unknown session ${params.sessionId}`);
1534
- }
1535
- const handler = session.getToolHandler(params.toolName);
1536
- if (!handler) {
1537
- return {
1538
- result: {
1539
- textResultForLlm: `Tool '${params.toolName}' is not supported by this client instance.`,
1540
- resultType: "failure",
1541
- error: `tool '${params.toolName}' not supported`,
1542
- toolTelemetry: {}
1543
- }
1544
- };
1545
- }
1546
- try {
1547
- const traceparent = params.traceparent;
1548
- const tracestate = params.tracestate;
1549
- const invocation = {
1550
- sessionId: params.sessionId,
1551
- toolCallId: params.toolCallId,
1552
- toolName: params.toolName,
1553
- arguments: params.arguments,
1554
- traceparent,
1555
- tracestate
1556
- };
1557
- const result = await handler(params.arguments, invocation);
1558
- return { result: this.normalizeToolResultV2(result) };
1559
- } catch (error) {
1560
- const message = error instanceof Error ? error.message : String(error);
1561
- return {
1562
- result: {
1563
- textResultForLlm: "Invoking this tool produced an error. Detailed information is not available.",
1564
- resultType: "failure",
1565
- error: message,
1566
- toolTelemetry: {}
1567
- }
1568
- };
1569
- }
1570
- }
1571
- /**
1572
- * Handles a v2-style permission.request RPC request from the server.
1573
- */
1574
- async handlePermissionRequestV2(params) {
1575
- if (!params || typeof params.sessionId !== "string" || !params.permissionRequest) {
1576
- throw new Error("Invalid permission request payload");
1577
- }
1578
- const session = this.sessions.get(params.sessionId);
1579
- if (!session) {
1580
- throw new Error(`Session not found: ${params.sessionId}`);
1581
- }
1582
- try {
1583
- const result = await session._handlePermissionRequestV2(params.permissionRequest);
1584
- return { result };
1585
- } catch (error) {
1586
- if (error instanceof Error && error.message === NO_RESULT_PERMISSION_V2_ERROR) {
1587
- throw error;
1588
- }
1589
- return {
1590
- result: {
1591
- kind: "user-not-available"
1592
- }
1593
- };
1594
- }
1595
- }
1596
- normalizeToolResultV2(result) {
1597
- if (result === void 0 || result === null) {
1598
- return {
1599
- textResultForLlm: "Tool returned no result",
1600
- resultType: "failure",
1601
- error: "tool returned no result",
1602
- toolTelemetry: {}
1603
- };
1604
- }
1605
- if (this.isToolResultObject(result)) {
1606
- return result;
1607
- }
1608
- const textResult = typeof result === "string" ? result : JSON.stringify(result);
1609
- return {
1610
- textResultForLlm: textResult,
1611
- resultType: "success",
1612
- toolTelemetry: {}
1613
- };
1614
- }
1615
- isToolResultObject(value) {
1616
- return typeof value === "object" && value !== null && "textResultForLlm" in value && typeof value.textResultForLlm === "string" && "resultType" in value;
1617
- }
1618
1508
  }
1619
1509
  export {
1620
1510
  CopilotClient
@@ -1,8 +1,10 @@
1
1
  import type { CopilotSession } from "./session.js";
2
- import { type PermissionHandler, type ResumeSessionConfig } from "./types.js";
2
+ import { type ExtensionInfo, type PermissionHandler, type ResumeSessionConfig } from "./types.js";
3
+ export { Canvas, CanvasError, createCanvas, type CanvasAction, type CanvasDeclaration, type CanvasHostContext, type CanvasJsonSchema, type CanvasOptions, } from "./canvas.js";
3
4
  export type JoinSessionConfig = Omit<ResumeSessionConfig, "onPermissionRequest"> & {
4
5
  onPermissionRequest?: PermissionHandler;
5
6
  };
7
+ export type { ExtensionInfo };
6
8
  /**
7
9
  * Joins the current foreground session.
8
10
  *
package/dist/extension.js CHANGED
@@ -2,6 +2,11 @@ import { CopilotClient } from "./client.js";
2
2
  import {
3
3
  defaultJoinSessionPermissionHandler
4
4
  } from "./types.js";
5
+ import {
6
+ Canvas,
7
+ CanvasError,
8
+ createCanvas
9
+ } from "./canvas.js";
5
10
  async function joinSession(config = {}) {
6
11
  const sessionId = process.env.SESSION_ID;
7
12
  if (!sessionId) {
@@ -17,5 +22,8 @@ async function joinSession(config = {}) {
17
22
  });
18
23
  }
19
24
  export {
25
+ Canvas,
26
+ CanvasError,
27
+ createCanvas,
20
28
  joinSession
21
29
  };