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

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.
@@ -371,6 +371,43 @@ function createSessionRpc(connection, sessionId) {
371
371
  setCredentials: async (params) => connection.sendRequest("session.auth.setCredentials", { sessionId, ...params })
372
372
  },
373
373
  /** @experimental */
374
+ canvas: {
375
+ /**
376
+ * Lists canvases declared for the session.
377
+ *
378
+ * @returns Declared canvases available in this session.
379
+ */
380
+ list: async () => connection.sendRequest("session.canvas.list", { sessionId }),
381
+ /**
382
+ * Lists currently open canvas instances for the live session.
383
+ *
384
+ * @returns Live open-canvas snapshot.
385
+ */
386
+ listOpen: async () => connection.sendRequest("session.canvas.listOpen", { sessionId }),
387
+ /**
388
+ * Opens or focuses a canvas instance.
389
+ *
390
+ * @param params Canvas open parameters.
391
+ *
392
+ * @returns Open canvas instance snapshot.
393
+ */
394
+ open: async (params) => connection.sendRequest("session.canvas.open", { sessionId, ...params }),
395
+ /**
396
+ * Closes an open canvas instance.
397
+ *
398
+ * @param params Canvas close parameters.
399
+ */
400
+ close: async (params) => connection.sendRequest("session.canvas.close", { sessionId, ...params }),
401
+ /**
402
+ * Invokes an action on an open canvas instance.
403
+ *
404
+ * @param params Canvas action invocation parameters.
405
+ *
406
+ * @returns Canvas action invocation result.
407
+ */
408
+ invokeAction: async (params) => connection.sendRequest("session.canvas.invokeAction", { sessionId, ...params })
409
+ },
410
+ /** @experimental */
374
411
  model: {
375
412
  /**
376
413
  * Gets the currently selected model for the session.
@@ -738,6 +775,53 @@ function createSessionRpc(connection, sessionId) {
738
775
  * @returns OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server.
739
776
  */
740
777
  login: async (params) => connection.sendRequest("session.mcp.oauth.login", { sessionId, ...params })
778
+ },
779
+ /** @experimental */
780
+ apps: {
781
+ /**
782
+ * Fetch an MCP resource (typically a `ui://` MCP App bundle, per SEP-1865) from a connected server. Requires the `mcp-apps` session capability.
783
+ *
784
+ * @param params MCP server and resource URI to fetch.
785
+ *
786
+ * @returns Resource contents returned by the MCP server.
787
+ */
788
+ readResource: async (params) => connection.sendRequest("session.mcp.apps.readResource", { sessionId, ...params }),
789
+ /**
790
+ * List tools that an MCP App view is allowed to call (SEP-1865 visibility filter). Returns tools whose `_meta.ui.visibility` is unset (default `["model","app"]`) or includes `"app"`.
791
+ *
792
+ * @param params MCP server to list app-callable tools for.
793
+ *
794
+ * @returns App-callable tools from the named MCP server.
795
+ */
796
+ listTools: async (params) => connection.sendRequest("session.mcp.apps.listTools", { sessionId, ...params }),
797
+ /**
798
+ * Call an MCP tool from an MCP App view (SEP-1865). Enforces the visibility check that prevents an app iframe from invoking model-only tools. Returns the standard MCP `CallToolResult`.
799
+ *
800
+ * @param params MCP server, tool name, and arguments to invoke from an MCP App view.
801
+ *
802
+ * @returns Standard MCP CallToolResult
803
+ */
804
+ callTool: async (params) => connection.sendRequest("session.mcp.apps.callTool", { sessionId, ...params }),
805
+ /**
806
+ * Replace the host context returned to MCP App guests on `ui/initialize`. Hosts use this to advertise theme, locale, or other metadata to the guest UI.
807
+ *
808
+ * @param params Host context to advertise to MCP App guests.
809
+ */
810
+ setHostContext: async (params) => connection.sendRequest("session.mcp.apps.setHostContext", { sessionId, ...params }),
811
+ /**
812
+ * Read the current host context advertised to MCP App guests.
813
+ *
814
+ * @returns Current host context advertised to MCP App guests.
815
+ */
816
+ getHostContext: async () => connection.sendRequest("session.mcp.apps.getHostContext", { sessionId }),
817
+ /**
818
+ * Diagnose MCP Apps wiring for a specific MCP server. Reports the session capability, feature-flag state, advertised extension, and how many tools have `_meta.ui` populated.
819
+ *
820
+ * @param params MCP server to diagnose MCP Apps wiring for.
821
+ *
822
+ * @returns Diagnostic snapshot of MCP Apps wiring for the named server.
823
+ */
824
+ diagnose: async (params) => connection.sendRequest("session.mcp.apps.diagnose", { sessionId, ...params })
741
825
  }
742
826
  },
