@github/copilot-sdk 1.0.0-beta.1 → 1.0.0-beta.11
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 +61 -48
- 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 +540 -299
- package/dist/cjs/extension.js +12 -3
- package/dist/cjs/generated/rpc.js +1332 -15
- 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 +541 -300
- package/dist/extension.d.ts +4 -2
- package/dist/extension.js +13 -3
- package/dist/generated/rpc.d.ts +10205 -994
- package/dist/generated/rpc.js +1332 -15
- package/dist/generated/session-events.d.ts +2061 -194
- package/dist/index.d.ts +6 -2
- package/dist/index.js +15 -2
- package/dist/session.d.ts +19 -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 +753 -123
- package/dist/types.js +36 -3
- package/docs/agent-author.md +31 -7
- package/docs/examples.md +29 -19
- package/package.json +4 -4
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,190 @@ 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,
|
|
785
|
+
contextTier: config.contextTier,
|
|
558
786
|
tools: config.tools?.map((tool) => ({
|
|
559
787
|
name: tool.name,
|
|
560
788
|
description: tool.description,
|
|
@@ -562,40 +790,82 @@ class CopilotClient {
|
|
|
562
790
|
overridesBuiltInTool: tool.overridesBuiltInTool,
|
|
563
791
|
skipPermission: tool.skipPermission
|
|
564
792
|
})),
|
|
793
|
+
canvases: config.canvases?.map((canvas) => canvas.declaration),
|
|
794
|
+
requestCanvasRenderer: config.requestCanvasRenderer,
|
|
795
|
+
requestExtensions: config.requestExtensions,
|
|
796
|
+
extensionSdkPath: config.extensionSdkPath,
|
|
797
|
+
extensionInfo: config.extensionInfo,
|
|
565
798
|
commands: config.commands?.map((cmd) => ({
|
|
566
799
|
name: cmd.name,
|
|
567
800
|
description: cmd.description
|
|
568
801
|
})),
|
|
569
802
|
systemMessage: wireSystemMessage,
|
|
570
|
-
availableTools:
|
|
571
|
-
excludedTools:
|
|
803
|
+
availableTools: toolFilterOptions.availableTools,
|
|
804
|
+
excludedTools: toolFilterOptions.excludedTools,
|
|
805
|
+
toolFilterPrecedence: toolFilterOptions.toolFilterPrecedence,
|
|
572
806
|
provider: config.provider,
|
|
807
|
+
enableSessionTelemetry: config.enableSessionTelemetry,
|
|
573
808
|
modelCapabilities: config.modelCapabilities,
|
|
574
|
-
|
|
809
|
+
largeOutput: toWireLargeOutput(config.largeOutput),
|
|
810
|
+
requestPermission: !!config.onPermissionRequest,
|
|
575
811
|
requestUserInput: !!config.onUserInputRequest,
|
|
576
812
|
requestElicitation: !!config.onElicitationRequest,
|
|
813
|
+
...config.enableMcpApps ? { requestMcpApps: true } : {},
|
|
814
|
+
requestExitPlanMode: !!config.onExitPlanModeRequest,
|
|
815
|
+
requestAutoModeSwitch: !!config.onAutoModeSwitchRequest,
|
|
577
816
|
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
578
817
|
workingDirectory: config.workingDirectory,
|
|
579
818
|
streaming: config.streaming,
|
|
580
819
|
includeSubAgentStreamingEvents: config.includeSubAgentStreamingEvents ?? true,
|
|
581
|
-
mcpServers: config.mcpServers,
|
|
820
|
+
mcpServers: toWireMcpServers(config.mcpServers),
|
|
821
|
+
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
582
822
|
envValueMode: "direct",
|
|
583
|
-
customAgents: config.customAgents,
|
|
823
|
+
customAgents: toWireCustomAgents(config.customAgents),
|
|
584
824
|
defaultAgent: config.defaultAgent,
|
|
585
825
|
agent: config.agent,
|
|
586
|
-
configDir: config.
|
|
826
|
+
configDir: config.configDirectory,
|
|
587
827
|
enableConfigDiscovery: config.enableConfigDiscovery,
|
|
828
|
+
skipEmbeddingRetrieval: config.skipEmbeddingRetrieval,
|
|
829
|
+
embeddingCacheStorage: config.embeddingCacheStorage,
|
|
830
|
+
organizationCustomInstructions: config.organizationCustomInstructions,
|
|
831
|
+
enableOnDemandInstructionDiscovery: config.enableOnDemandInstructionDiscovery,
|
|
832
|
+
enableFileHooks: config.enableFileHooks,
|
|
833
|
+
enableHostGitOperations: config.enableHostGitOperations,
|
|
834
|
+
enableSessionStore: config.enableSessionStore,
|
|
835
|
+
enableSkills: config.enableSkills,
|
|
588
836
|
skillDirectories: config.skillDirectories,
|
|
837
|
+
pluginDirectories: config.pluginDirectories,
|
|
589
838
|
instructionDirectories: config.instructionDirectories,
|
|
590
839
|
disabledSkills: config.disabledSkills,
|
|
591
840
|
infiniteSessions: config.infiniteSessions,
|
|
592
|
-
gitHubToken: config.gitHubToken
|
|
841
|
+
gitHubToken: config.gitHubToken,
|
|
842
|
+
remoteSession: config.remoteSession,
|
|
843
|
+
cloud: config.cloud
|
|
593
844
|
});
|
|
594
|
-
const {
|
|
845
|
+
const {
|
|
846
|
+
sessionId: returnedSessionId,
|
|
847
|
+
workspacePath,
|
|
848
|
+
capabilities
|
|
849
|
+
} = response;
|
|
850
|
+
if (!returnedSessionId) {
|
|
851
|
+
throw new Error("session.create response did not include a sessionId");
|
|
852
|
+
}
|
|
853
|
+
if (localSessionId !== void 0 && localSessionId !== returnedSessionId) {
|
|
854
|
+
throw new Error(
|
|
855
|
+
`session.create returned sessionId ${returnedSessionId} but the caller requested ${localSessionId}`
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
if (session === void 0) {
|
|
859
|
+
session = initializeSession(returnedSessionId);
|
|
860
|
+
registeredId = returnedSessionId;
|
|
861
|
+
}
|
|
595
862
|
session["_workspacePath"] = workspacePath;
|
|
596
863
|
session.setCapabilities(capabilities);
|
|
864
|
+
await this.updateSessionOptionsForMode(session, config);
|
|
597
865
|
} catch (e) {
|
|
598
|
-
|
|
866
|
+
if (registeredId !== void 0) {
|
|
867
|
+
this.sessions.delete(registeredId);
|
|
868
|
+
}
|
|
599
869
|
throw e;
|
|
600
870
|
}
|
|
601
871
|
return session;
|
|
@@ -625,17 +895,8 @@ class CopilotClient {
|
|
|
625
895
|
* ```
|
|
626
896
|
*/
|
|
627
897
|
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
898
|
if (!this.connection) {
|
|
634
|
-
|
|
635
|
-
await this.start();
|
|
636
|
-
} else {
|
|
637
|
-
throw new Error("Client not connected. Call start() first.");
|
|
638
|
-
}
|
|
899
|
+
await this.start();
|
|
639
900
|
}
|
|
640
901
|
const session = new import_session.CopilotSession(
|
|
641
902
|
sessionId,
|
|
@@ -644,6 +905,7 @@ class CopilotClient {
|
|
|
644
905
|
this.onGetTraceContext
|
|
645
906
|
);
|
|
646
907
|
session.registerTools(config.tools);
|
|
908
|
+
session.registerCanvases(config.canvases);
|
|
647
909
|
session.registerCommands(config.commands);
|
|
648
910
|
session.registerPermissionHandler(config.onPermissionRequest);
|
|
649
911
|
if (config.onUserInputRequest) {
|
|
@@ -652,9 +914,17 @@ class CopilotClient {
|
|
|
652
914
|
if (config.onElicitationRequest) {
|
|
653
915
|
session.registerElicitationHandler(config.onElicitationRequest);
|
|
654
916
|
}
|
|
917
|
+
if (config.onExitPlanModeRequest) {
|
|
918
|
+
session.registerExitPlanModeHandler(config.onExitPlanModeRequest);
|
|
919
|
+
}
|
|
920
|
+
if (config.onAutoModeSwitchRequest) {
|
|
921
|
+
session.registerAutoModeSwitchHandler(config.onAutoModeSwitchRequest);
|
|
922
|
+
}
|
|
655
923
|
if (config.hooks) {
|
|
656
924
|
session.registerHooks(config.hooks);
|
|
657
925
|
}
|
|
926
|
+
config = { ...this.configDefaultsForMode(), ...config };
|
|
927
|
+
config.systemMessage = this.getSystemMessageConfigForMode(config.systemMessage);
|
|
658
928
|
const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
|
|
659
929
|
config.systemMessage
|
|
660
930
|
);
|
|
@@ -665,17 +935,8 @@ class CopilotClient {
|
|
|
665
935
|
session.on(config.onEvent);
|
|
666
936
|
}
|
|
667
937
|
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
|
-
}
|
|
938
|
+
this.setupSessionFs(session, config);
|
|
939
|
+
const toolFilterOptions = this.resolveToolFilterOptions(config);
|
|
679
940
|
try {
|
|
680
941
|
const response = await this.connection.sendRequest("session.resume", {
|
|
681
942
|
...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
|
|
@@ -683,9 +944,13 @@ class CopilotClient {
|
|
|
683
944
|
clientName: config.clientName,
|
|
684
945
|
model: config.model,
|
|
685
946
|
reasoningEffort: config.reasoningEffort,
|
|
947
|
+
reasoningSummary: config.reasoningSummary,
|
|
948
|
+
contextTier: config.contextTier,
|
|
686
949
|
systemMessage: wireSystemMessage,
|
|
687
|
-
availableTools:
|
|
688
|
-
excludedTools:
|
|
950
|
+
availableTools: toolFilterOptions.availableTools,
|
|
951
|
+
excludedTools: toolFilterOptions.excludedTools,
|
|
952
|
+
toolFilterPrecedence: toolFilterOptions.toolFilterPrecedence,
|
|
953
|
+
enableSessionTelemetry: config.enableSessionTelemetry,
|
|
689
954
|
tools: config.tools?.map((tool) => ({
|
|
690
955
|
name: tool.name,
|
|
691
956
|
description: tool.description,
|
|
@@ -693,58 +958,66 @@ class CopilotClient {
|
|
|
693
958
|
overridesBuiltInTool: tool.overridesBuiltInTool,
|
|
694
959
|
skipPermission: tool.skipPermission
|
|
695
960
|
})),
|
|
961
|
+
canvases: config.canvases?.map((canvas) => canvas.declaration),
|
|
962
|
+
requestCanvasRenderer: config.requestCanvasRenderer,
|
|
963
|
+
requestExtensions: config.requestExtensions,
|
|
964
|
+
extensionSdkPath: config.extensionSdkPath,
|
|
965
|
+
extensionInfo: config.extensionInfo,
|
|
696
966
|
commands: config.commands?.map((cmd) => ({
|
|
697
967
|
name: cmd.name,
|
|
698
968
|
description: cmd.description
|
|
699
969
|
})),
|
|
700
970
|
provider: config.provider,
|
|
701
971
|
modelCapabilities: config.modelCapabilities,
|
|
972
|
+
largeOutput: toWireLargeOutput(config.largeOutput),
|
|
702
973
|
requestPermission: config.onPermissionRequest !== import_types.defaultJoinSessionPermissionHandler,
|
|
703
974
|
requestUserInput: !!config.onUserInputRequest,
|
|
704
975
|
requestElicitation: !!config.onElicitationRequest,
|
|
976
|
+
...config.enableMcpApps ? { requestMcpApps: true } : {},
|
|
977
|
+
requestExitPlanMode: !!config.onExitPlanModeRequest,
|
|
978
|
+
requestAutoModeSwitch: !!config.onAutoModeSwitchRequest,
|
|
705
979
|
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
706
980
|
workingDirectory: config.workingDirectory,
|
|
707
|
-
configDir: config.
|
|
981
|
+
configDir: config.configDirectory,
|
|
708
982
|
enableConfigDiscovery: config.enableConfigDiscovery,
|
|
983
|
+
skipEmbeddingRetrieval: config.skipEmbeddingRetrieval,
|
|
984
|
+
embeddingCacheStorage: config.embeddingCacheStorage,
|
|
985
|
+
organizationCustomInstructions: config.organizationCustomInstructions,
|
|
986
|
+
enableOnDemandInstructionDiscovery: config.enableOnDemandInstructionDiscovery,
|
|
987
|
+
enableFileHooks: config.enableFileHooks,
|
|
988
|
+
enableHostGitOperations: config.enableHostGitOperations,
|
|
989
|
+
enableSessionStore: config.enableSessionStore,
|
|
990
|
+
enableSkills: config.enableSkills,
|
|
709
991
|
streaming: config.streaming,
|
|
710
992
|
includeSubAgentStreamingEvents: config.includeSubAgentStreamingEvents ?? true,
|
|
711
|
-
mcpServers: config.mcpServers,
|
|
993
|
+
mcpServers: toWireMcpServers(config.mcpServers),
|
|
994
|
+
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
712
995
|
envValueMode: "direct",
|
|
713
|
-
customAgents: config.customAgents,
|
|
996
|
+
customAgents: toWireCustomAgents(config.customAgents),
|
|
714
997
|
defaultAgent: config.defaultAgent,
|
|
715
998
|
agent: config.agent,
|
|
716
999
|
skillDirectories: config.skillDirectories,
|
|
1000
|
+
pluginDirectories: config.pluginDirectories,
|
|
717
1001
|
instructionDirectories: config.instructionDirectories,
|
|
718
1002
|
disabledSkills: config.disabledSkills,
|
|
719
1003
|
infiniteSessions: config.infiniteSessions,
|
|
720
|
-
disableResume: config.
|
|
1004
|
+
disableResume: config.suppressResumeEvent,
|
|
721
1005
|
continuePendingWork: config.continuePendingWork,
|
|
722
|
-
gitHubToken: config.gitHubToken
|
|
1006
|
+
gitHubToken: config.gitHubToken,
|
|
1007
|
+
remoteSession: config.remoteSession,
|
|
1008
|
+
openCanvases: config.openCanvases
|
|
723
1009
|
});
|
|
724
|
-
const { workspacePath, capabilities } = response;
|
|
1010
|
+
const { workspacePath, capabilities, openCanvases } = response;
|
|
725
1011
|
session["_workspacePath"] = workspacePath;
|
|
726
1012
|
session.setCapabilities(capabilities);
|
|
1013
|
+
session.setOpenCanvases(openCanvases ?? []);
|
|
1014
|
+
await this.updateSessionOptionsForMode(session, config);
|
|
727
1015
|
} catch (e) {
|
|
728
1016
|
this.sessions.delete(sessionId);
|
|
729
1017
|
throw e;
|
|
730
1018
|
}
|
|
731
1019
|
return session;
|
|
732
1020
|
}
|
|
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
1021
|
/**
|
|
749
1022
|
* Sends a ping request to the server to verify connectivity.
|
|
750
1023
|
*
|
|
@@ -857,7 +1130,7 @@ class CopilotClient {
|
|
|
857
1130
|
);
|
|
858
1131
|
serverVersion = result.protocolVersion;
|
|
859
1132
|
} catch (err) {
|
|
860
|
-
if (err instanceof import_node.ResponseError && err.code === import_node.ErrorCodes.MethodNotFound) {
|
|
1133
|
+
if (err instanceof import_node.ResponseError && (err.code === import_node.ErrorCodes.MethodNotFound || err.message === "Unhandled method connect")) {
|
|
861
1134
|
serverVersion = (await raceAgainstExit(this.ping())).protocolVersion;
|
|
862
1135
|
} else {
|
|
863
1136
|
throw err;
|
|
@@ -946,8 +1219,13 @@ class CopilotClient {
|
|
|
946
1219
|
if (!this.connection) {
|
|
947
1220
|
throw new Error("Client not connected");
|
|
948
1221
|
}
|
|
1222
|
+
let wireFilter;
|
|
1223
|
+
if (filter) {
|
|
1224
|
+
const { workingDirectory, ...rest } = filter;
|
|
1225
|
+
wireFilter = { ...rest, cwd: workingDirectory };
|
|
1226
|
+
}
|
|
949
1227
|
const response = await this.connection.sendRequest("session.list", {
|
|
950
|
-
filter
|
|
1228
|
+
filter: wireFilter
|
|
951
1229
|
});
|
|
952
1230
|
const { sessions } = response;
|
|
953
1231
|
return sessions.map(CopilotClient.toSessionMetadata);
|
|
@@ -982,13 +1260,19 @@ class CopilotClient {
|
|
|
982
1260
|
return CopilotClient.toSessionMetadata(session);
|
|
983
1261
|
}
|
|
984
1262
|
static toSessionMetadata(raw) {
|
|
1263
|
+
const { context } = raw;
|
|
985
1264
|
return {
|
|
986
1265
|
sessionId: raw.sessionId,
|
|
987
1266
|
startTime: new Date(raw.startTime),
|
|
988
1267
|
modifiedTime: new Date(raw.modifiedTime),
|
|
989
1268
|
summary: raw.summary,
|
|
990
1269
|
isRemote: raw.isRemote,
|
|
991
|
-
context:
|
|
1270
|
+
context: context ? {
|
|
1271
|
+
workingDirectory: context.cwd,
|
|
1272
|
+
gitRoot: context.gitRoot,
|
|
1273
|
+
repository: context.repository,
|
|
1274
|
+
branch: context.branch
|
|
1275
|
+
} : void 0
|
|
992
1276
|
};
|
|
993
1277
|
}
|
|
994
1278
|
/**
|
|
@@ -1041,7 +1325,7 @@ class CopilotClient {
|
|
|
1041
1325
|
throw new Error(result.error || "Failed to set foreground session");
|
|
1042
1326
|
}
|
|
1043
1327
|
}
|
|
1044
|
-
|
|
1328
|
+
onLifecycle(eventTypeOrHandler, handler) {
|
|
1045
1329
|
if (typeof eventTypeOrHandler === "string" && handler) {
|
|
1046
1330
|
const eventType = eventTypeOrHandler;
|
|
1047
1331
|
if (!this.typedLifecycleHandlers.has(eventType)) {
|
|
@@ -1068,17 +1352,17 @@ class CopilotClient {
|
|
|
1068
1352
|
async startCLIServer() {
|
|
1069
1353
|
return new Promise((resolve, reject) => {
|
|
1070
1354
|
this.stderrBuffer = "";
|
|
1071
|
-
const args = [
|
|
1072
|
-
|
|
1073
|
-
"--
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
this.options.logLevel
|
|
1077
|
-
];
|
|
1078
|
-
if (this.options.useStdio) {
|
|
1355
|
+
const args = [...this.connectionExtraArgs, "--headless", "--no-auto-update"];
|
|
1356
|
+
if (this.options.logLevel) {
|
|
1357
|
+
args.push("--log-level", this.options.logLevel);
|
|
1358
|
+
}
|
|
1359
|
+
if (this.connectionConfig.kind === "stdio") {
|
|
1079
1360
|
args.push("--stdio");
|
|
1080
|
-
} else if (this.
|
|
1081
|
-
|
|
1361
|
+
} else if (this.connectionConfig.kind === "tcp") {
|
|
1362
|
+
const requestedPort = this.connectionConfig.port ?? 0;
|
|
1363
|
+
if (requestedPort > 0) {
|
|
1364
|
+
args.push("--port", requestedPort.toString());
|
|
1365
|
+
}
|
|
1082
1366
|
}
|
|
1083
1367
|
if (this.options.gitHubToken) {
|
|
1084
1368
|
args.push("--auth-token-env", "COPILOT_SDK_AUTH_TOKEN");
|
|
@@ -1092,7 +1376,10 @@ class CopilotClient {
|
|
|
1092
1376
|
this.options.sessionIdleTimeoutSeconds.toString()
|
|
1093
1377
|
);
|
|
1094
1378
|
}
|
|
1095
|
-
|
|
1379
|
+
if (this.options.enableRemoteSessions) {
|
|
1380
|
+
args.push("--remote");
|
|
1381
|
+
}
|
|
1382
|
+
const envWithoutNodeDebug = { ...this.resolvedEnv };
|
|
1096
1383
|
delete envWithoutNodeDebug.NODE_DEBUG;
|
|
1097
1384
|
if (this.options.gitHubToken) {
|
|
1098
1385
|
envWithoutNodeDebug.COPILOT_SDK_AUTH_TOKEN = this.options.gitHubToken;
|
|
@@ -1100,12 +1387,15 @@ class CopilotClient {
|
|
|
1100
1387
|
if (this.effectiveConnectionToken) {
|
|
1101
1388
|
envWithoutNodeDebug.COPILOT_CONNECTION_TOKEN = this.effectiveConnectionToken;
|
|
1102
1389
|
}
|
|
1103
|
-
if (this.options.
|
|
1104
|
-
envWithoutNodeDebug.COPILOT_HOME = this.options.
|
|
1390
|
+
if (this.options.baseDirectory) {
|
|
1391
|
+
envWithoutNodeDebug.COPILOT_HOME = this.options.baseDirectory;
|
|
1105
1392
|
}
|
|
1106
|
-
if (
|
|
1393
|
+
if (this.options.mode === "empty") {
|
|
1394
|
+
envWithoutNodeDebug.COPILOT_DISABLE_KEYTAR = "1";
|
|
1395
|
+
}
|
|
1396
|
+
if (!this.resolvedCliPath) {
|
|
1107
1397
|
throw new Error(
|
|
1108
|
-
"Path to Copilot CLI is required. Please
|
|
1398
|
+
"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
1399
|
);
|
|
1110
1400
|
}
|
|
1111
1401
|
if (this.options.telemetry) {
|
|
@@ -1124,31 +1414,31 @@ class CopilotClient {
|
|
|
1124
1414
|
t.captureContent
|
|
1125
1415
|
);
|
|
1126
1416
|
}
|
|
1127
|
-
if (!(0, import_node_fs.existsSync)(this.
|
|
1417
|
+
if (!(0, import_node_fs.existsSync)(this.resolvedCliPath)) {
|
|
1128
1418
|
throw new Error(
|
|
1129
|
-
`Copilot CLI not found at ${this.
|
|
1419
|
+
`Copilot CLI not found at ${this.resolvedCliPath}. Ensure @github/copilot is installed.`
|
|
1130
1420
|
);
|
|
1131
1421
|
}
|
|
1132
|
-
const stdioConfig = this.
|
|
1133
|
-
const isJsFile = this.
|
|
1422
|
+
const stdioConfig = this.connectionConfig.kind === "stdio" ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
|
|
1423
|
+
const isJsFile = this.resolvedCliPath.endsWith(".js");
|
|
1134
1424
|
if (isJsFile) {
|
|
1135
|
-
this.cliProcess = (0, import_node_child_process.spawn)(getNodeExecPath(), [this.
|
|
1425
|
+
this.cliProcess = (0, import_node_child_process.spawn)(getNodeExecPath(), [this.resolvedCliPath, ...args], {
|
|
1136
1426
|
stdio: stdioConfig,
|
|
1137
|
-
cwd: this.options.
|
|
1427
|
+
cwd: this.options.workingDirectory,
|
|
1138
1428
|
env: envWithoutNodeDebug,
|
|
1139
1429
|
windowsHide: true
|
|
1140
1430
|
});
|
|
1141
1431
|
} else {
|
|
1142
|
-
this.cliProcess = (0, import_node_child_process.spawn)(this.
|
|
1432
|
+
this.cliProcess = (0, import_node_child_process.spawn)(this.resolvedCliPath, args, {
|
|
1143
1433
|
stdio: stdioConfig,
|
|
1144
|
-
cwd: this.options.
|
|
1434
|
+
cwd: this.options.workingDirectory,
|
|
1145
1435
|
env: envWithoutNodeDebug,
|
|
1146
1436
|
windowsHide: true
|
|
1147
1437
|
});
|
|
1148
1438
|
}
|
|
1149
1439
|
let stdout = "";
|
|
1150
1440
|
let resolved = false;
|
|
1151
|
-
if (this.
|
|
1441
|
+
if (this.connectionConfig.kind === "stdio") {
|
|
1152
1442
|
resolved = true;
|
|
1153
1443
|
resolve();
|
|
1154
1444
|
} else {
|
|
@@ -1156,7 +1446,7 @@ class CopilotClient {
|
|
|
1156
1446
|
stdout += data.toString();
|
|
1157
1447
|
const match = stdout.match(/listening on port (\d+)/i);
|
|
1158
1448
|
if (match && !resolved) {
|
|
1159
|
-
this.
|
|
1449
|
+
this.runtimePort = parseInt(match[1], 10);
|
|
1160
1450
|
resolved = true;
|
|
1161
1451
|
resolve();
|
|
1162
1452
|
}
|
|
@@ -1230,19 +1520,21 @@ stderr: ${stderrOutput}`
|
|
|
1230
1520
|
resolved = true;
|
|
1231
1521
|
reject(new Error("Timeout waiting for CLI server to start"));
|
|
1232
1522
|
}
|
|
1233
|
-
},
|
|
1523
|
+
}, 3e4);
|
|
1234
1524
|
});
|
|
1235
1525
|
}
|
|
1236
1526
|
/**
|
|
1237
1527
|
* Connect to the CLI server (via socket or stdio)
|
|
1238
1528
|
*/
|
|
1239
1529
|
async connectToServer() {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1530
|
+
switch (this.connectionConfig.kind) {
|
|
1531
|
+
case "parent-process":
|
|
1532
|
+
return this.connectToParentProcessViaStdio();
|
|
1533
|
+
case "stdio":
|
|
1534
|
+
return this.connectToChildProcessViaStdio();
|
|
1535
|
+
case "tcp":
|
|
1536
|
+
case "uri":
|
|
1537
|
+
return this.connectViaTcp();
|
|
1246
1538
|
}
|
|
1247
1539
|
}
|
|
1248
1540
|
/**
|
|
@@ -1282,12 +1574,17 @@ stderr: ${stderrOutput}`
|
|
|
1282
1574
|
* Connect to the CLI server via TCP socket
|
|
1283
1575
|
*/
|
|
1284
1576
|
async connectViaTcp() {
|
|
1285
|
-
if (!this.
|
|
1577
|
+
if (!this.runtimePort) {
|
|
1286
1578
|
throw new Error("Server port not available");
|
|
1287
1579
|
}
|
|
1288
1580
|
return new Promise((resolve, reject) => {
|
|
1289
1581
|
this.socket = new import_node_net.Socket();
|
|
1290
|
-
|
|
1582
|
+
const connectionTimeout = setTimeout(() => {
|
|
1583
|
+
this.socket?.destroy();
|
|
1584
|
+
reject(new Error("Timeout connecting to CLI server"));
|
|
1585
|
+
}, 1e4);
|
|
1586
|
+
this.socket.connect(this.runtimePort, this.actualHost, () => {
|
|
1587
|
+
clearTimeout(connectionTimeout);
|
|
1291
1588
|
this.connection = (0, import_node.createMessageConnection)(
|
|
1292
1589
|
new import_node.StreamMessageReader(this.socket),
|
|
1293
1590
|
new import_node.StreamMessageWriter(this.socket)
|
|
@@ -1297,6 +1594,7 @@ stderr: ${stderrOutput}`
|
|
|
1297
1594
|
resolve();
|
|
1298
1595
|
});
|
|
1299
1596
|
this.socket.on("error", (error) => {
|
|
1597
|
+
clearTimeout(connectionTimeout);
|
|
1300
1598
|
reject(new Error(`Failed to connect to CLI server: ${error.message}`));
|
|
1301
1599
|
});
|
|
1302
1600
|
});
|
|
@@ -1312,16 +1610,16 @@ stderr: ${stderrOutput}`
|
|
|
1312
1610
|
this.handleSessionLifecycleNotification(notification);
|
|
1313
1611
|
});
|
|
1314
1612
|
this.connection.onRequest(
|
|
1315
|
-
"
|
|
1316
|
-
async (params) => await this.
|
|
1613
|
+
"userInput.request",
|
|
1614
|
+
async (params) => await this.handleUserInputRequest(params)
|
|
1317
1615
|
);
|
|
1318
1616
|
this.connection.onRequest(
|
|
1319
|
-
"
|
|
1320
|
-
async (params) => await this.
|
|
1617
|
+
"exitPlanMode.request",
|
|
1618
|
+
async (params) => await this.handleExitPlanModeRequest(params)
|
|
1321
1619
|
);
|
|
1322
1620
|
this.connection.onRequest(
|
|
1323
|
-
"
|
|
1324
|
-
async (params) => await this.
|
|
1621
|
+
"autoModeSwitch.request",
|
|
1622
|
+
async (params) => await this.handleAutoModeSwitchRequest(params)
|
|
1325
1623
|
);
|
|
1326
1624
|
this.connection.onRequest(
|
|
1327
1625
|
"hooks.invoke",
|
|
@@ -1357,7 +1655,20 @@ stderr: ${stderrOutput}`
|
|
|
1357
1655
|
if (typeof notification !== "object" || !notification || !("type" in notification) || typeof notification.type !== "string" || !("sessionId" in notification) || typeof notification.sessionId !== "string") {
|
|
1358
1656
|
return;
|
|
1359
1657
|
}
|
|
1360
|
-
const
|
|
1658
|
+
const raw = notification;
|
|
1659
|
+
let metadata;
|
|
1660
|
+
if (raw.metadata && raw.metadata.startTime && raw.metadata.modifiedTime) {
|
|
1661
|
+
metadata = {
|
|
1662
|
+
startTime: new Date(raw.metadata.startTime),
|
|
1663
|
+
modifiedTime: new Date(raw.metadata.modifiedTime),
|
|
1664
|
+
summary: raw.metadata.summary
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
const event = {
|
|
1668
|
+
type: raw.type,
|
|
1669
|
+
sessionId: raw.sessionId,
|
|
1670
|
+
metadata
|
|
1671
|
+
};
|
|
1361
1672
|
const typedHandlers = this.typedLifecycleHandlers.get(event.type);
|
|
1362
1673
|
if (typedHandlers) {
|
|
1363
1674
|
for (const handler of typedHandlers) {
|
|
@@ -1389,125 +1700,55 @@ stderr: ${stderrOutput}`
|
|
|
1389
1700
|
});
|
|
1390
1701
|
return result;
|
|
1391
1702
|
}
|
|
1392
|
-
async
|
|
1393
|
-
if (!params || typeof params.sessionId !== "string" || typeof params.
|
|
1394
|
-
throw new Error("Invalid
|
|
1703
|
+
async handleExitPlanModeRequest(params) {
|
|
1704
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.summary !== "string" || !Array.isArray(params.actions) || typeof params.recommendedAction !== "string") {
|
|
1705
|
+
throw new Error("Invalid exit plan mode request payload");
|
|
1395
1706
|
}
|
|
1396
1707
|
const session = this.sessions.get(params.sessionId);
|
|
1397
1708
|
if (!session) {
|
|
1398
1709
|
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1399
1710
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
1711
|
+
return await session._handleExitPlanModeRequest({
|
|
1712
|
+
summary: params.summary,
|
|
1713
|
+
planContent: params.planContent,
|
|
1714
|
+
actions: params.actions,
|
|
1715
|
+
recommendedAction: params.recommendedAction
|
|
1716
|
+
});
|
|
1402
1717
|
}
|
|
1403
|
-
async
|
|
1404
|
-
if (!params || typeof params.sessionId !== "string"
|
|
1405
|
-
throw new Error("Invalid
|
|
1718
|
+
async handleAutoModeSwitchRequest(params) {
|
|
1719
|
+
if (!params || typeof params.sessionId !== "string") {
|
|
1720
|
+
throw new Error("Invalid auto mode switch request payload");
|
|
1406
1721
|
}
|
|
1407
1722
|
const session = this.sessions.get(params.sessionId);
|
|
1408
1723
|
if (!session) {
|
|
1409
1724
|
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1410
1725
|
}
|
|
1411
|
-
|
|
1726
|
+
const response = await session._handleAutoModeSwitchRequest({
|
|
1727
|
+
errorCode: params.errorCode,
|
|
1728
|
+
retryAfterSeconds: params.retryAfterSeconds
|
|
1729
|
+
});
|
|
1730
|
+
return { response };
|
|
1412
1731
|
}
|
|
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");
|
|
1732
|
+
async handleHooksInvoke(params) {
|
|
1733
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
|
|
1734
|
+
throw new Error("Invalid hooks invoke payload");
|
|
1424
1735
|
}
|
|
1425
1736
|
const session = this.sessions.get(params.sessionId);
|
|
1426
1737
|
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
|
-
};
|
|
1738
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1463
1739
|
}
|
|
1740
|
+
const output = await session._handleHooksInvoke(params.hookType, params.input);
|
|
1741
|
+
return { output };
|
|
1464
1742
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
async handlePermissionRequestV2(params) {
|
|
1469
|
-
if (!params || typeof params.sessionId !== "string" || !params.permissionRequest) {
|
|
1470
|
-
throw new Error("Invalid permission request payload");
|
|
1743
|
+
async handleSystemMessageTransform(params) {
|
|
1744
|
+
if (!params || typeof params.sessionId !== "string" || !params.sections || typeof params.sections !== "object") {
|
|
1745
|
+
throw new Error("Invalid systemMessage.transform payload");
|
|
1471
1746
|
}
|
|
1472
1747
|
const session = this.sessions.get(params.sessionId);
|
|
1473
1748
|
if (!session) {
|
|
1474
1749
|
throw new Error(`Session not found: ${params.sessionId}`);
|
|
1475
1750
|
}
|
|
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;
|
|
1751
|
+
return await session._handleSystemMessageTransform(params.sections);
|
|
1511
1752
|
}
|
|
1512
1753
|
}
|
|
1513
1754
|
// Annotate the CommonJS export names for ESM import in node:
|