@github/copilot-sdk 1.0.17-preview.1 → 1.0.17-preview.10

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.
@@ -38,6 +38,18 @@ function copyDefinedWorkflowAgentOption(source, target, key) {
38
38
  target[key] = value;
39
39
  }
40
40
  }
41
+ function toToolDefinition(tool) {
42
+ return {
43
+ name: tool.name,
44
+ description: tool.description ?? "",
45
+ parameters: (0, import_schema.toJsonSchema)(tool.parameters),
46
+ overridesBuiltInTool: tool.overridesBuiltInTool,
47
+ skipPermission: tool.skipPermission,
48
+ defer: tool.defer,
49
+ metadata: tool.metadata,
50
+ isTerminal: tool.isTerminal
51
+ };
52
+ }
41
53
  const workflowExecutionStore = new import_node_async_hooks.AsyncLocalStorage();
42
54
  function throwIfWorkflowExecutionIsActive() {
43
55
  if (workflowExecutionStore.getStore()?.active) {
@@ -258,6 +270,8 @@ class CopilotSession {
258
270
  eventHandlers = /* @__PURE__ */ new Set();
259
271
  typedEventHandlers = /* @__PURE__ */ new Map();
260
272
  toolHandlers = /* @__PURE__ */ new Map();
273
+ /** Settles once every earlier `setTools` call has finished. */
274
+ setToolsQueue = Promise.resolve();
261
275
  pendingExternalTools = /* @__PURE__ */ new Map();
262
276
  canvases = /* @__PURE__ */ new Map();
263
277
  bearerTokenProviders = /* @__PURE__ */ new Map();
@@ -270,6 +284,7 @@ class CopilotSession {
270
284
  elicitationHandler;
271
285
  exitPlanModeHandler;
272
286
  autoModeSwitchHandler;
287
+ skillProvider;
273
288
  hooks;
274
289
  transformCallbacks;
275
290
  _rpc = null;
@@ -682,6 +697,7 @@ class CopilotSession {
682
697
  this.elicitationHandler = void 0;
683
698
  this.exitPlanModeHandler = void 0;
684
699
  this.autoModeSwitchHandler = void 0;
700
+ this.skillProvider = void 0;
685
701
  this.commandHandlers.clear();
686
702
  this.canvases.clear();
687
703
  this.workflows.clear();
@@ -1069,7 +1085,20 @@ class CopilotSession {
1069
1085
  }
1070
1086
  for (const tool of tools) {
1071
1087
  if (tool.handler) {
1072
- this.toolHandlers.set(tool.name, tool.handler);
1088
+ const handler = tool.handler;
1089
+ if (tool.name === "apply_patch" && tool.overridesBuiltInTool && (0, import_schema.toJsonSchema)(tool.parameters)?.type === "string") {
1090
+ this.toolHandlers.set(tool.name, (args, invocation) => {
1091
+ if (typeof args === "string") {
1092
+ return handler(args, invocation);
1093
+ }
1094
+ if (typeof args === "object" && args !== null && "input" in args && typeof args.input === "string") {
1095
+ return handler(args.input, invocation);
1096
+ }
1097
+ throw new TypeError("apply_patch string override requires a string input");
1098
+ });
1099
+ } else {
1100
+ this.toolHandlers.set(tool.name, handler);
1101
+ }
1073
1102
  }
1074
1103
  }
1075
1104
  }
@@ -1575,6 +1604,68 @@ class CopilotSession {
1575
1604
  registerUserInputHandler(handler) {
1576
1605
  this.userInputHandler = handler;
1577
1606
  }
1607
+ /**
1608
+ * Registers the session's skill provider.
1609
+ *
1610
+ * @param provider - The skill provider, or undefined to remove it
1611
+ * @internal This method is typically called internally when creating a session.
1612
+ */
1613
+ registerSkillProvider(provider) {
1614
+ this.skillProvider = provider;
1615
+ }
1616
+ /**
1617
+ * Handles a `skillProvider.list` request from the runtime.
1618
+ *
1619
+ * @internal This method is for internal use by the SDK.
1620
+ */
1621
+ async _handleSkillProviderList(token) {
1622
+ const provider = this.requireSkillProvider();
1623
+ return await this.callSkillProvider("listSkills", token, async (options) => ({
1624
+ skills: await provider.listSkills(options) ?? []
1625
+ }));
1626
+ }
1627
+ /**
1628
+ * Handles a `skillProvider.read` request from the runtime.
1629
+ *
1630
+ * @internal This method is for internal use by the SDK.
1631
+ */
1632
+ async _handleSkillProviderRead(name, token) {
1633
+ const provider = this.requireSkillProvider();
1634
+ return await this.callSkillProvider("readSkill", token, async (options) => ({
1635
+ markdown: await provider.readSkill(name, options) ?? null
1636
+ }));
1637
+ }
1638
+ requireSkillProvider() {
1639
+ if (!this.skillProvider) {
1640
+ throw new Error(`No skill provider for session: ${this.sessionId}`);
1641
+ }
1642
+ return this.skillProvider;
1643
+ }
1644
+ /**
1645
+ * Runs a provider call with an abort signal tied to the runtime's request
1646
+ * cancellation. Failures are logged locally and reported generically.
1647
+ */
1648
+ async callSkillProvider(operation, token, call) {
1649
+ const controller = new AbortController();
1650
+ const subscription = token?.onCancellationRequested(() => controller.abort());
1651
+ if (token?.isCancellationRequested) {
1652
+ controller.abort();
1653
+ }
1654
+ try {
1655
+ return await call({ signal: controller.signal });
1656
+ } catch (error) {
1657
+ if (controller.signal.aborted) {
1658
+ throw new import_node.ResponseError(-32800, `Skill provider ${operation} cancelled`);
1659
+ }
1660
+ console.error(`Skill provider ${operation} failed`, {
1661
+ sessionId: this.sessionId,
1662
+ error
1663
+ });
1664
+ throw skillProviderFailure(operation);
1665
+ } finally {
1666
+ subscription?.dispose();
1667
+ }
1668
+ }
1578
1669
  /**
1579
1670
  * Registers hook handlers for session lifecycle events.
1580
1671
  *
@@ -1664,7 +1755,9 @@ class CopilotSession {
1664
1755
  sessionStart: this.hooks.onSessionStart,
1665
1756
  sessionEnd: this.hooks.onSessionEnd,
1666
1757
  errorOccurred: this.hooks.onErrorOccurred,
1667
- agentStop: this.hooks.onAgentStop
1758
+ agentStop: this.hooks.onAgentStop,
1759
+ subagentStart: this.hooks.onSubagentStart,
1760
+ subagentStop: this.hooks.onSubagentStop
1668
1761
  };
1669
1762
  const handler = handlerMap[hookType];
1670
1763
  if (!handler) {
@@ -1828,6 +1921,59 @@ class CopilotSession {
1828
1921
  async setAutoTier(autoTier) {
1829
1922
  return await this.rpc.model.switchAutoTier({ autoTier });
1830
1923
  }
1924
+ /**
1925
+ * Replace the tools this client supplies to the session.
1926
+ *
1927
+ * `tools` becomes the complete set of tools this client implements,
1928
+ * replacing the ones it supplied when the session was created or resumed,
1929
+ * or in an earlier call. Built-in, MCP, and plugin tools, and tools other
1930
+ * connected clients supply, are unaffected. Pass an empty array to remove
1931
+ * all of this client's tools.
1932
+ *
1933
+ * Tools are defined the same way as for `createSession`: calls to tools
1934
+ * with a `handler` are dispatched to it, and tools without one are
1935
+ * declaration-only. Once the runtime accepts the replacement, every tool
1936
+ * call this session dispatches uses the new handlers; calls already
1937
+ * running finish on their original handlers. If the runtime rejects the
1938
+ * replacement, this rejects and the previous tools and handlers stay in
1939
+ * place. Concurrent calls on the same session are applied one at a time,
1940
+ * in the order they are made.
1941
+ *
1942
+ * The agent sees the new tools from its next model request, which can fall
1943
+ * within a turn in progress. A model request already in flight was made
1944
+ * with the previous tools, so the agent can still call a tool you removed.
1945
+ * This session doesn't answer that call, and it can stay pending until the
1946
+ * turn is aborted. If a running turn might still call a tool you remove,
1947
+ * replace tools while the session is idle.
1948
+ *
1949
+ * @param tools - The complete set of tools this client supplies
1950
+ *
1951
+ * @experimental Wraps the experimental `session.tools.set` RPC and may change
1952
+ * or be removed in a future release.
1953
+ *
1954
+ * @example
1955
+ * ```typescript
1956
+ * await session.setTools([
1957
+ * defineTool("search_issues", {
1958
+ * description: "Search the issues shown on the current page",
1959
+ * parameters: z.object({ query: z.string() }),
1960
+ * handler: async ({ query }) => searchIssues(query),
1961
+ * }),
1962
+ * ]);
1963
+ * ```
1964
+ */
1965
+ async setTools(tools) {
1966
+ const definitions = tools.map(toToolDefinition);
1967
+ const replacement = this.setToolsQueue.then(async () => {
1968
+ await this.rpc.tools.set({ tools: definitions });
1969
+ this.registerTools(tools);
1970
+ });
1971
+ this.setToolsQueue = replacement.then(
1972
+ () => void 0,
1973
+ () => void 0
1974
+ );
1975
+ await replacement;
1976
+ }
1831
1977
  /**
1832
1978
  * Log a message to the session timeline.
1833
1979
  * The message appears in the session event stream and is visible to SDK consumers
@@ -1873,6 +2019,9 @@ function toCanvasRpcError(error) {
1873
2019
  const message = error instanceof Error ? error.message : String(error);
1874
2020
  return new import_node.ResponseError(import_node.ErrorCodes.InternalError, message, { code, message });
1875
2021
  }
2022
+ function skillProviderFailure(operation) {
2023
+ return new import_node.ResponseError(import_node.ErrorCodes.InternalError, `Skill provider ${operation} failed`);
2024
+ }
1876
2025
  function strictJsonValidationError(context, category, message, path) {
1877
2026
  return new import_node.ResponseError(import_node.ErrorCodes.InternalError, message, {
1878
2027
  code: context.code,
@@ -19,9 +19,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var sessionFsProvider_exports = {};
20
20
  __export(sessionFsProvider_exports, {
21
21
  SessionFsSqliteTransactionFailure: () => SessionFsSqliteTransactionFailure,
22
+ SessionFsWriteFailure: () => SessionFsWriteFailure,
22
23
  createSessionFsAdapter: () => createSessionFsAdapter
23
24
  });
24
25
  module.exports = __toCommonJS(sessionFsProvider_exports);
26
+ const MAX_BINARY_BYTES = (64 * 1024 * 1024 - 1024) / 4 * 3;
27
+ const MAX_BINARY_CONTENT_LENGTH = Math.ceil(MAX_BINARY_BYTES / 3) * 4;
25
28
  class SessionFsSqliteTransactionFailure extends Error {
26
29
  /** Failure classification reported to the runtime. */
27
30
  errorClass;
@@ -31,6 +34,9 @@ class SessionFsSqliteTransactionFailure extends Error {
31
34
  this.errorClass = errorClass;
32
35
  }
33
36
  }
37
+ class SessionFsWriteFailure extends Error {
38
+ writeChanged = true;
39
+ }
34
40
  function normalizeSqliteParams(params) {
35
41
  if (!params) {
36
42
  return void 0;
@@ -53,10 +59,60 @@ function createSessionFsAdapter(provider) {
53
59
  return { content: "", error: toSessionFsError(err) };
54
60
  }
55
61
  },
62
+ readFileBytes: async ({ path }) => {
63
+ if (!provider.readFileBytes) {
64
+ return {
65
+ content: "",
66
+ error: { code: "UNKNOWN", message: "Binary reads are not supported" }
67
+ };
68
+ }
69
+ try {
70
+ const bytes = await provider.readFileBytes(path);
71
+ if (bytes.length > MAX_BINARY_BYTES) {
72
+ return {
73
+ content: "",
74
+ error: {
75
+ code: "UNKNOWN",
76
+ message: "sessionFs.readFileBytes content exceeds the binary read limit"
77
+ }
78
+ };
79
+ }
80
+ return {
81
+ content: Buffer.from(bytes).toString("base64")
82
+ };
83
+ } catch (err) {
84
+ return { content: "", error: toSessionFsError(err) };
85
+ }
86
+ },
56
87
  writeFile: async ({ path, content, mode }) => {
57
88
  try {
58
89
  await provider.writeFile(path, content, mode);
59
90
  return void 0;
91
+ } catch (err) {
92
+ const error = toSessionFsError(err);
93
+ return err instanceof SessionFsWriteFailure ? { ...error, writeChanged: true } : error;
94
+ }
95
+ },
96
+ writeFileBytes: async ({ path, content, mode }) => {
97
+ if (!provider.writeFileBytes) {
98
+ return { code: "UNKNOWN", message: "Binary writes are not supported" };
99
+ }
100
+ if (content.length > MAX_BINARY_CONTENT_LENGTH) {
101
+ return {
102
+ code: "UNKNOWN",
103
+ message: "sessionFs.writeFileBytes content exceeds the binary write limit"
104
+ };
105
+ }
106
+ const bytes = Buffer.from(content, "base64");
107
+ if (bytes.toString("base64") !== content || bytes.length > MAX_BINARY_BYTES) {
108
+ return {
109
+ code: "UNKNOWN",
110
+ message: "invalid sessionFs.writeFileBytes base64 content"
111
+ };
112
+ }
113
+ try {
114
+ await provider.writeFileBytes(path, bytes, mode);
115
+ return void 0;
60
116
  } catch (err) {
61
117
  return toSessionFsError(err);
62
118
  }
@@ -194,5 +250,6 @@ function toSqliteTransactionError(err) {
194
250
  // Annotate the CommonJS export names for ESM import in node:
195
251
  0 && (module.exports = {
196
252
  SessionFsSqliteTransactionFailure,
253
+ SessionFsWriteFailure,
197
254
  createSessionFsAdapter
198
255
  });
package/dist/cjs/types.js CHANGED
@@ -26,6 +26,7 @@ __export(types_exports, {
26
26
  RuntimeConnection: () => RuntimeConnection,
27
27
  SYSTEM_MESSAGE_SECTIONS: () => SYSTEM_MESSAGE_SECTIONS,
28
28
  SessionFsSqliteTransactionFailure: () => import_sessionFsProvider2.SessionFsSqliteTransactionFailure,
29
+ SessionFsWriteFailure: () => import_sessionFsProvider3.SessionFsWriteFailure,
29
30
  approveAll: () => approveAll,
30
31
  convertMcpCallToolResult: () => convertMcpCallToolResult,
31
32
  createAttributedPermissionResult: () => createAttributedPermissionResult,
@@ -37,6 +38,7 @@ __export(types_exports, {
37
38
  module.exports = __toCommonJS(types_exports);
38
39
  var import_sessionFsProvider = require("./sessionFsProvider.js");
39
40
  var import_sessionFsProvider2 = require("./sessionFsProvider.js");
41
+ var import_sessionFsProvider3 = require("./sessionFsProvider.js");
40
42
  var import_copilotRequestHandler = require("./copilotRequestHandler.js");
41
43
  const RuntimeConnection = {
42
44
  /**
@@ -138,10 +140,10 @@ const SYSTEM_MESSAGE_SECTIONS = {
138
140
  tool_instructions: { description: "Per-tool usage instructions" },
139
141
  custom_instructions: { description: "Repository and organization custom instructions" },
140
142
  runtime_instructions: {
141
- description: "Runtime-provided context and instructions (e.g. system notifications, memories, workspace context, mode-specific instructions, content-exclusion policy)"
143
+ description: "Runtime-provided system-prompt context and instructions, such as system notifications, memories, workspace context, and content-exclusion policy. Mode-specific instructions can travel in transition messages instead."
142
144
  },
143
145
  last_instructions: {
144
- description: "End-of-prompt instructions: parallel tool calling, persistence, task completion"
146
+ description: "End-of-prompt instructions: parallel tool calling, persistence, task completion, and configured subagent-model guidance when the task tool is available"
145
147
  }
146
148
  };
147
149
  function isAttributedPermissionResult(result) {
@@ -182,6 +184,7 @@ const DisableBypassPermissionsModes = {
182
184
  RuntimeConnection,
183
185
  SYSTEM_MESSAGE_SECTIONS,
184
186
  SessionFsSqliteTransactionFailure,
187
+ SessionFsWriteFailure,
185
188
  approveAll,
186
189
  convertMcpCallToolResult,
187
190
  createAttributedPermissionResult,
@@ -1,2 +1,2 @@
1
- export declare const COPILOT_CLI_VERSION = "1.0.92-1";
1
+ export declare const COPILOT_CLI_VERSION = "1.0.93-4";
2
2
  export declare const COPILOT_CLI_USE_NPM_PACKAGE = false;
@@ -1,4 +1,4 @@
1
- const COPILOT_CLI_VERSION = "1.0.92-1";
1
+ const COPILOT_CLI_VERSION = "1.0.93-4";
2
2
  const COPILOT_CLI_USE_NPM_PACKAGE = false;
3
3
  export {
4
4
  COPILOT_CLI_USE_NPM_PACKAGE,
package/dist/client.d.ts CHANGED
@@ -507,6 +507,7 @@ export declare class CopilotClient {
507
507
  private handleUserInputRequest;
508
508
  private handleExitPlanModeRequest;
509
509
  private handleAutoModeSwitchRequest;
510
+ private resolveSkillProviderSession;
510
511
  private handleHooksInvoke;
511
512
  private handleSystemMessageTransform;
512
513
  }
package/dist/client.js CHANGED
@@ -32,6 +32,7 @@ import { ToolSet } from "./toolSet.js";
32
32
  import { defaultJoinSessionPermissionHandler } from "./types.js";
33
33
  const MIN_PROTOCOL_VERSION = 3;
34
34
  const RUNTIME_SHUTDOWN_TIMEOUT_MS = 1e4;
35
+ const CLOUD_SESSION_CLEANUP_TIMEOUT_MS = 1e4;
35
36
  function createMessageConnection(reader, writer) {
36
37
  let dispatch;
37
38
  let finishDrain;
@@ -560,6 +561,11 @@ class CopilotClient {
560
561
  "SessionFsConfig declares capabilities.sqlite but the provider does not implement sqlite."
561
562
  );
562
563
  }
564
+ if (this.sessionFsConfig.capabilities?.binary && (!provider.readFileBytes || !provider.writeFileBytes)) {
565
+ throw new Error(
566
+ "SessionFsConfig declares capabilities.binary but the provider does not implement readFileBytes and writeFileBytes."
567
+ );
568
+ }
563
569
  session.clientSessionApis.sessionFs = createSessionFsAdapter(provider);
564
570
  }
565
571
  setupClientGlobalHandlers() {
@@ -1178,6 +1184,9 @@ class CopilotClient {
1178
1184
  if (config.gitHubToken !== void 0 && config.gitHubTokenProvider !== void 0) {
1179
1185
  throw new Error("gitHubToken and gitHubTokenProvider are mutually exclusive");
1180
1186
  }
1187
+ if (config.cloud != null && config.skillProvider) {
1188
+ throw new Error("Skill providers are not supported for cloud sessions.");
1189
+ }
1181
1190
  if (!this.connection) {
1182
1191
  await this.start();
1183
1192
  }
@@ -1237,18 +1246,22 @@ class CopilotClient {
1237
1246
  if (config.hooks) {
1238
1247
  s.registerHooks(config.hooks);
1239
1248
  }
1249
+ if (config.skillProvider) {
1250
+ s.registerSkillProvider(config.skillProvider);
1251
+ }
1240
1252
  if (transformCallbacks) {
1241
1253
  s.registerTransformCallbacks(transformCallbacks);
1242
1254
  }
1243
1255
  if (config.onEvent) {
1244
1256
  s.on(config.onEvent);
1245
1257
  }
1246
- this.sessions.set(sessionId, s);
1247
1258
  this.setupSessionFs(s, config);
1259
+ this.sessions.set(sessionId, s);
1248
1260
  return s;
1249
1261
  };
1250
1262
  let session;
1251
1263
  let registeredId;
1264
+ let uninitializedCloudSessionId;
1252
1265
  if (localSessionId !== void 0) {
1253
1266
  try {
1254
1267
  session = initializeSession(localSessionId);
@@ -1342,6 +1355,7 @@ class CopilotClient {
1342
1355
  enableSessionStore: config.enableSessionStore,
1343
1356
  enableSkills: config.enableSkills,
1344
1357
  skillDirectories: config.skillDirectories,
1358
+ ...config.skillProvider ? { hasSkillProvider: true } : {},
1345
1359
  pluginDirectories: config.pluginDirectories,
1346
1360
  instructionDirectories: config.instructionDirectories,
1347
1361
  disabledSkills: config.disabledSkills,
@@ -1371,7 +1385,9 @@ class CopilotClient {
1371
1385
  );
1372
1386
  }
1373
1387
  if (session === void 0) {
1388
+ uninitializedCloudSessionId = returnedSessionId;
1374
1389
  session = initializeSession(returnedSessionId);
1390
+ uninitializedCloudSessionId = void 0;
1375
1391
  registeredId = returnedSessionId;
1376
1392
  }
1377
1393
  this.assignGitHubTokenProvider(gitHubTokenProviderRegistrationId, returnedSessionId);
@@ -1393,6 +1409,20 @@ class CopilotClient {
1393
1409
  if (gitHubTokenProviderRegistrationId !== void 0) {
1394
1410
  this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1395
1411
  }
1412
+ if (uninitializedCloudSessionId !== void 0) {
1413
+ try {
1414
+ await withTimeout(
1415
+ this.deleteSession(uninitializedCloudSessionId),
1416
+ CLOUD_SESSION_CLEANUP_TIMEOUT_MS,
1417
+ `session.delete timed out after ${CLOUD_SESSION_CLEANUP_TIMEOUT_MS}ms`
1418
+ );
1419
+ } catch (cleanupError) {
1420
+ throw new AggregateError(
1421
+ [e, cleanupError],
1422
+ "Failed to initialize and delete cloud session"
1423
+ );
1424
+ }
1425
+ }
1396
1426
  throw e;
1397
1427
  }
1398
1428
  for (const entry of this.hostHandoffs.values()) {
@@ -1479,6 +1509,9 @@ class CopilotClient {
1479
1509
  if (config.hooks) {
1480
1510
  session.registerHooks(config.hooks);
1481
1511
  }
1512
+ if (config.skillProvider) {
1513
+ session.registerSkillProvider(config.skillProvider);
1514
+ }
1482
1515
  const modeDefaults = this.configDefaultsForMode();
1483
1516
  config = { ...modeDefaults, ...config };
1484
1517
  config.customAgentsLocalOnly ??= modeDefaults.customAgentsLocalOnly;
@@ -1492,9 +1525,10 @@ class CopilotClient {
1492
1525
  if (config.onEvent) {
1493
1526
  session.on(config.onEvent);
1494
1527
  }
1495
- this.sessions.set(sessionId, session);
1496
- this.setupSessionFs(session, config);
1497
1528
  const toolFilterOptions = this.resolveToolFilterOptions(config);
1529
+ this.setupSessionFs(session, config);
1530
+ const replacedSession = this.sessions.get(sessionId);
1531
+ this.sessions.set(sessionId, session);
1498
1532
  const gitHubTokenProviderRegistrationId = this.registerGitHubTokenProvider(
1499
1533
  config.gitHubTokenProvider,
1500
1534
  sessionId
@@ -1587,6 +1621,7 @@ class CopilotClient {
1587
1621
  defaultAgent: config.defaultAgent,
1588
1622
  agent: config.agent,
1589
1623
  skillDirectories: config.skillDirectories,
1624
+ ...config.skillProvider ? { hasSkillProvider: true } : {},
1590
1625
  pluginDirectories: config.pluginDirectories,
1591
1626
  instructionDirectories: config.instructionDirectories,
1592
1627
  disabledSkills: config.disabledSkills,
@@ -1631,7 +1666,13 @@ class CopilotClient {
1631
1666
  this.commitGitHubTokenProvider(sessionId, gitHubTokenProviderRegistrationId);
1632
1667
  } catch (e) {
1633
1668
  session._markDisconnected();
1634
- this.sessions.delete(sessionId);
1669
+ if (this.sessions.get(sessionId) === session) {
1670
+ if (replacedSession) {
1671
+ this.sessions.set(sessionId, replacedSession);
1672
+ } else {
1673
+ this.sessions.delete(sessionId);
1674
+ }
1675
+ }
1635
1676
  if (gitHubTokenProviderRegistrationId !== void 0) {
1636
1677
  this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
1637
1678
  }
@@ -2607,6 +2648,20 @@ stderr: ${stderrOutput}` : ""}`
2607
2648
  return await this.handleHooksInvoke(params);
2608
2649
  }
2609
2650
  );
2651
+ this.connection.onRequest(
2652
+ "skillProvider.list",
2653
+ async (params, token) => await this.resolveSkillProviderSession(params)._handleSkillProviderList(token)
2654
+ );
2655
+ this.connection.onRequest(
2656
+ "skillProvider.read",
2657
+ async (params, token) => {
2658
+ const session = this.resolveSkillProviderSession(params);
2659
+ if (typeof params.name !== "string") {
2660
+ throw new Error("Invalid skillProvider.read payload");
2661
+ }
2662
+ return await session._handleSkillProviderRead(params.name, token);
2663
+ }
2664
+ );
2610
2665
  const connection = this.connection;
2611
2666
  const messageWriter = this.messageWriter;
2612
2667
  const cliProcess = this.isExternalServer ? null : this.cliProcess;
@@ -2763,6 +2818,16 @@ stderr: ${stderrOutput}` : ""}`
2763
2818
  });
2764
2819
  return { response };
2765
2820
  }
2821
+ resolveSkillProviderSession(params) {
2822
+ if (!params || typeof params.sessionId !== "string") {
2823
+ throw new Error("Invalid skillProvider payload");
2824
+ }
2825
+ const session = this.sessions.get(params.sessionId);
2826
+ if (!session) {
2827
+ throw new Error(`Session not found: ${params.sessionId}`);
2828
+ }
2829
+ return session;
2830
+ }
2766
2831
  async handleHooksInvoke(params) {
2767
2832
  if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
2768
2833
  throw new Error("Invalid hooks invoke payload");
@@ -2,7 +2,7 @@ import type { CopilotSession } from "./session.js";
2
2
  import { type PermissionHandler, type ResumeSessionConfig } from "./types.js";
3
3
  import type { WorkflowHandle } from "./workflow.js";
4
4
  export { Canvas, CanvasError, createCanvas, type CanvasAction, type CanvasDeclaration, type CanvasHostContext, type CanvasJsonSchema, type CanvasOptions, } from "./canvas.js";
5
- export type JoinSessionConfig = Omit<ResumeSessionConfig, "onPermissionRequest" | "extensionSdkPath"> & {
5
+ export type JoinSessionConfig = Omit<ResumeSessionConfig, "onPermissionRequest" | "extensionSdkPath" | "skillProvider"> & {
6
6
  onPermissionRequest?: PermissionHandler;
7
7
  /**
8
8
  * Names of sensitive environment variables this extension needs, such as
package/dist/extension.js CHANGED
@@ -22,11 +22,13 @@ async function joinSession(config = {}) {
22
22
  const client = new CopilotClient({ _internalConnection: { kind: "parent-process" } });
23
23
  const {
24
24
  extensionSdkPath: _stripped,
25
+ skillProvider: _strippedSkillProvider,
25
26
  workflows,
26
27
  requestedEnvironmentVariables,
27
28
  ...rest
28
29
  } = config;
29
30
  void _stripped;
31
+ void _strippedSkillProvider;
30
32
  return client.resumeSessionForExtension(
31
33
  sessionId,
32
34
  {