743
827
  /** @experimental */
package/dist/cjs/index.js CHANGED
@@ -18,12 +18,15 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var index_exports = {};
20
20
  __export(index_exports, {
21
+ Canvas: () => import_canvas.Canvas,
22
+ CanvasError: () => import_canvas.CanvasError,
21
23
  CopilotClient: () => import_client.CopilotClient,
22
24
  CopilotSession: () => import_session.CopilotSession,
23
25
  RuntimeConnection: () => import_types.RuntimeConnection,
24
- SYSTEM_PROMPT_SECTIONS: () => import_types2.SYSTEM_PROMPT_SECTIONS,
26
+ SYSTEM_MESSAGE_SECTIONS: () => import_types2.SYSTEM_MESSAGE_SECTIONS,
25
27
  approveAll: () => import_types2.approveAll,
26
28
  convertMcpCallToolResult: () => import_types2.convertMcpCallToolResult,
29
+ createCanvas: () => import_canvas.createCanvas,
27
30
  createSessionFsAdapter: () => import_types2.createSessionFsAdapter,
28
31
  defineTool: () => import_types2.defineTool
29
32
  });
@@ -31,15 +34,19 @@ module.exports = __toCommonJS(index_exports);
31
34
  var import_client = require("./client.js");
32
35
  var import_types = require("./types.js");
33
36
  var import_session = require("./session.js");
37
+ var import_canvas = require("./canvas.js");
34
38
  var import_types2 = require("./types.js");
35
39
  // Annotate the CommonJS export names for ESM import in node:
36
40
  0 && (module.exports = {
41
+ Canvas,
42
+ CanvasError,
37
43
  CopilotClient,
38
44
  CopilotSession,
39
45
  RuntimeConnection,
40
- SYSTEM_PROMPT_SECTIONS,
46
+ SYSTEM_MESSAGE_SECTIONS,
41
47
  approveAll,
42
48
  convertMcpCallToolResult,
49
+ createCanvas,
43
50
  createSessionFsAdapter,
44
51
  defineTool
45
52
  });
@@ -18,14 +18,12 @@ 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");
27
26
  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
