@github/copilot-sdk 1.0.0-beta.1 → 1.0.0-beta.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.
- package/README.md +52 -43
- package/dist/canvas.d.ts +126 -0
- package/dist/canvas.js +49 -0
- package/dist/cjs/canvas.js +75 -0
- package/dist/cjs/client.js +536 -299
- package/dist/cjs/extension.js +9 -2
- package/dist/cjs/generated/rpc.js +1319 -14
- package/dist/cjs/index.js +22 -7
- package/dist/cjs/session.js +179 -93
- package/dist/cjs/sessionFsProvider.js +34 -0
- package/dist/cjs/toolSet.js +107 -0
- package/dist/cjs/types.js +38 -4
- package/dist/client.d.ts +63 -73
- package/dist/client.js +537 -300
- package/dist/extension.d.ts +3 -1
- package/dist/extension.js +10 -2
- package/dist/generated/rpc.d.ts +10187 -1028
- package/dist/generated/rpc.js +1319 -14
- package/dist/generated/session-events.d.ts +1982 -195
- package/dist/index.d.ts +6 -2
- package/dist/index.js +15 -2
- package/dist/session.d.ts +18 -186
- package/dist/session.js +179 -92
- package/dist/sessionFsProvider.d.ts +29 -2
- package/dist/sessionFsProvider.js +34 -0
- package/dist/toolSet.d.ts +75 -0
- package/dist/toolSet.js +82 -0
- package/dist/types.d.ts +730 -123
- package/dist/types.js +36 -3
- package/docs/agent-author.md +31 -7
- package/docs/examples.md +23 -16
- package/package.json +3 -3
package/dist/cjs/client.js
CHANGED
|
@@ -34,9 +34,10 @@ var import_sdkProtocolVersion = require("./sdkProtocolVersion.js");
|
|
|
34
34
|
var import_session = require("./session.js");
|
|
35
35
|
var import_sessionFsProvider = require("./sessionFsProvider.js");
|
|
36
36
|
var import_telemetry = require("./telemetry.js");
|
|
37
|
+
var import_toolSet = require("./toolSet.js");
|
|
37
38
|
var import_types = require("./types.js");
|
|
38
39
|
const import_meta = {};
|
|
39
|
-
const MIN_PROTOCOL_VERSION =
|
|
40
|
+
const MIN_PROTOCOL_VERSION = 3;
|
|
40
41
|
function isZodSchema(value) {
|
|
41
42
|
return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
|
|
42
43
|
}
|
|
@@ -47,6 +48,53 @@ function toJsonSchema(parameters) {
|
|
|
47
48
|
}
|
|
48
49
|
return parameters;
|
|
49
50
|
}
|
|
51
|
+
function toWireMcpServers(mcpServers) {
|
|
52
|
+
if (!mcpServers) return void 0;
|
|
53
|
+
return Object.fromEntries(
|
|
54
|
+
Object.entries(mcpServers).map(([name, server]) => {
|
|
55
|
+
if ("workingDirectory" in server) {
|
|
56
|
+
const { workingDirectory, ...rest } = server;
|
|
57
|
+
return [name, { ...rest, cwd: workingDirectory }];
|
|
58
|
+
}
|
|
59
|
+
return [name, server];
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
function toWireCustomAgents(agents) {
|
|
64
|
+
if (!agents) return void 0;
|
|
65
|
+
return agents.map((agent) => {
|
|
66
|
+
if (!agent.mcpServers) return agent;
|
|
67
|
+
const { mcpServers, ...rest } = agent;
|
|
68
|
+
return { ...rest, mcpServers: toWireMcpServers(mcpServers) };
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function toWireLargeOutput(config) {
|
|
72
|
+
if (!config) return void 0;
|
|
73
|
+
const { outputDirectory, ...rest } = config;
|
|
74
|
+
const wire = { ...rest };
|
|
75
|
+
if (outputDirectory !== void 0) {
|
|
76
|
+
wire.outputDir = outputDirectory;
|
|
77
|
+
}
|
|
78
|
+
return wire;
|
|
79
|
+
}
|
|
80
|
+
function toolFilterListToArray(value) {
|
|
81
|
+
if (value === void 0) {
|
|
82
|
+
return void 0;
|
|
83
|
+
}
|
|
84
|
+
return value instanceof import_toolSet.ToolSet ? value.toArray() : value;
|
|
85
|
+
}
|
|
86
|
+
function validateToolFilterList(field, list) {
|
|
87
|
+
if (!list) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
for (const entry of list) {
|
|
91
|
+
if (entry === "*") {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Invalid ${field} entry '*': there is no bare wildcard. Use one or more of \`new ToolSet().addBuiltIn('*')\`, \`.addMcp('*')\`, or \`.addCustom('*')\` to target a specific source.`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
50
98
|
function extractTransformCallbacks(systemMessage) {
|
|
51
99
|
if (!systemMessage || systemMessage.mode !== "customize" || !systemMessage.sections) {
|
|
52
100
|
return { wirePayload: systemMessage, transformCallbacks: void 0 };
|
|
@@ -100,12 +148,18 @@ class CopilotClient {
|
|
|
100
148
|
cliProcess = null;
|
|
101
149
|
connection = null;
|
|
102
150
|
socket = null;
|
|
103
|
-
|
|
151
|
+
runtimePort = null;
|
|
104
152
|
actualHost = "localhost";
|
|
105
153
|
state = "disconnected";
|
|
106
154
|
sessions = /* @__PURE__ */ new Map();
|
|
107
155
|
stderrBuffer = "";
|
|
108
156
|
// Captures CLI stderr for error messages
|
|
157
|
+
/** Resolved connection mode chosen in the constructor. */
|
|
158
|
+
connectionConfig;
|
|
159
|
+
/** Resolved path to the runtime executable (only used for child-process kinds). */
|
|
160
|
+
resolvedCliPath;
|
|
161
|
+
/** Resolved environment passed to the spawned runtime. */
|
|
162
|
+
resolvedEnv;
|
|
109
163
|
options;
|
|
110
164
|
isExternalServer = false;
|
|
111
165
|
forceStopping = false;
|
|
@@ -154,85 +208,90 @@ class CopilotClient {
|
|
|
154
208
|
* Creates a new CopilotClient instance.
|
|
155
209
|
*
|
|
156
210
|
* @param options - Configuration options for the client
|
|
157
|
-
* @throws Error if mutually exclusive options are provided (e.g., cliUrl with useStdio or cliPath)
|
|
158
211
|
*
|
|
159
212
|
* @example
|
|
160
213
|
* ```typescript
|
|
161
|
-
* // Default
|
|
214
|
+
* // Default: spawns the bundled runtime over stdio
|
|
162
215
|
* const client = new CopilotClient();
|
|
163
216
|
*
|
|
164
|
-
* // Connect to an existing
|
|
165
|
-
* const client = new CopilotClient({
|
|
217
|
+
* // Connect to an existing runtime
|
|
218
|
+
* const client = new CopilotClient({
|
|
219
|
+
* connection: RuntimeConnection.forUri("localhost:3000"),
|
|
220
|
+
* });
|
|
221
|
+
*
|
|
222
|
+
* // Spawn the runtime over TCP on a chosen port
|
|
223
|
+
* const client = new CopilotClient({
|
|
224
|
+
* connection: RuntimeConnection.forTcp({ port: 9001 }),
|
|
225
|
+
* });
|
|
166
226
|
*
|
|
167
|
-
* //
|
|
227
|
+
* // Use a custom runtime binary
|
|
168
228
|
* const client = new CopilotClient({
|
|
169
|
-
*
|
|
170
|
-
* logLevel: "debug"
|
|
229
|
+
* connection: RuntimeConnection.forStdio({ path: "/usr/local/bin/copilot" }),
|
|
230
|
+
* logLevel: "debug",
|
|
171
231
|
* });
|
|
172
232
|
* ```
|
|
173
233
|
*/
|
|
174
234
|
constructor(options = {}) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
if (options.isChildProcess && (options.cliUrl || options.useStdio === false)) {
|
|
179
|
-
throw new Error(
|
|
180
|
-
"isChildProcess must be used in conjunction with useStdio and not with cliUrl"
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
if (options.cliUrl && (options.gitHubToken || options.useLoggedInUser !== void 0)) {
|
|
235
|
+
const conn = options._internalConnection ?? options.connection ?? { kind: "stdio" };
|
|
236
|
+
if (conn.kind === "uri" && (options.gitHubToken !== void 0 || options.useLoggedInUser !== void 0)) {
|
|
184
237
|
throw new Error(
|
|
185
|
-
"gitHubToken and useLoggedInUser cannot be used with
|
|
238
|
+
"gitHubToken and useLoggedInUser cannot be used with RuntimeConnection.forUri (external server manages its own auth)"
|
|
186
239
|
);
|
|
187
240
|
}
|
|
188
|
-
if (
|
|
189
|
-
if (typeof
|
|
190
|
-
throw new Error("
|
|
191
|
-
}
|
|
192
|
-
if (options.useStdio === true) {
|
|
193
|
-
throw new Error("tcpConnectionToken cannot be used with useStdio: true");
|
|
241
|
+
if (conn.kind === "tcp" && conn.connectionToken !== void 0) {
|
|
242
|
+
if (typeof conn.connectionToken !== "string" || conn.connectionToken.length === 0) {
|
|
243
|
+
throw new Error("connectionToken must be a non-empty string");
|
|
194
244
|
}
|
|
195
245
|
}
|
|
196
|
-
|
|
197
|
-
const sdkSpawnsCli = !willUseStdio && !options.cliUrl && !options.isChildProcess;
|
|
198
|
-
this.effectiveConnectionToken = options.tcpConnectionToken ?? (sdkSpawnsCli ? (0, import_node_crypto.randomUUID)() : void 0);
|
|
246
|
+
this.connectionConfig = conn;
|
|
199
247
|
if (options.sessionFs) {
|
|
200
248
|
this.validateSessionFsConfig(options.sessionFs);
|
|
201
249
|
}
|
|
202
|
-
if (
|
|
203
|
-
const { host, port } = this.parseCliUrl(
|
|
250
|
+
if (conn.kind === "uri") {
|
|
251
|
+
const { host, port } = this.parseCliUrl(conn.url);
|
|
204
252
|
this.actualHost = host;
|
|
205
|
-
this.
|
|
253
|
+
this.runtimePort = port;
|
|
206
254
|
this.isExternalServer = true;
|
|
207
|
-
}
|
|
208
|
-
if (options.isChildProcess) {
|
|
255
|
+
} else if (conn.kind === "parent-process") {
|
|
209
256
|
this.isExternalServer = true;
|
|
210
257
|
}
|
|
258
|
+
if (conn.kind === "tcp") {
|
|
259
|
+
this.effectiveConnectionToken = conn.connectionToken ?? (0, import_node_crypto.randomUUID)();
|
|
260
|
+
} else if (conn.kind === "uri") {
|
|
261
|
+
this.effectiveConnectionToken = conn.connectionToken;
|
|
262
|
+
}
|
|
211
263
|
this.onListModels = options.onListModels;
|
|
212
264
|
this.onGetTraceContext = options.onGetTraceContext;
|
|
213
265
|
this.sessionFsConfig = options.sessionFs ?? null;
|
|
214
266
|
const effectiveEnv = options.env ?? process.env;
|
|
267
|
+
this.resolvedEnv = effectiveEnv;
|
|
268
|
+
this.resolvedCliPath = conn.kind === "stdio" || conn.kind === "tcp" ? conn.path ?? effectiveEnv.COPILOT_CLI_PATH ?? getBundledCliPath() : void 0;
|
|
269
|
+
const connArgs = conn.kind === "stdio" || conn.kind === "tcp" ? conn.args ?? [] : [];
|
|
270
|
+
this.connectionExtraArgs = [...connArgs];
|
|
215
271
|
this.options = {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
cwd: options.cwd ?? process.cwd(),
|
|
219
|
-
port: options.port || 0,
|
|
220
|
-
useStdio: options.cliUrl ? false : options.useStdio ?? true,
|
|
221
|
-
// Default to stdio unless cliUrl is provided
|
|
222
|
-
isChildProcess: options.isChildProcess ?? false,
|
|
223
|
-
cliUrl: options.cliUrl,
|
|
224
|
-
logLevel: options.logLevel || "debug",
|
|
225
|
-
autoStart: options.autoStart ?? true,
|
|
226
|
-
autoRestart: false,
|
|
227
|
-
env: effectiveEnv,
|
|
272
|
+
workingDirectory: options.workingDirectory ?? process.cwd(),
|
|
273
|
+
logLevel: options.logLevel,
|
|
228
274
|
gitHubToken: options.gitHubToken,
|
|
229
|
-
// Default useLoggedInUser to false when gitHubToken is provided, otherwise true
|
|
275
|
+
// Default useLoggedInUser to false when gitHubToken is provided, otherwise true.
|
|
230
276
|
useLoggedInUser: options.useLoggedInUser ?? (options.gitHubToken ? false : true),
|
|
231
277
|
telemetry: options.telemetry,
|
|
232
|
-
|
|
233
|
-
sessionIdleTimeoutSeconds: options.sessionIdleTimeoutSeconds ?? 0
|
|
278
|
+
baseDirectory: options.baseDirectory,
|
|
279
|
+
sessionIdleTimeoutSeconds: options.sessionIdleTimeoutSeconds ?? 0,
|
|
280
|
+
enableRemoteSessions: options.enableRemoteSessions ?? false,
|
|
281
|
+
mode: options.mode ?? "copilot-cli"
|
|
234
282
|
};
|
|
283
|
+
if (this.options.mode === "empty") {
|
|
284
|
+
const hasPersistence = this.options.baseDirectory !== void 0 || this.sessionFsConfig !== null || // External runtimes manage their own persistence layer; the SDK
|
|
285
|
+
// can't enforce it from here.
|
|
286
|
+
conn.kind === "uri" || conn.kind === "parent-process";
|
|
287
|
+
if (!hasPersistence) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
"CopilotClient was created with mode: 'empty' but neither 'baseDirectory' nor 'sessionFs' was set. Empty mode requires an explicit per-session persistence location; pick one."
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
235
293
|
}
|
|
294
|
+
connectionExtraArgs = [];
|
|
236
295
|
/**
|
|
237
296
|
* Parse CLI URL into host and port
|
|
238
297
|
* Supports formats: "host:port", "http://host:port", "https://host:port", or just "port"
|
|
@@ -266,20 +325,37 @@ class CopilotClient {
|
|
|
266
325
|
throw new Error("sessionFs.conventions must be either 'windows' or 'posix'");
|
|
267
326
|
}
|
|
268
327
|
}
|
|
328
|
+
setupSessionFs(session, config) {
|
|
329
|
+
if (!this.sessionFsConfig) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if (!config.createSessionFsProvider) {
|
|
333
|
+
throw new Error(
|
|
334
|
+
"createSessionFsProvider is required in session config when sessionFs is enabled in client options."
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
const provider = config.createSessionFsProvider(session);
|
|
338
|
+
if (this.sessionFsConfig.capabilities?.sqlite && !provider.sqlite) {
|
|
339
|
+
throw new Error(
|
|
340
|
+
"SessionFsConfig declares capabilities.sqlite but the provider does not implement sqlite."
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)(provider);
|
|
344
|
+
}
|
|
269
345
|
/**
|
|
270
346
|
* Starts the CLI server and establishes a connection.
|
|
271
347
|
*
|
|
272
348
|
* If connecting to an external server (via cliUrl), only establishes the connection.
|
|
273
349
|
* Otherwise, spawns the CLI server process and then connects.
|
|
274
350
|
*
|
|
275
|
-
* This method is called automatically
|
|
351
|
+
* This method is called automatically the first time you create or resume a session.
|
|
276
352
|
*
|
|
277
353
|
* @returns A promise that resolves when the connection is established
|
|
278
354
|
* @throws Error if the server fails to start or the connection fails
|
|
279
355
|
*
|
|
280
356
|
* @example
|
|
281
357
|
* ```typescript
|
|
282
|
-
* const client = new CopilotClient(
|
|
358
|
+
* const client = new CopilotClient();
|
|
283
359
|
* await client.start();
|
|
284
360
|
* // Now ready to create sessions
|
|
285
361
|
* ```
|
|
@@ -299,7 +375,8 @@ class CopilotClient {
|
|
|
299
375
|
await this.connection.sendRequest("sessionFs.setProvider", {
|
|
300
376
|
initialCwd: this.sessionFsConfig.initialCwd,
|
|
301
377
|
sessionStatePath: this.sessionFsConfig.sessionStatePath,
|
|
302
|
-
conventions: this.sessionFsConfig.conventions
|
|
378
|
+
conventions: this.sessionFsConfig.conventions,
|
|
379
|
+
capabilities: this.sessionFsConfig.capabilities
|
|
303
380
|
});
|
|
304
381
|
}
|
|
305
382
|
this.state = "connected";
|
|
@@ -373,8 +450,15 @@ class CopilotClient {
|
|
|
373
450
|
}
|
|
374
451
|
this.modelsCache = null;
|
|
375
452
|
if (this.socket) {
|
|
453
|
+
const socket = this.socket;
|
|
454
|
+
this.socket = null;
|
|
376
455
|
try {
|
|
377
|
-
|
|
456
|
+
if (!socket.destroyed) {
|
|
457
|
+
await new Promise((resolve) => {
|
|
458
|
+
socket.once("close", () => resolve());
|
|
459
|
+
socket.end();
|
|
460
|
+
});
|
|
461
|
+
}
|
|
378
462
|
} catch (error) {
|
|
379
463
|
errors.push(
|
|
380
464
|
new Error(
|
|
@@ -382,11 +466,18 @@ class CopilotClient {
|
|
|
382
466
|
)
|
|
383
467
|
);
|
|
384
468
|
}
|
|
385
|
-
this.socket = null;
|
|
386
469
|
}
|
|
387
470
|
if (this.cliProcess && !this.isExternalServer) {
|
|
471
|
+
const child = this.cliProcess;
|
|
472
|
+
this.cliProcess = null;
|
|
388
473
|
try {
|
|
389
|
-
|
|
474
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
475
|
+
const exited = new Promise((resolve) => {
|
|
476
|
+
child.once("exit", () => resolve());
|
|
477
|
+
});
|
|
478
|
+
child.kill();
|
|
479
|
+
await exited;
|
|
480
|
+
}
|
|
390
481
|
} catch (error) {
|
|
391
482
|
errors.push(
|
|
392
483
|
new Error(
|
|
@@ -394,18 +485,32 @@ class CopilotClient {
|
|
|
394
485
|
)
|
|
395
486
|
);
|
|
396
487
|
}
|
|
397
|
-
this.cliProcess = null;
|
|
398
488
|
}
|
|
399
489
|
if (this.cliStartTimeout) {
|
|
400
490
|
clearTimeout(this.cliStartTimeout);
|
|
401
491
|
this.cliStartTimeout = null;
|
|
402
492
|
}
|
|
403
493
|
this.state = "disconnected";
|
|
404
|
-
this.
|
|
494
|
+
this.runtimePort = null;
|
|
405
495
|
this.stderrBuffer = "";
|
|
406
496
|
this.processExitPromise = null;
|
|
407
497
|
return errors;
|
|
408
498
|
}
|
|
499
|
+
/**
|
|
500
|
+
* Alias for {@link stop} that lets `CopilotClient` participate in `await using`
|
|
501
|
+
* blocks for automatic cleanup.
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* ```typescript
|
|
505
|
+
* await using client = new CopilotClient();
|
|
506
|
+
* const session = await client.createSession({ onPermissionRequest: approveAll });
|
|
507
|
+
* await session.sendAndWait("Hello");
|
|
508
|
+
* // client.stop() is called automatically when the block exits.
|
|
509
|
+
* ```
|
|
510
|
+
*/
|
|
511
|
+
async [Symbol.asyncDispose]() {
|
|
512
|
+
await this.stop();
|
|
513
|
+
}
|
|
409
514
|
/**
|
|
410
515
|
* Forcefully stops the CLI server without graceful cleanup.
|
|
411
516
|
*
|
|
@@ -462,7 +567,7 @@ class CopilotClient {
|
|
|
462
567
|
this.cliStartTimeout = null;
|
|
463
568
|
}
|
|
464
569
|
this.state = "disconnected";
|
|
465
|
-
this.
|
|
570
|
+
this.runtimePort = null;
|
|
466
571
|
this.stderrBuffer = "";
|
|
467
572
|
this.processExitPromise = null;
|
|
468
573
|
}
|
|
@@ -470,12 +575,11 @@ class CopilotClient {
|
|
|
470
575
|
* Creates a new conversation session with the Copilot CLI.
|
|
471
576
|
*
|
|
472
577
|
* Sessions maintain conversation state, handle events, and manage tool execution.
|
|
473
|
-
* If the client is not connected
|
|
474
|
-
* start the connection.
|
|
578
|
+
* If the client is not connected, this method automatically starts the connection.
|
|
475
579
|
*
|
|
476
580
|
* @param config - Optional configuration for the session
|
|
477
581
|
* @returns A promise that resolves with the created session
|
|
478
|
-
* @throws Error if the client
|
|
582
|
+
* @throws Error if the client fails to start
|
|
479
583
|
*
|
|
480
584
|
* @example
|
|
481
585
|
* ```typescript
|
|
@@ -495,66 +599,189 @@ class CopilotClient {
|
|
|
495
599
|
* });
|
|
496
600
|
* ```
|
|
497
601
|
*/
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
602
|
+
/**
|
|
603
|
+
* Normalizes session-level tool filter options. Converts {@link ToolSet}
|
|
604
|
+
* instances to plain string arrays, rejects misuse (bare `"*"`) and the
|
|
605
|
+
* missing-availableTools case in `mode = "empty"`.
|
|
606
|
+
*
|
|
607
|
+
* The SDK always sends `toolFilterPrecedence: "excluded"` so callers can
|
|
608
|
+
* compose include + exclude lists naturally (e.g. "everything matching X
|
|
609
|
+
* except Y") regardless of mode. Allowlist-precedence is intentionally not
|
|
610
|
+
* exposed — it's available on the runtime side as a CLI-only concession to
|
|
611
|
+
* legacy behavior, but SDK consumers always get the composable semantics.
|
|
612
|
+
*
|
|
613
|
+
* @internal
|
|
614
|
+
*/
|
|
615
|
+
resolveToolFilterOptions(config) {
|
|
616
|
+
const availableTools = toolFilterListToArray(config.availableTools);
|
|
617
|
+
const excludedTools = toolFilterListToArray(config.excludedTools);
|
|
618
|
+
validateToolFilterList("availableTools", availableTools);
|
|
619
|
+
validateToolFilterList("excludedTools", excludedTools);
|
|
620
|
+
if (this.options.mode === "empty") {
|
|
621
|
+
if (availableTools === void 0) {
|
|
622
|
+
throw new Error(
|
|
623
|
+
"CopilotClient is in mode: 'empty' but the session config did not specify 'availableTools'. Empty mode requires every session to explicitly opt into the tools it wants \u2014 e.g. `new ToolSet().addBuiltIn(BuiltInTools.Isolated)`."
|
|
624
|
+
);
|
|
509
625
|
}
|
|
510
626
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
627
|
+
return { availableTools, excludedTools, toolFilterPrecedence: "excluded" };
|
|
628
|
+
}
|
|
629
|
+
/** Mode-specific defaults spread under the caller's config (app values win). */
|
|
630
|
+
configDefaultsForMode() {
|
|
631
|
+
if (this.options.mode === "empty") {
|
|
632
|
+
return {
|
|
633
|
+
enableSessionTelemetry: false,
|
|
634
|
+
mcpOAuthTokenStorage: "in-memory",
|
|
635
|
+
skipEmbeddingRetrieval: true,
|
|
636
|
+
embeddingCacheStorage: "in-memory",
|
|
637
|
+
enableOnDemandInstructionDiscovery: false,
|
|
638
|
+
enableFileHooks: false,
|
|
639
|
+
enableHostGitOperations: false,
|
|
640
|
+
enableSessionStore: false,
|
|
641
|
+
enableSkills: false
|
|
642
|
+
};
|
|
523
643
|
}
|
|
524
|
-
|
|
525
|
-
|
|
644
|
+
return {};
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Returns the systemMessage config to use, adjusted for the current mode.
|
|
648
|
+
* In empty mode we ensure the environment_context section is removed
|
|
649
|
+
* unless the app has already taken control of it. `append` (and
|
|
650
|
+
* unspecified) mode is promoted to `customize` so we can also strip
|
|
651
|
+
* environment_context; the caller's `content` is preserved verbatim
|
|
652
|
+
* because the runtime appends it as additional instructions in both
|
|
653
|
+
* customize and append modes.
|
|
654
|
+
*/
|
|
655
|
+
getSystemMessageConfigForMode(supplied) {
|
|
656
|
+
if (this.options.mode !== "empty") return supplied;
|
|
657
|
+
if (!supplied) {
|
|
658
|
+
return {
|
|
659
|
+
mode: "customize",
|
|
660
|
+
sections: { environment_context: { action: "remove" } }
|
|
661
|
+
};
|
|
526
662
|
}
|
|
527
|
-
|
|
528
|
-
|
|
663
|
+
switch (supplied.mode) {
|
|
664
|
+
case "replace":
|
|
665
|
+
return supplied;
|
|
666
|
+
case "customize":
|
|
667
|
+
if (supplied.sections?.environment_context) return supplied;
|
|
668
|
+
return {
|
|
669
|
+
...supplied,
|
|
670
|
+
sections: {
|
|
671
|
+
...supplied.sections,
|
|
672
|
+
environment_context: { action: "remove" }
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
case "append":
|
|
676
|
+
case void 0:
|
|
677
|
+
return {
|
|
678
|
+
mode: "customize",
|
|
679
|
+
content: supplied.content,
|
|
680
|
+
sections: { environment_context: { action: "remove" } }
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Mode-specific options applied via session.options.update after create/resume.
|
|
686
|
+
*
|
|
687
|
+
* In empty mode, defaults the four overridable feature flags to safe values
|
|
688
|
+
* (caller values from `config` win). `installedPlugins=[]` is unconditional
|
|
689
|
+
* in empty mode — apps that need custom plugins should switch modes.
|
|
690
|
+
*/
|
|
691
|
+
async updateSessionOptionsForMode(session, config) {
|
|
692
|
+
const patch = {};
|
|
693
|
+
if (this.options.mode === "empty") {
|
|
694
|
+
patch.skipCustomInstructions = config.skipCustomInstructions ?? true;
|
|
695
|
+
patch.customAgentsLocalOnly = config.customAgentsLocalOnly ?? true;
|
|
696
|
+
patch.coauthorEnabled = config.coauthorEnabled ?? false;
|
|
697
|
+
patch.manageScheduleEnabled = config.manageScheduleEnabled ?? false;
|
|
698
|
+
patch.installedPlugins = [];
|
|
699
|
+
} else {
|
|
700
|
+
if (config.skipCustomInstructions !== void 0)
|
|
701
|
+
patch.skipCustomInstructions = config.skipCustomInstructions;
|
|
702
|
+
if (config.customAgentsLocalOnly !== void 0)
|
|
703
|
+
patch.customAgentsLocalOnly = config.customAgentsLocalOnly;
|
|
704
|
+
if (config.coauthorEnabled !== void 0)
|
|
705
|
+
patch.coauthorEnabled = config.coauthorEnabled;
|
|
706
|
+
if (config.manageScheduleEnabled !== void 0)
|
|
707
|
+
patch.manageScheduleEnabled = config.manageScheduleEnabled;
|
|
708
|
+
}
|
|
709
|
+
if (Object.keys(patch).length === 0) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
try {
|
|
713
|
+
await session.rpc.options.update(patch);
|
|
714
|
+
} catch (e) {
|
|
715
|
+
try {
|
|
716
|
+
await session.disconnect();
|
|
717
|
+
} catch {
|
|
718
|
+
}
|
|
719
|
+
throw e;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
async createSession(config) {
|
|
723
|
+
if (!this.connection) {
|
|
724
|
+
await this.start();
|
|
529
725
|
}
|
|
726
|
+
config = { ...this.configDefaultsForMode(), ...config };
|
|
727
|
+
config.systemMessage = this.getSystemMessageConfigForMode(config.systemMessage);
|
|
728
|
+
const callerSessionId = config.sessionId;
|
|
729
|
+
const useServerGeneratedId = config.cloud != null && callerSessionId == null;
|
|
730
|
+
const localSessionId = useServerGeneratedId ? void 0 : callerSessionId ?? (0, import_node_crypto.randomUUID)();
|
|
530
731
|
const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
|
|
531
732
|
config.systemMessage
|
|
532
733
|
);
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
);
|
|
734
|
+
const initializeSession = (sessionId) => {
|
|
735
|
+
const s = new import_session.CopilotSession(
|
|
736
|
+
sessionId,
|
|
737
|
+
this.connection,
|
|
738
|
+
void 0,
|
|
739
|
+
this.onGetTraceContext
|
|
740
|
+
);
|
|
741
|
+
s.registerTools(config.tools);
|
|
742
|
+
s.registerCanvases(config.canvases);
|
|
743
|
+
s.registerCommands(config.commands);
|
|
744
|
+
s.registerPermissionHandler(config.onPermissionRequest);
|
|
745
|
+
if (config.onUserInputRequest) {
|
|
746
|
+
s.registerUserInputHandler(config.onUserInputRequest);
|
|
747
|
+
}
|
|
748
|
+
if (config.onElicitationRequest) {
|
|
749
|
+
s.registerElicitationHandler(config.onElicitationRequest);
|
|
750
|
+
}
|
|
751
|
+
if (config.onExitPlanModeRequest) {
|
|
752
|
+
s.registerExitPlanModeHandler(config.onExitPlanModeRequest);
|
|
753
|
+
}
|
|
754
|
+
if (config.onAutoModeSwitchRequest) {
|
|
755
|
+
s.registerAutoModeSwitchHandler(config.onAutoModeSwitchRequest);
|
|
756
|
+
}
|
|
757
|
+
if (config.hooks) {
|
|
758
|
+
s.registerHooks(config.hooks);
|
|
759
|
+
}
|
|
760
|
+
if (transformCallbacks) {
|
|
761
|
+
s.registerTransformCallbacks(transformCallbacks);
|
|
762
|
+
}
|
|
763
|
+
if (config.onEvent) {
|
|
764
|
+
s.on(config.onEvent);
|
|
549
765
|
}
|
|
766
|
+
this.sessions.set(sessionId, s);
|
|
767
|
+
this.setupSessionFs(s, config);
|
|
768
|
+
return s;
|
|
769
|
+
};
|
|
770
|
+
let session;
|
|
771
|
+
let registeredId;
|
|
772
|
+
if (localSessionId !== void 0) {
|
|
773
|
+
session = initializeSession(localSessionId);
|
|
774
|
+
registeredId = localSessionId;
|
|
550
775
|
}
|
|
776
|
+
const toolFilterOptions = this.resolveToolFilterOptions(config);
|
|
551
777
|
try {
|
|
552
778
|
const response = await this.connection.sendRequest("session.create", {
|
|
553
779
|
...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
|
|
554
780
|
model: config.model,
|
|
555
|
-
sessionId,
|
|
781
|
+
sessionId: localSessionId,
|
|
556
782
|
clientName: config.clientName,
|
|
557
783
|
reasoningEffort: config.reasoningEffort,
|
|
784
|
+
reasoningSummary: config.reasoningSummary,
|
|
558
785
|
tools: config.tools?.map((tool) => ({
|
|
559
786
|
name: tool.name,
|
|
560
787
|
description: tool.description,
|
|
@@ -562,40 +789,81 @@ class CopilotClient {
|
|
|
562
789
|
overridesBuiltInTool: tool.overridesBuiltInTool,
|
|
563
790
|
skipPermission: tool.skipPermission
|
|
564
791
|
})),
|
|
792
|
+
canvases: config.canvases?.map((canvas) => canvas.declaration),
|
|
793
|
+
requestCanvasRenderer: config.requestCanvasRenderer,
|
|
794
|
+
requestExtensions: config.requestExtensions,
|
|
795
|
+
extensionInfo: config.extensionInfo,
|
|
565
796
|
commands: config.commands?.map((cmd) => ({
|
|
566
797
|
name: cmd.name,
|
|
567
798
|
description: cmd.description
|
|
568
799
|
})),
|
|
569
800
|
systemMessage: wireSystemMessage,
|
|
570
|
-
availableTools:
|
|
571
|
-
excludedTools:
|
|
801
|
+
availableTools: toolFilterOptions.availableTools,
|
|
802
|
+
excludedTools: toolFilterOptions.excludedTools,
|
|
803
|
+
toolFilterPrecedence: toolFilterOptions.toolFilterPrecedence,
|
|
572
804
|
provider: config.provider,
|
|
805
|
+
enableSessionTelemetry: config.enableSessionTelemetry,
|
|
573
806
|
modelCapabilities: config.modelCapabilities,
|
|
574
|
-
|
|
807
|
+
largeOutput: toWireLargeOutput(config.largeOutput),
|
|
808
|
+
requestPermission: !!config.onPermissionRequest,
|
|
575
809
|
requestUserInput: !!config.onUserInputRequest,
|
|
576
810
|
requestElicitation: !!config.onElicitationRequest,
|
|
811
|
+
...config.enableMcpApps ? { requestMcpApps: true } : {},
|
|
812
|
+
requestExitPlanMode: !!config.onExitPlanModeRequest,
|
|
813
|
+
requestAutoModeSwitch: !!config.onAutoModeSwitchRequest,
|
|
577
814
|
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
578
815
|
workingDirectory: config.workingDirectory,
|
|
579
816
|
streaming: config.streaming,
|
|
580
817
|
includeSubAgentStreamingEvents: config.includeSubAgentStreamingEvents ?? true,
|
|
581
|
-
mcpServers: config.mcpServers,
|
|
818
|
+
mcpServers: toWireMcpServers(config.mcpServers),
|
|
819
|
+
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
582
820
|
envValueMode: "direct",
|
|
583
|
-
customAgents: config.customAgents,
|
|
821
|
+
customAgents: toWireCustomAgents(config.customAgents),
|
|
584
822
|
defaultAgent: config.defaultAgent,
|
|
585
823
|
agent: config.agent,
|
|
586
|
-
configDir: config.
|
|
824
|
+
configDir: config.configDirectory,
|
|
587
825
|
enableConfigDiscovery: config.enableConfigDiscovery,
|
|
826
|
+
skipEmbeddingRetrieval: config.skipEmbeddingRetrieval,
|
|
827
|
+
embeddingCacheStorage: config.embeddingCacheStorage,
|
|
828
|
+
organizationCustomInstructions: config.organizationCustomInstructions,
|
|
829
|
+
enableOnDemandInstructionDiscovery: config.enableOnDemandInstructionDiscovery,
|
|
830
|
+
enableFileHooks: config.enableFileHooks,
|
|
831
|
+
enableHostGitOperations: config.enableHostGitOperations,
|
|
832
|
+
enableSessionStore: config.enableSessionStore,
|
|
833
|
+
enableSkills: config.enableSkills,
|
|
588
834
|
skillDirectories: config.skillDirectories,
|
|
835
|
+
pluginDirectories: config.pluginDirectories,
|
|
589
836
|
instructionDirectories: config.instructionDirectories,
|
|
590
837
|
disabledSkills: config.disabledSkills,
|
|
591
838
|
infiniteSessions: config.infiniteSessions,
|
|
592
|
-
gitHubToken: config.gitHubToken
|
|
839
|
+
gitHubToken: config.gitHubToken,
|
|
840
|
+
remoteSession: config.remoteSession,
|
|
841
|
+
cloud: config.cloud
|
|
593
842
|
});
|
|
594
|
-
const {
|
|
843
|
+
const {
|
|
844
|
+
sessionId: returnedSessionId,
|
|
845
|
+
workspacePath,
|
|
846
|
+
capabilities
|
|
847
|
+
} = response;
|
|
848
|
+
if (!returnedSessionId) {
|
|
849
|
+
throw new Error("session.create response did not include a sessionId");
|
|
850
|
+
}
|
|
851
|
+
if (localSessionId !== void 0 && localSessionId !== returnedSessionId) {
|
|
852
|
+
throw new Error(
|
|
853
|
+
`session.create returned sessionId ${returnedSessionId} but the caller requested ${localSessionId}`
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
if (session === void 0) {
|
|
857
|
+
session = initializeSession(returnedSessionId);
|
|
858
|
+
registeredId = returnedSessionId;
|
|
859
|
+
}
|
|
595
860
|
session["_workspacePath"] = workspacePath;
|
|
596
861
|
session.setCapabilities(capabilities);
|
|
862
|
+
await this.updateSessionOptionsForMode(session, config);
|
|
597
863
|
} catch (e) {
|
|
598
|
-
|
|
864
|
+
if (registeredId !== void 0) {
|
|
865
|
+
this.sessions.delete(registeredId);
|
|
866
|
+
}
|
|
599
867
|
throw e;
|
|
600
868
|
}
|
|
601
869
|
return session;
|
|
@@ -625,17 +893,8 @@ class CopilotClient {
|
|
|
625
893
|
* ```
|
|
626
894
|
*/
|
|
627
895
|
async resumeSession(sessionId, config) {
|
|
628
|
-
if (!config?.onPermissionRequest) {
|
|
629
|
-
throw new Error(
|
|
630
|
-
"An onPermissionRequest handler is required when resuming a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }."
|
|
631
|
-
);
|
|
632
|
-
}
|
|
633
896
|
if (!this.connection) {
|
|
634
|
-
|
|
635
|
-
await this.start();
|
|
636
|
-
} else {
|
|
637
|
-
throw new Error("Client not connected. Call start() first.");
|
|
638
|
-
}
|
|
897
|
+
await this.start();
|
|
639
898
|
}
|
|
640
899
|
const session = new import_session.CopilotSession(
|
|
641
900
|
sessionId,
|
|
@@ -644,6 +903,7 @@ class CopilotClient {
|
|
|
644
903
|
this.onGetTraceContext
|
|
645
904
|
);
|
|
646
905
|
session.registerTools(config.tools);
|
|
906
|
+
session.registerCanvases(config.canvases);
|
|
647
907
|
session.registerCommands(config.commands);
|
|
648
908
|
session.registerPermissionHandler(config.onPermissionRequest);
|
|
649
909
|
if (config.onUserInputRequest) {
|
|
@@ -652,9 +912,17 @@ class CopilotClient {
|
|
|
652
912
|
if (config.onElicitationRequest) {
|
|
653
913
|
session.registerElicitationHandler(config.onElicitationRequest);
|
|
654
914
|
}
|
|
915
|
+
if (config.onExitPlanModeRequest) {
|
|
916
|
+
session.registerExitPlanModeHandler(config.onExitPlanModeRequest);
|
|
917
|
+
}
|
|
918
|
+
if (config.onAutoModeSwitchRequest) {
|
|
919
|
+
session.registerAutoModeSwitchHandler(config.onAutoModeSwitchRequest);
|
|
920
|
+
}
|
|
655
921
|
if (config.hooks) {
|
|
656
922
|
session.registerHooks(config.hooks);
|
|
657
923
|
}
|
|
924
|
+
config = { ...this.configDefaultsForMode(), ...config };
|
|
925
|
+
config.systemMessage = this.getSystemMessageConfigForMode(config.systemMessage);
|
|
658
926
|
const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
|
|
659
927
|
config.systemMessage
|
|
660
928
|
);
|
|
@@ -665,17 +933,8 @@ class CopilotClient {
|
|
|
665
933
|
session.on(config.onEvent);
|
|
666
934
|
}
|
|
667
935
|
this.sessions.set(sessionId, session);
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)(
|
|
671
|
-
config.createSessionFsHandler(session)
|
|
672
|
-
);
|
|
673
|
-
} else {
|
|
674
|
-
throw new Error(
|
|
675
|
-
"createSessionFsHandler is required in session config when sessionFs is enabled in client options."
|
|
676
|
-
);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
936
|
+
this.setupSessionFs(session, config);
|
|
937
|
+
const toolFilterOptions = this.resolveToolFilterOptions(config);
|
|
679
938
|
try {
|
|
680
939
|
const response = await this.connection.sendRequest("session.resume", {
|
|
681
940
|
...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
|
|
@@ -683,9 +942,12 @@ class CopilotClient {
|
|
|
683
942
|
clientName: config.clientName,
|
|
684
943
|
model: config.model,
|
|
685
944
|
reasoningEffort: config.reasoningEffort,
|
|
945
|
+
reasoningSummary: config.reasoningSummary,
|
|
686
946
|
systemMessage: wireSystemMessage,
|
|
687
|
-
availableTools:
|
|
688
|
-
excludedTools:
|
|
947
|
+
availableTools: toolFilterOptions.availableTools,
|
|
948
|
+
excludedTools: toolFilterOptions.excludedTools,
|
|
949
|
+
toolFilterPrecedence: toolFilterOptions.toolFilterPrecedence,
|
|
950
|
+
enableSessionTelemetry: config.enableSessionTelemetry,
|
|
689
951
|
tools: config.tools?.map((tool) => ({
|
|
690
952
|
name: tool.name,
|
|
691
953
|
description: tool.description,
|
|
@@ -693,58 +955,65 @@ class CopilotClient {
|
|
|
693
955
|
overridesBuiltInTool: tool.overridesBuiltInTool,
|
|
694
956
|
skipPermission: tool.skipPermission
|
|
695
957
|
})),
|
|
958
|
+
canvases: config.canvases?.map((canvas) => canvas.declaration),
|
|
959
|
+
requestCanvasRenderer: config.requestCanvasRenderer,
|
|
960
|
+
requestExtensions: config.requestExtensions,
|
|
961
|
+
extensionInfo: config.extensionInfo,
|
|
696
962
|
commands: config.commands?.map((cmd) => ({
|
|
697
963
|
name: cmd.name,
|
|
698
964
|
description: cmd.description
|
|
699
965
|
})),
|
|
700
966
|
provider: config.provider,
|
|
701
967
|
modelCapabilities: config.modelCapabilities,
|
|
968
|
+
largeOutput: toWireLargeOutput(config.largeOutput),
|
|
702
969
|
requestPermission: config.onPermissionRequest !== import_types.defaultJoinSessionPermissionHandler,
|
|
703
970
|
requestUserInput: !!config.onUserInputRequest,
|
|
704
971
|
requestElicitation: !!config.onElicitationRequest,
|
|
972
|
+
...config.enableMcpApps ? { requestMcpApps: true } : {},
|
|
973
|
+
requestExitPlanMode: !!config.onExitPlanModeRequest,
|
|
974
|
+
requestAutoModeSwitch: !!config.onAutoModeSwitchRequest,
|
|
705
975
|
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
706
976
|
workingDirectory: config.workingDirectory,
|
|
707
|
-
configDir: config.
|
|
977
|
+
configDir: config.configDirectory,
|
|
708
978
|
enableConfigDiscovery: config.enableConfigDiscovery,
|
|
979
|
+
skipEmbeddingRetrieval: config.skipEmbeddingRetrieval,
|
|
980
|
+
embeddingCacheStorage: config.embeddingCacheStorage,
|
|
981
|
+
organizationCustomInstructions: config.organizationCustomInstructions,
|
|
982
|
+
enableOnDemandInstructionDiscovery: config.enableOnDemandInstructionDiscovery,
|
|
983
|
+
enableFileHooks: config.enableFileHooks,
|
|
984
|
+
enableHostGitOperations: config.enableHostGitOperations,
|
|
985
|
+
enableSessionStore: config.enableSessionStore,
|
|
986
|
+
enableSkills: config.enableSkills,
|
|
709
987
|
streaming: config.streaming,
|
|
710
988
|
includeSubAgentStreamingEvents: config.includeSubAgentStreamingEvents ?? true,
|
|
711
|
-
mcpServers: config.mcpServers,
|
|
989
|
+
mcpServers: toWireMcpServers(config.mcpServers),
|
|
990
|
+
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
712
991
|
envValueMode: "direct",
|
|
713
|
-
customAgents: config.customAgents,
|
|
992
|
+
customAgents: toWireCustomAgents(config.customAgents),
|
|
714
993
|
defaultAgent: config.defaultAgent,
|
|
715
994
|
agent: config.agent,
|
|
716
995
|
skillDirectories: config.skillDirectories,
|
|
996
|
+
pluginDirectories: config.pluginDirectories,
|
|
717
997
|
instructionDirectories: config.instructionDirectories,
|
|
718
998
|
disabledSkills: config.disabledSkills,
|
|
719
999
|
infiniteSessions: config.infiniteSessions,
|
|
720
|
-
|
|
1000
|
+
suppressResumeEvent: config.suppressResumeEvent,
|
|
721
1001
|
continuePendingWork: config.continuePendingWork,
|
|
722
|
-
gitHubToken: config.gitHubToken
|
|
1002
|
+
gitHubToken: config.gitHubToken,
|
|
1003
|
+
remoteSession: config.remoteSession,
|
|
1004
|
+
openCanvases: config.openCanvases
|
|
723
1005
|
});
|
|
724
|
-
const { workspacePath, capabilities } = response;
|
|
1006
|
+
const { workspacePath, capabilities, openCanvases } = response;
|
|
725
1007
|
session["_workspacePath"] = workspacePath;
|
|
726
1008
|
session.setCapabilities(capabilities);
|
|
1009
|
+
session.setOpenCanvases(openCanvases ?? []);
|
|
1010
|
+
await this.updateSessionOptionsForMode(session, config);
|
|
727
1011
|
} catch (e) {
|
|
728
1012
|
this.sessions.delete(sessionId);
|
|
729
1013
|
throw e;
|
|
730
1014
|
}
|
|
731
1015
|
return session;
|
|
732
1016
|
}
|
|
733
|
-
/**
|
|
734
|
-
* Gets the current connection state of the client.
|
|
735
|
-
*
|
|
736
|
-
* @returns The current connection state: "disconnected", "connecting", "connected", or "error"
|
|
737
|
-
*
|
|
738
|
-
* @example
|
|
739
|
-
* ```typescript
|
|
740
|
-
* if (client.getState() === "connected") {
|
|
741
|
-
* const session = await client.createSession({ onPermissionRequest: approveAll });
|
|
742
|
-
* }
|
|
743
|
-
* ```
|
|
744
|
-
*/
|
|
745
|
-
getState() {
|
|
746
|
-
return this.state;
|
|
747
|
-
}
|
|
748
1017
|
/**
|
|
749
1018
|
* Sends a ping request to the server to verify connectivity.
|
|
750
1019
|
*
|
|
@@ -857,7 +1126,7 @@ class CopilotClient {
|
|
|
857
1126
|
);
|
|
858
1127
|
serverVersion = result.protocolVersion;
|
|
859
1128
|
} catch (err) {
|
|
860
|
-
if (err instanceof import_node.ResponseError && err.code === import_node.ErrorCodes.MethodNotFound) {
|
|
1129
|
+
if (err instanceof import_node.ResponseError && (err.code === import_node.ErrorCodes.MethodNotFound || err.message === "Unhandled method connect")) {
|
|
861
1130
|
serverVersion = (await raceAgainstExit(this.ping())).protocolVersion;
|
|
862
1131
|
} else {
|
|
863
1132
|
throw err;
|
|
@@ -946,8 +1215,13 @@ class CopilotClient {
|
|
|
946
1215
|
if (!this.connection) {
|
|
947
1216
|
throw new Error("Client not connected");
|
|
948
1217
|
}
|
|
1218
|
+
let wireFilter;
|
|
1219
|
+
if (filter) {
|
|
1220
|
+
const { workingDirectory, ...rest } = filter;
|
|
1221
|
+
wireFilter = { ...rest, cwd: workingDirectory };
|
|
1222
|
+
}
|
|
949
1223
|
const response = await this.connection.sendRequest("session.list", {
|
|
950
|
-
filter
|
|
1224
|
+
filter: wireFilter
|
|
951
1225
|
});
|
|
952
1226
|
const { sessions } = response;
|
|
953
1227
|
return sessions.map(CopilotClient.toSessionMetadata);
|
|
@@ -982,13 +1256,19 @@ class CopilotClient {
|
|
|
982
1256
|
return CopilotClient.toSessionMetadata(session);
|
|
983
1257
|
}
|
|
984
1258
|
static toSessionMetadata(raw) {
|
|
1259
|
+
const { context } = raw;
|
|
985
1260
|
return {
|
|
986
1261
|
sessionId: raw.sessionId,
|
|
987
1262
|
startTime: new Date(raw.startTime),
|
|
988
1263
|
modifiedTime: new Date(raw.modifiedTime),
|
|
989
1264
|
summary: raw.summary,
|
|
990
1265
|
isRemote: raw.isRemote,
|
|
991
|
-
context:
|
|
1266
|
+
context: context ? {
|
|
1267
|
+
workingDirectory: context.cwd,
|
|
1268
|
+
gitRoot: context.gitRoot,
|
|
1269
|
+
repository: context.repository,
|
|
1270
|
+
branch: context.branch
|
|
1271
|
+
} : void 0
|
|
992
1272
|
};
|
|
993
1273
|
}
|
|
994
1274
|
/**
|
|
@@ -1041,7 +1321,7 @@ class CopilotClient {
|
|
|
1041
1321
|
throw new Error(result.error || "Failed to set foreground session");
|
|
1042
1322
|
}
|
|
1043
1323
|
}
|
|
1044
|
-
|
|
1324
|
+
onLifecycle(eventTypeOrHandler, handler) {
|
|
1045
1325
|
if (typeof eventTypeOrHandler === "string" && handler) {
|
|
1046
1326
|
const eventType = eventTypeOrHandler;
|
|
1047
1327
|
if (!this.typedLifecycleHandlers.has(eventType)) {
|
|
@@ -1068,17 +1348,17 @@ class CopilotClient {
|
|
|
1068
1348
|
async startCLIServer() {
|
|
1069
1349
|
return new Promise((resolve, reject) => {
|
|
1070
1350
|
this.stderrBuffer = "";
|
|
1071
|
-
const args = [
|
|
1072
|
-
|
|
1073
|
-
"--
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
this.options.logLevel
|
|
1077
|
-
];
|
|
1078
|
-
if (this.options.useStdio) {
|
|
1351
|
+
const args = [...this.connectionExtraArgs, "--headless", "--no-auto-update"];
|
|
1352
|
+
if (this.options.logLevel) {
|
|
1353
|
+
args.push("--log-level", this.options.logLevel);
|
|
1354
|
+
}
|
|
1355
|
+
if (this.connectionConfig.kind === "stdio") {
|
|
1079
1356
|
args.push("--stdio");
|
|
1080
|
-
} else if (this.
|
|
1081
|
-
|
|
1357
|
+
} else if (this.connectionConfig.kind === "tcp") {
|
|
1358
|
+
const requestedPort = this.connectionConfig.port ?? 0;
|
|
1359
|
+
if (requestedPort > 0) {
|
|
1360
|
+
args.push("--port", requestedPort.toString());
|
|
1361
|
+
}
|
|
1082
1362
|
}
|
|
1083
1363
|
if (this.options.gitHubToken) {
|
|
1084
1364
|
args.push("--auth-token-env", "COPILOT_SDK_AUTH_TOKEN");
|
|
@@ -1092,7 +1372,10 @@ class CopilotClient {
|
|
|
1092
1372
|
this.options.sessionIdleTimeoutSeconds.toString()
|
|
1093
1373
|
);
|
|
1094
1374
|
}
|
|
1095
|
-
|
|
1375
|
+
if (this.options.enableRemoteSessions) {
|
|
1376
|
+
args.push("--remote");
|
|
1377
|
+
}
|
|
1378
|
+
const envWithoutNodeDebug = { ...this.resolvedEnv };
|
|
1096
1379
|
delete envWithoutNodeDebug.NODE_DEBUG;
|
|
1097
1380
|
if (this.options.gitHubToken) {
|
|
1098
1381
|
envWithoutNodeDebug.COPILOT_SDK_AUTH_TOKEN = this.options.gitHubToken;
|
|
@@ -1100,12 +1383,15 @@ class CopilotClient {
|
|
|
1100
1383
|
if (this.effectiveConnectionToken) {
|
|
1101
1384
|
envWithoutNodeDebug.COPILOT_CONNECTION_TOKEN = this.effectiveConnectionToken;
|
|
1102
1385
|
}
|
|
1103
|
-
if (this.options.
|
|
1104
|
-
envWithoutNodeDebug.COPILOT_HOME = this.options.
|
|
1386
|
+
if (this.options.baseDirectory) {
|
|
1387
|
+
envWithoutNodeDebug.COPILOT_HOME = this.options.baseDirectory;
|
|
1105
1388
|
}
|
|
1106
|
-
if (
|
|
1389
|
+
if (this.options.mode === "empty") {
|
|
1390
|
+
envWithoutNodeDebug.COPILOT_DISABLE_KEYTAR = "1";
|
|
1391
|
+
}
|
|
1392
|
+
if (!this.resolvedCliPath) {
|
|
1107
1393
|
throw new Error(
|
|
1108
|
-
"Path to Copilot CLI is required. Please
|
|
1394
|
+
"Path to Copilot CLI is required. Please supply it via `RuntimeConnection.forStdio({ path })` or `RuntimeConnection.forTcp({ path })`, set the COPILOT_CLI_PATH environment variable, or use `RuntimeConnection.forUri(...)` to connect to an already-running runtime."
|
|
1109
1395
|
);
|
|
1110
1396
|
}
|
|
1111
1397
|
if (this.options.telemetry) {
|
|
@@ -1124,31 +1410,31 @@ class CopilotClient {
|
|
|
1124
1410
|
t.captureContent
|
|
1125
1411
|
);
|
|
1126
1412
|
}
|
|
1127
|
-
if (!(0, import_node_fs.existsSync)(this.
|
|
1413
|
+
if (!(0, import_node_fs.existsSync)(this.resolvedCliPath)) {
|
|
1128
1414
|
throw new Error(
|
|
1129
|
-
`Copilot CLI not found at ${this.
|
|
1415
|
+
`Copilot CLI not found at ${this.resolvedCliPath}. Ensure @github/copilot is installed.`
|
|
1130
1416
|
);
|
|
1131
1417
|
}
|
|
1132
|
-
const stdioConfig = this.
|
|
1133
|
-
const isJsFile = this.
|
|
1418
|
+
const stdioConfig = this.connectionConfig.kind === "stdio" ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
|
|
1419
|
+
const isJsFile = this.resolvedCliPath.endsWith(".js");
|
|
1134
1420
|
if (isJsFile) {
|
|
1135
|
-
this.cliProcess = (0, import_node_child_process.spawn)(getNodeExecPath(), [this.
|
|
1421
|
+
this.cliProcess = (0, import_node_child_process.spawn)(getNodeExecPath(), [this.resolvedCliPath, ...args], {
|
|
1136
1422
|
stdio: stdioConfig,
|
|
1137
|
-
cwd: this.options.
|
|
1423
|
+
cwd: this.options.workingDirectory,
|
|
1138
1424
|
env: envWithoutNodeDebug,
|
|
1139
1425
|
windowsHide: true
|
|
1140
1426
|
});
|
|
1141
1427
|
} else {
|
|
1142
|
-
this.cliProcess = (0, import_node_child_process.spawn)(this.
|
|
1428
|
+
this.cliProcess = (0, import_node_child_process.spawn)(this.resolvedCliPath, args, {
|
|
1143
1429
|
stdio: stdioConfig,
|
|
1144
|
-
cwd: this.options.
|
|
1430
|
+
cwd: this.options.workingDirectory,
|
|
1145
1431
|
env: envWithoutNodeDebug,
|
|
1146
1432
|
windowsHide: true
|
|
1147
1433
|
});
|
|
1148
1434
|
}
|
|
1149
1435
|
let stdout = "";
|
|
1150
1436
|
let resolved = false;
|
|
1151
|
-
if (this.
|
|
1437
|
+
if (this.connectionConfig.kind === "stdio") {
|
|
1152
1438
|
resolved = true;
|
|
1153
1439
|
resolve();
|
|
1154
1440
|
} else {
|
|
@@ -1156,7 +1442,7 @@ class CopilotClient {
|
|
|
1156
1442
|
stdout += data.toString();
|
|
1157
1443
|
const match = stdout.match(/listening on port (\d+)/i);
|
|
1158
1444
|
if (match && !resolved) {
|
|
1159
|
-
this.
|
|
1445
|
+
this.runtimePort = parseInt(match[1], 10);
|
|
1160
1446
|
resolved = true;
|
|
1161
1447
|
resolve();
|
|
1162
1448
|
}
|
|
@@ -1230,19 +1516,21 @@ stderr: ${stderrOutput}`
|
|
|
1230
1516
|
resolved = true;
|
|
1231
1517
|
reject(new Error("Timeout waiting for CLI server to start"));
|
|
1232
1518
|
}
|
|
1233
|
-
},
|
|
1519
|
+
}, 3e4);
|
|
1234
1520
|
});
|
|
1235
1521
|
}
|
|
1236
1522
|
/**
|
|
1237
1523
|
* Connect to the CLI server (via socket or stdio)
|
|
1238
1524
|
*/
|
|
1239
1525
|
async connectToServer() {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1526
|
+
switch (this.connectionConfig.kind) {
|
|
1527
|
+
case "parent-process":
|
|
1528
|
+
return this.connectToParentProcessViaStdio();
|
|
1529
|
+
case "stdio":
|
|
1530
|
+
return this.connectToChildProcessViaStdio();
|
|
1531
|
+
case "tcp":
|
|
1532
|
+
case "uri":
|
|
1533
|
+
return this.connectViaTcp();
|
|
1246
1534
|
}
|
|
1247
1535
|
}
|
|
1248
1536
|
/**
|
|
@@ -1282,12 +1570,17 @@ stderr: ${stderrOutput}`
|
|
|
1282
1570
|
* Connect to the CLI server via TCP socket
|
|
1283
1571
|
*/
|
|
1284
1572
|
async connectViaTcp() {
|
|
1285
|
-
if (!this.
|
|
1573
|
+
if (!this.runtimePort) {
|
|
1286
1574
|
throw new Error("Server port not available");
|
|
1287
1575
|
}
|
|
1288
1576
|
return new Promise((resolve, reject) => {
|
|
1289
1577
|
this.socket = new import_node_net.Socket();
|
|
1290
|
-
|
|
1578
|
+
const connectionTimeout = setTimeout(() => {
|
|
1579
|
+
this.socket?.destroy();
|
|
1580
|
+
reject(new Error("Timeout connecting to CLI server"));
|
|
1581
|
+
}, 1e4);
|
|
1582
|
+
this.socket.connect(this.runtimePort, this.actualHost, () => {
|
|
1583
|
+
clearTimeout(connectionTimeout);
|
|
1291
1584
|
this.connection = (0, import_node.createMessageConnection)(
|
|
1292
1585
|
new import_node.StreamMessageReader(this.socket),
|
|
1293
1586
|
new import_node.StreamMessageWriter(this.socket)
|
|
@@ -1297,6 +1590,7 @@ stderr: ${stderrOutput}`
|
|
|
1297
1590
|
resolve();
|
|
1298
1591
|
});
|
|
1299
1592
|
this.socket.on("error", (error) => {
|
|
1593
|
+
clearTimeout(connectionTimeout);
|
|
1300
1594
|
reject(new Error(`Failed to connect to CLI server: ${error.message}`));
|
|
1301
1595
|
});
|
|
1302
1596
|
});
|
|
@@ -1312,16 +1606,16 @@ stderr: ${stderrOutput}`
|
|
|
1312
1606
|
this.handleSessionLifecycleNotification(notification);
|
|
1313
1607
|
});
|
|
1314
1608
|
this.connection.onRequest(
|
|
1315
|
-
"
|
|
1316
|
-
async (params) => await this.
|
|
1609
|
+
"userInput.request",
|
|
1610
|
+
async (params) => await this.handleUserInputRequest(params)
|
|
1317
1611
|
);
|
|
1318
1612
|
this.connection.onRequest(
|
|
1319
|
-
"
|
|
1320
|
-
async (params) => await this.
|
|
1613
|
+
"exitPlanMode.request",
|
|
1614
|
+
async (params) => await this.handleExitPlanModeRequest(params)
|
|
1321
1615
|
);
|
|
1322
1616
|
this.connection.onRequest(
|
|
1323
|
-
"
|
|
1324
|
-
async (params) => await this.
|
|
1617
|
+
"autoModeSwitch.request",
|
|
1618
|
+
async (params) => await this.handleAutoModeSwitchRequest(params)
|
|
1325
1619
|
);
|
|
1326
1620
|
this.connection.onRequest(
|
|
1327
1621
|
"hooks.invoke",
|
|
@@ -1357,7 +1651,20 @@ stderr: ${stderrOutput}`
|
|
|
1357
1651
|
if (typeof notification !== "object" || !notification || !("type" in notification) || typeof notification.type !== "string" || !("sessionId" in notification) || typeof notification.sessionId !== "string") {
|
|
1358
1652
|
return;
|
|
1359
1653
|
}
|
|
1360
|
-
const
|
|
1654
|
+
const raw = notification;
|
|
1655
|
+
let metadata;
|
|
1656
|
+
if (raw.metadata && raw.metadata.startTime && raw.metadata.modifiedTime) {
|
|
1657
|
+
metadata = {
|
|
1658
|
+
startTime: new Date(raw.metadata.startTime),
|
|
1659
|
+
modifiedTime: new Date(raw.metadata.modifiedTime),
|
|
1660
|
+
summary: raw.metadata.summary
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
const event = {
|
|
1664
|
+
type: raw.type,
|
|
1665
|
+
sessionId: raw.sessionId,
|
|
1666
|
+
metadata
|
|
1667
|
+
};
|
|
1361
1668
|
const typedHandlers = this.typedLifecycleHandlers.get(event.type);
|
|
1362
1669
|
if (typedHandlers) {
|
|
1363
1670
|
for (const handler of typedHandlers) {
|
|
@@ -1389,125 +1696,55 @@ stderr: ${stderrOutput}`
|
|
|
1389
1696
|
});
|
|
1390
1697
|
return result;
|
|
1391
1698
|
}
|
|
1392
|
-
async
|
|
1393
|
-
if (!params || typeof params.sessionId !== "string" || typeof params.
|
|
1394
|
-
throw new Error("Invalid
|
|
1699
|
+
async handleExitPlanModeRequest(params) {
|
|
1700
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.summary !== "string" || !Array.isArray(params.actions) || typeof params.recommendedAction !== "string") {
|
|
1701
|
+
throw new Error("Invalid exit plan mode request payload");
|
|
1395
1702
|
}
|
|
1396
1703
|
const session = this.sessions.get(params.sessionId);
|
|
1397
1704
|
if (!session) {
|
|
1398
1705
|
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1399
1706
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
1707
|
+
return await session._handleExitPlanModeRequest({
|
|
1708
|
+
summary: params.summary,
|
|
1709
|
+
planContent: params.planContent,
|
|
1710
|
+
actions: params.actions,
|
|
1711
|
+
recommendedAction: params.recommendedAction
|
|
1712
|
+
});
|
|
1402
1713
|
}
|
|
1403
|
-
async
|
|
1404
|
-
if (!params || typeof params.sessionId !== "string"
|
|
1405
|
-
throw new Error("Invalid
|
|
1714
|
+
async handleAutoModeSwitchRequest(params) {
|
|
1715
|
+
if (!params || typeof params.sessionId !== "string") {
|
|
1716
|
+
throw new Error("Invalid auto mode switch request payload");
|
|
1406
1717
|
}
|
|
1407
1718
|
const session = this.sessions.get(params.sessionId);
|
|
1408
1719
|
if (!session) {
|
|
1409
1720
|
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1410
1721
|
}
|
|
1411
|
-
|
|
1722
|
+
const response = await session._handleAutoModeSwitchRequest({
|
|
1723
|
+
errorCode: params.errorCode,
|
|
1724
|
+
retryAfterSeconds: params.retryAfterSeconds
|
|
1725
|
+
});
|
|
1726
|
+
return { response };
|
|
1412
1727
|
}
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
/**
|
|
1417
|
-
* Handles a v2-style tool.call RPC request from the server.
|
|
1418
|
-
* Looks up the session and tool handler, executes it, and returns the result
|
|
1419
|
-
* in the v2 response format.
|
|
1420
|
-
*/
|
|
1421
|
-
async handleToolCallRequestV2(params) {
|
|
1422
|
-
if (!params || typeof params.sessionId !== "string" || typeof params.toolCallId !== "string" || typeof params.toolName !== "string") {
|
|
1423
|
-
throw new Error("Invalid tool call payload");
|
|
1728
|
+
async handleHooksInvoke(params) {
|
|
1729
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
|
|
1730
|
+
throw new Error("Invalid hooks invoke payload");
|
|
1424
1731
|
}
|
|
1425
1732
|
const session = this.sessions.get(params.sessionId);
|
|
1426
1733
|
if (!session) {
|
|
1427
|
-
throw new Error(`
|
|
1428
|
-
}
|
|
1429
|
-
const handler = session.getToolHandler(params.toolName);
|
|
1430
|
-
if (!handler) {
|
|
1431
|
-
return {
|
|
1432
|
-
result: {
|
|
1433
|
-
textResultForLlm: `Tool '${params.toolName}' is not supported by this client instance.`,
|
|
1434
|
-
resultType: "failure",
|
|
1435
|
-
error: `tool '${params.toolName}' not supported`,
|
|
1436
|
-
toolTelemetry: {}
|
|
1437
|
-
}
|
|
1438
|
-
};
|
|
1439
|
-
}
|
|
1440
|
-
try {
|
|
1441
|
-
const traceparent = params.traceparent;
|
|
1442
|
-
const tracestate = params.tracestate;
|
|
1443
|
-
const invocation = {
|
|
1444
|
-
sessionId: params.sessionId,
|
|
1445
|
-
toolCallId: params.toolCallId,
|
|
1446
|
-
toolName: params.toolName,
|
|
1447
|
-
arguments: params.arguments,
|
|
1448
|
-
traceparent,
|
|
1449
|
-
tracestate
|
|
1450
|
-
};
|
|
1451
|
-
const result = await handler(params.arguments, invocation);
|
|
1452
|
-
return { result: this.normalizeToolResultV2(result) };
|
|
1453
|
-
} catch (error) {
|
|
1454
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1455
|
-
return {
|
|
1456
|
-
result: {
|
|
1457
|
-
textResultForLlm: "Invoking this tool produced an error. Detailed information is not available.",
|
|
1458
|
-
resultType: "failure",
|
|
1459
|
-
error: message,
|
|
1460
|
-
toolTelemetry: {}
|
|
1461
|
-
}
|
|
1462
|
-
};
|
|
1734
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1463
1735
|
}
|
|
1736
|
+
const output = await session._handleHooksInvoke(params.hookType, params.input);
|
|
1737
|
+
return { output };
|
|
1464
1738
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
async handlePermissionRequestV2(params) {
|
|
1469
|
-
if (!params || typeof params.sessionId !== "string" || !params.permissionRequest) {
|
|
1470
|
-
throw new Error("Invalid permission request payload");
|
|
1739
|
+
async handleSystemMessageTransform(params) {
|
|
1740
|
+
if (!params || typeof params.sessionId !== "string" || !params.sections || typeof params.sections !== "object") {
|
|
1741
|
+
throw new Error("Invalid systemMessage.transform payload");
|
|
1471
1742
|
}
|
|
1472
1743
|
const session = this.sessions.get(params.sessionId);
|
|
1473
1744
|
if (!session) {
|
|
1474
1745
|
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1475
1746
|
}
|
|
1476
|
-
|
|
1477
|
-
const result = await session._handlePermissionRequestV2(params.permissionRequest);
|
|
1478
|
-
return { result };
|
|
1479
|
-
} catch (error) {
|
|
1480
|
-
if (error instanceof Error && error.message === import_session.NO_RESULT_PERMISSION_V2_ERROR) {
|
|
1481
|
-
throw error;
|
|
1482
|
-
}
|
|
1483
|
-
return {
|
|
1484
|
-
result: {
|
|
1485
|
-
kind: "user-not-available"
|
|
1486
|
-
}
|
|
1487
|
-
};
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
normalizeToolResultV2(result) {
|
|
1491
|
-
if (result === void 0 || result === null) {
|
|
1492
|
-
return {
|
|
1493
|
-
textResultForLlm: "Tool returned no result",
|
|
1494
|
-
resultType: "failure",
|
|
1495
|
-
error: "tool returned no result",
|
|
1496
|
-
toolTelemetry: {}
|
|
1497
|
-
};
|
|
1498
|
-
}
|
|
1499
|
-
if (this.isToolResultObject(result)) {
|
|
1500
|
-
return result;
|
|
1501
|
-
}
|
|
1502
|
-
const textResult = typeof result === "string" ? result : JSON.stringify(result);
|
|
1503
|
-
return {
|
|
1504
|
-
textResultForLlm: textResult,
|
|
1505
|
-
resultType: "success",
|
|
1506
|
-
toolTelemetry: {}
|
|
1507
|
-
};
|
|
1508
|
-
}
|
|
1509
|
-
isToolResultObject(value) {
|
|
1510
|
-
return typeof value === "object" && value !== null && "textResultForLlm" in value && typeof value.textResultForLlm === "string" && "resultType" in value;
|
|
1747
|
+
return await session._handleSystemMessageTransform(params.sections);
|
|
1511
1748
|
}
|
|
1512
1749
|
}
|
|
1513
1750
|
// Annotate the CommonJS export names for ESM import in node:
|