@github/copilot-sdk 1.0.8 → 1.0.9-preview.1

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
@@ -71,6 +71,12 @@ await using session = await client.createSession({
71
71
  // session is automatically disconnected when leaving scope
72
72
  ```
73
73
 
74
+ When targeting MCP tools configured through `mcpServers`, remember the runtime
75
+ tool name is `<server-key>-<tool-name>`. For `availableTools` and
76
+ `excludedTools`, prefer `new ToolSet().addMcp("<server-key>-<tool-name>")` or
77
+ the raw `mcp:<server-key>-<tool-name>` form. For `customAgents[].tools` and
78
+ `defaultAgent.excludedTools`, use `<server-key>-<tool-name>` directly.
79
+
74
80
  ## API Reference
75
81
 
76
82
  ### CopilotClient
@@ -751,7 +757,7 @@ The SDK supports custom OpenAI-compatible API providers (BYOK - Bring Your Own K
751
757
  - `apiKey?: string` - API key (optional for local providers like Ollama)
752
758
  - `bearerToken?: string` - Bearer token for authentication (takes precedence over apiKey)
753
759
  - `wireApi?: "completions" | "responses"` - API format for OpenAI/Azure (default: "completions")
754
- - `azure?.apiVersion?: string` - Azure API version (default: "2024-10-21")
760
+ - `azure?.apiVersion?: string` - Azure API version; when omitted, the runtime uses the GA versionless `v1` route
755
761
 
756
762
  **Example with Ollama:**
757
763
 
@@ -1058,6 +1064,16 @@ const session = await client.createSession({
1058
1064
  errorHandling: "retry", // "retry", "skip", or "abort"
1059
1065
  };
1060
1066
  },
1067
+
1068
+ // Called when the top-level agent naturally stops
1069
+ onAgentStop: async (input, invocation) => {
1070
+ if (!input.stopHookActive && needsMoreWork()) {
1071
+ return {
1072
+ decision: "block",
1073
+ reason: "Run the final validation and fix any failures.",
1074
+ };
1075
+ }
1076
+ },
1061
1077
  },
1062
1078
  });
1063
1079
  ```
@@ -1071,6 +1087,7 @@ const session = await client.createSession({
1071
1087
  - `onSessionStart` - Run logic when a session starts or resumes.
1072
1088
  - `onSessionEnd` - Cleanup or logging when session ends.
1073
1089
  - `onErrorOccurred` - Handle errors with retry/skip/abort strategies.
1090
+ - `onAgentStop` - Observe natural top-level agent completion. Return `{ decision: "block", reason }` to request another turn; use `stopHookActive` to avoid repeated blocks.
1074
1091
 
1075
1092
  ## Error Handling
1076
1093
 
@@ -1203,6 +1203,13 @@ class CopilotClient {
1203
1203
  * ```
1204
1204
  */
1205
1205
  async resumeSession(sessionId, config) {
1206
+ return this.resumeSessionInternal(sessionId, config);
1207
+ }
1208
+ /** @internal */
1209
+ async resumeSessionForExtension(sessionId, config, factories) {
1210
+ return this.resumeSessionInternal(sessionId, config, factories);
1211
+ }
1212
+ async resumeSessionInternal(sessionId, config, factories) {
1206
1213
  if (!this.connection) {
1207
1214
  await this.start();
1208
1215
  }
@@ -1216,6 +1223,7 @@ class CopilotClient {
1216
1223
  session.registerTools(config.tools);
1217
1224
  session.registerCanvases(config.canvases);
1218
1225
  session.registerCommands(config.commands);
1226
+ session.registerFactories(factories);
1219
1227
  const {
1220
1228
  wireProvider: bearerWireProvider,
1221
1229
  wireProviders: bearerWireProviders,
@@ -1282,6 +1290,7 @@ class CopilotClient {
1282
1290
  })),
1283
1291
  toolSearch: config.toolSearch,
1284
1292
  canvases: config.canvases?.map((canvas) => canvas.declaration),
1293
+ factories: factories?.map((factory) => factory.meta),
1285
1294
  requestCanvasRenderer: config.requestCanvasRenderer,
1286
1295
  requestExtensions: config.requestExtensions,
1287
1296
  extensionSdkPath: config.extensionSdkPath,
@@ -20,13 +20,17 @@ var extension_exports = {};
20
20
  __export(extension_exports, {
21
21
  Canvas: () => import_canvas.Canvas,
22
22
  CanvasError: () => import_canvas.CanvasError,
23
+ FactoryResumeError: () => import_factory.FactoryResumeError,
23
24
  createCanvas: () => import_canvas.createCanvas,
25
+ defineFactory: () => import_factory.defineFactory,
26
+ isFactoryRunTerminal: () => import_factory.isFactoryRunTerminal,
24
27
  joinSession: () => joinSession
25
28
  });
26
29
  module.exports = __toCommonJS(extension_exports);
27
30
  var import_client = require("./client.js");
28
31
  var import_types = require("./types.js");
29
32
  var import_canvas = require("./canvas.js");
33
+ var import_factory = require("./factory.js");
30
34
  async function joinSession(config = {}) {
31
35
  const sessionId = process.env.SESSION_ID;
32
36
  if (!sessionId) {
@@ -35,18 +39,29 @@ async function joinSession(config = {}) {
35
39
  );
36
40
  }
37
41
  const client = new import_client.CopilotClient({ _internalConnection: { kind: "parent-process" } });
38
- const { extensionSdkPath: _stripped, ...rest } = config;
42
+ const {
43
+ extensionSdkPath: _stripped,
44
+ factories,
45
+ ...rest
46
+ } = config;
39
47
  void _stripped;
40
- return client.resumeSession(sessionId, {
41
- ...rest,
42
- onPermissionRequest: config.onPermissionRequest ?? import_types.defaultJoinSessionPermissionHandler,
43
- suppressResumeEvent: config.suppressResumeEvent ?? true
44
- });
48
+ return client.resumeSessionForExtension(
49
+ sessionId,
50
+ {
51
+ ...rest,
52
+ onPermissionRequest: config.onPermissionRequest ?? import_types.defaultJoinSessionPermissionHandler,
53
+ suppressResumeEvent: config.suppressResumeEvent ?? true
54
+ },
55
+ factories
56
+ );
45
57
  }
46
58
  // Annotate the CommonJS export names for ESM import in node:
47
59
  0 && (module.exports = {
48
60
  Canvas,
49
61
  CanvasError,
62
+ FactoryResumeError,
50
63
  createCanvas,
64
+ defineFactory,
65
+ isFactoryRunTerminal,
51
66
  joinSession
52
67
  });
@@ -0,0 +1,123 @@
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 factory_exports = {};
20
+ __export(factory_exports, {
21
+ FactoryResumeError: () => FactoryResumeError,
22
+ defineFactory: () => defineFactory,
23
+ getFactoryDefinition: () => getFactoryDefinition,
24
+ isFactoryRunTerminal: () => isFactoryRunTerminal
25
+ });
26
+ module.exports = __toCommonJS(factory_exports);
27
+ const FACTORY_TERMINAL_STATUSES = /* @__PURE__ */ new Set([
28
+ "completed",
29
+ "halted",
30
+ "cancelled",
31
+ "error"
32
+ ]);
33
+ function isFactoryRunTerminal(status) {
34
+ return FACTORY_TERMINAL_STATUSES.has(status);
35
+ }
36
+ class FactoryResumeError extends Error {
37
+ constructor(code, message) {
38
+ super(message);
39
+ this.code = code;
40
+ this.name = "FactoryResumeError";
41
+ }
42
+ code;
43
+ }
44
+ const factoryHandles = /* @__PURE__ */ new WeakMap();
45
+ const MAX_FACTORY_TIMEOUT_SECONDS = 2147483647e-3;
46
+ const NANO_AIU_PER_AIU = 1e9;
47
+ function deepFreeze(value) {
48
+ if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
49
+ Object.freeze(value);
50
+ for (const nested of Object.values(value)) {
51
+ deepFreeze(nested);
52
+ }
53
+ }
54
+ return value;
55
+ }
56
+ function validateLimits(meta) {
57
+ const limits = meta.limits;
58
+ if (!limits) {
59
+ return;
60
+ }
61
+ for (const field of ["maxConcurrentSubagents", "maxTotalSubagents"]) {
62
+ const value = limits[field];
63
+ if (value !== void 0 && (!Number.isInteger(value) || value <= 0)) {
64
+ throw new Error(`Factory limit "${field}" must be a positive integer`);
65
+ }
66
+ }
67
+ if (limits.timeoutSeconds !== void 0 && (!Number.isFinite(limits.timeoutSeconds) || limits.timeoutSeconds <= 0)) {
68
+ throw new Error(
69
+ 'Factory limit "timeoutSeconds" must be a positive, finite number of seconds'
70
+ );
71
+ }
72
+ if (limits.timeoutSeconds !== void 0 && limits.timeoutSeconds > MAX_FACTORY_TIMEOUT_SECONDS) {
73
+ throw new Error(
74
+ `Factory limit "timeoutSeconds" must not exceed ${MAX_FACTORY_TIMEOUT_SECONDS} seconds`
75
+ );
76
+ }
77
+ if (limits.maxAiCredits !== void 0) {
78
+ const maxNanoAiu = Math.round(limits.maxAiCredits * NANO_AIU_PER_AIU);
79
+ if (!Number.isFinite(limits.maxAiCredits) || limits.maxAiCredits <= 0 || !Number.isSafeInteger(maxNanoAiu) || maxNanoAiu < 1) {
80
+ throw new Error(
81
+ 'Factory limit "maxAiCredits" must be a positive, finite number that rounds to a safe positive integer nano-AIU ceiling'
82
+ );
83
+ }
84
+ }
85
+ }
86
+ function validatePhases(meta) {
87
+ const titles = /* @__PURE__ */ new Set();
88
+ for (const phase of meta.phases) {
89
+ if (phase.title.trim().length === 0) {
90
+ throw new Error("Factory phase titles must not be empty");
91
+ }
92
+ if (titles.has(phase.title)) {
93
+ throw new Error(`Factory phase title "${phase.title}" is declared more than once`);
94
+ }
95
+ titles.add(phase.title);
96
+ }
97
+ }
98
+ function defineFactory(definition) {
99
+ const meta = deepFreeze(structuredClone(definition.meta));
100
+ validateLimits(meta);
101
+ validatePhases(meta);
102
+ const stored = {
103
+ meta,
104
+ run: definition.run
105
+ };
106
+ const handle = Object.freeze({ meta });
107
+ factoryHandles.set(handle, stored);
108
+ return handle;
109
+ }
110
+ function getFactoryDefinition(handle) {
111
+ const definition = factoryHandles.get(handle);
112
+ if (!definition) {
113
+ throw new Error("Invalid factory handle");
114
+ }
115
+ return definition;
116
+ }
117
+ // Annotate the CommonJS export names for ESM import in node:
118
+ 0 && (module.exports = {
119
+ FactoryResumeError,
120
+ defineFactory,
121
+ getFactoryDefinition,
122
+ isFactoryRunTerminal
123
+ });