27
  function deserializeHookInput(raw) {
30
28
  if (!raw || typeof raw !== "object" || typeof raw.timestamp !== "number") {
31
29
  return raw;
@@ -53,6 +51,7 @@ class CopilotSession {
53
51
  eventHandlers = /* @__PURE__ */ new Set();
54
52
  typedEventHandlers = /* @__PURE__ */ new Map();
55
53
  toolHandlers = /* @__PURE__ */ new Map();
54
+ canvases = /* @__PURE__ */ new Map();
56
55
  commandHandlers = /* @__PURE__ */ new Map();
57
56
  permissionHandler;
58
57
  userInputHandler;
@@ -64,6 +63,7 @@ class CopilotSession {
64
63
  _rpc = null;
65
64
  traceContextProvider;
66
65
  _capabilities = {};
66
+ openCanvasInstances = [];
67
67
  /** @internal Client session API handlers, populated by CopilotClient during create/resume. */
68
68
  clientSessionApis = {};
69
69
  /**
@@ -393,6 +393,31 @@ class CopilotSession {
393
393
  getToolHandler(name) {
394
394
  return this.toolHandlers.get(name);
395
395
  }
396
+ /**
397
+ * Registers canvas declarations and handlers for this session.
398
+ *
399
+ * @param canvases - Canvases created via `createCanvas`, or undefined to clear all canvases
400
+ * @internal Called by the SDK when creating/resuming a session with `canvases`.
401
+ */
402
+ registerCanvases(canvases) {
403
+ this.canvases.clear();
404
+ if (!canvases) {
405
+ return;
406
+ }
407
+ for (const canvas of canvases) {
408
+ this.canvases.set(canvas.declaration.id, canvas);
409
+ }
410
+ }
411
+ /**
412
+ * Retrieves a registered canvas by id.
413
+ *
414
+ * @param canvasId - The id of the canvas to retrieve
415
+ * @returns The registered Canvas if found, or undefined
416
+ * @internal Used by the SDK's direct `canvas.*` dispatcher.
417
+ */
418
+ getCanvas(canvasId) {
419
+ return this.canvases.get(canvasId);
420
+ }
396
421
  /**
397
422
  * Registers command handlers for this session.
398
423
  *
@@ -489,6 +514,24 @@ class CopilotSession {
489
514
  setCapabilities(capabilities) {
490
515
  this._capabilities = capabilities ?? {};
491
516
  }
517
+ /**
518
+ * Snapshot of canvas instances that were already open when the session was
519
+ * resumed. Populated from the `session.resume` response; empty for freshly
520
+ * created sessions. Returns a defensive copy — mutating the returned array
521
+ * has no effect on the session.
522
+ */
523
+ get openCanvases() {
524
+ return [...this.openCanvasInstances];
525
+ }
526
+ /**
527
+ * Sets the open-canvas snapshot for this session.
528
+ *
529
+ * @param instances - The `openCanvases` array from the `session.resume` response.
530
+ * @internal This method is typically called internally when resuming a session.
531
+ */
532
+ setOpenCanvases(instances) {
533
+ this.openCanvasInstances = [...instances];
534
+ }
492
535
  assertElicitation() {
493
536
  if (!this._capabilities.ui?.elicitation) {
494
537
  throw new Error(
@@ -628,33 +671,6 @@ class CopilotSession {
628
671
  }
629
672
  return { sections: result };
630
673
  }
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
674
  /**
659
675
  * Handles a user input request from the Copilot CLI.
660
676
  *
@@ -853,6 +869,5 @@ function isToolResultObject(value) {
853
869
  }
854
870
  // Annotate the CommonJS export names for ESM import in node:
855
871
  0 && (module.exports = {
856
- CopilotSession,
857
- NO_RESULT_PERMISSION_V2_ERROR
872
+ CopilotSession
858
873
  });
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,6 @@ 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;
470
+ private handleCanvasProviderRequest;
471
+ private handleCanvasActionInvokeRequest;
495
472
  }
package/dist/client.js CHANGED
@@ -17,12 +17,15 @@ import {
17
17
  createInternalServerRpc,
18
18
  registerClientSessionApiHandlers
19
19
  } from "./generated/rpc.js";
20
+ import {
21
+ dispatchCanvasProviderRequest
22
+ } from "./canvas.js";
20
23
  import { getSdkProtocolVersion } from "./sdkProtocolVersion.js";
21
- import { CopilotSession, NO_RESULT_PERMISSION_V2_ERROR } from "./session.js";
24
+ import { CopilotSession } from "./session.js";
22
25
  import { createSessionFsAdapter } from "./sessionFsProvider.js";
23
26
  import { getTraceContext } from "./telemetry.js";
24
27
  import { defaultJoinSessionPermissionHandler } from "./types.js";
25
- const MIN_PROTOCOL_VERSION = 2;
28
+ const MIN_PROTOCOL_VERSION = 3;
26
29
  function isZodSchema(value) {
27
30
  return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
28
31
  }
@@ -53,6 +56,16 @@ function toWireCustomAgents(agents) {
53
56
  return { ...rest, mcpServers: toWireMcpServers(mcpServers) };
54
57
  });
55
58
  }
59
+ function isCanvasProviderRequestParams(params) {
60
+ if (!params || typeof params !== "object") {
61
+ return false;
62
+ }
63
+ const request = params;
64
+ return typeof request.sessionId === "string" && typeof request.extensionId === "string" && typeof request.canvasId === "string" && typeof request.instanceId === "string";
65
+ }
66
+ function isCanvasActionInvokeParams(params) {
67
+ return isCanvasProviderRequestParams(params) && typeof params.actionName === "string";
68
+ }
56
69
  function extractTransformCallbacks(systemMessage) {
57
70
  if (!systemMessage || systemMessage.mode !== "customize" || !systemMessage.sections) {
58
71
  return { wirePayload: systemMessage, transformCallbacks: void 0 };
@@ -558,6 +571,7 @@ class CopilotClient {
558
571
  this.onGetTraceContext
559
572
  );
560
573
  session.registerTools(config.tools);
574
+ session.registerCanvases(config.canvases);
561
575
  session.registerCommands(config.commands);
562
576
  session.registerPermissionHandler(config.onPermissionRequest);
563
577
  if (config.onUserInputRequest) {
@@ -600,6 +614,10 @@ class CopilotClient {
600
614
  overridesBuiltInTool: tool.overridesBuiltInTool,
601
615
  skipPermission: tool.skipPermission
602
616
  })),
617
+ canvases: config.canvases?.map((canvas) => canvas.declaration),
618
+ requestCanvasRenderer: config.requestCanvasRenderer,
619
+ requestExtensions: config.requestExtensions,
620
+ extensionInfo: config.extensionInfo,
603
621
  commands: config.commands?.map((cmd) => ({
604
622
  name: cmd.name,
605
623
  description: cmd.description
@@ -610,7 +628,7 @@ class CopilotClient {
610
628
  provider: config.provider,
611
629
  enableSessionTelemetry: config.enableSessionTelemetry,
612
630
  modelCapabilities: config.modelCapabilities,
613
- requestPermission: true,
631
+ requestPermission: !!config.onPermissionRequest,
614
632
  requestUserInput: !!config.onUserInputRequest,
615
633
  requestElicitation: !!config.onElicitationRequest,
616
634
  requestExitPlanMode: !!config.onExitPlanModeRequest,
@@ -678,6 +696,7 @@ class CopilotClient {
678
696
  this.onGetTraceContext
679
697
  );
680
698
  session.registerTools(config.tools);
699
+ session.registerCanvases(config.canvases);
681
700
  session.registerCommands(config.commands);
682
701
  session.registerPermissionHandler(config.onPermissionRequest);
683
702
  if (config.onUserInputRequest) {
@@ -724,6 +743,10 @@ class CopilotClient {
724
743
  overridesBuiltInTool: tool.overridesBuiltInTool,
725
744
  skipPermission: tool.skipPermission
726
745
  })),
746
+ canvases: config.canvases?.map((canvas) => canvas.declaration),
747
+ requestCanvasRenderer: config.requestCanvasRenderer,
748
+ requestExtensions: config.requestExtensions,
749
+ extensionInfo: config.extensionInfo,
727
750
  commands: config.commands?.map((cmd) => ({
728
751
  name: cmd.name,
729
752
  description: cmd.description
@@ -753,32 +776,19 @@ class CopilotClient {
753
776
  suppressResumeEvent: config.suppressResumeEvent,
754
777
  continuePendingWork: config.continuePendingWork,
755
778
  gitHubToken: config.gitHubToken,
756
- remoteSession: config.remoteSession
779
+ remoteSession: config.remoteSession,
780
+ openCanvases: config.openCanvases
757
781
  });
758
- const { workspacePath, capabilities } = response;
782
+ const { workspacePath, capabilities, openCanvases } = response;
759
783
  session["_workspacePath"] = workspacePath;
760
784
  session.setCapabilities(capabilities);
785
+ session.setOpenCanvases(openCanvases ?? []);
761
786
  } catch (e) {
762
787
  this.sessions.delete(sessionId);
763
788
  throw e;
764
789
  }
765
790
  return session;
766
791
  }
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
792
  /**
783
793
  * Sends a ping request to the server to verify connectivity.
784
794
  *
@@ -1367,14 +1377,6 @@ stderr: ${stderrOutput}`
1367
1377
  this.connection.onNotification("session.lifecycle", (notification) => {
1368
1378
  this.handleSessionLifecycleNotification(notification);
1369
1379
  });
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
1380
  this.connection.onRequest(
1379
1381
  "userInput.request",
1380
1382
  async (params) => await this.handleUserInputRequest(params)
@@ -1395,6 +1397,18 @@ stderr: ${stderrOutput}`
1395
1397
  "systemMessage.transform",
1396
1398
  async (params) => await this.handleSystemMessageTransform(params)
1397
1399
  );
1400
+ this.connection.onRequest(
1401
+ "canvas.open",
1402
+ async (params) => this.handleCanvasProviderRequest("canvas.open", params)
1403
+ );
1404
+ this.connection.onRequest(
1405
+ "canvas.close",
1406
+ async (params) => this.handleCanvasProviderRequest("canvas.close", params)
1407
+ );
1408
+ this.connection.onRequest(
1409
+ "canvas.action.invoke",
1410
+ async (params) => this.handleCanvasActionInvokeRequest(params)
1411
+ );
1398
1412
  const sessions = this.sessions;
1399
1413
  registerClientSessionApiHandlers(this.connection, (sessionId) => {
1400
1414
  const session = sessions.get(sessionId);
@@ -1516,104 +1530,25 @@ stderr: ${stderrOutput}`
1516
1530
  }
1517
1531
  return await session._handleSystemMessageTransform(params.sections);
1518
1532
  }
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");
1533
+ async handleCanvasProviderRequest(actionName, params) {
1534
+ if (!isCanvasProviderRequestParams(params)) {
1535
+ throw new Error("Invalid canvas provider request payload");
1577
1536
  }
1578
1537
  const session = this.sessions.get(params.sessionId);
1579
1538
  if (!session) {
1580
1539
  throw new Error(`Session not found: ${params.sessionId}`);
1581
1540
  }
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
- };
1541
+ const canvas = session.getCanvas(params.canvasId);
1542
+ if (!canvas) {
1543
+ throw new Error(`No canvas registered with id "${params.canvasId}"`);
1594
1544
  }
1545
+ return dispatchCanvasProviderRequest(canvas, actionName, params);
1595
1546
  }
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;
1547
+ async handleCanvasActionInvokeRequest(params) {
1548
+ if (!isCanvasActionInvokeParams(params)) {
1549
+ throw new Error("Invalid canvas provider request payload");
1607
1550
  }
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;
1551
+ return this.handleCanvasProviderRequest(params.actionName, params);
1617
1552
  }
1618
1553
  }
1619
1554
  export {
@@ -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 CanvasActionContext, type CanvasDeclaration, type CanvasHostContext, type CanvasJsonSchema, type CanvasLifecycleContext, type CanvasOpenContext, type CanvasOpenResponse, 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
  };