@github/copilot-sdk 1.0.13 → 1.0.14-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 +16 -0
- package/dist/cjs/cliVersion.js +1 -1
- package/dist/cjs/client.js +19 -3
- package/dist/cjs/factory.js +1 -0
- package/dist/cjs/ffiRuntimeHost.js +140 -55
- package/dist/cjs/generated/rpc.js +59 -7
- package/dist/cjs/session.js +56 -8
- package/dist/cliVersion.d.ts +1 -1
- package/dist/cliVersion.js +1 -1
- package/dist/client.d.ts +3 -0
- package/dist/client.js +19 -3
- package/dist/factory.d.ts +42 -16
- package/dist/factory.js +1 -0
- package/dist/ffiRuntimeHost.d.ts +8 -2
- package/dist/ffiRuntimeHost.js +140 -55
- package/dist/generated/rpc.d.ts +706 -45
- package/dist/generated/rpc.js +59 -7
- package/dist/generated/session-events.d.ts +461 -17
- package/dist/index.d.ts +2 -2
- package/dist/session.d.ts +1 -0
- package/dist/session.js +57 -9
- package/dist/types.d.ts +18 -1
- package/docs/factories.md +36 -19
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -267,11 +267,26 @@ Send a message to the session. Returns immediately after the message is queued;
|
|
|
267
267
|
**Options:**
|
|
268
268
|
|
|
269
269
|
- `prompt: string` - The message/prompt to send
|
|
270
|
+
- `source?: MessageSource` - `"user"`, `"system"`, or `` `agent-${string}` `` provenance; omitted by default
|
|
270
271
|
- `attachments?: Array<{type, path, displayName}>` - File attachments
|
|
271
272
|
- `mode?: "enqueue" | "immediate"` - Delivery mode
|
|
272
273
|
|
|
273
274
|
Returns the message ID.
|
|
274
275
|
|
|
276
|
+
Use `source: "system"` for automated messages from your application:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
await session.send({ prompt: "Context updated", source: "system" });
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
For a message from another agent, use its trusted sender ID:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
await session.send({ prompt: "Review complete", source: "agent-reviewer-id" });
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Source is independent of delivery mode. Leaving it unset preserves the existing human-message payload; it does not set billing flags or use the notification API.
|
|
289
|
+
|
|
275
290
|
##### `sendAndWait(options: MessageOptions, timeout?: number): Promise<AssistantMessageEvent | undefined>`
|
|
276
291
|
|
|
277
292
|
Send a message and wait until the session becomes idle.
|
|
@@ -279,6 +294,7 @@ Send a message and wait until the session becomes idle.
|
|
|
279
294
|
**Options:**
|
|
280
295
|
|
|
281
296
|
- `prompt: string` - The message/prompt to send
|
|
297
|
+
- `source?: MessageSource` - Same optional provenance as `send`
|
|
282
298
|
- `attachments?: Array<{type, path, displayName}>` - File attachments
|
|
283
299
|
- `mode?: "enqueue" | "immediate"` - Delivery mode
|
|
284
300
|
- `timeout?: number` - Optional timeout in milliseconds
|
package/dist/cjs/cliVersion.js
CHANGED
|
@@ -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.
|
|
25
|
+
const COPILOT_CLI_VERSION = "1.0.84-5";
|
|
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 = {
|
package/dist/cjs/client.js
CHANGED
|
@@ -241,6 +241,8 @@ class CopilotClient {
|
|
|
241
241
|
runtimePort = null;
|
|
242
242
|
actualHost = "localhost";
|
|
243
243
|
state = "disconnected";
|
|
244
|
+
/** Shared in-flight start; concurrent callers await it instead of spawning another CLI. */
|
|
245
|
+
startPromise = null;
|
|
244
246
|
sessions = /* @__PURE__ */ new Map();
|
|
245
247
|
stderrBuffer = "";
|
|
246
248
|
// Captures CLI stderr for error messages
|
|
@@ -618,6 +620,17 @@ class CopilotClient {
|
|
|
618
620
|
if (this.state === "connected") {
|
|
619
621
|
return;
|
|
620
622
|
}
|
|
623
|
+
if (this.startPromise) {
|
|
624
|
+
return this.startPromise;
|
|
625
|
+
}
|
|
626
|
+
this.startPromise = this.doStart();
|
|
627
|
+
try {
|
|
628
|
+
await this.startPromise;
|
|
629
|
+
} finally {
|
|
630
|
+
this.startPromise = null;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
async doStart() {
|
|
621
634
|
this.forceStopping = false;
|
|
622
635
|
this.connectionClosed = false;
|
|
623
636
|
this.processTransportError = null;
|
|
@@ -807,7 +820,7 @@ class CopilotClient {
|
|
|
807
820
|
const host = this.ffiHost;
|
|
808
821
|
this.ffiHost = null;
|
|
809
822
|
try {
|
|
810
|
-
host.dispose();
|
|
823
|
+
await host.dispose();
|
|
811
824
|
} catch (error) {
|
|
812
825
|
errors.push(
|
|
813
826
|
new Error(
|
|
@@ -902,11 +915,12 @@ class CopilotClient {
|
|
|
902
915
|
this.cliProcess = null;
|
|
903
916
|
}
|
|
904
917
|
if (this.ffiHost) {
|
|
918
|
+
const host = this.ffiHost;
|
|
919
|
+
this.ffiHost = null;
|
|
905
920
|
try {
|
|
906
|
-
|
|
921
|
+
await host.dispose();
|
|
907
922
|
} catch {
|
|
908
923
|
}
|
|
909
|
-
this.ffiHost = null;
|
|
910
924
|
}
|
|
911
925
|
if (this.cliStartTimeout) {
|
|
912
926
|
clearTimeout(this.cliStartTimeout);
|
|
@@ -1223,6 +1237,7 @@ class CopilotClient {
|
|
|
1223
1237
|
...this.onGitHubTelemetry != null ? { enableGitHubTelemetryForwarding: true } : {},
|
|
1224
1238
|
mcpServers: toWireMcpServers(config.mcpServers),
|
|
1225
1239
|
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
1240
|
+
authClientIdMetadataUrl: config.authClientIdMetadataUrl,
|
|
1226
1241
|
envValueMode: "direct",
|
|
1227
1242
|
customAgents: toWireCustomAgents(config.customAgents),
|
|
1228
1243
|
customAgentsLocalOnly: config.customAgentsLocalOnly,
|
|
@@ -1468,6 +1483,7 @@ class CopilotClient {
|
|
|
1468
1483
|
...this.onGitHubTelemetry != null ? { enableGitHubTelemetryForwarding: true } : {},
|
|
1469
1484
|
mcpServers: toWireMcpServers(config.mcpServers),
|
|
1470
1485
|
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
1486
|
+
authClientIdMetadataUrl: config.authClientIdMetadataUrl,
|
|
1471
1487
|
envValueMode: "direct",
|
|
1472
1488
|
customAgents: toWireCustomAgents(config.customAgents),
|
|
1473
1489
|
customAgentsLocalOnly: config.customAgentsLocalOnly,
|
package/dist/cjs/factory.js
CHANGED
|
@@ -37,6 +37,7 @@ var import_node_path = require("node:path");
|
|
|
37
37
|
var import_node_stream = require("node:stream");
|
|
38
38
|
const SYMBOL_PREFIX = "copilot_runtime_";
|
|
39
39
|
const KEEP_ALIVE_INTERVAL_MS = 1 << 30;
|
|
40
|
+
const CLEANUP_RETRY_INTERVAL_MS = 100;
|
|
40
41
|
let loadedLibraryPath;
|
|
41
42
|
let loadedLibrary;
|
|
42
43
|
function loadLibrary(libraryPath) {
|
|
@@ -129,12 +130,16 @@ class FfiRuntimeHost {
|
|
|
129
130
|
cliEntrypoint;
|
|
130
131
|
environment;
|
|
131
132
|
args;
|
|
133
|
+
static quarantinedHosts = /* @__PURE__ */ new Set();
|
|
132
134
|
lib;
|
|
133
135
|
serverId = 0;
|
|
134
136
|
connectionId = 0;
|
|
135
137
|
disposed = false;
|
|
138
|
+
starting = false;
|
|
136
139
|
outboundCallback;
|
|
137
140
|
keepAliveTimer;
|
|
141
|
+
cleanupRetryTimer;
|
|
142
|
+
cleanupInProgress = false;
|
|
138
143
|
/** The stream JSON-RPC reads server→client frames from. */
|
|
139
144
|
receiveStream;
|
|
140
145
|
/** The stream JSON-RPC writes client→server frames to. */
|
|
@@ -156,49 +161,65 @@ class FfiRuntimeHost {
|
|
|
156
161
|
}
|
|
157
162
|
/** Starts the in-process Rust runtime and opens the FFI JSON-RPC connection. */
|
|
158
163
|
async start() {
|
|
164
|
+
if (this.disposed) {
|
|
165
|
+
throw new Error("The in-process runtime host is disposed.");
|
|
166
|
+
}
|
|
167
|
+
this.starting = true;
|
|
159
168
|
const argvJson = buildArgvJson(this.cliEntrypoint, this.args);
|
|
160
169
|
const envJson = buildEnvJson(this.environment);
|
|
161
|
-
|
|
162
|
-
this.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
try {
|
|
171
|
+
this.serverId = await new Promise((resolvePromise, rejectPromise) => {
|
|
172
|
+
this.lib.hostStart.async(
|
|
173
|
+
argvJson,
|
|
174
|
+
argvJson.length,
|
|
175
|
+
envJson,
|
|
176
|
+
envJson ? envJson.length : 0,
|
|
177
|
+
(error, result) => {
|
|
178
|
+
if (error) {
|
|
179
|
+
rejectPromise(error);
|
|
180
|
+
} else {
|
|
181
|
+
resolvePromise(result);
|
|
182
|
+
}
|
|
172
183
|
}
|
|
173
|
-
|
|
184
|
+
);
|
|
185
|
+
});
|
|
186
|
+
if (!this.serverId) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`copilot_runtime_host_start failed (library '${this.libraryPath}').`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
if (this.disposed) {
|
|
192
|
+
throw new Error("The in-process runtime host was disposed during startup.");
|
|
193
|
+
}
|
|
194
|
+
this.outboundCallback = import_koffi.default.register(
|
|
195
|
+
(_userData, bytesPtr, bytesLen) => this.feedInbound(bytesPtr, bytesLen),
|
|
196
|
+
this.lib.outboundCallbackType
|
|
174
197
|
);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
this.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
this.connectionId = this.lib.connectionOpen(
|
|
199
|
+
this.serverId,
|
|
200
|
+
this.outboundCallback,
|
|
201
|
+
null,
|
|
202
|
+
null,
|
|
203
|
+
0,
|
|
204
|
+
null,
|
|
205
|
+
0,
|
|
206
|
+
null,
|
|
207
|
+
0
|
|
208
|
+
);
|
|
209
|
+
if (!this.connectionId) {
|
|
210
|
+
this.unregisterCallback();
|
|
211
|
+
this.lib.hostShutdown(this.serverId);
|
|
212
|
+
this.serverId = 0;
|
|
213
|
+
throw new Error("copilot_runtime_connection_open failed.");
|
|
214
|
+
}
|
|
215
|
+
this.keepAliveTimer = setInterval(() => {
|
|
216
|
+
}, KEEP_ALIVE_INTERVAL_MS);
|
|
217
|
+
} finally {
|
|
218
|
+
this.starting = false;
|
|
219
|
+
if (this.disposed) {
|
|
220
|
+
void this.tryFinalizeCleanup();
|
|
221
|
+
}
|
|
199
222
|
}
|
|
200
|
-
this.keepAliveTimer = setInterval(() => {
|
|
201
|
-
}, KEEP_ALIVE_INTERVAL_MS);
|
|
202
223
|
}
|
|
203
224
|
writeFrame(frame) {
|
|
204
225
|
if (this.disposed || !this.connectionId) {
|
|
@@ -237,41 +258,105 @@ class FfiRuntimeHost {
|
|
|
237
258
|
}
|
|
238
259
|
unregisterCallback() {
|
|
239
260
|
if (this.outboundCallback === void 0) {
|
|
240
|
-
return;
|
|
261
|
+
return true;
|
|
241
262
|
}
|
|
242
263
|
const callback = this.outboundCallback;
|
|
243
|
-
this.outboundCallback = void 0;
|
|
244
264
|
try {
|
|
245
265
|
import_koffi.default.unregister(callback);
|
|
246
|
-
|
|
266
|
+
this.outboundCallback = void 0;
|
|
267
|
+
return true;
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error(
|
|
270
|
+
`Failed to unregister in-process FFI callback: ${error instanceof Error ? error.stack ?? error.message : String(error)}`
|
|
271
|
+
);
|
|
272
|
+
FfiRuntimeHost.quarantinedHosts.add(this);
|
|
273
|
+
return false;
|
|
247
274
|
}
|
|
248
275
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if (this.disposed) {
|
|
276
|
+
scheduleCleanupRetry() {
|
|
277
|
+
if (this.cleanupRetryTimer !== void 0) {
|
|
252
278
|
return;
|
|
253
279
|
}
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
280
|
+
this.cleanupRetryTimer = setTimeout(() => {
|
|
281
|
+
this.cleanupRetryTimer = void 0;
|
|
282
|
+
void this.tryFinalizeCleanup();
|
|
283
|
+
}, CLEANUP_RETRY_INTERVAL_MS);
|
|
284
|
+
}
|
|
285
|
+
async tryFinalizeCleanup() {
|
|
286
|
+
if (this.cleanupInProgress) {
|
|
287
|
+
this.scheduleCleanupRetry();
|
|
288
|
+
return;
|
|
258
289
|
}
|
|
290
|
+
this.cleanupInProgress = true;
|
|
259
291
|
try {
|
|
260
292
|
if (this.connectionId) {
|
|
261
|
-
|
|
293
|
+
let closed = false;
|
|
294
|
+
try {
|
|
295
|
+
closed = await new Promise((resolvePromise, rejectPromise) => {
|
|
296
|
+
this.lib.connectionClose.async(
|
|
297
|
+
this.connectionId,
|
|
298
|
+
(error, result) => {
|
|
299
|
+
if (error) {
|
|
300
|
+
rejectPromise(error);
|
|
301
|
+
} else {
|
|
302
|
+
resolvePromise(result);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
} catch (error) {
|
|
308
|
+
console.error(
|
|
309
|
+
`Failed to close in-process FFI connection: ${error instanceof Error ? error.stack ?? error.message : String(error)}`
|
|
310
|
+
);
|
|
311
|
+
FfiRuntimeHost.quarantinedHosts.add(this);
|
|
312
|
+
if (this.keepAliveTimer !== void 0) {
|
|
313
|
+
clearInterval(this.keepAliveTimer);
|
|
314
|
+
this.keepAliveTimer = void 0;
|
|
315
|
+
}
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (!closed) {
|
|
319
|
+
this.scheduleCleanupRetry();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
262
322
|
this.connectionId = 0;
|
|
263
323
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
324
|
+
const callbackUnregistered = this.unregisterCallback();
|
|
325
|
+
if (this.keepAliveTimer !== void 0) {
|
|
326
|
+
clearInterval(this.keepAliveTimer);
|
|
327
|
+
this.keepAliveTimer = void 0;
|
|
328
|
+
}
|
|
267
329
|
if (this.serverId) {
|
|
268
|
-
|
|
330
|
+
try {
|
|
331
|
+
if (!this.lib.hostShutdown(this.serverId)) {
|
|
332
|
+
console.error(
|
|
333
|
+
`In-process FFI host shutdown did not recognize server ${this.serverId}.`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
} catch (error) {
|
|
337
|
+
console.error(
|
|
338
|
+
`Failed to shut down in-process FFI host: ${error instanceof Error ? error.stack ?? error.message : String(error)}`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
269
341
|
this.serverId = 0;
|
|
270
342
|
}
|
|
271
|
-
|
|
343
|
+
if (callbackUnregistered) {
|
|
344
|
+
FfiRuntimeHost.quarantinedHosts.delete(this);
|
|
345
|
+
}
|
|
346
|
+
} finally {
|
|
347
|
+
this.cleanupInProgress = false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/** Awaits the initial cleanup attempt; a non-quiescent close is retried in the background. */
|
|
351
|
+
async dispose() {
|
|
352
|
+
if (this.disposed) {
|
|
353
|
+
return;
|
|
272
354
|
}
|
|
355
|
+
this.disposed = true;
|
|
273
356
|
this.receiveStream.end();
|
|
274
|
-
this.
|
|
357
|
+
if (!this.starting) {
|
|
358
|
+
await this.tryFinalizeCleanup();
|
|
359
|
+
}
|
|
275
360
|
}
|
|
276
361
|
}
|
|
277
362
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -266,13 +266,13 @@ function createServerRpc(connection) {
|
|
|
266
266
|
/**
|
|
267
267
|
* Enables installed plugins for new sessions.
|
|
268
268
|
*
|
|
269
|
-
* @param params Plugin names (or specs) to enable.
|
|
269
|
+
* @param params Plugin names (or specs) to enable, plus the optional working directory the repository-controlled guard is evaluated against.
|
|
270
270
|
*/
|
|
271
271
|
enable: async (params) => connection.sendRequest("plugins.enable", params),
|
|
272
272
|
/**
|
|
273
273
|
* Disables installed plugins for new sessions.
|
|
274
274
|
*
|
|
275
|
-
* @param params Plugin names (or specs) to disable.
|
|
275
|
+
* @param params Plugin names (or specs) to disable, plus the optional working directory the repository-controlled guard is evaluated against.
|
|
276
276
|
*/
|
|
277
277
|
disable: async (params) => connection.sendRequest("plugins.disable", params),
|
|
278
278
|
/** @experimental */
|
|
@@ -522,7 +522,15 @@ function createServerRpc(connection) {
|
|
|
522
522
|
*/
|
|
523
523
|
list: async (params) => connection.sendRequest("sessions.list", params),
|
|
524
524
|
/**
|
|
525
|
-
* Reads
|
|
525
|
+
* Reads client-owned metadata for multiple persisted local sessions without opening them. Results preserve request order and report missing, corrupt, unsupported, or temporarily unavailable sessions independently.
|
|
526
|
+
*
|
|
527
|
+
* @param params Bounded batch request for client-owned metadata from persisted local sessions.
|
|
528
|
+
*
|
|
529
|
+
* @returns Ordered client metadata outcomes for the requested local sessions.
|
|
530
|
+
*/
|
|
531
|
+
getClientMetadata: async (params) => connection.sendRequest("sessions.getClientMetadata", params),
|
|
532
|
+
/**
|
|
533
|
+
* Reads a page of durable events directly from a local session's persisted journal without creating, resuming, or activating the session. The first read pins the currently opened journal generation and its byte-length boundary; opaque cursor continuations remain on that generation across runtime-owned compaction, truncation, and rewrite operations, which replace the live path atomically, and events appended after the boundary are excluded. For cold hydration, await the first successful page before activation and establish lossless live-event buffering before resume; merge subsequent live events by ID, preserving persisted order and letting live payloads win. Continuations are process-local, single-use capabilities bound to the originating session and storage context and must be paged sequentially; concurrent or repeated use of the same cursor expires that duplicate read rather than reading the generation twice. A complete snapshot has cursorStatus 'ok' and hasMore false. Snapshots expire after five idle minutes, with at most eight retained per process and idle-only eviction under pressure; completion and cancelled-worker exit release their handles. No transcript copy is created, but retained handles may keep replaced files' disk blocks alive until release. Pages have a soft 1 MiB serialized event-array budget including resolved binary assets; one oversized event is returned alone to guarantee progress. Working memory also includes a record/lookahead and asset resolution; resolving the first binary reference may scan the full pinned generation to build a bounded offset index. If the snapshot expires, is evicted, is cancelled before a continuation is established, or becomes unreadable after an observable unsupported in-place shortening, the continuation returns cursorStatus 'expired' with an empty terminal page and never falls back to a different generation. A missing or initially unreadable journal is an RPC error. Persisted history excludes ephemeral events and may omit payloads that are reconstructed only for an active session; use the active session event stream for post-resume live events.
|
|
526
534
|
*
|
|
527
535
|
* @param params Pagination options for reading an inactive or active local session's persisted event journal.
|
|
528
536
|
*
|
|
@@ -803,7 +811,15 @@ function createSessionRpc(connection, sessionId) {
|
|
|
803
811
|
*
|
|
804
812
|
* @returns Managed sandbox enforcement state for a session.
|
|
805
813
|
*/
|
|
806
|
-
getEnforcementStatus: async () => connection.sendRequest("session.sandbox.getEnforcementStatus", { sessionId })
|
|
814
|
+
getEnforcementStatus: async () => connection.sendRequest("session.sandbox.getEnforcementStatus", { sessionId }),
|
|
815
|
+
/**
|
|
816
|
+
* Disables sandboxing for the remainder of the current session and approves the referenced pending sandbox-bypass permission request. The request is rejected unless the exact request is still pending and the effective sandbox policy permits bypass.
|
|
817
|
+
*
|
|
818
|
+
* @param params Request to disable sandboxing for the current session while resolving an active sandbox-bypass permission prompt.
|
|
819
|
+
*
|
|
820
|
+
* @returns Result of attempting to disable sandboxing for the current session.
|
|
821
|
+
*/
|
|
822
|
+
disableForSession: async (params) => connection.sendRequest("session.sandbox.disableForSession", { sessionId, ...params })
|
|
807
823
|
},
|
|
808
824
|
/**
|
|
809
825
|
* Aborts the current agent turn.
|
|
@@ -967,6 +983,14 @@ function createSessionRpc(connection, sessionId) {
|
|
|
967
983
|
* @returns Complete current or terminal factory run envelope.
|
|
968
984
|
*/
|
|
969
985
|
cancel: async (params) => connection.sendRequest("session.factory.cancel", { sessionId, ...params }),
|
|
986
|
+
/**
|
|
987
|
+
* Pauses a running factory and returns its settled run envelope.
|
|
988
|
+
*
|
|
989
|
+
* @param params Parameters for pausing a running factory.
|
|
990
|
+
*
|
|
991
|
+
* @returns Complete current or terminal factory run envelope.
|
|
992
|
+
*/
|
|
993
|
+
pause: async (params) => connection.sendRequest("session.factory.pause", { sessionId, ...params }),
|
|
970
994
|
/**
|
|
971
995
|
* Records a batch of ordered factory progress lines.
|
|
972
996
|
*
|
|
@@ -1027,6 +1051,14 @@ function createSessionRpc(connection, sessionId) {
|
|
|
1027
1051
|
* @returns Immediate acknowledgement and Auto preference snapshot after a switch request. This result never implies that a pending preference committed.
|
|
1028
1052
|
*/
|
|
1029
1053
|
switchAutoTier: async (params) => connection.sendRequest("session.model.switchAutoTier", { sessionId, ...params }),
|
|
1054
|
+
/**
|
|
1055
|
+
* Replaces or clears the host-supplied model allowlist for a running session.
|
|
1056
|
+
*
|
|
1057
|
+
* @param params Host-supplied exact model selection IDs to allow for this running session. CAPI IDs are intersected with repository `.github/allowed_models.txt` policy; provider-qualified IDs remain exempt from repository-only policy but are restricted by this host list. Omit or pass null to clear the host restriction; an explicit empty or disjoint list is rejected. Validation and pre-selection fallback failures preserve the previous restriction. Failures after a fallback selection commits retain the new restriction and selected model; callers should inspect current session state after such an error.
|
|
1058
|
+
*
|
|
1059
|
+
* @returns The applied host allowlist and effective session model policy after intersection.
|
|
1060
|
+
*/
|
|
1061
|
+
setAllowedModels: async (params) => connection.sendRequest("session.model.setAllowedModels", { sessionId, ...params }),
|
|
1030
1062
|
/**
|
|
1031
1063
|
* Updates the session's reasoning effort without changing the selected model.
|
|
1032
1064
|
*
|
|
@@ -1272,7 +1304,7 @@ function createSessionRpc(connection, sessionId) {
|
|
|
1272
1304
|
/**
|
|
1273
1305
|
* Starts fleet mode by submitting the fleet orchestration prompt to the session.
|
|
1274
1306
|
*
|
|
1275
|
-
* @param params
|
|
1307
|
+
* @param params Parameters for starting fleet orchestration: an optional user prompt combined with the fleet instructions, plus the send options forwarded to the resulting turn.
|
|
1276
1308
|
*
|
|
1277
1309
|
* @returns Indicates whether fleet mode was successfully activated.
|
|
1278
1310
|
*/
|
|
@@ -1814,7 +1846,7 @@ function createSessionRpc(connection, sessionId) {
|
|
|
1814
1846
|
*/
|
|
1815
1847
|
set: async (params) => connection.sendRequest("session.tools.set", { sessionId, ...params }),
|
|
1816
1848
|
/**
|
|
1817
|
-
*
|
|
1849
|
+
* Sets the current session's live subagent settings override, which takes precedence over persisted user settings until cleared. Persisted user settings remain the source of truth for future sessions.
|
|
1818
1850
|
*
|
|
1819
1851
|
* @param params Subagent settings to apply to the current session
|
|
1820
1852
|
*
|
|
@@ -2164,6 +2196,20 @@ function createSessionRpc(connection, sessionId) {
|
|
|
2164
2196
|
* @returns Point-in-time snapshot of slow-changing session identifier and state fields
|
|
2165
2197
|
*/
|
|
2166
2198
|
snapshot: async () => connection.sendRequest("session.metadata.snapshot", { sessionId }),
|
|
2199
|
+
/**
|
|
2200
|
+
* Returns the client-owned string metadata persisted with this local session. The metadata is not included in model context, events, telemetry, snapshots, or remote exports.
|
|
2201
|
+
*
|
|
2202
|
+
* @returns Client-owned, case-sensitive string metadata persisted with a local session. Clients should namespace keys by owner. Keys must be non-empty and at most 256 UTF-8 bytes; keys under `copilot/` and `github/` are reserved. Values may contain at most 16 KiB of UTF-8 data. A bag may contain at most 128 entries and its serialized sidecar may contain at most 64 KiB. The runtime stores but never interprets these values.
|
|
2203
|
+
*/
|
|
2204
|
+
getClientMetadata: async () => connection.sendRequest("session.metadata.getClientMetadata", { sessionId }),
|
|
2205
|
+
/**
|
|
2206
|
+
* Atomically patches the client-owned string metadata persisted with this local session and returns the committed bag.
|
|
2207
|
+
*
|
|
2208
|
+
* @param params Atomic patch for client-owned session metadata. Operations apply in clear, remove, then set order. The resulting bag must satisfy the ClientMetadata entry and serialized-size limits. Local storage coordinates concurrent runtime processes; custom SessionFs providers must serialize writers that access the same session from multiple processes.
|
|
2209
|
+
*
|
|
2210
|
+
* @returns Client-owned, case-sensitive string metadata persisted with a local session. Clients should namespace keys by owner. Keys must be non-empty and at most 256 UTF-8 bytes; keys under `copilot/` and `github/` are reserved. Values may contain at most 16 KiB of UTF-8 data. A bag may contain at most 128 entries and its serialized sidecar may contain at most 64 KiB. The runtime stores but never interprets these values.
|
|
2211
|
+
*/
|
|
2212
|
+
updateClientMetadata: async (params) => connection.sendRequest("session.metadata.updateClientMetadata", { sessionId, ...params }),
|
|
2167
2213
|
/**
|
|
2168
2214
|
* Reports whether the local session is currently processing user/agent messages.
|
|
2169
2215
|
*
|
|
@@ -2621,7 +2667,13 @@ function createInternalSessionRpc(connection, sessionId) {
|
|
|
2621
2667
|
*
|
|
2622
2668
|
* @returns Resolved persisted factory identity and resumed run envelope.
|
|
2623
2669
|
*/
|
|
2624
|
-
resumeFromTool: async (params) => connection.sendRequest("session.factory.resumeFromTool", { sessionId, ...params })
|
|
2670
|
+
resumeFromTool: async (params) => connection.sendRequest("session.factory.resumeFromTool", { sessionId, ...params }),
|
|
2671
|
+
/**
|
|
2672
|
+
* Atomically pauses an owned factory attempt at a durable checkpoint.
|
|
2673
|
+
*
|
|
2674
|
+
* @param params Parameters for an owned durable pause checkpoint.
|
|
2675
|
+
*/
|
|
2676
|
+
pauseAtCheckpoint: async (params) => connection.sendRequest("session.factory.pauseAtCheckpoint", { sessionId, ...params })
|
|
2625
2677
|
},
|
|
2626
2678
|
/** @experimental */
|
|
2627
2679
|
model: {
|
package/dist/cjs/session.js
CHANGED
|
@@ -41,10 +41,14 @@ const factoryExecutionStore = new import_node_async_hooks.AsyncLocalStorage();
|
|
|
41
41
|
function throwIfFactoryExecutionIsActive() {
|
|
42
42
|
if (factoryExecutionStore.getStore()?.active) {
|
|
43
43
|
throw new Error(
|
|
44
|
-
"factory.run and factory.
|
|
44
|
+
"factory.run, factory.resume, and factory.pause are not allowed while a factory body is running on this call path."
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
function runInFactoryHelperScope(helperScope, callback) {
|
|
49
|
+
const current = factoryExecutionStore.getStore();
|
|
50
|
+
return factoryExecutionStore.run({ active: current?.active ?? false, helperScope }, callback);
|
|
51
|
+
}
|
|
48
52
|
function deserializeHookInput(raw) {
|
|
49
53
|
if (!raw || typeof raw !== "object" || typeof raw.timestamp !== "number") {
|
|
50
54
|
return raw;
|
|
@@ -88,7 +92,7 @@ async function runFactoryParallel(thunks) {
|
|
|
88
92
|
}
|
|
89
93
|
return Promise.all(
|
|
90
94
|
thunks.map(
|
|
91
|
-
(thunk) => Promise.resolve().then(() => thunk
|
|
95
|
+
(thunk) => Promise.resolve().then(() => runInFactoryHelperScope("parallel", thunk)).catch((error) => {
|
|
92
96
|
if (isFactoryFatalError(error)) {
|
|
93
97
|
throw error;
|
|
94
98
|
}
|
|
@@ -107,7 +111,10 @@ async function runFactoryPipeline(items, ...stages) {
|
|
|
107
111
|
let previous = item;
|
|
108
112
|
for (const stage of stages) {
|
|
109
113
|
try {
|
|
110
|
-
previous = await
|
|
114
|
+
previous = await runInFactoryHelperScope(
|
|
115
|
+
"pipeline",
|
|
116
|
+
() => stage(previous, item, index)
|
|
117
|
+
);
|
|
111
118
|
} catch (error) {
|
|
112
119
|
if (isFactoryFatalError(error)) {
|
|
113
120
|
throw error;
|
|
@@ -264,6 +271,7 @@ class CopilotSession {
|
|
|
264
271
|
hooks;
|
|
265
272
|
transformCallbacks;
|
|
266
273
|
_rpc = null;
|
|
274
|
+
_internalRpc = null;
|
|
267
275
|
traceContextProvider;
|
|
268
276
|
managedSettingsEnabled;
|
|
269
277
|
_capabilities = {};
|
|
@@ -330,6 +338,10 @@ class CopilotSession {
|
|
|
330
338
|
}),
|
|
331
339
|
getRunDetail: (runId) => this.rpc.factory.getRunDetail({ runId }),
|
|
332
340
|
getRunProgress: (runId, options = {}) => this.rpc.factory.getRunProgress({ runId, ...options }),
|
|
341
|
+
pause: async (runId) => {
|
|
342
|
+
throwIfFactoryExecutionIsActive();
|
|
343
|
+
return this.rpc.factory.pause({ runId });
|
|
344
|
+
},
|
|
333
345
|
cancel: async (runId) => this.rpc.factory.cancel({ runId })
|
|
334
346
|
};
|
|
335
347
|
/**
|
|
@@ -428,6 +440,13 @@ class CopilotSession {
|
|
|
428
440
|
}
|
|
429
441
|
return this._rpc;
|
|
430
442
|
}
|
|
443
|
+
/** @internal */
|
|
444
|
+
get internalRpc() {
|
|
445
|
+
if (!this._internalRpc) {
|
|
446
|
+
this._internalRpc = (0, import_rpc.createInternalSessionRpc)(this.connection, this.sessionId);
|
|
447
|
+
}
|
|
448
|
+
return this._internalRpc;
|
|
449
|
+
}
|
|
431
450
|
/**
|
|
432
451
|
* Path to the session workspace directory when infinite sessions are enabled.
|
|
433
452
|
* Contains checkpoints/, plan.md, and files/ subdirectories.
|
|
@@ -469,6 +488,7 @@ class CopilotSession {
|
|
|
469
488
|
...await (0, import_telemetry.getTraceContext)(this.traceContextProvider),
|
|
470
489
|
sessionId: this.sessionId,
|
|
471
490
|
prompt: options.prompt,
|
|
491
|
+
source: options.source,
|
|
472
492
|
displayPrompt: options.displayPrompt,
|
|
473
493
|
attachments: options.attachments,
|
|
474
494
|
mode: options.mode,
|
|
@@ -1109,6 +1129,36 @@ class CopilotSession {
|
|
|
1109
1129
|
);
|
|
1110
1130
|
return result2;
|
|
1111
1131
|
},
|
|
1132
|
+
pause: async (key) => {
|
|
1133
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
1134
|
+
throw new Error("Factory pause checkpoint key must not be empty");
|
|
1135
|
+
}
|
|
1136
|
+
const helperScope = factoryExecutionStore.getStore()?.helperScope;
|
|
1137
|
+
if (helperScope !== void 0) {
|
|
1138
|
+
throw new Error(
|
|
1139
|
+
`Factory pause checkpoints are not allowed inside ${helperScope}() branches`
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
await progress.flush();
|
|
1143
|
+
const response = await awaitFactoryOperation(
|
|
1144
|
+
() => self.internalRpc.factory.pauseAtCheckpoint({
|
|
1145
|
+
runId: params.runId,
|
|
1146
|
+
executionToken: params.executionToken,
|
|
1147
|
+
key
|
|
1148
|
+
}),
|
|
1149
|
+
controller.signal
|
|
1150
|
+
);
|
|
1151
|
+
switch (response.action) {
|
|
1152
|
+
case "continue":
|
|
1153
|
+
return;
|
|
1154
|
+
case "pause":
|
|
1155
|
+
await awaitFactoryOperation(
|
|
1156
|
+
() => new Promise(() => {
|
|
1157
|
+
}),
|
|
1158
|
+
controller.signal
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1112
1162
|
parallel: runFactoryParallel,
|
|
1113
1163
|
pipeline: runFactoryPipeline,
|
|
1114
1164
|
factory: async () => {
|
|
@@ -1144,11 +1194,9 @@ class CopilotSession {
|
|
|
1144
1194
|
},
|
|
1145
1195
|
async abort(params) {
|
|
1146
1196
|
const controllersForRun = self.factoryAbortControllers.get(params.runId);
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
controller.abort(reason);
|
|
1151
|
-
}
|
|
1197
|
+
const controller = controllersForRun?.get(params.executionToken);
|
|
1198
|
+
if (controller !== void 0) {
|
|
1199
|
+
controller.abort(new DOMException("Factory run was aborted", "AbortError"));
|
|
1152
1200
|
}
|
|
1153
1201
|
return {};
|
|
1154
1202
|
}
|
package/dist/cliVersion.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const COPILOT_CLI_VERSION = "1.0.
|
|
1
|
+
export declare const COPILOT_CLI_VERSION = "1.0.84-5";
|
|
2
2
|
export declare const COPILOT_CLI_USE_NPM_PACKAGE = false;
|
package/dist/cliVersion.js
CHANGED
package/dist/client.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export declare class CopilotClient {
|
|
|
12
12
|
private runtimePort;
|
|
13
13
|
private actualHost;
|
|
14
14
|
private state;
|
|
15
|
+
/** Shared in-flight start; concurrent callers await it instead of spawning another CLI. */
|
|
16
|
+
private startPromise;
|
|
15
17
|
private sessions;
|
|
16
18
|
private stderrBuffer;
|
|
17
19
|
/** Resolved connection mode chosen in the constructor. */
|
|
@@ -122,6 +124,7 @@ export declare class CopilotClient {
|
|
|
122
124
|
* ```
|
|
123
125
|
*/
|
|
124
126
|
start(): Promise<void>;
|
|
127
|
+
private doStart;
|
|
125
128
|
/**
|
|
126
129
|
* Stops the CLI server and closes all active sessions.
|
|
127
130
|
*
|